Merge branch 'main' of https://github.com/ArchipelagoMW/Archipelago into minecraft
This commit is contained in:
commit
92c21de61d
|
@ -910,14 +910,12 @@ async def main():
|
||||||
logging.exception(e)
|
logging.exception(e)
|
||||||
asyncio.create_task(run_game(adjustedromfile if adjusted else romfile))
|
asyncio.create_task(run_game(adjustedromfile if adjusted else romfile))
|
||||||
|
|
||||||
port = None
|
|
||||||
|
|
||||||
ctx = Context(args.snes, args.connect, args.password, args.founditems)
|
ctx = Context(args.snes, args.connect, args.password, args.founditems)
|
||||||
input_task = asyncio.create_task(console_loop(ctx), name="Input")
|
input_task = asyncio.create_task(console_loop(ctx), name="Input")
|
||||||
|
|
||||||
if ctx.server_task is None:
|
if ctx.server_task is None:
|
||||||
ctx.server_task = asyncio.create_task(server_loop(ctx), name="ServerLoop")
|
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")
|
watcher_task = asyncio.create_task(game_watcher(ctx), name="GameWatcher")
|
||||||
|
|
||||||
await ctx.exit_event.wait()
|
await ctx.exit_event.wait()
|
||||||
|
|
18
Main.py
18
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.Shops import create_shops, ShopSlotFill, SHOP_ID_START, total_shop_slots, FillDisabledShopSlots
|
||||||
from worlds.alttp.ItemPool import generate_itempool, difficulties, fill_prizes
|
from worlds.alttp.ItemPool import generate_itempool, difficulties, fill_prizes
|
||||||
from Utils import output_path, parse_player_names, get_options, __version__, version_tuple
|
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.generic.Rules import locality_rules
|
from worlds.generic.Rules import locality_rules
|
||||||
from worlds import Games, lookup_any_item_name_to_id, AutoWorld
|
from worlds import Games, lookup_any_item_name_to_id, AutoWorld
|
||||||
import Patch
|
import Patch
|
||||||
|
@ -194,9 +192,6 @@ def main(args, seed=None):
|
||||||
world.non_local_items[player] -= item_name_groups['Pendants']
|
world.non_local_items[player] -= item_name_groups['Pendants']
|
||||||
world.non_local_items[player] -= item_name_groups['Crystals']
|
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")
|
AutoWorld.call_all(world, "create_regions")
|
||||||
|
|
||||||
for player in world.alttp_player_ids:
|
for player in world.alttp_player_ids:
|
||||||
|
@ -258,9 +253,6 @@ def main(args, seed=None):
|
||||||
for player in world.alttp_player_ids:
|
for player in world.alttp_player_ids:
|
||||||
set_rules(world, player)
|
set_rules(world, player)
|
||||||
|
|
||||||
for player in world.hk_player_ids:
|
|
||||||
gen_hollow(world, player)
|
|
||||||
|
|
||||||
AutoWorld.call_all(world, "generate_basic")
|
AutoWorld.call_all(world, "generate_basic")
|
||||||
|
|
||||||
logger.info("Running Item Plando")
|
logger.info("Running Item Plando")
|
||||||
|
@ -489,10 +481,7 @@ def main(args, seed=None):
|
||||||
minimum_versions = {"server": (0, 1, 1), "clients": client_versions}
|
minimum_versions = {"server": (0, 1, 1), "clients": client_versions}
|
||||||
games = {}
|
games = {}
|
||||||
for slot in world.player_ids:
|
for slot in world.player_ids:
|
||||||
if world.game[slot] == "Factorio":
|
client_versions[slot] = world.worlds[slot].get_required_client_version()
|
||||||
client_versions[slot] = (0, 1, 2)
|
|
||||||
else:
|
|
||||||
client_versions[slot] = (0, 0, 3)
|
|
||||||
games[slot] = world.game[slot]
|
games[slot] = world.game[slot]
|
||||||
connect_names = {base64.b64encode(rom_name).decode(): (team, slot) for
|
connect_names = {base64.b64encode(rom_name).decode(): (team, slot) for
|
||||||
slot, team, rom_name in rom_names}
|
slot, team, rom_name in rom_names}
|
||||||
|
@ -512,10 +501,7 @@ def main(args, seed=None):
|
||||||
connect_names[name] = (i, player)
|
connect_names[name] = (i, player)
|
||||||
if world.hk_player_ids:
|
if world.hk_player_ids:
|
||||||
for slot in world.hk_player_ids:
|
for slot in world.hk_player_ids:
|
||||||
slots_data = slot_data[slot] = {}
|
slot_data[slot] = AutoWorld.call_single(world, "fill_slot_data", slot)
|
||||||
for option_name in world.worlds[slot].options:
|
|
||||||
option = getattr(world, option_name)[slot]
|
|
||||||
slots_data[option_name] = int(option.value)
|
|
||||||
for slot in world.minecraft_player_ids:
|
for slot in world.minecraft_player_ids:
|
||||||
slot_data[slot] = AutoWorld.call_single(world, "fill_slot_data", slot)
|
slot_data[slot] = AutoWorld.call_single(world, "fill_slot_data", slot)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import concurrent.futures
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
|
from shutil import which
|
||||||
|
|
||||||
|
|
||||||
def feedback(text: str):
|
def feedback(text: str):
|
||||||
|
@ -76,8 +77,10 @@ if __name__ == "__main__":
|
||||||
basemysterycommand = "ArchipelagoMystery.exe" # compiled windows
|
basemysterycommand = "ArchipelagoMystery.exe" # compiled windows
|
||||||
elif os.path.exists("ArchipelagoMystery"):
|
elif os.path.exists("ArchipelagoMystery"):
|
||||||
basemysterycommand = "./ArchipelagoMystery" # compiled linux
|
basemysterycommand = "./ArchipelagoMystery" # compiled linux
|
||||||
|
elif which('py'):
|
||||||
|
basemysterycommand = f"py -{py_version} Mystery.py" # source windows
|
||||||
else:
|
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)
|
weights_file_path = os.path.join(player_files_path, weights_file_path)
|
||||||
if os.path.exists(weights_file_path):
|
if os.path.exists(weights_file_path):
|
||||||
|
@ -210,8 +213,10 @@ if __name__ == "__main__":
|
||||||
baseservercommand = ["ArchipelagoServer.exe"] # compiled windows
|
baseservercommand = ["ArchipelagoServer.exe"] # compiled windows
|
||||||
elif os.path.exists("ArchipelagoServer"):
|
elif os.path.exists("ArchipelagoServer"):
|
||||||
baseservercommand = ["./ArchipelagoServer"] # compiled linux
|
baseservercommand = ["./ArchipelagoServer"] # compiled linux
|
||||||
|
elif which('py'):
|
||||||
|
baseservercommand = ["py", f"-{py_version}", "MultiServer.py"] # source windows
|
||||||
else:
|
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.
|
# 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)])
|
subprocess.call(baseservercommand + ["--multidata", os.path.join(output_path, multidataname)])
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
max-width: 40px;
|
max-width: 40px;
|
||||||
max-height: 40px;
|
max-height: 40px;
|
||||||
filter: grayscale(100%);
|
filter: grayscale(100%) contrast(75%) brightness(75%);
|
||||||
}
|
}
|
||||||
|
|
||||||
#inventory-table img.acquired{
|
#inventory-table img.acquired{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from worlds.hk import Options
|
from worlds.hk import HKWorld
|
||||||
from BaseClasses import MultiWorld
|
from BaseClasses import MultiWorld
|
||||||
from worlds.hk.Regions import create_regions
|
from worlds import AutoWorld
|
||||||
from worlds.hk import gen_hollow
|
from worlds.hk.Options import hollow_knight_randomize_options, hollow_knight_skip_options
|
||||||
|
|
||||||
from test.TestBase import TestBase
|
from test.TestBase import TestBase
|
||||||
|
|
||||||
|
@ -10,9 +10,11 @@ class TestVanilla(TestBase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.world = MultiWorld(1)
|
self.world = MultiWorld(1)
|
||||||
self.world.game[1] = "Hollow Knight"
|
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})
|
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})
|
setattr(self.world, hk_option, {1: option.default})
|
||||||
create_regions(self.world, 1)
|
AutoWorld.call_single(self.world, "create_regions", 1)
|
||||||
gen_hollow(self.world, 1)
|
AutoWorld.call_single(self.world, "generate_basic", 1)
|
||||||
|
AutoWorld.call_single(self.world, "set_rules", 1)
|
|
@ -45,3 +45,6 @@ class World(metaclass=AutoWorldRegister):
|
||||||
|
|
||||||
def generate_output(self):
|
def generate_output(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_required_client_version(self) -> tuple:
|
||||||
|
return 0, 0, 3
|
||||||
|
|
|
@ -44,7 +44,7 @@ class Factorio(World):
|
||||||
event = Item("Victory", True, None, player)
|
event = Item("Victory", True, None, player)
|
||||||
self.world.push_item(location, event, False)
|
self.world.push_item(location, event, False)
|
||||||
location.event = location.locked = True
|
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)
|
location = Location(player, f"Automate {ingredient}", None, nauvis)
|
||||||
nauvis.locations.append(location)
|
nauvis.locations.append(location)
|
||||||
event = Item(f"Automated {ingredient}", True, None, player)
|
event = Item(f"Automated {ingredient}", True, None, player)
|
||||||
|
@ -60,7 +60,7 @@ class Factorio(World):
|
||||||
shapes = get_shapes(self)
|
shapes = get_shapes(self)
|
||||||
if world.logic[player] != 'nologic':
|
if world.logic[player] != 'nologic':
|
||||||
from worlds.generic import Rules
|
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 = world.get_location(f"Automate {ingredient}", player)
|
||||||
location.access_rule = lambda state, ingredient=ingredient: \
|
location.access_rule = lambda state, ingredient=ingredient: \
|
||||||
all(state.has(technology.name, player) for technology in required_technologies[ingredient])
|
all(state.has(technology.name, player) for technology in required_technologies[ingredient])
|
||||||
|
@ -80,6 +80,9 @@ class Factorio(World):
|
||||||
|
|
||||||
world.completion_condition[player] = lambda state: state.has('Victory', player)
|
world.completion_condition[player] = lambda state: state.has('Victory', player)
|
||||||
|
|
||||||
|
def get_required_client_version(self) -> tuple:
|
||||||
|
return max((0, 1, 2), super(Factorio, self).get_required_client_version())
|
||||||
|
|
||||||
options = factorio_options
|
options = factorio_options
|
||||||
|
|
||||||
def set_custom_technologies(world: MultiWorld, player: int):
|
def set_custom_technologies(world: MultiWorld, player: int):
|
||||||
|
|
|
@ -6,12 +6,83 @@ from .Locations import lookup_name_to_id
|
||||||
from .Items import item_table
|
from .Items import item_table
|
||||||
from .Regions import create_regions
|
from .Regions import create_regions
|
||||||
from .Rules import set_rules
|
from .Rules import set_rules
|
||||||
|
from .Options import hollow_knight_options
|
||||||
|
|
||||||
from BaseClasses import Region, Entrance, Location, MultiWorld, Item
|
from BaseClasses import Region, Entrance, Location, MultiWorld, Item
|
||||||
from ..AutoWorld import World
|
from ..AutoWorld import World
|
||||||
|
|
||||||
class HKWorld(World):
|
class HKWorld(World):
|
||||||
game: str = "Hollow Knight"
|
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):
|
def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None):
|
||||||
ret = Region(name, None, name, player)
|
ret = Region(name, None, name, player)
|
||||||
|
@ -43,16 +114,6 @@ class HKItem(Item):
|
||||||
self.type = type
|
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"}
|
not_shufflable_types = {"Essence_Boss"}
|
||||||
|
|
||||||
option_to_type_lookup = {
|
option_to_type_lookup = {
|
||||||
|
@ -75,49 +136,6 @@ option_to_type_lookup = {
|
||||||
"Vessel": "RandomizeVesselFragments",
|
"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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue