diff --git a/worthless/gui.py b/worthless/gui.py index d33b5f7..66bb244 100755 --- a/worthless/gui.py +++ b/worthless/gui.py @@ -31,6 +31,9 @@ class UI: answer = input(question + " (y/n): ") return answer.lower() == 'y' + def override_game_version(self, version: str): + self._installer._version = version + def get_game_version(self): print(self._installer.get_game_version()) @@ -40,9 +43,9 @@ class UI: print("Updating game from archive (this may takes some time)...") self._installer.update_game(filepath) - def _install_from_archive(self, filepath): + def _install_from_archive(self, filepath, force_reinstall): print("Installing game from archive (this may takes some time)...") - self._installer.install_game(filepath) + self._installer.install_game(filepath, force_reinstall) def _apply_voiceover_from_archive(self, filepath): print("Applying voiceover from archive (this may takes some time)...") @@ -90,19 +93,44 @@ class UI: if not self._ask("Do you want to install the game? ({})".format(filepath)): print("Aborting installation process.") return - self._install_from_archive(filepath) + self._install_from_archive(filepath, False) print("Game installed successfully.") + def download_game(self): + print("Downloading full game (This will take a long time)...") + asyncio.run(self._installer.download_full_game()) + + def download_game_update(self): + print("Downloading game update (This will take a long time)...") + asyncio.run(self._installer.download_game_update()) + + def download_voiceover(self, languages: str): + res_info = asyncio.run(self._launcher.get_resource_info()) + for lng in languages.split(" "): + for vo in res_info.game.latest.voice_packs: + if not self._installer.voiceover_lang_translate(lng) == vo.language: + continue + print("Downloading voiceover pack for {} (This will take a long time)...".format(lng)) + asyncio.run(self._installer.download_full_voiceover(lng)) + + def download_voiceover_update(self, languages: str): + res_info = asyncio.run(self._launcher.get_resource_info()) + for lng in languages.split(" "): + for vo in res_info.game.latest.voice_packs: + if not self._installer.voiceover_lang_translate(lng) == vo.language: + continue + print("Downloading voiceover update pack for {} (This will take a long time)...".format(lng)) + asyncio.run(self._installer.download_voiceover_update(lng)) + def install_game(self, forced: bool = False): res_info = asyncio.run(self._launcher.get_resource_info()) print("Latest game version: {}".format(res_info.game.latest.version)) if not self._ask("Do you want to install the game?"): print("Aborting game installation process.") return - print("Downloading full game (This will take a long time)...") - asyncio.run(self._installer.download_full_game(forced)) + self.download_game() print("Installing game...") - self._install_from_archive(self._installer.temp_path.joinpath(res_info.game.latest.name)) + self._install_from_archive(self._installer.temp_path.joinpath(res_info.game.latest.name), forced) def install_voiceover(self, languages: str): res_info = asyncio.run(self._launcher.get_resource_info()) @@ -188,8 +216,16 @@ def main(): help="Patch the game (if not already patched, else do nothing)") parser.add_argument("--login-fix", action="store_true", help="Patch the game to fix login issues (if not already patched, else do nothing)") - parser.add_argument("-Sy", "--update", action="store", type=str, + parser.add_argument("-Sy", "--update", action="store", type=str, default="", help="Update the game and specified voiceover pack only (or install if not found)") + parser.add_argument("-Sw", "--download-game", action="store_true", + help="Download the full game to the temporary directory") + parser.add_argument("-Swv", "--download-voiceover", action="store", type=str, + help="Download the full voiceover to the temporary directory") + parser.add_argument("-Syw", "--download-game-update", action="store", type=str, default="", + help="Download the game and the voiceover update to the temporary directory") + parser.add_argument("-Sywv", "--download-voiceover-update", action="store", type=str, + help="Download the voiceover update to the temporary directory") parser.add_argument("-Sv", "--update-voiceover", action="store", type=str, help="Update the voiceover pack only (or install if not found)") parser.add_argument("-Syu", "--update-all", action="store_true", @@ -199,12 +235,15 @@ def main(): parser.add_argument("-Rv", "--remove-voiceover", action="store_true", help="Remove a Voiceover pack (if installed)") parser.add_argument("--get-game-version", action="store_true", help="Get the current game version") parser.add_argument("--no-overseas", action="store_true", help="Don't use overseas server") + parser.add_argument("--from-ver", action="store", help="Override the detected game version", type=str, default=None) parser.add_argument("--noconfirm", action="store_true", help="Do not ask any for confirmation. (Ignored in interactive mode)") args = parser.parse_args() interactive_mode = not args.install and not args.install_from_file and not args.patch and not args.update and not \ args.remove and not args.remove_patch and not args.remove_voiceover and not args.get_game_version and not \ - args.install_voiceover_from_file and not args.update_voiceover + args.install_voiceover_from_file and not args.update_voiceover and not args.download_game and not \ + args.download_voiceover and not args.download_game_update and not args.download_voiceover_update and not \ + args.install_voiceover_from_file and not args.update_all and not args.login_fix if args.temporary_dir: args.temporary_dir.mkdir(parents=True, exist_ok=True) @@ -225,6 +264,18 @@ def main(): if args.get_game_version: ui.get_game_version() + if args.download_game: + ui.download_game() + + if args.download_voiceover: + ui.download_voiceover(args.download_voiceover) + + if args.download_game_update: + ui.download_game_update() + + if args.download_voiceover_update: + ui.download_voiceover_update(args.download_voiceover_update) + if args.install: ui.install_game() diff --git a/worthless/patcher.py b/worthless/patcher.py index 23e1c43..6cf3411 100644 --- a/worthless/patcher.py +++ b/worthless/patcher.py @@ -1,7 +1,5 @@ import os import platform - -import xdelta3 import tarfile import appdirs from pathlib import Path @@ -12,6 +10,12 @@ from worthless import constants from worthless.launcher import Launcher from worthless.installer import Installer +NO_XDELTA3_MODULE = False +try: + import xdelta3 +except ImportError: + NO_XDELTA3_MODULE = True + class Patcher: def __init__(self, gamedir=Path.cwd(), data_dir: str | Path = None, patch_url: str = None, overseas=True): @@ -147,7 +151,7 @@ class Patcher: f.write(patched_xlua_bytes) def apply_xlua_patch(self, fallback=True): - if fallback: + if NO_XDELTA3_MODULE or fallback: asyncio.run(self._patch_xlua_fallback()) return self._patch_xlua() @@ -161,7 +165,7 @@ class Patcher: :return: None """ # Patch UnityPlayer.dll - if fallback: + if NO_XDELTA3_MODULE or fallback: asyncio.run(self._patch_unityplayer_fallback()) else: self._patch_unityplayer()