def __init__(self, abspath): if hasattr(abspath, "read"): infile = abspath elif abspath.lower().endswith(".bz2"): infile = bz2.BZ2File(abspath, "r") else: infile = _io.open(abspath, 'r+b') if infile.read(8) != "PBUFDEM\0": raise InvalidDemo('malformed header') gio = bytearray(infile.read(4)) # LE uint file offset gio = sum(gio[i] << (i * 8) for i in range(4)) try: tell = infile.tell() infile.seek(gio) p, m = d_io.construct(infile).read() self.file_info = d_io.parse(p.kind, p.compressed, m) assert p.kind == pb_d.DEM_FileInfo infile.seek(tell) except EOFError: raise InvalidDemo('no end game summary') self.prologue = load(infile) self.io = infile self._tell = infile.tell()
def stream(self, tick=0, sparse=False): self.io.seek(self._tell) p = self.prologue fp, rem = scan(p, d_io.construct(self.io), tick=tick) w, m, st = reconstitute(fp, p.class_bits, p.recv_tables, p.string_tables) return Stream(p, self.io, w, m, st, rem, sparse=sparse)
def __init__(self, prologue, io, world, string_tables, rem, sparse=False): self.prologue = prologue self.demo_io = d_io.construct(io) self.world = world self.string_tables = string_tables self.sparse = sparse for peek, message in rem: pbmsg = d_io.parse(peek.kind, peek.compressed, message) self.advance(peek.tick, pbmsg)
def __init__(self, prologue, io, world, mods, sttabs, rem, sparse=False): self.prologue = prologue self.demo_io = d_io.construct(io) self.world = world self.modifiers = mods self.string_tables = sttabs self.sparse = sparse for p, pb in rem: self.advance(p.tick, pb)
def __init__(self, abspath): infile = _io.open(abspath, 'r+b') if infile.read(8) != "PBUFDEM\0": raise InvalidDemo('malformed header') gio = bytearray(infile.read(4)) # LE uint file offset gio = sum(gio[i] << (i * 8) for i in range(4)) try: tell = infile.tell() infile.seek(gio) p, m = d_io.construct(infile).read() self.file_info = d_io.parse(p.kind, p.compressed, m) assert p.kind == pb_d.DEM_FileInfo infile.seek(tell) except EOFError: raise InvalidDemo('no end game summary') self.prologue = load(infile) self.io = infile self._tell = infile.tell()
def stream(self, tick=0, sparse=False): self.io.seek(self._tell) args = fast_forward(self.prologue, d_io.construct(self.io), tick=tick) return Stream(self.prologue, self.io, *args, sparse=sparse)
def load(io, tick=0): demo_io = d_io.construct(io) prologue = id_prologue.construct(demo_io) # mash all packet svc messages together, then index them signon_packets = list(prologue.all_dem_signon_packet) data = ''.join([pb.data for _, pb in signon_packets]) packet = ie_packet.construct(p_io.construct(data)) # meta: file header _, pbmsg = prologue.dem_file_header file_header = FileHeader(*[getattr(pbmsg, a) for a in FileHeader._fields]) # meta: server info _, pbmsg = packet.svc_server_info server_info = ServerInfo(*[getattr(pbmsg, a) for a in ServerInfo._fields]) # meta: voice init _, pbmsg = packet.svc_voice_init voice_init = VoiceInit(*[getattr(pbmsg, a) for a in VoiceInit._fields]) # prologue: meta meta = Meta(file_header, server_info, voice_init) # prologue: send tables _, pbmsg = prologue.dem_send_tables _send_tables = ie_send_tables.construct(p_io.construct(pbmsg.data)) send_tables = c.OrderedDict() for pbmsg in [pb for _, pb in _send_tables.all_svc_send_table]: if pbmsg.is_end: break send_table = _parse_cdemo_send_table(pbmsg) send_tables[send_table.dt] = send_table # prologue: recv tables flattener = Flattener(send_tables) recv_tables = c.OrderedDict() _, pbmsg = prologue.dem_class_info class_info = c.OrderedDict() for cls in pbmsg.classes: _id, dt, name = str(cls.class_id), cls.table_name, cls.network_name class_info[_id] = (dt, name) for st in filter(test_needs_decoder, send_tables.values()): props = flattener.flatten(st) cls = next(_id for _id, (dt, _) in class_info.items() if dt == st.dt) recv_tables[cls] = dt_r.construct(st.dt, props) # prologue: string tables pbmsgs = [pb for _, pb in packet.all_svc_create_string_table] string_tables = _parse_all_csvc_create_string_tables(pbmsgs) # prologue: game event list _, pbmsg = packet.svc_game_event_list game_event_list = c.OrderedDict() for desc in pbmsg.descriptors: _id, name = desc.eventid, desc.name keys = [(k.type, k.name) for k in desc.keys] game_event_list[_id] = (name, keys) # prologue: class bits class_bits = server_info.max_classes.bit_length() return Prologue(meta, recv_tables, string_tables, game_event_list, class_bits)
def load(io, tick=0): demo_io = d_io.construct(io) prologue = i_p.construct(demo_io) # mash all packet svc messages together, then index them signon_packets = list(prologue.signon_packets) pbmsgs = [d_io.parse(p.kind, p.compressed, m) for p, m in signon_packets] data = ''.join([p.data for p in pbmsgs]) packet_io = p_io.construct(data) packet = i.construct(packet_io) # class info peek, message = prologue.class_info pbmsg = d_io.parse(peek.kind, peek.compressed, message) class_info = c.OrderedDict() for _c in pbmsg.classes: _id, dt, name = str(_c.class_id), _c.table_name, _c.network_name class_info[_id] = (dt, name) # send tables peek, message = prologue.send_tables pbmsg = d_io.parse(peek.kind, peek.compressed, message) send_tables = c.OrderedDict() for peek, message in p_io.construct(pbmsg.data): pbmsg = p_io.parse(peek.kind, message) if pbmsg.is_end: break send_table = _parse_cdemo_send_table(pbmsg) send_tables[send_table.dt] = send_table # recv tables flattener = Flattener(send_tables) recv_tables = c.OrderedDict() for st in filter(test_needs_decoder, send_tables.values()): props = flattener.flatten(st) cls = next(_id for _id, (dt, _) in class_info.items() if dt == st.dt) recv_tables[cls] = dt_r.construct(st.dt, props) # game event list peek, message = packet.find(pb_n.svc_GameEventList) pbmsg = p_io.parse(peek.kind, message) game_event_list = c.OrderedDict() for desc in pbmsg.descriptors: _id, name = desc.eventid, desc.name keys = [(k.type, k.name) for k in desc.keys] game_event_list[_id] = (name, keys) # string tables entries = packet.find_all(pb_n.svc_CreateStringTable) pbmsgs = [p_io.parse(p.kind, m) for p, m in entries] string_tables = _parse_all_csvc_create_string_tables(pbmsgs) # meta: file header peek, message = prologue.file_header pbmsg = d_io.parse(peek.kind, peek.compressed, message) file_header = FileHeader(*[getattr(pbmsg, a) for a in FileHeader._fields]) # meta: server_info peek, message = packet.find(pb_n.svc_ServerInfo) pbmsg = p_io.parse(peek.kind, message) server_info = ServerInfo(*[getattr(pbmsg, a) for a in ServerInfo._fields]) # meta: class bits class_bits = server_info.max_classes.bit_length() # meta: voice init peek, message = packet.find(pb_n.svc_VoiceInit) pbmsg = p_io.parse(peek.kind, message) voice_init = VoiceInit(*[getattr(pbmsg, a) for a in VoiceInit._fields]) meta = Meta(file_header, server_info, voice_init) return Prologue(meta, recv_tables, string_tables, game_event_list, class_bits)