示例#1
0
        private void CL_DeltaEntity(Q3HuffmanReader decoder, CLSnapshot frame, int newnum, EntityState old, bool unchanged)
        {
            EntityState state;

            // save the parsed entity state into the big circular buffer so
            // it can be used as the source for a later delta

            state = Ext2 <int, EntityState> .GetOrCreate(client.parseEntities,
                                                         client.parseEntitiesNum& (Q3Const.MAX_PARSE_ENTITIES - 1));

            if (unchanged)
            {
                state.copy(old);
            }
            else
            {
                decoder.readDeltaEntity(state, newnum);
            }

            if (state.number == (Q3Const.MAX_GENTITIES - 1))
            {
                return;         // entity was delta removed
            }
            client.parseEntitiesNum++;
            frame.numEntities++;
        }
示例#2
0
        private void updateClientEvents(CLSnapshot snapshot)
        {
            if (client.dfvers <= 0 || client.mapname.Length <= 0)
            {
                return;
            }
            var time   = getTime(snapshot.ps, (int)snapshot.serverTime, client.dfvers, client.mapNameChecksum);
            var events = client.clientEvents;

            ClientEvent clientEvent = new ClientEvent(time, snapshot);

            var prevStat = 0;
            var newStat  = snapshot.ps.stats[12];

            if (events.Count == 0)
            {
                clientEvent.eventStartFile = true;
                if (snapshot.ps.pm_type == (int)ClientEvent.PlayerMode.PM_NORMAL)
                {
                    if ((prevStat & 4) != (newStat & 4) && (prevStat & 2) == 0)
                    {
                        clientEvent.eventStartTime = true;
                    }
                }
            }
            else
            {
                var prevEvent = events[events.Count - 1];
                if (prevEvent.playerNum != snapshot.ps.clientNum)
                {
                    clientEvent.eventChangeUser = true;
                }
                if (prevEvent.playerMode != snapshot.ps.pm_type)
                {
                    clientEvent.eventChangePmType = true;
                }
                prevStat = prevEvent.userStat;
                if (prevStat != newStat)
                {
                    if ((prevStat & 4) != (newStat & 4))
                    {
                        if (snapshot.ps.pm_type == (int)ClientEvent.PlayerMode.PM_NORMAL)
                        {
                            if ((prevStat & 2) == 0)
                            {
                                clientEvent.eventStartTime = true;
                            }
                            else
                            {
                                clientEvent.eventTimeReset = true;
                            }
                        }
                    }
                    else if ((prevStat & 8) == 0 && (newStat & 8) != 0)
                    {
                        if (!clientEvent.eventChangeUser)
                        {
                            clientEvent.eventFinish = true;
                        }
                    }
                    else if ((prevStat & 16) != (newStat & 16))
                    {
                        if (snapshot.ps.pm_type == (int)ClientEvent.PlayerMode.PM_NORMAL)
                        {
                            clientEvent.eventCheckPoint = true;
                        }
                    }
                    else if (prevEvent.eventFinish && (prevStat & 2) != 0 && (newStat & 2) == 0)
                    {
                        //fix double finish
                        if (!clientEvent.eventChangeUser)
                        {
                            prevEvent.eventFinish = false;
                            if (!prevEvent.hasAnyEvent)
                            {
                                events.RemoveAt(events.Count - 1);
                            }
                            clientEvent.eventFinish = true;
                        }
                    }
                    else if (prevEvent.eventStartTime && (prevStat & 2) == 0 && (newStat & 2) != 0)
                    {
                        //fix double start timer
                        if (snapshot.ps.pm_type == (int)ClientEvent.PlayerMode.PM_NORMAL)
                        {
                            prevEvent.eventStartTime = false;
                            if (!prevEvent.hasAnyEvent)
                            {
                                events.RemoveAt(events.Count - 1);
                            }
                            clientEvent.eventStartTime = true;
                        }
                    }
                    else if (prevEvent.eventTimeReset && (prevStat & 4) == 0 && (newStat & 2) != 0)
                    {
                        //fix double tr
                        if (snapshot.ps.pm_type == (int)ClientEvent.PlayerMode.PM_NORMAL)
                        {
                            prevEvent.eventTimeReset = false;
                            if (!prevEvent.hasAnyEvent)
                            {
                                events.RemoveAt(events.Count - 1);
                            }
                            clientEvent.eventTimeReset = true;
                        }
                    }
                    else
                    {
                        clientEvent.eventSomeTrigger = true;
                    }
                }
            }

            if (clientEvent.hasAnyEvent)
            {
                events.Add(clientEvent);
            }
        }
