mirror of
https://github.com/Omni-guides/Jackify.git
synced 2026-01-17 11:37:01 +01:00
Prepare v0.1.0 for public release
- Reorganize wiki images into structured folders - Remove old UserGuides directory structure - Update CHANGELOG and README for first release - Engine updates and GUI improvements
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.0.32"
|
||||
__version__ = "0.1.0"
|
||||
|
||||
@@ -443,7 +443,7 @@ exit"""
|
||||
try:
|
||||
# Use the existing protontricks handler
|
||||
from jackify.backend.handlers.protontricks_handler import ProtontricksHandler
|
||||
protontricks_handler = ProtontricksHandler(steamdeck=False)
|
||||
protontricks_handler = ProtontricksHandler(steamdeck=steamdeck or False)
|
||||
result = protontricks_handler.run_protontricks('-l')
|
||||
|
||||
if result.returncode == 0:
|
||||
@@ -1718,21 +1718,23 @@ echo Prefix creation complete.
|
||||
progress_callback("=== Steam Integration ===")
|
||||
progress_callback(f"{self._get_progress_timestamp()} Creating Steam shortcut with native service")
|
||||
|
||||
# DISABLED: Special game launch options - now using registry injection approach
|
||||
# from ..handlers.modlist_handler import ModlistHandler
|
||||
# modlist_handler = ModlistHandler()
|
||||
# special_game_type = modlist_handler.detect_special_game_type(modlist_install_dir)
|
||||
#
|
||||
# # Generate complete launch options for special games
|
||||
# custom_launch_options = None
|
||||
# if special_game_type in ["fnv", "enderal"]:
|
||||
# custom_launch_options = self._generate_special_game_launch_options(special_game_type, modlist_install_dir)
|
||||
# if not custom_launch_options:
|
||||
# logger.error(f"Failed to generate launch options for {special_game_type.upper()} modlist")
|
||||
# return False, None, None, None
|
||||
# Dual approach: Registry injection for FNV, launch options for Enderal
|
||||
from ..handlers.modlist_handler import ModlistHandler
|
||||
modlist_handler = ModlistHandler()
|
||||
special_game_type = modlist_handler.detect_special_game_type(modlist_install_dir)
|
||||
|
||||
# All modlists now use standard shortcut creation without custom launch options
|
||||
# Generate launch options only for Enderal (FNV uses registry injection)
|
||||
custom_launch_options = None
|
||||
if special_game_type == "enderal":
|
||||
custom_launch_options = self._generate_special_game_launch_options(special_game_type, modlist_install_dir)
|
||||
if not custom_launch_options:
|
||||
logger.error(f"Failed to generate launch options for Enderal modlist")
|
||||
return False, None, None, None
|
||||
logger.info("Using launch options approach for Enderal modlist")
|
||||
elif special_game_type == "fnv":
|
||||
logger.info("Using registry injection approach for FNV modlist")
|
||||
else:
|
||||
logger.debug("Standard modlist - no special game handling needed")
|
||||
|
||||
try:
|
||||
# Step 1: Create shortcut with native Steam service (pointing to ModOrganizer.exe initially)
|
||||
@@ -1806,17 +1808,27 @@ echo Prefix creation complete.
|
||||
if progress_callback:
|
||||
progress_callback(f"{self._get_progress_timestamp()} Setup verification completed")
|
||||
|
||||
# Step 5: Inject game registry entries for FNV/Enderal modlists
|
||||
logger.info("Step 5: Injecting game registry entries")
|
||||
if progress_callback:
|
||||
progress_callback(f"{self._get_progress_timestamp()} Injecting game registry entries...")
|
||||
|
||||
# Get prefix path for registry injection
|
||||
# Step 5: Inject game registry entries for FNV modlists (Enderal uses launch options)
|
||||
# Get prefix path (needed for logging regardless of game type)
|
||||
prefix_path = self.get_prefix_path(appid)
|
||||
if prefix_path:
|
||||
self._inject_game_registry_entries(str(prefix_path))
|
||||
|
||||
if special_game_type == "fnv":
|
||||
logger.info("Step 5: Injecting FNV game registry entries")
|
||||
if progress_callback:
|
||||
progress_callback(f"{self._get_progress_timestamp()} Injecting FNV game registry entries...")
|
||||
|
||||
if prefix_path:
|
||||
self._inject_game_registry_entries(str(prefix_path))
|
||||
else:
|
||||
logger.warning("Could not find prefix path for registry injection")
|
||||
elif special_game_type == "enderal":
|
||||
logger.info("Step 5: Skipping registry injection for Enderal (using launch options)")
|
||||
if progress_callback:
|
||||
progress_callback(f"{self._get_progress_timestamp()} Skipping registry injection for Enderal")
|
||||
else:
|
||||
logger.warning("Could not find prefix path for registry injection")
|
||||
logger.info("Step 5: Skipping registry injection for standard modlist")
|
||||
if progress_callback:
|
||||
progress_callback(f"{self._get_progress_timestamp()} No special game registry injection needed")
|
||||
|
||||
last_timestamp = self._get_progress_timestamp()
|
||||
logger.info(f" Working workflow completed successfully! AppID: {appid}, Prefix: {prefix_path}")
|
||||
|
||||
@@ -125,32 +125,25 @@ class NativeSteamService:
|
||||
|
||||
def generate_app_id(self, app_name: str, exe_path: str) -> Tuple[int, int]:
|
||||
"""
|
||||
Generate AppID using STL's exact algorithm (MD5-based).
|
||||
Generate random AppID to avoid Steam cache conflicts.
|
||||
|
||||
This matches STL's generateShortcutVDFAppId and generateSteamShortID functions:
|
||||
1. Combine AppName + ExePath
|
||||
2. Generate MD5 hash, take first 8 characters
|
||||
3. Convert to decimal, make negative, ensure < 1 billion
|
||||
4. Convert signed to unsigned for CompatToolMapping
|
||||
Uses random negative AppID similar to old working method to avoid
|
||||
Steam's cache conflicts that break Proton setting and "Installed Locally" visibility.
|
||||
AppID will be re-detected after Steam restart using existing detection logic.
|
||||
|
||||
Returns:
|
||||
(signed_app_id, unsigned_app_id) - Both the signed and unsigned versions
|
||||
"""
|
||||
# STL's algorithm: MD5 of app_name + exe_path
|
||||
input_string = f"{app_name}{exe_path}"
|
||||
import random
|
||||
|
||||
# Generate MD5 hash and take first 8 characters
|
||||
md5_hash = hashlib.md5(input_string.encode('utf-8')).hexdigest()
|
||||
seed = md5_hash[:8]
|
||||
# Generate random negative AppID in Steam's non-Steam app range
|
||||
# Use range that avoids conflicts with real Steam apps
|
||||
signed_app_id = -random.randint(100000000, 999999999)
|
||||
|
||||
# Convert hex to decimal and make it negative with modulo 1 billion
|
||||
seed_decimal = int(seed, 16)
|
||||
signed_app_id = -(seed_decimal % 1000000000)
|
||||
|
||||
# Convert to unsigned using steam-conductor/trentondyck method (signed_app_id + 2^32)
|
||||
# Convert to unsigned for CompatToolMapping
|
||||
unsigned_app_id = signed_app_id + 2**32
|
||||
|
||||
logger.info(f"Generated AppID using STL algorithm for '{app_name}' + '{exe_path}': {signed_app_id} (unsigned: {unsigned_app_id})")
|
||||
logger.info(f"Generated random AppID for '{app_name}': {signed_app_id} (unsigned: {unsigned_app_id})")
|
||||
return signed_app_id, unsigned_app_id
|
||||
|
||||
def create_shortcut(self, app_name: str, exe_path: str, start_dir: str = None,
|
||||
|
||||
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.
Binary file not shown.
@@ -150,6 +150,22 @@ class SuccessDialog(QDialog):
|
||||
)
|
||||
card_layout.addWidget(next_steps_label)
|
||||
|
||||
# Subtle Ko-Fi support link
|
||||
kofi_label = QLabel('<a href="https://ko-fi.com/omni1" style="color:#72A5F2; text-decoration:none;">Enjoying Jackify? Support development ♥</a>')
|
||||
kofi_label.setAlignment(Qt.AlignCenter)
|
||||
kofi_label.setStyleSheet(
|
||||
"QLabel { "
|
||||
" color: #72A5F2; "
|
||||
" font-size: 11px; "
|
||||
" margin-top: 8px; "
|
||||
" padding: 4px; "
|
||||
" background-color: transparent; "
|
||||
"}"
|
||||
)
|
||||
kofi_label.setTextInteractionFlags(Qt.TextBrowserInteraction)
|
||||
kofi_label.setOpenExternalLinks(True)
|
||||
card_layout.addWidget(kofi_label)
|
||||
|
||||
layout.addStretch()
|
||||
layout.addWidget(card, alignment=Qt.AlignCenter)
|
||||
layout.addStretch()
|
||||
|
||||
@@ -616,6 +616,17 @@ class JackifyMainWindow(QMainWindow):
|
||||
# Spacer
|
||||
bottom_bar_layout.addStretch(1)
|
||||
|
||||
# Ko-Fi support link (center)
|
||||
kofi_link = QLabel('<a href="https://ko-fi.com/omni1" style="color:#72A5F2; text-decoration:none;">♥ Support on Ko-fi</a>')
|
||||
kofi_link.setStyleSheet("color: #72A5F2; font-size: 13px;")
|
||||
kofi_link.setTextInteractionFlags(Qt.TextBrowserInteraction)
|
||||
kofi_link.setOpenExternalLinks(True)
|
||||
kofi_link.setToolTip("Support Jackify development")
|
||||
bottom_bar_layout.addWidget(kofi_link, alignment=Qt.AlignCenter)
|
||||
|
||||
# Spacer
|
||||
bottom_bar_layout.addStretch(1)
|
||||
|
||||
# Settings button (right)
|
||||
settings_btn = QLabel('<a href="#" style="color:#6cf; text-decoration:none;">Settings</a>')
|
||||
settings_btn.setStyleSheet("color: #6cf; font-size: 13px; padding-right: 8px;")
|
||||
|
||||
@@ -606,7 +606,7 @@ class ConfigureExistingModlistScreen(QWidget):
|
||||
# Include jackify-engine and related heavy processes
|
||||
heavy_processes = (
|
||||
"jackify-engine" in line_lower or "7zz" in line_lower or
|
||||
"compressonator" in line_lower or "wine" in line_lower or
|
||||
"texconv" in line_lower or "wine" in line_lower or
|
||||
"wine64" in line_lower or "protontricks" in line_lower
|
||||
)
|
||||
# Include Python processes running configure-modlist command
|
||||
|
||||
@@ -439,7 +439,7 @@ class ConfigureNewModlistScreen(QWidget):
|
||||
# Include jackify-engine and related heavy processes
|
||||
heavy_processes = (
|
||||
"jackify-engine" in line_lower or "7zz" in line_lower or
|
||||
"compressonator" in line_lower or "wine" in line_lower or
|
||||
"texconv" in line_lower or "wine" in line_lower or
|
||||
"wine64" in line_lower or "protontricks" in line_lower
|
||||
)
|
||||
# Include Python processes running configure-modlist command
|
||||
|
||||
@@ -996,7 +996,7 @@ class InstallModlistScreen(QWidget):
|
||||
for line in lines[1:]:
|
||||
line_lower = line.lower()
|
||||
if (
|
||||
("jackify-engine" in line_lower or "7zz" in line_lower or "compressonator" in line_lower or
|
||||
("jackify-engine" in line_lower or "7zz" in line_lower or "texconv" in line_lower or
|
||||
"wine" in line_lower or "wine64" in line_lower or "protontricks" in line_lower)
|
||||
and "jackify-gui.py" not in line_lower
|
||||
):
|
||||
|
||||
@@ -637,7 +637,7 @@ class TuxbornInstallerScreen(QWidget):
|
||||
for line in lines[1:]:
|
||||
line_lower = line.lower()
|
||||
if (
|
||||
("jackify-engine" in line_lower or "7zz" in line_lower or "compressonator" in line_lower or
|
||||
("jackify-engine" in line_lower or "7zz" in line_lower or "texconv" in line_lower or
|
||||
"wine" in line_lower or "wine64" in line_lower or "protontricks" in line_lower)
|
||||
and "jackify-gui.py" not in line_lower
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user