diff --git a/.gitignore b/.gitignore
index 5686f43de38..791f7b1bb7f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -150,7 +150,7 @@ venv/
ENV/
env.bak/
venv.bak/
-.code-workspace
+*.code-workspace
shell.nix
# Spyder project settings
diff --git a/BaseClasses.py b/BaseClasses.py
index 88857f80321..1c7dad7f3b9 100644
--- a/BaseClasses.py
+++ b/BaseClasses.py
@@ -680,13 +680,13 @@ def can_reach_entrance(self, spot: str, player: int) -> bool:
def can_reach_region(self, spot: str, player: int) -> bool:
return self.multiworld.get_region(spot, player).can_reach(self)
- def sweep_for_events(self, key_only: bool = False, locations: Optional[Iterable[Location]] = None) -> None:
+ def sweep_for_events(self, locations: Optional[Iterable[Location]] = None) -> None:
if locations is None:
locations = self.multiworld.get_filled_locations()
reachable_events = True
# since the loop has a good chance to run more than once, only filter the events once
- locations = {location for location in locations if location.advancement and location not in self.events and
- not key_only or getattr(location.item, "locked_dungeon_item", False)}
+ locations = {location for location in locations if location.advancement and location not in self.events}
+
while reachable_events:
reachable_events = {location for location in locations if location.can_reach(self)}
locations -= reachable_events
@@ -1291,8 +1291,6 @@ def create_playthrough(self, create_paths: bool = True) -> None:
state = CollectionState(multiworld)
collection_spheres = []
while required_locations:
- state.sweep_for_events(key_only=True)
-
sphere = set(filter(state.can_reach, required_locations))
for location in sphere:
diff --git a/CommonClient.py b/CommonClient.py
index f8d1fcb7a22..09937e4b9ab 100644
--- a/CommonClient.py
+++ b/CommonClient.py
@@ -61,6 +61,7 @@ def _cmd_connect(self, address: str = "") -> bool:
if address:
self.ctx.server_address = None
self.ctx.username = None
+ self.ctx.password = None
elif not self.ctx.server_address:
self.output("Please specify an address.")
return False
@@ -514,6 +515,7 @@ def update_permissions(self, permissions: typing.Dict[str, int]):
async def shutdown(self):
self.server_address = ""
self.username = None
+ self.password = None
self.cancel_autoreconnect()
if self.server and not self.server.socket.closed:
await self.server.socket.close()
diff --git a/Fill.py b/Fill.py
index 4967ff07360..5185bbb60ee 100644
--- a/Fill.py
+++ b/Fill.py
@@ -646,7 +646,6 @@ def balance_multiworld_progression(multiworld: MultiWorld) -> None:
def get_sphere_locations(sphere_state: CollectionState,
locations: typing.Set[Location]) -> typing.Set[Location]:
- sphere_state.sweep_for_events(key_only=True, locations=locations)
return {loc for loc in locations if sphere_state.can_reach(loc)}
def item_percentage(player: int, num: int) -> float:
diff --git a/Main.py b/Main.py
index de6b467f93d..56b3a6545db 100644
--- a/Main.py
+++ b/Main.py
@@ -124,14 +124,19 @@ def main(args, seed=None, baked_server_options: Optional[Dict[str, object]] = No
for player in multiworld.player_ids:
exclusion_rules(multiworld, player, multiworld.worlds[player].options.exclude_locations.value)
multiworld.worlds[player].options.priority_locations.value -= multiworld.worlds[player].options.exclude_locations.value
+ world_excluded_locations = set()
for location_name in multiworld.worlds[player].options.priority_locations.value:
try:
location = multiworld.get_location(location_name, player)
- except KeyError as e: # failed to find the given location. Check if it's a legitimate location
- if location_name not in multiworld.worlds[player].location_name_to_id:
- raise Exception(f"Unable to prioritize location {location_name} in player {player}'s world.") from e
- else:
+ except KeyError:
+ continue
+
+ if location.progress_type != LocationProgressType.EXCLUDED:
location.progress_type = LocationProgressType.PRIORITY
+ else:
+ logger.warning(f"Unable to prioritize location \"{location_name}\" in player {player}'s world because the world excluded it.")
+ world_excluded_locations.add(location_name)
+ multiworld.worlds[player].options.priority_locations.value -= world_excluded_locations
# Set local and non-local item rules.
if multiworld.players > 1:
diff --git a/WebHostLib/options.py b/WebHostLib/options.py
index 33339daa198..15b7bd61cee 100644
--- a/WebHostLib/options.py
+++ b/WebHostLib/options.py
@@ -231,6 +231,13 @@ def generate_yaml(game: str):
del options[key]
+ # Detect keys which end with -range, indicating a NamedRange with a possible custom value
+ elif key_parts[-1].endswith("-range"):
+ if options[key_parts[-1][:-6]] == "custom":
+ options[key_parts[-1][:-6]] = val
+
+ del options[key]
+
# Detect random-* keys and set their options accordingly
for key, val in options.copy().items():
if key.startswith("random-"):
diff --git a/WebHostLib/templates/playerOptions/macros.html b/WebHostLib/templates/playerOptions/macros.html
index 415739b861a..30a4fc78dff 100644
--- a/WebHostLib/templates/playerOptions/macros.html
+++ b/WebHostLib/templates/playerOptions/macros.html
@@ -54,7 +54,7 @@
{% macro NamedRange(option_name, option) %}
{{ OptionTitle(option_name, option) }}
-