From 07bb274c82e52d8f4da0eee6405a77f0bd5037d7 Mon Sep 17 00:00:00 2001 From: redseiko Date: Wed, 27 May 2026 19:14:28 -0700 Subject: [PATCH 1/3] Fix `ExtEquipment` and `GameVersions` for `v0.221.13` PTB patch. --- JotunnLib/Utils/ExtEquipment.cs | 32 ++++++++++++++++++-------------- JotunnLib/Utils/GameVersions.cs | 7 ++----- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/JotunnLib/Utils/ExtEquipment.cs b/JotunnLib/Utils/ExtEquipment.cs index 662c261ff..d60195154 100644 --- a/JotunnLib/Utils/ExtEquipment.cs +++ b/JotunnLib/Utils/ExtEquipment.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using HarmonyLib; using Mono.Cecil.Cil; @@ -9,6 +9,10 @@ namespace Jotunn.Utils { internal class ExtEquipment : MonoBehaviour { + const int RightItemVariantHash = -1781447240; // RightItemVariant + const int RightBackItemVariantHash = -1623696695; // RightBackItemVariant + const int ChestItemVariantHash = -1180934665; // ChestItemVariant + private static bool Enabled; private static readonly Dictionary Instances = @@ -42,9 +46,9 @@ private static void VisEquipment_UpdateEquipmentVisuals(VisEquipment __instance) { if (Instances.TryGetValue(__instance, out var instance)) { - instance.NewRightItemVariant = zdo.GetInt("RightItemVariant"); - instance.NewChestVariant = zdo.GetInt("ChestItemVariant"); - instance.NewRightBackItemVariant = zdo.GetInt("RightBackItemVariant"); + instance.NewRightItemVariant = zdo.GetInt(RightItemVariantHash); + instance.NewChestVariant = zdo.GetInt(ChestItemVariantHash); + instance.NewRightBackItemVariant = zdo.GetInt(RightBackItemVariantHash); } } } @@ -168,16 +172,16 @@ private static void VisEquipment_SetChestEquiped(ILContext il) /// Store the variant index of the right hand item to the ZDO if the variant has changed /// [HarmonyPatch(typeof(VisEquipment), nameof(VisEquipment.SetRightItem)), HarmonyPrefix] - private static void VisEquipment_SetRightItem(VisEquipment __instance, string name) + private static void VisEquipment_SetRightItem(VisEquipment __instance, int itemHash) { if (Instances.TryGetValue(__instance, out var instance) && instance.MyHumanoid && instance.MyHumanoid.m_rightItem != null && - !(__instance.m_rightItem == name && instance.MyHumanoid.m_rightItem.m_variant == instance.CurrentRightItemVariant)) + !(__instance.m_rightItem == itemHash && instance.MyHumanoid.m_rightItem.m_variant == instance.CurrentRightItemVariant)) { instance.NewRightItemVariant = instance.MyHumanoid.m_rightItem.m_variant; if (__instance.m_nview && __instance.m_nview.GetZDO() is ZDO zdo) { - zdo.Set("RightItemVariant", (!string.IsNullOrEmpty(name)) ? instance.NewRightItemVariant : 0); + zdo.Set(RightItemVariantHash, (itemHash != 0) ? instance.NewRightItemVariant : 0); } } } @@ -186,16 +190,16 @@ private static void VisEquipment_SetRightItem(VisEquipment __instance, string na /// Store the variant index of the right back item to the ZDO if the variant has changed /// [HarmonyPatch(typeof(VisEquipment), nameof(VisEquipment.SetRightBackItem)), HarmonyPrefix] - private static void VisEquipment_SetRightBackItem(VisEquipment __instance, string name) + private static void VisEquipment_SetRightBackItem(VisEquipment __instance, int itemHash) { if (Instances.TryGetValue(__instance, out var instance) && instance.MyHumanoid && instance.MyHumanoid.m_hiddenRightItem != null && - !(__instance.m_rightBackItem == name && instance.MyHumanoid.m_hiddenRightItem.m_variant == instance.CurrentRightBackItemVariant)) + !(__instance.m_rightBackItem == itemHash && instance.MyHumanoid.m_hiddenRightItem.m_variant == instance.CurrentRightBackItemVariant)) { instance.NewRightBackItemVariant = instance.MyHumanoid.m_hiddenRightItem.m_variant; if (__instance.m_nview && __instance.m_nview.GetZDO() is ZDO zdo) - { - zdo.Set("RightBackItemVariant", (!string.IsNullOrEmpty(name)) ? instance.NewRightBackItemVariant : 0); + { + zdo.Set(RightBackItemVariantHash, (itemHash != 0) ? instance.NewRightBackItemVariant : 0); } } } @@ -204,16 +208,16 @@ private static void VisEquipment_SetRightBackItem(VisEquipment __instance, strin /// Store the variant index of the chest item to the ZDO if the variant has changed /// [HarmonyPatch(typeof(VisEquipment), nameof(VisEquipment.SetChestItem)), HarmonyPrefix] - private static void VisEquipment_SetChestItem(VisEquipment __instance, string name) + private static void VisEquipment_SetChestItem(VisEquipment __instance, int itemHash) { if (Instances.TryGetValue(__instance, out var instance) && instance.MyHumanoid && instance.MyHumanoid.m_chestItem != null && - !(__instance.m_chestItem == name && instance.MyHumanoid.m_chestItem.m_variant == instance.CurrentChestVariant)) + !(__instance.m_chestItem == itemHash && instance.MyHumanoid.m_chestItem.m_variant == instance.CurrentChestVariant)) { instance.NewChestVariant = instance.MyHumanoid.m_chestItem.m_variant; if (__instance.m_nview && __instance.m_nview.GetZDO() is ZDO zdo) { - zdo.Set("ChestItemVariant", (!string.IsNullOrEmpty(name)) ? instance.NewChestVariant : 0); + zdo.Set(ChestItemVariantHash, (itemHash != 0) ? instance.NewChestVariant : 0); } } } diff --git a/JotunnLib/Utils/GameVersions.cs b/JotunnLib/Utils/GameVersions.cs index cd5a36419..c73f4507e 100644 --- a/JotunnLib/Utils/GameVersions.cs +++ b/JotunnLib/Utils/GameVersions.cs @@ -1,6 +1,3 @@ -using System; -using System.Diagnostics; -using System.Reflection; using HarmonyLib; namespace Jotunn.Utils @@ -27,8 +24,8 @@ private static System.Version GetValheimVersion() private static uint GetNetworkVersion() { - // use Reflection because Version.m_networkVersion is a constant field, i.e. evaluated at compile time - return (uint)AccessTools.Field(typeof(Version), nameof(Version.m_networkVersion)).GetValue(null); + // Use reflection because Version.c_networkVersion is a constant field, i.e. evaluated at compile time + return (uint) AccessTools.Field(typeof(Version), nameof(Version.c_networkVersion)).GetValue(null); } } } From 160debec87c0e65212447bd3de5e8f25d1e0ca21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Schm=C3=B6cker?= Date: Fri, 29 May 2026 17:40:52 +0200 Subject: [PATCH 2/3] chore: calculate variant hashes once instead of hardcoding them --- JotunnLib/Utils/ExtEquipment.cs | 11 +++++------ TestMod/TestMod.cs | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/JotunnLib/Utils/ExtEquipment.cs b/JotunnLib/Utils/ExtEquipment.cs index d60195154..3956a27ca 100644 --- a/JotunnLib/Utils/ExtEquipment.cs +++ b/JotunnLib/Utils/ExtEquipment.cs @@ -9,14 +9,13 @@ namespace Jotunn.Utils { internal class ExtEquipment : MonoBehaviour { - const int RightItemVariantHash = -1781447240; // RightItemVariant - const int RightBackItemVariantHash = -1623696695; // RightBackItemVariant - const int ChestItemVariantHash = -1180934665; // ChestItemVariant + private static int RightItemVariantHash = "RightItemVariant".GetStableHashCode(); + private static int RightBackItemVariantHash = "RightBackItemVariant".GetStableHashCode(); + private static int ChestItemVariantHash = "ChestItemVariant".GetStableHashCode(); private static bool Enabled; - private static readonly Dictionary Instances = - new Dictionary(); + private static readonly Dictionary Instances = new Dictionary(); public static void Enable() { @@ -198,7 +197,7 @@ private static void VisEquipment_SetRightBackItem(VisEquipment __instance, int i { instance.NewRightBackItemVariant = instance.MyHumanoid.m_hiddenRightItem.m_variant; if (__instance.m_nview && __instance.m_nview.GetZDO() is ZDO zdo) - { + { zdo.Set(RightBackItemVariantHash, (itemHash != 0) ? instance.NewRightBackItemVariant : 0); } } diff --git a/TestMod/TestMod.cs b/TestMod/TestMod.cs index 60cf20e68..f1a099a7b 100644 --- a/TestMod/TestMod.cs +++ b/TestMod/TestMod.cs @@ -206,7 +206,7 @@ private void Update() // Use the name of the ButtonConfig to identify the button pressed if (EvilSwordSpecialButton != null && MessageHud.instance != null && - Player.m_localPlayer != null && Player.m_localPlayer.m_visEquipment.m_rightItem == "EvilSword") + Player.m_localPlayer != null && Player.m_localPlayer.m_visEquipment.m_rightItem == "EvilSword".GetStableHashCode()) { if (ZInput.GetButton(EvilSwordSpecialButton.Name) && MessageHud.instance.m_msgQeue.Count == 0) { From 4d60d60462b550d5038428d426236f67ab65d897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Schm=C3=B6cker?= Date: Fri, 29 May 2026 17:52:59 +0200 Subject: [PATCH 3/3] chore: backwards compatible GetNetworkVersion --- JotunnLib/Utils/GameVersions.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/JotunnLib/Utils/GameVersions.cs b/JotunnLib/Utils/GameVersions.cs index c73f4507e..04c65f2a7 100644 --- a/JotunnLib/Utils/GameVersions.cs +++ b/JotunnLib/Utils/GameVersions.cs @@ -1,3 +1,4 @@ +using System; using HarmonyLib; namespace Jotunn.Utils @@ -24,8 +25,12 @@ private static System.Version GetValheimVersion() private static uint GetNetworkVersion() { + Logger.LogInfo("GetNetworkVersion"); // Use reflection because Version.c_networkVersion is a constant field, i.e. evaluated at compile time - return (uint) AccessTools.Field(typeof(Version), nameof(Version.c_networkVersion)).GetValue(null); + var field = AccessTools.Field(typeof(Version), nameof(Version.c_networkVersion)) + ?? AccessTools.Field(typeof(Version), "m_networkVersion") // older Valheim version + ?? throw new Exception("Could not find network version field in Version class"); + return (uint)field.GetValue(null); } } }