Skip to content

Commit

Permalink
Merge pull request #454 from loathingKernel/develop
Browse files Browse the repository at this point in the history
Fix issues with rare's process launcher
  • Loading branch information
loathingKernel authored Sep 16, 2024
2 parents c98de5a + 0079320 commit 57ca61f
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 60 deletions.
1 change: 0 additions & 1 deletion .github/workflows/job_cx-freeze-msi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ jobs:
run: |
pip3 install -r requirements.txt
pip3 install -r requirements-presence.txt
pip3 install -r requirements-webview.txt
- name: Build
run: |
python freeze.py bdist_msi
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/job_cx-freeze-zip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ jobs:
run: |
pip3 install -r requirements.txt
pip3 install -r requirements-presence.txt
pip3 install -r requirements-webview.txt
pip3 install .
- name: Build
run: cxfreeze -c rare/main.py --target-dir dist --target-name rare --icon rare/resources/images/Rare.ico -OO --base-name Win32GUI
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/job_macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ jobs:
run: |
pip install -r requirements.txt
pip install -r requirements-presence.txt
pip install -r requirements-webview.txt
- name: Move files
run: mv rare/__main__.py __main__.py
- name: Build
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/job_nuitka-win.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ jobs:
run: |
pip3 install -r requirements.txt
pip3 install -r requirements-presence.txt
pip3 install -r requirements-webview.txt
- name: Build
run: >-
python -m nuitka
Expand All @@ -37,7 +36,6 @@ jobs:
--standalone
--enable-plugin=anti-bloat
--enable-plugin=pyside6
--enable-plugin=pywebview
--show-modules
--show-anti-bloat-changes
--follow-stdlib
Expand Down
36 changes: 23 additions & 13 deletions rare/commands/launcher/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,16 @@ def prepare_launch(self, args: InitArgs) -> Optional[LaunchArgs]:
proc = get_configured_process()
proc.setProcessEnvironment(launch_args.environment)
self.signals.pre_launch_command_started.emit()
pre_launch_command = shlex.split(launch_args.pre_launch_command)
self.logger.debug("Running pre-launch command %s, %s", pre_launch_command[0], pre_launch_command[1:])
prelaunch = shlex.split(launch_args.pre_launch_command)
command = prelaunch.pop(0) if len(prelaunch) else ""
arguments = prelaunch if len(prelaunch) else []
self.logger.info("Running pre-launch command %s, %s", command, shlex.join(arguments))
if launch_args.pre_launch_wait:
proc.start(pre_launch_command[0], pre_launch_command[1:])
self.logger.debug("Waiting for pre-launch command to finish")
proc.start(command, arguments)
self.logger.info("Waiting for pre-launch command to finish")
proc.waitForFinished(-1)
else:
proc.startDetached(pre_launch_command[0], pre_launch_command[1:])
proc.startDetached(command, arguments)
return launch_args


Expand Down Expand Up @@ -172,6 +174,8 @@ def __init__(self, args: InitArgs):
self.console = ConsoleDialog(game.app_title)
self.console.show()

self.sync_dialog: Optional[CloudSyncDialog] = None

self.game_process.finished.connect(self.__process_finished)
self.game_process.errorOccurred.connect(self.__process_errored)
if self.console:
Expand Down Expand Up @@ -244,15 +248,18 @@ def check_saves_finished(self, exit_code: int):

if state == SaveGameStatus.LOCAL_NEWER and not self.no_sync_on_exit:
action = CloudSyncDialogResult.UPLOAD
self.__check_saved_finished(exit_code, action)
self.__check_saves_finished(exit_code, action)
else:
sync_dialog = CloudSyncDialog(self.rgame.igame, dt_local, dt_remote)
sync_dialog.result_ready.connect(lambda a: self.__check_saved_finished(exit_code, a))
sync_dialog.open()
self.sync_dialog = CloudSyncDialog(self.rgame.igame, dt_local, dt_remote)
self.sync_dialog.result_ready.connect(lambda a: self.__check_saves_finished(exit_code, a))
self.sync_dialog.open()

@Slot(int, int)
@Slot(int, CloudSyncDialogResult)
def __check_saved_finished(self, exit_code, action):
def __check_saves_finished(self, exit_code, action):
if self.sync_dialog is not None:
self.sync_dialog.deleteLater()
self.sync_dialog = None
action = CloudSyncDialogResult(action)
if action == CloudSyncDialogResult.UPLOAD:
if self.console:
Expand Down Expand Up @@ -364,13 +371,16 @@ def sync_ready(self):
return

