| 
									
										
										
										
											2021-06-29 03:49:29 +02:00
										 |  |  | import importlib | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2022-10-01 02:47:31 +02:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 |  |  | import typing | 
					
						
							| 
									
										
										
										
											2022-10-01 02:47:31 +02:00
										 |  |  | import warnings | 
					
						
							|  |  |  | import zipimport | 
					
						
							| 
									
										
										
										
											2021-02-26 21:03:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-15 23:52:03 +02: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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-28 02:25:53 +01:00
										 |  |  | class GamesPackage(typing.TypedDict): | 
					
						
							|  |  |  |     item_name_to_id: typing.Dict[str, int] | 
					
						
							|  |  |  |     location_name_to_id: typing.Dict[str, int] | 
					
						
							|  |  |  |     version: int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class DataPackage(typing.TypedDict): | 
					
						
							|  |  |  |     version: int | 
					
						
							|  |  |  |     games: typing.Dict[str, GamesPackage] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-15 23:52:03 +02: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 13:02:05 +02:00
										 |  |  |     # prevent loading of __pycache__ and allow _* for non-world folders, disable files/folders starting with "." | 
					
						
							|  |  |  |     if not file.name.startswith(("_", ".")): | 
					
						
							| 
									
										
										
										
											2022-08-15 23:52:03 +02: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 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-29 03:49:29 +02:00
										 |  |  | # import all submodules to trigger AutoWorldRegister | 
					
						
							| 
									
										
										
										
											2022-08-15 23:52:03 +02: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-10-01 02:47:31 +02:00
										 |  |  |         spec = importer.find_spec(world_source.path.split(".", 1)[0]) | 
					
						
							|  |  |  |         mod = importlib.util.module_from_spec(spec) | 
					
						
							|  |  |  |         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") | 
					
						
							|  |  |  |             importer.exec_module(mod) | 
					
						
							| 
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 |  |  |     else: | 
					
						
							|  |  |  |         importlib.import_module(f".{world_source.path}", "worlds") | 
					
						
							| 
									
										
										
										
											2021-07-12 18:05:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | lookup_any_item_id_to_name = {} | 
					
						
							|  |  |  | lookup_any_location_id_to_name = {} | 
					
						
							| 
									
										
										
										
											2022-11-28 02:25:53 +01:00
										 |  |  | games: typing.Dict[str, GamesPackage] = {} | 
					
						
							| 
									
										
										
										
											2021-07-12 18:05:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 |  |  | from .AutoWorld import AutoWorldRegister | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-12 18:05:46 +02:00
										 |  |  | for world_name, world in AutoWorldRegister.world_types.items(): | 
					
						
							|  |  |  |     games[world_name] = { | 
					
						
							| 
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 |  |  |         "item_name_to_id": world.item_name_to_id, | 
					
						
							| 
									
										
										
										
											2021-07-12 18:05:46 +02:00
										 |  |  |         "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) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-28 02:25:53 +01:00
										 |  |  | network_data_package: DataPackage = { | 
					
						
							| 
									
										
										
										
											2021-07-12 18:05:46 +02:00
										 |  |  |     "games": games, | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-08-22 04:22:34 +02: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 09:10:27 +02:00
										 |  |  |     import logging | 
					
						
							| 
									
										
										
										
											2022-08-15 23:52:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-18 04:53:09 +01: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]}") |