mirror of
https://github.com/Omni-guides/Jackify.git
synced 2026-01-17 19:47:00 +01:00
Sync from development - prepare for v0.1.4
This commit is contained in:
@@ -38,6 +38,44 @@ class AutomatedPrefixService:
|
||||
"""Get consistent progress timestamp"""
|
||||
from jackify.shared.timing import get_timestamp
|
||||
return get_timestamp()
|
||||
|
||||
def _get_user_proton_version(self):
|
||||
"""Get user's preferred Proton version from config, with fallback to auto-detection"""
|
||||
try:
|
||||
from jackify.backend.handlers.config_handler import ConfigHandler
|
||||
from jackify.backend.handlers.wine_utils import WineUtils
|
||||
|
||||
config_handler = ConfigHandler()
|
||||
user_proton_path = config_handler.get('proton_path', 'auto')
|
||||
|
||||
if user_proton_path == 'auto':
|
||||
# Use enhanced fallback logic with GE-Proton preference
|
||||
logger.info("User selected auto-detect, using GE-Proton → Experimental → Proton precedence")
|
||||
return WineUtils.select_best_proton()
|
||||
else:
|
||||
# User has selected a specific Proton version
|
||||
# Use the exact directory name for Steam config.vdf
|
||||
try:
|
||||
proton_version = os.path.basename(user_proton_path)
|
||||
# GE-Proton uses exact directory name, Valve Proton needs lowercase conversion
|
||||
if proton_version.startswith('GE-Proton'):
|
||||
# Keep GE-Proton name exactly as-is
|
||||
steam_proton_name = proton_version
|
||||
else:
|
||||
# Convert Valve Proton names to Steam's format
|
||||
steam_proton_name = proton_version.lower().replace(' - ', '_').replace(' ', '_').replace('-', '_')
|
||||
if not steam_proton_name.startswith('proton'):
|
||||
steam_proton_name = f"proton_{steam_proton_name}"
|
||||
|
||||
logger.info(f"Using user-selected Proton: {steam_proton_name}")
|
||||
return steam_proton_name
|
||||
except Exception as e:
|
||||
logger.warning(f"Invalid user Proton path '{user_proton_path}', falling back to auto: {e}")
|
||||
return WineUtils.select_best_proton()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get user Proton preference, using default: {e}")
|
||||
return "proton_experimental"
|
||||
|
||||
|
||||
def create_shortcut_with_native_service(self, shortcut_name: str, exe_path: str,
|
||||
@@ -87,6 +125,9 @@ class AutomatedPrefixService:
|
||||
logger.warning(f"Could not generate STEAM_COMPAT_MOUNTS, using default: {e}")
|
||||
launch_options = "%command%"
|
||||
|
||||
# Get user's preferred Proton version
|
||||
proton_version = self._get_user_proton_version()
|
||||
|
||||
# Create shortcut with Proton using native service
|
||||
success, app_id = steam_service.create_shortcut_with_proton(
|
||||
app_name=shortcut_name,
|
||||
@@ -94,7 +135,7 @@ class AutomatedPrefixService:
|
||||
start_dir=modlist_install_dir,
|
||||
launch_options=launch_options,
|
||||
tags=["Jackify"],
|
||||
proton_version="proton_experimental"
|
||||
proton_version=proton_version
|
||||
)
|
||||
|
||||
if success and app_id:
|
||||
@@ -292,13 +333,13 @@ class AutomatedPrefixService:
|
||||
logger.error(f"Steam userdata directory not found: {userdata_dir}")
|
||||
return None
|
||||
|
||||
# Find the first user directory (most systems have only one user)
|
||||
user_dirs = [d for d in userdata_dir.iterdir() if d.is_dir() and d.name.isdigit()]
|
||||
# Find user directories (excluding user 0 which is a system account)
|
||||
user_dirs = [d for d in userdata_dir.iterdir() if d.is_dir() and d.name.isdigit() and d.name != "0"]
|
||||
if not user_dirs:
|
||||
logger.error("No Steam user directories found in userdata")
|
||||
logger.error("No valid Steam user directories found in userdata (user 0 is not valid)")
|
||||
return None
|
||||
|
||||
# Use the first user directory found
|
||||
# Use the first valid user directory found
|
||||
user_dir = user_dirs[0]
|
||||
shortcuts_path = user_dir / "config" / "shortcuts.vdf"
|
||||
|
||||
@@ -2499,8 +2540,8 @@ echo Prefix creation complete.
|
||||
# Try the standard Steam userdata path
|
||||
steam_userdata_path = Path.home() / ".steam" / "steam" / "userdata"
|
||||
if steam_userdata_path.exists():
|
||||
# Find the first user directory (usually only one on Steam Deck)
|
||||
user_dirs = [d for d in steam_userdata_path.iterdir() if d.is_dir() and d.name.isdigit()]
|
||||
# Find user directories (excluding user 0 which is a system account)
|
||||
user_dirs = [d for d in steam_userdata_path.iterdir() if d.is_dir() and d.name.isdigit() and d.name != "0"]
|
||||
if user_dirs:
|
||||
localconfig_path = user_dirs[0] / "config" / "localconfig.vdf"
|
||||
if localconfig_path.exists():
|
||||
@@ -2601,8 +2642,11 @@ echo Prefix creation complete.
|
||||
env = os.environ.copy()
|
||||
env['STEAM_COMPAT_CLIENT_INSTALL_PATH'] = str(steam_root)
|
||||
env['STEAM_COMPAT_DATA_PATH'] = str(compatdata_dir / str(abs(appid)))
|
||||
# Suppress GUI windows by unsetting DISPLAY
|
||||
# Suppress GUI windows using jackify-engine's proven approach
|
||||
env['DISPLAY'] = ''
|
||||
env['WAYLAND_DISPLAY'] = ''
|
||||
env['WINEDEBUG'] = '-all'
|
||||
env['WINEDLLOVERRIDES'] = 'msdia80.dll=n;conhost.exe=d;cmd.exe=d'
|
||||
|
||||
# Create the compatdata directory
|
||||
compat_dir = compatdata_dir / str(abs(appid))
|
||||
@@ -2616,7 +2660,9 @@ echo Prefix creation complete.
|
||||
cmd = [str(proton_path), 'run', 'wineboot', '-u']
|
||||
logger.info(f"Running: {' '.join(cmd)}")
|
||||
|
||||
result = subprocess.run(cmd, env=env, capture_output=True, text=True, timeout=60)
|
||||
# Use jackify-engine's approach: UseShellExecute=false, CreateNoWindow=true equivalent
|
||||
result = subprocess.run(cmd, env=env, capture_output=True, text=True, timeout=60,
|
||||
shell=False, creationflags=getattr(subprocess, 'CREATE_NO_WINDOW', 0))
|
||||
logger.info(f"Proton exit code: {result.returncode}")
|
||||
|
||||
if result.stdout:
|
||||
@@ -2718,26 +2764,39 @@ echo Prefix creation complete.
|
||||
|
||||
def verify_compatibility_tool_persists(self, appid: int) -> bool:
|
||||
"""
|
||||
Verify that the compatibility tool setting persists.
|
||||
|
||||
Verify that the compatibility tool setting persists with correct Proton version.
|
||||
|
||||
Args:
|
||||
appid: The AppID to check
|
||||
|
||||
|
||||
Returns:
|
||||
True if compatibility tool is set, False otherwise
|
||||
True if compatibility tool is correctly set, False otherwise
|
||||
"""
|
||||
try:
|
||||
config_path = Path.home() / ".steam/steam/config/config.vdf"
|
||||
with open(config_path, 'r') as f:
|
||||
if not config_path.exists():
|
||||
logger.warning("Steam config.vdf not found")
|
||||
return False
|
||||
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
|
||||
# Check if AppID exists and has a Proton version set
|
||||
if f'"{appid}"' in content:
|
||||
logger.info(" Compatibility tool persists")
|
||||
return True
|
||||
# Get the expected Proton version
|
||||
expected_proton = self._get_user_proton_version()
|
||||
|
||||
# Look for the Proton version in the compatibility tool mapping
|
||||
if expected_proton in content:
|
||||
logger.info(f" Compatibility tool persists: {expected_proton}")
|
||||
return True
|
||||
else:
|
||||
logger.warning(f"AppID {appid} found but Proton version '{expected_proton}' not set")
|
||||
return False
|
||||
else:
|
||||
logger.warning("Compatibility tool not found")
|
||||
return False
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error verifying compatibility tool: {e}")
|
||||
return False
|
||||
|
||||
@@ -40,13 +40,13 @@ class NativeSteamService:
|
||||
logger.error("Steam userdata directory not found")
|
||||
return False
|
||||
|
||||
# Find the first user directory (usually there's only one)
|
||||
user_dirs = [d for d in self.userdata_path.iterdir() if d.is_dir() and d.name.isdigit()]
|
||||
# Find user directories (excluding user 0 which is a system account)
|
||||
user_dirs = [d for d in self.userdata_path.iterdir() if d.is_dir() and d.name.isdigit() and d.name != "0"]
|
||||
if not user_dirs:
|
||||
logger.error("No Steam user directories found")
|
||||
logger.error("No valid Steam user directories found (user 0 is not valid for shortcuts)")
|
||||
return False
|
||||
|
||||
# Use the first user directory
|
||||
# Use the first valid user directory
|
||||
user_dir = user_dirs[0]
|
||||
self.user_id = user_dir.name
|
||||
self.user_config_path = user_dir / "config"
|
||||
@@ -327,17 +327,27 @@ class NativeSteamService:
|
||||
logger.error(f"Error setting Proton version: {e}")
|
||||
return False
|
||||
|
||||
def create_shortcut_with_proton(self, app_name: str, exe_path: str, start_dir: str = None,
|
||||
def create_shortcut_with_proton(self, app_name: str, exe_path: str, start_dir: str = None,
|
||||
launch_options: str = "%command%", tags: List[str] = None,
|
||||
proton_version: str = "proton_experimental") -> Tuple[bool, Optional[int]]:
|
||||
proton_version: str = None) -> Tuple[bool, Optional[int]]:
|
||||
"""
|
||||
Complete workflow: Create shortcut and set Proton version.
|
||||
|
||||
|
||||
This is the main method that replaces STL entirely.
|
||||
|
||||
|
||||
Returns:
|
||||
(success, app_id) - Success status and the AppID
|
||||
"""
|
||||
# Auto-detect best Proton version if none provided
|
||||
if proton_version is None:
|
||||
try:
|
||||
from jackify.backend.core.modlist_operations import _get_user_proton_version
|
||||
proton_version = _get_user_proton_version()
|
||||
logger.info(f"Auto-detected Proton version: {proton_version}")
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to auto-detect Proton, falling back to experimental: {e}")
|
||||
proton_version = "proton_experimental"
|
||||
|
||||
logger.info(f"Creating shortcut with Proton: '{app_name}' -> '{proton_version}'")
|
||||
|
||||
# Step 1: Create the shortcut
|
||||
|
||||
Reference in New Issue
Block a user