diff --git a/Source/Mods/AllowTool.cs b/Source/Mods/AllowTool.cs index 066341a..9b31a09 100644 --- a/Source/Mods/AllowTool.cs +++ b/Source/Mods/AllowTool.cs @@ -143,9 +143,6 @@ public AllowTool(ModContentPack mod) // Recache haul urgently deterministically (currently uses Time.unscaledTime) { - // Used by DeterministicallyHandleReCaching - PatchingUtilities.InitCancelInInterface(); - var type = AccessTools.TypeByName("AllowTool.HaulUrgentlyCacheHandler"); MpCompat.harmony.Patch(AccessTools.Method(type, "RecacheIfNeeded"), prefix: new HarmonyMethod(typeof(AllowTool), nameof(DeterministicallyHandleReCaching))); @@ -306,7 +303,7 @@ private static bool DeterministicallyHandleReCaching(ref float currentTime) if (!MP.IsInMultiplayer) return true; // Can be called from MonoBehaviour.FixedUpdate and operates on a single map only, cancel in such cases - if (PatchingUtilities.ShouldCancel) + if (MP.InInterface) return false; currentTime = Find.TickManager.TicksGame; diff --git a/Source/Mods/MoreFactionInteraction.cs b/Source/Mods/MoreFactionInteraction.cs index 826416c..bb85fa2 100644 --- a/Source/Mods/MoreFactionInteraction.cs +++ b/Source/Mods/MoreFactionInteraction.cs @@ -1,5 +1,4 @@ -using System; -using System.Linq; +using System.Linq; using HarmonyLib; using Multiplayer.API; using Verse; @@ -14,16 +13,11 @@ internal class MoreFactionInteraction { public MoreFactionInteraction(ModContentPack mod) { - Type type = AccessTools.TypeByName("Multiplayer.Client.Patches.CloseDialogsForExpiredLetters"); - // We should probably add this to the API the next time we update it - // TODO: Expose in API - var registerAction = AccessTools.Method(type, "RegisterDefaultLetterChoice"); - - type = AccessTools.TypeByName("MoreFactionInteraction.ChoiceLetter_ReverseTradeRequest"); + var 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]); - registerAction.Invoke(null, new object[] {methods[1], type}); + MP.RegisterDefaultLetterChoice(methods[1], type); var typeNames = new[] { @@ -38,7 +32,7 @@ public MoreFactionInteraction(ModContentPack mod) methods = MpMethodUtil.GetLambda(type, "Choices", MethodType.Getter, null, 0, 1).ToArray(); MP.RegisterSyncMethod(methods[0]); MP.RegisterSyncMethod(methods[1]); - registerAction.Invoke(null, new object[] {methods[1], type}); + MP.RegisterDefaultLetterChoice(methods[1], type); } typeNames = new[] diff --git a/Source/Mods/PerformanceOptimizer.cs b/Source/Mods/PerformanceOptimizer.cs index 2d6f472..ffa9c41 100644 --- a/Source/Mods/PerformanceOptimizer.cs +++ b/Source/Mods/PerformanceOptimizer.cs @@ -174,7 +174,7 @@ private static IDictionary ReturnCorrectCache(IDictionary simulationCache) return null; // If simulation, return normal cache - if (!PatchingUtilities.ShouldCancel) + if (!MP.InInterface) return simulationCache; // If interface, try to return the cache from our dictionary diff --git a/Source/Mods/ResearchPowl.cs b/Source/Mods/ResearchPowl.cs index d941db9..bb42d42 100644 --- a/Source/Mods/ResearchPowl.cs +++ b/Source/Mods/ResearchPowl.cs @@ -95,7 +95,7 @@ private static void SyncResearchNode(SyncWorker sync, ref object node) private static bool PreSanityCheck(WorldComponent __instance, IList ____queue) { // Let it run normally in SP or in synced commands (or other contexts not needing syncing) - if (!PatchingUtilities.ShouldCancel) + if (!MP.InInterface) return true; foreach (var node in ____queue) diff --git a/Source/Mods/RimsentialSpaceports.cs b/Source/Mods/RimsentialSpaceports.cs index 473bfa7..933c135 100644 --- a/Source/Mods/RimsentialSpaceports.cs +++ b/Source/Mods/RimsentialSpaceports.cs @@ -33,16 +33,12 @@ public RimsentialSpaceports(ModContentPack mod) // 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 registerAction = AccessTools.DeclaredMethod(type, "RegisterDefaultLetterChoice"); - - type = AccessTools.TypeByName("Spaceports.Letters.PrisonerTransferLetter"); + var 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]); - registerAction.Invoke(null, new object[] { methods[2], type }); + MP.RegisterDefaultLetterChoice(methods[2], type); var typeNames = new[] { @@ -58,9 +54,9 @@ public RimsentialSpaceports(ModContentPack mod) methods = MpMethodUtil.GetLambda(type, "Choices", MethodType.Getter, null, 0, 1).ToArray(); MP.RegisterSyncMethod(methods[0]); MP.RegisterSyncMethod(methods[1]); - registerAction.Invoke(null, new object[] { methods[1], type }); + MP.RegisterDefaultLetterChoice(methods[1], type); } } } } -} +} \ No newline at end of file diff --git a/Source/Mods/RunandGun.cs b/Source/Mods/RunandGun.cs index 8e3ab4a..5eb75fe 100644 --- a/Source/Mods/RunandGun.cs +++ b/Source/Mods/RunandGun.cs @@ -15,7 +15,7 @@ public RunandGun(ModContentPack mod) { Type type = AccessTools.TypeByName("RunAndGun.Harmony.Pawn_DraftController_GetGizmos_Patch"); - MP.RegisterSyncDelegate(type, "<>c__DisplayClass0_0", "b__1"); + MP.RegisterSyncDelegateLambda(type, "Postfix", 1); PatchingUtilities.PatchSystemRand("RunAndGun.Harmony.MentalStateHandler_TryStartMentalState:shouldRunAndGun", false); } diff --git a/Source/Mods/SRTSExpanded.cs b/Source/Mods/SRTSExpanded.cs index 11018a2..2980558 100644 --- a/Source/Mods/SRTSExpanded.cs +++ b/Source/Mods/SRTSExpanded.cs @@ -56,7 +56,6 @@ private static void DelayedPatch(string modId) var tryLaunch = AccessTools.Method(type, "TryLaunch"); tryLaunchMethod = MethodInvoker.GetHandler(tryLaunch); - PatchingUtilities.InitCancelInInterface(); MpCompat.harmony.Patch(tryLaunch, prefix: new HarmonyMethod(typeof(SRTSExpanded), nameof(PreTryLaunch))); MP.RegisterSyncMethod(typeof(SRTSExpanded), nameof(SyncedLaunch)).ExposeParameter(2); @@ -83,7 +82,7 @@ private static void PostSyncBombType() private static bool PreTryLaunch(ThingComp __instance, int destinationTile, TransportPodsArrivalAction arrivalAction, Caravan cafr = null) { // Let the method run only if it's synced call - if (!PatchingUtilities.ShouldCancel) + if (!MP.InInterface) return true; var caravanFieldValue = caravanField(__instance); @@ -142,7 +141,7 @@ private static void PatchCarryalls() private static bool PreAddPawns(ThingComp __instance, List ___tmpAllowedPawns) { // Let the method run only if it's synced call - if (!PatchingUtilities.ShouldCancel) + if (!MP.InInterface) return true; SyncedAddPawns(__instance, ___tmpAllowedPawns); diff --git a/Source/Mods/SimpleSidearms.cs b/Source/Mods/SimpleSidearms.cs index a12b77c..65675bb 100644 --- a/Source/Mods/SimpleSidearms.cs +++ b/Source/Mods/SimpleSidearms.cs @@ -123,7 +123,7 @@ private static void HandleInteractionPostfix() [MpCompatPrefix("PeteTimesSix.SimpleSidearms.Utilities.GettersFilters", "findBestRangedWeapon", 8)] private static bool PrePrimaryVerbMethodCall(ThingWithComps __0, ref bool __result) { - if (!PatchingUtilities.ShouldCancel) + if (!MP.InInterface) return true; var comp = __0.GetComp(); diff --git a/Source/Mods/VanillaAnimalsEndangered.cs b/Source/Mods/VanillaAnimalsEndangered.cs index ffb5cdf..9885097 100644 --- a/Source/Mods/VanillaAnimalsEndangered.cs +++ b/Source/Mods/VanillaAnimalsEndangered.cs @@ -14,7 +14,7 @@ public VanillaAnimalsEndangered(ModContentPack mod) { var type = AccessTools.TypeByName("VanillaAnimalsExpandedEndangered.Pawn_GetGizmos_Patch"); - MP.RegisterSyncDelegate(type, "<>c__DisplayClass3_0", "b__1"); + MP.RegisterSyncDelegateLambda(type, "Postfix", 1); } } } diff --git a/Source/Mods/VanillaExpandedFramework.cs b/Source/Mods/VanillaExpandedFramework.cs index 0a95c63..0b17ea9 100644 --- a/Source/Mods/VanillaExpandedFramework.cs +++ b/Source/Mods/VanillaExpandedFramework.cs @@ -69,13 +69,6 @@ public VanillaExpandedFramework(ModContentPack mod) #region Shared sync workers and patches - // MP - ThingsById - private static Dictionary thingsById; - - // Right now only used by teleporter doors. Could potentially be used by other mods. - // It's a separate method instead of being always initialized in case this ever changes in MP and causes issues here. - private static void EnsureThingsByIdDictionaryActive() => thingsById ??= (Dictionary)AccessTools.Field(AccessTools.TypeByName("Multiplayer.Client.ThingsById"), "thingsById").GetValue(null); - private static void SyncCommandWithBuilding(SyncWorker sync, ref Command command) { var traverse = Traverse.Create(command); @@ -196,7 +189,6 @@ private static void PatchExtraPregnancyApproaches() private static void PatchExpandableProjectile() { - PatchingUtilities.InitCancelInInterface(); MpCompat.harmony.Patch(AccessTools.DeclaredPropertyGetter("VFECore.ExpandableProjectile:StartingPosition"), prefix: new HarmonyMethod(typeof(VanillaExpandedFramework), nameof(PreStartingPositionGetter)), postfix: new HarmonyMethod(typeof(VanillaExpandedFramework), nameof(PostStartingPositionGetter))); @@ -205,7 +197,7 @@ private static void PatchExpandableProjectile() private static void PreStartingPositionGetter(Vector3 ___startingPosition, bool ___pawnMoved, ref (Vector3, bool)? __state) { // If in interface, store the current values. - if (PatchingUtilities.ShouldCancel) + if (MP.InInterface) __state = (___startingPosition, ___pawnMoved); } @@ -943,22 +935,21 @@ private static void SyncFactionDiscoveryDialog(SyncWorker sync, ref Window windo private static ConstructorInfo renameDoorTeleporterDialogConstructor; private static AccessTools.FieldRef renameDoorTeleporterDialogThingField; - // DoorTeleporter.<>c__DisplayClass26_0 - private static Type innerClassDoorTeleporterLocalsType; - private static AccessTools.FieldRef innerClassDoorTeleporterThisField; - private static AccessTools.FieldRef innerClassDoorTeleporterPawnField; - - // DoorTeleporter.<>c__DisplayClass26_1 - private static AccessTools.FieldRef innerClassDoorTeleporterLocalsField; - private static AccessTools.FieldRef innerClassDoorTeleporterTargetField; - private static void PatchDoorTeleporter() { var type = AccessTools.TypeByName("VFECore.DoorTeleporter"); // Destroy MpCompat.RegisterLambdaMethod(type, "GetDoorTeleporterGismoz", 0).SetContext(SyncContext.None); // Teleport to x - MpCompat.RegisterLambdaDelegate(type, nameof(ThingWithComps.GetFloatMenuOptions), 0); + MpCompat.RegisterLambdaDelegate(type, nameof(ThingWithComps.GetFloatMenuOptions), 0)[0] + .TransformField("doorTeleporter", Serializer.New( + t => t.thingIDNumber, + id => + { + MP.TryGetThingById(id, out var thing); + return thing; + }), + true); renameDoorTeleporterDialogType = AccessTools.TypeByName("VFECore.Dialog_RenameDoorTeleporter"); renameDoorTeleporterDialogConstructor = AccessTools.DeclaredConstructor(renameDoorTeleporterDialogType, new[] { type }); @@ -974,51 +965,6 @@ private static void PatchDoorTeleporter() if (dialog is Window w) Find.WindowStack.TryRemove(w); }); - - var innerClassMethod = MpMethodUtil.GetLambda(type, nameof(ThingWithComps.GetFloatMenuOptions)); - - if (innerClassMethod == null) - Log.Error("Couldn't find inner class 1 for door teleporters, they won't work."); - else - { - var fields = AccessTools.GetDeclaredFields(innerClassMethod.DeclaringType); - if (fields.Count != 2) - Log.Error($"Found incorrect amount of fields while trying to register door teleporters (inner class 1) - found: {fields.Count}, expected: 2."); - - foreach (var field in fields) - { - if (field.FieldType == type) - innerClassDoorTeleporterTargetField = AccessTools.FieldRefAccess(field); - else - { - innerClassDoorTeleporterLocalsType = field.FieldType; - innerClassDoorTeleporterLocalsField = AccessTools.FieldRefAccess(field); - } - } - - if (innerClassDoorTeleporterLocalsType == null) - { - Log.Error("Couldn't find inner class 0 for door teleporters, they won't work."); - } - else - { - fields = AccessTools.GetDeclaredFields(innerClassDoorTeleporterLocalsType); - if (fields.Count != 2) - Log.Error($"Found incorrect amount of fields while trying to register door teleporters (inner class 0) - found: {fields.Count}, expected: 2."); - - foreach (var field in fields) - { - if (field.FieldType == type) - innerClassDoorTeleporterThisField = AccessTools.FieldRefAccess(field); - else if (field.FieldType == typeof(Pawn)) - innerClassDoorTeleporterPawnField = AccessTools.FieldRefAccess(field); - } - - EnsureThingsByIdDictionaryActive(); - MP.RegisterSyncWorker(SyncInnerDoorTeleporterClass, innerClassMethod.DeclaringType, shouldConstruct: true); - MP.RegisterSyncMethod(innerClassMethod); - } - } } private static void SyncDialogRenameDoorTeleporter(SyncWorker sync, ref Dialog_Rename dialog) @@ -1043,33 +989,6 @@ private static void SyncDialogRenameDoorTeleporter(SyncWorker sync, ref Dialog_R } } - private static void SyncInnerDoorTeleporterClass(SyncWorker sync, ref object obj) - { - if (sync.isWriting) - { - var locals = innerClassDoorTeleporterLocalsField(obj); - var target = innerClassDoorTeleporterTargetField(obj); - - // The target is on a different map, so we can't just sync it as MP does not allow it. - // We need to sync the ID number and manually get the target by ID instead. - sync.Write(target.thingIDNumber); - sync.Write(innerClassDoorTeleporterThisField(locals)); - sync.Write(innerClassDoorTeleporterPawnField(locals)); - } - else - { - // shouldConstruct: true, so obj is constructed - // but we need to construct the other object used for locals - var locals = Activator.CreateInstance(innerClassDoorTeleporterLocalsType); - innerClassDoorTeleporterLocalsField(obj) = locals; - - // Get the target by ID. - innerClassDoorTeleporterTargetField(obj) = thingsById.GetValueSafe(sync.Read()); - innerClassDoorTeleporterThisField(locals) = sync.Read(); - innerClassDoorTeleporterPawnField(locals) = sync.Read(); - } - } - #endregion #region Special Terrain diff --git a/Source/Mods/VanillaFactionsPirates.cs b/Source/Mods/VanillaFactionsPirates.cs index b26a5af..6e44460 100644 --- a/Source/Mods/VanillaFactionsPirates.cs +++ b/Source/Mods/VanillaFactionsPirates.cs @@ -50,7 +50,6 @@ public VanillaFactionsPirates(ModContentPack mod) // The code using the ability returns true, and we need to make sure it happens because // as far as I understand, sync method on non-void methods returns default value (which // would be false for bool) - PatchingUtilities.InitCancelInInterface(); MP.RegisterSyncMethod(typeof(VanillaFactionsPirates), nameof(SyncedShieldDetonation)); MpCompat.harmony.Patch(AccessTools.Method("VFEPirates.Verb_ShieldDetonation:TryCastShot"), prefix: new HarmonyMethod(typeof(VanillaFactionsPirates), nameof(PreShieldDetonation))); @@ -246,7 +245,7 @@ private static IEnumerable ReplaceButton(IEnumerable MP.RegisterSyncDelegate(AccessTools.TypeByName("VPEAutoPlow.Patch_Zone_Growing_GetGizmos"), "<>c__DisplayClass0_0", "b__1"); + => MP.RegisterSyncDelegateLambda(AccessTools.TypeByName("VPEAutoPlow.Patch_Zone_Growing_GetGizmos"), "Add_AllowAutoPlow_Gizmo", 1); } } diff --git a/Source/Mods/VanillaRacesAndroid.cs b/Source/Mods/VanillaRacesAndroid.cs index fddac8e..428136c 100644 --- a/Source/Mods/VanillaRacesAndroid.cs +++ b/Source/Mods/VanillaRacesAndroid.cs @@ -222,10 +222,7 @@ private static void LatePatch() // https://github.com/rwmt/Multiplayer/blob/c7a673a63178257fbcbbe4812b0d48f0e8df2593/Source/Client/Syncing/Game/SyncDelegates.cs#L277-L279 // https://github.com/rwmt/Multiplayer/blob/c7a673a63178257fbcbbe4812b0d48f0e8df2593/Source/Client/Syncing/Game/SyncDelegates.cs#L331-L356 - var type = AccessTools.TypeByName("Multiplayer.Client.Patches.CloseDialogsForExpiredLetters"); - var registerAction = AccessTools.DeclaredMethod(type, "RegisterDefaultLetterChoice"); - - type = AccessTools.TypeByName("VREAndroids.ChoiceLetter_AndroidAwakened"); + var type = AccessTools.TypeByName("VREAndroids.ChoiceLetter_AndroidAwakened"); var method = AccessTools.DeclaredMethod(type, "MakeChoices"); MP.RegisterSyncMethod(method).ExposeParameter(1); @@ -243,13 +240,7 @@ private static void LatePatch() passionChoicesField = AccessTools.FieldRefAccess>(type, "passionChoices"); traitChoicesField = AccessTools.FieldRefAccess>(type, "traitChoices"); - registerAction.Invoke( - null, - new object[] - { - AccessTools.DeclaredMethod(typeof(VanillaRacesAndroid), nameof(DefaultDialogSelection)), - type - }); + MP.RegisterDefaultLetterChoice(AccessTools.DeclaredMethod(typeof(VanillaRacesAndroid), nameof(DefaultDialogSelection)), type); type = AccessTools.TypeByName("VREAndroids.Dialog_AndroidAwakenedChoices"); MpCompat.harmony.Patch(AccessTools.DeclaredMethod(type, nameof(Window.DoWindowContents)), diff --git a/Source/PatchingUtilities.cs b/Source/PatchingUtilities.cs index 511cfd0..c79ed73 100644 --- a/Source/PatchingUtilities.cs +++ b/Source/PatchingUtilities.cs @@ -4,6 +4,7 @@ using System.Reflection; using System.Reflection.Emit; using HarmonyLib; +using Multiplayer.API; using RimWorld; using Verse; @@ -262,17 +263,6 @@ internal static IEnumerable FixUnityRNG(IEnumerable - /// Returns during ticking and synced commands. - /// Should be used to prevent any gameplay-related changes from being executed from UI or other unsafe contexts. - /// Requires calling or any method, otherwise it will always be . - /// - public static bool ShouldCancel => inInterfaceMethod(); - - private delegate bool InInterfaceDelegate(); - private static InInterfaceDelegate inInterfaceMethod = () => false; - private static bool inInterfaceMethodInitialized = false; - /// Patches the method to cancel the call if it ends up being called from the UI /// Names (type colon name) of the methods to patch public static void PatchCancelInInterface(params string[] methodNames) => PatchCancelInInterface(methodNames as IEnumerable); @@ -298,7 +288,6 @@ public static void PatchCancelInInterface(IEnumerable methodNames) /// Methods to patch public static void PatchCancelInInterface(IEnumerable methods) { - InitCancelInInterface(); var patch = new HarmonyMethod(typeof(PatchingUtilities), nameof(CancelInInterface)); foreach (var method in methods) PatchCancelInInterfaceInternal(method, patch); @@ -329,7 +318,6 @@ public static void PatchCancelInInterfaceSetResultToTrue(IEnumerable met /// Methods to patch public static void PatchCancelInInterfaceSetResultToTrue(IEnumerable methods) { - InitCancelInInterface(); var patch = new HarmonyMethod(typeof(PatchingUtilities), nameof(CancelInInterfaceSetResultToTrue)); foreach (var method in methods) PatchCancelInInterfaceInternal(method, patch); @@ -338,40 +326,11 @@ public static void PatchCancelInInterfaceSetResultToTrue(IEnumerable private static void PatchCancelInInterfaceInternal(MethodBase method, HarmonyMethod patch) => MpCompat.harmony.Patch(method, prefix: patch); - /// - /// Gets access to Multiplayer.Client.Multiplayer:InInterface getter to check if execution should be cancelled. - /// Called automatically from any method. - /// - public static void InitCancelInInterface() - { - if (inInterfaceMethodInitialized) - return; - - // Stop repeated attempts to initialize when finished or failed - inInterfaceMethodInitialized = true; - - var inInterface = AccessTools.PropertyGetter("Multiplayer.Client.Multiplayer:InInterface"); - if (inInterface == null) - { - Log.Error("Failed getting InInterface getter, was its location changed in MP?"); - return; - } - - try - { - inInterfaceMethod = AccessTools.MethodDelegate(inInterface); - } - catch (Exception e) - { - Log.Error($"Failed setting up InInterface delegate with exception:\n{e}"); - } - } - - private static bool CancelInInterface() => !ShouldCancel; + private static bool CancelInInterface() => !MP.InInterface; private static bool CancelInInterfaceSetResultToTrue(ref bool __result) { - if (!ShouldCancel) + if (!MP.InInterface) return true; __result = true; diff --git a/Source_Referenced/CashRegister.cs b/Source_Referenced/CashRegister.cs index 23f980d..61ce0a1 100644 --- a/Source_Referenced/CashRegister.cs +++ b/Source_Referenced/CashRegister.cs @@ -33,7 +33,6 @@ public CashRegister(ModContentPack mod) MP.RegisterSyncWorker(SyncShift); - PatchingUtilities.InitCancelInInterface(); MpCompat.harmony.Patch(AccessTools.DeclaredMethod(typeof(CompAssignableToPawn), nameof(CompAssignableToPawn.TryAssignPawn)), prefix: new HarmonyMethod(typeof(CashRegister), nameof(PreTryAssignPawn))); MpCompat.harmony.Patch(AccessTools.DeclaredMethod(typeof(CompAssignableToPawn), nameof(CompAssignableToPawn.TryUnassignPawn)), @@ -195,7 +194,7 @@ private static void SyncShift(SyncWorker sync, ref Shift shift) private static bool PreTryAssignPawn(CompAssignableToPawn __instance, Pawn pawn) { // Only catch the comp from CashRegister mod - if (!MP.IsInMultiplayer || !PatchingUtilities.ShouldCancel || __instance is not CompAssignableToPawn_Shifts shift) + if (!MP.IsInMultiplayer || !MP.InInterface || __instance is not CompAssignableToPawn_Shifts shift) return true; SyncedTryAssignPawnShifts(shift, pawn, GetRegisterShiftToIndex(shift)); @@ -207,7 +206,7 @@ private static bool PreTryAssignPawn(CompAssignableToPawn __instance, Pawn pawn) private static bool PreTryUnassignPawn(CompAssignableToPawn __instance, Pawn pawn) { // Only catch the comp from CashRegister mod - if (!MP.IsInMultiplayer || !PatchingUtilities.ShouldCancel || __instance is not CompAssignableToPawn_Shifts shift) + if (!MP.IsInMultiplayer || !MP.InInterface || __instance is not CompAssignableToPawn_Shifts shift) return true; SyncedTryUnassignPawnShifts(shift, pawn, GetRegisterShiftToIndex(shift)); diff --git a/Source_Referenced/VanillaFactionsEmpire.cs b/Source_Referenced/VanillaFactionsEmpire.cs index 9fe8c4f..fd6ecd6 100644 --- a/Source_Referenced/VanillaFactionsEmpire.cs +++ b/Source_Referenced/VanillaFactionsEmpire.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using HarmonyLib; using Multiplayer.API; @@ -61,10 +60,8 @@ public VanillaFactionsEmpire(ModContentPack mod) // (Re)generates data MP.RegisterSyncMethod(typeof(RoyaltyTabWorker_Hierarchy), nameof(RoyaltyTabWorker_Hierarchy.Notify_Open)); // Invite pawn - // TODO: Uncomment the following two lines once TransformField method is included in API, and remove the temporary patches call/method - // MpCompat.RegisterLambdaDelegate(typeof(RoyaltyTabWorker_Hierarchy), nameof(RoyaltyTabWorker_Hierarchy.DoMainSection), 1)[0] - // .TransformField("CS$<>8__locals2/CS$<>8__locals1/pawn", Serializer.New(WriteRoyalPawn, ReadRoyalPawn)); - LongEventHandler.ExecuteWhenFinished(InitTemporaryPatches); // Inside of long event, in case something ever breaks here + MpCompat.RegisterLambdaDelegate(typeof(RoyaltyTabWorker_Hierarchy), nameof(RoyaltyTabWorker_Hierarchy.DoMainSection), 1)[0] + .TransformField("CS$<>8__locals2/CS$<>8__locals1/pawn", Serializer.New(WriteRoyalPawn, ReadRoyalPawn)); // Syncing adding/removing honors MP.RegisterSyncMethod(typeof(HonorUtility), nameof(HonorUtility.AddHonor)); @@ -159,7 +156,7 @@ private static void SyncMainTabWindow_Royalty(SyncWorker sync, ref MainTabWindow sync.Bind(ref tab.CurCharacter); if (sync.isWriting) - sync.Write(/* MP.CanUseDevMode && */ tab.DevMode); // TODO: Uncomment the CanUseDevMode part once it's included in the API + sync.Write(MP.CanUseDevMode && tab.DevMode); else tab.DevMode = sync.Read(); } @@ -261,12 +258,11 @@ private static void SyncParadeCommand(SyncWorker sync, ref Command_Parade comman #region Transformers - // TODO: Uncomment those lines once sync transformers are included in the API - // private static int WriteRoyalPawn(Pawn pawn) - // => pawn.thingIDNumber; - // - // private static Pawn ReadRoyalPawn(int pawnId) - // => WorldComponent_Hierarchy.Instance.TitleHolders?.Find(pawn => pawn.thingIDNumber == pawnId); + private static int WriteRoyalPawn(Pawn pawn) + => pawn.thingIDNumber; + + private static Pawn ReadRoyalPawn(int pawnId) + => WorldComponent_Hierarchy.Instance.TitleHolders?.Find(pawn => pawn.thingIDNumber == pawnId); #endregion @@ -344,78 +340,5 @@ private static void SyncSlingBeam(RoyalTitlePermitWorker_Slicing permitWorker, L } #endregion - - #region Temporary Patches - - // TODO: Once the new API is in, remove this region and uncomment the code under the other TODOs that use the new API. - private static Type firstInnerType; - private static Type secondInnerType; - - private static AccessTools.FieldRef originalInnerTypePawnField; - private static AccessTools.FieldRef originalInnerTypeHonorCostField; - - private static AccessTools.FieldRef secondInnerTypePawnField; - private static AccessTools.FieldRef secondInnerTypeParentField; - - private static AccessTools.FieldRef firstInnerTypeField; - private static AccessTools.FieldRef secondInnerTypeField; - - private static void InitTemporaryPatches() - { - var method = MpMethodUtil.GetLambda(typeof(RoyaltyTabWorker_Hierarchy), nameof(RoyaltyTabWorker_Hierarchy.DoMainSection), MethodType.Normal, null, 1); - if (method?.DeclaringType == null) - return; - - var type = method.DeclaringType; - originalInnerTypePawnField = AccessTools.FieldRefAccess(type, "p"); - originalInnerTypeHonorCostField = AccessTools.FieldRefAccess(type, "honorCost"); - var field = AccessTools.DeclaredField(type, "CS$<>8__locals2"); - firstInnerType = field.FieldType; - firstInnerTypeField = AccessTools.FieldRefAccess(field); - - type = firstInnerType; - field = AccessTools.DeclaredField(type, "CS$<>8__locals1"); - secondInnerType = field.FieldType; - secondInnerTypeField = AccessTools.FieldRefAccess(field); - - type = secondInnerType; - secondInnerTypePawnField = AccessTools.FieldRefAccess(type, "pawn"); - secondInnerTypeParentField = AccessTools.FieldRefAccess(type, "<>4__this"); - - MP.RegisterSyncMethod(method); - MP.RegisterSyncWorker(SyncHierarchyTabInnerType, method.DeclaringType, shouldConstruct: true); - } - - private static void SyncHierarchyTabInnerType(SyncWorker sync, ref object obj) - { - if (sync.isWriting) - { - sync.Write(originalInnerTypePawnField(obj)); - sync.Write(originalInnerTypeHonorCostField(obj)); - - var first = firstInnerTypeField(obj); - var second = secondInnerTypeField(first); - - sync.Write(secondInnerTypePawnField(second).thingIDNumber); - sync.Write(secondInnerTypeParentField(second)); - } - else - { - originalInnerTypePawnField(obj) = sync.Read(); - originalInnerTypeHonorCostField(obj) = sync.Read(); - - var first = Activator.CreateInstance(firstInnerType); - firstInnerTypeField(obj) = first; - - var second = Activator.CreateInstance(secondInnerType); - secondInnerTypeField(first) = second; - - var pawnId = sync.Read(); - secondInnerTypePawnField(second) = WorldComponent_Hierarchy.Instance.TitleHolders?.Find(pawn => pawn.thingIDNumber == pawnId); - secondInnerTypeParentField(second) = sync.Read(); - } - } - - #endregion } } \ No newline at end of file diff --git a/Source_Referenced/VehicleFramework.cs b/Source_Referenced/VehicleFramework.cs index 3ddcf2c..0117ce2 100644 --- a/Source_Referenced/VehicleFramework.cs +++ b/Source_Referenced/VehicleFramework.cs @@ -69,7 +69,6 @@ static ISyncMethod TrySyncDeclaredMethod(Type targetType, string targetMethodNam // Should be initialized by PatchCancelInInterface calls later on, // so this exists here as an extra safety in case those ever get removed later on. - PatchingUtilities.InitCancelInInterface(); MpCompatPatchLoader.LoadPatch(); #endregion @@ -916,7 +915,7 @@ private static IEnumerable ReplaceVanillaBanishDialog(IEnumerab // the current mouse position, which we don't want and it's a feature we've disabled in MP. // There's however only 1 situation that it's not the case, this will handle it. // The situation is pressing the gizmo's cancel button to stop targetting att all. - private static bool CancelTurretSetTargetSync() => shouldSyncInInterface || !PatchingUtilities.ShouldCancel; + private static bool CancelTurretSetTargetSync() => shouldSyncInInterface || !MP.InInterface; private static void SyncSetTarget(VehicleTurret turret, LocalTargetInfo target) { @@ -1658,7 +1657,7 @@ private static void FinalizeDrawFormVehicleCaravan() private static bool PreNotifyChoseRoute(Dialog_FormVehicleCaravan __instance, int destinationTile) { - if (!PatchingUtilities.ShouldCancel) + if (!MP.InInterface) return true; MP.GetLocalSessionManager(__instance.map).GetFirstOfType()?.ChooseRoute(destinationTile); @@ -1667,7 +1666,7 @@ private static bool PreNotifyChoseRoute(Dialog_FormVehicleCaravan __instance, in private static bool PreTryReformCaravan(Dialog_FormVehicleCaravan __instance) { - if (!PatchingUtilities.ShouldCancel) + if (!MP.InInterface) return true; MP.GetLocalSessionManager(__instance.map).GetFirstOfType()?.TryReformCaravan(); @@ -1676,7 +1675,7 @@ private static bool PreTryReformCaravan(Dialog_FormVehicleCaravan __instance) private static bool PreTryFormAndSendCaravan(Dialog_FormVehicleCaravan __instance) { - if (!PatchingUtilities.ShouldCancel) + if (!MP.InInterface) return true; MP.GetLocalSessionManager(__instance.map).GetFirstOfType()?.TryFormAndSendCaravan(); @@ -1685,7 +1684,7 @@ private static bool PreTryFormAndSendCaravan(Dialog_FormVehicleCaravan __instanc private static bool PreDebugTryFormCaravanInstantly(Dialog_FormVehicleCaravan __instance) { - if (!PatchingUtilities.ShouldCancel) + if (!MP.InInterface) return true; MP.GetLocalSessionManager(__instance.map).GetFirstOfType()?.DebugTryFormCaravanInstantly(); @@ -2494,7 +2493,7 @@ private static void PostVehicleTick(VehiclePawn __instance) [MpCompatPrefix(typeof(VehicleTurret), nameof(VehicleTurret.TurretRotation), methodType: MethodType.Getter)] private static void PreTurretRotation(VehicleTurret __instance, float ___rotation, ref float? __state) { - if (PatchingUtilities.ShouldCancel) + if (MP.InInterface) __state = ___rotation; } @@ -2511,7 +2510,7 @@ private static bool PreTurretTargeterCurrentTurretGetter() // A couple of places during ticking check the current turret from the targeter. This will cause // issues due to conditional statements based on `TurretTargeter.Turret != this`, etc. so just // prevent the mod from returning the actual turret in interface (return default value/null). - return PatchingUtilities.ShouldCancel; // The inverse of what PatchingUtilities.PatchCancelInInterface does + return MP.InInterface; // The inverse of what PatchingUtilities.PatchCancelInInterface does } #endregion