static void TestBitStream() { BitStreamWriter writer = new BitStreamWriter(2); BitStreamReader reader = new BitStreamReader(); // Resize, basic int writer.WriteInt32(0x12345678); writer.WriteInt8(39); writer.WriteInt(2, 2); writer.WriteInt(87, 7); writer.WriteInt(33, 6); reader.SetBytes(writer.DumpBytes()); Assert.IsTrue(reader.ReadInt32() == 0x12345678); Assert.IsTrue(reader.ReadInt8() == 39); Assert.IsTrue(reader.ReadInt(2) == 2); Assert.IsTrue(reader.ReadInt(7) == 87); Assert.IsTrue(reader.ReadInt(6) == 33); // Concatnat bits // 1, 0000010 11000011, 1 // should be 00000101 10000110 00000011 writer.WriteBool(true); writer.WriteInt16(707); writer.WriteBool(true); var data = writer.DumpBytes(); Assert.IsTrue(data.Length == 3); Assert.IsTrue(data[0] == 0x05); Assert.IsTrue(data[1] == 0x86); Assert.IsTrue(data[2] == 0x03); reader.SetBytes(data); Assert.IsTrue(reader.ReadBool()); Assert.IsTrue(reader.ReadInt16() == 707); Assert.IsTrue(reader.ReadBool()); // float writer.WriteBool(false); writer.WriteFloat(12345.012345f); writer.WriteBool(true); reader.SetBytes(writer.DumpBytes()); Assert.IsFalse(reader.ReadBool()); Assert.IsTrue(reader.ReadFloat() == 12345.012345f); Assert.IsTrue(reader.ReadBool()); // vector3, quaternion Vector3 vec = new Vector3(-0.51231f, 0.113123f, 1.1231123f); Quaternion q = new Quaternion(-0.123f, 0.345f, 0.678f, -0.23f); q.Normalize(); writer.WriteQuaternionRot(q); writer.WriteBool(false); writer.WriteVector3(Vector3.one); writer.WriteVector3(vec); reader.SetBytes(writer.DumpBytes()); Assert.IsTrue(IsApprox(reader.ReadQuaternionRot(), q)); Assert.IsFalse(reader.ReadBool()); Assert.IsTrue(reader.ReadVector3() == Vector3.one); Assert.IsTrue(reader.ReadVector3() == vec); }
// 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) { bsr.ReadVectorCoord(out Pos); DecalTextureIndex = (int)bsr.ReadUInt(9); if (bsr.ReadBool()) { EntityIndex = bsr.ReadUInt(DemoInfo.MaxEdictBits); ModelIndex = bsr.ReadUInt(DemoInfo.MaxEdictBits); } LowPriority = bsr.ReadBool(); }
protected override void Parse(ref BitStreamReader bsr) { Name = bsr.ReadNullTerminatedString(); ushort entryCount = bsr.ReadUShort(); if (entryCount > 0) { TableEntries = new List <StringTableEntry>(entryCount); for (int i = 0; i < entryCount; i++) { var entry = new StringTableEntry(DemoRef, this); TableEntries.Add(entry); entry.ParseStream(ref bsr); } } if (bsr.ReadBool()) { ushort classCount = bsr.ReadUShort(); Classes = new List <StringTableClass>(classCount); for (int i = 0; i < classCount; i++) { var @class = new StringTableClass(DemoRef); Classes.Add(@class); @class.ParseStream(ref bsr); } } }
protected override void Parse(ref BitStreamReader bsr) { Client = bsr.ReadByte(); WantsToChat = bsr.ReadBool(); // TODO: fill out the rest of the UserMessage (don't know what SayText2 // is even but I guess it doesn't happen often at all since it hasn't broken a demo parse yet) }
protected override void Parse(ref BitStreamReader bsr) { Cmd = bsr.ReadUInt(); uint byteSize = bsr.ReadUInt(); int indexBeforeData = bsr.CurrentBitIndex; CommandNumber = bsr.ReadUIntIfExists(); TickCount = bsr.ReadUIntIfExists(); ViewAngleX = bsr.ReadFloatIfExists(); ViewAngleY = bsr.ReadFloatIfExists(); ViewAngleZ = bsr.ReadFloatIfExists(); SidewaysMovement = bsr.ReadFloatIfExists(); ForwardMovement = bsr.ReadFloatIfExists(); VerticalMovement = bsr.ReadFloatIfExists(); Buttons = (Buttons?)bsr.ReadUIntIfExists(); Impulse = bsr.ReadByteIfExists(); if (bsr.ReadBool()) { WeaponSelect = bsr.ReadUInt(11); WeaponSubtype = bsr.ReadUIntIfExists(6); } MouseDx = (short?)bsr.ReadUShortIfExists(); MouseDy = (short?)bsr.ReadUShortIfExists(); bsr.CurrentBitIndex = indexBeforeData + (int)(byteSize << 3); }
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); }
protected override void Parse(ref BitStreamReader bsr) { RemoveUser = bsr.ReadBool(); uint dataLen = bsr.ReadUInt(11); Data = bsr.SplitAndSkip(dataLen); }
// 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) { Relative = bsr.ReadBool(); Angle = new Vector3 { X = bsr.ReadBitAngle(16), Y = bsr.ReadBitAngle(16), Z = bsr.ReadBitAngle(16), }; }
protected override void Parse(ref BitStreamReader bsr) { Name = bsr.ReadNullTerminatedString(); if (bsr.ReadBool()) { ushort dataLen = bsr.ReadUShort(); Data = bsr.ReadStringOfLength(dataLen); } }
protected override void Parse(ref BitStreamReader bsr) { Name = bsr.ReadNullTerminatedString(); if (bsr.ReadBool()) { ushort byteLen = bsr.ReadUShort(); Debug.Assert(DemoRef.DataTableParser.FlattenedProps != null); EntryData = StringTableEntryDataFactory.CreateEntryData(DemoRef, null, TableRef.Name, Name); EntryData.ParseStream(bsr.SplitAndSkip(byteLen * 8)); } }
protected override void Parse(ref BitStreamReader bsr) { NeedsDecoder = bsr.ReadBool(); Name = bsr.ReadNullTerminatedString(); ExpectedPropCount = (int)bsr.ReadUInt(DemoInfo.Game == SourceGame.HL2_OE ? 9 : 10); SendProps = new List <SendTableProp>(ExpectedPropCount); for (int i = 0; i < ExpectedPropCount; i++) { var sendProp = new SendTableProp(DemoRef, this); SendProps.Add(sendProp); sendProp.ParseStream(ref bsr); } }
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) { 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); }
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"); } }
public void WriteBools() { var random = new Random(0); BitStreamWriter bsw = new BitStreamWriter(); List <bool> bools = new List <bool>(); for (int _ = 0; _ < Iterations; _++) { bool r = random.NextDouble() >= .5; bools.Add(r); bsw.WriteBool(r); } BitStreamReader bsr = new BitStreamReader(bsw); for (int i = 0; i < Iterations; i++) { Assert.AreEqual(bools[i], bsr.ReadBool(), $"index: {i}"); } }
protected override void Parse(ref BitStreamReader bsr) { TableName = bsr.ReadNullTerminatedString(); MaxEntries = (short)bsr.ReadUShort(); NumEntries = (int)bsr.ReadUInt(BitUtils.HighestBitIndex(MaxEntries) + 1); uint dataLen = bsr.ReadUInt(DemoInfo.IsLeft4Dead2() ? 21 : 20); UserDataFixedSize = bsr.ReadBool(); UserDataSize = (int)(UserDataFixedSize ? bsr.ReadUInt(12) : 0); UserDataSizeBits = (int)(UserDataFixedSize ? bsr.ReadUInt(4) : 0); if (DemoRef.Header.NetworkProtocol >= 15) { Flags = (StringTableFlags)bsr.ReadUInt(DemoInfo.NewDemoProtocol ? 2 : 1); } DemoRef.StringTablesManager.CreateStringTable(this); TableUpdates = new StringTableUpdates(DemoRef, TableName, NumEntries, true); TableUpdates.ParseStream(bsr.SplitAndSkip(dataLen)); }
private static void ReadHRDParameters(BitStreamReader bitReader, ref HRDParameters hrd) { hrd = new HRDParameters(); hrd.cpb_cnt_minus1 = bitReader.ReadUE(); hrd.bit_rate_scale = (int)bitReader.ReadNBit(4); hrd.cpb_size_scale = (int)bitReader.ReadNBit(4); hrd.bit_rate_value_minus1 = new int[hrd.cpb_cnt_minus1 + 1]; hrd.cpb_size_value_minus1 = new int[hrd.cpb_cnt_minus1 + 1]; hrd.cbr_flag = new bool[hrd.cpb_cnt_minus1 + 1]; for (int SchedSelIdx = 0; SchedSelIdx <= hrd.cpb_cnt_minus1; SchedSelIdx++) { hrd.bit_rate_value_minus1[SchedSelIdx] = bitReader.ReadUE(); hrd.cpb_size_value_minus1[SchedSelIdx] = bitReader.ReadUE(); hrd.cbr_flag[SchedSelIdx] = bitReader.ReadBool(); } hrd.initial_cpb_removal_delay_length_minus1 = (int)bitReader.ReadNBit(5); hrd.cpb_removal_delay_length_minus1 = (int)bitReader.ReadNBit(5); hrd.dpb_output_delay_length_minus1 = (int)bitReader.ReadNBit(5); hrd.time_offset_length = (int)bitReader.ReadNBit(5); }
private static void ReadScalingListMatrix(BitStreamReader bitReader, ref ScalingMatrix matrix) { matrix = new ScalingMatrix(); for (int i = 0; i < 8; i++) { bool seqScalingListPresentFlag = bitReader.ReadBool(); if (seqScalingListPresentFlag) { matrix.ScalingList4x4 = new ScalingList[8]; matrix.ScalingList8x8 = new ScalingList[8]; if (i < 6) { matrix.ScalingList4x4[i] = ScalingList.Read(bitReader, 16); } else { matrix.ScalingList8x8[i - 6] = ScalingList.Read(bitReader, 64); } } } }
public static void Deserialize(ref Boolean value, BitStreamReader reader) => value = reader.ReadBool();
private static void ReadVUIParameters(BitStreamReader bitReader, ref VUIParameters vuip) { vuip = new VUIParameters(); vuip.aspect_ratio_info_present_flag = bitReader.ReadBool(); if (vuip.aspect_ratio_info_present_flag) { vuip.aspect_ratio = bitReader.ReadNBit(8); if (vuip.aspect_ratio == 255) //Extended SAR { vuip.sar_width = bitReader.ReadNBit(16); vuip.sar_height = bitReader.ReadNBit(16); } } vuip.overscan_info_present_flag = bitReader.ReadBool(); if (vuip.overscan_info_present_flag) { vuip.overscan_appropriate_flag = bitReader.ReadBool(); } vuip.video_signal_type_present_flag = bitReader.ReadBool(); if (vuip.video_signal_type_present_flag) { vuip.video_format = bitReader.ReadNBit(3); vuip.video_full_range_flag = bitReader.ReadBool(); vuip.colour_description_present_flag = bitReader.ReadBool(); if (vuip.colour_description_present_flag) { vuip.colour_primaries = bitReader.ReadNBit(8); vuip.transfer_characteristics = bitReader.ReadNBit(8); vuip.matrix_coefficients = bitReader.ReadNBit(8); } } vuip.chroma_loc_info_present_flag = bitReader.ReadBool(); if (vuip.chroma_loc_info_present_flag) { vuip.chroma_sample_loc_type_top_field = bitReader.ReadUE(); vuip.chroma_sample_loc_type_bottom_field = bitReader.ReadUE(); } vuip.timing_info_present_flag = bitReader.ReadBool(); if (vuip.timing_info_present_flag) { vuip.num_units_in_tick = bitReader.ReadNBit(32); vuip.time_scale = bitReader.ReadNBit(32); vuip.fixed_frame_rate_flag = bitReader.ReadBool(); } bool nal_hrd_parameters_present_flag = bitReader.ReadBool(); if (nal_hrd_parameters_present_flag) { ReadHRDParameters(bitReader, ref vuip.nalHRDParams); } bool vcl_hrd_parameters_present_flag = bitReader.ReadBool(); if (vcl_hrd_parameters_present_flag) { ReadHRDParameters(bitReader, ref vuip.vclHRDParams); } if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) { vuip.low_delay_hrd_flag = bitReader.ReadBool(); } vuip.pic_struct_present_flag = bitReader.ReadBool(); bool bitstream_restriction_flag = bitReader.ReadBool(); if (bitstream_restriction_flag) { vuip.bitstreamRestriction = new VUIParameters.BitstreamRestriction(); vuip.bitstreamRestriction.motion_vectors_over_pic_boundaries_flag = bitReader.ReadBool(); vuip.bitstreamRestriction.max_bytes_per_pic_denom = bitReader.ReadUE(); vuip.bitstreamRestriction.max_bits_per_mb_denom = bitReader.ReadUE(); vuip.bitstreamRestriction.log2_max_mv_length_horizontal = bitReader.ReadUE(); vuip.bitstreamRestriction.log2_max_mv_length_vertical = bitReader.ReadUE(); vuip.bitstreamRestriction.num_reorder_frames = bitReader.ReadUE(); vuip.bitstreamRestriction.max_dec_frame_buffering = bitReader.ReadUE(); } }
public static SeqParameterSet Read(byte[] NALData) { BitStreamReader bitReader = new BitStreamReader(NALData); SeqParameterSet sps = new SeqParameterSet(); sps.profile_idc = bitReader.ReadNBit(8); sps.constraint_set_0_flag = bitReader.ReadBool(); sps.constraint_set_1_flag = bitReader.ReadBool(); sps.constraint_set_2_flag = bitReader.ReadBool(); sps.constraint_set_3_flag = bitReader.ReadBool(); bitReader.ReadNBit(4); //reserved_zero_4bits sps.level_idc = bitReader.ReadNBit(8); sps.seq_parameter_set_id = bitReader.ReadUE(); sps.chroma_format_idc = ChromaFormat.Yuv420; if (sps.profile_idc == 100 || sps.profile_idc == 110 || sps.profile_idc == 122 || sps.profile_idc == 244 || sps.profile_idc == 44) { sps.chroma_format_idc = (ChromaFormat)bitReader.ReadUE(); if (sps.chroma_format_idc == ChromaFormat.Yuv444) { sps.residual_color_transform_flag = bitReader.ReadBool(); } sps.bit_depth_luma_minus8 = bitReader.ReadUE(); sps.bit_depth_chroma_minus8 = bitReader.ReadUE(); sps.qpprime_y_zero_transform_bypass_flag = bitReader.ReadBool(); bool seqScalingMatrixPresent = bitReader.ReadBool(); if (seqScalingMatrixPresent) { ReadScalingListMatrix(bitReader, ref sps.scalingMatrix); } } sps.log2_max_frame_num_minus4 = bitReader.ReadUE(); sps.pic_order_cnt_type = bitReader.ReadUE(); if (sps.pic_order_cnt_type == 0) { sps.log2_max_pic_order_cnt_lsb_minus4 = bitReader.ReadUE(); } else if (sps.pic_order_cnt_type == 1) { sps.delta_pic_order_always_zero_flag = bitReader.ReadBool(); sps.offset_for_non_ref_pic = bitReader.ReadSE(); sps.offset_for_top_to_bottom_field = bitReader.ReadSE(); sps.num_ref_frames_in_pic_order_cnt_cycle = bitReader.ReadUE(); sps.offsetForRefFrame = new int[sps.num_ref_frames_in_pic_order_cnt_cycle]; for (int i = 0; i < sps.num_ref_frames_in_pic_order_cnt_cycle; i++) { sps.offsetForRefFrame[i] = bitReader.ReadSE(); } } sps.num_ref_frames = bitReader.ReadUE(); sps.gaps_in_frame_num_value_allowed_flag = bitReader.ReadBool(); sps.pic_width_in_mbs_minus1 = bitReader.ReadUE(); sps.pic_height_in_map_units_minus1 = bitReader.ReadUE(); sps.frame_mbs_only_flag = bitReader.ReadBool(); if (!sps.frame_mbs_only_flag) { sps.mb_adaptive_frame_field_flag = bitReader.ReadBool(); } sps.direct_8x8_inference_flag = bitReader.ReadBool(); sps.frame_cropping_flag = bitReader.ReadBool(); if (sps.frame_cropping_flag) { sps.frame_crop_left_offset = bitReader.ReadUE(); sps.frame_crop_right_offset = bitReader.ReadUE(); sps.frame_crop_top_offset = bitReader.ReadUE(); sps.frame_crop_bottom_offset = bitReader.ReadUE(); } bool vui_parameters_present_flag = bitReader.ReadBool(); if (vui_parameters_present_flag) { ReadVUIParameters(bitReader, ref sps.vuiParams); } return(sps); }
protected override void Parse(ref BitStreamReader bsr) { IsPaused = bsr.ReadBool(); }
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(); } }
public static Boolean Deserialize(BitStreamReader reader) => reader.ReadBool();