Implement per-school save functionality by introducing a dedicated save directory and updating the school management system to support loading and saving school states. Revise documentation to reflect these changes, including updates to the architecture and design documents, and enhance the API for reloading schools from disk. Update tests to ensure proper functionality of the new save and reload features.
ci / server (push) Failing after 3m40s
ci / client (push) Successful in 18s

This commit is contained in:
Leonid Pershin
2026-08-18 14:07:23 +03:00
parent f50f6eacf8
commit 37c39a3beb
28 changed files with 1032 additions and 219 deletions
+7 -4
View File
@@ -3,8 +3,8 @@ using HSchool.Simulation;
namespace HSchool.Server.Game;
/// <summary>
/// Work item handed from a request or connection thread to the loop thread. Schools are
/// single-threaded, so every mutation and every read of live state arrives as one of these.
/// Work item handed from a request or connection thread to the supervisor. Create, delete and
/// name suggestions stay here; open/close/running/speed are forwarded to the school's worker.
/// </summary>
internal abstract record GameCommand
{
@@ -17,16 +17,19 @@ internal abstract record GameCommand
internal sealed record SuggestName(SchoolNameLanguage Language, TaskCompletionSource<string> Result) : GameCommand;
/// <summary>A connection starts watching a school; its calendar starts running.</summary>
/// <summary>A connection starts watching a school; clock frames follow from that worker.</summary>
internal sealed record OpenSchool(uint PlayerId, int SchoolId) : GameCommand;
/// <summary>
/// Stops watching. The school id travels with the command because the connection may already
/// be gone from the registry by the time the loop thread gets here.
/// be gone from the registry by the time the supervisor gets here.
/// </summary>
internal sealed record CloseSchool(uint PlayerId, int SchoolId) : GameCommand;
internal sealed record SetRunning(uint PlayerId, bool Running) : GameCommand;
internal sealed record SetSpeed(uint PlayerId, byte SpeedIndex) : GameCommand;
/// <summary>Stops every worker, re-reads the save directory, starts workers from those files.</summary>
internal sealed record ReloadSaves(TaskCompletionSource Result) : GameCommand;
}