示例#1
0
        public static void Apply(Harmony harmony, ManualLogSource logger)
        {
            const string originalMethodName = nameof(PlanetFactory.DestructFinally);
            const string outputMethodName   = nameof(PlanetFactoryExtensions.DestructObject);

            Logger = logger;

            harmony.PatchAll(typeof(DestructFinallyPatch));

            harmony.CreateReversePatcher(
                typeof(PlanetFactory).GetMethod(originalMethodName),
                new HarmonyMethod(typeof(PlanetFactoryExtensions).GetMethod(outputMethodName))
                ).Patch();

            Logger.LogDebug($"Applied patch class {typeof(DestructFinallyPatch).FullName}.");
        }
        public static ReversePatcher?TryCreateReversePatcher(this Harmony harmony, MethodBase?original, MethodInfo?standin)
        {
            if (original is null || standin is null)
            {
                Trace.TraceError($"HarmonyExtensions.TryCreateReversePatcher: 'original' or 'standin' is null");
                return(null);
            }

            try
            {
                return(harmony.CreateReversePatcher(original, new HarmonyMethod(standin)));
            }
            catch (Exception e)
            {
                Trace.TraceError($"HarmonyExtensions.TryCreateReversePatcher: Exception occurred: {e}, original '{original}'");
                return(null);
            }
        }
        public void Test_ReverseTranspilerPatching()
        {
            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 = instance.CreateProcessor(originalMethod);

            _ = patcher.AddPostfix(new HarmonyMethod(postfix));
            _ = patcher.Patch();

            var standin = new HarmonyMethod(patchClass.GetMethod("StringOperation"));

            Assert.IsNotNull(standin);
            Assert.IsNotNull(standin.method);

            var reversePatcher = instance.CreateReversePatcher(originalMethod, standin);

            _ = reversePatcher.Patch();

            var result2 = class0.Method("al-gin-Ori", 456);

            Assert.AreEqual("EpilogOriginal", result2);
        }
        static OptionsVMMixin()
        {
            var harmony = new Harmony("bannerlord.mcm.ui.optionsvm");

            if (AccessTools2.Property(typeof(OptionsVM), "VideoOptions")?.GetMethod is { } m1)
            {
                harmony.Patch(m1, postfix: new HarmonyMethod(AccessTools2.Method(typeof(OptionsVMMixin), nameof(OptionsPostfix)), 300));
            }
            if (AccessTools2.Property(typeof(OptionsVM), "AudioOptions")?.GetMethod is { } m2)
            {
                harmony.Patch(m2, postfix: new HarmonyMethod(AccessTools2.Method(typeof(OptionsVMMixin), nameof(OptionsPostfix)), 300));
            }
            if (AccessTools2.Property(typeof(OptionsVM), "GameKeyOptionGroups")?.GetMethod is { } m3)
            {
                harmony.Patch(m3, postfix: new HarmonyMethod(AccessTools2.Method(typeof(OptionsVMMixin), nameof(OptionsPostfix)), 300));
            }
            if (AccessTools2.Property(typeof(OptionsVM), "GamepadOptions")?.GetMethod is { } m4)
            {
                harmony.Patch(m4, postfix: new HarmonyMethod(AccessTools2.Method(typeof(OptionsVMMixin), nameof(OptionsPostfix)), 300));
            }
            if (AccessTools2.Property(typeof(OptionsVM), "GameplayOptions")?.GetMethod is { } m5)
            {
                harmony.Patch(m5, postfix: new HarmonyMethod(AccessTools2.Method(typeof(OptionsVMMixin), nameof(OptionsPostfix)), 300));
            }
            if (AccessTools2.Property(typeof(OptionsVM), "PerformanceOptions")?.GetMethod is { } m6)
            {
                harmony.Patch(m6, postfix: new HarmonyMethod(AccessTools2.Method(typeof(OptionsVMMixin), nameof(OptionsPostfix)), 300));
            }
            if (AccessTools2.Property(typeof(OptionsVM), "GraphicsOptions")?.GetMethod is { } m7)
            {
                harmony.Patch(m7, postfix: new HarmonyMethod(AccessTools2.Method(typeof(OptionsVMMixin), nameof(OptionsPostfix)), 300));
            }

            harmony.CreateReversePatcher(
                AccessTools2.Method(typeof(OptionsVM), nameof(OptionsVM.ExecuteCloseOptions)),
                new HarmonyMethod(SymbolExtensions2.GetMethodInfo(() => OriginalExecuteCloseOptions(null !)))).Patch();

            harmony.Patch(
                AccessTools2.Method(typeof(OptionsVM), nameof(OptionsVM.ExecuteCloseOptions)),
                postfix: new HarmonyMethod(AccessTools2.Method(typeof(OptionsVMMixin), nameof(ExecuteCloseOptionsPostfix)), 300));
        }
        public void Test_ILManipulatorReversePatch()
        {
            var class2 = new Class2Reverse();

            Assert.AreEqual("some string", class2.SomeMethod());

            var original = AccessTools.Method(typeof(Class2Reverse), nameof(Class2Reverse.SomeMethod));

            Assert.NotNull(original);

            var stub = AccessTools.Method(typeof(Class2ReversePatch), nameof(Class2ReversePatch.SomeMethodReverse));

            Assert.NotNull(stub);

            var instance       = new Harmony("test-ilmanipulator-reverse");
            var reversePatcher = instance.CreateReversePatcher(original, new HarmonyMethod(stub));

            _ = reversePatcher.Patch();

            Assert.AreEqual("some other string", Class2ReversePatch.SomeMethodReverse());
        }
