From a3a68de34127ca0897265e331f5c899ccbf3c506 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sat, 26 Jun 2021 06:05:38 +0200 Subject: [PATCH 1/8] Factorio: only create events for required technologies --- worlds/factorio/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worlds/factorio/__init__.py b/worlds/factorio/__init__.py index ec6bf1da..8ca0a51c 100644 --- a/worlds/factorio/__init__.py +++ b/worlds/factorio/__init__.py @@ -44,7 +44,7 @@ class Factorio(World): event = Item("Victory", True, None, player) self.world.push_item(location, event, False) location.event = location.locked = True - for ingredient in all_ingredient_names: + for ingredient in self.world.max_science_pack[self.player].get_allowed_packs(): location = Location(player, f"Automate {ingredient}", None, nauvis) nauvis.locations.append(location) event = Item(f"Automated {ingredient}", True, None, player) @@ -60,7 +60,7 @@ class Factorio(World): shapes = get_shapes(self) if world.logic[player] != 'nologic': from worlds.generic import Rules - for ingredient in all_ingredient_names: + for ingredient in self.world.max_science_pack[self.player].get_allowed_packs(): location = world.get_location(f"Automate {ingredient}", player) location.access_rule = lambda state, ingredient=ingredient: \ all(state.has(technology.name, player) for technology in required_technologies[ingredient]) From 739b563bc2b0923df13eb63ad29dce0192c0b0b1 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sun, 27 Jun 2021 00:23:42 +0200 Subject: [PATCH 2/8] Move required Client Version to AutoWorld --- Main.py | 5 +---- worlds/AutoWorld.py | 3 +++ worlds/factorio/__init__.py | 3 +++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Main.py b/Main.py index c237cf6a..acdabdc8 100644 --- a/Main.py +++ b/Main.py @@ -497,10 +497,7 @@ def main(args, seed=None): minimum_versions = {"server": (0, 1, 1), "clients": client_versions} games = {} for slot in world.player_ids: - if world.game[slot] == "Factorio": - client_versions[slot] = (0, 1, 2) - else: - client_versions[slot] = (0, 0, 3) + client_versions[slot] = world.worlds[slot].get_required_client_version() games[slot] = world.game[slot] connect_names = {base64.b64encode(rom_name).decode(): (team, slot) for slot, team, rom_name in rom_names} diff --git a/worlds/AutoWorld.py b/worlds/AutoWorld.py index 8f94d257..9b649bfa 100644 --- a/worlds/AutoWorld.py +++ b/worlds/AutoWorld.py @@ -45,3 +45,6 @@ class World(metaclass=AutoWorldRegister): def generate_output(self): pass + + def get_required_client_version(self) -> tuple: + return 0, 0, 3 diff --git a/worlds/factorio/__init__.py b/worlds/factorio/__init__.py index 8ca0a51c..9b71bb3b 100644 --- a/worlds/factorio/__init__.py +++ b/worlds/factorio/__init__.py @@ -80,6 +80,9 @@ class Factorio(World): world.completion_condition[player] = lambda state: state.has('Victory', player) + def get_required_client_version(self) -> tuple: + return max((0, 1, 4), super(Factorio, self).get_required_client_version()) + options = factorio_options def set_custom_technologies(world: MultiWorld, player: int): From aa28b3887f02b48b8d2304bb5db0d1cf413df8f7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 26 Jun 2021 22:32:29 -0400 Subject: [PATCH 3/8] Apply Dewin's suggested filter to the Z3 Player Tracker --- WebHostLib/static/styles/playerTracker.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebHostLib/static/styles/playerTracker.css b/WebHostLib/static/styles/playerTracker.css index e0ffcc23..d5f47efe 100644 --- a/WebHostLib/static/styles/playerTracker.css +++ b/WebHostLib/static/styles/playerTracker.css @@ -24,7 +24,7 @@ height: 100%; max-width: 40px; max-height: 40px; - filter: grayscale(100%); + filter: grayscale(100%) contrast(75%) brightness(75%); } #inventory-table img.acquired{ From 8b5d7028f7df60b93ceb9a041a17b9ab308434a5 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sun, 27 Jun 2021 05:18:37 +0200 Subject: [PATCH 4/8] decrement Factorio Client version (for now, as nobody has that client yet) --- worlds/factorio/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worlds/factorio/__init__.py b/worlds/factorio/__init__.py index 9b71bb3b..9e6cce67 100644 --- a/worlds/factorio/__init__.py +++ b/worlds/factorio/__init__.py @@ -81,7 +81,7 @@ class Factorio(World): world.completion_condition[player] = lambda state: state.has('Victory', player) def get_required_client_version(self) -> tuple: - return max((0, 1, 4), super(Factorio, self).get_required_client_version()) + return max((0, 1, 2), super(Factorio, self).get_required_client_version()) options = factorio_options From 50ed657b0e690c0117e110dffc4cfef5f3f3f0b3 Mon Sep 17 00:00:00 2001 From: black-sliver <59490463+black-sliver@users.noreply.github.com> Date: Sun, 27 Jun 2021 18:52:09 +0200 Subject: [PATCH 5/8] Allow running MultiMystery.py from source on linux --- MultiMystery.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/MultiMystery.py b/MultiMystery.py index aefc260a..84b78e0c 100644 --- a/MultiMystery.py +++ b/MultiMystery.py @@ -6,6 +6,7 @@ import concurrent.futures import argparse import logging import random +from shutil import which def feedback(text: str): @@ -76,8 +77,10 @@ if __name__ == "__main__": basemysterycommand = "ArchipelagoMystery.exe" # compiled windows elif os.path.exists("ArchipelagoMystery"): basemysterycommand = "./ArchipelagoMystery" # compiled linux + elif which('py'): + basemysterycommand = f"py -{py_version} Mystery.py" # source windows else: - basemysterycommand = f"py -{py_version} Mystery.py" # source + basemysterycommand = f"python3 Mystery.py" # source others weights_file_path = os.path.join(player_files_path, weights_file_path) if os.path.exists(weights_file_path): @@ -210,8 +213,10 @@ if __name__ == "__main__": baseservercommand = ["ArchipelagoServer.exe"] # compiled windows elif os.path.exists("ArchipelagoServer"): baseservercommand = ["./ArchipelagoServer"] # compiled linux + elif which('py'): + baseservercommand = ["py", f"-{py_version}", "MultiServer.py"] # source windows else: - baseservercommand = ["py", f"-{py_version}", "MultiServer.py"] # source + baseservercommand = ["python3", "MultiServer.py"] # source others # don't have a mac to test that. If you try to run compiled on mac, good luck. subprocess.call(baseservercommand + ["--multidata", os.path.join(output_path, multidataname)]) except: From c7417623e60b3672b464dd4a2cbfe1bea6995051 Mon Sep 17 00:00:00 2001 From: espeon65536 Date: Sat, 26 Jun 2021 11:18:12 -0500 Subject: [PATCH 6/8] Converted Hollow Knight to AutoWorld system --- Main.py | 13 +---- worlds/hk/__init__.py | 124 ++++++++++++++++++++++++------------------ 2 files changed, 72 insertions(+), 65 deletions(-) diff --git a/Main.py b/Main.py index acdabdc8..20a7b055 100644 --- a/Main.py +++ b/Main.py @@ -21,8 +21,6 @@ from Fill import distribute_items_restrictive, flood_items, balance_multiworld_p from worlds.alttp.Shops import create_shops, ShopSlotFill, SHOP_ID_START, total_shop_slots, FillDisabledShopSlots from worlds.alttp.ItemPool import generate_itempool, difficulties, fill_prizes from Utils import output_path, parse_player_names, get_options, __version__, version_tuple -from worlds.hk import gen_hollow -from worlds.hk import create_regions as hk_create_regions 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 @@ -196,9 +194,6 @@ def main(args, seed=None): world.non_local_items[player] -= item_name_groups['Pendants'] world.non_local_items[player] -= item_name_groups['Crystals'] - for player in world.hk_player_ids: - hk_create_regions(world, player) - AutoWorld.call_all(world, "create_regions") for player in world.minecraft_player_ids: @@ -263,9 +258,6 @@ def main(args, seed=None): for player in world.alttp_player_ids: set_rules(world, player) - for player in world.hk_player_ids: - gen_hollow(world, player) - AutoWorld.call_all(world, "generate_basic") for player in world.minecraft_player_ids: @@ -517,10 +509,7 @@ def main(args, seed=None): connect_names[name] = (i, player) if world.hk_player_ids: for slot in world.hk_player_ids: - slots_data = slot_data[slot] = {} - for option_name in world.worlds[slot].options: - option = getattr(world, option_name)[slot] - slots_data[option_name] = int(option.value) + slot_data[slot] = AutoWorld.call_single(world, "fill_slot_data", slot) for slot in world.minecraft_player_ids: slot_data[slot] = fill_minecraft_slot_data(world, slot) diff --git a/worlds/hk/__init__.py b/worlds/hk/__init__.py index 12bc6448..db764a08 100644 --- a/worlds/hk/__init__.py +++ b/worlds/hk/__init__.py @@ -6,12 +6,83 @@ from .Locations import lookup_name_to_id from .Items import item_table from .Regions import create_regions from .Rules import set_rules +from .Options import hollow_knight_options from BaseClasses import Region, Entrance, Location, MultiWorld, Item from ..AutoWorld import World class HKWorld(World): game: str = "Hollow Knight" + options = hollow_knight_options + + def generate_basic(self): + # Link regions + self.world.get_entrance('Hollow Nest S&Q', self.player).connect(self.world.get_region('Hollow Nest', self.player)) + + # Generate item pool + pool = [] + for item_name, item_data in item_table.items(): + + item = HKItem(item_name, item_data.advancement, item_data.id, item_data.type, player=self.player) + + if item_data.type == "Event": + event_location = self.world.get_location(item_name, self.player) + self.world.push_item(event_location, item, collect=False) + event_location.event = True + event_location.locked = True + if item.name == "King's_Pass": + self.world.push_precollected(item) + elif item_data.type == "Cursed": + if self.world.CURSED[self.player]: + pool.append(item) + else: + # fill Focus Location with Focus and add it to start inventory as well. + event_location = self.world.get_location(item_name, self.player) + self.world.push_item(event_location, item) + event_location.event = True + event_location.locked = True + + elif item_data.type == "Fake": + pass + elif item_data.type in not_shufflable_types: + location = self.world.get_location(item_name, self.player) + self.world.push_item(location, item, collect=False) + location.event = item.advancement + location.locked = True + else: + target = option_to_type_lookup[item.type] + shuffle_it = getattr(self.world, target) + if shuffle_it[self.player]: + pool.append(item) + else: + location = self.world.get_location(item_name, self.player) + self.world.push_item(location, item, collect=False) + location.event = item.advancement + location.locked = True + logger.debug(f"Placed {item_name} to vanilla for player {self.player}") + + self.world.itempool += pool + + + def set_rules(self): + set_rules(self.world, self.player) + + + def create_regions(self): + create_regions(self.world, self.player) + + + def generate_output(self): + pass # Hollow Knight needs no output files + + + def fill_slot_data(self): + slot_data = {} + for option_name in self.options: + option = getattr(self.world, option_name)[self.player] + slot_data[option_name] = int(option.value) + return slot_data + def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None): ret = Region(name, None, name, player) @@ -43,16 +114,6 @@ class HKItem(Item): self.type = type -def gen_hollow(world: MultiWorld, player: int): - link_regions(world, player) - gen_items(world, player) - set_rules(world, player) - - -def link_regions(world: MultiWorld, player: int): - world.get_entrance('Hollow Nest S&Q', player).connect(world.get_region('Hollow Nest', player)) - - not_shufflable_types = {"Essence_Boss"} option_to_type_lookup = { @@ -75,49 +136,6 @@ option_to_type_lookup = { "Vessel": "RandomizeVesselFragments", } -def gen_items(world: MultiWorld, player: int): - pool = [] - for item_name, item_data in item_table.items(): - - item = HKItem(item_name, item_data.advancement, item_data.id, item_data.type, player=player) - - if item_data.type == "Event": - event_location = world.get_location(item_name, player) - world.push_item(event_location, item, collect=False) - event_location.event = True - event_location.locked = True - if item.name == "King's_Pass": - world.push_precollected(item) - elif item_data.type == "Cursed": - if world.CURSED[player]: - pool.append(item) - else: - # fill Focus Location with Focus and add it to start inventory as well. - event_location = world.get_location(item_name, player) - world.push_item(event_location, item) - event_location.event = True - event_location.locked = True - - elif item_data.type == "Fake": - pass - elif item_data.type in not_shufflable_types: - location = world.get_location(item_name, player) - world.push_item(location, item, collect=False) - location.event = item.advancement - location.locked = True - else: - target = option_to_type_lookup[item.type] - shuffle_it = getattr(world, target) - if shuffle_it[player]: - pool.append(item) - else: - location = world.get_location(item_name, player) - world.push_item(location, item, collect=False) - location.event = item.advancement - location.locked = True - logger.debug(f"Placed {item_name} to vanilla for player {player}") - - world.itempool += pool From 43e17f82b07f5c8917857f3249246a4c36fb812c Mon Sep 17 00:00:00 2001 From: espeon65536 Date: Sat, 26 Jun 2021 12:52:50 -0500 Subject: [PATCH 7/8] Updated HK test to use autoworld --- test/hollow_knight/__init__.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/test/hollow_knight/__init__.py b/test/hollow_knight/__init__.py index ec29f896..60e98cbc 100644 --- a/test/hollow_knight/__init__.py +++ b/test/hollow_knight/__init__.py @@ -1,7 +1,7 @@ -from worlds.hk import Options +from worlds.hk import HKWorld from BaseClasses import MultiWorld -from worlds.hk.Regions import create_regions -from worlds.hk import gen_hollow +from worlds import AutoWorld +from worlds.hk.Options import hollow_knight_randomize_options, hollow_knight_skip_options from test.TestBase import TestBase @@ -10,9 +10,11 @@ class TestVanilla(TestBase): def setUp(self): self.world = MultiWorld(1) self.world.game[1] = "Hollow Knight" - for hk_option in Options.hollow_knight_randomize_options: + self.world.worlds[1] = HKWorld(self.world, 1) + for hk_option in hollow_knight_randomize_options: setattr(self.world, hk_option, {1: True}) - for hk_option, option in Options.hollow_knight_skip_options.items(): + for hk_option, option in hollow_knight_skip_options.items(): setattr(self.world, hk_option, {1: option.default}) - create_regions(self.world, 1) - gen_hollow(self.world, 1) \ No newline at end of file + AutoWorld.call_single(self.world, "create_regions", 1) + AutoWorld.call_single(self.world, "generate_basic", 1) + AutoWorld.call_single(self.world, "set_rules", 1) \ No newline at end of file From 95e0f551e87cf54b318689334bfb46a50e189ed1 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Mon, 28 Jun 2021 01:27:52 +0200 Subject: [PATCH 8/8] LttP Client: restore auto-snes --- LttPClient.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/LttPClient.py b/LttPClient.py index 13674cbd..4cde4b68 100644 --- a/LttPClient.py +++ b/LttPClient.py @@ -910,14 +910,12 @@ async def main(): logging.exception(e) asyncio.create_task(run_game(adjustedromfile if adjusted else romfile)) - port = None - ctx = Context(args.snes, args.connect, args.password, args.founditems) input_task = asyncio.create_task(console_loop(ctx), name="Input") if ctx.server_task is None: ctx.server_task = asyncio.create_task(server_loop(ctx), name="ServerLoop") - + asyncio.create_task(snes_connect(ctx, ctx.snes_address)) watcher_task = asyncio.create_task(game_watcher(ctx), name="GameWatcher") await ctx.exit_event.wait()