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 move_node_from_area_to_area(self, old_area: Area, new_area: Area, node: Node): assert node in old_area.nodes if new_area.node_with_name(node.name) is not None: raise ValueError(f"New area {new_area.name} already contains a node named {node.name}") old_world = self.game.world_list.world_with_area(old_area) new_world = self.game.world_list.world_with_area(new_area) self.remove_node(old_area, node) self.add_node(new_area, node) self.replace_references_to_node_identifier( NodeIdentifier.create(old_world.name, old_area.name, node.name), NodeIdentifier.create(new_world.name, new_area.name, node.name), )
def test_add_elevator_connections_to_patches_vanilla(echoes_game_description, skip_final_bosses: bool, default_echoes_configuration, echoes_game_patches): # Setup patches_factory = echoes_game_description.game.generator.base_patches_factory expected = dataclasses.replace(echoes_game_patches, elevator_connection=echoes_game_description.get_default_elevator_connection()) if skip_final_bosses: node_ident = NodeIdentifier.create("Temple Grounds", "Sky Temple Gateway", "Teleport to Great Temple - Sky Temple Energy Controller") expected.elevator_connection[node_ident] = AreaIdentifier("Temple Grounds", "Credits") config = default_echoes_configuration config = dataclasses.replace(config, elevators=dataclasses.replace(config.elevators, skip_final_bosses=skip_final_bosses)) # Run result = patches_factory.add_elevator_connections_to_patches( config, Random(0), echoes_game_patches) # Assert assert result == expected
def static_teleporters(self) -> Dict[NodeIdentifier, AreaIdentifier]: static = {} if self.skip_final_bosses: if self.game == RandovaniaGame.METROID_PRIME: crater = NodeIdentifier.create( "Tallon Overworld", "Artifact Temple", "Teleport to Impact Crater - Crater Impact Point") static[crater] = AreaIdentifier("End of Game", "Credits") elif self.game == RandovaniaGame.METROID_PRIME_ECHOES: gateway = NodeIdentifier.create( "Temple Grounds", "Sky Temple Gateway", "Teleport to Great Temple - Sky Temple Energy Controller") static[gateway] = AreaIdentifier("Temple Grounds", "Credits") else: raise ValueError( f"Unsupported skip_final_bosses and {self.game}") return static
def _logbook_node(request, blank_game_description): has_translator = request.param translator = blank_game_description.resource_database.get_item("BlueKey") node = blank_game_description.world_list.node_by_identifier(NodeIdentifier.create( "Intro", "Hint Room", "Hint with Translator" if has_translator else "Hint no Translator", )) assert isinstance(node, LogbookNode) return has_translator, translator, node
def _pickup_node(): return PickupNode( pickup_index=PickupIndex(1), major_location=True, identifier=NodeIdentifier.create("W", "A", "Pickup (Ultra Beam)"), heal=False, location=None, layers=("default", ), description="", extra={}, )
def test_one_way_elevator_connections(echoes_game_description, replacement, expected): # Setup rng = random.Random(5000) target_locations = [AreaIdentifier(f"w{i}", f"a{i}") for i in range(6)] elevators = [ ElevatorHelper(NodeIdentifier.create(f"w{i}", f"a{i}", f"n{i}"), AreaIdentifier(f"w{i}", f"a{i}")) for i in range(6) ] database = tuple(elevators) # Run result = elevator_distributor.one_way_elevator_connections( rng, database, target_locations, replacement) # Assert assert result == expected
def test_sort_resource_requirement(): resources = [ NodeIdentifier.create("World", "Area", "Node"), PickupIndex(10), _make_resource("Resource"), TrickResourceInfo("Trick", "Trick", "Long Description"), ItemResourceInfo("Item", "Item", 1), ] # Assert resources has an entry for every type of ResourceInfo assert {type(it) for it in resources} == set(ResourceInfo.__args__) assert len(resources) == len(ResourceInfo.__args__) requirements = [ResourceRequirement.simple(it) for it in resources] result = sorted(requirements) assert result == list(reversed(requirements))
def test_two_way_elevator_connections_unchecked(): # Setup rng = random.Random(5000) elevators = [ ElevatorHelper(NodeIdentifier.create(f"w{i}", f"a{i}", f"n{i}"), AreaIdentifier(f"w{i}", f"a{i}")) for i in range(6) ] database = tuple(elevators) # Run result = elevator_distributor.two_way_elevator_connections( rng, database, False) # Assert assert result == { NodeIdentifier.create("w0", "a0", "n0"): AreaIdentifier("w4", "a4"), NodeIdentifier.create("w1", "a1", "n1"): AreaIdentifier("w2", "a2"), NodeIdentifier.create("w2", "a2", "n2"): AreaIdentifier("w1", "a1"), NodeIdentifier.create("w3", "a3", "n3"): AreaIdentifier("w5", "a5"), NodeIdentifier.create("w4", "a4", "n4"): AreaIdentifier("w0", "a0"), NodeIdentifier.create("w5", "a5", "n5"): AreaIdentifier("w3", "a3"), }
def add(world: str, area: str, node: str, target_world: str, target_area: str): elevator_connection[NodeIdentifier.create(world, area, node)] = AreaIdentifier(target_world, target_area)
def ni(w: str, a: str, n: str, tw: str, ta: str): elevator_connection[NodeIdentifier.create(w, a, n)] = AreaIdentifier(tw, ta)
def test_create_pickup_list_random_data_source(has_memo_data: bool, empty_patches, generic_item_category): # Setup rng = Random(5000) resource_b = ItemResourceInfo(0, "B", "B", 10) model_1 = MagicMock(spec=PickupModel) model_2 = MagicMock(spec=PickupModel) useless_model = PickupModel(game=RandovaniaGame.METROID_PRIME_CORRUPTION, name="Useless") pickup_a = PickupEntry("A", model_1, generic_item_category, generic_item_category, progression=tuple()) pickup_b = PickupEntry("B", model_2, generic_item_category, generic_item_category, progression=((resource_b, 1), (resource_b, 1))) pickup_c = PickupEntry("C", model_2, generic_item_category, generic_item_category, progression=tuple()) useless_pickup = PickupEntry("Useless", useless_model, USELESS_ITEM_CATEGORY, USELESS_ITEM_CATEGORY, progression=tuple()) patches = empty_patches.assign_new_pickups([ (PickupIndex(0), PickupTarget(pickup_a, 0)), (PickupIndex(2), PickupTarget(pickup_b, 0)), (PickupIndex(3), PickupTarget(pickup_a, 0)), (PickupIndex(4), PickupTarget(pickup_c, 0)), ]) if has_memo_data: memo_data = { "A": "This is an awesome item A", "B": "This is B. It is good.", "C": "What a nice day to have a C", "Useless": "Try again next time", } else: memo_data = { name: "{} acquired!".format(name) for name in ("A", "B", "C", "Useless") } creator = pickup_exporter.PickupExporterSolo(memo_data) world_list = MagicMock() world_list.iterate_nodes.return_value = [ PickupNode(NodeIdentifier.create("W", "A", f"Name {i}"), i, False, None, "", ("default",), {}, PickupIndex(i), False) for i in range(5) ] # Run result = pickup_exporter.export_all_indices( patches, PickupTarget(useless_pickup, 0), world_list, rng, PickupModelStyle.HIDE_ALL, PickupModelDataSource.RANDOM, creator, pickup_creator.create_visual_etm(), ) # Assert assert len(result) == 5 assert result[0] == pickup_exporter.ExportedPickupDetails( index=PickupIndex(0), scan_text="A", hud_text=[memo_data["A"]], conditional_resources=[ConditionalResources("A", None, ())], conversion=[], model=model_1, other_player=False, original_pickup=pickup_a, ) assert result[1] == pickup_exporter.ExportedPickupDetails( index=PickupIndex(1), scan_text="A", hud_text=[memo_data["A"]], conditional_resources=[ConditionalResources("Useless", None, ())], conversion=[], model=model_1, other_player=False, original_pickup=useless_pickup, ) assert result[2] == pickup_exporter.ExportedPickupDetails( index=PickupIndex(2), scan_text="C", hud_text=[memo_data["C"], memo_data["C"]], conditional_resources=[ ConditionalResources("B", None, ((resource_b, 1),)), ConditionalResources("B", resource_b, ((resource_b, 1),)), ], conversion=[], model=model_2, other_player=False, original_pickup=pickup_b, ) assert result[3] == pickup_exporter.ExportedPickupDetails( index=PickupIndex(3), scan_text="B", hud_text=[memo_data["B"]], conditional_resources=[ConditionalResources("A", None, ())], conversion=[], model=model_2, other_player=False, original_pickup=pickup_a, ) assert result[4] == pickup_exporter.ExportedPickupDetails( index=PickupIndex(4), scan_text="A", hud_text=[memo_data["A"]], conditional_resources=[ConditionalResources("C", None, ())], conversion=[], model=model_1, other_player=False, original_pickup=pickup_c, )
def test_create_pickup_list(model_style: PickupModelStyle, empty_patches, generic_item_category, blank_resource_db): # Setup has_scan_text = model_style in {PickupModelStyle.ALL_VISIBLE, PickupModelStyle.HIDE_MODEL} rng = Random(5000) model_0 = MagicMock(spec=PickupModel) model_1 = MagicMock(spec=PickupModel) model_2 = MagicMock(spec=PickupModel) useless_model = PickupModel( game=RandovaniaGame.METROID_PRIME_ECHOES, name="EnergyTransferModule", ) useless_resource = ItemResourceInfo(0, "Useless", "Useless", 10) resource_a = ItemResourceInfo(1, "A", "A", 10) resource_b = ItemResourceInfo(2, "B", "B", 10) pickup_a = PickupEntry("P-A", model_1, generic_item_category, generic_item_category, progression=((resource_a, 1),), ) pickup_b = PickupEntry("P-B", model_2, generic_item_category, generic_item_category, progression=((resource_b, 1), (resource_a, 5)), ) pickup_c = PickupEntry("P-C", model_2, AMMO_ITEM_CATEGORY, generic_item_category, progression=tuple(), extra_resources=((resource_b, 2), (resource_a, 1)), unlocks_resource=True, resource_lock=ResourceLock(resource_a, resource_a, useless_resource)) useless_pickup = PickupEntry("P-Useless", model_0, USELESS_ITEM_CATEGORY, USELESS_ITEM_CATEGORY, progression=((useless_resource, 1),)) patches = empty_patches.assign_new_pickups([ (PickupIndex(0), PickupTarget(pickup_a, 0)), (PickupIndex(2), PickupTarget(pickup_b, 0)), (PickupIndex(3), PickupTarget(pickup_a, 0)), (PickupIndex(4), PickupTarget(pickup_c, 0)), ]) creator = pickup_exporter.PickupExporterSolo(pickup_exporter.GenericAcquiredMemo()) world_list = MagicMock() world_list.iterate_nodes.return_value = [ PickupNode(NodeIdentifier.create("World", "Area", f"Name {i}"), i, False, None, "", ("default",), {}, PickupIndex(i), False) for i in range(5) ] # Run result = pickup_exporter.export_all_indices( patches, PickupTarget(useless_pickup, 0), world_list, rng, model_style, PickupModelDataSource.ETM, creator, pickup_creator.create_visual_etm(), ) # Assert assert len(result) == 5 assert result[0] == pickup_exporter.ExportedPickupDetails( index=PickupIndex(0), scan_text="P-A" if has_scan_text else "Unknown item", hud_text=["A acquired!"] if model_style != PickupModelStyle.HIDE_ALL else ['Unknown item acquired!'], conditional_resources=[ConditionalResources("A", None, ((resource_a, 1),))], conversion=[], model=model_1 if model_style == PickupModelStyle.ALL_VISIBLE else useless_model, other_player=False, original_pickup=pickup_a, ) assert result[1] == pickup_exporter.ExportedPickupDetails( index=PickupIndex(1), scan_text="P-Useless" if has_scan_text else "Unknown item", hud_text=["Useless acquired!"] if model_style != PickupModelStyle.HIDE_ALL else ['Unknown item acquired!'], conditional_resources=[ConditionalResources("Useless", None, ((useless_resource, 1),))], conversion=[], model=model_0 if model_style == PickupModelStyle.ALL_VISIBLE else useless_model, other_player=False, original_pickup=useless_pickup, ) assert result[2] == pickup_exporter.ExportedPickupDetails( index=PickupIndex(2), scan_text="P-B. Provides the following in order: B, A" if has_scan_text else "Unknown item", hud_text=["B acquired!", "A acquired!"] if model_style != PickupModelStyle.HIDE_ALL else [ 'Unknown item acquired!', 'Unknown item acquired!'], conditional_resources=[ ConditionalResources("B", None, ((resource_b, 1),)), ConditionalResources("A", resource_b, ((resource_a, 5),)), ], conversion=[], model=model_2 if model_style == PickupModelStyle.ALL_VISIBLE else useless_model, other_player=False, original_pickup=pickup_b, ) assert result[3] == pickup_exporter.ExportedPickupDetails( index=PickupIndex(3), scan_text="P-A" if has_scan_text else "Unknown item", hud_text=["A acquired!"] if model_style != PickupModelStyle.HIDE_ALL else ['Unknown item acquired!'], conditional_resources=[ConditionalResources("A", None, ((resource_a, 1),))], conversion=[], model=model_1 if model_style == PickupModelStyle.ALL_VISIBLE else useless_model, other_player=False, original_pickup=pickup_a, ) assert result[4] == pickup_exporter.ExportedPickupDetails( index=PickupIndex(4), scan_text="P-C. Provides 2 B and 1 A" if has_scan_text else "Unknown item", hud_text=["P-C acquired!"] if model_style != PickupModelStyle.HIDE_ALL else ['Unknown item acquired!'], conditional_resources=[ConditionalResources("P-C", None, ( (resource_b, 2), (resource_a, 1), ))], conversion=[ResourceConversion(source=useless_resource, target=resource_a)], model=model_2 if model_style == PickupModelStyle.ALL_VISIBLE else useless_model, other_player=False, original_pickup=pickup_c, )
def _create_identifier(self, node_name: str): return NodeIdentifier.create(self.current_world.name, self.current_area.name, node_name)
def _a(world, area, instance_id=None): if instance_id is not None: return NodeIdentifier.create(world, area, instance_id).as_json return AreaIdentifier(world, area).as_json
rng, database, False) # Assert assert result == { NodeIdentifier.create("w0", "a0", "n0"): AreaIdentifier("w4", "a4"), NodeIdentifier.create("w1", "a1", "n1"): AreaIdentifier("w2", "a2"), NodeIdentifier.create("w2", "a2", "n2"): AreaIdentifier("w1", "a1"), NodeIdentifier.create("w3", "a3", "n3"): AreaIdentifier("w5", "a5"), NodeIdentifier.create("w4", "a4", "n4"): AreaIdentifier("w0", "a0"), NodeIdentifier.create("w5", "a5", "n5"): AreaIdentifier("w3", "a3"), } @pytest.mark.parametrize(["replacement", "expected"], [ (False, { NodeIdentifier.create("w0", "a0", "n0"): AreaIdentifier("w1", "a1"), NodeIdentifier.create("w1", "a1", "n1"): AreaIdentifier("w2", "a2"), NodeIdentifier.create("w2", "a2", "n2"): AreaIdentifier("w3", "a3"), NodeIdentifier.create("w3", "a3", "n3"): AreaIdentifier("w5", "a5"), NodeIdentifier.create("w4", "a4", "n4"): AreaIdentifier("w0", "a0"), NodeIdentifier.create("w5", "a5", "n5"): AreaIdentifier("w4", "a4"), }), (True, { NodeIdentifier.create("w0", "a0", "n0"): AreaIdentifier("w2", "a2"), NodeIdentifier.create("w1", "a1", "n1"): AreaIdentifier("w3", "a3"), NodeIdentifier.create("w2", "a2", "n2"): AreaIdentifier("w4", "a4"), NodeIdentifier.create("w3", "a3", "n3"): AreaIdentifier("w2", "a2"), NodeIdentifier.create("w4", "a4", "n4"): AreaIdentifier("w5", "a5"), NodeIdentifier.create("w5", "a5", "n5"): AreaIdentifier("w3", "a3"), }), ])
def decode_single(player_index: int, all_pools: Dict[int, PoolResults], game: GameDescription, game_modifications: dict, configuration: BaseConfiguration) -> GamePatches: """ Decodes a dict created by `serialize` back into a GamePatches. :param player_index: :param all_pools: :param game: :param game_modifications: :param configuration: :return: """ world_list = game.world_list weakness_db = game.dock_weakness_database if game_modifications["game"] != game.game.value: raise ValueError( f"Expected '{game.game.value}', got '{game_modifications['game']}'" ) initial_pickup_assignment = all_pools[player_index].assignment # Starting Location starting_location = AreaIdentifier.from_string( game_modifications["starting_location"]) # Initial items starting_items = { find_resource_info_with_long_name(game.resource_database.item, resource_name): quantity for resource_name, quantity in game_modifications["starting_items"].items() } # Elevators elevator_connection: ElevatorConnection = { NodeIdentifier.from_string(source_name): AreaIdentifier.from_string(target_name) for source_name, target_name in game_modifications["teleporters"].items() } # Dock Weakness dock_weakness: dict[NodeIdentifier, DockWeakness] = { NodeIdentifier.from_string(source_name): weakness_db.get_by_weakness( weakness_data["type"], weakness_data["name"], ) for source_name, weakness_data in game_modifications["dock_weakness"].items() } # Configurable Nodes configurable_nodes = { NodeIdentifier.from_string(identifier): data_reader.read_requirement(requirement, game.resource_database) for identifier, requirement in game_modifications["configurable_nodes"].items() } # Pickups target_name_re = re.compile(r"(.*) for Player (\d+)") pickup_assignment: PickupAssignment = {} for world_name, world_data in game_modifications["locations"].items(): for area_node_name, target_name in typing.cast(dict[str, str], world_data).items(): if target_name == _ETM_NAME: continue pickup_name_match = target_name_re.match(target_name) if pickup_name_match is not None: pickup_name = pickup_name_match.group(1) target_player = int(pickup_name_match.group(2)) - 1 else: pickup_name = target_name target_player = 0 node_identifier = NodeIdentifier.create( world_name, *area_node_name.split("/", 1)) node = world_list.node_by_identifier(node_identifier) assert isinstance(node, PickupNode) if node.pickup_index in initial_pickup_assignment: pickup = initial_pickup_assignment[node.pickup_index] if (pickup_name, target_player) != (pickup.name, player_index): raise ValueError( f"{area_node_name} should be vanilla based on configuration" ) elif pickup_name != _ETM_NAME: configuration_item_pool = all_pools[target_player].pickups pickup = _find_pickup_with_name(configuration_item_pool, pickup_name) configuration_item_pool.remove(pickup) else: pickup = None if pickup is not None: pickup_assignment[node.pickup_index] = PickupTarget( pickup, target_player) # Hints hints = {} for identifier_str, hint in game_modifications["hints"].items(): hints[NodeIdentifier.from_string(identifier_str)] = Hint.from_json( hint) return GamePatches( player_index=player_index, configuration=configuration, pickup_assignment=pickup_assignment, # PickupAssignment elevator_connection=elevator_connection, # ElevatorConnection dock_connection={}, # Dict[Tuple[int, int], DockConnection] dock_weakness=dock_weakness, configurable_nodes=configurable_nodes, starting_items=starting_items, # ResourceGainTuple starting_location=starting_location, # AreaIdentifier hints=hints, )
def add(world: str, area: str, node: str, target_world: str, target_area: str): elevator_connection.append(( wl.get_teleporter_node(NodeIdentifier.create(world, area, node)), AreaIdentifier(target_world, target_area), ))
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}")
from randovania.layout import game_patches_serializer from randovania.layout.base.major_item_state import MajorItemState from randovania.layout.base.trick_level_configuration import TrickLevelConfiguration from randovania.layout.generator_parameters import GeneratorParameters from randovania.network_common.pickup_serializer import BitPackPickupEntry @pytest.fixture(params=[ {}, { "starting_item": "Morph Ball" }, { "elevator": NodeIdentifier.create( "Temple Grounds", "Transport to Agon Wastes", "Elevator to Agon Wastes - Transport to Temple Grounds") }, { "configurable_nodes": [("Agon Wastes/Mining Plaza/Translator Gate", "Cobalt"), ("Torvus Bog/Great Bridge/Translator Gate", "Emerald")] }, { "pickup": "Morph Ball Bomb" }, { "hint": [ 'Torvus Bog/Catacombs/Lore Scan', { "hint_type": "location", "dark_temple": None,