Core: add layer for patches that don't use `Patch.py` (#2889)

* Core: add layer for patches that don't use `Patch.py`

* bump container version

* APAutoPatchInterface name

* mystic quest change

* OoT and Adventure changes

* missed name in docstring

* container version compatibility
This commit is contained in:
Doug Hoskisson 2024-03-14 14:29:29 -07:00 committed by GitHub
parent fa233b2583
commit e534abeab0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 40 additions and 21 deletions

View File

@ -8,7 +8,7 @@ if __name__ == "__main__":
import ModuleUpdate
ModuleUpdate.update()
from worlds.Files import AutoPatchRegister, APPatch
from worlds.Files import AutoPatchRegister, APAutoPatchInterface
class RomMeta(TypedDict):
@ -20,7 +20,7 @@ class RomMeta(TypedDict):
def create_rom_file(patch_file: str) -> Tuple[RomMeta, str]:
auto_handler = AutoPatchRegister.get_handler(patch_file)
if auto_handler:
handler: APPatch = auto_handler(patch_file)
handler: APAutoPatchInterface = auto_handler(patch_file)
target = os.path.splitext(patch_file)[0]+handler.result_file_ending
handler.patch(target)
return {"server": handler.server,

View File

@ -6,7 +6,7 @@ import zipfile
import os
import threading
from typing import ClassVar, Dict, Tuple, Any, Optional, Union, BinaryIO
from typing import ClassVar, Dict, List, Literal, Tuple, Any, Optional, Union, BinaryIO
import bsdiff4
@ -38,7 +38,7 @@ class AutoPatchRegister(abc.ABCMeta):
return None
current_patch_version: int = 5
container_version: int = 6
class InvalidDataError(Exception):
@ -50,7 +50,7 @@ class InvalidDataError(Exception):
class APContainer:
"""A zipfile containing at least archipelago.json"""
version: int = current_patch_version
version: int = container_version
compression_level: int = 9
compression_method: int = zipfile.ZIP_DEFLATED
game: Optional[str] = None
@ -124,14 +124,31 @@ class APContainer:
"game": self.game,
# minimum version of patch system expected for patching to be successful
"compatible_version": 5,
"version": current_patch_version,
"version": container_version,
}
class APPatch(APContainer, abc.ABC, metaclass=AutoPatchRegister):
class APPatch(APContainer):
"""
An abstract `APContainer` that defines the requirements for an object
to be used by the `Patch.create_rom_file` function.
An `APContainer` that represents a patch file.
It includes the `procedure` key in the manifest to indicate that it is a patch.
Your implementation should inherit from this if your output file
represents a patch file, but will not be applied with AP's `Patch.py`
"""
procedure: Union[Literal["custom"], List[Tuple[str, List[Any]]]] = "custom"
def get_manifest(self) -> Dict[str, Any]:
manifest = super(APPatch, self).get_manifest()
manifest["procedure"] = self.procedure
manifest["compatible_version"] = 6
return manifest
class APAutoPatchInterface(APPatch, abc.ABC, metaclass=AutoPatchRegister):
"""
An abstract `APPatch` that defines the requirements for a patch
to be applied with AP's `Patch.py`
"""
result_file_ending: str = ".sfc"
@ -140,14 +157,15 @@ class APPatch(APContainer, abc.ABC, metaclass=AutoPatchRegister):
""" create the output file with the file name `target` """
class APDeltaPatch(APPatch):
"""An APPatch that additionally has delta.bsdiff4
containing a delta patch to get the desired file, often a rom."""
class APDeltaPatch(APAutoPatchInterface):
"""An implementation of `APAutoPatchInterface` that additionally
has delta.bsdiff4 containing a delta patch to get the desired file."""
hash: Optional[str] # base checksum of source file
patch_file_ending: str = ""
delta: Optional[bytes] = None
source_data: bytes
procedure = None # delete this line when APPP is added
def __init__(self, *args: Any, patched_path: str = "", **kwargs: Any) -> None:
self.patched_path = patched_path
@ -158,6 +176,7 @@ class APDeltaPatch(APPatch):
manifest["base_checksum"] = self.hash
manifest["result_file_ending"] = self.result_file_ending
manifest["patch_file_ending"] = self.patch_file_ending
manifest["compatible_version"] = 5 # delete this line when APPP is added
return manifest
@classmethod

View File

@ -7,7 +7,7 @@ from typing import Optional, Any
import Utils
from .Locations import AdventureLocation, LocationData
from settings import get_settings
from worlds.Files import APDeltaPatch, AutoPatchRegister, APContainer
from worlds.Files import APPatch, AutoPatchRegister
import bsdiff4
@ -78,7 +78,7 @@ class BatNoTouchLocation:
return ret_dict
class AdventureDeltaPatch(APContainer, metaclass=AutoPatchRegister):
class AdventureDeltaPatch(APPatch, metaclass=AutoPatchRegister):
hash = ADVENTUREHASH
game = "Adventure"
patch_file_ending = ".apadvn"

View File

@ -4,7 +4,7 @@ import zipfile
from copy import deepcopy
from .Regions import object_id_table
from Utils import __version__
from worlds.Files import APContainer
from worlds.Files import APPatch
import pkgutil
settings_template = yaml.load(pkgutil.get_data(__name__, "data/settings.yaml"), yaml.Loader)
@ -116,10 +116,10 @@ def generate_output(self, output_directory):
APMQ.write_contents(zf)
class APMQFile(APContainer):
class APMQFile(APPatch):
game = "Final Fantasy Mystic Quest"
def get_manifest(self):
manifest = super().get_manifest()
manifest["patch_file_ending"] = ".apmq"
return manifest
return manifest

View File

@ -29,14 +29,14 @@ from .TextBox import character_table, NORMAL_LINE_WIDTH, rom_safe_text
from .texture_util import ci4_rgba16patch_to_ci8, rgba16_patch
from .Utils import __version__
from worlds.Files import APContainer
from worlds.Files import APPatch
from Utils import __version__ as ap_version
AP_PROGRESSION = 0xD4
AP_JUNK = 0xD5
class OoTContainer(APContainer):
class OoTContainer(APPatch):
game: str = 'Ocarina of Time'
def __init__(self, patch_data: bytes, base_path: str, output_directory: str,

View File

@ -5,7 +5,7 @@ import zipfile
from typing_extensions import override
import Utils
from worlds.Files import APPatch
from worlds.Files import APAutoPatchInterface
from zilliandomizer.patch import Patcher
@ -14,7 +14,7 @@ from .gen_data import GenData
USHASH = 'd4bf9e7bcf9a48da53785d2ae7bc4270'
class ZillionPatch(APPatch):
class ZillionPatch(APAutoPatchInterface):
hash = USHASH
game = "Zillion"
patch_file_ending = ".apzl"