Patcher.cs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. using System.IO;
  2. using System.Linq;
  3. using System.Reflection;
  4. using Mono.Cecil;
  5. using Mono.Cecil.Cil;
  6. namespace COM3D2.CacheEditMenu.Patcher
  7. {
  8. public static class Patcher
  9. {
  10. public static readonly string[] TargetAssemblyNames = { "Assembly-CSharp.dll" };
  11. public static readonly string SybarisPath = Path.GetDirectoryName(typeof(Patcher).Assembly.Location);
  12. public static void Patch(AssemblyDefinition ad)
  13. {
  14. var hookAd = AssemblyDefinition.ReadAssembly(
  15. typeof(Patcher).Assembly.GetManifestResourceStream(
  16. "COM3D2.CacheEditMenu.Patcher.COM3D2.CacheEditMenu.dll"));
  17. var sceneEdit = ad.MainModule.GetType("SceneEdit");
  18. var getMenuItemSetUp = sceneEdit.Methods.FirstOrDefault(m => m.Name == "GetMenuItemSetUP");
  19. var hookType = hookAd.MainModule.GetType("COM3D2.CacheEditMenu.Hooks");
  20. var getMenuItemSetUpPrefix = hookType.Methods.FirstOrDefault(m => m.Name == "Prefix");
  21. var getMenuItemSetUpPostfix = hookType.Methods.FirstOrDefault(m => m.Name == "Postfix");
  22. var il = getMenuItemSetUp.Body.GetILProcessor();
  23. var resultVar = new VariableDefinition(ad.MainModule.ImportReference(typeof(bool)));
  24. getMenuItemSetUp.Body.Variables.Add(resultVar);
  25. var ins = getMenuItemSetUp.Body.Instructions[0];
  26. il.InsertBefore(ins, il.Create(OpCodes.Ldloca, resultVar));
  27. il.InsertBefore(ins, il.Create(OpCodes.Ldarg_0));
  28. il.InsertBefore(ins, il.Create(OpCodes.Ldarg_1));
  29. il.InsertBefore(ins, il.Create(OpCodes.Call, ad.MainModule.ImportReference(getMenuItemSetUpPrefix)));
  30. il.InsertBefore(ins, il.Create(OpCodes.Brtrue, ins));
  31. il.InsertBefore(ins, il.Create(OpCodes.Ldloc, resultVar));
  32. il.InsertBefore(ins, il.Create(OpCodes.Ret));
  33. ins = il.Create(OpCodes.Nop);
  34. foreach (var bodyInstruction in getMenuItemSetUp.Body.Instructions.Where(bodyInstruction => bodyInstruction.OpCode == OpCodes.Ret).Skip(1))
  35. {
  36. bodyInstruction.OpCode = OpCodes.Br;
  37. bodyInstruction.Operand = ins;
  38. }
  39. il.Append(ins);
  40. ins = il.Create(OpCodes.Ret);
  41. il.Append(ins);
  42. il.InsertBefore(ins, il.Create(OpCodes.Ldarg_0));
  43. il.InsertBefore(ins, il.Create(OpCodes.Ldarg_1));
  44. il.InsertBefore(ins, il.Create(OpCodes.Call, ad.MainModule.ImportReference(getMenuItemSetUpPostfix)));
  45. var buffer = new byte[4096];
  46. using(var s = typeof(Patcher).Assembly.GetManifestResourceStream(
  47. "COM3D2.CacheEditMenu.Patcher.COM3D2.CacheEditMenu.dll"))
  48. using (var ms = new MemoryStream())
  49. {
  50. int read;
  51. while ((read = s.Read(buffer, 0, buffer.Length)) > 0)
  52. ms.Write(buffer, 0, read);
  53. Assembly.Load(ms.ToArray());
  54. }
  55. }
  56. }
  57. }