diff --git a/Assets/Mirror/Components/Experimental/NetworkTransformBase.cs b/Assets/Mirror/Components/Experimental/NetworkTransformBase.cs index e9f629938..6e1fc9a1b 100644 --- a/Assets/Mirror/Components/Experimental/NetworkTransformBase.cs +++ b/Assets/Mirror/Components/Experimental/NetworkTransformBase.cs @@ -212,7 +212,7 @@ bool NeedsTeleport() } // local authority client sends sync message to server for broadcasting - [Command(channel = Channels.DefaultUnreliable)] + [Command(channel = Channels.Unreliable)] void CmdClientToServerSync(Vector3 position, uint packedRotation, Vector3 scale) { // Ignore messages from client if not in client authority mode @@ -229,7 +229,7 @@ void CmdClientToServerSync(Vector3 position, uint packedRotation, Vector3 scale) RpcMove(position, packedRotation, scale); } - [ClientRpc(channel = Channels.DefaultUnreliable)] + [ClientRpc(channel = Channels.Unreliable)] void RpcMove(Vector3 position, uint packedRotation, Vector3 scale) { if (hasAuthority && excludeOwnerUpdate) return; @@ -456,7 +456,7 @@ void DoTeleport(Vector3 newLocalPosition, Quaternion newLocalRotation) lastRotation = newLocalRotation; } - [ClientRpc(channel = Channels.DefaultUnreliable)] + [ClientRpc(channel = Channels.Unreliable)] void RpcTeleport(Vector3 newPosition, uint newPackedRotation, bool isClientAuthority) { DoTeleport(newPosition, Compression.DecompressQuaternion(newPackedRotation)); @@ -470,7 +470,7 @@ void RpcTeleport(Vector3 newPosition, uint newPackedRotation, bool isClientAutho /// This RPC will be invoked on server after client finishes overriding the position. /// /// - [Command(channel = Channels.DefaultUnreliable)] + [Command(channel = Channels.Unreliable)] void CmdTeleportFinished() { if (clientAuthorityBeforeTeleport) diff --git a/Assets/Mirror/Runtime/Attributes.cs b/Assets/Mirror/Runtime/Attributes.cs index 0a4d2e101..39b06fdf2 100644 --- a/Assets/Mirror/Runtime/Attributes.cs +++ b/Assets/Mirror/Runtime/Attributes.cs @@ -20,7 +20,7 @@ public class SyncVarAttribute : PropertyAttribute [AttributeUsage(AttributeTargets.Method)] public class CommandAttribute : Attribute { - public int channel = Channels.DefaultReliable; + public int channel = Channels.Reliable; public bool requiresAuthority = true; } @@ -30,7 +30,7 @@ public class CommandAttribute : Attribute [AttributeUsage(AttributeTargets.Method)] public class ClientRpcAttribute : Attribute { - public int channel = Channels.DefaultReliable; + public int channel = Channels.Reliable; public bool includeOwner = true; } @@ -40,7 +40,7 @@ public class ClientRpcAttribute : Attribute [AttributeUsage(AttributeTargets.Method)] public class TargetRpcAttribute : Attribute { - public int channel = Channels.DefaultReliable; + public int channel = Channels.Reliable; } /// diff --git a/Assets/Mirror/Runtime/LocalConnections.cs b/Assets/Mirror/Runtime/LocalConnections.cs index 072d0a6da..3386eb5b7 100644 --- a/Assets/Mirror/Runtime/LocalConnections.cs +++ b/Assets/Mirror/Runtime/LocalConnections.cs @@ -14,7 +14,7 @@ public LocalConnectionToClient() : base(LocalConnectionId, false, 0) {} public override string address => "localhost"; - internal override void Send(ArraySegment segment, int channelId = Channels.DefaultReliable) + internal override void Send(ArraySegment segment, int channelId = Channels.Reliable) { // get a writer to copy the message into since the segment is only // valid until returning. @@ -63,7 +63,7 @@ internal class LocalConnectionToServer : NetworkConnectionToServer internal void QueueConnectedEvent() => connectedEventPending = true; internal void QueueDisconnectedEvent() => disconnectedEventPending = true; - internal override void Send(ArraySegment segment, int channelId = Channels.DefaultReliable) + internal override void Send(ArraySegment segment, int channelId = Channels.Reliable) { if (segment.Count == 0) { @@ -91,7 +91,7 @@ internal void Update() PooledNetworkWriter writer = queue.Dequeue(); ArraySegment segment = writer.ToArraySegment(); //Debug.Log("Dequeue " + BitConverter.ToString(segment.Array, segment.Offset, segment.Count)); - TransportReceive(segment, Channels.DefaultReliable); + TransportReceive(segment, Channels.Reliable); NetworkWriterPool.Recycle(writer); } diff --git a/Assets/Mirror/Runtime/NetworkClient.cs b/Assets/Mirror/Runtime/NetworkClient.cs index 60a539207..7f04abc6f 100644 --- a/Assets/Mirror/Runtime/NetworkClient.cs +++ b/Assets/Mirror/Runtime/NetworkClient.cs @@ -290,7 +290,7 @@ static void OnDisconnected() // send //////////////////////////////////////////////////////////////// /// Send a NetworkMessage to the server over the given channel. - public static void Send(T message, int channelId = Channels.DefaultReliable) + public static void Send(T message, int channelId = Channels.Reliable) where T : struct, NetworkMessage { if (connection != null) diff --git a/Assets/Mirror/Runtime/NetworkConnection.cs b/Assets/Mirror/Runtime/NetworkConnection.cs index 5a25cecc4..366c08005 100644 --- a/Assets/Mirror/Runtime/NetworkConnection.cs +++ b/Assets/Mirror/Runtime/NetworkConnection.cs @@ -72,7 +72,7 @@ internal void SetHandlers(Dictionary handlers) } /// Send a NetworkMessage to this connection over the given channel. - public void Send(T msg, int channelId = Channels.DefaultReliable) + public void Send(T msg, int channelId = Channels.Reliable) where T : struct, NetworkMessage { using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter()) @@ -110,7 +110,7 @@ protected static bool ValidatePacketSize(ArraySegment segment, int channel // internal because no one except Mirror should send bytes directly to // the client. they would be detected as a message. send messages instead. - internal abstract void Send(ArraySegment segment, int channelId = Channels.DefaultReliable); + internal abstract void Send(ArraySegment segment, int channelId = Channels.Reliable); public override string ToString() => $"connection({connectionId})"; diff --git a/Assets/Mirror/Runtime/NetworkConnectionToClient.cs b/Assets/Mirror/Runtime/NetworkConnectionToClient.cs index 741a0cb41..bc2b5842a 100644 --- a/Assets/Mirror/Runtime/NetworkConnectionToClient.cs +++ b/Assets/Mirror/Runtime/NetworkConnectionToClient.cs @@ -122,7 +122,7 @@ internal void SendBatch(int channelId, Batch batch) batch.lastSendTime = NetworkTime.time; } - internal override void Send(ArraySegment segment, int channelId = Channels.DefaultReliable) + internal override void Send(ArraySegment segment, int channelId = Channels.Reliable) { //Debug.Log("ConnectionSend " + this + " bytes:" + BitConverter.ToString(segment.Array, segment.Offset, segment.Count)); diff --git a/Assets/Mirror/Runtime/NetworkConnectionToServer.cs b/Assets/Mirror/Runtime/NetworkConnectionToServer.cs index 9b7fb1911..29b1827bc 100644 --- a/Assets/Mirror/Runtime/NetworkConnectionToServer.cs +++ b/Assets/Mirror/Runtime/NetworkConnectionToServer.cs @@ -6,7 +6,7 @@ public class NetworkConnectionToServer : NetworkConnection { public override string address => ""; - internal override void Send(ArraySegment segment, int channelId = Channels.DefaultReliable) + internal override void Send(ArraySegment segment, int channelId = Channels.Reliable) { // Debug.Log("ConnectionSend " + this + " bytes:" + BitConverter.ToString(segment.Array, segment.Offset, segment.Count)); diff --git a/Assets/Mirror/Runtime/NetworkServer.cs b/Assets/Mirror/Runtime/NetworkServer.cs index 1d3ed1e72..cb552ef99 100644 --- a/Assets/Mirror/Runtime/NetworkServer.cs +++ b/Assets/Mirror/Runtime/NetworkServer.cs @@ -225,7 +225,7 @@ public static bool NoExternalConnections() // send //////////////////////////////////////////////////////////////// /// Send a message to all clients, even those that haven't joined the world yet (non ready) - public static void SendToAll(T message, int channelId = Channels.DefaultReliable, bool sendToReadyOnly = false) + public static void SendToAll(T message, int channelId = Channels.Reliable, bool sendToReadyOnly = false) where T : struct, NetworkMessage { if (!active) @@ -260,7 +260,7 @@ public static void SendToAll(T message, int channelId = Channels.DefaultRelia /// Send a message to all clients which have joined the world (are ready). // TODO put rpcs into NetworkServer.Update WorldState packet, then finally remove SendToReady! - public static void SendToReady(T message, int channelId = Channels.DefaultReliable) + public static void SendToReady(T message, int channelId = Channels.Reliable) where T : struct, NetworkMessage { if (!active) @@ -274,7 +274,7 @@ public static void SendToReady(T message, int channelId = Channels.DefaultRel /// Send a message to only clients which are ready with option to include the owner of the object identity // TODO put rpcs into NetworkServer.Update WorldState packet, then finally remove SendToReady! - public static void SendToReady(NetworkIdentity identity, T message, bool includeOwner = true, int channelId = Channels.DefaultReliable) + public static void SendToReady(NetworkIdentity identity, T message, bool includeOwner = true, int channelId = Channels.Reliable) where T : struct, NetworkMessage { // Debug.Log("Server.SendToReady msgType:" + typeof(T)); @@ -312,7 +312,7 @@ public static void SendToReady(NetworkIdentity identity, T message, int chann // this is like SendToReady - but it doesn't check the ready flag on the connection. // this is used for ObjectDestroy messages. - static void SendToObservers(NetworkIdentity identity, T message, int channelId = Channels.DefaultReliable) + static void SendToObservers(NetworkIdentity identity, T message, int channelId = Channels.Reliable) where T : struct, NetworkMessage { // Debug.Log("Server.SendToObservers id:" + typeof(T)); @@ -336,7 +336,7 @@ static void SendToObservers(NetworkIdentity identity, T message, int channelI /// Send this message to the player only [Obsolete("Use identity.connectionToClient.Send() instead! Previously Mirror needed this function internally, but not anymore.")] - public static void SendToClientOfPlayer(NetworkIdentity identity, T msg, int channelId = Channels.DefaultReliable) + public static void SendToClientOfPlayer(NetworkIdentity identity, T msg, int channelId = Channels.Reliable) where T : struct, NetworkMessage { if (identity != null) diff --git a/Assets/Mirror/Runtime/NetworkTime.cs b/Assets/Mirror/Runtime/NetworkTime.cs index 44066e410..5e8a9bc80 100644 --- a/Assets/Mirror/Runtime/NetworkTime.cs +++ b/Assets/Mirror/Runtime/NetworkTime.cs @@ -47,7 +47,7 @@ internal static void UpdateClient() if (Time.time - lastPingTime >= PingFrequency) { NetworkPingMessage pingMessage = new NetworkPingMessage(LocalTime()); - NetworkClient.Send(pingMessage, Channels.DefaultUnreliable); + NetworkClient.Send(pingMessage, Channels.Unreliable); lastPingTime = Time.time; } } @@ -63,7 +63,7 @@ internal static void OnServerPing(NetworkConnection conn, NetworkPingMessage mes clientTime = message.clientTime, serverTime = LocalTime() }; - conn.Send(pongMessage, Channels.DefaultUnreliable); + conn.Send(pongMessage, Channels.Unreliable); } // Executed at the client when we receive a Pong message diff --git a/Assets/Mirror/Runtime/Transport/KCP/MirrorTransport/KcpTransport.cs b/Assets/Mirror/Runtime/Transport/KCP/MirrorTransport/KcpTransport.cs index 731cd99ee..3dce7fc17 100644 --- a/Assets/Mirror/Runtime/Transport/KCP/MirrorTransport/KcpTransport.cs +++ b/Assets/Mirror/Runtime/Transport/KCP/MirrorTransport/KcpTransport.cs @@ -57,14 +57,14 @@ void Awake() // client client = new KcpClient( () => OnClientConnected.Invoke(), - (message) => OnClientDataReceived.Invoke(message, Channels.DefaultReliable), + (message) => OnClientDataReceived.Invoke(message, Channels.Reliable), () => OnClientDisconnected.Invoke() ); // server server = new KcpServer( (connectionId) => OnServerConnected.Invoke(connectionId), - (connectionId, message) => OnServerDataReceived.Invoke(connectionId, message, Channels.DefaultReliable), + (connectionId, message) => OnServerDataReceived.Invoke(connectionId, message, Channels.Reliable), (connectionId) => OnServerDisconnected.Invoke(connectionId), NoDelay, Interval, @@ -97,7 +97,7 @@ public override void ClientSend(int channelId, ArraySegment segment) // default to reliable just to be sure. switch (channelId) { - case Channels.DefaultUnreliable: + case Channels.Unreliable: client.Send(segment, KcpChannel.Unreliable); break; default: @@ -156,7 +156,7 @@ public override void ServerSend(int connectionId, int channelId, ArraySegment segment, List reliableQueue, List unreliableQueue) { @@ -84,34 +67,30 @@ void SimulateSend(int connectionId, int channelId, ArraySegment segment, L // (allocates for now. it's only for testing anyway.) byte[] bytes = new byte[segment.Count]; Buffer.BlockCopy(segment.Array, segment.Offset, bytes, 0, segment.Count); - // enqueue message. send after latency interval. QueuedMessage message = new QueuedMessage { connectionId = connectionId, - bytes = bytes + bytes = bytes, + time = Time.time }; switch (channelId) { - case Channels.DefaultReliable: - // simulate latency & spikes - message.timeToSend = Time.time + SimulateLatency(reliableLatency, reliableLatencySpikes); + case Channels.Reliable: + // simulate latency reliableQueue.Add(message); break; - case Channels.DefaultUnreliable: + case Channels.Unreliable: // simulate packet loss bool drop = random.NextDouble() < unreliableLoss; if (!drop) { // simulate scramble (Random.Next is < max, so +1) - // note that list entries are NOT ordered by time anymore - // after inserting randomly. int last = unreliableQueue.Count; int index = unreliableScramble ? random.Next(0, last + 1) : last; - // simulate latency & spikes - message.timeToSend = Time.time + SimulateLatency(unreliableLatency, unreliableLatencySpikes); + // simulate latency unreliableQueue.Insert(index, message); } break; @@ -184,32 +163,34 @@ public override void ServerStop() public override void ServerEarlyUpdate() => wrap.ServerEarlyUpdate(); public override void ClientLateUpdate() { - // flush reliable messages that are ready to be sent - // => list isn't ordered (due to scramble). need to iterate all. - for (int i = 0; i < reliableClientToServer.Count; ++i) + // flush reliable messages after latency + while (reliableClientToServer.Count > 0) { - QueuedMessage message = reliableClientToServer[i]; - if (Time.time >= message.timeToSend) + // check the first message time + QueuedMessage message = reliableClientToServer[0]; + if (message.time + reliableLatency <= Time.time) { - // send and remove - wrap.ClientSend(Channels.DefaultReliable, new ArraySegment(message.bytes)); - reliableClientToServer.RemoveAt(i); - --i; + // send and eat + wrap.ClientSend(Channels.Reliable, new ArraySegment(message.bytes)); + reliableClientToServer.RemoveAt(0); } + // not enough time elapsed yet + break; } - // flush unrelabe messages that are ready to be sent - // => list isn't ordered (due to scramble). need to iterate all. - for (int i = 0; i < unreliableClientToServer.Count; ++i) + // flush unreliable messages after latency + while (unreliableClientToServer.Count > 0) { - QueuedMessage message = unreliableClientToServer[i]; - if (Time.time >= message.timeToSend) + // check the first message time + QueuedMessage message = unreliableClientToServer[0]; + if (message.time + unreliableLatency <= Time.time) { - // send and remove - wrap.ClientSend(Channels.DefaultUnreliable, new ArraySegment(message.bytes)); - unreliableClientToServer.RemoveAt(i); - --i; + // send and eat + wrap.ClientSend(Channels.Unreliable, new ArraySegment(message.bytes)); + unreliableClientToServer.RemoveAt(0); } + // not enough time elapsed yet + break; } // update wrapped transport too @@ -217,32 +198,34 @@ public override void ClientLateUpdate() } public override void ServerLateUpdate() { - // flush reliable messages that are ready to be sent - // => list isn't ordered (due to scramble). need to iterate all. - for (int i = 0; i < reliableServerToClient.Count; ++i) + // flush reliable messages after latency + while (reliableServerToClient.Count > 0) { - QueuedMessage message = reliableServerToClient[i]; - if (Time.time >= message.timeToSend) + // check the first message time + QueuedMessage message = reliableServerToClient[0]; + if (message.time + reliableLatency <= Time.time) { - // send and remove - wrap.ServerSend(message.connectionId, Channels.DefaultReliable, new ArraySegment(message.bytes)); - reliableServerToClient.RemoveAt(i); - --i; + // send and eat + wrap.ServerSend(message.connectionId, Channels.Reliable, new ArraySegment(message.bytes)); + reliableServerToClient.RemoveAt(0); } + // not enough time elapsed yet + break; } - // flush unrelabe messages that are ready to be sent - // => list isn't ordered (due to scramble). need to iterate all. - for (int i = 0; i < unreliableServerToClient.Count; ++i) + // flush unreliable messages after latency + while (unreliableServerToClient.Count > 0) { - QueuedMessage message = unreliableServerToClient[i]; - if (Time.time >= message.timeToSend) + // check the first message time + QueuedMessage message = unreliableServerToClient[0]; + if (message.time + unreliableLatency <= Time.time) { - // send and remove - wrap.ServerSend(message.connectionId, Channels.DefaultUnreliable, new ArraySegment(message.bytes)); - unreliableServerToClient.RemoveAt(i); - --i; + // send and eat + wrap.ServerSend(message.connectionId, Channels.Unreliable, new ArraySegment(message.bytes)); + unreliableServerToClient.RemoveAt(0); } + // not enough time elapsed yet + break; } // update wrapped transport too diff --git a/Assets/Mirror/Runtime/Transport/SimpleWebTransport/SimpleWebTransport.cs b/Assets/Mirror/Runtime/Transport/SimpleWebTransport/SimpleWebTransport.cs index 2a56142ef..9e82b6499 100644 --- a/Assets/Mirror/Runtime/Transport/SimpleWebTransport/SimpleWebTransport.cs +++ b/Assets/Mirror/Runtime/Transport/SimpleWebTransport/SimpleWebTransport.cs @@ -150,7 +150,7 @@ public override void ClientConnect(string hostname) // there should be no more messages after disconnect client = null; }; - client.onData += (ArraySegment data) => OnClientDataReceived.Invoke(data, Channels.DefaultReliable); + client.onData += (ArraySegment data) => OnClientDataReceived.Invoke(data, Channels.Reliable); client.onError += (Exception e) => { OnClientError.Invoke(e); @@ -214,7 +214,7 @@ public override void ServerStart() server.onConnect += OnServerConnected.Invoke; server.onDisconnect += OnServerDisconnected.Invoke; - server.onData += (int connId, ArraySegment data) => OnServerDataReceived.Invoke(connId, data, Channels.DefaultReliable); + server.onData += (int connId, ArraySegment data) => OnServerDataReceived.Invoke(connId, data, Channels.Reliable); server.onError += OnServerError.Invoke; SendLoopConfig.batchSend = batchSend || waitBeforeSend; diff --git a/Assets/Mirror/Runtime/Transport/Telepathy/TelepathyTransport.cs b/Assets/Mirror/Runtime/Transport/Telepathy/TelepathyTransport.cs index 5ab66879f..bff3b7ce1 100644 --- a/Assets/Mirror/Runtime/Transport/Telepathy/TelepathyTransport.cs +++ b/Assets/Mirror/Runtime/Transport/Telepathy/TelepathyTransport.cs @@ -80,7 +80,7 @@ void Awake() // them all in a lambda and always call the latest hook. // (= lazy call) client.OnConnected = () => OnClientConnected.Invoke(); - client.OnData = (segment) => OnClientDataReceived.Invoke(segment, Channels.DefaultReliable); + client.OnData = (segment) => OnClientDataReceived.Invoke(segment, Channels.Reliable); client.OnDisconnected = () => OnClientDisconnected.Invoke(); // client configuration @@ -98,7 +98,7 @@ void Awake() // them all in a lambda and always call the latest hook. // (= lazy call) server.OnConnected = (connectionId) => OnServerConnected.Invoke(connectionId); - server.OnData = (connectionId, segment) => OnServerDataReceived.Invoke(connectionId, segment, Channels.DefaultReliable); + server.OnData = (connectionId, segment) => OnServerDataReceived.Invoke(connectionId, segment, Channels.Reliable); server.OnDisconnected = (connectionId) => OnServerDisconnected.Invoke(connectionId); // server configuration diff --git a/Assets/Mirror/Runtime/Transport/Transport.cs b/Assets/Mirror/Runtime/Transport/Transport.cs index da1f4bddd..ed5495eaf 100644 --- a/Assets/Mirror/Runtime/Transport/Transport.cs +++ b/Assets/Mirror/Runtime/Transport/Transport.cs @@ -1,46 +1,99 @@ -// Transport Rules -// -// All transports should follow these rules so that they work correctly with mirror: -// * When Monobehaviour is disabled the Transport should not invoke callbacks -// * Callbacks should be invoked on main thread. It is best to do this from LateUpdate -// * Callbacks can be invoked after ServerStop or ClientDisconnect has been called -// * ServerStop or ClientDisconnect can be called by mirror multiple times -// * Available should check the platform and 32 vs 64 bit if the transport only works on some of them -// * GetMaxPacketSize should return size even if transport is not running -// * Default channel should be reliable Channels.DefaultReliable using System; using UnityEngine; namespace Mirror { - /// Abstract transport layer component + /// + /// Abstract transport layer component + /// + /// + ///

