From bc7cfd54ad9b88036274db9cde1f28890f9f1a3d Mon Sep 17 00:00:00 2001 From: Sakura-TA Date: Tue, 24 Mar 2026 15:34:50 +0800 Subject: [PATCH 1/4] Sync OutfitStand.TryDrop --- Source/Client/Syncing/Game/SyncMethods.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Client/Syncing/Game/SyncMethods.cs b/Source/Client/Syncing/Game/SyncMethods.cs index 7817c63b9..1fade97f0 100644 --- a/Source/Client/Syncing/Game/SyncMethods.cs +++ b/Source/Client/Syncing/Game/SyncMethods.cs @@ -419,6 +419,9 @@ public static void Init() SyncMethod.Lambda(typeof(Gene_Healing), nameof(Gene_Healing.GetGizmos), 0).SetDebugOnly(); // Heal permament wound SyncMethod.Lambda(typeof(Gene_PsychicBonding), nameof(Gene_PsychicBonding.GetGizmos), 0).SetDebugOnly(); // Bond to random pawn + // Outfit stand + SyncMethod.Register(typeof(Building_OutfitStand), nameof(Building_OutfitStand.TryDrop)); + // Baby feeding SyncMethod.Register(typeof(Pawn_MindState), nameof(Pawn_MindState.SetAutofeeder)); // Called from ITab_Pawn_Feeding.GenerateFloatMenuOption From 99c37ceefa479d4282f095ec117c5431a21f1535 Mon Sep 17 00:00:00 2001 From: Sakura-TA Date: Tue, 24 Mar 2026 16:43:38 +0800 Subject: [PATCH 2/4] Sync Bookcase.TryDrop --- .../Client/Syncing/Dict/SyncDictRimWorld.cs | 30 +++++++++++++++++ Source/Client/Syncing/Game/SyncMethods.cs | 32 ++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/Source/Client/Syncing/Dict/SyncDictRimWorld.cs b/Source/Client/Syncing/Dict/SyncDictRimWorld.cs index 865528ac2..648ef8d9e 100644 --- a/Source/Client/Syncing/Dict/SyncDictRimWorld.cs +++ b/Source/Client/Syncing/Dict/SyncDictRimWorld.cs @@ -912,6 +912,36 @@ public static class SyncDictRimWorld } } }, + { + (SyncWorker sync, ref ThingOwner thingOwner) => + { + if(sync.isWriting) + { + if(thingOwner != null) + { + if(thingOwner.owner != null && thingOwner.owner is Thing) + { + sync.Write((Thing)thingOwner.owner); + } else + { + // Dunno other situation yet. + sync.Write(null); + } + } else + { + sync.Write(null); + } + } + else + { + IThingHolder thingHolder = sync.Read() as IThingHolder; + if(thingHolder != null) + { + thingOwner = thingHolder.GetDirectlyHeldThings(); + } + } + } + }, #endregion #region Databases diff --git a/Source/Client/Syncing/Game/SyncMethods.cs b/Source/Client/Syncing/Game/SyncMethods.cs index 1fade97f0..9b122fbd5 100644 --- a/Source/Client/Syncing/Game/SyncMethods.cs +++ b/Source/Client/Syncing/Game/SyncMethods.cs @@ -869,6 +869,36 @@ public static void TryDirtyCurrentPawnTable(object instance = null, object[] arg table.SetDirty(); } } - } + [HarmonyPatch(typeof(ITab_ContentsBooks), "DoRow")] + static class ITab_ContentsBooks_DoRow_Patch + { + static IEnumerable Transpiler(IEnumerable insts) + { + var target = AccessTools.Method(typeof(ThingOwner), nameof(ThingOwner.TryDrop), new[] { typeof(Thing), typeof(IntVec3), typeof(Map), typeof(ThingPlaceMode), typeof(int), typeof(Thing).MakeByRefType(), typeof(Action), typeof(Predicate) }); + var replacement = AccessTools.Method(typeof(SyncMethods), nameof(SyncThingOwnerTryDrop)); + + foreach (var ci in insts) + { + if (ci.Calls(target)) + ci.operand = replacement; + yield return ci; + } + } + } + + // Seems can't sync Action & Predicate so have to deduct params + // This is enough for bookcase to use but needs update for new situation if needed. + + static bool SyncThingOwnerTryDrop(ThingOwner owner, Thing thing, IntVec3 dropLoc, Map map, ThingPlaceMode mode, int count, out Thing resultingThing, Action placedAction = null, Predicate nearPlaceValidator = null) + { + return DoSyncThingOwnerTryDrop(owner, thing, dropLoc, map, mode, count, out resultingThing); + } + [SyncMethod] + static bool DoSyncThingOwnerTryDrop(ThingOwner owner, Thing thing, IntVec3 dropLoc, Map map, ThingPlaceMode mode, int count, out Thing resultingThing) + { + return owner.TryDrop(thing, dropLoc, map, mode, count, out resultingThing, + null, null); + } + } } From 1102ad8d3803ac445b4bbed7560b67c017c6d08d Mon Sep 17 00:00:00 2001 From: Sakura-TA Date: Tue, 24 Mar 2026 21:36:19 +0800 Subject: [PATCH 3/4] Using nameof instead of direct string --- Source/Client/Syncing/Game/SyncMethods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Client/Syncing/Game/SyncMethods.cs b/Source/Client/Syncing/Game/SyncMethods.cs index 9b122fbd5..8b0356c34 100644 --- a/Source/Client/Syncing/Game/SyncMethods.cs +++ b/Source/Client/Syncing/Game/SyncMethods.cs @@ -870,7 +870,7 @@ public static void TryDirtyCurrentPawnTable(object instance = null, object[] arg } } - [HarmonyPatch(typeof(ITab_ContentsBooks), "DoRow")] + [HarmonyPatch(typeof(ITab_ContentsBooks), nameof(ITab_ContentsBooks.DoRow))] static class ITab_ContentsBooks_DoRow_Patch { static IEnumerable Transpiler(IEnumerable insts) From c6113338355c289172fbf14b5256feb6f4e594b7 Mon Sep 17 00:00:00 2001 From: Sakura-TA Date: Wed, 25 Mar 2026 00:01:50 +0800 Subject: [PATCH 4/4] Using Bookcase instead of ThingOwner and remove unnecessary SyncWorker --- .../Client/Syncing/Dict/SyncDictRimWorld.cs | 30 ------------------- Source/Client/Syncing/Game/SyncMethods.cs | 17 +++++++---- 2 files changed, 11 insertions(+), 36 deletions(-) diff --git a/Source/Client/Syncing/Dict/SyncDictRimWorld.cs b/Source/Client/Syncing/Dict/SyncDictRimWorld.cs index 648ef8d9e..865528ac2 100644 --- a/Source/Client/Syncing/Dict/SyncDictRimWorld.cs +++ b/Source/Client/Syncing/Dict/SyncDictRimWorld.cs @@ -912,36 +912,6 @@ public static class SyncDictRimWorld } } }, - { - (SyncWorker sync, ref ThingOwner thingOwner) => - { - if(sync.isWriting) - { - if(thingOwner != null) - { - if(thingOwner.owner != null && thingOwner.owner is Thing) - { - sync.Write((Thing)thingOwner.owner); - } else - { - // Dunno other situation yet. - sync.Write(null); - } - } else - { - sync.Write(null); - } - } - else - { - IThingHolder thingHolder = sync.Read() as IThingHolder; - if(thingHolder != null) - { - thingOwner = thingHolder.GetDirectlyHeldThings(); - } - } - } - }, #endregion #region Databases diff --git a/Source/Client/Syncing/Game/SyncMethods.cs b/Source/Client/Syncing/Game/SyncMethods.cs index 8b0356c34..7199000de 100644 --- a/Source/Client/Syncing/Game/SyncMethods.cs +++ b/Source/Client/Syncing/Game/SyncMethods.cs @@ -875,12 +875,16 @@ static class ITab_ContentsBooks_DoRow_Patch { static IEnumerable Transpiler(IEnumerable insts) { - var target = AccessTools.Method(typeof(ThingOwner), nameof(ThingOwner.TryDrop), new[] { typeof(Thing), typeof(IntVec3), typeof(Map), typeof(ThingPlaceMode), typeof(int), typeof(Thing).MakeByRefType(), typeof(Action), typeof(Predicate) }); - var replacement = AccessTools.Method(typeof(SyncMethods), nameof(SyncThingOwnerTryDrop)); + var getDirectlyHeldThings = AccessTools.Method(typeof(Building_Bookcase), nameof(Building_Bookcase.GetDirectlyHeldThings)); + var tryDrop = AccessTools.Method(typeof(ThingOwner), nameof(ThingOwner.TryDrop), new[] { typeof(Thing), typeof(IntVec3), typeof(Map), typeof(ThingPlaceMode), typeof(int), typeof(Thing).MakeByRefType(), typeof(Action), typeof(Predicate) }); + var replacement = AccessTools.Method(typeof(SyncMethods), nameof(SyncBookcaseTryDrop)); foreach (var ci in insts) { - if (ci.Calls(target)) + if (ci.Calls(getDirectlyHeldThings)) + continue; + + if (ci.Calls(tryDrop)) ci.operand = replacement; yield return ci; } @@ -890,13 +894,14 @@ static IEnumerable Transpiler(IEnumerable inst // Seems can't sync Action & Predicate so have to deduct params // This is enough for bookcase to use but needs update for new situation if needed. - static bool SyncThingOwnerTryDrop(ThingOwner owner, Thing thing, IntVec3 dropLoc, Map map, ThingPlaceMode mode, int count, out Thing resultingThing, Action placedAction = null, Predicate nearPlaceValidator = null) + static bool SyncBookcaseTryDrop(Building_Bookcase bookcase, Thing thing, IntVec3 dropLoc, Map map, ThingPlaceMode mode, int count, out Thing resultingThing, Action placedAction = null, Predicate nearPlaceValidator = null) { - return DoSyncThingOwnerTryDrop(owner, thing, dropLoc, map, mode, count, out resultingThing); + return DoSyncBookcaseTryDrop(bookcase, thing, dropLoc, map, mode, count, out resultingThing); } [SyncMethod] - static bool DoSyncThingOwnerTryDrop(ThingOwner owner, Thing thing, IntVec3 dropLoc, Map map, ThingPlaceMode mode, int count, out Thing resultingThing) + static bool DoSyncBookcaseTryDrop(Building_Bookcase bookcase, Thing thing, IntVec3 dropLoc, Map map, ThingPlaceMode mode, int count, out Thing resultingThing) { + ThingOwner owner = bookcase.GetDirectlyHeldThings(); return owner.TryDrop(thing, dropLoc, map, mode, count, out resultingThing, null, null); }