public RimFridgeCompat(ModContentPack mod)
        {
            // Several Gizmos
            {
                Type type = AccessTools.TypeByName("RimFridge.CompRefrigerator");

                string[] methods =
                {
                    "<CompGetGizmosExtra>b__1",
                    "<CompGetGizmosExtra>b__2",
                    "<CompGetGizmosExtra>b__3",
                    "<CompGetGizmosExtra>b__4",
                    "<CompGetGizmosExtra>b__5"
                };

                foreach (string method in methods)
                {
                    MP.RegisterSyncDelegate(type, "<>c__DisplayClass10_0", method);
                }

                dialogType  = AccessTools.TypeByName("RimFridge.Dialog_RenameFridge");
                fridgeField = AccessTools.Field(dialogType, "fridge");

                MP.RegisterSyncWorker <Dialog_Rename>(SyncFridgeName, dialogType);
                MP.RegisterSyncMethod(dialogType, "SetName");
            }
        }
        public RunandGun(ModContentPack mod)
        {
            Type type = AccessTools.TypeByName("RunAndGun.Harmony.Pawn_DraftController_GetGizmos_Patch");

            MP.RegisterSyncDelegate(type, "<>c__DisplayClass0_0", "<Postfix>b__1");

            PatchingUtilities.PatchSystemRand("RunAndGun.Harmony.MentalStateHandler_TryStartMentalState:shouldRunAndGun", false);
        }
 static IEnumerable <ISyncDelegate> RegisterLambdaDelegate_Impl(Type parentType, string parentMethod, string[] fields, params int[] lambdaOrdinals)
 {
     foreach (int ord in lambdaOrdinals)
     {
         var method = MpMethodUtil.GetLambda(parentType, parentMethod, MethodType.Normal, null, ord);
         yield return(MP.RegisterSyncDelegate(parentType, method.DeclaringType.Name, method.Name, fields));
     }
 }
Example #4
0
 public ToggleRefuelable(ModContentPack mod)
 {
     MP.RegisterSyncDelegate(
         AccessTools.TypeByName("ToggleRefuelable.CompRefuelable_CompGetGizmosExtra_Patch"),
         "<>c__DisplayClass0_0",
         "<Postfix>b__1"
         );
 }
Example #5
0
        public MoreFactionInteraction(ModContentPack mod)
        {
            var type = AccessTools.TypeByName("Multiplayer.Client.Patches.CloseDialogsForExpiredLetters");
            // We should probably add this to the API the next time we update it
            var rejectMethods = (Dictionary <Type, MethodInfo>)AccessTools.Field(type, "rejectMethods").GetValue(null);

            type = AccessTools.TypeByName("MoreFactionInteraction.ChoiceLetter_ReverseTradeRequest");
            var methods = MpMethodUtil.GetLambda(type, "Choices", MethodType.Getter, null, 0, 3).ToArray();

            MP.RegisterSyncDelegate(type, methods[0].DeclaringType.Name, methods[0].Name);
            MP.RegisterSyncMethod(methods[1]);
            rejectMethods[type] = methods[1];

            var typeNames = new[]
            {
                "MoreFactionInteraction.ChoiceLetter_DiplomaticMarriage",
                "MoreFactionInteraction.ChoiceLetter_ExtortionDemand",
                "MoreFactionInteraction.ChoiceLetter_MysticalShaman",
            };

            foreach (var typeName in typeNames)
            {
                type    = AccessTools.TypeByName(typeName);
                methods = MpMethodUtil.GetLambda(type, "Choices", MethodType.Getter, null, 0, 1).ToArray();
                MP.RegisterSyncMethod(methods[0]);
                MP.RegisterSyncMethod(methods[1]);
                rejectMethods[type] = methods[1];
            }

            typeNames = new[]
            {
                "MoreFactionInteraction.FactionWarPeaceTalks",
                "MoreFactionInteraction.More_Flavour.AnnualExpo",
            };

            foreach (var typeName in typeNames)
            {
                type = AccessTools.TypeByName(typeName);
                MP.RegisterSyncDialogNodeTree(type, "Notify_CaravanArrived");
            }

            type = AccessTools.TypeByName("MoreFactionInteraction.IncidentWorker_MysticalShaman");
            MP.RegisterSyncDialogNodeTree(type, "TryExecuteWorker");

            typeNames = new[]
            {
                "MoreFactionInteraction.IncidentWorker_MysticalShaman",
                "MoreFactionInteraction.IncidentWorker_ReverseTradeRequest",
                "MoreFactionInteraction.IncidentWorker_RoadWorks",
            };

            foreach (var typeName in typeNames)
            {
                type = AccessTools.TypeByName(typeName);
                MP.RegisterSyncDialogNodeTree(type, "TryExecuteWorker");
            }
        }
        public ChoiceOfPsycastsCompat(ModContentPack mod)
        {
            var type = learnPsycastsType = AccessTools.TypeByName("RimWorld.ChoiceOfPsycasts.LearnPsycasts");

            MP.RegisterSyncDelegate(type, "<>c__DisplayClass3_0", "<Choice>b__0");

            levelField  = AccessTools.Field(type, "Level");
            parentField = AccessTools.Field(type, "Parent");
            MP.RegisterSyncWorker <Command_Action>(SyncLearnPsycasts, type);
        }
        public GiddyUpCoreCompat(ModContentPack mod)
        {
            Type type;

            // Gizmos
            {
                // Release Animals
                MP.RegisterSyncDelegate(
                    AccessTools.TypeByName("GiddyUpCore.Harmony.Pawn_PlayerSettings_GetGizmos"),
                    "<>c__DisplayClass1_0",
                    "<helpIterator>b__2"
                    );

                // Mount
                MP.RegisterSyncDelegate(
                    AccessTools.TypeByName("GiddyUpCore.Utilities.GUC_FloatMenuUtility"),
                    "<>c__DisplayClass0_0",
                    "<AddMountingOptions>b__0"
                    );

                // Dismount
                MP.RegisterSyncDelegate(
                    AccessTools.TypeByName("GiddyUpCore.Utilities.GUC_FloatMenuUtility"),
                    "<>c__DisplayClass0_0",
                    "<AddMountingOptions>b__1"
                    );
            }

            // Sync ExtendedPawnData
            {
                type = AccessTools.TypeByName("GiddyUpCore.Storage.ExtendedDataStorage");

                MpCompat.harmony.Patch(AccessTools.Constructor(type),
                                       postfix: new HarmonyMethod(typeof(GiddyUpCoreCompat), nameof(ExtendedDataStoragePostfix)));

                MpCompat.harmony.Patch(AccessTools.Method(type, "GetExtendedDataFor", new Type[] { typeof(Pawn) }),
                                       postfix: new HarmonyMethod(typeof(GiddyUpCoreCompat), nameof(GetExtendedDataForPostfix)));

                MpCompat.harmony.Patch(AccessTools.Method(type, "DeleteExtendedDataFor", new Type[] { typeof(Pawn) }),
                                       postfix: new HarmonyMethod(typeof(GiddyUpCoreCompat), nameof(DeleteExtendedDataForPostfix)));
            }
            {
                type = AccessTools.TypeByName("GiddyUpCore.Storage.ExtendedPawnData");

                MP.RegisterSyncWorker <object>(ExtendedPawnData, type);
            }

            // Remove Random
            {
                MpCompat.harmony.Patch(AccessTools.Method("GiddyUpCore.Utilities.NPCMountUtility:generateMounts"),
                                       prefix: new HarmonyMethod(typeof(GiddyUpCoreCompat), nameof(GenerateMountsPrefix)),
                                       postfix: new HarmonyMethod(typeof(GiddyUpCoreCompat), nameof(GenerateMountsPostfix)),
                                       transpiler: new HarmonyMethod(typeof(GiddyUpCoreCompat), nameof(GenerateMountsTranspiler)));
            }
        }
        // PowerLogic requires late loading as some of the Types have statics that are not ready early.
        void LateLoad()
        {
            Type type;

            type = AccessTools.TypeByName("PowerLogic.Building_BaseLogicGate");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__14_0");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__14_2");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__14_4");

            type = AccessTools.TypeByName("PowerLogic.Building_CurrentSensor");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__15_1");

            type = AccessTools.TypeByName("PowerLogic.Building_HeatSensor");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__30_0");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__30_1");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__30_2");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__30_3");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__30_4");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__30_6");

            type = AccessTools.TypeByName("PowerLogic.Building_LightSensor");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__30_0");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__30_1");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__30_3");

            type = AccessTools.TypeByName("PowerLogic.Building_StackSensor");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__19_0");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__19_1");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__19_2");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__19_3");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__19_4");
            MP.RegisterSyncMethod(type, "<GetGizmos>b__19_5");

            type = AccessTools.TypeByName("PowerLogic.CompIFF");
            MP.RegisterSyncMethod(type, "<CompGetGizmosExtra>b__5_1");
            MP.RegisterSyncMethod(type, "<CompGetGizmosExtra>b__5_3");

            type = AccessTools.TypeByName("PowerLogic.CompProxSensor");
            MP.RegisterSyncMethod(type, "<CompGetGizmosExtra>b__19_0");
            MP.RegisterSyncMethod(type, "<CompGetGizmosExtra>b__19_1");

            type = AccessTools.TypeByName("PowerLogic.CompTransceiver");
            MP.RegisterSyncMethod(type, "<CompGetGizmosExtra>b__46_0");
            MP.RegisterSyncMethod(type, "<CompGetGizmosExtra>b__46_1");
            MP.RegisterSyncMethod(type, "<CompGetGizmosExtra>b__46_2");
            MP.RegisterSyncMethod(type, "<CompGetGizmosExtra>b__46_3");

            type = AccessTools.TypeByName("PowerLogic.ITab_Entanglement");
            MP.RegisterSyncDelegate(type, "<>c__DisplayClass3_1", "<FillTab>b__2");

            // TODO: Need to transpile or pester modder to move his click actions into methods:
            // ITab_DoorMacro
            // ITab_ThingDirections
            // ITab_WifiPulser
        }
