diff --git a/docs/apworld specification.md b/docs/apworld specification.md index 591ce51cae..d2c8b72d95 100644 --- a/docs/apworld specification.md +++ b/docs/apworld specification.md @@ -32,6 +32,8 @@ If the APWorld is a folder, the only required field is "game": There are also the following optional fields: * `minimum_ap_version` and `maximum_ap_version` - which if present will each be compared against the current Archipelago version respectively to filter those files from being loaded. +* `platforms` - a list of strings indicating the `sys.platform`(s) the world can run on. + If empty or not set, it is assumed to be any that python itself can run on. * `world_version` - an arbitrary version for that world in order to only load the newest valid world. An APWorld without a world_version is always treated as older than one with a version (**Must** use exactly the format `"major.minor.build"`, e.g. `1.0.0`) diff --git a/setup.py b/setup.py index 949b1e3e30..1bf3c5c4f3 100644 --- a/setup.py +++ b/setup.py @@ -409,6 +409,7 @@ class BuildExeCommand(cx_Freeze.command.build_exe.build_exe): apworld = APWorldContainer(str(zip_path)) apworld.minimum_ap_version = version_tuple apworld.maximum_ap_version = version_tuple + apworld.platforms = [sys.platform] apworld.game = worldtype.game manifest.update(apworld.get_manifest()) apworld.manifest_path = f"{file_name}/archipelago.json" diff --git a/worlds/AutoWorld.py b/worlds/AutoWorld.py index 327746f1ce..f82277bce4 100644 --- a/worlds/AutoWorld.py +++ b/worlds/AutoWorld.py @@ -353,6 +353,8 @@ class World(metaclass=AutoWorldRegister): """path it was loaded from""" world_version: ClassVar[Version] = Version(0, 0, 0) """Optional world version loaded from archipelago.json""" + platforms: ClassVar[List[str]] = [] + """Optional platforms loaded from archipelago.json""" def __init__(self, multiworld: "MultiWorld", player: int): assert multiworld is not None diff --git a/worlds/Files.py b/worlds/Files.py index ddd1f4e1ce..ec36e7d806 100644 --- a/worlds/Files.py +++ b/worlds/Files.py @@ -197,6 +197,7 @@ class APWorldContainer(APContainer): world_version: "Version | None" = None minimum_ap_version: "Version | None" = None maximum_ap_version: "Version | None" = None + platforms: List[str] = [] def read_contents(self, opened_zipfile: zipfile.ZipFile) -> Dict[str, Any]: from Utils import tuplize_version @@ -205,6 +206,7 @@ class APWorldContainer(APContainer): for version_key in ("world_version", "minimum_ap_version", "maximum_ap_version"): if version_key in manifest: setattr(self, version_key, tuplize_version(manifest[version_key])) + self.platforms = manifest.get("platforms", []) return manifest def get_manifest(self) -> Dict[str, Any]: @@ -215,6 +217,8 @@ class APWorldContainer(APContainer): version = getattr(self, version_key) if version: manifest[version_key] = version.as_simple_string() + if self.platforms: + manifest["platforms"] = self.platforms return manifest diff --git a/worlds/__init__.py b/worlds/__init__.py index dd2d83a27e..e588c54c9a 100644 --- a/worlds/__init__.py +++ b/worlds/__init__.py @@ -118,6 +118,7 @@ for world_source in world_sources: game = manifest.get("game") if game in AutoWorldRegister.world_types: AutoWorldRegister.world_types[game].world_version = tuplize_version(manifest.get("world_version", "0.0.0")) + AutoWorldRegister.world_types[game].platforms = manifest.get("platforms", []) if apworlds: # encapsulation for namespace / gc purposes @@ -165,6 +166,11 @@ if apworlds: f"Did not load {apworld_source.path} " f"as its maximum core version {apworld.maximum_ap_version} " f"is lower than current core version {version_tuple}.") + elif apworld.platforms and sys.platform not in apworld.platforms: + fail_world(apworld.game, + f"Did not load {apworld_source.path} " + f"as it is not compatible with current platform {sys.platform}. " + f"Supported platforms: {', '.join(apworld.platforms)}") else: core_compatible.append((apworld_source, apworld)) # load highest version first @@ -199,6 +205,8 @@ if apworlds: # world could fail to load at this point if apworld.world_version: AutoWorldRegister.world_types[apworld.game].world_version = apworld.world_version + if apworld.platforms: + AutoWorldRegister.world_types[apworld.game].platforms = apworld.platforms load_apworlds() del load_apworlds