Ejemplo n.º 1
0
def _migrate_v1(data: dict) -> dict:
    game = RandovaniaGame(data["game"])
    for item in data["items"].values():
        item["progression"] = [
            migration_data.get_resource_name_from_index(
                game, progression, ResourceType.ITEM)
            for progression in item["progression"]
        ]
        ammo = item.get("ammo")
        if ammo is not None:
            item["ammo"] = [
                migration_data.get_resource_name_from_index(
                    game, ammo, ResourceType.ITEM) for ammo in item["ammo"]
            ]
    for ammo in data["ammo"].values():
        ammo["items"] = [
            migration_data.get_resource_name_from_index(
                game, item, ResourceType.ITEM) for item in ammo["items"]
        ]
        unlock = ammo.get("unlocked_by")
        if unlock is not None:
            ammo["unlocked_by"] = migration_data.get_resource_name_from_index(
                game, ammo["unlocked_by"], ResourceType.ITEM)
        temporary = ammo.get("temporary")
        if temporary is not None:
            ammo["temporary"] = migration_data.get_resource_name_from_index(
                game, ammo["temporary"], ResourceType.ITEM)
    return data
Ejemplo n.º 2
0
def create_permalink(args):
    from randovania.layout.permalink import Permalink
    from randovania.layout.generator_parameters import GeneratorParameters
    from randovania.interface_common.preset_manager import PresetManager

    game: RandovaniaGame = RandovaniaGame(args.game)
    preset_manager = PresetManager(None)
    presets = []
    for preset_name in args.preset_name:
        versioned = preset_manager.included_preset_with(game, preset_name)
        if versioned is None:
            raise ValueError(
                "Unknown included preset '{}' for game {}. Valid options are: {}"
                .format(preset_name, game.long_name, [
                    preset.name
                    for preset in preset_manager.included_presets.values()
                    if preset.game == game
                ]))
        presets.append(versioned.get_preset())

    seed = args.seed_number
    if seed is None:
        seed = random.randint(0, 2**31)

    return Permalink.from_parameters(
        GeneratorParameters(
            seed,
            spoiler=not args.race,
            presets=presets,
        ), )
Ejemplo n.º 3
0
 def from_json_dict(cls, json_dict: dict) -> "LayoutConfiguration":
     return LayoutConfiguration(
         game=RandovaniaGame(json_dict["game"]),
         trick_level_configuration=TrickLevelConfiguration.from_json(json_dict["trick_level"]),
         damage_strictness=LayoutDamageStrictness(json_dict["damage_strictness"]),
         sky_temple_keys=LayoutSkyTempleKeyMode(json_dict["sky_temple_keys"]),
         elevators=LayoutElevators(json_dict["elevators"]),
         starting_location=StartingLocation.from_json(json_dict["starting_location"]),
         available_locations=AvailableLocationsConfiguration.from_json(json_dict["available_locations"]),
         major_items_configuration=MajorItemsConfiguration.from_json(
             json_dict["major_items_configuration"],
             default_prime2_item_database(),
         ),
         ammo_configuration=AmmoConfiguration.from_json(
             json_dict["ammo_configuration"],
             default_prime2_item_database(),
         ),
         translator_configuration=TranslatorConfiguration.from_json(json_dict["translator_configuration"]),
         hints=HintConfiguration.from_json(json_dict["hints"]),
         beam_configuration=BeamConfiguration.from_json(json_dict["beam_configuration"]),
         skip_final_bosses=json_dict["skip_final_bosses"],
         energy_per_tank=json_dict["energy_per_tank"],
         safe_zone=LayoutSafeZone.from_json(json_dict["safe_zone"]),
         split_beam_ammo=json_dict["split_beam_ammo"],
     )
Ejemplo n.º 4
0
def decode_data_file(args) -> Dict:
    json_database: Optional[Path] = args.json_database
    if json_database is not None:
        with json_database.open() as data_file:
            return json.load(data_file)
    else:
        return default_data.read_json_then_binary(RandovaniaGame(args.game))[1]
Ejemplo n.º 5
0
    def from_json(cls, data) -> "GameSessionEntry":
        data = convert_to_raw_python(BinaryGameSessionEntry.parse(data))

        player_entries = [
            PlayerSessionEntry.from_json(player_json)
            for player_json in data["players"]
        ]
        return GameSessionEntry(
            id=data["id"],
            name=data["name"],
            presets=[
                VersionedPreset(json.loads(preset_json))
                for preset_json in data["presets"]
            ],
            players={
                player_entry.id: player_entry
                for player_entry in player_entries
            },
            game_details=GameDetails.from_json(data["game_details"])
            if data["game_details"] is not None else None,
            state=GameSessionState(data["state"]),
            generation_in_progress=data["generation_in_progress"],
            allowed_games=[
                RandovaniaGame(game) for game in data["allowed_games"]
            ],
        )
