diff --git a/Main.py b/Main.py index 456820a4..8bbbd74b 100644 --- a/Main.py +++ b/Main.py @@ -93,6 +93,15 @@ def main(args, seed=None, baked_server_options: dict[str, object] | None = None) del local_early del early + # items can't be both local and non-local, prefer local + multiworld.worlds[player].options.non_local_items.value -= multiworld.worlds[player].options.local_items.value + multiworld.worlds[player].options.non_local_items.value -= set(multiworld.local_early_items[player]) + + # Clear non-applicable local and non-local items. + if multiworld.players == 1: + multiworld.worlds[1].options.non_local_items.value = set() + multiworld.worlds[1].options.local_items.value = set() + logger.info('Creating MultiWorld.') AutoWorld.call_all(multiworld, "create_regions") @@ -100,12 +109,6 @@ def main(args, seed=None, baked_server_options: dict[str, object] | None = None) AutoWorld.call_all(multiworld, "create_items") logger.info('Calculating Access Rules.') - - for player in multiworld.player_ids: - # items can't be both local and non-local, prefer local - multiworld.worlds[player].options.non_local_items.value -= multiworld.worlds[player].options.local_items.value - multiworld.worlds[player].options.non_local_items.value -= set(multiworld.local_early_items[player]) - AutoWorld.call_all(multiworld, "set_rules") for player in multiworld.player_ids: @@ -126,11 +129,9 @@ def main(args, seed=None, baked_server_options: dict[str, object] | None = None) multiworld.worlds[player].options.priority_locations.value -= world_excluded_locations # Set local and non-local item rules. + # This function is called so late because worlds might otherwise overwrite item_rules which are how locality works if multiworld.players > 1: locality_rules(multiworld) - else: - multiworld.worlds[1].options.non_local_items.value = set() - multiworld.worlds[1].options.local_items.value = set() multiworld.plando_item_blocks = parse_planned_blocks(multiworld) diff --git a/docs/world api.md b/docs/world api.md index 677b1636..3bf48219 100644 --- a/docs/world api.md +++ b/docs/world api.md @@ -515,6 +515,7 @@ In addition, the following methods can be implemented and are called in this ord called per player before any items or locations are created. You can set properties on your world here. Already has access to player options and RNG. This is the earliest step where the world should start setting up for the current multiworld, as the multiworld itself is still setting up before this point. + You cannot modify `local_items`, or `non_local_items` after this step. * `create_regions(self)` called to place player's regions and their locations into the MultiWorld's regions list. If it's hard to separate, this can be done during `generate_early` or `create_items` as well. diff --git a/test/general/test_items.py b/test/general/test_items.py index 1b376b28..dbaca1c9 100644 --- a/test/general/test_items.py +++ b/test/general/test_items.py @@ -148,8 +148,8 @@ class TestBase(unittest.TestCase): def test_locality_not_modified(self): """Test that worlds don't modify the locality of items after duplicates are resolved""" - gen_steps = ("generate_early", "create_regions", "create_items") - additional_steps = ("set_rules", "connect_entrances", "generate_basic", "pre_fill") + gen_steps = ("generate_early",) + additional_steps = ("create_regions", "create_items", "set_rules", "connect_entrances", "generate_basic", "pre_fill") worlds_to_test = {game: world for game, world in AutoWorldRegister.world_types.items()} for game_name, world_type in worlds_to_test.items(): with self.subTest("Game", game=game_name):