Example #9
0
        public VanillaFactionsSettlers(ModContentPack mod)
        {
            var type = AccessTools.TypeByName("VFE_Settlers.Utilities.UtilityEvent");

            // Protection fee event
            MP.RegisterSyncDialogNodeTree(type, "ProtectionFee");
            // Caravan gizmo - turn in wanted criminal to settlement
            MP.RegisterSyncDelegate(type, "<>c__DisplayClass8_0", "<CommandTurnInWanted>b__0");
            // Toggle mode
            MpCompat.RegisterSyncMethodByIndex(AccessTools.TypeByName("Warmup.CompWarmUpReduction"), "<CompGetGizmosExtra>", 1);
            // Five fingers fillet table
            PatchingUtilities.PatchUnityRand("VFE_Settlers.JobGivers.JobDriver_PlayFiveFingerFillet:WatchTickAction", false);
        }
        private static void LatePatch()
        {
            // BuildingAltar continuation
            {
                // TempleCardUtility is used for UI drawing, called from BuildingAltar
                var type = AccessTools.TypeByName("Corruption.Worship.TempleCardUtility");
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass4_1", "<OpenDedicationSelectMenu>b__1");
                // We patch the modded method to intercept some of their calls that will need syncing and call them through our methods,
                // as syncing the actual methods themselves will sync way too much (methods might/will be called often)
                MpCompat.harmony.Patch(AccessTools.Method(type, "DrawSermonTemplate"),
                                       prefix: new HarmonyMethod(typeof(CorruptionWorship), nameof(DrawSermonTemplatePrefix)),
                                       postfix: new HarmonyMethod(typeof(CorruptionWorship), nameof(DrawSermonTemplatePostfix)),
                                       transpiler: new HarmonyMethod(typeof(CorruptionWorship), nameof(PatchDrawSermonTemplate)));

                // The previous inner class (<>c__DisplayClass4_1) needs the following one to be synced too, but this one uses sermon
                // which requires a bit more data to sync, so we make SyncWorker manually instead of using RegisterSyncDelegate
                var inner = AccessTools.Inner(type, "<>c__DisplayClass4_0");
                templeCardUtilityInnerAltarField  = AccessTools.FieldRefAccess <Building>(inner, "altar");
                templeCardUtilityInnerSermonField = AccessTools.FieldRefAccess <object>(inner, "template");

                MP.RegisterSyncMethod(typeof(CorruptionWorship), nameof(SyncedInterceptedReceiveMemo));
                MP.RegisterSyncMethod(typeof(CorruptionWorship), nameof(SyncedInterceptedEndSermon));
                MP.RegisterSyncMethod(typeof(CorruptionWorship), nameof(SyncedTryStartSermon)).SetDebugOnly();
                MP.RegisterSyncMethod(typeof(CorruptionWorship), nameof(SyncSimpleSermonData));
            }

            // Dialog_ReligiousRiot, opened when there's enough pawns of different religion
            // Should open for all players, so we assume we can get it/sync it using Find.WindowStack
            {
                religiousRiotType = AccessTools.TypeByName("Corruption.Worship.Dialog_ReligiousRiot");
                MP.RegisterSyncMethod(religiousRiotType, "ChooseNewReligion");
                MP.RegisterSyncMethod(religiousRiotType, "PreserveReligion");
                MP.RegisterSyncWorker <Window>(SyncReligiousRiotDialog, religiousRiotType);
            }

            // Other stuff
            {
                // Rotating worship statue
                var type = AccessTools.TypeByName("Corruption.Worship.Building_WorshipStatue");
                MpCompat.RegisterLambdaMethod(type, "GetGizmos", 0);

                // Debug ring the bell
                type = AccessTools.TypeByName("Corruption.Worship.CompBellTower");
                MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 0).SetDebugOnly();

                // Drop effigy
                type = AccessTools.TypeByName("Corruption.Worship.CompShrine");
                MP.RegisterSyncMethod(type, "DropEffigy");
            }
        }
        public AvoidFriendlyFire(ModContentPack mod)
        {
            Type type;
            {
                type = extendedPawnDataType = AccessTools.TypeByName("AvoidFriendlyFire.ExtendedPawnData");
                MP.RegisterSyncWorker <object>(SyncWorkerFor, type);

                avoidFriendlyFireField = type.GetField("AvoidFriendlyFire");
            }
            {
                type = AccessTools.TypeByName("AvoidFriendlyFire.Pawn_DraftController_GetGizmos_Patch");
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass0_0", "<Postfix>b__1");
            }
        }
