HarmonySharedState.cs 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Reflection.Emit;
  6. using HarmonyXInterop;
  7. namespace Harmony
  8. {
  9. internal class PatchHandler
  10. {
  11. private MethodBase mb;
  12. private PatchInfoWrapper previousState = new PatchInfoWrapper
  13. {
  14. prefixes = new PatchMethod[0],
  15. postfixes = new PatchMethod[0],
  16. transpilers = new PatchMethod[0],
  17. finalizers = new PatchMethod[0]
  18. };
  19. public void Apply()
  20. {
  21. PatchMethod[] ToPatchMethod(Patch[] patches)
  22. {
  23. return patches.Select(p => new PatchMethod
  24. {
  25. after = p.after,
  26. before = p.before,
  27. method = p.patch,
  28. priority = p.priority,
  29. owner = p.owner,
  30. }).ToArray();
  31. }
  32. var info = HarmonySharedState.GetPatchInfo(mb);
  33. var state = new PatchInfoWrapper
  34. {
  35. prefixes = ToPatchMethod(info.prefixes),
  36. postfixes = ToPatchMethod(info.postfixes),
  37. transpilers = ToPatchMethod(info.transpilers),
  38. finalizers = new PatchMethod[0]
  39. };
  40. var add = new PatchInfoWrapper { finalizers = new PatchMethod[0] };
  41. var remove = new PatchInfoWrapper { finalizers = new PatchMethod[0] };
  42. Diff(previousState.prefixes, state.prefixes, out add.prefixes, out remove.prefixes);
  43. Diff(previousState.postfixes, state.postfixes, out add.postfixes, out remove.postfixes);
  44. Diff(previousState.transpilers, state.transpilers, out add.transpilers, out remove.transpilers);
  45. previousState = state;
  46. HarmonyInterop.ApplyPatch(mb, add, remove);
  47. }
  48. static void Diff(PatchMethod[] last, PatchMethod[] curr, out PatchMethod[] add, out PatchMethod[] remove)
  49. {
  50. add = curr.Except(last, PatchMethodComparer.Instance).ToArray();
  51. remove = last.Except(curr, PatchMethodComparer.Instance).ToArray();
  52. }
  53. static Dictionary<MethodBase, PatchHandler> patchHandlers = new Dictionary<MethodBase, PatchHandler>();
  54. internal static PatchHandler Get(MethodBase method)
  55. {
  56. lock (patchHandlers)
  57. {
  58. if (!patchHandlers.TryGetValue(method, out var handler))
  59. patchHandlers[method] = handler = new PatchHandler {mb = method};
  60. return handler;
  61. }
  62. }
  63. }
  64. public static class HarmonySharedState
  65. {
  66. static Dictionary<MethodBase, PatchInfo> patchInfos = new Dictionary<MethodBase, PatchInfo>();
  67. internal static PatchInfo GetPatchInfo(MethodBase method)
  68. {
  69. lock (patchInfos)
  70. {
  71. if (!patchInfos.TryGetValue(method, out var info))
  72. patchInfos[method] = info = new PatchInfo();
  73. return info;
  74. }
  75. }
  76. internal static IEnumerable<MethodBase> GetPatchedMethods()
  77. {
  78. lock (patchInfos)
  79. {
  80. return patchInfos.Keys.ToList().AsEnumerable();
  81. }
  82. }
  83. }
  84. }