Add portrait settings support to school creation and update related API and UI components. Enhance error handling for invalid presets and ensure proper cloning of settings. Update tests to validate new functionality.
ci / server (push) Failing after 3m40s
ci / client (push) Failing after 14s

This commit is contained in:
Leonid Pershin
2026-08-20 08:17:58 +03:00
parent db95de0ddf
commit 9d96108516
20 changed files with 293 additions and 40 deletions
+35 -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.
@@ -414,7 +429,21 @@ 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);
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,
portraitSettings: portrait);
Track(worker);
worker.Start();
@@ -613,7 +642,8 @@ internal sealed class GameLoopService(
save.NativeLanguage,
createSeed: null,
save.Presence,
save.DressRules);
save.DressRules,
save.PortraitSettings);
worker.Start();
try
@@ -669,7 +699,8 @@ internal sealed class GameLoopService(
string? nativeLanguage,
int? createSeed = null,
IReadOnlyList<PresenceSnapshot>? presence = null,
SchoolDressRules? dressRules = null) =>
SchoolDressRules? dressRules = null,
SwarmUiConfigFile? portraitSettings = null) =>
new(
id,
name,
@@ -685,6 +716,7 @@ internal sealed class GameLoopService(
createSeed,
presence,
dressRules,
portraitSettings,
_options,
clients,
metrics,