Example #12
0
        public SimpleSidearmsCompat(ModContentPack mod)
        {
            Type type;

            {
                type = AccessTools.TypeByName("SimpleSidearms.intercepts.FloatMenuMakerMap_AddHumanLikeOrders_Postfix");

                MP.RegisterSyncDelegate(type, "<>c__DisplayClass0_0", "<AddHumanlikeOrders>b__0");
            }
            {
                type = AccessTools.TypeByName("SimpleSidearms.utilities.WeaponAssingment");

                MP.RegisterSyncMethod(type, "SetPrimary");
                MP.RegisterSyncMethod(type, "weaponSwapSpecific");
                MP.RegisterSyncMethod(type, "dropSidearm");
                MP.RegisterSyncMethod(type, "forgetSidearmMemory");
            }
            {
                type = AccessTools.TypeByName("SimpleSidearms.rimworld.GoldfishModule");

                MP.RegisterSyncMethod(type, "SetPrimaryEmpty");
                MP.RegisterSyncMethod(type, "AddSidearm");
                MP.RegisterSyncMethod(type, "DropPrimary");
                MP.RegisterSyncMethod(type, "DropSidearm");
                MP.RegisterSyncWorker <object>(SyncWorkerForGoldfishModule, type);

                GoldfishModule_PawnProperty             = AccessTools.Property(type, "Owner");
                GoldfishModule_GetGoldfishForPawnMethod = AccessTools.Method(type, "GetGoldfishForPawn");
            }
            // All the following for that tiny lock?!
            // This is an exercise of futility testing the limits of the API
            // TODO: Pester modder to encapsulate autoLockOnManualSwap in a method
            LongEventHandler.ExecuteWhenFinished(delegate {
                type = AccessTools.TypeByName("SimpleSidearms.rimworld.SwapControlsHandler");

                MP.RegisterSyncWorker <object>(SyncWorkerForSwapControlsHandler, type);

                autoLockOnManualSwapSyncField = MP.RegisterSyncField(type, "autoLockOnManualSwap");

                SwapControlsHandler_PawnProperty            = AccessTools.Property(type, "Owner");
                SwapControlsHandler_GetHandlerForPawnMethod = AccessTools.Method(type, "GetHandlerForPawn");

                type = AccessTools.TypeByName("SimpleSidearms.rimworld.Gizmo_SidearmsList");

                MpCompat.harmony.Patch(AccessTools.Method(type, "DrawLocklock"),
                                       prefix: new HarmonyMethod(typeof(SimpleSidearmsCompat), nameof(DrawLockPrefix)),
                                       postfix: new HarmonyMethod(typeof(SimpleSidearmsCompat), nameof(DrawLockPostfix)));
            });
        }
Example #13
0
        public GiddyUpRideAndRollCompat(ModContentPack mod)
        {
            // Stop waiting
            MP.RegisterSyncDelegate(
                AccessTools.TypeByName("GiddyUpRideAndRoll.Harmony.Pawn_GetGizmos"),
                "<>c__DisplayClass1_0",
                "<CreateGizmo_LeaveRider>b__0"
                );

            // Unsure... May not be needed. Harmless to have it.
            MP.RegisterSyncMethod(
                AccessTools.Method("GiddyUpRideAndRoll.Harmony.CaravanEnterMapUtility_Enter:MountCaravanMounts")
                );

            // Pawn Column Workers
            {
                MP.RegisterSyncMethod(AccessTools.Method("GiddyUpRideAndRoll.PawnColumns.PawnColumnWorker_RR_Mountable_Anyone:SetValue"));
                MP.RegisterSyncMethod(AccessTools.Method("GiddyUpRideAndRoll.PawnColumns.PawnColumnWorker_RR_Mountable_Master:SetValue"));
            }

            // AreaGU Randomness
            {
                AreaGUType = AccessTools.TypeByName("GiddyUpCore.Zones.Area_GU");

                MpCompat.harmony.Patch(AccessTools.Method("Verse.AreaManager:AddStartingAreas"),
                                       postfix: new HarmonyMethod(typeof(GiddyUpRideAndRollCompat), nameof(AddStartingAreasPostfix))
                                       );

                MpCompat.harmony.Patch(AccessTools.Method(AreaGUType, "GetUniqueLoadID"),
                                       postfix: new HarmonyMethod(typeof(GiddyUpRideAndRollCompat), nameof(GetUniqueLoadIDPostfix))
                                       );
            }

            // Designators
            {
                Type type = AccessTools.TypeByName("GiddyUpCore.Zones.Designator_GU");

                AreaLabelField        = AccessTools.Field(type, "areaLabel");
                SetSelectedAreaMethod = AccessTools.Method(type, "setSelectedArea");

                MP.RegisterSyncWorker <Designator>(DesignatorGU, type, true);

                DesignatorDropAnimalExpandType = AccessTools.TypeByName("GiddyUpRideAndRoll.Zones.Designator_GU_DropAnimal_Expand");
                DesignatorDropAnimalClearType  = AccessTools.TypeByName("GiddyUpRideAndRoll.Zones.Designator_GU_DropAnimal_Clear");
                DesignatorNoMountExpandType    = AccessTools.TypeByName("GiddyUpRideAndRoll.Zones.Designator_GU_NoMount_Expand");
                DesignatorNoMountClearType     = AccessTools.TypeByName("GiddyUpRideAndRoll.Zones.Designator_GU_NoMount_Clear");
            }
        }
