RareCore: Add options to exclude non-asset games and entitlements from startup
* Add options in settings to not request non-asset games and entitlements. This greatly improves startup time but reduces functionality a bit. Both options are disabled by default. * Remove the old options to exclude Win32 and Mac games as they were no longer relevant. * Add a performance context manager to log execution time when used. * Fixed an issue with UbisoftGroup where multiple threads would spawn.
This commit is contained in:
parent
a246f4ee16
commit
3c43da1594
|
@ -116,6 +116,19 @@ class LegendarySettings(QWidget, Ui_LegendarySettings):
|
|||
lambda: self.settings.setValue("unreal_meta", self.fetch_unreal_check.isChecked())
|
||||
)
|
||||
|
||||
self.exclude_non_asset_check.setChecked(
|
||||
self.settings.value("exclude_non_asset", False, bool)
|
||||
)
|
||||
self.exclude_non_asset_check.stateChanged.connect(
|
||||
lambda: self.settings.setValue("exclude_non_asset", self.exclude_non_asset_check.isChecked())
|
||||
)
|
||||
self.exclude_entitlements_check.setChecked(
|
||||
self.settings.value("exclude_entitlements", False, bool)
|
||||
)
|
||||
self.exclude_entitlements_check.stateChanged.connect(
|
||||
lambda: self.settings.setValue("exclude_entitlements", self.exclude_entitlements_check.isChecked())
|
||||
)
|
||||
|
||||
self.refresh_metadata_button.clicked.connect(self.refresh_metadata)
|
||||
# FIXME: Disable the button for now because it interferes with RareCore
|
||||
self.refresh_metadata_button.setEnabled(False)
|
||||
|
|
|
@ -9,12 +9,13 @@ from typing import Dict, Iterator, Callable, Optional, List, Union, Iterable, Tu
|
|||
from PyQt5.QtCore import QObject, pyqtSignal, QSettings, pyqtSlot, QThreadPool, QRunnable, QTimer
|
||||
from legendary.lfs.eos import EOSOverlayApp
|
||||
from legendary.models.game import Game, SaveGameFile
|
||||
from requests import HTTPError
|
||||
from requests.exceptions import HTTPError, ConnectionError
|
||||
|
||||
from rare.lgndr.core import LegendaryCore
|
||||
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 .image_manager import ImageManager
|
||||
from .workers import (
|
||||
QueueWorker,
|
||||
|
@ -50,7 +51,7 @@ class RareCore(QObject):
|
|||
self.__core: Optional[LegendaryCore] = None
|
||||
self.__image_manager: Optional[ImageManager] = None
|
||||
|
||||
self.__start_time = time.time()
|
||||
self.__start_time = time.perf_counter()
|
||||
|
||||
self.args(args)
|
||||
self.signals(init=True)
|
||||
|
@ -310,12 +311,12 @@ class RareCore(QObject):
|
|||
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")
|
||||
logger.debug(f"Fetch time {time.perf_counter() - self.__start_time} seconds")
|
||||
QTimer.singleShot(100, self.__post_init)
|
||||
self.completed.emit()
|
||||
|
||||
def fetch(self):
|
||||
self.__start_time = time.time()
|
||||
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)
|
||||
|
@ -323,9 +324,9 @@ class RareCore(QObject):
|
|||
|
||||
def fetch_saves(self):
|
||||
def __fetch() -> None:
|
||||
start_time = time.time()
|
||||
saves_dict: Dict[str, List[SaveGameFile]] = {}
|
||||
try:
|
||||
with timelogger(logger, "Request saves"):
|
||||
saves_list = self.__core.get_save_games()
|
||||
for s in saves_list:
|
||||
if s.app_name not in saves_dict.keys():
|
||||
|
@ -337,26 +338,28 @@ class RareCore(QObject):
|
|||
continue
|
||||
self.__library[app_name].load_saves(saves)
|
||||
except (HTTPError, ConnectionError) as e:
|
||||
logger.error(f"Exception while fetching saves from EGS: {e}")
|
||||
logger.error(f"Exception while fetching saves from EGS.")
|
||||
logger.error(e)
|
||||
return
|
||||
logger.debug(f"Saves: {len(saves_dict)}")
|
||||
logger.debug(f"Request saves: {time.time() - start_time} seconds")
|
||||
logger.info(f"Saves: {len(saves_dict)}")
|
||||
|
||||
saves_worker = QRunnable.create(__fetch)
|
||||
QThreadPool.globalInstance().start(saves_worker)
|
||||
|
||||
def fetch_entitlements(self) -> None:
|
||||
def __fetch() -> None:
|
||||
start_time = time.time()
|
||||
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"Failed to retrieve user entitlements from EGS: {e}")
|
||||
logger.error(f"Exception while fetching entitlements from EGS.")
|
||||
logger.error(e)
|
||||
return
|
||||
logger.debug(f"Entitlements: {len(list(entitlements))}")
|
||||
logger.debug(f"Request Entitlements: {time.time() - start_time} seconds")
|
||||
logger.info(f"Entitlements: {len(list(entitlements))}")
|
||||
|
||||
entitlements_worker = QRunnable.create(__fetch)
|
||||
QThreadPool.globalInstance().start(entitlements_worker)
|
||||
|
@ -368,7 +371,7 @@ class RareCore(QObject):
|
|||
def __post_init(self) -> None:
|
||||
if not self.__args.offline:
|
||||
self.fetch_saves()
|
||||
self.fetch_entitlements()
|
||||
# self.fetch_entitlements()
|
||||
self.resolve_origin()
|
||||
|
||||
@property
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import platform
|
||||
import time
|
||||
from argparse import Namespace
|
||||
from enum import IntEnum
|
||||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSignal, QSettings
|
||||
from requests.exceptions import ConnectionError, HTTPError
|
||||
from requests.exceptions import HTTPError, ConnectionError
|
||||
|
||||
from rare.lgndr.core import LegendaryCore
|
||||
from rare.utils.metrics import timelogger
|
||||
from .worker import Worker
|
||||
|
||||
logger = getLogger("FetchWorker")
|
||||
|
@ -32,13 +32,11 @@ class FetchWorker(Worker):
|
|||
|
||||
def run_real(self):
|
||||
# Fetch regular EGL games with assets
|
||||
start_time = time.time()
|
||||
|
||||
want_unreal = self.settings.value("unreal_meta", False, bool) or self.args.debug
|
||||
want_win32 = self.settings.value("win32_meta", False, bool)
|
||||
want_macos = self.settings.value("macos_meta", False, bool)
|
||||
need_macos = platform.system() == "Darwin"
|
||||
need_windows = not any([want_win32, want_macos, need_macos, self.args.debug])
|
||||
need_windows = not any([want_win32, want_macos, need_macos, self.args.debug]) and not self.args.offline
|
||||
|
||||
if want_win32 or self.args.debug:
|
||||
logger.info(
|
||||
|
@ -47,6 +45,7 @@ class FetchWorker(Worker):
|
|||
"with" if want_unreal else "without"
|
||||
)
|
||||
self.signals.progress.emit(00, self.signals.tr("Updating game metadata for Windows"))
|
||||
with timelogger(logger, "Request Win32 games"):
|
||||
self.core.get_game_and_dlc_list(
|
||||
update_assets=not self.args.offline, platform="Win32", skip_ue=not want_unreal
|
||||
)
|
||||
|
@ -58,6 +57,7 @@ class FetchWorker(Worker):
|
|||
"with" if want_unreal else "without"
|
||||
)
|
||||
self.signals.progress.emit(15, self.signals.tr("Updating game metadata for macOS"))
|
||||
with timelogger(logger, "Request macOS games"):
|
||||
self.core.get_game_and_dlc_list(
|
||||
update_assets=not self.args.offline, platform="Mac", skip_ue=not want_unreal
|
||||
)
|
||||
|
@ -68,19 +68,24 @@ class FetchWorker(Worker):
|
|||
"Requesting Windows metadata, %s Unreal engine",
|
||||
"with" if want_unreal else "without"
|
||||
)
|
||||
with timelogger(logger, "Request Windows games"):
|
||||
games, dlc_dict = self.core.get_game_and_dlc_list(
|
||||
update_assets=need_windows, platform="Windows", skip_ue=not want_unreal
|
||||
)
|
||||
logger.debug(f"Games {len(games)}, games with DLCs {len(dlc_dict)}")
|
||||
logger.debug(f"Request games: {time.time() - start_time} seconds")
|
||||
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
|
||||
if want_non_asset:
|
||||
self.signals.progress.emit(30, self.signals.tr("Updating non-asset game metadata"))
|
||||
start_time = time.time()
|
||||
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.warning(f"Exception while fetching non asset games from EGS: {e}")
|
||||
logger.error("Network exception while fetching non asset games from EGS.")
|
||||
logger.error(e)
|
||||
na_games, na_dlc_dict = ([], {})
|
||||
# FIXME:
|
||||
# This is here because of broken appIds from Epic:
|
||||
|
@ -89,10 +94,10 @@ class FetchWorker(Worker):
|
|||
# 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:
|
||||
logger.error(f"Exception while fetching non asset games from EGS: {e}")
|
||||
logger.error("General exception while fetching non asset games from EGS.")
|
||||
logger.error(e)
|
||||
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")
|
||||
logger.info("Non-asset: %s. Non-asset with DLCs: %s", len(na_games), len(na_dlc_dict))
|
||||
|
||||
# Combine the two games lists and the two dlc dictionaries between regular and non-asset results
|
||||
games += na_games
|
||||
|
@ -101,6 +106,15 @@ class FetchWorker(Worker):
|
|||
dlc_dict[catalog_id] += dlcs
|
||||
else:
|
||||
dlc_dict[catalog_id] = dlcs
|
||||
logger.debug(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:
|
||||
# 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)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'rare/ui/components/tabs/settings/legendary.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.10
|
||||
# Created by: PyQt5 UI code generator 5.15.7
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
@ -139,6 +139,12 @@ class Ui_LegendarySettings(object):
|
|||
self.fetch_unreal_check = QtWidgets.QCheckBox(self.metadata_group)
|
||||
self.fetch_unreal_check.setObjectName("fetch_unreal_check")
|
||||
self.verticalLayout_2.addWidget(self.fetch_unreal_check)
|
||||
self.exclude_non_asset_check = QtWidgets.QCheckBox(self.meta_group)
|
||||
self.exclude_non_asset_check.setObjectName("exclude_non_asset_check")
|
||||
self.verticalLayout_2.addWidget(self.exclude_non_asset_check)
|
||||
self.exclude_entitlements_check = QtWidgets.QCheckBox(self.meta_group)
|
||||
self.exclude_entitlements_check.setObjectName("exclude_entitlements_check")
|
||||
self.verticalLayout_2.addWidget(self.exclude_entitlements_check)
|
||||
self.metadata_info = QtWidgets.QLabel(self.metadata_group)
|
||||
font = QtGui.QFont()
|
||||
font.setItalic(True)
|
||||
|
@ -175,6 +181,14 @@ class Ui_LegendarySettings(object):
|
|||
self.fetch_win32_check.setText(_translate("LegendarySettings", "Include Win32 games"))
|
||||
self.fetch_macos_check.setText(_translate("LegendarySettings", "Include macOS games"))
|
||||
self.fetch_unreal_check.setText(_translate("LegendarySettings", "Include Unreal engine"))
|
||||
self.exclude_non_asset_check.setToolTip(_translate("LegendarySettings", "Do not load metadata for non-asset games (i.e. Origin games) on start-up.\n"
|
||||
"\n"
|
||||
"Disabling this greatly improves start-up time, but some games might not be visible in your library."))
|
||||
self.exclude_non_asset_check.setText(_translate("LegendarySettings", "Exclude non-asset games"))
|
||||
self.exclude_entitlements_check.setToolTip(_translate("LegendarySettings", "Do not load entitlement data (i.e game\'s date of purchase) on start-up.\n"
|
||||
"\n"
|
||||
"Disabling this greatly improves start-up time, but some library filters may not work."))
|
||||
self.exclude_entitlements_check.setText(_translate("LegendarySettings", "Exclude entitlements"))
|
||||
self.metadata_info.setText(_translate("LegendarySettings", "Restart Rare to apply"))
|
||||
self.refresh_metadata_button.setText(_translate("LegendarySettings", "Refresh metadata"))
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@
|
|||
<property name="title">
|
||||
<string>Platforms</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<layout class="QVBoxLayout" name="metadata_layout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="fetch_win32_check">
|
||||
<property name="text">
|
||||
|
@ -253,6 +253,30 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="exclude_non_asset_check">
|
||||
<property name="toolTip">
|
||||
<string>Do not load metadata for non-asset games (i.e. Origin games) on start-up.
|
||||
|
||||
Disabling this greatly improves start-up time, but some games might not be visible in your library.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Exclude non-asset games</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="exclude_entitlements_check">
|
||||
<property name="toolTip">
|
||||
<string>Do not load entitlement data (i.e game's date of purchase) on start-up.
|
||||
|
||||
Disabling this greatly improves start-up time, but some library filters may not work.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Exclude entitlements</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="metadata_info">
|
||||
<property name="font">
|
||||
|
|
Loading…
Reference in a new issue