demoparser package¶
Subpackages¶
Submodules¶
demoparser.bitbuffer module¶
-
class
demoparser.bitbuffer.
Bitbuffer
(data)¶ Bases:
object
Parse a stream of bits from a series of bytes.
Data is cast to unsigned int* and read one unsigned int at a time. As an unsigned int is 32 bits this has the effect of reading 4 bytes at once. Reads can span integer boundaries and the consecutive integers will be merged correctly.
Parameters: data (bytes) – Data to parse bit-by-bit Example: >>> buf = Bitbuffer(b'\x11\x22') >>> buf.read_uint_bits(8) 17 >>> buf.read_uint_bits(8) 34
-
next_dword
(self) → unsigned int¶ Move to the next 32-bit integer in the stream.
Returns: unsigned int
-
read_bit
(self) → unsigned char¶ Read a single bit.
Returns: one bit
-
read_bit_cell_coord
(self, unsigned int bits, unsigned int coord_type) → float¶ Read a cell coordinate.
A cell coordinate is a float which has been compressed. The number of bits indicates maximum value.
Parameters: - bits (unsigned int) – number of bits to read
- coord_type (unsigned int) – level of precision
Returns: float
-
read_bit_coord
(self) → float¶ Read a float and treat as a world coordinate.
Returns: float
-
read_bit_normal
(self) → float¶
-
read_sint_bits
(self, unsigned int bits) → int¶ Read a signed integer of bits bits.
First an unsigned integer is read then a two’s complement integer is computed.
Parameters: bits (unsigned int) – Number of bits to read Returns: int
-
read_string
(self, int length=-1) → str¶ Read a string.
If length is not provided characters are read until \0 is reached. If length is provided then exactly length bytes will be read and the string may not be zero-terminated.
Returns: str
-
read_uint_bits
(self, unsigned int bits) → unsigned int¶ Read the unsigned integer represented by bits bits.
If the number of bits remaining in the current word is not enough then the next word will be read.
Parameters: bits (unsigned int) – Number of bits to read Returns: unsigned int
-
read_user_data
(self, unsigned int bits) → bytes¶ Read user data.
Parameters: bits (unsigned int) – Number of bits to read Returns: bytes
-
read_var_int
(self) → unsigned int¶ Read a variable length integer.
Returns: unsigned int
-
demoparser.bytebuffer module¶
-
class
demoparser.bytebuffer.
Bytebuffer
(data)[source]¶ Bases:
object
Parse a stream of bytes from a .DEM file.
This class provdes convenience methods for parsing .DEM files. It handles unpacking bytes to different data types, reading variable-length integers, reading strings, and creating Bitbuffers.
Parameters: data (bytes) – Buffer data Example: >>> b = Bytebuffer(b'\x00\xf1\xaa') >>> b.read(1) 0 >>> b.read_short() 43761
-
read_bitstream
()[source]¶ Create a Bitbuffer from a number of bytes.
The numbers of bytes to include in the Bitbuffer is read. Then that number of bytes is used to instantiate a Bitbuffer instance.
Returns: Bitbuffer instance
-
read_command_data
()[source]¶ Read command info structure.
This is not used by the parser.
Returns: bytes
-
read_command_header
()[source]¶ Read the 6 byte command header.
See CommandHeader description for more details.
Returns: CommandHeader instance
-
read_packet_data
()[source]¶ Read a demo packet.
Each packet consists of a command and data. The command is an ID that references either a NET_ or SVC_ class defined in netmessages.proto.
The data is used to instantiate the class referred to by command.
Returns: Tuple (command, data)
-
read_raw_data
()[source]¶ Read number of bytes specified by a signed int.
First a 32-bit signed integer is read, then that number of bytes is read from the stream.
Returns: Tuple (bytes_read, bytes)
-
read_sequence_data
()[source]¶ Read two integers.
This data is not used by the parser.
Returns: Tuple of integers
-
read_string
()[source]¶ Read a zero-terminated string.
Reads characters until \0 is encountered.
Returns: str
-
demoparser.consts module¶
demoparser.demofile module¶
-
exception
demoparser.demofile.
ClassNotFoundError
¶ Bases:
Exception
-
exception
demoparser.demofile.
CommandError
¶ Bases:
Exception
-
class
demoparser.demofile.
DemoFile
¶ Bases:
object
-
add_callback
(self, event, func)¶ Register a callback function for an event.
-
class_by_message_name
(self, str name)¶ Find a Protobuf class for the given message.
The generated Protobuf modules create classes like C<type>Msg_<name>. For a given message name this method will convert the name to a Protobuf class name and return it.
Returns: Protobuf class
-
collect_exclusions
(self, table) → list¶
-
collect_props
(self, table, list exclusions) → list¶ Collect table properties which are not excluded.
If a property is part of an array or is flagged as excluded it will not be returned. Otherwise all properties are collected and data table entries are recursively collected.
Returns: Flat list of all table properties
-
create_string_table
(self, msg) → void¶ Create a string table.
A string table consists of a name and a list of entries. The maximum number of entries is created and initialized to None. This is done because future messages that update or reference string table entries do so by index.
Each entry is a dictionary with two keys, entry and user_data. Entry is the name of the entry and user_data contains binary data related to the entry. In the ‘user_info’ string table user_data describes a UserInfo object.
-
current_tick
¶ current_tick: ‘unsigned int’
-
data_table_by_name
(self, str name)¶
-
emit
(self, str event, args=None) → void¶ Run callback functions for an event.
Each time an event is trigged each registered callback will be called with the arguments provided to this method.
-
entities
¶ entities: object
-
flatten_data_table
(self, table)¶ Flatten a data table.
Data tables can contain other data tables as entries. This method collects all properties and sorts them by priority.
Returns: Flattened data table
-
handle_data_table
(self, cmd_header) → void¶ Create data tables.
Each entity class maintains a data table that describes how to encode each of its properties. These tables are called Send Tables and and genrally have names like DT_EntityClassName (DT_CSPlayer, DT_Weapon, etc.)
Emits: baseline_create, datatable_ready.
-
handle_demo_packet
(self, cmd_header) → void¶ Handle demo packet.
Demo packets are of type SVC_ or NET_. This method instantiates the appropriate protobuf class and triggers an event.
Emits: demo_packet.
-
handle_game_event
(self, msg) → void¶ Handle game event.
A game event message just contains an event ID. The corresponding event can be found in self.game_events. An event is then triggered for the game event itself.
Emits: game_event.
-
handle_game_event_list
(self, msg) → void¶ Create game event list.
This message contains a list of game events present in this replay. Later, when a game event occurs its ID can be used to get a game event object.
-
handle_packet_entities
(self, msg) → void¶ Create or update an entity.
Entities represent in-game objects and are networked (i.e. their state is maintained on the server and updates are sent to one or more clients).
Entities have a class ID which defines the type of entity it is. The class ID is also used to find the correct instance baseline. Instance baselines serve as default values when entities are created.
-
handle_string_table
(self, str table_name, Bitbuffer buf) → void¶ Populate a string table.
Emits: string_table_update.
-
handle_string_tables
(self, cmd_header) → void¶
-
handle_user_message
(self, msg) → void¶ Handle user message.
A user message is stuff like text chat, voice chat, radio messages, etc.
Emits: user_message
-
instance_baselines
¶ instance_baselines: object
-
parse
(self) → void¶ Parse the demofile.
Emits: tick_start, tick_end, end Raises: CommandError
-
parse_instance_baseline
(self, Bitbuffer buf, unsigned int class_id)¶ Parse baseline.
Baselines serve as default data for entities of type class_id.
Parameters: - buf (Bitbuffer) – Data to read
- class_id (unsigned int) – Server class ID
Returns: baseline for class_id.
-
parse_string_table_update
(self, Bitbuffer buf, table, unsigned int num_entries, unsigned int max_entries, unsigned int user_data_bits, bool user_data_fixed_size) → void¶ Update a string table.
A single update message can update multiple table entries. Both the entry name and the user data can be updated.
Emits: string_table_update.
-
read_new_entity
(self, Bitbuffer buf, entity) → void¶ Read entity data.
A list of updates is computed and for each one of those the appropritate property of the entity instance is updated.
Emits: change
-
table_by_name
(self, str name)¶
-
table_updated
(self, table, index, entry, user_data) → void¶ Update an instance baseline.
Each time a string table is updated this method is called. If a baseline doesn’t exist yet it is added to the list of pending baselines which are handled later when the correct server class is created. Server classes are created by DATATABLES commands.
-
update_string_table
(self, msg) → void¶
-
demoparser.fields module¶
-
class
demoparser.fields.
FixedLengthString
(length, **kwargs)[source]¶ Bases:
suitcase.fields.BaseField
A string of a fixed number of bytes.
The specified number of bytes are read and then any null bytes are stripped from the result.
Parameters: length (Integer) – Number of bytes to read. -
bytes_required
¶ Number of bytes to read from stream.
-
demoparser.props module¶
-
class
demoparser.props.
Decoder
¶ Bases:
object
Decode a property.
Properties of server classes are encoded differently depending on the type of the property.
Parameters: - buf (Bitbuffer) – Raw buffer data used for decoding
- prop (object) – Property to decode
-
decode
(self)¶
-
decode_array
(self) → list¶ Decode array.
Arrays contain one or more elements (including arrays) which are recursively decoded.
-
decode_float
(self) → float¶ Decode a floating point value.
First the value is decoded as a special float. If that returns NaN then a normal floating point value is calculated.
-
decode_int
(self) → long¶ Decode an integer.
Reads the number of bits specified in the num_bits field of the property. If the property has the SPROP_UNSIGNED flag set the number will be read as an unsigned int.
-
decode_int64
(self)¶ Decode a 64-bit integer.
CS:GO demos don’t appear to contain 64-bit ints.
-
decode_special_float
(self) → float¶ Decode a float
A special float is a float which is interpreted in some special way. The treatement is determined by the property’s flags.
Flag Explanation COORD Treat the float or vector as a world coordinate. COORD_MP Like COORD but special handling for multi-player games. COORD_MP_LOWPRECISION Like COORD_MP but the fractional component uses 3 bits instead of 5. COORD_MP_INTEGRAL Like COORD_MP but coordinates are rounded to integral boundaries. NOSCALE Don’t scale floating-point value to a range. NORMAL Treat vector as a normal. CELL_COORD Like COORD but has special encoding for cell coordinates which can’t be negative. CELL_COORD_LOWPRECISION Like CELL_COORD but fractional part uses 3 bits instead of 5. CELL_COORD_INTEGRAL Like CELL_COORD but coordinates are rounded to integral boundaries.
-
decode_string
(self) → str¶ Decode a string.
A fixed number of bits are read which may be more than the string’s length (i.e. some bits are read after a 0 is encountered).
Returns: str
-
decode_vector
(self) → dict¶ Decode a vector.
Returns: vector
-
decode_vector_xy
(self) → dict¶ Decode a two-element vector.
This only reads the X and Y coordinates for the vector and sets the Z coordinate to 0.0
Returns: vector
demoparser.structures module¶
-
class
demoparser.structures.
CommandHeader
(**kwargs)[source]¶ Bases:
suitcase.structure.Structure
Header for each command packet.
The header has the following format:
Byte Description 0 Command ID 1-4 Current tick 5 Player ID
-
class
demoparser.structures.
DemoHeader
(**kwargs)[source]¶ Bases:
suitcase.structure.Structure
1072 Byte header for .DEM file.
This header has the following format:
Byte Description 0-7 Fixed string ‘HL2DEMO0’. 8-11 Demo file protocol version. 12-15 Network protocol version. 16-275 Server name. 276-535 Name of client who recorded the demo. 536-795 Map name. 796-1055 Game directory. 1056-1059 Playback time in seconds. 1060-1063 Number of ticks in demo. 1064-1067 Number of frames in demo. 1068-1071 Length of signon data.
-
class
demoparser.structures.
UserInfo
(**kwargs)[source]¶ Bases:
suitcase.structure.Structure
Player data.
This structure has the following format:
Byte Description 0-7 Version. Same for all players. 8-15 xuid. Some sort of unique ID. 15-142 Player name. 143-146 Local server user ID. 147-179 GUID 180-183 Friend’s ID. 184-312 Friend’s Name. 313 Is player a bot? 314 Is player an HLTV proxy? 314-329 Custom files CRC. 330 Numbre of files downloaded by server. 331-335 Entity index. 336-340 No idea.
demoparser.util module¶
-
demoparser.util.
parse_entity_update
(Bitbuffer buf, server_class) → list¶ Parse entity updates.
First a list of all property indices is generated. For each property referenced by those indices the property’s value is decoded. The list of properties and their decoded values are collected and returned.
Returns: List of updated properties
-
demoparser.util.
read_field_index
(Bitbuffer buf, int last_index, bool new_way) → int¶ Read index.
This method determines the next index into the property list for a server class.
Returns: Next index or -1 if no more indices