mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
Weaver passes cmd/rpc/targetrpc/event names instead of hashcodes now. HLAPI worries about sending hashcodes instead.
This commit is contained in:
commit
53c1ea3788
19
Mirror/Runtime/Extensions.cs
Normal file
19
Mirror/Runtime/Extensions.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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" />
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user