KitchenChaos/Assets/Scripts/KitchenGameManager.cs

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;
}