extracted szs directory will now be repacked into szs files

This commit is contained in:
Faraphel 2022-07-15 00:28:04 +02:00
parent 7f5e709aec
commit 4d071e190f
4 changed files with 57 additions and 11 deletions

View file

@ -1,3 +1,4 @@
import shutil
from io import BytesIO from io import BytesIO
from pathlib import Path from pathlib import Path
from typing import Generator, IO from typing import Generator, IO
@ -5,6 +6,7 @@ from typing import Generator, IO
from source.mkw.ModConfig import ModConfig from source.mkw.ModConfig import ModConfig
from source.mkw.Patch.Patch import Patch from source.mkw.Patch.Patch import Patch
from source.wt import szs from source.wt import szs
from source.wt.wstrt import StrPath
class ExtractedGame: class ExtractedGame:
@ -12,12 +14,12 @@ class ExtractedGame:
Class that represents an extracted game Class that represents an extracted game
""" """
def __init__(self, path: Path | str, original_game: "Game" = None): def __init__(self, path: "Path | str", original_game: "Game" = None):
self.path = Path(path) self.path = Path(path)
self.original_game = original_game self.original_game = original_game
self._special_file: dict[str, IO] = {} self._special_file: dict[str, IO] = {}
def extract_autoadd(self, destination_path: Path | str) -> Generator[dict, None, None]: def extract_autoadd(self, destination_path: "Path | str") -> Generator[dict, None, None]:
""" """
Extract all the autoadd files from the game to destination_path Extract all the autoadd files from the game to destination_path
:param destination_path: directory where the autoadd files will be extracted :param destination_path: directory where the autoadd files will be extracted
@ -45,12 +47,31 @@ class ExtractedGame:
ct_icons.seek(0) ct_icons.seek(0)
self._special_file["ct_icon"] = ct_icons self._special_file["ct_icon"] = ct_icons
def prepare_dol(self) -> Generator[dict, None, None]:
"""
Prepare main.dol and StaticR.rel files (clean them and add lecode)
"""
yield {"description": "Preparing main.dol...", "determinate": False}
StrPath(self.path / "sys/main.dol").patch(clean_dol=True, add_lecode=True)
def recreate_all_szs(self) -> Generator[dict, None, None]:
"""
Repack all the .d directory into .szs files.
:param extracted_game: the extracted game
"""
yield {"description": f"Repacking all szs", "determinate": False}
for extracted_szs in filter(lambda path: path.is_dir(), self.path.rglob("*.d")):
# for every directory that end with a .d in the extracted game, recreate the szs
yield {"description": f"Repacking {extracted_szs} to szs", "determinate": False}
szs.create(extracted_szs, extracted_szs.with_suffix(".szs"), overwrite=True)
shutil.rmtree(str(extracted_szs.resolve()))
def install_all_patch(self, mod_config: ModConfig) -> Generator[dict, None, None]: def install_all_patch(self, mod_config: ModConfig) -> Generator[dict, None, None]:
""" """
Install all patchs of the mod_config into the game Install all patchs of the mod_config into the game
:param special_file: special file that can be used to patch the game
:param mod_config: the mod to install :param mod_config: the mod to install
:return:
""" """
yield {"description": "Installing all Patch...", "determinate": False} yield {"description": "Installing all Patch...", "determinate": False}
@ -62,3 +83,4 @@ class ExtractedGame:
for part_directory in mod_config.get_mod_directory().glob("[!_]*"): for part_directory in mod_config.get_mod_directory().glob("[!_]*"):
for patch_directory in part_directory.glob("_PATCH/"): for patch_directory in part_directory.glob("_PATCH/"):
yield from Patch(patch_directory, mod_config, self._special_file).install(self) yield from Patch(patch_directory, mod_config, self._special_file).install(self)

View file

