private void WriteEntry(HalfLifeDelta delta, BitWriter bitWriter, Entry e) { Boolean signed = ((e.Flags & EntryFlags.Signed) != 0); Object value = delta.FindEntryValue(e.Name); if ((e.Flags & EntryFlags.Byte) != 0) { if (signed) { SByte writeValue = (SByte)value; WriteInt(bitWriter, e, (Int32)writeValue); } else { Byte writeValue = (Byte)value; WriteUnsignedInt(bitWriter, e, (UInt32)writeValue); } } else if ((e.Flags & EntryFlags.Short) != 0) { if (signed) { Int16 writeValue = (Int16)value; WriteInt(bitWriter, e, (Int32)writeValue); } else { UInt16 writeValue = (UInt16)value; WriteUnsignedInt(bitWriter, e, (UInt32)writeValue); } } else if ((e.Flags & EntryFlags.Integer) != 0) { if (signed) { WriteInt(bitWriter, e, (Int32)value); } else { WriteUnsignedInt(bitWriter, e, (UInt32)value); } } else if ((e.Flags & EntryFlags.Angle) != 0) { bitWriter.WriteUnsignedBits((UInt32)((Single)value / (360.0f / (Single)(1 << (Int32)e.nBits))), (Int32)e.nBits); } else if ((e.Flags & EntryFlags.String) != 0) { bitWriter.WriteString((String)value); } else if ((e.Flags & EntryFlags.Float) != 0 || (e.Flags & EntryFlags.TimeWindow8) != 0 || (e.Flags & EntryFlags.TimeWindowBig) != 0) { Single writeValue = (Single)value; Int32 bitsToWrite = (Int32)e.nBits; if (signed) { bitWriter.WriteBoolean(writeValue < 0); bitsToWrite--; } bitWriter.WriteUnsignedBits((UInt32)(Math.Abs(writeValue) * e.Divisor), bitsToWrite); } else { throw new ApplicationException(String.Format("Unknown delta entry type {0}.", e.Flags)); } }
private void WriteUnsignedInt(BitWriter bitWriter, Entry e, UInt32 value) { UInt32 writeValue = value * (UInt32)e.Divisor; bitWriter.WriteUnsignedBits((UInt32)Math.Abs(writeValue), (Int32)e.nBits); }
private void MessageDeltaPacketEntities() { if (!demo.ConvertNetworkProtocol() || demo.IsBetaSteam()) { parser.MessageDeltaPacketEntities(); return; } Int32 messageStartOffset = parser.BitBuffer.CurrentByte; BitWriter bitWriter = new BitWriter(); // read message bitWriter.WriteUInt16(parser.BitBuffer.ReadUInt16()); // nEntities/maxEntities if (demo.NetworkProtocol <= 43) { parser.BitBuffer.Endian = BitBuffer.EndianType.Big; } bitWriter.WriteByte(parser.BitBuffer.ReadByte()); // delta sequence number UInt32 entityNumber = 0; while (true) { // check for footer UInt16 footer = parser.BitBuffer.ReadUInt16(); if (footer == 0) { bitWriter.WriteUInt16(footer); break; } parser.BitBuffer.SeekBits(-16); // option bits Boolean removeEntity = parser.BitBuffer.ReadBoolean(); bitWriter.WriteBoolean(removeEntity); Boolean absoluteEntityNumber = parser.BitBuffer.ReadBoolean(); bitWriter.WriteBoolean(absoluteEntityNumber); // entity number if (absoluteEntityNumber) { entityNumber = parser.BitBuffer.ReadUnsignedBits(11); bitWriter.WriteUnsignedBits(entityNumber, 11); } else { UInt32 deltaEntityNumber = parser.BitBuffer.ReadUnsignedBits(6); bitWriter.WriteUnsignedBits(deltaEntityNumber, 6); entityNumber += deltaEntityNumber; } if (!removeEntity) { // entity type Boolean custom = parser.BitBuffer.ReadBoolean(); bitWriter.WriteBoolean(custom); if (demo.NetworkProtocol <= 43) { parser.BitBuffer.SeekBits(1); // unknown, always 0 } String entityType = "entity_state_t"; if (entityNumber > 0 && entityNumber <= demo.MaxClients) { entityType = "entity_state_player_t"; } else if (custom) { entityType = "custom_entity_state_t"; } // delta compressed data Byte[] bitmaskBytes; HalfLifeDeltaStructure deltaDecoder = parser.GetDeltaStructure(entityType); HalfLifeDelta deltaEntity = deltaDecoder.CreateDelta(); deltaDecoder.ReadDelta(parser.BitBuffer, deltaEntity, out bitmaskBytes); if (demo.Game != null) { demo.Game.ConvertPacketEntititiesCallback(deltaEntity, entityType, demo.GameVersion); } deltaDecoder.WriteDelta(bitWriter, deltaEntity, bitmaskBytes); } } parser.BitBuffer.SkipRemainingBits(); parser.BitBuffer.Endian = BitBuffer.EndianType.Little; // insert new message ReWriteMessage(messageStartOffset, bitWriter.Data); }
private void MessageResourceList() { Int32 startByteIndex = parser.BitBuffer.CurrentByte; // read message if (demo.NetworkProtocol <= 43) { parser.BitBuffer.Endian = BitBuffer.EndianType.Big; } UInt32 nEntries = parser.BitBuffer.ReadUnsignedBits(12); List <Resource> resourceList = new List <Resource>((Int32)nEntries); for (Int32 i = 0; i < nEntries; i++) { Resource r = new Resource(); r.type = parser.BitBuffer.ReadUnsignedBits(4); r.name = parser.BitBuffer.ReadString(); r.index = parser.BitBuffer.ReadUnsignedBits(12); r.fileSize = parser.BitBuffer.ReadBits(24); // signed? r.flags = parser.BitBuffer.ReadUnsignedBits(3); if ((r.flags & 4) != 0) // md5 hash (RES_CUSTOM?) { r.md5Hash = parser.BitBuffer.ReadBytes(16); } r.hasReservedData = parser.BitBuffer.ReadBoolean(); if (r.hasReservedData) { r.reservedData = parser.BitBuffer.ReadBytes(32); } if (demo.Game == null || demo.Game.ConvertResourceListCallback(demo, r.type, r.index, ref r.name)) { resourceList.Add(r); } } // consistency list // indices of resources to force consistency upon? if (parser.BitBuffer.ReadBoolean()) { while (parser.BitBuffer.ReadBoolean()) { Int32 nBits = (parser.BitBuffer.ReadBoolean() ? 5 : 10); parser.BitBuffer.SeekBits(nBits); } } parser.BitBuffer.SkipRemainingBits(); parser.BitBuffer.Endian = BitBuffer.EndianType.Little; // stop now if we're not converting network protocols if (!demo.ConvertNetworkProtocol()) { return; } // create new message BitWriter bitWriter = new BitWriter(); bitWriter.WriteUnsignedBits((UInt32)resourceList.Count, 12); foreach (Resource r in resourceList) { bitWriter.WriteUnsignedBits(r.type, 4); bitWriter.WriteString(r.name); bitWriter.WriteUnsignedBits(r.index, 12); bitWriter.WriteBits(r.fileSize, 24); bitWriter.WriteUnsignedBits(r.flags, 3); if ((r.flags & 4) != 0) // md5 hash { bitWriter.WriteBytes(r.md5Hash); } bitWriter.WriteBoolean(r.hasReservedData); if (r.hasReservedData) { bitWriter.WriteBytes(r.reservedData); } } bitWriter.WriteBoolean(false); // consistency list // remove old message Int32 endByteIndex = parser.BitBuffer.CurrentByte; parser.Seek(startByteIndex, SeekOrigin.Begin); parser.BitBuffer.RemoveBytes(endByteIndex - startByteIndex); // insert new message into bitbuffer parser.BitBuffer.InsertBytes(bitWriter.Data); }
private void MessagePacketEntities() { if (!demo.ConvertNetworkProtocol()) { parser.MessagePacketEntities(); return; } Int32 messageStartOffset = parser.BitBuffer.CurrentByte; BitWriter bitWriter = new BitWriter(); // read message into new message bitWriter.WriteUInt16(parser.BitBuffer.ReadUInt16()); // nEntities/maxEntities if (demo.NetworkProtocol <= 43) { parser.BitBuffer.Endian = BitBuffer.EndianType.Big; } UInt32 entityNumber = 0; while (true) { UInt16 footer = parser.BitBuffer.ReadUInt16(); if (footer == 0) { bitWriter.WriteUInt16(footer); break; } else { parser.BitBuffer.SeekBits(-16); } if (!parser.BitBuffer.ReadBoolean()) // entity number isn't last entity number + 1, need to read it in { bitWriter.WriteBoolean(false); // is the following entity number absolute, or relative from the last one? if (parser.BitBuffer.ReadBoolean()) { bitWriter.WriteBoolean(true); entityNumber = parser.BitBuffer.ReadUnsignedBits(11); bitWriter.WriteUnsignedBits(entityNumber, 11); } else { bitWriter.WriteBoolean(false); UInt32 entityNumberDelta = parser.BitBuffer.ReadUnsignedBits(6); bitWriter.WriteUnsignedBits(entityNumberDelta, 6); entityNumber += entityNumberDelta; } } else { bitWriter.WriteBoolean(true); entityNumber++; } Boolean custom = parser.BitBuffer.ReadBoolean(); bitWriter.WriteBoolean(custom); Boolean baseline = parser.BitBuffer.ReadBoolean(); bitWriter.WriteBoolean(baseline); if (baseline) { bitWriter.WriteUnsignedBits(parser.BitBuffer.ReadUnsignedBits(6), 6); // baseline index } String entityType = "entity_state_t"; if (entityNumber > 0 && entityNumber <= demo.MaxClients) { entityType = "entity_state_player_t"; } else if (custom) { entityType = "custom_entity_state_t"; } HalfLifeDeltaStructure entityStateStructure = parser.GetDeltaStructure(entityType); HalfLifeDelta delta = entityStateStructure.CreateDelta(); Byte[] bitmaskBytes; entityStateStructure.ReadDelta(parser.BitBuffer, delta, out bitmaskBytes); if (demo.Game != null) { demo.Game.ConvertPacketEntititiesCallback(delta, entityType, demo.GameVersion); } entityStateStructure.WriteDelta(bitWriter, delta, bitmaskBytes); } parser.BitBuffer.SkipRemainingBits(); parser.BitBuffer.Endian = BitBuffer.EndianType.Little; // insert new message ReWriteMessage(messageStartOffset, bitWriter.Data); }
private void MessageNewUserMsg() { Int32 messageStartOffset = parser.BitBuffer.CurrentByte; // read message Byte id = parser.BitBuffer.ReadByte(); SByte length = parser.BitBuffer.ReadSByte(); String name = parser.BitBuffer.ReadString(16); parser.AddUserMessage(id, length, name); // FIXME: clean this up if (!demo.ConvertNetworkProtocol() && name != "CDChallenge" && name != "CDSalt") { return; } if (demo.Game == null || demo.Game.UserMessages == null) { return; } Byte newId; if (demo.Game.UserMessages.ContainsKey(name)) { newId = demo.Game.UserMessages[name]; } else { // cheating death // TODO: probably should have a list of "bad" user messages to remove... // TODO: should remove these messages even when not converting network protocols if (name == "CDChallenge" || name == "CDSalt") { // remove message Int32 messageFinishOffset = parser.BitBuffer.CurrentByte; parser.BitBuffer.SeekBytes(messageStartOffset - 1, SeekOrigin.Begin); parser.BitBuffer.RemoveBytes(messageFinishOffset - messageStartOffset + 1); // +1 for message id return; } // user message doesn't exist in CS 1.6. shouldn't happen, but meh... // TODO: use an id unused by compatibleUserMessageTable //newId = (Byte?)id; newId = firstFreeUserMessage; if (firstFreeUserMessage == 255) { throw new NoFreeUserMessageException(); } firstFreeUserMessage++; demo.Game.UserMessages.Add(name, newId); } BitWriter bitWriter = new BitWriter(); bitWriter.WriteByte((Byte)newId); bitWriter.WriteSByte(length); bitWriter.WriteString(name, 16); // insert new message ReWriteMessage(messageStartOffset, bitWriter.Data); }
private void MessageSpawnBaseline() { if (!demo.ConvertNetworkProtocol()) { parser.MessageSpawnBaseline(); return; } Int32 messageStartOffset = parser.BitBuffer.CurrentByte; BitWriter bitWriter = new BitWriter(); // read message into new message if (demo.NetworkProtocol <= 43) { parser.BitBuffer.Endian = BitBuffer.EndianType.Big; } while (true) { UInt32 entityIndex = parser.BitBuffer.ReadUnsignedBits(11); bitWriter.WriteUnsignedBits(entityIndex, 11); if (entityIndex == (1 << 11) - 1) // all 1's { break; } UInt32 entityType = parser.BitBuffer.ReadUnsignedBits(2); bitWriter.WriteUnsignedBits(entityType, 2); String entityTypeString; if ((entityType & 1) != 0) { if (entityIndex > 0 && entityIndex <= demo.MaxClients) { entityTypeString = "entity_state_player_t"; } else { entityTypeString = "entity_state_t"; } } else { entityTypeString = "custom_entity_state_t"; } HalfLifeDeltaStructure deltaStructure = parser.GetDeltaStructure(entityTypeString); HalfLifeDelta delta = deltaStructure.CreateDelta(); Byte[] bitmaskBytes; deltaStructure.ReadDelta(parser.BitBuffer, delta, out bitmaskBytes); if (demo.Game != null) { demo.Game.ConvertPacketEntititiesCallback(delta, entityTypeString, demo.GameVersion); } deltaStructure.WriteDelta(bitWriter, delta, bitmaskBytes); } UInt32 footer = parser.BitBuffer.ReadUnsignedBits(5); // should be all 1's bitWriter.WriteUnsignedBits(footer, 5); if (footer != (1 << 5) - 1) { throw new ApplicationException("Bad svc_spawnbaseline footer."); } UInt32 nExtraData = parser.BitBuffer.ReadUnsignedBits(6); bitWriter.WriteUnsignedBits(nExtraData, 6); HalfLifeDeltaStructure entityStateStructure = parser.GetDeltaStructure("entity_state_t"); for (Int32 i = 0; i < nExtraData; i++) { HalfLifeDelta delta = entityStateStructure.CreateDelta(); Byte[] bitmaskBytes; entityStateStructure.ReadDelta(parser.BitBuffer, delta, out bitmaskBytes); entityStateStructure.WriteDelta(bitWriter, delta, bitmaskBytes); } parser.BitBuffer.Endian = BitBuffer.EndianType.Little; parser.BitBuffer.SkipRemainingBits(); // insert new message ReWriteMessage(messageStartOffset, bitWriter.Data); }
private void MessageClientData() { if (demo.Perspective == Demo.Perspectives.Hltv) { return; } if (!demo.ConvertNetworkProtocol() || demo.IsBetaSteam()) { parser.MessageClientData(); return; } // read message Int32 messageStartOffset = parser.BitBuffer.CurrentByte; if (demo.NetworkProtocol <= 43) { parser.BitBuffer.Endian = BitBuffer.EndianType.Big; } BitWriter bitWriter = new BitWriter(); HalfLifeDeltaStructure clientDataStructure = parser.GetDeltaStructure("clientdata_t"); HalfLifeDeltaStructure weaponDataStructure = parser.GetDeltaStructure("weapon_data_t"); Boolean deltaSequence = parser.BitBuffer.ReadBoolean(); bitWriter.WriteBoolean(deltaSequence); UInt32 deltaSequenceNumber = 0; if (deltaSequence) { deltaSequenceNumber = parser.BitBuffer.ReadUnsignedBits(8); bitWriter.WriteUnsignedBits(deltaSequenceNumber, 8); } HalfLifeDelta clientData = clientDataStructure.CreateDelta(); Byte[] clientDataBitmaskBytes; clientDataStructure.ReadDelta(parser.BitBuffer, clientData, out clientDataBitmaskBytes); clientDataStructure.WriteDelta(bitWriter, clientData, clientDataBitmaskBytes); while (parser.BitBuffer.ReadBoolean()) { bitWriter.WriteBoolean(true); if (demo.NetworkProtocol < 47 && !demo.IsBetaSteam()) { bitWriter.WriteUnsignedBits(parser.BitBuffer.ReadUnsignedBits(5), 6); } else { bitWriter.WriteUnsignedBits(parser.BitBuffer.ReadUnsignedBits(6), 6); } HalfLifeDelta weaponData = weaponDataStructure.CreateDelta(); Byte[] bitmaskBytes; weaponDataStructure.ReadDelta(parser.BitBuffer, weaponData, out bitmaskBytes); weaponDataStructure.WriteDelta(bitWriter, weaponData, bitmaskBytes); } bitWriter.WriteBoolean(false); parser.BitBuffer.SkipRemainingBits(); parser.BitBuffer.Endian = BitBuffer.EndianType.Little; // insert new message ReWriteMessage(messageStartOffset, bitWriter.Data); }
private void MessageEvent() { if (!demo.ConvertNetworkProtocol()) { parser.MessageEvent(); return; } Int32 messageStartOffset = parser.BitBuffer.CurrentByte; // read message if (demo.NetworkProtocol <= 43) { parser.BitBuffer.Endian = BitBuffer.EndianType.Big; } BitWriter bitWriter = new BitWriter(); HalfLifeDeltaStructure eventStructure = parser.GetDeltaStructure("event_t"); UInt32 nEvents = parser.BitBuffer.ReadUnsignedBits(5); bitWriter.WriteUnsignedBits(nEvents, 5); for (Int32 i = 0; i < nEvents; i++) { UInt32 eventIndex = parser.BitBuffer.ReadUnsignedBits(10); bitWriter.WriteUnsignedBits(eventIndex, 10); // event index Boolean packetIndexBit = parser.BitBuffer.ReadBoolean(); bitWriter.WriteBoolean(packetIndexBit); if (packetIndexBit) { bitWriter.WriteUnsignedBits(parser.BitBuffer.ReadUnsignedBits(11), 11); // packet index Boolean deltaBit = parser.BitBuffer.ReadBoolean(); bitWriter.WriteBoolean(deltaBit); if (deltaBit) { HalfLifeDelta delta = eventStructure.CreateDelta(); Byte[] bitmaskBytes; eventStructure.ReadDelta(parser.BitBuffer, delta, out bitmaskBytes); if (demo.Game != null) { demo.Game.ConvertEventCallback(demo, delta, eventIndex); } eventStructure.WriteDelta(bitWriter, delta, bitmaskBytes); } } Boolean fireTimeBit = parser.BitBuffer.ReadBoolean(); bitWriter.WriteBoolean(fireTimeBit); if (fireTimeBit) { bitWriter.WriteUnsignedBits(parser.BitBuffer.ReadUnsignedBits(16), 16); // fire time } } parser.BitBuffer.SkipRemainingBits(); parser.BitBuffer.Endian = BitBuffer.EndianType.Little; // insert new message ReWriteMessage(messageStartOffset, bitWriter.Data); }