using FishNet.Managing.Logging; using FishNet.Serializing.Helping; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; namespace FishNet.Managing.Scened { /// <summary> /// Extensions for SceneLookupData. /// </summary> internal static class SceneLookupDataExtensions { /// <summary> /// Returns Names from SceneLookupData. /// </summary> /// <param name="datas"></param> /// <returns></returns> public static string[] GetNames(this SceneLookupData[] datas) { string[] names = new string[datas.Length]; for (int i = 0; i < datas.Length; i++) names[i] = datas[i].Name; return names; } } /// <summary> /// Data container for looking up, loading, or unloading a scene. /// </summary> public class SceneLookupData { /// <summary> /// Handle of the scene. If value is 0, then handle is not used. /// </summary> public int Handle; /// <summary> /// Name of the scene. /// </summary> public string Name = string.Empty; /// <summary> /// Returns the scene name without a directory path should one exist. /// </summary> public string NameOnly => System.IO.Path.GetFileNameWithoutExtension(Name); /// <summary> /// Returns if this data is valid for use. /// Being valid does not mean that the scene exist, rather that there is enough data to try and lookup a scene. /// </summary> public bool IsValid => (Name != string.Empty || Handle != 0); #region Const /// <summary> /// String to display when scene data is invalid. /// </summary> private const string INVALID_SCENE = "One or more scene information entries contain invalid data and have been skipped."; #endregion /// <summary> /// /// </summary> public SceneLookupData() { } /// <summary> /// /// </summary> /// <param name="scene">Scene to generate from.</param> public SceneLookupData(Scene scene) { Handle = scene.handle; Name = scene.name; } /// <summary> /// /// </summary> /// <param name="name">Scene name to generate from.</param> public SceneLookupData(string name) { Name = name; } /// <summary> /// /// </summary> /// <param name="handle">Scene handle to generate from.</param> public SceneLookupData(int handle) { Handle = handle; } /// <summary> /// /// </summary> /// <param name="handle">Scene handle to generate from.</param> /// <param name="name">Name to generate from if handle is 0.</param> public SceneLookupData(int handle, string name) { Handle = handle; Name = name; } #region Comparers. public static bool operator ==(SceneLookupData sldA, SceneLookupData sldB) { //One is null while the other is not. if ((sldA is null) != (sldB is null)) return false; /*If here both are either null or have value. */ if (!(sldA is null)) return sldA.Equals(sldB); else if (!(sldB is null)) return sldB.Equals(sldA); //Fall through indicates both are null. return true; } public static bool operator !=(SceneLookupData sldA, SceneLookupData sldB) { //One is null while the other is not. if ((sldA is null) != (sldB is null)) return true; /*If here both are either null or have value. */ if (!(sldA is null)) return !sldA.Equals(sldB); else if (!(sldB is null)) return !sldB.Equals(sldA); //Fall through indicates both are null. return true; } public bool Equals(SceneLookupData sld) { //Comparing instanced against null. if (sld is null) return false; //True if both handles are empty. bool bothHandlesEmpty = ( (this.Handle == 0) && (sld.Handle == 0) ); //If both have handles and they match. if (!bothHandlesEmpty && sld.Handle == this.Handle) return true; //If neither have handles and name matches. else if (bothHandlesEmpty && sld.Name == this.Name) return true; //Fall through. return false; } public override int GetHashCode() { int hashCode = 2053068273; hashCode = hashCode * -1521134295 + Handle.GetHashCode(); hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Name); return hashCode; } public override bool Equals(object obj) { return base.Equals(obj); } public override string ToString() { return base.ToString(); } #endregion #region CreateData. /// <summary> /// Returns a new SceneLookupData. /// </summary> /// <param name="scene">Scene to create from.</param> /// <returns></returns> public static SceneLookupData CreateData(Scene scene) => new SceneLookupData(scene); /// <summary> /// Returns a new SceneLookupData. /// </summary> /// <param name="scene">Scene name to create from.</param> /// <returns></returns> public static SceneLookupData CreateData(string name) => new SceneLookupData(name); /// <summary> /// Returns a new SceneLookupData. /// </summary> /// <param name="scene">Scene handle to create from.</param> /// <returns></returns> public static SceneLookupData CreateData(int handle) => new SceneLookupData(handle); /// <summary> /// Returns a SceneLookupData collection. /// </summary> /// <param name="scenes">Scenes to create from.</param> /// <returns></returns> public static SceneLookupData[] CreateData(List<Scene> scenes) => CreateData(scenes.ToArray()); /// <summary> /// Returns a SceneLookupData collection. /// </summary> /// <param name="names">Scene names to create from.</param> /// <returns></returns> public static SceneLookupData[] CreateData(List<string> names) => CreateData(names.ToArray()); /// <summary> /// Returns a SceneLookupData collection. /// </summary> /// <param name="handles">Scene handles to create from.</param> /// <returns></returns> public static SceneLookupData[] CreateData(List<int> handles) => CreateData(handles.ToArray()); /// <summary> /// Returns a SceneLookupData collection. /// </summary> /// <param name="scenes">Scenes to create from.</param> /// <returns></returns> public static SceneLookupData[] CreateData(Scene[] scenes) { bool invalidFound = false; List<SceneLookupData> result = new List<SceneLookupData>(); foreach (Scene item in scenes) { if (!item.IsValid()) { invalidFound = true; continue; } result.Add(CreateData(item)); } if (invalidFound) NetworkManager.StaticLogWarning(INVALID_SCENE); return result.ToArray(); } /// <summary> /// Returns a SceneLookupData collection. /// </summary> /// <param name="names">Scene names to create from.</param> /// <returns></returns> public static SceneLookupData[] CreateData(string[] names) { bool invalidFound = false; List<SceneLookupData> result = new List<SceneLookupData>(); foreach (string item in names) { if (string.IsNullOrEmpty(item)) { invalidFound = true; continue; } string nameOnly = System.IO.Path.GetFileNameWithoutExtension(item); result.Add(CreateData(nameOnly)); } if (invalidFound) NetworkManager.StaticLogWarning(INVALID_SCENE); return result.ToArray(); } /// <summary> /// Returns a SceneLookupData collection. /// </summary> /// <param name="handles">Scene handles to create from.</param> /// <returns></returns> public static SceneLookupData[] CreateData(int[] handles) { bool invalidFound = false; List<SceneLookupData> result = new List<SceneLookupData>(); foreach (int item in handles) { if (item == 0) { invalidFound = true; continue; } result.Add(CreateData(item)); } if (invalidFound) NetworkManager.StaticLogWarning(INVALID_SCENE); return result.ToArray(); } #endregion /// <summary> /// Returns the first scene found using Handle or Name, preferring Handle. /// </summary> /// <returns></returns> /// <param name="foundByHandle">True if scene was found by handle. Handle is always checked first.</param> public Scene GetScene(out bool foundByHandle) { foundByHandle = false; if (Handle == 0 && string.IsNullOrEmpty(Name)) { NetworkManager.StaticLogWarning("Scene handle and name is unset; scene cannot be returned."); return default; } Scene result = default; //Lookup my handle. if (Handle != 0) { result = SceneManager.GetScene(Handle); if (result.handle != 0) foundByHandle = true; } //If couldnt find handle try by string. if (!foundByHandle) result = SceneManager.GetScene(NameOnly); return result; } } }