Esempio n. 1
0
        public static void ProfilePatch()
        {
            MethodTransplanting.PatchMethods(typeof(H_InfoCard));

            Modbase.Harmony.Patch(AccessTools.Method(typeof(StatsReportUtility), nameof(StatsReportUtility.DrawStatsReport), new[] { typeof(Rect), typeof(Thing) }),
                                  new HarmonyMethod(typeof(H_InfoCard), nameof(FUUUCK)));
        }
Esempio n. 2
0
        private static IEnumerable <CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable <CodeInstruction> codeInstructions)
        {
            var enumerable = codeInstructions.ToList();

            try
            {
                List <CodeInstruction> instructions = enumerable;

                for (int i = 0; i < instructions.Count; i++)
                {
                    if (!IsFunctionCall(instructions[i].opcode))
                    {
                        continue;
                    }
                    if (!(instructions[i].operand is MethodInfo meth))
                    {
                        continue;
                    }

                    // Check for constrained
                    if (i != 0 && instructions[i - 1].opcode == OpCodes.Constrained)
                    {
                        continue;
                    }
                    // Make sure it is not an analyzer profiling method
                    if (meth.DeclaringType.FullName.Contains("Analyzer.Profiling"))
                    {
                        continue;
                    }

                    var key   = Utility.GetMethodKey(meth);
                    var index = MethodInfoCache.AddMethod(key, meth);

                    var inst = MethodTransplanting.ReplaceMethodInstruction(
                        instructions[i],
                        key,
                        GUIController.types[__originalMethod.DeclaringType + ":" + __originalMethod.Name + "-int"],
                        index);

                    instructions[i] = inst;
                }

                return(instructions);
            }
            catch (Exception e)
            {
#if DEBUG
                ThreadSafeLogger.Error($"Failed to patch the internal method {__originalMethod.DeclaringType.FullName}:{__originalMethod.Name}, failed with the error " + e.Message);
#else
                if (Settings.verboseLogging)
                {
                    ThreadSafeLogger.Warning($"Failed to patch the internal method {__originalMethod.DeclaringType.FullName}:{__originalMethod.Name}, failed with the error " + e.Message);
                }
#endif

                return(enumerable);
            }
        }
        private static IEnumerable <CodeInstruction> Transpiler(MethodBase __originalMethod,
                                                                IEnumerable <CodeInstruction> instructions)
        {
            var inst        = PatchProcessor.GetOriginalInstructions(__originalMethod);
            var modInstList = instructions.ToList();

            var insts = new Myers <CodeInstruction>(inst.ToArray(), modInstList.ToArray(), methComparer);

            insts.Compute();

            var key   = Utility.GetMethodKey(__originalMethod as MethodInfo);
            var index = MethodInfoCache.AddMethod(key, __originalMethod as MethodInfo);

            foreach (var thing in insts.changeSet)
            {
                // We only want added methods
                if (thing.change != ChangeType.Added)
                {
                    continue;
                }
                if (!InternalMethodUtility.IsFunctionCall(thing.value.opcode) ||
                    !(thing.value.operand is MethodInfo meth))
                {
                    continue;
                }

                // swap our instruction
                var replaceInstruction = MethodTransplanting.ReplaceMethodInstruction(
                    thing.value,
                    key,
                    typeof(H_HarmonyTranspilersInternalMethods),
                    index);

                // Find the place it was in our method, and replace the instruction (Optimisation Opportunity to improve this)
                for (var i = 0; i < modInstList.Count; i++)
                {
                    var instruction = modInstList[i];
                    if (!InternalMethodUtility.IsFunctionCall(instruction.opcode))
                    {
                        continue;
                    }
                    if (!(instruction.operand is MethodInfo info) || info.Name != meth.Name)
                    {
                        continue;
                    }


                    if (instruction != replaceInstruction)
                    {
                        modInstList[i] = replaceInstruction;
                    }
                    break;
                }
            }

            return(modInstList);
        }
Esempio n. 4
0
 public static void ProfilePatch()
 {
     try
     {
         MethodTransplanting.PatchMethods(typeof(H_HarmonyPatches));
     }
     catch (Exception e)
     {
         ThreadSafeLogger.Error("Patching HarmonyPatches failed, errored with the message" + e.Message);
     }
 }
 public static void ProfilePatch()
 {
     try
     {
         MethodTransplanting.PatchMethods(typeof(H_HarmonyPatches));
     }
     catch (Exception e)
     {
         ThreadSafeLogger.ReportException(e, "Failed to patch HarmonyPatches");
     }
 }
