116 lines
3.0 KiB
C#
116 lines
3.0 KiB
C#
using System;
|
|
using Unity.Netcode;
|
|
using UnityEngine;
|
|
|
|
public enum RoundPhase : byte
|
|
{
|
|
WaitingForPlayers,
|
|
WaitingForPlayersToLeave,
|
|
WorkInProgress
|
|
}
|
|
|
|
[RequireComponent(typeof(NetworkObject))]
|
|
public sealed class RoundGameLoopController : NetworkBehaviour
|
|
{
|
|
private readonly NetworkVariable<RoundPhase> phase = new(
|
|
RoundPhase.WaitingForPlayers,
|
|
NetworkVariableReadPermission.Everyone,
|
|
NetworkVariableWritePermission.Server);
|
|
|
|
private StartRoomZone startRoom;
|
|
|
|
public RoundPhase Phase => phase.Value;
|
|
|
|
public event Action<RoundPhase> PhaseChanged;
|
|
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
phase.OnValueChanged += HandlePhaseChanged;
|
|
|
|
startRoom = FindFirstObjectByType<StartRoomZone>();
|
|
|
|
if (IsServer)
|
|
phase.Value = RoundPhase.WaitingForPlayers;
|
|
}
|
|
|
|
public override void OnNetworkDespawn()
|
|
{
|
|
phase.OnValueChanged -= HandlePhaseChanged;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!IsServer)
|
|
return;
|
|
|
|
if (startRoom == null)
|
|
startRoom = FindFirstObjectByType<StartRoomZone>();
|
|
|
|
if (startRoom == null)
|
|
return;
|
|
|
|
switch (phase.Value)
|
|
{
|
|
case RoundPhase.WaitingForPlayers:
|
|
if (AreAllPlayersInStartRoom())
|
|
phase.Value = RoundPhase.WaitingForPlayersToLeave;
|
|
break;
|
|
|
|
case RoundPhase.WaitingForPlayersToLeave:
|
|
if (AreAllPlayersOutsideStartRoom())
|
|
phase.Value = RoundPhase.WorkInProgress;
|
|
break;
|
|
}
|
|
}
|
|
|
|
private bool AreAllPlayersInStartRoom()
|
|
{
|
|
if (!TryGetConnectedPlayers(out int playerCount))
|
|
return false;
|
|
|
|
int playersInside = 0;
|
|
foreach (NetworkClient client in NetworkManager.ConnectedClients.Values)
|
|
{
|
|
if (client.PlayerObject != null && startRoom.Contains(client.PlayerObject.transform.position))
|
|
playersInside++;
|
|
}
|
|
|
|
return playersInside == playerCount;
|
|
}
|
|
|
|
private bool AreAllPlayersOutsideStartRoom()
|
|
{
|
|
if (!TryGetConnectedPlayers(out int playerCount))
|
|
return false;
|
|
|
|
int playersOutside = 0;
|
|
foreach (NetworkClient client in NetworkManager.ConnectedClients.Values)
|
|
{
|
|
if (client.PlayerObject != null && !startRoom.Contains(client.PlayerObject.transform.position))
|
|
playersOutside++;
|
|
}
|
|
|
|
return playersOutside == playerCount;
|
|
}
|
|
|
|
private bool TryGetConnectedPlayers(out int playerCount)
|
|
{
|
|
playerCount = 0;
|
|
if (NetworkManager == null || NetworkManager.ConnectedClients.Count == 0)
|
|
return false;
|
|
|
|
foreach (NetworkClient client in NetworkManager.ConnectedClients.Values)
|
|
{
|
|
if (client.PlayerObject == null)
|
|
return false;
|
|
|
|
playerCount++;
|
|
}
|
|
|
|
return playerCount > 0;
|
|
}
|
|
|
|
private void HandlePhaseChanged(RoundPhase _, RoundPhase current) =>
|
|
PhaseChanged?.Invoke(current);
|
|
}
|