NeighUncensorPatcher.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using Mono.Cecil;
  6. using Mono.Cecil.Cil;
  7. using UnityEngine;
  8. namespace COM3D2.NeighUncensor.Patcher
  9. {
  10. public static class NeighUncensorPatcher
  11. {
  12. public static readonly string[] TargetAssemblyNames = { "Assembly-CSharp.dll", "UnityEngine.dll" };
  13. private static Dictionary<string, Action<AssemblyDefinition, TypeDefinition>> patches = new Dictionary<string, Action<AssemblyDefinition, TypeDefinition>>
  14. {
  15. ["Assembly-CSharp"] = PatchAssemblyCSharp,
  16. ["UnityEngine"] = PatchUnityEngine
  17. };
  18. public static void Patch(AssemblyDefinition ad)
  19. {
  20. var hookAd = AssemblyDefinition.ReadAssembly(Assembly.GetExecutingAssembly().Location);
  21. var hooks = hookAd.MainModule.GetType("COM3D2.NeighUncensor.Patcher.Hooks");
  22. if (patches.TryGetValue(ad.Name.Name, out var patch))
  23. patch(ad, hooks);
  24. }
  25. private static void PatchPostfix(MethodDefinition method, MethodReference postfix, bool passInstance = false)
  26. {
  27. var il = method.Body.GetILProcessor();
  28. var mRef = method.Module.ImportReference(postfix);
  29. foreach (var ins in method.Body.Instructions.ToList())
  30. {
  31. if (ins.OpCode != OpCodes.Ret)
  32. continue;
  33. ins.OpCode = OpCodes.Nop;
  34. il.InsertAfter(ins, il.Create(OpCodes.Ret));
  35. il.InsertAfter(ins, il.Create(OpCodes.Call, mRef));
  36. if(passInstance)
  37. il.InsertAfter(ins, il.Create(OpCodes.Ldarg_0));
  38. }
  39. }
  40. private static void PatchAssemblyCSharp(AssemblyDefinition ad, TypeDefinition hooks)
  41. {
  42. var tBody = ad.MainModule.GetType("TBody");
  43. var importCM = ad.MainModule.GetType("ImportCM");
  44. var fixMaskFlag = tBody.Methods.FirstOrDefault(m => m.Name == "FixMaskFlag");
  45. PatchPostfix(fixMaskFlag, hooks.Methods.FirstOrDefault(m => m.Name == nameof(Hooks.PostFixMaskFlag)), true);
  46. var loadSkinMeshR = importCM.Methods.FirstOrDefault(m => m.Name == "LoadSkinMesh_R");
  47. PatchPostfix(loadSkinMeshR, hooks.Methods.FirstOrDefault(m => m.Name == nameof(Hooks.PostLoadMesh)));
  48. }
  49. private static void PatchUnityEngine(AssemblyDefinition ad, TypeDefinition hooks)
  50. {
  51. var resources = ad.MainModule.GetType("UnityEngine.Resources");
  52. var load = resources.Methods.FirstOrDefault(
  53. m => m.Name == "Load" && m.Parameters.Count == 1 &&
  54. m.ReturnType.FullName == "UnityEngine.Object");
  55. PatchPostfix(load, hooks.Methods.FirstOrDefault(m => m.Name == nameof(Hooks.OnResourceLoad)));
  56. }
  57. }
  58. public static class Hooks
  59. {
  60. private static object diffuse;
  61. public static void PostFixMaskFlag(TBody tbody)
  62. {
  63. tbody.goSlot[(int)TBody.hashSlotName["moza"]].boVisible = false;
  64. }
  65. public static GameObject PostLoadMesh(GameObject result)
  66. {
  67. TryUncensor(result);
  68. return result;
  69. }
  70. public static UnityEngine.Object OnResourceLoad(UnityEngine.Object result)
  71. {
  72. if (result is GameObject go)
  73. TryUncensor(go);
  74. return result;
  75. }
  76. private static void TryUncensor(GameObject go)
  77. {
  78. if (go == null)
  79. return;
  80. var smr = go.GetComponentInChildren<Renderer>();
  81. if (smr == null || smr.materials == null)
  82. return;
  83. foreach (var mm in smr.materials)
  84. {
  85. if (mm.shader?.name.ToLowerInvariant().Contains("mosaic") ?? false)
  86. {
  87. if (diffuse == null)
  88. diffuse = Shader.Find("CM3D2/Toony_Lighted_Trans");
  89. mm.shader = diffuse as Shader;
  90. mm.color += new Color(0f, 0f, 0f, -1f);
  91. }
  92. }
  93. }
  94. }
  95. }