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 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 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