_, (dt_local, dt_remote) = self.rgame.save_game_state
sync_dialog = CloudSyncDialog(self.rgame.igame, dt_local, dt_remote)
sync_dialog.result_ready.connect(self.__sync_ready)
sync_dialog.open()
self.sync_dialog = CloudSyncDialog(self.rgame.igame, dt_local, dt_remote)
self.sync_dialog.result_ready.connect(self.__sync_ready)
self.sync_dialog.open()

@Slot(int)
@Slot(CloudSyncDialogResult)
def __sync_ready(self, action: CloudSyncDialogResult):
if self.sync_dialog is not None:
self.sync_dialog.deleteLater()
self.sync_dialog = None
action = CloudSyncDialogResult(action)
if action == CloudSyncDialogResult.CANCEL:
self.no_sync_on_exit = True
Expand Down
2 changes: 1 addition & 1 deletion rare/commands/launcher/lgd_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from rare.models.base_game import RareGameSlim

logger = getLogger("RareLauncherHelper")
logger = getLogger("RareLauncherUtils")


class GameArgsError(Exception):
Expand Down
56 changes: 35 additions & 21 deletions rare/components/tabs/settings/widgets/launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from PySide6.QtCore import Qt, Slot
from PySide6.QtGui import QShowEvent
from PySide6.QtWidgets import QCheckBox, QFileDialog, QFormLayout, QVBoxLayout, QGroupBox
from PySide6.QtWidgets import QCheckBox, QFileDialog, QFormLayout, QVBoxLayout, QGroupBox, QLineEdit

