internal static void OnApplicationQuit() { if (IsInitialized && (Mods.Count() > 0)) { foreach (MelonMod mod in Mods) { try { mod.OnApplicationQuit(); } catch (Exception ex) { MelonModLogger.LogModError(ex.ToString(), mod.InfoAttribute.Name); } } } ModPrefs.SaveConfig(); NET_SDK.Harmony.Manager.UnpatchAll(); }
// Returns true if 'assembly' was already loaded or could be loaded, false if the required assembly was missing. private static bool TryLoad(AssemblyName assembly) { try { Assembly.Load(assembly); return(true); } catch (FileNotFoundException) { return(false); } catch (Exception ex) { MelonModLogger.LogError("Loading mod dependency failed: " + ex); return(false); } }
public static float GetFloat(string section, string name) { if (prefs.TryGetValue(section, out Dictionary <string, PrefDesc> prefsInSection) && prefsInSection.TryGetValue(name, out PrefDesc pref)) { if (float.TryParse(pref.Value, out float valueF)) { return(valueF); } } MelonModLogger.LogError("Trying to get unregistered Pref " + section + ":" + name); return(0.0f); }
public static void SetString(string section, string name, string value) { if (prefs.TryGetValue(section, out Dictionary <string, PrefDesc> prefsInSection) && prefsInSection.TryGetValue(name, out PrefDesc pref)) { pref.Value = value; ModPrefsController.SetString(section, name, value); } else { MelonModLogger.LogError("Trying to save unknown pref " + section + ":" + name); } }
internal static void OnGUI() { if (IsInitialized) { if (Mods.Count() > 0) { foreach (MelonMod mod in Mods) { try { mod.OnGUI(); } catch (Exception ex) { MelonModLogger.LogModError(ex.ToString(), mod.InfoAttribute.Name); } } } } }
private static void LoadAssembly(byte[] data, bool preload = false) { Assembly asm = Assembly.Load(data); if (!asm.Equals(null)) { LoadModFromAssembly(asm, preload); } else { MelonModLogger.LogError("Unable to load " + asm); } }
public static void SaveConfig() { foreach (KeyValuePair <string, Dictionary <string, PrefDesc> > prefsInSection in prefs) { foreach (KeyValuePair <string, PrefDesc> pref in prefsInSection.Value) { pref.Value.Value = pref.Value.ValueEdited; ModPrefsController.SetString(prefsInSection.Key, pref.Key, pref.Value.Value); } } Main.OnModSettingsApplied(); MelonModLogger.Log("Config Saved!"); }
public static void OnGUI() { if (Mods.Count() > 0) { for (int i = 0; i < Mods.Count; i++) { MelonMod mod = Mods[i]; if (mod != null) { try { mod.OnGUI(); } catch (Exception ex) { MelonModLogger.LogDLLError(ex.ToString(), mod.InfoAttribute.Name); } } } } }
internal static void OnModSettingsApplied() { if (Mods.Count() > 0) { for (int i = 0; i < Mods.Count; i++) { MelonMod mod = Mods[i]; if (mod != null) { try { mod.OnModSettingsApplied(); } catch (Exception ex) { MelonModLogger.LogModError(ex.ToString(), mod.InfoAttribute.Name); } } } } }
internal static void OnLevelWasLoaded(int level) { if (Mods.Count() > 0) { for (int i = 0; i < Mods.Count; i++) { MelonMod mod = Mods[i]; if (mod != null) { try { mod.OnLevelWasLoaded(level); } catch (Exception ex) { MelonModLogger.LogDLLError(ex.ToString(), mod.InfoAttribute.Name); } } } } }
internal static void OnLevelWasLoaded(int level) { if (IsInitialized) { if (Mods.Count() > 0) { foreach (MelonMod mod in Mods) { try { mod.OnLevelWasLoaded(level); } catch (Exception ex) { MelonModLogger.LogModError(ex.ToString(), mod.InfoAttribute.Name); } } } was_level_loaded = true; level_loaded_index = level; } }
private static void OnApplicationQuit() { if (Mods.Count() > 0) { for (int i = 0; i < Mods.Count; i++) { MelonMod mod = Mods[i]; if (mod != null) { try { mod.OnApplicationQuit(); } catch (Exception ex) { MelonModLogger.LogModError(ex.ToString(), mod.InfoAttribute.Name); } } } } ModPrefs.SaveConfig(); Harmony.HarmonyInstance.UnpatchAllInstances(); }
internal static void OnFixedUpdate() { if (IsInitialized) { if (Mods.Count() > 0) { foreach (MelonMod mod in Mods) { try { mod.OnFixedUpdate(); } catch (Exception ex) { MelonModLogger.LogModError(ex.ToString(), mod.InfoAttribute.Name); } } } if (Imports.IsIl2CppGame() && !Imports.IsMUPOTMode()) { MelonCoroutines.ProcessWaitForFixedUpdate(); } } }
public static void OnUpdate() { SceneHandler.CheckForSceneChange(); if (Imports.IsIl2CppGame() && IsVRChat) { VRChat_CheckUiManager(); } if (Mods.Count() > 0) { for (int i = 0; i < Mods.Count; i++) { MelonMod mod = Mods[i]; if (mod != null) { try { mod.OnUpdate(); } catch (Exception ex) { MelonModLogger.LogDLLError(ex.ToString(), mod.InfoAttribute.Name); } } } } }
public static void OnApplicationQuit() { if (Mods.Count() > 0) { for (int i = 0; i < Mods.Count; i++) { MelonMod mod = Mods[i]; if (mod != null) { try { mod.OnApplicationQuit(); } catch (Exception ex) { MelonModLogger.LogModError(ex.ToString(), mod.InfoAttribute.Name); } } } ModPrefs.SaveConfig(); } Harmony.HarmonyInstance.UnpatchAllInstances(); Imports.UNLOAD_MELONLOADER(); if (Imports.IsQuitFix()) { Process.GetCurrentProcess().Kill(); } }
internal static void Initialize() { try { string filepath = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "MelonLoader"), (Imports.IsIl2CppGame() ? "MelonLoader.Support.Il2Cpp.dll" : (File.Exists(Path.Combine(Imports.GetAssemblyDirectory(), "UnityEngine.CoreModule.dll")) ? "MelonLoader.Support.Mono.dll" : "MelonLoader.Support.Mono.Pre2017.dll"))); if (File.Exists(filepath)) { byte[] data = File.ReadAllBytes(filepath); if (data.Length > 0) { assembly = Assembly.Load(data); if (!assembly.Equals(null)) { type = assembly.GetType("MelonLoader.Support.Main"); if (!type.Equals(null)) { MethodInfo method = type.GetMethod("Initialize", BindingFlags.NonPublic | BindingFlags.Static); if (!method.Equals(null)) { supportModule = (ISupportModule)method.Invoke(null, new object[0]); } } } } } else { MelonModLogger.LogError("Unable to load Support Module! Support Module is Missing!"); MelonModLogger.Log("------------------------------"); } } catch (Exception e) { MelonModLogger.LogError("Unable to load Support Module!\n" + e.ToString()); MelonModLogger.Log("------------------------------"); } }
private static void RegisterPref(string section, string name, string defaultValue, string displayText, PrefType type, bool hideFromList) { if (prefs.TryGetValue(section, out Dictionary <string, PrefDesc> prefsInSection)) { if (prefsInSection.TryGetValue(name, out PrefDesc pref)) { MelonModLogger.LogError("Trying to registered Pref " + section + ":" + name + " more than one time"); } else { string toStoreValue = defaultValue; if (ModPrefsController.HasKey(section, name)) { toStoreValue = ModPrefsController.GetString(section, name, defaultValue); } else { ModPrefsController.SetString(section, name, defaultValue); } prefsInSection.Add(name, new PrefDesc(toStoreValue, type, hideFromList, (displayText ?? "") == "" ? name : displayText)); } } else { Dictionary <string, PrefDesc> dic = new Dictionary <string, PrefDesc>(); string toStoreValue = defaultValue; if (ModPrefsController.HasKey(section, name)) { toStoreValue = ModPrefsController.GetString(section, name, defaultValue); } else { ModPrefsController.SetString(section, name, defaultValue); } dic.Add(name, new PrefDesc(toStoreValue, type, hideFromList, (displayText ?? "") == "" ? name : displayText)); prefs.Add(section, dic); } }
private void TopologicalSortInto(IList <T> loadedMods) { int[] unloadedDependencies = new int[vertices.Length]; SortedList <string, Vertex> loadableMods = new SortedList <string, Vertex>(); int skippedMods = 0; // Find all sinks in the dependency graph, i.e. mods without any dependencies on other mods for (int i = 0; i < vertices.Length; ++i) { Vertex vertex = vertices[i]; int dependencyCount = vertex.dependencies.Count; unloadedDependencies[i] = dependencyCount; if (dependencyCount == 0) { loadableMods.Add(vertex.name, vertex); } } // Perform the (reverse) topological sorting while (loadableMods.Count > 0) { Vertex mod = loadableMods.Values[0]; loadableMods.RemoveAt(0); if (!mod.skipLoading) { loadedMods.Add(mod.mod); } else { ++skippedMods; } foreach (Vertex dependent in mod.dependents) { unloadedDependencies[dependent.index] -= 1; dependent.skipLoading |= mod.skipLoading; if (unloadedDependencies[dependent.index] == 0) { loadableMods.Add(dependent.name, dependent); } } } // Check if all mods were either loaded or skipped. If this is not the case, there is a cycle in the dependency graph if (loadedMods.Count + skippedMods < vertices.Length) { StringBuilder errorMessage = new StringBuilder("Some mods could not be loaded due to a cyclic dependency:\n"); for (int i = 0; i < vertices.Length; ++i) { if (unloadedDependencies[i] > 0) { errorMessage.Append($"- '{vertices[i].name}'\n"); } } errorMessage.Length -= 1; // Remove trailing newline MelonModLogger.LogError(errorMessage.ToString()); } }
public static void OnModSettingsApplied() { if (Plugins.Count > 0) { for (int i = 0; i < Plugins.Count; i++) { MelonPlugin plugin = Plugins[i]; if (plugin != null) { try { plugin.OnModSettingsApplied(); } catch (Exception ex) { MelonModLogger.LogDLLError(ex.ToString(), plugin.InfoAttribute.Name); } } } } if (Mods.Count() > 0) { for (int i = 0; i < Mods.Count; i++) { MelonMod mod = Mods[i]; if (mod != null) { try { mod.OnModSettingsApplied(); } catch (Exception ex) { MelonModLogger.LogDLLError(ex.ToString(), mod.InfoAttribute.Name); } } } } }
private static void Initialize() { if (string.IsNullOrEmpty(AppDomain.CurrentDomain.BaseDirectory)) { ((AppDomainSetup)typeof(AppDomain).GetProperty("SetupInformationNoCopy", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(AppDomain.CurrentDomain, new object[0])).ApplicationBase = Imports.GetGameDirectory(); } Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory); AppDomain.CurrentDomain.UnhandledException += ExceptionHandler; CurrentGameAttribute = new MelonModGameAttribute(Imports.GetCompanyName(), Imports.GetProductName()); UnityVersion = GetUnityFileVersion(); if (Imports.IsIl2CppGame()) { IsVRChat = CurrentGameAttribute.IsGame("VRChat", "VRChat"); IsBoneworks = CurrentGameAttribute.IsGame("Stress Level Zero", "BONEWORKS"); } if (!Imports.IsDebugMode() #if !DEBUG && Imports.IsConsoleEnabled() #endif ) { Console.Enabled = true; Console.Create(); } if (!Imports.IsIl2CppGame() || AssemblyGenerator.Main.Initialize()) { HasGeneratedAssembly = true; } else { Imports.UNLOAD_MELONLOADER(); } if (HasGeneratedAssembly) { LoadDLLs(true); if (Plugins.Count > 0) { HashSet <MelonPlugin> failedPlugins = new HashSet <MelonPlugin>(); TempPlugins = Plugins.Where(plugin => (plugin.Compatibility < MelonBase.MelonCompatibility.INCOMPATIBLE)).ToList(); DependencyGraph <MelonPlugin> .TopologicalSort(TempPlugins, plugin => plugin.InfoAttribute.Name); for (int i = 0; i < TempPlugins.Count; i++) { MelonPlugin plugin = TempPlugins[i]; if (plugin != null) { try { plugin.OnPreInitialization(); } catch (Exception ex) { MelonModLogger.LogDLLError(ex.ToString(), plugin.InfoAttribute.Name); failedPlugins.Add(plugin); } } } TempPlugins.RemoveAll(plugin => failedPlugins.Contains(plugin)); } } }
private DependencyGraph(IList <T> mods, Func <T, string> modNameGetter) { int size = mods.Count; vertices = new Vertex[size]; IDictionary <string, Vertex> nameLookup = new Dictionary <string, Vertex>(size); // Create a vertex in the dependency graph for each mod to load for (int i = 0; i < size; ++i) { Assembly modAssembly = mods[i].Assembly; string modName = modNameGetter(mods[i]); Vertex modVertex = new Vertex(i, mods[i], modName); vertices[i] = modVertex; nameLookup[modAssembly.GetName().Name] = modVertex; } // Add an edge for each dependency between mods IDictionary <string, IList <AssemblyName> > modsWithMissingDeps = new SortedDictionary <string, IList <AssemblyName> >(); List <AssemblyName> missingDependencies = new List <AssemblyName>(); HashSet <string> optionalDependencies = new HashSet <string>(); foreach (Vertex modVertex in vertices) { Assembly modAssembly = modVertex.mod.Assembly; missingDependencies.Clear(); optionalDependencies.Clear(); MelonOptionalDependenciesAttribute optionals = (MelonOptionalDependenciesAttribute)Attribute.GetCustomAttribute(modAssembly, typeof(MelonOptionalDependenciesAttribute)); if (optionals != null && optionals.AssemblyNames != null) { optionalDependencies.UnionWith(optionals.AssemblyNames); } foreach (AssemblyName dependency in modAssembly.GetReferencedAssemblies()) { if (nameLookup.TryGetValue(dependency.Name, out Vertex dependencyVertex)) { modVertex.dependencies.Add(dependencyVertex); dependencyVertex.dependents.Add(modVertex); } else if (!TryLoad(dependency) && !optionalDependencies.Contains(dependency.Name)) { missingDependencies.Add(dependency); } } if (missingDependencies.Count > 0) { // modVertex.skipLoading = true; modsWithMissingDeps.Add(modNameGetter(modVertex.mod), missingDependencies.ToArray()); } } if (modsWithMissingDeps.Count > 0) { // Some mods are missing dependencies. Don't load these mods and show an error message MelonModLogger.LogWarning(BuildMissingDependencyMessage(modsWithMissingDeps)); } }
private static void VRChat_CheckUiManager() { if (IsInitialized && ShouldCheckForUiManager) { if (VRCUiManager == null) { VRCUiManager = NET_SDK.SDK.GetClass("VRCUiManager"); } if (VRCUiManager != null) { if (VRCUiManager_GetInstance == null) { NET_SDK.Reflection.IL2CPP_Method[] methods = VRCUiManager.GetMethods(); foreach (NET_SDK.Reflection.IL2CPP_Method method in methods) { NET_SDK.Reflection.IL2CPP_Type returntype = method.GetReturnType(); if ((returntype != null) && !string.IsNullOrEmpty(returntype.Name) && returntype.Name.Equals("VRCUiManager")) { if (method.HasFlag(NET_SDK.Reflection.IL2CPP_BindingFlags.METHOD_STATIC)) { VRCUiManager_GetInstance = method; break; } } } } if (VRCUiManager_GetInstance != null) { NET_SDK.Reflection.IL2CPP_Object returnval = VRCUiManager_GetInstance.Invoke(); if (returnval != null) { ShouldCheckForUiManager = false; if (Mods.Count() > 0) { foreach (MelonMod mod in Mods) { try { mod.VRChat_OnUiManagerInit(); } catch (Exception ex) { MelonModLogger.LogModError(ex.ToString(), mod.InfoAttribute.Name); } } } } } } } }
private static void ExceptionHandler(object sender, UnhandledExceptionEventArgs e) => MelonModLogger.LogError((e.ExceptionObject as Exception).ToString());
private static void VRChat_CheckUiManager() { if (ShouldCheckForUiManager) { if (VRCUiManager == null) { VRCUiManager = Assembly_CSharp.GetType("VRCUiManager"); } if (VRCUiManager != null) { if (VRCUiManager_Instance == null) { VRCUiManager_Instance = VRCUiManager.GetProperty("field_Protected_Static_VRCUiManager_0"); } if (VRCUiManager_Instance != null) { object returnval = VRCUiManager_Instance.GetValue(null, new object[0]); if (returnval != null) { ShouldCheckForUiManager = false; if (Mods.Count() > 0) { for (int i = 0; i < Mods.Count; i++) { MelonMod mod = Mods[i]; if (mod != null) { try { mod.VRChat_OnUiManagerInit(); } catch (Exception ex) { MelonModLogger.LogDLLError(ex.ToString(), mod.InfoAttribute.Name); } } } } } } } } }
private static void LoadMods(bool preload = false) { string modDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Combine("Mods", (preload ? "PRELOAD" : ""))); if (!Directory.Exists(modDirectory)) { Directory.CreateDirectory(modDirectory); } else { // DLL string[] files = Directory.GetFiles(modDirectory, "*.dll", SearchOption.TopDirectoryOnly); if (files.Length > 0) { for (int i = 0; i < files.Count(); i++) { string file = files[i]; if (!string.IsNullOrEmpty(file)) { try { byte[] data = File.ReadAllBytes(file); if (data.Length > 0) { LoadAssembly(data, preload); } else { MelonModLogger.LogError("Unable to load " + file); MelonModLogger.Log("------------------------------"); } } catch (Exception e) { MelonModLogger.LogError("Unable to load " + file + ":\n" + e.ToString()); MelonModLogger.Log("------------------------------"); } } } } // ZIP /* * string[] zippedFiles = Directory.GetFiles(modDirectory, "*.zip", SearchOption.TopDirectoryOnly); * if (zippedFiles.Length > 0) * { * for (int i = 0; i < zippedFiles.Count(); i++) * { * string file = zippedFiles[i]; * if (!string.IsNullOrEmpty(file)) * { * try * { * using (var fileStream = File.OpenRead(file)) * { * using (var zipInputStream = new ZipInputStream(fileStream)) * { * ZipEntry entry; * while ((entry = zipInputStream.GetNextEntry()) != null) * { * if ((Path.GetFileName(entry.Name).Length <= 0) || !Path.GetFileName(entry.Name).EndsWith(".dll")) * continue; * * using (var unzippedFileStream = new MemoryStream()) * { * int size = 0; * byte[] buffer = new byte[4096]; * while (true) * { * size = zipInputStream.Read(buffer, 0, buffer.Length); * if (size > 0) * unzippedFileStream.Write(buffer, 0, size); * else * break; * } * LoadAssembly(unzippedFileStream.ToArray(), preload); * } * } * } * } * } * catch (Exception e) * { * MelonModLogger.LogError("Unable to load " + file + ":\n" + e.ToString()); * MelonModLogger.Log("------------------------------"); * } * } * } * } */ } }
private static void Initialize() { if (string.IsNullOrEmpty(AppDomain.CurrentDomain.BaseDirectory)) { ((AppDomainSetup)typeof(AppDomain).GetProperty("SetupInformationNoCopy", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(AppDomain.CurrentDomain, new object[0])).ApplicationBase = Imports.GetGameDirectory(); } Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory); AppDomain.CurrentDomain.UnhandledException += ExceptionHandler; CurrentGameAttribute = new MelonModGameAttribute(Imports.GetCompanyName(), Imports.GetProductName()); UnityVersion = GetUnityFileVersion(); if (Imports.IsIl2CppGame()) { IsVRChat = CurrentGameAttribute.IsGame("VRChat", "VRChat"); IsBoneworks = CurrentGameAttribute.IsGame("Stress Level Zero", "BONEWORKS"); } if (!Imports.IsDebugMode()) { Console.Enabled = true; Console.Create(); } if (Imports.IsIl2CppGame() && !AssemblyGenerator.Main.Initialize()) { Imports.UNLOAD_MELONLOADER(true); } else { LoadMods(true); if (Mods.Count > 0) { for (int i = 0; i < Mods.Count; i++) { MelonMod mod = Mods[i]; if (mod != null) { try { mod.OnPreInitialization(); } catch (Exception ex) { MelonModLogger.LogModError(ex.ToString(), mod.InfoAttribute.Name); } } } } } }
private static void LoadDLLs(bool plugins = false) { string searchdir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, (plugins ? "Plugins" : "Mods")); if (!Directory.Exists(searchdir)) { Directory.CreateDirectory(searchdir); } else { // DLL string[] files = Directory.GetFiles(searchdir, "*.dll"); if (files.Length > 0) { for (int i = 0; i < files.Count(); i++) { string file = files[i]; if (!string.IsNullOrEmpty(file)) { if (plugins) { if ((Imports.IsDevPluginsOnly() && !file.EndsWith("-dev.dll")) || (!Imports.IsDevPluginsOnly() && file.EndsWith("-dev.dll"))) { continue; } } else { if ((Imports.IsDevModsOnly() && !file.EndsWith("-dev.dll")) || (!Imports.IsDevModsOnly() && file.EndsWith("-dev.dll"))) { continue; } } try { LoadAssembly(File.ReadAllBytes(file), plugins, file); } catch (Exception e) { MelonModLogger.LogError("Unable to load " + file + ":\n" + e.ToString()); MelonModLogger.Log("------------------------------"); } } } } // ZIP string[] zippedFiles = Directory.GetFiles(searchdir, "*.zip"); if (zippedFiles.Length > 0) { for (int i = 0; i < zippedFiles.Count(); i++) { string file = zippedFiles[i]; if (!string.IsNullOrEmpty(file)) { try { using (var fileStream = File.OpenRead(file)) { using (var zipInputStream = new ZipInputStream(fileStream)) { ZipEntry entry; while ((entry = zipInputStream.GetNextEntry()) != null) { string filename = Path.GetFileName(entry.Name); if (string.IsNullOrEmpty(filename) || !filename.EndsWith(".dll")) { continue; } if (plugins) { if ((Imports.IsDevPluginsOnly() && !filename.EndsWith("-dev.dll")) || (!Imports.IsDevPluginsOnly() && filename.EndsWith("-dev.dll"))) { continue; } } else { if ((Imports.IsDevModsOnly() && !filename.EndsWith("-dev.dll")) || (!Imports.IsDevModsOnly() && filename.EndsWith("-dev.dll"))) { continue; } } using (var unzippedFileStream = new MemoryStream()) { int size = 0; byte[] buffer = new byte[4096]; while (true) { size = zipInputStream.Read(buffer, 0, buffer.Length); if (size > 0) { unzippedFileStream.Write(buffer, 0, size); } else { break; } } LoadAssembly(unzippedFileStream.ToArray(), plugins, (file + "/" + filename)); } } } } } catch (Exception e) { MelonModLogger.LogError("Unable to load " + file + ":\n" + e.ToString()); MelonModLogger.Log("------------------------------"); } } } } } }
private static void LoadModFromAssembly(Assembly assembly, bool isPlugin = false) { MelonModInfoAttribute modInfoAttribute = assembly.GetCustomAttributes(false).FirstOrDefault(x => (x.GetType() == typeof(MelonModInfoAttribute))) as MelonModInfoAttribute; if ((modInfoAttribute != null) && (modInfoAttribute.ModType != null) && modInfoAttribute.ModType.IsSubclassOf(typeof(MelonMod))) { bool should_continue = false; bool isUniversal = false; MelonModGameAttribute[] modGameAttributes = assembly.GetCustomAttributes(typeof(MelonModGameAttribute), true) as MelonModGameAttribute[]; int modGameAttributes_Count = modGameAttributes.Length; if (modGameAttributes_Count > 0) { for (int i = 0; i < modGameAttributes_Count; i++) { MelonModGameAttribute modGameAttribute = modGameAttributes[i]; if (CurrentGameAttribute.IsCompatible(modGameAttribute)) { isUniversal = CurrentGameAttribute.IsCompatibleBecauseUniversal(modGameAttribute); should_continue = true; break; } } } else { isUniversal = true; should_continue = true; } if (should_continue) { try { MelonMod modInstance = Activator.CreateInstance(modInfoAttribute.ModType) as MelonMod; if (modInstance != null) { modInstance.IsUniversal = isUniversal; modInstance.IsPlugin = isPlugin; modInstance.InfoAttribute = modInfoAttribute; if (modGameAttributes_Count > 0) { modInstance.GameAttributes = modGameAttributes; } else { modInstance.GameAttributes = null; } modInstance.ModAssembly = assembly; Harmony.HarmonyInstance.Create(assembly.FullName).PatchAll(assembly); Mods.Add(modInstance); } else { MelonModLogger.LogError("Unable to load Mod in " + assembly.GetName() + "! Failed to Create Instance!"); } } catch (Exception e) { MelonModLogger.LogError("Unable to load Mod in " + assembly.GetName() + "! " + e.ToString()); } } else { MelonModLogger.LogModStatus(3); } } }
private static void OnApplicationStart() { if (!HasGeneratedAssembly) { return; } if (Imports.IsIl2CppGame()) { if (IsVRChat) { Assembly_CSharp = Assembly.Load("Assembly-CSharp"); } UnhollowerSupport.Initialize(); } SupportModule.Initialize(); MelonModLogger.Log("------------------------------"); MelonModLogger.Log("Unity " + UnityVersion); MelonModLogger.Log("------------------------------"); MelonModLogger.Log("Name: " + CurrentGameAttribute.GameName); MelonModLogger.Log("Developer: " + CurrentGameAttribute.Developer); MelonModLogger.Log("Type: " + (Imports.IsIl2CppGame() ? "Il2Cpp" : (Imports.IsOldMono() ? "Mono" : "MonoBleedingEdge"))); MelonModLogger.Log("------------------------------"); MelonModLogger.Log("Using v" + BuildInfo.Version + " Open-Beta"); MelonModLogger.Log("------------------------------"); LoadDLLs(); if (Plugins.Count > 0) { for (int i = 0; i < Plugins.Count; i++) { MelonPlugin plugin = Plugins[i]; if (plugin != null) { MelonModLogger.Log(plugin.InfoAttribute.Name + (!string.IsNullOrEmpty(plugin.InfoAttribute.Version) ? (" v" + plugin.InfoAttribute.Version) : "") + (!string.IsNullOrEmpty(plugin.InfoAttribute.Author) ? (" by " + plugin.InfoAttribute.Author) : "") + (!string.IsNullOrEmpty(plugin.InfoAttribute.DownloadLink) ? (" (" + plugin.InfoAttribute.DownloadLink + ")") : "") ); MelonModLogger.LogDLLStatus(plugin.Compatibility); MelonModLogger.Log("------------------------------"); } } Plugins = TempPlugins; } if (Plugins.Count <= 0) { MelonModLogger.Log("No Plugins Loaded!"); MelonModLogger.Log("------------------------------"); } if (Mods.Count > 0) { for (int i = 0; i < Mods.Count; i++) { MelonMod mod = Mods[i]; if (mod != null) { MelonModLogger.Log(mod.InfoAttribute.Name + (!string.IsNullOrEmpty(mod.InfoAttribute.Version) ? (" v" + mod.InfoAttribute.Version) : "") + (!string.IsNullOrEmpty(mod.InfoAttribute.Author) ? (" by " + mod.InfoAttribute.Author) : "") + (!string.IsNullOrEmpty(mod.InfoAttribute.DownloadLink) ? (" (" + mod.InfoAttribute.DownloadLink + ")") : "") ); MelonModLogger.LogDLLStatus(mod.Compatibility); MelonModLogger.Log("------------------------------"); } } Mods.RemoveAll((MelonMod mod) => (mod.Compatibility >= MelonBase.MelonCompatibility.INCOMPATIBLE)); DependencyGraph <MelonMod> .TopologicalSort(Mods, mod => mod.InfoAttribute.Name); } if (Mods.Count <= 0) { MelonModLogger.Log("No Mods Loaded!"); MelonModLogger.Log("------------------------------"); } if ((Plugins.Count > 0) || (Mods.Count > 0)) { AddUnityDebugLog(); } if (Plugins.Count > 0) { HashSet <MelonPlugin> failedPlugins = new HashSet <MelonPlugin>(); for (int i = 0; i < Plugins.Count; i++) { MelonPlugin plugin = Plugins[i]; if (plugin != null) { try { InitializeModOrPlugin(plugin); } catch (Exception ex) { MelonModLogger.LogDLLError(ex.ToString(), plugin.InfoAttribute.Name); failedPlugins.Add(plugin); } } } Plugins.RemoveAll(plugin => failedPlugins.Contains(plugin)); } if (Mods.Count > 0) { HashSet <MelonMod> failedMods = new HashSet <MelonMod>(); for (int i = 0; i < Mods.Count; i++) { MelonMod mod = Mods[i]; if (mod != null) { try { InitializeModOrPlugin(mod); } catch (Exception ex) { MelonModLogger.LogDLLError(ex.ToString(), mod.InfoAttribute.Name); failedMods.Add(mod); } } } Mods.RemoveAll(mod => failedMods.Contains(mod)); } if ((Plugins.Count <= 0) && (Mods.Count <= 0)) { SupportModule.Destroy(); } }
private static void OnApplicationStart() { if (!HasGeneratedAssembly) { return; } if (Imports.IsIl2CppGame()) { if (IsVRChat) { Assembly_CSharp = Assembly.Load("Assembly-CSharp"); } UnhollowerSupport.Initialize(); } SupportModule.Initialize(); MelonModLogger.Log("------------------------------"); MelonModLogger.Log("Unity " + UnityVersion); MelonModLogger.Log("------------------------------"); MelonModLogger.Log("Name: " + CurrentGameAttribute.GameName); MelonModLogger.Log("Developer: " + CurrentGameAttribute.Developer); MelonModLogger.Log("Type: " + (Imports.IsIl2CppGame() ? "Il2Cpp" : (Imports.IsOldMono() ? "Mono" : "MonoBleedingEdge"))); MelonModLogger.Log("------------------------------"); MelonModLogger.Log("Using v" + BuildInfo.Version + " Open-Beta"); MelonModLogger.Log("------------------------------"); LoadMods(); if (Mods.Count > 0) { AddUnityDebugLog(); for (int i = 0; i < Mods.Count; i++) { MelonMod mod = Mods[i]; if (mod != null) { MelonModLogger.Log(mod.InfoAttribute.Name + (!string.IsNullOrEmpty(mod.InfoAttribute.Version) ? (" v" + mod.InfoAttribute.Version) : "") + (!string.IsNullOrEmpty(mod.InfoAttribute.Author) ? (" by " + mod.InfoAttribute.Author) : "") + (!string.IsNullOrEmpty(mod.InfoAttribute.DownloadLink) ? (" (" + mod.InfoAttribute.DownloadLink + ")") : "") ); if (Imports.IsDebugMode()) { MelonModLogger.Log("Plugin: " + mod.IsPlugin.ToString()); } MelonModLogger.LogModStatus((mod.GameAttributes.Any()) ? (mod.IsUniversal ? 0 : 1) : 2); MelonModLogger.Log("------------------------------"); } } for (int i = 0; i < Mods.Count; i++) { MelonMod mod = Mods[i]; if (mod != null) { try { mod.OnApplicationStart(); } catch (Exception ex) { MelonModLogger.LogModError(ex.ToString(), mod.InfoAttribute.Name); } } } } else { MelonModLogger.Log("No Mods Loaded!"); MelonModLogger.Log("------------------------------"); } }