Core Game Loop Additions

This commit is contained in:
2026-06-03 22:41:27 -07:00
parent 79ff06a7df
commit 8e9b4412ce
70 changed files with 3084 additions and 2 deletions
@@ -0,0 +1,61 @@
using Unity.Entities;
using Unity.NetCode;
namespace ProjectM.Simulation
{
/// <summary>
/// Macro-loop state for "The Aether Cycle": which phase the run is in, the cycle number, and the server
/// tick the current (timed) phase ends. Server-authoritative, maintained by CyclePhaseSystem. Currently a
/// server-side singleton; the [GhostField]s below are inert until it is moved onto the runtime-spawned
/// CycleDirector ghost (when the client HUD is wired), at which point the same struct replicates unchanged.
/// The Defend phase is NOT timed — it ends when the base-defense wave is cleared — so PhaseEndTick is only
/// meaningful in Expedition/Build (0 during Defend).
/// </summary>
public struct CycleState : IComponentData
{
/// <summary>Current phase (see <see cref="CyclePhase"/>).</summary>
[GhostField] public byte Phase;
/// <summary>1-based cycle counter (increments when a new Expedition begins).</summary>
[GhostField] public int CycleNumber;
/// <summary>Server tick the current timed phase ends (Expedition/Build only; 0 in Defend).</summary>
[GhostField] public uint PhaseEndTick;
}
/// <summary>Phase constants for <see cref="CycleState.Phase"/> (a byte, not an enum, for trivial Burst/serialization).</summary>
public static class CyclePhase
{
/// <summary>Out in the procedural field gathering resources (timed).</summary>
public const byte Expedition = 0;
/// <summary>The base is under assault by a Husk wave (ends when the wave is cleared).</summary>
public const byte Defend = 1;
/// <summary>Calm at base: spend resources to build/upgrade (timed).</summary>
public const byte Build = 2;
/// <summary>Expedition phase duration in server ticks (SimulationTickRate = 60). Tunable; short for the M6 slice.</summary>
public const uint ExpeditionTicks = 3600; // ~60s cap (early return via the gate ends it sooner)
/// <summary>Build phase duration in server ticks.</summary>
public const uint BuildTicks = 1200; // ~20s
}
/// <summary>
/// Server-only bookkeeping for the cycle state machine that must NOT replicate (kept separate from the
/// replicated <see cref="CycleState"/>). Records the wave number captured when the Defend phase began so
/// the director can detect "this Defend's wave has now been spawned and cleared".
/// </summary>
public struct CycleRuntime : IComponentData
{
/// <summary>WaveState.WaveNumber captured at the moment the current Defend phase started.</summary>
public int DefendStartWave;
/// <summary>Cycle phase from the previous tick — lets ExpeditionFieldSystem edge-detect entering/leaving Expedition.</summary>
public byte PrevPhase;
/// <summary>CycleNumber the expedition field was last seeded for (compared by int equality, never tick math).</summary>
public int LastSpawnedCycle;
}
}