private static Entity ReadEnterPVS(IBitStream reader, int id, DemoParser parser) { int serverClassID = (int)reader.ReadInt(parser.SendTableParser.ClassBits); ServerClass entityClass = parser.SendTableParser.ServerClasses[serverClassID]; reader.ReadInt(10); //Entity serial. Entity newEntity = new Entity(id, entityClass); newEntity.ServerClass.AnnounceNewEntity(newEntity); object[] fastBaseline; if (parser.PreprocessedBaselines.TryGetValue(serverClassID, out fastBaseline)) { PropertyEntry.Emit(newEntity, fastBaseline); } else { var preprocessedBaseline = new List <object>(); if (parser.instanceBaseline.ContainsKey(serverClassID)) { using (var collector = new PropertyCollector(newEntity, preprocessedBaseline)) using (var bitStream = BitStreamUtil.Create(parser.instanceBaseline[serverClassID])) newEntity.ApplyUpdate(bitStream); } parser.PreprocessedBaselines.Add(serverClassID, preprocessedBaseline.ToArray()); } return(newEntity); }
public bool TryApplyMessage(ProtoBuf.IExtensible message, DemoParser parser) { CSVCMsg_PacketEntities packetEntities = message as CSVCMsg_PacketEntities; if (packetEntities == null) { return(false); } // TODO check // In official C++ source code, loop is from last to first entities in packetEntities -> impact ? using (IBitStream reader = BitStreamUtil.Create(packetEntities.entity_data)) { int currentEntity = -1; for (int i = 0; i < packetEntities.updated_entries; i++) { currentEntity += 1 + (int)reader.ReadUBitInt(); if (!reader.ReadBit()) { Entity entity; if (reader.ReadBit()) { // EnterPVS = add entity entity = EnterPVS(reader, currentEntity, parser); } else { // DeltaEnt = update entity entity = parser.entities[currentEntity]; } entity.ApplyUpdate(reader); UpdateModel(entity, parser); Debug.WriteLine("Entity #" + entity.ID + ": " + entity.ServerClass.Name); } else { // LeavePVS if (reader.ReadBit()) { parser.entities.Remove(currentEntity); } } } } return(true); }
public void ParsePacket(Stream stream, DemoParser parser) { using (IBitStream reader = BitStreamUtil.Create(stream)) { int numTables = reader.ReadByte(); for (int i = 0; i < numTables; i++) { string tableName = reader.ReadString(); ParseStringTable(reader, tableName, parser); } } }
/// <summary> /// Reads an update that occures when a new edict enters the PVS (potentially visible system) /// </summary> /// <returns>The new Entity.</returns> private static Entity ReadEnterPVS(IBitStream reader, int id, DemoParser parser) { //What kind of entity? int serverClassID = (int)reader.ReadInt(parser.SendTableParser.ClassBits); //So find the correct server class ServerClass entityClass = parser.SendTableParser.ServerClasses[serverClassID]; reader.ReadInt(10); //Entity serial. //Never used anywhere I guess. Every parser just skips this Entity newEntity = new Entity(id, entityClass); //give people the chance to subscribe to events for this newEntity.ServerClass.AnnounceNewEntity(newEntity); //And then parse the instancebaseline. //basically you could call //newEntity.ApplyUpdate(parser.instanceBaseline[entityClass]; //This code below is just faster, since it only parses stuff once //which is faster. object[] fastBaseline; if (parser.PreprocessedBaselines.TryGetValue(serverClassID, out fastBaseline)) { PropertyEntry.Emit(newEntity, fastBaseline); } else { var preprocessedBaseline = new List <object>(); if (parser.instanceBaseline.ContainsKey(serverClassID)) { using (var collector = new PropertyCollector(newEntity, preprocessedBaseline)) using (var bitStream = BitStreamUtil.Create(parser.instanceBaseline[serverClassID])) newEntity.ApplyUpdate(bitStream); } parser.PreprocessedBaselines.Add(serverClassID, preprocessedBaseline.ToArray()); } return(newEntity); }
private static void ProcessPacket(byte[] bytes) { var length = bytes.Length; uint seq, ack; byte flags; using (var stream = BitStreamUtil.Create(bytes)) { seq = stream.ReadInt(32); ack = stream.ReadInt(32); flags = stream.ReadByte(); ushort checksum = (ushort)stream.ReadInt(16); stream.BeginChunk((length - 11) * 8); ushort computed = CrcUtils.Compute16(stream); stream.EndChunk(); if (checksum != computed) { //Console.WriteLine( // "failed checksum:" // + "recv seq {0} ack {1} flags {2:x} checksum {3:x} computed {4:x}", // seq, ack, flags, checksum, computed); return; } } var remaining = new byte[length - 11]; Array.Copy(bytes, 11, remaining, 0, length - 11); using (var stream = BitStreamUtil.Create(remaining)) { byte reliableState = stream.ReadByte(); if ((flags & 0x10) == 0x10) { //Console.WriteLine( // "choke {0}: recv seq {1} ack {2} flags {3:x}", // stream.ReadByte(), seq, ack, flags); return; } if (seq < sequenceIn) { // We no longer care. //Console.WriteLine("dropped: recv seq {0} ack {1}", seq, ack); return; } if ((flags & (uint)PacketFlags.IsReliable) != 0) { return; } //filter2++; //Console.WriteLine($"filter2: {filter2}"); try { stream.BeginChunk((remaining.Length - 1) * 8); DemoPacketParser.ParsePacket(stream, demoParser); stream.EndChunk(); demoParser.ForceTick(true); } catch { } lastAckRecv = ack; sequenceIn = seq; } }
public void ParseStringTableMessage(CSVCMsg_CreateStringTable table, DemoParser parser) { using (IBitStream reader = BitStreamUtil.Create(table.string_data)) { if (reader.ReadBit()) { throw new NotImplementedException("Encoded with dictionaries, unable to decode"); } int nTemp = table.max_entries; int nEntryBits = 0; while ((nTemp >>= 1) != 0) { ++nEntryBits; } List <string> history = new List <string>(); int lastEntry = -1; for (int i = 0; i < table.num_entries; i++) { int entryIndex = lastEntry + 1; // read in the entity-index if (!reader.ReadBit()) { entryIndex = (int)reader.ReadInt(nEntryBits); } lastEntry = entryIndex; // Read the name of the string into entry. string entry = ""; if (entryIndex < 0 || entryIndex >= table.max_entries) { throw new InvalidDataException("bogus string index"); } if (reader.ReadBit()) { bool substringcheck = reader.ReadBit(); if (substringcheck) { int index = (int)reader.ReadInt(5); int bytestocopy = (int)reader.ReadInt(5); entry = history[index].Substring(0, bytestocopy); entry += reader.ReadString(1024); } else { entry = reader.ReadString(1024); } } if (entry == null) { entry = ""; } if (history.Count > 31) { history.RemoveAt(0); } // Read in the user data. byte[] userdata = new byte[0]; if (reader.ReadBit()) { if (table.user_data_fixed_size) { userdata = reader.ReadBits(table.user_data_size_bits); } else { int bytesToRead = (int)reader.ReadInt(14); userdata = reader.ReadBytes(bytesToRead); } } if (userdata.Length == 0) { break; } // Now we'll parse the players out of it. BinaryReader playerReader = new BinaryReader(new MemoryStream(userdata)); PlayerInfo info = PlayerInfo.ParseFrom(playerReader); UpdatePlayer(info, parser); } } }