diff --git a/MLAPI/Core/NetworkedBehaviour.cs b/MLAPI/Core/NetworkedBehaviour.cs index cf4dbf2d70..f113fc87d8 100644 --- a/MLAPI/Core/NetworkedBehaviour.cs +++ b/MLAPI/Core/NetworkedBehaviour.cs @@ -1258,48 +1258,20 @@ internal void SendClientRPCPerformance(ulong hash, List clientIds, Strea stream.CopyFrom(messageStream); - if (clientIds == null) + if (IsHost) { - for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++) + if (this.NetworkedObject.observers.Contains(NetworkingManager.Singleton.LocalClientId)) { - if (!this.NetworkedObject.observers.Contains(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId)) - { - if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) NetworkLog.LogWarning("Silently suppressed ClientRPC because a target in the bulk list was not an observer"); - continue; - } - - if (IsHost && NetworkingManager.Singleton.ConnectedClientsList[i].ClientId == NetworkingManager.Singleton.LocalClientId) - { - messageStream.Position = 0; - InvokeClientRPCLocal(hash, NetworkingManager.Singleton.LocalClientId, messageStream); - } - else - { - InternalMessageSender.Send(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, MLAPIConstants.MLAPI_CLIENT_RPC, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null); - } + messageStream.Position = 0; + InvokeClientRPCLocal(hash, NetworkingManager.Singleton.LocalClientId, messageStream); } - } - else - { - for (int i = 0; i < clientIds.Count; i++) + else { - if (!this.NetworkedObject.observers.Contains(clientIds[i])) - { - if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) NetworkLog.LogWarning("Cannot send ClientRPC to client without visibility to the object"); - continue; - } - - if (IsHost && clientIds[i] == NetworkingManager.Singleton.LocalClientId) - { - messageStream.Position = 0; - InvokeClientRPCLocal(hash, NetworkingManager.Singleton.LocalClientId, messageStream); - } - else - { - InternalMessageSender.Send(clientIds[i], MLAPIConstants.MLAPI_CLIENT_RPC, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null); - } + if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) NetworkLog.LogWarning("Silently suppressed ClientRPC because a connected client was not an observer"); } } + + InternalMessageSender.Send(MLAPIConstants.MLAPI_CLIENT_RPC, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, clientIds, stream, security, this.NetworkedObject); } } } @@ -1324,28 +1296,20 @@ internal void SendClientRPCPerformance(ulong hash, Stream messageStream, ulong c stream.CopyFrom(messageStream); - for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++) + if (IsHost && NetworkingManager.Singleton.LocalClientId != clientIdToIgnore) { - if (NetworkingManager.Singleton.ConnectedClientsList[i].ClientId == clientIdToIgnore) - continue; - - if (!this.NetworkedObject.observers.Contains(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId)) - { - if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) NetworkLog.LogWarning("Silently suppressed ClientRPC because a connected client was not an observer"); - continue; - } - - - if (IsHost && NetworkingManager.Singleton.ConnectedClientsList[i].ClientId == NetworkingManager.Singleton.LocalClientId) + if (this.NetworkedObject.observers.Contains(NetworkingManager.Singleton.LocalClientId)) { messageStream.Position = 0; InvokeClientRPCLocal(hash, NetworkingManager.Singleton.LocalClientId, messageStream); } else { - InternalMessageSender.Send(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, MLAPIConstants.MLAPI_CLIENT_RPC, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null); + if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) NetworkLog.LogWarning("Silently suppressed ClientRPC because a connected client was not an observer"); } } + + InternalMessageSender.Send(MLAPIConstants.MLAPI_CLIENT_RPC, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, clientIdToIgnore, stream, security, this.NetworkedObject); } } } diff --git a/MLAPI/Core/NetworkingManager.cs b/MLAPI/Core/NetworkingManager.cs index d237d7c15e..aae30d3a95 100644 --- a/MLAPI/Core/NetworkingManager.cs +++ b/MLAPI/Core/NetworkingManager.cs @@ -938,29 +938,6 @@ internal void HandleIncomingData(ulong clientId, string channelName, ArraySegmen return; } - - void bufferCallback(ulong networkId) - { - if (!allowBuffer) - { - // This is to prevent recursive buffering - if (NetworkLog.CurrentLogLevel <= LogLevel.Error) NetworkLog.LogError("A message of type " + MLAPIConstants.MESSAGE_NAMES[messageType] + " was recursivley buffered. It has been dropped."); - return; - } - - if (!NetworkConfig.EnableMessageBuffering) - { - throw new InvalidOperationException("Cannot buffer with buffering disabled."); - } - - if (IsServer) - { - throw new InvalidOperationException("Cannot buffer on server."); - } - - BufferManager.BufferMessageForNetworkId(networkId, clientId, channelName, receiveTime, data); - } - #region INTERNAL MESSAGE switch (messageType) @@ -993,10 +970,26 @@ void bufferCallback(ulong networkId) if (IsClient) InternalMessageHandler.HandleTimeSync(clientId, messageStream, receiveTime); break; case MLAPIConstants.MLAPI_NETWORKED_VAR_DELTA: - InternalMessageHandler.HandleNetworkedVarDelta(clientId, messageStream, bufferCallback); + InternalMessageHandler.HandleNetworkedVarDelta(clientId, messageStream, BufferCallback, new PreBufferPreset() + { + AllowBuffer = allowBuffer, + ChannelName = channelName, + ClientId = clientId, + Data = data, + MessageType = messageType, + ReceiveTime = receiveTime + }); break; case MLAPIConstants.MLAPI_NETWORKED_VAR_UPDATE: - InternalMessageHandler.HandleNetworkedVarUpdate(clientId, messageStream, bufferCallback); + InternalMessageHandler.HandleNetworkedVarUpdate(clientId, messageStream, BufferCallback, new PreBufferPreset() + { + AllowBuffer = allowBuffer, + ChannelName = channelName, + ClientId = clientId, + Data = data, + MessageType = messageType, + ReceiveTime = receiveTime + }); break; case MLAPIConstants.MLAPI_SERVER_RPC: if (IsServer) InternalMessageHandler.HandleServerRPC(clientId, messageStream); @@ -1008,10 +1001,26 @@ void bufferCallback(ulong networkId) if (IsClient) InternalMessageHandler.HandleServerRPCResponse(clientId, messageStream); break; case MLAPIConstants.MLAPI_CLIENT_RPC: - if (IsClient) InternalMessageHandler.HandleClientRPC(clientId, messageStream, bufferCallback); + if (IsClient) InternalMessageHandler.HandleClientRPC(clientId, messageStream, BufferCallback, new PreBufferPreset() + { + AllowBuffer = allowBuffer, + ChannelName = channelName, + ClientId = clientId, + Data = data, + MessageType = messageType, + ReceiveTime = receiveTime + }); break; case MLAPIConstants.MLAPI_CLIENT_RPC_REQUEST: - if (IsClient) InternalMessageHandler.HandleClientRPCRequest(clientId, messageStream, channelName, security, bufferCallback); + if (IsClient) InternalMessageHandler.HandleClientRPCRequest(clientId, messageStream, channelName, security, BufferCallback, new PreBufferPreset() + { + AllowBuffer = allowBuffer, + ChannelName = channelName, + ClientId = clientId, + Data = data, + MessageType = messageType, + ReceiveTime = receiveTime + }); break; case MLAPIConstants.MLAPI_CLIENT_RPC_RESPONSE: if (IsServer) InternalMessageHandler.HandleClientRPCResponse(clientId, messageStream); @@ -1052,6 +1061,28 @@ void bufferCallback(ulong networkId) } } + private void BufferCallback(ulong networkId, PreBufferPreset preset) + { + if (!preset.AllowBuffer) + { + // This is to prevent recursive buffering + if (NetworkLog.CurrentLogLevel <= LogLevel.Error) NetworkLog.LogError("A message of type " + MLAPIConstants.MESSAGE_NAMES[preset.MessageType] + " was recursivley buffered. It has been dropped."); + return; + } + + if (!NetworkConfig.EnableMessageBuffering) + { + throw new InvalidOperationException("Cannot buffer with buffering disabled."); + } + + if (IsServer) + { + throw new InvalidOperationException("Cannot buffer on server."); + } + + BufferManager.BufferMessageForNetworkId(networkId, preset.ClientId, preset.ChannelName, preset.ReceiveTime, preset.Data); + } + /// /// Disconnects the remote client. /// diff --git a/MLAPI/Messaging/Buffering/PreBufferPreset.cs b/MLAPI/Messaging/Buffering/PreBufferPreset.cs new file mode 100644 index 0000000000..a285a5b981 --- /dev/null +++ b/MLAPI/Messaging/Buffering/PreBufferPreset.cs @@ -0,0 +1,13 @@ +using System; +namespace MLAPI.Messaging.Buffering +{ + internal struct PreBufferPreset + { + public byte MessageType; + public bool AllowBuffer; + public ulong ClientId; + public string ChannelName; + public float ReceiveTime; + public ArraySegment Data; + } +} diff --git a/MLAPI/Messaging/InternalMessageHandler.cs b/MLAPI/Messaging/InternalMessageHandler.cs index 3d3d10db6d..ab5082d003 100644 --- a/MLAPI/Messaging/InternalMessageHandler.cs +++ b/MLAPI/Messaging/InternalMessageHandler.cs @@ -497,7 +497,7 @@ internal static void HandleTimeSync(ulong clientId, Stream stream, float receive } } - internal static void HandleNetworkedVarDelta(ulong clientId, Stream stream, Action bufferCallback) + internal static void HandleNetworkedVarDelta(ulong clientId, Stream stream, Action bufferCallback, PreBufferPreset bufferPreset) { if (!NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar) { @@ -530,12 +530,12 @@ internal static void HandleNetworkedVarDelta(ulong clientId, Stream stream, Acti else { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) NetworkLog.LogWarning("NetworkedVarDelta message recieved for a non existant object with id: " + networkId + ". This delta will be buffered and might be recovered."); - bufferCallback(networkId); + bufferCallback(networkId, bufferPreset); } } } - internal static void HandleNetworkedVarUpdate(ulong clientId, Stream stream, Action bufferCallback) + internal static void HandleNetworkedVarUpdate(ulong clientId, Stream stream, Action bufferCallback, PreBufferPreset bufferPreset) { if (!NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar) { @@ -568,7 +568,7 @@ internal static void HandleNetworkedVarUpdate(ulong clientId, Stream stream, Act else { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) NetworkLog.LogWarning("NetworkedVarUpdate message recieved for a non existant object with id: " + networkId + ". This delta will be buffered and might be recovered."); - bufferCallback(networkId); + bufferCallback(networkId, bufferPreset); } } } @@ -689,7 +689,7 @@ internal static void HandleServerRPCResponse(ulong clientId, Stream stream) } } - internal static void HandleClientRPC(ulong clientId, Stream stream, Action bufferCallback) + internal static void HandleClientRPC(ulong clientId, Stream stream, Action bufferCallback, PreBufferPreset bufferPreset) { using (PooledBitReader reader = PooledBitReader.Get(stream)) { @@ -717,12 +717,12 @@ internal static void HandleClientRPC(ulong clientId, Stream stream, Action bufferCallback) + internal static void HandleClientRPCRequest(ulong clientId, Stream stream, string channelName, SecuritySendFlags security, Action bufferCallback, PreBufferPreset bufferPreset) { using (PooledBitReader reader = PooledBitReader.Get(stream)) { @@ -762,7 +762,7 @@ internal static void HandleClientRPCRequest(ulong clientId, Stream stream, strin else { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) NetworkLog.LogWarning("ClientRPCRequest message recieved for a non existant object with id: " + networkId + ". This message will be buffered and might be recovered."); - bufferCallback(networkId); + bufferCallback(networkId, bufferPreset); } } } diff --git a/MLAPI/Messaging/InternalMessageSender.cs b/MLAPI/Messaging/InternalMessageSender.cs index 1c0d658d24..b97ec1a971 100644 --- a/MLAPI/Messaging/InternalMessageSender.cs +++ b/MLAPI/Messaging/InternalMessageSender.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using MLAPI.Configuration; using MLAPI.Internal; using MLAPI.Logging; @@ -70,6 +71,49 @@ internal static void Send(byte messageType, string channelName, BitStream messag } } + internal static void Send(byte messageType, string channelName, List clientIds, BitStream messageStream, SecuritySendFlags flags, NetworkedObject targetObject) + { + if (clientIds == null) + { + Send(messageType, channelName, messageStream, flags, targetObject); + return; + } + + bool encrypted = ((flags & SecuritySendFlags.Encrypted) == SecuritySendFlags.Encrypted) && NetworkingManager.Singleton.NetworkConfig.EnableEncryption; + bool authenticated = ((flags & SecuritySendFlags.Authenticated) == SecuritySendFlags.Authenticated) && NetworkingManager.Singleton.NetworkConfig.EnableEncryption; + + if (authenticated || encrypted) + { + for (int i = 0; i < clientIds.Count; i++) + { + Send(clientIds[i], messageType, channelName, messageStream, flags, targetObject); + } + } + else + { + messageStream.PadStream(); + + using (BitStream stream = MessagePacker.WrapMessage(messageType, 0, messageStream, flags)) + { + NetworkProfiler.StartEvent(TickType.Send, (uint)stream.Length, channelName, MLAPIConstants.MESSAGE_NAMES[messageType]); + for (int i = 0; i < clientIds.Count; i++) + { + if (NetworkingManager.Singleton.IsServer && clientIds[i] == NetworkingManager.Singleton.ServerClientId) + continue; + + if (targetObject != null && !targetObject.observers.Contains(clientIds[i])) + { + if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) NetworkLog.LogWarning("Silently suppressed send(all) call because it was directed to an object without visibility"); + continue; + } + + NetworkingManager.Singleton.NetworkConfig.NetworkTransport.Send(clientIds[i], new ArraySegment(stream.GetBuffer(), 0, (int)stream.Length), channelName); + } + NetworkProfiler.EndEvent(); + } + } + } + internal static void Send(byte messageType, string channelName, ulong clientIdToIgnore, BitStream messageStream, SecuritySendFlags flags, NetworkedObject targetObject) { bool encrypted = ((flags & SecuritySendFlags.Encrypted) == SecuritySendFlags.Encrypted) && NetworkingManager.Singleton.NetworkConfig.EnableEncryption;