Пример #1
0
        private void parseGameState(Q3HuffmanReader reader)
        {
            reader.readLong();

            while (true)
            {
                byte cmd = reader.readByte();
                if (cmd == Q3_SVC.EOF)
                {
                    break;
                }

                switch (cmd)
                {
                case Q3_SVC.CONFIGSTRING:
                    short key = reader.readShort();
                    if (key < 0 || key > Q3Const.MAX_CONFIGSTRINGS)
                    {
                        return;
                    }
                    clc.configs[key] = reader.readBigString();
                    break;

                case Q3_SVC.BASELINE:
                    long newnum = reader.readNumBits(Q3Const.GENTITYNUM_BITS);
                    if (newnum < 0 || newnum >= Q3Const.MAX_GENTITIES)
                    {
                        Q3Utils.PrintDebug(clc.errors, "Baseline number out of range: {0}", newnum);
                        return;
                    }

                    EntityState es = Ext2 <long, EntityState> .GetOrCreate(clc.entityBaselines, newnum);

                    if (!reader.readDeltaEntity(es, (int)newnum))
                    {
                        Q3Utils.PrintDebug(clc.errors, "unable to parse delta-entity state");
                        return;
                    }
                    break;

                default:
                    Q3Utils.PrintDebug(clc.errors, "bad command in parseGameState");
                    return;
                }
            }

            //clc.clientNum
            clc.clientNum = reader.readLong();

            //clc.checksumFeed
            clc.checksumFeed = reader.readLong();
        }
Пример #2
0
        private void parseServerCommand(Q3HuffmanReader reader)
        {
            var key   = reader.readLong();
            var value = reader.readString();

            clc.console[key] = value;
        }
Пример #3
0
        public bool parse(Q3DemoMessage message)
        {
            clc.serverMessageSequence = message.sequence;
            Q3HuffmanReader reader = new Q3HuffmanReader(message.data);

            reader.readLong();

            while (!reader.isEOD())
            {
                var b = reader.readByte();
                switch (b)
                {
                case Q3_SVC.BAD:
                case Q3_SVC.NOP:
                    return(true);

                case Q3_SVC.EOF:
                    return(true);

                case Q3_SVC.SERVERCOMMAND:
                    this.parseServerCommand(reader);
                    break;

                case Q3_SVC.GAMESTATE:
                    this.parseGameState(reader);
                    break;

                case Q3_SVC.SNAPSHOT:
                    this.parseSnapshot(reader);
                    // snapshots couldn't be mixed with game-state command in a single message
                    break;

                default:
                    // unknown command / corrupted stream
                    return(true);
                }
            }
            return(true);
        }
