internal static void DisableQueuedGadgets() { Logger.Log("Unloading Gadgets..."); foreach (GadgetInfo gadget in QueuedGadgets) { gadget.Gadget.Unload(); LootTables.RemoveModEntries(gadget.Gadget.ModID); GadgetCoreAPI.RemoveModResources(gadget.Gadget.ModID); GadgetCoreAPI.UnregisterStatModifiers(gadget.Gadget.ModID); GadgetNetwork.UnregisterSyncVars(gadget.Gadget.ModID); PlanetRegistry.UnregisterGadget(gadget.Gadget.ModID); foreach (Registry reg in GameRegistry.ListAllRegistries()) { reg.UnregisterGadget(gadget); } } Logger.Log("Done unloading Gadgets."); Logger.Log("Unpatching Gadgets..."); foreach (GadgetInfo gadget in QueuedGadgets.ToList()) { try { gadget.Gadget.HarmonyInstance.UnpatchAll(gadget.Mod.Name + "." + gadget.Attribute.Name + ".gadget"); } catch (Exception e) { Logger.LogError("Exception Unpatching Gadget '" + gadget.Attribute.Name + "':" + Environment.NewLine + e.ToString()); } } Logger.Log("Done patching Gadgets."); Logger.Log("Sorting Gadgets..."); Gadgets.SortGadgets(); Logger.Log("Done sorting Gadgets."); QueuedGadgets.Clear(); }
/// <summary> /// Unloads the given GadgetMod. /// Cannot fully release the mod'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 garbage collection, causing a short freeze! /// </summary> public static void UnloadMod(GadgetMod mod) { try { if (mod.Name == "GadgetCore") { throw new InvalidOperationException(GadgetMods.GetModByAssembly(Assembly.GetCallingAssembly()).Name + " seriously just tried to unload GadgetCore... Really?"); } List <GadgetMod> modsToUnload = mod.LoadedGadgets.SelectMany(x => Gadgets.LoadOrderTree.Find(x).FlattenUniqueByBreadth().Where(y => y != x)).Where(x => x != null).Select(x => x.Mod).Distinct().ToList(); bool wasBatchLoading = BatchLoading; BatchLoading = true; foreach (GadgetMod modToUnload in modsToUnload) { UnloadModInternal(modToUnload); } mod.Unload(); GC.Collect(); BatchLoading = wasBatchLoading; DisableQueuedGadgets(); Gadgets.SortGadgets(); } catch (Exception e) { Logger.LogError("Error unloading " + mod.Name + ": " + e); } }
internal static void LoadAllMods() { try { BatchLoading = true; Logger.Log("Loading mod files..."); foreach (string modDir in Directory.GetDirectories(GadgetPaths.ModsPath)) { LoadModDir(modDir); } foreach (string modFile in Directory.GetFiles(GadgetPaths.ModsPath)) { LoadModFile(modFile); } Logger.Log("Done loading mod files."); Logger.Log("Loading mods..."); foreach (GadgetMod mod in GadgetMods.ListAllMods(true)) { LoadGadgetMod(mod); } Logger.Log("Done loading mods."); if (GadgetCoreAPI.GetUMFAPI() != null) { Logger.Log("Loading Gadgets inside UMF mods..."); foreach (string mod in GadgetCoreAPI.GetUMFAPI().GetModNamesEnabled()) { ProcessUMFMod(mod); } Logger.Log("Done loading Gadgets inside UMF mods."); } Logger.Log("Sorting Gadgets..."); Gadgets.SortGadgets(); Logger.Log("Done sorting Gadgets."); Logger.Log("Queueing Gadgets for initialization..."); foreach (GadgetInfo gadget in Gadgets.ListAllEnabledGadgetInfos()) { QueuedGadgets.Add(gadget); } Logger.Log("Done queueing Gadgets."); EnableQueuedGadgets(); BatchLoading = false; Logger.Log("Initial load complete."); } catch (Exception e) { Logger.LogError("Uncaught exception during mod load: " + e); } }
internal static void UnregisterMod(GadgetMod Mod) { ModsByName.Remove(Mod.Name); ModsByPath.Remove(Mod.ModPath); ModsByAssembly.Remove(Mod.Assembly); bool wasBatchLoading = GadgetLoader.BatchLoading; GadgetLoader.BatchLoading = true; foreach (GadgetInfo gadget in Mod.LoadedGadgets.ToList()) { Gadgets.UnregisterGadget(gadget); GadgetLoader.QueuedGadgets.Add(gadget); } GadgetLoader.BatchLoading = wasBatchLoading; if (!GadgetLoader.BatchLoading) { GadgetLoader.DisableQueuedGadgets(); Gadgets.SortGadgets(); } }
/// <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); }