def __call__(self, data, replay): # The replay.message.events file is a single long list containing three # different element types (minimap pings, player messages, and some sort # of network packets); each differentiated by flags. data = BitPackedDecoder(data) pings = list() messages = list() packets = list() frame = 0 while not data.done(): # All the element types share the same time, pid, flags header. frame += data.read_frames() pid = data.read_bits(5) t = data.read_bits(3) flags = data.read_uint8() if flags in (0x83, 0x89): # We need some tests for this, probably not right x = data.read_uint32() y = data.read_uint32() pings.append(PingEvent(frame, pid, flags, x, y)) elif flags == 0x80: info = data.read_bytes(4) packets.append(PacketEvent(frame, pid, flags, info)) elif flags & 0x80 == 0: lo_mask = 2**self.TARGET_BITS - 1 hi_mask = 0xFF ^ lo_mask target = flags & lo_mask extension = (flags & hi_mask) << 3 length = data.read_uint8() text = data.read_bytes(length + extension) messages.append( ChatEvent(frame, pid, flags, target, text, (flags, lo_mask, hi_mask, length, extension))) return AttributeDict(pings=pings, messages=messages, packets=packets)
def __call__(self, data, replay): # The replay.message.events file is a single long list containing three # different element types (minimap pings, player messages, and some sort # of network packets); each differentiated by flags. data = BitPackedDecoder(data) pings = list() messages = list() packets = list() frame = 0 while not data.done(): # All the element types share the same time, pid, flags header. frame += data.read_frames() pid = data.read_bits(5) t = data.read_bits(3) flags = data.read_uint8() if flags in (0x83,0x89): # We need some tests for this, probably not right x = data.read_uint32() y = data.read_uint32() pings.append(PingEvent(frame, pid, flags, x, y)) elif flags == 0x80: info = data.read_bytes(4) packets.append(PacketEvent(frame, pid, flags, info)) elif flags & 0x80 == 0: lo_mask = 2**self.TARGET_BITS-1 hi_mask = 0xFF ^ lo_mask target = flags & lo_mask extension = (flags & hi_mask) << 3 length = data.read_uint8() text = data.read_bytes(length + extension) messages.append(ChatEvent(frame, pid, flags, target, text, (flags, lo_mask, hi_mask, length, extension))) return AttributeDict(pings=pings, messages=messages, packets=packets)
def __init__(self, summary_file, filename=None, lang='enUS', **options): super(GameSummary, self).__init__(summary_file, filename, lang=lang, **options) #: A dict of team# -> teams self.team = dict() #: A list of teams self.teams = list() #: Players, a dict of :class`PlayerSummary` from the game self.players = list() self.observers = list() #: Game start and end times self.start_time = None self.end_time = None self.winners = list() self.player = dict() self.settings = dict() self.player_stats = dict() self.player_settings = defaultdict(dict) self.build_orders = defaultdict(list) self.image_urls = list() self.localization_urls = dict() self.lobby_properties = dict() self.lobby_player_properties = dict() self.game_type = str() self.real_type = str() # The first 16 bytes appear to be some sort of compression header buffer = BitPackedDecoder(zlib.decompress(summary_file.read()[16:])) # TODO: Is there a fixed number of entries? # TODO: Maybe the # of parts is recorded somewhere? self.parts = list() while not buffer.done(): self.parts.append(buffer.read_struct()) self.end_time = datetime.utcfromtimestamp(self.parts[0][8]) self.game_speed = LOBBY_PROPERTIES[0xBB8][1][self.parts[0][0] [1].decode('utf8')] self.game_length = utils.Length(seconds=self.parts[0][7]) self.real_length = utils.Length( seconds=int(self.parts[0][7] / GAME_SPEED_FACTOR[self.game_speed])) self.start_time = datetime.utcfromtimestamp(self.parts[0][8] - self.real_length.seconds) self.load_translations() self.load_map_info() self.load_settings() self.load_player_stats() self.load_players() dependencies = [sheet[1] for sheet in self.lang_sheets['enUS']] if 'Swarm (Mod)' in dependencies: self.expansion = 'HotS' elif 'Liberty (Mod)' in dependencies: self.expansion = 'WoL' else: self.expansion = '' self.game_type = self.settings['Teams'].replace(" ", "") self.real_type = utils.get_real_type(self.teams) # The s2gs file also keeps reference to a series of s2mv files # Some of these appear to be encoded bytes and others appear to be # the preview images that authors may bundle with their maps. self.s2mv_urls = [ str(utils.DepotFile(file_hash)) for file_hash in self.parts[0][6][7] ]
def __init__(self, summary_file, filename=None, lang='enUS', **options): super(GameSummary, self).__init__(summary_file, filename, lang=lang, **options) #: A dict of team# -> teams self.team = dict() #: A list of teams self.teams = list() #: Players, a dict of :class`PlayerSummary` from the game self.players = list() self.observers = list() #: Game start and end times self.start_time = None self.end_time = None self.winners = list() self.player = dict() self.settings = dict() self.player_stats = dict() self.player_settings = defaultdict(dict) self.build_orders = defaultdict(list) self.image_urls = list() self.localization_urls = dict() self.lobby_properties = dict() self.lobby_player_properties = dict() self.game_type = str() self.real_type = str() # The first 16 bytes appear to be some sort of compression header buffer = BitPackedDecoder(zlib.decompress(summary_file.read()[16:])) # TODO: Is there a fixed number of entries? # TODO: Maybe the # of parts is recorded somewhere? self.parts = list() while not buffer.done(): self.parts.append(buffer.read_struct()) self.end_time = datetime.utcfromtimestamp(self.parts[0][8]) self.game_speed = LOBBY_PROPERTIES[0xBB8][1][self.parts[0][0][1].decode('utf8')] self.game_length = utils.Length(seconds=self.parts[0][7]) self.real_length = utils.Length(seconds=int(self.parts[0][7]/GAME_SPEED_FACTOR[self.game_speed])) self.start_time = datetime.utcfromtimestamp(self.parts[0][8] - self.real_length.seconds) self.load_translations() self.load_map_info() self.load_settings() self.load_player_stats() self.load_players() dependencies = [sheet[1] for sheet in self.lang_sheets['enUS']] if 'Swarm (Mod)' in dependencies: self.expansion = 'HotS' elif 'Liberty (Mod)' in dependencies: self.expansion = 'WoL' else: self.expansion = '' self.game_type = self.settings['Teams'].replace(" ", "") self.real_type = utils.get_real_type(self.teams) # The s2gs file also keeps reference to a series of s2mv files # Some of these appear to be encoded bytes and others appear to be # the preview images that authors may bundle with their maps. self.s2mv_urls = [str(utils.DepotFile(file_hash)) for file_hash in self.parts[0][6][7]]