Weaver passes cmd/rpc/targetrpc/event names instead of hashcodes now. HLAPI worries about sending hashcodes instead.

This commit is contained in:
vis2k 2018-12-30 17:13:03 +01:00 committed by GitHub
commit 53c1ea3788
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 111 deletions

View File

@ -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;
}
}
}
}

View File

@ -65,6 +65,7 @@
<Compile Include="ClientScene.cs" />
<Compile Include="CustomAttributes.cs" />
<Compile Include="DotNetCompatibility.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="LocalConnections.cs" />
<Compile Include="LogFilter.cs" />
<Compile Include="Messages.cs" />

View File

@ -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<int, Invoker> s_CmdHandlerDelegates = new Dictionary<int, Invoker>();
[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)

View File

@ -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)