2022-05-14 08:11:24 +12:00
|
|
|
import os
|
|
|
|
import platform
|
|
|
|
import shutil
|
2023-03-03 11:39:03 +13:00
|
|
|
from argparse import Namespace
|
2022-05-14 08:11:24 +12:00
|
|
|
from dataclasses import dataclass
|
|
|
|
from logging import getLogger
|
2022-07-08 09:56:19 +12:00
|
|
|
from typing import List
|
2022-05-14 08:11:24 +12:00
|
|
|
|
|
|
|
from PyQt5.QtCore import QProcess, QProcessEnvironment
|
|
|
|
from legendary.models.game import InstalledGame, LaunchParameters
|
|
|
|
|
2022-09-05 06:40:41 +12:00
|
|
|
from rare.lgndr.core import LegendaryCore
|
|
|
|
|
|
|
|
|
2022-05-14 08:11:24 +12:00
|
|
|
logger = getLogger("Helper")
|
|
|
|
|
|
|
|
|
2022-06-09 07:14:48 +12:00
|
|
|
class GameArgsError(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2023-03-03 11:39:03 +13:00
|
|
|
class InitArgs(Namespace):
|
2022-05-14 08:11:24 +12:00
|
|
|
app_name: str
|
2023-02-13 05:13:05 +13:00
|
|
|
dry_run: bool = False
|
2022-09-09 00:32:54 +12:00
|
|
|
debug: bool = False
|
2022-05-14 08:11:24 +12:00
|
|
|
offline: bool = False
|
2022-10-01 11:44:37 +13:00
|
|
|
skip_update_check: bool = False
|
2022-05-14 08:11:24 +12:00
|
|
|
wine_prefix: str = ""
|
|
|
|
wine_bin: str = ""
|
|
|
|
|
2022-05-19 09:41:48 +12:00
|
|
|
@classmethod
|
|
|
|
def from_argparse(cls, args):
|
|
|
|
return cls(
|
|
|
|
app_name=args.app_name,
|
2022-09-09 00:32:54 +12:00
|
|
|
debug=args.debug,
|
2022-05-19 09:41:48 +12:00
|
|
|
offline=args.offline,
|
2022-10-01 11:44:37 +13:00
|
|
|
skip_update_check=args.skip_update_check,
|
2022-05-19 09:41:48 +12:00
|
|
|
wine_bin=args.wine_bin,
|
2022-09-08 23:58:11 +12:00
|
|
|
wine_prefix=args.wine_pfx,
|
2023-02-13 05:13:05 +13:00
|
|
|
dry_run=args.dry_run
|
2022-05-19 09:41:48 +12:00
|
|
|
)
|
2022-05-14 08:11:24 +12:00
|
|
|
|
2022-05-21 22:40:21 +12:00
|
|
|
|
2022-05-14 08:11:24 +12:00
|
|
|
@dataclass
|
2022-05-19 09:41:48 +12:00
|
|
|
class LaunchArgs:
|
2022-05-14 08:11:24 +12:00
|
|
|
executable: str = ""
|
|
|
|
args: List[str] = None
|
2022-06-12 02:59:53 +12:00
|
|
|
cwd: str = None
|
2022-05-14 08:11:24 +12:00
|
|
|
env: QProcessEnvironment = None
|
|
|
|
pre_launch_command: str = ""
|
|
|
|
pre_launch_wait: bool = False
|
|
|
|
is_origin_game: bool = False # only for windows to launch as url
|
|
|
|
|
|
|
|
def __bool__(self):
|
|
|
|
return bool(self.executable)
|
|
|
|
|
|
|
|
|
|
|
|
def get_origin_params(core: LegendaryCore, app_name, offline: bool,
|
2022-05-19 09:41:48 +12:00
|
|
|
launch_args: LaunchArgs) -> LaunchArgs:
|
2022-05-14 08:11:24 +12:00
|
|
|
origin_uri = core.get_origin_uri(app_name, offline)
|
|
|
|
if platform.system() == "Windows":
|
|
|
|
launch_args.executable = origin_uri
|
|
|
|
launch_args.args = []
|
|
|
|
# only set it here true, because on linux it is a launch command like every other game
|
|
|
|
launch_args.is_origin_game = True
|
|
|
|
return launch_args
|
|
|
|
|
|
|
|
command = core.get_app_launch_command(app_name)
|
|
|
|
if not os.path.exists(command[0]) and shutil.which(command[0]) is None:
|
|
|
|
return launch_args
|
|
|
|
command.append(origin_uri)
|
|
|
|
|
2022-05-19 09:41:48 +12:00
|
|
|
env = core.get_app_environment(app_name)
|
2022-05-21 22:40:21 +12:00
|
|
|
launch_args.env = QProcessEnvironment.systemEnvironment()
|
2022-07-08 09:56:19 +12:00
|
|
|
for name, value in env.items():
|
2022-05-19 09:41:48 +12:00
|
|
|
launch_args.env.insert(name, value)
|
|
|
|
|
2022-05-14 08:11:24 +12:00
|
|
|
launch_args.executable = command[0]
|
|
|
|
launch_args.args = command[1:]
|
|
|
|
return launch_args
|
|
|
|
|
|
|
|
|
2022-05-19 09:41:48 +12:00
|
|
|
def get_game_params(core: LegendaryCore, igame: InstalledGame, args: InitArgs,
|
|
|
|
launch_args: LaunchArgs) -> LaunchArgs:
|
|
|
|
if not args.offline: # skip for update
|
2022-10-01 11:44:37 +13:00
|
|
|
if not args.skip_update_check and not core.is_noupdate_game(igame.app_name):
|
|
|
|
print("Checking for updates...")
|
2022-05-14 08:11:24 +12:00
|
|
|
# check updates
|
|
|
|
try:
|
|
|
|
latest = core.get_asset(
|
|
|
|
igame.app_name, igame.platform, update=False
|
|
|
|
)
|
|
|
|
except ValueError:
|
2022-06-09 07:14:48 +12:00
|
|
|
raise GameArgsError("Metadata doesn't exist")
|
2022-05-14 08:11:24 +12:00
|
|
|
else:
|
|
|
|
if latest.build_version != igame.version:
|
2022-06-09 07:14:48 +12:00
|
|
|
raise GameArgsError("Game is not up to date. Please update first")
|
|
|
|
|
2022-05-14 08:11:24 +12:00
|
|
|
params: LaunchParameters = core.get_launch_parameters(
|
2022-05-19 09:41:48 +12:00
|
|
|
app_name=igame.app_name, offline=args.offline
|
2022-05-14 08:11:24 +12:00
|
|
|
)
|
|
|
|
|
|
|
|
full_params = list()
|
|
|
|
|
|
|
|
if os.environ.get("container") == "flatpak":
|
|
|
|
full_params.extend(["flatpak-spawn", "--host"])
|
|
|
|
|
|
|
|
full_params.extend(params.launch_command)
|
|
|
|
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)
|
|
|
|
|
|
|
|
launch_args.executable = full_params[0]
|
|
|
|
launch_args.args = full_params[1:]
|
|
|
|
|
2022-05-21 22:40:21 +12:00
|
|
|
launch_args.env = QProcessEnvironment.systemEnvironment()
|
2022-05-19 09:41:48 +12:00
|
|
|
for name, value in params.environment.items():
|
|
|
|
launch_args.env.insert(name, value)
|
2022-06-12 02:59:53 +12:00
|
|
|
launch_args.cwd = params.working_directory
|
2022-05-14 08:11:24 +12:00
|
|
|
return launch_args
|
|
|
|
|
|
|
|
|
2022-05-19 09:41:48 +12:00
|
|
|
def get_launch_args(core: LegendaryCore, args: InitArgs = None) -> LaunchArgs:
|
2022-05-14 08:11:24 +12:00
|
|
|
game = core.get_game(args.app_name)
|
|
|
|
igame = core.get_installed_game(args.app_name)
|
|
|
|
|
2022-05-19 09:41:48 +12:00
|
|
|
resp = LaunchArgs()
|
2022-05-14 08:11:24 +12:00
|
|
|
|
|
|
|
if not game:
|
2022-06-09 07:14:48 +12:00
|
|
|
raise GameArgsError(f"Could not find metadata for ")
|
2022-05-14 08:11:24 +12:00
|
|
|
|
|
|
|
if game.third_party_store == "Origin":
|
|
|
|
args.offline = False
|
|
|
|
else:
|
|
|
|
if not igame:
|
2022-06-09 07:14:48 +12:00
|
|
|
raise GameArgsError("Game is not installed or has unsupported format")
|
2022-05-14 08:11:24 +12:00
|
|
|
|
|
|
|
if game.is_dlc:
|
2022-06-09 07:14:48 +12:00
|
|
|
raise GameArgsError("Game is a DLC")
|
2022-05-14 08:11:24 +12:00
|
|
|
if not os.path.exists(igame.install_path):
|
2022-06-09 07:14:48 +12:00
|
|
|
raise GameArgsError("Game path does not exist")
|
2022-05-14 08:11:24 +12:00
|
|
|
|
|
|
|
if game.third_party_store == "Origin":
|
|
|
|
resp = get_origin_params(core, args.app_name, args.offline, resp)
|
|
|
|
else:
|
2022-05-19 09:41:48 +12:00
|
|
|
resp = get_game_params(core, igame, args, resp)
|
2022-05-14 08:11:24 +12:00
|
|
|
|
|
|
|
pre_cmd, wait = core.get_pre_launch_command(args.app_name)
|
|
|
|
resp.pre_launch_command, resp.pre_launch_wait = pre_cmd, wait
|
|
|
|
return resp
|
|
|
|
|
|
|
|
|
|
|
|
def get_configured_process(env: dict = None):
|
|
|
|
proc = QProcess()
|
2022-06-24 07:26:08 +12:00
|
|
|
proc.setProcessChannelMode(QProcess.MergedChannels)
|
2022-05-14 08:11:24 +12:00
|
|
|
proc.readyReadStandardOutput.connect(
|
2022-06-09 07:14:48 +12:00
|
|
|
lambda: logger.info(
|
2022-05-14 08:11:24 +12:00
|
|
|
str(proc.readAllStandardOutput().data(), "utf-8", "ignore")
|
|
|
|
)
|
|
|
|
)
|
2022-05-21 22:40:21 +12:00
|
|
|
environment = QProcessEnvironment.systemEnvironment()
|
2022-05-14 08:11:24 +12:00
|
|
|
if env:
|
|
|
|
for e in env:
|
|
|
|
environment.insert(e, env[e])
|
2022-05-21 22:40:21 +12:00
|
|
|
proc.setProcessEnvironment(environment)
|
2022-05-14 08:11:24 +12:00
|
|
|
|
|
|
|
return proc
|