Compare commits
10 Commits
5a6f8e39af
...
efc7ff2be9
Author | SHA1 | Date | |
---|---|---|---|
efc7ff2be9 | |||
5e46b23752 | |||
973ae2a5e6 | |||
aa4fe4d5ed | |||
836c843b2e | |||
0af4c4f2df | |||
a6600cf573 | |||
305021d8b7 | |||
2d5c75109a | |||
45006ef4b5 |
2
setup.py
2
setup.py
@ -10,7 +10,7 @@ README = (HERE / "README.md").read_text()
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='worthless',
|
name='worthless',
|
||||||
version='2.2.16',
|
version='2.2.20',
|
||||||
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',
|
||||||
|
@ -4,4 +4,4 @@ Launcher = launcher.Launcher
|
|||||||
Installer = installer.Installer
|
Installer = installer.Installer
|
||||||
|
|
||||||
|
|
||||||
__version__ = "2.2.16"
|
__version__ = "2.2.20"
|
||||||
|
0
worthless/__main__.py
Executable file → Normal file
0
worthless/__main__.py
Executable file → Normal file
@ -9,7 +9,6 @@ from configparser import ConfigParser
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from aiopath import AsyncPath
|
|
||||||
|
|
||||||
from worthless import constants
|
from worthless import constants
|
||||||
from worthless.launcher import Launcher
|
from worthless.launcher import Launcher
|
||||||
@ -25,16 +24,16 @@ async def _download_file(file_url: str, file_name: str, file_path: Path | str, f
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
headers = {}
|
headers = {}
|
||||||
file_path = AsyncPath(file_path).joinpath(file_name)
|
file_path = Path(file_path).joinpath(file_name)
|
||||||
if overwrite:
|
if overwrite:
|
||||||
await file_path.unlink(missing_ok=True)
|
await file_path.unlink(missing_ok=True)
|
||||||
if await file_path.exists():
|
if file_path.exists():
|
||||||
cur_len = (await file_path.stat()).st_size
|
cur_len = (file_path.stat()).st_size
|
||||||
headers |= {
|
headers |= {
|
||||||
"Range": f"bytes={cur_len}-{file_len if file_len else ''}"
|
"Range": f"bytes={cur_len}-{file_len if file_len else ''}"
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
await file_path.touch()
|
file_path.touch()
|
||||||
print(f"Downloading {file_url} to {file_path}...")
|
print(f"Downloading {file_url} to {file_path}...")
|
||||||
async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=60*60, sock_read=240)) as session:
|
async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=60*60, sock_read=240)) as session:
|
||||||
rsp = await session.get(file_url, headers=headers, timeout=None)
|
rsp = await session.get(file_url, headers=headers, timeout=None)
|
||||||
@ -46,8 +45,8 @@ async def _download_file(file_url: str, file_name: str, file_path: Path | str, f
|
|||||||
await asyncio.sleep(0)
|
await asyncio.sleep(0)
|
||||||
if not chunk:
|
if not chunk:
|
||||||
break
|
break
|
||||||
async with file_path.open("ab") as f:
|
with file_path.open("ab") as f:
|
||||||
await f.write(chunk)
|
f.write(chunk)
|
||||||
|
|
||||||
|
|
||||||
def calculate_md5(file_to_calculate):
|
def calculate_md5(file_to_calculate):
|
||||||
@ -167,17 +166,17 @@ class HDiffPatch:
|
|||||||
|
|
||||||
|
|
||||||
class Installer:
|
class Installer:
|
||||||
def __init__(self, gamedir: str | Path | AsyncPath = AsyncPath.cwd(),
|
def __init__(self, gamedir: str | Path = Path.cwd(),
|
||||||
overseas: bool = True, data_dir: str | Path | AsyncPath = None):
|
overseas: bool = True, data_dir: str | Path = None):
|
||||||
if isinstance(gamedir, str | Path):
|
if isinstance(gamedir, str | Path):
|
||||||
gamedir = AsyncPath(gamedir)
|
gamedir = Path(gamedir)
|
||||||
self._gamedir = gamedir
|
self._gamedir = gamedir
|
||||||
if not data_dir:
|
if not data_dir:
|
||||||
self._appdirs = constants.APPDIRS
|
self._appdirs = constants.APPDIRS
|
||||||
self.temp_path = AsyncPath(self._appdirs.user_cache_dir).joinpath("Installer")
|
self.temp_path = Path(self._appdirs.user_cache_dir).joinpath("Installer")
|
||||||
else:
|
else:
|
||||||
if isinstance(data_dir, str | AsyncPath):
|
if isinstance(data_dir, str | Path):
|
||||||
data_dir = AsyncPath(data_dir)
|
data_dir = Path(data_dir)
|
||||||
self.temp_path = data_dir.joinpath("Temp/Installer/")
|
self.temp_path = data_dir.joinpath("Temp/Installer/")
|
||||||
Path(self.temp_path).mkdir(parents=True, exist_ok=True)
|
Path(self.temp_path).mkdir(parents=True, exist_ok=True)
|
||||||
config_file = self._gamedir.joinpath("config.ini")
|
config_file = self._gamedir.joinpath("config.ini")
|
||||||
@ -201,13 +200,13 @@ class Installer:
|
|||||||
chunks=self._download_chunk)
|
chunks=self._download_chunk)
|
||||||
|
|
||||||
async def read_version_from_config(self):
|
async def read_version_from_config(self):
|
||||||
if not await self._config_file.exists():
|
if not self._config_file.exists():
|
||||||
raise FileNotFoundError(f"Config file {self._config_file} not found")
|
raise FileNotFoundError(f"Config file {self._config_file} not found")
|
||||||
cfg = ConfigParser()
|
cfg = ConfigParser()
|
||||||
await asyncio.to_thread(cfg.read, str(self._config_file))
|
await asyncio.to_thread(cfg.read, str(self._config_file))
|
||||||
return cfg.get("General", "game_version")
|
return cfg.get("General", "game_version")
|
||||||
|
|
||||||
async def read_version_from_game_file(self, globalgamemanagers: AsyncPath | Path | bytes) -> str:
|
async def read_version_from_game_file(self, globalgamemanagers: Path | Path | bytes) -> str:
|
||||||
"""
|
"""
|
||||||
Reads the version from the globalgamemanagers file. (Data/globalgamemanagers)
|
Reads the version from the globalgamemanagers file. (Data/globalgamemanagers)
|
||||||
|
|
||||||
@ -216,9 +215,9 @@ class Installer:
|
|||||||
|
|
||||||
:return: Game version (ex 1.0.0)
|
:return: Game version (ex 1.0.0)
|
||||||
"""
|
"""
|
||||||
if isinstance(globalgamemanagers, Path | AsyncPath):
|
if isinstance(globalgamemanagers, Path | Path):
|
||||||
globalgamemanagers = AsyncPath(globalgamemanagers)
|
globalgamemanagers = Path(globalgamemanagers)
|
||||||
data = await globalgamemanagers.read_text("ascii", errors="ignore")
|
data = globalgamemanagers.read_text("ascii", errors="ignore")
|
||||||
else:
|
else:
|
||||||
data = globalgamemanagers.decode("ascii", errors="ignore")
|
data = globalgamemanagers.decode("ascii", errors="ignore")
|
||||||
result = self._game_version_re.search(data)
|
result = self._game_version_re.search(data)
|
||||||
@ -258,7 +257,7 @@ class Installer:
|
|||||||
return lang
|
return lang
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def get_voiceover_archive_language(voiceover_archive: str | Path | AsyncPath) -> str:
|
async def get_voiceover_archive_language(voiceover_archive: str | Path | Path) -> str:
|
||||||
if isinstance(voiceover_archive, str | Path):
|
if isinstance(voiceover_archive, str | Path):
|
||||||
voiceover_archive = Path(voiceover_archive).resolve()
|
voiceover_archive = Path(voiceover_archive).resolve()
|
||||||
if not voiceover_archive.exists():
|
if not voiceover_archive.exists():
|
||||||
@ -293,7 +292,7 @@ class Installer:
|
|||||||
else:
|
else:
|
||||||
return "YuanShen_Data/"
|
return "YuanShen_Data/"
|
||||||
|
|
||||||
def get_game_data_path(self) -> AsyncPath:
|
def get_game_data_path(self) -> Path:
|
||||||
return self._gamedir.joinpath(self.get_game_data_name())
|
return self._gamedir.joinpath(self.get_game_data_name())
|
||||||
|
|
||||||
async def get_game_archive_version(self, game_archive: str | Path):
|
async def get_game_archive_version(self, game_archive: str | Path):
|
||||||
@ -307,7 +306,7 @@ class Installer:
|
|||||||
|
|
||||||
async def get_game_version(self) -> str | None:
|
async def get_game_version(self) -> str | None:
|
||||||
globalgamemanagers = self.get_game_data_path().joinpath("./globalgamemanagers")
|
globalgamemanagers = self.get_game_data_path().joinpath("./globalgamemanagers")
|
||||||
if not await globalgamemanagers.exists():
|
if not globalgamemanagers.exists():
|
||||||
try:
|
try:
|
||||||
return await self.read_version_from_config()
|
return await self.read_version_from_config()
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
@ -323,11 +322,11 @@ class Installer:
|
|||||||
voiceovers = []
|
voiceovers = []
|
||||||
async for file in self.get_game_data_path()\
|
async for file in self.get_game_data_path()\
|
||||||
.joinpath("StreamingAssets/AudioAssets/").iterdir():
|
.joinpath("StreamingAssets/AudioAssets/").iterdir():
|
||||||
if await file.is_dir():
|
if file.is_dir():
|
||||||
voiceovers.append(file.name)
|
voiceovers.append(file.name)
|
||||||
return voiceovers
|
return voiceovers
|
||||||
|
|
||||||
async def _update(self, game_archive: str | Path | AsyncPath):
|
async def _update(self, game_archive: str | Path | Path):
|
||||||
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():
|
||||||
@ -343,6 +342,22 @@ class Installer:
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
deletefiles = archive.read("deletefiles.txt").decode().split("\r\n")
|
||||||
|
for file in deletefiles:
|
||||||
|
current_game_file = Path(self._gamedir).joinpath(file)
|
||||||
|
if current_game_file == Path(self._gamedir):
|
||||||
|
# Don't delete the game folder
|
||||||
|
print("Game folder detected, not deleting:", current_game_file)
|
||||||
|
continue
|
||||||
|
if not current_game_file.relative_to(Path(self._gamedir)):
|
||||||
|
print("Not deleting (not relative to game):", current_game_file)
|
||||||
|
continue
|
||||||
|
print("Deleting", file)
|
||||||
|
current_game_file.unlink(missing_ok=True)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error while reading deletefiles.txt: {e}")
|
||||||
|
|
||||||
# hdiffpatch implementation
|
# hdiffpatch implementation
|
||||||
try:
|
try:
|
||||||
hdifffiles = []
|
hdifffiles = []
|
||||||
@ -354,7 +369,7 @@ class Installer:
|
|||||||
count = 0
|
count = 0
|
||||||
for file in hdifffiles:
|
for file in hdifffiles:
|
||||||
current_game_file = self._gamedir.joinpath(file)
|
current_game_file = self._gamedir.joinpath(file)
|
||||||
if not await current_game_file.exists():
|
if not current_game_file.exists():
|
||||||
print("File", file, "not found")
|
print("File", file, "not found")
|
||||||
# Not patching since we don't have the file
|
# Not patching since we don't have the file
|
||||||
continue
|
continue
|
||||||
@ -371,18 +386,18 @@ class Installer:
|
|||||||
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 = 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()
|
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))
|
old_file.rename(old_file.with_suffix(old_suffix))
|
||||||
|
|
||||||
files.remove(patch_file)
|
files.remove(patch_file)
|
||||||
# Limit to 8 process running so it doesn't hang the PC.
|
# Limit to 8 process running so it doesn't hang the PC.
|
||||||
@ -403,24 +418,11 @@ class Installer:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error while reading hdifffiles.txt: {e}")
|
print(f"Error while reading hdifffiles.txt: {e}")
|
||||||
|
|
||||||
try:
|
|
||||||
deletefiles = archive.read("deletefiles.txt").decode().split("\n")
|
|
||||||
for file in deletefiles:
|
|
||||||
current_game_file = Path(self._gamedir.joinpath(file))
|
|
||||||
if current_game_file == Path(self._gamedir):
|
|
||||||
continue
|
|
||||||
if not current_game_file.is_file():
|
|
||||||
continue
|
|
||||||
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):
|
async def update_game(self, game_archive: str | Path | Path):
|
||||||
if not await self.get_game_data_path().exists():
|
if not self.get_game_data_path().exists():
|
||||||
raise FileNotFoundError(f"Game not found in {self._gamedir}")
|
raise FileNotFoundError(f"Game not found in {self._gamedir}")
|
||||||
if isinstance(game_archive, str | Path):
|
if isinstance(game_archive, str | Path):
|
||||||
game_archive = Path(game_archive).resolve()
|
game_archive = Path(game_archive).resolve()
|
||||||
@ -440,10 +442,24 @@ class Installer:
|
|||||||
|
|
||||||
async def download_full_game(self, pre_download=False):
|
async def download_full_game(self, pre_download=False):
|
||||||
game = await self._get_game(pre_download)
|
game = await self._get_game(pre_download)
|
||||||
|
if not game.latest.path == "":
|
||||||
archive_name = game.latest.path.split("/")[-1]
|
archive_name = game.latest.path.split("/")[-1]
|
||||||
await self._download_file(game.latest.path, archive_name, game.latest.size)
|
|
||||||
if calculate_md5(self.temp_path.joinpath(archive_name)) != game.latest.md5:
|
if calculate_md5(self.temp_path.joinpath(archive_name)) != game.latest.md5:
|
||||||
raise RuntimeError("mismatch md5 for downloaded game archive")
|
raise RuntimeError("mismatch md5 for downloaded game archive")
|
||||||
|
return
|
||||||
|
# Segment download
|
||||||
|
base_archive = None
|
||||||
|
for i, segment in enumerate(game.latest.segments):
|
||||||
|
archive_name = segment["path"].split("/")[-1]
|
||||||
|
if i == 0:
|
||||||
|
base_archive = archive_name = Path(archive_name).stem # Remove .001
|
||||||
|
await self._download_file(segment["path"], archive_name)
|
||||||
|
if i != 0:
|
||||||
|
with open(self.temp_path.joinpath(base_archive), 'ab') as f:
|
||||||
|
with open(self.temp_path.joinpath(archive_name), 'rb') as f2:
|
||||||
|
f.write(f2.read())
|
||||||
|
self.temp_path.joinpath(archive_name).unlink()
|
||||||
|
|
||||||
|
|
||||||
async def download_full_voiceover(self, language: str, pre_download=False):
|
async def download_full_voiceover(self, language: str, pre_download=False):
|
||||||
game = await self._get_game(pre_download)
|
game = await self._get_game(pre_download)
|
||||||
@ -455,8 +471,8 @@ class Installer:
|
|||||||
async def uninstall_game(self):
|
async def uninstall_game(self):
|
||||||
await asyncio.to_thread(shutil.rmtree, self._gamedir, ignore_errors=True)
|
await asyncio.to_thread(shutil.rmtree, self._gamedir, ignore_errors=True)
|
||||||
|
|
||||||
async def _extract_game_file(self, archive: str | Path | AsyncPath):
|
async def _extract_game_file(self, archive: str | Path | Path):
|
||||||
if isinstance(archive, str | AsyncPath):
|
if isinstance(archive, str | Path):
|
||||||
archive = Path(archive).resolve()
|
archive = Path(archive).resolve()
|
||||||
if not archive.exists():
|
if not archive.exists():
|
||||||
raise FileNotFoundError(f"'{archive}' not found")
|
raise FileNotFoundError(f"'{archive}' not found")
|
||||||
@ -467,24 +483,24 @@ class Installer:
|
|||||||
# Since Voiceover packages are unclear about diff package or full package
|
# Since Voiceover packages are unclear about diff package or full package
|
||||||
# we will try to extract the voiceover package and apply it to the game
|
# we will try to extract the voiceover package and apply it to the game
|
||||||
# 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 self.get_game_data_path().exists():
|
||||||
raise FileNotFoundError(f"Game not found in {self._gamedir}")
|
raise FileNotFoundError(f"Game not found in {self._gamedir}")
|
||||||
if isinstance(voiceover_archive, str | Path):
|
if isinstance(voiceover_archive, str | Path):
|
||||||
voiceover_archive = Path(voiceover_archive).resolve()
|
voiceover_archive = Path(voiceover_archive).resolve()
|
||||||
await self._update(voiceover_archive)
|
await self._update(voiceover_archive)
|
||||||
# await self._extract_game_file(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 | Path, force_reinstall: bool = False):
|
||||||
"""Installs the game to the current directory
|
"""Installs the game to the current directory
|
||||||
|
|
||||||
If `force_reinstall` is True, the game will be uninstalled then reinstalled.
|
If `force_reinstall` is True, the game will be uninstalled then reinstalled.
|
||||||
"""
|
"""
|
||||||
if await self.get_game_data_path().exists():
|
if self.get_game_data_path().exists():
|
||||||
if not force_reinstall:
|
if not force_reinstall:
|
||||||
raise ValueError(f"Game is already installed in {self._gamedir}")
|
raise ValueError(f"Game is already installed in {self._gamedir}")
|
||||||
await self.uninstall_game()
|
await self.uninstall_game()
|
||||||
|
|
||||||
await self._gamedir.mkdir(parents=True, exist_ok=True)
|
self._gamedir.mkdir(parents=True, exist_ok=True)
|
||||||
await self._extract_game_file(game_archive)
|
await self._extract_game_file(game_archive)
|
||||||
self._version = await self.get_game_version()
|
self._version = await self.get_game_version()
|
||||||
self.set_version_config()
|
self.set_version_config()
|
||||||
@ -556,8 +572,8 @@ class Installer:
|
|||||||
if v.version == from_version:
|
if v.version == from_version:
|
||||||
return v
|
return v
|
||||||
|
|
||||||
async def verify_from_pkg_version(self, pkg_version: AsyncPath, ignore_mismatch=False):
|
async def verify_from_pkg_version(self, pkg_version: Path, ignore_mismatch=False):
|
||||||
contents = await pkg_version.read_text()
|
contents = pkg_version.read_text()
|
||||||
|
|
||||||
async def verify_file(file_to_verify, md5):
|
async def verify_file(file_to_verify, md5):
|
||||||
print("Verifying file:", file_to_verify)
|
print("Verifying file:", file_to_verify)
|
||||||
@ -593,7 +609,7 @@ class Installer:
|
|||||||
|
|
||||||
return None if not failed_files else failed_files
|
return None if not failed_files else failed_files
|
||||||
|
|
||||||
async def verify_game(self, pkg_version: str | Path | AsyncPath = None, ignore_mismatch=False):
|
async def verify_game(self, pkg_version: str | Path | Path = None, ignore_mismatch=False):
|
||||||
if pkg_version is None:
|
if pkg_version is None:
|
||||||
pkg_version = self._gamedir.joinpath("pkg_version")
|
pkg_version = self._gamedir.joinpath("pkg_version")
|
||||||
return await self.verify_from_pkg_version(pkg_version, ignore_mismatch)
|
return await self.verify_from_pkg_version(pkg_version, ignore_mismatch)
|
||||||
|
@ -237,13 +237,19 @@ class Patcher:
|
|||||||
disable_files = [
|
disable_files = [
|
||||||
self._installer.get_game_data_name() + "upload_crash.exe",
|
self._installer.get_game_data_name() + "upload_crash.exe",
|
||||||
self._installer.get_game_data_name() + "Plugins/crashreport.exe",
|
self._installer.get_game_data_name() + "Plugins/crashreport.exe",
|
||||||
self._installer.get_game_data_name() + "Plugins/blueReporter.exe",
|
self._installer.get_game_data_name() + "blueReporter.exe",
|
||||||
]
|
]
|
||||||
for file in disable_files:
|
for file in disable_files:
|
||||||
file_path = Path(self._gamedir.joinpath(file)).resolve()
|
file_path = Path(self._gamedir.joinpath(file)).resolve()
|
||||||
if file_path.exists():
|
if file_path.exists():
|
||||||
await AsyncPath(file_path).rename(str(file_path) + ".bak")
|
await AsyncPath(file_path).rename(str(file_path) + ".bak")
|
||||||
|
|
||||||
|
# Delete old Telemetry.dll on Linux (cAsE sEnsItIvE)
|
||||||
|
if platform.system() == "Linux":
|
||||||
|
telemetry_path = Path(self._installer.get_game_data_name()).joinpath("Plugins/Telemetry.dll")
|
||||||
|
if telemetry_path.exists() and Path(self._installer.get_game_data_name()).joinpath("Plugins/telemetry.dll").exists():
|
||||||
|
await telemetry_path.unlink()
|
||||||
|
|
||||||
patch_jobs.append(disable_crashreporters())
|
patch_jobs.append(disable_crashreporters())
|
||||||
await asyncio.gather(*patch_jobs)
|
await asyncio.gather(*patch_jobs)
|
||||||
|
|
||||||
@ -291,6 +297,7 @@ class Patcher:
|
|||||||
self._installer.get_game_data_name() + "upload_crash.exe",
|
self._installer.get_game_data_name() + "upload_crash.exe",
|
||||||
self._installer.get_game_data_name() + "Plugins/crashreport.exe",
|
self._installer.get_game_data_name() + "Plugins/crashreport.exe",
|
||||||
self._installer.get_game_data_name() + "Plugins/xlua.dll",
|
self._installer.get_game_data_name() + "Plugins/xlua.dll",
|
||||||
|
self._installer.get_game_data_name() + "blueReporter.exe",
|
||||||
]
|
]
|
||||||
revert_job = []
|
revert_job = []
|
||||||
for file in revert_files:
|
for file in revert_files:
|
||||||
|
Loading…
Reference in New Issue
Block a user