feat: hdiff in voiceover update

This commit is contained in:
tretrauit 2023-01-18 12:38:43 +07:00
parent 089b799a5f
commit 820bc70e9d
3 changed files with 85 additions and 70 deletions

View File

@ -10,7 +10,7 @@ README = (HERE / "README.md").read_text()
setup( setup(
name='worthless', name='worthless',
version='2.2.11', version='2.2.12',
packages=['worthless', 'worthless.classes', 'worthless.classes.launcher', 'worthless.classes.installer'], packages=['worthless', 'worthless.classes', 'worthless.classes.launcher', 'worthless.classes.installer'],
url='https://git.froggi.es/tretrauit/worthless-launcher', url='https://git.froggi.es/tretrauit/worthless-launcher',
license='MIT License', license='MIT License',

View File

@ -3,3 +3,5 @@ from worthless import launcher, installer
Launcher = launcher.Launcher Launcher = launcher.Launcher
Installer = installer.Installer Installer = installer.Installer
__version__ = "2.2.12"

View File

@ -326,20 +326,14 @@ class Installer:
voiceovers.append(file.name) voiceovers.append(file.name)
return voiceovers return voiceovers
async def update_game(self, game_archive: str | Path | AsyncPath): async def _update(self, game_archive: str | Path | AsyncPath):
if not await self.get_game_data_path().exists():
raise FileNotFoundError(f"Game not found in {self._gamedir}")
if isinstance(game_archive, str | Path):
game_archive = Path(game_archive).resolve()
if not game_archive.exists():
raise FileNotFoundError(f"Update archive {game_archive} not found")
archive = zipfile.ZipFile(game_archive, 'r') archive = zipfile.ZipFile(game_archive, 'r')
if not self._hdiffpatch.get_hpatchz_executable(): if not self._hdiffpatch.get_hpatchz_executable():
await self._hdiffpatch.download_latest_release() await self._hdiffpatch.download_latest_release()
files = archive.namelist() files = archive.namelist()
# Don't extract these files (they're useless and if the game isn't patched then it'll # Don't extract these files (they're useless and if the game isn't patched then it'll
# raise 31-4xxx error ingame) # raise 31-4xxx error ingame)
for file in ["deletefiles.txt", "hdifffiles.txt"]: for file in ["deletefiles.txt", "hdifffiles.txt"]:
@ -349,59 +343,75 @@ class Installer:
pass pass
# hdiffpatch implementation # hdiffpatch implementation
hdifffiles = [] try:
for x in (await asyncio.to_thread(archive.read, "hdifffiles.txt")).decode().split("\n"): hdifffiles = []
if x: for x in (await asyncio.to_thread(archive.read, "hdifffiles.txt")).decode().split("\n"):
hdifffiles.append(json.loads(x)["remoteName"]) if x:
patch_jobs = [] hdifffiles.append(json.loads(x)["remoteName"])
for file in hdifffiles: patch_jobs = []
current_game_file = self._gamedir.joinpath(file) for file in hdifffiles:
if not await current_game_file.exists(): current_game_file = self._gamedir.joinpath(file)
# Not patching since we don't have the file if not await current_game_file.exists():
continue # Not patching since we don't have the file
continue
patch_file = str(file) + ".hdiff" patch_file = str(file) + ".hdiff"
async def extract_and_patch(old_file, diff_file): async def extract_and_patch(old_file, diff_file):
patch_path = self.temp_path.joinpath(diff_file) patch_path = self.temp_path.joinpath(diff_file)
patch_path.unlink(missing_ok=True) patch_path.unlink(missing_ok=True)
try: try:
print(diff_file) print(diff_file)
await asyncio.to_thread(archive.extract, diff_file, self.temp_path) await asyncio.to_thread(archive.extract, diff_file, self.temp_path)
except FileExistsError: except FileExistsError:
print("Failed to extract diff file", diff_file) print("Failed to extract diff file", diff_file)
return return
old_suffix = old_file.suffix old_suffix = old_file.suffix
old_file = await old_file.rename(old_file.with_suffix(".bak")) old_file = await old_file.rename(old_file.with_suffix(".bak"))
proc = await self._hdiffpatch.patch_file(old_file, old_file.with_suffix(old_suffix), proc = await self._hdiffpatch.patch_file(old_file, old_file.with_suffix(old_suffix),
patch_path, wait=True) patch_path, wait=True)
patch_path.unlink() patch_path.unlink()
if proc.returncode == 0: if proc.returncode == 0:
await old_file.unlink() await old_file.unlink()
return return
# Let the game download the file. # Let the game download the file.
print("Failed to patch {}, reverting and let the in-game updater do the job...".format( print("Failed to patch {}, reverting and let the in-game updater do the job...".format(
old_file.with_suffix(old_suffix)) old_file.with_suffix(old_suffix))
) )
await old_file.rename(old_file.with_suffix(old_suffix)) await old_file.rename(old_file.with_suffix(old_suffix))
files.remove(patch_file) files.remove(patch_file)
patch_jobs.append(extract_and_patch(current_game_file, patch_file)) patch_jobs.append(extract_and_patch(current_game_file, patch_file))
await asyncio.gather(*patch_jobs) await asyncio.gather(*patch_jobs)
except Exception as e:
print(f"Error while reading hdifffiles.txt: {e}")
deletefiles = archive.read("deletefiles.txt").decode().split("\n") try:
for file in deletefiles: deletefiles = archive.read("deletefiles.txt").decode().split("\n")
current_game_file = Path(self._gamedir.joinpath(file)) for file in deletefiles:
if current_game_file == Path(self._gamedir): current_game_file = Path(self._gamedir.joinpath(file))
continue if current_game_file == Path(self._gamedir):
if not current_game_file.is_file(): continue
continue if not current_game_file.is_file():
print("Deleting ", file) continue
current_game_file.unlink(missing_ok=True) print("Deleting ", file)
current_game_file.unlink(missing_ok=True)
except Exception as e:
print(f"Error while reading deletefiles.txt: {e}")
await asyncio.to_thread(archive.extractall, self._gamedir, members=files) await asyncio.to_thread(archive.extractall, self._gamedir, members=files)
archive.close() archive.close()
async def update_game(self, game_archive: str | Path | AsyncPath):
if not await self.get_game_data_path().exists():
raise FileNotFoundError(f"Game not found in {self._gamedir}")
if isinstance(game_archive, str | Path):
game_archive = Path(game_archive).resolve()
if not game_archive.exists():
raise FileNotFoundError(f"Update archive {game_archive} not found")
self._update(game_archive=game_archive)
# Update game version on local variable. # Update game version on local variable.
self._version = await self.get_game_version() self._version = await self.get_game_version()
self.set_version_config() self.set_version_config()
@ -443,7 +453,10 @@ class Installer:
# making this function universal for both cases # making this function universal for both cases
if not await self.get_game_data_path().exists(): if not await self.get_game_data_path().exists():
raise FileNotFoundError(f"Game not found in {self._gamedir}") raise FileNotFoundError(f"Game not found in {self._gamedir}")
await self._extract_game_file(voiceover_archive) if isinstance(voiceover_archive, str | Path):
voiceover_archive = Path(voiceover_archive).resolve()
await self._update(voiceover_archive)
# await self._extract_game_file(voiceover_archive)
async def install_game(self, game_archive: str | Path | AsyncPath, force_reinstall: bool = False): async def install_game(self, game_archive: str | Path | AsyncPath, force_reinstall: bool = False):
"""Installs the game to the current directory """Installs the game to the current directory