2022-05-04 09:02:28 +12:00
|
|
|
import json
|
|
|
|
import sys
|
|
|
|
import time
|
|
|
|
from logging import getLogger
|
|
|
|
from typing import List, Union
|
|
|
|
|
2022-05-14 08:11:24 +12:00
|
|
|
from PyQt5.QtCore import QObject, QProcess, pyqtSignal, QUrl
|
|
|
|
from PyQt5.QtGui import QDesktopServices
|
2022-05-04 09:02:28 +12:00
|
|
|
from PyQt5.QtNetwork import QLocalServer, QLocalSocket
|
2022-05-14 08:11:24 +12:00
|
|
|
from PyQt5.QtWidgets import QApplication, QPushButton
|
2022-05-04 09:02:28 +12:00
|
|
|
|
2022-05-15 11:25:13 +12:00
|
|
|
from .lgd_helper import get_launch_args, LaunchArgs, get_configured_process
|
|
|
|
from legendary.core import LegendaryCore
|
2022-05-04 09:02:28 +12:00
|
|
|
|
|
|
|
|
|
|
|
class GameProcessHelper(QObject):
|
|
|
|
game_process: QProcess
|
|
|
|
server: QLocalServer
|
|
|
|
socket: QLocalSocket = None
|
|
|
|
exit_app = pyqtSignal()
|
|
|
|
success: bool = True
|
|
|
|
|
|
|
|
def __init__(self, app_name: str):
|
|
|
|
super(GameProcessHelper, self).__init__()
|
|
|
|
self.game_process = QProcess()
|
|
|
|
self.app_name = app_name
|
|
|
|
self.logger = getLogger(self.app_name)
|
|
|
|
self.core = LegendaryCore()
|
|
|
|
|
|
|
|
self.server = QLocalServer()
|
2022-05-15 11:25:13 +12:00
|
|
|
ret = self.server.listen(f"rare1_{self.app_name}")
|
2022-05-04 09:02:28 +12:00
|
|
|
if not ret:
|
|
|
|
self.logger.info(self.server.errorString())
|
2022-05-14 08:11:24 +12:00
|
|
|
print("Server is running")
|
2022-05-04 09:02:28 +12:00
|
|
|
self.server.close()
|
|
|
|
self.success = False
|
|
|
|
return
|
|
|
|
self.server.newConnection.connect(self.new_server_connection)
|
|
|
|
|
|
|
|
self.game_process.finished.connect(self.game_finished)
|
|
|
|
self.start_time = time.time()
|
|
|
|
|
2022-05-14 08:11:24 +12:00
|
|
|
def prepare_launch(self, app_name) -> List[str]:
|
|
|
|
args = get_launch_args(self.core, LaunchArgs(app_name))
|
|
|
|
if not args:
|
|
|
|
return []
|
|
|
|
|
|
|
|
self.game_process.setProcessEnvironment(args.env)
|
|
|
|
|
|
|
|
if args.pre_launch_command:
|
|
|
|
proc = get_configured_process()
|
|
|
|
proc.setProcessEnvironment(args.env)
|
|
|
|
proc.start(args.pre_launch_command[0], args.pre_launch_command[1:])
|
|
|
|
if args.pre_launch_wait:
|
|
|
|
proc.waitForFinished(-1)
|
|
|
|
|
2022-05-04 09:02:28 +12:00
|
|
|
return [
|
2022-05-14 08:11:24 +12:00
|
|
|
args.executable, args.args, args.is_origin_game
|
2022-05-04 09:02:28 +12:00
|
|
|
]
|
|
|
|
|
|
|
|
def new_server_connection(self):
|
|
|
|
if self.socket is not None:
|
|
|
|
self.socket.disconnectFromServer()
|
|
|
|
self.logger.info("New connection")
|
|
|
|
self.socket = self.server.nextPendingConnection()
|
|
|
|
self.socket.disconnected.connect(self.socket.deleteLater)
|
|
|
|
self.socket.flush()
|
|
|
|
|
|
|
|
def send_message(self, message: Union[bytes, str]):
|
|
|
|
if isinstance(message, str):
|
|
|
|
message = message.encode("utf-8")
|
|
|
|
if self.socket:
|
|
|
|
self.socket.write(message)
|
|
|
|
self.socket.flush()
|
|
|
|
else:
|
2022-05-15 11:25:13 +12:00
|
|
|
print("Can't send message")
|
2022-05-04 09:02:28 +12:00
|
|
|
|
|
|
|
def game_finished(self, exit_code):
|
|
|
|
print("game finished")
|
|
|
|
self.send_message(
|
|
|
|
json.dumps({
|
|
|
|
"action": "finished",
|
2022-05-15 11:25:13 +12:00
|
|
|
"app_name": self.app_name,
|
2022-05-04 09:02:28 +12:00
|
|
|
"exit_code": exit_code,
|
|
|
|
"playtime": int(time.time() - self.start_time)
|
|
|
|
})
|
|
|
|
)
|
|
|
|
self.exit_app.emit()
|
|
|
|
|
2022-05-14 08:11:24 +12:00
|
|
|
def start(self, app_name):
|
|
|
|
# if offline
|
|
|
|
try:
|
|
|
|
if not self.core.login():
|
|
|
|
raise ValueError("You are not logged in")
|
|
|
|
except ValueError:
|
|
|
|
# automatically launch offline if available
|
|
|
|
self.logger.error("Not logged in. Try to launch game offline")
|
|
|
|
# offline = True
|
|
|
|
|
|
|
|
args = self.prepare_launch(app_name)
|
|
|
|
if not args:
|
|
|
|
print(args)
|
|
|
|
self.server.close()
|
|
|
|
self.server.deleteLater()
|
|
|
|
return
|
|
|
|
if args[2]:
|
|
|
|
# origin game on Windows
|
|
|
|
QDesktopServices.openUrl(QUrl(args[2]))
|
|
|
|
return
|
|
|
|
self.game_process.start(*args[:2])
|
2022-05-04 09:02:28 +12:00
|
|
|
self.start_time = time.time()
|
|
|
|
|
|
|
|
|
2022-05-15 11:25:13 +12:00
|
|
|
def start_game(app_name: str):
|
2022-05-14 08:11:24 +12:00
|
|
|
app = QApplication(sys.argv)
|
2022-05-04 09:02:28 +12:00
|
|
|
helper = GameProcessHelper(app_name)
|
|
|
|
if not helper.success:
|
|
|
|
return
|
2022-05-14 08:11:24 +12:00
|
|
|
helper.start(app_name)
|
2022-05-04 09:02:28 +12:00
|
|
|
helper.exit_app.connect(lambda: app.exit(0))
|
2022-05-14 08:11:24 +12:00
|
|
|
|
|
|
|
# this button is for debug. Closing with keyboard interrupt does not kill the server
|
|
|
|
quit_button = QPushButton("Quit")
|
|
|
|
quit_button.show()
|
|
|
|
quit_button.clicked.connect(lambda: app.exit(0))
|
2022-05-04 09:02:28 +12:00
|
|
|
app.exec_()
|
|
|
|
helper.server.close()
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2022-05-14 08:11:24 +12:00
|
|
|
# TODO add argparse for offline app name, wine prefix/binary ...
|
2022-05-15 11:25:13 +12:00
|
|
|
start_game("963137e4c29d4c79a81323b8fab03a40")
|