406 lines
14 KiB
C#
406 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Data.ScriptableObjects;
|
|
using FishNet.Connection;
|
|
using FishNet.Object;
|
|
using FishNet.Object.Synchronizing;
|
|
using Types;
|
|
using UnityEngine;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace Managers
|
|
{
|
|
public class GameManager : NetworkBehaviour
|
|
{
|
|
[SerializeField] private SaveManager saveManager;
|
|
[SerializeField] private HotkeyManager hotkeyManager;
|
|
[SerializeField] private AudioManager audioManager;
|
|
[SerializeField] private UIManager uiManager;
|
|
|
|
// person who's running the game, owner.
|
|
[FormerlySerializedAs("playerManager")] [SerializeField]
|
|
private PlayerManager ownerPlayerManager;
|
|
|
|
[SerializeField] public ItemDatabase itemDatabase;
|
|
|
|
private readonly SyncVar<int> _syncGameSeed = new(new SyncTypeSettings
|
|
{
|
|
WritePermission = WritePermission.ServerOnly,
|
|
ReadPermission = ReadPermission.Observers
|
|
});
|
|
|
|
private readonly SyncVar<GameStatus> _syncGameStatus = new(new SyncTypeSettings
|
|
{
|
|
WritePermission = WritePermission.ServerOnly,
|
|
ReadPermission = ReadPermission.Observers
|
|
});
|
|
|
|
private readonly SyncVar<GameTimeSettings> _syncGameTimeSettings = new(new SyncTypeSettings
|
|
{
|
|
WritePermission = WritePermission.ServerOnly,
|
|
ReadPermission = ReadPermission.Observers
|
|
});
|
|
|
|
private readonly SyncDictionary<int, GamePlayer> _syncPlayers = new(new SyncTypeSettings
|
|
{
|
|
WritePermission = WritePermission.ServerOnly,
|
|
ReadPermission = ReadPermission.Observers
|
|
});
|
|
|
|
private readonly SyncVar<WeatherConditions> _syncWeather = new(new SyncTypeSettings
|
|
{
|
|
WritePermission = WritePermission.ServerOnly,
|
|
ReadPermission = ReadPermission.Observers
|
|
});
|
|
|
|
public static GameManager Instance { get; set; }
|
|
|
|
private void Awake()
|
|
{
|
|
Debug.Log("Starting GameManager");
|
|
itemDatabase = Resources.Load<ItemDatabase>("GameItems/ItemDatabase");
|
|
|
|
|
|
// Players = new Dictionary<int, GamePlayer>(),
|
|
// TimeSettings = new GameTimeSettings(),
|
|
// GameStatus = GameStatus.WaitingForPlayers,
|
|
// Weather = WeatherConditions.Sunny,
|
|
|
|
|
|
_syncPlayers.OnChange += SyncPlayersChange;
|
|
_syncGameTimeSettings.OnChange += SyncGameTimeSettingsChange;
|
|
_syncGameStatus.OnChange += SyncGameStatusChange;
|
|
_syncWeather.OnChange += SyncWeatherChange;
|
|
|
|
|
|
if (Instance != null)
|
|
{
|
|
Destroy(this);
|
|
return;
|
|
}
|
|
|
|
Instance = this;
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (Instance == this)
|
|
Instance = null;
|
|
|
|
Debug.Log("GameManager destroyed");
|
|
}
|
|
|
|
private void SyncWeatherChange(WeatherConditions prev, WeatherConditions next, bool asserver)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
private void SyncGameStatusChange(GameStatus prev, GameStatus next, bool asserver)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
private void SyncGameTimeSettingsChange(GameTimeSettings prev, GameTimeSettings next, bool asserver)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
private void SyncPlayersChange(SyncDictionaryOperation op, int key, GamePlayer value, bool asServer)
|
|
{
|
|
Debug.Log($"SyncPlayersChange Triggered - Operation: {op}, Key: {key}, AsServer: {asServer}");
|
|
|
|
switch (op)
|
|
{
|
|
case SyncDictionaryOperation.Add:
|
|
Debug.Log($"Player added - ID: {key}, Name: {value.PlayerName}");
|
|
// Implement logic for when a new player is added
|
|
OnPlayerAdded(key, value);
|
|
break;
|
|
case SyncDictionaryOperation.Remove:
|
|
Debug.Log($"Player removed - ID: {key}");
|
|
// Implement logic for when a player is removed
|
|
OnPlayerRemoved(key);
|
|
break;
|
|
case SyncDictionaryOperation.Clear:
|
|
Debug.Log("All players cleared");
|
|
// Implement logic for when all players are cleared
|
|
OnAllPlayersCleared();
|
|
break;
|
|
case SyncDictionaryOperation.Set:
|
|
Debug.Log($"Player updated - ID: {key}, Name: {value.PlayerName}");
|
|
// Implement logic for when a player's data is updated
|
|
OnPlayerUpdated(key, value);
|
|
break;
|
|
}
|
|
|
|
// Notify any listeners that the player list has changed
|
|
OnPlayersListChanged();
|
|
}
|
|
|
|
private void OnPlayerAdded(int playerId, GamePlayer player)
|
|
{
|
|
// Implement logic for when a new player is added
|
|
// For example, update UI, spawn player object, etc.
|
|
}
|
|
|
|
private void OnPlayerRemoved(int playerId)
|
|
{
|
|
// Implement logic for when a player is removed
|
|
// For example, remove player from UI, destroy player object, etc.
|
|
}
|
|
|
|
private void OnAllPlayersCleared()
|
|
{
|
|
// Implement logic for when all players are cleared
|
|
// For example, reset UI, clear all player objects, etc.
|
|
}
|
|
|
|
private void OnPlayerUpdated(int playerId, GamePlayer player)
|
|
{
|
|
// Implement logic for when a player's data is updated
|
|
// For example, update UI elements, update player object properties, etc.
|
|
}
|
|
|
|
private void OnPlayersListChanged()
|
|
{
|
|
// Notify any parts of your game that need to know when the player list changes
|
|
// For example, update a player list UI, recalculate game state, etc.
|
|
}
|
|
|
|
[ServerRpc(RequireOwnership = false)]
|
|
public void RegisterPlayerServerRpc(NetworkConnection conn, GamePlayer player)
|
|
{
|
|
try
|
|
{
|
|
Debug.Log(
|
|
$"Attempting to register player. Connection ID: {conn?.ClientId}, Player null?: {player == null}");
|
|
|
|
if (conn == null)
|
|
{
|
|
Debug.LogError("RegisterPlayerServerRpc: NetworkConnection is null");
|
|
return;
|
|
}
|
|
|
|
if (player == null)
|
|
{
|
|
Debug.LogError($"RegisterPlayerServerRpc: GamePlayer is null for connection {conn.ClientId}");
|
|
return;
|
|
}
|
|
|
|
if (_syncPlayers.TryAdd(conn.ClientId, player))
|
|
{
|
|
Debug.Log($"Player registered successfully: {conn.ClientId}");
|
|
OnPlayerRegisteredObserversRpc(conn.ClientId);
|
|
_syncPlayers.Dirty(conn.ClientId);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning($"Player with ID {conn.ClientId} is already registered");
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogError($"Error in RegisterPlayerServerRpc: {e.Message}\nStack Trace: {e.StackTrace}");
|
|
}
|
|
}
|
|
|
|
|
|
[ObserversRpc]
|
|
private void OnPlayerRegisteredObserversRpc(int clientId)
|
|
{
|
|
Debug.Log($"OBS: Player with ID {clientId} has joined the game!");
|
|
// You can add any client-side logic here when a new player joins
|
|
}
|
|
|
|
public override void OnStartNetwork()
|
|
{
|
|
base.OnStartNetwork();
|
|
Debug.Log("Network started");
|
|
}
|
|
|
|
// method to handle player connections
|
|
public override void OnStartClient()
|
|
{
|
|
Debug.Log("Client connected to server");
|
|
base.OnStartClient();
|
|
if (IsServerInitialized) Instance = this;
|
|
// Server logic for new player connections
|
|
}
|
|
|
|
|
|
// get player by client id
|
|
public GamePlayer GetPlayer(int clientId)
|
|
{
|
|
// Debug.Log("Getting player: " + clientId);
|
|
if (_syncPlayers.Count == 0)
|
|
{
|
|
Debug.LogWarning("Players not yet initialized");
|
|
return null;
|
|
}
|
|
|
|
// Debug.Log("Players: " + _syncGameState.Value.Players.Count);
|
|
return _syncPlayers.GetValueOrDefault(clientId);
|
|
}
|
|
|
|
public Dictionary<int, GamePlayer> GetPlayers()
|
|
{
|
|
return (Dictionary<int, GamePlayer>)_syncPlayers.Values;
|
|
}
|
|
|
|
public override void OnStopClient()
|
|
{
|
|
base.OnStopClient();
|
|
// client specific cleanup code?
|
|
|
|
if (IsServerInitialized)
|
|
{
|
|
// server logic for disconnection
|
|
}
|
|
// client logic for disconnection
|
|
}
|
|
|
|
[ServerRpc(RequireOwnership = false)]
|
|
public void StartGameServerRpc()
|
|
{
|
|
UIManager.ShowMainMenuScreen(false);
|
|
// AudioManager.PlayMusic("MainTheme");
|
|
}
|
|
|
|
[ObserversRpc]
|
|
public void StartGameObserversRpc()
|
|
{
|
|
UIManager.ShowMainMenuScreen(false);
|
|
}
|
|
|
|
[ServerRpc(RequireOwnership = false)]
|
|
// client ot server comm? i.e client is telling the server to run this code
|
|
public void EndGameServerRpc()
|
|
{
|
|
Debug.Log("ServerRPC Game Over");
|
|
UIManager.ShowGameOverScreen(true);
|
|
// AudioManager.PlayMusic("GameOverTheme");
|
|
}
|
|
|
|
[ObserversRpc]
|
|
// server to client communication i.e server is telling the client to run this code
|
|
public void EndGameObserversRpc()
|
|
{
|
|
Debug.Log("ObserverRPC Game Over");
|
|
UIManager.ShowGameOverScreen(true);
|
|
}
|
|
|
|
public void StartGame()
|
|
{
|
|
if (IsServerInitialized)
|
|
StartGameServerRpc();
|
|
else
|
|
StartGameObserversRpc();
|
|
}
|
|
|
|
public GameTimeSettings GetTimeSettings()
|
|
{
|
|
return _syncGameTimeSettings.Value;
|
|
}
|
|
|
|
private static GameStateChange GetGameStateChanges(GameState oldState, GameState newState)
|
|
{
|
|
var changes = new GameStateChange();
|
|
|
|
// Compare players
|
|
foreach (var kvp in newState.Players)
|
|
if (!oldState.Players.TryGetValue(kvp.Key, out var oldPlayer) || !oldPlayer.Equals(kvp.Value))
|
|
changes.PlayerChanges[kvp.Key] = kvp.Value;
|
|
|
|
// Compare TimeSettings
|
|
if (!oldState.TimeSettings.Equals(newState.TimeSettings))
|
|
changes.TimeSettingsChanges = newState.TimeSettings;
|
|
|
|
// Compare GameStatus
|
|
if (oldState.GameStatus != newState.GameStatus) changes.StatusChange = newState.GameStatus;
|
|
|
|
// Compare Weather
|
|
if (oldState.Weather != newState.Weather) changes.WeatherChange = newState.Weather;
|
|
|
|
// Compare GameSeed
|
|
if (oldState.GameSeed != newState.GameSeed) changes.GameSeedChange = newState.GameSeed;
|
|
|
|
return changes;
|
|
}
|
|
|
|
[Server]
|
|
private void UpdatePlayer(int playerId, GamePlayer player)
|
|
{
|
|
Debug.Log("Updating player: " + playerId);
|
|
_syncPlayers[playerId] = player;
|
|
_syncPlayers.Dirty(playerId);
|
|
}
|
|
|
|
[Server]
|
|
private void UpdateTimeSettings(GameTimeSettings timeSettings)
|
|
{
|
|
_syncGameTimeSettings.Value = new GameTimeSettings(timeSettings);
|
|
}
|
|
|
|
[Server]
|
|
private void UpdateGameStatus(GameStatus status)
|
|
{
|
|
_syncGameStatus.Value = status;
|
|
}
|
|
|
|
[Server]
|
|
private void UpdateWeather(WeatherConditions weather)
|
|
{
|
|
_syncWeather.Value = weather;
|
|
}
|
|
|
|
|
|
[ServerRpc(RequireOwnership = false)]
|
|
public void RequestUpdatePlayerServerRpc(int playerId, GamePlayer player, NetworkConnection sender = null)
|
|
{
|
|
// Validate the request (e.g., ensure the sender is allowed to update this player)
|
|
if (sender != null && (sender.ClientId == playerId || IsServerInitialized)) UpdatePlayer(playerId, player);
|
|
}
|
|
|
|
[ServerRpc(RequireOwnership = false)]
|
|
public void RequestUpdateTimeSettingsServerRpc(GameTimeSettings timeSettings)
|
|
{
|
|
// You might want to add validation here
|
|
UpdateTimeSettings(timeSettings);
|
|
}
|
|
|
|
[ServerRpc(RequireOwnership = false)]
|
|
public void RequestUpdateGameStatusServerRpc(GameStatus status)
|
|
{
|
|
// Add validation if needed
|
|
UpdateGameStatus(status);
|
|
}
|
|
|
|
[ServerRpc(RequireOwnership = false)]
|
|
public void RequestUpdateWeatherServerRpc(WeatherConditions weather)
|
|
{
|
|
// Add validation if needed
|
|
UpdateWeather(weather);
|
|
}
|
|
|
|
public GamePlayer GetCurrentPlayer()
|
|
{
|
|
if (!IsServerInitialized && !IsClientInitialized)
|
|
{
|
|
Debug.LogError("GameManager not initialized");
|
|
return null;
|
|
}
|
|
|
|
var clientId = ClientManager.Connection.ClientId;
|
|
|
|
if (_syncPlayers.TryGetValue(clientId, out var player))
|
|
{
|
|
Debug.Log("Found player for clientId: " + clientId);
|
|
Debug.Log("Player name: " + player.PlayerName);
|
|
return player;
|
|
}
|
|
|
|
Debug.LogError("Player not found for clientId: " + clientId);
|
|
return null;
|
|
}
|
|
}
|
|
} |