2021-07-12 15:33:20 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from __future__ import annotations
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-05 15:49:19 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import logging
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-30 01:11:01 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import sys
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-18 00:27:37 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import pathlib
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-28 14:54:10 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from typing import Dict, FrozenSet, Set, Tuple, List, Optional, TextIO, Any, Callable, Type, Union, TYPE_CHECKING
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-12 13:54:47 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-28 14:54:10 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from Options import AssembleOptions
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from BaseClasses import CollectionState
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								if TYPE_CHECKING:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    from BaseClasses import MultiWorld, Item, Location, Tutorial
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 18:02:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class AutoWorldRegister(type):
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-28 14:54:10 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    world_types: Dict[str, Type[World]] = {}
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-03 22:14:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __new__(mcs, name: str, bases: Tuple[type, ...], dct: Dict[str, Any]) -> AutoWorldRegister:
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-03 19:08:50 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if "web" in dct:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            assert isinstance(dct["web"], WebWorld), "WebWorld has to be instantiated."
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-12 18:47:58 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # filter out any events
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        dct["item_name_to_id"] = {name: id for name, id in dct["item_name_to_id"].items() if id}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        dct["location_name_to_id"] = {name: id for name, id in dct["location_name_to_id"].items() if id}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # build reverse lookups
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-12 18:05:46 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        dct["item_id_to_name"] = {code: name for name, code in dct["item_name_to_id"].items()}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        dct["location_id_to_name"] = {code: name for name, code in dct["location_name_to_id"].items()}
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-29 20:27:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # build rest
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        dct["item_names"] = frozenset(dct["item_name_to_id"])
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-23 23:33:30 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        dct["item_name_groups"] = {group_name: frozenset(group_set) for group_name, group_set
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                   in dct.get("item_name_groups", {}).items()}
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-05 16:55:11 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        dct["item_name_groups"]["Everything"] = dct["item_names"]
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-29 20:27:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        dct["location_names"] = frozenset(dct["location_name_to_id"])
							 | 
						
					
						
							
								
									
										
										
										
											2022-01-16 02:20:37 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        dct["all_item_and_group_names"] = frozenset(dct["item_names"] | set(dct.get("item_name_groups", {})))
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-29 20:27:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-08 11:16:36 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # move away from get_required_client_version function
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if "game" in dct:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            assert "get_required_client_version" not in dct, f"{name}: required_client_version is an attribute now"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # set minimum required_client_version from bases
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if "required_client_version" in dct and bases:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            for base in bases:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if "required_client_version" in base.__dict__:
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    dct["required_client_version"] = max(dct["required_client_version"],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                                         base.__dict__["required_client_version"])
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-08 11:16:36 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-12 18:47:58 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # construct class
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-03 22:14:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        new_class = super().__new__(mcs, name, bases, dct)
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if "game" in dct:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if dct["game"] in AutoWorldRegister.world_types:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                raise RuntimeError(f"""Game {dct["game"]} already registered.""")
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            AutoWorldRegister.world_types[dct["game"]] = new_class
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-30 01:11:01 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        new_class.__file__ = sys.modules[new_class.__module__].__file__
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-18 00:27:37 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if ".apworld" in new_class.__file__:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            new_class.zip_path = pathlib.Path(new_class.__file__).parents[1]
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return new_class
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-21 18:08:15 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-15 13:31:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								class AutoLogicRegister(type):
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-18 00:27:37 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __new__(mcs, name: str, bases: Tuple[type, ...], dct: Dict[str, Any]) -> AutoLogicRegister:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        new_class = super().__new__(mcs, name, bases, dct)
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        function: Callable[..., Any]
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-16 12:23:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        for item_name, function in dct.items():
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-17 07:07:34 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if item_name == "copy_mixin":
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                CollectionState.additional_copy_functions.append(function)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            elif item_name == "init_mixin":
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                CollectionState.additional_init_functions.append(function)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            elif not item_name.startswith("__"):
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-16 12:23:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                if hasattr(CollectionState, item_name):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    raise Exception(f"Name conflict on Logic Mixin {name} trying to overwrite {item_name}")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                setattr(CollectionState, item_name, function)
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-15 13:31:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return new_class
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-21 18:08:15 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								def call_single(world: "MultiWorld", method_name: str, player: int, *args: Any) -> Any:
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    method = getattr(world.worlds[player], method_name)
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-21 18:08:15 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    return method(*args)
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								def call_all(world: "MultiWorld", method_name: str, *args: Any) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    world_types: Set[AutoWorldRegister] = set()
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    for player in world.player_ids:
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-20 10:42:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        prev_item_count = len(world.itempool)
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 06:50:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        world_types.add(world.worlds[player].__class__)
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-21 18:08:15 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        call_single(world, method_name, player, *args)
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-20 10:42:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if __debug__:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            new_items = world.itempool[prev_item_count:]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            for i, item in enumerate(new_items):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                for other in new_items[i+1:]:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    assert item is not other, (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        f"Duplicate item reference of \"{item.name}\" in \"{world.worlds[player].game}\" "
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        f"of player \"{world.player_name[player]}\". Please make a copy instead.")
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-06 11:32:49 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-28 12:56:50 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # TODO: investigate: Iterating through a set is not a deterministic order.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # If any random is used, this could make unreproducible seed.
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 06:50:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    for world_type in world_types:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        stage_callable = getattr(world_type, f"stage_{method_name}", None)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if stage_callable:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 09:15:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            stage_callable(world, *args)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								def call_stage(world: "MultiWorld", method_name: str, *args: Any) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 09:15:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    world_types = {world.worlds[player].__class__ for player in world.player_ids}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    for world_type in world_types:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        stage_callable = getattr(world_type, f"stage_{method_name}", None)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if stage_callable:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            stage_callable(world, *args)
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-20 21:54:00 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								class WebWorld:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """Webhost integration"""
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-22 16:50:16 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-20 21:54:00 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    settings_page: Union[bool, str] = True
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-22 16:50:16 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    """display a settings page. Can be a link to a specific page or external tool."""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    game_info_languages: List[str] = ['en']
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-22 16:50:16 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    """docs folder will be scanned for game info pages using this list in the format '{language}_{game_name}.md'"""
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    tutorials: List["Tutorial"]
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-22 16:50:16 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    """docs folder will also be scanned for tutorial guides. Each Tutorial class is to be used for one guide."""
							 | 
						
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
											 
										 
										
											
												Website Style Upgrade (#353)
* [WebHost] Update WebHost to include modular themes system, remove unused and outdated assets
* Landing Page Updates
* Markdown updates, colors coming later
* Remove testing theme from FF1
* Color updates for markdown styles
* Updates to generated pages, so many updates
* [WebHost] Update WebHost to include modular themes system, remove unused and outdated assets
* Landing Page Updates
* Markdown updates, colors coming later
* Remove testing theme from FF1
* Color updates for markdown styles
* Updates to generated pages, so many updates
* Seed download page improvements
* Add styles to weighted-settings page
* Minor adjustments to styles
* Revert base theme to grass
* Add more items to ArchipIDLE
* [WebHost] Update WebHost to include modular themes system, remove unused and outdated assets
* Landing Page Updates
* Markdown updates, colors coming later
* Remove testing theme from FF1
* Color updates for markdown styles
* Updates to generated pages, so many updates
* Seed download page improvements
* [WebHost] Update WebHost to include modular themes system, remove unused and outdated assets
* Landing Page Updates
* Markdown updates, colors coming later
* Remove testing theme from FF1
* Color updates for markdown styles
* Updates to generated pages, so many updates
* Add styles to weighted-settings page
* Minor adjustments to styles
* Revert base theme to grass
* Add more items to ArchipIDLE
* Improve Archipidle item name
* [WebHost] Update background images, waiting on jungle.png, added partyTime theme
* [WebHost] Fix tab ordering on landing page, remove islands on screen scale, fix tutorial page width scaling
* [WebHost] Final touches to WebHost
* Improve get_world_theme function, add partyTime theme to ArchipIDLE WebWorld
* Remove sending_visible from AutoWorld
* AP Ocarina of Time Client (#352)
* Core: update jinja (#351)
* some typing and cleaning, mostly in Fill.py (#349)
* some typing and cleaning, mostly in Fill.py
* address missing Option types
* resolve a few TODOs discussed in pull request
* SM: Optimize a bit (#350)
* SM: Optimize a bit
* SM: init bosses only once
* New World Order (#355)
* Core: update jinja
* SM: Optimize a bit
* AutoWorld: import worlds in alphabetical order, to be predictable rather than arbitrary
Co-authored-by: Hussein Farran <hmfarran@gmail.com>
* Remove references to Z5Client in English OoT setup guide
* Prevent markdown code blocks from overflowing their container
Co-authored-by: espeon65536 <81029175+espeon65536@users.noreply.github.com>
Co-authored-by: Fabian Dill <Berserker66@users.noreply.github.com>
Co-authored-by: Doug Hoskisson <beauxq@users.noreply.github.com>
Co-authored-by: Hussein Farran <hmfarran@gmail.com>
											
										 
										
											2022-03-28 20:12:17 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    theme = "grass"
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-22 16:50:16 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    """Choose a theme for you /game/* pages.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Available: dirt, grass, grassFlowers, ice, jungle, ocean, partyTime, stone"""
							 | 
						
					
						
							
								
									
										
											 
										 
										
											
												Website Style Upgrade (#353)
* [WebHost] Update WebHost to include modular themes system, remove unused and outdated assets
* Landing Page Updates
* Markdown updates, colors coming later
* Remove testing theme from FF1
* Color updates for markdown styles
* Updates to generated pages, so many updates
* [WebHost] Update WebHost to include modular themes system, remove unused and outdated assets
* Landing Page Updates
* Markdown updates, colors coming later
* Remove testing theme from FF1
* Color updates for markdown styles
* Updates to generated pages, so many updates
* Seed download page improvements
* Add styles to weighted-settings page
* Minor adjustments to styles
* Revert base theme to grass
* Add more items to ArchipIDLE
* [WebHost] Update WebHost to include modular themes system, remove unused and outdated assets
* Landing Page Updates
* Markdown updates, colors coming later
* Remove testing theme from FF1
* Color updates for markdown styles
* Updates to generated pages, so many updates
* Seed download page improvements
* [WebHost] Update WebHost to include modular themes system, remove unused and outdated assets
* Landing Page Updates
* Markdown updates, colors coming later
* Remove testing theme from FF1
* Color updates for markdown styles
* Updates to generated pages, so many updates
* Add styles to weighted-settings page
* Minor adjustments to styles
* Revert base theme to grass
* Add more items to ArchipIDLE
* Improve Archipidle item name
* [WebHost] Update background images, waiting on jungle.png, added partyTime theme
* [WebHost] Fix tab ordering on landing page, remove islands on screen scale, fix tutorial page width scaling
* [WebHost] Final touches to WebHost
* Improve get_world_theme function, add partyTime theme to ArchipIDLE WebWorld
* Remove sending_visible from AutoWorld
* AP Ocarina of Time Client (#352)
* Core: update jinja (#351)
* some typing and cleaning, mostly in Fill.py (#349)
* some typing and cleaning, mostly in Fill.py
* address missing Option types
* resolve a few TODOs discussed in pull request
* SM: Optimize a bit (#350)
* SM: Optimize a bit
* SM: init bosses only once
* New World Order (#355)
* Core: update jinja
* SM: Optimize a bit
* AutoWorld: import worlds in alphabetical order, to be predictable rather than arbitrary
Co-authored-by: Hussein Farran <hmfarran@gmail.com>
* Remove references to Z5Client in English OoT setup guide
* Prevent markdown code blocks from overflowing their container
Co-authored-by: espeon65536 <81029175+espeon65536@users.noreply.github.com>
Co-authored-by: Fabian Dill <Berserker66@users.noreply.github.com>
Co-authored-by: Doug Hoskisson <beauxq@users.noreply.github.com>
Co-authored-by: Hussein Farran <hmfarran@gmail.com>
											
										 
										
											2022-03-28 20:12:17 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-12 14:37:05 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    bug_report_page: Optional[str]
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-22 16:50:16 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    """display a link to a bug report page, most likely a link to a GitHub issue page."""
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-12 14:37:05 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-20 21:54:00 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class World(metaclass=AutoWorldRegister):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    """A World object encompasses a game's Items, Locations, Rules and additional data or functionality required.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    A Game should have its own subclass of World in which it defines the required data structures."""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-28 14:54:10 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    option_definitions: Dict[str, AssembleOptions] = {}  # link your Options mapping
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 06:50:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    game: str  # name the game
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-08 11:07:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    topology_present: bool = False  # indicate if world type has any meaningful layout/pathing
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # gets automatically populated with all item and item group names
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    all_item_and_group_names: FrozenSet[str] = frozenset()
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-12 15:33:20 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-12 18:05:46 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # map names to their IDs
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    item_name_to_id: Dict[str, int] = {}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    location_name_to_id: Dict[str, int] = {}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-29 20:27:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # maps item group names to sets of items. Example: "Weapons" -> {"Sword", "Bow"}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    item_name_groups: Dict[str, Set[str]] = {}
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-12 18:05:46 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-22 04:22:34 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # increment this every time something in your world's names/id mappings changes.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # While this is set to 0 in *any* AutoWorld, the entire DataPackage is considered in testing mode and will be
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # retrieved by clients on every connection.
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-30 19:51:07 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    data_version: int = 1
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-12 18:05:46 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-08 11:16:36 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # override this if changes to a world break forward-compatibility of the client
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # The base version of (0, 1, 6) is provided for backwards compatibility and does *not* need to be updated in the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # future. Protocol level compatibility check moved to MultiServer.min_client_version.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    required_client_version: Tuple[int, int, int] = (0, 1, 6)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # update this if the resulting multidata breaks forward-compatibility of the server
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    required_server_version: Tuple[int, int, int] = (0, 2, 4)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    hint_blacklist: FrozenSet[str] = frozenset()  # any names that should not be hintable
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 18:02:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-05 15:49:19 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # NOTE: remote_items and remote_start_inventory are now available in the network protocol for the client to set.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # These values will be removed.
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-13 19:14:57 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # if a world is set to remote_items, then it just needs to send location checks to the server and the server
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # sends back the items
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # if a world is set to remote_items = False, then the server never sends an item where receiver == finder,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # the client finds its own items in its own world.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    remote_items: bool = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-23 03:48:37 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # If remote_start_inventory is true, the start_inventory/world.precollected_items is sent on connection,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # otherwise the world implementation is in charge of writing the items to their output data.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    remote_start_inventory: bool = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-31 16:04:37 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # For games where after a victory it is impossible to go back in and get additional/remaining Locations checked.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # this forces forfeit:  auto for those games.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    forced_auto_forfeit: bool = False
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-27 20:46:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # Hide World Type from various views. Does not remove functionality.
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-30 19:51:07 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    hidden: bool = False
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-27 20:46:23 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # see WebWorld for options
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    web: WebWorld = WebWorld()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-15 13:31:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # autoset on creation:
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    multiworld: "MultiWorld"
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-15 13:31:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    player: int
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-29 20:27:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # automatically generated
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    item_id_to_name: Dict[int, str]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    location_id_to_name: Dict[int, str]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    item_names: Set[str]  # set of all potential item names
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    location_names: Set[str]  # set of all potential location names
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-18 00:27:37 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    zip_path: Optional[pathlib.Path] = None  # If loaded from a .apworld, this is the Path to it.
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    __file__: str  # path it was loaded from
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-20 21:54:00 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __init__(self, world: "MultiWorld", player: int):
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.multiworld = world
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 18:02:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.player = player
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-22 15:51:50 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # overridable methods that get called by Main.py, sorted by execution order
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-06 16:17:10 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # can also be implemented as a classmethod and called "stage_<original_name>",
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 06:50:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # in that case the MultiWorld object is passed as an argument and it gets called once for the entire multiworld.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # An example of this can be found in alttp as stage_pre_fill
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-29 20:37:28 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    @classmethod
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def assert_generate(cls) -> None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        """Checks that a game is capable of generating, usually checks for some base file like a ROM.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Not run for unittests since they don't produce output"""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def generate_early(self) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-15 08:50:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def create_regions(self) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 18:02:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def create_items(self) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-22 15:51:50 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def set_rules(self) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def generate_basic(self) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def pre_fill(self) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 06:50:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        """Optional method that is supposed to be used for special fill stages. This is run *after* plando."""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-30 07:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    @classmethod
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def fill_hook(cls,
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  progitempool: List["Item"],
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-16 20:06:25 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  usefulitempool: List["Item"],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  filleritempool: List["Item"],
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  fill_locations: List["Location"]) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        """Special method that gets called as part of distribute_items_restrictive (main fill).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        This gets called once per present world type."""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def post_fill(self) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-28 14:54:10 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        """Optional Method that is called after regular fill. Can be used to do adjustments before output generation.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        This happens before progression balancing, so the items may not be in their final locations yet."""
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-30 01:16:04 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def generate_output(self, output_directory: str) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-08 05:09:34 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        """This method gets called from a threadpool, do not use world.random here.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        If you need any last-second randomization, use MultiWorld.slot_seeds[slot] instead."""
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 14:22:44 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-27 00:23:42 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def fill_slot_data(self) -> Dict[str, Any]:  # json of WebHostLib.models.Slot
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-28 14:54:10 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        """Fill in the `slot_data` field in the `Connected` network package.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        This is a way the generator can give custom data to the client.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        The client will receive this as JSON in the `Connected` response."""
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-21 18:08:15 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return {}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-09-18 14:30:43 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def extend_hint_information(self, hint_data: Dict[int, Dict[int, str]]):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        """Fill in additional entrance information text into locations, which is displayed when hinted.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        structure is {player_id: {location_id: text}} You will need to insert your own player_id."""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def modify_multidata(self, multidata: Dict[str, Any]) -> None:  # TODO: TypedDict for multidata?
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-09 09:15:41 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        """For deeper modification of server multidata."""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-02 12:29:29 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # Spoiler writing is optional, these may not get called.
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def write_spoiler_header(self, spoiler_handle: TextIO) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-02 12:29:29 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        """Write to the spoiler header. If individual it's right at the end of that player's options,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if as stage it's right under the common header before per-player options."""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def write_spoiler(self, spoiler_handle: TextIO) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-02 12:29:29 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        """Write to the spoiler "middle", this is after the per-player options and before locations,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        meant for useful or interesting info."""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def write_spoiler_end(self, spoiler_handle: TextIO) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-02 12:29:29 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        """Write to the end of the spoiler"""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        pass
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-17 07:07:34 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-19 23:23:48 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # end of ordered Main.py calls
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-08 05:09:34 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def create_item(self, name: str) -> "Item":
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-05 15:49:19 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        """Create an item for this world type and player.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Warning: this may be called with self.world = None, for example by MultiServer"""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        raise NotImplementedError
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def get_filler_item_name(self) -> str:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        """Called when the item pool needs to be filled with additional items to match location count."""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        logging.warning(f"World {self} is generating a filler item without custom filler pool.")
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return self.multiworld.random.choice(tuple(self.item_name_to_id.keys()))
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-05 15:49:19 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # decent place to implement progressive items, in most cases can stay as-is
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def collect_item(self, state: "CollectionState", item: "Item", remove: bool = False) -> Optional[str]:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:47:28 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        """Collect an item name into state. For speed reasons items that aren't logically useful get skipped.
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        Collect None to skip item.
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-05 15:49:19 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        :param state: CollectionState to collect into
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        :param item: Item to decide on if it should be collected into state
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        :param remove: indicate if this is meant to remove from state instead of adding."""
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-04 15:47:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if item.advancement:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:47:28 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return item.name
							 | 
						
					
						
							
								
									
										
										
										
											2022-04-28 09:03:44 -07:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return None
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-04 15:47:11 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-13 23:02:18 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # called to create all_state, return Items that are created during pre_fill
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def get_pre_fill_items(self) -> List["Item"]:
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-13 23:02:18 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return []
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-22 08:02:15 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # following methods should not need to be overridden.
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def collect(self, state: "CollectionState", item: "Item") -> bool:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:47:28 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        name = self.collect_item(state, item)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if name:
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-05 15:49:19 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            state.prog_items[name, self.player] += 1
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:47:28 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return False
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def remove(self, state: "CollectionState", item: "Item") -> bool:
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        name = self.collect_item(state, item, True)
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:47:28 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if name:
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-05 15:49:19 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            state.prog_items[name, self.player] -= 1
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if state.prog_items[name, self.player] < 1:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                del (state.prog_items[name, self.player])
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-10 09:47:28 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return False
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-16 12:23:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def create_filler(self) -> "Item":
							 | 
						
					
						
							
								
									
										
										
										
											2022-03-20 11:07:51 -04:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return self.create_item(self.get_filler_item_name())
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-05 15:49:19 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-08-21 06:55:08 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-15 13:31:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								# any methods attached to this can be used as part of CollectionState,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# please use a prefix as all of them get clobbered together
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class LogicMixin(metaclass=AutoLogicRegister):
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-16 12:23:05 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    pass
							 |