Skip to content

Commit

Permalink
feat: Transport can send to multiple connections at once (#1120)
Browse files Browse the repository at this point in the history
* so far

* consider local conn

* internal Send(list) to avoid obsolete later

* typo

* empty line
  • Loading branch information
miwarnec committed Sep 28, 2019
1 parent 268a2cc commit bc7e116
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 5 deletions.
16 changes: 16 additions & 0 deletions Assets/Mirror/Runtime/NetworkConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,22 @@ internal virtual bool Send(byte[] bytes, int channelId = Channels.DefaultReliabl
return false;
}

// Send to many. basically Transport.Send(connections) + checks.
internal static bool Send(List<int> connectionIds, byte[] bytes, int channelId = Channels.DefaultReliable)
{
// validate packet size first.
if (ValidatePacketSize(bytes, channelId))
{
// only the server sends to many, we don't have that function on
// a client.
if (Transport.activeTransport.ServerActive())
{
return Transport.activeTransport.ServerSend(connectionIds, channelId, bytes);
}
}
return false;
}

public override string ToString()
{
return $"connectionId: {connectionId} isReady: {isReady}";
Expand Down
49 changes: 45 additions & 4 deletions Assets/Mirror/Runtime/NetworkServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ public static class NetworkServer
/// </summary>
public static bool localClientActive { get; private set; }

// cache the Send(connectionIds) list to avoid allocating each time
static List<int> connectionIdsCache = new List<int>();

/// <summary>
/// Reset the NetworkServer singleton.
/// </summary>
Expand Down Expand Up @@ -246,11 +249,24 @@ static bool SendToObservers(NetworkIdentity identity, short msgType, MessageBase
// pack message into byte[] once
byte[] bytes = MessagePacker.Pack(msg);

// filter and then send to all internet connections at once
// -> makes code more complicated, but is HIGHLY worth it to
// avoid allocations, allow for multicast, etc.
connectionIdsCache.Clear();
bool result = true;
foreach (KeyValuePair<int, NetworkConnection> kvp in identity.observers)
{
result &= kvp.Value.Send(bytes);
// use local connection directly because it doesn't send via transport
if (kvp.Value is ULocalConnectionToClient)
result &= localConnection.Send(bytes);
// gather all internet connections
else
connectionIdsCache.Add(kvp.Key);
}

// send to all internet connections at once
if (connectionIdsCache.Count > 0)
result &= NetworkConnection.Send(connectionIdsCache, bytes);
NetworkDiagnostics.OnSend(msg, Channels.DefaultReliable, bytes.Length, identity.observers.Count);
return result;
}
Expand Down Expand Up @@ -292,14 +308,25 @@ public static bool SendToAll(int msgType, MessageBase msg, int channelId = Chann
// pack message into byte[] once
byte[] bytes = MessagePacker.Pack(msg);

// filter and then send to all internet connections at once
// -> makes code more complicated, but is HIGHLY worth it to
// avoid allocations, allow for multicast, etc.
connectionIdsCache.Clear();
bool result = true;
foreach (KeyValuePair<int, NetworkConnection> kvp in connections)
{
result &= kvp.Value.Send(bytes, channelId);
// use local connection directly because it doesn't send via transport
if (kvp.Value is ULocalConnectionToClient)
result &= localConnection.Send(bytes);
// gather all internet connections
else
connectionIdsCache.Add(kvp.Key);
}

// send to all internet connections at once
if (connectionIdsCache.Count > 0)
result &= NetworkConnection.Send(connectionIdsCache, bytes);
NetworkDiagnostics.OnSend(msg, channelId, bytes.Length, connections.Count);

return result;
}

Expand Down Expand Up @@ -350,17 +377,31 @@ public static bool SendToReady(NetworkIdentity identity, short msgType, MessageB
byte[] bytes = MessagePacker.Pack(msg);
int count = 0;

// filter and then send to all internet connections at once
// -> makes code more complicated, but is HIGHLY worth it to
// avoid allocations, allow for multicast, etc.
connectionIdsCache.Clear();
bool result = true;
foreach (KeyValuePair<int, NetworkConnection> kvp in identity.observers)
{
bool isSelf = kvp.Value == identity.connectionToClient;
if ((!isSelf || includeSelf) &&
kvp.Value.isReady)
{
result &= kvp.Value.Send(bytes, channelId);
count++;

// use local connection directly because it doesn't send via transport
if (kvp.Value is ULocalConnectionToClient)
result &= localConnection.Send(bytes);
// gather all internet connections
else
connectionIdsCache.Add(kvp.Key);
}
}

// send to all internet connections at once
if (connectionIdsCache.Count > 0)
result &= NetworkConnection.Send(connectionIdsCache, bytes);
NetworkDiagnostics.OnSend(msg, channelId, bytes.Length, count);
return result;
}
Expand Down
17 changes: 16 additions & 1 deletion Assets/Mirror/Runtime/Transport/Transport.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// abstract transport layer component
// note: not all transports need a port, so add it to yours if needed.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using UnityEngine;
using UnityEngine.Events;
Expand All @@ -17,7 +18,7 @@ namespace Mirror
public abstract class Transport : MonoBehaviour
{
/// <summary>
/// The current transport used by Mirror.
/// The current transport used by Mirror.
/// </summary>
public static Transport activeTransport;

Expand Down Expand Up @@ -125,6 +126,20 @@ public virtual bool Available()
/// <returns>true if the data was sent</returns>
public abstract bool ServerSend(int connectionId, int channelId, byte[] data);

/// <summary>
/// Send data to multiple clients at once.
/// Calls ServerSend by default. Can be overwritten by transports that can send to multiple
/// clients at once more efficiently if needed.
/// </summary>
internal virtual bool ServerSend(List<int> connectionIds, int channelId, byte[] data)
{
// true by default (for empty lists)
bool result = true;
foreach (int connectionId in connectionIds)
result &= ServerSend(connectionId, channelId, data);
return result;
}

/// <summary>
/// Disconnect a client from this server. Useful to kick people out.
/// </summary>
Expand Down

0 comments on commit bc7e116

Please sign in to comment.