From 5307932656872d82a6f7021c5edda55ff9c00183 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Mon, 29 May 2023 16:11:17 +0300 Subject: [PATCH] RareCore: Replace individual fetch workers with a single one. The workers where co-dependent anyways as the non-asset worker was started after the games worker had sent back its results. By combining them we can move any data manipulations to the worker and simplify the handling in RareCore. --- rare/shared/rare_core.py | 64 +++++++-------------------------- rare/shared/workers/__init__.py | 2 +- rare/shared/workers/fetch.py | 44 ++++++++++++++--------- 3 files changed, 41 insertions(+), 69 deletions(-) diff --git a/rare/shared/rare_core.py b/rare/shared/rare_core.py index 8b1b4d79..50be6226 100644 --- a/rare/shared/rare_core.py +++ b/rare/shared/rare_core.py @@ -4,7 +4,7 @@ import time from argparse import Namespace from itertools import chain from logging import getLogger -from typing import Dict, Iterator, Callable, Optional, List, Union, Iterable +from typing import Dict, Iterator, Callable, Optional, List, Union, Iterable, Tuple from PyQt5.QtCore import QObject, pyqtSignal, QSettings, pyqtSlot, QThreadPool, QRunnable, QTimer from legendary.lfs.eos import EOSOverlayApp @@ -21,8 +21,6 @@ from .workers import ( VerifyWorker, MoveWorker, FetchWorker, - GamesWorker, - NonAssetWorker, OriginWineWorker, ) from .workers.uninstall import uninstall_game @@ -52,11 +50,6 @@ class RareCore(QObject): self.__image_manager: Optional[ImageManager] = None self.__start_time = time.time() - self.__fetched_games: List = [] - self.__fetched_dlcs: Dict = {} - - self.__games_fetched: bool = False - self.__non_asset_fetched: bool = False self.args(args) self.signals(init=True) @@ -270,54 +263,21 @@ class RareCore(QObject): self.progress.emit(int(idx/length * 80) + 20, self.tr("Loaded {}").format(rgame.app_title)) @pyqtSlot(object, int) - def handle_result(self, result: object, res_type: int): - status = "" - if res_type == FetchWorker.Result.GAMES: - games, dlc_dict = result - self.__fetched_games += games - self.__fetched_dlcs.update(dlc_dict) - self.fetch_non_asset() - self.__games_fetched = True - status = self.tr("Prepared games") - if res_type == FetchWorker.Result.NON_ASSET: - games, dlc_dict = result - self.__fetched_games += games - for catalog_id, dlcs in dlc_dict.items(): - if catalog_id in self.__fetched_dlcs.keys(): - self.__fetched_dlcs[catalog_id] += dlcs - else: - self.__fetched_dlcs[catalog_id] = dlcs - self.__non_asset_fetched = True - status = self.tr("Prepared games without assets") + def __on_fetch_result(self, result: Tuple[List, Dict], res_type: int): logger.info(f"Got API results for {FetchWorker.Result(res_type).name}") - - fetched = [ - self.__games_fetched, - self.__non_asset_fetched, - ] - - self.progress.emit(sum(fetched) * 10, status) - - if all(fetched): - self.__add_games_and_dlcs(self.__fetched_games, self.__fetched_dlcs) - self.progress.emit(100, self.tr("Launching Rare")) - logger.debug(f"Fetch time {time.time() - self.__start_time} seconds") - QTimer.singleShot(100, self.__post_init) - self.completed.emit() + self.progress.emit(15, self.tr("Preparing library")) + self.__add_games_and_dlcs(*result) + self.progress.emit(100, self.tr("Launching Rare")) + logger.debug(f"Fetch time {time.time() - self.__start_time} seconds") + QTimer.singleShot(100, self.__post_init) + self.completed.emit() def fetch(self): - self.__games_fetched: bool = False - self.__non_asset_fetched: bool = False self.__start_time = time.time() - - games_worker = GamesWorker(self.__core, self.__args) - games_worker.signals.result.connect(self.handle_result) - QThreadPool.globalInstance().start(games_worker) - - def fetch_non_asset(self): - non_asset_worker = NonAssetWorker(self.__core, self.__args) - non_asset_worker.signals.result.connect(self.handle_result) - QThreadPool.globalInstance().start(non_asset_worker) + fetch_worker = FetchWorker(self.__core, self.__args) + fetch_worker.signals.progress.connect(self.progress) + fetch_worker.signals.result.connect(self.__on_fetch_result) + QThreadPool.globalInstance().start(fetch_worker) def fetch_saves(self): def __fetch() -> None: diff --git a/rare/shared/workers/__init__.py b/rare/shared/workers/__init__.py index a5b8cd46..b11df089 100644 --- a/rare/shared/workers/__init__.py +++ b/rare/shared/workers/__init__.py @@ -1,4 +1,4 @@ -from .fetch import FetchWorker, GamesWorker, NonAssetWorker +from .fetch import FetchWorker from .install_info import InstallInfoWorker from .move import MoveWorker from .uninstall import UninstallWorker diff --git a/rare/shared/workers/fetch.py b/rare/shared/workers/fetch.py index e1abe669..701e1890 100644 --- a/rare/shared/workers/fetch.py +++ b/rare/shared/workers/fetch.py @@ -16,8 +16,10 @@ class FetchWorker(Worker): class Result(IntEnum): GAMES = 1 NON_ASSET = 2 + COMBINED = 3 class Signals(QObject): + progress = pyqtSignal(int, str) result = pyqtSignal(object, int) def __init__(self, core: LegendaryCore, args: Namespace): @@ -26,33 +28,43 @@ class FetchWorker(Worker): self.core = core self.args = args - -class GamesWorker(FetchWorker): def run_real(self): + # Fetch regular EGL games with assets + self.signals.progress.emit(0, self.signals.tr("Updating game metadata")) start_time = time.time() - result = self.core.get_game_and_dlc_list(update_assets=not self.args.offline, platform="Windows", skip_ue=False) - self.signals.result.emit(result, FetchWorker.Result.GAMES) - logger.debug(f"Games: {len(result[0])}, DLCs {len(result[1])}") - logger.debug(f"Request Games: {time.time() - start_time} seconds") + games, dlc_dict = self.core.get_game_and_dlc_list( + update_assets=not self.args.offline, platform="Windows", skip_ue=False + ) + logger.debug(f"Games {len(games)}, games with DLCs {len(dlc_dict)}") + logger.debug(f"Request games: {time.time() - start_time} seconds") - -class NonAssetWorker(FetchWorker): - def run_real(self): + # Fetch non-asset games + self.signals.progress.emit(10, self.signals.tr("Updating non-asset metadata")) start_time = time.time() try: - result = self.core.get_non_asset_library_items(force_refresh=False, skip_ue=False) + na_games, na_dlc_dict = self.core.get_non_asset_library_items(force_refresh=False, skip_ue=False) except (HTTPError, ConnectionError) as e: logger.warning(f"Exception while fetching non asset games from EGS: {e}") - result = ([], {}) + na_games, na_dlc_dict = ([], {}) # FIXME: # This is here because of broken appIds from Epic: # https://discord.com/channels/826881530310819914/884510635642216499/1111321692703305729 # There is a tab character in the appId of Fallout New Vegas: Honest Hearts DLC, this breaks metadata storage # on Windows as they can't handle tabs at the end of the filename (?) - # Legendary and Heroic are also affected, but it completed breaks Rare, so dodge it for now pending a fix. + # Legendary and Heroic are also affected, but it completely breaks Rare, so dodge it for now pending a fix. except Exception as e: logger.error(f"Exception while fetching non asset games from EGS: {e}") - result = ([], {}) - self.signals.result.emit(result, FetchWorker.Result.NON_ASSET) - logger.debug(f"Non asset: {len(result[0])}, DLCs {len(result[1])}") - logger.debug(f"Request Non Asset: {time.time() - start_time} seconds") + na_games, na_dlc_dict = ([], {}) + logger.debug(f"Non-asset {len(na_games)}, games with non-asset DLCs {len(na_dlc_dict)}") + logger.debug(f"Request non-asset: {time.time() - start_time} seconds") + + # Combine the two games lists and the two dlc dictionaries between regular and non-asset results + games += na_games + for catalog_id, dlcs in na_dlc_dict.items(): + if catalog_id in dlc_dict.keys(): + dlc_dict[catalog_id] += dlcs + else: + dlc_dict[catalog_id] = dlcs + logger.debug(f"Games {len(games)}, games with DLCs {len(dlc_dict)}") + + self.signals.result.emit((games, dlc_dict), FetchWorker.Result.COMBINED)