namespace Theriapolis.Core.Tactical;
///
/// Persists per-chunk player-caused modifications (chopped trees, dropped items,
/// emptied bandit camps). Implementations: in-memory (Phase 4 tests + runtime
/// cache), MessagePack-backed (Phase 4 save body — see ).
///
public interface IChunkDeltaStore
{
/// Returns the delta for a chunk, or null if no modifications recorded.
ChunkDelta? Get(ChunkCoord cc);
/// Records a chunk's delta. Overwrites any existing entry.
void Put(ChunkCoord cc, ChunkDelta delta);
/// Erases a chunk's delta — the chunk reverts to its deterministic baseline.
void Remove(ChunkCoord cc);
/// Snapshot of every recorded delta, used by SaveCodec to flush the world.
IReadOnlyDictionary All { get; }
}
///
/// Sparse delta for a single chunk: just the tactical-tile cells that diverge
/// from 's output. Phase 4 stores both
/// the surface and the deco; richer per-tile state arrives later.
///
public sealed class ChunkDelta
{
public List TileMods { get; } = new();
/// True if the spawn list has been consumed (all spawns cleared).
public bool SpawnsConsumed { get; set; }
}
public readonly struct TileMod
{
public readonly byte LocalX;
public readonly byte LocalY;
public readonly TacticalSurface Surface;
public readonly TacticalDeco Deco;
public readonly byte Flags;
public TileMod(int lx, int ly, TacticalSurface s, TacticalDeco d, byte f)
{
LocalX = (byte)lx; LocalY = (byte)ly; Surface = s; Deco = d; Flags = f;
}
}
/// Trivial in-memory implementation. Used by tests and at runtime before save.
public sealed class InMemoryChunkDeltaStore : IChunkDeltaStore
{
private readonly Dictionary _store = new();
public ChunkDelta? Get(ChunkCoord cc) => _store.TryGetValue(cc, out var d) ? d : null;
public void Put(ChunkCoord cc, ChunkDelta delta) => _store[cc] = delta;
public void Remove(ChunkCoord cc) => _store.Remove(cc);
public IReadOnlyDictionary All => _store;
}