diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/ContextualLogger.cs b/com.unity.netcode.gameobjects/Runtime/Logging/ContextualLogger.cs index 006f919ce1..d87ec8cc9f 100644 --- a/com.unity.netcode.gameobjects/Runtime/Logging/ContextualLogger.cs +++ b/com.unity.netcode.gameobjects/Runtime/Logging/ContextualLogger.cs @@ -60,7 +60,7 @@ public ContextualLogger(Object inspectorObject, [NotNull] NetworkManager network } /// Used for the NetworkLog - internal ContextualLogger(NetworkManager networkManager, bool useCompatibilityMode) + internal ContextualLogger(NetworkManager networkManager, bool useCompatibilityMode = false) { m_UseCompatibilityMode = useCompatibilityMode; m_ManagerContext = new LogContextNetworkManager(networkManager); @@ -125,6 +125,19 @@ public void Exception(Exception exception) { Debug.unityLogger.LogException(exception, m_Object); } + [HideInCallstack] + public void Exception(Exception exception, Context context) + { + // Don't act if the LogLevel is higher than the level of this log + if (m_ManagerContext.LogLevel > context.Level) + { + return; + } + + var message = BuildLog(context); + Debug.unityLogger.LogException(new Exception(message, exception), context.RelevantObjectOverride ?? m_Object); + } + [HideInCallstack] private void Log(LogType logType, Context context) diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/LogBuilder.cs b/com.unity.netcode.gameobjects/Runtime/Logging/LogBuilder.cs index 0c59e10bd4..c8f8c1ba25 100644 --- a/com.unity.netcode.gameobjects/Runtime/Logging/LogBuilder.cs +++ b/com.unity.netcode.gameobjects/Runtime/Logging/LogBuilder.cs @@ -31,6 +31,7 @@ public void AppendInfo(object key, object value) } public void Append(string value) => m_Builder.Append(value); + public void AppendLine(string value) => m_Builder.AppendLine(value); public string Build() => m_Builder.ToString(); } diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/LogContext.cs b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext.cs deleted file mode 100644 index 8c6cbd0bf1..0000000000 --- a/com.unity.netcode.gameobjects/Runtime/Logging/LogContext.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Runtime.CompilerServices; -using Object = UnityEngine.Object; - -namespace Unity.Netcode.Logging -{ - internal interface ILogContext - { - public void AppendTo(LogBuilder builder) - { - } - } - - internal struct Context : ILogContext - { - public readonly LogLevel Level; - private readonly string m_CallingFunction; - internal readonly string Message; - internal Object RelevantObjectOverride; - - private readonly GenericContext m_Other; - - public Context(LogLevel level, string msg, [CallerMemberName] string memberName = "") - { - Level = level; - Message = msg; - m_CallingFunction = memberName; - - m_Other = GenericContext.Create(); - RelevantObjectOverride = null; - } - - internal Context(LogLevel level, string msg, bool noCaller) - { - Level = level; - Message = msg; - m_CallingFunction = null; - - m_Other = GenericContext.Create(); - RelevantObjectOverride = null; - } - - public void AppendTo(LogBuilder builder) - { - // [CallingFunction] - if (!string.IsNullOrEmpty(m_CallingFunction)) - { - builder.AppendTag(m_CallingFunction); - } - - // [SomeContext][SomeName:SomeValue] - m_Other.AppendTo(builder); - - // Human-readable log message - builder.Append(" "); - builder.Append(Message); - } - - public Context AddInfo(object key, object value) - { - m_Other.StoreInfo(key, value); - return this; - } - - public Context AddTag(string msg) - { - m_Other.StoreTag(msg); - return this; - } - - public Context AddObject(Object obj) - { - RelevantObjectOverride = obj; - return this; - } - } -} diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/LogContext.meta b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext.meta new file mode 100644 index 0000000000..7c7f21c305 --- /dev/null +++ b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1a57adef9bcf4768866c1e922dff4ad1 +timeCreated: 1779217887 \ No newline at end of file diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/CollectionContext.cs b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/CollectionContext.cs new file mode 100644 index 0000000000..70c493950d --- /dev/null +++ b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/CollectionContext.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace Unity.Netcode.Logging +{ + internal delegate string LogCollectionBuilder(TItem item); + internal readonly struct CollectionContext : ILogContext + { + private readonly LogCollectionBuilder m_Delegate; + private readonly IEnumerable m_Collection; + + public CollectionContext(IEnumerable collection, LogCollectionBuilder builder) + { + m_Delegate = builder; + m_Collection = collection; + } + + public void AppendTo(LogBuilder builder) + { + foreach (var item in m_Collection) + { + builder.AppendLine(m_Delegate(item)); + } + } + } +} diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/CollectionContext.cs.meta b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/CollectionContext.cs.meta new file mode 100644 index 0000000000..5323a6eda2 --- /dev/null +++ b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/CollectionContext.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f64de1e86c70433e96280f0c8af6e8f6 +timeCreated: 1779214517 \ No newline at end of file diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/GenericContext.cs b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/GenericContext.cs similarity index 78% rename from com.unity.netcode.gameobjects/Runtime/Logging/GenericContext.cs rename to com.unity.netcode.gameobjects/Runtime/Logging/LogContext/GenericContext.cs index 47d198f447..e41b8d512b 100644 --- a/com.unity.netcode.gameobjects/Runtime/Logging/GenericContext.cs +++ b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/GenericContext.cs @@ -1,24 +1,25 @@ using System; using System.Collections.Generic; +using UnityEngine; namespace Unity.Netcode.Logging { internal readonly struct GenericContext : ILogContext, IDisposable { - private readonly List m_Contexts; + private readonly List m_Tags; private readonly Dictionary m_Info; - private GenericContext(List contexts, Dictionary info) + private GenericContext(List tags, Dictionary info) { - m_Contexts = contexts; + m_Tags = tags; m_Info = info; } public void AppendTo(LogBuilder builder) { - if (m_Contexts != null) + if (m_Tags != null) { - foreach (var ctx in m_Contexts) + foreach (var ctx in m_Tags) { builder.AppendTag(ctx); } @@ -33,9 +34,9 @@ public void AppendTo(LogBuilder builder) } } - public void StoreTag(string msg) + public void StoreTag(string tag) { - m_Contexts.Add(msg); + m_Tags.Add(tag); } public void StoreInfo(object key, object value) @@ -43,11 +44,16 @@ public void StoreInfo(object key, object value) m_Info.Add(key, value); } - public void ClearInfo(object key) + public void RemoveInfo(object key) { m_Info?.Remove(key); } + public void RemoveTag(string tag) + { + m_Tags?.Remove(tag); + } + public void Dispose() { PreallocatedStore.Free(this); @@ -76,7 +82,7 @@ internal static GenericContext GetPreallocated() internal static void Free(GenericContext ctx) { - ctx.m_Contexts.Clear(); + ctx.m_Tags.Clear(); ctx.m_Info.Clear(); k_Preallocated.Enqueue(ctx); } diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/GenericContext.cs.meta b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/GenericContext.cs.meta similarity index 100% rename from com.unity.netcode.gameobjects/Runtime/Logging/GenericContext.cs.meta rename to com.unity.netcode.gameobjects/Runtime/Logging/LogContext/GenericContext.cs.meta diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContext.cs b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContext.cs new file mode 100644 index 0000000000..a36b6b91fb --- /dev/null +++ b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContext.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using Object = UnityEngine.Object; + +namespace Unity.Netcode.Logging +{ + internal interface ILogContext + { + public void AppendTo(LogBuilder builder); + } + + internal struct Context : ILogContext, IDisposable + { + public readonly LogLevel Level; + private readonly string m_CallingFunction; + internal readonly string Message; + internal Object RelevantObjectOverride; + + private readonly GenericContext m_Other; + private List m_Prepend; + private List m_Postpend; + + public Context(LogLevel level, string msg, [CallerMemberName] string memberName = "") + { + Level = level; + Message = msg; + m_CallingFunction = memberName; + + m_Other = GenericContext.Create(); + RelevantObjectOverride = null; + m_Prepend = null; + m_Postpend = null; + } + + internal Context(LogLevel level, string msg, bool noCaller) + { + Level = level; + Message = msg; + m_CallingFunction = null; + + m_Other = GenericContext.Create(); + RelevantObjectOverride = null; + m_Prepend = null; + m_Postpend = null; + } + + public void AppendTo(LogBuilder builder) + { + // [CallingFunction] + if (!string.IsNullOrEmpty(m_CallingFunction)) + { + builder.AppendTag(m_CallingFunction); + } + + + // [SomeContext][SomeName:SomeValue] + m_Other.AppendTo(builder); + + if (m_Prepend != null) + { + foreach (var context in m_Prepend) + { + context.AppendTo(builder); + } + } + + // Human-readable log message + builder.Append(" "); + builder.Append(Message); + + if (m_Postpend != null) + { + foreach (var context in m_Postpend) + { + context.AppendTo(builder); + } + } + } + + public Context AddInfo(object key, object value) + { + m_Other.StoreInfo(key, value); + return this; + } + + public Context AddTag(string msg) + { + m_Other.StoreTag(msg); + return this; + } + + public Context AddObject(Object obj) + { + RelevantObjectOverride = obj; + return this; + } + + public Context AddNetworkObject(NetworkObject networkObject) + { + AddPrepend(new LogContextNetworkObject(networkObject)); + RelevantObjectOverride = networkObject; + return this; + } + + public Context AddNetworkBehaviour(NetworkBehaviour networkBehaviour) + { + AddPrepend(new LogContextNetworkBehaviour(networkBehaviour)); + RelevantObjectOverride = networkBehaviour; + return this; + } + + public Context AddCollection(IEnumerable collection, LogCollectionBuilder builder) + { + AddPostpend(new CollectionContext(collection, builder)); + return this; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void AddPrepend(ILogContext prepend) + { + if (m_Prepend == null) + { + m_Prepend = PreallocatedStore.GetPreallocated(); + } + m_Prepend.Add(prepend); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void AddPostpend(ILogContext postpend) + { + if (m_Postpend == null) + { + m_Postpend = PreallocatedStore.GetPreallocated(); + } + m_Postpend.Add(postpend); + } + + public void Dispose() + { + m_Other.Dispose(); + PreallocatedStore.Free(m_Prepend); + PreallocatedStore.Free(m_Postpend); + m_Prepend = null; + m_Postpend = null; + } + + private static class PreallocatedStore + { + private static readonly Queue> k_Preallocated = new(); + + internal static List GetPreallocated() + { + if (k_Preallocated.Count > 0) + { + k_Preallocated.Dequeue(); + } + + return new List(); + } + + internal static void Free(List collection) + { + collection.Clear(); + k_Preallocated.Enqueue(collection); + } + } + } +} diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/LogContext.cs.meta b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContext.cs.meta similarity index 100% rename from com.unity.netcode.gameobjects/Runtime/Logging/LogContext.cs.meta rename to com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContext.cs.meta diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkBehaviour.cs b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkBehaviour.cs new file mode 100644 index 0000000000..149fd001ff --- /dev/null +++ b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkBehaviour.cs @@ -0,0 +1,21 @@ +namespace Unity.Netcode.Logging +{ + internal readonly struct LogContextNetworkBehaviour : ILogContext + { + private readonly NetworkBehaviour m_NetworkBehaviour; + + public LogContextNetworkBehaviour(NetworkBehaviour networkBehaviour) + { + m_NetworkBehaviour = networkBehaviour; + } + + public void AppendTo(LogBuilder builder) + { + builder.AppendTag(m_NetworkBehaviour.gameObject.name); + if (m_NetworkBehaviour.IsSpawned) + { + builder.AppendInfo(nameof(NetworkBehaviour.NetworkBehaviourId), m_NetworkBehaviour.NetworkBehaviourId); + } + } + } +} diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkBehaviour.cs.meta b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkBehaviour.cs.meta new file mode 100644 index 0000000000..a4f9cae7ed --- /dev/null +++ b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkBehaviour.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ce875bd203c24cf1b916741eac3a55f8 +timeCreated: 1779217913 \ No newline at end of file diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/LogContextNetworkManager.cs b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkManager.cs similarity index 100% rename from com.unity.netcode.gameobjects/Runtime/Logging/LogContextNetworkManager.cs rename to com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkManager.cs diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/LogContextNetworkManager.cs.meta b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkManager.cs.meta similarity index 100% rename from com.unity.netcode.gameobjects/Runtime/Logging/LogContextNetworkManager.cs.meta rename to com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkManager.cs.meta diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkObject.cs b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkObject.cs new file mode 100644 index 0000000000..d7feb201b1 --- /dev/null +++ b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkObject.cs @@ -0,0 +1,21 @@ +namespace Unity.Netcode.Logging +{ + internal readonly struct LogContextNetworkObject : ILogContext + { + private readonly NetworkObject m_NetworkObject; + + public LogContextNetworkObject(NetworkObject networkObject) + { + m_NetworkObject = networkObject; + } + + public void AppendTo(LogBuilder builder) + { + builder.AppendTag(m_NetworkObject.name); + if (m_NetworkObject.IsSpawned) + { + builder.AppendInfo(nameof(NetworkObject.NetworkObjectId), m_NetworkObject.NetworkObjectId); + } + } + } +} diff --git a/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkObject.cs.meta b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkObject.cs.meta new file mode 100644 index 0000000000..9c98d47b80 --- /dev/null +++ b/com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContextNetworkObject.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d6f400599d664e92a747913ca672e02e +timeCreated: 1779217114 \ No newline at end of file diff --git a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/RpcMessages.cs b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/RpcMessages.cs index c8be0c251d..843d875216 100644 --- a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/RpcMessages.cs +++ b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/RpcMessages.cs @@ -1,6 +1,6 @@ using System; using Unity.Collections; -using UnityEngine; +using Unity.Netcode.Logging; namespace Unity.Netcode { @@ -16,80 +16,79 @@ public static unsafe void Serialize(ref FastBufferWriter writer, ref RpcMetadata public static unsafe bool Deserialize(ref FastBufferReader reader, ref NetworkContext context, ref RpcMetadata metadata, ref FastBufferReader payload, string messageType) { + var networkManager = (NetworkManager)context.SystemOwner; ByteUnpacker.ReadValueBitPacked(reader, out metadata.NetworkObjectId); - ByteUnpacker.ReadValueBitPacked(reader, out metadata.NetworkBehaviourId); - ByteUnpacker.ReadValueBitPacked(reader, out metadata.NetworkRpcMethodId); - var networkManager = (NetworkManager)context.SystemOwner; - if (!networkManager.SpawnManager.SpawnedObjects.ContainsKey(metadata.NetworkObjectId)) + if (!networkManager.SpawnManager.SpawnedObjects.TryGetValue(metadata.NetworkObjectId, out var networkObject)) { + networkManager.Log.Info(new Context(LogLevel.Developer, $"Received RPC message for {nameof(NetworkObject)} that doesn't exist yet. Deferring the message.").AddInfo("SenderClientId", context.SenderId).AddInfo(nameof(NetworkObject.NetworkObjectId), metadata.NetworkObjectId).AddInfo(nameof(RpcMetadata.NetworkRpcMethodId), metadata.NetworkRpcMethodId)); networkManager.DeferredMessageManager.DeferMessage(IDeferredNetworkMessageManager.TriggerType.OnSpawn, metadata.NetworkObjectId, reader, ref context, messageType); return false; } - var networkObject = networkManager.SpawnManager.SpawnedObjects[metadata.NetworkObjectId]; - var networkBehaviour = networkManager.SpawnManager.SpawnedObjects[metadata.NetworkObjectId].GetNetworkBehaviourAtOrderIndex(metadata.NetworkBehaviourId); - if (networkBehaviour == null) - { - return false; - } - - if (!NetworkBehaviour.__rpc_func_table[networkBehaviour.GetType()].ContainsKey(metadata.NetworkRpcMethodId)) - { - return false; - } + ByteUnpacker.ReadValueBitPacked(reader, out metadata.NetworkBehaviourId); + ByteUnpacker.ReadValueBitPacked(reader, out metadata.NetworkRpcMethodId); payload = new FastBufferReader(reader.GetUnsafePtrAtCurrentPosition(), Allocator.None, reader.Length - reader.Position); -#if MULTIPLAYER_TOOLS && (DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE) - networkBehaviour.TrackRpcMetricsReceive(ref metadata, ref context, reader.Length); -#endif return true; } public static void Handle(ref NetworkContext context, ref RpcMetadata metadata, ref FastBufferReader payload, ref __RpcParams rpcParams) { var networkManager = (NetworkManager)context.SystemOwner; + if (!networkManager.SpawnManager.SpawnedObjects.TryGetValue(metadata.NetworkObjectId, out var networkObject)) { // If the NetworkObject no longer exists then just log a warning when developer mode logging is enabled and exit. // This can happen if NetworkObject is despawned and a client sends an RPC before receiving the despawn message. - if (networkManager.LogLevel == LogLevel.Developer) - { - NetworkLog.LogWarning($"[{metadata.NetworkObjectId}, {metadata.NetworkBehaviourId}, {metadata.NetworkRpcMethodId}] An RPC called on a {nameof(NetworkObject)} that is not in the spawned objects list. Please make sure the {nameof(NetworkObject)} is spawned before calling RPCs."); - } - + networkManager.Log.Warning(new Context(LogLevel.Developer, $"Received RPC message for {nameof(NetworkObject)} that doesn't exist yet. Deferring the message.").AddInfo(nameof(NetworkObject.NetworkObjectId), metadata.NetworkObjectId).AddInfo(nameof(RpcMetadata.NetworkRpcMethodId), metadata.NetworkRpcMethodId)); return; } var networkBehaviour = networkObject.GetNetworkBehaviourAtOrderIndex(metadata.NetworkBehaviourId); - try + if (networkBehaviour == null) + { + networkManager.Log.Error(new Context(LogLevel.Normal, $"Received RPC message for {nameof(NetworkBehaviour)} that doesn't exist. Dropping RPC message").AddNetworkObject(networkObject).AddInfo(nameof(NetworkBehaviour.NetworkBehaviourId), networkBehaviour.NetworkBehaviourId)); + return; + } + + var type = networkBehaviour.GetType(); + if (!NetworkBehaviour.__rpc_func_table.TryGetValue(type, out var rpcsForBehaviour) || !NetworkBehaviour.__rpc_permission_table.TryGetValue(type, out var permissionsTable)) + { + networkManager.Log.Error(new Context(LogLevel.Normal, $"Rpc table doesn't have RPCs registered for this {nameof(NetworkBehaviour)}. Dropping RPC message").AddNetworkObject(networkObject).AddInfo(nameof(NetworkBehaviour.NetworkBehaviourId), networkBehaviour.NetworkBehaviourId).AddInfo(nameof(NetworkBehaviour), type)); + return; + } + if (!rpcsForBehaviour.TryGetValue(metadata.NetworkRpcMethodId, out var receiveHandler) || !permissionsTable.TryGetValue(metadata.NetworkRpcMethodId, out var permission)) { - var permission = NetworkBehaviour.__rpc_permission_table[networkBehaviour.GetType()][metadata.NetworkRpcMethodId]; + networkManager.Log.Error(new Context(LogLevel.Normal, "Received RPC message for RPC receiver that doesn't exist. Dropping RPC message").AddNetworkBehaviour(networkBehaviour).AddInfo(nameof(RpcMetadata.NetworkRpcMethodId), metadata.NetworkRpcMethodId)); + return; + } - if ((permission == RpcInvokePermission.Server && rpcParams.SenderId != NetworkManager.ServerClientId) || - (permission == RpcInvokePermission.Owner && rpcParams.SenderId != networkObject.OwnerClientId)) - { - if (networkManager.LogLevel <= LogLevel.Developer) - { - NetworkLog.LogErrorServer($"Rpc message received from client-{rpcParams.SenderId} who does not have permission to perform this operation!"); - } - return; - } + if ((permission == RpcInvokePermission.Server && rpcParams.SenderId != NetworkManager.ServerClientId) || + (permission == RpcInvokePermission.Owner && rpcParams.SenderId != networkObject.OwnerClientId)) + { + networkManager.Log.ErrorServer(new Context(LogLevel.Normal, "Rpc message received from a client without permission to perform this operation!. Dropping RPC message").AddNetworkBehaviour(networkBehaviour)); + return; + } + +#if MULTIPLAYER_TOOLS && (DEVELOPMENT_BUILD || UNITY_EDITOR || UNITY_MP_TOOLS_NET_STATS_MONITOR_ENABLED_IN_RELEASE) + networkBehaviour.TrackRpcMetricsReceive(ref metadata, ref context, payload.Length); +#endif - NetworkBehaviour.__rpc_func_table[networkBehaviour.GetType()][metadata.NetworkRpcMethodId](networkBehaviour, payload, rpcParams); + try + { + receiveHandler(networkBehaviour, payload, rpcParams); } catch (Exception ex) { - Debug.LogException(new Exception($"Unhandled RPC exception!", ex)); - if (networkManager.LogLevel <= LogLevel.Developer) + networkManager.Log.Exception(ex, new Context(LogLevel.Error, "Unhandled RPC exception!").AddNetworkBehaviour(networkBehaviour)); + + var methodId = metadata.NetworkRpcMethodId; + networkManager.Log.Info(new Context(LogLevel.Developer, "RPC Table Contents").AddCollection(rpcsForBehaviour, entry => { - Debug.Log($"RPC Table Contents"); - foreach (var entry in NetworkBehaviour.__rpc_func_table[networkBehaviour.GetType()]) - { - var permission = NetworkBehaviour.__rpc_permission_table[networkBehaviour.GetType()][metadata.NetworkRpcMethodId]; - Debug.Log($"{entry.Key} | {entry.Value.Method.Name} | {permission}"); - } - } + var invokePermission = NetworkBehaviour.__rpc_permission_table[networkBehaviour.GetType()][methodId]; + return $"{entry.Key} | {entry.Value.Method.Name} | {invokePermission}"; + })); } } } @@ -270,12 +269,12 @@ public void Handle(ref NetworkContext context) } catch (Exception ex) { - Debug.LogException(ex); + networkManager.Log.Exception(ex); } } else { - NetworkLog.LogErrorServer($"Received {nameof(ForwardServerRpcMessage)} on client-{networkManager.LocalClientId}! Only DAHost may forward RPC messages!"); + networkManager.Log.ErrorServer(new Context(LogLevel.Error, $"Received {nameof(ForwardServerRpcMessage)} when not the DAHost! Only DAHost may forward RPC messages!").AddInfo("SenderClientId", context.SenderId)); } ServerRpcMessage.ReadBuffer.Dispose(); ServerRpcMessage.WriteBuffer.Dispose(); @@ -351,7 +350,7 @@ public void Handle(ref NetworkContext context) } else { - NetworkLog.LogErrorServer($"Received {nameof(ForwardClientRpcMessage)} on client-{networkManager.LocalClientId}! Only DAHost may forward RPC messages!"); + networkManager.Log.ErrorServer(new Context(LogLevel.Error, $"Received {nameof(ForwardClientRpcMessage)} when not the DAHost! Only DAHost may forward RPC messages!").AddInfo("SenderClientId", context.SenderId)); } ClientRpcMessage.WriteBuffer.Dispose(); ClientRpcMessage.ReadBuffer.Dispose(); diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Rpc/RpcInvocationTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Rpc/RpcInvocationTests.cs index 996021d425..613b81f5e5 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Rpc/RpcInvocationTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Rpc/RpcInvocationTests.cs @@ -139,7 +139,16 @@ public IEnumerator RpcInvokePermissionSendingTests() [UnityTest] public IEnumerator RpcInvokePermissionReceivingTests() { - var firstClient = GetNonAuthorityNetworkManager(0); + NetworkManager firstClient = null; + foreach (var networkManager in m_NetworkManagers) + { + if (firstClient == null && !networkManager.IsServer && !networkManager.LocalClient.IsSessionOwner) + { + firstClient = networkManager; + } + + networkManager.LogLevel = LogLevel.Error; + } var spawnedObject = SpawnObject(m_Prefab, firstClient).GetComponent();