private static void SetupSupportModule(AppDomain domain) { try { string BaseDirectory = Path.Combine(Path.Combine(Path.Combine(MelonUtils.GameDirectory, "MelonLoader"), "Dependencies"), "SupportModules"); if (!Directory.Exists(BaseDirectory)) { MelonLogger.Error("Failed to Find SupportModules Directory!"); return; } Assembly CompatibilityLayerAssembly = Assembly.LoadFrom(Path.Combine(BaseDirectory, "CompatibilityLayer.dll")); if (CompatibilityLayerAssembly == null) { MelonLogger.Error("Failed to Load Assembly for CompatibilityLayer!"); return; } Type CompatibilityLayerType = CompatibilityLayerAssembly.GetType("MelonLoader.Support.CompatibilityLayer"); if (CompatibilityLayerType == null) { MelonLogger.Error("Failed to Get Type for CompatibilityLayer!"); return; } MethodInfo CompatibilityLayerSetupMethod = CompatibilityLayerType.GetMethod("Setup", BindingFlags.NonPublic | BindingFlags.Static); if (CompatibilityLayerType == null) { MelonLogger.Error("Failed to Get Setup Method for CompatibilityLayer!"); return; } CompatibilityLayerSetupMethod.Invoke(null, new object[] { domain }); } catch (Exception ex) { MelonLogger.Error(ex.ToString()); } }
public override DynamicMethodDefinition CopyOriginal() { DynamicMethodDefinition method = Original.ToNewDynamicMethodDefinition(); method.Definition.Name += "_wrapper"; ILContext ilcontext = new ILContext(method.Definition); ILCursor ilcursor = new ILCursor(ilcontext); FieldReference tempfieldreference = null; if (ilcursor.TryGotoNext(x => x.MatchLdsfld(out tempfieldreference), x => x.MatchCall(UnhollowerSupport.IL2CPPType, "il2cpp_object_get_virtual_method"))) { // Virtual method: Replace the sequence // - ldarg.0 // - call native int[UnhollowerBaseLib] UnhollowerBaseLib.IL2CPP::Il2CppObjectBaseToPtr(class [UnhollowerBaseLib] UnhollowerBaseLib.Il2CppObjectBase) // - ldsfld native int SomeClass::NativeMethodInfoPtr_Etc // - call native int[UnhollowerBaseLib] UnhollowerBaseLib.IL2CPP::il2cpp_object_get_virtual_method(native int, native int) ilcursor.Index -= 2; ilcursor.RemoveRange(4); } else if (ilcursor.TryGotoNext(x => x.MatchLdsfld(UnhollowerSupport.MethodBaseToIl2CppFieldInfo(Original)))) { ilcursor.Remove(); } else { MelonLogger.Error("Harmony Patcher could not rewrite Il2Cpp Unhollowed Method. Expect a stack overflow."); return(method); } ilcursor.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I8, copiedMethodInfoPointer.ToInt64()); ilcursor.Emit(Mono.Cecil.Cil.OpCodes.Conv_I); return(method); }
public void SaveToFile(bool printmsg = true) { Preferences.IO.File currentfile = File; if (currentfile == null) { currentfile = MelonPreferences.DefaultFile; } foreach (MelonPreferences_Entry entry in Entries) { if (!(entry.DontSaveDefault && entry.GetValueAsString() == entry.GetDefaultValueAsString()) && entry.GetValueAsString() != null) { currentfile.InsertIntoDocument(Identifier, entry.Identifier, entry.Save()); } } try { currentfile.Save(); } catch (Exception ex) { MelonLogger.Error($"Error while Saving Preferences to {currentfile.FilePath}: {ex}"); currentfile.WasError = true; } if (printmsg) { MelonLogger.Msg($"MelonPreferences Saved to {currentfile.FilePath}"); } MelonHandler.OnPreferencesSaved(); }
internal static bool Setup() { UnityEngine_CoreModule_Path = Path.Combine(MelonUtils.GetManagedDirectory(), "UnityEngine.CoreModule.dll"); BaseDirectory = Path.Combine(Path.Combine(Path.Combine(MelonUtils.BaseDirectory, "MelonLoader"), "Dependencies"), "SupportModules"); if (!Directory.Exists(BaseDirectory)) { MelonLogger.Error("Failed to Find SupportModules Directory!"); return(false); } LemonEnumerator <ModuleListing> enumerator = new LemonEnumerator <ModuleListing>(Modules); while (enumerator.MoveNext()) { string ModulePath = Path.Combine(BaseDirectory, enumerator.Current.FileName); if (!File.Exists(ModulePath)) { continue; } try { if (enumerator.Current.LoadSpecifier != null) { if (!enumerator.Current.LoadSpecifier()) { File.Delete(ModulePath); continue; } } if (Interface != null) { continue; } if (!LoadInterface(ModulePath)) { continue; } } catch (Exception ex) { MelonDebug.Error($"Support Module [{enumerator.Current.FileName}] threw an Exception: {ex}"); continue; } } if (Interface == null) { MelonLogger.Error("No Support Module Loaded!"); return(false); } return(true); }
// 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) { MelonLogger.Error("Loading mod dependency failed: " + ex); return(false); } }
internal static void Quit() { MelonHandler.OnApplicationQuit(); try { MelonPreferences.Save(); } catch (Exception ex) { MelonLogger.Error("MelonPreferences.Save Exception: " + ex.ToString()); MelonPreferences.WasError = true; } Harmony.HarmonyInstance.UnpatchAllInstances(); try { bHaptics.Quit(); } catch (Exception ex) { MelonLogger.Error("bHaptics.Quit Exception: " + ex.ToString()); bHaptics.WasError = true; } MelonLogger.Flush(); if (QuitFix()) { System.Diagnostics.Process.GetCurrentProcess().Kill(); } }
private static void Start() { if (!SupportModule.Initialize()) { return; } AddUnityDebugLog(); try { bHaptics.Start(); } catch (Exception ex) { MelonLogger.Error("bHaptics.Start Exception: " + ex.ToString()); bHaptics.WasError = true; } MelonHandler.OnApplicationStart_Plugins(); MelonHandler.LoadMods(); Main.LegacySupport(); MelonHandler.OnApplicationStart_Mods(); }
internal static bool Initialize() { MelonLogger.Msg("Loading Support Module..."); string BaseDirectory = Path.Combine(Path.Combine(Path.Combine(MelonUtils.GameDirectory, "MelonLoader"), "Dependencies"), "SupportModules"); if (!Directory.Exists(BaseDirectory)) { MelonLogger.Error("Failed to Find SupportModules Directory!"); return(false); } string ModuleName = (MelonUtils.IsGameIl2Cpp() ? "Il2Cpp.dll" : (File.Exists(Path.Combine(MelonUtils.GetManagedDirectory(), "UnityEngine.CoreModule.dll")) ? "Mono.dll" : (IsOldUnity() ? "Mono.Pre-5.dll" : "Mono.Pre-2017.dll"))); string ModulePath = Path.Combine(BaseDirectory, ModuleName); if (!File.Exists(ModulePath)) { MelonLogger.Error("Failed to Find Support Module " + ModuleName + "!"); return(false); } try { Assembly assembly = Assembly.LoadFrom(ModulePath); if (assembly == null) { MelonLogger.Error("Failed to Load Assembly from " + ModuleName + "!"); return(false); } Type type = assembly.GetType("MelonLoader.Support.Main"); if (type == null) { MelonLogger.Error("Failed to Get Type MelonLoader.Support.Main!"); return(false); } MethodInfo method = type.GetMethod("Initialize", BindingFlags.NonPublic | BindingFlags.Static); if (method == null) { MelonLogger.Error("Failed to Get Method Initialize!"); return(false); } Interface = (ISupportModule_To)method.Invoke(null, new object[] { new SupportModule_From() }); if (Interface == null) { MelonLogger.Error("Failed to Initialize Interface!"); return(false); } } catch (Exception ex) { MelonLogger.Error(ex.ToString()); return(false); } return(true); }
internal static int Initialize(ConfigFile configFile) { AppDomain curDomain = AppDomain.CurrentDomain; HarmonyInstance = new HarmonyLib.Harmony(BuildInfo.Name); if (MelonLaunchOptions.Core.EnableFixes) { Fixes.UnhandledException.Run(curDomain); Fixes.InvariantCurrentCulture.Install(); } try { MelonUtils.Setup(); } catch (Exception ex) { MelonLogger.Error($"MelonUtils.Setup Exception: {ex}"); throw; } if (MelonLaunchOptions.Core.EnableFixes) { Fixes.ApplicationBase.Run(curDomain); Fixes.ExtraCleanup.Run(); } MelonPreferences.Load(); MelonLaunchOptions.Load(configFile); if (MelonLaunchOptions.Core.EnableCompatibilityLayers) { MelonCompatibilityLayer.Setup(); } if (MelonLaunchOptions.Core.EnablePatchShield) { PatchShield.Install(); } if (MelonLaunchOptions.Core.EnableBHapticsIntegration) { bHaptics.Load(); } if (MelonLaunchOptions.Core.EnableCompatibilityLayers) { MelonCompatibilityLayer.SetupModules(MelonCompatibilityLayer.SetupType.OnPreInitialization); } MelonHandler.LoadPlugins(); MelonHandler.OnPreInitialization(); return(0); }
internal static void Load() { if (!MelonUtils.IsGameIl2Cpp()) { return; } MelonLogger.Msg("Loading Il2CppAssemblyGenerator..."); string BaseDirectory = Path.Combine(Path.Combine(Path.Combine(MelonUtils.GameDirectory, "MelonLoader"), "Dependencies"), "Il2CppAssemblyGenerator"); if (!Directory.Exists(BaseDirectory)) { MelonLogger.Error("Failed to Find Il2CppAssemblyGenerator Directory!"); return; } string AssemblyPath = Path.Combine(BaseDirectory, FileNameWithExtension); if (!File.Exists(AssemblyPath)) { MelonLogger.Error($"Failed to Find {FileNameWithExtension}!"); return; } try { asm = Assembly.LoadFrom(AssemblyPath); if (asm == null) { MelonLogger.ThrowInternalFailure($"Failed to Load Assembly for {FileNameWithExtension}!"); return; } AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolver; Type type = asm.GetType("MelonLoader.Il2CppAssemblyGenerator.Core"); if (type == null) { MelonLogger.ThrowInternalFailure($"Failed to Get Type for MelonLoader.Il2CppAssemblyGenerator.Core!"); return; } RunMethod = type.GetMethod("Run", BindingFlags.NonPublic | BindingFlags.Static); } catch (Exception ex) { MelonLogger.ThrowInternalFailure($"Il2CppAssemblyGenerator Exception: {ex}"); } }
static Core() { AppDomain curDomain = AppDomain.CurrentDomain; HarmonyInstance = new HarmonyLib.Harmony(BuildInfo.Name); Fixes.UnhandledException.Run(curDomain); Fixes.InvariantCurrentCulture.Install(); try { MelonUtils.Setup(); } catch (Exception ex) { MelonLogger.Error("MelonUtils.Setup Exception: " + ex.ToString()); throw ex; } Fixes.ApplicationBase.Run(curDomain); Fixes.ExtraCleanup.Run(); MelonPreferences.Load(); MelonLaunchOptions.Load(); MelonCompatibilityLayer.Setup(curDomain); //PatchShield.Install(); }
static Core() { try { MelonUtils.Setup(); } catch (Exception ex) { MelonLogger.Error("MelonUtils.Setup Exception: " + ex.ToString()); throw ex; } Harmony.HarmonyInstance harmonyInstance = Harmony.HarmonyInstance.Create("MelonLoader"); try { harmonyInstance.Patch(typeof(Thread).GetProperty("CurrentCulture", BindingFlags.Public | BindingFlags.Instance).GetGetMethod(), new Harmony.HarmonyMethod(typeof(Core).GetMethod("GetCurrentCulturePrefix", BindingFlags.NonPublic | BindingFlags.Static))); } catch (Exception ex) { MelonLogger.Warning("Thread.CurrentCulture Exception: " + ex.ToString()); } try { harmonyInstance.Patch(typeof(Thread).GetProperty("CurrentUICulture", BindingFlags.Public | BindingFlags.Instance).GetGetMethod(), new Harmony.HarmonyMethod(typeof(Core).GetMethod("GetCurrentCulturePrefix", BindingFlags.NonPublic | BindingFlags.Static))); } catch (Exception ex) { MelonLogger.Warning("Thread.CurrentUICulture Exception: " + ex.ToString()); } try { ((AppDomainSetup)typeof(AppDomain).GetProperty("SetupInformationNoCopy", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(AppDomain.CurrentDomain, new object[0])).ApplicationBase = MelonUtils.GameDirectory; } catch (Exception ex) { MelonLogger.Warning("AppDomainSetup.ApplicationBase Exception: " + ex.ToString()); } Directory.SetCurrentDirectory(MelonUtils.GameDirectory); AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler; AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolveHandler; AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += AssemblyResolveHandler; try { MelonPreferences.LegacyCheck(); } catch (Exception ex) { MelonLogger.Error("MelonPreferences.LegacyCheck Exception: " + ex.ToString()); MelonPreferences.WasError = true; } try { MelonPreferences.Load_Internal(); } catch (Exception ex) { MelonLogger.Error("MelonPreferences.Load_Internal Exception: " + ex.ToString()); MelonPreferences.WasError = true; } if (MelonPreferences.WasLegacyLoaded) { try { MelonPreferences.Save_Internal(); } catch (Exception ex) { MelonLogger.Error("MelonPreferences.Save_Internal Exception: " + ex.ToString()); MelonPreferences.WasError = true; } } MelonPreferences.SaveAfterEntryCreation = true; try { bHaptics_NativeLibrary.Load(); } catch (Exception ex) { MelonLogger.Error("bHaptics_NativeLibrary.Load Exception: " + ex.ToString()); bHaptics.WasError = true; } }
private static bool LoadInterface(string ModulePath) { Assembly assembly = Assembly.LoadFrom(ModulePath); if (assembly == null) { return(false); } Type type = assembly.GetType("MelonLoader.Support.Main"); if (type == null) { MelonLogger.Error("Failed to Get Type MelonLoader.Support.Main!"); return(false); } MethodInfo method = type.GetMethod("Initialize", BindingFlags.NonPublic | BindingFlags.Static); if (method == null) { MelonLogger.Error("Failed to Get Method Initialize!"); return(false); } Interface = (ISupportModule_To)method.Invoke(null, new object[] { new SupportModule_From() }); if (Interface == null) { MelonLogger.Error("Failed to Initialize Interface!"); return(false); } MelonDebug.Msg($"Support Module Loaded: {ModulePath}"); return(true); }
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 MelonLogger.Error(errorMessage.ToString()); } }
private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e) => MelonLogger.Error((e.ExceptionObject as Exception).ToString());