diff --git a/.gitignore b/.gitignore index fbe3fdc..ee75701 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /.idea/ +/.cache/ /option.json diff --git a/source/gui/install.py b/source/gui/install.py index dc037bc..e197294 100644 --- a/source/gui/install.py +++ b/source/gui/install.py @@ -77,8 +77,8 @@ class Window(tkinter.Tk): self.after(0, self.run_after) self.mainloop() - @event.register - def run_after(self) -> None: + @staticmethod + def run_after() -> None: """ Run after the installer has been initialised, can be used to add plugins :return: @@ -454,7 +454,13 @@ class ProgressBar(ttk.LabelFrame): :param value: the value :return: """ - self.progress_bar.configure(mode="determinate" if value else "indeterminate") + if value: + if self.progress_bar["mode"] == "indeterminate": self.progress_bar.stop() + self.progress_bar.configure(mode="determinate") + + else: + if self.progress_bar["mode"] == "determinate": self.progress_bar.start(50) + self.progress_bar.configure(mode="indeterminate") # Combobox to select the pack diff --git a/source/mkw/Game.py b/source/mkw/Game.py index 5cddbad..63d438f 100644 --- a/source/mkw/Game.py +++ b/source/mkw/Game.py @@ -1,11 +1,32 @@ -import time from pathlib import Path from typing import Generator from source.mkw.ModConfig import ModConfig +from source.wt import szs from source.wt.wit import WITPath, Region, Extension +def extract_autoadd(extracted_game: Path | str, destination_path: Path | str) -> Path: + """ + Extract all the autoadd files from the game to destination_path + :param extracted_game: path of the extracted game + :param destination_path: directory where the autoadd files will be extracted + :return: directory where the autoadd files were extracted + """ + yield {"description": "Extracting autoadd files...", "determinate": False} + szs.autoadd(extracted_game / "files/Race/Course/", destination_path) + + +def install_mystuff(extracted_game: Path | str) -> None: + """ + Install mystuff directory + :param extracted_game: the extracted game + :return: + """ + yield {"description": "Installing MyStuff directory...", "determinate": False} + + + class Game: def __init__(self, path: Path | str): self.wit_path = WITPath(path) @@ -34,7 +55,6 @@ class Game: yield { "description": f'EXTRACTING - {gen_data["percentage"]}% - (estimated time remaining: ' f'{gen_data["estimation"] if gen_data["estimation"] is not None else "-:--"})', - "maximum": 100, "value": gen_data["percentage"], "determinate": True @@ -43,6 +63,25 @@ class Game: except StopIteration as e: return e.value + def get_output_directory(self, dest: Path | str, mod_config: ModConfig) -> Path: + """ + Return the directory where the game will be installed + :param mod_config: mod configuration + :return: directory where the game will be installed + """ + dest = Path(dest) + + extracted_game: Path = Path(dest / f"{mod_config.nickname} {mod_config.version}") + dest_name: str = extracted_game.name + + # if the directory already exist, add a number to the name + i: int = 0 + while extracted_game.exists(): + i += 1 + extracted_game = extracted_game.with_name(dest_name + f" ({i})") + + return extracted_game + def install_mod(self, dest: Path, mod_config: ModConfig, output_type: Extension) -> Generator[dict, None, None]: """ Patch the game with the mod @@ -50,6 +89,14 @@ class Game: :mod_config: mod configuration :output_type: type of the destination game """ - # yield from self.extract(dest / f"{mod_config.nickname} {mod_config.version}") - print(mod_config.get_ctfile()) - yield {} + # create a cache directory for some files + cache_directory: Path = Path("./.cache") + cache_directory.mkdir(parents=True, exist_ok=True) + + # get the directory where the game will be extracted + extracted_game: Path = self.get_output_directory(dest, mod_config) + + yield from self.extract(extracted_game) + yield from extract_autoadd(extracted_game, cache_directory / "autoadd/") + yield from install_mystuff(extracted_game) + diff --git a/source/mkw/ModConfig.py b/source/mkw/ModConfig.py index 6f2fed3..451fc92 100644 --- a/source/mkw/ModConfig.py +++ b/source/mkw/ModConfig.py @@ -34,9 +34,9 @@ class ModConfig: self.default_track: "Track | TrackGroup" = default_track if default_track is not None else None self._tracks: list["Track | TrackGroup"] = tracks if tracks is not None else [] self.track_formatting: dict[str, str] = { - "menu_name": "{{ getattr(track, 'name', '/') }}", - "race_name": "{{ getattr(track, 'name', '/') }}", - "file_name": "{{ getattr(track, 'sha1', '/') }}" + "menu_name": "{{ getattr(track, 'name', '') }}", + "race_name": "{{ getattr(track, 'name', '') }}", + "file_name": "{{ getattr(track, 'sha1', '_') }}", } | (track_formatting if track_formatting is not None else {}) self.original_track_prefix: bool = original_track_prefix if original_track_prefix is not None else True diff --git a/source/mkw/Track.py b/source/mkw/Track.py index ccec002..c2554b7 100644 --- a/source/mkw/Track.py +++ b/source/mkw/Track.py @@ -103,7 +103,6 @@ class Track: :hidden: if the track is in a group :return: ctfile """ - # TODO: filename, info and - are not implemented menu_name = f'{self.repr_format(mod_config=mod_config, format=mod_config.track_formatting["menu_name"])!r}' file_name = f'{self.repr_format(mod_config=mod_config, format=mod_config.track_formatting["file_name"])!r}' diff --git a/source/option.py b/source/option.py index a93c3b6..6f69cef 100644 --- a/source/option.py +++ b/source/option.py @@ -43,7 +43,7 @@ class Option: :return: None """ if option_file is None: option_file = self._path - if isinstance(option_file, str): option_file = Path(option_file) + option_file = Path(option_file) with option_file.open("w") as file: json.dump(self._options, file, indent=4, ensure_ascii=False) @@ -68,7 +68,7 @@ class Option: :param option_file: the option file :return: Option """ - if isinstance(option_file, str): option_file = Path(option_file) + option_file = Path(option_file) if not option_file.exists(): obj = cls() else: obj = cls.from_dict(json.loads(option_file.read_text(encoding="utf8"))) diff --git a/source/safe_eval.py b/source/safe_eval.py index 1d9ff61..5e81c69 100644 --- a/source/safe_eval.py +++ b/source/safe_eval.py @@ -44,7 +44,7 @@ class SafeFunction: :return: the attribute value """ attr = getattr(obj, attr) if default is None else getattr(obj, attr, default) - if callable(attr): raise AttributeError(f"getattr can't be used for functions (tried: tr{attr})") + if callable(attr): raise AttributeError(f"getattr can't be used for functions (tried: {attr})") return attr diff --git a/source/wt/szs.py b/source/wt/szs.py index 3745bfd..96600cd 100644 --- a/source/wt/szs.py +++ b/source/wt/szs.py @@ -4,11 +4,24 @@ from source.wt import _run, _run_dict tools_path = tools_szs_dir / ("wszst.exe" if system == "win64" else "wszst") +@better_wt_error(tools_path) +def autoadd(course_directory: Path | str, destination_path: Path | str) -> Path: + """ + Extract all the autoadd files from course_directory to destination_path + :param course_directory: directory with all the default tracks of the game + :param destination_path: directory where the autoadd files will be extracted + :return: directory where the autoadd files were extracted + """ + destination_path = Path(destination_path) + _run(tools_path, "AUTOADD", course_directory, "-D", destination_path) + return destination_path + + class SZSPath: __slots__ = ("path", "_analyze") def __init__(self, path: Path | str): - self.path: Path = path if isinstance(path, Path) else Path(path) + self.path: Path = Path(path) self._analyze = None def __repr__(self) -> str: @@ -58,10 +71,10 @@ class SZSPath: :param dest: output directory :return: """ - dest: Path = dest if isinstance(dest, Path) else Path(dest) + dest: Path = Path(dest) if dest.is_dir(): dest /= self.path.name - self._run("EXTRACT", self.path, "-d", dest) + self._run("EXTRACT", self.path, "-D", dest) return dest def analyze(self) -> dict: @@ -128,7 +141,7 @@ class SZSSubPath: """ if self.is_dir(): raise ValueError("Can't extract a directory") - dest: Path = dest if isinstance(dest, Path) else Path(dest) + dest: Path = Path(dest) if dest.is_dir(): dest /= self.basename() with dest.open("wb") as file: diff --git a/source/wt/wit.py b/source/wt/wit.py index ea8ed46..03175db 100644 --- a/source/wt/wit.py +++ b/source/wt/wit.py @@ -35,7 +35,7 @@ class Region(enum.Enum): """ PAL = "PAL" USA = "USA" - EUR = "EUR" + JAP = "JAP" KOR = "KOR" @@ -214,7 +214,7 @@ class WITSubPath: :param dest: destination directory :return: the extracted file path """ - dest: Path = dest if isinstance(dest, Path) else Path(dest) + dest: Path = Path(dest) if self.wit_path.extension == Extension.FST: # if flat is used, extract the file / dir into the destination directory, without subdirectory