using System.IO; using System.Linq; using System.Reflection; using Mono.Cecil; using Mono.Cecil.Cil; namespace COM3D2.CacheEditMenu.Patcher { public static class Patcher { public static readonly string[] TargetAssemblyNames = { "Assembly-CSharp.dll" }; public static readonly string SybarisPath = Path.GetDirectoryName(typeof(Patcher).Assembly.Location); public static void Patch(AssemblyDefinition ad) { var hookAd = AssemblyDefinition.ReadAssembly( typeof(Patcher).Assembly.GetManifestResourceStream( "COM3D2.CacheEditMenu.Patcher.COM3D2.CacheEditMenu.dll")); var sceneEdit = ad.MainModule.GetType("SceneEdit"); var getMenuItemSetUp = sceneEdit.Methods.FirstOrDefault(m => m.Name == "GetMenuItemSetUP"); var hookType = hookAd.MainModule.GetType("COM3D2.CacheEditMenu.Hooks"); var getMenuItemSetUpPrefix = hookType.Methods.FirstOrDefault(m => m.Name == "Prefix"); var getMenuItemSetUpPostfix = hookType.Methods.FirstOrDefault(m => m.Name == "Postfix"); var il = getMenuItemSetUp.Body.GetILProcessor(); var resultVar = new VariableDefinition(ad.MainModule.ImportReference(typeof(bool))); getMenuItemSetUp.Body.Variables.Add(resultVar); var ins = getMenuItemSetUp.Body.Instructions[0]; il.InsertBefore(ins, il.Create(OpCodes.Ldloca, resultVar)); il.InsertBefore(ins, il.Create(OpCodes.Ldarg_0)); il.InsertBefore(ins, il.Create(OpCodes.Ldarg_1)); il.InsertBefore(ins, il.Create(OpCodes.Call, ad.MainModule.ImportReference(getMenuItemSetUpPrefix))); il.InsertBefore(ins, il.Create(OpCodes.Brtrue, ins)); il.InsertBefore(ins, il.Create(OpCodes.Ldloc, resultVar)); il.InsertBefore(ins, il.Create(OpCodes.Ret)); ins = il.Create(OpCodes.Nop); foreach (var bodyInstruction in getMenuItemSetUp.Body.Instructions.Where(bodyInstruction => bodyInstruction.OpCode == OpCodes.Ret).Skip(1)) { bodyInstruction.OpCode = OpCodes.Br; bodyInstruction.Operand = ins; } il.Append(ins); ins = il.Create(OpCodes.Ret); il.Append(ins); il.InsertBefore(ins, il.Create(OpCodes.Ldarg_0)); il.InsertBefore(ins, il.Create(OpCodes.Ldarg_1)); il.InsertBefore(ins, il.Create(OpCodes.Call, ad.MainModule.ImportReference(getMenuItemSetUpPostfix))); var buffer = new byte[4096]; using(var s = typeof(Patcher).Assembly.GetManifestResourceStream( "COM3D2.CacheEditMenu.Patcher.COM3D2.CacheEditMenu.dll")) using (var ms = new MemoryStream()) { int read; while ((read = s.Read(buffer, 0, buffer.Length)) > 0) ms.Write(buffer, 0, read); Assembly.Load(ms.ToArray()); } } } }