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) { PlayerMasks = new PlayerMask[VoiceMaxPlayers]; for (int i = 0; i < VoiceMaxPlayers; i++) { PlayerMasks[i] = new PlayerMask { GameRulesMask = bsr.ReadSInt(), BanMask = bsr.ReadSInt() } } ; PlayerModEnable = bsr.ReadByte() != 0; }
protected override void Parse(ref BitStreamReader bsr) { FileStamp = bsr.ReadStringOfLength(8); DemoProtocol = bsr.ReadUInt(); NetworkProtocol = bsr.ReadUInt(); ServerName = bsr.ReadStringOfLength(260); ClientName = bsr.ReadStringOfLength(260); MapName = bsr.ReadStringOfLength(260); GameDirectory = bsr.ReadStringOfLength(260); PlaybackTime = bsr.ReadFloat(); TickCount = bsr.ReadSInt(); FrameCount = bsr.ReadSInt(); SignOnLength = bsr.ReadUInt(); }
public static unsafe byte[] Decompress(ref BitStreamReader bsr, int compSize) { uint type = bsr.ReadUInt(); int decompSize = bsr.ReadSInt(); switch (type) { case LZSS_ID: Span <byte> dataIn = compSize < 100000 ? stackalloc byte[compSize] : new byte[compSize]; bsr.ReadToSpan(dataIn); byte[] arrOut = new byte[decompSize]; fixed(byte *pDataIn = dataIn) fixed(byte *pDataOut = arrOut) DecompressLZSS(pDataIn, pDataOut); return(arrOut); case SNAPPY_ID: Debug.Assert(false); throw new NotImplementedException("snappy decompression not implemented"); default: throw new InvalidOperationException("unknown compression method"); } }
// src_main/common/netmessages.cpp SVC_ServerInfo::WriteToBuffer protected override void Parse(ref BitStreamReader bsr) { NetworkProtocol = bsr.ReadUShort(); ServerCount = bsr.ReadUInt(); IsHltv = bsr.ReadBool(); IsDedicated = bsr.ReadBool(); if (DemoInfo.IsLeft4Dead() && DemoInfo.Game >= SourceGame.L4D2_2147) { UnknownBit = bsr.ReadBool(); } ClientCrc = bsr.ReadSInt(); if (DemoInfo.NewDemoProtocol) // unknown field, could be before ClientCrc { Unknown = bsr.ReadUInt(); } MaxServerClasses = bsr.ReadUShort(); if (NetworkProtocol == 24) { MapMD5 = bsr.ReadBytes(16); } else { MapCrc = bsr.ReadUInt(); // network protocol < 18 according to p2 leak, but doesn't add up for l4d2 and p2 } PlayerCount = bsr.ReadByte(); MaxClients = bsr.ReadByte(); TickInterval = bsr.ReadFloat(); Platform = (char)bsr.ReadByte(); GameDirBitIndex = bsr.AbsoluteBitIndex; GameDir = bsr.ReadNullTerminatedString(); MapName = bsr.ReadNullTerminatedString(); SkyName = bsr.ReadNullTerminatedString(); HostName = bsr.ReadNullTerminatedString(); if (DemoInfo.IsLeft4Dead() && DemoInfo.Game >= SourceGame.L4D2_2147) { MissionName = bsr.ReadNullTerminatedString(); MutationName = bsr.ReadNullTerminatedString(); } if (NetworkProtocol == 24) { HasReplay = bsr.ReadBool(); // protocol version >= 16 } // there's a good change that the first SvcServerInfo parsed is parsed correctly // prevent the interval from being overwritten by subsequent, incorrectly detected, SvcServerInfo messages // TODO: check if changing tickrate mid game sends another SvcServerInfo if (!DemoInfo.HasParsedTickInterval) { DemoInfo.TickInterval = TickInterval; DemoInfo.HasParsedTickInterval = true; } // this packet always(?) appears before the creation of any tables DemoRef.StringTablesManager.ClearCurrentTables(); // init baselines here DemoRef.EntBaseLines = new EntityBaseLines(DemoRef, MaxServerClasses); }
protected override void Parse(ref BitStreamReader bsr) { Armor = bsr.ReadByte(); DamageTaken = bsr.ReadByte(); BitsDamage = bsr.ReadSInt(); bsr.ReadVector3(out VecFrom); /*VecFrom = new Vector3 { old engine? * X = bsr.ReadCoord(), * Y = bsr.ReadCoord(), * Z = bsr.ReadCoord() * };*/ }
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) { Command = bsr.ReadStringOfLength(bsr.ReadSInt()); TimingAdjustment.AdjustFromConsoleCmd(this); Match match = KeyPressRegex.Match(Command); if (match.Success) { int val = int.Parse(match.Groups[1].Value); if (val >= 0 && val < (int)Packets.ButtonCode.LAST) { ButtonCode = (ButtonCode)val; } } }
protected override void Parse(ref BitStreamReader bsr) { int byteLen = bsr.ReadSInt(); int indexBeforeTables = bsr.CurrentBitIndex; byte tableCount = bsr.ReadByte(); Tables = new List <StringTable>(tableCount); for (int i = 0; i < tableCount; i++) { var table = new StringTable(DemoRef); Tables.Add(table); table.ParseStream(ref bsr); } bsr.CurrentBitIndex = indexBeforeTables + byteLen * 8; // if this packet exists make sure to create the tables manager after we parse this DemoRef.StringTablesManager.CreateTablesFromPacket(this); }
protected override void Parse(ref BitStreamReader bsr) { byte typeVal = bsr.ReadByte(); Type = DemoPacket.ByteToPacketType(DemoInfo, typeVal); if (Type == PacketType.Unknown) { throw new ArgumentException("no byte->packet mapper found for this game!"); } else if (Type == PacketType.Invalid) { throw new ArgumentException($"Illegal packet type: {typeVal}"); } // very last byte is cut off in (all?) demos, copy data from the previous frame if this is the case Tick = bsr.BitsRemaining >= 32 ? bsr.ReadSInt() : (int)bsr.ReadUInt(24) | (DemoRef.Frames[^ 2].Tick & (0xff << 24));
// we're reading a player_info_t, so take alignment into account protected override void Parse(ref BitStreamReader bsr) { if (DemoInfo.NewDemoProtocol && !DemoInfo.IsLeft4Dead1()) { SteamId = (CSteamId)bsr.ReadULong(); } Name = bsr.ReadStringOfLength(MaxPlayerNameLength); UserId = bsr.ReadSInt(); Guid = bsr.ReadStringOfLength(SignedGuidLen + 1); bsr.SkipBytes(3); FriendsId = bsr.ReadUInt(); FriendsName = bsr.ReadStringOfLength(MaxPlayerNameLength); FakePlayer = bsr.ReadByte() != 0; IsHlTv = bsr.ReadByte() != 0; bsr.SkipBytes(2); CustomFiles = new[] { bsr.ReadUInt(), bsr.ReadUInt(), bsr.ReadUInt(), bsr.ReadUInt() }; FilesDownloaded = bsr.ReadByte(); bsr.SkipBytes(3); // for demo protocol 4 there's 4 additional bytes somewhere for some reason }
protected override void Parse(ref BitStreamReader bsr) { // first, we read the main message info here MaxEntries = (ushort)bsr.ReadUInt(11); IsDelta = bsr.ReadBool(); DeltaFrom = IsDelta ? bsr.ReadSInt() : -1; BaseLine = bsr.ReadUInt(1); UpdatedEntries = (ushort)bsr.ReadUInt(11); uint dataLen = bsr.ReadUInt(20); UpdateBaseline = bsr.ReadBool(); _entBsr = bsr.SplitAndSkip(dataLen); #if !FORCE_PROCESS_ENTS if ((DemoRef.DemoParseResult & DemoParseResult.EntParsingEnabled) == 0 || (DemoRef.DemoParseResult & DemoParseResult.EntParsingFailed) != 0) { return; } #endif // now, we do some setup for ent parsing ref EntitySnapshot?snapshot = ref DemoRef.EntitySnapshot;
protected override void Parse(ref BitStreamReader bsr) { SignOnState = (SignOnState)bsr.ReadByte(); SpawnCount = bsr.ReadSInt(); if (DemoInfo.NewDemoProtocol) { NumServerPlayers = bsr.ReadUInt(); int length = (int)bsr.ReadUInt(); if (length > 0) { PlayerNetworkIds = bsr.ReadBytes(length); } length = (int)bsr.ReadUInt(); if (length > 0) // the string still seams to be null terminated (sometimes?) { MapName = bsr.ReadStringOfLength(length).Split(new char[] { '\0' }, 2)[0]; } } if (SignOnState == SignOnState.PreSpawn) { DemoRef.ClientSoundSequence = 1; // reset sound sequence number after receiving SignOn sounds } }
public void WriteSInts() { var random = new Random(0); BitStreamWriter bsw = new BitStreamWriter(); List <(int val, int size)> bits = new List <(int val, int size)>(); for (int _ = 0; _ < Iterations; _++) { (int val, int size)r = (random.Next(), random.Next(1, 33)); r.val &= int.MaxValue >> (32 - r.size); if ((r.val & (1 << (r.size - 1))) != 0) // sign extend, not necessary for primitive types { r.val |= int.MaxValue << r.size; // can use int here since the leftmost 0 will get shifted away anyway } bits.Add(r); bsw.WriteBitsFromSInt(r.val, r.size); } BitStreamReader bsr = new BitStreamReader(bsw); for (int i = 0; i < Iterations; i++) { Assert.AreEqual(bits[i].val, bsr.ReadSInt(bits[i].size), $"index: {i}"); } }
protected override void Parse(ref BitStreamReader bsr) { Unk = bsr.ReadSInt(); }
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(); } }
protected override void Parse(ref BitStreamReader bsr) { Unknown = bsr.ReadSInt(); CallbackStr = bsr.ReadNullTerminatedString(); }
protected override void Parse(ref BitStreamReader bsr) { Cookie = bsr.ReadSInt(); CvarName = bsr.ReadNullTerminatedString(); }