Пример #4
0
        private void parseSnapshot(Q3HuffmanReader decoder)
        {
            if (client.clientConfig == null)
            {
                client.clientConfig = new Dictionary <string, string>();

                if (clc.configs.ContainsKey(Q3Const.Q3_DEMO_CFG_FIELD_GAME))
                {
                    var gameConfig = Q3Utils.split_config(clc.configs[Q3Const.Q3_DEMO_CFG_FIELD_GAME]);
                    client.isCheatsOn = Ext.GetOrZero(gameConfig, "sv_cheats") > 0;
                }
                if (clc.configs.ContainsKey(Q3Const.Q3_DEMO_CFG_FIELD_CLIENT))
                {
                    client.clientConfig    = Q3Utils.split_config(clc.configs[Q3Const.Q3_DEMO_CFG_FIELD_CLIENT]);
                    client.dfvers          = Ext.GetOrZero(client.clientConfig, "defrag_vers");
                    client.mapname         = Ext.GetOrNull(client.clientConfig, "mapname");
                    client.mapNameChecksum = getMapNameChecksum(client.mapname);
                    client.isOnline        = Ext.GetOrZero(client.clientConfig, "defrag_gametype") > 4;
                }
            }

            CLSnapshot newSnap = new CLSnapshot();
            CLSnapshot old     = null;

            newSnap.serverCommandNum = clc.serverCommandSequence;
            newSnap.serverTime       = decoder.readLong();
            newSnap.messageNum       = clc.serverMessageSequence;

            int deltaNum = decoder.readByte();

            if (deltaNum == 0)
            {
                newSnap.deltaNum = -1;
            }
            else
            {
                newSnap.deltaNum = newSnap.messageNum - deltaNum;
            }
            newSnap.snapFlags = decoder.readByte();
            // If the frame is delta compressed from data that we
            // no longer have available, we must suck up the rest of
            // the frame, but not use it, then ask for a non-compressed
            // message
            if (newSnap.deltaNum <= 0)
            {
                newSnap.valid   = true;        // uncompressed frame
                old             = null;
                clc.demowaiting = false;       // we can start recording now
            }
            else
            {
                old = Ext2 <int, CLSnapshot> .GetOrCreate(client.snapshots, newSnap.deltaNum& Q3Const.PACKET_MASK);

                if (old == null || !old.valid)
                {
                    // should never happen
                    Q3Utils.PrintDebug(clc.errors, "Delta from invalid frame (not supposed to happen!)");
                }
                else if (old.messageNum != newSnap.deltaNum)
                {
                    // The frame that the server did the delta from
                    // is too old, so we can't reconstruct it properly.
                    Q3Utils.PrintDebug(clc.errors, "Delta frame too old.");
                }
                else if ((client.parseEntitiesNum - old.parseEntitiesNum) > (Q3Const.MAX_PARSE_ENTITIES - 128))
                {
                    Q3Utils.PrintDebug(clc.errors, "Delta parseEntitiesNum too old");
                }
                else
                {
                    newSnap.valid = true;  // valid delta parse
                }
            }

            int len = decoder.readByte();

            if (len > newSnap.areamask.Length)
            {
                Q3Utils.PrintDebug(clc.errors, "CL_ParseSnapshot: Invalid size {0} for areamask", len);
                return;
            }
            decoder.readData(newSnap.areamask, len);
            if (old != null)
            {
                newSnap.ps.copy(old.ps);
            }
            decoder.readDeltaPlayerState(newSnap.ps);
            parsePacketEntities(decoder, old, newSnap);

            // if not valid, dump the entire thing now that it has
            // been properly read
            if (!newSnap.valid)
            {
                return;
            }

            // clear the valid flags of any snapshots between the last
            // received and this one, so if there was a dropped packet
            // it won't look like something valid to delta from next
            // time we wrap around in the buffer
            int oldMessageNum = client.snap.messageNum + 1;

            if (newSnap.messageNum - oldMessageNum >= Q3Const.PACKET_BACKUP)
            {
                oldMessageNum = newSnap.messageNum - (Q3Const.PACKET_BACKUP - 1);
            }
            for (; oldMessageNum < newSnap.messageNum; oldMessageNum++)
            {
                CLSnapshot s;
                if (client.snapshots.TryGetValue(oldMessageNum & Q3Const.PACKET_MASK, out s))
                {
                    if (s != null)
                    {
                        s.valid = false;
                    }
                }
            }

            // copy to the current good spot
            client.snap = newSnap;

            // skip ping calculations
            client.snap.ping = 0;

            // save the frame off in the backup array for later delta comparisons
            client.snapshots[client.snap.messageNum & Q3Const.PACKET_MASK] = client.snap;

            client.newSnapshots = true;

            updateClientEvents(newSnap);
        }
