Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions worlds/LauncherComponents.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ def _install_apworld(apworld_src: str = "") -> Optional[Tuple[pathlib.Path, path
"so a Launcher restart is required to use the new installation.")
world_source = worlds.WorldSource(str(target), is_zip=True, relative=False)
bisect.insort(worlds.world_sources, world_source)
worlds.add_apworld_spec(world_source, worlds.APWorldContainer(world_source.resolved_path))
world_source.load()

return apworld_path, target
Expand Down
35 changes: 20 additions & 15 deletions worlds/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from NetUtils import DataPackage
from Utils import local_path, user_path, Version, version_tuple, tuplize_version, messagebox
from .Files import APWorldContainer

local_folder = os.path.dirname(__file__)
user_folder = user_path("worlds") if user_path() != local_path() else user_path("custom_worlds")
Expand Down Expand Up @@ -74,6 +75,23 @@ def load(self) -> bool:
return False


apworld_module_specs = {}
class APWorldModuleFinder(importlib.abc.MetaPathFinder):
def find_spec(
self, fullname: str, _path: Sequence[str] | None, _target: ModuleType | None = None
) -> importlib.machinery.ModuleSpec | None:
return apworld_module_specs.get(fullname)
sys.meta_path.insert(0, APWorldModuleFinder())


def add_apworld_spec(source: WorldSource, container: APWorldContainer):
importer = zipimport.zipimporter(source.resolved_path)
world_name = Path(container.path).stem

spec = importer.find_spec(f"worlds.{world_name}")
apworld_module_specs[f"worlds.{world_name}"] = spec


# find potential world containers, currently folders and zip-importable .apworld's
world_sources: List[WorldSource] = []
for folder in (folder for folder in (user_folder, local_folder) if folder):
Expand Down Expand Up @@ -125,7 +143,7 @@ def load(self) -> bool:
# encapsulation for namespace / gc purposes
def load_apworlds() -> None:
global apworlds
from .Files import APWorldContainer, InvalidDataError
from .Files import InvalidDataError
core_compatible: list[tuple[WorldSource, APWorldContainer]] = []

def fail_world(game_name: str, reason: str, add_as_failed_to_load: bool = True) -> None:
Expand Down Expand Up @@ -174,27 +192,14 @@ def fail_world(game_name: str, reason: str, add_as_failed_to_load: bool = True)
key=lambda element: element[1].world_version if element[1].world_version else Version(0, 0, 0),
reverse=True)

apworld_module_specs = {}
class APWorldModuleFinder(importlib.abc.MetaPathFinder):
def find_spec(
self, fullname: str, _path: Sequence[str] | None, _target: ModuleType = None
) -> importlib.machinery.ModuleSpec | None:
return apworld_module_specs.get(fullname)

sys.meta_path.insert(0, APWorldModuleFinder())

for apworld_source, apworld in core_compatible:
if apworld.game and apworld.game in AutoWorldRegister.world_types:
fail_world(apworld.game,
f"Did not load {apworld_source.path} "
f"as its game {apworld.game} is already loaded.",
add_as_failed_to_load=False)
else:
importer = zipimport.zipimporter(apworld_source.resolved_path)
world_name = Path(apworld.path).stem

spec = importer.find_spec(f"worlds.{world_name}")
apworld_module_specs[f"worlds.{world_name}"] = spec
add_apworld_spec(apworld_source, apworld)

apworld_source.load()
if apworld.game in AutoWorldRegister.world_types:
Expand Down
Loading