Ejemplo n.º 6
0
 def from_json(cls, data) -> "GameSessionEntry":
     player_entries = [
         PlayerSessionEntry.from_json(player_json)
         for player_json in data["players"]
     ]
     return GameSessionEntry(
         id=data["id"],
         name=data["name"],
         presets=[
             VersionedPreset(preset_json) for preset_json in data["presets"]
         ],
         players={
             player_entry.id: player_entry
             for player_entry in player_entries
         },
         actions=[
             GameSessionAction.from_json(item) for item in data["actions"]
         ],
         seed_hash=data["seed_hash"],
         word_hash=data["word_hash"],
         spoiler=data["spoiler"],
         permalink=data["permalink"],
         state=GameSessionState(data["state"]),
         generation_in_progress=data["generation_in_progress"],
         allowed_games=[
             RandovaniaGame(game) for game in data["allowed_games"]
         ],
     )
Ejemplo n.º 7
0
def decode_data_with_world_reader(
        data: Dict) -> Tuple[WorldReader, GameDescription]:
    game = RandovaniaGame(data["game"])

    resource_database = read_resource_database(data["resource_database"])
    dock_weakness_database = read_dock_weakness_database(
        data["dock_weakness_database"], resource_database)
    if game == RandovaniaGame.PRIME2:
        game_specific = read_game_specific(data["game_specific"],
                                           resource_database)
    else:
        game_specific = None

    world_reader = WorldReader(resource_database, dock_weakness_database)
    world_list = world_reader.read_world_list(data["worlds"])

    victory_condition = read_requirement(data["victory_condition"],
                                         resource_database)
    starting_location = AreaLocation.from_json(data["starting_location"])
    initial_states = read_initial_states(data["initial_states"],
                                         resource_database)

    return world_reader, GameDescription(
        game=game,
        resource_database=resource_database,
        game_specific=game_specific,
        dock_weakness_database=dock_weakness_database,
        world_list=world_list,
        victory_condition=victory_condition,
        starting_location=starting_location,
        initial_states=initial_states,
    )
Ejemplo n.º 8
0
def _all_hash_words() -> Dict[RandovaniaGame, typing.List[str]]:
    with (get_data_path() / "hash_words" /
          "hash_words.json").open() as hash_words_file:
        return {
            RandovaniaGame(key): words
            for key, words in json.load(hash_words_file).items()
        }
Ejemplo n.º 9
0
def decode_data_with_world_reader(
        data: Dict) -> Tuple[WorldReader, GameDescription]:
    data = game_migration.migrate_to_current(copy.deepcopy(data))

    game = RandovaniaGame(data["game"])

    resource_database = read_resource_database(game, data["resource_database"])
    dock_weakness_database = read_dock_weakness_database(
        data["dock_weakness_database"], resource_database)

    layers = frozen_lib.wrap(data["layers"])
    world_reader = WorldReader(resource_database, dock_weakness_database)
    world_list = world_reader.read_world_list(data["worlds"])

    victory_condition = read_requirement(data["victory_condition"],
                                         resource_database)
    starting_location = AreaIdentifier.from_json(data["starting_location"])
    initial_states = read_initial_states(data["initial_states"],
                                         resource_database)
    minimal_logic = read_minimal_logic_db(data["minimal_logic"])

    return world_reader, GameDescription(
        game=game,
        resource_database=resource_database,
        layers=layers,
        dock_weakness_database=dock_weakness_database,
        world_list=world_list,
        victory_condition=victory_condition,
        starting_location=starting_location,
        initial_states=initial_states,
        minimal_logic=minimal_logic,
    )
Ejemplo n.º 10
0
    def game(self) -> RandovaniaGame:
        if self.data is None:
            return self._preset.configuration.game

        if self.data["schema_version"] < 6:
            return RandovaniaGame.PRIME2

        return RandovaniaGame(self.data["game"])
Ejemplo n.º 11
0
    def game(self) -> RandovaniaGame:
        if self._preset is not None:
            return self._preset.configuration.game

        if self.data["schema_version"] < 6:
            return RandovaniaGame.METROID_PRIME_ECHOES

        return RandovaniaGame(self.data["game"])
