def create_from_dock(cls, dock: DockNode) -> DockLockNode: lock_identifier = dock.get_lock_node_identifier_from_identifier(dock.identifier) return DockLockNode( identifier=lock_identifier, heal=False, location=None, description="", layers=dock.layers, extra={}, dock_identifier=dock.identifier, )
def test_connections_from_dock_blast_shield(empty_patches): # Setup trivial = Requirement.trivial() req_1 = ResourceRequirement.simple( SimpleResourceInfo(0, "Ev1", "Ev1", ResourceType.EVENT)) req_2 = ResourceRequirement.simple( SimpleResourceInfo(1, "Ev2", "Ev2", ResourceType.EVENT)) dock_type = DockType("Type", "Type", frozendict()) weak_1 = DockWeakness(0, "Weak 1", frozendict(), req_1, None) weak_2 = DockWeakness(1, "Weak 2", frozendict(), trivial, DockLock(DockLockType.FRONT_BLAST_BACK_BLAST, req_2)) node_1_identifier = NodeIdentifier.create("W", "Area 1", "Node 1") node_2_identifier = NodeIdentifier.create("W", "Area 2", "Node 2") node_1 = DockNode(node_1_identifier, 0, False, None, "", ("default", ), {}, dock_type, node_2_identifier, weak_1, None, None) node_1_lock = DockLockNode.create_from_dock(node_1, 1) node_2 = DockNode(node_2_identifier, 2, False, None, "", ("default", ), {}, dock_type, node_1_identifier, weak_2, None, None) node_2_lock = DockLockNode.create_from_dock(node_2, 3) area_1 = Area("Area 1", None, True, [node_1, node_1_lock], {}, {}) area_2 = Area("Area 2", None, True, [node_2, node_2_lock], {}, {}) world = World("W", [area_1, area_2], {}) world_list = WorldList([world]) world_list.ensure_has_node_cache() game_mock = MagicMock() game_mock.world_list = world_list patches = dataclasses.replace(empty_patches, game=game_mock) context = NodeContext( patches=patches, current_resources=ResourceCollection(), database=patches.game.resource_database, node_provider=world_list, ) # Run result_1 = list(node_1.connections_from(context)) result_2 = list(node_2.connections_from(context)) # Assert simple = ResourceRequirement.simple assert result_1 == [ (node_2, RequirementAnd( [req_1, simple(NodeResourceInfo.from_node(node_2, context))])), (node_1_lock, RequirementAnd([trivial, req_2])), ] assert result_2 == [ (node_1, simple(NodeResourceInfo.from_node(node_2, context))), (node_2_lock, req_2), ]
def test_connections_from_dock_blast_shield(empty_patches): # Setup trivial = Requirement.trivial() req_1 = ResourceRequirement( SimpleResourceInfo("Ev1", "Ev1", ResourceType.EVENT), 1, False) req_2 = ResourceRequirement( SimpleResourceInfo("Ev2", "Ev2", ResourceType.EVENT), 1, False) dock_type = DockType("Type", "Type", frozendict()) weak_1 = DockWeakness("Weak 1", frozendict(), req_1, None) weak_2 = DockWeakness("Weak 2", frozendict(), trivial, DockLock(DockLockType.FRONT_BLAST_BACK_BLAST, req_2)) node_1_identifier = NodeIdentifier.create("W", "Area 1", "Node 1") node_2_identifier = NodeIdentifier.create("W", "Area 2", "Node 2") node_1 = DockNode(node_1_identifier, False, None, "", ("default", ), {}, dock_type, node_2_identifier, weak_1, None, None) node_1_lock = DockLockNode.create_from_dock(node_1) node_2 = DockNode(node_2_identifier, False, None, "", ("default", ), {}, dock_type, node_1_identifier, weak_2, None, None) node_2_lock = DockLockNode.create_from_dock(node_2) area_1 = Area("Area 1", None, True, [node_1, node_1_lock], {}, {}) area_2 = Area("Area 2", None, True, [node_2, node_2_lock], {}, {}) world = World("W", [area_1, area_2], {}) world_list = WorldList([world]) context = NodeContext( patches=empty_patches, current_resources={}, database=None, node_provider=world_list, ) # Run result_1 = list(node_1.connections_from(context)) result_2 = list(node_2.connections_from(context)) # Assert assert result_1 == [ (node_2, RequirementAnd([req_1, ResourceRequirement.simple(node_2_identifier)])), (node_1_lock, RequirementAnd([trivial, req_2])), ] assert result_2 == [ (node_1, ResourceRequirement.simple(node_2_identifier)), (node_2_lock, req_2), ]
def read_node(self, name: str, data: Dict) -> Node: try: location = None if data["coordinates"] is not None: location = location_from_json(data["coordinates"]) generic_args = { "identifier": NodeIdentifier.create(self.current_world_name, self.current_area_name, name), "heal": data["heal"], "location": location, "description": data["description"], "layers": tuple(data["layers"]), "extra": frozen_lib.wrap(data["extra"]), } node_type: int = data["node_type"] if node_type == "generic": return GenericNode(**generic_args) elif node_type == "dock": return DockNode( **generic_args, dock_type=self.dock_weakness_database.find_type( data["dock_type"]), default_connection=NodeIdentifier.from_json( data["default_connection"]), default_dock_weakness=self.dock_weakness_database. get_by_weakness( data["dock_type"], data["default_dock_weakness"], ), override_default_open_requirement=read_optional_requirement( data["override_default_open_requirement"], self.resource_database), override_default_lock_requirement=read_optional_requirement( data["override_default_lock_requirement"], self.resource_database), ) elif node_type == "pickup": return PickupNode( **generic_args, pickup_index=PickupIndex(data["pickup_index"]), major_location=data["major_location"], ) elif node_type == "teleporter": return TeleporterNode( **generic_args, default_connection=AreaIdentifier.from_json( data["destination"]), keep_name_when_vanilla=data["keep_name_when_vanilla"], editable=data["editable"], ) elif node_type == "event": return EventNode( **generic_args, event=self.resource_database.get_by_type_and_index( ResourceType.EVENT, data["event_name"])) elif node_type == "configurable_node": return ConfigurableNode(**generic_args, ) elif node_type == "logbook": lore_type = LoreType(data["lore_type"]) if lore_type == LoreType.REQUIRES_ITEM: required_translator = self.resource_database.get_item( data["extra"]["translator"]) else: required_translator = None if lore_type in { LoreType.SPECIFIC_PICKUP, LoreType.SKY_TEMPLE_KEY_HINT }: hint_index = data["extra"]["hint_index"] else: hint_index = None return LogbookNode( **generic_args, string_asset_id=data["string_asset_id"], scan_visor=self._get_scan_visor(), lore_type=lore_type, required_translator=required_translator, hint_index=hint_index, ) elif node_type == "player_ship": return PlayerShipNode( **generic_args, is_unlocked=read_requirement(data["is_unlocked"], self.resource_database), item_to_summon=self._get_command_visor(), ) else: raise Exception(f"Unknown type: {node_type}") except Exception as e: raise Exception(f"In node {name}, got error: {e}")
def create_new_node(self) -> Node: node_type = self.node_type_combo.currentData() identifier = dataclasses.replace(self.node.identifier, node_name=self.name_edit.text()) heal = self.heals_check.isChecked() location = None if self.location_group.isChecked(): location = NodeLocation(self.location_x_spin.value(), self.location_y_spin.value(), self.location_z_spin.value()) description = self.description_edit.toMarkdown() extra = json.loads(self.extra_edit.toPlainText()) layers = (self.layers_combo.currentText(),) if node_type == GenericNode: return GenericNode(identifier, heal, location, description, layers, extra) elif node_type == DockNode: connection_node: Node = self.dock_connection_node_combo.currentData() return DockNode( identifier, heal, location, description, layers, extra, self.dock_type_combo.currentData(), self.game.world_list.identifier_for_node(connection_node), self.dock_weakness_combo.currentData(), None, None, ) elif node_type == PickupNode: return PickupNode( identifier, heal, location, description, layers, extra, PickupIndex(self.pickup_index_spin.value()), self.major_location_check.isChecked(), ) elif node_type == TeleporterNode: dest_world: World = self.teleporter_destination_world_combo.currentData() dest_area: Area = self.teleporter_destination_area_combo.currentData() return TeleporterNode( identifier, heal, location, description, layers, extra, AreaIdentifier( world_name=dest_world.name, area_name=dest_area.name, ), self.teleporter_vanilla_name_edit.isChecked(), self.teleporter_editable_check.isChecked(), ) elif node_type == EventNode: event = self.event_resource_combo.currentData() if event is None: raise ValueError("There are no events in the database, unable to create EventNode.") return EventNode( identifier, heal, location, description, layers, extra, event, ) elif node_type == ConfigurableNode: return ConfigurableNode( identifier, heal, location, description, layers, extra, ) elif node_type == LogbookNode: lore_type: LoreType = self.lore_type_combo.currentData() if lore_type == LoreType.REQUIRES_ITEM: required_translator = self.logbook_extra_combo.currentData() if required_translator is None: raise ValueError("Missing required translator.") else: required_translator = None if lore_type == LoreType.SPECIFIC_PICKUP: hint_index = self.logbook_extra_combo.currentData() else: hint_index = None return LogbookNode( identifier, heal, location, description, layers, extra, int(self.logbook_string_asset_id_edit.text(), 0), self._get_scan_visor(), lore_type, required_translator, hint_index ) elif node_type == PlayerShipNode: return PlayerShipNode( identifier, heal, location, description, layers, extra, self._unlocked_by_requirement, self._get_command_visor() ) else: raise RuntimeError(f"Unknown node type: {node_type}")
def _create_new_dock(self, location: NodeLocation, target_area: Area): current_area = self.current_area target_identifier = self.world_list.identifier_for_area(target_area) source_identifier = self.world_list.identifier_for_area(current_area) dock_weakness = self.game_description.dock_weakness_database.default_weakness source_name_base = integrity_check.base_dock_name_raw( dock_weakness[0], dock_weakness[1], target_identifier) target_name_base = integrity_check.base_dock_name_raw( dock_weakness[0], dock_weakness[1], source_identifier) source_count = len( integrity_check.docks_with_same_base_name(current_area, source_name_base)) if source_count != len( integrity_check.docks_with_same_base_name( target_area, target_name_base)): raise ValueError( f"Expected {target_area.name} to also have {source_count} " f"docks with name {target_name_base}") if source_count > 0: source_name = f"{source_name_base} ({source_count + 1})" target_name = f"{target_name_base} ({source_count + 1})" else: source_name = source_name_base target_name = target_name_base new_node_this_area_identifier = NodeIdentifier( self.world_list.identifier_for_area(current_area), source_name) new_node_other_area_identifier = NodeIdentifier( self.world_list.identifier_for_area(target_area), target_name) new_node_this_area = DockNode( identifier=new_node_this_area_identifier, node_index=self.editor.new_node_index(), heal=False, location=location, description="", layers=("default", ), extra={}, dock_type=dock_weakness[0], default_connection=new_node_other_area_identifier, default_dock_weakness=dock_weakness[1], override_default_open_requirement=None, override_default_lock_requirement=None, ) new_node_other_area = DockNode( identifier=new_node_other_area_identifier, node_index=self.editor.new_node_index(), heal=False, location=location, description="", layers=("default", ), extra={}, dock_type=dock_weakness[0], default_connection=new_node_this_area_identifier, default_dock_weakness=dock_weakness[1], override_default_open_requirement=None, override_default_lock_requirement=None, ) self.editor.add_node(current_area, new_node_this_area) self.editor.add_node(target_area, new_node_other_area) if source_count == 1: self.editor.rename_node( current_area, current_area.node_with_name(source_name_base), f"{source_name_base} (1)", ) self.editor.rename_node( target_area, target_area.node_with_name(target_name_base), f"{target_name_base} (1)", ) self.on_select_area(new_node_this_area)