internal void Start() { for (int i = 0; i < umfModEntries.Count; i++) { wasEnabled[umfModEntries[i].Name] = umfModEntries[i].Type != ModMenuEntryType.DISABLED_UMF; } for (int i = 0; i < Gadgets.CountGadgets(); i++) { wasEnabled[Gadgets.GetGadgetInfo(i).Attribute.Name] = Gadgets.GetGadgetInfo(i).Gadget.Enabled; } StartCoroutine(WatchForRestartNeeded()); }
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; if (valid && splitDependency.Length == 2) { string versionString = splitDependency[1].Replace("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 = (VersionSpecificity)targetVersionNums.Length; 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; 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 { gadget.Gadget.HarmonyInstance.CreateClassProcessor(type).Patch(); patches++; } catch (Exception e) { Logger.LogError("Exception running patch '" + type.Name + "' for Gadget '" + gadget.Attribute.Name + "': " + Environment.NewLine + e.ToString()); } } }); Logger.Log("Performed " + patches + " patches for " + gadget.Attribute.Name); } 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."); 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.modRegistering = gadget.Gadget.ModID; gadget.Gadget.Initialize(); } 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.modRegistering = -1; } } Logger.Log("Done initializing Gadgets."); QueuedGadgets.Clear(); }
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); gadget.Config = new GadgetConfig(Path.Combine(GadgetPaths.ConfigsPath, mod.Name + ".ini"), attribute.Name); 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 version: " + new string(attribute.TargetGCVersion.TakeWhile(x => (x == '.' ? --rD : rD) > 0).ToArray())); } } mod.IsLoaded = true; }
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 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(); }