Archipelago/worlds/__init__.py

74 lines
2.6 KiB
Python

import importlib
import zipimport
import os
import typing
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
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):
if not file.name.startswith("_"): # prevent explicitly loading __pycache__ and allow _* names for non-world folders
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))
# import all submodules to trigger AutoWorldRegister
world_sources.sort()
for world_source in world_sources:
if world_source.is_zip:
importer = zipimport.zipimporter(os.path.join(folder, world_source.path))
importer.load_module(world_source.path.split(".", 1)[0])
else:
importlib.import_module(f".{world_source.path}", "worlds")
lookup_any_item_id_to_name = {}
lookup_any_location_id_to_name = {}
games = {}
from .AutoWorld import AutoWorldRegister
for world_name, world in AutoWorldRegister.world_types.items():
games[world_name] = {
"item_name_to_id": world.item_name_to_id,
"location_name_to_id": world.location_name_to_id,
"version": world.data_version,
# seems clients don't actually want this. Keeping it here in case someone changes their mind.
# "item_name_groups": {name: tuple(items) for name, items in world.item_name_groups.items()}
}
lookup_any_item_id_to_name.update(world.item_id_to_name)
lookup_any_location_id_to_name.update(world.location_id_to_name)
network_data_package = {
"version": sum(world.data_version for world in AutoWorldRegister.world_types.values()),
"games": games,
}
# 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()):
network_data_package["version"] = 0
import logging
logging.warning(f"Datapackage is in custom mode. Custom Worlds: "
f"{[world for world in AutoWorldRegister.world_types.values() if not world.data_version]}")