Ejemplo n.º 12
0
 def from_json_dict(cls, value) -> "Preset":
     game = RandovaniaGame(value["game"])
     return Preset(
         name=value["name"],
         description=value["description"],
         base_preset_name=value["base_preset_name"],
         game=game,
         configuration=_game_to_config[game].from_json(
             value["configuration"]),
     )
Ejemplo n.º 13
0
def update_human_readable_logic(args):
    from randovania.game_description import pretty_print
    from randovania.game_description import data_reader
    game = RandovaniaGame(args.game)

    path, data = default_data.read_json_then_binary(game)
    gd = data_reader.decode_data(data)

    path.with_suffix("").mkdir(parents=True, exist_ok=True)
    pretty_print.write_human_readable_game(gd, path.with_suffix(""))
Ejemplo n.º 14
0
    async def _create_permalink(args_) -> Permalink:
        from randovania.interface_common.preset_manager import PresetManager

        preset_manager = PresetManager(None)
        preset = preset_manager.included_preset_with(RandovaniaGame(args_.game), args_.preset_name).get_preset()

        return Permalink(
            args_.seed_number,
            spoiler=True,
            presets={i: preset for i in range(args_.player_count)},
        )
Ejemplo n.º 15
0
    async def game_session_request_pickups(
            self) -> Tuple[RandovaniaGame, List[Tuple[str, bytes]]]:
        data = await self._emit_with_result("game_session_request_pickups",
                                            self._current_game_session.id)
        if data is None:
            return RandovaniaGame.PRIME2, []

        return RandovaniaGame(data["game"]), [
            (item["provider_name"], base64.b85decode(item["pickup"]))
            for item in data["pickups"] if item is not None
        ]
Ejemplo n.º 16
0
def export_videos_command_logic(args):
    from randovania.cli.commands.export_db_videos import export_videos
    games = list()

    if args.game is not None:
        games.append(RandovaniaGame(args.game))
    else:
        games = [g for g in RandovaniaGame]

    for game in games:
        export_videos(game, args.output_dir)
Ejemplo n.º 17
0
 def from_json_dict(cls, value) -> "Preset":
     game = RandovaniaGame(value["game"])
     return Preset(
         name=value["name"],
         uuid=uuid.UUID(value["uuid"]),
         description=value["description"],
         base_preset_uuid=uuid.UUID(value["base_preset_uuid"])
         if value["base_preset_uuid"] is not None else None,
         game=game,
         configuration=game.data.layout.configuration.from_json(
             value["configuration"]),
     )
Ejemplo n.º 18
0
    async def _on_game_session_pickups_update_raw(self, data):
        game = RandovaniaGame(data["game"])
        resource_database = default_database.resource_database_for(game)

        await self.on_game_session_pickups_update(
            GameSessionPickups(
                game=game,
                pickups=tuple(
                    (item["provider_name"],
                     _decode_pickup(item["pickup"], resource_database))
                    for item in data["pickups"]),
            ))
Ejemplo n.º 19
0
async def display_window_for(app, options, command: str, args):
    if command == "tracker":
        await show_tracker(app)
    elif command == "main":
        await show_main_window(app, options, args.preview)
    elif command == "data_editor":
        show_data_editor(app, options, RandovaniaGame(args.game))
    elif command == "game":
        show_game_details(app, options, args.rdvgame)
    elif command == "session":
        await show_game_session(app, options, args.session_id)
    else:
        raise RuntimeError(f"Unknown command: {command}")
Ejemplo n.º 20
0
def rename_docks_logic(args):
    from randovania.game_description import data_reader
    from randovania.game_description import data_writer
    from randovania.game_description import pretty_print
    from randovania.game_description.editor import Editor
    from randovania.game_description.world.dock_node import DockNode
    from randovania.game_description import integrity_check

    game = RandovaniaGame(args.game)

    path, data = default_data.read_json_then_binary(game)
    gd = data_reader.decode_data(data)

    # Make the changes
    editor = Editor(gd)

    for world in gd.world_list.worlds:
        for area in world.areas:
            for i in range(len(area.nodes)):
                node = area.nodes[i]
                if not isinstance(node, DockNode):
                    continue

                valid_name, suffix = integrity_check.dock_has_correct_name(
                    area, node)

                if not valid_name:
                    expected_name = integrity_check.base_dock_name(node)
                    docks_to_same_target = integrity_check.docks_with_same_base_name(
                        area, expected_name)

                    if suffix is None:
                        suffix = f" ({docks_to_same_target.index(node) + 1})"

                    print(
                        f"In {area.name}, renaming '{node.name}' to '{expected_name}{suffix}'"
                    )
                    editor.replace_node(
                        area, node,
                        dataclasses.replace(node,
                                            name=f"{expected_name}{suffix}"))

    # Write it back
    logging.info("Writing database files")
    new_data = data_writer.write_game_description(gd)
    data_writer.write_as_split_files(new_data, path)

    logging.info("Writing human readable")
    path.with_suffix("").mkdir(parents=True, exist_ok=True)
    pretty_print.write_human_readable_game(gd, path.with_suffix(""))
