void Awake() { Debug.Log ("SQUARE"); squareMatrixScript = GameObject.FindGameObjectWithTag ("Block").GetComponent<SquareMatrix> (); gadgetsScript = GameObject.FindGameObjectWithTag ("Gadgets").GetComponent<Gadgets> (); initSquare (); initMazeMatrix (); }
void Awake() { progressBar = GameObject.Find ("ProgressBar").guiTexture; currWidth = barWidth = Screen.width; barHeight = Screen.width/14; seconds = 60.0f; currWidth = barWidth; fadeDuration = 2.0f; startColor = guiTexture.color; endColor = Color.red; transform.position = Vector3.zero; transform.localScale = Vector3.zero; squareMatrixScript = GameObject.FindGameObjectWithTag ("Block").GetComponent<SquareMatrix> (); gadgetsScript = GameObject.FindGameObjectWithTag ("Gadgets").GetComponent<Gadgets> (); freezeSeconds = 0f; }
private bool IsRestartNeeded() { if (unpackedMods.Count > 0) { return(true); } int umfModCount = umfModEntries?.Count ?? 0; foreach (GadgetInfo gadget in Gadgets.ListAllGadgetInfos()) { if (GadgetCoreConfig.enabledGadgets[gadget.Attribute.Name] != gadget.Gadget.Enabled) { return(true); } if (originalConfig.ContainsKey(gadget.Attribute.Name)) { if (!originalConfig[gadget.Attribute.Name].Equals(File.ReadAllText(GadgetPaths.ConfigsPath + "/" + Gadgets.GetGadgetInfo(modIndex).Mod.Name + ".ini"))) { return(true); } } } if (GadgetCoreAPI.GetUMFAPI() != null) { if (!File.Exists(GadgetCoreAPI.GetUMFAPI().GetDisabledModsFile())) { File.Create(GadgetCoreAPI.GetUMFAPI().GetDisabledModsFile()).Dispose(); } string[] disabledMods = File.ReadAllLines(GadgetCoreAPI.GetUMFAPI().GetDisabledModsFile()).Where(x => !string.IsNullOrEmpty(x)).ToArray(); for (int i = 0; i < umfModEntries.Count; i++) { if (wasEnabled.ContainsKey(umfModEntries[i].Name)) { if (wasEnabled[umfModEntries[i].Name] == disabledMods.Contains(umfModEntries[i].Name)) { return(true); } } if (originalConfig.ContainsKey(umfModEntries[i].Name)) { if (!originalConfig[umfModEntries[i].Name].Equals(File.ReadAllText(GadgetCoreAPI.GetUMFAPI().GetConfigsPath() + "/" + umfModEntries[i].Name + ".ini"))) { return(true); } } } } return(false); }
internal void SendRequiredModList(string modList, NetworkMessageInfo info) { try { bool isCompatible = true; int modCount = 0; string[][] splitModList = string.IsNullOrEmpty(modList) ? new string[0][] : modList.Split(',').Select(x => x.Split(':')).ToArray(); foreach (GadgetInfo mod in Gadgets.ListAllGadgetInfos().Where(x => x.Gadget.Enabled && x.Attribute.RequiredOnClients)) { modCount++; int[] hostVersionNums = mod.Gadget.GetModVersionString().Split('.').Select(x => int.Parse(x)).ToArray(); int[] clientVersionNums = splitModList.SingleOrDefault(x => x[0] == mod.Attribute.Name)?[1].Split('.').Select(x => int.Parse(x)).Take(4).ToArray(); if (clientVersionNums == null) { isCompatible = false; break; } hostVersionNums = hostVersionNums.Concat(Enumerable.Repeat(0, 4 - hostVersionNums.Length)).ToArray(); clientVersionNums = clientVersionNums.Concat(Enumerable.Repeat(0, 4 - clientVersionNums.Length)).ToArray(); if (!((mod.Attribute.GadgetCoreVersionSpecificity == VersionSpecificity.MAJOR && clientVersionNums[0] == hostVersionNums[0] && (clientVersionNums[1] > hostVersionNums[1] || (clientVersionNums[1] == hostVersionNums[1] && (clientVersionNums[2] > hostVersionNums[2] || (clientVersionNums[2] == hostVersionNums[2] && clientVersionNums[3] >= hostVersionNums[3]))))) || (mod.Attribute.GadgetCoreVersionSpecificity == VersionSpecificity.MINOR && clientVersionNums[0] == hostVersionNums[0] && clientVersionNums[1] == hostVersionNums[1] && (clientVersionNums[2] > hostVersionNums[2] || (clientVersionNums[2] == hostVersionNums[2] && clientVersionNums[3] >= hostVersionNums[3]))) || (mod.Attribute.GadgetCoreVersionSpecificity == VersionSpecificity.NONBREAKING && clientVersionNums[0] == hostVersionNums[0] && clientVersionNums[1] == hostVersionNums[1] && clientVersionNums[2] == hostVersionNums[2] && clientVersionNums[3] >= hostVersionNums[3]) || (mod.Attribute.GadgetCoreVersionSpecificity == VersionSpecificity.BUGFIX && clientVersionNums[0] == hostVersionNums[0] && clientVersionNums[1] == hostVersionNums[1] && clientVersionNums[2] == hostVersionNums[2] && clientVersionNums[3] == hostVersionNums[3]))) { isCompatible = false; break; } } if (isCompatible && modCount != splitModList.Length) { isCompatible = false; } if (isCompatible) { if (string.IsNullOrEmpty(info.sender.ipAddress)) { GadgetCore.CoreLogger.Log("Self-connection succesfully established and identified."); ReceiveIDMatrixData(GadgetNetwork.GenerateIDMatrixData()); } else { GadgetCore.CoreLogger.Log("A client connected with compatible mods: " + info.sender.ipAddress); view.RPC("ReceiveIDMatrixData", info.sender, GadgetNetwork.GenerateIDMatrixData()); } } else { GadgetCore.CoreLogger.LogWarning("A client tried to connect with incompatible mods: " + info.sender.ipAddress + Environment.NewLine + modList); if (Network.isServer) { Network.CloseConnection(info.sender, true); } else { Network.Disconnect(); } } } catch (Exception e) { GadgetCore.CoreLogger.LogWarning("The following error occured processing an incoming client's mod list: " + info.sender.ipAddress + Environment.NewLine + modList + Environment.NewLine + e.ToString()); if (Network.isServer) { Network.CloseConnection(info.sender, true); } else { Network.Disconnect(); } } }
private static void VerifyCompatible(NetworkPlayer pl) { if (!GadgetNetwork.MatrixReady && GadgetNetwork.GetTimeSinceConnect() > GadgetNetwork.MatrixTimeout && Gadgets.ListAllGadgetInfos().Any(x => x.Attribute.RequiredOnClients)) { Network.CloseConnection(pl, true); } }
private void OnSelectAllExecute() { Gadgets.ForEach(x => x.IsSelected = true); }
public static bool Prefix(GameScript __instance) { if (!GadgetNetwork.MatrixReady && GadgetNetwork.GetTimeSinceConnect() < GadgetNetwork.MatrixTimeout) { if (InstanceTracker.GameScript.gameObject.GetComponent <RPCHooks>() == null) { InstanceTracker.GameScript.gameObject.AddComponent <RPCHooks>(); } RPCHooks.InitiateGadgetNetwork(); __instance.StartCoroutine(WaitAndTryAgain(__instance)); return(false); } else { if (GadgetNetwork.GetTimeSinceConnect() > GadgetNetwork.MatrixTimeout && Gadgets.ListAllGadgetInfos().Any(x => x.Attribute.RequiredOnClients)) { GadgetCore.CoreLogger.LogWarning("Disconnecting from server due to timout! You can try raising NetworkTimeout in the config."); Network.Disconnect(); return(false); } return(true); } }
private void RefreshGadgets() { Gadgets.Clear(); service.GetAllGadgets().ForEach(g => Gadgets.Add(g)); }
private static void LoadGadgetMod(GadgetMod mod) { Logger.Log("Loading mod '" + mod.Name + "'"); if (mod.ModDependencies.Any(x => GadgetMods.GetModByName(x) == null)) { m_IncompatibleMods.Add(mod); Logger.LogWarning("Aborted loading mod '" + mod.Name + "' because of the following missing dependencies: " + mod.ModDependencies.Where(x => GadgetMods.GetModByName(x) == null).Concat()); return; } Type[] gadgetTypes = mod.Assembly.GetExportedTypes().Where(x => x.IsSubclassOf(typeof(Gadget)) && x.GetCustomAttributes(typeof(GadgetAttribute), true).FirstOrDefault() != null).ToArray(); if (gadgetTypes.Length == 0) { m_EmptyMods.Add(mod); Logger.LogWarning("Aborted loading mod '" + mod.Name + "' because it does not contain any Gadgets"); } mod.m_LoadedGadgets = new List <GadgetInfo>(); mod.LoadedGadgets = new ReadOnlyCollection <GadgetInfo>(mod.m_LoadedGadgets); mod.m_UnloadedGadgets = new List <GadgetInfo>(); mod.UnloadedGadgets = new ReadOnlyCollection <GadgetInfo>(mod.m_UnloadedGadgets); for (int i = 0; i < gadgetTypes.Length; i++) { Type type = gadgetTypes[i]; GadgetAttribute attribute = (GadgetAttribute)type.GetCustomAttributes(typeof(GadgetAttribute), true).FirstOrDefault(); if (mod.m_LoadedGadgets.Any(x => x.Attribute.Name == attribute.Name)) { throw new InvalidOperationException("It is illegal for a mod to contain multiple Gadgets with the same name: " + attribute.Name); } int[] targetVersionNums = attribute.TargetGCVersion.Split('.').Select(x => int.Parse(x)).ToArray(); if (targetVersionNums.Length != 4) { Array.Resize(ref targetVersionNums, 4); } if ((attribute.GadgetCoreVersionSpecificity == VersionSpecificity.MAJOR && GadgetCoreAPI.currentVersionNums[0] == targetVersionNums[0] && (GadgetCoreAPI.currentVersionNums[1] > targetVersionNums[1] || (GadgetCoreAPI.currentVersionNums[1] == targetVersionNums[1] && (GadgetCoreAPI.currentVersionNums[2] > targetVersionNums[2] || (GadgetCoreAPI.currentVersionNums[2] == targetVersionNums[2] && GadgetCoreAPI.currentVersionNums[3] >= targetVersionNums[3]))))) || (attribute.GadgetCoreVersionSpecificity == VersionSpecificity.MINOR && GadgetCoreAPI.currentVersionNums[0] == targetVersionNums[0] && GadgetCoreAPI.currentVersionNums[1] == targetVersionNums[1] && (GadgetCoreAPI.currentVersionNums[2] > targetVersionNums[2] || (GadgetCoreAPI.currentVersionNums[2] == targetVersionNums[2] && GadgetCoreAPI.currentVersionNums[3] >= targetVersionNums[3]))) || (attribute.GadgetCoreVersionSpecificity == VersionSpecificity.NONBREAKING && GadgetCoreAPI.currentVersionNums[0] == targetVersionNums[0] && GadgetCoreAPI.currentVersionNums[1] == targetVersionNums[1] && GadgetCoreAPI.currentVersionNums[2] == targetVersionNums[2] && GadgetCoreAPI.currentVersionNums[3] >= targetVersionNums[3]) || (attribute.GadgetCoreVersionSpecificity == VersionSpecificity.BUGFIX && GadgetCoreAPI.currentVersionNums[0] == targetVersionNums[0] && GadgetCoreAPI.currentVersionNums[1] == targetVersionNums[1] && GadgetCoreAPI.currentVersionNums[2] == targetVersionNums[2] && GadgetCoreAPI.currentVersionNums[3] == targetVersionNums[3])) { Gadget gadget = null; try { gadget = Activator.CreateInstance(type) as Gadget; } catch (Exception e) { Logger.LogWarning("Found Gadget that could not be constructed: " + attribute.Name + ", in mod: {" + mod.Name + "}: Error: " + e); } if (gadget != null) { try { Logger.Log("Found Gadget to load: " + attribute.Name + ", in mod: {" + mod.Name + "}"); gadget.CreateSingleton(gadget); GadgetInfo info = new GadgetInfo(gadget, attribute, mod); gadget.Logger = new GadgetLogger(mod.Name, attribute.Name); string configFileName = Path.Combine(GadgetPaths.ConfigsPath, mod.Assembly.GetName().Name) + ".ini"; string oldConfigFileName = Path.Combine(GadgetPaths.ConfigsPath, mod.Name + ".ini"); if (!File.Exists(configFileName) && File.Exists(oldConfigFileName)) { File.Move(oldConfigFileName, configFileName); } gadget.Config = new GadgetConfig(configFileName, Regex.Replace(attribute.Name, @"\s+", "")); Gadgets.RegisterGadget(info); mod.m_LoadedGadgets.Add(info); if (!BatchLoading) { QueuedGadgets.Add(info); EnableQueuedGadgets(); } } catch (Exception e) { Logger.LogWarning("Found Gadget that had an error during registration: " + attribute.Name + ", in mod: {" + mod.Name + "}. Error: " + e); if (Gadgets.GetGadgetInfo(attribute.Name) != null) { Gadgets.UnregisterGadget(Gadgets.GetGadgetInfo(attribute.Name)); } } } } else { int rD = (int)attribute.GadgetCoreVersionSpecificity; Logger.LogWarning("Found Gadget with an incompatible version: " + attribute.Name + ", in mod: {" + mod.Name + "}. Requires at least version: " + attribute.TargetGCVersion + ", but no greater than version: " + new string(attribute.TargetGCVersion.TakeWhile(x => (x == '.' ? --rD : rD) > 0).ToArray())); } } mod.IsLoaded = true; }
/// <summary> /// Hard-reloads the given GadgetMod. (Loads it freshly from the disk). /// Also reloads all mods that are dependent on this mod. /// Causes a permanent increase in the game's RAM usage, as the old instance of the mod assembly that is stored in RAM cannot be fully removed. /// WARNING: Will trigger an immediate GC collection, causing a short freeze! /// </summary> public static GadgetMod ReloadMod(GadgetMod mod) { try { if (mod.Name == "GadgetCore") { throw new InvalidOperationException(GadgetMods.GetModByAssembly(Assembly.GetCallingAssembly()).Name + " seriously just tried to reload GadgetCore... Really?"); } string modPath = mod.ModPath; List <GadgetMod> modsToReload = mod.LoadedGadgets.SelectMany(x => Gadgets.LoadOrderTree.Find(x).FlattenUniqueByBreadth()).Where(x => x != null).Select(x => x.Mod).Distinct().ToList(); foreach (GadgetMod modToUnload in modsToReload) { if (modToUnload.Name != "GadgetCore") { UnloadModInternal(modToUnload); } } GC.Collect(); BatchLoading = true; Logger.Log("Loading mod files..."); for (int i = 0; i < modsToReload.Count; i++) { if (modsToReload[i].Name != "GadgetCore") { if (modsToReload[i].IsArchive) { if (modsToReload[i].ModPath == modPath) { modsToReload[i] = mod = LoadModFile(modsToReload[i].ModPath); } else { modsToReload[i] = LoadModFile(modsToReload[i].ModPath); } } else { if (modsToReload[i].ModPath == modPath) { modsToReload[i] = mod = LoadModDir(modsToReload[i].ModPath); } else { modsToReload[i] = LoadModDir(modsToReload[i].ModPath); } } } else { RefreshMod(modsToReload[i]); } } Logger.Log("Done loading mod files."); Logger.Log("Loading mods..."); foreach (GadgetMod modToReload in modsToReload) { LoadGadgetMod(modToReload); } Logger.Log("Done loading mods."); Logger.Log("Sorting Gadgets..."); Gadgets.SortGadgets(); Logger.Log("Done sorting Gadgets."); Logger.Log("Queueing Gadgets for initialization..."); foreach (GadgetInfo gadget in modsToReload.SelectMany(x => x.LoadedGadgets)) { QueuedGadgets.Add(gadget); } Logger.Log("Done queueing Gadgets."); EnableQueuedGadgets(); BatchLoading = false; } catch (Exception e) { Logger.LogError("Error reloading " + mod.Name + ": " + e); } return(mod); }
void InitializeGadgets() { DataManager dataManager = GameObject.FindGameObjectWithTag("DataManager").GetComponent <DataManager>(); gadgetList = new List <Gadgets>(); PersistentGadget[] allGadgets; allGadgets = dataManager.Gadgets; foreach (PersistentGadget g in allGadgets) { if (!g.isLocked) { if (g.gadgetName == "Turbo Boots") { gadgetList.Add(new Turbo_boots(g.gadgetName, g.image, g.coolDown, g.boostDuration, player)); } else if (g.gadgetName == "Vibrating Stone") { gadgetList.Add(new Rock(g.gadgetName, g.image, g.coolDown, g.boostDuration, player)); rockPosition = gadgetList.Count - 1; } else if (g.gadgetName == "Lock Pick") { gadgetList.Add(new Lock_pick(g.gadgetName, g.image, g.coolDown, g.boostDuration, player)); } else if (g.gadgetName == "Electronic Cracker") { gadgetList.Add(new Electronic_safe_opener(g.gadgetName, g.image, g.coolDown, g.boostDuration, player)); } else if (g.gadgetName == "Banana") { gadgetList.Add(new Banana(g.gadgetName, g.image, g.coolDown, g.boostDuration, player)); bananaPosition = gadgetList.Count - 1; } else if (g.gadgetName == "Laser Visor") { gadgetList.Add(new Laser_visor(g.gadgetName, g.image, g.coolDown, g.boostDuration, player)); } else { gadgetList.Add(new Gadgets(g.gadgetName, g.image, g.coolDown, g.boostDuration, player)); } } } gadgetNumber = gadgetList.Count; if (gadgetList.Count > 0 && sceneIndex != homeScene) { gadgetPanel.SetActive(true); currentGadget = gadgetList[0]; gadgetImage.sprite = currentGadget.sprite; gadgetText.text = currentGadget.name; gadgetPanelActive = true; } else { gadgetPanel.SetActive(false); gadgetPanelActive = false; } }
private async Task ExecuteLoadItemsCommand() { IsBusy = true; try { Gadgets.Clear(); var gadgets = await _gadgetDataStore.GetAllAsync(true); if (gadgets == null || gadgets.Count() == 0) { return; } var unsortedGadgetList = new List <GadgetViewModel>(); foreach (Gadget gadget in gadgets) { GadgetStatus gadgetStatus = await _webRequestService.GetStatusAsync(gadget); var statusIndicatorColor = GadgetHelper.GetStatusIndicatorColor(gadgetStatus); if (gadgetStatus == null) { gadgetStatus = new GadgetStatus { temperature = 0.00, overtemperature = false, temperature_status = "undefined", mac = "", voltage = 0.00 }; } var viewModel = new GadgetViewModel { Id = gadget.Id, DeviceId = gadgetStatus.mac, Name = gadget.Name, Location = gadget.Location, IpAddress = gadget.IpAddress, Description = gadget.Description, IsStatusOk = gadgetStatus.temperature_status == "Normal", StatusIndicatorColor = statusIndicatorColor.ToString(), TemperatureStatus = gadgetStatus.temperature_status, Temperature = gadgetStatus.temperature, TemperatureC = $"{ gadgetStatus.temperature } °C", Voltage = gadgetStatus.voltage, VoltageV = $"{ gadgetStatus.voltage } V" }; if (gadgetStatus.temperature_status == "undefined") { viewModel.TemperatureC = AppTranslations.Page_GadgetDetail_Fallback_NotAvailable; } unsortedGadgetList.Add(viewModel); } List <GadgetViewModel> sortedGadgetList = await GadgetHelper.SortGadgetListBySettingAsync(unsortedGadgetList); sortedGadgetList.ForEach(Gadgets.Add); } catch (Exception ex) { var properties = new Dictionary <string, string> { { "Method", "ExecuteLoadItemsCommand" }, { "Event", "Could not Add GadgetViewModel" } }; AppHelper.TrackError(ex, properties); } finally { IsBusy = false; } }
void initVariables() { rows = 7; columns = 7; offset = 3.8f; score = 0; combo = 0; paintedSquares = 0; randomSquaresPainted = 4; listLeft = new List<string>(); listRight = new List<string>(); listDown = new List<string>(); listUp = new List<string>(); listLine = new List<string>(); selectedSquare = null; selectedSquareDest = null; selectedSquareColor = Color.clear; selectedSquareDestColor = Color.clear; colors = new SquareColors (); gadgetsScript = GameObject.FindGameObjectWithTag ("Gadgets").GetComponent<Gadgets> (); }
public async Task <IActionResult> GetGadgets(int id) { Gadgets gadgets = await dataContx.Gadgets.Where(x => x.OwnerID == id).FirstAsync(); return(Ok(gadgets)); }
public static bool Prefix(GameScript __instance) { if (!GadgetNetwork.MatrixReady && GadgetNetwork.GetTimeSinceConnect() < GadgetNetwork.MatrixTimeout) { if (InstanceTracker.GameScript.gameObject.GetComponent <RPCHooks>() == null) { InstanceTracker.GameScript.gameObject.AddComponent <RPCHooks>(); } __instance.StartCoroutine(WaitAndTryAgain(__instance)); return(false); } else { if (GadgetNetwork.GetTimeSinceConnect() > GadgetNetwork.MatrixTimeout && Gadgets.ListAllGadgetInfos().Any(x => x.Attribute.RequiredOnClients)) { Network.Disconnect(); return(false); } return(true); } }
private static void VerifyCompatible(NetworkPlayer pl) { if (!GadgetNetwork.MatrixReady && GadgetNetwork.GetTimeSinceConnect() > GadgetNetwork.MatrixTimeout && Gadgets.ListAllGadgetInfos().Any(x => x.Attribute.RequiredOnClients)) { GadgetCore.CoreLogger.LogWarning("Disconnecting client " + pl.ipAddress + " due to timout! You can try raising NetworkTimeout in the config."); Network.CloseConnection(pl, true); } }
private static void BuildModMenu() { GadgetCore.CoreLogger.Log("Injecting Mod Menu into Main Menu"); ModMenu = new GameObject("MODMENU"); ModMenu.SetActive(false); ModMenuBackButtonBeam = UnityEngine.Object.Instantiate(InstanceTracker.Menuu.menuOptions.transform.Find("beamm").gameObject, ModMenu.transform); ModMenuBackButtonBeam.name = "beamm"; ModMenuBackButtonBeam.transform.localScale = new Vector3(30, 0, 1); ModMenuBackButtonBeam.transform.position = new Vector3(0, -13.5f, 1); ModMenuBackButtonHolder = UnityEngine.Object.Instantiate(InstanceTracker.Menuu.menuOptions.transform.Find("BUTTONHOLDER").gameObject, ModMenu.transform); ModMenuBackButtonHolder.name = "BUTTONHOLDER"; ModMenuBackButtonHolder.transform.position = new Vector3(0, -13.5f, 0); ModMenuBackButtonHolder.GetComponent <Animation>().RemoveClip("bbbac2"); ModMenuBackButtonHolder.GetComponent <Animation>().AddClip(BuildModMenuButtonAnimClip(true), "bbbac2"); ModMenuBackButtonHolder.GetComponent <Animation>().clip = ModMenuBackButtonHolder.GetComponent <Animation>().GetClip("bbbac2"); ModMenuCanvas = new GameObject("Mod Menu Canvas", typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster), typeof(CanvasGroup)).GetComponent <Canvas>(); ModMenuCanvas.GetComponent <CanvasGroup>().alpha = 0; ModMenuCanvas.GetComponent <CanvasGroup>().interactable = false; ModMenuCanvas.GetComponent <CanvasGroup>().blocksRaycasts = false; ModMenuCanvas.GetComponent <RectTransform>().pivot = new Vector2(0.5f, 0.5f); ModMenuCanvas.renderMode = RenderMode.ScreenSpaceOverlay; ModMenuCanvas.pixelPerfect = true; CanvasScaler scaler = ModMenuCanvas.GetComponent <CanvasScaler>(); scaler.scaleFactor = 2; scaler.referencePixelsPerUnit = 100; ModConfigMenuText = UnityEngine.Object.Instantiate(InstanceTracker.Menuu.menuOptions.transform.Find("txt0").gameObject, ModMenu.transform); ModConfigMenuText.name = "txt0"; ModConfigMenuText.transform.localPosition = new Vector3(0, 14, -1); Array.ForEach(ModConfigMenuText.GetComponentsInChildren <TextMesh>(), x => { x.text = "MOD CONFIG MENU"; x.anchor = TextAnchor.UpperCenter; }); GameObject restartRequiredText = UnityEngine.Object.Instantiate(ModConfigMenuText, ModMenu.transform); restartRequiredText.SetActive(false); restartRequiredText.name = "Restart Required Text"; restartRequiredText.transform.localPosition = new Vector3(0, -10.5f, -1); restartRequiredText.transform.localScale *= 0.75f; Array.ForEach(restartRequiredText.GetComponentsInChildren <TextMesh>(), x => { x.text = "Restart Required!"; x.anchor = TextAnchor.UpperCenter; }); ModMenuPanel = new GameObject("Panel", typeof(RectTransform), typeof(ModMenuController)).GetComponent <ModMenuController>(); ModMenuPanel.GetComponent <RectTransform>().SetParent(ModMenuCanvas.transform); ModMenuPanel.GetComponent <RectTransform>().anchorMin = new Vector2(0.15f, 0.15f); ModMenuPanel.GetComponent <RectTransform>().anchorMax = new Vector2(0.85f, 0.85f); ModMenuPanel.GetComponent <RectTransform>().offsetMin = Vector2.zero; ModMenuPanel.GetComponent <RectTransform>().offsetMax = Vector2.zero; ModConfigMenus = new GameObject("Mod Config Menus", typeof(RectTransform)).GetComponent <RectTransform>(); ModConfigMenus.SetParent(ModMenuCanvas.transform); ModConfigMenus.anchorMin = new Vector2(0.15f, 0.15f); ModConfigMenus.anchorMax = new Vector2(0.85f, 0.85f); ModConfigMenus.offsetMin = Vector2.zero; ModConfigMenus.offsetMax = Vector2.zero; Image background = new GameObject("Background", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image)).GetComponent <Image>(); background.transform.SetParent(ModMenuPanel.transform); background.rectTransform.anchorMin = new Vector2(0f, 0f); background.rectTransform.anchorMax = new Vector2(01f, 1f); background.rectTransform.offsetMin = Vector2.zero; background.rectTransform.offsetMax = Vector2.zero; background.type = Image.Type.Sliced; background.fillCenter = true; background.sprite = BoxSprite; ModMenuDescPanel = new GameObject("Mod Desc Panel", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(ScrollRect)).GetComponent <ScrollRect>(); ModMenuDescPanel.GetComponent <RectTransform>().SetParent(ModMenuPanel.transform); ModMenuDescPanel.GetComponent <RectTransform>().anchorMin = new Vector2(0.4f, 0.25f); ModMenuDescPanel.GetComponent <RectTransform>().anchorMax = new Vector2(1f, 1f); ModMenuDescPanel.GetComponent <RectTransform>().offsetMin = new Vector2(0, 5); ModMenuDescPanel.GetComponent <RectTransform>().offsetMax = new Vector2(-10, -10); ModMenuDescPanel.GetComponent <Image>().sprite = BoxSprite; ModMenuDescPanel.GetComponent <Image>().type = Image.Type.Sliced; ModMenuDescPanel.GetComponent <Image>().fillCenter = true; Mask modMenuDescPanelMask = new GameObject("Mask", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Mask)).GetComponent <Mask>(); modMenuDescPanelMask.GetComponent <RectTransform>().SetParent(ModMenuDescPanel.transform); modMenuDescPanelMask.GetComponent <RectTransform>().anchorMin = new Vector2(0f, 0f); modMenuDescPanelMask.GetComponent <RectTransform>().anchorMax = new Vector2(1f, 1f); modMenuDescPanelMask.GetComponent <RectTransform>().offsetMin = Vector2.zero; modMenuDescPanelMask.GetComponent <RectTransform>().offsetMax = Vector2.zero; modMenuDescPanelMask.GetComponent <Image>().sprite = BoxMask; modMenuDescPanelMask.GetComponent <Image>().type = Image.Type.Sliced; modMenuDescPanelMask.GetComponent <Image>().fillCenter = true; modMenuDescPanelMask.showMaskGraphic = false; RectTransform modMenuDescViewport = new GameObject("Viewport", typeof(RectTransform)).GetComponent <RectTransform>(); modMenuDescViewport.SetParent(modMenuDescPanelMask.transform); modMenuDescViewport.anchorMin = new Vector2(0f, 0f); modMenuDescViewport.anchorMax = new Vector2(1f, 1f); modMenuDescViewport.offsetMin = new Vector2(10, 10); modMenuDescViewport.offsetMax = new Vector2(-10, -10); Text modMenuDescText = new GameObject("Description", typeof(RectTransform), typeof(CanvasRenderer), typeof(Text), typeof(ContentSizeFitter)).GetComponent <Text>(); modMenuDescText.rectTransform.SetParent(modMenuDescViewport); modMenuDescText.rectTransform.anchorMin = new Vector2(0f, 0f); modMenuDescText.rectTransform.anchorMax = new Vector2(1f, 1f); modMenuDescText.rectTransform.offsetMin = Vector2.zero; modMenuDescText.rectTransform.offsetMax = Vector2.zero; modMenuDescText.rectTransform.pivot = new Vector2(0.5f, 1f); modMenuDescText.font = ModConfigMenuText.GetComponent <TextMesh>().font; modMenuDescText.fontSize = 12; modMenuDescText.horizontalOverflow = HorizontalWrapMode.Wrap; modMenuDescText.GetComponent <ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize; ModMenuDescPanel.GetComponent <ScrollRect>().content = modMenuDescText.rectTransform; ModMenuDescPanel.GetComponent <ScrollRect>().horizontal = false; ModMenuDescPanel.GetComponent <ScrollRect>().scrollSensitivity = 5; ModMenuDescPanel.GetComponent <ScrollRect>().viewport = modMenuDescViewport; ModMenuPanel.descText = modMenuDescText; ModMenuPanel.restartRequiredText = restartRequiredText; Image modMenuButtonPanel = new GameObject("Button Panel", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image)).GetComponent <Image>(); modMenuButtonPanel.GetComponent <RectTransform>().SetParent(ModMenuPanel.transform); modMenuButtonPanel.GetComponent <RectTransform>().anchorMin = new Vector2(0.4f, 0f); modMenuButtonPanel.GetComponent <RectTransform>().anchorMax = new Vector2(1f, 0.25f); modMenuButtonPanel.GetComponent <RectTransform>().offsetMin = new Vector2(0, 10); modMenuButtonPanel.GetComponent <RectTransform>().offsetMax = new Vector2(-10, -5); modMenuButtonPanel.GetComponent <Image>().sprite = BoxSprite; modMenuButtonPanel.GetComponent <Image>().type = Image.Type.Sliced; modMenuButtonPanel.GetComponent <Image>().fillCenter = true; ModMenuPanel.enableButton = new GameObject("Enable Button", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button)).GetComponent <Button>(); ModMenuPanel.enableButton.GetComponent <RectTransform>().SetParent(modMenuButtonPanel.transform); ModMenuPanel.enableButton.GetComponent <RectTransform>().anchorMin = new Vector2(0f, 0f); ModMenuPanel.enableButton.GetComponent <RectTransform>().anchorMax = new Vector2(1f / 3f, 1f); ModMenuPanel.enableButton.GetComponent <RectTransform>().offsetMin = new Vector2(10, 10); ModMenuPanel.enableButton.GetComponent <RectTransform>().offsetMax = new Vector2(-10, -10); ModMenuPanel.enableButton.GetComponent <Image>().sprite = BoxSprite; ModMenuPanel.enableButton.GetComponent <Image>().type = Image.Type.Sliced; ModMenuPanel.enableButton.GetComponent <Image>().fillCenter = true; ModMenuPanel.enableButton.targetGraphic = ModMenuPanel.enableButton.GetComponent <Image>(); ModMenuPanel.enableButton.onClick.AddListener(ModMenuPanel.EnableButton); Text enableButtonText = new GameObject("Text", typeof(RectTransform), typeof(CanvasRenderer), typeof(Text)).GetComponent <Text>(); enableButtonText.rectTransform.SetParent(ModMenuPanel.enableButton.transform); enableButtonText.rectTransform.anchorMin = new Vector2(0f, 0f); enableButtonText.rectTransform.anchorMax = new Vector2(1f, 1f); enableButtonText.rectTransform.offsetMin = Vector2.zero; enableButtonText.rectTransform.offsetMax = Vector2.zero; enableButtonText.alignment = TextAnchor.MiddleCenter; enableButtonText.font = modMenuDescText.font; enableButtonText.fontSize = 12; enableButtonText.text = "Enable"; ModMenuPanel.reloadButton = new GameObject("Reload Button", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button)).GetComponent <Button>(); ModMenuPanel.reloadButton.GetComponent <RectTransform>().SetParent(modMenuButtonPanel.transform); ModMenuPanel.reloadButton.GetComponent <RectTransform>().anchorMin = new Vector2(1f / 3f, 0f); ModMenuPanel.reloadButton.GetComponent <RectTransform>().anchorMax = new Vector2(2f / 3f, 1f); ModMenuPanel.reloadButton.GetComponent <RectTransform>().offsetMin = new Vector2(10, 10); ModMenuPanel.reloadButton.GetComponent <RectTransform>().offsetMax = new Vector2(-10, -10); ModMenuPanel.reloadButton.GetComponent <Image>().sprite = BoxSprite; ModMenuPanel.reloadButton.GetComponent <Image>().type = Image.Type.Sliced; ModMenuPanel.reloadButton.GetComponent <Image>().fillCenter = true; ModMenuPanel.reloadButton.targetGraphic = ModMenuPanel.reloadButton.GetComponent <Image>(); ModMenuPanel.reloadButton.onClick.AddListener(ModMenuPanel.ReloadButton); Text reloadButtonText = new GameObject("Text", typeof(RectTransform), typeof(CanvasRenderer), typeof(Text)).GetComponent <Text>(); reloadButtonText.rectTransform.SetParent(ModMenuPanel.reloadButton.transform); reloadButtonText.rectTransform.anchorMin = new Vector2(0f, 0f); reloadButtonText.rectTransform.anchorMax = new Vector2(1f, 1f); reloadButtonText.rectTransform.offsetMin = Vector2.zero; reloadButtonText.rectTransform.offsetMax = Vector2.zero; reloadButtonText.alignment = TextAnchor.MiddleCenter; reloadButtonText.font = modMenuDescText.font; reloadButtonText.fontSize = 12; reloadButtonText.text = "Reload"; ModMenuPanel.configButton = new GameObject("Config Button", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button)).GetComponent <Button>(); ModMenuPanel.configButton.GetComponent <RectTransform>().SetParent(modMenuButtonPanel.transform); ModMenuPanel.configButton.GetComponent <RectTransform>().anchorMin = new Vector2(2f / 3f, 0f); ModMenuPanel.configButton.GetComponent <RectTransform>().anchorMax = new Vector2(1f, 1f); ModMenuPanel.configButton.GetComponent <RectTransform>().offsetMin = new Vector2(10, 10); ModMenuPanel.configButton.GetComponent <RectTransform>().offsetMax = new Vector2(-10, -10); ModMenuPanel.configButton.GetComponent <Image>().sprite = BoxSprite; ModMenuPanel.configButton.GetComponent <Image>().type = Image.Type.Sliced; ModMenuPanel.configButton.GetComponent <Image>().fillCenter = true; ModMenuPanel.configButton.targetGraphic = ModMenuPanel.configButton.GetComponent <Image>(); ModMenuPanel.configButton.onClick.AddListener(ModMenuPanel.ConfigButton); Text configButtonText = new GameObject("Text", typeof(RectTransform), typeof(CanvasRenderer), typeof(Text)).GetComponent <Text>(); configButtonText.rectTransform.SetParent(ModMenuPanel.configButton.transform); configButtonText.rectTransform.anchorMin = new Vector2(0f, 0f); configButtonText.rectTransform.anchorMax = new Vector2(1f, 1f); configButtonText.rectTransform.offsetMin = Vector2.zero; configButtonText.rectTransform.offsetMax = Vector2.zero; configButtonText.alignment = TextAnchor.MiddleCenter; configButtonText.font = modMenuDescText.font; configButtonText.fontSize = 12; configButtonText.text = "Configure"; if (GadgetCoreAPI.GetUMFAPI() != null) { ModMenuPanel.umfConfigButton = new GameObject("UMF Config Button", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button)).GetComponent <Button>(); ModMenuPanel.umfConfigButton.GetComponent <RectTransform>().SetParent(ModMenuCanvas.transform); ModMenuPanel.umfConfigButton.GetComponent <RectTransform>().anchorMin = new Vector2(0.025f, 0.4f); ModMenuPanel.umfConfigButton.GetComponent <RectTransform>().anchorMax = new Vector2(0.125f, 0.6f); ModMenuPanel.umfConfigButton.GetComponent <RectTransform>().offsetMin = new Vector2(0, 0); ModMenuPanel.umfConfigButton.GetComponent <RectTransform>().offsetMax = new Vector2(0, 0); ModMenuPanel.umfConfigButton.GetComponent <Image>().sprite = BoxSprite; ModMenuPanel.umfConfigButton.GetComponent <Image>().type = Image.Type.Sliced; ModMenuPanel.umfConfigButton.GetComponent <Image>().fillCenter = true; ModMenuPanel.umfConfigButton.targetGraphic = ModMenuPanel.umfConfigButton.GetComponent <Image>(); ModMenuPanel.umfConfigButton.onClick.AddListener(ModMenuPanel.UMFConfigButton); Text umfConfigButtonText = new GameObject("Text", typeof(RectTransform), typeof(CanvasRenderer), typeof(Text)).GetComponent <Text>(); umfConfigButtonText.rectTransform.SetParent(ModMenuPanel.umfConfigButton.transform); umfConfigButtonText.rectTransform.anchorMin = new Vector2(0f, 0f); umfConfigButtonText.rectTransform.anchorMax = new Vector2(1f, 1f); umfConfigButtonText.rectTransform.offsetMin = Vector2.zero; umfConfigButtonText.rectTransform.offsetMax = Vector2.zero; umfConfigButtonText.alignment = TextAnchor.MiddleCenter; umfConfigButtonText.font = modMenuDescText.font; umfConfigButtonText.fontSize = 12; umfConfigButtonText.text = "Configure UMF"; } Button configReloadButton = new GameObject("Config Reload Button", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button)).GetComponent <Button>(); configReloadButton.GetComponent <RectTransform>().SetParent(ModMenuCanvas.transform); configReloadButton.GetComponent <RectTransform>().anchorMin = new Vector2(0.875f, 0.4f); configReloadButton.GetComponent <RectTransform>().anchorMax = new Vector2(0.975f, 0.6f); configReloadButton.GetComponent <RectTransform>().offsetMin = new Vector2(0, 0); configReloadButton.GetComponent <RectTransform>().offsetMax = new Vector2(0, 0); configReloadButton.GetComponent <Image>().sprite = BoxSprite; configReloadButton.GetComponent <Image>().type = Image.Type.Sliced; configReloadButton.GetComponent <Image>().fillCenter = true; configReloadButton.targetGraphic = configReloadButton.GetComponent <Image>(); configReloadButton.onClick.AddListener(() => { foreach (GadgetInfo gadget in Gadgets.ListAllEnabledGadgetInfos()) { if (gadget.Attribute.AllowConfigReloading) { gadget.Gadget.ReloadConfig(); } } if (GadgetCore.UMFAPI != null) { foreach (string mod in GadgetCore.UMFAPI.GetModNames()) { GadgetCore.UMFAPI.SendCommand("cfgReload " + mod); } } GadgetModConfigs.ResetAllConfigMenus(); }); Text configReloadButtonText = new GameObject("Text", typeof(RectTransform), typeof(CanvasRenderer), typeof(Text)).GetComponent <Text>(); configReloadButtonText.rectTransform.SetParent(configReloadButton.transform); configReloadButtonText.rectTransform.anchorMin = new Vector2(0f, 0f); configReloadButtonText.rectTransform.anchorMax = new Vector2(1f, 1f); configReloadButtonText.rectTransform.offsetMin = Vector2.zero; configReloadButtonText.rectTransform.offsetMax = Vector2.zero; configReloadButtonText.alignment = TextAnchor.MiddleCenter; configReloadButtonText.font = modMenuDescText.font; configReloadButtonText.fontSize = 12; configReloadButtonText.text = "Reload Configs"; GadgetModConfigs.ConfigMenus.Clear(); }
internal void SendRequiredModList(string modList, NetworkMessageInfo info) { GadgetCore.CoreLogger.Log("Client has sent local mod list. Processing..."); try { bool isCompatible = true; List <string> incompatibleReasons = new List <string>(); HashSet <string> handledGadgets = new HashSet <string>(); string[][] splitModList = string.IsNullOrEmpty(modList) ? new string[0][] : modList.Split(',').Select(x => x.Split(':')).ToArray(); foreach (GadgetInfo mod in Gadgets.ListAllGadgetInfos().Where(x => x.Gadget.Enabled && x.Attribute.RequiredOnClients)) { handledGadgets.Add(mod.Attribute.Name); string clientVersion = splitModList.SingleOrDefault(x => x[0] == mod.Attribute.Name)?[1]; if (clientVersion == null) { isCompatible = false; incompatibleReasons.Add($"The Gadget '{mod.Attribute.Name}' (From the mod '{mod.ModName}') is not present on the client"); continue; } int[] clientVersionNums = clientVersion.Split('.').Select(x => int.Parse(x)).Take(4).ToArray(); int[] hostVersionNums = mod.Gadget.GetModVersionString().Split('.').Select(x => int.Parse(x)).ToArray(); hostVersionNums = hostVersionNums.Concat(Enumerable.Repeat(0, 4 - hostVersionNums.Length)).ToArray(); clientVersionNums = clientVersionNums.Concat(Enumerable.Repeat(0, 4 - clientVersionNums.Length)).ToArray(); if (!((mod.Attribute.GadgetCoreVersionSpecificity == VersionSpecificity.MAJOR && clientVersionNums[0] == hostVersionNums[0] && (clientVersionNums[1] > hostVersionNums[1] || (clientVersionNums[1] == hostVersionNums[1] && (clientVersionNums[2] > hostVersionNums[2] || (clientVersionNums[2] == hostVersionNums[2] && clientVersionNums[3] >= hostVersionNums[3]))))) || (mod.Attribute.GadgetCoreVersionSpecificity == VersionSpecificity.MINOR && clientVersionNums[0] == hostVersionNums[0] && clientVersionNums[1] == hostVersionNums[1] && (clientVersionNums[2] > hostVersionNums[2] || (clientVersionNums[2] == hostVersionNums[2] && clientVersionNums[3] >= hostVersionNums[3]))) || (mod.Attribute.GadgetCoreVersionSpecificity == VersionSpecificity.NONBREAKING && clientVersionNums[0] == hostVersionNums[0] && clientVersionNums[1] == hostVersionNums[1] && clientVersionNums[2] == hostVersionNums[2] && clientVersionNums[3] >= hostVersionNums[3]) || (mod.Attribute.GadgetCoreVersionSpecificity == VersionSpecificity.BUGFIX && clientVersionNums[0] == hostVersionNums[0] && clientVersionNums[1] == hostVersionNums[1] && clientVersionNums[2] == hostVersionNums[2] && clientVersionNums[3] == hostVersionNums[3]))) { isCompatible = false; incompatibleReasons.Add($"The Gadget '{mod.Attribute.Name}' (From the mod '{mod.ModName}') is of incompatible versions: Host: {mod.Gadget.GetModVersionString()}, Client: {clientVersion}"); continue; } } if (handledGadgets.Count != splitModList.Length) { isCompatible = false; foreach (string[] modEntry in splitModList.Where(x => !handledGadgets.Contains(x[0]))) { incompatibleReasons.Add($"The Gadget '{modEntry[0]}' (From an unknown mod) is present on the client, but not on the host"); } } if (isCompatible) { if (info.Equals(serverNMI)) { GadgetCore.CoreLogger.Log("Self-connection succesfully established and identified."); ReceiveIDMatrixData(GadgetNetwork.GenerateIDMatrixData()); } else { GadgetCore.CoreLogger.Log("A client connected with compatible mods: " + info.sender.ipAddress); string matrixData = GadgetNetwork.GenerateIDMatrixData(); if (matrixData.Length <= 4096) { GadgetCore.CoreLogger.Log("Sending ID Matrix data as a single block..."); view.RPC("ReceiveIDMatrixData", info.sender, matrixData); } else { string[] splitMatrixData = matrixData.SplitOnLength(MaxChunkSize).ToArray(); GadgetCore.CoreLogger.Log($"Sending ID Matrix data as {splitMatrixData.Length} chunks..."); for (int i = 0; i < splitMatrixData.Length; i++) { view.RPC("ReceiveIDMatrixDataChunk", info.sender, splitMatrixData[i], i, splitMatrixData.Length); } } } } else { GadgetCore.CoreLogger.LogWarning("A client tried to connect with incompatible mods: " + info.sender.ipAddress + Environment.NewLine + " - " + incompatibleReasons.Concat(Environment.NewLine + " - ")); if (Network.isServer) { DisconnectWithMessage(info.sender, "Your mods are incompatible with the server:" + Environment.NewLine + " - " + incompatibleReasons.Concat(Environment.NewLine + " - ")); } else { Network.Disconnect(); } } } catch (Exception e) { GadgetCore.CoreLogger.LogWarning("The following error occured processing an incoming client's mod list: " + info.sender.ipAddress + Environment.NewLine + modList + Environment.NewLine + e.ToString()); if (Network.isServer) { DisconnectWithMessage(info.sender, "An error occured processing your mod list:" + Environment.NewLine + modList + Environment.NewLine + e.ToString()); } else { Network.Disconnect(); } } }
internal static void EnableQueuedGadgets() { List <GadgetInfo> preFilteredQueuedGadgets = QueuedGadgets; QueuedGadgets = new List <GadgetInfo>(); foreach (GadgetInfo gadget in preFilteredQueuedGadgets) { bool valid = true; foreach (string dependency in gadget.Attribute.Dependencies) { string[] splitDependency = dependency.Split(':'); GadgetInfo dependencyGadget = Gadgets.GetGadgetInfo(splitDependency[0]); valid = dependencyGadget != null && dependencyGadget.Gadget.Enabled; if (valid) { if (splitDependency.Length == 2) { string versionString = splitDependency[1].TrimStart('v'); int[] targetVersionNums = versionString.Split('.').Select(x => int.Parse(x)).ToArray(); if (targetVersionNums.Length > 4) { continue; } int[] actualVersionNums = dependencyGadget.Mod.Version.ToString().Split('.').Select(x => int.Parse(x)).ToArray(); if (targetVersionNums.Length != 4) { Array.Resize(ref targetVersionNums, 4); } if (actualVersionNums.Length != 4) { Array.Resize(ref actualVersionNums, 4); } valid = actualVersionNums[0] == targetVersionNums[0] && actualVersionNums[1] == targetVersionNums[1] && (actualVersionNums[2] > targetVersionNums[2] || (actualVersionNums[2] == targetVersionNums[2] && actualVersionNums[3] >= targetVersionNums[3])); } else if (splitDependency.Length == 3) { string versionString = splitDependency[1].TrimStart('v'); int[] targetVersionNums = versionString.Split('.').Select(x => int.Parse(x)).ToArray(); if (targetVersionNums.Length > 4) { continue; } int[] actualVersionNums = dependencyGadget.Mod.Version.ToString().Split('.').Select(x => int.Parse(x)).ToArray(); VersionSpecificity versionSpecificity; try { versionSpecificity = (VersionSpecificity)Enum.Parse(typeof(VersionSpecificity), splitDependency[2], true); } catch (ArgumentException) { Logger.LogWarning("Gadget " + gadget.Attribute.Name + " has an improperly-formatted dependency version string: " + dependency); versionSpecificity = VersionSpecificity.MINOR; } if (targetVersionNums.Length != 4) { Array.Resize(ref targetVersionNums, 4); } if (actualVersionNums.Length != 4) { Array.Resize(ref actualVersionNums, 4); } valid = (versionSpecificity == VersionSpecificity.MAJOR && actualVersionNums[0] == targetVersionNums[0] && (actualVersionNums[1] > targetVersionNums[1] || (actualVersionNums[1] == targetVersionNums[1] && (actualVersionNums[2] > targetVersionNums[2] || (actualVersionNums[2] == targetVersionNums[2] && actualVersionNums[3] >= targetVersionNums[3]))))) || (versionSpecificity == VersionSpecificity.MINOR && actualVersionNums[0] == targetVersionNums[0] && actualVersionNums[1] == targetVersionNums[1] && (actualVersionNums[2] > targetVersionNums[2] || (actualVersionNums[2] == targetVersionNums[2] && actualVersionNums[3] >= targetVersionNums[3]))) || (versionSpecificity == VersionSpecificity.NONBREAKING && actualVersionNums[0] == targetVersionNums[0] && actualVersionNums[1] == targetVersionNums[1] && actualVersionNums[2] == targetVersionNums[2] && actualVersionNums[3] >= targetVersionNums[3]) || (versionSpecificity == VersionSpecificity.BUGFIX && actualVersionNums[0] == targetVersionNums[0] && actualVersionNums[1] == targetVersionNums[1] && actualVersionNums[2] == targetVersionNums[2] && actualVersionNums[3] == targetVersionNums[3]); } } } if (valid) { QueuedGadgets.Add(gadget); } else { gadget.Gadget.Enabled = false; GadgetCoreConfig.enabledGadgets[gadget.Attribute.Name] = false; Gadgets.UnregisterGadget(gadget); Logger.LogWarning("Aborted loading Gadget " + gadget.Attribute.Name + " due to missing dependencies."); } } Logger.Log("Loading Gadget configs..."); foreach (GadgetInfo gadget in QueuedGadgets.ToList()) { Logger.Log("Loading Config for Gadget '" + gadget.Attribute.Name + "'"); try { gadget.Gadget.LoadConfig(); } catch (Exception e) { gadget.Gadget.Enabled = false; GadgetCoreConfig.enabledGadgets[gadget.Attribute.Name] = false; Gadgets.UnregisterGadget(gadget); QueuedGadgets.Remove(gadget); Logger.LogError("Exception Loading Config For Gadget '" + gadget.Attribute.Name + "':" + Environment.NewLine + e.ToString()); } } Logger.Log("Done loading Gadget configs."); Logger.Log("Preparing Gadgets for patching..."); foreach (GadgetInfo gadget in QueuedGadgets.ToList()) { Logger.Log("PrePatching Gadget '" + gadget.Attribute.Name + "'"); try { gadget.Gadget.HarmonyInstance = new Harmony(gadget.Mod.Name + "." + gadget.Attribute.Name + ".gadget"); gadget.Gadget.PrePatch(); } catch (Exception e) { gadget.Gadget.Enabled = false; GadgetCoreConfig.enabledGadgets[gadget.Attribute.Name] = false; Gadgets.UnregisterGadget(gadget); QueuedGadgets.Remove(gadget); Logger.LogError("Exception PrePatching Gadget '" + gadget.Attribute.Name + "':" + Environment.NewLine + e.ToString()); } } Logger.Log("Done preparing Gadgets for patching."); Logger.Log("Patching Gadgets..."); foreach (GadgetInfo gadget in QueuedGadgets.ToList()) { int patches = 0, totalMethods = 0, errorPatching = 0, targetMissing = 0; try { gadget.Mod.Assembly.GetExportedTypes().Do(delegate(Type type) { HarmonyGadgetAttribute attribute = type.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(HarmonyGadgetAttribute)) as HarmonyGadgetAttribute; if (attribute?.Gadget == gadget.Attribute.Name && attribute.RequiredGadgets.All(x => Gadgets.GetGadget(x) != null)) { try { List <MethodInfo> methods = gadget.Gadget.HarmonyInstance.CreateClassProcessor(type).Patch(); totalMethods += methods?.Count ?? 0; if (methods == null || methods.Count == 0) { Logger.Log("Skipping patch '" + type.Name + "' for Gadget '" + gadget.Attribute.Name + "': Attribute target does not exist."); targetMissing++; } else { patches++; } } catch (Exception e) { if (e.InnerException == null || !e.InnerException.Message.EndsWith("returned an unexpected result: null")) { Logger.LogError("Exception running patch '" + type.Name + "' for Gadget '" + gadget.Attribute.Name + "': " + Environment.NewLine + e.ToString()); errorPatching++; } else { Logger.Log("Skipping patch '" + type.Name + "' for Gadget '" + gadget.Attribute.Name + "': TargetMethod returned null."); targetMissing++; } } } }); Logger.Log("Performed " + patches + " patches for '" + gadget.Attribute.Name + "'" + (totalMethods > 0 ? $" ({totalMethods} total methods patched)" : string.Empty) + (errorPatching > 0 ? targetMissing > 0 ? $" ({errorPatching} skipped due to errors, {targetMissing} skipped due to missing targets)" : $" ({errorPatching} skipped due to errors)" : targetMissing > 0 ? $" ({targetMissing} skipped due to missing targets)" : string.Empty)); } catch (Exception e) { gadget.Gadget.Enabled = false; GadgetCoreConfig.enabledGadgets[gadget.Attribute.Name] = false; Gadgets.UnregisterGadget(gadget); QueuedGadgets.Remove(gadget); Logger.LogError("Exception patching Gadget '" + gadget.Attribute.Name + "':" + Environment.NewLine + e.ToString()); } } Logger.Log("Done patching Gadgets."); bool logOverrideWarnings = false; foreach (MethodBase patchedMethod in Harmony.GetAllPatchedMethods()) { HarmonyLib.Patches patches = Harmony.GetPatchInfo(patchedMethod); if (patches == null) { continue; } Dictionary <string, string> owners = new Dictionary <string, string>(); List <Patch> overridingPrefixes = patches.Prefixes.Where(x => x.PatchMethod.ReturnType == typeof(bool) && (x.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverridesAttribute)) as HarmonyOverridesAttribute)?.Overrides.Length != 0).ToList(); if (overridingPrefixes != null && overridingPrefixes.Count > 0) { foreach (string ownerID in patches.Owners) { if (ownerID == GadgetCore.HarmonyInstance.Id) { owners[ownerID] = "GadgetCore"; } else { string[] splitOwnerID = ownerID.Split('.'); if (splitOwnerID.Length == 3 && splitOwnerID[2] == "gadget") { GadgetMod mod = GadgetMods.GetModByName(splitOwnerID[0]); GadgetInfo gadget = mod?.LoadedGadgets.SingleOrDefault(x => x.Attribute.Name == splitOwnerID[1]); if (gadget != null) { owners[ownerID] = $"'{splitOwnerID[1]}' from the mod {{{splitOwnerID[0]}}}"; } else { owners[ownerID] = $"Unrecognized patcher '{ownerID}'"; } } else { owners[ownerID] = $"Unrecognized patcher '{ownerID}'"; } } } IEnumerable <Patch> problematicPrefixes = patches.Prefixes.Where(x => !overridingPrefixes.Contains(x) && (x.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverriddenAttribute)) as HarmonyOverriddenAttribute)?.Overrides.Length != 0 && overridingPrefixes.Any( p => x.owner != p.owner && (x.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverriddenAttribute)) as HarmonyOverriddenAttribute)?.Overrides.Contains(p.owner) != true && (p.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverridesAttribute)) as HarmonyOverridesAttribute)?.Overrides.Contains(x.owner) != true && x.priority <= p.priority && !x.before.Contains(p.owner) && !p.after.Contains(x.owner))); IEnumerable <Patch> problematicTranspilers = patches.Transpilers.Where(x => (x.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverriddenAttribute)) as HarmonyOverriddenAttribute)?.Overrides.Length != 0 && overridingPrefixes.Any( p => x.owner != p.owner && (x.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverriddenAttribute)) as HarmonyOverriddenAttribute)?.Overrides.Contains(p.owner) != true && (p.PatchMethod.GetCustomAttributes(true).FirstOrDefault(a => a.GetType() == typeof(HarmonyOverridesAttribute)) as HarmonyOverridesAttribute)?.Overrides.Contains(x.owner) != true)); if (problematicPrefixes != null && problematicPrefixes.Any() || problematicTranspilers != null && problematicTranspilers.Any()) { if (!logOverrideWarnings) { logOverrideWarnings = true; Logger.LogWarning("Possibly problematic patch overrides detected!", false); } Logger.Log($"Patches to {patchedMethod.DeclaringType.FullName}.{patchedMethod.Name} by {overridingPrefixes.Select(x => owners[x.owner]).Concat()} may override the following patch{(problematicPrefixes.Count() + problematicTranspilers.Count() > 1 ? "es" : "")}:"); if (problematicPrefixes != null) { foreach (Patch patch in problematicPrefixes) { Logger.Log($" - Prefix from {owners[patch.owner]}"); } } if (problematicTranspilers != null) { foreach (Patch patch in problematicTranspilers) { Logger.Log($" - Transpiler from {owners[patch.owner]}"); } } } } } if (logOverrideWarnings) { Logger.Log("End of possibly problematic patch overrides."); } Logger.Log("Creating registries..."); foreach (GadgetInfo gadget in QueuedGadgets.ToList()) { if (gadget.Gadget.Enabled) { foreach (Registry registry in gadget.Gadget.CreateRegistries()) { GameRegistry.RegisterRegistry(registry); } } } Logger.Log("Done creating registries."); Logger.Log("Initializing Gadgets..."); foreach (GadgetInfo gadget in QueuedGadgets.ToList()) { Logger.Log("Initializing Gadget '" + gadget.Attribute.Name + "'"); try { Registry.gadgetRegistering = gadget.Gadget.ModID; gadget.Gadget.LoadInternal(); } catch (Exception e) { gadget.Gadget.Enabled = false; GadgetCoreConfig.enabledGadgets[gadget.Attribute.Name] = false; Gadgets.UnregisterGadget(gadget); QueuedGadgets.Remove(gadget); Logger.LogError("Exception Initializing Gadget '" + gadget.Attribute.Name + "':" + Environment.NewLine + e.ToString()); } finally { Registry.gadgetRegistering = -1; } } Logger.Log("Done initializing Gadgets."); QueuedGadgets.Clear(); GadgetCoreConfig.Update(); }