mirror of
https://github.com/Omni-guides/Jackify.git
synced 2026-01-17 11:37:01 +01:00
Sync from development - prepare for v0.1.7.1
This commit is contained in:
@@ -5,4 +5,4 @@ This package provides both CLI and GUI interfaces for managing
|
||||
Wabbajack modlists natively on Linux systems.
|
||||
"""
|
||||
|
||||
__version__ = "0.1.7"
|
||||
__version__ = "0.1.7.1"
|
||||
|
||||
@@ -100,7 +100,8 @@ class ConfigHandler:
|
||||
libraryfolders_vdf_paths = [
|
||||
os.path.expanduser("~/.steam/steam/config/libraryfolders.vdf"),
|
||||
os.path.expanduser("~/.local/share/Steam/config/libraryfolders.vdf"),
|
||||
os.path.expanduser("~/.steam/root/config/libraryfolders.vdf")
|
||||
os.path.expanduser("~/.steam/root/config/libraryfolders.vdf"),
|
||||
os.path.expanduser("~/.var/app/com.valvesoftware.Steam/.local/share/Steam/config/libraryfolders.vdf") # Flatpak
|
||||
]
|
||||
|
||||
for vdf_path in libraryfolders_vdf_paths:
|
||||
|
||||
@@ -784,7 +784,8 @@ class FileSystemHandler:
|
||||
possible_vdf_paths = [
|
||||
Path.home() / ".steam/steam/config/libraryfolders.vdf",
|
||||
Path.home() / ".local/share/Steam/config/libraryfolders.vdf",
|
||||
Path.home() / ".steam/root/config/libraryfolders.vdf"
|
||||
Path.home() / ".steam/root/config/libraryfolders.vdf",
|
||||
Path.home() / ".var/app/com.valvesoftware.Steam/.local/share/Steam/config/libraryfolders.vdf" # Flatpak
|
||||
]
|
||||
|
||||
libraryfolders_vdf_path: Optional[Path] = None
|
||||
|
||||
@@ -650,6 +650,10 @@ class ModlistMenuHandler:
|
||||
print("Modlist Install and Configuration complete!")
|
||||
print(f"• You should now be able to Launch '{context.get('name')}' through Steam")
|
||||
print("• Congratulations and enjoy the game!")
|
||||
print("")
|
||||
print("NOTE: If you experience ENB issues, consider using GE-Proton 10-14 instead of")
|
||||
print(" Valve's Proton 10 (known ENB compatibility issues in Valve's Proton 10).")
|
||||
print("")
|
||||
print("Detailed log available at: ~/Jackify/logs/Configure_New_Modlist_workflow.log")
|
||||
# Only wait for input in CLI mode, not GUI mode
|
||||
if not gui_mode:
|
||||
|
||||
@@ -329,22 +329,18 @@ class ModlistHandler:
|
||||
# On non-Steam Deck systems, /media mounts should use Z: drive, not D: drive
|
||||
is_on_sdcard_path = str(self.modlist_dir).startswith("/run/media") or str(self.modlist_dir).startswith("/media")
|
||||
|
||||
# DEBUG: Log SD card detection logic
|
||||
self.logger.debug(f"[SD_CARD_DEBUG] SD card detection for instance id={id(self)}:")
|
||||
self.logger.debug(f"[SD_CARD_DEBUG] modlist_dir: {self.modlist_dir}")
|
||||
self.logger.debug(f"[SD_CARD_DEBUG] is_on_sdcard_path: {is_on_sdcard_path}")
|
||||
self.logger.debug(f"[SD_CARD_DEBUG] self.steamdeck: {self.steamdeck}")
|
||||
# Log SD card detection for debugging
|
||||
self.logger.debug(f"SD card detection: modlist_dir={self.modlist_dir}, is_sdcard_path={is_on_sdcard_path}, steamdeck={self.steamdeck}")
|
||||
|
||||
if is_on_sdcard_path and self.steamdeck:
|
||||
self.modlist_sdcard = True
|
||||
self.logger.info("Modlist appears to be on an SD card (Steam Deck).")
|
||||
self.logger.debug(f"[SD_CARD_DEBUG] Set modlist_sdcard=True")
|
||||
self.logger.debug(f"Set modlist_sdcard=True")
|
||||
else:
|
||||
self.modlist_sdcard = False
|
||||
self.logger.debug(f"[SD_CARD_DEBUG] Set modlist_sdcard=False because: is_on_sdcard_path={is_on_sdcard_path} AND steamdeck={self.steamdeck}")
|
||||
self.logger.debug(f"Set modlist_sdcard=False (is_on_sdcard_path={is_on_sdcard_path}, steamdeck={self.steamdeck})")
|
||||
if is_on_sdcard_path and not self.steamdeck:
|
||||
self.logger.info("Modlist on /media mount detected on non-Steam Deck system - using Z: drive mapping.")
|
||||
self.logger.debug("[SD_CARD_DEBUG] This is the ROOT CAUSE - SD card path but steamdeck=False!")
|
||||
|
||||
# Find and set compatdata path now that we have appid
|
||||
# Ensure PathHandler is available (should be initialized in __init__)
|
||||
@@ -722,6 +718,8 @@ class ModlistHandler:
|
||||
success = self.winetricks_handler.install_wine_components(wineprefix, self.game_var_full, specific_components=components)
|
||||
if success:
|
||||
self.logger.info("Wine component installation completed successfully")
|
||||
if status_callback:
|
||||
status_callback(f"{self._get_progress_timestamp()} Wine components verified and installed successfully")
|
||||
else:
|
||||
self.logger.error("Wine component installation failed")
|
||||
print("Error: Failed to install necessary Wine components.")
|
||||
@@ -752,6 +750,19 @@ class ModlistHandler:
|
||||
self.logger.error("=" * 80)
|
||||
# Continue but user should be aware of potential issues
|
||||
|
||||
# Step 4.6: Enable dotfiles visibility for Wine prefix
|
||||
if status_callback:
|
||||
status_callback(f"{self._get_progress_timestamp()} Enabling dotfiles visibility")
|
||||
self.logger.info("Step 4.6: Enabling dotfiles visibility in Wine prefix...")
|
||||
try:
|
||||
if self.protontricks_handler.enable_dotfiles(self.appid):
|
||||
self.logger.info("Dotfiles visibility enabled successfully")
|
||||
else:
|
||||
self.logger.warning("Failed to enable dotfiles visibility (non-critical, continuing)")
|
||||
except Exception as e:
|
||||
self.logger.warning(f"Error enabling dotfiles visibility: {e} (non-critical, continuing)")
|
||||
self.logger.info("Step 4.6: Enabling dotfiles visibility... Done")
|
||||
|
||||
# Step 5: Ensure permissions of Modlist directory
|
||||
if status_callback:
|
||||
status_callback(f"{self._get_progress_timestamp()} Setting ownership and permissions for modlist directory")
|
||||
|
||||
@@ -390,7 +390,7 @@ class PathHandler:
|
||||
libraryfolders_vdf_paths = [
|
||||
os.path.expanduser("~/.steam/steam/config/libraryfolders.vdf"),
|
||||
os.path.expanduser("~/.local/share/Steam/config/libraryfolders.vdf"),
|
||||
# Add other potential standard locations if necessary
|
||||
os.path.expanduser("~/.var/app/com.valvesoftware.Steam/.local/share/Steam/config/libraryfolders.vdf"), # Flatpak
|
||||
]
|
||||
|
||||
# Simple backup mechanism (optional but good practice)
|
||||
@@ -622,7 +622,9 @@ class PathHandler:
|
||||
m = re.search(r'"path"\s*"([^"]+)"', line)
|
||||
if m:
|
||||
lib_path = Path(m.group(1))
|
||||
library_paths.add(lib_path)
|
||||
# Resolve symlinks for consistency (mmcblk0p1 -> deck/UUID)
|
||||
resolved_path = lib_path.resolve()
|
||||
library_paths.add(resolved_path)
|
||||
except Exception as e:
|
||||
logger.error(f"[DEBUG] Failed to parse {vdf_path}: {e}")
|
||||
logger.info(f"[DEBUG] All detected Steam libraries: {library_paths}")
|
||||
@@ -871,10 +873,9 @@ class PathHandler:
|
||||
else:
|
||||
found_stock = None
|
||||
for folder in STOCK_GAME_FOLDERS:
|
||||
folder_pattern = f"/{folder.replace(' ', '')}".lower()
|
||||
value_part_lower = value_part.replace(' ', '').lower()
|
||||
if folder_pattern in value_part_lower:
|
||||
idx = value_part_lower.index(folder_pattern)
|
||||
folder_pattern = f"/{folder}"
|
||||
if folder_pattern in value_part:
|
||||
idx = value_part.index(folder_pattern)
|
||||
rel_path = value_part[idx:].lstrip('/')
|
||||
found_stock = folder
|
||||
break
|
||||
|
||||
@@ -117,23 +117,21 @@ class ProtontricksHandler:
|
||||
try:
|
||||
# PyInstaller fix: Comprehensive environment cleaning for subprocess calls
|
||||
env = self._get_clean_subprocess_env()
|
||||
|
||||
|
||||
result = subprocess.run(
|
||||
["flatpak", "list"],
|
||||
capture_output=True,
|
||||
["flatpak", "list"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL, # Suppress stderr to avoid error messages when flatpak not installed
|
||||
text=True,
|
||||
check=True,
|
||||
env=env # Use comprehensively cleaned environment
|
||||
)
|
||||
if "com.github.Matoking.protontricks" in result.stdout:
|
||||
if result.returncode == 0 and "com.github.Matoking.protontricks" in result.stdout:
|
||||
logger.info("Flatpak Protontricks is installed")
|
||||
self.which_protontricks = 'flatpak'
|
||||
flatpak_installed = True
|
||||
return True
|
||||
except FileNotFoundError:
|
||||
logger.warning("'flatpak' command not found. Cannot check for Flatpak Protontricks.")
|
||||
except subprocess.CalledProcessError as e:
|
||||
logger.warning(f"Error checking flatpak list: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error checking flatpak: {e}")
|
||||
|
||||
@@ -707,8 +705,15 @@ class ProtontricksHandler:
|
||||
result = self.run_protontricks("--no-bwrap", appid, "-q", *components_to_install, env=env, timeout=600)
|
||||
self.logger.debug(f"Protontricks output: {result.stdout if result else ''}")
|
||||
if result and result.returncode == 0:
|
||||
self.logger.info("Wine Component installation command completed successfully.")
|
||||
return True
|
||||
self.logger.info("Wine Component installation command completed.")
|
||||
|
||||
# Verify components were actually installed
|
||||
if self._verify_components_installed(appid, components_to_install):
|
||||
self.logger.info("Component verification successful - all components installed correctly.")
|
||||
return True
|
||||
else:
|
||||
self.logger.error(f"Component verification failed (Attempt {attempt}/{max_attempts})")
|
||||
# Continue to retry
|
||||
else:
|
||||
self.logger.error(f"Protontricks command failed (Attempt {attempt}/{max_attempts}). Return Code: {result.returncode if result else 'N/A'}")
|
||||
self.logger.error(f"Stdout: {result.stdout.strip() if result else ''}")
|
||||
@@ -718,14 +723,73 @@ class ProtontricksHandler:
|
||||
self.logger.error(f"Failed to install Wine components after {max_attempts} attempts.")
|
||||
return False
|
||||
|
||||
def _verify_components_installed(self, appid: str, components: List[str]) -> bool:
|
||||
"""
|
||||
Verify that Wine components were actually installed by querying protontricks.
|
||||
|
||||
Args:
|
||||
appid: Steam AppID
|
||||
components: List of components that should be installed
|
||||
|
||||
Returns:
|
||||
bool: True if all critical components are verified, False otherwise
|
||||
"""
|
||||
try:
|
||||
self.logger.info("Verifying installed components...")
|
||||
|
||||
# Run protontricks list-installed to get actual installed components
|
||||
result = self.run_protontricks("--no-bwrap", appid, "list-installed", timeout=30)
|
||||
|
||||
if not result or result.returncode != 0:
|
||||
self.logger.error("Failed to query installed components")
|
||||
self.logger.debug(f"list-installed stderr: {result.stderr if result else 'N/A'}")
|
||||
return False
|
||||
|
||||
installed_output = result.stdout.lower()
|
||||
self.logger.debug(f"Installed components output: {installed_output}")
|
||||
|
||||
# Define critical components that MUST be installed
|
||||
# These are the core components that determine success
|
||||
critical_components = ["vcrun2022", "xact"]
|
||||
|
||||
# Check for critical components
|
||||
missing_critical = []
|
||||
for component in critical_components:
|
||||
if component.lower() not in installed_output:
|
||||
missing_critical.append(component)
|
||||
|
||||
if missing_critical:
|
||||
self.logger.error(f"CRITICAL: Missing essential components: {missing_critical}")
|
||||
self.logger.error("Installation reported success but components are NOT installed")
|
||||
return False
|
||||
|
||||
# Check for requested components (warn but don't fail)
|
||||
missing_requested = []
|
||||
for component in components:
|
||||
# Handle settings like fontsmooth=rgb (just check the base component name)
|
||||
base_component = component.split('=')[0].lower()
|
||||
if base_component not in installed_output and component.lower() not in installed_output:
|
||||
missing_requested.append(component)
|
||||
|
||||
if missing_requested:
|
||||
self.logger.warning(f"Some requested components may not be installed: {missing_requested}")
|
||||
self.logger.warning("This may cause issues, but critical components are present")
|
||||
|
||||
self.logger.info(f"Verification passed - critical components confirmed: {critical_components}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error verifying components: {e}", exc_info=True)
|
||||
return False
|
||||
|
||||
def _cleanup_wine_processes(self):
|
||||
"""
|
||||
Internal method to clean up wine processes during component installation
|
||||
"""
|
||||
try:
|
||||
subprocess.run("pgrep -f 'win7|win10|ShowDotFiles|protontricks' | xargs -r kill -9",
|
||||
subprocess.run("pgrep -f 'win7|win10|ShowDotFiles|protontricks' | xargs -r kill -9",
|
||||
shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
subprocess.run("pkill -9 winetricks",
|
||||
subprocess.run("pkill -9 winetricks",
|
||||
shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
except Exception as e:
|
||||
logger.error(f"Error cleaning up wine processes: {e}")
|
||||
|
||||
@@ -200,40 +200,55 @@ class WineUtils:
|
||||
@staticmethod
|
||||
def _get_sd_card_mounts():
|
||||
"""
|
||||
Dynamically detect all current SD card mount points
|
||||
Returns list of mount point paths
|
||||
Detect SD card mount points using df.
|
||||
Returns list of actual mount paths from /run/media (e.g., /run/media/deck/MicroSD).
|
||||
"""
|
||||
try:
|
||||
import subprocess
|
||||
result = subprocess.run(['df', '-h'], capture_output=True, text=True, timeout=5)
|
||||
sd_mounts = []
|
||||
for line in result.stdout.split('\n'):
|
||||
# Look for common SD card mount patterns
|
||||
if '/run/media' in line or ('/mnt' in line and 'sdcard' in line.lower()):
|
||||
parts = line.split()
|
||||
if len(parts) >= 6: # df output has 6+ columns
|
||||
mount_point = parts[-1] # Last column is mount point
|
||||
if mount_point.startswith(('/run/media', '/mnt')):
|
||||
sd_mounts.append(mount_point)
|
||||
return sd_mounts
|
||||
except Exception:
|
||||
# Fallback to common patterns if df fails
|
||||
return ['/run/media/mmcblk0p1', '/run/media/deck']
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
result = subprocess.run(['df', '-h'], capture_output=True, text=True, timeout=5)
|
||||
sd_mounts = []
|
||||
|
||||
for line in result.stdout.split('\n'):
|
||||
if '/run/media' in line:
|
||||
parts = line.split()
|
||||
if len(parts) >= 6:
|
||||
mount_point = parts[-1] # Last column is the mount point
|
||||
if mount_point.startswith('/run/media/'):
|
||||
sd_mounts.append(mount_point)
|
||||
|
||||
# Sort by length (longest first) to match most specific paths first
|
||||
sd_mounts.sort(key=len, reverse=True)
|
||||
logger.debug(f"Detected SD card mounts from df: {sd_mounts}")
|
||||
return sd_mounts
|
||||
|
||||
@staticmethod
|
||||
def _strip_sdcard_path(path):
|
||||
"""
|
||||
Strip any detected SD card mount prefix from paths
|
||||
Handles both /run/media/mmcblk0p1 and /run/media/deck/UUID patterns
|
||||
Strip SD card mount prefix from path.
|
||||
Handles both /run/media/mmcblk0p1 and /run/media/deck/UUID patterns.
|
||||
Pattern: /run/media/deck/UUID/Games/... becomes /Games/...
|
||||
Pattern: /run/media/mmcblk0p1/Games/... becomes /Games/...
|
||||
"""
|
||||
sd_mounts = WineUtils._get_sd_card_mounts()
|
||||
import re
|
||||
|
||||
for mount in sd_mounts:
|
||||
if path.startswith(mount):
|
||||
# Strip the mount prefix and ensure proper leading slash
|
||||
relative_path = path[len(mount):].lstrip('/')
|
||||
return "/" + relative_path if relative_path else "/"
|
||||
# Pattern 1: /run/media/deck/UUID/... strip everything up to and including UUID
|
||||
# This matches the bash: "${path#*/run/media/deck/*/*}"
|
||||
deck_pattern = r'^/run/media/deck/[^/]+(/.*)?$'
|
||||
match = re.match(deck_pattern, path)
|
||||
if match:
|
||||
stripped = match.group(1) if match.group(1) else "/"
|
||||
logger.debug(f"Stripped SD card path (deck pattern): {path} -> {stripped}")
|
||||
return stripped
|
||||
|
||||
# Pattern 2: /run/media/mmcblk0p1/... strip /run/media/mmcblk0p1
|
||||
# This matches the bash: "${path#*mmcblk0p1}"
|
||||
if path.startswith('/run/media/mmcblk0p1/'):
|
||||
stripped = path.replace('/run/media/mmcblk0p1', '', 1)
|
||||
logger.debug(f"Stripped SD card path (mmcblk pattern): {path} -> {stripped}")
|
||||
return stripped
|
||||
|
||||
# No SD card pattern matched
|
||||
return path
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -349,10 +349,17 @@ class WinetricksHandler:
|
||||
|
||||
self.logger.debug(f"Winetricks output: {result.stdout}")
|
||||
if result.returncode == 0:
|
||||
self.logger.info("Wine Component installation command completed successfully.")
|
||||
# Set Windows 10 mode after component installation (matches legacy script timing)
|
||||
self._set_windows_10_mode(wineprefix, env.get('WINE', ''))
|
||||
return True
|
||||
self.logger.info("Wine Component installation command completed.")
|
||||
|
||||
# Verify components were actually installed
|
||||
if self._verify_components_installed(wineprefix, components_to_install, env):
|
||||
self.logger.info("Component verification successful - all components installed correctly.")
|
||||
# Set Windows 10 mode after component installation (matches legacy script timing)
|
||||
self._set_windows_10_mode(wineprefix, env.get('WINE', ''))
|
||||
return True
|
||||
else:
|
||||
self.logger.error(f"Component verification failed (Attempt {attempt}/{max_attempts})")
|
||||
# Continue to retry
|
||||
else:
|
||||
# Special handling for dotnet40 verification issue (mimics protontricks behavior)
|
||||
if "dotnet40" in components_to_install and "ngen.exe not found" in result.stderr:
|
||||
@@ -430,11 +437,36 @@ class WinetricksHandler:
|
||||
if winetricks_failed:
|
||||
self.logger.error(f"Winetricks failed after {max_attempts} attempts.")
|
||||
|
||||
# Check if protontricks is available for fallback
|
||||
# Network diagnostics before fallback (non-fatal)
|
||||
self.logger.warning("=" * 80)
|
||||
self.logger.warning("NETWORK DIAGNOSTICS: Testing connectivity to component download sources...")
|
||||
try:
|
||||
protontricks_check = subprocess.run(['which', 'protontricks'],
|
||||
capture_output=True, text=True, timeout=5)
|
||||
if protontricks_check.returncode == 0:
|
||||
# Check if curl is available
|
||||
curl_check = subprocess.run(['which', 'curl'], capture_output=True, timeout=5)
|
||||
if curl_check.returncode == 0:
|
||||
# Test Microsoft download servers (used by winetricks for .NET, VC runtimes, DirectX)
|
||||
test_result = subprocess.run(['curl', '-I', '--max-time', '10', 'https://download.microsoft.com'],
|
||||
capture_output=True, text=True, timeout=15)
|
||||
if test_result.returncode == 0:
|
||||
self.logger.warning("Can reach download.microsoft.com")
|
||||
else:
|
||||
self.logger.error("Cannot reach download.microsoft.com - network/DNS issue likely")
|
||||
self.logger.error(f" Curl exit code: {test_result.returncode}")
|
||||
if test_result.stderr:
|
||||
self.logger.error(f" Curl error: {test_result.stderr.strip()}")
|
||||
else:
|
||||
self.logger.warning("curl not available, skipping network diagnostic test")
|
||||
except Exception as e:
|
||||
self.logger.warning(f"Network diagnostic test skipped: {e}")
|
||||
self.logger.warning("=" * 80)
|
||||
|
||||
# Check if protontricks is available for fallback using centralized handler
|
||||
try:
|
||||
from .protontricks_handler import ProtontricksHandler
|
||||
protontricks_handler = ProtontricksHandler()
|
||||
protontricks_available = protontricks_handler.is_available()
|
||||
|
||||
if protontricks_available:
|
||||
self.logger.warning("=" * 80)
|
||||
self.logger.warning("AUTOMATIC FALLBACK: Winetricks failed, attempting protontricks fallback...")
|
||||
self.logger.warning(f"Last winetricks error: {last_error_details}")
|
||||
@@ -721,13 +753,6 @@ class WinetricksHandler:
|
||||
|
||||
if success:
|
||||
self.logger.info(f"Legacy .NET components {legacy_components} installed successfully with protontricks")
|
||||
|
||||
# Enable dotfiles and symlinks for the prefix
|
||||
if protontricks_handler.enable_dotfiles(appid):
|
||||
self.logger.info("Enabled dotfiles and symlinks support")
|
||||
else:
|
||||
self.logger.warning("Failed to enable dotfiles/symlinks (non-critical)")
|
||||
|
||||
return True
|
||||
else:
|
||||
self.logger.error(f"Legacy .NET components {legacy_components} installation failed with protontricks")
|
||||
@@ -844,11 +869,18 @@ class WinetricksHandler:
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
self.logger.info(f"Winetricks components installed successfully: {components}")
|
||||
# Set Windows 10 mode after component installation (matches legacy script timing)
|
||||
wine_binary = env.get('WINE', '')
|
||||
self._set_windows_10_mode(env.get('WINEPREFIX', ''), wine_binary)
|
||||
return True
|
||||
self.logger.info(f"Winetricks components installation command completed.")
|
||||
|
||||
# Verify components were actually installed
|
||||
if self._verify_components_installed(wineprefix, components, env):
|
||||
self.logger.info("Component verification successful - all components installed correctly.")
|
||||
# Set Windows 10 mode after component installation (matches legacy script timing)
|
||||
wine_binary = env.get('WINE', '')
|
||||
self._set_windows_10_mode(env.get('WINEPREFIX', ''), wine_binary)
|
||||
return True
|
||||
else:
|
||||
self.logger.error(f"Component verification failed (attempt {attempt})")
|
||||
# Continue to retry
|
||||
else:
|
||||
self.logger.error(f"Winetricks failed (attempt {attempt}): {result.stderr.strip()}")
|
||||
|
||||
@@ -992,6 +1024,70 @@ class WinetricksHandler:
|
||||
self.logger.error(f"Error getting wine binary for prefix: {e}")
|
||||
return ""
|
||||
|
||||
def _verify_components_installed(self, wineprefix: str, components: List[str], env: dict) -> bool:
|
||||
"""
|
||||
Verify that Wine components were actually installed by checking winetricks.log.
|
||||
|
||||
Args:
|
||||
wineprefix: Wine prefix path
|
||||
components: List of components that should be installed
|
||||
env: Environment variables (includes WINE path)
|
||||
|
||||
Returns:
|
||||
bool: True if all critical components are verified, False otherwise
|
||||
"""
|
||||
try:
|
||||
self.logger.info("Verifying installed components...")
|
||||
|
||||
# Check winetricks.log file for installed components
|
||||
winetricks_log = os.path.join(wineprefix, 'winetricks.log')
|
||||
|
||||
if not os.path.exists(winetricks_log):
|
||||
self.logger.error(f"winetricks.log not found at {winetricks_log}")
|
||||
return False
|
||||
|
||||
try:
|
||||
with open(winetricks_log, 'r', encoding='utf-8', errors='ignore') as f:
|
||||
log_content = f.read().lower()
|
||||
except Exception as e:
|
||||
self.logger.error(f"Failed to read winetricks.log: {e}")
|
||||
return False
|
||||
|
||||
self.logger.debug(f"winetricks.log length: {len(log_content)} bytes")
|
||||
|
||||
# Define critical components that MUST be installed
|
||||
critical_components = ["vcrun2022", "xact"]
|
||||
|
||||
# Check for critical components
|
||||
missing_critical = []
|
||||
for component in critical_components:
|
||||
if component.lower() not in log_content:
|
||||
missing_critical.append(component)
|
||||
|
||||
if missing_critical:
|
||||
self.logger.error(f"CRITICAL: Missing essential components: {missing_critical}")
|
||||
self.logger.error("Installation reported success but components are NOT in winetricks.log")
|
||||
return False
|
||||
|
||||
# Check for requested components (warn but don't fail)
|
||||
missing_requested = []
|
||||
for component in components:
|
||||
# Handle settings like fontsmooth=rgb (just check the base component name)
|
||||
base_component = component.split('=')[0].lower()
|
||||
if base_component not in log_content and component.lower() not in log_content:
|
||||
missing_requested.append(component)
|
||||
|
||||
if missing_requested:
|
||||
self.logger.warning(f"Some requested components may not be installed: {missing_requested}")
|
||||
self.logger.warning("This may cause issues, but critical components are present")
|
||||
|
||||
self.logger.info(f"Verification passed - critical components confirmed: {critical_components}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error verifying components: {e}", exc_info=True)
|
||||
return False
|
||||
|
||||
def _cleanup_wine_processes(self):
|
||||
"""
|
||||
Internal method to clean up wine processes during component installation
|
||||
|
||||
@@ -2904,10 +2904,21 @@ echo Prefix creation complete.
|
||||
"""Find a Steam game installation path by AppID and common names"""
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# Get Steam libraries from libraryfolders.vdf
|
||||
steam_config_path = Path.home() / ".steam/steam/config/libraryfolders.vdf"
|
||||
if not steam_config_path.exists():
|
||||
|
||||
# Get Steam libraries from libraryfolders.vdf - check multiple possible locations
|
||||
possible_config_paths = [
|
||||
Path.home() / ".steam/steam/config/libraryfolders.vdf",
|
||||
Path.home() / ".local/share/Steam/config/libraryfolders.vdf",
|
||||
Path.home() / ".var/app/com.valvesoftware.Steam/.local/share/Steam/config/libraryfolders.vdf" # Flatpak
|
||||
]
|
||||
|
||||
steam_config_path = None
|
||||
for path in possible_config_paths:
|
||||
if path.exists():
|
||||
steam_config_path = path
|
||||
break
|
||||
|
||||
if not steam_config_path:
|
||||
return None
|
||||
|
||||
steam_libraries = []
|
||||
|
||||
@@ -135,6 +135,9 @@ class NativeSteamOperationsService:
|
||||
steam_locations = [
|
||||
Path.home() / ".steam/steam",
|
||||
Path.home() / ".local/share/Steam",
|
||||
# Flatpak Steam - direct data directory
|
||||
Path.home() / ".var/app/com.valvesoftware.Steam/.local/share/Steam",
|
||||
# Flatpak Steam - symlinked home paths
|
||||
Path.home() / ".var/app/com.valvesoftware.Steam/home/.steam/steam",
|
||||
Path.home() / ".var/app/com.valvesoftware.Steam/home/.local/share/Steam"
|
||||
]
|
||||
@@ -161,6 +164,9 @@ class NativeSteamOperationsService:
|
||||
standard_locations = [
|
||||
Path.home() / ".steam/steam/steamapps/compatdata",
|
||||
Path.home() / ".local/share/Steam/steamapps/compatdata",
|
||||
# Flatpak Steam - direct data directory
|
||||
Path.home() / ".var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/compatdata",
|
||||
# Flatpak Steam - symlinked home paths
|
||||
Path.home() / ".var/app/com.valvesoftware.Steam/home/.steam/steam/steamapps/compatdata",
|
||||
Path.home() / ".var/app/com.valvesoftware.Steam/home/.local/share/Steam/steamapps/compatdata"
|
||||
]
|
||||
|
||||
@@ -127,20 +127,18 @@ class ProtontricksDetectionService:
|
||||
try:
|
||||
env = handler._get_clean_subprocess_env()
|
||||
result = subprocess.run(
|
||||
["flatpak", "list"],
|
||||
capture_output=True,
|
||||
["flatpak", "list"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL, # Suppress stderr to avoid error messages
|
||||
text=True,
|
||||
check=True,
|
||||
env=env
|
||||
)
|
||||
if "com.github.Matoking.protontricks" in result.stdout:
|
||||
if result.returncode == 0 and "com.github.Matoking.protontricks" in result.stdout:
|
||||
logger.info("Flatpak Protontricks is installed")
|
||||
handler.which_protontricks = 'flatpak'
|
||||
return True
|
||||
except FileNotFoundError:
|
||||
logger.warning("'flatpak' command not found. Cannot check for Flatpak Protontricks.")
|
||||
except subprocess.CalledProcessError as e:
|
||||
logger.warning(f"Error checking flatpak list: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error checking flatpak: {e}")
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import signal
|
||||
import psutil
|
||||
import logging
|
||||
import sys
|
||||
import shutil
|
||||
from typing import Callable, Optional
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -86,6 +87,25 @@ def is_steam_deck() -> bool:
|
||||
logger.debug(f"Error detecting Steam Deck: {e}")
|
||||
return False
|
||||
|
||||
def is_flatpak_steam() -> bool:
|
||||
"""Detect if Steam is installed as a Flatpak."""
|
||||
try:
|
||||
# First check if flatpak command exists
|
||||
if not shutil.which('flatpak'):
|
||||
return False
|
||||
|
||||
# Verify the app is actually installed (not just directory exists)
|
||||
result = subprocess.run(['flatpak', 'list', '--app'],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL, # Suppress stderr to avoid error messages
|
||||
text=True,
|
||||
timeout=5)
|
||||
if result.returncode == 0 and 'com.valvesoftware.Steam' in result.stdout:
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.debug(f"Error detecting Flatpak Steam: {e}")
|
||||
return False
|
||||
|
||||
def get_steam_processes() -> list:
|
||||
"""Return a list of psutil.Process objects for running Steam processes."""
|
||||
steam_procs = []
|
||||
@@ -122,16 +142,37 @@ def start_steam() -> bool:
|
||||
"""Attempt to start Steam using the exact methods from existing working logic."""
|
||||
env = _get_clean_subprocess_env()
|
||||
try:
|
||||
# Try systemd user service (Steam Deck)
|
||||
# Try systemd user service (Steam Deck) - HIGHEST PRIORITY
|
||||
if is_steam_deck():
|
||||
subprocess.Popen(["systemctl", "--user", "restart", "app-steam@autostart.service"], env=env)
|
||||
return True
|
||||
|
||||
|
||||
# Check if Flatpak Steam (only if not Steam Deck)
|
||||
if is_flatpak_steam():
|
||||
logger.info("Flatpak Steam detected - using flatpak run command")
|
||||
try:
|
||||
# Redirect flatpak's stderr to suppress "app not installed" errors on systems without flatpak Steam
|
||||
# Steam's own stdout/stderr will still go through (flatpak forwards them)
|
||||
subprocess.Popen(["flatpak", "run", "com.valvesoftware.Steam", "-silent"],
|
||||
env=env, stderr=subprocess.DEVNULL)
|
||||
time.sleep(5)
|
||||
check_result = subprocess.run(['pgrep', '-f', 'steam'], capture_output=True, timeout=10, env=env)
|
||||
if check_result.returncode == 0:
|
||||
logger.info("Flatpak Steam process detected after start.")
|
||||
return True
|
||||
else:
|
||||
logger.warning("Flatpak Steam process not detected after start attempt.")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"Error starting Flatpak Steam: {e}")
|
||||
return False
|
||||
|
||||
# Use startup methods with only -silent flag (no -minimized or -no-browser)
|
||||
# Don't redirect stdout/stderr or use start_new_session to allow Steam to connect to display/tray
|
||||
start_methods = [
|
||||
{"name": "Popen", "cmd": ["steam", "-silent"], "kwargs": {"stdout": subprocess.DEVNULL, "stderr": subprocess.DEVNULL, "stdin": subprocess.DEVNULL, "start_new_session": True, "env": env}},
|
||||
{"name": "setsid", "cmd": ["setsid", "steam", "-silent"], "kwargs": {"stdout": subprocess.DEVNULL, "stderr": subprocess.DEVNULL, "stdin": subprocess.DEVNULL, "env": env}},
|
||||
{"name": "nohup", "cmd": ["nohup", "steam", "-silent"], "kwargs": {"stdout": subprocess.DEVNULL, "stderr": subprocess.DEVNULL, "stdin": subprocess.DEVNULL, "start_new_session": True, "preexec_fn": os.setpgrp, "env": env}}
|
||||
{"name": "Popen", "cmd": ["steam", "-silent"], "kwargs": {"env": env}},
|
||||
{"name": "setsid", "cmd": ["setsid", "steam", "-silent"], "kwargs": {"env": env}},
|
||||
{"name": "nohup", "cmd": ["nohup", "steam", "-silent"], "kwargs": {"preexec_fn": os.setpgrp, "env": env}}
|
||||
]
|
||||
|
||||
for method in start_methods:
|
||||
@@ -174,17 +215,26 @@ def robust_steam_restart(progress_callback: Optional[Callable[[str], None]] = No
|
||||
progress_callback(msg)
|
||||
|
||||
report("Shutting down Steam...")
|
||||
|
||||
# Steam Deck: Use systemctl for shutdown (special handling)
|
||||
|
||||
# Steam Deck: Use systemctl for shutdown (special handling) - HIGHEST PRIORITY
|
||||
if is_steam_deck():
|
||||
try:
|
||||
report("Steam Deck detected - using systemctl shutdown...")
|
||||
subprocess.run(['systemctl', '--user', 'stop', 'app-steam@autostart.service'],
|
||||
subprocess.run(['systemctl', '--user', 'stop', 'app-steam@autostart.service'],
|
||||
timeout=15, check=False, capture_output=True, env=env)
|
||||
time.sleep(2)
|
||||
except Exception as e:
|
||||
logger.debug(f"systemctl stop failed on Steam Deck: {e}")
|
||||
|
||||
# Flatpak Steam: Use flatpak kill command (only if not Steam Deck)
|
||||
elif is_flatpak_steam():
|
||||
try:
|
||||
report("Flatpak Steam detected - stopping via flatpak...")
|
||||
subprocess.run(['flatpak', 'kill', 'com.valvesoftware.Steam'],
|
||||
timeout=15, check=False, capture_output=True, stderr=subprocess.DEVNULL, env=env)
|
||||
time.sleep(2)
|
||||
except Exception as e:
|
||||
logger.debug(f"flatpak kill failed: {e}")
|
||||
|
||||
# All systems: Use pkill approach (proven 15/16 test success rate)
|
||||
try:
|
||||
# Skip unreliable steam -shutdown, go straight to pkill
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -7,7 +7,7 @@
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v8.0": {},
|
||||
".NETCoreApp,Version=v8.0/linux-x64": {
|
||||
"jackify-engine/0.3.17": {
|
||||
"jackify-engine/0.3.18": {
|
||||
"dependencies": {
|
||||
"Markdig": "0.40.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "9.0.1",
|
||||
@@ -22,16 +22,16 @@
|
||||
"SixLabors.ImageSharp": "3.1.6",
|
||||
"System.CommandLine": "2.0.0-beta4.22272.1",
|
||||
"System.CommandLine.NamingConventionBinder": "2.0.0-beta4.22272.1",
|
||||
"Wabbajack.CLI.Builder": "0.3.17",
|
||||
"Wabbajack.Downloaders.Bethesda": "0.3.17",
|
||||
"Wabbajack.Downloaders.Dispatcher": "0.3.17",
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.17",
|
||||
"Wabbajack.Networking.Discord": "0.3.17",
|
||||
"Wabbajack.Networking.GitHub": "0.3.17",
|
||||
"Wabbajack.Paths.IO": "0.3.17",
|
||||
"Wabbajack.Server.Lib": "0.3.17",
|
||||
"Wabbajack.Services.OSIntegrated": "0.3.17",
|
||||
"Wabbajack.VFS": "0.3.17",
|
||||
"Wabbajack.CLI.Builder": "0.3.18",
|
||||
"Wabbajack.Downloaders.Bethesda": "0.3.18",
|
||||
"Wabbajack.Downloaders.Dispatcher": "0.3.18",
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.18",
|
||||
"Wabbajack.Networking.Discord": "0.3.18",
|
||||
"Wabbajack.Networking.GitHub": "0.3.18",
|
||||
"Wabbajack.Paths.IO": "0.3.18",
|
||||
"Wabbajack.Server.Lib": "0.3.18",
|
||||
"Wabbajack.Services.OSIntegrated": "0.3.18",
|
||||
"Wabbajack.VFS": "0.3.18",
|
||||
"MegaApiClient": "1.0.0.0",
|
||||
"runtimepack.Microsoft.NETCore.App.Runtime.linux-x64": "8.0.19"
|
||||
},
|
||||
@@ -1781,7 +1781,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Wabbajack.CLI.Builder/0.3.17": {
|
||||
"Wabbajack.CLI.Builder/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Json": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
@@ -1791,109 +1791,109 @@
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"System.CommandLine": "2.0.0-beta4.22272.1",
|
||||
"System.CommandLine.NamingConventionBinder": "2.0.0-beta4.22272.1",
|
||||
"Wabbajack.Paths": "0.3.17"
|
||||
"Wabbajack.Paths": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.CLI.Builder.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Common/0.3.17": {
|
||||
"Wabbajack.Common/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"System.Reactive": "6.0.1",
|
||||
"Wabbajack.DTOs": "0.3.17",
|
||||
"Wabbajack.Networking.Http": "0.3.17",
|
||||
"Wabbajack.Paths.IO": "0.3.17"
|
||||
"Wabbajack.DTOs": "0.3.18",
|
||||
"Wabbajack.Networking.Http": "0.3.18",
|
||||
"Wabbajack.Paths.IO": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Common.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Compiler/0.3.17": {
|
||||
"Wabbajack.Compiler/0.3.18": {
|
||||
"dependencies": {
|
||||
"F23.StringSimilarity": "6.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Newtonsoft.Json": "13.0.3",
|
||||
"SixLabors.ImageSharp": "3.1.6",
|
||||
"Wabbajack.Downloaders.Dispatcher": "0.3.17",
|
||||
"Wabbajack.Installer": "0.3.17",
|
||||
"Wabbajack.VFS": "0.3.17",
|
||||
"Wabbajack.Downloaders.Dispatcher": "0.3.18",
|
||||
"Wabbajack.Installer": "0.3.18",
|
||||
"Wabbajack.VFS": "0.3.18",
|
||||
"ini-parser-netstandard": "2.5.2"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Compiler.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Compression.BSA/0.3.17": {
|
||||
"Wabbajack.Compression.BSA/0.3.18": {
|
||||
"dependencies": {
|
||||
"K4os.Compression.LZ4.Streams": "1.3.8",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"SharpZipLib": "1.4.2",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.DTOs": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.DTOs": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Compression.BSA.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Compression.Zip/0.3.17": {
|
||||
"Wabbajack.Compression.Zip/0.3.18": {
|
||||
"dependencies": {
|
||||
"Wabbajack.IO.Async": "0.3.17"
|
||||
"Wabbajack.IO.Async": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Compression.Zip.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Configuration/0.3.17": {
|
||||
"Wabbajack.Configuration/0.3.18": {
|
||||
"runtime": {
|
||||
"Wabbajack.Configuration.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.Bethesda/0.3.17": {
|
||||
"Wabbajack.Downloaders.Bethesda/0.3.18": {
|
||||
"dependencies": {
|
||||
"LibAES-CTR": "1.1.0",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"SharpZipLib": "1.4.2",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.17",
|
||||
"Wabbajack.Networking.BethesdaNet": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.18",
|
||||
"Wabbajack.Networking.BethesdaNet": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.Bethesda.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.Dispatcher/0.3.17": {
|
||||
"Wabbajack.Downloaders.Dispatcher/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Newtonsoft.Json": "13.0.3",
|
||||
"SixLabors.ImageSharp": "3.1.6",
|
||||
"Wabbajack.Downloaders.Bethesda": "0.3.17",
|
||||
"Wabbajack.Downloaders.GameFile": "0.3.17",
|
||||
"Wabbajack.Downloaders.GoogleDrive": "0.3.17",
|
||||
"Wabbajack.Downloaders.Http": "0.3.17",
|
||||
"Wabbajack.Downloaders.IPS4OAuth2Downloader": "0.3.17",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.17",
|
||||
"Wabbajack.Downloaders.Manual": "0.3.17",
|
||||
"Wabbajack.Downloaders.MediaFire": "0.3.17",
|
||||
"Wabbajack.Downloaders.Mega": "0.3.17",
|
||||
"Wabbajack.Downloaders.ModDB": "0.3.17",
|
||||
"Wabbajack.Downloaders.Nexus": "0.3.17",
|
||||
"Wabbajack.Downloaders.VerificationCache": "0.3.17",
|
||||
"Wabbajack.Downloaders.WabbajackCDN": "0.3.17",
|
||||
"Wabbajack.Networking.WabbajackClientApi": "0.3.17"
|
||||
"Wabbajack.Downloaders.Bethesda": "0.3.18",
|
||||
"Wabbajack.Downloaders.GameFile": "0.3.18",
|
||||
"Wabbajack.Downloaders.GoogleDrive": "0.3.18",
|
||||
"Wabbajack.Downloaders.Http": "0.3.18",
|
||||
"Wabbajack.Downloaders.IPS4OAuth2Downloader": "0.3.18",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.18",
|
||||
"Wabbajack.Downloaders.Manual": "0.3.18",
|
||||
"Wabbajack.Downloaders.MediaFire": "0.3.18",
|
||||
"Wabbajack.Downloaders.Mega": "0.3.18",
|
||||
"Wabbajack.Downloaders.ModDB": "0.3.18",
|
||||
"Wabbajack.Downloaders.Nexus": "0.3.18",
|
||||
"Wabbajack.Downloaders.VerificationCache": "0.3.18",
|
||||
"Wabbajack.Downloaders.WabbajackCDN": "0.3.18",
|
||||
"Wabbajack.Networking.WabbajackClientApi": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.Dispatcher.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.GameFile/0.3.17": {
|
||||
"Wabbajack.Downloaders.GameFile/0.3.18": {
|
||||
"dependencies": {
|
||||
"GameFinder.StoreHandlers.EADesktop": "4.5.0",
|
||||
"GameFinder.StoreHandlers.EGS": "4.5.0",
|
||||
@@ -1903,360 +1903,360 @@
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"SixLabors.ImageSharp": "3.1.6",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.17",
|
||||
"Wabbajack.VFS": "0.3.17"
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.18",
|
||||
"Wabbajack.VFS": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.GameFile.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.GoogleDrive/0.3.17": {
|
||||
"Wabbajack.Downloaders.GoogleDrive/0.3.18": {
|
||||
"dependencies": {
|
||||
"HtmlAgilityPack": "1.11.72",
|
||||
"Microsoft.AspNetCore.Http.Extensions": "2.3.0",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.DTOs": "0.3.17",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.17",
|
||||
"Wabbajack.Networking.Http": "0.3.17",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.DTOs": "0.3.18",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.18",
|
||||
"Wabbajack.Networking.Http": "0.3.18",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.GoogleDrive.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.Http/0.3.17": {
|
||||
"Wabbajack.Downloaders.Http/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.DTOs": "0.3.17",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.17",
|
||||
"Wabbajack.Networking.BethesdaNet": "0.3.17",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.17",
|
||||
"Wabbajack.Paths.IO": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.DTOs": "0.3.18",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.18",
|
||||
"Wabbajack.Networking.BethesdaNet": "0.3.18",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.18",
|
||||
"Wabbajack.Paths.IO": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.Http.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.Interfaces/0.3.17": {
|
||||
"Wabbajack.Downloaders.Interfaces/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Wabbajack.Compression.Zip": "0.3.17",
|
||||
"Wabbajack.DTOs": "0.3.17",
|
||||
"Wabbajack.Paths.IO": "0.3.17"
|
||||
"Wabbajack.Compression.Zip": "0.3.18",
|
||||
"Wabbajack.DTOs": "0.3.18",
|
||||
"Wabbajack.Paths.IO": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.Interfaces.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.IPS4OAuth2Downloader/0.3.17": {
|
||||
"Wabbajack.Downloaders.IPS4OAuth2Downloader/0.3.18": {
|
||||
"dependencies": {
|
||||
"F23.StringSimilarity": "6.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.17",
|
||||
"Wabbajack.Networking.Http": "0.3.17",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.18",
|
||||
"Wabbajack.Networking.Http": "0.3.18",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.IPS4OAuth2Downloader.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.Manual/0.3.17": {
|
||||
"Wabbajack.Downloaders.Manual/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.Manual.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.MediaFire/0.3.17": {
|
||||
"Wabbajack.Downloaders.MediaFire/0.3.18": {
|
||||
"dependencies": {
|
||||
"HtmlAgilityPack": "1.11.72",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.17",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.18",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.MediaFire.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.Mega/0.3.17": {
|
||||
"Wabbajack.Downloaders.Mega/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Newtonsoft.Json": "13.0.3",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.17",
|
||||
"Wabbajack.Paths.IO": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.18",
|
||||
"Wabbajack.Paths.IO": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.Mega.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.ModDB/0.3.17": {
|
||||
"Wabbajack.Downloaders.ModDB/0.3.18": {
|
||||
"dependencies": {
|
||||
"HtmlAgilityPack": "1.11.72",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Newtonsoft.Json": "13.0.3",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.17",
|
||||
"Wabbajack.Networking.Http": "0.3.17",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.18",
|
||||
"Wabbajack.Networking.Http": "0.3.18",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.ModDB.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.Nexus/0.3.17": {
|
||||
"Wabbajack.Downloaders.Nexus/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Wabbajack.DTOs": "0.3.17",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.17",
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.17",
|
||||
"Wabbajack.Networking.Http": "0.3.17",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.17",
|
||||
"Wabbajack.Networking.NexusApi": "0.3.17",
|
||||
"Wabbajack.Paths": "0.3.17"
|
||||
"Wabbajack.DTOs": "0.3.18",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.18",
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.18",
|
||||
"Wabbajack.Networking.Http": "0.3.18",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.18",
|
||||
"Wabbajack.Networking.NexusApi": "0.3.18",
|
||||
"Wabbajack.Paths": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.Nexus.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.VerificationCache/0.3.17": {
|
||||
"Wabbajack.Downloaders.VerificationCache/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Stub.System.Data.SQLite.Core.NetStandard": "1.0.119",
|
||||
"Wabbajack.DTOs": "0.3.17",
|
||||
"Wabbajack.Paths.IO": "0.3.17"
|
||||
"Wabbajack.DTOs": "0.3.18",
|
||||
"Wabbajack.Paths.IO": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.VerificationCache.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Downloaders.WabbajackCDN/0.3.17": {
|
||||
"Wabbajack.Downloaders.WabbajackCDN/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Microsoft.Toolkit.HighPerformance": "7.1.2",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.17",
|
||||
"Wabbajack.Networking.Http": "0.3.17",
|
||||
"Wabbajack.RateLimiter": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.18",
|
||||
"Wabbajack.Networking.Http": "0.3.18",
|
||||
"Wabbajack.RateLimiter": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Downloaders.WabbajackCDN.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.DTOs/0.3.17": {
|
||||
"Wabbajack.DTOs/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.17",
|
||||
"Wabbajack.Paths": "0.3.17"
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.18",
|
||||
"Wabbajack.Paths": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.DTOs.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.FileExtractor/0.3.17": {
|
||||
"Wabbajack.FileExtractor/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"OMODFramework": "3.0.1",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.Compression.BSA": "0.3.17",
|
||||
"Wabbajack.Hashing.PHash": "0.3.17",
|
||||
"Wabbajack.Paths": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.Compression.BSA": "0.3.18",
|
||||
"Wabbajack.Hashing.PHash": "0.3.18",
|
||||
"Wabbajack.Paths": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.FileExtractor.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Hashing.PHash/0.3.17": {
|
||||
"Wabbajack.Hashing.PHash/0.3.18": {
|
||||
"dependencies": {
|
||||
"BCnEncoder.Net.ImageSharp": "1.1.1",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Shipwreck.Phash": "0.5.0",
|
||||
"SixLabors.ImageSharp": "3.1.6",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.DTOs": "0.3.17",
|
||||
"Wabbajack.Paths": "0.3.17",
|
||||
"Wabbajack.Paths.IO": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.DTOs": "0.3.18",
|
||||
"Wabbajack.Paths": "0.3.18",
|
||||
"Wabbajack.Paths.IO": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Hashing.PHash.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Hashing.xxHash64/0.3.17": {
|
||||
"Wabbajack.Hashing.xxHash64/0.3.18": {
|
||||
"dependencies": {
|
||||
"Wabbajack.Paths": "0.3.17",
|
||||
"Wabbajack.RateLimiter": "0.3.17"
|
||||
"Wabbajack.Paths": "0.3.18",
|
||||
"Wabbajack.RateLimiter": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Hashing.xxHash64.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Installer/0.3.17": {
|
||||
"Wabbajack.Installer/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Newtonsoft.Json": "13.0.3",
|
||||
"Octopus.Octodiff": "2.0.548",
|
||||
"SixLabors.ImageSharp": "3.1.6",
|
||||
"Wabbajack.DTOs": "0.3.17",
|
||||
"Wabbajack.Downloaders.Dispatcher": "0.3.17",
|
||||
"Wabbajack.Downloaders.GameFile": "0.3.17",
|
||||
"Wabbajack.FileExtractor": "0.3.17",
|
||||
"Wabbajack.Networking.WabbajackClientApi": "0.3.17",
|
||||
"Wabbajack.Paths": "0.3.17",
|
||||
"Wabbajack.Paths.IO": "0.3.17",
|
||||
"Wabbajack.VFS": "0.3.17",
|
||||
"Wabbajack.DTOs": "0.3.18",
|
||||
"Wabbajack.Downloaders.Dispatcher": "0.3.18",
|
||||
"Wabbajack.Downloaders.GameFile": "0.3.18",
|
||||
"Wabbajack.FileExtractor": "0.3.18",
|
||||
"Wabbajack.Networking.WabbajackClientApi": "0.3.18",
|
||||
"Wabbajack.Paths": "0.3.18",
|
||||
"Wabbajack.Paths.IO": "0.3.18",
|
||||
"Wabbajack.VFS": "0.3.18",
|
||||
"ini-parser-netstandard": "2.5.2"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Installer.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.IO.Async/0.3.17": {
|
||||
"Wabbajack.IO.Async/0.3.18": {
|
||||
"runtime": {
|
||||
"Wabbajack.IO.Async.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Networking.BethesdaNet/0.3.17": {
|
||||
"Wabbajack.Networking.BethesdaNet/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Wabbajack.DTOs": "0.3.17",
|
||||
"Wabbajack.Networking.Http": "0.3.17",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.17"
|
||||
"Wabbajack.DTOs": "0.3.18",
|
||||
"Wabbajack.Networking.Http": "0.3.18",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Networking.BethesdaNet.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Networking.Discord/0.3.17": {
|
||||
"Wabbajack.Networking.Discord/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.17"
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Networking.Discord.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Networking.GitHub/0.3.17": {
|
||||
"Wabbajack.Networking.GitHub/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Octokit": "14.0.0",
|
||||
"Wabbajack.DTOs": "0.3.17",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.17"
|
||||
"Wabbajack.DTOs": "0.3.18",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Networking.GitHub.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Networking.Http/0.3.17": {
|
||||
"Wabbajack.Networking.Http/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Http": "9.0.1",
|
||||
"Microsoft.Extensions.Logging": "9.0.1",
|
||||
"Wabbajack.Configuration": "0.3.17",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.17",
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.17",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.17",
|
||||
"Wabbajack.Paths": "0.3.17",
|
||||
"Wabbajack.Paths.IO": "0.3.17"
|
||||
"Wabbajack.Configuration": "0.3.18",
|
||||
"Wabbajack.Downloaders.Interfaces": "0.3.18",
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.18",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.18",
|
||||
"Wabbajack.Paths": "0.3.18",
|
||||
"Wabbajack.Paths.IO": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Networking.Http.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Networking.Http.Interfaces/0.3.17": {
|
||||
"Wabbajack.Networking.Http.Interfaces/0.3.18": {
|
||||
"dependencies": {
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.17"
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Networking.Http.Interfaces.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Networking.NexusApi/0.3.17": {
|
||||
"Wabbajack.Networking.NexusApi/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Wabbajack.DTOs": "0.3.17",
|
||||
"Wabbajack.Networking.Http": "0.3.17",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.17",
|
||||
"Wabbajack.Networking.WabbajackClientApi": "0.3.17"
|
||||
"Wabbajack.DTOs": "0.3.18",
|
||||
"Wabbajack.Networking.Http": "0.3.18",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.18",
|
||||
"Wabbajack.Networking.WabbajackClientApi": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Networking.NexusApi.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Networking.WabbajackClientApi/0.3.17": {
|
||||
"Wabbajack.Networking.WabbajackClientApi/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"Octokit": "14.0.0",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.DTOs": "0.3.17",
|
||||
"Wabbajack.Paths.IO": "0.3.17",
|
||||
"Wabbajack.VFS.Interfaces": "0.3.17",
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.DTOs": "0.3.18",
|
||||
"Wabbajack.Paths.IO": "0.3.18",
|
||||
"Wabbajack.VFS.Interfaces": "0.3.18",
|
||||
"YamlDotNet": "16.3.0"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Networking.WabbajackClientApi.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Paths/0.3.17": {
|
||||
"Wabbajack.Paths/0.3.18": {
|
||||
"runtime": {
|
||||
"Wabbajack.Paths.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Paths.IO/0.3.17": {
|
||||
"Wabbajack.Paths.IO/0.3.18": {
|
||||
"dependencies": {
|
||||
"Wabbajack.Paths": "0.3.17",
|
||||
"Wabbajack.Paths": "0.3.18",
|
||||
"shortid": "4.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Paths.IO.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.RateLimiter/0.3.17": {
|
||||
"Wabbajack.RateLimiter/0.3.18": {
|
||||
"runtime": {
|
||||
"Wabbajack.RateLimiter.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Server.Lib/0.3.17": {
|
||||
"Wabbajack.Server.Lib/0.3.18": {
|
||||
"dependencies": {
|
||||
"FluentFTP": "52.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
@@ -2264,58 +2264,58 @@
|
||||
"Nettle": "3.0.0",
|
||||
"Newtonsoft.Json": "13.0.3",
|
||||
"SixLabors.ImageSharp": "3.1.6",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.17",
|
||||
"Wabbajack.Services.OSIntegrated": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.Networking.Http.Interfaces": "0.3.18",
|
||||
"Wabbajack.Services.OSIntegrated": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Server.Lib.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.Services.OSIntegrated/0.3.17": {
|
||||
"Wabbajack.Services.OSIntegrated/0.3.18": {
|
||||
"dependencies": {
|
||||
"DeviceId": "6.8.0",
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Newtonsoft.Json": "13.0.3",
|
||||
"SixLabors.ImageSharp": "3.1.6",
|
||||
"Wabbajack.Compiler": "0.3.17",
|
||||
"Wabbajack.Downloaders.Dispatcher": "0.3.17",
|
||||
"Wabbajack.Installer": "0.3.17",
|
||||
"Wabbajack.Networking.BethesdaNet": "0.3.17",
|
||||
"Wabbajack.Networking.Discord": "0.3.17",
|
||||
"Wabbajack.VFS": "0.3.17"
|
||||
"Wabbajack.Compiler": "0.3.18",
|
||||
"Wabbajack.Downloaders.Dispatcher": "0.3.18",
|
||||
"Wabbajack.Installer": "0.3.18",
|
||||
"Wabbajack.Networking.BethesdaNet": "0.3.18",
|
||||
"Wabbajack.Networking.Discord": "0.3.18",
|
||||
"Wabbajack.VFS": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.Services.OSIntegrated.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.VFS/0.3.17": {
|
||||
"Wabbajack.VFS/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "9.0.1",
|
||||
"SixLabors.ImageSharp": "3.1.6",
|
||||
"System.Data.SQLite.Core": "1.0.119",
|
||||
"Wabbajack.Common": "0.3.17",
|
||||
"Wabbajack.FileExtractor": "0.3.17",
|
||||
"Wabbajack.Hashing.PHash": "0.3.17",
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.17",
|
||||
"Wabbajack.Paths": "0.3.17",
|
||||
"Wabbajack.Paths.IO": "0.3.17",
|
||||
"Wabbajack.VFS.Interfaces": "0.3.17"
|
||||
"Wabbajack.Common": "0.3.18",
|
||||
"Wabbajack.FileExtractor": "0.3.18",
|
||||
"Wabbajack.Hashing.PHash": "0.3.18",
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.18",
|
||||
"Wabbajack.Paths": "0.3.18",
|
||||
"Wabbajack.Paths.IO": "0.3.18",
|
||||
"Wabbajack.VFS.Interfaces": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.VFS.dll": {}
|
||||
}
|
||||
},
|
||||
"Wabbajack.VFS.Interfaces/0.3.17": {
|
||||
"Wabbajack.VFS.Interfaces/0.3.18": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection": "9.0.1",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1",
|
||||
"Wabbajack.DTOs": "0.3.17",
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.17",
|
||||
"Wabbajack.Paths": "0.3.17"
|
||||
"Wabbajack.DTOs": "0.3.18",
|
||||
"Wabbajack.Hashing.xxHash64": "0.3.18",
|
||||
"Wabbajack.Paths": "0.3.18"
|
||||
},
|
||||
"runtime": {
|
||||
"Wabbajack.VFS.Interfaces.dll": {}
|
||||
@@ -2332,7 +2332,7 @@
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"jackify-engine/0.3.17": {
|
||||
"jackify-engine/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
@@ -3021,202 +3021,202 @@
|
||||
"path": "yamldotnet/16.3.0",
|
||||
"hashPath": "yamldotnet.16.3.0.nupkg.sha512"
|
||||
},
|
||||
"Wabbajack.CLI.Builder/0.3.17": {
|
||||
"Wabbajack.CLI.Builder/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Common/0.3.17": {
|
||||
"Wabbajack.Common/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Compiler/0.3.17": {
|
||||
"Wabbajack.Compiler/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Compression.BSA/0.3.17": {
|
||||
"Wabbajack.Compression.BSA/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Compression.Zip/0.3.17": {
|
||||
"Wabbajack.Compression.Zip/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Configuration/0.3.17": {
|
||||
"Wabbajack.Configuration/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.Bethesda/0.3.17": {
|
||||
"Wabbajack.Downloaders.Bethesda/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.Dispatcher/0.3.17": {
|
||||
"Wabbajack.Downloaders.Dispatcher/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.GameFile/0.3.17": {
|
||||
"Wabbajack.Downloaders.GameFile/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.GoogleDrive/0.3.17": {
|
||||
"Wabbajack.Downloaders.GoogleDrive/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.Http/0.3.17": {
|
||||
"Wabbajack.Downloaders.Http/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.Interfaces/0.3.17": {
|
||||
"Wabbajack.Downloaders.Interfaces/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.IPS4OAuth2Downloader/0.3.17": {
|
||||
"Wabbajack.Downloaders.IPS4OAuth2Downloader/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.Manual/0.3.17": {
|
||||
"Wabbajack.Downloaders.Manual/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.MediaFire/0.3.17": {
|
||||
"Wabbajack.Downloaders.MediaFire/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.Mega/0.3.17": {
|
||||
"Wabbajack.Downloaders.Mega/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.ModDB/0.3.17": {
|
||||
"Wabbajack.Downloaders.ModDB/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.Nexus/0.3.17": {
|
||||
"Wabbajack.Downloaders.Nexus/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.VerificationCache/0.3.17": {
|
||||
"Wabbajack.Downloaders.VerificationCache/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Downloaders.WabbajackCDN/0.3.17": {
|
||||
"Wabbajack.Downloaders.WabbajackCDN/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.DTOs/0.3.17": {
|
||||
"Wabbajack.DTOs/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.FileExtractor/0.3.17": {
|
||||
"Wabbajack.FileExtractor/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Hashing.PHash/0.3.17": {
|
||||
"Wabbajack.Hashing.PHash/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Hashing.xxHash64/0.3.17": {
|
||||
"Wabbajack.Hashing.xxHash64/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Installer/0.3.17": {
|
||||
"Wabbajack.Installer/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.IO.Async/0.3.17": {
|
||||
"Wabbajack.IO.Async/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Networking.BethesdaNet/0.3.17": {
|
||||
"Wabbajack.Networking.BethesdaNet/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Networking.Discord/0.3.17": {
|
||||
"Wabbajack.Networking.Discord/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Networking.GitHub/0.3.17": {
|
||||
"Wabbajack.Networking.GitHub/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Networking.Http/0.3.17": {
|
||||
"Wabbajack.Networking.Http/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Networking.Http.Interfaces/0.3.17": {
|
||||
"Wabbajack.Networking.Http.Interfaces/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Networking.NexusApi/0.3.17": {
|
||||
"Wabbajack.Networking.NexusApi/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Networking.WabbajackClientApi/0.3.17": {
|
||||
"Wabbajack.Networking.WabbajackClientApi/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Paths/0.3.17": {
|
||||
"Wabbajack.Paths/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Paths.IO/0.3.17": {
|
||||
"Wabbajack.Paths.IO/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.RateLimiter/0.3.17": {
|
||||
"Wabbajack.RateLimiter/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Server.Lib/0.3.17": {
|
||||
"Wabbajack.Server.Lib/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.Services.OSIntegrated/0.3.17": {
|
||||
"Wabbajack.Services.OSIntegrated/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.VFS/0.3.17": {
|
||||
"Wabbajack.VFS/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Wabbajack.VFS.Interfaces/0.3.17": {
|
||||
"Wabbajack.VFS.Interfaces/0.3.18": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
|
||||
Binary file not shown.
BIN
jackify/engine/test.png
Normal file
BIN
jackify/engine/test.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 335 B |
@@ -183,7 +183,7 @@ class NextStepsDialog(QDialog):
|
||||
def _build_completion_text(self) -> str:
|
||||
"""
|
||||
Build the completion text matching the CLI version from menu_handler.py.
|
||||
|
||||
|
||||
Returns:
|
||||
Formatted completion text string
|
||||
"""
|
||||
@@ -195,6 +195,9 @@ Modlist Install and Configuration complete!:
|
||||
• You should now be able to Launch '{self.modlist_name}' through Steam.
|
||||
• Congratulations and enjoy the game!
|
||||
|
||||
NOTE: If you experience ENB issues, consider using GE-Proton 10-14 instead of
|
||||
Valve's Proton 10 (known ENB compatibility issues in Valve's Proton 10).
|
||||
|
||||
Detailed log available at: ~/Jackify/logs/Configure_New_Modlist_workflow.log"""
|
||||
|
||||
|
||||
return completion_text
|
||||
@@ -40,12 +40,12 @@ class SuccessDialog(QDialog):
|
||||
self.setWindowTitle("Success!")
|
||||
self.setWindowModality(Qt.NonModal)
|
||||
self.setAttribute(Qt.WA_ShowWithoutActivating, True)
|
||||
self.setFixedSize(500, 420)
|
||||
self.setFixedSize(500, 500)
|
||||
self.setWindowFlag(Qt.WindowDoesNotAcceptFocus, True)
|
||||
self.setStyleSheet("QDialog { background: #181818; color: #fff; border-radius: 12px; }" )
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setSpacing(0)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setContentsMargins(30, 30, 30, 30)
|
||||
|
||||
# --- Card background for content ---
|
||||
card = QFrame(self)
|
||||
@@ -53,6 +53,7 @@ class SuccessDialog(QDialog):
|
||||
card.setFrameShape(QFrame.StyledPanel)
|
||||
card.setFrameShadow(QFrame.Raised)
|
||||
card.setFixedWidth(440)
|
||||
card.setMinimumHeight(380)
|
||||
card_layout = QVBoxLayout(card)
|
||||
card_layout.setSpacing(12)
|
||||
card_layout.setContentsMargins(28, 28, 28, 28)
|
||||
@@ -65,23 +66,6 @@ class SuccessDialog(QDialog):
|
||||
)
|
||||
card.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
|
||||
# Trophy icon (smaller, more subtle)
|
||||
trophy_label = QLabel()
|
||||
trophy_label.setAlignment(Qt.AlignCenter)
|
||||
trophy_icon_path = Path(__file__).parent.parent.parent.parent.parent / "Files" / "trophy.png"
|
||||
if trophy_icon_path.exists():
|
||||
pixmap = QPixmap(str(trophy_icon_path)).scaled(36, 36, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
||||
trophy_label.setPixmap(pixmap)
|
||||
else:
|
||||
trophy_label.setText("✓")
|
||||
trophy_label.setStyleSheet(
|
||||
"QLabel { "
|
||||
" font-size: 28px; "
|
||||
" margin-bottom: 4px; "
|
||||
"}"
|
||||
)
|
||||
card_layout.addWidget(trophy_label)
|
||||
|
||||
# Success title (less saturated green)
|
||||
title_label = QLabel("Success!")
|
||||
title_label.setAlignment(Qt.AlignCenter)
|
||||
@@ -137,11 +121,12 @@ class SuccessDialog(QDialog):
|
||||
next_steps_label = QLabel(next_steps_text)
|
||||
next_steps_label.setAlignment(Qt.AlignCenter)
|
||||
next_steps_label.setWordWrap(True)
|
||||
next_steps_label.setMinimumHeight(100)
|
||||
next_steps_label.setStyleSheet(
|
||||
"QLabel { "
|
||||
" font-size: 13px; "
|
||||
" color: #b0b0b0; "
|
||||
" line-height: 1.2; "
|
||||
" line-height: 1.4; "
|
||||
" padding: 6px; "
|
||||
" background-color: transparent; "
|
||||
" border-radius: 6px; "
|
||||
@@ -232,15 +217,22 @@ class SuccessDialog(QDialog):
|
||||
def _build_next_steps(self) -> str:
|
||||
"""
|
||||
Build the next steps guidance based on workflow type.
|
||||
|
||||
|
||||
Returns:
|
||||
Formatted next steps string
|
||||
"""
|
||||
game_display = self.game_name or self.modlist_name
|
||||
|
||||
base_message = ""
|
||||
if self.workflow_type == "tuxborn":
|
||||
return f"You can now launch Tuxborn from Steam and enjoy your modded {game_display} experience!"
|
||||
base_message = f"You can now launch Tuxborn from Steam and enjoy your modded {game_display} experience!"
|
||||
else:
|
||||
return f"You can now launch {self.modlist_name} from Steam and enjoy your modded {game_display} experience!"
|
||||
base_message = f"You can now launch {self.modlist_name} from Steam and enjoy your modded {game_display} experience!"
|
||||
|
||||
# Add GE-Proton recommendation
|
||||
proton_note = "\n\nNOTE: If you experience ENB issues, consider using GE-Proton 10-14 instead of Valve's Proton 10 (known ENB compatibility issues)."
|
||||
|
||||
return base_message + proton_note
|
||||
|
||||
def _update_countdown(self):
|
||||
if self._countdown > 0:
|
||||
|
||||
Reference in New Issue
Block a user