Пример #5
0
        public static void updatePlayerState(PlayerState state, int number, Q3HuffmanReader reader, bool reset)
        {
            switch (number)
            {
            case 0: state.commandTime = reset ? 0 : reader.readLong();            break;

            case 1: state.origin[0] = reset ? 0 : reader.readFloatIntegral();   break;

            case 2: state.origin[1] = reset ? 0 : reader.readFloatIntegral();   break;

            case 3: state.bobCycle = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 4: state.velocity[0] = reset ? 0 : reader.readFloatIntegral();   break;

            case 5: state.velocity[1] = reset ? 0 : reader.readFloatIntegral();   break;

            case 6: state.viewangles[1] = reset ? 0 : reader.readFloatIntegral();   break;

            case 7: state.viewangles[0] = reset ? 0 : reader.readFloatIntegral();   break;

            case 8: state.weaponTime = reset ? 0 : (int)reader.readNumBits(-16); break;

            case 9: state.origin[2] = reset ? 0 : reader.readFloatIntegral();   break;

            case 10: state.velocity[2] = reset ? 0 : reader.readFloatIntegral();   break;

            case 11: state.legsTimer = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 12: state.pm_time = reset ? 0 : (int)reader.readNumBits(-16); break;

            case 13: state.eventSequence = reset ? 0 : (int)reader.readNumBits(16);  break;

            case 14: state.torsoAnim = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 15: state.movementDir = reset ? 0 : (int)reader.readNumBits(4);   break;

            case 16: state.events[0] = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 17: state.legsAnim = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 18: state.events[1] = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 19: state.pm_flags = reset ? 0 : (int)reader.readNumBits(16);  break;

            case 20: state.groundEntityNum = reset ? 0 : (int)reader.readNumBits(10);  break;

            case 21: state.weaponstate = reset ? 0 : (int)reader.readNumBits(4);   break;

            case 22: state.eFlags = reset ? 0 : (int)reader.readNumBits(16);  break;

            case 23: state.externalEvent = reset ? 0 : (int)reader.readNumBits(10);  break;

            case 24: state.gravity = reset ? 0 : (int)reader.readNumBits(16);  break;

            case 25: state.speed = reset ? 0 : (int)reader.readNumBits(16);  break;

            case 26: state.delta_angles[1] = reset ? 0 : (int)reader.readNumBits(16);  break;

            case 27: state.externalEventParm = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 28: state.viewheight = reset ? 0 : (int)reader.readNumBits(-8);  break;

            case 29: state.damageEvent = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 30: state.damageYaw = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 31: state.damagePitch = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 32: state.damageCount = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 33: state.generic1 = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 34: state.pm_type = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 35: state.delta_angles[0] = reset ? 0 : (int)reader.readNumBits(16);  break;

            case 36: state.delta_angles[2] = reset ? 0 : (int)reader.readNumBits(16);  break;

            case 37: state.torsoTimer = reset ? 0 : (int)reader.readNumBits(12);  break;

            case 38: state.eventParms[0] = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 39: state.eventParms[1] = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 40: state.clientNum = reset ? 0 : (int)reader.readNumBits(8);   break;

            case 41: state.weapon = reset ? 0 : (int)reader.readNumBits(5);   break;

            case 42: state.viewangles[2] = reset ? 0 : reader.readFloatIntegral();   break;

            case 43: state.grapplePoint[0] = reset ? 0 : reader.readFloatIntegral();   break;

            case 44: state.grapplePoint[1] = reset ? 0 : reader.readFloatIntegral();   break;

            case 45: state.grapplePoint[2] = reset ? 0 : reader.readFloatIntegral();   break;

            case 46: state.jumppad_ent = reset ? 0 : (int)reader.readNumBits(10);  break;

            case 47: state.loopSound = reset ? 0 : (int)reader.readNumBits(16);  break;
            }
        }
