using Unity.Entities;
using Unity.NetCode;
namespace ProjectM.Simulation
{
///
/// Lifecycle states for a co-op expedition run (). A byte, never an enum
/// (Burst/serialization safe), APPEND-ONLY. is appended after the original four so no
/// value is re-meaned. The party is at the base hub in ; a discrete run spans
/// →→→ (loop) →
/// →.
///
public static class RunLifecycle
{
/// Party in the base hub; ready-check active; no expedition ghosts exist.
public const byte Staging = 0;
/// All-ready launch transient: seed chosen, party teleporting into room 0.
public const byte Launching = 1;
/// Active room populated; party fighting/looting.
public const byte InRoom = 2;
/// Room cleared; per-player boon offers pending; room torn down.
public const byte RoomReward = 3;
/// Run ended (boss cleared / party wiped / all left): teleport home, bank, → Staging.
public const byte Returning = 4;
/// Boons picked; party choosing the next branch (no room materialized — the teardown gap).
public const byte RouteSelect = 5;
/// DR-046: room cleared + boon picked, but the room + resource NODES persist and a portal is up.
/// Party loots; interacting the portal (or a soft-timeout) tears the room down + advances (RouteSelect, or
/// Returning if the boss fell). Append-only byte value — no ghost re-mean.
public const byte RoomExplore = 6;
}
///
/// The REPLICATED run-lifecycle summary the whole party observes — a server-decided, client-observed FSM on the
/// GLOBAL untagged CycleDirector ghost (so it is relevant cross-region for free, like /
/// /). SOLE writer: RunDirectorSystem. Distinct from
/// (that stays the BASE Calm↔Siege posture for retaliation/final sieges).
///
/// Fields split three ways: the lifecycle/room readout (HUD "Room i/N", biome cross-fade), the branching-map
/// wire ( so the client regenerates the map for DISPLAY, + and the
/// authoritative reachable RouteOpt* the clickable options bind to), and a two-field mirror of the
/// persisted meta counters for the HUD. All integers/bytes → replicate exact (no quantization). Adding this
/// [GhostField] component re-hashes the runtime-spawned director ghost (server + client bake the same
/// prefab → hash matches), exactly like /.
///
public struct RunInfo : IComponentData
{
// ---- lifecycle + room readout ----
/// .
[GhostField] public byte Lifecycle;
/// 0-based depth of the active room (HUD "Room CurrentRoom+1 / RoomCount").
[GhostField] public int CurrentRoom;
/// Total rooms this run (== map layer count, seed-varied in [6,10]).
[GhostField] public int RoomCount;
/// of the active room.
[GhostField] public byte CurrentRoomType;
/// of the active room (client atmosphere cross-fade).
[GhostField] public byte CurrentBiome;
/// Server tick the launch countdown elapses (0 = none). Via ; compared with IsNewerThan.
[GhostField] public uint LaunchTick;
// ---- branching map wire ----
/// The run seed — clients regenerate the map layout for DISPLAY via (no gameplay authority).
[GhostField] public uint RunSeed;
/// The party's current column in the active layer.
[GhostField] public byte CurrentCol;
/// Number of reachable next-room options (0 unless ).
[GhostField] public byte RouteOptionCount;
/// Reachable next-layer column for option 0 (authoritative — the clickable button binds to this, not the regen).
[GhostField] public byte RouteOpt0Col;
[GhostField] public byte RouteOpt1Col;
[GhostField] public byte RouteOpt2Col;
/// of option 0 (so the HUD labels the choice).
[GhostField] public byte RouteOpt0Type;
[GhostField] public byte RouteOpt1Type;
[GhostField] public byte RouteOpt2Type;
// ---- persisted-meta HUD mirror ----
/// Runs completed (boss-cleared), mirrored for the HUD from the persisted meta counters.
[GhostField] public int RunsCompleted;
/// Deepest room reached across runs, mirrored for the HUD.
[GhostField] public int MaxDepthReached;
}
}