From ca5ee703c930b38216d3925f8ae08f0738fbef0f Mon Sep 17 00:00:00 2001 From: MrGadget <9826063+MrGadget1024@users.noreply.github.com> Date: Thu, 26 Mar 2026 02:49:21 -0400 Subject: [PATCH] fix: Use GetStableHashCode16 instead of truncation --- Assets/Mirror/Core/NetworkBehaviour.cs | 12 ++++++------ Assets/Mirror/Core/RemoteCalls.cs | 2 +- .../Editor/Weaver/Processors/CommandProcessor.cs | 2 +- .../Mirror/Editor/Weaver/Processors/RpcProcessor.cs | 2 +- .../Editor/Weaver/Processors/TargetRpcProcessor.cs | 2 +- .../Editor/NetworkBehaviour/NetworkBehaviourTests.cs | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Assets/Mirror/Core/NetworkBehaviour.cs b/Assets/Mirror/Core/NetworkBehaviour.cs index 0749dcd1bf2..1f885f0176b 100644 --- a/Assets/Mirror/Core/NetworkBehaviour.cs +++ b/Assets/Mirror/Core/NetworkBehaviour.cs @@ -364,7 +364,7 @@ protected void InitSyncObject(SyncObject syncObject) } // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions - protected void SendCommandInternal(string functionFullName, int functionHashCode, NetworkWriter writer, int channelId, bool requiresAuthority = true) + protected void SendCommandInternal(string functionFullName, ushort functionHashCode, NetworkWriter writer, int channelId, bool requiresAuthority = true) { // this was in Weaver before // NOTE: we could remove this later to allow calling Cmds on Server @@ -418,7 +418,7 @@ protected void SendCommandInternal(string functionFullName, int functionHashCode netId = netId, componentIndex = ComponentIndex, // type+func so Inventory.RpcUse != Equipment.RpcUse - functionHash = (ushort)functionHashCode, + functionHash = functionHashCode, // segment to avoid reader allocations payload = writer.ToArraySegment() }; @@ -434,7 +434,7 @@ protected void SendCommandInternal(string functionFullName, int functionHashCode } // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions - protected void SendRPCInternal(string functionFullName, int functionHashCode, NetworkWriter writer, int channelId, bool includeOwner) + protected void SendRPCInternal(string functionFullName, ushort functionHashCode, NetworkWriter writer, int channelId, bool includeOwner) { // this was in Weaver before if (!NetworkServer.active) @@ -456,7 +456,7 @@ protected void SendRPCInternal(string functionFullName, int functionHashCode, Ne netId = netId, componentIndex = ComponentIndex, // type+func so Inventory.RpcUse != Equipment.RpcUse - functionHash = (ushort)functionHashCode, + functionHash = functionHashCode, // segment to avoid reader allocations payload = writer.ToArraySegment() }; @@ -488,7 +488,7 @@ protected void SendRPCInternal(string functionFullName, int functionHashCode, Ne } // pass full function name to avoid ClassA.Func <-> ClassB.Func collisions - protected void SendTargetRPCInternal(NetworkConnection conn, string functionFullName, int functionHashCode, NetworkWriter writer, int channelId) + protected void SendTargetRPCInternal(NetworkConnection conn, string functionFullName, ushort functionHashCode, NetworkWriter writer, int channelId) { if (!NetworkServer.active) { @@ -527,7 +527,7 @@ protected void SendTargetRPCInternal(NetworkConnection conn, string functionFull netId = netId, componentIndex = ComponentIndex, // type+func so Inventory.RpcUse != Equipment.RpcUse - functionHash = (ushort)functionHashCode, + functionHash = functionHashCode, // segment to avoid reader allocations payload = writer.ToArraySegment() }; diff --git a/Assets/Mirror/Core/RemoteCalls.cs b/Assets/Mirror/Core/RemoteCalls.cs index 5dbe52f6404..06ec44fe594 100644 --- a/Assets/Mirror/Core/RemoteCalls.cs +++ b/Assets/Mirror/Core/RemoteCalls.cs @@ -70,7 +70,7 @@ static bool CheckIfDelegateExists(Type componentType, RemoteCallType remoteCallT internal static ushort RegisterDelegate(Type componentType, string functionFullName, RemoteCallType remoteCallType, RemoteCallDelegate func, bool cmdRequiresAuthority = true) { // type+func so Inventory.RpcUse != Equipment.RpcUse - ushort hash = (ushort)(functionFullName.GetStableHashCode() & 0xFFFF); + ushort hash = functionFullName.GetStableHashCode16(); if (CheckIfDelegateExists(componentType, remoteCallType, func, hash)) return hash; diff --git a/Assets/Mirror/Editor/Weaver/Processors/CommandProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/CommandProcessor.cs index 0e40564ac67..a98546d8967 100644 --- a/Assets/Mirror/Editor/Weaver/Processors/CommandProcessor.cs +++ b/Assets/Mirror/Editor/Weaver/Processors/CommandProcessor.cs @@ -128,7 +128,7 @@ public static MethodDefinition ProcessCommandCall(WeaverTypes weaverTypes, Write // otherwise each GetStableHash call requires O(N) complexity. // noticeable for long function names: // https://github.com/MirrorNetworking/Mirror/issues/3375 - worker.Emit(OpCodes.Ldc_I4, md.FullName.GetStableHashCode()); + worker.Emit(OpCodes.Ldc_I4, md.FullName.GetStableHashCode16()); // writer worker.Emit(OpCodes.Ldloc_0); worker.Emit(OpCodes.Ldc_I4, channel); diff --git a/Assets/Mirror/Editor/Weaver/Processors/RpcProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/RpcProcessor.cs index ca2d7b94ff3..50f3bf24bf5 100644 --- a/Assets/Mirror/Editor/Weaver/Processors/RpcProcessor.cs +++ b/Assets/Mirror/Editor/Weaver/Processors/RpcProcessor.cs @@ -86,7 +86,7 @@ public static MethodDefinition ProcessRpcCall(WeaverTypes weaverTypes, Writers w // otherwise each GetStableHash call requires O(N) complexity. // noticeable for long function names: // https://github.com/MirrorNetworking/Mirror/issues/3375 - worker.Emit(OpCodes.Ldc_I4, md.FullName.GetStableHashCode()); + worker.Emit(OpCodes.Ldc_I4, md.FullName.GetStableHashCode16()); // writer worker.Emit(OpCodes.Ldloc_0); worker.Emit(OpCodes.Ldc_I4, channel); diff --git a/Assets/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs index 8d56040a622..b2bc6ea76cc 100644 --- a/Assets/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs +++ b/Assets/Mirror/Editor/Weaver/Processors/TargetRpcProcessor.cs @@ -143,7 +143,7 @@ public static MethodDefinition ProcessTargetRpcCall(WeaverTypes weaverTypes, Wri // otherwise each GetStableHash call requires O(N) complexity. // noticeable for long function names: // https://github.com/MirrorNetworking/Mirror/issues/3375 - worker.Emit(OpCodes.Ldc_I4, md.FullName.GetStableHashCode()); + worker.Emit(OpCodes.Ldc_I4, md.FullName.GetStableHashCode16()); // writer worker.Emit(OpCodes.Ldloc_0); worker.Emit(OpCodes.Ldc_I4, targetRpcAttr.GetField("channel", 0)); diff --git a/Assets/Mirror/Tests/Editor/NetworkBehaviour/NetworkBehaviourTests.cs b/Assets/Mirror/Tests/Editor/NetworkBehaviour/NetworkBehaviourTests.cs index 5413a0e5e1e..80f7eafabbf 100644 --- a/Assets/Mirror/Tests/Editor/NetworkBehaviour/NetworkBehaviourTests.cs +++ b/Assets/Mirror/Tests/Editor/NetworkBehaviour/NetworkBehaviourTests.cs @@ -201,7 +201,7 @@ public void GetDelegate() false); // get handler - ushort cmdHash = (ushort)nameof(NetworkBehaviourDelegateComponent.Delegate).GetStableHashCode(); + ushort cmdHash = nameof(NetworkBehaviourDelegateComponent.Delegate).GetStableHashCode16(); RemoteCallDelegate func = RemoteProcedureCalls.GetDelegate(cmdHash); RemoteCallDelegate expected = NetworkBehaviourDelegateComponent.Delegate; Assert.That(func, Is.EqualTo(expected));