Пример #1
0
        public static void PatchAssembly(string name, Category type)
        {
            var mod = LoadedModManager.RunningMods.FirstOrDefault(m => m.Name == name || m.PackageId == name.ToLower());

            if (mod == null)
            {
                Error($"Failed to locate the mod {name}");
                return;
            }

            Notify($"Assembly count: {mod.assemblies?.loadedAssemblies?.Count ?? 0}");
            var assemblies = mod?.assemblies?.loadedAssemblies?.Where(ValidAssembly).ToList();

            Notify($"Assembly count after removing Harmony/Cecil/Multiplayer/UnityEngine: {assemblies?.Count}");

            if (assemblies != null && assemblies.Count() != 0)
            {
                GUIController.AddEntry(mod.Name + "-prof", type);
                GUIController.SwapToEntry(mod.Name + "-prof");

                Task.Factory.StartNew(() => PatchAssemblyFull(mod.Name + "-prof", assemblies.ToList()));
            }
            else
            {
                Error($"Failed to patch {name} - There are no assemblies");
            }
        }
Пример #2
0
        private static void PatchInternalMethodFull(MethodInfo method, Category category)
        {
            try
            {
                var guiEntry = method.DeclaringType + ":" + method.Name + "-int";
                GUIController.AddEntry(guiEntry, category);
                GUIController.SwapToEntry(guiEntry);

                InternalMethodUtility.PatchedInternals.Add(method);

                Task.Factory.StartNew(() =>
                {
                    try
                    {
                        Modbase.Harmony.Patch(method, transpiler: InternalMethodUtility.InternalProfiler);
                    }
                    catch (Exception e)
                    {
                        Error($"Failed to internal patch method {method.DeclaringType.FullName}:{method.Name}, failed with the exep " + e.Message);
                    }
                });
            }
            catch (Exception e)
            {
                Error("Failed to patch internal methods, failed with the error " + e.Message);
                InternalMethodUtility.PatchedInternals.Remove(method);
            }
        }
        private static void PatchInternalMethodFull(MethodInfo method, Category category)
        {
            try
            {
                bool Valid()
                {
                    var bytes = method.GetMethodBody()?.GetILAsByteArray();

                    if (bytes == null)
                    {
                        return(false);
                    }
                    if (bytes.Length == 0)
                    {
                        return(false);
                    }
                    if (bytes.Length == 1 && bytes.First() == 0x2A)
                    {
                        return(false);
                    }
                    return(true);
                }

                if (Valid() == false)
                {
                    Error("Can not patch this method, this is likely a method which is virtually dispatched or marked as external, and thus can not be generically examined.");
                    return;
                }

                var guiEntry = method.DeclaringType + ":" + method.Name + "-int";
                GUIController.AddEntry(guiEntry, category);
                GUIController.SwapToEntry(guiEntry);

                InternalMethodUtility.PatchedInternals.Add(method);

                Task.Factory.StartNew(() =>
                {
                    try
                    {
                        Modbase.Harmony.Patch(method, transpiler: InternalMethodUtility.InternalProfiler);
                    }
                    catch (Exception e)
                    {
                        ReportException(e, $"Failed to patch the internal methods within {Utility.GetSignature(method, false)}");
                    }
                });
            }
            catch (Exception e)
            {
                ReportException(e, "Failed to set up state to patch internal methods");
                InternalMethodUtility.PatchedInternals.Remove(method);
            }
        }
Пример #4
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");
            }
        }
Пример #5
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}");
            }
        }
Пример #6
0
        private static void DrawEntry(ref Rect row, KeyValuePair <Entry, Type> entry)
        {
            row = listing.GetRect(30f);
            Widgets.DrawHighlightIfMouseover(row);

            if (GUIController.CurrentEntry == entry.Key)
            {
                Widgets.DrawOptionSelected(row);
            }

            row.x   += 20f;
            yOffset += 30f;

            Widgets.Label(row, entry.Key.name);

            if (Widgets.ButtonInvisible(row))
            {
                GUIController.SwapToEntry(entry.Key.name);
            }

            if (entry.Key.isClosable)
            {
                if (Input.GetMouseButtonDown(1) && row.Contains(Event.current.mousePosition))
                {
                    List <FloatMenuOption> options = new List <FloatMenuOption>()
                    {
                        new FloatMenuOption("Close", () => GUIController.RemoveEntry(entry.Key.name))
                    };
                    Find.WindowStack.Add(new FloatMenu(options));
                }
            }

            TooltipHandler.TipRegion(row, entry.Key.tip);

            if (GUIController.CurrentEntry == entry.Key)
            {
                bool firstEntry = true;
                foreach (KeyValuePair <FieldInfo, Setting> keySetting in entry.Key.Settings)
                {
                    if (keySetting.Key.FieldType == typeof(bool))
                    {
                        row       = listing.GetRect(30f);
                        row.x    += 20f;
                        GUI.color = Widgets.OptionSelectedBGBorderColor;
                        Widgets.DrawLineVertical(row.x, row.y, 15f);

                        if (!firstEntry)
                        {
                            Widgets.DrawLineVertical(row.x, row.y - 15f, 15f);
                        }

                        row.x += 10f;
                        Widgets.DrawLineHorizontal(row.x - 10f, row.y + 15f, 10f);
                        GUI.color = Color.white;
                        yOffset  += 30f;

                        bool cur = (bool)keySetting.Key.GetValue(null);

                        if (DubGUI.Checkbox(row, keySetting.Value.name, ref cur))
                        {
                            keySetting.Key.SetValue(null, cur);

                            GUIController.ResetProfilers();
                        }
                    }

                    if (keySetting.Value.tip != null)
                    {
                        TooltipHandler.TipRegion(row, keySetting.Value.tip);
                    }

                    firstEntry = false;
                }
            }
        }