+ /// Transport Rules + ///

+ /// + /// + /// All transports should follow these rules so that they work correctly with mirror + /// + /// + /// When Monobehaviour is disabled the Transport should not invoke callbacks + /// + /// + /// Callbacks should be invoked on main thread. It is best to do this from LateUpdate + /// + /// + /// Callbacks can be invoked after or as been called + /// + /// + /// or can be called by mirror multiple times + /// + /// + /// should check the platform and 32 vs 64 bit if the transport only works on some of them + /// + /// + /// should return size even if transport is not running + /// + /// + /// Default channel should be reliable + /// + /// + ///
public abstract class Transport : MonoBehaviour { - /// The current transport used by Mirror. + /// + /// The current transport used by Mirror. + /// public static Transport activeTransport; - /// Transport available on this platform? Some aren't available on all platforms. + /// + /// Is this transport available in the current platform? + /// Some transports might only be available in mobile + /// Many will not work in webgl + /// Example usage: return Application.platform == RuntimePlatform.WebGLPlayer + /// + /// True if this transport works in the current platform public abstract bool Available(); - /// Notify subscribers when this client establish a successful connection to the server + #region Client + /// + /// Notify subscribers when this client establish a successful connection to the server + /// callback() + /// public Action OnClientConnected = () => Debug.LogWarning("OnClientConnected called with no handler"); - /// Notify subscribers when this client receive data from the server + /// + /// Notify subscribers when this client receive data from the server + /// callback(ArraySegment<byte> data, int channel) + /// public Action, int> OnClientDataReceived = (data, channel) => Debug.LogWarning("OnClientDataReceived called with no handler"); - /// Notify subscribers when this client encounters an error communicating with the server + /// + /// Notify subscribers when this client encounters an error communicating with the server + /// callback(Exception e) + /// public Action OnClientError = (error) => Debug.LogWarning("OnClientError called with no handler"); - /// Notify subscribers when this client disconnects from the server + /// + /// Notify subscribers when this client disconnects from the server + /// callback() + /// public Action OnClientDisconnected = () => Debug.LogWarning("OnClientDisconnected called with no handler"); - /// Determines if we are currently connected to the server + /// + /// Determines if we are currently connected to the server + /// + /// True if a connection has been established to the server public abstract bool ClientConnected(); - /// Establish a connection to a server + /// + /// Establish a connection to a server + /// + /// The IP address or FQDN of the server we are trying to connect to public abstract void ClientConnect(string address); - /// Establish a connection to a server + /// + /// Establish a connection to a server + /// + /// The address of the server we are trying to connect to public virtual void ClientConnect(Uri uri) { // By default, to keep backwards compatibility, just connect to the host @@ -48,60 +101,120 @@ public virtual void ClientConnect(Uri uri) ClientConnect(uri.Host); } - /// Send data to the server over a given channel + /// + /// Send data to the server + /// + /// The channel to use. 0 is the default channel, + /// but some transports might want to provide unreliable, encrypted, compressed, or any other feature + /// as new channels + /// The data to send to the server. Will be recycled after returning, so either use it directly or copy it internally. This allows for allocation-free sends! public abstract void ClientSend(int channelId, ArraySegment segment); - /// Disconnect this client from the server + /// + /// Disconnect this client from the server + /// public abstract void ClientDisconnect(); - /// Get the address of this server. Useful for network discovery + #endregion + + #region Server + + + /// + /// Retrieves the address of this server. + /// Useful for network discovery + /// + /// the url at which this server can be reached public abstract Uri ServerUri(); - /// Notify subscribers when a client connects to this server + /// + /// Notify subscribers when a client connects to this server + /// callback(int connId) + /// public Action OnServerConnected = (connId) => Debug.LogWarning("OnServerConnected called with no handler"); - /// Notify subscribers when this server receives data from the client + /// + /// Notify subscribers when this server receives data from the client + /// callback(int connId, ArraySegment<byte> data, int channel) + /// public Action, int> OnServerDataReceived = (connId, data, channel) => Debug.LogWarning("OnServerDataReceived called with no handler"); - /// Notify subscribers when this server has some problem communicating with the client + /// + /// Notify subscribers when this server has some problem communicating with the client + /// callback(int connId, Exception e) + /// public Action OnServerError = (connId, error) => Debug.LogWarning("OnServerError called with no handler"); - /// Notify subscribers when a client disconnects from this server + /// + /// Notify subscribers when a client disconnects from this server + /// callback(int connId) + /// public Action OnServerDisconnected = (connId) => Debug.LogWarning("OnServerDisconnected called with no handler"); - /// Determines if the server is up and running + /// + /// Determines if the server is up and running + /// + /// true if the transport is ready for connections from clients public abstract bool ServerActive(); - /// Start listening for clients + /// + /// Start listening for clients + /// public abstract void ServerStart(); - /// Send data to the client with connectionId over the given channel. + /// + /// Send data to a client. + /// + /// The client connection id to send the data to + /// The channel to be used. Transports can use channels to implement + /// other features such as unreliable, encryption, compression, etc... + /// public abstract void ServerSend(int connectionId, int channelId, ArraySegment segment); - /// Disconnect a client from this server. Useful to kick people out. + /// + /// Disconnect a client from this server. Useful to kick people out. + /// + /// the id of the client to disconnect + /// true if the client was kicked public abstract bool ServerDisconnect(int connectionId); - /// Get the client address, useful for IP bans etc. + /// + /// Get the client address + /// + /// id of the client + /// address of the client public abstract string ServerGetClientAddress(int connectionId); - /// Stop listening for clients and disconnect all existing clients + /// + /// Stop listening for clients and disconnect all existing clients + /// public abstract void ServerStop(); - /// The maximum packet size for a given channel. - // Unreliable transports usually can only deliver small packets. - // Reliable fragmented channels can usually deliver large ones. - // - // GetMaxPacketSize needs to return a value at all times. Even if the - // Transport isn't running, or isn't Available(). This is because - // Fallback and Multiplex transports need to find the smallest possible - // packet size at runtime. - public abstract int GetMaxPacketSize(int channelId = Channels.DefaultReliable); + #endregion - /// The maximum batch(!) size for a given channel. - // Uses GetMaxPacketSize by default. - // Some transports like kcp support large max packet sizes which should - // not be used for batching all the time because they end up being too - // slow (head of line blocking etc.). + /// + /// The maximum packet size for a given channel. Unreliable transports + /// usually can only deliver small packets. Reliable fragmented channels + /// can usually deliver large ones. + /// + /// GetMaxPacketSize needs to return a value at all times. Even if the + /// Transport isn't running, or isn't Available(). This is because + /// Fallback and Multiplex transports need to find the smallest possible + /// packet size at runtime. + /// + /// channel id + /// the size in bytes that can be sent via the provided channel + public abstract int GetMaxPacketSize(int channelId = Channels.Reliable); + + /// + /// The maximum batch(!) size for a given channel. + /// Uses GetMaxPacketSize by default. + /// Some transports like kcp support large max packet sizes which should + /// not be used for batching all the time because they end up being too + /// slow (head of line blocking etc.). + /// + /// channel id + /// the size in bytes that should be batched via the provided channel public virtual int GetMaxBatchSize(int channelId) => GetMaxPacketSize(channelId); @@ -122,12 +235,14 @@ public void Update() {} public void LateUpdate() {} #pragma warning restore UNT0001 // Empty Unity message - // NetworkLoop NetworkEarly/LateUpdate were added for a proper network - // update order. the goal is to: - // process_incoming() - // update_world() - // process_outgoing() - // in order to avoid unnecessary latency and data races. + /// + /// NetworkLoop NetworkEarly/LateUpdate were added for a proper network + /// update order. the goal is to: + /// process_incoming() + /// update_world() + /// process_outgoing() + /// in order to avoid unnecessary latency and data races. + /// // => split into client and server parts so that we can cleanly call // them from NetworkClient/Server // => VIRTUAL for now so we can take our time to convert transports @@ -137,13 +252,15 @@ public virtual void ServerEarlyUpdate() {} public virtual void ClientLateUpdate() {} public virtual void ServerLateUpdate() {} - /// Shut down the transport, both as client and server + /// + /// Shut down the transport, both as client and server + /// public abstract void Shutdown(); - // called when quitting the application by closing the window / pressing - // stop in the editor. - // virtual so that inheriting classes' OnApplicationQuit() can call - // base.OnApplicationQuit() too + /// + /// called when quitting the application by closing the window / pressing stop in the editor + /// virtual so that inheriting classes' OnApplicationQuit() can call base.OnApplicationQuit() too + /// public virtual void OnApplicationQuit() { // stop transport (e.g. to shut down threads) diff --git a/Assets/Mirror/Runtime/Utils.cs b/Assets/Mirror/Runtime/Utils.cs index 688974a4d..cc8ba94d8 100644 --- a/Assets/Mirror/Runtime/Utils.cs +++ b/Assets/Mirror/Runtime/Utils.cs @@ -38,8 +38,13 @@ public enum Version // add custom channels anymore. public static class Channels { - public const int DefaultReliable = 0; - public const int DefaultUnreliable = 1; + public const int Reliable = 0; // ordered + public const int Unreliable = 1; // unordered + + [Obsolete("Use Channels.Reliable instead")] + public const int DefaultReliable = Reliable; + [Obsolete("Use Channels.Unreliable instead")] + public const int DefaultUnreliable = Unreliable; } // -- helpers for float conversion without allocations -- diff --git a/Assets/Mirror/Tests/Editor/BatchingTests.cs b/Assets/Mirror/Tests/Editor/BatchingTests.cs index edaf21aac..5269964f4 100644 --- a/Assets/Mirror/Tests/Editor/BatchingTests.cs +++ b/Assets/Mirror/Tests/Editor/BatchingTests.cs @@ -39,7 +39,7 @@ public void TearDown() public void SendEmptyBatch() { // empty batch - nothing should be sent - connection.SendBatch(Channels.DefaultReliable, batch); + connection.SendBatch(Channels.Reliable, batch); Assert.That(transport.clientIncoming.Count, Is.EqualTo(0)); } @@ -47,7 +47,7 @@ public void SendEmptyBatch() public void SendAlmostMaxBatchSizedMessageBatch() { // create a message < max batch size - int max = transport.GetMaxBatchSize(Channels.DefaultReliable); + int max = transport.GetMaxBatchSize(Channels.Reliable); byte[] message = new byte[max-1]; // add to batch queue @@ -56,7 +56,7 @@ public void SendAlmostMaxBatchSizedMessageBatch() batch.messages.Enqueue(writer); // send batch - client should receive that exact message - connection.SendBatch(Channels.DefaultReliable, batch); + connection.SendBatch(Channels.Reliable, batch); Assert.That(transport.clientIncoming.Count, Is.EqualTo(1)); Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(message.Length)); } @@ -65,7 +65,7 @@ public void SendAlmostMaxBatchSizedMessageBatch() public void SendMaxBatchSizedMessageBatch() { // create a message == max batch size - int max = transport.GetMaxBatchSize(Channels.DefaultReliable); + int max = transport.GetMaxBatchSize(Channels.Reliable); byte[] message = new byte[max]; // add to batch queue @@ -74,7 +74,7 @@ public void SendMaxBatchSizedMessageBatch() batch.messages.Enqueue(writer); // send batch - client should receive that exact message - connection.SendBatch(Channels.DefaultReliable, batch); + connection.SendBatch(Channels.Reliable, batch); Assert.That(transport.clientIncoming.Count, Is.EqualTo(1)); Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(message.Length)); } @@ -97,7 +97,7 @@ public void SendTwoSmallMessagesBatch() batch.messages.Enqueue(writerB); // send batch - client should receive one message that contains A, B - connection.SendBatch(Channels.DefaultReliable, batch); + connection.SendBatch(Channels.Reliable, batch); Assert.That(transport.clientIncoming.Count, Is.EqualTo(1)); MemoryTransport.Message msg = transport.clientIncoming.Dequeue(); Assert.That(msg.data.Length, Is.EqualTo(4)); @@ -111,7 +111,7 @@ public void SendTwoSmallMessagesBatch() public void SendAlmostMaxBatchSizedAndSmallMessageBatch() { // create a message < max batch size - int max = transport.GetMaxBatchSize(Channels.DefaultReliable); + int max = transport.GetMaxBatchSize(Channels.Reliable); byte[] almost = new byte[max-1]; // create small message @@ -129,7 +129,7 @@ public void SendAlmostMaxBatchSizedAndSmallMessageBatch() // send batch - should send the first one and then the second one // because both together would've been > max - connection.SendBatch(Channels.DefaultReliable, batch); + connection.SendBatch(Channels.Reliable, batch); Assert.That(transport.clientIncoming.Count, Is.EqualTo(2)); Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(almost.Length)); Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(small.Length)); @@ -142,8 +142,8 @@ public void SendAlmostMaxBatchSizedAndSmallMessageBatch() [Test] public void SendLargerMaxBatchSizedMessageBatch() { - int maxBatch = transport.GetMaxBatchSize(Channels.DefaultReliable); - int maxPacket = transport.GetMaxPacketSize(Channels.DefaultReliable); + int maxBatch = transport.GetMaxBatchSize(Channels.Reliable); + int maxPacket = transport.GetMaxPacketSize(Channels.Reliable); // we can only tested if transport max batch < max message Assert.That(maxBatch < maxPacket, Is.True); @@ -157,7 +157,7 @@ public void SendLargerMaxBatchSizedMessageBatch() batch.messages.Enqueue(writer); // send batch - client should receive that exact message - connection.SendBatch(Channels.DefaultReliable, batch); + connection.SendBatch(Channels.Reliable, batch); Assert.That(transport.clientIncoming.Count, Is.EqualTo(1)); Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(message.Length)); } diff --git a/Assets/Mirror/Tests/Editor/CustomAttrributeTest.cs b/Assets/Mirror/Tests/Editor/CustomAttrributeTest.cs index b5559a1cf..37e11fc7f 100644 --- a/Assets/Mirror/Tests/Editor/CustomAttrributeTest.cs +++ b/Assets/Mirror/Tests/Editor/CustomAttrributeTest.cs @@ -21,11 +21,11 @@ public void CommandAttributeTest() { CommandAttribute attrib = new CommandAttribute(); - Assert.That(attrib.channel == Channels.DefaultReliable); + Assert.That(attrib.channel == Channels.Reliable); - attrib.channel = Channels.DefaultUnreliable; + attrib.channel = Channels.Unreliable; - Assert.That(attrib.channel == Channels.DefaultUnreliable); + Assert.That(attrib.channel == Channels.Unreliable); } [Test] @@ -33,11 +33,11 @@ public void ClientRPCAttributeTest() { ClientRpcAttribute attrib = new ClientRpcAttribute(); - Assert.That(attrib.channel == Channels.DefaultReliable); + Assert.That(attrib.channel == Channels.Reliable); - attrib.channel = Channels.DefaultUnreliable; + attrib.channel = Channels.Unreliable; - Assert.That(attrib.channel == Channels.DefaultUnreliable); + Assert.That(attrib.channel == Channels.Unreliable); } [Test] @@ -45,9 +45,9 @@ public void TargetRPCAttributeTest() { TargetRpcAttribute attrib = new TargetRpcAttribute(); - Assert.That(attrib.channel == Channels.DefaultReliable); + Assert.That(attrib.channel == Channels.Reliable); - attrib.channel = Channels.DefaultUnreliable; + attrib.channel = Channels.Unreliable; Assert.That(attrib.channel == 1); } diff --git a/Assets/Mirror/Tests/Editor/MiddlewareTransportTest.cs b/Assets/Mirror/Tests/Editor/MiddlewareTransportTest.cs index 5f5eee380..b7b598d37 100644 --- a/Assets/Mirror/Tests/Editor/MiddlewareTransportTest.cs +++ b/Assets/Mirror/Tests/Editor/MiddlewareTransportTest.cs @@ -44,9 +44,9 @@ public void TestAvailable(bool available) } [Test] - [TestCase(Channels.DefaultReliable, 4000)] - [TestCase(Channels.DefaultReliable, 2000)] - [TestCase(Channels.DefaultUnreliable, 4000)] + [TestCase(Channels.Reliable, 4000)] + [TestCase(Channels.Reliable, 2000)] + [TestCase(Channels.Unreliable, 4000)] public void TestGetMaxPacketSize(int channel, int packageSize) { inner.GetMaxPacketSize(Arg.Any()).Returns(packageSize); @@ -97,8 +97,8 @@ public void TestClientDisconnect() } [Test] - [TestCase(Channels.DefaultReliable)] - [TestCase(Channels.DefaultUnreliable)] + [TestCase(Channels.Reliable)] + [TestCase(Channels.Unreliable)] public void TestClientSend(int channel) { byte[] array = new byte[10];