def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata) -> "MajorItemsConfiguration": from randovania.game_description import default_database item_database = default_database.default_prime2_item_database() progressive_suit = bitpacking.decode_bool(decoder) progressive_grapple = bitpacking.decode_bool(decoder) progressive_launcher = bitpacking.decode_bool(decoder) default = MajorItemsConfiguration.default() num_items = decoder.decode_single(len(default.items_state)) indices_with_custom = { decoder.decode_single(len(default.items_state)) for _ in range(num_items) } items_state = {} for index, item in enumerate(item_database.major_items.values()): if index in indices_with_custom: items_state[item] = MajorItemState.bit_pack_unpack( decoder, item) else: items_state[item] = default.items_state[item] minimum, maximum = decoder.decode(RANDOM_STARTING_ITEMS_LIMIT, RANDOM_STARTING_ITEMS_LIMIT) return cls(items_state, progressive_suit=progressive_suit, progressive_grapple=progressive_grapple, progressive_launcher=progressive_launcher, minimum_random_starting_items=minimum, maximum_random_starting_items=maximum)
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata) -> "TranslatorConfiguration": from randovania.layout import configuration_factory templates = [ configuration_factory.get_vanilla_actual_translator_configurations( ), configuration_factory.get_vanilla_colors_translator_configurations( ), cls.default().with_full_random().translator_requirement, None, ] fixed_gfmc_compound = bitpacking.decode_bool(decoder) fixed_torvus_temple = bitpacking.decode_bool(decoder) fixed_great_temple = bitpacking.decode_bool(decoder) translator_requirement = decoder.decode_element(templates) if translator_requirement is None: translator_requirement = {} for gate in templates[0].keys(): translator_requirement[ gate] = LayoutTranslatorRequirement.bit_pack_unpack( decoder, {}) return cls( translator_requirement, fixed_gfmc_compound=fixed_gfmc_compound, fixed_torvus_temple=fixed_torvus_temple, fixed_great_temple=fixed_great_temple, )
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata) -> "Permalink": version, seed_number = decoder.decode(_PERMALINK_MAX_VERSION, _PERMALINK_MAX_SEED) cls._raise_if_different_version(version) spoiler = bitpacking.decode_bool(decoder) player_count = bitpacking.decode_int_with_limits( decoder, _PERMALINK_PLAYER_COUNT_LIMITS) manager = PresetManager(None) previous_unique_presets = [] presets = {} for index in range(player_count): in_previous_presets = bitpacking.decode_bool(decoder) if in_previous_presets: presets[index] = decoder.decode_element( previous_unique_presets) continue preset = _decode_preset(decoder, manager) previous_unique_presets.append(preset) presets[index] = preset return Permalink(seed_number, spoiler, presets)
def _decode_item_category(decoder: BitPackDecoder) -> ItemCategory: return ItemCategory(name=bitpacking.decode_string(decoder), long_name=bitpacking.decode_string(decoder), hint_details=(bitpacking.decode_string(decoder), bitpacking.decode_string(decoder)), is_major=bitpacking.decode_bool(decoder), is_key=bitpacking.decode_bool(decoder))
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, )
def bit_pack_unpack(cls, decoder: BitPackDecoder, name: str, database: ResourceDatabase) -> PickupEntry: model_index = decoder.decode_single(255) probability_offset = BitPackFloat.bit_pack_unpack( decoder, _PROBABILITY_OFFSET_META) probability_multiplier = BitPackFloat.bit_pack_unpack( decoder, _PROBABILITY_MULTIPLIER_META) item_category = ItemCategory.bit_pack_unpack(decoder, {}) broad_category = ItemCategory.bit_pack_unpack(decoder, {}) has_name = bitpacking.decode_bool(decoder) num_conditional = decoder.decode_single( MAXIMUM_PICKUP_CONDITIONAL_RESOURCES) + 1 conditional_resources = [] for i in range(num_conditional): item_name = None # TODO: get the first resource name if i > 0: item_dependency = decoder.decode_element(database.item) else: item_dependency = None resources = [] for _ in range(decoder.decode_single(MAXIMUM_PICKUP_RESOURCES + 1)): resource = decoder.decode_element(database.item) quantity = decoder.decode_single(255) resources.append((resource, quantity)) if has_name: if bitpacking.decode_bool(decoder): item_name = name else: item_name = resources[0][0].long_name conditional_resources.append( ConditionalResources( name=item_name, item=item_dependency, resources=tuple(resources), )) num_convert = decoder.decode_single(MAXIMUM_PICKUP_CONVERSION + 1) convert_resources = [] for i in range(num_convert): source = decoder.decode_element(database.item) target = decoder.decode_element(database.item) convert_resources.append(ResourceConversion(source, target)) return PickupEntry( name=name, model_index=model_index, item_category=item_category, broad_category=broad_category, resources=tuple(conditional_resources), convert_resources=tuple(convert_resources), probability_offset=probability_offset, probability_multiplier=probability_multiplier, )
def bit_pack_unpack(cls, decoder: BitPackDecoder, item: MajorItem, reference: "MajorItemState") -> "MajorItemState": db = default_database.resource_database_for(item.game) if item.progression: main_index = item.progression[0] else: main_index = item.ammo_index[0] main_item = db.get_item(main_index) # original location original = False if item.original_index is not None: original = bitpacking.decode_bool(decoder) # num shuffled shuffled = bitpacking.decode_int_with_limits(decoder, DEFAULT_MAXIMUM_SHUFFLED) # starting item if main_item.max_capacity > 1: starting = bitpacking.decode_int_with_limits( decoder, (2, main_item.max_capacity + 1)) else: starting = decoder.decode_single(main_item.max_capacity + 1) # priority priority = bitpacking.BitPackFloat.bit_pack_unpack( decoder, PRIORITY_LIMITS) # ammo index if item.ammo_index: custom_ammo = bitpacking.decode_bool(decoder) if custom_ammo: all_equal = len( item.ammo_index) <= 1 or bitpacking.decode_bool(decoder) if all_equal: ammo = decoder.decode_single( db.get_item(item.ammo_index[0]).max_capacity + 1) included_ammo = [ammo] * len(item.ammo_index) else: included_ammo = [ decoder.decode_single( db.get_item(item).max_capacity + 1) for item in item.ammo_index ] else: included_ammo = reference.included_ammo else: included_ammo = [] return cls( include_copy_in_original_location=original, num_shuffled_pickups=shuffled, num_included_in_starting_items=starting, priority=priority, included_ammo=tuple(included_ammo), )
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata): minimal_logic = bitpacking.decode_bool(decoder) encodable_levels = list(LayoutTrickLevel) encodable_levels.remove(LayoutTrickLevel.NO_TRICKS) encodable_levels.remove(LayoutTrickLevel.MINIMAL_LOGIC) specific_levels = {} for trick in sorted(_all_tricks()): if bitpacking.decode_bool(decoder): specific_levels[trick.short_name] = decoder.decode_element( encodable_levels) return cls(minimal_logic, specific_levels)
def _decode_preset(decoder: BitPackDecoder, manager: PresetManager) -> Preset: included_presets = [versioned.get_preset() for versioned in manager.included_presets] is_custom_preset = bitpacking.decode_bool(decoder) reference_preset = decoder.decode_element(included_presets) if is_custom_preset: patcher_configuration = PatcherConfiguration.bit_pack_unpack( decoder, {"reference": reference_preset.patcher_configuration}) layout_configuration = LayoutConfiguration.bit_pack_unpack( decoder, {"reference": reference_preset.layout_configuration}) preset = Preset( name="{} Custom".format(reference_preset.name), description="A customized preset.", base_preset_name=reference_preset.name, patcher_configuration=patcher_configuration, layout_configuration=layout_configuration, ) else: preset = reference_preset included_data_hash = decoder.decode_single(256) expected_data_hash = _dictionary_byte_hash(preset.layout_configuration.game_data) if included_data_hash != expected_data_hash: raise ValueError("Given permalink is for a Randovania database with hash '{}', " "but current database has hash '{}'.".format(included_data_hash, expected_data_hash)) return preset
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata) -> "Preset": from randovania.interface_common.preset_manager import PresetManager manager: PresetManager = metadata["manager"] included_presets = [ versioned.get_preset() for versioned in manager.included_presets ] is_custom_preset = bitpacking.decode_bool(decoder) reference = decoder.decode_element(included_presets) if is_custom_preset: preset = Preset( name="{} Custom".format(reference.name), description="A customized preset.", base_preset_name=reference.name, game=reference.game, configuration=reference.configuration.bit_pack_unpack( decoder, {"reference": reference.configuration}), ) else: preset = reference included_data_hash = decoder.decode_single(256) expected_data_hash = _dictionary_byte_hash( preset.configuration.game_data) if included_data_hash != expected_data_hash: raise ValueError( "Given permalink is for a Randovania database with hash '{}', " "but current database has hash '{}'.".format( included_data_hash, expected_data_hash)) return preset
def bit_pack_unpack(cls, decoder: BitPackDecoder, item: MajorItem) -> "MajorItemState": original = decoder.decode_single(2) # num shuffled shuffled = bitpacking.decode_int_with_limits(decoder, DEFAULT_MAXIMUM_SHUFFLED) # starting item starting = decoder.decode_single( ENERGY_TANK_MAXIMUM_COUNT if item.item_category == ItemCategory.ENERGY_TANK else 2) if item.ammo_index: included_ammo = decoder.decode(*[256 for _ in item.ammo_index]) else: included_ammo = [] # allowed_as_random_starting_item allowed_as_random_starting_item = bitpacking.decode_bool(decoder) return cls( include_copy_in_original_location=bool(original), num_shuffled_pickups=shuffled, num_included_in_starting_items=starting, included_ammo=tuple(included_ammo), allowed_as_random_starting_item=allowed_as_random_starting_item, )
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata) -> "AmmoState": ammo: Ammo = metadata["ammo"] db = default_database.resource_database_for(ammo.game) # Ammo Count ammo_count = [] for ammo_index in ammo.items: ammo_item = db.get_item(ammo_index) ammo_count.append( bitpacking.decode_int_with_limits( decoder, (ammo_item.max_capacity // 2, ammo_item.max_capacity + 1), )) # Pickup Count pickup_count = bitpacking.decode_big_int(decoder) # Require Major Item requires_major_item = True if ammo.unlocked_by is not None: requires_major_item = bitpacking.decode_bool(decoder) return cls( ammo_count=tuple(ammo_count), pickup_count=pickup_count, requires_major_item=requires_major_item, )
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata): game = metadata["reference"].game game_data = default_data.read_json_then_binary(game)[1] minimal_logic = bitpacking.decode_bool(decoder) specific_levels = {} if not minimal_logic: encodable_levels = list(LayoutTrickLevel) encodable_levels.remove(LayoutTrickLevel.DISABLED) for trick in sorted(_all_tricks(game_data)): if bitpacking.decode_bool(decoder): specific_levels[trick.short_name] = decoder.decode_element(encodable_levels) return cls(minimal_logic, specific_levels, game)
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata): game = metadata["reference"].game resource_database = default_database.resource_database_for(game) minimal_logic = bitpacking.decode_bool(decoder) specific_levels = {} if not minimal_logic: encodable_levels = list(LayoutTrickLevel) encodable_levels.remove(LayoutTrickLevel.DISABLED) for trick in _all_tricks(resource_database): if bitpacking.decode_bool(decoder): specific_levels[trick.short_name] = decoder.decode_element( encodable_levels) return cls(minimal_logic, specific_levels, game)
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata) -> "AmmoState": pickup_count = decoder.decode_single(cls.maximum_pickup_count()) requires_major_item = bitpacking.decode_bool(decoder) return cls( variance=0, pickup_count=pickup_count, requires_major_item=requires_major_item, )
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata): default: AmmoConfiguration = metadata["reference"] # Maximum Ammo maximum_ammo = {} for item_key, default_value in default.maximum_ammo.items(): is_different = bitpacking.decode_bool(decoder) if is_different: maximum_ammo[item_key] = decoder.decode_single(256) else: maximum_ammo[item_key] = default_value items_state = {} for item, default_state in default.items_state.items(): is_different = bitpacking.decode_bool(decoder) if is_different: items_state[item] = AmmoState.bit_pack_unpack(decoder, {}) else: items_state[item] = default_state return cls(maximum_ammo, items_state)
def test_decode_bool(bool_fixture): # Setup value, encoded = bool_fixture decoder = MagicMock() decoder.decode_single.return_value = encoded[0] # Run result = bitpacking.decode_bool(decoder) # Assert decoder.decode_single.assert_called_once_with(encoded[1]) assert result == value
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata): randomization_mode = RandomizationMode.bit_pack_unpack(decoder, metadata) if bitpacking.decode_bool(decoder): indices = bitpacking.decode_sorted_array_elements(decoder, _ALL_INDICES) else: indices = [] return AvailableLocationsConfiguration( randomization_mode=randomization_mode, excluded_indices=frozenset(PickupIndex(item) for item in indices), )
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata): global_level = LayoutTrickLevel.bit_pack_unpack(decoder, metadata) encodable_levels = list(LayoutTrickLevel) encodable_levels.remove(LayoutTrickLevel.MINIMAL_LOGIC) specific_levels = {} for trick in sorted(_all_trick_indices()): if bitpacking.decode_bool(decoder): specific_levels[trick] = decoder.decode_element(encodable_levels) return cls(global_level, specific_levels)
def bit_pack_unpack(cls, decoder: bitpacking.BitPackDecoder, metadata): default: AmmoConfiguration = metadata["reference"] items_state = {} for ammo, default_state in default.items_state.items(): is_different = bitpacking.decode_bool(decoder) if is_different: items_state[ammo] = AmmoState.bit_pack_unpack( decoder, {"ammo": ammo}) else: items_state[ammo] = default_state return cls(items_state)
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata): game = metadata["reference"].game db = default_database.game_description_for(game) randomization_mode = RandomizationMode.bit_pack_unpack(decoder, metadata) if bitpacking.decode_bool(decoder): indices = bitpacking.decode_sorted_array_elements(decoder, _all_indices(db)) else: indices = [] return AvailableLocationsConfiguration( randomization_mode=randomization_mode, excluded_indices=frozenset(PickupIndex(item) for item in indices), game=game, )
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata) -> "GeneratorParameters": games = decode_game_list(decoder) seed_number = decoder.decode_single(_PERMALINK_MAX_SEED) spoiler = bitpacking.decode_bool(decoder) manager = PresetManager(None) presets = [ Preset.bit_pack_unpack(decoder, {"manager": manager, "game": game}) for game in games ] for game in _get_unique_games(presets): included_data_hash = decoder.decode_single(256) expected_data_hash = _game_db_hash(game) if included_data_hash != expected_data_hash: raise ValueError("Given permalink is for a Randovania {} database with hash '{}', " "but current database has hash '{}'.".format(game.long_name, included_data_hash, expected_data_hash)) return GeneratorParameters(seed_number, spoiler, presets)
def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata) -> "Permalink": version, seed, spoiler = decoder.decode(_PERMALINK_MAX_VERSION, _PERMALINK_MAX_SEED, 2) cls._raise_if_different_version(version) included_data_hash = decoder.decode_single(256) manager = PresetManager(None) is_custom_preset = bitpacking.decode_bool(decoder) reference_preset = decoder.decode_element(manager.included_presets) if is_custom_preset: patcher_configuration = PatcherConfiguration.bit_pack_unpack( decoder, {"reference": reference_preset.patcher_configuration}) layout_configuration = LayoutConfiguration.bit_pack_unpack( decoder, {"reference": reference_preset.layout_configuration}) preset = Preset( name="{} Custom".format(reference_preset.name), description="A customized preset.", base_preset_name=reference_preset.name, patcher_configuration=patcher_configuration, layout_configuration=layout_configuration, ) else: preset = reference_preset expected_data_hash = _dictionary_byte_hash( preset.layout_configuration.game_data) if included_data_hash != expected_data_hash: raise ValueError( "Given permalink is for a Randovania database with hash '{}', " "but current database has hash '{}'.".format( included_data_hash, expected_data_hash)) return Permalink( seed, bool(spoiler), preset, )