Files
Jackify/jackify/backend/handlers/wabbajack_verification.py
2026-02-07 18:26:54 +00:00

152 lines
8.3 KiB
Python

"""Verification methods for InstallWabbajackHandler (Mixin)."""
import logging
import shutil
from pathlib import Path
from typing import Optional
from .status_utils import clear_status, show_status
from .ui_colors import COLOR_ERROR, COLOR_INFO, COLOR_RESET
logger = logging.getLogger(__name__)
class WabbajackVerificationMixin:
"""Mixin providing verification and validation methods."""
def _find_steam_config_vdf(self) -> Optional[Path]:
"""Finds the path to the primary Steam config.vdf file."""
self.logger.debug("Searching for Steam config.vdf...")
common_paths = [
Path.home() / ".steam/steam/config/config.vdf",
Path.home() / ".local/share/Steam/config/config.vdf",
Path.home() / ".var/app/com.valvesoftware.Steam/.config/Valve Corporation/Steam/config/config.vdf"
]
for path in common_paths:
if path.is_file():
self.logger.info(f"Found config.vdf at: {path}")
return path
self.logger.error("Could not find Steam config.vdf in common locations.")
return None
def _verify_manual_steps(self) -> bool:
"""
Verifies that the user has performed the manual steps using ModlistHandler.
Checks AppID, Proton version set, and prefix existence.
Returns:
bool: True if verification passes AND compatdata_path is set, False otherwise.
"""
self.logger.info("Verifying manual Proton setup steps...")
self.compatdata_path = None
clear_status()
if not self._redetect_appid():
print(f"{COLOR_ERROR}Error: Could not find the Steam shortcut '{self.shortcut_name}' using protontricks.{COLOR_RESET}")
print(f"{COLOR_INFO}Ensure Steam has restarted and the shortcut is visible.{COLOR_RESET}")
return False
self.logger.debug(f"Verification using final AppID: {self.final_appid}")
show_status("Verifying Proton Setup")
if not hasattr(self, 'modlist_handler') or not self.modlist_handler:
self.logger.critical("ModlistHandler not initialized in InstallWabbajackHandler!")
self.logger.error("Internal Error: Modlist handler not available for verification.")
return False
verified, status_code = self.modlist_handler.verify_proton_setup(self.final_appid)
if not verified:
if status_code == 'wrong_proton_version':
proton_ver = getattr(self.modlist_handler, 'proton_ver', 'Unknown')
print(f"{COLOR_ERROR}\nVerification Failed: Incorrect Proton version detected ('{proton_ver}'). Expected 'Proton Experimental' (or similar).{COLOR_RESET}")
print(f"{COLOR_INFO}Please ensure you selected the correct Proton version in the shortcut's Compatibility properties.{COLOR_RESET}")
elif status_code == 'proton_check_failed':
print(f"{COLOR_ERROR}\nVerification Failed: Compatibility tool not detected as set for '{self.shortcut_name}' in Steam config.{COLOR_RESET}")
print(f"{COLOR_INFO}Please ensure you forced a Proton version in the shortcut's Compatibility properties.{COLOR_RESET}")
elif status_code == 'compatdata_missing':
print(f"{COLOR_ERROR}\nVerification Failed: Steam compatdata directory for AppID {self.final_appid} not found.{COLOR_RESET}")
print(f"{COLOR_INFO}Have you launched the shortcut '{self.shortcut_name}' at least once after setting Proton?{COLOR_RESET}")
elif status_code == 'prefix_missing':
print(f"{COLOR_ERROR}\nVerification Failed: Wine prefix directory (pfx) not found inside compatdata.{COLOR_RESET}")
print(f"{COLOR_INFO}This usually means the shortcut hasn't been launched successfully after setting Proton.{COLOR_RESET}")
elif status_code == 'config_vdf_missing' or status_code == 'config_vdf_error':
print(f"{COLOR_ERROR}\nVerification Failed: Could not read or parse Steam's config.vdf file ({status_code}).{COLOR_RESET}")
print(f"{COLOR_INFO}Check file permissions or integrity. Check logs for details.{COLOR_RESET}")
else:
print(f"{COLOR_ERROR}\nVerification Failed: An unexpected error occurred ({status_code}). Check logs.{COLOR_RESET}")
return False
self.logger.info("Basic verification checks passed. Confirming compatdata path...")
modlist_handler_compat_path = getattr(self.modlist_handler, 'compat_data_path', None)
if modlist_handler_compat_path:
self.compatdata_path = modlist_handler_compat_path
self.logger.info(f"Compatdata path obtained from ModlistHandler: {self.compatdata_path}")
else:
self.logger.info("ModlistHandler did not set compat_data_path. Attempting manual lookup via PathHandler.")
if not hasattr(self, 'path_handler') or not self.path_handler:
self.logger.critical("PathHandler not initialized in InstallWabbajackHandler!")
self.logger.error("Internal Error: Path handler not available for verification.")
return False
self.compatdata_path = self.path_handler.find_compat_data(self.final_appid)
if self.compatdata_path:
self.logger.info(f"Manually found compatdata path via PathHandler: {self.compatdata_path}")
else:
self.logger.error("Verification checks passed, but COULD NOT FIND compatdata path via ModlistHandler or PathHandler.")
print(f"\n{COLOR_ERROR}Verification Error: Basic checks passed, but failed to locate the compatdata directory for AppID {self.final_appid}.{COLOR_RESET}")
print(f"{COLOR_INFO}This is unexpected. Check Steam filesystem structure and logs.{COLOR_RESET}")
return False
self.logger.info("Manual steps verification successful (including path confirmation).")
logger.info(f"Verification successful! (AppID: {self.final_appid}, Path: {self.compatdata_path})")
return True
def _backup_and_replace_final_reg_files(self) -> bool:
"""Backs up current reg files and replaces them with the final downloaded versions."""
if not self.compatdata_path:
self.logger.error("Cannot backup/replace reg files: compatdata_path not set.")
return False
pfx_path = self.compatdata_path / 'pfx'
system_reg = pfx_path / 'system.reg'
user_reg = pfx_path / 'user.reg'
system_reg_bak = pfx_path / 'system.reg.orig'
user_reg_bak = pfx_path / 'user.reg.orig'
self.logger.info("Backing up existing registry files...")
logger.info("Backing up current registry files...")
try:
if system_reg.exists():
shutil.copy2(system_reg, system_reg_bak)
self.logger.debug(f"Backed up {system_reg} to {system_reg_bak}")
else:
self.logger.warning(f"Original {system_reg} not found for backup.")
if user_reg.exists():
shutil.copy2(user_reg, user_reg_bak)
self.logger.debug(f"Backed up {user_reg} to {user_reg_bak}")
else:
self.logger.warning(f"Original {user_reg} not found for backup.")
except Exception as e:
self.logger.error(f"Error backing up registry files: {e}", exc_info=True)
print(f"{COLOR_ERROR}Error backing up registry files: {e}{COLOR_RESET}")
return False
final_system_reg_url = "https://github.com/Omni-guides/Wabbajack-Modlist-Linux/raw/refs/heads/main/files/system.reg.github"
final_user_reg_url = "https://github.com/Omni-guides/Wabbajack-Modlist-Linux/raw/refs/heads/main/files/user.reg.github"
logger.info("Downloading and applying final registry settings...")
system_ok = self._download_and_replace_reg_file(final_system_reg_url, system_reg)
user_ok = self._download_and_replace_reg_file(final_user_reg_url, user_reg)
if system_ok and user_ok:
self.logger.info("Successfully applied final registry files.")
return True
else:
self.logger.error("Failed to download or replace one or both final registry files.")
self.logger.error("Failed to apply final registry settings.")
return False