Ejemplo n.º 21
0
    def __getattr__(self, item):
        if isinstance(item, str) and item.startswith("game_"):
            game_name = item[len("game_"):]
            try:
                game: RandovaniaGame = RandovaniaGame(game_name)
            except ValueError:
                raise AttributeError(item)

            result = getattr(self, f"_{item}", None)
            if result is None:
                result = game.options.default_for_game(game)
            return result

        raise AttributeError(item)
Ejemplo n.º 22
0
def _migrate_v32(preset: dict) -> dict:
    game = RandovaniaGame(preset["game"])
    weakness_database = default_database.game_description_for(
        game).dock_weakness_database

    preset["configuration"]["dock_rando"] = {
        "mode": DockRandoMode.VANILLA.value,
        "types_state": {
            dock_type.short_name:
            DockTypeState.default_state(game, dock_type.short_name).as_json
            for dock_type in weakness_database.dock_types
        }
    }
    return preset
Ejemplo n.º 23
0
 def from_json(cls, value: dict) -> "EchoesPerGameOptions":
     game = RandovaniaGame.METROID_PRIME_ECHOES
     cosmetic_patches = game.data.layout.cosmetic_patches.from_json(
         value["cosmetic_patches"])
     return cls(
         cosmetic_patches=cosmetic_patches,
         input_path=decode_if_not_none(value["input_path"], Path),
         output_directory=decode_if_not_none(value["output_directory"],
                                             Path),
         use_external_models={
             RandovaniaGame(g)
             for g in value["use_external_models"]
         },
     )
Ejemplo n.º 24
0
def bulk_move_node_logic(args):
    game = RandovaniaGame(args.game)

    path, data = default_data.read_json_then_binary(game)
    gd = data_reader.decode_data(data)

    # Make the changes
    editor = Editor(gd)
    world = gd.world_list.world_with_name(args.world)

    source_area = world.area_by_name(args.source_area)
    target_area = world.area_by_name(args.target_area)

    node_names = args.node_names

    requirements: dict[str, dict[str, Requirement]] = {
        node_name: {
            target.name: req
            for target, req in source_area.connections[
                source_area.node_with_name(node_name)].items()
        }
        for node_name in node_names
    }

    for node_name in node_names:
        logging.info("Moving node %s", node_name)
        editor.move_node_from_area_to_area(
            source_area, target_area, source_area.node_with_name(node_name))

    for name, connections in requirements.items():
        source_node = target_area.node_with_name(name)
        for target, req in connections.items():
            editor.edit_connections(
                target_area,
                source_node,
                target_area.node_with_name(target),
                req,
            )

    # Write it back
    logging.info("Writing database files")
    new_data = data_writer.write_game_description(gd)
    data_writer.write_as_split_files(new_data, path)

    logging.info("Writing human readable")
    path.with_suffix("").mkdir(parents=True, exist_ok=True)
    pretty_print.write_human_readable_game(gd, path.with_suffix(""))
Ejemplo n.º 25
0
def _migrate_v8(preset: dict) -> dict:
    from randovania.game_description import default_database
    game = default_database.game_description_for(RandovaniaGame(
        preset["game"]))

    def _name_to_location(name: str):
        world_name, area_name = name.split("/", 1)
        world = game.world_list.world_with_name(world_name)
        area = world.area_by_name(area_name)
        return AreaLocation(world.world_asset_id, area.area_asset_id)

    preset["configuration"]["starting_location"] = [
        _name_to_location(location).as_json
        for location in preset["configuration"]["starting_location"]
    ]

    return preset
Ejemplo n.º 26
0
async def permalink_command_body(args):
    from randovania.interface_common.preset_manager import PresetManager

    preset_manager = PresetManager(None)
    versioned_preset = preset_manager.included_preset_with(
        RandovaniaGame(args.game), args.preset)
    if versioned_preset is None:
        raise ValueError(f"Unknown preset: {args.preset}")

    seed = args.seed
    if seed is None:
        seed = random.randint(0, 2**31)

    preset = versioned_preset.get_preset()
    permalink = Permalink(
        seed_number=seed,
        spoiler=not args.race,
        presets={i: preset
                 for i in range(args.player_count)})
    print(permalink.as_base64_str)

    Permalink.from_str(permalink.as_base64_str)
