1
0
Fork 0
mirror of synced 2024-06-02 10:44:40 +12:00

Lgndr: Rename a few fields to reflect legendary's names

This commit is contained in:
loathingKernel 2022-08-08 21:06:58 +03:00
parent e97e9fe841
commit 5e022e6d28
6 changed files with 131 additions and 33 deletions

View file

@ -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
)

View file

@ -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:")

View file

@ -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

View file

@ -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

View file

@ -47,7 +47,7 @@ class InstallOptionsModel:
@dataclass
class InstallDownloadModel:
dlmanager: DLManager
dlm: DLManager
analysis: AnalysisResult
igame: InstalledGame
game: Game

View file

@ -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)