Skip to content

Commit 43711af

Browse files
authored
Update game_manager.py
1 parent e12019a commit 43711af

File tree

1 file changed

+107
-33
lines changed

1 file changed

+107
-33
lines changed

game_manager.py

Lines changed: 107 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,132 @@
11
import subprocess
22
import os
33
import shutil
4+
import logging
45
from config_manager import ConfigManager
6+
57
class GameManager:
68
def __init__(self, proton_manager):
79
self.proton_manager = proton_manager
810
self.config_manager = ConfigManager()
11+
912
def add_game(self, game):
1013
games = self.config_manager.load_games()
1114
games.append(game)
1215
self.config_manager.save_games(games)
16+
logging.info(f"Added game: {game['name']}")
17+
1318
def remove_game(self, name):
1419
games = self.config_manager.load_games()
1520
games = [g for g in games if g['name'] != name]
1621
self.config_manager.save_games(games)
22+
logging.info(f"Removed game: {name}")
23+
1724
def launch_game(self, game, gamescope=False):
1825
runner = game['runner']
1926
exe = game['exe']
27+
if not os.path.exists(exe) and runner != 'Steam':
28+
raise Exception(f"Executable does not exist: {exe}")
2029
launch_options = game.get('launch_options', '').split()
30+
env = os.environ.copy()
31+
prefix = game.get('prefix', '')
32+
if runner in ['Wine', 'Proton']:
33+
if not prefix:
34+
raise Exception("Prefix not set for Wine/Proton runner")
35+
# Ensure prefix is writable by the current user
36+
try:
37+
os.makedirs(prefix, exist_ok=True)
38+
# Fix ownership if running as root (optional, for robustness)
39+
if os.geteuid() == 0: # Running as root
40+
user_id = os.getuid()
41+
group_id = os.getgid()
42+
subprocess.run(['chown', '-R', f'{user_id}:{group_id}', prefix], check=True)
43+
except Exception as e:
44+
raise Exception(f"Failed to set up prefix {prefix}: {e}")
45+
env['WINEPREFIX'] = prefix
46+
if game.get('enable_dxvk', False):
47+
env['WINEDLLOVERRIDES'] = 'd3d11=n,b;dxgi=n,b'
48+
# Per-game overrides if set, else global
49+
env['WINEESYNC'] = '1' if game.get('enable_esync', self.config_manager.load_settings()['enable_esync']) else '0'
50+
env['WINEFSYNC'] = '1' if game.get('enable_fsync', self.config_manager.load_settings()['enable_fsync']) else '0'
51+
env['DXVK_ASYNC'] = '1' if game.get('enable_dxvk_async', self.config_manager.load_settings()['enable_dxvk_async']) else '0'
52+
cmd = []
2153
if gamescope:
2254
if not shutil.which('gamescope'):
23-
raise Exception("Gamescope is not installed. Please install it using 'sudo apt install gamescope'.")
24-
cmd = ['gamescope', '--']
25-
if '--bigpicture' in launch_options:
26-
cmd.extend(['-e', '-f'])
27-
launch_options.remove('--bigpicture')
55+
raise Exception("Gamescope is not installed. Please install it via your package manager (e.g., apt, dnf, pacman).")
56+
cmd = ['gamescope']
57+
# Expanded Gamescope options without duplication
58+
options_to_remove = []
59+
if '--adaptive-sync' in launch_options:
60+
cmd.append('--adaptive-sync')
61+
options_to_remove.append('--adaptive-sync')
62+
if '--force-grab-cursor' in launch_options:
63+
cmd.append('--force-grab-cursor')
64+
options_to_remove.append('--force-grab-cursor')
65+
width_idx = next((i for i, opt in enumerate(launch_options) if opt.startswith('--width=')), None)
66+
if width_idx is not None:
67+
cmd.append('-W')
68+
cmd.append(launch_options[width_idx].split('=')[1])
69+
options_to_remove.append(launch_options[width_idx])
70+
height_idx = next((i for i, opt in enumerate(launch_options) if opt.startswith('--height=')), None)
71+
if height_idx is not None:
72+
cmd.append('-H')
73+
cmd.append(launch_options[height_idx].split('=')[1])
74+
options_to_remove.append(launch_options[height_idx])
2875
if '--fullscreen' in launch_options:
2976
cmd.append('-f')
30-
launch_options.remove('--fullscreen')
31-
else:
32-
cmd = []
77+
options_to_remove.append('--fullscreen')
3378
if '--bigpicture' in launch_options:
34-
launch_options.remove('--bigpicture') # Handled separately if needed
35-
if '--fullscreen' in launch_options:
36-
launch_options.append('-f')
37-
if runner == 'Native':
38-
cmd.extend([exe] + launch_options)
39-
subprocess.Popen(cmd)
40-
elif runner == 'Wine':
41-
env = os.environ.copy()
42-
env['WINEPREFIX'] = game['prefix']
43-
cmd.extend(['wine', exe] + launch_options)
44-
subprocess.Popen(cmd, env=env)
45-
elif runner == 'Flatpak':
46-
cmd.extend(['flatpak', 'run', exe] + launch_options)
47-
subprocess.Popen(cmd)
48-
elif runner == 'Snap':
49-
cmd.extend(['snap', 'run', exe] + launch_options)
50-
subprocess.Popen(cmd)
51-
else: # Proton
52-
proton_path = self.proton_manager.get_proton_path(runner)
53-
prefix = game['prefix']
54-
os.makedirs(prefix, exist_ok=True)
55-
env = os.environ.copy()
56-
env['STEAM_COMPAT_DATA_PATH'] = prefix
57-
cmd.extend([proton_path, 'run', exe] + launch_options)
58-
subprocess.Popen(cmd, env=env)
79+
cmd.extend(['-e', '-f'])
80+
options_to_remove.append('--bigpicture')
81+
for opt in options_to_remove:
82+
if opt in launch_options:
83+
launch_options.remove(opt)
84+
cmd.append('--')
85+
try:
86+
if runner == 'Native':
87+
cmd.extend([exe] + launch_options)
88+
elif runner == 'Wine':
89+
cmd.extend(['wine', exe] + launch_options)
90+
elif runner == 'Flatpak':
91+
if not shutil.which('flatpak'):
92+
raise Exception("Flatpak not installed.")
93+
cmd.extend(['flatpak', 'run', exe] + launch_options)
94+
elif runner == 'Snap':
95+
if not shutil.which('snap'):
96+
raise Exception("Snap not installed.")
97+
cmd.extend(['snap', 'run', exe] + launch_options)
98+
elif runner == 'Steam':
99+
app_id = game.get('app_id', '')
100+
if not app_id:
101+
raise Exception("Steam App ID not set.")
102+
cmd.extend(['steam', '-applaunch', app_id] + launch_options)
103+
else: # Proton
104+
proton_path = self.proton_manager.get_proton_path(runner)
105+
if not os.path.exists(proton_path):
106+
raise Exception(f"Proton binary not found for {runner}")
107+
env['STEAM_COMPAT_DATA_PATH'] = prefix
108+
# Set STEAM_COMPAT_CLIENT_INSTALL_PATH
109+
steam_dir = os.path.expanduser('~/.steam/steam')
110+
if not os.path.exists(steam_dir):
111+
steam_dir = os.path.expanduser('~/.local/share/Steam')
112+
if not os.path.exists(steam_dir):
113+
# Try Flatpak Steam
114+
steam_dir = os.path.expanduser('~/.var/app/com.valvesoftware.Steam/data/Steam')
115+
if not os.path.exists(steam_dir):
116+
raise Exception("Steam installation not found. Please ensure Steam is installed.")
117+
env['STEAM_COMPAT_CLIENT_INSTALL_PATH'] = steam_dir
118+
cmd.extend([proton_path, 'run', exe] + launch_options)
119+
# Additional Proton fallbacks
120+
if 'GE-Proton' in runner:
121+
try:
122+
subprocess.Popen(cmd, env=env)
123+
return
124+
except:
125+
cmd = [proton_path, 'waitforexitandrun', exe] + launch_options
126+
log_file = os.path.join(self.config_manager.logs_dir, f"{game['name'].replace(' ', '_')}.log")
127+
with open(log_file, 'w') as f:
128+
process = subprocess.Popen(cmd, env=env, stdout=f, stderr=f)
129+
logging.info(f"Launched game: {game['name']} with cmd: {' '.join(cmd)}")
130+
except Exception as e:
131+
logging.error(f"Failed to launch {game['name']}: {e}")
132+
raise

0 commit comments

Comments
 (0)