Ejemplo n.º 27
0
def _migrate_v14(preset: dict) -> dict:
    game = RandovaniaGame(preset["game"])
    db = default_database.game_description_for(game)

    def _migrate_area_location(old_loc: dict[str, int]) -> dict[str, str]:
        result = migration_data.convert_area_loc_id_to_name(game, old_loc)

        if "instance_id" in old_loc:
            # FIXME
            world = db.world_list.world_with_name(result["world_name"])
            area = world.area_by_name(result["area_name"])
            for node in area.nodes:
                if node.extra.get(
                        "teleporter_instance_id") == old_loc["instance_id"]:
                    result["node_name"] = node.name
                    break

        return result

    preset["configuration"]["starting_location"] = [
        _migrate_area_location(old_loc)
        for old_loc in preset["configuration"]["starting_location"]
    ]

    if "elevators" in preset["configuration"]:
        elevators = preset["configuration"]["elevators"]

        elevators["excluded_teleporters"] = [
            _migrate_area_location(old_loc)
            for old_loc in elevators["excluded_teleporters"]
        ]
        elevators["excluded_targets"] = [
            _migrate_area_location(old_loc)
            for old_loc in elevators["excluded_targets"]
        ]

        preset["configuration"]["elevators"] = elevators

    return preset
Ejemplo n.º 28
0
    def __getattr__(self, item):
        if isinstance(item, str):
            if item.startswith("game_"):
                game_name = item[len("game_"):]
            elif item.startswith("is_game_expanded_"):
                game_name = item[len("is_game_expanded_"):]
            else:
                raise AttributeError(item)

            try:
                game: RandovaniaGame = RandovaniaGame(game_name)
            except ValueError:
                raise AttributeError(item)

            result = getattr(self, f"_{item}", None)
            if result is None:
                if item.startswith("game_"):
                    result = game.options.default_for_game(game)
                else:
                    result = game.data.development_state.is_stable
            return result

        raise AttributeError(item)
Ejemplo n.º 29
0
 async def database_command(self, ctx: SlashContext, game: str):
     game = RandovaniaGame(game)
     embed, components = self._message_components_for_game(game)
     await ctx.send(embed=embed, components=components, hidden=True)
Ejemplo n.º 30
0
def _migrate_v8(preset: dict) -> dict:
    game = default_database.game_description_for(RandovaniaGame(
        preset["game"]))

    # FIXME: area location is now something different, this code broke

    def _name_to_location(name: str):
        world_name, area_name = name.split("/", 1)
        world = game.world_list.world_with_name(world_name)
        area = world.area_by_name(area_name)
        return {
            "world_asset_id": world.extra["asset_id"],
            "area_asset_id": area.extra["asset_id"],
        }

    preset["configuration"]["multi_pickup_placement"] = False

    if "energy_per_tank" in preset["configuration"]:
        preset["configuration"]["energy_per_tank"] = int(
            preset["configuration"]["energy_per_tank"])

    preset["configuration"]["starting_location"] = [
        _name_to_location(location)
        for location in preset["configuration"]["starting_location"]
    ]

    excluded_teleporters = []
    if preset["game"] == "prime2":
        excluded_teleporters = [
            {
                "world_asset_id": 464164546,
                "area_asset_id": 3136899603,
                "instance_id": 204865660
            },
            {
                "world_asset_id": 2252328306,
                "area_asset_id": 2068511343,
                "instance_id": 589949
            },
            {
                "world_asset_id": 464164546,
                "area_asset_id": 1564082177,
                "instance_id": 4260106
            },
            {
                "world_asset_id": 1006255871,
                "area_asset_id": 2278776548,
                "instance_id": 136970379
            },
        ]

    preset["configuration"]["elevators"] = {
        "mode":
        preset["configuration"]["elevators"],
        "excluded_teleporters":
        excluded_teleporters,
        "excluded_targets": [],
        "skip_final_bosses":
        preset["configuration"].pop("skip_final_bosses", False),
        "allow_unvisited_room_names":
        True,
    }
    if preset["configuration"]["major_items_configuration"][
            "default_items"].get("visor") == "Dark Visor":
        preset["configuration"]["major_items_configuration"]["default_items"][
            "visor"] = "Combat Visor"
        preset["configuration"]["major_items_configuration"]["items_state"][
            "Scan Visor"] = {
                "num_included_in_starting_items": 1
            }

    return preset