mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
* Fix issue #75, determining the command target If you add the same networkbehavior twice to a gameobject, only the commands in the first one work. This can also happen if you have a base class, you inherit it, and you add more than one of the inherited classes to the same gameobject. * Improve error message * Fix issue #75 for all RPC methods * Fix formatting consistency * Fix build, replace logDebug with Debug * Use new NetworkBehaviours cache * Use FindIndex instead than for loop * No need for local variable * use int instead of byte for simplicity * component index are int now
This commit is contained in:
parent
1795cf8c2c
commit
39ad76cad1
@ -555,7 +555,7 @@ static void OnRPCMessage(NetworkMessage netMsg)
|
||||
NetworkIdentity uv;
|
||||
if (s_NetworkScene.GetNetworkIdentity(message.netId, out uv))
|
||||
{
|
||||
uv.HandleRPC(message.rpcHash, new NetworkReader(message.payload));
|
||||
uv.HandleRPC(message.componentIndex, message.rpcHash, new NetworkReader(message.payload));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -573,7 +573,7 @@ static void OnSyncEventMessage(NetworkMessage netMsg)
|
||||
NetworkIdentity uv;
|
||||
if (s_NetworkScene.GetNetworkIdentity(message.netId, out uv))
|
||||
{
|
||||
uv.HandleSyncEvent(message.eventHash, new NetworkReader(message.payload));
|
||||
uv.HandleSyncEvent(message.componentIndex, message.eventHash, new NetworkReader(message.payload));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -149,12 +149,14 @@ public class RemovePlayerMessage : MessageBase
|
||||
class CommandMessage : MessageBase
|
||||
{
|
||||
public uint netId;
|
||||
public int componentIndex;
|
||||
public int cmdHash;
|
||||
public byte[] payload; // the parameters for the Cmd function
|
||||
|
||||
public override void Deserialize(NetworkReader reader)
|
||||
{
|
||||
netId = reader.ReadPackedUInt32();
|
||||
componentIndex = (int)reader.ReadPackedUInt32();
|
||||
cmdHash = reader.ReadInt32(); // hash is always 4 full bytes, WritePackedInt would send 1 extra byte here
|
||||
payload = reader.ReadBytesAndSize();
|
||||
}
|
||||
@ -162,6 +164,7 @@ public override void Deserialize(NetworkReader reader)
|
||||
public override void Serialize(NetworkWriter writer)
|
||||
{
|
||||
writer.WritePackedUInt32(netId);
|
||||
writer.WritePackedUInt32((uint)componentIndex);
|
||||
writer.Write(cmdHash);
|
||||
writer.WriteBytesAndSize(payload);
|
||||
}
|
||||
@ -170,12 +173,14 @@ public override void Serialize(NetworkWriter writer)
|
||||
class RpcMessage : MessageBase
|
||||
{
|
||||
public uint netId;
|
||||
public int componentIndex;
|
||||
public int rpcHash;
|
||||
public byte[] payload; // the parameters for the Rpc function
|
||||
|
||||
public override void Deserialize(NetworkReader reader)
|
||||
{
|
||||
netId = reader.ReadPackedUInt32();
|
||||
componentIndex = (int)reader.ReadPackedUInt32();
|
||||
rpcHash = reader.ReadInt32(); // hash is always 4 full bytes, WritePackedInt would send 1 extra byte here
|
||||
payload = reader.ReadBytesAndSize();
|
||||
}
|
||||
@ -183,6 +188,7 @@ public override void Deserialize(NetworkReader reader)
|
||||
public override void Serialize(NetworkWriter writer)
|
||||
{
|
||||
writer.WritePackedUInt32(netId);
|
||||
writer.WritePackedUInt32((uint)componentIndex);
|
||||
writer.Write(rpcHash);
|
||||
writer.WriteBytesAndSize(payload);
|
||||
}
|
||||
@ -191,12 +197,14 @@ public override void Serialize(NetworkWriter writer)
|
||||
class SyncEventMessage : MessageBase
|
||||
{
|
||||
public uint netId;
|
||||
public int componentIndex;
|
||||
public int eventHash;
|
||||
public byte[] payload; // the parameters for the Rpc function
|
||||
|
||||
public override void Deserialize(NetworkReader reader)
|
||||
{
|
||||
netId = reader.ReadPackedUInt32();
|
||||
componentIndex = (int)reader.ReadPackedUInt32();
|
||||
eventHash = reader.ReadInt32(); // hash is always 4 full bytes, WritePackedInt would send 1 extra byte here
|
||||
payload = reader.ReadBytesAndSize();
|
||||
}
|
||||
@ -204,6 +212,7 @@ public override void Deserialize(NetworkReader reader)
|
||||
public override void Serialize(NetworkWriter writer)
|
||||
{
|
||||
writer.WritePackedUInt32(netId);
|
||||
writer.WritePackedUInt32((uint)componentIndex);
|
||||
writer.Write(eventHash);
|
||||
writer.WriteBytesAndSize(payload);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using UnityEngine;
|
||||
@ -48,6 +48,21 @@ NetworkIdentity myView
|
||||
}
|
||||
}
|
||||
|
||||
public int ComponentIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
int index = Array.FindIndex(m_MyView.NetworkBehaviours, component => component == this);
|
||||
if (index < 0)
|
||||
{
|
||||
// this should never happen
|
||||
Debug.LogError("Could not find component in gameobject. You shoud not add/remove components in networked objects dinamically", this);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
// this gets called in the constructor by the weaver
|
||||
// for every SyncObject in the component (e.g. SyncLists).
|
||||
// We collect all of them and we synchronize them with OnSerialize/OnDeserialize
|
||||
@ -77,6 +92,7 @@ protected void SendCommandInternal(int cmdHash, NetworkWriter writer, string cmd
|
||||
// construct the message
|
||||
CommandMessage message = new CommandMessage();
|
||||
message.netId = netId;
|
||||
message.componentIndex = ComponentIndex;
|
||||
message.cmdHash = cmdHash;
|
||||
message.payload = writer.ToArray();
|
||||
|
||||
@ -104,6 +120,7 @@ protected void SendRPCInternal(int rpcHash, NetworkWriter writer, string rpcName
|
||||
// construct the message
|
||||
RpcMessage message = new RpcMessage();
|
||||
message.netId = netId;
|
||||
message.componentIndex = ComponentIndex;
|
||||
message.rpcHash = rpcHash;
|
||||
message.payload = writer.ToArray();
|
||||
|
||||
@ -123,6 +140,7 @@ protected void SendTargetRPCInternal(NetworkConnection conn, int rpcHash, Networ
|
||||
// construct the message
|
||||
RpcMessage message = new RpcMessage();
|
||||
message.netId = netId;
|
||||
message.componentIndex = ComponentIndex;
|
||||
message.rpcHash = rpcHash;
|
||||
message.payload = writer.ToArray();
|
||||
|
||||
@ -149,6 +167,7 @@ protected void SendEventInternal(int eventHash, NetworkWriter writer, string eve
|
||||
// construct the message
|
||||
SyncEventMessage message = new SyncEventMessage();
|
||||
message.netId = netId;
|
||||
message.componentIndex = ComponentIndex;
|
||||
message.eventHash = eventHash;
|
||||
message.payload = writer.ToArray();
|
||||
|
||||
@ -244,28 +263,27 @@ internal static string GetInvoker(int cmdHash)
|
||||
}
|
||||
|
||||
// wrapper fucntions for each type of network operation
|
||||
internal static bool GetInvokerForHashCommand(int cmdHash, out Type invokeClass, out CmdDelegate invokeFunction)
|
||||
internal static bool GetInvokerForHashCommand(int cmdHash, out CmdDelegate invokeFunction)
|
||||
{
|
||||
return GetInvokerForHash(cmdHash, UNetInvokeType.Command, out invokeClass, out invokeFunction);
|
||||
return GetInvokerForHash(cmdHash, UNetInvokeType.Command, out invokeFunction);
|
||||
}
|
||||
|
||||
internal static bool GetInvokerForHashClientRpc(int cmdHash, out Type invokeClass, out CmdDelegate invokeFunction)
|
||||
internal static bool GetInvokerForHashClientRpc(int cmdHash, out CmdDelegate invokeFunction)
|
||||
{
|
||||
return GetInvokerForHash(cmdHash, UNetInvokeType.ClientRpc, out invokeClass, out invokeFunction);
|
||||
return GetInvokerForHash(cmdHash, UNetInvokeType.ClientRpc, out invokeFunction);
|
||||
}
|
||||
|
||||
internal static bool GetInvokerForHashSyncEvent(int cmdHash, out Type invokeClass, out CmdDelegate invokeFunction)
|
||||
internal static bool GetInvokerForHashSyncEvent(int cmdHash, out CmdDelegate invokeFunction)
|
||||
{
|
||||
return GetInvokerForHash(cmdHash, UNetInvokeType.SyncEvent, out invokeClass, out invokeFunction);
|
||||
return GetInvokerForHash(cmdHash, UNetInvokeType.SyncEvent, out invokeFunction);
|
||||
}
|
||||
|
||||
static bool GetInvokerForHash(int cmdHash, UNetInvokeType invokeType, out Type invokeClass, out CmdDelegate invokeFunction)
|
||||
static bool GetInvokerForHash(int cmdHash, UNetInvokeType invokeType, out CmdDelegate invokeFunction)
|
||||
{
|
||||
Invoker invoker = null;
|
||||
if (!s_CmdHandlerDelegates.TryGetValue(cmdHash, out invoker))
|
||||
{
|
||||
if (LogFilter.Debug) { Debug.Log("GetInvokerForHash hash:" + cmdHash + " not found"); }
|
||||
invokeClass = null;
|
||||
invokeFunction = null;
|
||||
return false;
|
||||
}
|
||||
@ -273,7 +291,6 @@ static bool GetInvokerForHash(int cmdHash, UNetInvokeType invokeType, out Type i
|
||||
if (invoker == null)
|
||||
{
|
||||
if (LogFilter.Debug) { Debug.Log("GetInvokerForHash hash:" + cmdHash + " invoker null"); }
|
||||
invokeClass = null;
|
||||
invokeFunction = null;
|
||||
return false;
|
||||
}
|
||||
@ -281,12 +298,10 @@ static bool GetInvokerForHash(int cmdHash, UNetInvokeType invokeType, out Type i
|
||||
if (invoker.invokeType != invokeType)
|
||||
{
|
||||
Debug.LogError("GetInvokerForHash hash:" + cmdHash + " mismatched invokeType");
|
||||
invokeClass = null;
|
||||
invokeFunction = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
invokeClass = invoker.invokeClass;
|
||||
invokeFunction = invoker.invokeFunction;
|
||||
return true;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
@ -546,24 +546,8 @@ internal void HandleClientAuthority(bool authority)
|
||||
ForceAuthority(authority);
|
||||
}
|
||||
|
||||
// helper function for Handle** functions
|
||||
bool GetInvokeComponent(int cmdHash, Type invokeClass, out NetworkBehaviour invokeComponent)
|
||||
{
|
||||
// dont use GetComponent(), already have a list - avoids an allocation
|
||||
invokeComponent = Array.Find(m_NetworkBehaviours,
|
||||
comp => comp.GetType() == invokeClass || comp.GetType().IsSubclassOf(invokeClass)
|
||||
);
|
||||
if (invokeComponent == null)
|
||||
{
|
||||
string errorCmdName = NetworkBehaviour.GetCmdHashHandlerName(cmdHash);
|
||||
Debug.LogError("Found no behaviour for incoming [" + errorCmdName + "] on " + gameObject + ", the server and client should have the same NetworkBehaviour instances [netId=" + netId + "].");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// happens on client
|
||||
internal void HandleSyncEvent(int cmdHash, NetworkReader reader)
|
||||
internal void HandleSyncEvent(int componentIndex, int cmdHash, NetworkReader reader)
|
||||
{
|
||||
// this doesn't use NetworkBehaviour.InvokeSyncEvent function (anymore). this method of calling is faster.
|
||||
// The hash is only looked up once, insted of twice(!) per NetworkBehaviour on the object.
|
||||
@ -577,8 +561,7 @@ internal void HandleSyncEvent(int cmdHash, NetworkReader reader)
|
||||
|
||||
// find the matching SyncEvent function and networkBehaviour class
|
||||
NetworkBehaviour.CmdDelegate invokeFunction;
|
||||
Type invokeClass;
|
||||
bool invokeFound = NetworkBehaviour.GetInvokerForHashSyncEvent(cmdHash, out invokeClass, out invokeFunction);
|
||||
bool invokeFound = NetworkBehaviour.GetInvokerForHashSyncEvent(cmdHash, out invokeFunction);
|
||||
if (!invokeFound)
|
||||
{
|
||||
// We don't get a valid lookup of the command name when it doesn't exist...
|
||||
@ -588,19 +571,18 @@ internal void HandleSyncEvent(int cmdHash, NetworkReader reader)
|
||||
}
|
||||
|
||||
// find the right component to invoke the function on
|
||||
NetworkBehaviour invokeComponent;
|
||||
if (!GetInvokeComponent(cmdHash, invokeClass, out invokeComponent))
|
||||
if (componentIndex >= m_NetworkBehaviours.Length)
|
||||
{
|
||||
string errorCmdName = NetworkBehaviour.GetCmdHashHandlerName(cmdHash);
|
||||
Debug.LogWarning("SyncEvent [" + errorCmdName + "] handler not found [netId=" + netId + "]");
|
||||
Debug.LogWarning("Component [" + componentIndex + "] not found for [netId=" + netId + "]");
|
||||
return;
|
||||
}
|
||||
NetworkBehaviour invokeComponent = m_NetworkBehaviours[componentIndex];
|
||||
|
||||
invokeFunction(invokeComponent, reader);
|
||||
}
|
||||
|
||||
// happens on server
|
||||
internal void HandleCommand(int cmdHash, NetworkReader reader)
|
||||
internal void HandleCommand(int componentIndex, int cmdHash, NetworkReader reader)
|
||||
{
|
||||
// this doesn't use NetworkBehaviour.InvokeCommand function (anymore). this method of calling is faster.
|
||||
// The hash is only looked up once, insted of twice(!) per NetworkBehaviour on the object.
|
||||
@ -614,8 +596,7 @@ internal void HandleCommand(int cmdHash, NetworkReader reader)
|
||||
|
||||
// find the matching Command function and networkBehaviour class
|
||||
NetworkBehaviour.CmdDelegate invokeFunction;
|
||||
Type invokeClass;
|
||||
bool invokeFound = NetworkBehaviour.GetInvokerForHashCommand(cmdHash, out invokeClass, out invokeFunction);
|
||||
bool invokeFound = NetworkBehaviour.GetInvokerForHashCommand(cmdHash, out invokeFunction);
|
||||
if (!invokeFound)
|
||||
{
|
||||
// We don't get a valid lookup of the command name when it doesn't exist...
|
||||
@ -625,19 +606,18 @@ internal void HandleCommand(int cmdHash, NetworkReader reader)
|
||||
}
|
||||
|
||||
// find the right component to invoke the function on
|
||||
NetworkBehaviour invokeComponent;
|
||||
if (!GetInvokeComponent(cmdHash, invokeClass, out invokeComponent))
|
||||
if (componentIndex >= m_NetworkBehaviours.Length)
|
||||
{
|
||||
string errorCmdName = NetworkBehaviour.GetCmdHashHandlerName(cmdHash);
|
||||
Debug.LogWarning("Command [" + errorCmdName + "] handler not found [netId=" + netId + "]");
|
||||
Debug.LogWarning("Component [" + componentIndex + "] not found for [netId=" + netId + "]");
|
||||
return;
|
||||
}
|
||||
NetworkBehaviour invokeComponent = m_NetworkBehaviours[componentIndex];
|
||||
|
||||
invokeFunction(invokeComponent, reader);
|
||||
}
|
||||
|
||||
// happens on client
|
||||
internal void HandleRPC(int cmdHash, NetworkReader reader)
|
||||
internal void HandleRPC(int componentIndex, int cmdHash, NetworkReader reader)
|
||||
{
|
||||
// this doesn't use NetworkBehaviour.InvokeClientRpc function (anymore). this method of calling is faster.
|
||||
// The hash is only looked up once, insted of twice(!) per NetworkBehaviour on the object.
|
||||
@ -651,8 +631,7 @@ internal void HandleRPC(int cmdHash, NetworkReader reader)
|
||||
|
||||
// find the matching ClientRpc function and networkBehaviour class
|
||||
NetworkBehaviour.CmdDelegate invokeFunction;
|
||||
Type invokeClass;
|
||||
bool invokeFound = NetworkBehaviour.GetInvokerForHashClientRpc(cmdHash, out invokeClass, out invokeFunction);
|
||||
bool invokeFound = NetworkBehaviour.GetInvokerForHashClientRpc(cmdHash, out invokeFunction);
|
||||
if (!invokeFound)
|
||||
{
|
||||
// We don't get a valid lookup of the command name when it doesn't exist...
|
||||
@ -662,13 +641,12 @@ internal void HandleRPC(int cmdHash, NetworkReader reader)
|
||||
}
|
||||
|
||||
// find the right component to invoke the function on
|
||||
NetworkBehaviour invokeComponent;
|
||||
if (!GetInvokeComponent(cmdHash, invokeClass, out invokeComponent))
|
||||
if (componentIndex >= m_NetworkBehaviours.Length)
|
||||
{
|
||||
string errorCmdName = NetworkBehaviour.GetCmdHashHandlerName(cmdHash);
|
||||
Debug.LogWarning("ClientRpc [" + errorCmdName + "] handler not found [netId=" + netId + "]");
|
||||
Debug.LogWarning("Component [" + componentIndex + "] not found for [netId=" + netId + "]");
|
||||
return;
|
||||
}
|
||||
NetworkBehaviour invokeComponent = m_NetworkBehaviours[componentIndex];
|
||||
|
||||
invokeFunction(invokeComponent, reader);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
@ -902,7 +902,7 @@ static void OnCommandMessage(NetworkMessage netMsg)
|
||||
}
|
||||
|
||||
if (LogFilter.Debug) { Debug.Log("OnCommandMessage for netId=" + message.netId + " conn=" + netMsg.conn); }
|
||||
uv.HandleCommand(message.cmdHash, new NetworkReader(message.payload));
|
||||
uv.HandleCommand(message.componentIndex, message.cmdHash, new NetworkReader(message.payload));
|
||||
}
|
||||
|
||||
internal static void SpawnObject(GameObject obj)
|
||||
|
Loading…
Reference in New Issue
Block a user