diff --git a/Mirror/Runtime/Extensions.cs b/Mirror/Runtime/Extensions.cs new file mode 100644 index 000000000..42991fb2f --- /dev/null +++ b/Mirror/Runtime/Extensions.cs @@ -0,0 +1,19 @@ +namespace Mirror +{ + + public static class Extensions + { + // string.GetHashCode is not guaranteed to be the same on all machines, but + // we need one that is the same on all machines. simple and stupid: + public static int GetStableHashCode(this string text) + { + unchecked + { + int hash = 23; + foreach (char c in text) + hash = hash * 31 + c; + return hash; + } + } + } +} \ No newline at end of file diff --git a/Mirror/Runtime/Mirror.Runtime.csproj b/Mirror/Runtime/Mirror.Runtime.csproj index e7a8d0ba5..671cb2b60 100644 --- a/Mirror/Runtime/Mirror.Runtime.csproj +++ b/Mirror/Runtime/Mirror.Runtime.csproj @@ -65,6 +65,7 @@ + diff --git a/Mirror/Runtime/NetworkBehaviour.cs b/Mirror/Runtime/NetworkBehaviour.cs index 8af4c1b91..9728a4a5e 100644 --- a/Mirror/Runtime/NetworkBehaviour.cs +++ b/Mirror/Runtime/NetworkBehaviour.cs @@ -76,7 +76,7 @@ protected void InitSyncObject(SyncObject syncObject) // ----------------------------- Commands -------------------------------- [EditorBrowsable(EditorBrowsableState.Never)] - protected void SendCommandInternal(int cmdHash, NetworkWriter writer, int channelId, string cmdName) + protected void SendCommandInternal(string cmdName, NetworkWriter writer, int channelId) { // local players can always send commands, regardless of authority, other objects must have authority. if (!(isLocalPlayer || hasAuthority)) @@ -95,7 +95,7 @@ protected void SendCommandInternal(int cmdHash, NetworkWriter writer, int channe CommandMessage message = new CommandMessage(); message.netId = netId; message.componentIndex = ComponentIndex; - message.cmdHash = cmdHash; + message.cmdHash = cmdName.GetStableHashCode(); message.payload = writer.ToArray(); ClientScene.readyConnection.Send((short)MsgType.Command, message, channelId); @@ -110,7 +110,7 @@ public virtual bool InvokeCommand(int cmdHash, NetworkReader reader) // ----------------------------- Client RPCs -------------------------------- [EditorBrowsable(EditorBrowsableState.Never)] - protected void SendRPCInternal(int rpcHash, NetworkWriter writer, int channelId, string rpcName) + protected void SendRPCInternal(string rpcName, NetworkWriter writer, int channelId) { // This cannot use NetworkServer.active, as that is not specific to this object. if (!isServer) @@ -123,14 +123,14 @@ protected void SendRPCInternal(int rpcHash, NetworkWriter writer, int channelId, RpcMessage message = new RpcMessage(); message.netId = netId; message.componentIndex = ComponentIndex; - message.rpcHash = rpcHash; + message.rpcHash = rpcName.GetStableHashCode(); message.payload = writer.ToArray(); NetworkServer.SendToReady(gameObject, (short)MsgType.Rpc, message, channelId); } [EditorBrowsable(EditorBrowsableState.Never)] - protected void SendTargetRPCInternal(NetworkConnection conn, int rpcHash, NetworkWriter writer, int channelId, string rpcName) + protected void SendTargetRPCInternal(NetworkConnection conn, string rpcName, NetworkWriter writer, int channelId) { // This cannot use NetworkServer.active, as that is not specific to this object. if (!isServer) @@ -143,7 +143,7 @@ protected void SendTargetRPCInternal(NetworkConnection conn, int rpcHash, Networ RpcMessage message = new RpcMessage(); message.netId = netId; message.componentIndex = ComponentIndex; - message.rpcHash = rpcHash; + message.rpcHash = rpcName.GetStableHashCode(); message.payload = writer.ToArray(); conn.Send((short)MsgType.Rpc, message, channelId); @@ -158,7 +158,7 @@ public virtual bool InvokeRPC(int cmdHash, NetworkReader reader) // ----------------------------- Sync Events -------------------------------- [EditorBrowsable(EditorBrowsableState.Never)] - protected void SendEventInternal(int eventHash, NetworkWriter writer, int channelId, string eventName) + protected void SendEventInternal(string eventName, NetworkWriter writer, int channelId) { if (!NetworkServer.active) { @@ -170,7 +170,7 @@ protected void SendEventInternal(int eventHash, NetworkWriter writer, int channe SyncEventMessage message = new SyncEventMessage(); message.netId = netId; message.componentIndex = ComponentIndex; - message.eventHash = eventHash; + message.eventHash = eventName.GetStableHashCode(); message.payload = writer.ToArray(); NetworkServer.SendToReady(gameObject, (short)MsgType.SyncEvent, message, channelId); @@ -208,8 +208,9 @@ public string DebugString() static Dictionary s_CmdHandlerDelegates = new Dictionary(); [EditorBrowsable(EditorBrowsableState.Never)] - protected static void RegisterCommandDelegate(Type invokeClass, int cmdHash, CmdDelegate func) + protected static void RegisterCommandDelegate(Type invokeClass, string cmdName, CmdDelegate func) { + int cmdHash = cmdName.GetStableHashCode(); if (s_CmdHandlerDelegates.ContainsKey(cmdHash)) { return; @@ -223,9 +224,10 @@ protected static void RegisterCommandDelegate(Type invokeClass, int cmdHash, Cmd } [EditorBrowsable(EditorBrowsableState.Never)] - protected static void RegisterRpcDelegate(Type invokeClass, int cmdHash, CmdDelegate func) + protected static void RegisterRpcDelegate(Type invokeClass, string rpcName, CmdDelegate func) { - if (s_CmdHandlerDelegates.ContainsKey(cmdHash)) + int rpcHash = rpcName.GetStableHashCode(); + if (s_CmdHandlerDelegates.ContainsKey(rpcHash)) { return; } @@ -233,14 +235,15 @@ protected static void RegisterRpcDelegate(Type invokeClass, int cmdHash, CmdDele inv.invokeType = UNetInvokeType.ClientRpc; inv.invokeClass = invokeClass; inv.invokeFunction = func; - s_CmdHandlerDelegates[cmdHash] = inv; - if (LogFilter.Debug) { Debug.Log("RegisterRpcDelegate hash:" + cmdHash + " " + func.GetMethodName()); } + s_CmdHandlerDelegates[rpcHash] = inv; + if (LogFilter.Debug) { Debug.Log("RegisterRpcDelegate hash:" + rpcHash + " " + func.GetMethodName()); } } [EditorBrowsable(EditorBrowsableState.Never)] - protected static void RegisterEventDelegate(Type invokeClass, int cmdHash, CmdDelegate func) + protected static void RegisterEventDelegate(Type invokeClass, string eventName, CmdDelegate func) { - if (s_CmdHandlerDelegates.ContainsKey(cmdHash)) + int eventHash = eventName.GetStableHashCode(); + if (s_CmdHandlerDelegates.ContainsKey(eventHash)) { return; } @@ -248,8 +251,8 @@ protected static void RegisterEventDelegate(Type invokeClass, int cmdHash, CmdDe inv.invokeType = UNetInvokeType.SyncEvent; inv.invokeClass = invokeClass; inv.invokeFunction = func; - s_CmdHandlerDelegates[cmdHash] = inv; - if (LogFilter.Debug) { Debug.Log("RegisterEventDelegate hash:" + cmdHash + " " + func.GetMethodName()); } + s_CmdHandlerDelegates[eventHash] = inv; + if (LogFilter.Debug) { Debug.Log("RegisterEventDelegate hash:" + eventHash + " " + func.GetMethodName()); } } internal static string GetInvoker(int cmdHash) diff --git a/Mirror/Weaver/UNetBehaviourProcessor.cs b/Mirror/Weaver/UNetBehaviourProcessor.cs index d3071fab1..48e63973d 100644 --- a/Mirror/Weaver/UNetBehaviourProcessor.cs +++ b/Mirror/Weaver/UNetBehaviourProcessor.cs @@ -238,56 +238,28 @@ void GenerateConstants() int cmdIndex = 0; foreach (MethodDefinition md in m_Cmds) { - FieldReference cmdConstant = Weaver.ResolveField(m_td, "kCmd" + md.Name); - - int cmdHash = GetHashCode(m_td.Name + ":Cmd:" + md.Name); - cctorWorker.Append(cctorWorker.Create(OpCodes.Ldc_I4, cmdHash)); - cctorWorker.Append(cctorWorker.Create(OpCodes.Stsfld, cmdConstant)); - //Weaver.DLog(m_td, " Constant " + m_td.Name + ":Cmd:" + md.Name); - - GenerateCommandDelegate(cctorWorker, Weaver.registerCommandDelegateReference, m_CmdInvocationFuncs[cmdIndex], cmdConstant); + GenerateCommandDelegate(cctorWorker, Weaver.registerCommandDelegateReference, m_CmdInvocationFuncs[cmdIndex], md.Name); cmdIndex += 1; } int rpcIndex = 0; foreach (MethodDefinition md in m_Rpcs) { - FieldReference rpcConstant = Weaver.ResolveField(m_td, "kRpc" + md.Name); - - int rpcHash = GetHashCode(m_td.Name + ":Rpc:" + md.Name); - cctorWorker.Append(cctorWorker.Create(OpCodes.Ldc_I4, rpcHash)); - cctorWorker.Append(cctorWorker.Create(OpCodes.Stsfld, rpcConstant)); - //Weaver.DLog(m_td, " Constant " + m_td.Name + ":Rpc:" + md.Name); - - GenerateCommandDelegate(cctorWorker, Weaver.registerRpcDelegateReference, m_RpcInvocationFuncs[rpcIndex], rpcConstant); + GenerateCommandDelegate(cctorWorker, Weaver.registerRpcDelegateReference, m_RpcInvocationFuncs[rpcIndex], md.Name); rpcIndex += 1; } int targetRpcIndex = 0; foreach (MethodDefinition md in m_TargetRpcs) { - FieldReference targetRpcConstant = Weaver.ResolveField(m_td, "kTargetRpc" + md.Name); - - int targetRpcHash = GetHashCode(m_td.Name + ":TargetRpc:" + md.Name); - cctorWorker.Append(cctorWorker.Create(OpCodes.Ldc_I4, targetRpcHash)); - cctorWorker.Append(cctorWorker.Create(OpCodes.Stsfld, targetRpcConstant)); - //Weaver.DLog(m_td, " Constant " + m_td.Name + ":Rpc:" + md.Name); - - GenerateCommandDelegate(cctorWorker, Weaver.registerRpcDelegateReference, m_TargetRpcInvocationFuncs[targetRpcIndex], targetRpcConstant); + GenerateCommandDelegate(cctorWorker, Weaver.registerRpcDelegateReference, m_TargetRpcInvocationFuncs[targetRpcIndex], md.Name); targetRpcIndex += 1; } int eventIndex = 0; foreach (EventDefinition ed in m_Events) { - FieldReference eventConstant = Weaver.ResolveField(m_td, "kEvent" + ed.Name); - - int eventHash = GetHashCode(m_td.Name + ":Event:" + ed.Name); - cctorWorker.Append(cctorWorker.Create(OpCodes.Ldc_I4, eventHash)); - cctorWorker.Append(cctorWorker.Create(OpCodes.Stsfld, eventConstant)); - //Weaver.DLog(m_td, " Constant " + m_td.Name + ":Event:" + ed.Name); - - GenerateCommandDelegate(cctorWorker, Weaver.registerEventDelegateReference, m_EventInvocationFuncs[eventIndex], eventConstant); + GenerateCommandDelegate(cctorWorker, Weaver.registerEventDelegateReference, m_EventInvocationFuncs[eventIndex], ed.Name); eventIndex += 1; } @@ -338,13 +310,13 @@ void GenerateSyncListInstanceInitializer(ILProcessor ctorWorker, FieldDefinition /* // This generates code like: - NetworkBehaviour.RegisterCommandDelegate(base.GetType(), ShipControl.kCmdCmdThrust, new NetworkBehaviour.CmdDelegate(ShipControl.InvokeCmdCmdThrust)); + NetworkBehaviour.RegisterCommandDelegate(base.GetType(), "CmdThrust", new NetworkBehaviour.CmdDelegate(ShipControl.InvokeCmdCmdThrust)); */ - void GenerateCommandDelegate(ILProcessor awakeWorker, MethodReference registerMethod, MethodDefinition func, FieldReference field) + void GenerateCommandDelegate(ILProcessor awakeWorker, MethodReference registerMethod, MethodDefinition func, string cmdName) { awakeWorker.Append(awakeWorker.Create(OpCodes.Ldtoken, m_td)); awakeWorker.Append(awakeWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldsfld, field)); + awakeWorker.Append(awakeWorker.Create(OpCodes.Ldstr, cmdName)); awakeWorker.Append(awakeWorker.Create(OpCodes.Ldnull)); awakeWorker.Append(awakeWorker.Create(OpCodes.Ldftn, func)); @@ -910,7 +882,7 @@ public void CallCmdThrust(float thrusting, int spin) NetworkWriter networkWriter = new NetworkWriter(); networkWriter.Write(thrusting); networkWriter.WritePackedUInt32((uint)spin); - base.SendCommandInternal(ShipControl.kCmdCmdThrust, networkWriter, cmdName); + base.SendCommandInternal(cmdName, networkWriter, cmdName); } */ MethodDefinition ProcessCommandCall(MethodDefinition md, CustomAttribute ca) @@ -957,12 +929,6 @@ MethodDefinition ProcessCommandCall(MethodDefinition md, CustomAttribute ca) // NetworkWriter writer = new NetworkWriter(); WriteCreateWriter(cmdWorker); - // create the command id constant - FieldDefinition cmdConstant = new FieldDefinition("kCmd" + md.Name, - FieldAttributes.Static | FieldAttributes.Private, - Weaver.int32Type); - m_td.Fields.Add(cmdConstant); - // write all the arguments that the user passed to the Cmd call if (!WriteArguments(cmdWorker, md, "Command", false)) return null; @@ -976,10 +942,9 @@ MethodDefinition ProcessCommandCall(MethodDefinition md, CustomAttribute ca) // invoke interal send and return cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0)); // load 'base.' to call the SendCommand function with - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldsfld, cmdConstant)); // cmdHash + cmdWorker.Append(cmdWorker.Create(OpCodes.Ldstr, cmdName)); cmdWorker.Append(cmdWorker.Create(OpCodes.Ldloc_0)); // writer cmdWorker.Append(cmdWorker.Create(OpCodes.Ldc_I4, GetChannelId(ca))); - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldstr, cmdName)); cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.sendCommandInternal)); cmdWorker.Append(cmdWorker.Create(OpCodes.Ret)); @@ -1056,7 +1021,7 @@ public void CallTargetTest (NetworkConnection conn, int param) } else { NetworkWriter writer = new NetworkWriter (); writer.WritePackedUInt32 ((uint)param); - base.SendTargetRPCInternal (conn, Player.kTargetRpcTargetTest, val, "TargetTest"); + base.SendTargetRPCInternal (conn, "TargetTest", val); } } */ @@ -1093,12 +1058,6 @@ MethodDefinition ProcessTargetRpcCall(MethodDefinition md, CustomAttribute ca) WriteCreateWriter(rpcWorker); - // create the targetrpc id constant - FieldDefinition rpcConstant = new FieldDefinition("kTargetRpc" + md.Name, - FieldAttributes.Static | FieldAttributes.Private, - Weaver.int32Type); - m_td.Fields.Add(rpcConstant); - // write all the arguments that the user passed to the TargetRpc call if (!WriteArguments(rpcWorker, md, "TargetRPC", true)) return null; @@ -1113,10 +1072,9 @@ MethodDefinition ProcessTargetRpcCall(MethodDefinition md, CustomAttribute ca) // invoke SendInternal and return rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); // this rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_1)); // connection - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldsfld, rpcConstant)); // rpcHash + rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, rpcName)); rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0)); // writer rpcWorker.Append(rpcWorker.Create(OpCodes.Ldc_I4, GetChannelId(ca))); - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, rpcName)); rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.sendTargetRpcInternal)); rpcWorker.Append(rpcWorker.Create(OpCodes.Ret)); @@ -1132,7 +1090,7 @@ public void CallRpcTest (int param) } else { NetworkWriter writer = new NetworkWriter (); writer.WritePackedUInt32((uint)param); - base.SendRPCInternal(Player.kRpcRpcTest, writer, 0, "RpcTest"); + base.SendRPCInternal("RpcTest", writer, 0); } } */ @@ -1157,12 +1115,6 @@ MethodDefinition ProcessRpcCall(MethodDefinition md, CustomAttribute ca) WriteCreateWriter(rpcWorker); - // create the rpc id constant - FieldDefinition rpcConstant = new FieldDefinition("kRpc" + md.Name, - FieldAttributes.Static | FieldAttributes.Private, - Weaver.int32Type); - m_td.Fields.Add(rpcConstant); - // write all the arguments that the user passed to the Rpc call if (!WriteArguments(rpcWorker, md, "RPC", false)) return null; @@ -1176,10 +1128,9 @@ MethodDefinition ProcessRpcCall(MethodDefinition md, CustomAttribute ca) // invoke SendInternal and return rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); // this - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldsfld, rpcConstant)); // rpcHash + rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, rpcName)); rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0)); // writer rpcWorker.Append(rpcWorker.Create(OpCodes.Ldc_I4, GetChannelId(ca))); - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, rpcName)); rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.sendRpcInternal)); rpcWorker.Append(rpcWorker.Create(OpCodes.Ret)); @@ -1574,22 +1525,15 @@ MethodDefinition ProcessEventCall(EventDefinition ed, CustomAttribute ca) WriteCreateWriter(evtWorker); - // create the syncevent id constant - FieldDefinition evtConstant = new FieldDefinition("kEvent" + ed.Name, - FieldAttributes.Static | FieldAttributes.Private, - Weaver.int32Type); - m_td.Fields.Add(evtConstant); - // write all the arguments that the user passed to the syncevent if (!WriteArguments(evtWorker, invoke.Resolve(), "SyncEvent", false)) return null; // invoke interal send and return evtWorker.Append(evtWorker.Create(OpCodes.Ldarg_0)); // this - evtWorker.Append(evtWorker.Create(OpCodes.Ldsfld, evtConstant)); // eventHash + evtWorker.Append(evtWorker.Create(OpCodes.Ldstr, ed.Name)); evtWorker.Append(evtWorker.Create(OpCodes.Ldloc_0)); // writer evtWorker.Append(evtWorker.Create(OpCodes.Ldc_I4, GetChannelId(ca))); - evtWorker.Append(evtWorker.Create(OpCodes.Ldstr, ed.Name)); evtWorker.Append(evtWorker.Create(OpCodes.Call, Weaver.sendEventInternal)); evtWorker.Append(evtWorker.Create(OpCodes.Ret)); @@ -1908,30 +1852,6 @@ void ProcessSyncVars() Weaver.SetNumSyncVars(m_td.FullName, numSyncVars); } - // Copy of Mono string.GetHashCode(), so that we generate same hashes regardless of runtime (mono/MS .NET) - private static int GetHashCode(string s) - { - unsafe - { - int length = s.Length; - fixed(char* c = s) - { - char* cc = c; - char* end = cc + length - 1; - int h = 0; - for (; cc < end; cc += 2) - { - h = (h << 5) - h + *cc; - h = (h << 5) - h + cc[1]; - } - ++end; - if (cc < end) - h = (h << 5) - h + *cc; - return h; - } - } - } - bool HasMethod(string name) { foreach (var method in m_td.Methods)