123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using Mono.Cecil;
- using Mono.Cecil.Cil;
- using UnityEngine;
- using Object = UnityEngine.Object;
- namespace COM3D2.NeighUncensor.Patcher
- {
- public static class NeighUncensorPatcher
- {
- public static readonly string[] TargetAssemblyNames = { "Assembly-CSharp.dll", "UnityEngine.dll" };
- private static readonly Dictionary<string, Action<AssemblyDefinition, TypeDefinition>> patches =
- new Dictionary<string, Action<AssemblyDefinition, TypeDefinition>>
- {
- ["Assembly-CSharp"] = PatchAssemblyCSharp, ["UnityEngine"] = PatchUnityEngine
- };
- public static void Patch(AssemblyDefinition ad)
- {
- var hookAd = AssemblyDefinition.ReadAssembly(Assembly.GetExecutingAssembly().Location);
- var hooks = hookAd.MainModule.GetType("COM3D2.NeighUncensor.Patcher.Hooks");
- if (patches.TryGetValue(ad.Name.Name, out var patch))
- patch(ad, hooks);
- }
- private static void PatchPostfix(MethodDefinition method, MethodReference postfix, bool passInstance = false)
- {
- var il = method.Body.GetILProcessor();
- var mRef = method.Module.ImportReference(postfix);
- foreach (var ins in method.Body.Instructions.ToList())
- {
- if (ins.OpCode != OpCodes.Ret)
- continue;
- ins.OpCode = OpCodes.Nop;
- il.InsertAfter(ins, il.Create(OpCodes.Ret));
- il.InsertAfter(ins, il.Create(OpCodes.Call, mRef));
- if (passInstance)
- il.InsertAfter(ins, il.Create(OpCodes.Ldarg_0));
- }
- }
- private static void PatchAssemblyCSharp(AssemblyDefinition ad, TypeDefinition hooks)
- {
- var bgMgr = ad.MainModule.GetType("BgMgr");
- var importCM = ad.MainModule.GetType("ImportCM");
- var createAssetBundle = bgMgr.Methods.FirstOrDefault(m => m.Name == "CreateAssetBundle");
- PatchPostfix(createAssetBundle,
- hooks.Methods.FirstOrDefault(m => m.Name == nameof(Hooks.PostCreateAssetBundle)));
- var readMaterial = importCM.Methods.FirstOrDefault(m => m.Name == "ReadMaterial");
- PatchPostfix(readMaterial, hooks.Methods.FirstOrDefault(m => m.Name == nameof(Hooks.PostReadMaterial)));
- }
- private static void PatchUnityEngine(AssemblyDefinition ad, TypeDefinition hooks)
- {
- var resources = ad.MainModule.GetType("UnityEngine.Resources");
- var load = resources.Methods.FirstOrDefault(
- m => m.Name == "Load" && m.Parameters.Count == 1 &&
- m.ReturnType.FullName == "UnityEngine.Object");
- PatchPostfix(load, hooks.Methods.FirstOrDefault(m => m.Name == nameof(Hooks.OnResourceLoad)));
- }
- }
- public static class Hooks
- {
- private static object replacement;
- public static Material PostReadMaterial(Material result)
- {
- if (result.shader?.name.ToLowerInvariant().Contains("mosaic") ?? false)
- {
- if (replacement == null)
- replacement = Shader.Find("Unlit/Transparent");
- result.shader = (Shader)replacement;
- result.renderQueue = 0;
- }
- return result;
- }
- public static GameObject PostCreateAssetBundle(GameObject result)
- {
- TryUncensor(result);
- return result;
- }
- public static Object OnResourceLoad(Object result)
- {
- if (result is GameObject go)
- TryUncensor(go);
- return result;
- }
- private static void TryUncensor(GameObject go)
- {
- if (go == null)
- return;
- var smr = go.GetComponentInChildren<Renderer>();
- if (smr == null || smr.materials == null)
- return;
- foreach (var mm in smr.materials)
- PostReadMaterial(mm);
- }
- }
- }
|