Esempio n. 1
0
        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();
                    }
                }
            }
        }
Esempio n. 2
0
        public void SetUp()
        {
            var testMethod   = TestContext.CurrentContext.Test.Name;
            var parts        = testMethod.Split('_');
            var originalType = AccessTools.TypeByName("HarmonyLibTests.Assets." + parts[1]);
            var patchType    = AccessTools.TypeByName("HarmonyLibTests.Assets." + parts[2]);

            Assert.IsNotNull(originalType);
            var originalMethod = originalType.GetMethod("Method");

            Assert.IsNotNull(originalMethod);

            var finalizer = patchType.GetMethod("Finalizer");

            Assert.IsNotNull(finalizer);

            var instance = new Harmony("test");

            Assert.IsNotNull(instance);
            var patcher = new PatchProcessor(instance, originalMethod);

            Assert.IsNotNull(patcher);
            patcher.AddFinalizer(finalizer);
            patcher.Patch();

            var trv = Traverse.Create(patchType);

            trv.Field("finalized").SetValue(false);
            trv.Field("exception").SetValue(new NullReferenceException("replace-me"));

            var obj      = Activator.CreateInstance(originalType);
            var m_method = AccessTools.Method(originalType, "Method");

            info = new Dictionary <string, object>();
            try
            {
                if (m_method.ReturnType == typeof(void))
                {
                    m_method.Invoke(obj, null);
                }
                else
                {
                    info["result"] = m_method.Invoke(obj, null);
                }
                info["outerexception"] = null;
            }
            catch (TargetInvocationException e)
            {
                info["outerexception"] = e.InnerException;
            }

            trv.Fields().ForEach(name => info[name] = trv.Field(name).GetValue());

            instance.UnpatchAll();

            Assert.IsTrue((bool)info["finalized"], "Finalizer not called");
        }
Esempio n. 3
0
        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();
                }
            }
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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);
            }
        }
Esempio n. 6
0
 /// <summary>
 ///     Apply a finalizer to the original method
 /// </summary>
 /// <param name="action">Finalizer to apply</param>
 /// <typeparam name="T">Finalizer delegate type</typeparam>
 /// <returns>Current patch processor</returns>
 public PatchComposer Finalizer <T>(T action) where T : Delegate
 {
     processor.AddFinalizer(GetPatchMethod(action));
     return(this);
 }