def as_json(self) -> dict: result = { "model_name": self.model_name, "items": frozen_lib.unwrap(self.items), "broad_category": self.broad_category.name, "extra": frozen_lib.unwrap(self.extra), } if self.unlocked_by is not None: result["temporary"] = self.temporary result["unlocked_by"] = self.unlocked_by return result
def write_area(area: Area) -> dict: """ :param area: :return: """ errors = [] nodes = {} for node in area.nodes: if node.is_derived_node: continue try: data = write_node(node) data["connections"] = { target_node.name: write_requirement(area.connections[node][target_node]) for target_node in area.nodes if not target_node.is_derived_node and target_node in area.connections[node] } nodes[node.name] = data except ValueError as e: errors.append(str(e)) if errors: raise ValueError("Area {} nodes has the following errors:\n* {}".format( area.name, "\n* ".join(errors))) extra = frozen_lib.unwrap(area.extra) return { "default_node": area.default_node, "valid_starting_location": area.valid_starting_location, "extra": extra, "nodes": nodes, }
def as_json(self) -> dict: result = { "long_name": self.long_name, "hint_details": frozen_lib.unwrap(self.hint_details), "is_major": self.is_major, } if self.is_key: result["is_key"] = self.is_key return result
def as_json(self) -> dict: result = { "item_category": self.item_category.name, "broad_category": self.broad_category.name, "model_name": self.model_name, "progression": frozen_lib.unwrap(self.progression), "default_shuffled_count": self.default_shuffled_count, "default_starting_count": self.default_starting_count, "ammo": frozen_lib.unwrap(self.ammo_index), "unlocks_ammo": self.unlocks_ammo, "hide_from_gui": self.hide_from_gui, "must_be_starting": self.must_be_starting, "probability_offset": self.probability_offset, "probability_multiplier": self.probability_multiplier, "extra": frozen_lib.unwrap(self.extra), } if self.original_index is not None: result["original_index"] = self.original_index.index if self.warning is not None: result["warning"] = self.warning return result
def write_game_description(game: GameDescription) -> dict: return { "schema_version": game_migration.CURRENT_VERSION, "game": game.game.value, "resource_database": write_resource_database(game.resource_database), "layers": frozen_lib.unwrap(game.layers), "starting_location": game.starting_location.as_json, "initial_states": write_initial_states(game.initial_states), "minimal_logic": write_minimal_logic_db(game.minimal_logic), "victory_condition": write_requirement(game.victory_condition), "dock_weakness_database": write_dock_weakness_database(game.dock_weakness_database), "worlds": write_world_list(game.world_list), }
def write_world(world: World) -> dict: errors = [] areas = {} for area in world.areas: try: areas[area.name] = write_area(area) except ValueError as e: errors.append(str(e)) if errors: raise ValueError("World {} has the following errors:\n> {}".format( world.name, "\n\n> ".join(errors))) return { "name": world.name, "extra": frozen_lib.unwrap(world.extra), "areas": areas, }
def write_dock_weakness_database(database: DockWeaknessDatabase) -> dict: return { "types": { dock_type.short_name: { "name": dock_type.long_name, "extra": frozen_lib.unwrap(dock_type.extra), "items": { name: write_dock_weakness(weakness) for name, weakness in database.weaknesses[dock_type].items() }, "dock_rando": write_dock_rando_params(database.dock_rando_params[dock_type]), } for dock_type in database.dock_types }, "default_weakness": { "type": database.default_weakness[0].short_name, "name": database.default_weakness[1].name, } }
def encode_extra(qt_value): try: decoded = json.loads(qt_value) if isinstance(decoded, dict): return True, frozen_lib.wrap(decoded) except json.JSONDecodeError: return False, None GENERIC_FIELDS = [ FieldDefinition("Short Name", "short_name", lambda v: v, lambda v: (True, v)), FieldDefinition("Long Name", "long_name", lambda v: v, lambda v: (True, v)), FieldDefinition("Extra", "extra", lambda v: json.dumps(frozen_lib.unwrap(v)), encode_extra), ] class ResourceDatabaseGenericModel(QtCore.QAbstractTableModel): def __init__(self, db: ResourceDatabase, resource_type: ResourceType): super().__init__() self.db = db self.resource_type = resource_type self.allow_edits = True def _get_items(self): return self.db.get_by_type(self.resource_type) def set_allow_edits(self, value: bool): self.beginResetModel()
def __init__(self, game: GameDescription, node: Node): super().__init__() self.setupUi(self) common_qt_lib.set_default_window_icon(self) self.game = game self.node = node self._type_to_tab = { GenericNode: self.tab_generic, DockNode: self.tab_dock, PickupNode: self.tab_pickup, TeleporterNode: self.tab_teleporter, EventNode: self.tab_event, ConfigurableNode: self.tab_translator_gate, LogbookNode: self.tab_logbook, PlayerShipNode: self.tab_player_ship, } tab_to_type = {tab: node_type for node_type, tab in self._type_to_tab.items()} # Dynamic Stuff for i, node_type in enumerate(self._type_to_tab.keys()): self.node_type_combo.setItemData(i, node_type) self.layers_combo.clear() for layer in game.layers: self.layers_combo.addItem(layer) self.dock_type_combo.clear() for i, dock_type in enumerate(game.dock_weakness_database.dock_types): self.dock_type_combo.addItem(dock_type.long_name, userData=dock_type) refresh_if_needed(self.dock_type_combo, self.on_dock_type_combo) for world in sorted(game.world_list.worlds, key=lambda x: x.name): self.dock_connection_world_combo.addItem(world.name, userData=world) self.teleporter_destination_world_combo.addItem(world.name, userData=world) refresh_if_needed(self.teleporter_destination_world_combo, self.on_dock_connection_world_combo) refresh_if_needed(self.teleporter_destination_world_combo, self.on_teleporter_destination_world_combo) for event in sorted(game.resource_database.event, key=lambda it: it.long_name): self.event_resource_combo.addItem(event.long_name, event) if self.event_resource_combo.count() == 0: self.event_resource_combo.addItem("No events in database", None) self.event_resource_combo.setEnabled(False) for i, dock_type in enumerate(enum_lib.iterate_enum(LoreType)): self.lore_type_combo.setItemData(i, dock_type) refresh_if_needed(self.lore_type_combo, self.on_lore_type_combo) self.set_unlocked_by(Requirement.trivial()) # Signals self.button_box.accepted.connect(self.try_accept) self.button_box.rejected.connect(self.reject) self.name_edit.textEdited.connect(self.on_name_edit) self.node_type_combo.currentIndexChanged.connect(self.on_node_type_combo) self.dock_connection_world_combo.currentIndexChanged.connect(self.on_dock_connection_world_combo) self.dock_connection_area_combo.currentIndexChanged.connect(self.on_dock_connection_area_combo) self.dock_type_combo.currentIndexChanged.connect(self.on_dock_type_combo) self.dock_update_name_button.clicked.connect(self.on_dock_update_name_button) self.teleporter_destination_world_combo.currentIndexChanged.connect(self.on_teleporter_destination_world_combo) self.lore_type_combo.currentIndexChanged.connect(self.on_lore_type_combo) self.player_ship_unlocked_button.clicked.connect(self.on_player_ship_unlocked_button) # Hide the tab bar tab_bar: QtWidgets.QTabBar = self.tab_widget.findChild(QtWidgets.QTabBar) tab_bar.hide() # Values self.name_edit.setText(node.name) self.heals_check.setChecked(node.heal) self.location_group.setChecked(node.location is not None) if node.location is not None: self.location_x_spin.setValue(node.location.x) self.location_y_spin.setValue(node.location.y) self.location_z_spin.setValue(node.location.z) self.description_edit.setMarkdown(node.description) self.extra_edit.setPlainText(json.dumps(frozen_lib.unwrap(node.extra), indent=4)) try: visible_tab = self._fill_for_type(node) self.node_type_combo.setCurrentIndex(self.node_type_combo.findData(tab_to_type[visible_tab])) refresh_if_needed(self.node_type_combo, self.on_node_type_combo) except Exception: pass self.on_name_edit(self.name_edit.text())
def write_node(node: Node) -> dict: """ :param node: :return: """ data = {} common_fields = { "heal": node.heal, "coordinates": {"x": node.location.x, "y": node.location.y, "z": node.location.z} if node.location else None, "description": node.description, "layers": frozen_lib.unwrap(node.layers), "extra": frozen_lib.unwrap(node.extra), } if isinstance(node, GenericNode): data["node_type"] = "generic" data.update(common_fields) elif isinstance(node, DockNode): data["node_type"] = "dock" data.update(common_fields) data["dock_type"] = node.dock_type.short_name data["default_connection"] = node.default_connection.as_json data["default_dock_weakness"] = node.default_dock_weakness.name data["override_default_open_requirement"] = write_optional_requirement(node.override_default_open_requirement) data["override_default_lock_requirement"] = write_optional_requirement(node.override_default_lock_requirement) elif isinstance(node, PickupNode): data["node_type"] = "pickup" data.update(common_fields) data["pickup_index"] = node.pickup_index.index data["major_location"] = node.major_location elif isinstance(node, TeleporterNode): data["node_type"] = "teleporter" data.update(common_fields) data["destination"] = node.default_connection.as_json data["keep_name_when_vanilla"] = node.keep_name_when_vanilla data["editable"] = node.editable elif isinstance(node, EventNode): data["node_type"] = "event" data.update(common_fields) data["event_name"] = node.event.short_name elif isinstance(node, ConfigurableNode): data["node_type"] = "configurable_node" data.update(common_fields) elif isinstance(node, LogbookNode): data["node_type"] = "logbook" data.update(common_fields) data["string_asset_id"] = node.string_asset_id data["lore_type"] = node.lore_type.value if node.lore_type == LoreType.REQUIRES_ITEM: data["extra"]["translator"] = node.required_translator.short_name elif node.lore_type in {LoreType.SPECIFIC_PICKUP, LoreType.SKY_TEMPLE_KEY_HINT}: data["extra"]["hint_index"] = node.hint_index elif isinstance(node, PlayerShipNode): data["node_type"] = "player_ship" data.update(common_fields) data["is_unlocked"] = write_requirement(node.is_unlocked) else: raise ValueError("Unknown node class: {}".format(node)) return data
def write_dock_weakness(dock_weakness: DockWeakness) -> dict: return { "extra": frozen_lib.unwrap(dock_weakness.extra), "requirement": write_requirement(dock_weakness.requirement), "lock": write_dock_lock(dock_weakness.lock), }
def write_trick_resource(resource: TrickResourceInfo) -> dict: return { "long_name": resource.long_name, "description": resource.description, "extra": frozen_lib.unwrap(resource.extra), }
def write_item_resource(resource: ItemResourceInfo) -> dict: return { "long_name": resource.long_name, "max_capacity": resource.max_capacity, "extra": frozen_lib.unwrap(resource.extra), }
def write_simple_resource(resource: SimpleResourceInfo) -> dict: return { "long_name": resource.long_name, "extra": frozen_lib.unwrap(resource.extra), }
from_qt: typing.Callable[[typing.Any], tuple[bool, typing.Any]] def encode_extra(qt_value): try: decoded = json.loads(qt_value) if isinstance(decoded, dict): return True, frozen_lib.wrap(decoded) except json.JSONDecodeError: return False, None GENERIC_FIELDS = [ FieldDefinition("Short Name", "short_name", lambda v: v, lambda v: (True, v)), FieldDefinition("Long Name", "long_name", lambda v: v, lambda v: (True, v)), FieldDefinition("Extra", "extra", lambda v: json.dumps(frozen_lib.unwrap(v)), encode_extra), ] class ResourceDatabaseGenericModel(QtCore.QAbstractTableModel): def __init__(self, db: ResourceDatabase, resource_type: ResourceType): super().__init__() self.db = db self.resource_type = resource_type self.allow_edits = True def _get_items(self): return self.db.get_by_type(self.resource_type) def set_allow_edits(self, value: bool): self.beginResetModel()