RareCore: Move entitlements request into an independent worker
Yes, we are back at this. Entitlements are important to have early as Ubisoft redemption requires them, and they don't depend on anything else. * Move config helper initialization into RareCore to make it available earlier.
This commit is contained in:
parent
acbe8836cc
commit
7ae06ff5d8
|
@ -12,7 +12,7 @@ from requests import HTTPError
|
||||||
from rare.components.dialogs.launch_dialog import LaunchDialog
|
from rare.components.dialogs.launch_dialog import LaunchDialog
|
||||||
from rare.components.main_window import MainWindow
|
from rare.components.main_window import MainWindow
|
||||||
from rare.shared import RareCore
|
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.utils.misc import ExitCodes
|
||||||
from rare.widgets.rare_app import RareApp, RareAppException
|
from rare.widgets.rare_app import RareApp, RareAppException
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,15 @@ from rare.models.base_game import RareSaveGame
|
||||||
from rare.models.game import RareGame, RareEosOverlay
|
from rare.models.game import RareGame, RareEosOverlay
|
||||||
from rare.models.signals import GlobalSignals
|
from rare.models.signals import GlobalSignals
|
||||||
from rare.utils.metrics import timelogger
|
from rare.utils.metrics import timelogger
|
||||||
|
from rare.utils import config_helper
|
||||||
from .image_manager import ImageManager
|
from .image_manager import ImageManager
|
||||||
from .workers import (
|
from .workers import (
|
||||||
QueueWorker,
|
QueueWorker,
|
||||||
VerifyWorker,
|
VerifyWorker,
|
||||||
MoveWorker,
|
MoveWorker,
|
||||||
FetchWorker,
|
FetchWorker,
|
||||||
|
GamesDlcsWorker,
|
||||||
|
EntitlementsWorker,
|
||||||
OriginWineWorker,
|
OriginWineWorker,
|
||||||
)
|
)
|
||||||
from .workers.uninstall import uninstall_game
|
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.install.connect(self.__signals.game.install)
|
||||||
self.__eos_overlay.signals.game.uninstall.connect(self.__signals.game.uninstall)
|
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
|
RareCore.__instance = self
|
||||||
|
|
||||||
def enqueue_worker(self, rgame: RareGame, worker: QueueWorker):
|
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.info(f'Marking "{rgame.app_title}" as not installed because an exception has occurred...')
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
rgame.set_installed(False)
|
rgame.set_installed(False)
|
||||||
self.progress.emit(int(idx/length * 80) + 20, self.tr("Loaded <b>{}</b>").format(rgame.app_title))
|
progress = int(idx/length * self.__fetch_progress) + (100 - self.__fetch_progress)
|
||||||
|
self.progress.emit(progress, self.tr("Loaded <b>{}</b>").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)
|
@pyqtSlot(object, int)
|
||||||
def __on_fetch_result(self, result: Tuple[List, Dict], res_type: int):
|
def __on_fetch_result(self, result: Tuple, result_type: int):
|
||||||
logger.info(f"Got API results for {FetchWorker.Result(res_type).name}")
|
if result_type == FetchWorker.Result.GAMESDLCS:
|
||||||
self.progress.emit(15, self.tr("Preparing library"))
|
self.__add_games_and_dlcs(*result)
|
||||||
self.__add_games_and_dlcs(*result)
|
self.__fetched_games_dlcs = True
|
||||||
self.progress.emit(100, self.tr("Launching Rare"))
|
|
||||||
logger.debug(f"Fetch time {time.perf_counter() - self.__start_time} seconds")
|
if result_type == FetchWorker.Result.ENTITLEMENTS:
|
||||||
QTimer.singleShot(100, self.__post_init)
|
self.__core.lgd.entitlements = result
|
||||||
self.completed.emit()
|
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):
|
def fetch(self):
|
||||||
self.__start_time = time.perf_counter()
|
self.__start_time = time.perf_counter()
|
||||||
fetch_worker = FetchWorker(self.__core, self.__args)
|
|
||||||
fetch_worker.signals.progress.connect(self.progress)
|
games_dlcs_worker = GamesDlcsWorker(self.__core, self.__args)
|
||||||
fetch_worker.signals.result.connect(self.__on_fetch_result)
|
games_dlcs_worker.signals.progress.connect(self.__on_fetch_progress)
|
||||||
QThreadPool.globalInstance().start(fetch_worker)
|
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_saves(self):
|
||||||
def __fetch() -> None:
|
def __fetch() -> None:
|
||||||
|
@ -346,24 +374,6 @@ class RareCore(QObject):
|
||||||
saves_worker = QRunnable.create(__fetch)
|
saves_worker = QRunnable.create(__fetch)
|
||||||
QThreadPool.globalInstance().start(saves_worker)
|
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:
|
def resolve_origin(self) -> None:
|
||||||
origin_worker = OriginWineWorker(self.__core, list(self.origin_games))
|
origin_worker = OriginWineWorker(self.__core, list(self.origin_games))
|
||||||
QThreadPool.globalInstance().start(origin_worker)
|
QThreadPool.globalInstance().start(origin_worker)
|
||||||
|
@ -371,7 +381,6 @@ class RareCore(QObject):
|
||||||
def __post_init(self) -> None:
|
def __post_init(self) -> None:
|
||||||
if not self.__args.offline:
|
if not self.__args.offline:
|
||||||
self.fetch_saves()
|
self.fetch_saves()
|
||||||
# self.fetch_entitlements()
|
|
||||||
self.resolve_origin()
|
self.resolve_origin()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from .fetch import FetchWorker
|
from .fetch import FetchWorker, GamesDlcsWorker, EntitlementsWorker
|
||||||
from .install_info import InstallInfoWorker
|
from .install_info import InstallInfoWorker
|
||||||
from .move import MoveWorker
|
from .move import MoveWorker
|
||||||
from .uninstall import UninstallWorker
|
from .uninstall import UninstallWorker
|
||||||
|
|
|
@ -15,9 +15,9 @@ logger = getLogger("FetchWorker")
|
||||||
|
|
||||||
class FetchWorker(Worker):
|
class FetchWorker(Worker):
|
||||||
class Result(IntEnum):
|
class Result(IntEnum):
|
||||||
GAMES = 1
|
ERROR = 0
|
||||||
NON_ASSET = 2
|
GAMESDLCS = 1
|
||||||
COMBINED = 3
|
ENTITLEMENTS = 2
|
||||||
|
|
||||||
class Signals(QObject):
|
class Signals(QObject):
|
||||||
progress = pyqtSignal(int, str)
|
progress = pyqtSignal(int, str)
|
||||||
|
@ -30,7 +30,33 @@ class FetchWorker(Worker):
|
||||||
self.args = args
|
self.args = args
|
||||||
self.settings = QSettings()
|
self.settings = QSettings()
|
||||||
|
|
||||||
|
|
||||||
|
class EntitlementsWorker(FetchWorker):
|
||||||
|
def __init__(self, core: LegendaryCore, args: Namespace):
|
||||||
|
super(EntitlementsWorker, self).__init__(core, args)
|
||||||
|
|
||||||
def run_real(self):
|
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
|
# Fetch regular EGL games with assets
|
||||||
want_unreal = self.settings.value("unreal_meta", False, bool) or self.args.debug
|
want_unreal = self.settings.value("unreal_meta", False, bool) or self.args.debug
|
||||||
want_win32 = self.settings.value("win32_meta", False, bool)
|
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))
|
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
|
# Fetch non-asset games
|
||||||
|
want_non_asset = not self.settings.value("exclude_non_asset", False, bool)
|
||||||
if want_non_asset:
|
if want_non_asset:
|
||||||
self.signals.progress.emit(30, self.signals.tr("Updating non-asset game metadata"))
|
self.signals.progress.emit(30, self.signals.tr("Updating non-asset game metadata"))
|
||||||
try:
|
try:
|
||||||
with timelogger(logger, "Request non-asset"):
|
with timelogger(logger, "Request non-asset"):
|
||||||
na_games, na_dlc_dict = 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:
|
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)
|
logger.error(e)
|
||||||
na_games, na_dlc_dict = ([], {})
|
na_games, na_dlc_dict = ([], {})
|
||||||
# FIXME:
|
# NOTE: This is here because of broken appIds from Epic
|
||||||
# This is here because of broken appIds from Epic:
|
# https://discord.com/channels/826881530310819914/884510635642216499/1111321692703305729
|
||||||
# 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.
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("General exception while fetching non asset games from EGS.")
|
logger.error("General exception while fetching non asset games from EGS.")
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
|
@ -108,13 +128,5 @@ class FetchWorker(Worker):
|
||||||
dlc_dict[catalog_id] = dlcs
|
dlc_dict[catalog_id] = dlcs
|
||||||
logger.info(f"Games: {len(games)}. Games with DLCs: {len(dlc_dict)}")
|
logger.info(f"Games: {len(games)}. Games with DLCs: {len(dlc_dict)}")
|
||||||
|
|
||||||
if want_entitlements:
|
self.signals.progress.emit(40, self.signals.tr("Preparing library"))
|
||||||
# Get entitlements, Ubisoft integration also uses them
|
self.signals.result.emit((games, dlc_dict), FetchWorker.Result.GAMESDLCS)
|
||||||
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)
|
|
||||||
|
|
Loading…
Reference in a new issue