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 RunDirectorSystem raises on the terminal bank: reads the shared /// resource ledger + permanent meta off the director ghost, writes the JSON save (), /// then clears the flag. ServerSimulation-only, so a pure (Join) client never writes. /// [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); // The shared ledger lives on this same director 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 }; // Persist player-built structures (single shared scan; drift-proof vs the quit-to-menu writer). // 2026-08-07 audit purge: structures and the permanent-meta slice are deleted; the save now carries // the LEDGER only. SaveData keeps its Structures / MetaUpgrades / RunsCompleted / MaxDepthReached // fields so a v7 file written before the purge still loads — they are simply written empty now. SaveService.Save(new SaveData { Ledger = rows, SavedAtMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), }); } } }