From d43bbf5b81496d40f727dc88aedf4f73d3c0cd5f Mon Sep 17 00:00:00 2001 From: SokyranTheDragon Date: Tue, 11 Jun 2024 23:17:27 +0200 Subject: [PATCH] Update position of attached motes based on real position This should fix the issue with Noctol eyes, along with other attached motes being drawn away from the pawns they are attached to. This was likely never really noticed before due to no other vanilla attached motes having their position as important as here. Getting a DrawPos of a pawn during ticking will cause `PawnTweener.TweenedPos` to return `TweenedPosRoot` in MP to make the method deterministic. However, `MoteAttached` updated during simulation will draw it in an incorrect position due to the pawn position not being where it is visually. The fix here is to cause `PawnTweener.TweenedPos` patch not to run while calculating the position of the attached mote. Potential alternative approach would be to make a method that works like `Pawn_DrawTracker.DrawPos`, but using `PawnTweener.tweenedPos` field directly rather than `PawnTweener.TweenedPos` getter. Another potential approach would be to make a reverse patch on `PawnTweener.TweenedPos`, but (again) replace the call to the getter with a direct field access in the transpiler. There's possibly other ways to handle this situation, but those 3 are the only ones I could think of. --- Source/Client/Patches/Determinism.cs | 6 ++++-- Source/Client/Patches/Patches.cs | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Source/Client/Patches/Determinism.cs b/Source/Client/Patches/Determinism.cs index 1eac7ec5..b00d1e94 100644 --- a/Source/Client/Patches/Determinism.cs +++ b/Source/Client/Patches/Determinism.cs @@ -19,12 +19,14 @@ namespace Multiplayer.Client.Patches [HarmonyPatch(nameof(PawnTweener.TweenedPos), MethodType.Getter)] static class DrawPosPatch { - static bool Prefix() => Multiplayer.Client == null || Multiplayer.InInterface; + public static bool returnTruePosition = false; + + static bool Prefix() => Multiplayer.Client == null || Multiplayer.InInterface || returnTruePosition; // Give the root position during ticking static void Postfix(PawnTweener __instance, ref Vector3 __result) { - if (Multiplayer.Client == null || Multiplayer.InInterface) return; + if (Multiplayer.Client == null || Multiplayer.InInterface || returnTruePosition) return; __result = __instance.TweenedPosRoot(); } } diff --git a/Source/Client/Patches/Patches.cs b/Source/Client/Patches/Patches.cs index a0c35a87..37e4e25c 100644 --- a/Source/Client/Patches/Patches.cs +++ b/Source/Client/Patches/Patches.cs @@ -9,6 +9,7 @@ using System.Reflection.Emit; using System.Text.RegularExpressions; using System.Xml.Linq; +using Multiplayer.Client.Patches; using UnityEngine; using Verse; using Verse.AI; @@ -581,4 +582,12 @@ static void FixStorage(IStoreSettingsParent __instance, StorageSettings ___allow ___allowedNutritionSettings.owner ??= __instance; } } + + [HarmonyPatch(typeof(MoteAttachLink), nameof(MoteAttachLink.UpdateDrawPos))] + static class MoteAttachLinkUsesTruePosition + { + static void Prefix() => DrawPosPatch.returnTruePosition = true; + + static void Finalizer() => DrawPosPatch.returnTruePosition = false; + } }