1
0
Fork 0
mirror of synced 2024-07-05 22:51:11 +12:00
Rare/rare/shared/game_utils.py

245 lines
9.1 KiB
Python
Raw Normal View History

import os
import platform
from logging import getLogger
from PyQt5.QtCore import QObject, QProcess, pyqtSignal, QUrl, pyqtSlot
from PyQt5.QtCore import QStandardPaths
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtWidgets import QMessageBox, QPushButton
from legendary.core import LegendaryCore
from rare.components.dialogs.uninstall_dialog import UninstallDialog
from rare.lgndr.cli import LegendaryCLI
from rare.lgndr.glue.arguments import LgndrUninstallGameArgs
from rare.lgndr.glue.monkeys import LgndrIndirectStatus
from rare.models.game import RareGame
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
from rare.shared.game_process import GameProcess
from rare.utils import config_helper, misc
from .cloud_save_utils import CloudSaveUtils
logger = getLogger("GameUtils")
def uninstall_game(core: LegendaryCore, app_name: str, keep_files=False, keep_config=False):
igame = core.get_installed_game(app_name)
# remove shortcuts link
desktop = QStandardPaths.writableLocation(QStandardPaths.DesktopLocation)
applications = QStandardPaths.writableLocation(QStandardPaths.ApplicationsLocation)
if platform.system() == "Linux":
desktop_shortcut = os.path.join(desktop, f"{igame.title}.desktop")
if os.path.exists(desktop_shortcut):
os.remove(desktop_shortcut)
applications_shortcut = os.path.join(applications, f"{igame.title}.desktop")
if os.path.exists(applications_shortcut):
os.remove(applications_shortcut)
elif platform.system() == "Windows":
game_title = igame.title.split(":")[0]
desktop_shortcut = os.path.join(desktop, f"{game_title}.lnk")
if os.path.exists(desktop_shortcut):
os.remove(desktop_shortcut)
start_menu_shortcut = os.path.join(applications, "..", f"{game_title}.lnk")
if os.path.exists(start_menu_shortcut):
os.remove(start_menu_shortcut)
status = LgndrIndirectStatus()
LegendaryCLI(core).uninstall_game(
LgndrUninstallGameArgs(
app_name=app_name,
keep_files=keep_files,
indirect_status=status,
yes=True,
)
)
if not keep_config:
logger.info("Removing sections in config file")
config_helper.remove_section(app_name)
config_helper.remove_section(f"{app_name}.env")
config_helper.save_config()
return status.success, status.message
class GameUtils(QObject):
2021-11-17 10:54:23 +13:00
finished = pyqtSignal(str, str) # app_name, error
cloud_save_finished = pyqtSignal(str)
game_launched = pyqtSignal(RareGame)
2021-11-17 10:54:23 +13:00
update_list = pyqtSignal(str)
def __init__(self, parent=None):
super(GameUtils, self).__init__(parent=parent)
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.args = ArgumentsSingleton()
self.running_games = {}
self.launch_queue = {}
self.cloud_save_utils = CloudSaveUtils()
self.cloud_save_utils.sync_finished.connect(self.sync_finished)
def check_running(self, rgame: RareGame):
if rgame.is_installed:
game_process = GameProcess(rgame, on_startup=True)
2022-06-09 07:55:54 +12:00
game_process.game_finished.connect(self.game_finished)
2022-06-12 02:59:53 +12:00
game_process.game_launched.connect(self.game_launched.emit)
self.running_games[rgame.app_name] = game_process
2022-06-09 07:55:54 +12:00
def uninstall_game(self, rgame: RareGame) -> bool:
2021-11-17 10:54:23 +13:00
# returns if uninstalled
if not os.path.exists(rgame.igame.install_path):
2021-12-24 22:09:50 +13:00
if QMessageBox.Yes == QMessageBox.question(
None,
self.tr("Uninstall - {}").format(rgame.igame.title),
self.tr(
"Game files of {} do not exist. Remove it from installed games?"
).format(rgame.igame.title),
QMessageBox.Yes | QMessageBox.No,
QMessageBox.Yes,
2021-12-24 22:09:50 +13:00
):
self.core.lgd.remove_installed_game(rgame.app_name)
2021-11-17 10:54:23 +13:00
return True
else:
return False
proceed, keep_files, keep_config = UninstallDialog(rgame.game).get_options()
if not proceed:
return False
success, message = uninstall_game(self.core, rgame.app_name, keep_files, keep_config)
if not success:
QMessageBox.warning(None, self.tr("Uninstall - {}").format(rgame.title), message, QMessageBox.Close)
self.signals.game.uninstalled.emit(rgame.app_name)
return True
2021-12-24 22:09:50 +13:00
def prepare_launch(
self, rgame: RareGame, offline: bool = False, skip_update_check: bool = False
2021-12-24 22:09:50 +13:00
):
2021-11-17 10:54:23 +13:00
dont_sync_after_finish = False
2022-06-12 02:59:53 +12:00
# TODO move this to helper
if rgame.game.supports_cloud_saves and not offline:
2021-11-17 10:54:23 +13:00
try:
sync = self.cloud_save_utils.sync_before_launch_game(rgame)
2021-11-17 10:54:23 +13:00
except ValueError:
logger.info("Cancel startup")
self.sync_finished(rgame)
return
2021-11-17 10:54:23 +13:00
except AssertionError:
dont_sync_after_finish = True
else:
if sync:
self.launch_queue[rgame.app_name] = (rgame, skip_update_check, offline)
2021-11-17 10:54:23 +13:00
return
self.sync_finished(rgame)
2021-12-24 22:09:50 +13:00
self.launch_game(
rgame, offline, skip_update_check, ask_always_sync=dont_sync_after_finish
2021-12-24 22:09:50 +13:00
)
def launch_game(
self,
rgame: RareGame,
offline: bool = False,
skip_update_check: bool = False,
wine_bin: str = None,
wine_pfx: str = None,
ask_always_sync: bool = False,
2021-12-24 22:09:50 +13:00
):
2022-07-30 18:02:08 +12:00
executable = misc.get_rare_executable()
executable, args = executable[0], executable[1:]
args.extend([
"start", rgame.app_name
])
if offline:
args.append("--offline")
if skip_update_check:
args.append("--skip-update-check")
if wine_bin:
args.extend(["--wine-bin", wine_bin])
if wine_pfx:
args.extend(["--wine-prefix", wine_pfx])
if ask_always_sync:
args.extend("--ask-always-sync")
2022-06-12 02:59:53 +12:00
# kill me, if I don't change it before commit
QProcess.startDetached(executable, args)
logger.info(f"Start new Process: ({executable} {' '.join(args)})")
game_process = GameProcess(rgame, ask_always_sync)
game_process.game_finished.connect(self.game_finished)
2022-06-12 02:59:53 +12:00
game_process.game_launched.connect(self.game_launched.emit)
self.running_games[rgame.app_name] = game_process
@pyqtSlot(RareGame, int)
def game_finished(self, rgame: RareGame, exit_code):
if self.running_games.get(rgame.app_name):
self.running_games.pop(rgame.app_name)
2022-06-24 08:01:14 +12:00
if exit_code == -1234:
return
self.finished.emit(rgame.app_name, "")
2022-06-24 08:01:14 +12:00
logger.info(f"Game exited with exit code: {exit_code}")
self.signals.discord_rpc.set_title.emit("")
if exit_code == 1 and rgame.is_origin:
msg_box = QMessageBox()
2021-12-24 22:09:50 +13:00
msg_box.setText(
self.tr(
"Origin is not installed. Do you want to download installer file? "
)
)
msg_box.addButton(QPushButton("Download"), QMessageBox.YesRole)
msg_box.addButton(QPushButton("Cancel"), QMessageBox.RejectRole)
resp = msg_box.exec()
# click install button
if resp == 0:
2022-03-28 10:03:48 +13:00
QDesktopServices.openUrl(QUrl("https://www.dm.origin.com/download"))
return
2022-06-24 08:01:14 +12:00
if exit_code != 0:
2022-08-01 11:22:37 +12:00
pass
"""
2021-12-24 22:09:50 +13:00
QMessageBox.warning(
None,
"Warning",
self.tr("Failed to launch {}. Check logs to find error").format(
2021-12-24 22:09:50 +13:00
self.core.get_game(app_name).app_title
),
)
2022-08-01 11:22:37 +12:00
"""
if rgame.app_name in self.running_games.keys():
self.running_games.pop(rgame.app_name)
if rgame.game.supports_cloud_saves:
if exit_code != 0:
2021-12-24 22:09:50 +13:00
r = QMessageBox.question(
None,
"Question",
self.tr(
"Game exited with code {}, which is not a normal code. "
"It could be caused by a crash. Do you want to sync cloud saves"
2021-12-24 22:09:50 +13:00
).format(exit_code),
buttons=QMessageBox.Yes | QMessageBox.No,
defaultButton=QMessageBox.Yes,
)
if r != QMessageBox.Yes:
return
2022-06-24 08:01:14 +12:00
# TODO move this to helper
self.cloud_save_utils.game_finished(rgame, always_ask=False)
@pyqtSlot(RareGame)
def sync_finished(self, rgame: RareGame):
if rgame.app_name in self.launch_queue.keys():
self.cloud_save_finished.emit(rgame.app_name)
params = self.launch_queue[rgame.app_name]
self.launch_queue.pop(rgame.app_name)
self.launch_game(*params)
else:
self.cloud_save_finished.emit(rgame.app_name)