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) { // send to all connections, but don't wait for them player.Send(segment, channelId); count++; } NetworkDiagnostics.OnSend(msg, channelId, segment.Count, count); } }
internal void InvokeHandler(int msgType, NetworkReader reader, int channelId) { if (messageHandlers.TryGetValue(msgType, out NetworkMessageDelegate msgDelegate)) { msgDelegate(this, reader, channelId); } else { try { Type type = MessagePacker.GetMessageType(msgType); throw new InvalidDataException($"Unexpected message {type} received in {this}. Did you register a handler for it?"); } catch (KeyNotFoundException) { throw new InvalidDataException($"Unexpected message ID {msgType} received in {this}. May be due to no existing RegisterHandler for this message."); } } }
internal void ReceiveNotify(NotifyPacket notifyPacket, NetworkReader networkReader, int channelId) { int sequenceDistance = (int)sequencer.Distance(notifyPacket.Sequence, receiveSequence); // sequence is so far out of bounds we can't save, just kick him (or her!) if (Math.Abs(sequenceDistance) > WINDOW_SIZE) { connection?.Disconnect(); return; } // this message is old, we already received // a newer or duplicate packet. Discard it if (sequenceDistance <= 0) { return; } receiveSequence = notifyPacket.Sequence; if (sequenceDistance >= ACK_MASK_BITS) { receiveMask = 1; } else { receiveMask = (receiveMask << sequenceDistance) | 1; } AckPackets(notifyPacket.ReceiveSequence, notifyPacket.AckMask); int msgType = MessagePacker.UnpackId(networkReader); InvokeHandler(msgType, networkReader, channelId); if (Time.unscaledTime - lastNotifySentTime > NOTIFY_ACK_TIMEOUT) { SendNotify(new NotifyAck(), null, channelId); } }
/// <summary> /// Unregisters a handler for a particular message type. /// </summary> /// <typeparam name="T">Message type</typeparam> public void UnregisterHandler <T>() { int msgType = MessagePacker.GetId <T>(); messageHandlers.Remove(msgType); }