Пример #6
0
        public static void updateEntityState(EntityState state, int number, Q3HuffmanReader reader, bool reset)
        {
            switch (number)
            {
            case 0:  state.pos.trTime = reset ? 0 : reader.readLong();           break;

            case 1:  state.pos.trBase[0] = reset ? 0 : reader.readFloatIntegral();  break;

            case 2:  state.pos.trBase[1] = reset ? 0 : reader.readFloatIntegral();  break;

            case 3:  state.pos.trDelta[0] = reset ? 0 : reader.readFloatIntegral();  break;

            case 4:  state.pos.trDelta[1] = reset ? 0 : reader.readFloatIntegral();  break;

            case 5:  state.pos.trBase[2] = reset ? 0 : reader.readFloatIntegral();  break;

            case 6:  state.apos.trBase[1] = reset ? 0 : reader.readFloatIntegral();  break;

            case 7:  state.pos.trDelta[2] = reset ? 0 : reader.readFloatIntegral();  break;

            case 8:  state.apos.trBase[0] = reset ? 0 : reader.readFloatIntegral();  break;

            case 9:  state.events = reset ? 0 : (int)reader.readNumBits(10); break;

            case 10: state.angles2[1] = reset ? 0 : reader.readFloatIntegral();  break;

            case 11: state.eType = reset ? 0 : (int)reader.readNumBits(8);  break;

            case 12: state.torsoAnim = reset ? 0 : (int)reader.readNumBits(8);  break;

            case 13: state.eventParm = reset ? 0 : (int)reader.readNumBits(8);  break;

            case 14: state.legsAnim = reset ? 0 : (int)reader.readNumBits(8);  break;

            case 15: state.groundEntityNum = reset ? 0 : (int)reader.readNumBits(10); break;

            case 16: state.pos.trType = reset ? 0 : (TrType)reader.readByte();  break;

            case 17: state.eFlags = reset ? 0 : (int)reader.readNumBits(19); break;

            case 18: state.otherEntityNum = reset ? 0 : (int)reader.readNumBits(10); break;

            case 19: state.weapon = reset ? 0 : (int)reader.readNumBits(8);  break;

            case 20: state.clientNum = reset ? 0 : (int)reader.readNumBits(8);  break;

            case 21: state.angles[1] = reset ? 0 : reader.readFloatIntegral();  break;

            case 22: state.pos.trDuration = reset ? 0 : reader.readLong();           break;

            case 23: state.apos.trType = reset ? 0 : (TrType)reader.readByte();   break;

            case 24: state.origin[0] = reset ? 0 : reader.readFloatIntegral();  break;

            case 25: state.origin[1] = reset ? 0 : reader.readFloatIntegral();  break;

            case 26: state.origin[2] = reset ? 0 : reader.readFloatIntegral();  break;

            case 27: state.solid = reset ? 0 : (int)reader.readNumBits(24); break;

            case 28: state.powerups = reset ? 0 : (int)reader.readNumBits(16); break;

            case 29: state.modelindex = reset ? 0 : (int)reader.readNumBits(8);  break;

            case 30: state.otherEntityNum2 = reset ? 0 : (int)reader.readNumBits(10); break;

            case 31: state.loopSound = reset ? 0 : (int)reader.readNumBits(8);  break;

            case 32: state.generic1 = reset ? 0 : (int)reader.readNumBits(8);  break;

            case 33: state.origin2[2] = reset ? 0 : reader.readFloatIntegral();  break;

            case 34: state.origin2[0] = reset ? 0 : reader.readFloatIntegral();  break;

            case 35: state.origin2[1] = reset ? 0 : reader.readFloatIntegral();  break;

            case 36: state.modelindex2 = reset ? 0 : (int)reader.readNumBits(8);  break;

            case 37: state.angles[0] = reset ? 0 : reader.readFloatIntegral();  break;

            case 38: state.time = reset ? 0 : reader.readLong();           break;

            case 39: state.apos.trTime = reset ? 0 : reader.readLong();           break;

            case 40: state.apos.trDuration = reset ? 0 : reader.readLong();           break;

            case 41: state.apos.trBase[2] = reset ? 0 : reader.readFloatIntegral();  break;

            case 42: state.apos.trDelta[0] = reset ? 0 : reader.readFloatIntegral();  break;

            case 43: state.apos.trDelta[1] = reset ? 0 : reader.readFloatIntegral();  break;

            case 44: state.apos.trDelta[2] = reset ? 0 : reader.readFloatIntegral();  break;

            case 45: state.time2 = reset ? 0 : reader.readLong();           break;

            case 46: state.angles[2] = reset ? 0 : reader.readFloatIntegral();  break;

            case 47: state.angles2[0] = reset ? 0 : reader.readFloatIntegral();  break;

            case 48: state.angles2[2] = reset ? 0 : reader.readFloatIntegral();  break;

            case 49: state.constantLight = reset ? 0 : reader.readLong();           break;

            case 50: state.frame = reset ? 0 : (int)reader.readNumBits(16); break;
            }
        }