From 909172cbadf915991f08b61b93734744e8ba2ff7 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sun, 9 May 2021 21:22:21 +0200 Subject: [PATCH] Factorio, Minecraft & Hollow Knight: add startinventory support --- BaseClasses.py | 2 +- Main.py | 18 ++++++++---------- MultiServer.py | 6 ++++++ Mystery.py | 26 +++++++++++--------------- WebHostLib/tracker.py | 4 ++-- playerSettings.yaml | 11 ++++++----- worlds/__init__.py | 2 +- worlds/alttp/EntranceRandomizer.py | 3 +-- worlds/alttp/Regions.py | 6 ++++-- worlds/alttp/__init__.py | 19 ------------------- 10 files changed, 40 insertions(+), 57 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index d931309f..84a558d1 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -68,6 +68,7 @@ class MultiWorld(): self.fix_palaceofdarkness_exit = self.AttributeProxy(lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeonssimple']) self.fix_trock_exit = self.AttributeProxy(lambda player: self.shuffle[player] not in ['vanilla', 'simple', 'restricted', 'dungeonssimple']) self.NOTCURSED = self.AttributeProxy(lambda player: not self.CURSED[player]) + self.remote_items = self.AttributeProxy(lambda player: self.game[player] != "A Link to the Past") for player in range(1, players + 1): def set_player_attr(attr, val): @@ -87,7 +88,6 @@ class MultiWorld(): set_player_attr('retro', False) set_player_attr('hints', True) set_player_attr('player_names', []) - set_player_attr('remote_items', False) set_player_attr('required_medallions', ['Ether', 'Quake']) set_player_attr('swamp_patch_required', False) set_player_attr('powder_patch_required', False) diff --git a/Main.py b/Main.py index 289869dc..8dc772a8 100644 --- a/Main.py +++ b/Main.py @@ -29,7 +29,7 @@ from worlds.factorio.Mod import generate_mod from worlds.minecraft import gen_minecraft, fill_minecraft_slot_data, generate_mc_data from worlds.minecraft.Regions import minecraft_create_regions from worlds.generic.Rules import locality_rules -from worlds import Games +from worlds import Games, lookup_any_item_name_to_id import Patch seeddigits = 20 @@ -89,7 +89,6 @@ def main(args, seed=None): world.hints = args.hints.copy() - world.remote_items = args.remote_items.copy() world.mapshuffle = args.mapshuffle.copy() world.compassshuffle = args.compassshuffle.copy() world.keyshuffle = args.keyshuffle.copy() @@ -171,15 +170,15 @@ def main(args, seed=None): world.player_names[player].append(name) logger.info('') + for player in world.player_ids: + for item_name in args.startinventory[player]: + item = Item(item_name, True, lookup_any_item_name_to_id[item_name], player) + world.push_precollected(item) for player in world.alttp_player_ids: world.difficulty_requirements[player] = difficulties[world.difficulty[player]] for player in world.player_ids: - for tok in filter(None, args.startinventory[player].split(',')): - item = ItemFactory(tok.strip(), player) - if item: - world.push_precollected(item) # enforce pre-defined local items. if world.goal[player] in ["localtriforcehunt", "localganontriforcehunt"]: @@ -489,9 +488,9 @@ def main(args, seed=None): er_hint_data[player][location_id] = main_entrance.name oldmancaves.append(((location_id, player), (item.code, player))) - precollected_items = [[] for player in range(world.players)] + precollected_items = {player: [] for player in range(1, world.players+1)} for item in world.precollected_items: - precollected_items[item.player - 1].append(item.code) + precollected_items[item.player].append(item.code) FillDisabledShopSlots(world) @@ -527,8 +526,7 @@ def main(args, seed=None): "names": parsed_names, "connect_names": connect_names, "remote_items": {player for player in range(1, world.players + 1) if - world.remote_items[player] or - world.game[player] != "A Link to the Past"}, + world.remote_items[player]}, "locations": { (location.address, location.player): (location.item.code, location.item.player) diff --git a/MultiServer.py b/MultiServer.py index 167b8c83..d070efab 100644 --- a/MultiServer.py +++ b/MultiServer.py @@ -150,6 +150,12 @@ class Context(Node): self.er_hint_data = {int(player): {int(address): name for address, name in loc_data.items()} for player, loc_data in decoded_obj["er_hint_data"].items()} self.games = decoded_obj["games"] + # award remote-items start inventory: + for team in range(len(decoded_obj['names'])): + for slot, item_codes in decoded_obj["precollected_items"].items(): + if slot in self.remote_items: + self.received_items[team, slot] = [NetworkItem(item_code, -2, 0) for item_code in item_codes] + if use_embedded_server_options: server_options = decoded_obj.get("server_options", {}) self._set_options(server_options) diff --git a/Mystery.py b/Mystery.py index 8be7c1b0..aae386b2 100644 --- a/Mystery.py +++ b/Mystery.py @@ -528,6 +528,17 @@ def roll_settings(weights: dict, plando_options: typing.Set[str] = frozenset(("b else: raise Exception(f"Could not force item {item} to be world-non-local, as it was not recognized.") + inventoryweights = weights.get('startinventory', {}) + startitems = [] + for item in inventoryweights.keys(): + itemvalue = get_choice(item, inventoryweights) + if isinstance(itemvalue, int): + for i in range(int(itemvalue)): + startitems.append(item) + elif itemvalue: + startitems.append(item) + ret.startinventory = startitems + if ret.game == "A Link to the Past": roll_alttp_settings(ret, weights, plando_options) elif ret.game == "Hollow Knight": @@ -700,23 +711,8 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options): if not ret.required_medallions[index]: raise Exception(f"unknown Medallion {medallion} for {'misery mire' if index == 0 else 'turtle rock'}") - inventoryweights = weights.get('startinventory', {}) - startitems = [] - for item in inventoryweights.keys(): - itemvalue = get_choice(item, inventoryweights) - if item.startswith(('Progressive ', 'Small Key ', 'Rupee', 'Piece of Heart', 'Boss Heart Container', - 'Sanctuary Heart Container', 'Arrow', 'Bombs ', 'Bomb ', 'Bottle')) and isinstance( - itemvalue, int): - for i in range(int(itemvalue)): - startitems.append(item) - elif itemvalue: - startitems.append(item) - ret.startinventory = ','.join(startitems) - ret.glitch_boots = get_choice('glitch_boots', weights, True) - ret.remote_items = get_choice('remote_items', weights, False) - if get_choice("local_keys", weights, "l" in dungeon_items): # () important for ordering of commands, without them the Big Keys section is part of the Small Key else ret.local_items |= item_name_groups["Small Keys"] if ret.keyshuffle else set() diff --git a/WebHostLib/tracker.py b/WebHostLib/tracker.py index 3770e3d5..5c491822 100644 --- a/WebHostLib/tracker.py +++ b/WebHostLib/tracker.py @@ -351,7 +351,7 @@ def getPlayerTracker(tracker: UUID, tracked_team: int, tracked_player: int): checks_done = {loc_name: 0 for loc_name in default_locations} # Add starting items to inventory - starting_items = precollected_items[tracked_player - 1] + starting_items = precollected_items[tracked_player] if starting_items: for item_id in starting_items: attribute_item_solo(inventory, item_id) @@ -506,7 +506,7 @@ def getTracker(tracker: UUID): for (team, player), locations_checked in multisave.get("location_checks", {}): if precollected_items: - precollected = precollected_items[player - 1] + precollected = precollected_items[player] for item_id in precollected: attribute_item(inventory, team, player, item_id) for location in locations_checked: diff --git a/playerSettings.yaml b/playerSettings.yaml index 8dff638d..a1e811f3 100644 --- a/playerSettings.yaml +++ b/playerSettings.yaml @@ -36,6 +36,12 @@ accessibility: progression_balancing: on: 50 # A system to reduce BK, as in times during which you can't do anything by moving your items into an earlier access sphere to make it likely you have stuff to do off: 0 # Turn this off if you don't mind a longer multiworld, or can glitch/sequence break around missing items. +# Can be uncommented to use it +# startinventory: # Begin the file with the listed items/upgrades + # Please only use items for the correct game, use triggers if need to be have seperated lists. + # Pegasus Boots: on + # Bomb Upgrade (+10): 4 + # Arrow Upgrade (+10): 4 # Factorio options: tech_tree_layout: single: 1 @@ -347,11 +353,6 @@ green_clock_time: # For all timer modes, the amount of time in minutes to gain o # - "Moon Pearl" # - "Small Keys" # - "Big Keys" -# Can be uncommented to use it -# startinventory: # Begin the file with the listed items/upgrades - # Pegasus Boots: on - # Bomb Upgrade (+10): 4 - # Arrow Upgrade (+10): 4 glitch_boots: on: 50 # Start with Pegasus Boots in any glitched logic mode that makes use of them off: 0 diff --git a/worlds/__init__.py b/worlds/__init__.py index 67608fe4..14744e62 100644 --- a/worlds/__init__.py +++ b/worlds/__init__.py @@ -27,7 +27,7 @@ lookup_any_location_name_to_id = {name: id for id, name in lookup_any_location_i network_data_package = {"lookup_any_location_id_to_name": lookup_any_location_id_to_name, "lookup_any_item_id_to_name": lookup_any_item_id_to_name, - "version": 5} + "version": 6} @enum.unique diff --git a/worlds/alttp/EntranceRandomizer.py b/worlds/alttp/EntranceRandomizer.py index 0e8d744a..2d2d2c4b 100644 --- a/worlds/alttp/EntranceRandomizer.py +++ b/worlds/alttp/EntranceRandomizer.py @@ -352,7 +352,6 @@ def parse_arguments(argv, no_defaults=False): Torches means additionally easily accessible Torches that can be lit with Fire Rod are considered doable. None means full traversal through dark rooms without tools is considered doable.''') parser.add_argument('--restrict_dungeon_item_on_boss', default=defval(False), action="store_true") - parser.add_argument('--remote_items', default=defval(False), action='store_true') parser.add_argument('--multi', default=defval(1), type=lambda value: min(max(int(value), 1), 255)) parser.add_argument('--names', default=defval('')) parser.add_argument('--teams', default=defval(1), type=lambda value: max(int(value), 1)) @@ -409,7 +408,7 @@ def parse_arguments(argv, no_defaults=False): "triforce_pieces_required", "shop_shuffle", "shop_shuffle_slots", "required_medallions", "plando_items", "plando_texts", "plando_connections", "er_seeds", - 'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots', 'killable_thieves', + 'progressive', 'dungeon_counters', 'glitch_boots', 'killable_thieves', 'tile_shuffle', 'bush_shuffle', 'shuffle_prizes', 'sprite_pool', 'dark_room_logic', 'restrict_dungeon_item_on_boss', 'reduceflashing', 'game', 'hud_palettes', 'sword_palettes', 'shield_palettes', 'link_palettes', 'triforcehud']: diff --git a/worlds/alttp/Regions.py b/worlds/alttp/Regions.py index e703eba9..89a462ac 100644 --- a/worlds/alttp/Regions.py +++ b/worlds/alttp/Regions.py @@ -676,10 +676,12 @@ location_table: typing.Dict[str, from worlds.alttp.Shops import shop_table_by_location_id, shop_table_by_location lookup_id_to_name = {data[0]: name for name, data in location_table.items() if type(data[0]) == int} -lookup_id_to_name = {**lookup_id_to_name, **{data[1]: name for name, data in key_drop_data.items()}, -1: "cheat console"} +lookup_id_to_name = {**lookup_id_to_name, **{data[1]: name for name, data in key_drop_data.items()}, + -1: "Cheat Console", -2: "Server"} lookup_id_to_name.update(shop_table_by_location_id) lookup_name_to_id = {name: data[0] for name, data in location_table.items() if type(data[0]) == int} -lookup_name_to_id = {**lookup_name_to_id, **{name: data[1] for name, data in key_drop_data.items()}, "cheat console": -1} +lookup_name_to_id = {**lookup_name_to_id, **{name: data[1] for name, data in key_drop_data.items()}, + "Cheat Console": -1, "Server": -2} lookup_name_to_id.update(shop_table_by_location) lookup_vanilla_location_to_entrance = {1572883: 'Kings Grave Inner Rocks', 191256: 'Kings Grave Inner Rocks', diff --git a/worlds/alttp/__init__.py b/worlds/alttp/__init__.py index 633cc50c..c3f7edbb 100644 --- a/worlds/alttp/__init__.py +++ b/worlds/alttp/__init__.py @@ -91,25 +91,6 @@ from BaseClasses import Location, Item # self.dark_room_logic = "lamp" # self.restrict_dungeon_item_on_boss = False # -# @property -# def sewer_light_cone(self): -# return self.mode == "standard" -# -# @property -# def fix_trock_doors(self): -# return self.shuffle != 'vanilla' or self.mode == 'inverted' -# -# @property -# def fix_skullwoods_exit(self): -# return self.shuffle not in {'vanilla', 'simple', 'restricted', 'dungeonssimple'} -# -# @property -# def fix_palaceofdarkness_exit(self): -# return self.shuffle not in {'vanilla', 'simple', 'restricted', 'dungeonssimple'} -# -# @property -# def fix_trock_exit(self): -# return self.shuffle not in {'vanilla', 'simple', 'restricted', 'dungeonssimple'} class ALttPLocation(Location):