Example #14
0
        public VanillaFactionsSettlers(ModContentPack mod)
        {
            var type = AccessTools.TypeByName("VFE_Settlers.Utilities.UtilityEvent");

            // Protection fee event
            NodeTreeDialogSync.EnableNodeTreeDialogSync();
            MpCompat.harmony.Patch(AccessTools.Method(type, "ProtectionFee"), prefix: NodeTreeDialogSync.HarmonyMethodMarkDialogAsOpen);
            // Caravan gizmo - turn in wanted criminal to settlement
            MP.RegisterSyncDelegate(type, "<>c__DisplayClass8_0", "<CommandTurnInWanted>b__0");
            // Dev mode set progress to 1
            MpCompat.RegisterSyncMethodByIndex(AccessTools.TypeByName("VFE_Settlers.Buildings.Building_ChemshineBarrel"), "<GetGizmos>", 0);
            // Toggle mode
            MpCompat.RegisterSyncMethodByIndex(AccessTools.TypeByName("VanillaFactionsExpandedSettlers.CompWarmUpReduction"), "<CompGetGizmosExtra>", 1);
            // Five fingers fillet table
            PatchingUtilities.PatchUnityRand("VFE_Settlers.JobGivers.JobDriver_PlayFiveFingerFillet:WatchTickAction", false);
        }
        public VanillaExpandedFramework(ModContentPack mod)
        {
            var type = AccessTools.TypeByName("ItemProcessor.Building_ItemProcessor");

            // _1, _5 and _7 are used to check if gizmo should be enabled, so we don't sync them
            MpCompat.RegisterSyncMethodsByIndex(type, "<GetGizmos>", 0, 2, 3, 4, 6, 8, 9, 10);

            type = AccessTools.TypeByName("ItemProcessor.Command_SetQualityList");
            MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true);
            MpCompat.RegisterSyncMethodsByIndex(type, "<ProcessInput>", Enumerable.Range(0, 8).ToArray());

            type = AccessTools.TypeByName("ItemProcessor.Command_SetOutputList");
            MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true);
            MP.RegisterSyncMethod(type, "TryConfigureIngredientsByOutput");

            // Keep an eye on this in the future, seems like something the devs could combine into a single class at some point
            foreach (var ingredientNumber in new[] { "First", "Second", "Third", "Fourth" })
            {
                type = AccessTools.TypeByName($"ItemProcessor.Command_Set{ingredientNumber}ItemList");
                MP.RegisterSyncWorker <Command>(SyncSetIngredientCommand, type, shouldConstruct: true);
                MP.RegisterSyncMethod(type, $"TryInsert{ingredientNumber}Thing");
                MpCompat.RegisterSyncMethodsByIndex(type, "<ProcessInput>", 0);
            }

            // AddHediff desyncs with Arbiter, but seems fine without it
            PatchingUtilities.PatchPushPopRand("VanillaCookingExpanded.Thought_Hediff:MoodOffset");

            type = AccessTools.TypeByName("VFECore.CompPawnDependsOn");
            MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0).SetDebugOnly();

            type = AccessTools.TypeByName("VanillaFurnitureExpanded.CompConfigurableSpawner");
            MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0).SetDebugOnly();

            type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetItemsToSpawn");
            MP.RegisterSyncDelegate(type, "<>c__DisplayClass2_0", "<ProcessInput>b__1");

            type = AccessTools.TypeByName("VanillaFurnitureExpanded.CompRockSpawner");
            MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0);

            type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetStoneType");
            setStoneBuildingField = AccessTools.Field(type, "building");
            MpCompat.RegisterSyncMethodByIndex(type, "<ProcessInput>", 0);
            MP.RegisterSyncWorker <Command>(SyncSetStoneTypeCommand, type, shouldConstruct: true);
            MP.RegisterSyncDelegate(type, "<>c__DisplayClass2_0", "<ProcessInput>b__1");
        }
        public SRTSExpanded(ModContentPack mod)
        {
            LongEventHandler.ExecuteWhenFinished(DelayedPatch);

            // Refuel shuttle
            MP.RegisterSyncDelegate(AccessTools.TypeByName("SRTS.StartUp"), "<>c__DisplayClass24_1", "<LaunchAndBombGizmosPassthrough>b__3");

            // Bombing
            MP.RegisterSyncWorker <Pair <IntVec3, IntVec3> >(SyncIntVec3Pair, typeof(Pair <IntVec3, IntVec3>));
            var type = AccessTools.TypeByName("SRTS.CompBombFlyer");

            MP.RegisterSyncMethod(type, "TryLaunchBombRun");
            bombTypeSync = MP.RegisterSyncField(type, "bombType");

            foreach (MethodInfo method in MpCompat.MethodsByIndex(type, "<CompGetGizmosExtra>", 1, 2))
            {
                MpCompat.harmony.Patch(method,
                                       prefix: new HarmonyMethod(typeof(SRTSExpanded), nameof(PreSyncBombType)),
                                       postfix: new HarmonyMethod(typeof(SRTSExpanded), nameof(PostSyncBombType)));
            }
        }
        public VanillaAnimalsEndangered(ModContentPack mod)
        {
            var type = AccessTools.TypeByName("VanillaAnimalsExpandedEndangered.Pawn_GetGizmos_Patch");

            MP.RegisterSyncDelegate(type, "<>c__DisplayClass3_0", "<Postfix>b__1");
        }
Example #18
0
        public RunandGun(ModContentPack mod)
        {
            Type type = AccessTools.TypeByName("RunAndGun.Harmony.Pawn_DraftController_GetGizmos_Patch");

            MP.RegisterSyncDelegate(type, "<>c__DisplayClass0_0", "<Postfix>b__1");
        }
        public DragonsDescent(ModContentPack mod)
        {
            // Incubator
            {
                var type    = AccessTools.TypeByName("DD.CompEggIncubator");
                var methods = MpCompat.RegisterSyncMethodsByIndex(type, "<CompGetGizmosExtra>", 1, 2, 3, 4);
                foreach (var method in methods.Skip(1)) // All but the first one are debug-only gizmos
                {
                    method.SetDebugOnly();
                }

                type = AccessTools.TypeByName("DD.CompProperties_EggIncubator");
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass7_0", "<CreateGizmo>b__0");
            }

            // Abilities
            {
                var type = AccessTools.TypeByName("DD.AbilityComp_AbilityControl");
                var gizmoActionMethod = MpCompat.MethodByIndex(type, "<get_Gizmo>", 1);
                MP.RegisterSyncMethod(gizmoActionMethod); // Toggle active
                MpCompat.harmony.Patch(gizmoActionMethod,
                                       prefix: new HarmonyMethod(typeof(DragonsDescent), nameof(PreGizmoActionCalled)));
                abilityCompGizmoGetter = AccessTools.PropertyGetter(type, "Gizmo");
            }

            // Hostility response type changing
            {
                var type = AccessTools.TypeByName("DD.CompHostileResponse");
                hostilityResponseTypeField = AccessTools.Field(type, "type");

                var inner = AccessTools.Inner(type, "<>c__DisplayClass15_0");
                MP.RegisterSyncMethod(typeof(DragonsDescent), nameof(SyncSetHostilityResponseType));
                compHostileResponseField = AccessTools.Field(inner, "<>4__this");
                MpCompat.harmony.Patch(AccessTools.Method(inner, "<get_Gizmo>b__1"),
                                       prefix: new HarmonyMethod(typeof(DragonsDescent), nameof(PreSetHostilityResponseType)));
            }

            // Altar
            {
                compRitualAltarType = AccessTools.TypeByName("DD.CompRitualAltar");
                MP.RegisterSyncDelegate(compRitualAltarType, "<>c__DisplayClass11_0", "<CompGetGizmosExtra>b__0").SetDebugOnly();
                MP.RegisterSyncDelegate(compRitualAltarType, "<>c__DisplayClass11_0", "<CompGetGizmosExtra>b__1").SetDebugOnly();
                MP.RegisterSyncDelegate(compRitualAltarType, "<>c__DisplayClass11_0", "<CompGetGizmosExtra>b__2").SetDebugOnly();
                MP.RegisterSyncDelegate(compRitualAltarType, "<>c__DisplayClass11_0", "<CompGetGizmosExtra>b__3").SetDebugOnly();

                var type = AccessTools.TypeByName("DD.RitualTracker");
                MP.RegisterSyncWorker <object>(SyncRitualTracker, type);
                ritualTrackerGetRitualMethod = AccessTools.Method(type, "GetRitual");
                ritualTrackerMapField        = AccessTools.Field(type, "map");

                trackerMapComponentType         = AccessTools.TypeByName("DD.MapComponent_Tracker");
                trackerMapComponentRitualsField = AccessTools.Field(trackerMapComponentType, "rituals");

                ritualReferenceType     = AccessTools.TypeByName("DD.RitualReference");
                ritualReferenceDefField = AccessTools.Field(ritualReferenceType, "def");

                var inner = AccessTools.Inner(ritualReferenceType, "<>c__DisplayClass12_0");
                MpCompat.RegisterSyncMethodsByIndex(inner, "<SetupAction>", 0, 1);
                MP.RegisterSyncWorker <object>(SyncRitualReferenceInnerClass, inner, shouldConstruct: true);
                ritualReferenceInnerRitualField  = AccessTools.Field(inner, "ritual");
                ritualReferenceInnerSelfField    = AccessTools.Field(inner, "<>4__this");
                ritualReferenceInnerParentField  = AccessTools.Field(inner, "parent");
                ritualReferenceInnerRitualsField = AccessTools.Field(inner, "rituals");

                type = AccessTools.TypeByName("DD.CompProperties_Ritual");
                ritualCompPropertiesRitualsField = AccessTools.Field(type, "rituals");
            }
        }
