Merge main into phase/39-school-owners.

Keep school owners and phase 41 opinions/portraits together; ResetAsync wipes all saves so shared AppHost tests stay isolated.
This commit is contained in:
Leonid Pershin
2026-08-20 08:36:13 +03:00
44 changed files with 1388 additions and 85 deletions
+36 -3
View File
@@ -20,6 +20,7 @@ internal sealed class GameLoopService(
GameMetrics metrics,
SchoolStore store,
ModContent mods,
SwarmUiSettingsStore swarmSettings,
ILoggerFactory loggerFactory,
ILogger<GameLoopService> logger) : BackgroundService
{
@@ -61,6 +62,20 @@ internal sealed class GameLoopService(
}
}
/// <summary>Create-time SwarmUI copy for this living school, or null on older saves.</summary>
public SwarmUiConfigFile? PortraitSettingsOf(int schoolId)
{
foreach (var worker in Volatile.Read(ref _publishedWorkers))
{
if (worker.Id == schoolId)
{
return worker.PortraitSettings;
}
}
return null;
}
/// <summary>
/// Menu-style read of one school's published roster and frozen catalog. Does not post to the
/// mailbox — the list is HTTP over a snapshot, the same way the menu reads clocks.
@@ -453,7 +468,22 @@ internal sealed class GameLoopService(
var nativeLanguage = NativeLanguages.Pick(country.Names, seed, command.NativeLanguage, rollIfOmitted: true);
var climatePresetId = CountryClimate.Pick(country, seed, rollIfOmitted: true);
var worker = SpawnWorker(id, normalized, command.StartDate, running: true, ClockSpeed.DefaultIndex, isNew: true, packIds, command.Map, countryId, climatePresetId, nativeLanguage, seed, owner: command.Owner);
var portrait = SwarmUiConfigFile.Clone(command.PortraitSettings ?? swarmSettings.Current);
var worker = SpawnWorker(
id,
normalized,
command.StartDate,
running: true,
ClockSpeed.DefaultIndex,
isNew: true,
packIds,
command.Map,
countryId,
climatePresetId,
nativeLanguage,
seed,
owner: command.Owner,
portraitSettings: portrait);
Track(worker);
worker.Start();
@@ -670,7 +700,8 @@ internal sealed class GameLoopService(
createSeed: null,
save.Presence,
save.DressRules,
save.Owner);
save.Owner,
save.PortraitSettings);
worker.Start();
try
@@ -727,7 +758,8 @@ internal sealed class GameLoopService(
int? createSeed = null,
IReadOnlyList<PresenceSnapshot>? presence = null,
SchoolDressRules? dressRules = null,
string? owner = null) =>
string? owner = null,
SwarmUiConfigFile? portraitSettings = null) =>
new(
id,
name,
@@ -744,6 +776,7 @@ internal sealed class GameLoopService(
presence,
dressRules,
owner,
portraitSettings,
_options,
clients,
metrics,