Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions rare/commands/launcher/lgd_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,19 +109,18 @@ def get_game_params(rgame: RareGameSlim, init: InitParams, launch: LaunchParams)
full_params = []
full_params.extend(params.launch_command)
if 'LEGENDARY_WRAPPER_EXE' in params.environment:
lgd_wrapper = params.environment.pop('LEGENDARY_WRAPPER_EXE').strip()
if os.path.isfile(lgd_wrapper):
lgd_wrapper = params.environment.pop('LEGENDARY_WRAPPER_EXE', '').strip()
if lgd_wrapper and os.path.isfile(lgd_wrapper):
full_params.append(lgd_wrapper)
full_params.append(os.path.join(params.game_directory, params.game_executable))
full_params.extend(params.game_parameters)
full_params.extend(params.egl_parameters)
full_params.extend(params.user_parameters)

exe, init, env = prepare_process(full_params, params.environment)

launch.executable = exe
launch.arguments = init
launch.environment = env
_exe, _init, _env = prepare_process(full_params, params.environment)
launch.executable = _exe
launch.arguments = _init
launch.environment = _env
launch.working_directory = params.working_directory

return launch
Expand Down
4 changes: 2 additions & 2 deletions rare/components/dialogs/install/dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ def __init__(self, settings: RareAppSettings, rgame: 'RareGame', options: Instal

self.install_dir_edit.setDisabled(rgame.is_installed or rgame.is_dlc)
self.ui.install_dir_label.setDisabled(rgame.is_installed or rgame.is_dlc)
self.ui.shortcut_label.setDisabled(rgame.is_installed or rgame.is_dlc)
self.ui.shortcut_check.setDisabled(rgame.is_installed or rgame.is_dlc)
self.ui.shortcut_label.setDisabled(rgame.is_installed or rgame.is_dlc or 'WINEUSERNAME' in os.environ)
self.ui.shortcut_check.setDisabled(rgame.is_installed or rgame.is_dlc or 'WINEUSERNAME' in os.environ)
self.ui.shortcut_check.setChecked(not rgame.is_installed and self.settings.get_value(app_settings.create_shortcut))
self.ui.shortcut_check.checkStateChanged.connect(self._on_option_changed_no_reload)

Expand Down
29 changes: 19 additions & 10 deletions rare/components/tabs/library/details/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from rare.models.settings import RareAppSettings
from rare.shared import RareCore
from rare.utils import config_helper as config
from rare.utils.wrapper_exe import wrapper_path
from rare.widgets.indicator_edit import IndicatorReasonsCommon, PathEdit

logger = getLogger('LocalGameSettings')
Expand All @@ -34,13 +35,13 @@ def __init__(self, rcore: RareCore, parent=None):
self.skip_update_combo.addItem(self.tr('Default'), None)
self.skip_update_combo.addItem(self.tr('No'), 'false')
self.skip_update_combo.addItem(self.tr('Yes'), 'true')
self.skip_update_combo.currentIndexChanged.connect(self.__skip_update_changed)
self.skip_update_combo.currentIndexChanged.connect(self._skip_update_changed)

self.offline_combo = QComboBox(self)
self.offline_combo.addItem(self.tr('Default'), None)
self.offline_combo.addItem(self.tr('No'), 'false')
self.offline_combo.addItem(self.tr('Yes'), 'true')
self.offline_combo.currentIndexChanged.connect(self.__offline_changed)
self.offline_combo.currentIndexChanged.connect(self._offline_changed)

self.override_exe_name_filters: tuple[str, ...] = (
'*.exe',
Expand All @@ -54,14 +55,14 @@ def __init__(self, rcore: RareCore, parent=None):
file_mode=QFileDialog.FileMode.ExistingFile,
name_filters=self.override_exe_name_filters,
placeholder=self.tr('Relative path to the replacement executable'),
edit_func=self.__override_exe_edit_callback,
save_func=self.__override_exe_save_callback,
edit_func=self._override_exe_edit_callback,
save_func=self._override_exe_save_callback,
parent=self,
)

self.launch_params_edit = QLineEdit(self)
self.launch_params_edit.setPlaceholderText(self.tr('Game specific command line arguments'))
self.launch_params_edit.textChanged.connect(self.__launch_params_changed)
self.launch_params_edit.textChanged.connect(self._launch_params_changed)

self.main_layout.insertRow(0, self.tr('Skip update check'), self.skip_update_combo)
self.main_layout.insertRow(1, self.tr('Offline mode'), self.offline_combo)
Expand Down Expand Up @@ -94,11 +95,11 @@ def showEvent(self, a0: QShowEvent):
return super().showEvent(a0)

@Slot(int)
def __skip_update_changed(self, index):
def _skip_update_changed(self, index):
data = self.skip_update_combo.itemData(index, Qt.ItemDataRole.UserRole)
config.adjust_option(self.app_name, 'skip_update_check', data)

def __override_exe_edit_callback(self, path: str) -> tuple[bool, str, int]:
def _override_exe_edit_callback(self, path: str) -> tuple[bool, str, int]:
if not path or self.igame is None:
return True, path, IndicatorReasonsCommon.VALID
if not os.path.isabs(path):
Expand All @@ -116,17 +117,25 @@ def __override_exe_edit_callback(self, path: str) -> tuple[bool, str, int]:
path = os.path.relpath(path, self.igame.install_path)
return True, path, IndicatorReasonsCommon.VALID

def __override_exe_save_callback(self, path: str):
def _override_exe_save_callback(self, path: str):
config.adjust_option(self.app_name, 'override_exe', path)

@Slot(int)
def __offline_changed(self, index):
def _offline_changed(self, index):
data = self.skip_update_combo.itemData(index, Qt.ItemDataRole.UserRole)
config.adjust_option(self.app_name, 'offline', data)

def __launch_params_changed(self, value) -> None:
def _launch_params_changed(self, value) -> None:
config.adjust_option(self.app_name, 'start_params', value)

@Slot(Qt.CheckState)
def _lgd_wrapper_check_changed(self, state: Qt.CheckState):
_wrapper = str(wrapper_path())
config.adjust_envvar_with_global(
self.app_name, 'LEGENDARY_WRAPPER_EXE', _wrapper if state == Qt.CheckState.Checked else ''
)
self.environ_changed.emit('LEGENDARY_WRAPPER_EXE')

def load_settings(self, rgame: RareGame):
self.game = rgame.game
self.igame = rgame.igame
Expand Down
6 changes: 5 additions & 1 deletion rare/components/tabs/settings/game.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from PySide6.QtCore import Qt
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QHideEvent
from PySide6.QtWidgets import QVBoxLayout, QWidget

Expand All @@ -12,6 +12,9 @@


class GameSettingsBase(QWidget, SideTabContents):
# str: option key
environ_changed: Signal = Signal(str)

def __init__(
self,
settings: RareAppSettings,
Expand All @@ -26,6 +29,7 @@ def __init__(
self.app_name: str = 'default'

self.launch = launch_widget(rcore, self)
self.launch.environ_changed.connect(self.environ_changed)

self.main_layout = QVBoxLayout(self)
self.main_layout.addWidget(self.launch, stretch=0)
Expand Down
42 changes: 32 additions & 10 deletions rare/components/tabs/settings/widgets/launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import shutil
from typing import TypeVar

from PySide6.QtCore import Qt, Slot
from PySide6.QtCore import Qt, Signal, Slot
from PySide6.QtGui import QShowEvent
from PySide6.QtWidgets import (
QCheckBox,
Expand All @@ -16,12 +16,16 @@

import rare.utils.config_helper as config
from rare.shared import RareCore
from rare.utils.wrapper_exe import wrapper_path
from rare.widgets.indicator_edit import IndicatorReasonsCommon, PathEdit

from .wrappers import WrapperSettings


class LaunchSettingsBase(QGroupBox):
# str: option key
environ_changed: Signal = Signal(str)

def __init__(self, rcore: RareCore, wrapper_widget: type[WrapperSettings], parent=None):
super(LaunchSettingsBase, self).__init__(parent=parent)
self.setTitle(self.tr('Launch'))
Expand All @@ -33,21 +37,21 @@ def __init__(self, rcore: RareCore, wrapper_widget: type[WrapperSettings], paren
path='',
placeholder=self.tr('Path to a script or program to run before the game'),
file_mode=QFileDialog.FileMode.ExistingFile,
edit_func=self.__prelaunch_cmd_edit_callback,
save_func=self.__prelaunch_cmd_save_callback,
edit_func=self._prelaunch_cmd_edit_callback,
save_func=self._prelaunch_cmd_save_callback,
)

self.prelaunch_args = QLineEdit('')
self.prelaunch_args.setPlaceholderText(self.tr('Arguments to the script or program to run before the game'))
self.prelaunch_args.setToolTip(self.prelaunch_args.placeholderText())
self.prelaunch_args.textChanged.connect(self.__prelaunch_changed)
self.prelaunch_args.textChanged.connect(self._prelaunch_changed)

font = self.font()
font.setItalic(True)

self.prelaunch_check = QCheckBox(self.tr('Wait for the pre-launch command to finish before launching the game'))
self.prelaunch_check.setFont(font)
self.prelaunch_check.checkStateChanged.connect(self.__prelauch_check_changed)
self.prelaunch_check.checkStateChanged.connect(self._prelauch_check_changed)

prelaunch_layout = QVBoxLayout()
prelaunch_layout.addWidget(self.prelaunch_cmd)
Expand All @@ -61,6 +65,13 @@ def __init__(self, rcore: RareCore, wrapper_widget: type[WrapperSettings], paren

self.wrappers_widget = wrapper_widget(rcore, self)

self.lgd_wrapper = QCheckBox(
self.tr('Use "EpicGamesLauncher.exe" shim for compatibility with third-party launchers (Rockstar etc.)')
)
self.lgd_wrapper.setFont(font)
self.lgd_wrapper.checkStateChanged.connect(self._lgd_wrapper_check_changed)

self.main_layout.addRow(self.tr('Use fake EGL'), self.lgd_wrapper)
self.main_layout.addRow(self.tr('Wrappers'), self.wrappers_widget)
self.main_layout.addRow(self.tr('Pre-launch'), prelaunch_layout)

Expand All @@ -77,31 +88,36 @@ def showEvent(self, a0: QShowEvent):
self.prelaunch_check.setChecked(wait)
self.prelaunch_check.setEnabled(bool(command))

wrapper = config.get_envvar_with_global(self.app_name, 'LEGENDARY_WRAPPER_EXE', fallback=False)

self.lgd_wrapper.setEnabled(wrapper_path().exists())
self.lgd_wrapper.setChecked(wrapper_path().exists() and bool(wrapper) and os.path.exists(wrapper))

return super().showEvent(a0)

@Slot()
def tool_enabled(self):
self.wrappers_widget.update_state()

@staticmethod
def __prelaunch_cmd_edit_callback(text: str) -> tuple[bool, str, int]:
def _prelaunch_cmd_edit_callback(text: str) -> tuple[bool, str, int]:
if not text.strip():
return True, text, IndicatorReasonsCommon.UNDEFINED
if not os.path.isfile(text) and not shutil.which(text):
return False, text, IndicatorReasonsCommon.FILE_NOT_EXISTS
else:
return True, text, IndicatorReasonsCommon.VALID

def __prelaunch_cmd_save_callback(self, text):
def _prelaunch_cmd_save_callback(self, text):
self.prelaunch_check.setEnabled(bool(text))
self.__prelaunch_changed()
self._prelaunch_changed()

@Slot(Qt.CheckState)
def __prelauch_check_changed(self, state: Qt.CheckState):
def _prelauch_check_changed(self, state: Qt.CheckState):
config.set_boolean(self.app_name, 'pre_launch_wait', state != Qt.CheckState.Unchecked)

@Slot()
def __prelaunch_changed(self):
def _prelaunch_changed(self):
command = self.prelaunch_cmd.text().strip()
if not command:
config.adjust_option(self.app_name, 'pre_launch_command', command)
Expand All @@ -111,5 +127,11 @@ def __prelaunch_changed(self):
arguments = self.prelaunch_args.text().strip()
config.adjust_option(self.app_name, 'pre_launch_command', ' '.join([command, arguments]))

@Slot(Qt.CheckState)
def _lgd_wrapper_check_changed(self, state: Qt.CheckState):
_wrapper = str(wrapper_path())
config.adjust_envvar(self.app_name, 'LEGENDARY_WRAPPER_EXE', _wrapper if state == Qt.CheckState.Checked else '')
self.environ_changed.emit('LEGENDARY_WRAPPER_EXE')


LaunchSettingsType = TypeVar('LaunchSettingsType', bound=LaunchSettingsBase)
5 changes: 4 additions & 1 deletion rare/models/settings.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import locale
import os
import platform as pf
from argparse import Namespace
from typing import Any, Optional
Expand Down Expand Up @@ -59,7 +60,9 @@ class Settings(Namespace):
discord_rpc_os = Setting(key='discord_rpc_os', default=True, dtype=bool)

local_shader_cache = Setting(key='local_shader_cache', default=False, dtype=bool)
create_shortcut = Setting(key='create_shortcut', default=pf.system() == 'Windows', dtype=bool)
create_shortcut = Setting(
key='create_shortcut', default=pf.system() == 'Windows' and 'WINEUSERNAME' not in os.environ, dtype=bool
)


app_settings = Settings()
Expand Down
27 changes: 14 additions & 13 deletions rare/shared/rare_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from collections.abc import Callable, Iterable, Iterator
from itertools import chain
from logging import getLogger
from typing import Optional

from legendary.lfs.eos import EOSOverlayApp
from legendary.models.game import Game, SaveGameFile
Expand Down Expand Up @@ -46,19 +45,19 @@ class RareCore(QObject):
# completed_entitlements = Signal()

# lk: special case class attribute, this has to be here
__instance: Optional['RareCore'] = None
__instance: 'RareCore' = None

def __init__(self, settings: RareAppSettings, args: Namespace):
if self.__instance is not None:
raise RuntimeError('RareCore already initialized')
super(RareCore, self).__init__()
self.logger = getLogger(type(self).__name__)
self.__settings = settings
self.__args: Namespace | None = None
self.__signals: GlobalSignals | None = None
self.__core: LegendaryCore | None = None
self.__image_manager: ImageManager | None = None
self.__wrappers: Wrappers | None = None
self.__args: Namespace = None
self.__signals: GlobalSignals = None
self.__core: LegendaryCore = None
self.__image_manager: ImageManager = None
self.__wrappers: Wrappers = None

self.__start_time = time.perf_counter()

Expand All @@ -84,7 +83,7 @@ def __init__(self, settings: RareAppSettings, args: Namespace):
self.__fetch_progress: int = 0
self.__fetched_games_dlcs: bool = False
self.__fetched_entitlements: bool = False
self.__fetched_steamappids: bool = False
self.__fetched_runtimeassets: bool = False

RareCore.__instance = self

Expand Down Expand Up @@ -196,12 +195,14 @@ def check_config(option: str, accepted: set = None) -> bool:
self.__core.lgd.config.set('Legendary', 'default_platform', self.__core.default_platform)
if not check_config('install_dir'):
self.__core.lgd.config.set('Legendary', 'install_dir', self.__core.get_default_install_dir())
os.makedirs(self.__core.get_default_install_dir(), exist_ok=True)
if not check_config('mac_install_dir'):
self.__core.lgd.config.set(
'Legendary',
'mac_install_dir',
self.__core.get_default_install_dir(self.__core.default_platform),
)
os.makedirs(self.__core.get_default_install_dir(self.__core.default_platform), exist_ok=True)

# Always set these options
# Avoid implicitly falling back to Windows games on macOS
Expand Down Expand Up @@ -320,7 +321,7 @@ def __filter_games(self, condition: Callable[[RareGame], bool]) -> Iterator[Rare
return filter(condition, self.__library.values())

def __create_or_update_rgame(self, game: Game) -> RareGame:
if rgame := self.__library.get(game.app_name, False):
if rgame := self.__library.get(game.app_name):
self.logger.warning(f'{rgame.app_name} already present in {type(self).__name__}')
self.logger.info(f'Updating Game for {rgame.app_name}')
rgame.update_rgame()
Expand All @@ -333,7 +334,7 @@ def __add_games_and_dlcs(self, games: list[Game], dlcs_dict: dict[str, list]) ->
length = len(games)
for idx, game in enumerate(games):
rgame = self.__create_or_update_rgame(game)
if game_dlcs := dlcs_dict.get(rgame.game.catalog_item_id, False):
if game_dlcs := dlcs_dict.get(rgame.game.catalog_item_id):
for dlc in game_dlcs:
rdlc = self.__create_or_update_rgame(dlc)
if rdlc not in rgame.owned_dlcs:
Expand Down Expand Up @@ -366,8 +367,8 @@ def __on_fetch_result(self, result: tuple, result_type: int):
self.__core.lgd.entitlements = result
self.__fetched_entitlements = True

if result_type == FetchWorker.Result.EXTRAS:
self.__fetched_steamappids = True
if result_type == FetchWorker.Result.RUNTIMEASSETS:
self.__fetched_runtimeassets = True

self.logger.info('Acquired data from %s worker', FetchWorker.Result(result_type).name)

Expand All @@ -376,7 +377,7 @@ def __on_fetch_result(self, result: tuple, result_type: int):
{
self.__fetched_games_dlcs,
self.__fetched_entitlements,
self.__fetched_steamappids,
self.__fetched_runtimeassets,
}
):
return
Expand Down
Loading
Loading