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);
}
}
}
}