예제 #1
0
        public void Deserialize(BitStream message, UserCommand?old)
        {
            if (old == null)
            {
                ServerTime = message.ReadUInt32();
                Buttons    = (ClientButtons)message.ReadInt16();
            }
            else
            {
                var oldCommand = old.Value;

                // read server time
                if (message.ReadBool())
                {
                    // is delta time
                    ServerTime = oldCommand.ServerTime + message.ReadByte();
                }
                else
                {
                    // is absolute time
                    ServerTime = message.ReadUInt32();
                }

                // read buttons
                Buttons = (ClientButtons)message.ReadDeltaInt16((short)oldCommand.Buttons);
            }
        }
예제 #2
0
        public uint ReadUInt32()
        {
            uint value = (_baseStream == null) ? 0 : _baseStream.ReadUInt32();

            if (_bitStream.ReadBool())
            {
                value = _bitStream.ReadUInt32();
            }

            _newBaseStream.WriteUInt32(value);

            return(value);
        }
예제 #3
0
        public void WriteUInt32(uint value)
        {
            _newBaseStream.WriteUInt32(value);

            if (_baseStream != null && value == _baseStream.ReadUInt32())
            {
                _bitStream.WriteBool(false);
            }
            else
            {
                _bitStream.WriteBool(true);
                _bitStream.WriteUInt32(value);
            }
        }
예제 #4
0
        public static void ProcessPacket(NetAddress from, byte[] packet)
        {
            if (packet.Length < 4)
            {
                return;
            }

            var message     = new BitStream(packet);
            var sequenceNum = message.ReadUInt32();

            if (sequenceNum == 0xFFFFFFFF)
            {
                ProcessOutOfBand(from, packet);
                return;
            }

            if (from != _serverChannel.Address)
            {
                return;
            }

            if (_serverChannel.ProcessPacket(packet))
            {
                message = new BitStream(packet); // reset the bitstream
                ProcessServerMessage(message);
            }
        }
예제 #5
0
        private static void ProcessReliableCommand(BitStream message)
        {
            uint   commandSequence = message.ReadUInt32();
            string command         = message.ReadString();

            if (commandSequence <= _lastExecutedReliable)
            {
                return;
            }

            string[] args = Command.Tokenize(command);

            switch (args[0])
            {
            case "print":
                if (args.Length < 2)
                {
                    break;
                }

                Log.Write(LogLevel.Info, "{0}", string.Join(" ", args, 1, args.Length - 1));
                break;

            case "disconnect":
                State = ClientState.Idle;
                Log.Write(LogLevel.Error, "Disconnected from server: {0}", (args.Length == 2) ? args[1] : "no message");
                break;
            }

            _lastExecutedReliable = commandSequence;
            _lastReliableMessage  = commandSequence;
        }
예제 #6
0
        private static void ProcessClientReliableCommand(ServerClient client, BitStream message)
        {
            uint   commandSequence = message.ReadUInt32();
            string command         = message.ReadString();

            if (commandSequence <= client.LastExecutedReliableCommand)
            {
                return;
            }

            string[] args = Command.Tokenize(command);

            switch (args[0])
            {
            case "say":
                if (args.Length < 2)
                {
                    break;
                }

                string msg = string.Format("{0}: {1}", client.Name, string.Join(" ", args, 1, args.Length - 1));
                Log.Write(LogLevel.Info, msg);
                SendReliableCommand(null, "print \"" + msg + "\"");
                break;

            case "disconnect":
                DropClient(client, "Disconnected from server");
                break;
            }

            client.LastReceivedReliableCommand = commandSequence;
            client.LastExecutedReliableCommand = commandSequence;
        }
예제 #7
0
        public static void ProcessPacket(NetAddress from, byte[] packet)
        {
            if (packet.Length < 4)
            {
                return;
            }

            var message     = new BitStream(packet);
            var sequenceNum = message.ReadUInt32();

            if (sequenceNum == 0xFFFFFFFF)
            {
                ProcessOutOfBand(from, packet);
                return;
            }

            for (int i = 0; i < _clients.Length; i++)
            {
                if (_clients[i] != null)
                {
                    if (_clients[i].Channel.Address == from)
                    {
                        if (_clients[i].Channel.ProcessPacket(packet))
                        {
                            ProcessClientMessage(_clients[i], message);
                        }
                    }
                }
            }
        }
