Adding Match State controller
This commit is contained in:
parent
c100db52e5
commit
abcefcd7f1
13 changed files with 445 additions and 99 deletions
138
Assets/_Project/Scripts/Gameplay/MatchState.cs
Normal file
138
Assets/_Project/Scripts/Gameplay/MatchState.cs
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
// Assets/_Project/Scripts/Gameplay/MatchState.cs
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using TD.Core;
|
||||
|
||||
namespace TD.Gameplay
|
||||
{
|
||||
/// <summary>
|
||||
/// Singleton NetworkBehaviour that tracks global match data.
|
||||
/// Lives on a persistent scene object.
|
||||
///
|
||||
/// All state is server-authoritative (Server-write NetworkVariables).
|
||||
/// Clients react to OnValueChanged events on individual fields.
|
||||
/// Phase transitions (Lobby → CountDown → Playing → Victory/Defeat)
|
||||
/// and wave/lives logic are wired in Phases 1.4–1.6 and 1.8.
|
||||
/// </summary>
|
||||
public class MatchState : NetworkBehaviour
|
||||
{
|
||||
// --- Singleton ---------------------------------------------------
|
||||
|
||||
public static MatchState Instance { get; private set; }
|
||||
|
||||
// --- Networked state ---------------------------------------------
|
||||
|
||||
private readonly NetworkVariable<MatchPhase> phase = new NetworkVariable<MatchPhase>(
|
||||
value: MatchPhase.Playing,
|
||||
readPerm: NetworkVariableReadPermission.Everyone,
|
||||
writePerm: NetworkVariableWritePermission.Server
|
||||
);
|
||||
|
||||
/// <summary>Current match phase. Authoritative on the server, replicated to all clients.</summary>
|
||||
public MatchPhase Phase => phase.Value;
|
||||
|
||||
// STUBBED — written by the wave system (Phase 1.5/1.6). Zero until waves begin.
|
||||
[Tooltip("STUBBED — not written until the wave system lands (Phase 1.5/1.6).")]
|
||||
private readonly NetworkVariable<int> currentWave = new NetworkVariable<int>(
|
||||
value: 0,
|
||||
readPerm: NetworkVariableReadPermission.Everyone,
|
||||
writePerm: NetworkVariableWritePermission.Server
|
||||
);
|
||||
|
||||
/// <summary>STUBBED. Current wave index. Zero until the wave system (Phase 1.5/1.6) writes it.</summary>
|
||||
public int CurrentWave => currentWave.Value;
|
||||
|
||||
// STUBBED — written by the combat/leak system (Phase 1.4). Zero until then.
|
||||
[Tooltip("STUBBED — not written until the combat/leak system lands (Phase 1.4).")]
|
||||
private readonly NetworkVariable<int> lives = new NetworkVariable<int>(
|
||||
value: 0,
|
||||
readPerm: NetworkVariableReadPermission.Everyone,
|
||||
writePerm: NetworkVariableWritePermission.Server
|
||||
);
|
||||
|
||||
/// <summary>STUBBED. Shared lives pool. Zero until the combat/leak system (Phase 1.4) writes it.</summary>
|
||||
public int Lives => lives.Value;
|
||||
|
||||
// STUBBED — driven by the race-pick UI (Phase 1.8). Zero when no pick is in progress.
|
||||
[Tooltip("STUBBED — not driven until the race-pick system lands (Phase 1.8).")]
|
||||
private readonly NetworkVariable<float> racePickTimer = new NetworkVariable<float>(
|
||||
value: 0f,
|
||||
readPerm: NetworkVariableReadPermission.Everyone,
|
||||
writePerm: NetworkVariableWritePermission.Server
|
||||
);
|
||||
|
||||
/// <summary>STUBBED. Seconds remaining in the race-pick countdown. Zero when no pick is in progress.</summary>
|
||||
public float RacePickTimer => racePickTimer.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Fired on every peer (server and clients) when the phase changes.
|
||||
/// Subscribe to react to phase transitions without polling.
|
||||
/// </summary>
|
||||
public event System.Action<MatchPhase, MatchPhase> OnPhaseChanged;
|
||||
|
||||
// --- Lifecycle ---------------------------------------------------
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Debug.LogError("[MatchState] Duplicate MatchState detected — only one may exist per scene. " +
|
||||
"Despawning the duplicate.");
|
||||
NetworkObject.Despawn();
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = this;
|
||||
phase.OnValueChanged += HandlePhaseChanged;
|
||||
|
||||
Debug.Log($"[MatchState] Spawned. Phase={phase.Value}");
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
phase.OnValueChanged -= HandlePhaseChanged;
|
||||
if (Instance == this) Instance = null;
|
||||
}
|
||||
|
||||
// --- Server API --------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Transitions to a new phase. Server-only; no-op on clients with a log warning.
|
||||
/// </summary>
|
||||
public void SetPhase(MatchPhase next)
|
||||
{
|
||||
if (!IsServer) { Debug.LogWarning("[MatchState] SetPhase called on a client — ignored."); return; }
|
||||
if (phase.Value == next) return;
|
||||
phase.Value = next;
|
||||
}
|
||||
|
||||
/// <summary>STUBBED. Sets the current wave index. Called by the wave system (Phase 1.5/1.6).</summary>
|
||||
public void SetCurrentWave(int wave)
|
||||
{
|
||||
if (!IsServer) { Debug.LogWarning("[MatchState] SetCurrentWave called on a client — ignored."); return; }
|
||||
currentWave.Value = wave;
|
||||
}
|
||||
|
||||
/// <summary>STUBBED. Sets the shared lives pool. Called by the combat/leak system (Phase 1.4).</summary>
|
||||
public void SetLives(int value)
|
||||
{
|
||||
if (!IsServer) { Debug.LogWarning("[MatchState] SetLives called on a client — ignored."); return; }
|
||||
lives.Value = Mathf.Max(0, value);
|
||||
}
|
||||
|
||||
/// <summary>STUBBED. Sets the race-pick countdown timer. Called by the race-pick system (Phase 1.8).</summary>
|
||||
public void SetRacePickTimer(float seconds)
|
||||
{
|
||||
if (!IsServer) { Debug.LogWarning("[MatchState] SetRacePickTimer called on a client — ignored."); return; }
|
||||
racePickTimer.Value = Mathf.Max(0f, seconds);
|
||||
}
|
||||
|
||||
// --- Handlers ----------------------------------------------------
|
||||
|
||||
private void HandlePhaseChanged(MatchPhase previous, MatchPhase current)
|
||||
{
|
||||
Debug.Log($"[MatchState] Phase: {previous} → {current}");
|
||||
OnPhaseChanged?.Invoke(previous, current);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue