public void Generate() { if (Directory.Exists(FullPath)) { Modder.Log($"[DbgIlGen] Clearing {FullPath}"); DeleteRecursive(FullPath); } Directory.CreateDirectory(FullPath); Thread.Sleep(0); // Required to stay in sync with filesystem... thanks, .NET Framework! CustomAttribute debuggable = Modder.Module.Assembly.GetCustomAttribute("System.Diagnostics.DebuggableAttribute"); if (debuggable != null) { Modder.Module.Assembly.CustomAttributes.Remove(debuggable); } debuggable = new CustomAttribute(Modder.Module.ImportReference(m_DebuggableAttribute_ctor)); debuggable.ConstructorArguments.Add(new CustomAttributeArgument( Modder.Module.ImportReference(typeof(DebuggableAttribute.DebuggingModes)), DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.EnableEditAndContinue )); Modder.Module.Assembly.AddAttribute(debuggable); GenerateMetadata(); foreach (TypeDefinition type in Modder.Module.Types) { GenerateFor(type); } }
public static void RelinkModule(string from, string toName) { MonoModder self = Modder; from = from.Inject(MonoModExt.SharedData); toName = toName.Inject(MonoModExt.SharedData); bool retrying = false; ModuleDefinition to = null; RETRY: if (toName + ".dll" == self.Module.Name) { to = self.Module; } else if (self.DependencyCache.TryGetValue(toName, out to)) { } else if (!retrying) { self.MapDependency(self.Module, toName); retrying = true; goto RETRY; } if (to != null) { self.Log($"[MonoModRules] RelinkModule: {from} -> {toName}"); self.RelinkModuleMap[from] = to; } }
public static void RelinkMember(string from, string toType, string toMember) { MonoModder self = Modder; self.Log($"[MonoModRules] RelinkMember: {from} -> {toType}::{toMember}"); self.RelinkMap[from] = new RelinkMapEntry(toType, toMember); }
public static void RelinkType(string from, string to) { MonoModder self = Modder; self.Log($"[MonoModRules] RelinkType: {from} -> {to}"); self.RelinkMap[from] = to; }
public static void RelinkType(MonoModder self, string from, string to) { from = from.Inject(MonoModder.Data); to = to.Inject(MonoModder.Data); self.Log($"[MonoModRules] RelinkType: {from} -> {to}"); self.RelinkMap[from] = to; }
public static void RelinkMember(MonoModder self, string from, string toType, string toMember) { from = from.Inject(MonoModder.Data); toType = toType.Inject(MonoModder.Data); toMember = toMember.Inject(MonoModder.Data); self.Log($"[MonoModRules] RelinkMember: {from} -> {toType}::{toMember}"); self.RelinkMap[from] = Tuple.Create(toType, toMember); }
public static void RelinkMember(string from, string toType, string toMember) { MonoModder self = Modder; from = from.Inject(MonoModExt.SharedData); toType = toType.Inject(MonoModExt.SharedData); toMember = toMember.Inject(MonoModExt.SharedData); self.Log($"[MonoModRules] RelinkMember: {from} -> {toType}::{toMember}"); self.RelinkMap[from] = new RelinkMapEntry(toType, toMember); }
public static void Patch(MonoModder self, string id, bool patch) { id = id.Inject(MonoModder.Data); self.Log($"[MonoModRules] Patch: {id}: {patch}"); if (patch && self.SkipList.Contains(id)) { self.SkipList.Remove(id); } else if (!patch && !self.SkipList.Contains(id)) { self.SkipList.Add(id); } }
/// <summary>Generates the HOOKS-Assembly-CSharp.dll the same as Partiality</summary> void GenerateHooks() { string pathIn = Path.Combine(Paths.ManagedPath, "Assembly-CSharp.dll"); string pathOut = Path.Combine(Path.GetDirectoryName(Info.Location), "HOOKS-Assembly-CSharp.dll"); if (File.Exists(pathOut)) { // Only Regenerate if Managed is newer than HOOKS if (File.GetLastWriteTime(pathOut) > File.GetLastWriteTime(pathIn)) { return; } File.Delete(pathOut); } using (MonoModder mm = new MonoModder { InputPath = pathIn, OutputPath = pathOut, PublicEverything = true, DependencyDirs = new List <string>() { Paths.ManagedPath, Paths.BepInExAssemblyDirectory }, }) { mm.Read(); mm.MapDependencies(); mm.Log("[HookGen] Starting HookGenerator"); HookGenerator gen = new HookGenerator(mm, Path.GetFileName(pathOut)); using (ModuleDefinition mOut = gen.OutputModule) { gen.HookPrivate = true; gen.Generate(); mOut.Write(pathOut); } mm.Log("[HookGen] Done."); } }
static void Main(string[] args) { Console.WriteLine("MonoMod.RuntimeDetour.HookGen " + typeof(Program).Assembly.GetName().Version); Console.WriteLine("using MonoMod " + typeof(MonoModder).Assembly.GetName().Version); Console.WriteLine("using MonoMod.RuntimeDetour " + typeof(Detour).Assembly.GetName().Version); if (args.Length == 0) { Console.WriteLine("No valid arguments (assembly path) passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return; } string pathIn; string pathOut; int pathInI = 0; for (int i = 0; i < args.Length; i++) { if (args[i] == "--namespace" && i + 2 < args.Length) { i++; Environment.SetEnvironmentVariable("MONOMOD_HOOKGEN_NAMESPACE", args[i]); } else if (args[i] == "--orig") { Environment.SetEnvironmentVariable("MONOMOD_HOOKGEN_ORIG", "1"); } else if (args[i] == "--private") { Environment.SetEnvironmentVariable("MONOMOD_HOOKGEN_PRIVATE", "1"); } else { pathInI = i; break; } } if (pathInI >= args.Length) { Console.WriteLine("No assembly path passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return; } pathIn = args[pathInI]; pathOut = args.Length != 1 && pathInI != args.Length - 1 ? args[args.Length - 1] : null; pathOut = pathOut ?? Path.Combine(Path.GetDirectoryName(pathIn), "MMHOOK_" + Path.ChangeExtension(Path.GetFileName(pathIn), "dll")); using (MonoModder mm = new MonoModder() { InputPath = pathIn, OutputPath = pathOut }) { mm.Read(); mm.MapDependencies(); if (File.Exists(pathOut)) { mm.Log($"[HookGen] Clearing {pathOut}"); File.Delete(pathOut); } mm.Log("[HookGen] Starting HookGenerator"); HookGenerator gen = new HookGenerator(mm, Path.GetFileName(pathOut)); using (ModuleDefinition mOut = gen.OutputModule) { gen.Generate(); mOut.Write(pathOut); } mm.Log("[HookGen] Done."); } if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } }
public static void Main(string[] args) { #if CECIL0_9 throw new NotSupportedException(); #else Console.WriteLine("MonoMod.DebugIL " + typeof(Program).Assembly.GetName().Version); if (args.Length == 0) { Console.WriteLine("No valid arguments (assembly path) passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return; } string pathIn; string pathOut; int pathInI = 0; for (int i = 0; i < args.Length; i++) { if (args[i] == "--relative") { Environment.SetEnvironmentVariable("MONOMOD_DEBUGIL_RELATIVE", "1"); pathInI = i + 1; } else if (args[i] == "--skip-maxstack") { Environment.SetEnvironmentVariable("MONOMOD_DEBUGIL_SKIP_MAXSTACK", "1"); pathInI = i + 1; } } if (pathInI >= args.Length) { Console.WriteLine("No assembly path passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return; } pathIn = args[pathInI]; pathOut = args.Length != 1 && pathInI != args.Length - 1 ? args[args.Length - 1] : null; pathOut = pathOut ?? Path.Combine(Path.GetDirectoryName(pathIn), "MMDBGIL_" + Path.GetFileName(pathIn)); using (MonoModder mm = new MonoModder() { InputPath = pathIn, OutputPath = pathOut }) { mm.Read(); mm.Log("[DbgILGen] DebugILGenerator.Generate(mm);"); DebugILGenerator.Generate(mm); mm.Write(); mm.Log("[DbgILGen] Done."); } if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } #endif }
public static void Main(string[] args) { Console.WriteLine("MonoMod " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version); if (args.Length == 0) { Console.WriteLine("No valid arguments (assembly path) passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return; } string pathIn; string pathOut; if (args.Length > 1 && args[0] == "--generate-debug-il" || args[0] == "--gen-dbg-il") { Console.WriteLine("[DbgILGen] Generating debug hierarchy and debug data (pdb / mdb)."); pathIn = args[1]; pathOut = args.Length != 2 ? args[args.Length - 1] : Path.Combine(Path.GetDirectoryName(pathIn), "MMDBGIL_" + Path.GetFileName(pathIn)); using (MonoModder mm = new MonoModder() { InputPath = pathIn, OutputPath = pathOut }) { mm.Read(false); mm.Log("[DbgILGen] DebugILGenerator.Generate(mm);"); DebugILGenerator.Generate(mm); mm.Write(); mm.Log("[DbgILGen] Done."); } if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return; } int pathInI = 0; for (int i = 0; i < args.Length; i++) { if (args[i] == "--dependency-missing-throw=0" || args[i] == "--lean-dependencies") { Environment.SetEnvironmentVariable("MONOMOD_DEPENDENCY_MISSING_THROW", "0"); pathInI = i + 1; } else if (args[i] == "--cleanup=0" || args[i] == "--skip-cleanup") { Environment.SetEnvironmentVariable("MONOMOD_CLEANUP", "0"); pathInI = i + 1; } else if (args[i] == "--cleanup-all=1" || args[i] == "--cleanup-all") { Environment.SetEnvironmentVariable("MONOMOD_CLEANUP_ALL", "1"); pathInI = i + 1; } else if (args[i] == "--verbose=1" || args[i] == "--verbose" || args[i] == "-v") { Environment.SetEnvironmentVariable("MONOMOD_VERBOSE", "1"); pathInI = i + 1; } } if (pathInI >= args.Length) { Console.WriteLine("No assembly path passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return; } pathIn = args[pathInI]; pathOut = args.Length != 1 && pathInI != args.Length - 1 ? args[args.Length - 1] : Path.Combine(Path.GetDirectoryName(pathIn), "MONOMODDED_" + Path.GetFileName(pathIn)); if (File.Exists(pathOut)) { File.Delete(pathOut); } try { using (MonoModder mm = new MonoModder() { InputPath = pathIn, OutputPath = pathOut, Verbose = Environment.GetEnvironmentVariable("MONOMOD_VERBOSE") == "1" }) { mm.Read(false); if (args.Length <= 2) { mm.Log("[Main] Scanning for mods in directory."); mm.ReadMod(Directory.GetParent(pathIn).FullName); } else { mm.Log("[Main] Reading mods list from arguments."); for (int i = pathInI + 1; i < args.Length - 2; i++) { mm.ReadMod(args[i]); } } mm.Read(true); mm.Log("[Main] mm.AutoPatch();"); mm.AutoPatch(); mm.Write(); mm.Log("[Main] Done."); } } catch (Exception e) { Console.WriteLine(e); } if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } }
public static void PatchGame() { string executablePath = Assembly.GetEntryAssembly().Location; string executableDirectory = Directory.GetParent(executablePath).FullName; string monoModPath = Path.Combine(executableDirectory, "MonoMod.exe"); string hookGenPath = Path.Combine(executableDirectory, "MonoMod.RuntimeDetour.HookGen.exe"); string runtimeDetourDLL = "MonoMod.RuntimeDetour.dll"; string mmUtilsDLL = "MonoMod.Utils.dll"; string jsonDLL = "YamlDotNet.dll"; string gameDirectory = Directory.GetParent(GameManager.exePath).FullName; string hashesFolder = Path.Combine(gameDirectory, "DustDevilHashes"); string modDependencies = Path.Combine(gameDirectory, "ModDependencies"); string dataDirectory = Path.Combine(gameDirectory, Path.GetFileNameWithoutExtension(GameManager.exePath) + "_Data"); string managedFolder = Path.Combine(dataDirectory, "Managed"); string codeDll = Path.Combine(managedFolder, "Assembly-CSharp.dll"); string hookGenDLL = Path.Combine(managedFolder, "HOOKS-Assembly-CSharp.dll"); string engineDll = Path.Combine(managedFolder, "UnityEngine.dll"); string coreModuleDLL = Path.Combine(managedFolder, "UnityEngine.CoreModule.dll"); string backupFolder = managedFolder + "_backup"; Process currentProcess = Process.GetCurrentProcess(); Process monomodProcess = new Process(); monomodProcess.StartInfo.FileName = monoModPath; //monomodProcess.StartInfo.CreateNoWindow = true; monomodProcess.StartInfo.UseShellExecute = false; monomodProcess.StartInfo.RedirectStandardOutput = true; //Create backup if there isn't one if (!Directory.Exists(backupFolder)) { Directory.CreateDirectory(backupFolder); CopyFilesRecursively(managedFolder, backupFolder); } //Install the default patch for Partiality { string engineDLLName = "UnityEngine.dll"; if (File.Exists(coreModuleDLL)) { engineDLLName = "UnityEngine.CoreModule.dll"; engineDll = coreModuleDLL; } string moddedDLL = Path.Combine(Path.GetDirectoryName(engineDll), "patched" + engineDLLName); string defaultPatchLocation = Path.Combine(executableDirectory, "PartialityPatch.dll"); string partialityModLocation = Path.Combine(Path.GetDirectoryName(engineDll), "Partiality.dll"); bool shouldPatch = false; if (!File.Exists(Path.Combine(hashesFolder, "ENGINEHASH.hash"))) { shouldPatch = true; } else { shouldPatch = !ModMetadata.CompareHashes(defaultPatchLocation, Path.Combine(hashesFolder, "ENGINEHASH.hash")); } //Delete mod if it exists if (File.Exists(partialityModLocation)) { File.Delete(partialityModLocation); } //Copy mod to folder with assembly-chsharp.dll File.Copy(Path.Combine(executableDirectory, "Partiality.dll"), partialityModLocation); if (shouldPatch) { //Restore backup File.Delete(engineDll); File.Copy(Path.Combine(backupFolder, engineDLLName), engineDll); //Set monomod arguments to "[UnityEngine.dll] [PartialityPatch.dll] [patched_UnityEngine.dll]" monomodProcess.StartInfo.Arguments = ('"' + engineDll + '"') + " " + ('"' + defaultPatchLocation + '"') + " " + ('"' + moddedDLL + '"'); monomodProcess.Start(); string mmoutput = monomodProcess.StandardOutput.ReadToEnd(); Console.WriteLine(mmoutput); monomodProcess.WaitForExit(); int exitCode = monomodProcess.ExitCode; Console.WriteLine("MMEC:" + exitCode); Console.WriteLine(mmoutput); //Replace file if (File.Exists(moddedDLL)) { //Move modded .dll over original .dll File.Delete(engineDll); File.Copy(moddedDLL, engineDll); File.Delete(moddedDLL); } byte[] newHash = ChecksumHasher.ComputeHash(File.ReadAllBytes(defaultPatchLocation)); File.WriteAllBytes(Path.Combine(hashesFolder, "ENGINEHASH.hash"), newHash); } } //Install custom patches { string[] files = Directory.GetFiles(modDependencies); //Copy mod dependencies foreach (string dependency in files) { string fileName = Path.GetFileName(dependency); //Delete the dependency if it already exists if (File.Exists(Path.Combine(managedFolder, fileName))) { File.Delete(Path.Combine(managedFolder, fileName)); } //Copy the file File.Copy(dependency, Path.Combine(managedFolder, fileName)); } bool shouldPatch = false; string moddedDLL = Path.Combine(Path.GetDirectoryName(engineDll), "patched_Assembly-CSharp.dll"); string epListLocation = Path.Combine(hashesFolder, "ENABLEDPATCHES.enp"); //Check if we have the same enabled/disabled mods as last time, if we do, then { string totalEnabledPatches = "Partiality+"; foreach (ModMetadata md in GameManager.modMetas) { if ((md.isStandalone || md.isPatch) && md.isEnabled) { totalEnabledPatches += Path.GetFileNameWithoutExtension(md.modPath) + "+"; } } DebugLogger.Log(totalEnabledPatches); if (File.Exists(epListLocation)) { string getList = File.ReadAllText(epListLocation); shouldPatch = getList != totalEnabledPatches; if (shouldPatch) { File.WriteAllText(epListLocation, totalEnabledPatches); } } else { shouldPatch = true; File.WriteAllText(epListLocation, totalEnabledPatches); } } //If all the same mods are enabled, check if any mods are dirty. If they are, we gotta re-patch. if (!shouldPatch) { foreach (ModMetadata md in GameManager.modMetas) { if (md.isDirty) { shouldPatch = true; break; } } } if (shouldPatch) { DebugLogger.Log("Patching Assembly-CSharp"); string backupDll = Path.Combine(backupFolder, "Assembly-CSharp.dll"); foreach (ModMetadata md in GameManager.modMetas) { if (md.isStandalone && md.isEnabled) { backupDll = md.modPath; } } //Restore backup File.Delete(codeDll); File.Copy(backupDll, codeDll); List <string> failedPatches = new List <string>(); foreach (ModMetadata md in GameManager.modMetas) { if (md.isPatch && md.isEnabled) { monomodProcess.StartInfo.Arguments = ('"' + codeDll + '"') + " " + ('"' + md.modPath + '"') + " " + ('"' + moddedDLL + '"'); monomodProcess.Start(); string mmoutput = monomodProcess.StandardOutput.ReadToEnd(); monomodProcess.WaitForExit(); int exitCode = monomodProcess.ExitCode; DebugLogger.Log("MMEC:" + exitCode); DebugLogger.Log(mmoutput); if (exitCode != 0) { failedPatches.Add(Path.GetFileNameWithoutExtension(md.modPath)); } //Replace file if (File.Exists(moddedDLL)) { //Move modded .dll over original .dll File.Delete(codeDll); File.Copy(moddedDLL, codeDll); File.Delete(moddedDLL); } } } if (failedPatches.Count > 0) { Eto.Forms.MessageBox.Show("Some mods failed to apply correctly! Please send your LOG.txt (in the Partiality folder) to someone who can help, probably from the people who made the mod."); } //Set mods to all not be dirty, and save them. foreach (ModMetadata md in GameManager.modMetas) { md.isDirty = false; } try { GameManager.SaveAllMetadata(); } catch (System.Exception e) { DebugLogger.Log(e); } } } //HookGen stuff { //Delete Legacy DLL if (File.Exists(Path.Combine(managedFolder, "HOOKS-Assembly-CSharp.dll"))) { File.Delete(Path.Combine(managedFolder, "HOOKS-Assembly-CSharp.dll")); } if (File.Exists(hookGenDLL)) { File.Delete(hookGenDLL); } //Delete files if they existed, so we can update them. if (File.Exists(Path.Combine(managedFolder, runtimeDetourDLL))) { File.Delete(Path.Combine(managedFolder, runtimeDetourDLL)); } if (File.Exists(Path.Combine(managedFolder, mmUtilsDLL))) { File.Delete(Path.Combine(managedFolder, mmUtilsDLL)); } if (File.Exists(Path.Combine(managedFolder, jsonDLL))) { File.Delete(Path.Combine(managedFolder, jsonDLL)); } //Copy files File.Copy(Path.Combine(executableDirectory, runtimeDetourDLL), Path.Combine(managedFolder, runtimeDetourDLL)); File.Copy(Path.Combine(executableDirectory, mmUtilsDLL), Path.Combine(managedFolder, mmUtilsDLL)); File.Copy(Path.Combine(executableDirectory, jsonDLL), Path.Combine(managedFolder, jsonDLL)); string pathIn = codeDll; string pathOut = hookGenDLL; using (MonoModder mm = new MonoModder { InputPath = pathIn, OutputPath = pathOut }) { mm.Read(); mm.MapDependencies(); if (File.Exists(pathOut)) { mm.Log(string.Format("Clearing {0}", pathOut)); File.Delete(pathOut); } mm.Log("[HookGen] Starting HookGenerator"); HookGenerator gen = new HookGenerator(mm, Path.GetFileName(pathOut)); using (ModuleDefinition mOut = gen.OutputModule) { gen.HookPrivate = true; gen.Generate(); mOut.Write(pathOut); } mm.Log("[HookGen] Done."); } } //File.WriteAllText( gameDirectory + "\\PARTIALITY_OUTPUT.txt", ); }
public static int Main(string[] args) { Console.WriteLine("MonoMod " + typeof(Program).GetTypeInfo().Assembly.GetName().Version); if (args.Length == 0) { Console.WriteLine("No valid arguments (assembly path) passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); } string pathIn; string pathOut; int pathInI = 0; for (int i = 0; i < args.Length; i++) { if (args[i] == "--dependency-missing-throw=0" || args[i] == "--lean-dependencies") { Environment.SetEnvironmentVariable("MONOMOD_DEPENDENCY_MISSING_THROW", "0"); pathInI = i + 1; } else if (args[i] == "--cleanup=0" || args[i] == "--skip-cleanup") { Environment.SetEnvironmentVariable("MONOMOD_CLEANUP", "0"); pathInI = i + 1; } else if (args[i] == "--cleanup-all=1" || args[i] == "--cleanup-all") { Environment.SetEnvironmentVariable("MONOMOD_CLEANUP_ALL", "1"); pathInI = i + 1; } else if (args[i] == "--verbose=1" || args[i] == "--verbose" || args[i] == "-v") { Environment.SetEnvironmentVariable("MONOMOD_LOG_VERBOSE", "1"); pathInI = i + 1; } else if (args[i] == "--cache=0" || args[i] == "--uncached") { Environment.SetEnvironmentVariable("MONOMOD_RELINKER_CACHED", "0"); pathInI = i + 1; } } if (pathInI >= args.Length) { Console.WriteLine("No assembly path passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); } pathIn = args[pathInI]; pathOut = args.Length != 1 && pathInI != args.Length - 1 ? args[args.Length - 1] : null; pathOut = pathOut ?? Path.Combine(Path.GetDirectoryName(pathIn), "MONOMODDED_" + Path.GetFileName(pathIn)); if (File.Exists(pathOut)) { File.Delete(pathOut); } #if !DEBUG try { #endif using (MonoModder mm = new MonoModder() { InputPath = pathIn, OutputPath = pathOut }) { mm.Read(); if (args.Length <= 2) { mm.Log("[Main] Scanning for mods in directory."); mm.ReadMod(Directory.GetParent(pathIn).FullName); } else { mm.Log("[Main] Reading mods list from arguments."); for (int i = pathInI + 1; i < args.Length - 1; i++) { mm.ReadMod(args[i]); } } mm.MapDependencies(); mm.Log("[Main] mm.AutoPatch();"); mm.AutoPatch(); mm.Write(); mm.Log("[Main] Done."); } #if !DEBUG } catch (Exception e) { Console.WriteLine(e); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(-1); } #endif if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); }
public static Type ExecuteRules(this MonoModder self, TypeDefinition orig) { ModuleDefinition wrapper = ModuleDefinition.CreateModule( $"{orig.Module.Name.Substring(0, orig.Module.Name.Length - 4)}.MonoModRules -ID:{MMILProxyManager.GetId(self)} -MMILRT", new ModuleParameters() { Architecture = orig.Module.Architecture, AssemblyResolver = self.AssemblyResolver, Kind = ModuleKind.Dll, MetadataResolver = orig.Module.MetadataResolver, Runtime = orig.Module.Runtime } ); MonoModder wrapperMod = new MonoModder() { Module = wrapper, Logger = msg => self.Log("[MonoModRule] " + msg), CleanupEnabled = false, DependencyDirs = self.DependencyDirs, MissingDependencyResolver = self.MissingDependencyResolver }; wrapperMod.WriterParameters.WriteSymbols = false; wrapperMod.WriterParameters.SymbolWriterProvider = null; // Only add a copy of the map - adding the MMILRT asm itself to the map only causes issues. wrapperMod.DependencyCache.AddRange(self.DependencyCache); foreach (KeyValuePair <ModuleDefinition, List <ModuleDefinition> > mapping in self.DependencyMap) { wrapperMod.DependencyMap[mapping.Key] = new List <ModuleDefinition>(mapping.Value); } // Required as the relinker only deep-relinks if the method the type comes from is a mod. // Fixes nasty reference import sharing issues. wrapperMod.Mods.Add(self.Module); wrapperMod.Relinker = (mtp, context) => mtp is TypeReference && ((TypeReference)mtp).IsMMILType() ? MMILProxyManager.RelinkToProxy(wrapperMod, (TypeReference)mtp) : mtp is TypeReference && ((TypeReference)mtp).FullName == orig.FullName ? wrapper.GetType(orig.FullName) : wrapperMod.DefaultRelinker(mtp, context); wrapperMod.PrePatchType(orig, forceAdd: true); wrapperMod.PatchType(orig); TypeDefinition rulesCecil = wrapper.GetType(orig.FullName); wrapperMod.PatchRefsInType(rulesCecil); Assembly asm; using (MemoryStream asmStream = new MemoryStream()) { wrapperMod.Write(asmStream); asm = Assembly.Load(asmStream.GetBuffer()); } /**//* * using (FileStream debugStream = File.OpenWrite(Path.Combine( * self.DependencyDirs[0], $"{orig.Module.Name.Substring(0, orig.Module.Name.Length - 4)}.MonoModRules-MMILRT.dll"))) * wrapperMod.Write(debugStream); * /**/ Type rules = asm.GetType(orig.FullName); RuntimeHelpers.RunClassConstructor(rules.TypeHandle); return(rules); }
public static int Main(string[] args) { Console.WriteLine("MonoMod " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version); if (args.Length == 0) { Console.WriteLine("No valid arguments (assembly path) passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); } if (args[0] == "--test") { Console.WriteLine("[QuickDebugTest] Running..."); int result = QuickDebugTest.Run(args); if (result == 0) { Console.WriteLine("[QuickDebugTest] Passed!"); } else { Console.WriteLine($"[QuickDebugTest] Failed: {result}"); } if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(result); } string pathIn; string pathOut; int pathInI = 0; bool generateDebugIL = false; for (int i = 0; i < args.Length; i++) { if (args[i] == "--dependency-missing-throw=0" || args[i] == "--lean-dependencies") { Environment.SetEnvironmentVariable("MONOMOD_DEPENDENCY_MISSING_THROW", "0"); pathInI = i + 1; } else if (args[i] == "--cleanup=0" || args[i] == "--skip-cleanup") { Environment.SetEnvironmentVariable("MONOMOD_CLEANUP", "0"); pathInI = i + 1; } else if (args[i] == "--cleanup-all=1" || args[i] == "--cleanup-all") { Environment.SetEnvironmentVariable("MONOMOD_CLEANUP_ALL", "1"); pathInI = i + 1; } else if (args[i] == "--verbose=1" || args[i] == "--verbose" || args[i] == "-v") { Environment.SetEnvironmentVariable("MONOMOD_LOG_VERBOSE", "1"); pathInI = i + 1; } else if (args[i] == "--cache=0" || args[i] == "--uncached") { Environment.SetEnvironmentVariable("MONOMOD_RELINKER_CACHED", "0"); pathInI = i + 1; } else if (args[i] == "--generate-debug-il" || args[i] == "--gen-dbg-il") { generateDebugIL = true; pathInI = i + 1; } else if (args[i] == "--debug-il-relative" || args[i] == "--dbg-il-relative") { Environment.SetEnvironmentVariable("MONOMOD_DEBUGIL_RELATIVE", "1"); pathInI = i + 1; } } if (pathInI >= args.Length) { Console.WriteLine("No assembly path passed."); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); } pathIn = args[pathInI]; pathOut = args.Length != 1 && pathInI != args.Length - 1 ? args[args.Length - 1] : null; if (generateDebugIL) { Console.WriteLine("[DbgILGen] Generating debug hierarchy and debug data (pdb / mdb)."); pathOut = pathOut ?? Path.Combine(Path.GetDirectoryName(pathIn), "MMDBGIL_" + Path.GetFileName(pathIn)); using (MonoModder mm = new MonoModder() { InputPath = pathIn, OutputPath = pathOut }) { mm.Read(); mm.Log("[DbgILGen] DebugILGenerator.Generate(mm);"); DebugILGenerator.Generate(mm); mm.Write(); mm.Log("[DbgILGen] Done."); } if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); } pathOut = pathOut ?? Path.Combine(Path.GetDirectoryName(pathIn), "MONOMODDED_" + Path.GetFileName(pathIn)); if (File.Exists(pathOut)) { File.Delete(pathOut); } #if !DEBUG try { #endif using (MonoModder mm = new MonoModder() { InputPath = pathIn, OutputPath = pathOut }) { mm.Read(); if (args.Length <= 2) { mm.Log("[Main] Scanning for mods in directory."); mm.ReadMod(Directory.GetParent(pathIn).FullName); } else { mm.Log("[Main] Reading mods list from arguments."); for (int i = pathInI + 1; i < args.Length - 1; i++) { mm.ReadMod(args[i]); } } mm.MapDependencies(); mm.Log("[Main] mm.AutoPatch();"); mm.AutoPatch(); mm.Write(); mm.Log("[Main] Done."); } #if !DEBUG } catch (Exception e) { Console.WriteLine(e); if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(-1); } #endif if (System.Diagnostics.Debugger.IsAttached) // Keep window open when running in IDE { Console.ReadKey(); } return(0); }