@ -7,19 +7,19 @@ from source.wt.wit import WITPath, Region, Extension
class NotMKWGameError(Exception): class NotMKWGameError(Exception):
def __init__(self, path: Path | str): def __init__(self, path: "Path | str"):
path = Path(path) path = Path(path)
super().__init__(f'Not a Mario Kart Wii game : "{path.name}"') super().__init__(f'Not a Mario Kart Wii game : "{path.name}"')
class NotVanillaError(Exception): class NotVanillaError(Exception):
def __init__(self, path: Path | str): def __init__(self, path: "Path | str"):
path = Path(path) path = Path(path)
super().__init__(f'This game is already modded : "{path.name}"') super().__init__(f'This game is already modded : "{path.name}"')
class Game: class Game:
def __init__(self, path: Path | str): def __init__(self, path: "Path | str"):
self.wit_path = WITPath(path) self.wit_path = WITPath(path)
def is_mkw(self) -> bool: def is_mkw(self) -> bool:
@ -36,7 +36,7 @@ class Game:
""" """
return not any(self.wit_path[f"./files/rel/lecode-{region.value}.bin"].exists() for region in Region) return not any(self.wit_path[f"./files/rel/lecode-{region.value}.bin"].exists() for region in Region)
def extract(self, dest: Path | str) -> Generator[dict, None, Path]: def extract(self, dest: "Path | str") -> Generator[dict, None, Path]:
""" """
Extract the game to the destination directory. If the game is a FST, just copy to the destination Extract the game to the destination directory. If the game is a FST, just copy to the destination
:param dest: destination directory :param dest: destination directory
@ -67,7 +67,7 @@ class Game:
return e.value return e.value
@staticmethod @staticmethod
def get_output_directory(dest: Path | str, mod_config: ModConfig) -> Path: def get_output_directory(dest: "Path | str", mod_config: ModConfig) -> Path:
""" """
Return the directory where the game will be installed Return the directory where the game will be installed
:param dest: destination directory :param dest: destination directory
@ -107,5 +107,7 @@ class Game:
yield from self.extract(extracted_game.path) yield from self.extract(extracted_game.path)
yield from extracted_game.extract_autoadd(cache_directory / "autoadd/") yield from extracted_game.extract_autoadd(cache_directory / "autoadd/")
yield from extracted_game.install_mystuff() yield from extracted_game.install_mystuff()
yield from extracted_game.prepare_dol()
yield from extracted_game.install_all_patch(mod_config) yield from extracted_game.install_all_patch(mod_config)
yield from extracted_game.recreate_all_szs()

View file

@ -2,6 +2,7 @@ from typing import Generator, IO
from source.mkw.Patch import * from source.mkw.Patch import *
from source.safe_eval import safe_eval, multiple_safe_eval from source.safe_eval import safe_eval, multiple_safe_eval
from source.wt import szs
class Patch: class Patch:
@ -34,8 +35,10 @@ class Patch:
def install(self, extracted_game: "ExtractedGame") -> Generator[dict, None, None]: def install(self, extracted_game: "ExtractedGame") -> Generator[dict, None, None]:
""" """
patch a game with this Patch patch a game with this Patch
:param extracted_game: the extracted game
""" """
from source.mkw.Patch.PatchDirectory import PatchDirectory from source.mkw.Patch.PatchDirectory import PatchDirectory
yield {"description": f"Installing the patch", "determinate": False}
# take all the files in the root directory, and patch them into the game. # take all the files in the root directory, and patch them into the game.
# Patch is not directly applied to the root to avoid custom configuration # Patch is not directly applied to the root to avoid custom configuration

View file

@ -21,6 +21,25 @@ def autoadd(course_directory: Path | str, destination_path: Path | str) -> Path:
return destination_path return destination_path
@better_wt_error(tools_path)
def create(extracted_szs: Path | str, dest: Path | str, overwrite: bool = False) -> "SZSPath":
"""
Convert extracted_szs into a szs archive
:param overwrite: should the destination be overwritten
:param dest: destination where to create the szs file
:param extracted_szs: the extracted szs directory
:return: a SZSPath
"""
extracted_szs = Path(extracted_szs)
dest = Path(dest)
args = []
if overwrite: args.append("--overwrite")
_tools_run("CREATE", extracted_szs, "--DEST", dest, *args)
return SZSPath(dest)
class SZSPath: class SZSPath:
__slots__ = ("path", "_analyze") __slots__ = ("path", "_analyze")
@ -40,7 +59,7 @@ class SZSPath:
:param subfile: subfile name :param subfile: subfile name
:return: the content of the subfile :return: the content of the subfile
""" """
return _tools_run("cat", self.path / subfile) return _tools_run("cat", (self.path / subfile))
def extract(self, subfile: str, dest: Path | str) -> Path: def extract(self, subfile: str, dest: Path | str) -> Path:
""" """
@ -60,7 +79,7 @@ class SZSPath:
dest: Path = Path(dest) dest: Path = Path(dest)
if dest.is_dir(): dest /= self.path.name if dest.is_dir(): dest /= self.path.name
_tools_run("EXTRACT", self.path, "-D", dest) _tools_run("EXTRACT", self.path, "--DEST", dest)
return dest return dest
def analyze(self) -> dict: def analyze(self) -> dict: