예제 #1
0
        protected override void Parse(ref BitStreamReader bsr)
        {
            PacketInfo = new CmdInfo[DemoInfo.MaxSplitscreenPlayers];
            for (int i = 0; i < PacketInfo.Length; i++)
            {
                PacketInfo[i] = new CmdInfo(DemoRef);
                PacketInfo[i].ParseStream(ref bsr);
            }
            InSequence    = bsr.ReadUInt();
            OutSequence   = bsr.ReadUInt();
            MessageStream = new MessageStream(DemoRef);
            MessageStream.ParseStream(ref bsr);

            // After we're doing with the packet, we can process all the messages.
            // Most things should be processed during parsing, but any additional checks should be done here.

            var netTickMessages = MessageStream.Where(tuple => tuple.messageType == MessageType.NetTick).ToList();

            if (netTickMessages.Count > 1)
            {
                DemoRef.LogError("there's more than 2 net tick messages in this packet");
            }
            NetTick?tickInfo = (NetTick?)netTickMessages.FirstOrDefault().message;

            if (tickInfo != null)
            {
                if (DemoRef.EntitySnapshot != null)
                {
                    DemoRef.EntitySnapshot.EngineTick = tickInfo.EngineTick;
                }
            }
            // todo fill prop handles with data here
            TimingAdjustment.AdjustFromPacket(this);
        }
