Lgndr: Rename a few fields to reflect legendary's names
This commit is contained in:
parent
e97e9fe841
commit
5e022e6d28
|
@ -138,7 +138,7 @@ class DownloadsTab(QWidget, Ui_DownloadsTab):
|
|||
self.active_game = queue_item.download.game
|
||||
self.thread = DownloadThread(self.core, queue_item)
|
||||
self.thread.exit_status.connect(self.status)
|
||||
self.thread.statistics.connect(self.statistics)
|
||||
self.thread.ui_update.connect(self.progress_update)
|
||||
self.thread.start()
|
||||
self.kill_button.setDisabled(False)
|
||||
self.analysis = queue_item.download.analysis
|
||||
|
@ -213,7 +213,7 @@ class DownloadsTab(QWidget, Ui_DownloadsTab):
|
|||
self.downloaded.setText("n/a")
|
||||
self.analysis = None
|
||||
|
||||
def statistics(self, ui_update: UIUpdate):
|
||||
def progress_update(self, ui_update: UIUpdate):
|
||||
self.progress_bar.setValue(
|
||||
100 * ui_update.total_downloaded // self.analysis.dl_size
|
||||
)
|
||||
|
|
|
@ -14,7 +14,7 @@ from rare.lgndr.api_monkeys import DLManagerSignals
|
|||
from rare.lgndr.cli import LegendaryCLI
|
||||
from rare.lgndr.downloading import UIUpdate
|
||||
from rare.models.install import InstallQueueItemModel
|
||||
from rare.shared import GlobalSignalsSingleton
|
||||
from rare.shared import GlobalSignalsSingleton, ArgumentsSingleton
|
||||
|
||||
logger = getLogger("DownloadThread")
|
||||
|
||||
|
@ -35,7 +35,7 @@ class DownloadThread(QThread):
|
|||
shortcuts: bool = False
|
||||
|
||||
exit_status = pyqtSignal(ExitStatus)
|
||||
statistics = pyqtSignal(UIUpdate)
|
||||
ui_update = pyqtSignal(UIUpdate)
|
||||
|
||||
def __init__(self, core: LegendaryCore, item: InstallQueueItemModel):
|
||||
super(DownloadThread, self).__init__()
|
||||
|
@ -45,46 +45,49 @@ class DownloadThread(QThread):
|
|||
self.dlm_signals: DLManagerSignals = DLManagerSignals()
|
||||
|
||||
def run(self):
|
||||
_exit_status = DownloadThread.ExitStatus(self.item.download.game.app_name, DownloadThread.ExitCode.ERROR)
|
||||
cli = LegendaryCLI(self.core)
|
||||
self.item.download.dlm.logging_queue = cli.logging_queue
|
||||
self.item.download.dlm.proc_debug = ArgumentsSingleton().debug
|
||||
exit_status = DownloadThread.ExitStatus(self.item.download.game.app_name, DownloadThread.ExitCode.ERROR)
|
||||
start_t = time.time()
|
||||
try:
|
||||
self.item.download.dlmanager.start()
|
||||
self.item.download.dlm.start()
|
||||
time.sleep(1)
|
||||
while self.item.download.dlmanager.is_alive():
|
||||
while self.item.download.dlm.is_alive():
|
||||
try:
|
||||
self.statistics.emit(self.item.download.dlmanager.status_queue.get(timeout=1.0))
|
||||
self.ui_update.emit(self.item.download.dlm.status_queue.get(timeout=1.0))
|
||||
except queue.Empty:
|
||||
pass
|
||||
if self.dlm_signals.update:
|
||||
try:
|
||||
self.item.download.dlmanager.signals_queue.put(self.dlm_signals, block=False, timeout=1.0)
|
||||
self.item.download.dlm.signals_queue.put(self.dlm_signals, block=False, timeout=1.0)
|
||||
except queue.Full:
|
||||
pass
|
||||
time.sleep(self.item.download.dlmanager.update_interval/10)
|
||||
self.item.download.dlmanager.join()
|
||||
time.sleep(self.item.download.dlm.update_interval / 10)
|
||||
self.item.download.dlm.join()
|
||||
except Exception as e:
|
||||
end_t = time.time()
|
||||
logger.error(f"Installation failed after {end_t - start_t:.02f} seconds.")
|
||||
logger.warning(f"The following exception occurred while waiting for the downloader to finish: {e!r}.")
|
||||
_exit_status.exit_code = DownloadThread.ExitCode.ERROR
|
||||
_exit_status.message = f"{e!r}"
|
||||
self.exit_status.emit(_exit_status)
|
||||
exit_status.exit_code = DownloadThread.ExitCode.ERROR
|
||||
exit_status.message = f"{e!r}"
|
||||
self.exit_status.emit(exit_status)
|
||||
return
|
||||
else:
|
||||
end_t = time.time()
|
||||
if self.dlm_signals.kill is True:
|
||||
logger.info(f"Download stopped after {end_t - start_t:.02f} seconds.")
|
||||
_exit_status.exit_code = DownloadThread.ExitCode.STOPPED
|
||||
self.exit_status.emit(_exit_status)
|
||||
exit_status.exit_code = DownloadThread.ExitCode.STOPPED
|
||||
self.exit_status.emit(exit_status)
|
||||
return
|
||||
logger.info(f"Download finished in {end_t - start_t:.02f} seconds.")
|
||||
|
||||
_exit_status.exit_code = DownloadThread.ExitCode.FINISHED
|
||||
exit_status.exit_code = DownloadThread.ExitCode.FINISHED
|
||||
|
||||
if self.item.options.overlay:
|
||||
self.signals.overlay_installation_finished.emit()
|
||||
self.core.finish_overlay_install(self.item.download.igame)
|
||||
self.exit_status.emit(_exit_status)
|
||||
self.exit_status.emit(exit_status)
|
||||
return
|
||||
|
||||
if not self.item.options.no_install:
|
||||
|
@ -101,14 +104,14 @@ class DownloadThread(QThread):
|
|||
dlcs = self.core.get_dlc_for_game(self.item.download.igame.app_name)
|
||||
if dlcs and not self.item.options.skip_dlcs:
|
||||
for dlc in dlcs:
|
||||
_exit_status.dlcs.append(
|
||||
exit_status.dlcs.append(
|
||||
{"app_name": dlc.app_name, "app_title": dlc.app_title, "app_version": dlc.app_version}
|
||||
)
|
||||
|
||||
if self.item.download.game.supports_cloud_saves and not self.item.download.game.is_dlc:
|
||||
_exit_status.sync_saves = True
|
||||
exit_status.sync_saves = True
|
||||
|
||||
LegendaryCLI(self.core).clean_post_install(
|
||||
LegendaryCLI(self.core).install_game_cleanup(
|
||||
self.item.download.game,
|
||||
self.item.download.igame,
|
||||
self.item.download.repair,
|
||||
|
@ -116,9 +119,9 @@ class DownloadThread(QThread):
|
|||
)
|
||||
|
||||
if not self.item.options.update and self.item.options.create_shortcut:
|
||||
_exit_status.shortcuts = True
|
||||
exit_status.shortcuts = True
|
||||
|
||||
self.exit_status.emit(_exit_status)
|
||||
self.exit_status.emit(exit_status)
|
||||
|
||||
def _handle_postinstall(self, postinstall, igame):
|
||||
logger.info("This game lists the following prequisites to be installed:")
|
||||
|
|
|
@ -76,8 +76,6 @@ class LgndrInstallGameArgs:
|
|||
reset_sdl: bool = False
|
||||
skip_sdl: bool = False
|
||||
disable_https: bool = False
|
||||
skip_dlcs: bool = False
|
||||
with_dlcs: bool = False
|
||||
yes: bool = True
|
||||
# Rare: Extra arguments
|
||||
indirect_status: LgndrIndirectStatus = LgndrIndirectStatus()
|
||||
|
@ -89,3 +87,20 @@ class LgndrInstallGameArgs:
|
|||
# if self.sdl_prompt is None:
|
||||
# self.sdl_prompt: Callable[[str, str], list] = \
|
||||
# lambda app_name, title: self.install_tag if self.install_tag is not None else [""]
|
||||
|
||||
|
||||
@dataclass
|
||||
class LgndrInstallGameRealArgs:
|
||||
app_name: str
|
||||
platform: str = "Windows"
|
||||
repair_mode: bool = False
|
||||
repair_file: str = ""
|
||||
no_install: bool = False
|
||||
save_path: str = ""
|
||||
skip_dlcs: bool = False
|
||||
with_dlcs: bool = False
|
||||
dlm_debug: bool = False
|
||||
yes: bool = True
|
||||
# Rare: Extra arguments
|
||||
indirect_status: LgndrIndirectStatus = LgndrIndirectStatus()
|
||||
get_boolean_choice: GetBooleanChoiceProtocol = get_boolean_choice
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
import time
|
||||
from typing import Optional, Union, Tuple
|
||||
|
||||
from legendary.cli import LegendaryCLI as LegendaryCLIReal
|
||||
|
@ -10,7 +10,13 @@ from legendary.models.game import Game, InstalledGame, VerifyResult
|
|||
from legendary.utils.lfs import validate_files
|
||||
from legendary.utils.selective_dl import get_sdl_appname
|
||||
|
||||
from .api_arguments import LgndrInstallGameArgs, LgndrImportGameArgs, LgndrVerifyGameArgs, LgndrUninstallGameArgs
|
||||
from .api_arguments import (
|
||||
LgndrInstallGameArgs,
|
||||
LgndrImportGameArgs,
|
||||
LgndrVerifyGameArgs,
|
||||
LgndrUninstallGameArgs,
|
||||
LgndrInstallGameRealArgs,
|
||||
)
|
||||
from .api_monkeys import LgndrIndirectStatus, LgndrIndirectLogger
|
||||
from .core import LegendaryCore
|
||||
from .manager import DLManager
|
||||
|
@ -24,6 +30,10 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
self.core = core
|
||||
self.logger = logging.getLogger('cli')
|
||||
self.logging_queue = None
|
||||
self.ql = self.setup_threaded_logging()
|
||||
|
||||
def __del__(self):
|
||||
self.ql.stop()
|
||||
|
||||
def resolve_aliases(self, name):
|
||||
return super(LegendaryCLI, self)._resolve_aliases(name)
|
||||
|
@ -178,7 +188,7 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
# game is either up-to-date or hasn't changed, so we have nothing to do
|
||||
if not analysis.dl_size:
|
||||
logger.info('Download size is 0, the game is either already up to date or has not changed. Exiting...')
|
||||
self.clean_post_install(game, igame, args.repair_mode, repair_file)
|
||||
self.install_game_cleanup(game, igame, args.repair_mode, repair_file)
|
||||
return
|
||||
|
||||
res = self.core.check_installation_conditions(analysis=analysis, install=igame, game=game,
|
||||
|
@ -187,12 +197,82 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
|
||||
return dlm, analysis, igame, game, args.repair_mode, repair_file, res
|
||||
|
||||
def clean_post_install(self, game: Game, igame: InstalledGame, repair: bool = False, repair_file: str = '') -> None:
|
||||
# Rare: This is currently handled in DownloadThread, this is a trial
|
||||
def install_game_real(self, args: LgndrInstallGameRealArgs, dlm: DLManager, game: Game, igame: InstalledGame) -> None:
|
||||
# Override logger for the local context to use message as part of the indirect return value
|
||||
logger = LgndrIndirectLogger(args.indirect_status, self.logger)
|
||||
get_boolean_choice = args.get_boolean_choice
|
||||
|
||||
start_t = time.time()
|
||||
|
||||
try:
|
||||
# set up logging stuff (should be moved somewhere else later)
|
||||
dlm.logging_queue = self.logging_queue
|
||||
dlm.proc_debug = args.dlm_debug
|
||||
|
||||
dlm.start()
|
||||
dlm.join()
|
||||
except Exception as e:
|
||||
end_t = time.time()
|
||||
logger.info(f'Installation failed after {end_t - start_t:.02f} seconds.')
|
||||
logger.warning(f'The following exception occurred while waiting for the downloader to finish: {e!r}. '
|
||||
f'Try restarting the process, the resume file will be used to start where it failed. '
|
||||
f'If it continues to fail please open an issue on GitHub.')
|
||||
else:
|
||||
end_t = time.time()
|
||||
if not args.no_install:
|
||||
# Allow setting savegame directory at install time so sync-saves will work immediately
|
||||
if (game.supports_cloud_saves or game.supports_mac_cloud_saves) and args.save_path:
|
||||
igame.save_path = args.save_path
|
||||
|
||||
postinstall = self.core.install_game(igame)
|
||||
if postinstall:
|
||||
self._handle_postinstall(postinstall, igame, yes=args.yes)
|
||||
|
||||
dlcs = self.core.get_dlc_for_game(game.app_name)
|
||||
if dlcs and not args.skip_dlcs:
|
||||
print('\nThe following DLCs are available for this game:')
|
||||
for dlc in dlcs:
|
||||
print(f' - {dlc.app_title} (App name: {dlc.app_name}, version: '
|
||||
f'{dlc.app_version(args.platform)})')
|
||||
print('\nYou can manually install these later by running this command with the DLC\'s app name.')
|
||||
|
||||
install_dlcs = not args.skip_dlcs
|
||||
if not args.yes and not args.with_dlcs and not args.skip_dlcs:
|
||||
if not get_boolean_choice(f'Do you wish to automatically install DLCs?'):
|
||||
install_dlcs = False
|
||||
|
||||
if install_dlcs:
|
||||
_yes, _app_name = args.yes, args.app_name
|
||||
args.yes = True
|
||||
for dlc in dlcs:
|
||||
args.app_name = dlc.app_name
|
||||
self.install_game(args)
|
||||
args.yes, args.app_name = _yes, _app_name
|
||||
else:
|
||||
print('')
|
||||
|
||||
if (game.supports_cloud_saves or game.supports_mac_cloud_saves) and not game.is_dlc:
|
||||
# todo option to automatically download saves after the installation
|
||||
# args does not have the required attributes for sync_saves in here,
|
||||
# not sure how to solve that elegantly.
|
||||
logger.info(f'This game supports cloud saves, syncing is handled by the "sync-saves" command. '
|
||||
f'To download saves for this game run "legendary sync-saves {args.app_name}"')
|
||||
|
||||
# show tip again after installation finishes so users hopefully actually see it
|
||||
if tip_url := self.core.get_game_tip(igame.app_name):
|
||||
print(f'\nThis game may require additional setup, see: {tip_url}\n')
|
||||
|
||||
self.install_game_cleanup(game, igame, args.repair_mode, args.repair_file)
|
||||
|
||||
logger.info(f'Finished installation process in {end_t - start_t:.02f} seconds.')
|
||||
|
||||
def install_game_cleanup(self, game: Game, igame: InstalledGame, repair_mode: bool = False, repair_file: str = '') -> None:
|
||||
# Override logger for the local context to use message as part of the indirect return value
|
||||
logger = LgndrIndirectLogger(LgndrIndirectStatus(), self.logger)
|
||||
|
||||
old_igame = self.core.get_installed_game(game.app_name)
|
||||
if old_igame and repair and os.path.exists(repair_file):
|
||||
if old_igame and repair_mode and os.path.exists(repair_file):
|
||||
if old_igame.needs_verification:
|
||||
old_igame.needs_verification = False
|
||||
self.core.install_game(old_igame)
|
||||
|
@ -207,7 +287,7 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
self.core.uninstall_tag(old_igame)
|
||||
self.core.install_game(old_igame)
|
||||
|
||||
def _handle_postinstall(self, postinstall, igame, yes=False, choice=False):
|
||||
def _handle_postinstall(self, postinstall, igame, yes=False, choice=True):
|
||||
# Override logger for the local context to use message as part of the indirect return value
|
||||
logger = LgndrIndirectLogger(LgndrIndirectStatus(), self.logger)
|
||||
# noinspection PyShadowingBuiltins
|
||||
|
|
|
@ -47,7 +47,7 @@ class InstallOptionsModel:
|
|||
|
||||
@dataclass
|
||||
class InstallDownloadModel:
|
||||
dlmanager: DLManager
|
||||
dlm: DLManager
|
||||
analysis: AnalysisResult
|
||||
igame: InstalledGame
|
||||
game: Game
|
||||
|
|
|
@ -129,6 +129,6 @@ class VerifyWorker(QRunnable):
|
|||
igame = self.core.get_installed_game(self.app_name)
|
||||
game = self.core.get_game(self.app_name, platform=igame.platform)
|
||||
repair_file = os.path.join(self.core.lgd.get_tmp_path(), f"{self.app_name}.repair")
|
||||
cli.clean_post_install(game=game, igame=igame, repair=True, repair_file=repair_file)
|
||||
cli.install_game_cleanup(game=game, igame=igame, repair_mode=True, repair_file=repair_file)
|
||||
|
||||
self.signals.result.emit(self.app_name, success, *result)
|
||||
|
|
Loading…
Reference in a new issue