示例#3
0
        private void parsePacketEntities(Q3HuffmanReader decoder, CLSnapshot oldframe, CLSnapshot newframe)
        {
            newframe.parseEntitiesNum = client.parseEntitiesNum;
            newframe.numEntities      = 0;
            int         newnum   = 0;
            int         oldindex = 0;
            int         oldnum   = 0;
            EntityState oldstate = null;

            if (oldframe == null)
            {
                oldnum = 99999;
            }
            else
            {
                if (oldindex >= oldframe.numEntities)
                {
                    oldnum = 99999;
                }
                else
                {
                    oldstate = Ext2 <int, EntityState> .GetOrCreate(client.parseEntities, (oldframe.parseEntitiesNum + oldindex)& (Q3Const.MAX_PARSE_ENTITIES - 1));

                    oldnum = oldstate.number;
                }
            }

            while (true)
            {
                newnum = (int)decoder.readNumBits(Q3Const.GENTITYNUM_BITS);

                if (newnum == (Q3Const.MAX_GENTITIES - 1))
                {
                    break;
                }

                if (decoder.isEOD())
                {
                    Q3Utils.PrintDebug(clc.errors, "ERR_DROP, CL_ParsePacketEntities: end of message");
                    return;
                }

                while (oldnum < newnum)
                {
                    // one or more entities from the old packet are unchanged
                    CL_DeltaEntity(decoder, newframe, oldnum, oldstate, true);

                    oldindex++;

                    if (oldindex >= oldframe.numEntities)
                    {
                        oldnum = 99999;
                    }
                    else
                    {
                        oldstate = Ext2 <int, EntityState> .GetOrCreate(client.parseEntities,
                                                                        (oldframe.parseEntitiesNum + oldindex)& (Q3Const.MAX_PARSE_ENTITIES - 1));

                        oldnum = oldstate.number;
                    }
                }

                if (oldnum == newnum)
                {
                    // delta from previous state
                    CL_DeltaEntity(decoder, newframe, newnum, oldstate, false);

                    oldindex++;

                    if (oldindex >= oldframe.numEntities)
                    {
                        oldnum = 99999;
                    }
                    else
                    {
                        oldstate = Ext2 <int, EntityState> .GetOrCreate(client.parseEntities,
                                                                        (oldframe.parseEntitiesNum + oldindex)& (Q3Const.MAX_PARSE_ENTITIES - 1));

                        oldnum = oldstate.number;
                    }
                    continue;
                }

                if (oldnum > newnum)
                {
                    // delta from baseline
                    EntityState es = Ext2 <int, EntityState> .GetOrCreate(client.entityBaselines, newnum);

                    CL_DeltaEntity(decoder, newframe, newnum, es, false);
                    continue;
                }
            }

            // any remaining entities in the old frame are copied over
            while (oldnum != 99999)
            {
                // one or more entities from the old packet are unchanged
                CL_DeltaEntity(decoder, newframe, oldnum, oldstate, true);

                oldindex++;

                if (oldindex >= oldframe.numEntities)
                {
                    oldnum = 99999;
                }
                else
                {
                    oldstate = Ext2 <int, EntityState> .GetOrCreate(client.parseEntities,
                                                                    (oldframe.parseEntitiesNum + oldindex)& (Q3Const.MAX_PARSE_ENTITIES - 1));

                    oldnum = oldstate.number;
                }
            }
        }
示例#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);
        }