178 lines
5.8 KiB
C#
178 lines
5.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Unity.Netcode;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
public class KitchenGameManager : NetworkBehaviour {
|
|
public enum GameState {
|
|
WaitingToStart,
|
|
CountdownToStart,
|
|
GamePlaying,
|
|
GameOver
|
|
}
|
|
|
|
private const float gamePlayingTimerMax = 300f;
|
|
public NetworkVariable<GameState> ActualGameState = new();
|
|
public NetworkVariable<float> CountdownToStartTimer = new(3f);
|
|
public NetworkVariable<float> GamePlayingTimer = new(gamePlayingTimerMax);
|
|
|
|
[SerializeField] private Transform PlayerPrefab;
|
|
|
|
private readonly NetworkVariable<bool> isGamePaused = new();
|
|
private readonly Dictionary<ulong, bool> playerPausedDictionary = new();
|
|
private readonly Dictionary<ulong, bool> playerReadyDictionary = new();
|
|
private bool autoTestGamePausedState;
|
|
private bool isLocalGamePaused;
|
|
public static KitchenGameManager Instance { get; private set; }
|
|
public bool IsLocalPlayerReady { get; private set; }
|
|
|
|
private void Awake() {
|
|
Instance = this;
|
|
}
|
|
|
|
private void Start() {
|
|
GameInput.Instance.OnPauseAction += GameInput_OnPauseAction;
|
|
GameInput.Instance.OnInteractAction += GameInput_OnInteractAction;
|
|
}
|
|
|
|
private void Update() {
|
|
if (!IsServer) return;
|
|
|
|
switch (ActualGameState.Value) {
|
|
case GameState.WaitingToStart:
|
|
break;
|
|
case GameState.CountdownToStart:
|
|
CountdownToStartTimer.Value -= Time.deltaTime;
|
|
if (CountdownToStartTimer.Value > 0f) return;
|
|
|
|
ActualGameState.Value = GameState.GamePlaying;
|
|
break;
|
|
case GameState.GamePlaying:
|
|
GamePlayingTimer.Value -= Time.deltaTime;
|
|
if (GamePlayingTimer.Value > 0f) return;
|
|
|
|
ActualGameState.Value = GameState.GameOver;
|
|
GamePlayingTimer.Value = gamePlayingTimerMax;
|
|
break;
|
|
case GameState.GameOver:
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void LateUpdate() {
|
|
if (autoTestGamePausedState) {
|
|
autoTestGamePausedState = false;
|
|
TestGamePausedState();
|
|
}
|
|
}
|
|
|
|
public override void OnNetworkSpawn() {
|
|
GamePlayingTimer.Value = gamePlayingTimerMax;
|
|
ActualGameState.OnValueChanged += ActualGameState_OnValueChanged;
|
|
isGamePaused.OnValueChanged += IsGamePaused_OnValueChanged;
|
|
|
|
if (IsServer) {
|
|
NetworkManager.Singleton.OnClientDisconnectCallback += NetworkManager_OnClientDisconnectCallback;
|
|
NetworkManager.Singleton.SceneManager.OnLoadEventCompleted += SceneManager_OnLoadEventCompleted;
|
|
}
|
|
}
|
|
|
|
private void SceneManager_OnLoadEventCompleted(string scenename, LoadSceneMode loadscenemode, List<ulong> clientscompleted, List<ulong> clientstimedout) {
|
|
foreach (ulong clientId in NetworkManager.Singleton.ConnectedClientsIds) {
|
|
Transform playerTransform = Instantiate(PlayerPrefab);
|
|
playerTransform.GetComponent<NetworkObject>().SpawnAsPlayerObject(clientId, true);
|
|
}
|
|
}
|
|
|
|
private void NetworkManager_OnClientDisconnectCallback(ulong clientId) => autoTestGamePausedState = true;
|
|
|
|
private void IsGamePaused_OnValueChanged(bool previousValue, bool newValue) {
|
|
if (isGamePaused.Value) {
|
|
Time.timeScale = 0f;
|
|
OnMultiplayerGamePaused?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
else {
|
|
Time.timeScale = 1f;
|
|
OnMultiplayerGameUnpaused?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
}
|
|
|
|
private void ActualGameState_OnValueChanged(GameState previousValue, GameState newValue) {
|
|
Debug.Log($"GameState changed to {newValue}");
|
|
OnStateChanged?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
|
|
public event EventHandler OnStateChanged;
|
|
public event EventHandler OnLocalGamePaused;
|
|
public event EventHandler OnLocalGameUnpaused;
|
|
public event EventHandler OnLocalPlayerReadyChanged;
|
|
public event EventHandler OnMultiplayerGamePaused;
|
|
public event EventHandler OnMultiplayerGameUnpaused;
|
|
|
|
|
|
private void GameInput_OnPauseAction(object sender, EventArgs e) {
|
|
TogglePauseGame();
|
|
}
|
|
|
|
private void GameInput_OnInteractAction(object sender, EventArgs e) {
|
|
if (ActualGameState.Value is GameState.WaitingToStart) {
|
|
IsLocalPlayerReady = true;
|
|
OnLocalPlayerReadyChanged?.Invoke(this, EventArgs.Empty);
|
|
SetPlayerReadyServerRpc();
|
|
}
|
|
}
|
|
|
|
[ServerRpc(RequireOwnership = false)]
|
|
private void SetPlayerReadyServerRpc(ServerRpcParams serverRpcParams = default) {
|
|
playerReadyDictionary[serverRpcParams.Receive.SenderClientId] = true;
|
|
if (NetworkManager.Singleton.ConnectedClientsIds.All(clientId => playerReadyDictionary.ContainsKey(clientId) && playerReadyDictionary[clientId]))
|
|
ActualGameState.Value = GameState.CountdownToStart;
|
|
}
|
|
|
|
public void TogglePauseGame() {
|
|
isLocalGamePaused = !isLocalGamePaused;
|
|
if (isLocalGamePaused) {
|
|
PauseGameServerRpc();
|
|
OnLocalGamePaused?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
else {
|
|
UnpauseGameServerRpc();
|
|
OnLocalGameUnpaused?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
}
|
|
|
|
[ServerRpc(RequireOwnership = false)]
|
|
private void PauseGameServerRpc(ServerRpcParams serverRpcParams = default) {
|
|
playerPausedDictionary[serverRpcParams.Receive.SenderClientId] = true;
|
|
TestGamePausedState();
|
|
}
|
|
|
|
[ServerRpc(RequireOwnership = false)]
|
|
private void UnpauseGameServerRpc(ServerRpcParams serverRpcParams = default) {
|
|
playerPausedDictionary[serverRpcParams.Receive.SenderClientId] = false;
|
|
TestGamePausedState();
|
|
}
|
|
|
|
private void TestGamePausedState() {
|
|
if (NetworkManager.Singleton.ConnectedClientsIds.Any(clientId => playerPausedDictionary.ContainsKey(clientId) && playerPausedDictionary[clientId])) {
|
|
//This player is paused
|
|
isGamePaused.Value = true;
|
|
return;
|
|
}
|
|
|
|
// All players are unpaused
|
|
isGamePaused.Value = false;
|
|
}
|
|
|
|
public bool IsGamePlaying() => ActualGameState.Value is GameState.GamePlaying;
|
|
|
|
public bool IsCountToStartActive() => ActualGameState.Value is GameState.CountdownToStart;
|
|
|
|
public bool IsGameOver() => ActualGameState.Value is GameState.GameOver;
|
|
|
|
public float GetGamePlayingTimerNormalized() => 1 - GamePlayingTimer.Value / gamePlayingTimerMax;
|
|
|
|
public bool IsWaitingToStart() => ActualGameState.Value is GameState.WaitingToStart;
|
|
} |