using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; public static class CommunicationEvents { public static UnityEvent<RaycastHit[]> TriggerEvent = new(); public static UnityEvent<RaycastHit[]> TriggerModFireEvent = new(); public static UnityEvent<int> ToolModeChangedEvent = new(); public static UnityEvent<Fact> AddFactEvent = new(); public static UnityEvent<Fact> RemoveFactEvent = new(); public static UnityEvent gameSucceededEvent = new(); public static UnityEvent gameNotSucceededEvent = new(); public static UnityEvent StartT0Event = new(); /** <summary>Inform ui that it should animate the given fact with the given material.</summary> */ public static UnityEvent<string, FactWrapper.FactMaterials> AnimateExistingFactEvent = new(); /** <summary>Start firework and invoke AnimateExistingFactEvent.</summary> */ public static UnityEvent<Fact, FactWrapper.FactMaterials> AnimateExistingAsSolutionEvent = new(); /** <summary>Show a missing fact for a short time as hint for the user.</summary> */ public static UnityEvent<Fact> AnimateNonExistingFactEvent = new(); //------------------------------------------------------------------------------------ //-------------------------------Global Variables------------------------------------- // TODO! move to GlobalStatic/Behaviour public static bool ServerAutoStart = true; public static bool ServerRunning = true; //CHANGE HERE PORT OF SERVER public static readonly string ServerPortDefault = "8085"; //used for Local public static readonly string ServerAddressLocal = "localhost:" + ServerPortDefault; // there is currently never a reason to change this. public static string ServerAdress = "http://localhost:8085"; //need "http://" //used by displayScrolls.cs //http://10.231.4.95:8085"; //IMPORTANT for MAINMENU public static Process process_mmt_frameIT_server; public static int ToolID_new; public static int ToolID_selected;//Script /// <summary> /// The Servers stored in NetworkJSON, as an enum to have consistent names.<br/> /// Why are <see cref="ServerSlot.last"/>,<see cref="ServerSlot.newIP"/> and /// <see cref="ServerSlot.selecIP"/> in here? Historical Reasons^TM <br/> /// If one wants to optimize things, it is likely advisable to make them variables instead. /// But this also requires changing the read/write of NetworkJSON, and likely more ... /// </summary> [System.Serializable] public enum ServerSlot {// The numbers are due to legacy code, specifically ServerRunningA indices last = 1, newIP = 2, slot1 = 3, slot2 = 4, slot3 = 5, selecIP = 6, slot4 = 7, slot5 = 8, localServer } /// <summary> /// The status of a <c>ServerSlot</c> in <see cref="ServerSlots"/> /// </summary> public enum ServerStatus {// The numbers are due to legacy code, specifically ServerRunningA values offline = 0, online = 2, checking = 1, NoNetworkAddress = 3 } /// <summary> /// All data to a Server stored in a Server /// </summary> public class ServerSlotData { public string domain; public ServerStatus currentStatus = ServerStatus.offline; public bool hasBeenChecked = false; //Define constructor via expression body definition public ServerSlotData(string serverURL) => domain = serverURL; /// <summary> /// Ping the server to see if it is online. /// Start as a <c>Coroutine</c>, because this involves a <c>WebRequest</c> /// </summary> public IEnumerator UpdateServerStatus(bool skipIfAlreadyChecked = false) { if (skipIfAlreadyChecked && hasBeenChecked) { yield break; // Skip, if not neccessary } currentStatus = ServerStatus.checking; ServerSlot myKey = ServerSlots.FirstOrDefault(x => x.Value == this).Key; if (string.IsNullOrEmpty(domain)) { currentStatus = ServerStatus.NoNetworkAddress; UnityEngine.Debug.LogWarning("Server " + myKey.ToString() + " has no network adress."); } else { UnityWebRequest request = UnityWebRequest.Get("http://" + domain + "/fact/list"); yield return request.SendWebRequest(); if (request.result == UnityWebRequest.Result.Success) { currentStatus = ServerStatus.online; } else { UnityEngine.Debug.Log("Couldn't connect to Server " + myKey.ToString() + " under " + domain + " : " + request.error + "\n"); currentStatus = ServerStatus.offline; //try again //request.Dispose(); //request = pingMMTServer(NetwAddress); //yield return request.SendWebRequest(); //request.Dispose(); } request.Dispose(); } hasBeenChecked = true; // To keep ServerRunningA updated. Delete if you saved the world from that abomination ServerRunningA[(int)myKey] = (int)currentStatus; } } /// <summary> /// Gather the <see cref="ServerSlotData"/> of all <see cref="ServerSlot"/> in one place, so one can iterate over all of them.<br/> /// <remarks><list type="bullet"> /// <item><seealso cref="LastIP"/>, <seealso cref="SelecIP"/> and alike offer more compact access to the domains.</item> /// <item>Accessing other data in this Dict is kind of ugly, but I cannot think of a much better way to implement it, as it shoud be iteratable and indexable.</item> /// </list> </remarks> /// </summary> public static Dictionary<ServerSlot, ServerSlotData> ServerSlots = new() { { ServerSlot.last, new ServerSlotData("") }, { ServerSlot.newIP, new ServerSlotData("") }, { ServerSlot.slot1, new ServerSlotData("- if you can read this") }, { ServerSlot.slot2, new ServerSlotData("- NetworkConfig") }, { ServerSlot.slot3, new ServerSlotData("- GO TO -> 'Options'") }, { ServerSlot.slot4, new ServerSlotData("- -> 'Reset Options'") }, { ServerSlot.slot5, new ServerSlotData("- -> PRESS: 'Reset Configurations'") }, { ServerSlot.selecIP, new ServerSlotData("") }, { ServerSlot.localServer, new ServerSlotData(ServerAddressLocal) } }; /// <summary> /// Iterate over all members of <see cref="ServerSlots"/> and have them update their <see cref="ServerSlotData.currentStatus"/><br/> /// <br/> /// Currently it is not possible to only load the domains via <see cref="StreamingAssetLoader.NetworkJSON_Load_x(string)"/>. If this changes, it might make sense to call the initial loading of the domains from in here. /// </summary> public static IEnumerator UpdateAllServers() { foreach (ServerSlotData server in ServerSlots.Values) { yield return server.UpdateServerStatus(); } } //Enum.GetNames(typeof(KnownServers)).Length; //Number of known Server slots, to be able to add more later /* * will be loaded from other config file, * and I am not going to refactor all of this as well, so just an indirection. * * LastIP and SelecIP are likely useful shortcuts to the most relevant parts of 'ServerSlots' above, anyway. * * (Also those are domain names (+ port) not IPs) */ public static string LastIP { get => ServerSlots[ServerSlot.last].domain; set => ServerSlots[ServerSlot.last].domain = value; } public static string NewIP { get => ServerSlots[ServerSlot.newIP].domain; set => ServerSlots[ServerSlot.newIP].domain = value; } public static string IPslot1 { get => ServerSlots[ServerSlot.slot1].domain; set => ServerSlots[ServerSlot.slot1].domain = value; } public static string IPslot2 { get => ServerSlots[ServerSlot.slot2].domain; set => ServerSlots[ServerSlot.slot2].domain = value; } public static string IPslot3 { get => ServerSlots[ServerSlot.slot3].domain; set => ServerSlots[ServerSlot.slot3].domain = value; } public static string IPslot4 { get => ServerSlots[ServerSlot.slot4].domain; set => ServerSlots[ServerSlot.slot4].domain = value; } public static string IPslot5 { get => ServerSlots[ServerSlot.slot5].domain; set => ServerSlots[ServerSlot.slot5].domain = value; } public static string SelecIP { get => ServerSlots[ServerSlot.selecIP].domain; set => ServerSlots[ServerSlot.selecIP].domain = value; } /// <summary> /// IF YOU NEED THIS DATA, USE THE <see cref="ServerSlotData.currentStatus"/> OF THE <see cref="ServerSlots"/> MEMBERS.<br/> /// Holds the status of the stored Servers.<br/> /// This is acts like a function <see cref="ServerSlot"/> -> <see cref="ServerStatus"/> with a dont-care value at index 0.<br/> /// There are so many references to this abomination that I will leave it here and just update it, to be consistent with /// <see cref="ServerSlots"/>. /// </summary> public static int[] ServerRunningA = new int[10] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; //other, lastIP, newIP, IP1, IP2, IP3, selecIP, IP4, IP5,...} //0: offline, 1: Checking, 2: online, 3: NoNetworkAddress; //------ public static bool autoOSrecognition = true; public static OperationSystem Opsys = OperationSystem.Windows; //Scripts public enum OperationSystem { Windows = 0, Android = 1, iOS = 2, WindowsStoreApps = 3, } public static bool CursorVisDefault = true; //Script. public static bool CursorVisLastUsedIngame = true; //Script. public static bool GadgetCanBeUsed = false; // Configs public static bool VerboseURI = false; public enum Directories { misc, Stages, SaveGames, ValidationSets, FactStateMachines, } public static string CreateHierarchiePath(List<Directories> hierarchie, string prefix = "", string postfix = "") { foreach (var dir in hierarchie) prefix = Path.Combine(prefix, dir.ToString()); return Path.Combine(prefix, postfix); } public static string Get_DataPath() { bool use_replacementfolder = false; if (Application.isEditor) return use_replacementfolder ? Path.Combine(Application.persistentDataPath, "DataPath_writeable") : Path.Combine(Application.dataPath, "StreamingAssets", "StreamToDataPath_withHandler"); return Opsys switch { OperationSystem.Android => Path.Combine(Application.persistentDataPath, "DataPath_writeable"), OperationSystem.Windows or _ => Application.dataPath, }; } // TODO! avoid tree traversel with name public static string CreatePathToFile(out bool file_exists, string name, string format = null, List<Directories> hierarchie = null, bool use_install_folder = false) { string ending = ""; if (!string.IsNullOrEmpty(format)) switch (format) { case "JSON": ending = ".JSON"; break; default: break; } string path = use_install_folder ? Get_DataPath() : Application.persistentDataPath; if (hierarchie != null) { path = CreateHierarchiePath(hierarchie, path); Directory.CreateDirectory(path); } path = Path.Combine(path, name + ending); file_exists = File.Exists(path); return path; } }