Example #20
0
        static void LateLoad()
        {
            Type type;

            // Float Menus
            {
                type = AccessTools.TypeByName("CombatExtended.Harmony.FloatMenuMakerMap_Modify_AddHumanlikeOrders");

                // CE_Stabilizing
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass1_1", "<AddMenuItems>b__1");

                // PickUp
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass1_2", "<AddMenuItems>b__4");

                // PickUpAll
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass1_2", "<AddMenuItems>b__5");

                // PickUpSome
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass1_2", "<AddMenuItems>b__7");

                // Dialog_Slider
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass1_3", "<AddMenuItems>b__6");
            }

            // Pawn Gizmos
            {
                // Reload
                type = AccessTools.TypeByName("CombatExtended.CompAmmoUser");

                MP.RegisterSyncMethod(type, "TryStartReload");
            }
            {
                // Toggles
                type = AccessTools.TypeByName("CombatExtended.CompFireModes");

                MP.RegisterSyncMethod(type, "ResetModes");
                MP.RegisterSyncMethod(type, "ToggleAimMode");
                MP.RegisterSyncMethod(type, "ToggleFireMode");
            }

            // Turret Gizmos
            {
                type = AccessTools.TypeByName("CombatExtended.Building_TurretGunCE");

                MP.RegisterSyncMethod(type, "<GetGizmos>b__64_0");
                MP.RegisterSyncMethod(type, "<GetGizmos>b__64_1");

                MP.RegisterSyncMethod(type, "TryOrderReload");
            }

            // Loadouts
            {
                type = AccessTools.TypeByName("CombatExtended.Utility_Loadouts");

                MP.RegisterSyncMethod(type, "SetLoadout");
                MP.RegisterSyncMethod(type, "SetLoadoutById");
                MP.RegisterSyncMethod(type, "GenerateLoadoutFromPawn");
            }
            {
                type = AccessTools.TypeByName("CombatExtended.Loadout");

                MP.RegisterSyncMethod(type, "Copy", new SyncType[] { type });
                MP.RegisterSyncMethod(type, "Copy");
                MP.RegisterSyncMethod(type, "AddSlot");
                MP.RegisterSyncMethod(type, "MoveSlot");
                MP.RegisterSyncMethod(type, "RemoveSlot", new SyncType[] { typeof(int) });
                MP.RegisterSyncMethod(type, "RemoveSlot", new SyncType[] { AccessTools.TypeByName("CombatExtended.LoadoutSlot") });
            }

            // iTab Inventory?
            {
                // TODO
            }

            // RNG prevention
            {
                var methods = new[] {
                    AccessTools.Method("CombatExtended.CompSuppressable:AddSuppression"),
                    AccessTools.Method("CombatExtended.CompSuppressable:CompTick"),
                    // oh boy shooting doesn't work...
                    // TODO
                };

                foreach (var method in methods)
                {
                    MpCompat.harmony.Patch(method,
                                           prefix: new HarmonyMethod(typeof(CombatExtendedCompat), nameof(FixRNGPre)),
                                           postfix: new HarmonyMethod(typeof(CombatExtendedCompat), nameof(FixRNGPos))
                                           );
                }
            }
        }
        public GeneticRimCompat(ModContentPack mod)
        {
            Type type;

            // Several Gizmos
            {
                type = AccessTools.TypeByName("GeneticRim.GeneticRim_Pawn_GetGizmos_Patch");

                string[] methods =
                {
                    "<AddGizmo>b__0",
                    "<AddGizmo>b__1",
                    "<AddGizmo>b__10",
                    "<AddGizmo>b__11",
                    "<AddGizmo>b__12",
                    "<AddGizmo>b__13",
                    "<AddGizmo>b__14",
                    "<AddGizmo>b__15",
                    "<AddGizmo>b__16",
                    "<AddGizmo>b__17",
                    "<AddGizmo>b__3",
                    "<AddGizmo>b__5",
                    "<AddGizmo>b__7",
                    "<AddGizmo>b__8",
                    "<AddGizmo>b__9",
                };

                foreach (string method in methods)
                {
                    MP.RegisterSyncDelegate(type, "<>c__DisplayClass0_0", method);
                }
            }

            // ArchotechShip startup
            {
                MP.RegisterSyncMethod(AccessTools.Method("GeneticRim.ArchotechUtility:StartupHibernatingParts"));
                MP.RegisterSyncMethod(AccessTools.Method("GeneticRim.ArchotechCountdown:InitiateCountdown"));
            }
            {
                type = AccessTools.TypeByName("GeneticRim.ArchotechCountdown");

                string[] methods =
                {
                    "InitiateCountdown",
                    "CancelCountdown",
                    "CountdownEnded"
                };

                foreach (string method in methods)
                {
                    MP.RegisterSyncMethod(AccessTools.Method(type, method));
                }
            }

            // RNG patching
            {
                string[] constructorsToPatch =
                {
                    "GeneticRim.CompHatcherRandomizer",
                    "GeneticRim.CompIncubator",
                    "GeneticRim.CompRecombinator",
                    "GeneticRim.CompRecombinatorSerum",
                    "GeneticRim.DeathActionWorker_Eggxplosion",
                    "GeneticRim.CompExploder",
                };

                PatchingUtilities.PatchSystemRandCtor(constructorsToPatch, false);

                string[] methodsWithRand =
                {
                    "GeneticRim.CompHatcherRandomizer:Hatch",
                    "GeneticRim.CompIncubator:Hatch",
                    "GeneticRim.CompRecombinator:Hatch",
                    "GeneticRim.CompRecombinator:RecombinateAgain",
                    "GeneticRim.CompRecombinatorSerum:Hatch",
                    "GeneticRim.DeathActionWorker_Eggxplosion:PawnDied",
                    "GeneticRim.CompExploder:wickInitializer",
                };

                PatchingUtilities.PatchPushPopRand(methodsWithRand);
            }
        }
        public VanillaExpandedFramework(ModContentPack mod)
        {
            // ItemProcessor
            {
                var type = AccessTools.TypeByName("ItemProcessor.Building_ItemProcessor");
                // _1, _5 and _7 are used to check if gizmo should be enabled, so we don't sync them
                MpCompat.RegisterSyncMethodsByIndex(type, "<GetGizmos>", 0, 2, 3, 4, 6, 8, 9, 10);

                type = AccessTools.TypeByName("ItemProcessor.Command_SetQualityList");
                MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true);
                MpCompat.RegisterSyncMethodsByIndex(type, "<ProcessInput>", Enumerable.Range(0, 8).ToArray());

                type = AccessTools.TypeByName("ItemProcessor.Command_SetOutputList");
                MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true);
                MP.RegisterSyncMethod(type, "TryConfigureIngredientsByOutput");

                // Keep an eye on this in the future, seems like something the devs could combine into a single class at some point
                foreach (var ingredientNumber in new[] { "First", "Second", "Third", "Fourth" })
                {
                    type = AccessTools.TypeByName($"ItemProcessor.Command_Set{ingredientNumber}ItemList");
                    MP.RegisterSyncWorker <Command>(SyncSetIngredientCommand, type, shouldConstruct: true);
                    MP.RegisterSyncMethod(type, $"TryInsert{ingredientNumber}Thing");
                    MpCompat.RegisterSyncMethodsByIndex(type, "<ProcessInput>", 0);
                }
            }

            // Vanilla Cooking Expanded
            {
                // AddHediff desyncs with Arbiter, but seems fine without it
                PatchingUtilities.PatchPushPopRand("VanillaCookingExpanded.Thought_Hediff:MoodOffset");
            }

            // VFE Core
            {
                var type = AccessTools.TypeByName("VFECore.CompPawnDependsOn");
                MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0).SetDebugOnly();
            }

            // Vanilla Furniture Expanded
            {
                var type = AccessTools.TypeByName("VanillaFurnitureExpanded.CompConfigurableSpawner");
                MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0).SetDebugOnly();

                type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetItemsToSpawn");
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass2_0", "<ProcessInput>b__1");

                type = AccessTools.TypeByName("VanillaFurnitureExpanded.CompRockSpawner");
                MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0);

                type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetStoneType");
                setStoneBuildingField = AccessTools.Field(type, "building");
                MpCompat.RegisterSyncMethodByIndex(type, "<ProcessInput>", 0);
                MP.RegisterSyncWorker <Command>(SyncSetStoneTypeCommand, type, shouldConstruct: true);
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass2_0", "<ProcessInput>b__1");
            }

            // Vanilla Faction Mechanoids
            {
                var type = AccessTools.TypeByName("VFE.Mechanoids.CompMachineChargingStation");
                MP.RegisterSyncDelegate(type, "<>c", "<CompGetGizmosExtra>b__21_1", Array.Empty <string>()).SetContext(SyncContext.MapSelected);
                MP.RegisterSyncDelegate(type, "<>c", "<CompGetGizmosExtra>b__21_6", Array.Empty <string>()).SetContext(SyncContext.MapSelected);
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass21_0", "<CompGetGizmosExtra>b__4");
            }

            // AnimalBehaviours
            {
                // RNG
                PatchingUtilities.PatchSystemRand("AnimalBehaviours.DamageWorker_ExtraInfecter:ApplySpecialEffectsToPart", false);
                PatchingUtilities.PatchSystemRandCtor(new[] { "AnimalBehaviours.CompAnimalProduct", "AnimalBehaviours.CompGasProducer" }, false);

                // Gizmos
                // Might not work, as I could not find a mod that uses this to test this
                var type = AccessTools.TypeByName("AnimalBehaviours.CompDestroyThisItem");
                MP.RegisterSyncMethod(type, "SetObjectForDestruction");
                MP.RegisterSyncMethod(type, "CancelObjectForDestruction");
            }

            // MVCF (Multi Verb Combat Framework)
            {
                var type = AccessTools.TypeByName("MVCF.WorldComponent_MVCF");
                mvcfGetWorldCompMethod   = AccessTools.Method(type, "GetComp");
                mvcfAllManagersListField = AccessTools.Field(type, "allManagers");
                mvcfManagersTableField   = AccessTools.Field(type, "managers");
                MP.RegisterSyncMethod(typeof(VanillaExpandedFramework), nameof(SyncedInitVerbManager));
                MpCompat.harmony.Patch(AccessTools.Method(type, "GetManagerFor"),
                                       prefix: new HarmonyMethod(typeof(VanillaExpandedFramework), nameof(GetManagerForPrefix)));

                type = AccessTools.TypeByName("MVCF.VerbManager");
                MP.RegisterSyncWorker <object>(SyncVerbManager, type, isImplicit: true);
                mvcfVerbManagerCtor         = AccessTools.Constructor(type);
                mvcfInitializeManagerMethod = AccessTools.Method(type, "Initialize");
                mvcfPawnGetter = AccessTools.PropertyGetter(type, "Pawn");
                mvcfVerbsField = AccessTools.Field(type, "verbs");

                var weakReferenceType = typeof(System.WeakReference <>).MakeGenericType(new[] { type });
                weakReferenceCtor = AccessTools.FirstConstructor(weakReferenceType, ctor => ctor.GetParameters().Count() == 1);

                var conditionalWeakTableType = typeof(System.Runtime.CompilerServices.ConditionalWeakTable <,>).MakeGenericType(new[] { typeof(Pawn), type });
                conditionalWeakTableAddMethod         = AccessTools.Method(conditionalWeakTableType, "Add");
                conditionalWeakTableTryGetValueMethod = AccessTools.Method(conditionalWeakTableType, "TryGetValue");

                type = AccessTools.TypeByName("MVCF.ManagedVerb");
                mvcfManagerVerbManagerField = AccessTools.Field(type, "man");
                MP.RegisterSyncWorker <object>(SyncManagedVerb, type, isImplicit: true);
                // Seems like selecting the Thing that holds the verb inits some stuff, so we need to set the context
                MP.RegisterSyncMethod(type, "Toggle");

                type = AccessTools.TypeByName("MVCF.Harmony.Gizmos");
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass5_0", "<GetGizmos_Postfix>b__1");       // Fire at will
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass6_0", "<GetAttackGizmos_Postfix>b__4"); // Interrupt Attack
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass7_0", "<Pawn_GetGizmos_Postfix>b__0");  // Also interrupt Attack
            }
        }