示例#6
0
        //public static Type EdgeTypeSpec() => EdgeType<Type, Type>().MakeGenericType(new Type[] { NodeType(), NodeType() });
        #endregion

        #region "patchworks"
        public static void Execute(Harmony instance, string modName, bool altRPal = false)
        {
            //Harmony.DEBUG = true;
            ModName = modName;
            AltRPal = altRPal;

            //ResearchProjectDef_Extensions
            instance.CreateReversePatcher(AccessTools.Method(modName + ".ResearchProjectDef_Extensions:GetUnlockDefsAndDescs"),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(GetUnlockDefsAndDescs)))).Patch();
            instance.CreateReversePatcher(AccessTools.Method(modName + ".ResearchProjectDef_Extensions:GetRecipesUnlocked"),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(GetRecipesUnlocked)))).Patch();
            instance.CreateReversePatcher(AccessTools.Method(modName + ".ResearchProjectDef_Extensions:GetThingsUnlocked"),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(GetThingsUnlocked)))).Patch();
            instance.CreateReversePatcher(AccessTools.Method(modName + ".ResearchProjectDef_Extensions:GetPlantsUnlocked"),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(GetPlantsUnlocked)))).Patch();
            instance.CreateReversePatcher(AccessTools.Method(modName + ".ResearchProjectDef_Extensions:Ancestors"),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(Ancestors)))).Patch();
            if (altRPal)
            {
                ResearchNodeInfo = AccessTools.Method(modName + ".ResearchProjectDef_Extensions:ResearchNode");
            }

            //Node
            IsVisibleInfo     = AccessTools.Method(NodeType(), "IsVisible");
            RectInfo          = AccessTools.Property(NodeType(), "Rect");
            RightInfo         = AccessTools.Property(NodeType(), "Right");
            _rightInfo        = AccessTools.Field(NodeType(), "_right");
            largeLabelInfo    = AccessTools.Field(NodeType(), "_largeLabel");
            LabelRectInfo     = AccessTools.Property(NodeType(), "LabelRect");
            CostLabelRectInfo = AccessTools.Property(NodeType(), "CostLabelRect");
            CostIconRectInfo  = AccessTools.Property(NodeType(), "CostIconRect");
            IconsRectInfo     = AccessTools.Property(NodeType(), "IconsRect");
            if (altRPal)
            {
                instance.CreateReversePatcher(AccessTools.Method(modName + ".Node:Highlighted"),
                                              new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(Highlighted)))).Patch();
                InEdgeColorInfo = AccessTools.Method(modName + ".Node:InEdgeColor");
            }
            else
            {
                EdgeColorInfo   = AccessTools.Property(NodeType(), "EdgeColor");
                HighlightedInfo = AccessTools.Property(NodeType(), "Highlighted");
            }
            instance.Patch(AccessTools.Method(NodeType(), "SetRects", new Type[] { typeof(Vector2) }),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(Node_SetRects_Prefix))),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(Node_SetRects_Postfix))));

            //ResearchNode
            if (altRPal)
            {
                instance.Patch(AccessTools.Method(ResearchNodeType(), "HandleDragging", new Type[] { typeof(bool) }),
                               new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(HandleDragging_Prefix))));
                instance.Patch(AccessTools.Method(ResearchNodeType(), "LeftClick"),
                               new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(LeftClick_Prefix))));
                HighlightInfo       = AccessTools.Method(ResearchNodeType(), "Highlight");
                BuildingPresentInfo = AccessTools.Method(ResearchNodeType(), "BuildingPresent", new Type[] { ResearchNodeType() });
                isMatchedInfo       = AccessTools.Field(ResearchNodeType(), "isMatched");
            }
            else
            {
                instance.CreateReversePatcher(AccessTools.Method(ResearchNodeType(), "BuildingPresent", new Type[] { typeof(ResearchProjectDef) }),
                                              new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(BuildingPresent)))).Patch();
                instance.Patch(AccessTools.Method(ResearchNodeType(), "Draw"),
                               new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(ResearchNode_Draw_Prefix))));
                instance.Patch(AccessTools.PropertyGetter(ResearchNodeType(), "EdgeColor"),
                               new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(EdgeColor_Prefix))));
                GetMissingRequiredRecursiveInfo = AccessTools.Method(ResearchNodeType(), "GetMissingRequiredRecursive");
                AvailableInfo = AccessTools.Property(ResearchNodeType(), "Available");
            }
            instance.CreateReversePatcher(AccessTools.Method(ResearchNodeType(), "TechprintAvailable", new Type[] { typeof(ResearchProjectDef) }),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(TechprintAvailable)))).Patch();
            instance.CreateReversePatcher(AccessTools.Method(ResearchNodeType(), "MissingFacilities", new Type[] { typeof(ResearchProjectDef) }),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(MissingFacilities)))).Patch();
            instance.Patch(AccessTools.PropertyGetter(ResearchNodeType(), "Color"),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(Color_Prefix))));
            instance.Patch(AccessTools.Constructor(ResearchNodeType(), new Type[] { typeof(ResearchProjectDef) }),
                           null, new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(ResearchNode_Postfix))));
            instance.Patch(AccessTools.Method(ResearchNodeType(), "GetResearchTooltipString"),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(GetResearchTooltipString_Prefix))));
            ChildrenInfo = AccessTools.Property(ResearchNodeType(), "Children");
            ColorInfo    = AccessTools.Property(ResearchNodeType(), "Color");
            ResearchInfo = AccessTools.Field(ResearchNodeType(), "Research");
            GetResearchTooltipStringInfo = AccessTools.Method(ResearchNodeType(), "GetResearchTooltipString");

            //Def_Extensions
            instance.CreateReversePatcher(AccessTools.Method(modName + ".Def_Extensions:DrawColouredIcon"),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(DrawColouredIcon)))).Patch();

            //Edge
            instance.Patch(AccessTools.Method(EdgeType <Type, Type>(), "Draw"), null,
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(Edge_Draw_Postfix))));
            InInfo  = AccessTools.Property(EdgeType <Type, Type>(), "In");
            OutInfo = AccessTools.Property(EdgeType <Type, Type>(), "Out");
            if (altRPal)
            {
                InResearchInfo = AccessTools.Method(EdgeType <Type, Type>(), "InResearch");
            }

            //MainTabWindow_ResearchTree
            if (AltRPal)
            {
                searchActiveInfo = AccessTools.Field(MainTabType(), "_searchActive");
            }
            else
            {
                ZoomLevelInfo = AccessTools.Property(MainTabType(), "ZoomLevel");

                //fix for tree overlapping search bar on higher UI scales
                instance.Patch(AccessTools.Method(MainTabType(), "SetRects"),
                               null, new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(MainTabWindow_SetRects_Postfix))));
            };
            if (modName != "ResearchPal")
            {
                instance.Patch(AccessTools.Method(MainTabType(), "Notify_TreeInitialized"),
                               null, new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(TreeInitialized_Postfix))));
            }
            instance.Patch(AccessTools.Method(MainTabType(), "DoWindowContents"),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(DoWindowContents_Postfix))));
            instance.Patch(AccessTools.Method(typeof(Window), "PostClose"),
                           null, new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(Close_Postfix))));
            instance.Patch(AccessTools.PropertyGetter(MainTabType(), "TreeRect"),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(TreeRect_Prefix))));

            InstanceInfo = AccessTools.Property(MainTabType(), "Instance");
            Type windowNodeType = AltRPal ? ResearchNodeType() : NodeType();

            MainTabCenterOnInfo = AccessTools.Method(MainTabType(), "CenterOn", new Type[] { windowNodeType });

            //Tree
            instance.Patch(AccessTools.Method(TreeType(), "PopulateNodes"),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(PopulateNodes_Prefix))),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(PopulateNodes_Postfix))));
            if (modName == "ResearchPal")
            {
                string initializer = AltRPal ? "InitializeLayout" : "Initialize";
                instance.Patch(AccessTools.Method(TreeType(), initializer),
                               null, new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(TreeInitialized_Postfix))));
                if (AltRPal)
                {
                    HandleFixedHighlightInfo = AccessTools.Method(TreeType(), "HandleFixedHighlight");
                    StopFixedHighlightsInfo  = AccessTools.Method(TreeType(), "StopFixedHighlights");
                }
            }
            NodesInfo = AccessTools.Property(TreeType(), "Nodes");

            //Queue
            if (altRPal)
            {
                instance.Patch(AccessTools.Method(QueueType(), "DrawS"),
                               new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(QueueDraw_Prefix))));
            }
            else
            {
                instance.Patch(AccessTools.Method(QueueType(), "DrawQueue"),
                               new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(DrawQueue_Prefix))));
            }

            //Constants
            EpsilonInfo = AccessTools.Field(ConstantsType(), "Epsilon");
            DetailedModeZoomLevelCutoffInfo = AccessTools.Field(ConstantsType(), "DetailedModeZoomLevelCutoff");
            MarginInfo         = AccessTools.Field(ConstantsType(), "Margin");
            QueueLabelSizeInfo = AccessTools.Field(ConstantsType(), "QueueLabelSize");
            IconSizeInfo       = AccessTools.Field(ConstantsType(), "IconSize");
            NodeMarginsInfo    = AccessTools.Field(ConstantsType(), "NodeMargins");
            NodeSizeInfo       = AccessTools.Field(ConstantsType(), "NodeSize");
            TopBarHeightInfo   = AccessTools.Field(ConstantsType(), "TopBarHeight");
            if (altRPal)
            {
                TopBarHeightInfo.SetValue(instance, NodeSize.y * 0.6f + 2 * Margin);
            }

            //Assets
            if (altRPal)
            {
                NormalHighlightColorInfo = AccessTools.Field(AssetsType(), "NormalHighlightColor"); //default blue
                HoverPrimaryColorInfo    = AccessTools.Field(AssetsType(), "HoverPrimaryColor");    //violet
                FixedPrimaryColorInfo    = AccessTools.Field(AssetsType(), "FixedPrimaryColor");    //cyan
                NormalHighlightColorInfo.SetValue(instance, ShadedColor);                           //mustard
                HoverPrimaryColorInfo.SetValue(instance, BrightColor);                              //yellow
                FixedPrimaryColorInfo.SetValue(instance, VariantColor);                             //light orange
            }

            //Harmony.DEBUG = false;
        }
