def do_info(self, **kwargs): """Add informational item to the minutes.""" m = items.Info(**kwargs) self.additem(m)
def __init__(self, map_path): # default list of item types for type_ in ITEM_TYPES: if type_ != 'version' and type_ != 'layer': setattr(self, ''.join([type_, 's']), []) path, filename = os.path.split(map_path) self.name, extension = os.path.splitext(filename) if extension == '': self.map_path = os.extsep.join([map_path, 'map']) elif extension != ''.join([os.extsep, 'map']): raise TypeError('Invalid file') else: self.map_path = map_path with open(self.map_path, 'rb') as f: self.f = f self.header = Header(f) self.item_types = [] for i in range(self.header.num_item_types): val = unpack('3i', f.read(12)) self.item_types.append({ 'type': val[0], 'start': val[1], 'num': val[2], }) fmt = '{0}i'.format(self.header.num_items) self.item_offsets = unpack(fmt, f.read(self.header.num_items * 4)) fmt = '{0}i'.format(self.header.num_raw_data) self.data_offsets = unpack(fmt, f.read(self.header.num_raw_data * 4)) # check version item_size, version_item = self.find_item(f, ITEM_VERSION, 0) fmt = '{0}i'.format(item_size/4) version = unpack(fmt, version_item)[0] # we only expect 1 element here if version != 1: raise ValueError('Wrong version') # load items # begin with map info item = self.find_item(f, ITEM_INFO, 0) if item is not None: item_size, item_data = item fmt = '{0}i'.format(item_size/4) item_data = unpack(fmt, item_data) version, author, map_version, credits, \ license = item_data[:items.Info.type_size] if author > -1: author = decompress(self.get_compressed_data(f, author))[:-1] else: author = None if map_version > -1: map_version = decompress(self.get_compressed_data(f, map_version))[:-1] else: map_version = None if credits > -1: credits = decompress(self.get_compressed_data(f, credits))[:-1] else: credits = None if license > -1: license = decompress(self.get_compressed_data(f, license))[:-1] else: license = None self.info = items.Info(author=author, map_version=map_version, credits=credits, license=license) else: self.info = None # load images start, num = self.get_item_type(ITEM_IMAGE) for i in range(num): item = self.get_item(f, start+i) item_size, item_data = item fmt = '{0}i'.format(item_size/4) item_data = unpack(fmt, item_data) version, width, height, external, image_name, \ image_data = item_data[:items.Image.type_size] external = bool(external) name = decompress(self.get_compressed_data(f, image_name))[:-1] data = decompress(self.get_compressed_data(f, image_data)) if not external else None image = items.Image(external=external, name=name, data=data, width=width, height=height) self.images.append(image) # load groups group_item_start, group_item_num = self.get_item_type(ITEM_GROUP) for i in range(group_item_num): item_size, item_data = self.get_item(f, group_item_start+i) fmt = '{0}i'.format(item_size/4) item_data = unpack(fmt, item_data) version, offset_x, offset_y, parallax_x, parallax_y, \ start_layer, num_layers, use_clipping, clip_x, clip_y, \ clip_w, clip_h = item_data[:items.Group.type_size-3] if version >= 3: data = item_data[items.Group.type_size-3:items.Group.type_size] group_name = ints_to_string(data) or None else: group_name = None start_layer, num_layers = item_data[5:7] # load layers in group layer_item_start, layer_item_num = self.get_item_type(ITEM_LAYER) layers = [] for j in range(num_layers): item_size, item_data = self.get_item(f, layer_item_start+start_layer+j) fmt = '{0}i'.format(item_size/4) item_data = unpack(fmt, item_data) layer_version, type_, flags = item_data[:items.Layer.type_size] detail = True if flags else False if type_ == LAYERTYPE_TILES: type_size = items.TileLayer.type_size color = 4*[0] version, width, height, game, color[0], color[1], \ color[2], color[3], color_env, color_env_offset, \ image_id, data = item_data[3:type_size-3] name = None if version >= 3: name = ints_to_string(item_data[type_size-3:type_size]) or None tile_list = [] if game == 8: # Hack for front layer if version >= 3: tile_data = item_data[items.TileLayer.type_size+2] else: tile_data = item_data[items.TileLayer.type_size-1] tile_data = decompress(self.get_compressed_data(f, tile_data)) else: tile_data = decompress(self.get_compressed_data(f, data)) for i in xrange(0, len(tile_data), 4): tile_list.append(tile_data[i:i+4]) tiles = items.TileManager(data=tile_list) tele_tiles = None speedup_tiles = None if game == 2: tele_list = [] if version >= 3: # num of tele data is right after the default type length if len(item_data) > items.TileLayer.type_size: # some security tele_data = item_data[items.TileLayer.type_size] if tele_data > -1 and tele_data < self.header.num_raw_data: tele_data = decompress(self.get_compressed_data(f, tele_data)) for i in xrange(0, len(tele_data), 2): tele_list.append(tele_data[i:i+2]) tele_tiles = items.TileManager(data=tele_list, _type=1) else: # num of tele data is right after num of data for old maps if len(item_data) > items.TileLayer.type_size-3: # some security tele_data = item_data[items.TileLayer.type_size-3] if tele_data > -1 and tele_data < self.header.num_raw_data: tele_data = decompress(self.get_compressed_data(f, tele_data)) for i in xrange(0, len(tele_data), 2): tele_list.append(tele_data[i:i+2]) tele_tiles = items.TileManager(data=tele_list, _type=1) elif game == 4: speedup_list = [] if version >= 3: # num of speedup data is right after tele data if len(item_data) > items.TileLayer.type_size+1: # some security speedup_data = item_data[items.TileLayer.type_size+1] if speedup_data > -1 and speedup_data < self.header.num_raw_data: speedup_data = decompress(self.get_compressed_data(f, speedup_data)) for i in xrange(0, len(speedup_data), 4): speedup_list.append(speedup_data[i:i+4]) speedup_tiles = items.TileManager(data=speedup_list, _type=2) else: # num of speedup data is right after tele data if len(item_data) > items.TileLayer.type_size-2: # some security speedup_data = item_data[items.TileLayer.type_size-2] if speedup_data > -1 and speedup_data < self.header.num_raw_data: speedup_data = decompress(self.get_compressed_data(f, speedup_data)) for i in xrange(0, len(speedup_data), 4): speedup_list.append(speedup_data[i:i+4]) speedup_tiles = items.TileManager(data=speedup_list, _type=2) layer = items.TileLayer(width=width, height=height, name=name, detail=detail, game=game, color=tuple(color), color_env=color_env, color_env_offset=color_env_offset, image_id=image_id, tiles=tiles, tele_tiles=tele_tiles, speedup_tiles=speedup_tiles) layers.append(layer) elif type_ == LAYERTYPE_QUADS: type_size = items.QuadLayer.type_size version, num_quads, data, image_id = item_data[3:type_size-3] name = None if version >= 2: name = ints_to_string(item_data[type_size-3:type_size]) or None quad_data = decompress(self.get_compressed_data(f, data)) quad_list = [] for k in xrange(0, len(quad_data), 152): quad_list.append(quad_data[k:k+152]) quads = items.QuadManager(data=quad_list) layer = items.QuadLayer(name=name, detail=detail, image_id=image_id, quads=quads) layers.append(layer) group = items.Group(name=group_name, offset_x=offset_x, offset_y=offset_y, parallax_x=parallax_x, parallax_y=parallax_y, use_clipping=use_clipping, clip_x=clip_x, clip_y=clip_y, clip_w=clip_w, clip_h=clip_h, layers=layers) self.groups.append(group) # load envpoints item_size, item = self.find_item(f, ITEM_ENVPOINT, 0) fmt = '{0}i'.format(item_size/4) item = unpack(fmt, item) type_size = items.Envpoint.type_size for i in range(len(item)/6): point = list(item[(i*6):(i*6+6)]) time, curvetype = point[:type_size-4] values = point[type_size-4:type_size] envpoint = items.Envpoint(time=time, curvetype=curvetype, values=values) self.envpoints.append(envpoint) # load envelopes start, num = self.get_item_type(ITEM_ENVELOPE) type_size = items.Envelope.type_size for i in range(num): item_size, item_data = self.get_item(f, start+i) fmt = '{0}i'.format(item_size/4) item_data = unpack(fmt, item_data) version, channels, start_point, \ num_point = item_data[:type_size-9] name = ints_to_string(item_data[type_size-9:type_size-1]) envpoints = self.envpoints[start_point:start_point+num_point] synced = True if version < 2 or item_data[type_size-1] else False envelope = items.Envelope(name=name, version=version, channels=channels, envpoints=envpoints, synced=synced) self.envelopes.append(envelope)