Example #23
0
        private static void LatePatch()
        {
            // Tables
            {
                var type = AccessTools.TypeByName("Gastronomy.Dining.CompCanDineAt");
                MP.RegisterSyncMethod(type, "ChangeDeco");
                MP.RegisterSyncMethod(type, "ToggleDining");
            }
            // Register menu
            {
                // ITab_Register
                var type = AccessTools.TypeByName("Gastronomy.TableTops.ITab_Register");
                hiddenSpecialThingFiltersMethod = AccessTools.Method(type, "HiddenSpecialThingFilters");
                MpCompat.harmony.Patch(
                    AccessTools.Method(type, "FillTab"),
                    prefix: new HarmonyMethod(typeof(Gastronomy), nameof(FillTabPrefix)),
                    postfix: new HarmonyMethod(typeof(Gastronomy), nameof(FillTabPostfix)));

                // Clear debt on cliking it
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass18_0", "<DrawDebts>b__1").CancelIfAnyFieldNull().CancelIfNoSelectedObjects().SetContext(SyncContext.CurrentMap);

                // Sync worker for debt itself, requires SyncContext.CurrentMap
                type = AccessTools.TypeByName("Gastronomy.Restaurant.Debt");
                MP.RegisterSyncWorker <object>(SyncDebt, type);

                // RestaurantDebt, used for finding the debt
                type = AccessTools.TypeByName("Gastronomy.Restaurant.RestaurantDebt");
                restaurantDebtAllDebtsField = AccessTools.Field(type, "debts");

                // Building_CashRegister
                type = AccessTools.TypeByName("Gastronomy.TableTops.Building_CashRegister");
                restaurantControllerField = AccessTools.Field(type, "restaurant");

                // TimetableBool
                type = AccessTools.TypeByName("Gastronomy.Restaurant.Timetable.TimetableBool");
                timetableTimesField = AccessTools.Field(type, "times");

                // RestaurantMenu
                type                       = AccessTools.TypeByName("Gastronomy.Restaurant.RestaurantMenu");
                menuFilterField            = AccessTools.Field(type, "menuFilter");
                menuGlobalFilterField      = AccessTools.Field(type, "menuGlobalFilter");
                initMenuFilterMethod       = AccessTools.Method(type, "InitMenuFilter");
                initMenuGlobalFilterMethod = AccessTools.Method(type, "InitMenuGlobalFilter");
                MpCompat.harmony.Patch(
                    AccessTools.Constructor(type),
                    prefix: new HarmonyMethod(typeof(Gastronomy), nameof(RestaurantMenuConstructorPrefix)));

                // RestaurantController
                restaurantControllerType = AccessTools.TypeByName("Gastronomy.RestaurantController");
                controllerFieldsToSync   = (new[] { "openForBusiness", "allowGuests", "allowColonists", "allowPrisoners", "guestPricePercentage" }).Select(x => MP.RegisterSyncField(restaurantControllerType, x)).ToArray();
                controllerTimetableField = AccessTools.Field(restaurantControllerType, "timetableOpen");
                controllerMenuField      = AccessTools.Field(restaurantControllerType, "menu");
                controllerTimesSync      = MP.RegisterSyncField(restaurantControllerType, "timetableOpen/times").SetBufferChanges();
                controllerDebtField      = AccessTools.Field(restaurantControllerType, "debts");
            }
            // MP overrides
            {
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Multiplayer.cs#L58
                shouldSyncGetter = AccessTools.PropertyGetter(AccessTools.TypeByName("Multiplayer.Client.Multiplayer"), "ShouldSync");
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L771
                allowCategoryHelperMethod = AccessTools.Method(AccessTools.TypeByName("Multiplayer.Client.SyncThingFilters"), "ThingFilter_AllowCategory_Helper");

                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncSerialization.cs#L33
                // We get the thingFilterTarget, and add our own filter to it
                var thingFilterTarget = AccessTools.Field(AccessTools.TypeByName("Multiplayer.Client.Sync"), "thingFilterTarget");
                var target            = thingFilterTarget.GetValue(null);

                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/Sync.cs#L1243
                // Get and call the method to add our filter
                AccessTools.Method(AccessTools.TypeByName("Multiplayer.Client.MultiTarget"), "Add", new Type[] { typeof(Type), typeof(string) })
                .Invoke(target, new object[] { restaurantControllerType, "menu/menuFilter" });

                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L960
                MpCompat.harmony.Patch(AccessTools.PropertyGetter(AccessTools.TypeByName("Multiplayer.Client.SyncMarkers"), "ThingFilterOwner"),
                                       prefix: new HarmonyMethod(typeof(Gastronomy), nameof(ThingFilterOwnerPrefix)));

                // Set prefixes to the 3 methods that need some additional work that isn't universal to all filters
                // (See the methods for github links)
                MpCompat.harmony.Patch(AccessTools.Method(typeof(ThingFilter), nameof(ThingFilter.SetAllow), new[] { typeof(ThingCategoryDef), typeof(bool), typeof(IEnumerable <ThingDef>), typeof(IEnumerable <SpecialThingFilterDef>) }),
                                       prefix: new HarmonyMethod(typeof(Gastronomy), nameof(ThingFilter_SetAllowPrefix)));
                MpCompat.harmony.Patch(AccessTools.Method(typeof(ThingFilter), nameof(ThingFilter.SetDisallowAll)),
                                       prefix: new HarmonyMethod(typeof(Gastronomy), nameof(ThingFilter_SetDisallowAllPrefix)));
                MpCompat.harmony.Patch(AccessTools.Method(typeof(ThingFilter), nameof(ThingFilter.SetAllowAll)),
                                       prefix: new HarmonyMethod(typeof(Gastronomy), nameof(ThingFilter_SetAllowAllPrefix)));

                // Methods that we'll need to setup SyncFields/SyncMethods for MultiTarget
                var type = AccessTools.TypeByName("Multiplayer.Client.Sync");
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/Sync.cs#L801
                var methodMultiTarget = AccessTools.Method(type, "MethodMultiTarget");
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/Sync.cs#L818
                var fieldMultiTarget = AccessTools.Method(type, "FieldMultiTarget");

                // Create fields for SyncFields that will include our filter
                type = AccessTools.TypeByName("Multiplayer.Client.SyncFieldsPatches");
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L66
                var values = (Array)fieldMultiTarget.Invoke(null, new[] { target, nameof(ThingFilter.AllowedHitPointsPercents) });
                foreach (var value in values)
                {
                    ((ISyncField)value).SetBufferChanges();
                }
                AccessTools.Field(type, "SyncThingFilterHitPoints").SetValue(null, values);
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L69
                values = (Array)fieldMultiTarget.Invoke(null, new[] { target, nameof(ThingFilter.AllowedQualityLevels) });
                foreach (var value in values)
                {
                    ((ISyncField)value).SetBufferChanges();
                }
                AccessTools.Field(type, "SyncThingFilterQuality").SetValue(null, values);

                // Create fields for SyncMethods that will include our filter
                type = AccessTools.TypeByName("Multiplayer.Client.SyncThingFilters");
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L658
                AccessTools.Field(type, "SyncThingFilterAllowThing").SetValue(null, methodMultiTarget.Invoke(null, new[] { target, nameof(ThingFilter.SetAllow), new SyncType[] { typeof(ThingDef), typeof(bool) } }));
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L659
                AccessTools.Field(type, "SyncThingFilterAllowSpecial").SetValue(null, methodMultiTarget.Invoke(null, new[] { target, nameof(ThingFilter.SetAllow), new SyncType[] { typeof(SpecialThingFilterDef), typeof(bool) } }));
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L660
                AccessTools.Field(type, "SyncThingFilterAllowStuffCategory").SetValue(null, methodMultiTarget.Invoke(null, new[] { target, nameof(ThingFilter.SetAllow), new SyncType[] { typeof(StuffCategoryDef), typeof(bool) } }));

                // Sync our helper methods
                // (See the methods for github links)
                MP.RegisterSyncMethod(typeof(Gastronomy), nameof(ThingFilter_DisallowAll_HelperRestaurant));
                MP.RegisterSyncMethod(typeof(Gastronomy), nameof(ThingFilter_AllowAll_HelperRestaurant));
                MP.RegisterSyncMethod(typeof(Gastronomy), nameof(ThingFilter_AllowCategory_HelperRestaurant));
            }
        }
        public GeneticRimCompat(ModContentPack mod)
        {
            Type type;

            // Several Gizmos
            {
                type = AccessTools.TypeByName("DraftingPatcher.Pawn_GetGizmos_Patch");

                string[] methods =
                {
                    "<AddGizmo>b__0",
                    "<AddGizmo>b__1",
                    "<AddGizmo>b__10",
                    "<AddGizmo>b__11",
                    "<AddGizmo>b__12",
                    "<AddGizmo>b__13",
                    "<AddGizmo>b__14",
                    "<AddGizmo>b__15",
                    "<AddGizmo>b__16",
                    "<AddGizmo>b__17",
                    "<AddGizmo>b__3",
                    "<AddGizmo>b__5",
                    "<AddGizmo>b__7",
                    "<AddGizmo>b__8",
                    "<AddGizmo>b__9",
                };

                foreach (string method in methods)
                {
                    MP.RegisterSyncDelegate(type, "<>c__DisplayClass0_0", method);
                }
            }

            // ArchotechShip startup
            {
                MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.ArchotechUtility:StartupHibernatingParts"));
                MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.ArchotechCountdown:InitiateCountdown"));
            }
            {
                type = AccessTools.TypeByName("NewMachinery.ArchotechCountdown");

                string[] methods =
                {
                    "InitiateCountdown",
                    "CancelCountdown",
                    "CountdownEnded"
                };

                foreach (string method in methods)
                {
                    MP.RegisterSyncMethod(AccessTools.Method(type, method));
                }
            }

            // Genepod
            {
                type = AccessTools.TypeByName("NewMachinery.Building_NewGenePod");

                MP.RegisterSyncMethod(type, "<GetGizmos>b__20_0");
                MP.RegisterSyncMethod(type, "<GetGizmos>b__20_1");
            }

            // Commands
            {
                MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.Command_SetGene2List:ProcessInput"));
                MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.Command_SetGeneList:ProcessInput"));
            }

            // RNG patching
            {
                string[] constructorsToPatch =
                {
                    "NewHatcher.CompHatcherRandomizer",
                    "NewHatcher.CompIncubator",
                    "NewHatcher.CompRecombinator",
                    "NewHatcher.CompRecombinatorSerum",
                };

                PatchingUtilities.PatchSystemRandCtor(constructorsToPatch, false);

                string[] methodsWithRand =
                {
                    "NewHatcher.CompHatcherRandomizer:Hatch",
                    "NewHatcher.CompIncubator:Hatch",
                    "NewHatcher.CompRecombinator:Hatch",
                    "NewHatcher.CompRecombinator:RecombinateAgain",
                    "NewHatcher.CompRecombinatorSerum:Hatch",
                };

                PatchingUtilities.PatchPushPopRand(methodsWithRand);
            }
        }
        public GeneticRimCompat(ModContentPack mod)
        {
            Type type;

            // Several Gizmos
            {
                type = AccessTools.TypeByName("DraftingPatcher.Pawn_GetGizmos_Patch");

                string[] methods =
                {
                    "<AddGizmo>b__0",
                    "<AddGizmo>b__1",
                    "<AddGizmo>b__10",
                    "<AddGizmo>b__11",
                    "<AddGizmo>b__12",
                    "<AddGizmo>b__13",
                    "<AddGizmo>b__14",
                    "<AddGizmo>b__15",
                    "<AddGizmo>b__16",
                    "<AddGizmo>b__17",
                    "<AddGizmo>b__3",
                    "<AddGizmo>b__5",
                    "<AddGizmo>b__7",
                    "<AddGizmo>b__8",
                    "<AddGizmo>b__9",
                };

                foreach (string method in methods)
                {
                    MP.RegisterSyncDelegate(type, "<>c__DisplayClass0_0", method);
                }
            }

            // ArchotechShip startup
            {
                MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.ArchotechUtility:StartupHibernatingParts"));
                MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.ArchotechCountdown:InitiateCountdown"));
            }
            {
                type = AccessTools.TypeByName("NewMachinery.ArchotechCountdown");

                string[] methods =
                {
                    "InitiateCountdown",
                    "CancelCountdown",
                    "CountdownEnded"
                };

                foreach (string method in methods)
                {
                    MP.RegisterSyncMethod(AccessTools.Method(type, method));
                }
            }

            // Genepod
            {
                type = AccessTools.TypeByName("NewMachinery.Building_NewGenePod");

                MP.RegisterSyncMethod(type, "<GetGizmos>b__20_0");
                MP.RegisterSyncMethod(type, "<GetGizmos>b__20_1");
            }

            // Commands
            {
                MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.Command_SetGene2List:ProcessInput"));
                MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.Command_SetGeneList:ProcessInput"));
            }

            // RNG mitigation
            {
                string[] typesWithRand =
                {
                    "NewHatcher.CompHatcherRandomizer",
                    "NewHatcher.CompIncubator",
                    "NewHatcher.CompRecombinator",
                    "NewHatcher.CompRecombinatorSerum",
                };

                foreach (string typeName in typesWithRand)
                {
                    type = AccessTools.TypeByName(typeName);

                    MpCompat.harmony.Patch(AccessTools.Constructor(type),
                                           postfix: new HarmonyMethod(typeof(GeneticRimCompat), nameof(MitigateRNG))
                                           );
                }
            }
        }