Files
Project-M/Assets/_Project/Scripts/Server/Persistence/SaveWriteSystem.cs
T
kronic b34945c2d2 LANTERN purge B3+B5: delete the cycle/core/win-lose spine + onboarding; save epoch v7
Deletes CyclePhaseSystem, GoalReachedSystem, CoreDamage/CoreRestore, ThreatDirector,
CoreIntegrity/GoalProgress/RunPhase/RunOutcome/ThreatState components,
CoreVisualFeedbackSystem, and the whole Client/Onboarding slice (+6 test files).

Keepers reworked: RunDirectorSystem (UpdateBefore attr + launch guard + goal/threat
bank removed; sole SaveRequest raiser now), CycleDirectorSpawnSystem (ledger/meta
host only), WaveSystem UNGATED (waves run wherever a WaveDirector is baked),
EnemyAISystem core-fallback stripped, AmbientAudioSystem reworked (bed + run cues;
no CycleState gate), MusicSystem RunInfo-only, HudSystem big trim (goal meter, core
bar, siege banner, terminal banner, outcome flash, onboarding hook all gone),
MetaShop/ClassPrep/AimReticle siege gates dropped, DebugOverlay/ops re-meant
(SpawnWave=force next wave, EndSiege=quiet arena; SetCalm/AdvanceGoal/SetHeat
retired, bytes reserved), TuningConfig Core knobs retired (ids 20-23 reserved),
StorageMath.DrainFraction deleted, HowToPlay copy rewritten.

Save epoch v7 (fresh epoch, operator-approved): SaveData drops goal/core/outcome +
conveyor/machine-IO fields; MinLoadableVersion=7; PendingSave/PendingStructure
trimmed; RollTerminalCampaignForward deleted; SaveStructureScan signature slimmed.

390 tests green; Play world-creation clean (player + waves live, no exceptions).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 15:27:12 -07:00

58 lines
2.4 KiB
C#

using System;
using ProjectM.Simulation;
using Unity.Entities;
using Unity.NetCode;
namespace ProjectM.Server
{
/// <summary>
/// Host-only autosave writer. A managed <see cref="SystemBase"/> (file IO =&gt; NO Burst) that reacts to the
/// <see cref="SaveRequest"/> flag <c>RunDirectorSystem</c> raises on the terminal bank: reads the shared
/// resource ledger + permanent meta off the director ghost, writes the JSON save (<see cref="SaveService"/>),
/// then clears the flag. ServerSimulation-only, so a pure (Join) client never writes.
/// </summary>
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
public partial class SaveWriteSystem : SystemBase
{
protected override void OnCreate()
{
RequireForUpdate<SaveRequest>();
RequireForUpdate<NetworkTime>();
}
protected override void OnUpdate()
{
var dir = SystemAPI.GetSingletonEntity<SaveRequest>();
var req = SystemAPI.GetComponent<SaveRequest>(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<StorageEntry>(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).
uint nowTick = SystemAPI.GetSingleton<NetworkTime>().ServerTick.TickIndexForValidTick;
SaveStructureScan.Collect(EntityManager, nowTick, out var structures);
// v6: the permanent-meta slice via the ONE shared collector.
MetaSaveScan.Collect(EntityManager, dir, out var metaRows, out var runsCompleted, out var maxDepth);
SaveService.Save(new SaveData
{
RunsCompleted = runsCompleted,
MaxDepthReached = maxDepth,
MetaUpgrades = metaRows,
Ledger = rows,
Structures = structures,
SavedAtMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
});
}
}
}