Enhance school creation and map management features by updating the API to support mod packs and map layouts. Introduce a new map snapshot protocol for efficient data handling during school sessions. Revise documentation to reflect these changes, including updates to the protocol and architecture documents. Improve UI components for mod selection and map editing, ensuring a better user experience. Update tests to validate new functionalities and ensure robustness.
ci / server (push) Failing after 3m31s
ci / client (push) Successful in 14s

This commit is contained in:
Leonid Pershin
2026-08-18 15:15:49 +03:00
parent 1bc75244e8
commit 30cc937069
36 changed files with 1876 additions and 171 deletions
+33 -1
View File
@@ -169,10 +169,27 @@ internal sealed class GameLoopService(
return;
}
var extras = command.ExtraModIds ?? [];
foreach (var packId in extras)
{
if (!ModContent.IsSafePackId(packId) || !mods.PackExists(packId))
{
command.Result.TrySetResult(new SchoolCreationOutcome(null, SchoolCreationError.UnknownMod));
return;
}
}
var packIds = mods.NormalizePackIds(extras);
if (!mods.PackExists(CatalogLoader.CorePackId))
{
command.Result.TrySetResult(new SchoolCreationOutcome(null, SchoolCreationError.InvalidCatalog));
return;
}
var id = _nextId++;
store.WriteNextId(_nextId);
var worker = SpawnWorker(id, normalized, command.StartDate, running: true, ClockSpeed.DefaultIndex, isNew: true, modIds: null, map: null);
var worker = SpawnWorker(id, normalized, command.StartDate, running: true, ClockSpeed.DefaultIndex, isNew: true, packIds, command.Map);
Track(worker);
worker.Start();
@@ -180,6 +197,13 @@ internal sealed class GameLoopService(
{
await worker.Started.ConfigureAwait(false);
}
catch (SchoolContentUnavailableException ex)
{
Untrack(id);
await worker.StopAsync(persist: false).ConfigureAwait(false);
command.Result.TrySetResult(new SchoolCreationOutcome(null, ContentError(ex)));
return;
}
catch
{
Untrack(id);
@@ -427,6 +451,14 @@ internal sealed class GameLoopService(
client.TrySend(frame.AsMemory(0, length));
}
private static SchoolCreationError ContentError(SchoolContentUnavailableException ex) =>
ex.InnerException switch
{
MapValidationException => SchoolCreationError.InvalidMap,
ContentLoadException => SchoolCreationError.InvalidCatalog,
_ => SchoolCreationError.InvalidCatalog,
};
/// <summary>Runs work for a waiting request thread without letting an exception kill the supervisor.</summary>
private static void Complete<T>(TaskCompletionSource<T> completion, Func<T> work)
{