using System; using ProjectM.Simulation; using Unity.Entities; using Unity.NetCode; namespace ProjectM.Server { /// /// Host-only autosave writer. A managed (file IO => NO Burst) that reacts to the /// flag the Bursted CyclePhaseSystem raises on the Siege->Calm checkpoint: /// reads the authoritative + shared resource ledger off the CycleDirector ghost, /// writes the JSON save (), then clears the flag. ServerSimulation-only, so a pure /// (Join) client never writes. Deliberately carries NO [UpdateAfter(CyclePhaseSystem)] (that would risk /// a sort-cycle); a one-tick-late autosave is irrelevant. /// [WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)] public partial class SaveWriteSystem : SystemBase { protected override void OnCreate() { RequireForUpdate(); RequireForUpdate(); } protected override void OnUpdate() { var dir = SystemAPI.GetSingletonEntity(); var req = SystemAPI.GetComponent(dir); if (req.Pending == 0) return; req.Pending = 0; SystemAPI.SetComponent(dir, req); var goal = SystemAPI.HasComponent(dir) ? SystemAPI.GetComponent(dir) : default; // END-1: persist the Engine Core integrity (a wounded base stays wounded across save/quit). var core = SystemAPI.HasComponent(dir) ? SystemAPI.GetComponent(dir) : default; // The shared ledger lives on this same CycleDirector ghost (ResourceLedger-tagged StorageEntry buffer). var buffer = SystemAPI.GetBuffer(dir); var rows = new LedgerRow[buffer.Length]; for (int i = 0; i < buffer.Length; i++) rows[i] = new LedgerRow { ItemId = buffer[i].ItemId, Count = buffer[i].Count }; // M7: also persist player-built structures + their production tick-state / inventory (single shared scan). uint nowTick = SystemAPI.GetSingleton().ServerTick.TickIndexForValidTick; SaveStructureScan.Collect(EntityManager, nowTick, out var structures, out var structureIo); SaveService.Save(new SaveData { GoalCharge = goal.Charge, GoalTarget = goal.Target, CoreCurrent = core.Current, Ledger = rows, Structures = structures, StructureIo = structureIo, SavedAtMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), }); } } }