from rare.shared import LegendaryCoreSingleton
import rare.utils.config_helper as config
Expand All @@ -26,41 +26,50 @@ def __init__(
self.core = LegendaryCoreSingleton()
self.app_name: str = "default"

self.prelaunch_edit = PathEdit(
self.prelaunch_cmd = PathEdit(
path="",
placeholder=self.tr("Path to script or program to run before the game launches"),
placeholder=self.tr("Path to a script or program to run before the game"),
file_mode=QFileDialog.FileMode.ExistingFile,
edit_func=self.__prelaunch_edit_callback,
save_func=self.__prelaunch_save_callback,
edit_func=self.__prelaunch_cmd_edit_callback,
save_func=self.__prelaunch_cmd_save_callback,
)

self.wrappers_widget = wrapper_widget(self)
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_check = QCheckBox(self.tr("Wait for command to finish before starting the game"))
self.prelaunch_check = QCheckBox(self.tr("Wait for the pre-launch command to finish before launching the game"))
font = self.font()
font.setItalic(True)
self.prelaunch_check.setFont(font)
self.prelaunch_check.stateChanged.connect(self.__prelauch_check_changed)

prelaunch_layout = QVBoxLayout()
prelaunch_layout.addWidget(self.prelaunch_edit)
prelaunch_layout.addWidget(self.prelaunch_cmd)
prelaunch_layout.addWidget(self.prelaunch_args)
prelaunch_layout.addWidget(self.prelaunch_check)

self.main_layout = QFormLayout(self)
self.main_layout.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.ExpandingFieldsGrow)
self.main_layout.setLabelAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
self.main_layout.setFormAlignment(Qt.AlignmentFlag.AlignLeading | Qt.AlignmentFlag.AlignTop)

self.wrappers_widget = wrapper_widget(self)

self.main_layout.addRow(self.tr("Wrappers"), self.wrappers_widget)
self.main_layout.addRow(self.tr("Prelaunch"), prelaunch_layout)
self.main_layout.addRow(self.tr("Pre-launch"), prelaunch_layout)

def showEvent(self, a0: QShowEvent):
if a0.spontaneous():
return super().showEvent(a0)
command = config.get_option(self.app_name, "pre_launch_command", fallback="")
prelaunch = shlex.split(config.get_option(self.app_name, "pre_launch_command", fallback=""))
command = prelaunch.pop(0) if len(prelaunch) else ""
arguments = prelaunch if len(prelaunch) else []
wait = config.get_boolean(self.app_name, "pre_launch_wait", fallback=False)

self.prelaunch_edit.setText(command)
self.prelaunch_cmd.setText(command)
self.prelaunch_args.setText(shlex.join(arguments))
self.prelaunch_check.setChecked(wait)
self.prelaunch_check.setEnabled(bool(command))

Expand All @@ -71,26 +80,31 @@ def tool_enabled(self):
self.wrappers_widget.update_state()

@staticmethod
def __prelaunch_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.VALID
try:
command = shlex.split(text)[0]
except ValueError:
return False, text, IndicatorReasonsCommon.WRONG_FORMAT
if not os.path.isfile(command) and not shutil.which(command):
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_save_callback(self, text):
config.save_option(self.app_name, "pre_launch_command", text)
def __prelaunch_cmd_save_callback(self, text):
self.prelaunch_check.setEnabled(bool(text))
if not text:
config.remove_option(self.app_name, "pre_launch_wait")
self.__prelaunch_changed()

def __prelauch_check_changed(self):
config.set_boolean(self.app_name, "pre_launch_wait", self.prelaunch_check.isChecked())

@Slot()
def __prelaunch_changed(self):
command = self.prelaunch_cmd.text().strip()
if not command:
config.save_option(self.app_name, "pre_launch_command", command)
config.remove_option(self.app_name, "pre_launch_wait")
return
command = shlex.quote(command)
arguments = self.prelaunch_args.text().strip()
config.save_option(self.app_name, "pre_launch_command", " ".join([command, arguments]))


LaunchSettingsType = TypeVar("LaunchSettingsType", bound=LaunchSettingsBase)
6 changes: 3 additions & 3 deletions rare/utils/config_helper.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os
from typing import Callable, Optional, Set, Any, List, Tuple
from typing import Callable, Optional, Set, Any, Tuple

from legendary.core import LegendaryCore
from legendary.models.config import LGDConf
Expand Down Expand Up @@ -165,11 +165,11 @@ def get_prefix(app_name: str = "default") -> Optional[str]:
if _wine_prefix and prefix_exists(_wine_prefix):
return _wine_prefix

_compat_path = _config.get(f"default.env", "STEAM_COMPAT_DATA_PATH", fallback=None)
_compat_path = _config.get("default.env", "STEAM_COMPAT_DATA_PATH", fallback=None)
if _compat_path and prefix_exists(_compat_prefix := os.path.join(_compat_path, "pfx")):
return _compat_prefix

_wine_prefix = _config.get(f"default.env", "WINEPREFIX", fallback=None)
_wine_prefix = _config.get("default.env", "WINEPREFIX", fallback=None)
_wine_prefix = _config.get("default", "wine_prefix", fallback=_wine_prefix)
if _wine_prefix and prefix_exists(_wine_prefix):
return _wine_prefix
Expand Down
5 changes: 1 addition & 4 deletions rare/widgets/indicator_edit.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import os
from enum import IntEnum, Enum
from logging import getLogger
import shlex
from typing import Callable, Tuple, Optional, Dict, List

from PySide6.QtCore import (
Expand Down Expand Up @@ -345,7 +344,5 @@ def __set_path(self):
dlg.setNameFilter(" ".join(self.__name_filter))
if dlg.exec_():
name = dlg.selectedFiles()[0]
if " " in name:
name = shlex.quote(name)
self.line_edit.setText(name)
self.__completer_model.setRootPath(name)
self.line_edit.setText(name)
3 changes: 0 additions & 3 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ wheel
pylint
mypy
black[d]
toml
cx-freeze
nuitka
ordered-set
PySide6-stubs
qstylizer
graphql-query
19 changes: 10 additions & 9 deletions requirements-full.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
requests<3.0
PyQt5
requests
PySide6-Essentials
QtAwesome
setuptools
legendary-gl>=0.20.34; platform_system != "Windows" or platform_system != "Darwin"
legendary-gl @ git+https:/derrod/legendary@96e07ff ; platform_system == "Windows" or platform_system == "Darwin"
legendary-gl @ https:/derrod/legendary/archive/3963382b3f33116154399be5dd2d2913336a1f0e.zip ; platform_system == "Windows" or platform_system == "Darwin"
orjson
vdf
pywin32; platform_system == "Windows"
pywebview[qt]; platform_system == "Linux"
pywebview[qt]; platform_system == "FreeBSD"
pythonnet>=3.0.0rc4; platform_system == "Windows"
cefpython3; platform_system == "Windows"
pywebview[cef]; platform_system == "Windows"
pypresence
# pywebview with QtWebEngine backend has issues with EGS login form, so use GTK
pywebview[gtk]; platform_system == "Linux"
pywebview[gtk]; platform_system == "FreeBSD"
pythonnet; platform_system == "Windows"
pywebview; platform_system == "Windows"
pyobjc; platform_system == "Darwin"
pywebview; platform_system == "Darwin"

2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
requests<3.0
requests
PySide6-Essentials
QtAwesome
setuptools
Expand Down

0 comments on commit 57ca61f

Please sign in to comment.