def from_block(self, block, offset): super(EscalatorOrStairwayDoor, self).from_block(block, offset) self.type = block[offset + 2] if not DoorType.is_valid(self.type): raise InvalidUserDataError("Door had invalid type of %#x" % self.type) self.direction = block.read_multi(offset + 3, 2) if not StairDirection.is_valid(self.direction): raise InvalidUserDataError("Door had invalid escalator/stairs direction of %#x" % self.direction)
def yml_rep(self): out = super(EscalatorOrStairwayDoor, self).yml_rep() try: out["Type"] = DoorType.tostring(self.type) except InvalidArgumentError: raise InvalidUserDataError("Door had invalid type of %#x" % self.type) try: out["Direction"] = StairDirection.tostring(self.direction) except InvalidArgumentError: raise InvalidUserDataError("Door had invalid escalator/stairs direction of %#x" % self.direction) return out
def get_enum_from_user_dict(yml_rep, key, enum_class): try: value = yml_rep[key] except KeyError: raise MissingUserDataError("Attribute \"%s\" was not provided" % key) if not isinstance(value, str): raise InvalidUserDataError("Attribute \"%s\" was not a string" % key) try: return enum_class.fromstring(value) except InvalidArgumentError: raise InvalidUserDataError( "Attribute \"%s\" had unknown value \"%s\"" % (key, value))
def read_staff_text_from_project(self, resource_open): with resource_open(STAFF_TEXT_FILE_NAME, 'md', True) as f: line = f.readline() while line: line = line.strip() if not line: line = f.readline() continue text = line[1:].lstrip() mark = line[0] line = f.readline() if mark == '>': self.read_space_from_project(int(text)) elif mark not in ['#', '-']: self.read_keyword_from_project(mark + text) elif len(text) > SCREEN_WIDTH_IN_TILES: raise InvalidUserDataError( 'Text \'{}\' is too long - must have at most {} characters' .format(text, SCREEN_WIDTH_IN_TILES)) elif mark == '#': self.read_small_line_from_project(text) else: self.read_big_line_from_project(text) self.data.append(CONTROL_END_OF_STAFF)
def from_block(self, block, offset): super(NpcDoor, self).from_block(block, offset) self.type = block[offset + 2] if not DoorType.is_valid(self.type): raise InvalidUserDataError("Door had invalid type of %#x" % self.type) destination_offset = block.read_multi(offset + 3, 2) | 0xF0000 self.text_pointer.from_block(block, destination_offset)
def yml_rep(self): out = super(RopeOrLadderDoor, self).yml_rep() try: out["Type"] = ClimbableType.tostring(self.climbable_type) except InvalidArgumentError: raise InvalidUserDataError("Door had invalid climbability setting of %#x" % self.climbable_type) return out
def yml_rep(self): out = super(NpcDoor, self).yml_rep() try: out["Type"] = DoorType.tostring(self.type) except InvalidArgumentError: raise InvalidUserDataError("Door had invalid type of %#x" % self.type) out["Text Pointer"] = self.text_pointer.yml_rep() return out
def from_image(self, image, tileset, palette, no_flip=False): if palette.num_subpalettes == 1: self._from_image_with_single_subpalette(image, tileset, palette, no_flip) else: # Multiple subpalettes, so we have to figure out which tile should use which subpalette palette.from_image(image) rgb_image = image.convert("RGB") del (image) rgb_image_data = rgb_image.load() del rgb_image tile = [ array('B', [0] * tileset.tile_width) for i in xrange(tileset.tile_height) ] for arrangement_y in xrange(self.height): image_y = arrangement_y * tileset.tile_height for arrangement_x in xrange(self.width): image_x = arrangement_x * tileset.tile_width tile_colors = set() for tile_y in xrange(tileset.tile_height): image_tile_y = image_y + tile_y for tile_x in xrange(tileset.tile_width): r, g, b = rgb_image_data[image_x + tile_x, image_tile_y] tile_colors.add( EbColor(r=r & 0xf8, g=g & 0xf8, b=b & 0xf8)) try: subpalette_id = palette.get_subpalette_for_colors( tile_colors) except InvalidArgumentError as e: raise InvalidUserDataError( "Could not fit all colors in {}x{} square at ({},{}) into a single {}-color subpalette\nColors: {}\nPalette: {}" .format(tileset.tile_width, tileset.tile_height, image_x, image_y, palette.subpalette_length, list(tile_colors), palette.subpalettes)) for tile_y in xrange(tileset.tile_height): image_tile_y = image_y + tile_y for tile_x in xrange(tileset.tile_width): image_tile_x = image_x + tile_x tile[tile_y][tile_x] = palette.get_color_id( rgb_image_data[image_tile_x, image_tile_y], subpalette_id) tile_id, vflip, hflip = tileset.add_tile(tile, no_flip) arrangement_item = self.arrangement[arrangement_y][ arrangement_x] arrangement_item.tile = tile_id arrangement_item.subpalette = subpalette_id arrangement_item.is_vertically_flipped = vflip arrangement_item.is_horizontally_flipped = hflip arrangement_item.is_priority = False
def read_keyword_from_project(self, keyword): if keyword not in KEYWORD_BYTE_HEIGHT: raise InvalidUserDataError( 'Invalid keyword={} in {}.yml - should be one of {}.'.format( keyword, name, KEYWORD_BYTE_HEIGHT.keys())) byte, height = KEYWORD_BYTE_HEIGHT[keyword] self.data.append(byte) self.height += height
def read_from_project(self, resource_open): with resource_open("Fonts/character_substitutions", "yml") as f: data = yml_load(f) if data is not None: for key, value in data.iteritems(): if not isinstance(key, basestring): raise InvalidUserDataError( "String to be replaced is not actually a string: " + key) if len(key) != 1: raise InvalidUserDataError( "String to be replaced must be a 1 character long: " + key) if not isinstance(value, basestring): raise InvalidUserDataError( "String to replace with is not actually a string: " + value) CharacterSubstitutions.character_substitutions = data
def get_from_user_dict(yml_rep, key, object_type): try: value = yml_rep[key] except KeyError: raise MissingUserDataError("Attribute \"%s\" was not provided" % key) if not isinstance(value, object_type): raise InvalidUserDataError("Attribute \"%s\" was not of type %s" % (key, object_type.__name__)) return value
def from_block(self, block, offset): super(Door, self).from_block(block, offset) destination_offset = block.read_multi(offset + 3, 2) | 0xF0000 self.text_pointer.from_block(block, destination_offset) self.flag = block.read_multi(destination_offset + 4, 2) self.destination_y = block[destination_offset + 6] self.destination_y |= (block[destination_offset + 7] & 0x3f) << 8 self.destination_direction = (block[destination_offset + 7] & 0xc0) >> 6 if not DestinationDirection.is_valid(self.destination_direction): raise InvalidUserDataError("Door had invalid destination direction of %#x" % self.destination_direction) self.destination_x = block.read_multi(destination_offset + 8, 2) self.destination_style = block[destination_offset + 10]
def from_yml_rep(self, yml_rep): self.address = None if yml_rep is None: raise MissingUserDataError("Pointer was not specified") elif isinstance(yml_rep, str): try: if yml_rep[0] == '$': self.address = int(yml_rep[1:], 16) except (IndexError, ValueError): raise InvalidUserDataError("Pointer \"%s\" was invalid" % yml_rep) if self.address is None: try: self.address = EbPointer.label_address_map[yml_rep] except KeyError: raise InvalidUserDataError( "Unknown label \"%s\" provided for pointer" % yml_rep) else: raise InvalidUserDataError("Pointer \"%s\" was invalid" % yml_rep)
def yml_rep(self): out = super(Door, self).yml_rep() out["Type"] = DoorType.tostring(DoorType.DOOR) out["Text Pointer"] = self.text_pointer.yml_rep() out["Event Flag"] = EbEventFlagTableEntry.to_yml_rep(self.flag) out["Destination X"] = self.destination_x out["Destination Y"] = self.destination_y try: out["Direction"] = DestinationDirection.tostring(self.destination_direction) except InvalidArgumentError: raise InvalidUserDataError("Door had invalid destination direction of %#x" % self.destination_direction) out["Style"] = self.destination_style return out
def door_from_yml_rep(yml_rep): try: door_type_yml_rep = yml_rep["Type"] except KeyError: message = "Door was missing \"Type\" attribute" raise MissingUserDataError(message) try: door = DOOR_TYPE_NAME_TO_CLASS_MAP[door_type_yml_rep]() except KeyError: message = "Door had unknown \"Type\" of \"%s\"" % door_type_yml_rep raise InvalidUserDataError(message) door.from_yml_rep(yml_rep) return door
def read_staff_chars(self, yml_data): log.debug('Reading staff character-to-code mapping') for k, v in yml_data.items(): vrow = v[ENTRY_ROW] vcol = v[ENTRY_COL] self.check_row_col_error(ENTRY_ROW, vrow, MAX_ROW) self.check_row_col_error(ENTRY_COL, vcol, MAX_COL) vtile = (vrow << 4) | vcol vtype = v[ENTRY_TYPE] vchar = v[ENTRY_CHAR] if vtype == 'big': self.big[str(vchar)] = vtile + 0x40 elif vtype == 'small': self.small[str(vchar)] = vtile + 0x40 else: raise InvalidUserDataError( 'Invalid \'{}\' for entry with \'{}\'={}, \'{}\'={} and \'{}\'={}.' .format(ENTRY_TYPE, ENTRY_ROW, vrow, ENTRY_COL, vcol, ENTRY_CHAR, vchar))
def check_row_col_error(name, val, max_val): if val > max_val: raise InvalidUserDataError( 'Invalid \'{}\'={} - should be between 0 and {}.'.format( name, val, max_val))
def from_block(self, block, offset): super(RopeOrLadderDoor, self).from_block(block, offset) self.climbable_type = block.read_multi(offset + 3, 2) if not ClimbableType.is_valid(self.climbable_type): raise InvalidUserDataError("Door had invalid climbability setting of %#x" % self.climbable_type)