Exemple #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
Exemple #2
0
 def allowed_games(self) -> List[RandovaniaGame]:
     dev_features = self.dev_features or ""
     return [
         game for game in RandovaniaGame.sorted_all_games()
         if game.data.defaults_available_in_game_sessions
         or game.value in dev_features
     ]
 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"],
     )
Exemple #4
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"]
         ],
     )
Exemple #5
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]
Exemple #6
0
    def bit_pack_unpack(cls, decoder: BitPackDecoder, database: ResourceDatabase) -> PickupEntry:
        helper = DatabaseBitPackHelper(database)

        name = bitpacking.decode_string(decoder)
        model = PickupModel(
            game=RandovaniaGame.bit_pack_unpack(decoder, {}),
            name=bitpacking.decode_string(decoder),
        )
        item_category = ItemCategory.bit_pack_unpack(decoder, {})
        broad_category = ItemCategory.bit_pack_unpack(decoder, {})
        progression = bitpacking.decode_tuple(decoder, helper.decode_resource_quantity)
        extra_resources = bitpacking.decode_tuple(decoder, helper.decode_resource_quantity)
        unlocks_resource = bitpacking.decode_bool(decoder)
        resource_lock = None
        if bitpacking.decode_bool(decoder):
            resource_lock = helper.decode_resource_lock(decoder)
        respects_lock = bitpacking.decode_bool(decoder)
        probability_offset = BitPackFloat.bit_pack_unpack(decoder, _PROBABILITY_OFFSET_META)
        probability_multiplier = BitPackFloat.bit_pack_unpack(decoder, _PROBABILITY_MULTIPLIER_META)

        return PickupEntry(
            name=name,
            model=model,
            item_category=item_category,
            broad_category=broad_category,
            progression=progression,
            extra_resources=extra_resources,
            unlocks_resource=unlocks_resource,
            resource_lock=resource_lock,
            respects_lock=respects_lock,
            probability_offset=probability_offset,
            probability_multiplier=probability_multiplier,
        )
Exemple #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,
    )
    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"]
            ],
        )
Exemple #9
0
    def update_items(self):
        self.clear()

        tree_item: dict[Any, QtWidgets.QTreeWidgetItem] = {}
        for game in RandovaniaGame.sorted_all_games():
            if not game.data.development_state.can_view(
                    self.show_experimental):
                continue

            root = QtWidgets.QTreeWidgetItem(self)
            root.setText(0, game.long_name)
            root.setExpanded(True)
            tree_item[game] = root

        self.preset_to_item = {}

        # Included presets
        for preset in self.window_manager.preset_manager.included_presets.values(
        ):
            if not preset.game.data.development_state.can_view(
                    self.show_experimental):
                continue

            item = QtWidgets.QTreeWidgetItem(tree_item[preset.game])
            item.setText(0, preset.name)
            item.setExpanded(True)
            item.setData(0, Qt.UserRole, preset.uuid)
            self.preset_to_item[preset.uuid] = item

        # Custom Presets
        for preset in self.window_manager.preset_manager.custom_presets.values(
        ):
            if not preset.game.data.development_state.can_view(
                    self.show_experimental):
                continue

            item = QtWidgets.QTreeWidgetItem(tree_item[preset.game])
            item.setText(0, preset.name)
            item.setData(0, Qt.UserRole, preset.uuid)
            self.preset_to_item[preset.uuid] = item

        # Set parents after, so don't have issues with order
        for preset in sorted(
                self.window_manager.preset_manager.custom_presets.values(),
                key=lambda it: it.name):
            if preset.base_preset_uuid in self.preset_to_item:
                root_item = tree_item[preset.game]
                self_item = self.preset_to_item[preset.uuid]
                target_parent = parent_item = self.preset_to_item[
                    preset.base_preset_uuid]

                while parent_item != root_item:
                    if parent_item == self_item:
                        # LOOP DETECTED!
                        target_parent = root_item
                        break
                    parent_item = parent_item.parent()

                root_item.removeChild(self_item)
                target_parent.addChild(self_item)
Exemple #10
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,
    )
Exemple #11
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()
        }
Exemple #12
0
    def __init__(self, data_dir: Path, user_dir: Optional[Path] = None):
        self._data_dir = data_dir
        self._user_dir = user_dir or data_dir
        self._last_changelog_displayed = str(update_checker.strict_current_version())

        for game in RandovaniaGame.all_games():
            self._set_field(f"game_{game.value}", None)
Exemple #13
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,
        ), )
Exemple #14
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"])
Exemple #15
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"])
Exemple #16
0
def add_per_game_serializer():
    def make_decoder(g):
        return lambda it: g.options.from_json(it)

    for game in RandovaniaGame.all_games():
        _SERIALIZER_FOR_FIELD[f"game_{game.value}"] = Serializer(
            lambda it: it.as_json,
            make_decoder(game),
        )
Exemple #17
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"]),
     )
Exemple #18
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(""))
Exemple #19
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)},
        )
Exemple #20
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
        ]
Exemple #21
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)
Exemple #22
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"]),
     )
Exemple #23
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"]),
            ))
Exemple #24
0
    def _on_first_show(self):
        self._index_for_game = {}

        for game in RandovaniaGame.sorted_all_games():
            if game.gui.help_widget is None:
                continue

            index = self.addTab(game.gui.help_widget(), game.long_name)
            self.setTabVisible(
                index,
                game.data.development_state.can_view(
                    self._experimental_visible))
            self._index_for_game[game] = index
Exemple #25
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}")
Exemple #26
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"]
         },
     )
Exemple #27
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)
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
Exemple #29
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(""))
Exemple #30
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(""))