Enhance school simulation and management by integrating roster functionality, allowing for the installation and persistence of student and staff data. Update the school architecture to include a roster alongside existing components, ensuring proper validation against map layouts. Revise room definitions to support homeroom designations and update related tests to validate new functionalities and ensure robustness in roster handling.
ci / server (push) Failing after 3m43s
ci / client (push) Failing after 10s

This commit is contained in:
Leonid Pershin
2026-08-18 19:21:40 +03:00
parent e6182e0e45
commit 52c5082418
27 changed files with 732 additions and 66 deletions
+27 -6
View File
@@ -1,13 +1,12 @@
using Arch.Core;
using HSchool.Content;
using HSchool.People;
namespace HSchool.Simulation;
/// <summary>
/// One save: a name, a calendar, a frozen def catalog, a map instance, and the ECS world that will
/// hold everything the school is made of. The world is empty for now — pupils, rooms and staff
/// land in it as the game grows — but it is created and destroyed with the school so ownership is
/// never in question.
/// One save: a name, a calendar, a frozen def catalog, a map instance, the ECS world, and — once
/// people exist — the roster those entities were built from.
/// </summary>
public sealed class School : IDisposable
{
@@ -66,12 +65,34 @@ public sealed class School : IDisposable
/// <summary>The Arch world backing this school. Only this school's worker thread may touch it.</summary>
public World World { get; }
/// <summary>Runs one fixed step of the school. Today that is only the calendar.</summary>
/// <summary>Composition snapshot. Null in clock-only tests or before <see cref="InstallPeople"/>.</summary>
public Roster? Roster { get; private set; }
public int PeopleSeed { get; private set; }
/// <summary>
/// Installs a roster that already matches the map. Spawns entities; does not write to disk.
/// </summary>
public void InstallPeople(Roster roster, int seed)
{
ObjectDisposedException.ThrowIf(_disposed, this);
ArgumentNullException.ThrowIfNull(roster);
Roster = roster;
PeopleSeed = seed;
RosterSpawner.Spawn(World, roster);
}
/// <summary>Runs one fixed step of the school: calendar, then need decay.</summary>
public void Tick(double deltaTime, double gameMinutesPerRealSecond)
{
ObjectDisposedException.ThrowIf(_disposed, this);
Clock.Advance(deltaTime, gameMinutesPerRealSecond);
var gameMinutes = Clock.Advance(deltaTime, gameMinutesPerRealSecond);
if (gameMinutes > 0 && Catalog is not null)
{
NeedDecay.Apply(World, Catalog, gameMinutes);
}
}
public void Dispose()