def command_command_count_decrease( reader: ReplayReader) -> Dict[str, Union[str, int]]: return { "type": "command_count_decrease", "command_id": reader.read_uint(), "delta": reader.read_int() }
def command_set_command_type( reader: ReplayReader) -> Dict[str, Union[str, int]]: return { "type": "set_command_type", "command_id": reader.read_uint(), "target_id": reader.read_int() }
def parse( input_data: Union[RawIOBase, bytearray, bytes], parse_body: bool = True, **kwargs ) -> Dict[str, Any]: """ Parses replay :param (RawIOBase, bytearray, bytes) input_data: data source :param bool parse_body: define what to parse """ reader = ReplayReader(input_data, **kwargs) result = { "header": ReplayHeader(reader).to_dict(), "body_offset": reader.offset(), } if parse_body: body_parser = ReplayBody(reader, **kwargs) body_parser.parse() result["body"] = body_parser.get_body() result["messages"] = body_parser.get_messages() result["desync_ticks"] = body_parser.get_desync_ticks() result["last_tick"] = body_parser.tick return result
def _parse_formation(reader: ReplayReader) -> TYPE_FORMATION: formation = reader.read_int() if formation != -1: w = reader.read_float() position = _read_vector(reader) scale = reader.read_float() return {"w": w, "position": position, "scale": scale} return None
def command_process_info_pair(reader: ReplayReader) -> Dict[str, Union[int, str]]: entity_id = reader.read_int() arg1 = reader.read_string() arg2 = reader.read_string() return {"type": "process_info_pair", "entity_id": entity_id, "arg1": arg1, "arg2": arg2}
def command_create_unit(reader: ReplayReader) -> Dict[str, Union[int, str, TYPE_VECTOR]]: army_index = reader.read_byte() blueprint_id = reader.read_string() x, y, heading = _read_vector(reader) return {"type": "create_unit", "army_index": army_index, "blueprint_id": blueprint_id, "vector": (x, y, heading)}
def command_verify_checksum( reader: ReplayReader) -> Dict[str, Union[str, int]]: checksum = "".join("{:02X}".format(ord(reader.read(1))) for _ in range(16)) return { "type": "verify_checksum", "checksum": checksum, "tick": reader.read_uint() }
def _parse_target(reader: ReplayReader) -> TYPE_TARGET: target = reader.read_byte() entity_id = None position = None if target == TargetType.Entity: entity_id = reader.read_int() elif target == TargetType.Position: position = _read_vector(reader) return {"target": target, "entity_id": entity_id, "position": position}
def command_debug_command(reader: ReplayReader) -> Dict[str, Union[str, TYPE_VECTOR, int, TYPE_ENTITY_IDS_SET]]: debug_command = reader.read_string() vector = _read_vector(reader) focus_army_index = reader.read_byte() unit_ids = _parse_entity_ids_set(reader) return {"type": "debug_command", "debug_command": debug_command, "vector": vector, "focus_army_index": focus_army_index, "entity_ids_set": unit_ids}
def _parse_command_data(reader: ReplayReader) -> TYPE_COMMAND_DATA: command_id = reader.read_int() arg1 = reader.read(4) command_type = reader.read_byte() arg2 = reader.read(4) target = _parse_target(reader) arg3 = reader.read(1) formation = _parse_formation(reader) blueprint_id = reader.read_string() arg4 = reader.read(12) arg5 = None cells = reader.read_lua() if cells: arg5 = reader.read(1) return { "command_id": command_id, "command_type": command_type, "target": target, "formation": formation, "blueprint_id": blueprint_id, "cells": cells, "arg1": arg1, "arg2": arg2, "arg3": arg3, "arg4": arg4, "arg5": arg5 }
def test_continuous_parse_command_by_command(replays): sender_stream = continuous_parse(replays, parse_header=True, parse_commands={ CommandStates.Advance, CommandStates.SetCommandSource, CommandStates.CommandSourceTerminated, CommandStates.VerifyChecksum, }) server_body_buffer = BytesIO() server_body_parser = ReplayBody(ReplayReader(server_body_buffer), parse_commands={x for x in range(7)}) header = next(sender_stream) assert "header" in header assert "body_offset" in header for tick, command_type, data in sender_stream: times = 0 for tick2, command_type2, data2 in server_body_parser.continuous_parse( data): assert tick == tick2 assert command_type == command_type2 assert data == data2 times += 1 assert times == 1
def __init__(self, reader: ReplayReader, stop_on_desync: bool = False, parse_commands: set = None, store_body: bool = False, **kwargs) -> None: """ :param ReplayReader reader: Handles basic operations on stream :param bool stop_on_desync: stops parsing at first desync :param set parse_commands: set or list of commands ids to parse, list is defined in from `replay_parser.commands.COMMAND_PARSERS`. Important: you can't detect desyncs, if you won't have CommandStates.VerifyChecksum :param bool store_body: stores every next tick data of replay to content to self.body. To get list of commands use get_body """ self.replay_reader: ReplayReader = reader self.command_reader: ReplayReader = ReplayReader() self.body: List = [] self.last_players_tick: Dict = {} self.desync_ticks: List = [] self.messages: Dict = {} self.tick: int = 0 self.tick_data: Dict = {} self.player_id: int = -1 self.previous_tick = -1 self.previous_checksum = None self.stop_on_desync = bool(stop_on_desync) self.parse_commands = set(parse_commands or set()) self.store_body = bool(store_body)
def command_lua_sim_callback(reader: ReplayReader) -> Dict[str, Union[str, TYPE_LUA, bytes]]: lua_name = reader.read_string() lua = reader.read_lua() size = None data = None if lua: size = reader.read_int() data = reader.read(4 * size) else: data = reader.read(4 + 3) return {"type": "lua_sim_callback", "lua_name": lua_name, "lua": lua, "size": size, "data": data}
def command_warp_entity( reader: ReplayReader) -> Dict[str, Union[str, TYPE_VECTOR]]: return { "type": "warp_entity", "entity_id": reader.read_int(), "vector": _read_vector(reader) }
def command_create_prop( reader: ReplayReader) -> Dict[str, Union[str, TYPE_VECTOR]]: return { "type": "create_prop", "name": reader.read_string(), "vector": _read_vector(reader) }
def command_set_command_target( reader: ReplayReader) -> Dict[str, Union[int, TYPE_TARGET]]: return { "type": "set_command_target", "command_id": reader.read_uint(), "target": _parse_target(reader) }
def command_set_command_cells(reader: ReplayReader) -> Dict[str, Union[str, int, TYPE_LUA]]: command_id = reader.read_int() cells = reader.read_lua() if cells: reader.read(1) vector = (reader.read_float(), reader.read_float(), reader.read_float()) return {"type": "set_command_cells", "command_id": command_id, "cells": cells, "vector": vector}
def continuous_parse( input_data: Union[RawIOBase, bytearray, bytes], parse_header: bool = False, **kwargs ) -> Iterator[Union[Dict[str, Union[int, Dict]], Tuple]]: """ Used for continuous replay body parsing, when header is not needed. Returns `ReplayBody` parser, that has `continuous_parse`. Example: :: >>> reader = ReplayReader(FileIO(input_data)) >>> ReplayHeader(reader) # jump over header >>> for row in ReplayBody(reader).continuous_parse(): pass """ reader = ReplayReader(input_data, **kwargs) if parse_header: yield { "header": ReplayHeader(reader).to_dict(), "body_offset": reader.offset(), } for result in ReplayBody(reader, **kwargs).continuous_parse(): yield result
def _read_vector(reader: ReplayReader) -> TYPE_VECTOR: return reader.read_float(), reader.read_float(), reader.read_float()
def command_destroy_entity(reader: ReplayReader) -> Dict[str, int]: return {"type": "destroy_entity", "entity_id": reader.read_int()}
def command_execute_lua_in_sim(reader: ReplayReader) -> Dict[str, str]: return {"type": "execute_lua_in_sim", "lua": reader.read_string()}
def command_remove_from_queue(reader: ReplayReader) -> Dict[str, int]: return { "type": "remove_from_queue", "command_id": reader.read_uint(), "unit_id": reader.read_int() }
def command_set_command_source(reader: ReplayReader) -> Dict[str, int]: return {"type": "set_command_source", "player_id": reader.read_byte()}
def _parse_entity_ids_set(reader: ReplayReader) -> TYPE_ENTITY_IDS_SET: units_number = reader.read_uint() unit_ids = [] for i in range(units_number): unit_ids.append(reader.read_uint()) return {"units_number": units_number, "unit_ids": unit_ids}
def __init__(self, reader: ReplayReader) -> None: self.version = reader.read_string() reader.read(3) self.replay_version, self.map_name = reader.read_string().split( "\r\n", 1) reader.read(4) mods_size = reader.read_int() self.mods = reader.read_lua() scenario_size = reader.read_int() self.scenario = reader.read_lua() sources_number = reader.read_byte() self.players = {} for i in range(sources_number): name = reader.read_string() player_id = reader.read_int() self.players[name] = str(player_id) self.cheats_enabled = reader.read_bool() self.numbers_of_armies = reader.read_byte() self.armies = {} for i in range(self.numbers_of_armies): player_data_size = reader.read_int() player_data = reader.read_lua() player_source = reader.read_byte() self.armies[player_source] = player_data if player_source != 255: reader.read(1) self.random_seed = reader.read_float()
def command_advance(reader: ReplayReader) -> Dict[str, int]: return {"type": "advance", "advance": reader.read_uint()}