2021-06-29 01:49:29 +00:00
|
|
|
import importlib
|
|
|
|
import os
|
2022-10-01 00:47:31 +00:00
|
|
|
import sys
|
2022-08-15 21:52:03 +00:00
|
|
|
import typing
|
2022-10-01 00:47:31 +00:00
|
|
|
import warnings
|
|
|
|
import zipimport
|
2021-02-26 20:03:16 +00:00
|
|
|
|
2022-08-15 21:52:03 +00:00
|
|
|
folder = os.path.dirname(__file__)
|
|
|
|
|
|
|
|
__all__ = {
|
|
|
|
"lookup_any_item_id_to_name",
|
|
|
|
"lookup_any_location_id_to_name",
|
|
|
|
"network_data_package",
|
|
|
|
"AutoWorldRegister",
|
|
|
|
"world_sources",
|
|
|
|
"folder",
|
|
|
|
}
|
|
|
|
|
|
|
|
if typing.TYPE_CHECKING:
|
|
|
|
from .AutoWorld import World
|
|
|
|
|
|
|
|
|
2023-03-20 16:01:08 +00:00
|
|
|
class GamesData(typing.TypedDict):
|
|
|
|
item_name_groups: typing.Dict[str, typing.List[str]]
|
2022-11-28 01:25:53 +00:00
|
|
|
item_name_to_id: typing.Dict[str, int]
|
2023-03-20 16:01:08 +00:00
|
|
|
location_name_groups: typing.Dict[str, typing.List[str]]
|
2022-11-28 01:25:53 +00:00
|
|
|
location_name_to_id: typing.Dict[str, int]
|
|
|
|
version: int
|
|
|
|
|
|
|
|
|
2023-03-20 16:01:08 +00:00
|
|
|
class GamesPackage(GamesData, total=False):
|
|
|
|
checksum: str
|
|
|
|
|
|
|
|
|
2022-11-28 01:25:53 +00:00
|
|
|
class DataPackage(typing.TypedDict):
|
|
|
|
games: typing.Dict[str, GamesPackage]
|
|
|
|
|
|
|
|
|
2022-08-15 21:52:03 +00:00
|
|
|
class WorldSource(typing.NamedTuple):
|
|
|
|
path: str # typically relative path from this module
|
|
|
|
is_zip: bool = False
|
|
|
|
|
|
|
|
|
|
|
|
# find potential world containers, currently folders and zip-importable .apworld's
|
|
|
|
world_sources: typing.List[WorldSource] = []
|
|
|
|
file: os.DirEntry # for me (Berserker) at least, PyCharm doesn't seem to infer the type correctly
|
|
|
|
for file in os.scandir(folder):
|
2022-09-18 11:02:05 +00:00
|
|
|
# prevent loading of __pycache__ and allow _* for non-world folders, disable files/folders starting with "."
|
|
|
|
if not file.name.startswith(("_", ".")):
|
2022-08-15 21:52:03 +00:00
|
|
|
if file.is_dir():
|
|
|
|
world_sources.append(WorldSource(file.name))
|
|
|
|
elif file.is_file() and file.name.endswith(".apworld"):
|
|
|
|
world_sources.append(WorldSource(file.name, is_zip=True))
|
2021-02-21 19:17:24 +00:00
|
|
|
|
2021-06-29 01:49:29 +00:00
|
|
|
# import all submodules to trigger AutoWorldRegister
|
2022-08-15 21:52:03 +00:00
|
|
|
world_sources.sort()
|
|
|
|
for world_source in world_sources:
|
|
|
|
if world_source.is_zip:
|
|
|
|
importer = zipimport.zipimporter(os.path.join(folder, world_source.path))
|
2022-12-19 05:49:38 +00:00
|
|
|
if hasattr(importer, "find_spec"): # new in Python 3.10
|
|
|
|
spec = importer.find_spec(world_source.path.split(".", 1)[0])
|
|
|
|
mod = importlib.util.module_from_spec(spec)
|
|
|
|
else: # TODO: remove with 3.8 support
|
|
|
|
mod = importer.load_module(world_source.path.split(".", 1)[0])
|
|
|
|
|
2022-10-01 00:47:31 +00:00
|
|
|
mod.__package__ = f"worlds.{mod.__package__}"
|
|
|
|
mod.__name__ = f"worlds.{mod.__name__}"
|
|
|
|
sys.modules[mod.__name__] = mod
|
|
|
|
with warnings.catch_warnings():
|
|
|
|
warnings.filterwarnings("ignore", message="__package__ != __spec__.parent")
|
2022-12-19 05:49:38 +00:00
|
|
|
# Found no equivalent for < 3.10
|
|
|
|
if hasattr(importer, "exec_module"):
|
|
|
|
importer.exec_module(mod)
|
2022-08-15 21:52:03 +00:00
|
|
|
else:
|
|
|
|
importlib.import_module(f".{world_source.path}", "worlds")
|
2021-07-12 16:05:46 +00:00
|
|
|
|
|
|
|
lookup_any_item_id_to_name = {}
|
|
|
|
lookup_any_location_id_to_name = {}
|
2022-11-28 01:25:53 +00:00
|
|
|
games: typing.Dict[str, GamesPackage] = {}
|
2021-07-12 16:05:46 +00:00
|
|
|
|
2022-08-15 21:52:03 +00:00
|
|
|
from .AutoWorld import AutoWorldRegister
|
|
|
|
|
2023-03-20 16:01:08 +00:00
|
|
|
# Build the data package for each game.
|
2021-07-12 16:05:46 +00:00
|
|
|
for world_name, world in AutoWorldRegister.world_types.items():
|
2023-03-20 16:01:08 +00:00
|
|
|
games[world_name] = world.get_data_package_data()
|
2021-07-12 16:05:46 +00:00
|
|
|
lookup_any_item_id_to_name.update(world.item_id_to_name)
|
|
|
|
lookup_any_location_id_to_name.update(world.location_id_to_name)
|
|
|
|
|
2022-11-28 01:25:53 +00:00
|
|
|
network_data_package: DataPackage = {
|
2021-07-12 16:05:46 +00:00
|
|
|
"games": games,
|
|
|
|
}
|
2021-08-22 02:22:34 +00:00
|
|
|
|
|
|
|
# Set entire datapackage to version 0 if any of them are set to 0
|
|
|
|
if any(not world.data_version for world in AutoWorldRegister.world_types.values()):
|
2021-09-26 07:10:27 +00:00
|
|
|
import logging
|
2022-08-15 21:52:03 +00:00
|
|
|
|
2022-03-18 03:53:09 +00:00
|
|
|
logging.warning(f"Datapackage is in custom mode. Custom Worlds: "
|
|
|
|
f"{[world for world in AutoWorldRegister.world_types.values() if not world.data_version]}")
|