Пример #1
0
        public void Handle(ByteArray data, Connection <T> connection)
        {
            if (connection.destroyed)
            {
                return;
            }
            if (data.Length < 12)
            {
                return;
            }
            int recvSendingID = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.data, 0));
            int recvPartID    = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.data, 4));
            int recvLength    = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.data, 8));
            //Always send an ACK back immediately
            NetworkMessage nm = NetworkMessage.Create(-5, 8, NetworkMessageType.UNORDERED_UNRELIABLE);

            Array.Copy(data.data, 0, nm.data.data, 0, 8);
            handler.SendMessageWithHighPriority(nm, connection);

            ReliableMessageReceiveTracking rmrt = null;

            if (receivingMessages.ContainsKey(recvSendingID))
            {
                rmrt = receivingMessages[recvSendingID];
            }
            //Received either a new chunk or a duplicate, if the messageID is higher than what we have received, it's new.
            if (rmrt == null)
            {
                if (recvSendingID > 0)
                {
                    int distance = recvSendingID - unorderedReceiveID;
                    //A message in the past (doesn't detect wrap around)
                    bool fromThePast = distance <= 0;
                    //A future message received before we have wrapped around
                    bool massivelyInPast = -distance > (Int32.MaxValue / 4);
                    //A past message received when we have wrapped around
                    bool massivelyInFuture = distance > (Int32.MaxValue / 4);
                    if (fromThePast && !massivelyInPast || massivelyInFuture)
                    {
                        return;
                    }
                    while (recvSendingID != unorderedReceiveID)
                    {
                        if (unorderedReceiveID == Int32.MaxValue)
                        {
                            unorderedReceiveID = 0;
                        }
                        unorderedReceiveID++;
                        rmrt = ReliableMessageReceiveTracking.Create();
                        lock (receivingMessages)
                        {
                            receivingMessages.Add(unorderedReceiveID, rmrt);
                        }
                    }
                }
                else
                {
                    int distance = -recvSendingID - orderedReceiveID;
                    //A message in the past (doesn't detect wrap around)
                    bool fromThePast = distance <= 0;
                    //A future message received before we have wrapped around
                    bool massivelyInPast = -distance > (Int32.MaxValue / 4);
                    //A past message received when we have wrapped around
                    bool massivelyInFuture = distance > (Int32.MaxValue / 4);
                    if (fromThePast && !massivelyInPast || massivelyInFuture)
                    {
                        return;
                    }
                    while (-recvSendingID != orderedReceiveID)
                    {
                        if (orderedReceiveID == Int32.MaxValue)
                        {
                            orderedReceiveID = 0;
                        }
                        orderedReceiveID++;
                        rmrt = ReliableMessageReceiveTracking.Create();
                        lock (receivingMessages)
                        {
                            receivingMessages.Add(-orderedReceiveID, rmrt);
                        }
                    }
                }
                rmrt = receivingMessages[recvSendingID];
            }

            //Fist setup if needed
            if (rmrt.networkMessage == null)
            {
                if (recvSendingID > 0)
                {
                    rmrt.Setup(recvLength, NetworkMessageType.UNORDERED_RELIABLE);
                }
                else
                {
                    rmrt.Setup(recvLength, NetworkMessageType.ORDERED_RELIABLE);
                }
            }

            //Handle incoming data
            rmrt.Handle(recvPartID, recvLength, data);

            //We have all the parts
            if (rmrt.receivePartsLeft == 0)
            {
                if (recvSendingID > 0)
                {
                    handler.Handle(rmrt.networkMessage, connection);
                }
                else
                {
                    //This message is received in order
                    if (-recvSendingID == orderedHandleID)
                    {
                        orderedHandleID++;
                        if (orderedHandleID == Int32.MaxValue)
                        {
                            orderedHandleID = 0;
                        }
                        handler.Handle(rmrt.networkMessage, connection);
                    }
                    else
                    {
                        //This message is received out of order and we need to hold onto it
                        orderedHandleMessages.Add(-recvSendingID, rmrt.networkMessage);
                    }
                    //If a message fills the missing hole this can play out.
                    while (orderedHandleMessages.ContainsKey(orderedHandleID))
                    {
                        NetworkMessage handleMessage = orderedHandleMessages[orderedHandleID];
                        orderedHandleMessages.Remove(orderedHandleID);
                        handler.Handle(handleMessage, connection);
                        orderedHandleID++;
                        if (orderedHandleID == Int32.MaxValue)
                        {
                            orderedHandleID = 0;
                        }
                    }
                }
                rmrt.Destroy();
                lock (receivingMessages)
                {
                    receivingMessages.Remove(recvSendingID);
                }
            }
        }