예제 #8
0
        private static void ProcessClientMessage(ServerClient client, BitStream message)
        {
            client.LastMessageReceivedAt   = _serverTime;
            client.LastAcknowledgedMessage = message.ReadUInt32();
            client.ReliableAcknowledged    = message.ReadUInt32();

            // check if this command is from an older initialization state
            var stateID = message.ReadInt32();

            if (stateID != _stateID)
            {
                if (client.LastAcknowledgedMessage >= client.LastInitStateMessage)
                {
                    SendInitializationState(client);
                }

                return;
            }

            byte command = 0;

            try
            {
                do
                {
                    command = message.ReadByte();

                    switch (command)
                    {
                    case UserCommand.CommandType:
                        ProcessClientUserCommand(client, message);
                        break;

                    case 2:     // TODO: magic number fix
                        ProcessClientReliableCommand(client, message);
                        break;
                    }
                } while (command != 0xFF);
            }
            catch (Exception e)
            {
                Log.Write(LogLevel.Warning, "Error while processing client message: " + e.ToString());
                DropClient(client, "Error while processing client message.");
            }
        }
예제 #9
0
        public bool ProcessPacket(byte[] packet)
        {
            var message  = new BitStream(packet);
            var sequence = message.ReadUInt32();

            if (sequence < SequenceIn)
            {
                Log.Write(LogLevel.Debug, "out of order packet ({0}, {1})", sequence, SequenceIn);
                return(false);
            }

            if (sequence > (SequenceIn + 1))
            {
                Log.Write(LogLevel.Debug, "dropped packet ({0}, {1})", sequence, SequenceIn);
            }

            SequenceIn = sequence;

            return(true);
        }
예제 #10
0
        private static void ProcessServerMessage(BitStream message)
        {
            _lastMessageReceivedAt = _clientTime;
            _lastServerMessage     = message.ReadUInt32();

            byte command = 0;

#if !DEBUG
            try
            {
#endif
            do
            {
                command = message.ReadByte();

                switch (command)
                {
                case Server.SnapshotNumber:
                    ProcessSnapshot(message);
                    break;

                case Server.ReliableCommandNumber:
                    ProcessReliableCommand(message);
                    break;

                case Server.InitStateNumber:
                    ProcessInitializationState(message);
                    break;
                }
            } while (command != 0xFF);
#if !DEBUG
        }

        catch (Exception e)
        {
            Log.Write(LogLevel.Warning, "Error while processing client message: " + e.ToString());
            // TODO: disconnect client
        }
#endif
        }
예제 #11
0
        private static void ProcessSnapshot(BitStream message)
        {
            if (State == ClientState.Connected)
            {
                State = ClientState.Ingame;
            }

            var snapshot = new Snapshot();

            snapshot.Sequence   = _serverChannel.SequenceIn;
            snapshot.ServerTime = message.ReadUInt32();

            _serverTimeDelta = (int)((int)snapshot.ServerTime - (int)_clientTime);

            _reliableAcknowledged = message.ReadInt32();

            int entityNumber = message.ReadInt32(12);

            while (entityNumber != 4095)
            {
                var entityBase   = (_entityBases[entityNumber] != null) ? _entityBases[entityNumber] : null;
                var deltaMessage = new DeltaBitStream(entityBase, message);

                var spawnKey = deltaMessage.ReadInt32(20);
                var typeCode = deltaMessage.ReadInt32(4);

                snapshot.Entities[entityNumber] = Entity.Create(typeCode);
                snapshot.Entities[entityNumber].Deserialize(deltaMessage);

                _entityBases[entityNumber] = deltaMessage.NewBase;

                entityNumber = message.ReadInt32(12);
            }

            // push snapshot history array back by one
            for (int i = (_snapHistory.Length - 2); i >= 0; i--)
            {
                _snapHistory[i + 1] = _snapHistory[i];
            }

            // and set the first snapshot to the current one
            _snapHistory[0] = snapshot;

            // define current and previous snapshots
            int delayMsec = cl_snapDelay.GetValue <int>();
            int numSnaps  = 0;

            for (int i = 0; i < _snapHistory.Length; i++)
            {
                if (_snapHistory[i] != null)
                {
                    if (_snapHistory[i].ServerTime < (_snapHistory[0].ServerTime - delayMsec))
                    {
                        numSnaps = i;
                        break;
                    }
                }
            }

            int snapDelay = Math.Max(0, Math.Min(_snapHistory.Length - 2, numSnaps));

            _lastSnap = _snapHistory[snapDelay + 1];
            _curSnap  = _snapHistory[snapDelay];

            if (_curSnap == null)
            {
                _curSnap = _snapHistory[0];
            }

            _curSnap.ClientTime = _clientTime;
        }