示例#7
0
        public static void Execute(Harmony instance, string modName)
        {
            ModName = modName;

            //ResearchProjectDef_Extensions
            instance.CreateReversePatcher(AccessTools.Method(modName + ".ResearchProjectDef_Extensions:GetUnlockDefsAndDescs"),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(GetUnlockDefsAndDescs)))).Patch();
            instance.CreateReversePatcher(AccessTools.Method(modName + ".ResearchProjectDef_Extensions:GetRecipesUnlocked"),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(GetRecipesUnlocked)))).Patch();
            instance.CreateReversePatcher(AccessTools.Method(modName + ".ResearchProjectDef_Extensions:GetThingsUnlocked"),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(GetThingsUnlocked)))).Patch();
            instance.CreateReversePatcher(AccessTools.Method(modName + ".ResearchProjectDef_Extensions:GetPlantsUnlocked"),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(GetPlantsUnlocked)))).Patch();
            instance.CreateReversePatcher(AccessTools.Method(modName + ".ResearchProjectDef_Extensions:Ancestors"),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(Ancestors)))).Patch();

            //Node
            IsVisibleInfo     = AccessTools.Method(NodeType(), "IsVisible");
            HighlightedInfo   = AccessTools.Property(NodeType(), "Highlighted");
            RectInfo          = AccessTools.Property(NodeType(), "Rect");
            largeLabelInfo    = AccessTools.Field(NodeType(), "_largeLabel");
            LabelRectInfo     = AccessTools.Property(NodeType(), "LabelRect");
            CostLabelRectInfo = AccessTools.Property(NodeType(), "CostLabelRect");
            CostIconRectInfo  = AccessTools.Property(NodeType(), "CostIconRect");
            IconsRectInfo     = AccessTools.Property(NodeType(), "IconsRect");

            //ResearchNode
            instance.CreateReversePatcher(AccessTools.Method(ResearchNodeType(), "BuildingPresent", new Type[] { typeof(ResearchProjectDef) }),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(BuildingPresent)))).Patch();
            instance.CreateReversePatcher(AccessTools.Method(ResearchNodeType(), "TechprintAvailable", new Type[] { typeof(ResearchProjectDef) }),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(TechprintAvailable)))).Patch();
            instance.CreateReversePatcher(AccessTools.Method(ResearchNodeType(), "MissingFacilities", new Type[] { typeof(ResearchProjectDef) }),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(MissingFacilities)))).Patch();
            instance.Patch(AccessTools.Method(ResearchNodeType(), "Draw"),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(Draw_Prefix))));
            instance.Patch(AccessTools.PropertyGetter(ResearchNodeType(), "Color"),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(Color_Prefix))));
            instance.Patch(AccessTools.PropertyGetter(ResearchNodeType(), "EdgeColor"),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(EdgeColor_Prefix))));
            instance.Patch(AccessTools.Constructor(ResearchNodeType(), new Type[] { typeof(ResearchProjectDef) }),
                           null, new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(ResearchNode_Postfix))));
            instance.Patch(AccessTools.Method(ResearchNodeType(), "GetResearchTooltipString"),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(GetResearchTooltipString_Prefix))));

            GetMissingRequiredRecursiveInfo = AccessTools.Method(ResearchNodeType(), "GetMissingRequiredRecursive");
            ChildrenInfo  = AccessTools.Property(ResearchNodeType(), "Children");
            ColorInfo     = AccessTools.Property(ResearchNodeType(), "Color");
            AvailableInfo = AccessTools.Property(ResearchNodeType(), "Available");
            CompletedInfo = AccessTools.Property(ResearchNodeType(), "Completed");
            ResearchInfo  = AccessTools.Field(ResearchNodeType(), "Research");
            GetResearchTooltipStringInfo = AccessTools.Method(ResearchNodeType(), "GetResearchTooltipString");

            //Def_Extensions
            instance.CreateReversePatcher(AccessTools.Method(modName + ".Def_Extensions:DrawColouredIcon"),
                                          new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(DrawColouredIcon)))).Patch();
            //fix for tree overlapping search bar on higher UI scales
            instance.Patch(AccessTools.Method(MainTabType(), "SetRects"),
                           null, new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(Set_Rects_Postfix))));

            InstanceInfo  = AccessTools.Property(MainTabType(), "Instance");
            ZoomLevelInfo = AccessTools.Property(MainTabType(), "ZoomLevel");

            //MainTabWindow_ResearchTree
            instance.Patch(AccessTools.Method(MainTabType(), "DoWindowContents"),
                           null, new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(DoWindowContents_Postfix))));
            if (modName != "ResearchPal")
            {
                instance.Patch(AccessTools.Method(MainTabType(), "Notify_TreeInitialized"),
                               null, new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(TreeInitialized_Postfix))));
            }
            instance.Patch(AccessTools.Method(typeof(Window), "PostClose"),
                           null, new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(Close_Postfix))));


            //Tree
            instance.Patch(AccessTools.Method(TreeType(), "PopulateNodes"),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(PopulateNodes_Prefix))),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(PopulateNodes_Postfix))));
            if (modName == "ResearchPal")
            {
                instance.Patch(AccessTools.Method(TreeType(), "Initialize"),
                               null, new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(TreeInitialized_Postfix))));
            }
            NodesInfo = AccessTools.Property(TreeType(), "Nodes");

            //Queue
            instance.Patch(AccessTools.Method(QueueType(), "DrawQueue"),
                           new HarmonyMethod(AccessTools.Method(typeof(ResearchTree_Patches), nameof(DrawQueue_Prefix))));

            //Constants
            EpsilonInfo = AccessTools.Field(ConstantsType(), "Epsilon");
            DetailedModeZoomLevelCutoffInfo = AccessTools.Field(ConstantsType(), "DetailedModeZoomLevelCutoff");
            MarginInfo         = AccessTools.Field(ConstantsType(), "Margin");
            QueueLabelSizeInfo = AccessTools.Field(ConstantsType(), "QueueLabelSize");
            IconSizeInfo       = AccessTools.Field(ConstantsType(), "IconSize");
            NodeMarginsInfo    = AccessTools.Field(ConstantsType(), "NodeMargins");
            NodeSizeInfo       = AccessTools.Field(ConstantsType(), "NodeSize");
            TopBarHeightInfo   = AccessTools.Field(ConstantsType(), "TopBarHeight");
        }
 public static void Execute(Harmony instance)
 {
     instance.CreateReversePatcher(AccessTools.Method("Hospitality.GuestUtility:IsGuest", new[] { typeof(Pawn), typeof(bool) }),
                                   new HarmonyMethod(AccessTools.Method(typeof(Hospitality_Patches), nameof(IsGuestExternal)))).Patch();
     active = true;
 }