using System.Collections; using System.Collections.Generic; using System.Linq; using FishNet; using FishNet.Connection; using FishNet.Managing.Scened; using FishNet.Object; using Managers; using UI; using UnityEngine; using UnityEngine.EventSystems; using Utils; public class SceneLoader : NetworkBehaviour, IPointerClickHandler { private static readonly Dictionary playerScenes = new(); [SerializeField] public string sceneName; [SerializeField] public Vector3 spawnPosition; private int _stackedSceneHandle; private void Awake() { } private void Start() { InstanceFinder.SceneManager.OnLoadEnd += SceneManager_OnLoadEnd; } private void OnDestroy() { if (InstanceFinder.SceneManager != null) InstanceFinder.SceneManager.OnLoadEnd -= SceneManager_OnLoadEnd; } private void OnCollisionEnter(Collision collision) { GameLogger.Log("OnCollisionEnter triggered"); } private void OnTriggerEnter2D(Collider2D other) { GameLogger.Log("OnTriggerEnter triggered"); if (!IsClientInitialized) return; GameTimeManager.Instance.Pause(); LoadingScreenUIController.Instance.TriggerLoadingScreen(); GameLogger.Log("On Trigger ENTERED"); var nob = other.gameObject.GetComponent(); // GameLogger.Log("Player with clientID " + other.gameObject.GetInstanceID() + " entered trigger"); var otherConnection = other.GetComponent().Owner; GameLogger.Log("Player with clientID " + otherConnection.ClientId + " entered trigger"); // if (nob != null) LoadScene(InstanceFinder.ClientManager.Connection.ClientId); RequestSceneLoadServerRpc(otherConnection.ClientId); GameTimeManager.Instance.Resume(); } public void OnPointerClick(PointerEventData eventData) { /*if (!IsOwner) { GameLogger.Log("Not local player owner, not loading scene"); return; }*/ GameLogger.Log("Clicked scene loader"); var clientId = InstanceFinder.ClientManager.Connection.ClientId; GameLogger.Log("Player with clientID " + clientId + " clicked scene loader"); LoadScene(clientId); } [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] private static void ResetStaticData() { playerScenes.Clear(); Debug.Log("SceneLoader: playerScenes dictionary has been cleared."); } [ServerRpc(RequireOwnership = false)] public void RequestSceneLoadServerRpc(int clientId) { if (!IsServerInitialized) { GameLogger.LogWarning( "RequestSceneLoadServerRpc called on client. This should only be called on the server."); return; } if (!InstanceFinder.ServerManager.Clients.ContainsKey(clientId)) { GameLogger.LogWarning( $"Client {clientId} not found in ServerManager.Clients. The client might not be fully connected yet."); return; } LoadSceneForClient(clientId); } /*[Server] private void LoadSceneForClient(int clientId) { GameLogger.Log($"Loading scene for client {clientId}"); var connection = InstanceFinder.ServerManager.Clients[clientId]; if (connection == null) { GameLogger.LogError($"No connection found for client {clientId}"); return; } var sceneLoadData = new SceneLoadData(SceneLookupData.CreateData(sceneName)); sceneLoadData.ReplaceScenes = ReplaceOption.All; sceneLoadData.Options.AllowStacking = true; // Allow multiple scene instances InstanceFinder.SceneManager.LoadConnectionScenes(connection, sceneLoadData); // Unload the previous scene for this client if (playerScenes.TryGetValue(clientId, out var previousScene)) InstanceFinder.SceneManager.UnloadConnectionScenes(connection, new SceneUnloadData(previousScene)); // Update the player's current scene playerScenes[clientId] = sceneName; // Move the player to the spawn position var playerManager = PlayerManager.GetPlayerManager(clientId); if (playerManager != null) { var player = playerManager.GetPlayerGo(); if (player != null) { player.transform.position = spawnPosition; UpdatePlayerPositionObserversRpc(clientId, spawnPosition); } } }*/ private void SceneManager_OnLoadEnd(SceneLoadEndEventArgs data) { if (!data.QueueData.AsServer) return; if (_stackedSceneHandle != 0) return; if (data.LoadedScenes.Length > 0) _stackedSceneHandle = data.LoadedScenes[0].handle; } public override void OnStartServer() { GameLogger.Log("SceneLoader OnStartServer"); base.OnStartServer(); // var networkObject = GetComponent(); // if (networkObject != null) networkObject.GiveOwnership(NetworkManager.ServerManager.Clients[0]); } [ServerRpc(RequireOwnership = false)] private void LoadScene(int clientId) { GameLogger.Log("Loading scene"); var sceneLoadData = new SceneLoadData(SceneLookupData.CreateData(sceneName)); sceneLoadData.ReplaceScenes = ReplaceOption.None; sceneLoadData.Options.AllowStacking = false; InstanceFinder.SceneManager.LoadConnectionScenes(InstanceFinder.ClientManager.Connection, sceneLoadData); InstanceFinder.SceneManager.UnloadConnectionScenes(InstanceFinder.ClientManager.Connection, new SceneUnloadData("StartMenu")); // GameLogger.Log("Moving player to spawn position for clientId" + clientId); // MovePlayerToSpawnPositionServerRpc(clientId); // StartCoroutine(MovePlayerToSpawnPosition(clientId)); var player = PlayerManager.GetPlayerManager(clientId).GetPlayerGo(); var playerCamera = PlayerManager.GetPlayerManager(clientId).GetPlayerCamera(); // get players network object if (player == null) { GameLogger.LogError("Player is null, can not move player to spawn position"); return; } GameLogger.Log("Moving player to spawn position: " + spawnPosition); player.transform.position = spawnPosition; playerCamera.gameObject.SetActive(true); // if (Camera.main != null) Camera.main.gameObject.SetActive(false); // playerCamera.gameObject.SetActive(true); UpdatePlayerPositionObserversRpc(player.gameObject.GetInstanceID(), spawnPosition); SetupPlayerCameraObserversRpc(clientId); } [ObserversRpc] private void SetupPlayerCameraObserversRpc(int clientId) { GameLogger.Log("Setting up player camera for clientId: " + clientId); var playerManager = PlayerManager.GetPlayerManager(clientId); if (playerManager == null) { GameLogger.LogError("PlayerManager not found for client " + clientId); return; } var playerGo = playerManager.GetPlayerGo(); if (playerGo == null) { GameLogger.LogError("PlayerGo not found for client " + clientId); return; } var camera = playerGo.GetComponentInChildren(); if (camera == null) { GameLogger.LogError("Camera not found for client " + clientId); return; } // enable camera only for the local player camera.enabled = true; Camera.main.gameObject.SetActive(false); camera.tag = "MainCamera"; playerManager.SetupCamera(); } // [ServerRpc(RequireOwnership = false)] // private void MovePlayerToSpawnPositionServerRpc(int clientId) // { // GameLogger.Log("Preparing to move player to spawn position (SERVERRPC) for clientId " + clientId); // StartCoroutine(MovePlayerToSpawnPosition(clientId)); // } // private IEnumerator MovePlayerToSpawnPosition(int clientId) // { // // yield return new WaitForEndOfFrame(); // // wait until the scence is finished loading // // yield return new WaitUntil(() => InstanceFinder.SceneManager // yield return new WaitForSeconds(0.5f); // Wait a short time to ensure everything is set up // // var player = PlayerManager.GetPlayerManager(clientId).GetPlayerGo(); // // get players network object // // if (player == null) // { // GameLogger.LogError("Player is null, can not move player to spawn position"); // yield return null; // } // // if (player != null) // { // GameLogger.Log("Moving player to spawn position: " + spawnPosition); // player.transform.position = spawnPosition; // // UpdatePlayerPositionObserversRpc(player.gameObject.GetInstanceID(), spawnPosition); // } // } // Get all scenes loaded for this connection [ServerRpc(RequireOwnership = false)] private void UnloadPreviousSceneServerRpc(NetworkConnection connection, string newSceneName) { var sceneConnections = InstanceFinder.SceneManager.SceneConnections; foreach (var kvp in sceneConnections) { var scene = kvp.Key; var connections = kvp.Value; // Check if this scene is loaded for the current connection if (connections.Contains(connection)) // Unload all scenes except the new one and any persistent scenes /*if (scene.name != newSceneName && !scene.name.Equals("PersistentScene")) { var unloadSceneData = new SceneUnloadData(scene.name); InstanceFinder.SceneManager.UnloadConnectionScenes(connection, unloadSceneData); }*/ // unload scenes where no players are connected if (scene.name != newSceneName) { var unloadSceneData = new SceneUnloadData(scene.name); InstanceFinder.SceneManager.UnloadConnectionScenes(connection, unloadSceneData); } } } [ObserversRpc] private void UpdatePlayerPositionObserversRpc(int playerObjectId, Vector3 position) { GameLogger.Log("Moving player to spawn position: " + spawnPosition); if (InstanceFinder.ClientManager.Objects.Spawned.TryGetValue(playerObjectId, out var playerObject)) playerObject.transform.position = position; else GameLogger.LogWarning("Player not found"); } [Server] private void LoadSceneForClient(int clientId) { GameLogger.Log($"Received scene load request for client {clientId}"); var connection = InstanceFinder.ServerManager.Clients[clientId]; if (connection == null) { GameLogger.LogError($"No connection found for client {clientId}"); return; } var sceneLoadData = new SceneLoadData(SceneLookupData.CreateData(sceneName)); sceneLoadData.ReplaceScenes = ReplaceOption.All; sceneLoadData.Options.AllowStacking = true; // Subscribe to the OnLoadEnd event // InstanceFinder.SceneManager.OnLoadEnd += OnSceneLoadEnd; // Start loading the scene InstanceFinder.SceneManager.LoadConnectionScenes(connection, sceneLoadData); StartCoroutine(WaitForSceneLoad(clientId)); } private IEnumerator WaitForSceneLoad(int clientId) { GameLogger.Log("Waiting for scene load for client " + clientId); var timeout = 10f; var elapsedTime = 0f; while (elapsedTime < timeout) { var sceneFound = !InstanceFinder.SceneManager.SceneConnections.Any(sc => sc.Key.name == sceneName && sc.Value.Contains(InstanceFinder.ServerManager.Clients[clientId])); // GameLogger.Log("Waiting for scene load for client " + clientId); GameLogger.Log("Looking for scene " + sceneName); if (sceneFound) { GameLogger.Log("Scene found for client " + clientId); OnSceneLoadComplete(clientId); yield break; } elapsedTime += Time.deltaTime; yield return null; } GameLogger.LogError("Timed out waiting for scene load for client " + clientId); } private IEnumerator LoadSceneWithRetry(NetworkConnection connection, SceneLoadData sceneLoadData, int clientId, int maxRetries = 3) { var retryCount = 0; var loadSuccessful = false; while (!loadSuccessful && retryCount < maxRetries) { GameLogger.Log($"Attempting to load scene for client {clientId}. Attempt {retryCount + 1} of {maxRetries}"); InstanceFinder.SceneManager.LoadConnectionScenes(connection, sceneLoadData); // Wait for the scene to load yield return new WaitUntil(() => InstanceFinder.SceneManager.SceneConnections.Any(sc => sc.Key.name == sceneName && sc.Value.Contains(connection))); if (InstanceFinder.SceneManager.SceneConnections.Any(sc => sc.Key.name == sceneName && sc.Value.Contains(connection))) { loadSuccessful = true; GameLogger.Log($"Scene successfully loaded for client {clientId}"); } else { retryCount++; GameLogger.LogWarning($"Scene load attempt failed for client {clientId}. Retrying..."); yield return new WaitForSeconds(1f); // Wait before retrying } } if (!loadSuccessful) GameLogger.LogError($"Failed to load scene for client {clientId} after {maxRetries} attempts"); } private void OnSceneLoadComplete(int clientId) { GameLogger.Log($"Scene load completed for client {clientId}"); // Unload the previous scene for this client if (playerScenes.TryGetValue(clientId, out var previousScene)) { GameLogger.Log($"Unloading previous scene for client {clientId}: {previousScene}"); var connection = InstanceFinder.ServerManager.Clients[clientId]; InstanceFinder.SceneManager.UnloadConnectionScenes(connection, new SceneUnloadData(previousScene)); } // Update the player's current scene playerScenes[clientId] = sceneName; // Move the player to the spawn position var playerManager = PlayerManager.GetPlayerManager(clientId); if (playerManager != null) { var player = playerManager.GetPlayerGo(); if (player != null) { player.transform.position = spawnPosition; UpdatePlayerPositionObserversRpc(clientId, spawnPosition); SetupPlayerCameraObserversRpc(clientId); } } else { GameLogger.LogError("PlayerManager not found for client " + clientId); } } public void UnloadScene() { // if (_stackedScenceHandle == 0) // return; // InstanceFinder.SceneManager.UnloadScene(_stackedScenceHandle); // _stackedScenceHandle = 0; } }