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)