예제 #2
0
        protected override void Parse(ref BitStreamReader bsr)
        {
            ClassCount     = bsr.ReadUShort();
            CreateOnClient = bsr.ReadBool();
            if (!CreateOnClient)
            {
                // if this ever gets used then it should update the mutable tables
                string s = $"I haven't implemented {GetType().Name} to update the C_string tables.";
                DemoRef.LogError(s);
                Debug.WriteLine(s);

                ServerClasses = new ServerClass[ClassCount];
                for (int i = 0; i < ServerClasses.Length; i++)
                {
                    ServerClasses[i] = new ServerClass(DemoRef, this);
                    ServerClasses[i].ParseStream(ref bsr);
                    // this is an assumption I make in the structure of all the entity stuff, very critical
                    if (i != ServerClasses[i].DataTableId)
                    {
                        throw new ConstraintException("server class ID does not match it's index in the list");
                    }
                }
            }

            DemoRef.EntBaseLines ??= new EntityBaseLines(DemoRef, ClassCount);
        }
        // I don't think I've seen this in demos yet, I'll just log it for now and deal with it later
        protected override void Parse(ref BitStreamReader bsr)
        {
            NeedsDecoder = bsr.ReadBool();
            ushort len = bsr.ReadUShort();

            _props = bsr.Split(len);
            DemoRef.LogError($"unprocessed {GetType().Name} message");             // todo se2007/engine/dt_send_eng.cpp line 800
        }
        protected override void Parse(ref BitStreamReader bsr)
        {
            StringTablesManager manager = DemoRef.StringTablesManager;

            if (!manager.TableReadable.GetValueOrDefault(_tableName))
            {
                DemoRef.LogError($"{_tableName} table is marked as non-readable, can't update :/");
                _exceptionWhileParsing = true;
                bsr.SkipToEnd();
                return;
            }

            if (manager.CreationLookup.Single(table => table.TableName == _tableName).Flags == StringTableFlags.Fake)
            {
                DemoRef.LogError($"{_tableName} table was created manually - not parsed in SvcServerInfo");
                _exceptionWhileParsing = true;
                bsr.SkipToEnd();
                return;
            }

            try {             // se2007/engine/networkstringtable.cpp  line 595
                MutableStringTable tableToUpdate = manager.Tables[_tableName];

                int?decompressedIndex = null;
                if (tableToUpdate.Flags.HasValue && (tableToUpdate.Flags & StringTableFlags.DataCompressed) != 0 && _canCompress)
                {
                    // decompress the data - engine/baseclientstate.cpp (hl2_src) line 1364
                    int    uncompressedSize = bsr.ReadSInt();
                    int    compressedSize   = bsr.ReadSInt();
                    byte[] data             = Compression.Decompress(ref bsr, compressedSize - 8); // -8 to ignore header
                    decompressedIndex = DemoRef.DecompressedLookup.Count;
                    DemoRef.DecompressedLookup.Add(data);                                          // so that we can access the reader for the entries later
                    if (data.Length != uncompressedSize)
                    {
                        throw new Exception("could not decompress data in string table update");
                    }
                    bsr = new BitStreamReader(data);
                }

                int entryIndex = -1;
                var history    = new C5.CircularQueue <string>(32);

                for (int i = 0; i < _numUpdatedEntries; i++)
                {
                    entryIndex++;
                    if (!bsr.ReadBool())
                    {
                        entryIndex = (int)bsr.ReadUInt(BitUtils.HighestBitIndex(tableToUpdate.MaxEntries));
                    }

                    string?entryName = null;
                    if (bsr.ReadBool())
                    {
                        if (bsr.ReadBool())                           // the first part of the string may be the same as for other entries
                        {
                            int index     = (int)bsr.ReadUInt(5);
                            int subStrLen = (int)bsr.ReadUInt(SubStringBits);
                            entryName  = history[index][..subStrLen];
 protected override void Parse(ref BitStreamReader bsr)
 {
     Count = bsr.ReadByte();
     if (Count != 1)
     {
         DemoRef.LogError($"{GetType()} is borking, there should only be one string but count is {Count}");
     }
     KeyString = bsr.ReadNullTerminatedString();
 }
예제 #6
0
        /* Okay, this is pretty wacky. First I read a byte, and based off of that I try to determine the type of
         * user message. If I don't have a lookup list for whatever game this is or the type seems bogus, I log an
         * error. Otherwise, create the message instance, and if it's not empty, try to parse it. If parsing fails,
         * log an error. Finally, if not all bits of the message are parsed, then it's likely that I did something
         * wrong, (since it seems like the user messages use up all the bits in the message) so log an error.
         */
        protected override void Parse(ref BitStreamReader bsr)
        {
            byte typeVal = bsr.ReadByte();

            MessageType = UserMessage.ByteToUserMessageType(DemoInfo, typeVal);
            uint   messageLength = bsr.ReadUInt(DemoInfo.UserMessageLengthBits);
            string?errorStr      = null;

            var uMessageReader = bsr.SplitAndSkip(messageLength);

            switch (MessageType)
            {
            case UserMessageType.Unknown:
                errorStr = $"There is no SvcUserMessage list for this game, type {typeVal} was found";
                break;

            case UserMessageType.Invalid:
                errorStr = $"SvcUserMessage with value {typeVal} is invalid";
                break;

            default:
                UserMessage = SvcUserMessageFactory.CreateUserMessage(DemoRef, MessageType) !;
                if (UserMessage == null)
                {
                    errorStr       = $"Unimplemented SvcUserMessage: {MessageType}";
                    _unimplemented = true;
                }
                else
                {
                    try {                             // empty messages might still have 1-2 bytes, might need to do something 'bout that
                        if (UserMessage.ParseStream(uMessageReader) != 0)
                        {
                            errorStr = $"{GetType().Name} - {MessageType} ({typeVal}) didn't parse all bits";
                        }
                    } catch (Exception e) {
                        errorStr = $"{GetType().Name} - {MessageType} ({typeVal}) " +
                                   $"threw exception during parsing, message: {e.Message}";
                    }
                }
                break;
            }

            #region error logging

            // if parsing fails, just convert to an unknown type - the byte array that it will print is still useful
            if (errorStr != null)
            {
                int rem = uMessageReader.BitsRemaining;
                DemoRef.LogError($"{errorStr}, ({rem} bit{(rem == 1 ? "" : "s")}) - " +
                                 $"{uMessageReader.FromBeginning().ToHexString()}");
                UserMessage = new UnknownUserMessage(DemoRef);
                UserMessage.ParseStream(uMessageReader);
            }

            #endregion
        }
        protected override void Parse(ref BitStreamReader bsr)
        {
            DataType = (CustomDataType)bsr.ReadSInt();
            uint size = bsr.ReadUInt();

            DataMessage = CustomDataFactory.CreateCustomDataMessage(DemoRef, DataType);
            try {
                DataMessage.ParseStream(bsr.SplitAndSkip(size * 8));
            } catch (Exception e) {
                DemoRef.LogError($"error while parsing custom data of type: {DataType}... {e.Message}");
                DataMessage = new UnknownCustomDataMessage(DemoRef);
            }
        }
        protected override void Parse(ref BitStreamReader bsr)
        {
            int byteSize        = (int)bsr.ReadUInt();
            int indexBeforeData = bsr.CurrentBitIndex;

            try {
                Tables = new List <SendTable>();
                while (bsr.ReadBool())
                {
                    var table = new SendTable(DemoRef);
                    Tables.Add(table);
                    table.ParseStream(ref bsr);
                }

                ushort classCount = bsr.ReadUShort();
                ServerClasses = new List <ServerClass>(classCount);
                for (int i = 0; i < classCount; i++)
                {
                    var @class = new ServerClass(DemoRef, null);
                    ServerClasses.Add(@class);
                    @class.ParseStream(ref bsr);
                    // I assume in many places that the ID of the table matches its index
                    if (i != ServerClasses[i].DataTableId)
                    {
                        throw new ConstraintException("server class ID does not match its index in the list");
                    }
                }

                // in case SvcServerInfo parsing fails
                DemoRef.EntBaseLines ??= new EntityBaseLines(DemoRef, ServerClasses.Count);

                // re-init the baselines if the count doesn't match (maybe I should just init them from here?)
                if (DemoRef.EntBaseLines !.Baselines.Length != classCount)
                {
                    DemoRef.EntBaseLines.ClearBaseLineState(classCount);
                }

                // create the prop list for each class
                DemoRef.DataTableParser = new DataTableParser(DemoRef, this);
                DemoRef.DataTableParser.FlattenClasses(true);
            } catch (Exception e) {
                DemoRef.LogError($"exception while parsing datatables\n\texception: {e.Message}");
                Debug.WriteLine(e);
            }

            bsr.CurrentBitIndex = indexBeforeData + (byteSize << 3);
        }
예제 #9
0
        protected override void Parse(ref BitStreamReader bsr)
        {
            Reliable = bsr.ReadBool();
            int soundCount = Reliable ? 1 : bsr.ReadByte();
            int dataBitLen = (int)bsr.ReadUInt(Reliable ? 8 : 16);

            BitStreamReader soundBsr = bsr.SplitAndSkip(dataBitLen);

            SoundInfo sound = new SoundInfo(DemoRef);
            SoundInfo delta = new SoundInfo(DemoRef);

            delta.SetDefault();

            Exception?e = null;

            try {
                Sounds = new SoundInfo[soundCount];
                for (int i = 0; i < soundCount; i++)
                {
                    sound.ParseDelta(ref soundBsr, delta);
                    delta = sound;
                    if (Reliable)                       // client is incrementing the reliable sequence numbers itself
                    {
                        DemoRef.ClientSoundSequence = ++DemoRef.ClientSoundSequence & SndSeqNumMask;
                        if (sound.SequenceNumber != 0)
                        {
                            throw new ArgumentException($"expected sequence number 0, got: {sound.SequenceNumber}");
                        }
                        sound.SequenceNumber = DemoRef.ClientSoundSequence;
                    }
                    Sounds[i] = new SoundInfo(sound);
                }
            } catch (Exception exp) {
                e = exp;
            }
            if (e != null)
            {
                Sounds = null;
                DemoRef.LogError($"exception while parsing {nameof(SoundInfo)}: {e.Message}");
            }
            else if (soundBsr.BitsRemaining != 0)
            {
                Sounds = null;
                DemoRef.LogError($"exception while parsing {nameof(SoundInfo)}: {soundBsr.BitsRemaining} bits left to read");
            }
        }
        protected override void Parse(ref BitStreamReader bsr)
        {
            var soundIndexBits = DemoInfo.IsLeft4Dead2() ? DemoInfo.Game >= SourceGame.L4D2_2091 ? 15 : 14 : 13;

            SoundIndex = (int)bsr.ReadUInt(soundIndexBits);

            var mgr = DemoRef.StringTablesManager;

            if (mgr.TableReadable.GetValueOrDefault(TableNames.SoundPreCache))
            {
                if (SoundIndex >= mgr.Tables[TableNames.SoundPreCache].Entries.Count)
                {
                    DemoRef.LogError($"{GetType().Name} - sound index out of range: {SoundIndex}");
                }
                else if (SoundIndex != 0)
                {
                    SoundName = mgr.Tables[TableNames.SoundPreCache].Entries[SoundIndex].EntryName;
                }
            }
        }
예제 #11
0
        protected override void Parse(ref BitStreamReader bsr)
        {
            EntityIndex = bsr.ReadBool() ? bsr.ReadUInt(bsr.ReadBool() ? 5 : DemoInfo.MaxEdictBits) : _deltaTmp.EntityIndex;

#pragma warning disable 8629
            if (DemoInfo.NewDemoProtocol)
            {
                Flags = (SoundFlags?)bsr.ReadUIntIfExists(DemoInfo.SoundFlagBitsEncode) ?? _deltaTmp.Flags;
                if ((Flags & SoundFlags.IsScriptHandle) != 0)
                {
                    ScriptHash = bsr.ReadUInt();
                }
                else
                {
                    SoundNum = (int?)bsr.ReadUIntIfExists(DemoInfo.MaxSndIndexBits) ?? _deltaTmp.SoundNum;
                }
            }
            else
            {
                SoundNum = (int?)bsr.ReadUIntIfExists(DemoInfo.MaxSndIndexBits) ?? _deltaTmp.SoundNum;
                Flags    = (SoundFlags?)bsr.ReadUIntIfExists(DemoInfo.SoundFlagBitsEncode) ?? _deltaTmp.Flags;
            }
            Chan = (Channel?)bsr.ReadUIntIfExists(3) ?? _deltaTmp.Chan;
#pragma warning restore 8629

            #region get sound name

            if (SoundNum.HasValue)
            {
                var mgr = DemoRef.StringTablesManager;

                if (mgr.TableReadable.GetValueOrDefault(TableNames.SoundPreCache))
                {
                    _soundTableReadable = true;
                    if (SoundNum >= mgr.Tables[TableNames.SoundPreCache].Entries.Count)
                    {
                        DemoRef.LogError($"{GetType().Name} - sound index out of range: {SoundNum}");
                    }
                    else if (SoundNum != 0)
                    {
                        SoundName = mgr.Tables[TableNames.SoundPreCache].Entries[SoundNum.Value].EntryName;
                    }
                }
            }

            #endregion

            IsAmbient  = bsr.ReadBool();
            IsSentence = bsr.ReadBool();

            if (Flags != SoundFlags.Stop)
            {
                if (bsr.ReadBool())
                {
                    SequenceNumber = _deltaTmp.SequenceNumber;
                }
                else if (bsr.ReadBool())
                {
                    SequenceNumber = _deltaTmp.SequenceNumber + 1;
                }
                else
                {
                    SequenceNumber = bsr.ReadUInt(SndSeqNumberBits);
                }

                Volume     = bsr.ReadUIntIfExists(7) / 127.0f ?? _deltaTmp.Volume;
                SoundLevel = bsr.ReadUIntIfExists(MaxSndLvlBits) ?? _deltaTmp.SoundLevel;
                Pitch      = bsr.ReadUIntIfExists(8) ?? _deltaTmp.Pitch;
                if (!DemoInfo.NewDemoProtocol && DemoRef.Header.NetworkProtocol > 21)
                {
                    SpecialDspCount = bsr.ReadByteIfExists() ?? _deltaTmp.SpecialDspCount;
                }

                if (DemoInfo.NewDemoProtocol)
                {
                    RandomSeed = bsr.ReadSIntIfExists(6) ?? _deltaTmp.RandomSeed;                     // 6, 18, or 29
                    Delay      = bsr.ReadFloatIfExists() ?? _deltaTmp.Delay;
                }
                else
                {
                    if (bsr.ReadBool())
                    {
                        Delay = bsr.ReadSInt(MaxSndDelayMSecEncodeBits) / 1000.0f;
                        if (Delay < 0)
                        {
                            Delay *= 10.0f;
                        }
                        Delay -= SndDelayOffset;
                    }
                    else
                    {
                        Delay = _deltaTmp.Delay;
                    }
                }

                Origin = new Vector3 {
                    X = bsr.ReadSIntIfExists(PropDecodeConsts.CoordIntBits - 2) * 8 ?? _deltaTmp.Origin.X,
                    Y = bsr.ReadSIntIfExists(PropDecodeConsts.CoordIntBits - 2) * 8 ?? _deltaTmp.Origin.Y,
                    Z = bsr.ReadSIntIfExists(PropDecodeConsts.CoordIntBits - 2) * 8 ?? _deltaTmp.Origin.Z
                };
                SpeakerEntity = bsr.ReadSIntIfExists(DemoInfo.MaxEdictBits + 1) ?? _deltaTmp.SpeakerEntity;
            }
            else
            {
                ClearStopFields();
            }
        }