using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Fusion; using Fusion.Sockets; using UnityEngine; using OnlyScove.Scripts; namespace Hallucinate.UI { public class _BasicSpawner : MonoBehaviour, INetworkRunnerCallbacks { private NetworkRunner _runner { get; set; } public event Action> OnSessionListUpdatedEvent; public event Action OnShutdownEvent; public event Action OnJoinStartedEvent; public event Action OnJoinFailedEvent; private void Awake() { if (_runner == null) _runner = gameObject.AddComponent(); DontDestroyOnLoad(gameObject); } public _PlayerProfile LocalPlayerProfile { get; private set; } public void SetLocalPlayerProfile(_PlayerProfile _profile) { LocalPlayerProfile = _profile; } public async Task StartLobby() { if (_runner == null) _runner = gameObject.AddComponent(); _runner.ProvideInput = true; _runner.AddCallbacks(this); var result = await _runner.JoinSessionLobby(SessionLobby.ClientServer); if (!result.Ok) Debug.LogError($"Failed to join lobby: {result.ShutdownReason}"); } public async Task StartHost(string sessionName, string password = null) { OnJoinStartedEvent?.Invoke(); var customProps = new Dictionary(); if (!string.IsNullOrEmpty(password)) { customProps.Add("pw", password); } var result = await _runner.StartGame(new StartGameArgs() { GameMode = GameMode.Host, SessionName = sessionName, SessionProperties = customProps, PlayerCount = 2, SceneManager = gameObject.AddComponent() }); if (!result.Ok) { Debug.LogError($"Failed to start host: {result.ShutdownReason}"); OnJoinFailedEvent?.Invoke(); } } public async Task StartClient(string sessionName, string password = null) { OnJoinStartedEvent?.Invoke(); var result = await _runner.StartGame(new StartGameArgs() { GameMode = GameMode.Client, SessionName = sessionName, SceneManager = gameObject.AddComponent() }); if (!result.Ok) { Debug.LogError($"Failed to join client: {result.ShutdownReason}"); OnJoinFailedEvent?.Invoke(); } } [SerializeField] private NetworkPrefabRef _playerPrefab; private Dictionary _spawnedCharacters = new Dictionary(); public void OnPlayerJoined(NetworkRunner runner, PlayerRef player) { if (player == runner.LocalPlayer) { var pdm = FindFirstObjectByType<_PlayerDataManager>(); if (pdm != null) { var metaData = new _PlayerMetaData() { Name = LocalPlayerProfile.Name, Role = LocalPlayerProfile.Role, IsReady = false }; pdm.RPC_UpdatePlayerMetaData(player, metaData); } } } public void StartGame() { if (_runner.IsServer) { _runner.LoadScene("Main Scene"); } } public void OnPlayerLeft(NetworkRunner runner, PlayerRef player) { if (_spawnedCharacters.TryGetValue(player, out NetworkObject networkObject)) { runner.Despawn(networkObject); _spawnedCharacters.Remove(player); if (runner.IsServer) runner.Shutdown(); } } public void OnShutdown(NetworkRunner runner, ShutdownReason shutdownReason) { OnShutdownEvent?.Invoke(shutdownReason.ToString()); } public void OnSessionListUpdated(NetworkRunner runner, List sessionList) { OnSessionListUpdatedEvent?.Invoke(sessionList); } public void OnInput(NetworkRunner runner, NetworkInput input) { var data = new PlayerInputData(); // Try to get input from the local player's InputReader if (PlayerStateMachine.Local != null && PlayerStateMachine.Local.Input != null) { var inputReader = PlayerStateMachine.Local.Input; data.Direction = inputReader.MoveInput; data.sprint = inputReader.IsSprintHeld; if (PlayerStateMachine.Local.Cam != null) { data.rot = PlayerStateMachine.Local.Cam.PlanarRotation; } } else { // Fallback to basic input if player not spawned or InputReader missing data.Direction = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")); data.sprint = Input.GetKey(KeyCode.LeftShift); } input.Set(data); } public void OnConnectedToServer(NetworkRunner runner) { } public void OnDisconnectedFromServer(NetworkRunner runner, NetDisconnectReason reason) { } public void OnConnectRequest(NetworkRunner runner, NetworkRunnerCallbackArgs.ConnectRequest request, byte[] token) { } public void OnConnectFailed(NetworkRunner runner, NetAddress remoteAddress, NetConnectFailedReason reason) { } public void OnUserSimulationMessage(NetworkRunner runner, SimulationMessagePtr message) { } public void OnReliableDataReceived(NetworkRunner runner, PlayerRef player, ReliableKey key, ArraySegment data) { } public void OnReliableDataProgress(NetworkRunner runner, PlayerRef player, ReliableKey key, float progress) { } public void OnInputMissing(NetworkRunner runner, PlayerRef player, NetworkInput input) { } public void OnObjectExitAOI(NetworkRunner runner, NetworkObject obj, PlayerRef player) { } public void OnObjectEnterAOI(NetworkRunner runner, NetworkObject obj, PlayerRef player) { } public void OnCustomAuthenticationResponse(NetworkRunner runner, Dictionary data) { } public void OnHostMigration(NetworkRunner runner, HostMigrationToken hostMigrationToken) { } public void OnSceneLoadDone(NetworkRunner runner) { string currentSceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name; if (runner.IsServer && currentSceneName == "Main Scene") { foreach (var player in runner.ActivePlayers) { Vector2 spawnPosition = (player == runner.LocalPlayer) ? new Vector2(-8, 0) : new Vector2(8, 0); var networkPlayerObject = runner.Spawn(_playerPrefab, spawnPosition, Quaternion.identity, player); _spawnedCharacters.Add(player, networkPlayerObject); } } if (currentSceneName == "Main Scene") { if (UIManager.Instance != null) UIManager.Instance.OnGameStarted(); } else if (currentSceneName == "Lobby" || currentSceneName == "Menu") { if (UIManager.Instance != null) UIManager.Instance.OnBackToMenu(); } } public void OnSceneLoadStart(NetworkRunner runner) { } } }