using System.Collections.Generic; using RebootKit.Engine.Main; using RebootKit.Engine.Services.Console; using RebootKit.Engine.Services.Simulation; using RebootReality.jelycho.Player; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.Assertions; using Logger = RebootKit.Engine.Foundation.Logger; namespace RebootReality.jelycho.Main { class PlayerState : INetworkSerializable { public ulong clientID; public PlayerController Controller; public PlayerActor Actor; public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter { } } public class JelychoGame : Game { static readonly Logger s_Logger = new Logger(nameof(JelychoGame)); [Header("Gameplay")] [SerializeField] GameWorldController m_GameWorldControllerPrefab; public GameWorldController m_GameWorldController; [Header("Player")] [SerializeField] PlayerController m_PlayerControllerPrefab; [SerializeField] PlayerActor m_PlayerActorPrefab; readonly List m_PlayerStates = new List(); void Awake() { } public override void OnDestroy() { base.OnDestroy(); } public override void OnNetworkSpawn() { base.OnNetworkSpawn(); NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnected; NetworkManager.Singleton.OnClientDisconnectCallback += OnClientStopped; } public override void OnNetworkDespawn() { base.OnNetworkDespawn(); NetworkManager.Singleton.OnClientConnectedCallback -= OnClientConnected; NetworkManager.Singleton.OnClientDisconnectCallback -= OnClientStopped; } void OnClientConnected(ulong clientID) { s_Logger.Info($"Client {clientID} connected"); if (IsServer) { s_Logger.Info($"Creating player state for client {clientID}"); PlayerController controller = Instantiate(m_PlayerControllerPrefab); controller.name = $"PlayerController_{clientID}"; controller.NetworkObject.SpawnAsPlayerObject(clientID); m_PlayerStates.Add(new PlayerState { clientID = clientID, Controller = controller, }); } } void OnClientStopped(ulong clientID) { s_Logger.Info($"Client {clientID} disconnected"); if (IsServer) { for (int i = m_PlayerStates.Count - 1; i >= 0; i--) { if (m_PlayerStates[i].clientID == clientID) { s_Logger.Info($"Removing player state for client {clientID}"); m_PlayerStates.RemoveAtSwapBack(i); break; } } } } public override void OnWorldLoaded() { base.OnWorldLoaded(); if (IsServer) { m_GameWorldController = Instantiate(m_GameWorldControllerPrefab); m_GameWorldController.NetworkObject.Spawn(); } OnPlayerReadyRpc(NetworkManager.Singleton.LocalClientId); } public override void OnWorldUnload() { base.OnWorldUnload(); if (IsServer) { m_GameWorldController.NetworkObject.Despawn(); Destroy(m_GameWorldController.gameObject); } } [Rpc(SendTo.Server)] void OnPlayerReadyRpc(ulong clientID) { if (!IsServer) { return; } PlayerActor actor = Instantiate(m_PlayerActorPrefab); actor.name = $"PlayerActor_{clientID}"; actor.NetworkObject.SpawnAsPlayerObject(clientID); PlayerState playerState = GetPlayerState(clientID); Assert.IsNotNull(playerState); playerState.Actor = actor; playerState.Controller.SetActorClientRpc(actor.NetworkObjectId); } PlayerState GetPlayerState(ulong clientID) { foreach (PlayerState state in m_PlayerStates) { if (state.clientID == clientID) { return state; } } s_Logger.Error($"Player state for client {clientID} not found"); return null; } } public static class JelychoConsoleCommands { [RCCMD("worlds", "Lists all worlds")] public static void Worlds(string[] args) { if (args.Length != 1) { RR.WriteToConsole($"Usage: {args[0]}"); return; } RR.WriteToConsole("Worlds:"); foreach (WorldConfigAsset worldConfigAsset in RR.WorldConfigsAssets) { RR.WriteToConsole($" {worldConfigAsset.Config.name}"); } } [RCCMD("connect", "Connects to a server with given Steam ID. Usage: connect ")] public static void ConnectToServer(string[] args) { if (args.Length < 1 || args.Length > 2) { RR.WriteToConsole($"Usage: {args[0]} "); return; } RR.WriteToConsole("Connecting to server..."); if (args.Length != 2) { RR.WriteToConsole($"Usage: {args[0]} "); return; } if (ulong.TryParse(args[1], out ulong steamID)) { RR.ConnectWithSteamID(steamID); } else { RR.WriteToConsole($"Invalid Steam ID: {args[1]}"); } } [RCCMD("disconnect", "Disconnects from the current server")] public static void DisconnectFromServer(string[] args) { if (args.Length != 1) { RR.WriteToConsole($"Usage: {args[0]}"); return; } RR.Disconnect(); } [RCCMD("version", "Displays the current game version")] public static void GameVersion(string[] args) { RR.WriteToConsole($"Game version: {Application.version}"); } } }