using System; using System.Collections.Generic; using UnityEngine; using AsyncOperation = UnityEngine.AsyncOperation; namespace MLAPI.SceneManagement { /// /// Class for tracking scene switching progress by server and clients. /// public class SceneSwitchProgress { /// /// List of clientIds of those clients that is done loading the scene. /// public List DoneClients { get; } = new List(); /// /// The NetworkTime time at the moment the scene switch was initiated by the server. /// public float TimeAtInitiation { get; } = NetworkManager.Singleton.NetworkTime; /// /// Delegate type for when the switch scene progress is completed. Either by all clients done loading the scene or by time out. /// public delegate void OnCompletedDelegate(bool timedOut); /// /// The callback invoked when the switch scene progress is completed. Either by all clients done loading the scene or by time out. /// public event OnCompletedDelegate OnComplete; /// /// Is this scene switch progresses completed, all clients are done loading the scene or a timeout has occured. /// public bool IsCompleted { get; private set; } /// /// If all clients are done loading the scene, at the moment of completed. /// public bool IsAllClientsDoneLoading { get; private set; } /// /// Delegate type for when a client is done loading the scene. /// public delegate void OnClientLoadedSceneDelegate(ulong clientId); /// /// The callback invoked when a client is done loading the scene. /// public event OnClientLoadedSceneDelegate OnClientLoadedScene; internal Guid Guid { get; } = Guid.NewGuid(); private Coroutine m_TimeOutCoroutine; private AsyncOperation m_SceneLoadOperation; internal SceneSwitchProgress() { m_TimeOutCoroutine = NetworkManager.Singleton.StartCoroutine(NetworkManager.Singleton.TimeOutSwitchSceneProgress(this)); } internal void AddClientAsDone(ulong clientId) { DoneClients.Add(clientId); OnClientLoadedScene?.Invoke(clientId); CheckCompletion(); } internal void RemoveClientAsDone(ulong clientId) { DoneClients.Remove(clientId); CheckCompletion(); } internal void SetSceneLoadOperation(AsyncOperation sceneLoadOperation) { m_SceneLoadOperation = sceneLoadOperation; m_SceneLoadOperation.completed += operation => CheckCompletion(); } internal void CheckCompletion() { if (!IsCompleted && DoneClients.Count == NetworkManager.Singleton.ConnectedClientsList.Count && m_SceneLoadOperation.isDone) { IsCompleted = true; IsAllClientsDoneLoading = true; NetworkSceneManager.SceneSwitchProgresses.Remove(Guid); OnComplete?.Invoke(false); NetworkManager.Singleton.StopCoroutine(m_TimeOutCoroutine); } } internal void SetTimedOut() { if (!IsCompleted) { IsCompleted = true; NetworkSceneManager.SceneSwitchProgresses.Remove(Guid); OnComplete?.Invoke(true); } } } }