예제 #1
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);
            }
        }
예제 #2
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");
            }
        }
예제 #3
0
        public static void Draw(Rect rect)
        {
            var row = rect.LeftPartPixels(25f);

            if (Widgets.ButtonImage(row, TexButton.SpeedButtonTextures[Analyzer.CurrentlyPaused ? 1 : 0]))
            {
                Analyzer.CurrentlyPaused = !Analyzer.CurrentlyPaused;
                GUIController.CurrentEntry.SetActive(!Analyzer.CurrentlyPaused);
            }

            TooltipHandler.TipRegion(row, Strings.top_pause_analyzer);
            rect.AdjustHorizonallyBy(25f);

            row = rect.LeftPartPixels(25);
            if (Widgets.ButtonImage(row, Textures.refresh))
            {
                GUIController.ResetProfilers();
            }

            TooltipHandler.TipRegion(row, Strings.top_refresh);

            var searchbox = rect.LeftPartPixels(rect.width - 300f);

            searchbox.x += 25f;

            DubGUI.InputField(searchbox, Strings.top_search, ref TimesFilter, DubGUI.MintSearch);

            rect.AdjustHorizonallyBy(rect.width - 250f);

            Text.Anchor = TextAnchor.UpperLeft;
            Text.Font   = GameFont.Tiny;

            var cat = GUIController.CurrentCategory == Category.Tick ? "tick" : "update";
            var str = $"{ProfileController.updateAverage:F3}ms/{cat}";

            var strLen = str.GetWidthCached();

            var periodLen = rect.LeftPartPixels(130);

            rect.AdjustHorizonallyBy(130);

            Widgets.Label(periodLen, str);


            var tpsFpsRect = rect;

            tpsFpsRect.width = 50f;
            Widgets.Label(tpsFpsRect, $"FPS: {GUIElement_TPS.FPS}");
            TooltipHandler.TipRegion(tpsFpsRect, Strings.top_fps_tip);
            tpsFpsRect.x     = tpsFpsRect.xMax + 5;
            tpsFpsRect.width = 90f;
            Widgets.Label(tpsFpsRect, $"TPS: {GUIElement_TPS.TPS}({GUIElement_TPS.TPSTarget})");
            TooltipHandler.TipRegion(tpsFpsRect, Strings.top_tps_tip);
            tpsFpsRect.x     = tpsFpsRect.xMax + 5;
            tpsFpsRect.width = 30f;
            Text.Font        = GameFont.Medium;
        }
        public static void Draw(Rect rect)
        {
            var row = rect.LeftPartPixels(25f);

            if (Widgets.ButtonImage(row, TexButton.SpeedButtonTextures[Analyzer.CurrentlyPaused ? 1 : 0]))
            {
                Analyzer.CurrentlyPaused = !Analyzer.CurrentlyPaused;
                GUIController.CurrentEntry.SetActive(!Analyzer.CurrentlyPaused);
            }

            TooltipHandler.TipRegion(row, Strings.top_pause_analyzer);
            rect.AdjustHorizonallyBy(25f);

            row = rect.LeftPartPixels(25);
            if (Widgets.ButtonImage(row, Textures.refresh))
            {
                GUIController.ResetProfilers();
            }

            TooltipHandler.TipRegion(row, Strings.top_refresh);

            var searchbox = rect.LeftPartPixels(rect.width - 220f);

            searchbox.x += 25f;

            DubGUI.InputField(searchbox, Strings.top_search, ref TimesFilter, DubGUI.MintSearch);
            //    searchbox.x = searchbox.xMax;
            //    searchbox.width = 150;
            //   GUI.color = Color.grey;
            //   Widgets.Label(searchbox, MatchType);
            //   GUI.color = Color.white;


            // bit shitty and distracting, replace with a mini graph and or an entire page dedicated to garbage if it even matters realistically now which it probably doesn't so why bother aye just keep it clean
            //row.x = searchbox.xMax + 5;
            // row.width = 130f;
            //Text.Anchor = TextAnchor.MiddleCenter;
            //Widgets.FillableBar(row, Mathf.Clamp01(Mathf.InverseLerp(H_RootUpdate.LastMinGC, H_RootUpdate.LastMaxGC, H_RootUpdate.totalBytesOfMemoryUsed)), Textures.darkgrey);
            //Widgets.Label(row, H_RootUpdate.GarbageCollectionInfo);
            //TooltipHandler.TipRegion(row, Strings.top_gc_tip);

            Text.Anchor = TextAnchor.UpperLeft;
            Text.Font   = GameFont.Tiny;

            row.width = 50f;
            row.x     = searchbox.xMax + 10;
            Widgets.Label(row, $"FPS: {GUIElement_TPS.FPS}");
            TooltipHandler.TipRegion(row, Strings.top_fps_tip);
            row.x     = row.xMax + 5;
            row.width = 90f;
            Widgets.Label(row, $"TPS: {GUIElement_TPS.TPS}({GUIElement_TPS.TPSTarget})");
            TooltipHandler.TipRegion(row, Strings.top_tps_tip);
            row.x     = row.xMax + 5;
            row.width = 30f;
            Text.Font = GameFont.Medium;
        }
        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);
            }
        }