Esempio n. 6
0
        public static void ExecutePatch(CurrentInput mode, string strinput, Category cat)
        {
            try
            {
                var entry = cat == Category.Tick ? typeof(CustomProfilersTick) : typeof(CustomProfilersUpdate);
                List <MethodInfo> methods = null;

                var temp = mode switch
                {
                    CurrentInput.Method => Utility.GetMethods(strinput),
                    CurrentInput.Type => Utility.GetTypeMethods(AccessTools.TypeByName(strinput)),
                    CurrentInput.MethodHarmony => Utility.GetMethodsPatching(strinput),
                    CurrentInput.SubClasses => Utility.SubClassImplementationsOf(AccessTools.TypeByName(strinput), m => true),
                    CurrentInput.TypeHarmony => Utility.GetMethodsPatchingType(AccessTools.TypeByName(strinput)),
                    _ => null,
                };

                if (temp is null)
                {
                    if (mode == CurrentInput.InternalMethod)
                    {
                        Utility.PatchInternalMethod(strinput, cat);
                    }
                    else
                    {
                        Utility.PatchAssembly(strinput, cat);
                    }

                    return;
                }

                methods = temp.ToList();

                if (methods.Count == 0)
                {
                    Messages.Message($"Failed to find the method(s) represented by {strinput}", MessageTypeDefOf.CautionInput, false);
                    return;
                }

                Messages.Message(methods.Count != 1 ? $"Patching {methods.Count} methods in the category {cat}" : $"Patching {Utility.GetSignature(methods[0])} in the category {cat}", MessageTypeDefOf.CautionInput, false);

                MethodTransplanting.UpdateMethods(entry, methods.ToList());
                GUIController.Tab(cat).collapsed = false;

                var entryName = (cat == Category.Tick) ? "Custom Tick" : "Custom Update";
                GUIController.SwapToEntry(entryName);
            }
            catch (Exception e)
            {
                ThreadSafeLogger.ReportException(e, $"Failed to process search bar input");
            }
        }
        private static void PatchAssemblyFull(string key, List <Assembly> assemblies)
        {
            var meths = new HashSet <MethodInfo>();

            foreach (var asm in assemblies)
            {
                try
                {
                    var asmName = $"{asm.GetName().Name}.dll";
                    if (patchedAssemblies.Contains(asm.FullName))
                    {
                        Warn($"patching {asmName} failed, already patched");
                        continue;
                    }

                    patchedAssemblies.Add(asm.FullName);

                    foreach (var type in AccessTools.GetTypesFromAssembly(asm))
                    {
                        var methods = AccessTools.GetDeclaredMethods(type).ToList();
                        foreach (var m in methods)
                        {
                            try
                            {
                                if (ValidMethod(m) && m.DeclaringType == type)
                                {
                                    meths.TryAdd(m);
                                }
                            }
                            catch (Exception e)
                            {
                                ReportException(e, $"Skipping method {GetSignature(m)}");
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    ReportException(e, $"Failed to patch the assembly {asm.FullName}");
                }
            }

            var asms      = assemblies.Select(a => a.GetName().Name + ".dll").Join();
            var asmString = assemblies.Count > 1 ? "assemblies" : "assembly";

            Messages.Message($"Attempting to patch {meths.Count} methods from the {asmString} [{asms}]", MessageTypeDefOf.CautionInput, false);

            MethodTransplanting.UpdateMethods(GUIController.types[key], meths);
        }
        public static void ClearPatchCaches()
        {
            patchedAssemblies.Clear();
            patchedTypes.Clear();
            patchedMethods.Clear();

            InternalMethodUtility.ClearCaches();
            MethodTransplanting.ClearCaches();
            TranspilerMethodUtility.ClearCaches();

            MethodInfoCache.ClearCache();

#if DEBUG
            ThreadSafeLogger.Message("[Analyzer] Cleared all caches");
#endif
        }
Esempio n. 9
0
        private static IEnumerable <CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable <CodeInstruction> instructions)
        {
            var inst        = PatchProcessor.GetOriginalInstructions(__originalMethod);
            var modInstList = instructions.ToList();

            var insts = new Myers <CodeInstruction>(inst.ToArray(), modInstList.ToArray(), methComparer);

            insts.Compute();

            var key   = Utility.GetMethodKey(__originalMethod);
            var index = MethodInfoCache.AddMethod(key, __originalMethod);

            foreach (var thing in insts.changeSet)
            {
                // We only want added methods
                if (thing.change != ChangeType.Added)
                {
                    continue;
                }

                if (!Utility.ValidCallInstruction(thing.value, null, out var meth, out _))
                {
                    continue;
                }
                if (!(meth is MethodInfo))
                {
                    continue;
                }

                // swap our instruction
                var replaceInstruction = MethodTransplanting.ReplaceMethodInstruction(
                    thing.value,
                    key,
                    typeof(H_HarmonyTranspilersInternalMethods),
                    index);

                modInstList[thing.rIndex] = replaceInstruction;
            }

            return(modInstList);
        }
        private static IEnumerable <CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable <CodeInstruction> codeInstructions)
        {
            try
            {
                var instructions = codeInstructions.ToList();

                for (int i = 0; i < instructions.Count; i++)
                {
                    if (!Utility.ValidCallInstruction(instructions[i], i == 0 ? null : instructions[i - 1], out var meth, out var key))
                    {
                        continue;
                    }

                    var index = MethodInfoCache.AddMethod(key, meth);

                    var inst = MethodTransplanting.ReplaceMethodInstruction(
                        instructions[i],
                        key,
                        GUIController.types[__originalMethod.DeclaringType + ":" + __originalMethod.Name + "-int"],
                        index);

                    instructions[i] = inst;
                }

                return(instructions);
            }
            catch (Exception e)
            {
#if DEBUG
                ThreadSafeLogger.ReportException(e, $"Failed to patch the methods inside {Utility.GetSignature(__originalMethod, false)}");
#else
                if (Settings.verboseLogging)
                {
                    ThreadSafeLogger.ReportException(e, $"Failed to patch the methods inside {Utility.GetSignature(__originalMethod, false)}");
                }
#endif

                return(codeInstructions);
            }
        }
Esempio n. 11
0
        private static void PatchAssemblyFull(string key, List <Assembly> assemblies)
        {
            var meths = new HashSet <MethodInfo>();

            foreach (var assembly in assemblies)
            {
                try
                {
                    if (patchedAssemblies.Contains(assembly.FullName))
                    {
                        Warn($"patching {assembly.FullName} failed, already patched");
                        return;
                    }

                    patchedAssemblies.Add(assembly.FullName);

                    foreach (var type in assembly.GetTypes())
                    {
                        foreach (var method in AccessTools.GetDeclaredMethods(type).Where(m => ValidMethod(m) && m.DeclaringType == type))
                        {
                            if (!meths.Contains(method))
                            {
                                meths.Add(method);
                            }
                        }
                    }

                    Notify($"Patched {assembly.FullName}");
                }
                catch (Exception e)
                {
                    Error($"Patching {assembly.FullName} failed, {e.Message}");
                    return;
                }
            }

            MethodTransplanting.UpdateMethods(GUIController.types[key], meths);
        }
Esempio n. 12
0
        public static void ExecutePatch()
        {
            try
            {
                if (patchType == Category.Tick)
                {
                    switch (input)
                    {
                    case CurrentInput.Method:
                        MethodTransplanting.UpdateMethods(typeof(CustomProfilersTick), Utility.GetMethods(currentInput));
                        break;

                    case CurrentInput.Type:
                        MethodTransplanting.UpdateMethods(typeof(CustomProfilersTick), Utility.GetTypeMethods(AccessTools.TypeByName(currentInput)));
                        break;

                    case CurrentInput.MethodHarmony:
                        MethodTransplanting.UpdateMethods(typeof(CustomProfilersTick), Utility.GetMethodsPatching(currentInput));
                        break;

                    case CurrentInput.SubClasses:
                        MethodTransplanting.UpdateMethods(typeof(CustomProfilersTick), Utility.SubClassImplementationsOf(AccessTools.TypeByName(currentInput), m => true));
                        break;

                    case CurrentInput.TypeHarmony:
                        MethodTransplanting.UpdateMethods(typeof(CustomProfilersTick), Utility.GetMethodsPatchingType(AccessTools.TypeByName(currentInput)));
                        break;

                    case CurrentInput.InternalMethod:
                        Utility.PatchInternalMethod(currentInput, Category.Tick);
                        return;

                    case CurrentInput.Assembly:
                        Utility.PatchAssembly(currentInput, Category.Tick);
                        return;
                    }

                    GUIController.SwapToEntry("Custom Tick");
                }
                else
                {
                    switch (input)
                    {
                    case CurrentInput.Method:
                        MethodTransplanting.UpdateMethods(typeof(CustomProfilersUpdate), Utility.GetMethods(currentInput));
                        break;

                    case CurrentInput.Type:
                        MethodTransplanting.UpdateMethods(typeof(CustomProfilersUpdate), Utility.GetTypeMethods(AccessTools.TypeByName(currentInput)));
                        break;

                    case CurrentInput.MethodHarmony:
                        MethodTransplanting.UpdateMethods(typeof(CustomProfilersUpdate), Utility.GetMethodsPatching(currentInput));
                        break;

                    case CurrentInput.SubClasses:
                        MethodTransplanting.UpdateMethods(typeof(CustomProfilersUpdate), Utility.SubClassImplementationsOf(AccessTools.TypeByName(currentInput), m => true));
                        break;

                    case CurrentInput.TypeHarmony:
                        MethodTransplanting.UpdateMethods(typeof(CustomProfilersUpdate), Utility.GetMethodsPatchingType(AccessTools.TypeByName(currentInput)));
                        break;

                    case CurrentInput.InternalMethod:
                        Utility.PatchInternalMethod(currentInput, Category.Update);
                        return;

                    case CurrentInput.Assembly:
                        Utility.PatchAssembly(currentInput, Category.Update);
                        return;
                    }

                    GUIController.SwapToEntry("Custom Update");
                }
            }
            catch (Exception e)
            {
                ThreadSafeLogger.Error($"Failed to process input, failed with the error {e.Message}");
            }
        }
        public static void ProfilePatch()
        {
            Modbase.Harmony.Patch(AccessTools.Method(typeof(ThinkNode_Priority), nameof(ThinkNode_Priority.TryIssueJobPackage)), new HarmonyMethod(typeof(H_GetLord), nameof(Fringe)));

            MethodTransplanting.UpdateMethods(typeof(H_GetLord), Utility.GetTypeMethods(typeof(Lord)).ToList());
        }