Beispiel #1
0
        /// <summary>
        /// Send a message to all connected clients.
        /// </summary>
        /// <typeparam name="T">Message type</typeparam>
        /// <param name="msg">Message</param>
        /// <param name="channelId">Transport channel to use</param>
        public void SendToAll <T>(T msg, int channelId = Channel.Reliable)
        {
            if (logger.LogEnabled())
            {
                logger.Log("Server.SendToAll id:" + typeof(T));
            }

            using (var writer = NetworkWriterPool.GetWriter())
            {
                // pack message into byte[] once
                MessagePacker.Pack(msg, writer);
                var segment = writer.ToArraySegment();
                var count   = 0;

                // using SendToMany (with IEnumerable) will cause Enumerator to be boxed and create GC/alloc
                // instead we can use while loop and MoveNext to avoid boxing
                var enumerator = _connections.Values.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    var player = enumerator.Current;
                    player.Send(segment, channelId);
                    count++;
                }
                enumerator.Dispose();

                NetworkDiagnostics.OnSend(msg, segment.Count, count);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Sends a message, but notify when it is delivered or lost
        /// </summary>
        /// <typeparam name="T">type of message to send</typeparam>
        /// <param name="message">message to send</param>
        /// <param name="token">a arbitrary object that the sender will receive with their notification</param>
        public void SendNotify <T>(T message, object token, int channelId = Channel.Unreliable)
        {
            if (sendWindow.Count == WINDOW_SIZE)
            {
                NotifyLost?.Invoke(this, token);
                return;
            }

            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
            {
                var notifyPacket = new NotifyPacket
                {
                    Sequence        = (ushort)sequencer.Next(),
                    ReceiveSequence = receiveSequence,
                    AckMask         = receiveMask
                };

                sendWindow.Enqueue(new PacketEnvelope
                {
                    Sequence = notifyPacket.Sequence,
                    Token    = token
                });

                MessagePacker.Pack(notifyPacket, writer);
                MessagePacker.Pack(message, writer);
                NetworkDiagnostics.OnSend(message, channelId, writer.Length, 1);
                Send(writer.ToArraySegment(), channelId);
                lastNotifySentTime = Time.unscaledTime;
            }
        }
Beispiel #3
0
 /// <summary>
 /// This sends a network message to the connection.
 /// </summary>
 /// <typeparam name="T">The message type</typeparam>
 /// <param name="msg">The message to send.</param>
 /// <param name="channelId">The transport layer channel to send on.</param>
 /// <returns></returns>
 public void Send <T>(T message, int channelId = Channel.Reliable)
 {
     using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
     {
         // pack message and send allocation free
         MessagePacker.Pack(message, writer);
         NetworkDiagnostics.OnSend(message, channelId, writer.Length, 1);
         Send(writer.ToArraySegment(), channelId);
     }
 }
Beispiel #4
0
 /// <summary>
 /// This sends a network message to the connection. You can await it to check for errors
 /// </summary>
 /// <typeparam name="T">The message type</typeparam>
 /// <param name="msg">The message to send.</param>
 /// <param name="channelId">The transport layer channel to send on.</param>
 /// <returns></returns>
 public virtual UniTask SendAsync <T>(T msg, int channelId = Channel.Reliable)
 {
     using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
     {
         // pack message and send allocation free
         MessagePacker.Pack(msg, writer);
         NetworkDiagnostics.OnSend(msg, channelId, writer.Length, 1);
         return(SendAsync(writer.ToArraySegment(), channelId));
     }
 }
Beispiel #5
0
        /// <summary>
        /// This sends a network message to the connection.
        /// </summary>
        /// <typeparam name="T">The message type</typeparam>
        /// <param name="msg">The message to send.</param>
        /// <param name="channelId">The transport layer channel to send on.</param>
        /// <returns></returns>
        public void Send <T>(T message, INotifyCallBack token)
        {
            if (isDisconnected)
            {
                return;
            }

            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
            {
                MessagePacker.Pack(message, writer);

                var segment = writer.ToArraySegment();
                NetworkDiagnostics.OnSend(message, segment.Count, 1);
                connection.SendNotify(segment, token);
            }
        }
Beispiel #6
0
        /// <summary>
        /// This sends a network message to the connection.
        /// </summary>
        /// <typeparam name="T">The message type</typeparam>
        /// <param name="msg">The message to send.</param>
        /// <param name="channelId">The transport layer channel to send on.</param>
        /// <returns></returns>
        public void Send <T>(T message, int channelId = Channel.Reliable)
        {
            if (isDisconnected)
            {
                return;
            }

            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
            {
                MessagePacker.Pack(message, writer);

                var segment = writer.ToArraySegment();
                NetworkDiagnostics.OnSend(message, segment.Count, 1);
                Send(segment, channelId);
            }
        }
Beispiel #7
0
        /// <summary>
        /// Sends a message to many connections
        /// <para>
        /// Same as <see cref="SendToMany{T}(IEnumerable{INetworkPlayer}, T, int)"/> but uses for loop to avoid allocations
        /// </para>
        /// </summary>
        /// <remarks>
        /// Using list in foreach loop causes Unity's mono version to box the struct which causes allocations, <see href="https://docs.unity3d.com/2019.4/Documentation/Manual/BestPracticeUnderstandingPerformanceInUnity4-1.html">Understanding the managed heap</see>
        /// </remarks>
        public static void SendToMany <T>(IReadOnlyList <INetworkPlayer> players, T msg, int channelId = Channel.Reliable)
        {
            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
            {
                // pack message into byte[] once
                MessagePacker.Pack(msg, writer);
                var segment = writer.ToArraySegment();
                int count   = players.Count;

                for (int i = 0; i < count; i++)
                {
                    players[i].Send(segment, channelId);
                }

                NetworkDiagnostics.OnSend(msg, segment.Count, count);
            }
        }
Beispiel #8
0
        /// <summary>
        /// Sends a message to many connections
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="players"></param>
        /// <param name="msg"></param>
        /// <param name="channelId"></param>
        public static void SendToMany <T>(IEnumerable <INetworkPlayer> players, T msg, int channelId = Channel.Reliable)
        {
            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
            {
                // pack message into byte[] once
                MessagePacker.Pack(msg, writer);
                var segment = writer.ToArraySegment();
                int count   = 0;

                foreach (INetworkPlayer player in players)
                {
                    player.Send(segment, channelId);
                    count++;
                }

                NetworkDiagnostics.OnSend(msg, segment.Count, count);
            }
        }
Beispiel #9
0
        public static void Send <T>(IEnumerable <INetworkConnection> connections, T msg, int channelId = Channel.Reliable)
        {
            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
            {
                // pack message into byte[] once
                MessagePacker.Pack(msg, writer);
                var segment = writer.ToArraySegment();
                int count   = 0;

                foreach (INetworkConnection conn in connections)
                {
                    // send to all connections, but don't wait for them
                    conn.Send(segment, channelId);
                    count++;
                }

                NetworkDiagnostics.OnSend(msg, channelId, segment.Count, count);
            }
        }