예제 #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");
            }
        }
예제 #7
0
        public static void Draw(Rect rect)
        {
            Rect row = rect.LeftPartPixels(25f);

            if (Widgets.ButtonImage(row, TexButton.SpeedButtonTextures[Analyzer.CurrentlyPaused ? 1 : 0]))
            {
                Analyzer.CurrentlyPaused = !Analyzer.CurrentlyPaused;
                GUIController.CurrentEntry.SetActive(!Analyzer.CurrentlyPaused);
            }

            TooltipHandler.TipRegion(row, ResourceCache.Strings.top_pause_analyzer);
            rect.AdjustHorizonallyBy(25f);

            row = rect.LeftPartPixels(25);
            if (Widgets.ButtonImage(row, ResourceCache.GUI.refresh))
            {
                GUIController.ResetProfilers();
            }

            TooltipHandler.TipRegion(row, ResourceCache.Strings.top_refresh);

            Rect searchbox = rect.LeftPartPixels(rect.width - 350f);

            searchbox.x += 25f;
            DubGUI.InputField(searchbox, ResourceCache.Strings.top_search, ref TimesFilter, DubGUI.MintSearch);
            row.x       = searchbox.xMax + 5;
            row.width   = 130f;
            Text.Anchor = TextAnchor.MiddleCenter;
            Text.Font   = GameFont.Tiny;
            Widgets.FillableBar(row, Mathf.Clamp01(Mathf.InverseLerp(H_RootUpdate.LastMinGC, H_RootUpdate.LastMaxGC, H_RootUpdate.totalBytesOfMemoryUsed)), ResourceCache.GUI.darkgrey);
            Widgets.Label(row, H_RootUpdate.GarbageCollectionInfo);
            Text.Anchor = TextAnchor.UpperLeft;
            TooltipHandler.TipRegion(row, ResourceCache.Strings.top_gc_tip);

            row.x     = row.xMax + 5;
            row.width = 50f;
            Widgets.Label(row, "FPS: " + GUIElement_TPS.FPS.ToString());
            TooltipHandler.TipRegion(row, ResourceCache.Strings.top_fps_tip);
            row.x     = row.xMax + 5;
            row.width = 90f;
            Widgets.Label(row, "TPS: " + GUIElement_TPS.TPS.ToString() + "(" + GUIElement_TPS.TPSTarget.ToString() + ")");
            TooltipHandler.TipRegion(row, ResourceCache.Strings.top_tps_tip);
            row.x     = row.xMax + 5;
            row.width = 30f;
            Text.Font = GameFont.Medium;
        }
예제 #8
0
        // Iterates through each child element in the document and attempts to extract method(s) from the strings inside the children
        private static void Parse(XmlDocument doc)
        {
            foreach (XmlNode node in doc.DocumentElement.ChildNodes) // entries should be
            {
                var meths = new HashSet <MethodInfo>();
                foreach (XmlNode child in node.ChildNodes)
                {
                    switch (child.Name.ToLower())
                    {
                    case "methods":
                    case "method":
                        foreach (XmlNode method in child.ChildNodes)
                        {
                            meths.Add(ParseMethod(method.InnerText));
                        }
                        break;

                    case "types":
                    case "type":
                        foreach (XmlNode type in child.ChildNodes)
                        {
                            meths.AddRange(ParseTypeMethods(type.InnerText));
                        }
                        break;

                    case "nestedtype":
                    case "nestedtypes":
                        foreach (XmlNode type in child.ChildNodes)
                        {
                            meths.AddRange(ParseSubTypeTypeMethods(type.InnerText));
                        }
                        break;

                    default:
                        ThreadSafeLogger.Error($"[Analyzer] Attempting to read unknown value from an Analyzer.xml, the given input was {child.Name}, it should have been either '(M/m)ethods', '(T/t)ypes' '(N/n)estedTypes");
                        break;
                    }
                }

                Type myType = DynamicTypeBuilder.CreateType(node.Name, meths);

                GUIController.Tab(Category.Modder).entries.Add(Entry.Create(myType.Name, Category.Modder, myType, false, true), myType);
            }
        }
예제 #9
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}");
            }
        }
예제 #10
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;
                }
            }
        }