public static IEnumerable <MethodInfo> GetLambda(Type parentType, string parentMethod = null, MethodType parentMethodType = MethodType.Normal, Type[] parentArgs = null, params int[] lambdaOrdinals) { foreach (int ord in lambdaOrdinals) { yield return(MpMethodUtil.GetLambda(parentType, parentMethod, parentMethodType, parentArgs, ord)); } }
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)); } }
static IEnumerable <ISyncMethod> RegisterLambdaMethod_Impl(Type parentType, string parentMethod, params int[] lambdaOrdinals) { foreach (int ord in lambdaOrdinals) { var method = MpMethodUtil.GetLambda(parentType, parentMethod, MethodType.Normal, null, ord); yield return(MP.RegisterSyncMethod(method)); } }
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 RimsentialSpaceports(ModContentPack mod) { // Gizmos { var type = AccessTools.TypeByName("Spaceports.Buildings.Building_Beacon"); MpCompat.RegisterLambdaMethod(type, "GetGizmos", 1, 2, 3); MP.RegisterSyncMethod(type, "ConfirmAction"); type = AccessTools.TypeByName("Spaceports.Buildings.Building_Shuttle"); MpCompat.RegisterLambdaMethod(type, "GetGizmos", 0, 1); type = AccessTools.TypeByName("Spaceports.Buildings.Building_ShuttlePad"); MP.RegisterSyncMethod(type, "SetAccessState"); type = AccessTools.TypeByName("Spaceports.Buildings.Building_ShuttleSpot"); MP.RegisterSyncMethod(type, "SetAccessState"); } // Choice letters { 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("Spaceports.Letters.PrisonerTransferLetter"); var methods = MpMethodUtil.GetLambda(type, "Choices", MethodType.Getter, null, 0, 1, 2).ToArray(); MP.RegisterSyncMethod(methods[0]); MP.RegisterSyncMethod(methods[1]); MP.RegisterSyncMethod(methods[2]); rejectMethods[type] = methods[2]; var typeNames = new[] { "Spaceports.Letters.InterstellarDerelictLetter", "Spaceports.Letters.MedevacLetter", "Spaceports.Letters.MysteryCargoLetter", "Spaceports.Letters.SpicyPawnLendingLetter", }; 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]; } } }
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 MpMethodUtil.GetLambda(type, "CompGetGizmosExtra", MethodType.Normal, null, 1, 2)) { MpCompat.harmony.Patch(method, prefix: new HarmonyMethod(typeof(SRTSExpanded), nameof(PreSyncBombType)), postfix: new HarmonyMethod(typeof(SRTSExpanded), nameof(PostSyncBombType))); } }
public AndroidTiers(ModContentPack mod) { // RNG { var methods = new[] { "MOARANDROIDS.CompHeatSensitive:PostSpawnSetup", "MOARANDROIDS.CompHeatSensitive:CheckTemperature", "MOARANDROIDS.StartingPawnUtility_Patch+NewGeneratedStartingPawn_Patch:Listener", "MOARANDROIDS.AndroidFactionDialogOverride:Postfix", "MOARANDROIDS.MultiplePawnRacesAtStart:Postfix", "MOARANDROIDS.Recipe_MemoryCorruptionChance:RandomCorruption", "MOARANDROIDS.Recipe_AndroidRewireSurgery:RandomCorruption", "MOARANDROIDS.Recipe_RemoveSentience:RandomCorruption", "MOARANDROIDS.Recipe_RerollTraits:RandomCorruption", "MOARANDROIDS.StockGenerator_SlaveAndroids+<GenerateThings>d__0:MoveNext", }; PatchingUtilities.PatchSystemRand(methods, false); } // Gizmos { var type = AccessTools.TypeByName("MOARANDROIDS.CompAndroidState"); MpCompat.RegisterLambdaDelegate(type, "CompGetGizmosExtra", 0, 2, 4, 5, 7, 10, 11, 12, 14); type = AccessTools.TypeByName("MOARANDROIDS.CompAutoDoor"); MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 0, 1); type = AccessTools.TypeByName("MOARANDROIDS.CompRemotelyControlledTurret"); MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 0); // Really ugly... We can't sync the pawns directly here, as they're inaccessible - the ThingComp is holding them inside // however, it does not implement IThingHolder or whatever it's supposed to in cases like those // so we do a lot of workarounds to not rely on the pawn sync worker type = compSkyCloudCoreType = AccessTools.TypeByName("MOARANDROIDS.CompSkyCloudCore"); skyCloudCoreStoredMindsField = AccessTools.FieldRefAccess <List <Pawn> >(type, "storedMinds"); MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 6, 10, 11, 12, 13, 26, 27); var methods = MpMethodUtil.GetLambda(type, "CompGetGizmosExtra", MethodType.Normal, null, 4, 16, 24); foreach (var method in methods) { MP.RegisterSyncMethod(method); MP.RegisterSyncWorker <object>(SyncInnerClassWithPawn, method.DeclaringType, shouldConstruct: true); } var methodsArray = MpMethodUtil.GetLambda(type, "CompGetGizmosExtra", MethodType.Normal, null, 6, 11, 27).ToArray(); skyCloudCoreGetGizmos6 = MethodInvoker.GetHandler(methodsArray[0]); skyCloudCoreGetGizmos11 = MethodInvoker.GetHandler(methodsArray[1]); skyCloudCoreGetGizmos27 = MethodInvoker.GetHandler(methodsArray[2]); MP.RegisterSyncMethod(typeof(AndroidTiers), nameof(SyncedGetGizmos6)); MP.RegisterSyncMethod(typeof(AndroidTiers), nameof(SyncedGetGizmos11)); MP.RegisterSyncMethod(typeof(AndroidTiers), nameof(SyncedGetGizmos27)); MpCompat.harmony.Patch(methodsArray[0], prefix: new HarmonyMethod(typeof(AndroidTiers), nameof(PreCompGetGizmos6))); MpCompat.harmony.Patch(methodsArray[1], prefix: new HarmonyMethod(typeof(AndroidTiers), nameof(PreCompGetGizmos11))); MpCompat.harmony.Patch(methodsArray[2], prefix: new HarmonyMethod(typeof(AndroidTiers), nameof(PreCompGetGizmos27))); type = AccessTools.TypeByName("MOARANDROIDS.CompSkyMind"); MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 1, 3); type = compSurrogateOwnerType = AccessTools.TypeByName("MOARANDROIDS.CompSurrogateOwner"); surrogateOwnerSkyCloudHostField = AccessTools.FieldRefAccess <Thing>(type, "skyCloudHost"); MpCompat.RegisterLambdaDelegate(type, "CompGetGizmosExtra", 1, 3, 5, 9, 10, 13, 16, 19, 23); type = AccessTools.TypeByName("MOARANDROIDS.CPaths"); MpCompat.RegisterLambdaDelegate(type, "QEE_BuildingPawnVatGrower_GetGizmosPostfix", 2, 5, 8); // CompComputer - all gizmos end up using a designator to pick a target, so we sync the designator } // Designators { var type = AccessTools.TypeByName("MOARANDROIDS.Designator_SurrogateToHack"); surrogateToHackConstructor = AccessTools.Constructor(type, new[] { typeof(int) }); surrogateToHackPosField = AccessTools.FieldRefAccess <IntVec3>(type, "pos"); surrogateToHackTargetField = AccessTools.FieldRefAccess <Pawn>(type, "target"); surrogateToHackMapField = AccessTools.FieldRefAccess <Map>(type, "cmap"); surrogateToHackHackTypeField = AccessTools.FieldRefAccess <int>(type, "hackType"); MP.RegisterSyncWorker <Designator>(SyncSurrogateToHackDesignator, type); type = AccessTools.TypeByName("MOARANDROIDS.Designator_AndroidToControl"); androidToControlConstructor = AccessTools.Constructor(type, new[] { typeof(Pawn), typeof(bool) }); androidToControlPawnField = AccessTools.FieldRefAccess <Pawn>(type, "controller"); androidToControlFromSkyCloudField = AccessTools.FieldRefAccess <bool>(type, "fromSkyCloud"); androidToControlKindOfTargetField = AccessTools.FieldRefAccess <int>(type, "kindOfTarget"); androidToControlPosField = AccessTools.FieldRefAccess <IntVec3>(type, "pos"); androidToControlTargetField = AccessTools.FieldRefAccess <Thing>(type, "target"); androidToControlMapField = AccessTools.FieldRefAccess <Map>(type, "cmap"); MP.RegisterSyncWorker <Designator>(SyncAndroidToControlDesignator, type); MP.RegisterSyncMethod(typeof(AndroidTiers), nameof(SyncedConnectToSkyMind)); MpCompat.harmony.Patch(AccessTools.Method(type, "CanDesignateThing"), transpiler: new HarmonyMethod(typeof(AndroidTiers), nameof(ReplaceConnectToSkyMind))); } // Dialogs { var type = AccessTools.TypeByName("MOARANDROIDS.Dialog_SkillUp"); skillUpDialogConstructor = AccessTools.Constructor(type, new[] { typeof(Pawn), typeof(bool) }); skillUpGetNbPointsWantedToBuyMethod = MethodInvoker.GetHandler(AccessTools.Method(type, "getNbPointsWantedToBuy")); skillUpAndroidField = AccessTools.FieldRefAccess <Pawn>(type, "android"); skillUpSkillDefListField = AccessTools.FieldRefAccess <List <SkillDef> >(type, "sd"); skillUpPointsField = AccessTools.FieldRefAccess <List <int> >(type, "points"); skillUpPassionsStateField = AccessTools.FieldRefAccess <List <int> >(type, "points"); skillUpPointsNeededPerSkillField = AccessTools.FieldRefAccess <int>(type, "pointsNeededPerSkill"); skillUppointsNeededToIncreasePassionField = AccessTools.FieldRefAccess <int>(type, "pointsNeededToIncreasePassion"); MP.RegisterSyncMethod(typeof(AndroidTiers), nameof(SyncedSkillUpDialogAccept)); MP.RegisterSyncWorker <Window>(SyncSkillUpDialog, type); MpCompat.harmony.Patch(AccessTools.Method(type, "DoWindowContents"), transpiler: new HarmonyMethod(typeof(AndroidTiers), nameof(ReplaceButton))); type = AccessTools.TypeByName("MOARANDROIDS.Utils"); gcAttpCompField = AccessTools.StaticFieldRefAccess <GameComponent>(AccessTools.Field(type, "GCATPP")); type = AccessTools.TypeByName("MOARANDROIDS.GC_ATPP"); gameComponentDecSkillPointsMethod = MethodInvoker.GetHandler(AccessTools.Method(type, "decSkillPoints")); gameComponentConnectUserMethod = MethodInvoker.GetHandler(AccessTools.Method(type, "connectUser")); gameComponentConnectedThingField = AccessTools.FieldRefAccess <HashSet <Thing> >(type, "connectedThing"); gameComponentNbSlotField = AccessTools.FieldRefAccess <int>(type, "nbSlot"); } // Choice letters { 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); var typeNames = new[] { "MOARANDROIDS.ChoiceLetter_RansomDemand", "MOARANDROIDS.ChoiceLetter_RansomwareDemand", }; foreach (var typeName in typeNames) { type = AccessTools.TypeByName(typeName); rejectMethods.Add(type, AccessTools.Method(typeof(ChoiceLetter), nameof(ChoiceLetter.Option_Reject))); // Generic reject option var method = MpMethodUtil.GetLambda(type, "Choices", MethodType.Getter, lambdaOrdinal: 0); MP.RegisterSyncMethod(method); } } }
// 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); }
public DragonsDescent(ModContentPack mod) { // Incubator { var type = AccessTools.TypeByName("DD.CompEggIncubator"); var methods = MpCompat.RegisterLambdaMethod(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 = MpMethodUtil.GetLambda(type, "get_Gizmo", MethodType.Normal, null, 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.RegisterLambdaMethod(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"); } }