public void TestMethod8() { var originalClass = typeof(Class8); Assert.IsNotNull(originalClass); var originalMethod = originalClass.GetMethod("Method8"); Assert.IsNotNull(originalMethod); var patchClass = typeof(Class8Patch); var postfix = patchClass.GetMethod("Postfix"); Assert.IsNotNull(postfix); var instance = new Harmony("test"); Assert.IsNotNull(instance); var patcher = new PatchProcessor(instance, originalMethod); Assert.IsNotNull(patcher); patcher.AddPostfix(postfix); Assert.IsNotNull(patcher); patcher.Patch(); var result = Class8.Method8("patched"); Assert.IsTrue(Class8.mainRun); Assert.AreEqual(10, result.a); Assert.AreEqual(20, result.b); }
public void TestMethod7() { var originalClass = typeof(Class7); Assert.IsNotNull(originalClass); var originalMethod = originalClass.GetMethod("Method7"); Assert.IsNotNull(originalMethod); var patchClass = typeof(Class7Patch); var postfix = patchClass.GetMethod("Postfix"); Assert.IsNotNull(postfix); var instance = new Harmony("test"); Assert.IsNotNull(instance); var patcher = new PatchProcessor(instance, originalMethod); Assert.IsNotNull(patcher); patcher.AddPostfix(postfix); patcher.Patch(); Class7.state2 = "before"; var instance7 = new Class7(); var result = instance7.Method7("parameter"); Console.WriteLine(Class7.state2); Assert.AreEqual("parameter", instance7.state1); Assert.AreEqual(10, result.a); Assert.AreEqual(20, result.b); }
public void TestMethod10() { var originalClass = typeof(Class10); Assert.IsNotNull(originalClass); var originalMethod = originalClass.GetMethod("Method10"); Assert.IsNotNull(originalMethod); var patchClass = typeof(Class10Patch); var postfix = patchClass.GetMethod("Postfix"); Assert.IsNotNull(postfix); var instance = new Harmony("test"); Assert.IsNotNull(instance); var patcher = new PatchProcessor(instance, originalMethod); Assert.IsNotNull(patcher); patcher.AddPostfix(postfix); patcher.Patch(); new Class10().Method10(); Assert.IsTrue(Class10Patch.postfixed); Assert.IsTrue(Class10Patch.originalResult); }
public void TestMethod5() { var originalClass = typeof(Class5); Assert.IsNotNull(originalClass); var originalMethod = originalClass.GetMethod("Method5"); Assert.IsNotNull(originalMethod); var patchClass = typeof(Class5Patch); var prefix = patchClass.GetMethod("Prefix"); Assert.IsNotNull(prefix); var postfix = patchClass.GetMethod("Postfix"); Assert.IsNotNull(postfix); Class5Patch.ResetTest(); var instance = new Harmony("test"); Assert.IsNotNull(instance); var patcher = new PatchProcessor(instance, originalMethod); Assert.IsNotNull(patcher); patcher.AddPrefix(prefix); patcher.AddPostfix(postfix); patcher.Patch(); new Class5().Method5("foo"); Assert.IsTrue(Class5Patch.prefixed, "Prefix was not executed"); Assert.IsTrue(Class5Patch.postfixed, "Prefix was not executed"); }
public void TestPatchUnpatch() { var originalClass = typeof(Class9); Assert.IsNotNull(originalClass); var originalMethod = originalClass.GetMethod("ToString"); Assert.IsNotNull(originalMethod); var patchClass = typeof(Class9Patch); var prefix = patchClass.GetMethod("Prefix"); Assert.IsNotNull(prefix); var postfix = patchClass.GetMethod("Postfix"); Assert.IsNotNull(postfix); var instance = new Harmony("test"); Assert.IsNotNull(instance); var patcher = new PatchProcessor(instance, originalMethod); Assert.IsNotNull(patcher); patcher.AddPrefix(prefix); patcher.AddPostfix(postfix); patcher.Patch(); var instanceB = new Harmony("test"); Assert.IsNotNull(instanceB); instanceB.UnpatchAll("test"); }
public void TestMethod0() { var originalClass = typeof(Class0); Assert.IsNotNull(originalClass); var originalMethod = originalClass.GetMethod("Method0"); Assert.IsNotNull(originalMethod); var patchClass = typeof(Class0Patch); var postfix = patchClass.GetMethod("Postfix"); Assert.IsNotNull(postfix); var instance = new Harmony("test"); Assert.IsNotNull(instance); var patcher = new PatchProcessor(instance, originalMethod); Assert.IsNotNull(patcher); patcher.AddPostfix(postfix); patcher.Patch(); var result = new Class0().Method0(); Assert.AreEqual("patched", result); }
static Main() { var harmony = new Harmony("Garthor.More_Traits"); harmony.PatchAll(); // Get all types in the Compatibility namespace var types = from x in Assembly.GetExecutingAssembly().GetTypes() where x.IsClass && x.Namespace == "Garthor_More_Traits.Compatibility" select x; // Iterate through types tagged with the PatchIfMod attribute foreach (var t in types) { var attr = t.GetCustomAttribute <Compatibility.PatchIfModAttribute>(); if (attr != null && attr.IsModLoaded()) { Dictionary <MethodBase, PatchProcessor> patches = new Dictionary <MethodBase, PatchProcessor>(); foreach (var method in t.GetMethods()) { foreach (var harmonyPatch in method.GetCustomAttributes <HarmonyPatch>()) { // First add a PatchProcessor for the method we're targeting to the patches list, if not already present MethodBase mb = harmonyPatch.info.declaringType.GetMethod(harmonyPatch.info.methodName); if (!patches.ContainsKey(mb)) { patches.Add(mb, new PatchProcessor(harmony, mb)); } PatchProcessor patch = patches[mb]; // Next add this method to the prefix, postfix, transpiler, or finalizer lists, as appropriate // (bit repetitive, but it's short and would be a bit convoluted to improve it) if (method.GetCustomAttributes <HarmonyPrefix>().Any()) { patch.AddPrefix(new HarmonyMethod(method)); } if (method.GetCustomAttributes <HarmonyPostfix>().Any()) { patch.AddPostfix(new HarmonyMethod(method)); } if (method.GetCustomAttributes <HarmonyTranspiler>().Any()) { patch.AddTranspiler(new HarmonyMethod(method)); } if (method.GetCustomAttributes <HarmonyFinalizer>().Any()) { patch.AddFinalizer(new HarmonyMethod(method)); } } } // Apply the patches for this mod foreach (PatchProcessor processor in patches.Values) { processor.Patch(); } } } }
static HarmonyLoader() { // load directly embedded patches var harmony = new Harmony("harmony-loader-" + Guid.NewGuid().ToString("N")); var assembly = Assembly.GetExecutingAssembly(); foreach (var type in assembly.GetTypes()) { foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) { var harmonyMethods = HarmonyMethodExtensions.GetFromMethod(method); if (harmonyMethods is null || !harmonyMethods.Any()) { continue; } var merged = new HarmonyMethod() { methodType = MethodType.Normal }.Merge(HarmonyMethod.Merge(harmonyMethods)); Logger.LogDebug($"found method: {method} / {merged}"); var proc = new PatchProcessor(harmony); proc.AddOriginal(PatchProcessor.GetOriginalMethod(merged) /*(MethodBase) Info.OfMethod<PatchProcessor>("GetOriginalMethod").Invoke(null, new[] {merged})*/); if (method.GetCustomAttributes <HarmonyTranspiler>().Any()) { proc.AddTranspiler(method); } if (method.GetCustomAttributes <HarmonyPrefix>().Any()) { proc.AddPrefix(method); } if (method.GetCustomAttributes <HarmonyPostfix>().Any()) { proc.AddPostfix(method); } if (method.GetCustomAttributes <HarmonyFinalizer>().Any()) { proc.AddFinalizer(method); } proc.Patch(); } } // load the normal style of patches Harmony.CreateAndPatchAll(typeof(AutoLoadManager).Assembly); }
static HarmonyLoader() { // load directly embedded patches var harmony = new Harmony("harmony-loader-" + Guid.NewGuid().ToString("N")); var assembly = Assembly.GetExecutingAssembly(); foreach (var type in assembly.GetTypes()) { foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) { var harmonyMethods = HarmonyMethodExtensions.GetFromMethod(method); if (harmonyMethods is null || !harmonyMethods.Any()) { continue; } var merged = new HarmonyMethod() { methodType = MethodType.Normal }.Merge(HarmonyMethod.Merge(harmonyMethods)); Logger.LogDebug($"found method: {method} / {merged}"); #if BepInEx var proc = new PatchProcessor(harmony); proc.AddOriginal(PatchProcessor.GetOriginalMethod(merged)); #elif UMM var proc = new PatchProcessor(harmony, merged.GetOriginalMethod()); #endif if (method.GetCustomAttributes <HarmonyTranspiler>().Any()) { proc.AddTranspiler(method); } if (method.GetCustomAttributes <HarmonyPrefix>().Any()) { proc.AddPrefix(method); } if (method.GetCustomAttributes <HarmonyPostfix>().Any()) { proc.AddPostfix(method); } if (method.GetCustomAttributes <HarmonyFinalizer>().Any()) { proc.AddFinalizer(method); } proc.Patch(); } } }
public override void LoadPlugin() { base.LoadPlugin(); HarmonyInstance = new Harmony("PlayerIPPatch"); Logger.Log("Player IP Patch by ShimmyMySherbet (great job nelson!)"); Logger.Log("Patching IP Methods..."); MethodInfo PatchBase = typeof(SteamGameServerNetworking).GetMethod("GetP2PSessionState"); PatchProcessor Processor = HarmonyInstance.CreateProcessor(PatchBase); Processor.AddPostfix(new HarmonyMethod(typeof(PlayerIPPatch).GetMethod("PostFixObj"))); Processor.Patch(); Logger.Log("Patched!"); }
public void TestMethod2() { var originalClass = typeof(Class2); Assert.IsNotNull(originalClass); var originalMethod = originalClass.GetMethod("Method2"); Assert.IsNotNull(originalMethod); var patchClass = typeof(Class2Patch); var prefix = patchClass.GetMethod("Prefix"); var postfix = patchClass.GetMethod("Postfix"); var transpiler = patchClass.GetMethod("Transpiler"); Assert.IsNotNull(prefix); Assert.IsNotNull(postfix); Assert.IsNotNull(transpiler); Class2Patch.ResetTest(); var instance = new Harmony("test"); Assert.IsNotNull(instance); var patcher = new PatchProcessor(instance, originalMethod); Assert.IsNotNull(patcher); patcher.AddPrefix(prefix); patcher.AddPostfix(postfix); patcher.AddTranspiler(transpiler); patcher.Patch(); // unsafe // { // var patchedCode = *(byte*) originalMethodStartPre; // if (IntPtr.Size == sizeof(long)) // Assert.IsTrue(patchedCode == 0x48); // else // Assert.IsTrue(patchedCode == 0x68); // } new Class2().Method2(); Assert.IsTrue(Class2Patch.prefixed, "Prefix was not executed"); Assert.IsTrue(Class2Patch.originalExecuted, "Original was not executed"); Assert.IsTrue(Class2Patch.postfixed, "Postfix was not executed"); }
public void TestGenericStructReturnTypes() { TestGenericStructReturnTypes_Patch.Prepare(); var originalClass = typeof(MyList <>).MakeGenericType(typeof(int)); Assert.IsNotNull(originalClass); var originalMethod = originalClass.GetMethod("GetEnumerator"); Assert.IsNotNull(originalMethod); var patchClass = typeof(TestGenericStructReturnTypes_Patch); var postfix = patchClass.GetMethod("Postfix"); Assert.IsNotNull(postfix); var instance = new Harmony("test"); Assert.IsNotNull(instance); var patcher = new PatchProcessor(instance, originalMethod); Assert.IsNotNull(patcher); _ = patcher.AddPostfix(postfix); _ = patcher.Patch(); var list = new MyList <int> { list = new List <int>() { 1, 2, 3 } }; var enumerator = list.GetEnumerator(); var result = new List <int>(); while (enumerator.MoveNext()) { result.Add(enumerator.Current); } Assert.AreEqual(3, result.Count); Assert.AreEqual(100, result[0]); Assert.AreEqual(200, result[1]); Assert.AreEqual(300, result[2]); }
public void TestReverseTranspilerPatching() { var class0 = new Class0Reverse(); var result1 = class0.Method("al-gin-Ori", 123); Assert.AreEqual("Original123Prolog", result1); var originalClass = typeof(Class0Reverse); Assert.IsNotNull(originalClass); var originalMethod = originalClass.GetMethod("Method"); Assert.IsNotNull(originalMethod); var patchClass = typeof(Class0ReversePatch); var postfix = patchClass.GetMethod("Postfix"); Assert.IsNotNull(postfix); //Harmony.DEBUG = true; var instance = new Harmony("test"); Assert.IsNotNull(instance); var patcher = new PatchProcessor(instance, originalMethod); patcher.AddPostfix(new HarmonyMethod(postfix)); patcher.Patch(); var standin = patchClass.GetMethod("StringOperation"); Assert.IsNotNull(standin); var reversePatcher = instance.CreateReversePatcher(originalMethod, standin); reversePatcher.Patch(); var result2 = class0.Method("al-gin-Ori", 456); Assert.AreEqual("EpilogOriginal", result2); }
public void Test_InjectingBaseClassField() { var testInstance = new InjectFieldSubClass(); testInstance.Method("foo"); Assert.AreEqual("foo", testInstance.TestValue); var originalClass = testInstance.GetType(); Assert.IsNotNull(originalClass); var originalMethod = originalClass.GetMethod("Method"); Assert.IsNotNull(originalMethod); var patchClass = typeof(InjectFieldSubClass_Patch); var postfix = patchClass.GetMethod("Postfix"); Assert.IsNotNull(postfix); var instance = new Harmony("test"); Assert.IsNotNull(instance); instance.Patch(originalMethod, postfix: new HarmonyMethod(postfix)); var patcher = new PatchProcessor(instance, originalMethod); Assert.IsNotNull(patcher); _ = patcher.AddPostfix(postfix); Assert.IsNotNull(patcher); _ = patcher.Patch(); testInstance.Method("bar"); Assert.AreEqual("patched", testInstance.TestValue); }
public void TestNativePatch() { // Currently NativeDetours don't work properly on .NET Core (except when running in debug mode) // ¯\_(ツ)_/¯ #if NETCOREAPP3_0 return; #endif var originalClass = typeof(NativeClass); Assert.IsNotNull(originalClass); var originalMethod = originalClass.GetMethod("Rand"); Assert.IsNotNull(originalMethod); var patchClass = typeof(NativeClassPatch); var prefix = patchClass.GetMethod("Prefix"); Assert.IsNotNull(prefix); var postfix = patchClass.GetMethod("Postfix"); Assert.IsNotNull(postfix); var transpiler = patchClass.GetMethod("Transpiler"); Assert.IsNotNull(transpiler); var instance = new Harmony("test-native"); Assert.IsNotNull(instance); var patcher = new PatchProcessor(instance, originalMethod); Assert.IsNotNull(patcher); patcher.AddPrefix(prefix); patcher.AddPostfix(postfix); patcher.AddTranspiler(transpiler); patcher.Patch(); var result = NativeClass.Rand(); Assert.AreEqual(-1, result); Assert.IsTrue(NativeClassPatch.prefixCalled, "Prefix wasn't run"); Assert.IsTrue(NativeClassPatch.postfixCalled, "Postfix wasn't run"); Assert.IsTrue(NativeClassPatch.transpilerCalled, "Transpiler wasn't run"); }
/// <summary> /// Apply a postfix to the original method /// </summary> /// <param name="action">Postfix to apply</param> /// <typeparam name="T">Postfix delegate type</typeparam> /// <returns>Current patch processor</returns> public PatchComposer Postfix <T>(T action) where T : Delegate { processor.AddPostfix(GetPatchMethod(action)); return(this); }
public ProcessorInfo AddPostfix(HarmonyMethod postfix) { processor.AddPostfix(postfix); return(this); }
public void AttemptProhibitedPatch(Harmony h) { testName = "TEST/" + "API/ACL2/" + typeof(HarmonyHelper).Assembly.GetName().Name + " " + typeof(HarmonyHelper).Assembly.GetName().Version; PatchProcessor processor = null; MethodInfo prohibitedPatch = null; try { var targetName = "CompareTo"; MethodInfo target = typeof(Patch).GetMethod(targetName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (target == null) { throw new TestFailed($"Target fn ({targetName}) was not found."); } processor = h.CreateProcessor(target); if (processor == null) { UnityEngine.Debug.Log($"[{testName}] INFO - Processor=null. BAD"); throw new TestFailed($"Failed to create processor."); } prohibitedPatch = typeof(ACLPatchDefinitions).GetMethod("ProhibitedPatch", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (prohibitedPatch == null) { throw new TestFailed("Patch fn (ProhibitedPatch) was not found."); } processor.AddPostfix(prohibitedPatch); processor.Patch(); throw new TestFailed("Installing a prohibited patch did not throw HarmonyModACLException"); } catch (TestFailed ex) { UnityEngine.Debug.Log($"[{testName}] ERROR : {ex.Message}. BAD"); throw ex; } catch (Exception ex) { if (ex.GetType().Name != "HarmonyModACLException") { throw new TestFailed($"Installing a prohibited patch failed but not because of ACL: {ex.Message}"); } UnityEngine.Debug.Log($"[{testName}] INFO - Attempting to install a prohibited patch was blocked ({ex.Message}). OK."); } finally { if (processor != null && prohibitedPatch != null) { try { processor.Unpatch(prohibitedPatch); } catch (Exception ex) { if (ex.GetType().Name != "HarmonyModACLException") { throw new TestFailed($"Uninstalling a prohibited patch failed but not because of ACL: {ex.Message}"); } UnityEngine.Debug.Log($"[{testName}] INFO - Attempting to remove a prohibited patch was blocked ({ex.Message}). OK."); } } else { throw new TestFailed($"Prohibited patch test is broken. processor={processor != null} patch={prohibitedPatch != null}"); } } }
public bool CompileAndGenerateProcessor(string patchSource) { Unpatch(); try { patchProcessor = ExplorerCore.Harmony.CreateProcessor(TargetMethod); // Dynamically compile the patch method var codeBuilder = new StringBuilder(); codeBuilder.AppendLine($"public class DynamicPatch_{DateTime.Now.Ticks}"); codeBuilder.AppendLine("{"); codeBuilder.AppendLine(patchSource); codeBuilder.AppendLine("}"); scriptEvaluator.Run(codeBuilder.ToString()); if (ScriptEvaluator._reportPrinter.ErrorsCount > 0) { throw new FormatException($"Unable to compile the generated patch!"); } // TODO: Publicize MCS to avoid this reflection // Get the most recent Patch type in the source file var typeContainer = ((CompilationSourceFile)fi_sourceFile.GetValue(scriptEvaluator)) .Containers .Last(it => it.MemberName.Name.StartsWith("DynamicPatch_")); // Get the TypeSpec from the TypeDefinition, then get its "MetaInfo" (System.Type) var patchClass = ((TypeSpec)pi_Definition.GetValue((Class)typeContainer, null)).GetMetaInfo(); // Create the harmony patches as defined postfix = patchClass.GetMethod("Postfix", ReflectionUtility.FLAGS); if (postfix != null) { patchProcessor.AddPostfix(new HarmonyMethod(postfix)); } prefix = patchClass.GetMethod("Prefix", ReflectionUtility.FLAGS); if (prefix != null) { patchProcessor.AddPrefix(new HarmonyMethod(prefix)); } finalizer = patchClass.GetMethod("Finalizer", ReflectionUtility.FLAGS); if (finalizer != null) { patchProcessor.AddFinalizer(new HarmonyMethod(finalizer)); } transpiler = patchClass.GetMethod("Transpiler", ReflectionUtility.FLAGS); if (transpiler != null) { patchProcessor.AddTranspiler(new HarmonyMethod(transpiler)); } return(true); } catch (Exception ex) { ExplorerCore.LogWarning($"Exception creating patch processor for target method {TargetMethod.FullDescription()}!\r\n{ex}"); return(false); } }