mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 12:11:33 -06:00
Core: allow loading worlds from zip modules (#747)
* Core: allow loading worlds from zip modules RoR2: make it zipimport compatible (remove relative imports beyond local top-level) * WebHost: add support for .apworld
This commit is contained in:
@@ -1,29 +1,57 @@
|
||||
import importlib
|
||||
import zipimport
|
||||
import os
|
||||
import typing
|
||||
|
||||
__all__ = {"lookup_any_item_id_to_name",
|
||||
"lookup_any_location_id_to_name",
|
||||
"network_data_package",
|
||||
"AutoWorldRegister"}
|
||||
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_folders = []
|
||||
for file in os.scandir(os.path.dirname(__file__)):
|
||||
if file.is_dir():
|
||||
world_folders.append(file.name)
|
||||
world_folders.sort()
|
||||
for world in world_folders:
|
||||
if not world.startswith("_"): # prevent explicitly loading __pycache__ and allow _* names for non-world folders
|
||||
importlib.import_module(f".{world}", "worlds")
|
||||
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")
|
||||
|
||||
from .AutoWorld import AutoWorldRegister
|
||||
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,
|
||||
"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.
|
||||
@@ -41,5 +69,6 @@ network_data_package = {
|
||||
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]}")
|
||||
|
Reference in New Issue
Block a user