From e3219ba45253132b932c1bad93d9d567d85e91c6 Mon Sep 17 00:00:00 2001 From: Silvris <58583688+Silvris@users.noreply.github.com> Date: Thu, 22 May 2025 02:47:48 -0500 Subject: [PATCH] WebHost: allow APPlayerContainers from "custom" worlds to be displayed in rooms (#4981) Gives WebHost the ability to verify that a patch file is an APPlayerContainer (defined by #4331 as a APContainer containing the "player" field), and allowed it to display any patch file that it can verify is an APPlayerContainer. --- WebHostLib/__init__.py | 4 +--- WebHostLib/templates/hostGame.html | 4 +--- WebHostLib/templates/macros.html | 14 +------------- worlds/Files.py | 13 +++++++++++++ 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/WebHostLib/__init__.py b/WebHostLib/__init__.py index 9c713419..934cc249 100644 --- a/WebHostLib/__init__.py +++ b/WebHostLib/__init__.py @@ -80,10 +80,8 @@ def register(): """Import submodules, triggering their registering on flask routing. Note: initializes worlds subsystem.""" # has automatic patch integration - import worlds.AutoWorld import worlds.Files - app.jinja_env.filters['supports_apdeltapatch'] = lambda game_name: \ - game_name in worlds.Files.AutoPatchRegister.patch_types + app.jinja_env.filters['is_applayercontainer'] = worlds.Files.is_ap_player_container from WebHostLib.customserver import run_server_process # to trigger app routing picking up on it diff --git a/WebHostLib/templates/hostGame.html b/WebHostLib/templates/hostGame.html index 38406351..d7d0a963 100644 --- a/WebHostLib/templates/hostGame.html +++ b/WebHostLib/templates/hostGame.html @@ -17,9 +17,7 @@ This page allows you to host a game which was not generated by the website. For example, if you have generated a game on your own computer, you may upload the zip file created by the generator to host the game here. This will also provide a tracker, and the ability for your players to download - their patch files if the game is core-verified. For Custom Games, you can find the patch files in - the output .zip file you are uploading here. You need to manually distribute those patch files to - your players. + their patch files.

In addition to the zip file created by the generator, you may upload a multidata file here as well.

diff --git a/WebHostLib/templates/macros.html b/WebHostLib/templates/macros.html index b95b8820..0416658d 100644 --- a/WebHostLib/templates/macros.html +++ b/WebHostLib/templates/macros.html @@ -29,27 +29,15 @@ {% if patch.game == "Minecraft" %} Download APMC File... - {% elif patch.game == "Factorio" %} - - Download Factorio Mod... - {% elif patch.game == "Kingdom Hearts 2" %} - - Download Kingdom Hearts 2 Mod... - {% elif patch.game == "Ocarina of Time" %} - - Download APZ5 File... {% elif patch.game == "VVVVVV" and room.seed.slots|length == 1 %} Download APV6 File... {% elif patch.game == "Super Mario 64" and room.seed.slots|length == 1 %} Download APSM64EX File... - {% elif patch.game | supports_apdeltapatch %} + {% elif patch.game | is_applayercontainer(patch.data, patch.player_id) %} Download Patch File... - {% elif patch.game == "Final Fantasy Mystic Quest" %} - - Download APMQ File... {% else %} No file to download for this game. {% endif %} diff --git a/worlds/Files.py b/worlds/Files.py index e451d08c..447219bd 100644 --- a/worlds/Files.py +++ b/worlds/Files.py @@ -6,6 +6,7 @@ import zipfile from enum import IntEnum import os import threading +from io import BytesIO from typing import ClassVar, Dict, List, Literal, Tuple, Any, Optional, Union, BinaryIO, overload, Sequence @@ -70,6 +71,18 @@ class AutoPatchExtensionRegister(abc.ABCMeta): container_version: int = 6 +def is_ap_player_container(game: str, data: bytes, player: int): + if not zipfile.is_zipfile(BytesIO(data)): + return False + with zipfile.ZipFile(BytesIO(data), mode='r') as zf: + if "archipelago.json" in zf.namelist(): + manifest = json.loads(zf.read("archipelago.json")) + if "game" in manifest and "player" in manifest: + if game == manifest["game"] and player == manifest["player"]: + return True + return False + + class InvalidDataError(Exception): """ Since games can override `read_contents` in APContainer,