mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
Shorten Channel Enums (#2644)
Co-authored-by: MrGadget1024 <chris@clevertech.net>
This commit is contained in:
parent
254a0b929d
commit
53dad15e04
@ -212,7 +212,7 @@ bool NeedsTeleport()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// local authority client sends sync message to server for broadcasting
|
// 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)
|
void CmdClientToServerSync(Vector3 position, uint packedRotation, Vector3 scale)
|
||||||
{
|
{
|
||||||
// Ignore messages from client if not in client authority mode
|
// 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);
|
RpcMove(position, packedRotation, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
[ClientRpc(channel = Channels.DefaultUnreliable)]
|
[ClientRpc(channel = Channels.Unreliable)]
|
||||||
void RpcMove(Vector3 position, uint packedRotation, Vector3 scale)
|
void RpcMove(Vector3 position, uint packedRotation, Vector3 scale)
|
||||||
{
|
{
|
||||||
if (hasAuthority && excludeOwnerUpdate) return;
|
if (hasAuthority && excludeOwnerUpdate) return;
|
||||||
@ -456,7 +456,7 @@ void DoTeleport(Vector3 newLocalPosition, Quaternion newLocalRotation)
|
|||||||
lastRotation = newLocalRotation;
|
lastRotation = newLocalRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
[ClientRpc(channel = Channels.DefaultUnreliable)]
|
[ClientRpc(channel = Channels.Unreliable)]
|
||||||
void RpcTeleport(Vector3 newPosition, uint newPackedRotation, bool isClientAuthority)
|
void RpcTeleport(Vector3 newPosition, uint newPackedRotation, bool isClientAuthority)
|
||||||
{
|
{
|
||||||
DoTeleport(newPosition, Compression.DecompressQuaternion(newPackedRotation));
|
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.
|
/// This RPC will be invoked on server after client finishes overriding the position.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="initialAuthority"></param>
|
/// <param name="initialAuthority"></param>
|
||||||
[Command(channel = Channels.DefaultUnreliable)]
|
[Command(channel = Channels.Unreliable)]
|
||||||
void CmdTeleportFinished()
|
void CmdTeleportFinished()
|
||||||
{
|
{
|
||||||
if (clientAuthorityBeforeTeleport)
|
if (clientAuthorityBeforeTeleport)
|
||||||
|
@ -20,7 +20,7 @@ public class SyncVarAttribute : PropertyAttribute
|
|||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
public class CommandAttribute : Attribute
|
public class CommandAttribute : Attribute
|
||||||
{
|
{
|
||||||
public int channel = Channels.DefaultReliable;
|
public int channel = Channels.Reliable;
|
||||||
public bool requiresAuthority = true;
|
public bool requiresAuthority = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ public class CommandAttribute : Attribute
|
|||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
public class ClientRpcAttribute : Attribute
|
public class ClientRpcAttribute : Attribute
|
||||||
{
|
{
|
||||||
public int channel = Channels.DefaultReliable;
|
public int channel = Channels.Reliable;
|
||||||
public bool includeOwner = true;
|
public bool includeOwner = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ public class ClientRpcAttribute : Attribute
|
|||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
public class TargetRpcAttribute : Attribute
|
public class TargetRpcAttribute : Attribute
|
||||||
{
|
{
|
||||||
public int channel = Channels.DefaultReliable;
|
public int channel = Channels.Reliable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -14,7 +14,7 @@ public LocalConnectionToClient() : base(LocalConnectionId, false, 0) {}
|
|||||||
|
|
||||||
public override string address => "localhost";
|
public override string address => "localhost";
|
||||||
|
|
||||||
internal override void Send(ArraySegment<byte> segment, int channelId = Channels.DefaultReliable)
|
internal override void Send(ArraySegment<byte> segment, int channelId = Channels.Reliable)
|
||||||
{
|
{
|
||||||
// get a writer to copy the message into since the segment is only
|
// get a writer to copy the message into since the segment is only
|
||||||
// valid until returning.
|
// valid until returning.
|
||||||
@ -63,7 +63,7 @@ internal class LocalConnectionToServer : NetworkConnectionToServer
|
|||||||
internal void QueueConnectedEvent() => connectedEventPending = true;
|
internal void QueueConnectedEvent() => connectedEventPending = true;
|
||||||
internal void QueueDisconnectedEvent() => disconnectedEventPending = true;
|
internal void QueueDisconnectedEvent() => disconnectedEventPending = true;
|
||||||
|
|
||||||
internal override void Send(ArraySegment<byte> segment, int channelId = Channels.DefaultReliable)
|
internal override void Send(ArraySegment<byte> segment, int channelId = Channels.Reliable)
|
||||||
{
|
{
|
||||||
if (segment.Count == 0)
|
if (segment.Count == 0)
|
||||||
{
|
{
|
||||||
@ -91,7 +91,7 @@ internal void Update()
|
|||||||
PooledNetworkWriter writer = queue.Dequeue();
|
PooledNetworkWriter writer = queue.Dequeue();
|
||||||
ArraySegment<byte> segment = writer.ToArraySegment();
|
ArraySegment<byte> segment = writer.ToArraySegment();
|
||||||
//Debug.Log("Dequeue " + BitConverter.ToString(segment.Array, segment.Offset, segment.Count));
|
//Debug.Log("Dequeue " + BitConverter.ToString(segment.Array, segment.Offset, segment.Count));
|
||||||
TransportReceive(segment, Channels.DefaultReliable);
|
TransportReceive(segment, Channels.Reliable);
|
||||||
NetworkWriterPool.Recycle(writer);
|
NetworkWriterPool.Recycle(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,7 +290,7 @@ static void OnDisconnected()
|
|||||||
|
|
||||||
// send ////////////////////////////////////////////////////////////////
|
// send ////////////////////////////////////////////////////////////////
|
||||||
/// <summary>Send a NetworkMessage to the server over the given channel.</summary>
|
/// <summary>Send a NetworkMessage to the server over the given channel.</summary>
|
||||||
public static void Send<T>(T message, int channelId = Channels.DefaultReliable)
|
public static void Send<T>(T message, int channelId = Channels.Reliable)
|
||||||
where T : struct, NetworkMessage
|
where T : struct, NetworkMessage
|
||||||
{
|
{
|
||||||
if (connection != null)
|
if (connection != null)
|
||||||
|
@ -72,7 +72,7 @@ internal void SetHandlers(Dictionary<int, NetworkMessageDelegate> handlers)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Send a NetworkMessage to this connection over the given channel.</summary>
|
/// <summary>Send a NetworkMessage to this connection over the given channel.</summary>
|
||||||
public void Send<T>(T msg, int channelId = Channels.DefaultReliable)
|
public void Send<T>(T msg, int channelId = Channels.Reliable)
|
||||||
where T : struct, NetworkMessage
|
where T : struct, NetworkMessage
|
||||||
{
|
{
|
||||||
using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
|
using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
|
||||||
@ -110,7 +110,7 @@ protected static bool ValidatePacketSize(ArraySegment<byte> segment, int channel
|
|||||||
|
|
||||||
// internal because no one except Mirror should send bytes directly to
|
// internal because no one except Mirror should send bytes directly to
|
||||||
// the client. they would be detected as a message. send messages instead.
|
// the client. they would be detected as a message. send messages instead.
|
||||||
internal abstract void Send(ArraySegment<byte> segment, int channelId = Channels.DefaultReliable);
|
internal abstract void Send(ArraySegment<byte> segment, int channelId = Channels.Reliable);
|
||||||
|
|
||||||
public override string ToString() => $"connection({connectionId})";
|
public override string ToString() => $"connection({connectionId})";
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ internal void SendBatch(int channelId, Batch batch)
|
|||||||
batch.lastSendTime = NetworkTime.time;
|
batch.lastSendTime = NetworkTime.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void Send(ArraySegment<byte> segment, int channelId = Channels.DefaultReliable)
|
internal override void Send(ArraySegment<byte> segment, int channelId = Channels.Reliable)
|
||||||
{
|
{
|
||||||
//Debug.Log("ConnectionSend " + this + " bytes:" + BitConverter.ToString(segment.Array, segment.Offset, segment.Count));
|
//Debug.Log("ConnectionSend " + this + " bytes:" + BitConverter.ToString(segment.Array, segment.Offset, segment.Count));
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ public class NetworkConnectionToServer : NetworkConnection
|
|||||||
{
|
{
|
||||||
public override string address => "";
|
public override string address => "";
|
||||||
|
|
||||||
internal override void Send(ArraySegment<byte> segment, int channelId = Channels.DefaultReliable)
|
internal override void Send(ArraySegment<byte> segment, int channelId = Channels.Reliable)
|
||||||
{
|
{
|
||||||
// Debug.Log("ConnectionSend " + this + " bytes:" + BitConverter.ToString(segment.Array, segment.Offset, segment.Count));
|
// Debug.Log("ConnectionSend " + this + " bytes:" + BitConverter.ToString(segment.Array, segment.Offset, segment.Count));
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ public static bool NoExternalConnections()
|
|||||||
|
|
||||||
// send ////////////////////////////////////////////////////////////////
|
// send ////////////////////////////////////////////////////////////////
|
||||||
/// <summary>Send a message to all clients, even those that haven't joined the world yet (non ready)</summary>
|
/// <summary>Send a message to all clients, even those that haven't joined the world yet (non ready)</summary>
|
||||||
public static void SendToAll<T>(T message, int channelId = Channels.DefaultReliable, bool sendToReadyOnly = false)
|
public static void SendToAll<T>(T message, int channelId = Channels.Reliable, bool sendToReadyOnly = false)
|
||||||
where T : struct, NetworkMessage
|
where T : struct, NetworkMessage
|
||||||
{
|
{
|
||||||
if (!active)
|
if (!active)
|
||||||
@ -260,7 +260,7 @@ public static void SendToAll<T>(T message, int channelId = Channels.DefaultRelia
|
|||||||
|
|
||||||
/// <summary>Send a message to all clients which have joined the world (are ready).</summary>
|
/// <summary>Send a message to all clients which have joined the world (are ready).</summary>
|
||||||
// TODO put rpcs into NetworkServer.Update WorldState packet, then finally remove SendToReady!
|
// TODO put rpcs into NetworkServer.Update WorldState packet, then finally remove SendToReady!
|
||||||
public static void SendToReady<T>(T message, int channelId = Channels.DefaultReliable)
|
public static void SendToReady<T>(T message, int channelId = Channels.Reliable)
|
||||||
where T : struct, NetworkMessage
|
where T : struct, NetworkMessage
|
||||||
{
|
{
|
||||||
if (!active)
|
if (!active)
|
||||||
@ -274,7 +274,7 @@ public static void SendToReady<T>(T message, int channelId = Channels.DefaultRel
|
|||||||
|
|
||||||
/// <summary>Send a message to only clients which are ready with option to include the owner of the object identity</summary>
|
/// <summary>Send a message to only clients which are ready with option to include the owner of the object identity</summary>
|
||||||
// TODO put rpcs into NetworkServer.Update WorldState packet, then finally remove SendToReady!
|
// TODO put rpcs into NetworkServer.Update WorldState packet, then finally remove SendToReady!
|
||||||
public static void SendToReady<T>(NetworkIdentity identity, T message, bool includeOwner = true, int channelId = Channels.DefaultReliable)
|
public static void SendToReady<T>(NetworkIdentity identity, T message, bool includeOwner = true, int channelId = Channels.Reliable)
|
||||||
where T : struct, NetworkMessage
|
where T : struct, NetworkMessage
|
||||||
{
|
{
|
||||||
// Debug.Log("Server.SendToReady msgType:" + typeof(T));
|
// Debug.Log("Server.SendToReady msgType:" + typeof(T));
|
||||||
@ -312,7 +312,7 @@ public static void SendToReady<T>(NetworkIdentity identity, T message, int chann
|
|||||||
|
|
||||||
// this is like SendToReady - but it doesn't check the ready flag on the connection.
|
// this is like SendToReady - but it doesn't check the ready flag on the connection.
|
||||||
// this is used for ObjectDestroy messages.
|
// this is used for ObjectDestroy messages.
|
||||||
static void SendToObservers<T>(NetworkIdentity identity, T message, int channelId = Channels.DefaultReliable)
|
static void SendToObservers<T>(NetworkIdentity identity, T message, int channelId = Channels.Reliable)
|
||||||
where T : struct, NetworkMessage
|
where T : struct, NetworkMessage
|
||||||
{
|
{
|
||||||
// Debug.Log("Server.SendToObservers id:" + typeof(T));
|
// Debug.Log("Server.SendToObservers id:" + typeof(T));
|
||||||
@ -336,7 +336,7 @@ static void SendToObservers<T>(NetworkIdentity identity, T message, int channelI
|
|||||||
|
|
||||||
/// <summary>Send this message to the player only</summary>
|
/// <summary>Send this message to the player only</summary>
|
||||||
[Obsolete("Use identity.connectionToClient.Send() instead! Previously Mirror needed this function internally, but not anymore.")]
|
[Obsolete("Use identity.connectionToClient.Send() instead! Previously Mirror needed this function internally, but not anymore.")]
|
||||||
public static void SendToClientOfPlayer<T>(NetworkIdentity identity, T msg, int channelId = Channels.DefaultReliable)
|
public static void SendToClientOfPlayer<T>(NetworkIdentity identity, T msg, int channelId = Channels.Reliable)
|
||||||
where T : struct, NetworkMessage
|
where T : struct, NetworkMessage
|
||||||
{
|
{
|
||||||
if (identity != null)
|
if (identity != null)
|
||||||
|
@ -47,7 +47,7 @@ internal static void UpdateClient()
|
|||||||
if (Time.time - lastPingTime >= PingFrequency)
|
if (Time.time - lastPingTime >= PingFrequency)
|
||||||
{
|
{
|
||||||
NetworkPingMessage pingMessage = new NetworkPingMessage(LocalTime());
|
NetworkPingMessage pingMessage = new NetworkPingMessage(LocalTime());
|
||||||
NetworkClient.Send(pingMessage, Channels.DefaultUnreliable);
|
NetworkClient.Send(pingMessage, Channels.Unreliable);
|
||||||
lastPingTime = Time.time;
|
lastPingTime = Time.time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ internal static void OnServerPing(NetworkConnection conn, NetworkPingMessage mes
|
|||||||
clientTime = message.clientTime,
|
clientTime = message.clientTime,
|
||||||
serverTime = LocalTime()
|
serverTime = LocalTime()
|
||||||
};
|
};
|
||||||
conn.Send(pongMessage, Channels.DefaultUnreliable);
|
conn.Send(pongMessage, Channels.Unreliable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executed at the client when we receive a Pong message
|
// Executed at the client when we receive a Pong message
|
||||||
|
@ -57,14 +57,14 @@ void Awake()
|
|||||||
// client
|
// client
|
||||||
client = new KcpClient(
|
client = new KcpClient(
|
||||||
() => OnClientConnected.Invoke(),
|
() => OnClientConnected.Invoke(),
|
||||||
(message) => OnClientDataReceived.Invoke(message, Channels.DefaultReliable),
|
(message) => OnClientDataReceived.Invoke(message, Channels.Reliable),
|
||||||
() => OnClientDisconnected.Invoke()
|
() => OnClientDisconnected.Invoke()
|
||||||
);
|
);
|
||||||
|
|
||||||
// server
|
// server
|
||||||
server = new KcpServer(
|
server = new KcpServer(
|
||||||
(connectionId) => OnServerConnected.Invoke(connectionId),
|
(connectionId) => OnServerConnected.Invoke(connectionId),
|
||||||
(connectionId, message) => OnServerDataReceived.Invoke(connectionId, message, Channels.DefaultReliable),
|
(connectionId, message) => OnServerDataReceived.Invoke(connectionId, message, Channels.Reliable),
|
||||||
(connectionId) => OnServerDisconnected.Invoke(connectionId),
|
(connectionId) => OnServerDisconnected.Invoke(connectionId),
|
||||||
NoDelay,
|
NoDelay,
|
||||||
Interval,
|
Interval,
|
||||||
@ -97,7 +97,7 @@ public override void ClientSend(int channelId, ArraySegment<byte> segment)
|
|||||||
// default to reliable just to be sure.
|
// default to reliable just to be sure.
|
||||||
switch (channelId)
|
switch (channelId)
|
||||||
{
|
{
|
||||||
case Channels.DefaultUnreliable:
|
case Channels.Unreliable:
|
||||||
client.Send(segment, KcpChannel.Unreliable);
|
client.Send(segment, KcpChannel.Unreliable);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -156,7 +156,7 @@ public override void ServerSend(int connectionId, int channelId, ArraySegment<by
|
|||||||
// default to reliable just to be sure.
|
// default to reliable just to be sure.
|
||||||
switch (channelId)
|
switch (channelId)
|
||||||
{
|
{
|
||||||
case Channels.DefaultUnreliable:
|
case Channels.Unreliable:
|
||||||
server.Send(connectionId, segment, KcpChannel.Unreliable);
|
server.Send(connectionId, segment, KcpChannel.Unreliable);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -187,14 +187,14 @@ public override void ServerEarlyUpdate()
|
|||||||
public override void Shutdown() {}
|
public override void Shutdown() {}
|
||||||
|
|
||||||
// max message size
|
// max message size
|
||||||
public override int GetMaxPacketSize(int channelId = Channels.DefaultReliable)
|
public override int GetMaxPacketSize(int channelId = Channels.Reliable)
|
||||||
{
|
{
|
||||||
// switch to kcp channel.
|
// switch to kcp channel.
|
||||||
// unreliable or reliable.
|
// unreliable or reliable.
|
||||||
// default to reliable just to be sure.
|
// default to reliable just to be sure.
|
||||||
switch (channelId)
|
switch (channelId)
|
||||||
{
|
{
|
||||||
case Channels.DefaultUnreliable:
|
case Channels.Unreliable:
|
||||||
return KcpConnection.UnreliableMaxMessageSize;
|
return KcpConnection.UnreliableMaxMessageSize;
|
||||||
default:
|
default:
|
||||||
return KcpConnection.ReliableMaxMessageSize;
|
return KcpConnection.ReliableMaxMessageSize;
|
||||||
|
@ -12,7 +12,7 @@ struct QueuedMessage
|
|||||||
{
|
{
|
||||||
public int connectionId;
|
public int connectionId;
|
||||||
public byte[] bytes;
|
public byte[] bytes;
|
||||||
public float timeToSend;
|
public float time;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HelpURL("https://mirror-networking.gitbook.io/docs/transports/latency-simulaton-transport")]
|
[HelpURL("https://mirror-networking.gitbook.io/docs/transports/latency-simulaton-transport")]
|
||||||
@ -24,19 +24,15 @@ public class LatencySimulation : Transport
|
|||||||
[Header("Reliable Messages")]
|
[Header("Reliable Messages")]
|
||||||
[Tooltip("Reliable latency in seconds")]
|
[Tooltip("Reliable latency in seconds")]
|
||||||
public float reliableLatency = 0;
|
public float reliableLatency = 0;
|
||||||
[Tooltip("Simulate latency spikes with % of latency for % of messages.")]
|
|
||||||
[Range(0, 1)] public float reliableLatencySpikes;
|
|
||||||
// note: packet loss over reliable manifests itself in latency.
|
// note: packet loss over reliable manifests itself in latency.
|
||||||
// don't need (and can't add) a loss option here.
|
// don't need (and can't add) a loss option here.
|
||||||
// note: reliable is ordered by definition. no need to scramble.
|
// note: reliable is ordered by definition. no need to scramble.
|
||||||
|
|
||||||
[Header("Unreliable Messages")]
|
[Header("Unreliable Messages")]
|
||||||
[Tooltip("Unreliable latency in seconds")]
|
|
||||||
public float unreliableLatency = 0;
|
|
||||||
[Tooltip("Simulate latency spikes with % of latency for % of messages.")]
|
|
||||||
[Range(0, 1)] public float unreliableLatencySpikes;
|
|
||||||
[Tooltip("Packet loss in %")]
|
[Tooltip("Packet loss in %")]
|
||||||
[Range(0, 1)] public float unreliableLoss;
|
[Range(0, 1)] public float unreliableLoss;
|
||||||
|
[Tooltip("Unreliable latency in seconds")]
|
||||||
|
public float unreliableLatency = 0;
|
||||||
[Tooltip("Scramble unreliable messages, just like over the real network. Mirror unreliable is unordered.")]
|
[Tooltip("Scramble unreliable messages, just like over the real network. Mirror unreliable is unordered.")]
|
||||||
public bool unreliableScramble;
|
public bool unreliableScramble;
|
||||||
|
|
||||||
@ -64,19 +60,6 @@ public void Awake()
|
|||||||
void OnEnable() { wrap.enabled = true; }
|
void OnEnable() { wrap.enabled = true; }
|
||||||
void OnDisable() { wrap.enabled = false; }
|
void OnDisable() { wrap.enabled = false; }
|
||||||
|
|
||||||
// helper function to simulate latency & spike with spike probability
|
|
||||||
float SimulateLatency(float latency, float spikesPercent)
|
|
||||||
{
|
|
||||||
// will this one spike?
|
|
||||||
bool spike = random.NextDouble() < spikesPercent;
|
|
||||||
|
|
||||||
// if it spiked, add spike latency by percent of original latency
|
|
||||||
float add = spike ? latency * spikesPercent : 0;
|
|
||||||
|
|
||||||
// return latency + spike
|
|
||||||
return latency + add;
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper function to simulate a send with latency/loss/scramble
|
// helper function to simulate a send with latency/loss/scramble
|
||||||
void SimulateSend(int connectionId, int channelId, ArraySegment<byte> segment, List<QueuedMessage> reliableQueue, List<QueuedMessage> unreliableQueue)
|
void SimulateSend(int connectionId, int channelId, ArraySegment<byte> segment, List<QueuedMessage> reliableQueue, List<QueuedMessage> unreliableQueue)
|
||||||
{
|
{
|
||||||
@ -84,34 +67,30 @@ void SimulateSend(int connectionId, int channelId, ArraySegment<byte> segment, L
|
|||||||
// (allocates for now. it's only for testing anyway.)
|
// (allocates for now. it's only for testing anyway.)
|
||||||
byte[] bytes = new byte[segment.Count];
|
byte[] bytes = new byte[segment.Count];
|
||||||
Buffer.BlockCopy(segment.Array, segment.Offset, bytes, 0, segment.Count);
|
Buffer.BlockCopy(segment.Array, segment.Offset, bytes, 0, segment.Count);
|
||||||
|
|
||||||
// enqueue message. send after latency interval.
|
// enqueue message. send after latency interval.
|
||||||
QueuedMessage message = new QueuedMessage
|
QueuedMessage message = new QueuedMessage
|
||||||
{
|
{
|
||||||
connectionId = connectionId,
|
connectionId = connectionId,
|
||||||
bytes = bytes
|
bytes = bytes,
|
||||||
|
time = Time.time
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (channelId)
|
switch (channelId)
|
||||||
{
|
{
|
||||||
case Channels.DefaultReliable:
|
case Channels.Reliable:
|
||||||
// simulate latency & spikes
|
// simulate latency
|
||||||
message.timeToSend = Time.time + SimulateLatency(reliableLatency, reliableLatencySpikes);
|
|
||||||
reliableQueue.Add(message);
|
reliableQueue.Add(message);
|
||||||
break;
|
break;
|
||||||
case Channels.DefaultUnreliable:
|
case Channels.Unreliable:
|
||||||
// simulate packet loss
|
// simulate packet loss
|
||||||
bool drop = random.NextDouble() < unreliableLoss;
|
bool drop = random.NextDouble() < unreliableLoss;
|
||||||
if (!drop)
|
if (!drop)
|
||||||
{
|
{
|
||||||
// simulate scramble (Random.Next is < max, so +1)
|
// 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 last = unreliableQueue.Count;
|
||||||
int index = unreliableScramble ? random.Next(0, last + 1) : last;
|
int index = unreliableScramble ? random.Next(0, last + 1) : last;
|
||||||
|
|
||||||
// simulate latency & spikes
|
// simulate latency
|
||||||
message.timeToSend = Time.time + SimulateLatency(unreliableLatency, unreliableLatencySpikes);
|
|
||||||
unreliableQueue.Insert(index, message);
|
unreliableQueue.Insert(index, message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -184,32 +163,34 @@ public override void ServerStop()
|
|||||||
public override void ServerEarlyUpdate() => wrap.ServerEarlyUpdate();
|
public override void ServerEarlyUpdate() => wrap.ServerEarlyUpdate();
|
||||||
public override void ClientLateUpdate()
|
public override void ClientLateUpdate()
|
||||||
{
|
{
|
||||||
// flush reliable messages that are ready to be sent
|
// flush reliable messages after latency
|
||||||
// => list isn't ordered (due to scramble). need to iterate all.
|
while (reliableClientToServer.Count > 0)
|
||||||
for (int i = 0; i < reliableClientToServer.Count; ++i)
|
|
||||||
{
|
{
|
||||||
QueuedMessage message = reliableClientToServer[i];
|
// check the first message time
|
||||||
if (Time.time >= message.timeToSend)
|
QueuedMessage message = reliableClientToServer[0];
|
||||||
|
if (message.time + reliableLatency <= Time.time)
|
||||||
{
|
{
|
||||||
// send and remove
|
// send and eat
|
||||||
wrap.ClientSend(Channels.DefaultReliable, new ArraySegment<byte>(message.bytes));
|
wrap.ClientSend(Channels.Reliable, new ArraySegment<byte>(message.bytes));
|
||||||
reliableClientToServer.RemoveAt(i);
|
reliableClientToServer.RemoveAt(0);
|
||||||
--i;
|
|
||||||
}
|
}
|
||||||
|
// not enough time elapsed yet
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// flush unrelabe messages that are ready to be sent
|
// flush unreliable messages after latency
|
||||||
// => list isn't ordered (due to scramble). need to iterate all.
|
while (unreliableClientToServer.Count > 0)
|
||||||
for (int i = 0; i < unreliableClientToServer.Count; ++i)
|
|
||||||
{
|
{
|
||||||
QueuedMessage message = unreliableClientToServer[i];
|
// check the first message time
|
||||||
if (Time.time >= message.timeToSend)
|
QueuedMessage message = unreliableClientToServer[0];
|
||||||
|
if (message.time + unreliableLatency <= Time.time)
|
||||||
{
|
{
|
||||||
// send and remove
|
// send and eat
|
||||||
wrap.ClientSend(Channels.DefaultUnreliable, new ArraySegment<byte>(message.bytes));
|
wrap.ClientSend(Channels.Unreliable, new ArraySegment<byte>(message.bytes));
|
||||||
unreliableClientToServer.RemoveAt(i);
|
unreliableClientToServer.RemoveAt(0);
|
||||||
--i;
|
|
||||||
}
|
}
|
||||||
|
// not enough time elapsed yet
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update wrapped transport too
|
// update wrapped transport too
|
||||||
@ -217,32 +198,34 @@ public override void ClientLateUpdate()
|
|||||||
}
|
}
|
||||||
public override void ServerLateUpdate()
|
public override void ServerLateUpdate()
|
||||||
{
|
{
|
||||||
// flush reliable messages that are ready to be sent
|
// flush reliable messages after latency
|
||||||
// => list isn't ordered (due to scramble). need to iterate all.
|
while (reliableServerToClient.Count > 0)
|
||||||
for (int i = 0; i < reliableServerToClient.Count; ++i)
|
|
||||||
{
|
{
|
||||||
QueuedMessage message = reliableServerToClient[i];
|
// check the first message time
|
||||||
if (Time.time >= message.timeToSend)
|
QueuedMessage message = reliableServerToClient[0];
|
||||||
|
if (message.time + reliableLatency <= Time.time)
|
||||||
{
|
{
|
||||||
// send and remove
|
// send and eat
|
||||||
wrap.ServerSend(message.connectionId, Channels.DefaultReliable, new ArraySegment<byte>(message.bytes));
|
wrap.ServerSend(message.connectionId, Channels.Reliable, new ArraySegment<byte>(message.bytes));
|
||||||
reliableServerToClient.RemoveAt(i);
|
reliableServerToClient.RemoveAt(0);
|
||||||
--i;
|
|
||||||
}
|
}
|
||||||
|
// not enough time elapsed yet
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// flush unrelabe messages that are ready to be sent
|
// flush unreliable messages after latency
|
||||||
// => list isn't ordered (due to scramble). need to iterate all.
|
while (unreliableServerToClient.Count > 0)
|
||||||
for (int i = 0; i < unreliableServerToClient.Count; ++i)
|
|
||||||
{
|
{
|
||||||
QueuedMessage message = unreliableServerToClient[i];
|
// check the first message time
|
||||||
if (Time.time >= message.timeToSend)
|
QueuedMessage message = unreliableServerToClient[0];
|
||||||
|
if (message.time + unreliableLatency <= Time.time)
|
||||||
{
|
{
|
||||||
// send and remove
|
// send and eat
|
||||||
wrap.ServerSend(message.connectionId, Channels.DefaultUnreliable, new ArraySegment<byte>(message.bytes));
|
wrap.ServerSend(message.connectionId, Channels.Unreliable, new ArraySegment<byte>(message.bytes));
|
||||||
unreliableServerToClient.RemoveAt(i);
|
unreliableServerToClient.RemoveAt(0);
|
||||||
--i;
|
|
||||||
}
|
}
|
||||||
|
// not enough time elapsed yet
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update wrapped transport too
|
// update wrapped transport too
|
||||||
|
@ -150,7 +150,7 @@ public override void ClientConnect(string hostname)
|
|||||||
// there should be no more messages after disconnect
|
// there should be no more messages after disconnect
|
||||||
client = null;
|
client = null;
|
||||||
};
|
};
|
||||||
client.onData += (ArraySegment<byte> data) => OnClientDataReceived.Invoke(data, Channels.DefaultReliable);
|
client.onData += (ArraySegment<byte> data) => OnClientDataReceived.Invoke(data, Channels.Reliable);
|
||||||
client.onError += (Exception e) =>
|
client.onError += (Exception e) =>
|
||||||
{
|
{
|
||||||
OnClientError.Invoke(e);
|
OnClientError.Invoke(e);
|
||||||
@ -214,7 +214,7 @@ public override void ServerStart()
|
|||||||
|
|
||||||
server.onConnect += OnServerConnected.Invoke;
|
server.onConnect += OnServerConnected.Invoke;
|
||||||
server.onDisconnect += OnServerDisconnected.Invoke;
|
server.onDisconnect += OnServerDisconnected.Invoke;
|
||||||
server.onData += (int connId, ArraySegment<byte> data) => OnServerDataReceived.Invoke(connId, data, Channels.DefaultReliable);
|
server.onData += (int connId, ArraySegment<byte> data) => OnServerDataReceived.Invoke(connId, data, Channels.Reliable);
|
||||||
server.onError += OnServerError.Invoke;
|
server.onError += OnServerError.Invoke;
|
||||||
|
|
||||||
SendLoopConfig.batchSend = batchSend || waitBeforeSend;
|
SendLoopConfig.batchSend = batchSend || waitBeforeSend;
|
||||||
|
@ -80,7 +80,7 @@ void Awake()
|
|||||||
// them all in a lambda and always call the latest hook.
|
// them all in a lambda and always call the latest hook.
|
||||||
// (= lazy call)
|
// (= lazy call)
|
||||||
client.OnConnected = () => OnClientConnected.Invoke();
|
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.OnDisconnected = () => OnClientDisconnected.Invoke();
|
||||||
|
|
||||||
// client configuration
|
// client configuration
|
||||||
@ -98,7 +98,7 @@ void Awake()
|
|||||||
// them all in a lambda and always call the latest hook.
|
// them all in a lambda and always call the latest hook.
|
||||||
// (= lazy call)
|
// (= lazy call)
|
||||||
server.OnConnected = (connectionId) => OnServerConnected.Invoke(connectionId);
|
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.OnDisconnected = (connectionId) => OnServerDisconnected.Invoke(connectionId);
|
||||||
|
|
||||||
// server configuration
|
// server configuration
|
||||||
|
@ -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 System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Mirror
|
namespace Mirror
|
||||||
{
|
{
|
||||||
/// <summary>Abstract transport layer component</summary>
|
/// <summary>
|
||||||
|
/// Abstract transport layer component
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <h2>
|
||||||
|
/// Transport Rules
|
||||||
|
/// </h2>
|
||||||
|
/// <list type="bullet">
|
||||||
|
/// <listheader><description>
|
||||||
|
/// All transports should follow these rules so that they work correctly with mirror
|
||||||
|
/// </description></listheader>
|
||||||
|
/// <item><description>
|
||||||
|
/// When Monobehaviour is disabled the Transport should not invoke callbacks
|
||||||
|
/// </description></item>
|
||||||
|
/// <item><description>
|
||||||
|
/// Callbacks should be invoked on main thread. It is best to do this from LateUpdate
|
||||||
|
/// </description></item>
|
||||||
|
/// <item><description>
|
||||||
|
/// Callbacks can be invoked after <see cref="ServerStop"/> or <see cref="ClientDisconnect"/> as been called
|
||||||
|
/// </description></item>
|
||||||
|
/// <item><description>
|
||||||
|
/// <see cref="ServerStop"/> or <see cref="ClientDisconnect"/> can be called by mirror multiple times
|
||||||
|
/// </description></item>
|
||||||
|
/// <item><description>
|
||||||
|
/// <see cref="Available"/> should check the platform and 32 vs 64 bit if the transport only works on some of them
|
||||||
|
/// </description></item>
|
||||||
|
/// <item><description>
|
||||||
|
/// <see cref="GetMaxPacketSize"/> should return size even if transport is not running
|
||||||
|
/// </description></item>
|
||||||
|
/// <item><description>
|
||||||
|
/// Default channel should be reliable <see cref="Channels.Reliable"/>
|
||||||
|
/// </description></item>
|
||||||
|
/// </list>
|
||||||
|
/// </remarks>
|
||||||
public abstract class Transport : MonoBehaviour
|
public abstract class Transport : MonoBehaviour
|
||||||
{
|
{
|
||||||
/// <summary>The current transport used by Mirror.</summary>
|
/// <summary>
|
||||||
|
/// The current transport used by Mirror.
|
||||||
|
/// </summary>
|
||||||
public static Transport activeTransport;
|
public static Transport activeTransport;
|
||||||
|
|
||||||
/// <summary>Transport available on this platform? Some aren't available on all platforms.</summary>
|
/// <summary>
|
||||||
|
/// Is this transport available in the current platform?
|
||||||
|
/// <para>Some transports might only be available in mobile</para>
|
||||||
|
/// <para>Many will not work in webgl</para>
|
||||||
|
/// <para>Example usage: return Application.platform == RuntimePlatform.WebGLPlayer</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if this transport works in the current platform</returns>
|
||||||
public abstract bool Available();
|
public abstract bool Available();
|
||||||
|
|
||||||
/// <summary>Notify subscribers when this client establish a successful connection to the server</summary>
|
#region Client
|
||||||
|
/// <summary>
|
||||||
|
/// Notify subscribers when this client establish a successful connection to the server
|
||||||
|
/// <para>callback()</para>
|
||||||
|
/// </summary>
|
||||||
public Action OnClientConnected = () => Debug.LogWarning("OnClientConnected called with no handler");
|
public Action OnClientConnected = () => Debug.LogWarning("OnClientConnected called with no handler");
|
||||||
|
|
||||||
/// <summary>Notify subscribers when this client receive data from the server</summary>
|
/// <summary>
|
||||||
|
/// Notify subscribers when this client receive data from the server
|
||||||
|
/// <para>callback(ArraySegment<byte> data, int channel)</para>
|
||||||
|
/// </summary>
|
||||||
public Action<ArraySegment<byte>, int> OnClientDataReceived = (data, channel) => Debug.LogWarning("OnClientDataReceived called with no handler");
|
public Action<ArraySegment<byte>, int> OnClientDataReceived = (data, channel) => Debug.LogWarning("OnClientDataReceived called with no handler");
|
||||||
|
|
||||||
/// <summary>Notify subscribers when this client encounters an error communicating with the server</summary>
|
/// <summary>
|
||||||
|
/// Notify subscribers when this client encounters an error communicating with the server
|
||||||
|
/// <para>callback(Exception e)</para>
|
||||||
|
/// </summary>
|
||||||
public Action<Exception> OnClientError = (error) => Debug.LogWarning("OnClientError called with no handler");
|
public Action<Exception> OnClientError = (error) => Debug.LogWarning("OnClientError called with no handler");
|
||||||
|
|
||||||
/// <summary>Notify subscribers when this client disconnects from the server</summary>
|
/// <summary>
|
||||||
|
/// Notify subscribers when this client disconnects from the server
|
||||||
|
/// <para>callback()</para>
|
||||||
|
/// </summary>
|
||||||
public Action OnClientDisconnected = () => Debug.LogWarning("OnClientDisconnected called with no handler");
|
public Action OnClientDisconnected = () => Debug.LogWarning("OnClientDisconnected called with no handler");
|
||||||
|
|
||||||
/// <summary>Determines if we are currently connected to the server</summary>
|
/// <summary>
|
||||||
|
/// Determines if we are currently connected to the server
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if a connection has been established to the server</returns>
|
||||||
public abstract bool ClientConnected();
|
public abstract bool ClientConnected();
|
||||||
|
|
||||||
/// <summary>Establish a connection to a server</summary>
|
/// <summary>
|
||||||
|
/// Establish a connection to a server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">The IP address or FQDN of the server we are trying to connect to</param>
|
||||||
public abstract void ClientConnect(string address);
|
public abstract void ClientConnect(string address);
|
||||||
|
|
||||||
/// <summary>Establish a connection to a server</summary>
|
/// <summary>
|
||||||
|
/// Establish a connection to a server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uri">The address of the server we are trying to connect to</param>
|
||||||
public virtual void ClientConnect(Uri uri)
|
public virtual void ClientConnect(Uri uri)
|
||||||
{
|
{
|
||||||
// By default, to keep backwards compatibility, just connect to the host
|
// By default, to keep backwards compatibility, just connect to the host
|
||||||
@ -48,60 +101,120 @@ public virtual void ClientConnect(Uri uri)
|
|||||||
ClientConnect(uri.Host);
|
ClientConnect(uri.Host);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Send data to the server over a given channel</summary>
|
/// <summary>
|
||||||
|
/// Send data to the server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channelId">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</param>
|
||||||
|
/// <param name="segment">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!</param>
|
||||||
public abstract void ClientSend(int channelId, ArraySegment<byte> segment);
|
public abstract void ClientSend(int channelId, ArraySegment<byte> segment);
|
||||||
|
|
||||||
/// <summary>Disconnect this client from the server</summary>
|
/// <summary>
|
||||||
|
/// Disconnect this client from the server
|
||||||
|
/// </summary>
|
||||||
public abstract void ClientDisconnect();
|
public abstract void ClientDisconnect();
|
||||||
|
|
||||||
/// <summary>Get the address of this server. Useful for network discovery</summary>
|
#endregion
|
||||||
|
|
||||||
|
#region Server
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the address of this server.
|
||||||
|
/// Useful for network discovery
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>the url at which this server can be reached</returns>
|
||||||
public abstract Uri ServerUri();
|
public abstract Uri ServerUri();
|
||||||
|
|
||||||
/// <summary>Notify subscribers when a client connects to this server</summary>
|
/// <summary>
|
||||||
|
/// Notify subscribers when a client connects to this server
|
||||||
|
/// <para>callback(int connId)</para>
|
||||||
|
/// </summary>
|
||||||
public Action<int> OnServerConnected = (connId) => Debug.LogWarning("OnServerConnected called with no handler");
|
public Action<int> OnServerConnected = (connId) => Debug.LogWarning("OnServerConnected called with no handler");
|
||||||
|
|
||||||
/// <summary>Notify subscribers when this server receives data from the client</summary>
|
/// <summary>
|
||||||
|
/// Notify subscribers when this server receives data from the client
|
||||||
|
/// <para>callback(int connId, ArraySegment<byte> data, int channel)</para>
|
||||||
|
/// </summary>
|
||||||
public Action<int, ArraySegment<byte>, int> OnServerDataReceived = (connId, data, channel) => Debug.LogWarning("OnServerDataReceived called with no handler");
|
public Action<int, ArraySegment<byte>, int> OnServerDataReceived = (connId, data, channel) => Debug.LogWarning("OnServerDataReceived called with no handler");
|
||||||
|
|
||||||
/// <summary>Notify subscribers when this server has some problem communicating with the client</summary>
|
/// <summary>
|
||||||
|
/// Notify subscribers when this server has some problem communicating with the client
|
||||||
|
/// <para>callback(int connId, Exception e)</para>
|
||||||
|
/// </summary>
|
||||||
public Action<int, Exception> OnServerError = (connId, error) => Debug.LogWarning("OnServerError called with no handler");
|
public Action<int, Exception> OnServerError = (connId, error) => Debug.LogWarning("OnServerError called with no handler");
|
||||||
|
|
||||||
/// <summary>Notify subscribers when a client disconnects from this server</summary>
|
/// <summary>
|
||||||
|
/// Notify subscribers when a client disconnects from this server
|
||||||
|
/// <para>callback(int connId)</para>
|
||||||
|
/// </summary>
|
||||||
public Action<int> OnServerDisconnected = (connId) => Debug.LogWarning("OnServerDisconnected called with no handler");
|
public Action<int> OnServerDisconnected = (connId) => Debug.LogWarning("OnServerDisconnected called with no handler");
|
||||||
|
|
||||||
/// <summary>Determines if the server is up and running</summary>
|
/// <summary>
|
||||||
|
/// Determines if the server is up and running
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>true if the transport is ready for connections from clients</returns>
|
||||||
public abstract bool ServerActive();
|
public abstract bool ServerActive();
|
||||||
|
|
||||||
/// <summary>Start listening for clients</summary>
|
/// <summary>
|
||||||
|
/// Start listening for clients
|
||||||
|
/// </summary>
|
||||||
public abstract void ServerStart();
|
public abstract void ServerStart();
|
||||||
|
|
||||||
/// <summary>Send data to the client with connectionId over the given channel.</summary>
|
/// <summary>
|
||||||
|
/// Send data to a client.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connectionId">The client connection id to send the data to</param>
|
||||||
|
/// <param name="channelId">The channel to be used. Transports can use channels to implement
|
||||||
|
/// other features such as unreliable, encryption, compression, etc...</param>
|
||||||
|
/// <param name="data"></param>
|
||||||
public abstract void ServerSend(int connectionId, int channelId, ArraySegment<byte> segment);
|
public abstract void ServerSend(int connectionId, int channelId, ArraySegment<byte> segment);
|
||||||
|
|
||||||
/// <summary>Disconnect a client from this server. Useful to kick people out.</summary>
|
/// <summary>
|
||||||
|
/// Disconnect a client from this server. Useful to kick people out.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connectionId">the id of the client to disconnect</param>
|
||||||
|
/// <returns>true if the client was kicked</returns>
|
||||||
public abstract bool ServerDisconnect(int connectionId);
|
public abstract bool ServerDisconnect(int connectionId);
|
||||||
|
|
||||||
/// <summary>Get the client address, useful for IP bans etc.</summary>
|
/// <summary>
|
||||||
|
/// Get the client address
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connectionId">id of the client</param>
|
||||||
|
/// <returns>address of the client</returns>
|
||||||
public abstract string ServerGetClientAddress(int connectionId);
|
public abstract string ServerGetClientAddress(int connectionId);
|
||||||
|
|
||||||
/// <summary>Stop listening for clients and disconnect all existing clients</summary>
|
/// <summary>
|
||||||
|
/// Stop listening for clients and disconnect all existing clients
|
||||||
|
/// </summary>
|
||||||
public abstract void ServerStop();
|
public abstract void ServerStop();
|
||||||
|
|
||||||
/// <summary>The maximum packet size for a given channel.</summary>
|
#endregion
|
||||||
// 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);
|
|
||||||
|
|
||||||
/// <summary>The maximum batch(!) size for a given channel.</summary>
|
/// <summary>
|
||||||
// Uses GetMaxPacketSize by default.
|
/// The maximum packet size for a given channel. Unreliable transports
|
||||||
// Some transports like kcp support large max packet sizes which should
|
/// usually can only deliver small packets. Reliable fragmented channels
|
||||||
// not be used for batching all the time because they end up being too
|
/// can usually deliver large ones.
|
||||||
// slow (head of line blocking etc.).
|
///
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channelId">channel id</param>
|
||||||
|
/// <returns>the size in bytes that can be sent via the provided channel</returns>
|
||||||
|
public abstract int GetMaxPacketSize(int channelId = Channels.Reliable);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channelId">channel id</param>
|
||||||
|
/// <returns>the size in bytes that should be batched via the provided channel</returns>
|
||||||
public virtual int GetMaxBatchSize(int channelId) =>
|
public virtual int GetMaxBatchSize(int channelId) =>
|
||||||
GetMaxPacketSize(channelId);
|
GetMaxPacketSize(channelId);
|
||||||
|
|
||||||
@ -122,12 +235,14 @@ public void Update() {}
|
|||||||
public void LateUpdate() {}
|
public void LateUpdate() {}
|
||||||
#pragma warning restore UNT0001 // Empty Unity message
|
#pragma warning restore UNT0001 // Empty Unity message
|
||||||
|
|
||||||
// NetworkLoop NetworkEarly/LateUpdate were added for a proper network
|
/// <summary>
|
||||||
// update order. the goal is to:
|
/// NetworkLoop NetworkEarly/LateUpdate were added for a proper network
|
||||||
// process_incoming()
|
/// update order. the goal is to:
|
||||||
// update_world()
|
/// process_incoming()
|
||||||
// process_outgoing()
|
/// update_world()
|
||||||
// in order to avoid unnecessary latency and data races.
|
/// process_outgoing()
|
||||||
|
/// in order to avoid unnecessary latency and data races.
|
||||||
|
/// </summary>
|
||||||
// => split into client and server parts so that we can cleanly call
|
// => split into client and server parts so that we can cleanly call
|
||||||
// them from NetworkClient/Server
|
// them from NetworkClient/Server
|
||||||
// => VIRTUAL for now so we can take our time to convert transports
|
// => 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 ClientLateUpdate() {}
|
||||||
public virtual void ServerLateUpdate() {}
|
public virtual void ServerLateUpdate() {}
|
||||||
|
|
||||||
/// <summary>Shut down the transport, both as client and server</summary>
|
/// <summary>
|
||||||
|
/// Shut down the transport, both as client and server
|
||||||
|
/// </summary>
|
||||||
public abstract void Shutdown();
|
public abstract void Shutdown();
|
||||||
|
|
||||||
// called when quitting the application by closing the window / pressing
|
/// <summary>
|
||||||
// stop in the editor.
|
/// called when quitting the application by closing the window / pressing stop in the editor
|
||||||
// virtual so that inheriting classes' OnApplicationQuit() can call
|
/// <para>virtual so that inheriting classes' OnApplicationQuit() can call base.OnApplicationQuit() too</para>
|
||||||
// base.OnApplicationQuit() too</para>
|
/// </summary>
|
||||||
public virtual void OnApplicationQuit()
|
public virtual void OnApplicationQuit()
|
||||||
{
|
{
|
||||||
// stop transport (e.g. to shut down threads)
|
// stop transport (e.g. to shut down threads)
|
||||||
|
@ -38,8 +38,13 @@ public enum Version
|
|||||||
// add custom channels anymore.
|
// add custom channels anymore.
|
||||||
public static class Channels
|
public static class Channels
|
||||||
{
|
{
|
||||||
public const int DefaultReliable = 0;
|
public const int Reliable = 0; // ordered
|
||||||
public const int DefaultUnreliable = 1;
|
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 --
|
// -- helpers for float conversion without allocations --
|
||||||
|
@ -39,7 +39,7 @@ public void TearDown()
|
|||||||
public void SendEmptyBatch()
|
public void SendEmptyBatch()
|
||||||
{
|
{
|
||||||
// empty batch - nothing should be sent
|
// empty batch - nothing should be sent
|
||||||
connection.SendBatch(Channels.DefaultReliable, batch);
|
connection.SendBatch(Channels.Reliable, batch);
|
||||||
Assert.That(transport.clientIncoming.Count, Is.EqualTo(0));
|
Assert.That(transport.clientIncoming.Count, Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ public void SendEmptyBatch()
|
|||||||
public void SendAlmostMaxBatchSizedMessageBatch()
|
public void SendAlmostMaxBatchSizedMessageBatch()
|
||||||
{
|
{
|
||||||
// create a message < max batch size
|
// create a message < max batch size
|
||||||
int max = transport.GetMaxBatchSize(Channels.DefaultReliable);
|
int max = transport.GetMaxBatchSize(Channels.Reliable);
|
||||||
byte[] message = new byte[max-1];
|
byte[] message = new byte[max-1];
|
||||||
|
|
||||||
// add to batch queue
|
// add to batch queue
|
||||||
@ -56,7 +56,7 @@ public void SendAlmostMaxBatchSizedMessageBatch()
|
|||||||
batch.messages.Enqueue(writer);
|
batch.messages.Enqueue(writer);
|
||||||
|
|
||||||
// send batch - client should receive that exact message
|
// 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.Count, Is.EqualTo(1));
|
||||||
Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(message.Length));
|
Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(message.Length));
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ public void SendAlmostMaxBatchSizedMessageBatch()
|
|||||||
public void SendMaxBatchSizedMessageBatch()
|
public void SendMaxBatchSizedMessageBatch()
|
||||||
{
|
{
|
||||||
// create a message == max batch size
|
// create a message == max batch size
|
||||||
int max = transport.GetMaxBatchSize(Channels.DefaultReliable);
|
int max = transport.GetMaxBatchSize(Channels.Reliable);
|
||||||
byte[] message = new byte[max];
|
byte[] message = new byte[max];
|
||||||
|
|
||||||
// add to batch queue
|
// add to batch queue
|
||||||
@ -74,7 +74,7 @@ public void SendMaxBatchSizedMessageBatch()
|
|||||||
batch.messages.Enqueue(writer);
|
batch.messages.Enqueue(writer);
|
||||||
|
|
||||||
// send batch - client should receive that exact message
|
// 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.Count, Is.EqualTo(1));
|
||||||
Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(message.Length));
|
Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(message.Length));
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ public void SendTwoSmallMessagesBatch()
|
|||||||
batch.messages.Enqueue(writerB);
|
batch.messages.Enqueue(writerB);
|
||||||
|
|
||||||
// send batch - client should receive one message that contains A, B
|
// 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));
|
Assert.That(transport.clientIncoming.Count, Is.EqualTo(1));
|
||||||
MemoryTransport.Message msg = transport.clientIncoming.Dequeue();
|
MemoryTransport.Message msg = transport.clientIncoming.Dequeue();
|
||||||
Assert.That(msg.data.Length, Is.EqualTo(4));
|
Assert.That(msg.data.Length, Is.EqualTo(4));
|
||||||
@ -111,7 +111,7 @@ public void SendTwoSmallMessagesBatch()
|
|||||||
public void SendAlmostMaxBatchSizedAndSmallMessageBatch()
|
public void SendAlmostMaxBatchSizedAndSmallMessageBatch()
|
||||||
{
|
{
|
||||||
// create a message < max batch size
|
// create a message < max batch size
|
||||||
int max = transport.GetMaxBatchSize(Channels.DefaultReliable);
|
int max = transport.GetMaxBatchSize(Channels.Reliable);
|
||||||
byte[] almost = new byte[max-1];
|
byte[] almost = new byte[max-1];
|
||||||
|
|
||||||
// create small message
|
// create small message
|
||||||
@ -129,7 +129,7 @@ public void SendAlmostMaxBatchSizedAndSmallMessageBatch()
|
|||||||
|
|
||||||
// send batch - should send the first one and then the second one
|
// send batch - should send the first one and then the second one
|
||||||
// because both together would've been > max
|
// 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.Count, Is.EqualTo(2));
|
||||||
Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(almost.Length));
|
Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(almost.Length));
|
||||||
Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(small.Length));
|
Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(small.Length));
|
||||||
@ -142,8 +142,8 @@ public void SendAlmostMaxBatchSizedAndSmallMessageBatch()
|
|||||||
[Test]
|
[Test]
|
||||||
public void SendLargerMaxBatchSizedMessageBatch()
|
public void SendLargerMaxBatchSizedMessageBatch()
|
||||||
{
|
{
|
||||||
int maxBatch = transport.GetMaxBatchSize(Channels.DefaultReliable);
|
int maxBatch = transport.GetMaxBatchSize(Channels.Reliable);
|
||||||
int maxPacket = transport.GetMaxPacketSize(Channels.DefaultReliable);
|
int maxPacket = transport.GetMaxPacketSize(Channels.Reliable);
|
||||||
|
|
||||||
// we can only tested if transport max batch < max message
|
// we can only tested if transport max batch < max message
|
||||||
Assert.That(maxBatch < maxPacket, Is.True);
|
Assert.That(maxBatch < maxPacket, Is.True);
|
||||||
@ -157,7 +157,7 @@ public void SendLargerMaxBatchSizedMessageBatch()
|
|||||||
batch.messages.Enqueue(writer);
|
batch.messages.Enqueue(writer);
|
||||||
|
|
||||||
// send batch - client should receive that exact message
|
// 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.Count, Is.EqualTo(1));
|
||||||
Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(message.Length));
|
Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(message.Length));
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,11 @@ public void CommandAttributeTest()
|
|||||||
{
|
{
|
||||||
CommandAttribute attrib = new CommandAttribute();
|
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]
|
[Test]
|
||||||
@ -33,11 +33,11 @@ public void ClientRPCAttributeTest()
|
|||||||
{
|
{
|
||||||
ClientRpcAttribute attrib = new ClientRpcAttribute();
|
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]
|
[Test]
|
||||||
@ -45,9 +45,9 @@ public void TargetRPCAttributeTest()
|
|||||||
{
|
{
|
||||||
TargetRpcAttribute attrib = new TargetRpcAttribute();
|
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);
|
Assert.That(attrib.channel == 1);
|
||||||
}
|
}
|
||||||
|
@ -44,9 +44,9 @@ public void TestAvailable(bool available)
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
[TestCase(Channels.DefaultReliable, 4000)]
|
[TestCase(Channels.Reliable, 4000)]
|
||||||
[TestCase(Channels.DefaultReliable, 2000)]
|
[TestCase(Channels.Reliable, 2000)]
|
||||||
[TestCase(Channels.DefaultUnreliable, 4000)]
|
[TestCase(Channels.Unreliable, 4000)]
|
||||||
public void TestGetMaxPacketSize(int channel, int packageSize)
|
public void TestGetMaxPacketSize(int channel, int packageSize)
|
||||||
{
|
{
|
||||||
inner.GetMaxPacketSize(Arg.Any<int>()).Returns(packageSize);
|
inner.GetMaxPacketSize(Arg.Any<int>()).Returns(packageSize);
|
||||||
@ -97,8 +97,8 @@ public void TestClientDisconnect()
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
[TestCase(Channels.DefaultReliable)]
|
[TestCase(Channels.Reliable)]
|
||||||
[TestCase(Channels.DefaultUnreliable)]
|
[TestCase(Channels.Unreliable)]
|
||||||
public void TestClientSend(int channel)
|
public void TestClientSend(int channel)
|
||||||
{
|
{
|
||||||
byte[] array = new byte[10];
|
byte[] array = new byte[10];
|
||||||
|
Loading…
Reference in New Issue
Block a user