Skip to content

Commit

Permalink
Core: add layer for patches that don't use Patch.py (ArchipelagoMW#…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
beauxq authored and EmilyV99 committed Apr 15, 2024
1 parent b95bbc5 commit 5ef1f76
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 21 deletions.
4 changes: 2 additions & 2 deletions Patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import ModuleUpdate
ModuleUpdate.update()

from worlds.Files import AutoPatchRegister, APPatch
from worlds.Files import AutoPatchRegister, APAutoPatchInterface


class RomMeta(TypedDict):
Expand All @@ -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,
Expand Down
39 changes: 29 additions & 10 deletions worlds/Files.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
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

Expand Down Expand Up @@ -38,7 +38,7 @@ def get_handler(file: str) -> Optional[AutoPatchRegister]:
return None


current_patch_version: int = 5
container_version: int = 6


class InvalidDataError(Exception):
Expand All @@ -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
Expand Down Expand Up @@ -124,14 +124,31 @@ def get_manifest(self) -> Dict[str, Any]:
"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"

Expand All @@ -140,14 +157,15 @@ def patch(self, target: str) -> None:
""" 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
Expand All @@ -158,6 +176,7 @@ def get_manifest(self) -> Dict[str, Any]:
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
Expand Down
4 changes: 2 additions & 2 deletions worlds/adventure/Rom.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
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

Expand Down Expand Up @@ -78,7 +78,7 @@ def get_dict(self):
return ret_dict


class AdventureDeltaPatch(APContainer, metaclass=AutoPatchRegister):
class AdventureDeltaPatch(APPatch, metaclass=AutoPatchRegister):
hash = ADVENTUREHASH
game = "Adventure"
patch_file_ending = ".apadvn"
Expand Down
6 changes: 3 additions & 3 deletions worlds/ffmq/Output.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
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)
Expand Down Expand Up @@ -116,10 +116,10 @@ def tf(option):
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
4 changes: 2 additions & 2 deletions worlds/oot/Patches.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@
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,
Expand Down
4 changes: 2 additions & 2 deletions worlds/zillion/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from typing_extensions import override

import Utils
from worlds.Files import APPatch
from worlds.Files import APAutoPatchInterface

from zilliandomizer.patch import Patcher

Expand All @@ -14,7 +14,7 @@
USHASH = 'd4bf9e7bcf9a48da53785d2ae7bc4270'


class ZillionPatch(APPatch):
class ZillionPatch(APAutoPatchInterface):
hash = USHASH
game = "Zillion"
patch_file_ending = ".apzl"
Expand Down

0 comments on commit 5ef1f76

Please sign in to comment.