diff --git a/rare/components/__init__.py b/rare/components/__init__.py
index e76dacf1..f4c9cce4 100644
--- a/rare/components/__init__.py
+++ b/rare/components/__init__.py
@@ -12,7 +12,7 @@ from requests import HTTPError
from rare.components.dialogs.launch_dialog import LaunchDialog
from rare.components.main_window import MainWindow
from rare.shared import RareCore
-from rare.utils import config_helper, paths
+from rare.utils import paths
from rare.utils.misc import ExitCodes
from rare.widgets.rare_app import RareApp, RareAppException
diff --git a/rare/shared/rare_core.py b/rare/shared/rare_core.py
index 3582304a..9afcaac2 100644
--- a/rare/shared/rare_core.py
+++ b/rare/shared/rare_core.py
@@ -16,12 +16,15 @@ from rare.models.base_game import RareSaveGame
from rare.models.game import RareGame, RareEosOverlay
from rare.models.signals import GlobalSignals
from rare.utils.metrics import timelogger
+from rare.utils import config_helper
from .image_manager import ImageManager
from .workers import (
QueueWorker,
VerifyWorker,
MoveWorker,
FetchWorker,
+ GamesDlcsWorker,
+ EntitlementsWorker,
OriginWineWorker,
)
from .workers.uninstall import uninstall_game
@@ -70,6 +73,10 @@ class RareCore(QObject):
self.__eos_overlay.signals.game.install.connect(self.__signals.game.install)
self.__eos_overlay.signals.game.uninstall.connect(self.__signals.game.uninstall)
+ self.__fetch_progress: int = 0
+ self.__fetched_games_dlcs: bool = False
+ self.__fetched_entitlements: bool = False
+
RareCore.__instance = self
def enqueue_worker(self, rgame: RareGame, worker: QueueWorker):
@@ -303,24 +310,45 @@ class RareCore(QObject):
logger.info(f'Marking "{rgame.app_title}" as not installed because an exception has occurred...')
logger.error(e)
rgame.set_installed(False)
- self.progress.emit(int(idx/length * 80) + 20, self.tr("Loaded {}").format(rgame.app_title))
+ progress = int(idx/length * self.__fetch_progress) + (100 - self.__fetch_progress)
+ self.progress.emit(progress, self.tr("Loaded {}").format(rgame.app_title))
+
+ @pyqtSlot(int, str)
+ def __on_fetch_progress(self, increment: int, message: str):
+ self.__fetch_progress += increment
+ self.progress.emit(self.__fetch_progress, message)
@pyqtSlot(object, int)
- def __on_fetch_result(self, result: Tuple[List, Dict], res_type: int):
- logger.info(f"Got API results for {FetchWorker.Result(res_type).name}")
- 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.perf_counter() - self.__start_time} seconds")
- QTimer.singleShot(100, self.__post_init)
- self.completed.emit()
+ def __on_fetch_result(self, result: Tuple, result_type: int):
+ if result_type == FetchWorker.Result.GAMESDLCS:
+ self.__add_games_and_dlcs(*result)
+ self.__fetched_games_dlcs = True
+
+ if result_type == FetchWorker.Result.ENTITLEMENTS:
+ self.__core.lgd.entitlements = result
+ self.__fetched_entitlements = True
+
+ logger.info(f"Acquired data for {FetchWorker.Result(result_type).name}")
+
+ if all([self.__fetched_games_dlcs, self.__fetched_entitlements]):
+ logger.debug(f"Fetch time {time.perf_counter() - self.__start_time} seconds")
+ self.progress.emit(100, self.tr("Launching Rare"))
+ self.completed.emit()
+ QTimer.singleShot(100, self.__post_init)
def fetch(self):
self.__start_time = time.perf_counter()
- 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)
+
+ games_dlcs_worker = GamesDlcsWorker(self.__core, self.__args)
+ games_dlcs_worker.signals.progress.connect(self.__on_fetch_progress)
+ games_dlcs_worker.signals.result.connect(self.__on_fetch_result)
+
+ entitlements_worker = EntitlementsWorker(self.__core, self.__args)
+ entitlements_worker.signals.progress.connect(self.__on_fetch_progress)
+ entitlements_worker.signals.result.connect(self.__on_fetch_result)
+
+ QThreadPool.globalInstance().start(games_dlcs_worker)
+ QThreadPool.globalInstance().start(entitlements_worker)
def fetch_saves(self):
def __fetch() -> None:
@@ -346,24 +374,6 @@ class RareCore(QObject):
saves_worker = QRunnable.create(__fetch)
QThreadPool.globalInstance().start(saves_worker)
- def fetch_entitlements(self) -> None:
- def __fetch() -> None:
- try:
- if (entitlements := self.__core.lgd.entitlements) is None:
- with timelogger(logger, "Request entitlements"):
- entitlements = self.__core.egs.get_user_entitlements()
- self.__core.lgd.entitlements = entitlements
- for game in self.__library.values():
- game.grant_date()
- except (HTTPError, ConnectionError) as e:
- logger.error(f"Exception while fetching entitlements from EGS.")
- logger.error(e)
- return
- logger.info(f"Entitlements: {len(list(entitlements))}")
-
- entitlements_worker = QRunnable.create(__fetch)
- QThreadPool.globalInstance().start(entitlements_worker)
-
def resolve_origin(self) -> None:
origin_worker = OriginWineWorker(self.__core, list(self.origin_games))
QThreadPool.globalInstance().start(origin_worker)
@@ -371,7 +381,6 @@ class RareCore(QObject):
def __post_init(self) -> None:
if not self.__args.offline:
self.fetch_saves()
- # self.fetch_entitlements()
self.resolve_origin()
@property
diff --git a/rare/shared/workers/__init__.py b/rare/shared/workers/__init__.py
index b11df089..12d816c0 100644
--- a/rare/shared/workers/__init__.py
+++ b/rare/shared/workers/__init__.py
@@ -1,4 +1,4 @@
-from .fetch import FetchWorker
+from .fetch import FetchWorker, GamesDlcsWorker, EntitlementsWorker
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 a1173ad5..1d4fe761 100644
--- a/rare/shared/workers/fetch.py
+++ b/rare/shared/workers/fetch.py
@@ -15,9 +15,9 @@ logger = getLogger("FetchWorker")
class FetchWorker(Worker):
class Result(IntEnum):
- GAMES = 1
- NON_ASSET = 2
- COMBINED = 3
+ ERROR = 0
+ GAMESDLCS = 1
+ ENTITLEMENTS = 2
class Signals(QObject):
progress = pyqtSignal(int, str)
@@ -30,7 +30,33 @@ class FetchWorker(Worker):
self.args = args
self.settings = QSettings()
+
+class EntitlementsWorker(FetchWorker):
+ def __init__(self, core: LegendaryCore, args: Namespace):
+ super(EntitlementsWorker, self).__init__(core, args)
+
def run_real(self):
+ entitlements = ()
+ want_entitlements = not self.settings.value("exclude_entitlements", False, bool)
+ if want_entitlements:
+ # Get entitlements, Ubisoft integration also uses them
+ self.signals.progress.emit(0, self.signals.tr("Updating entitlements"))
+ with timelogger(logger, "Request entitlements"):
+ entitlements = self.core.egs.get_user_entitlements()
+ self.core.lgd.entitlements = entitlements
+ logger.info(f"Entitlements: %s", len(list(entitlements)))
+ self.signals.result.emit(entitlements, FetchWorker.Result.ENTITLEMENTS)
+ return
+
+
+class GamesDlcsWorker(FetchWorker):
+
+ def __init__(self, core: LegendaryCore, args: Namespace):
+ super(GamesDlcsWorker, self).__init__(core, args)
+ self.exclude_non_asset = QSettings().value("exclude_non_asset", False, bool)
+
+ def run_real(self):
+
# Fetch regular EGL games with assets
want_unreal = self.settings.value("unreal_meta", False, bool) or self.args.debug
want_win32 = self.settings.value("win32_meta", False, bool)
@@ -74,25 +100,19 @@ class FetchWorker(Worker):
)
logger.info(f"Games: %s. Games with DLCs: %s", len(games), len(dlc_dict))
- want_non_asset = not self.settings.value("exclude_non_asset", False, bool)
- want_entitlements = not self.settings.value("exclude_entitlements", False, bool)
-
# Fetch non-asset games
+ want_non_asset = not self.settings.value("exclude_non_asset", False, bool)
if want_non_asset:
self.signals.progress.emit(30, self.signals.tr("Updating non-asset game metadata"))
try:
with timelogger(logger, "Request non-asset"):
na_games, na_dlc_dict = self.core.get_non_asset_library_items(force_refresh=False, skip_ue=False)
except (HTTPError, ConnectionError) as e:
- logger.error("Network exception while fetching non asset games from EGS.")
+ logger.error(f"Network error while fetching non asset games")
logger.error(e)
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 completely breaks Rare, so dodge it for now pending a fix.
+ # NOTE: This is here because of broken appIds from Epic
+ # https://discord.com/channels/826881530310819914/884510635642216499/1111321692703305729
except Exception as e:
logger.error("General exception while fetching non asset games from EGS.")
logger.error(e)
@@ -108,13 +128,5 @@ class FetchWorker(Worker):
dlc_dict[catalog_id] = dlcs
logger.info(f"Games: {len(games)}. Games with DLCs: {len(dlc_dict)}")
- if want_entitlements:
- # Get entitlements, Ubisoft integration also uses them
- self.signals.progress.emit(40, self.signals.tr("Updating entitlements"))
- with timelogger(logger, "Request entitlements"):
- entitlements = self.core.egs.get_user_entitlements()
- self.core.lgd.entitlements = entitlements
- logger.info(f"Entitlements: {len(list(entitlements))}")
-
- self.signals.progress.emit(50, self.signals.tr("Preparing games"))
- self.signals.result.emit((games, dlc_dict), FetchWorker.Result.COMBINED)
+ self.signals.progress.emit(40, self.signals.tr("Preparing library"))
+ self.signals.result.emit((games, dlc_dict), FetchWorker.Result.GAMESDLCS)