public void LatePatch() { // Facepaint changeFacepaintDialogType = AccessTools.TypeByName("VFEV.Facepaint.Dialog_ChangeFacepaint"); //setFacepaintMethod = AccessTools.Method(changeFacepaintDialogType, "SetHairstyle"); orderedFacepaintDefsField = AccessTools.Field(changeFacepaintDialogType, "orderedFacepaintDefs"); newFacepaintComboSync = MP.RegisterSyncField(AccessTools.Field(changeFacepaintDialogType, "newFacepaintCombo")); coloursTiedSync = MP.RegisterSyncField(AccessTools.Field(changeFacepaintDialogType, "coloursTied")); MP.RegisterSyncMethod(changeFacepaintDialogType, "SetHairstyle"); MP.RegisterSyncWorker <Window>(SyncDialog, changeFacepaintDialogType); MP.RegisterSyncMethod(typeof(VanillaFactionsVikings), nameof(SyncedTryRemoveWindow)); MpCompat.harmony.Patch(AccessTools.Method(changeFacepaintDialogType, "DoWindowContents"), prefix: new HarmonyMethod(typeof(VanillaFactionsVikings), nameof(PreDoWindowContents)), postfix: new HarmonyMethod(typeof(VanillaFactionsVikings), nameof(PostDoWindowContents))); var type = AccessTools.Inner(changeFacepaintDialogType, "FacepaintCombination"); MP.RegisterSyncWorker <object>(SyncFacepaintCombination, type); facepaintDefOneField = AccessTools.Field(type, "facepaintDefOne"); facepaintDefTwoField = AccessTools.Field(type, "facepaintDefTwo"); facepaintColourOneField = AccessTools.Field(type, "colourOne"); facepaintColourTwoField = AccessTools.Field(type, "colourTwo"); MpCompat.harmony.Patch(AccessTools.Method(typeof(WindowStack), nameof(WindowStack.TryRemove), new[] { typeof(Window), typeof(bool) }), prefix: new HarmonyMethod(typeof(VanillaFactionsVikings), nameof(PreTryRemoveWindow))); }
static ExtendedOutfitProxy() { if (!MP.enabled) { return; } ProxyFields = new ISyncField[] { MP.RegisterSyncField(typeof(ExtendedOutfitProxy), nameof(targetWeight)) .SetBufferChanges().PostApply(Update) }; ExtendedOutfitFields = new ISyncField[] { MP.RegisterSyncField(typeof(ExtendedOutfit), nameof(ExtendedOutfit.targetTemperaturesOverride)), MP.RegisterSyncField(typeof(ExtendedOutfit), nameof(ExtendedOutfit.targetTemperatures)), MP.RegisterSyncField(typeof(ExtendedOutfit), nameof(ExtendedOutfit.PenaltyWornByCorpse)), MP.RegisterSyncField(typeof(ExtendedOutfit), nameof(ExtendedOutfit.AutoWorkPriorities)), }; MP.RegisterSyncMethod(typeof(ExtendedOutfit), nameof(ExtendedOutfit.AddStatPriority)); MP.RegisterSyncMethod(typeof(ExtendedOutfit), nameof(ExtendedOutfit.RemoveStatPriority)); MP.RegisterSyncMethod(typeof(ExtendedOutfitProxy), nameof(SetStat)); MP.RegisterSyncWorker <ExtendedOutfit>(ExtendedOutfitSyncer); }
public AnimalTab(ModContentPack mod) { var type = AccessTools.TypeByName("AnimalTab.Command_HandlerSettings"); commandCtor = AccessTools.Constructor(type, new[] { AccessTools.TypeByName("AnimalTab.CompHandlerSettings") }); compField = AccessTools.FieldRefAccess <ThingComp>(type, "comp"); MP.RegisterSyncMethod(type, "MassSetMode").SetContext(SyncContext.MapSelected); MP.RegisterSyncMethod(type, "MassSetHandler").SetContext(SyncContext.MapSelected); MP.RegisterSyncMethod(type, "MassSetLevel").SetContext(SyncContext.MapSelected); MP.RegisterSyncWorker <Command_Action>(SyncHandlerSettingsCommand, type); type = AccessTools.TypeByName("AnimalTab.PawnColumnWorker_Handler"); MpCompat.RegisterLambdaDelegate(type, "DoHandlerFloatMenu", 0, 1, 2); MpCompat.RegisterLambdaDelegate(type, "DoMassHandlerFloatMenu", 0, 1, 4); MpCompat.harmony.Patch(AccessTools.Method(type, nameof(PawnColumnWorker.DoHeader)), prefix: new HarmonyMethod(typeof(AnimalTab), nameof(PreDoHeader)), postfix: new HarmonyMethod(typeof(AnimalTab), nameof(StopWatch))); MpCompat.harmony.Patch(AccessTools.Method(type, nameof(PawnColumnWorker.DoCell)), prefix: new HarmonyMethod(typeof(AnimalTab), nameof(PreDoCell)), postfix: new HarmonyMethod(typeof(AnimalTab), nameof(StopWatch))); type = compHandlerSettingsType = AccessTools.TypeByName("AnimalTab.CompHandlerSettings"); modeField = MP.RegisterSyncField(type, "_mode"); levelField = MP.RegisterSyncField(type, "_level"); }
private static void LatePatch() { // Window_Psyker psykerWindowType = AccessTools.TypeByName("Corruption.Psykers.Window_Psyker"); psykerWindowCompField = AccessTools.Field(psykerWindowType, "comp"); MP.RegisterSyncMethod(typeof(CorruptionPsykers), nameof(SyncedAddMinorDiscipline)); MpCompat.harmony.Patch(AccessTools.Method(psykerWindowType, nameof(Window.DoWindowContents)), prefix: new HarmonyMethod(typeof(CorruptionPsykers), nameof(PrePsykerDoWindowContents)), postfix: new HarmonyMethod(typeof(CorruptionPsykers), nameof(PostPsykerDoWindowContents))); MP.RegisterSyncMethod(typeof(CorruptionPsykers), nameof(SyncedTryLearnPower)); var psykerLearnablePowerType = AccessTools.TypeByName("Corruption.Psykers.PsykerLearnablePower"); var type = AccessTools.TypeByName("Corruption.Psykers.CompPsyker"); compPsykerTryLearnPowerMethod = AccessTools.Method(type, "TryLearnPower", new Type[] { psykerLearnablePowerType }); compPsykerAddXpMethod = AccessTools.Method(type, "AddXP"); compPsykerMainDisciplineField = AccessTools.Field(type, "MainDiscipline"); compPsykerMinorDisciplinesField = AccessTools.Field(type, "minorDisciplines"); compPsykerXpSyncField = MP.RegisterSyncField(type, "PsykerXP"); type = AccessTools.TypeByName("Corruption.Psykers.PsykerDisciplineDef"); psykerDisciplineDefAbilitiesField = AccessTools.Field(type, "abilities"); var database = typeof(DefDatabase <>).MakeGenericType(new Type[] { type }); getDefByShortHash = AccessTools.Method(database, "GetByShortHash"); MpCompat.harmony.Patch(AccessTools.Method(psykerWindowType, "DrawSelectedPower"), transpiler: new HarmonyMethod(typeof(CorruptionPsykers), nameof(Transpiler))); }
public CorruptionCore(ModContentPack mod) { // ITab_Pawn_Soul - checkboxes to allow praying and show prayers var type = AccessTools.TypeByName("Corruption.Core.Soul.ITab_Pawn_Soul"); pawnSoulITabSoulToShowGetter = AccessTools.PropertyGetter(type, "SoulToShow"); MP.RegisterSyncMethod(typeof(CorruptionCore), nameof(SyncFavourValue)); MpCompat.harmony.Patch(AccessTools.Method(type, "FillTab"), prefix: new HarmonyMethod(typeof(CorruptionCore), nameof(PreFillTab)), postfix: new HarmonyMethod(typeof(CorruptionCore), nameof(PostFillTab))); type = AccessTools.TypeByName("Corruption.Core.Soul.CompSoul"); compSoulFavourTrackerField = AccessTools.Field(type, "FavourTracker"); compSoulAllowPrayingSync = MP.RegisterSyncField(type, "PrayerTracker/AllowPraying"); compSoulShowPrayerSync = MP.RegisterSyncField(type, "PrayerTracker/ShowPrayer"); setPawnPantheonDialogType = AccessTools.TypeByName("Corruption.Core.Dialog_SetPawnPantheon"); setPawnPantheonDialogSoulField = AccessTools.Field(setPawnPantheonDialogType, "soul"); MP.RegisterSyncMethod(setPawnPantheonDialogType, "SelectionChanged"); MP.RegisterSyncWorker <object>(SyncDialogSetPawnPantheon, setPawnPantheonDialogType); type = AccessTools.TypeByName("Corruption.Core.Soul.Soul_FavourTracker"); soulFavourTrackerFavoursField = AccessTools.Field(type, "Favours"); type = AccessTools.TypeByName("Corruption.Core.Soul.FavourProgress"); favourProgressFavourValueField = AccessTools.Field(type, "favourValue"); }
public CommonSense(ModContentPack mod) { manualUnloadEnabledField = AccessTools.Field(AccessTools.TypeByName("CommonSense.Settings"), "gui_manual_unload"); var type = AccessTools.TypeByName("CommonSense.CompUnloadChecker"); MP.RegisterSyncWorker <ThingComp>(SyncComp, type); shouldUnloadSyncField = MP.RegisterSyncField(AccessTools.Field(type, "ShouldUnload")); getCompUnlockerCheckerMethod = AccessTools.Method(type, "GetChecker"); MpCompat.harmony.Patch(AccessTools.Method("RimWorld.ITab_Pawn_Gear:DrawThingRow"), prefix: new HarmonyMethod(typeof(CommonSense), nameof(CommonSensePatchPrefix)), postfix: new HarmonyMethod(typeof(CommonSense), nameof(CommonSensePatchPostix))); }
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))); }); }
public CommonSense(ModContentPack mod) { var type = AccessTools.TypeByName("CommonSense.CompUnloadChecker"); // We need to make a sync worker for this Comp, as it is initialized dynamically and might not exists at the time MP.RegisterSyncWorker <ThingComp>(SyncComp, type); shouldUnloadSyncField = MP.RegisterSyncField(AccessTools.Field(type, "ShouldUnload")); // The GetChecker method either gets an existing, or creates a new comp getCompUnlockerCheckerMethod = AccessTools.Method(type, "GetChecker"); // Watch unload bool changes MpCompat.harmony.Patch(AccessTools.Method("CommonSense.Utility:DrawThingRow"), prefix: new HarmonyMethod(typeof(CommonSense), nameof(CommonSensePatchPrefix)), postfix: new HarmonyMethod(typeof(CommonSense), nameof(CommonSensePatchPostix))); // RNG Patch PatchingUtilities.PatchUnityRand("CommonSense.JobGiver_Wander_TryGiveJob_CommonSensePatch:Postfix", false); }
public Pharmacist(ModContentPack mod) { var type = AccessTools.TypeByName("Pharmacist.PharmacistSettings"); var outer = type; setDefaultsMethod = AccessTools.MethodDelegate <SetDefaults>(AccessTools.Method(type, "SetDefaults")); medicalCareField = AccessTools.StaticFieldRefAccess <object>(AccessTools.Field(type, "medicalCare")); type = AccessTools.Inner(outer, "MedicalCare"); diseaseMarginField = MP.RegisterSyncField(type, "_diseaseMargin"); minorWoundsThresholdField = MP.RegisterSyncField(type, "_minorWoundsThreshold"); diseaseThresholdField = MP.RegisterSyncField(type, "_diseaseThreshold"); MP.RegisterSyncWorker <object>(SyncMedicalCare, type); type = AccessTools.TypeByName("Pharmacist.MainTabWindow_Pharmacist"); MpCompat.RegisterLambdaDelegate(type, "DrawCareSelectors", 0, 1, 2); MpCompat.harmony.Patch(AccessTools.Method(type, "DrawOptions"), prefix: new HarmonyMethod(typeof(Pharmacist), nameof(PreDrawOptions)), postfix: new HarmonyMethod(typeof(Pharmacist), nameof(PostDrawOptions))); }
// Token: 0x06000089 RID: 137 RVA: 0x00007314 File Offset: 0x00005514 static MultiplayerSupport() { if (!MP.enabled) { return; } MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainMinor", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainSerious", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainIntense", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainExtreme", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainMinorNone", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainSeriousNone", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainIntenseNone", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainExtremeNone", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetMalady", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetMaladyDrug", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetMaladyDrugNone", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetMaladySet", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "ClearMaladyOne", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "ClearMaladyAll", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetUsePR", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetUseDR", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetDoPrisoners", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetDoDRPrisoners", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetShowNPR", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetShowNDR", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetUseNM", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetShowR", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetBillsHPain", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetDoIfImm", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetUseRB", null); MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetUseDB", null); MP.RegisterSyncWorker <DRSettings>(new SyncWorkerDelegate <DRSettings>(MultiplayerSupport.SyncWriterForDRSettings), null, false, false); MultiplayerSupport.DRSettingsFields = new ISyncField[] { MP.RegisterSyncField(typeof(DRSettings), "DRWaitPeriod").SetBufferChanges(), MP.RegisterSyncField(typeof(DRSettings), "DRWaitPeriod2").SetBufferChanges(), MP.RegisterSyncField(typeof(DRSettings), "PainReliefWaitPeriod").SetBufferChanges() }; MultiplayerSupport.harmony.Patch(AccessTools.Method(typeof(MainTabWindow_DrugResponse), "DoWindowContents", null, null), new HarmonyMethod(typeof(MultiplayerSupport), "WatchBegin", null), new HarmonyMethod(typeof(MultiplayerSupport), "WatchEnd", null), null, null); }
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))); } }
static Multiplayer() { if (!MP.enabled) { return; } // CompGuest guestFields = new [] { MP.RegisterSyncField(typeof(CompGuest), "guestArea_int").SetBufferChanges(), MP.RegisterSyncField(typeof(CompGuest), "shoppingArea_int").SetBufferChanges(), MP.RegisterSyncField(typeof(CompGuest), nameof(CompGuest.makeFriends)), MP.RegisterSyncField(typeof(CompGuest), nameof(CompGuest.entertain)), MP.RegisterSyncField(typeof(CompGuest), nameof(CompGuest.sentAway)), }; // Hospitality_MapComponent mapFields = new [] { MP.RegisterSyncField(typeof(Hospitality_MapComponent), nameof(Hospitality_MapComponent.defaultMakeFriends)), MP.RegisterSyncField(typeof(Hospitality_MapComponent), nameof(Hospitality_MapComponent.defaultEntertain)), MP.RegisterSyncField(typeof(Hospitality_MapComponent), nameof(Hospitality_MapComponent.guestsAreWelcome)), MP.RegisterSyncField(typeof(Hospitality_MapComponent), nameof(Hospitality_MapComponent.defaultAreaRestriction)).SetBufferChanges(), MP.RegisterSyncField(typeof(Hospitality_MapComponent), nameof(Hospitality_MapComponent.defaultAreaShopping)).SetBufferChanges(), MP.RegisterSyncField(typeof(Hospitality_MapComponent), nameof(Hospitality_MapComponent.refuseGuestsUntilWeHaveBeds)), }; // Guest ITab { MP.RegisterSyncMethod(AccessTools.Method(typeof(ITab_Pawn_Guest), nameof(ITab_Pawn_Guest.SendHome))); MP.RegisterSyncMethod(AccessTools.Method(typeof(GuestUtility), nameof(GuestUtility.Recruit))); MP.RegisterSyncMethod(AccessTools.Method(typeof(ITab_Pawn_Guest), nameof(ITab_Pawn_Guest.SetAllDefaults))); } // Beds { MP.RegisterSyncMethod(AccessTools.Method(typeof(Building_GuestBed), nameof(Building_GuestBed.Swap))); MP.RegisterSyncMethod(AccessTools.Method(typeof(Building_GuestBed), nameof(Building_GuestBed.AdjustFee))); } }
public CorruptionCore(ModContentPack mod) { // ITab_Pawn_Soul - checkboxes to allow praying and show prayers var type = AccessTools.TypeByName("Corruption.Core.Soul.ITab_Pawn_Soul"); pawnSoulITabSoulToShowGetter = MethodInvoker.GetHandler(AccessTools.PropertyGetter(type, "SoulToShow")); MP.RegisterSyncMethod(typeof(CorruptionCore), nameof(SyncFavourValue)); MpCompat.harmony.Patch(AccessTools.Method(type, "FillTab"), prefix: new HarmonyMethod(typeof(CorruptionCore), nameof(PreFillTab)), postfix: new HarmonyMethod(typeof(CorruptionCore), nameof(PostFillTab))); type = AccessTools.TypeByName("Corruption.Core.Soul.CompSoul"); compSoulFavourTrackerField = AccessTools.FieldRefAccess <object>(type, "FavourTracker"); compSoulPrayerTrackerField = AccessTools.FieldRefAccess <object>(type, "PrayerTracker"); type = AccessTools.TypeByName("Corruption.Core.Dialog_SetPawnPantheon"); setPawnPantheonDialogConstructor = AccessTools.DeclaredConstructor(type); setPawnPantheonDialogSoulField = AccessTools.FieldRefAccess <ThingComp>(type, "soul"); MP.RegisterSyncMethod(type, "SelectionChanged"); MP.RegisterSyncWorker <object>(SyncDialogSetPawnPantheon, type); type = AccessTools.TypeByName("Corruption.Core.Soul.Soul_FavourTracker"); soulFavourTrackerFavoursField = AccessTools.FieldRefAccess <IList>(type, "Favours"); type = AccessTools.TypeByName("Corruption.Core.Gods.Pawn_PrayerTracker"); prayerTrackerCompSoulField = AccessTools.FieldRefAccess <ThingComp>(type, "compSoul"); prayerTrackerAllowPrayingSync = MP.RegisterSyncField(type, "AllowPraying"); prayerTrackerShowPrayerSync = MP.RegisterSyncField(type, "ShowPrayer"); MP.RegisterSyncWorker <object>(SyncPawnPrayerTracker, type); MpCompat.harmony.Patch(AccessTools.Method(type, "AdvancePrayer"), prefix: new HarmonyMethod(typeof(CorruptionCore), nameof(PreAdvancePrayer)), postfix: new HarmonyMethod(typeof(CorruptionCore), nameof(PostAdvancePrayer))); type = AccessTools.TypeByName("Corruption.Core.Soul.FavourProgress"); favourProgressFavourValueField = AccessTools.FieldRefAccess <float>(type, "favourValue"); }
public SimpleSidearmsCompat(ModContentPack mod) { Type type; // Gizmo interactions { type = AccessTools.TypeByName("PeteTimesSix.SimpleSidearms.Utilities.WeaponAssingment"); var methods = new[] { "equipSpecificWeaponTypeFromInventory", "equipSpecificWeapon", "dropSidearm", }; foreach (string method in methods) { MP.RegisterSyncMethod(AccessTools.Method(type, method)); } } { type = AccessTools.TypeByName("SimpleSidearms.rimworld.CompSidearmMemory"); var methods = new[] { "SetWeaponAsForced", "SetRangedWeaponTypeAsDefault", "SetMeleeWeaponTypeAsPreferred", "SetUnarmedAsForced", "SetUnarmedAsPreferredMelee", "UnsetForcedWeapon", "UnsetRangedWeaponDefault", "UnsetMeleeWeaponPreference", "UnsetUnarmedAsForced", "UnsetMeleeWeaponPreference", "ForgetSidearmMemory", }; foreach (string method in methods) { MP.RegisterSyncMethod(AccessTools.Method(type, method)); } // TODO: Suggest the author to encapsulate this, would simplify things so much primaryWeaponModeSyncField = MP.RegisterSyncField(AccessTools.Field(type, "primaryWeaponMode")); } // Required for primaryWeaponMode { type = AccessTools.TypeByName("SimpleSidearms.rimworld.Gizmo_SidearmsList"); MpCompat.harmony.Patch(AccessTools.Method(type, "handleInteraction"), prefix: new HarmonyMethod(typeof(SimpleSidearmsCompat), nameof(HandleInteractionPrefix)), postfix: new HarmonyMethod(typeof(SimpleSidearmsCompat), nameof(HandleInteractionPostfix))); } { type = AccessTools.TypeByName("SimpleSidearms.rimworld.CompSidearmMemory"); MpCompat.harmony.Patch(AccessTools.Method(type, "GetMemoryCompForPawn"), postfix: new HarmonyMethod(typeof(SimpleSidearmsCompat), nameof(CaptureTheMemory))); } // Used often in the Set* methods for CompSidearmMemory { type = AccessTools.TypeByName("SimpleSidearms.rimworld.ThingDefStuffDefPair"); MP.RegisterSyncWorker <object>(SyncWorkerForThingDefStuffDefPair, type); } }
static void LateLoad() { Type type; // Bed Gizmo { MP.RegisterSyncMethod(AccessTools.Method("Hospitality.Building_GuestBed:Swap")); } // Guest MainTab { MP.RegisterSyncMethod(AccessTools.Method("Hospitality.MainTab.PawnColumnWorker_AccommodationArea:SetArea")); MP.RegisterSyncMethod(AccessTools.Method("Hospitality.MainTab.PawnColumnWorker_ShoppingArea:SetArea")); MP.RegisterSyncMethod(AccessTools.Method("Hospitality.MainTab.PawnColumnWorker_Entertain:SetValue")); MP.RegisterSyncMethod(AccessTools.Method("Hospitality.MainTab.PawnColumnWorker_Recruit:SetValue")); } // Guest Tab { // force recruit button MP.RegisterSyncMethod(AccessTools.Method("Hospitality.GuestUtility:ForceRecruit")); } { type = AccessTools.TypeByName("Hospitality.ITab_Pawn_Guest"); // send home button MP.RegisterSyncMethod(AccessTools.Method(type, "SendHome")); } { // field watching as Tab shows MpCompat.harmony.Patch(AccessTools.Method(type, "FillTabGuest"), prefix: new HarmonyMethod(typeof(HospitalityCompat), nameof(WatchPrefix)), postfix: new HarmonyMethod(typeof(HospitalityCompat), nameof(WatchPostfix)) ); } { // Individual Guest type = AccessTools.TypeByName("Hospitality.CompGuest"); _chat = MP.RegisterSyncField(type, "chat"); _recruit = MP.RegisterSyncField(type, "recruit"); _arrived = MP.RegisterSyncField(type, "arrived"); _sentAway = MP.RegisterSyncField(type, "sentAway"); _areaGuest = MP.RegisterSyncField(type, "guestArea_int").SetBufferChanges(); _areaShop = MP.RegisterSyncField(type, "shoppingArea_int").SetBufferChanges(); GetCompMethod = AccessTools.Method("Verse.ThingWithComps:GetComp").MakeGenericMethod(type); MP.RegisterSyncWorker <ThingComp>(SyncWorkerForCompGuest, type); } { // Stops infinite recursion bug, seems to be outdated and unnecesary code in Hospitality. // Should report to author. MpCompat.harmony.Patch(AccessTools.Method("Hospitality.GenericUtility:DoAreaRestriction"), transpiler: new HarmonyMethod(typeof(HospitalityCompat), nameof(StopRecursiveCall)) ); } { // Default preferences type = AccessTools.TypeByName("Hospitality.Hospitality_MapComponent"); _defMode = MP.RegisterSyncField(type, "defaultInteractionMode"); _defAreaGuest = MP.RegisterSyncField(type, "defaultAreaRestriction"); _defAreaShop = MP.RegisterSyncField(type, "defaultAreaShopping"); GetMapCompMethod = AccessTools.Method(type, "Instance"); MP.RegisterSyncWorker <MapComponent>(SyncWorkerForMapComp, type); } }
// Things we don't sync as they're unfinished, and seem to not be implemented yet: // Dialog_StartRitual, which is created from BuildingSacrificialAltar public CorruptionWorship(ModContentPack mod) { // BuildingAltar { var type = AccessTools.TypeByName("Corruption.Worship.BuildingAltar"); altarNameSyncField = MP.RegisterSyncField(type, "RoomName"); altarSermonTemplatesField = AccessTools.FieldRefAccess <IList>(type, "Templates"); altarEndSermonMethod = MethodInvoker.GetHandler(AccessTools.Method(type, "EndSermon")); altarTryStartSermonMethod = MethodInvoker.GetHandler(AccessTools.Method(type, "TryStartSermon")); // The class representing a sermon, with all the required data type = AccessTools.TypeByName("Corruption.Worship.SermonTemplate"); sermonTemplateNameField = AccessTools.FieldRefAccess <string>(type, "Name"); sermonTemplatePreferredStartTimeField = AccessTools.FieldRefAccess <int>(type, "preferredStartTime"); sermonTemplateSermonDurationHoursField = AccessTools.FieldRefAccess <float>(type, "SermonDurationHours"); sermonTemplateActiveField = AccessTools.FieldRefAccess <bool>(type, "Active"); // Dialog for renaming the altar, created from TempleCardUtility type = AccessTools.TypeByName("Corruption.Worship.Dialog_RenameTemple"); MP.RegisterSyncMethod(typeof(CorruptionWorship), nameof(SyncSermonName)); MpCompat.harmony.Patch(AccessTools.Method(type, nameof(Window.DoWindowContents)), prefix: new HarmonyMethod(typeof(CorruptionWorship), nameof(RenameTemplePrefix)), postfix: new HarmonyMethod(typeof(CorruptionWorship), nameof(RenameTemplePostfix))); // Dialog for renaming a specific sermon, created from TempleCardUtility type = AccessTools.TypeByName("Corruption.Worship.Dialog_RenameSermon"); MpCompat.harmony.Patch(AccessTools.Method(type, "DoWindowContents"), prefix: new HarmonyMethod(typeof(CorruptionWorship), nameof(RenameSermonPrefix)), postfix: new HarmonyMethod(typeof(CorruptionWorship), nameof(RenameSermonPostfix))); // Dialog used for assigning a preacher, created from TempleCardUtility assignPreacherType = AccessTools.TypeByName("Corruption.Worship.Dialog_AssignPreacher"); assignPreacherAltarField = AccessTools.FieldRefAccess <Building>(assignPreacherType, "altar"); assignPreacherSermonField = AccessTools.FieldRefAccess <object>(assignPreacherType, "sermon"); MP.RegisterSyncMethod(assignPreacherType, "AssignPawn"); MP.RegisterSyncMethod(assignPreacherType, "UnassignPawn"); MP.RegisterSyncWorker <Window>(SyncDialogAssignPreacher, assignPreacherType); // Dialog used for assigning a preacher, you guessed it, created from TempleCardUtility // This is a subclass of Dialog_AssignPreacher assignAssistantType = AccessTools.TypeByName("Corruption.Worship.Dialog_AssignAssistant"); MP.RegisterSyncMethod(assignAssistantType, "AssignPawn"); MP.RegisterSyncMethod(assignAssistantType, "UnassignPawn"); MP.RegisterSyncWorker <Window>(SyncDialogAssignPreacher, assignAssistantType); } // MainTabWindow_Worship { // WonderWorker, does the work to execute the wonder defined in the MainTabWindow_Worship var wonderWorkerType = AccessTools.TypeByName("Corruption.Worship.Wonders.WonderWorker"); var wonderWorkerTargetableType = AccessTools.TypeByName("Corruption.Worship.Wonders.WonderWorker_Targetable"); wonderWorkerDefField = AccessTools.FieldRefAccess <Def>(wonderWorkerType, "Def"); wonderWorkerTargetableTargetField = AccessTools.FieldRefAccess <TargetInfo>(wonderWorkerTargetableType, "target"); wonderWorkerTargetableCanceledField = AccessTools.FieldRefAccess <bool>(wonderWorkerTargetableType, "cancelled"); MP.RegisterSyncWorker <object>(SyncWonderWorker, wonderWorkerType, isImplicit: true); MP.RegisterSyncWorker <object>(SyncWonderTargetableWorker, wonderWorkerTargetableType, isImplicit: true); MP.RegisterSyncMethod(wonderWorkerTargetableType, "StartTargeting"); MP.RegisterSyncMethod(wonderWorkerTargetableType, "CheckCancelled"); // Sync the method for each class inheriting from TryExecuteWonder // If we ever want to sync the base class too, include .Concat(type) there // But since all it does is returning false, we'll skip it // We also check if it's not a subtype of WonderWorker_Targetable, as it uses TryDoEffectOnTarget method for the reward // (and then we pray that there's not another class doing it in a special way) foreach (var subtype in wonderWorkerType.AllSubclasses().Where(x => !x.IsAssignableFrom(wonderWorkerTargetableType))) { // Include types for maximum safety var method = AccessTools.Method(subtype, "TryExecuteWonder", new[] { typeof(Def), typeof(int) }); if (method != null) { MP.RegisterSyncMethod(method); } } var methods = MpMethodUtil.GetLambda(wonderWorkerTargetableType, "TryExecuteWonderInt", lambdaOrdinals: new[] { 0, 1 }).ToArray(); wonderWorkerTargetableInnerBaseField = AccessTools.FieldRefAccess <object>(methods[0].DeclaringType, "<>4__this"); MpCompat.harmony.Patch(methods[0], prefix: new HarmonyMethod(typeof(CorruptionWorship), nameof(PreStartTargetting))); MpCompat.harmony.Patch(methods[1], prefix: new HarmonyMethod(typeof(CorruptionWorship), nameof(PreCheckCancelled))); // WonderDef, all we want is the field storing the WonderWorker for sync worker var type = AccessTools.TypeByName("Corruption.Worship.Wonders.WonderDef"); wonderDefWorkerIntField = AccessTools.FieldRefAccess <object>(type, "workerInt"); var database = typeof(DefDatabase <>).MakeGenericType(new Type[] { type }); getDefByShortHash = MethodInvoker.GetHandler(AccessTools.Method(database, "GetByShortHash")); // GlobalWorshipTracker, we sync favor usage when the user decides to purchase a wonder type = AccessTools.TypeByName("Corruption.Worship.GlobalWorshipTracker"); MP.RegisterSyncMethod(type, "ConsumeFavourFor"); } LongEventHandler.ExecuteWhenFinished(LatePatch); }
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)); } }