diff --git a/CHANGELOG.md b/CHANGELOG.md index 642efa9..b8469dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,30 @@ # Jackify Changelog +## v0.1.0.1 - Engine Update and Stability Improvements +**Release Date:** September 14, 2025 + +### Engine Updates +- **jackify-engine v0.3.13**: Major stability and resource management improvements + - **Wine Prefix Cleanup**: Automatic cleanup of ~281MB Wine prefix directories after each modlist installation + - **Manual Download Handling**: Fixed installation crashes when manual downloads are required + - **Enhanced Error Messaging**: Detailed mod information for failed downloads (Nexus ModID/FileID, Google Drive, HTTP sources) + - **Resource Settings Compliance**: Fixed resource settings not being respected during VFS and Installer operations + - **VFS Crash Prevention**: Fixed KeyNotFoundException crashes during "Priming VFS" phase with missing archives + - **Creation Club File Handling**: Fixed incorrect re-download attempts for Creation Club files + - **BSA Extraction Fix**: Fixed DirectoryNotFoundException during BSA building operations + +### Improvements +- **Disk Space Management**: No more accumulation of Wine prefix directories consuming hundreds of MB per installation +- **Clean Error Handling**: Manual download requirements now show clear summary instead of stack traces +- **Better Resource Control**: Users can now properly control CPU usage during installation via resource_settings.json + +### Bug Fixes +- **Download System**: Fixed GoogleDrive and MEGA download regressions +- **Configuration Integration**: MEGA tokens properly stored in Jackify's config directory structure +- **Installation Reliability**: Enhanced error handling prevents crashes with missing or corrupted archives + +--- + ## v0.1.0 - First Public Release **Release Date:** September 11, 2025 diff --git a/jackify/__init__.py b/jackify/__init__.py index 27218a2..570236d 100644 --- a/jackify/__init__.py +++ b/jackify/__init__.py @@ -5,4 +5,4 @@ This package provides both CLI and GUI interfaces for managing Wabbajack modlists natively on Linux systems. """ -__version__ = "0.1.0" +__version__ = "0.1.0.1" diff --git a/jackify/backend/core/modlist_operations.py b/jackify/backend/core/modlist_operations.py index 43c8920..5b37a51 100644 --- a/jackify/backend/core/modlist_operations.py +++ b/jackify/backend/core/modlist_operations.py @@ -1400,8 +1400,9 @@ class ModlistInstallCLI: # Remove status indicators to get clean line clean_line = line.replace('[DOWN]', '').replace('[NSFW]', '').strip() - # Split on ' - ' to get: [Modlist Name, Game, Sizes, MachineURL] - parts = clean_line.split(' - ') + # Split from right to handle modlist names with dashes + # Format: "NAME - GAME - SIZES - MACHINE_URL" + parts = clean_line.rsplit(' - ', 3) # Split from right, max 3 splits = 4 parts if len(parts) != 4: continue # Skip malformed lines diff --git a/jackify/backend/handlers/config_handler.py b/jackify/backend/handlers/config_handler.py index b0eb731..6da81d8 100644 --- a/jackify/backend/handlers/config_handler.py +++ b/jackify/backend/handlers/config_handler.py @@ -213,11 +213,14 @@ class ConfigHandler: def get_api_key(self): """ Retrieve and decode the saved Nexus API key + Always reads fresh from disk to pick up changes from other instances Returns: str: Decoded API key or None if not saved """ try: + # Reload config from disk to pick up changes from Settings dialog + self._load_config() encoded_key = self.settings.get("nexus_api_key") if encoded_key: # Decode the base64 encoded key @@ -231,10 +234,13 @@ class ConfigHandler: def has_saved_api_key(self): """ Check if an API key is saved in configuration + Always reads fresh from disk to pick up changes from other instances Returns: bool: True if API key exists, False otherwise """ + # Reload config from disk to pick up changes from Settings dialog + self._load_config() return self.settings.get("nexus_api_key") is not None def clear_api_key(self): diff --git a/jackify/backend/handlers/modlist_handler.py b/jackify/backend/handlers/modlist_handler.py index dbf38a2..141583d 100644 --- a/jackify/backend/handlers/modlist_handler.py +++ b/jackify/backend/handlers/modlist_handler.py @@ -1117,6 +1117,7 @@ class ModlistHandler: ("grid-hero.png", f"{appid}_hero.png"), ("grid-logo.png", f"{appid}_logo.png"), ("grid-tall.png", f"{appid}.png"), + ("grid-tall.png", f"{appid}p.png"), ] for src_name, dest_name in images: diff --git a/jackify/backend/handlers/modlist_install_cli.py b/jackify/backend/handlers/modlist_install_cli.py index 49e2e59..6fd3ead 100644 --- a/jackify/backend/handlers/modlist_install_cli.py +++ b/jackify/backend/handlers/modlist_install_cli.py @@ -1020,8 +1020,9 @@ class ModlistInstallCLI: # Remove status indicators to get clean line clean_line = line.replace('[DOWN]', '').replace('[NSFW]', '').strip() - # Split on ' - ' to get: [Modlist Name, Game, Sizes, MachineURL] - parts = clean_line.split(' - ') + # Split from right to handle modlist names with dashes + # Format: "NAME - GAME - SIZES - MACHINE_URL" + parts = clean_line.rsplit(' - ', 3) # Split from right, max 3 splits = 4 parts if len(parts) != 4: continue # Skip malformed lines diff --git a/jackify/engine/Wabbajack.CLI.Builder.dll b/jackify/engine/Wabbajack.CLI.Builder.dll index 7997f59..141ad96 100644 Binary files a/jackify/engine/Wabbajack.CLI.Builder.dll and b/jackify/engine/Wabbajack.CLI.Builder.dll differ diff --git a/jackify/engine/Wabbajack.Common.dll b/jackify/engine/Wabbajack.Common.dll index b5aa117..3dba4a4 100644 Binary files a/jackify/engine/Wabbajack.Common.dll and b/jackify/engine/Wabbajack.Common.dll differ diff --git a/jackify/engine/Wabbajack.Compiler.dll b/jackify/engine/Wabbajack.Compiler.dll index 1038597..875c5c8 100644 Binary files a/jackify/engine/Wabbajack.Compiler.dll and b/jackify/engine/Wabbajack.Compiler.dll differ diff --git a/jackify/engine/Wabbajack.Compression.BSA.dll b/jackify/engine/Wabbajack.Compression.BSA.dll index ebc131e..5c900cc 100644 Binary files a/jackify/engine/Wabbajack.Compression.BSA.dll and b/jackify/engine/Wabbajack.Compression.BSA.dll differ diff --git a/jackify/engine/Wabbajack.Compression.Zip.dll b/jackify/engine/Wabbajack.Compression.Zip.dll index 738858a..570a92d 100644 Binary files a/jackify/engine/Wabbajack.Compression.Zip.dll and b/jackify/engine/Wabbajack.Compression.Zip.dll differ diff --git a/jackify/engine/Wabbajack.Configuration.dll b/jackify/engine/Wabbajack.Configuration.dll index a7c0677..23d2d71 100644 Binary files a/jackify/engine/Wabbajack.Configuration.dll and b/jackify/engine/Wabbajack.Configuration.dll differ diff --git a/jackify/engine/Wabbajack.DTOs.dll b/jackify/engine/Wabbajack.DTOs.dll index 647d6ab..123e7ed 100644 Binary files a/jackify/engine/Wabbajack.DTOs.dll and b/jackify/engine/Wabbajack.DTOs.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.Bethesda.dll b/jackify/engine/Wabbajack.Downloaders.Bethesda.dll index 73d9955..e49890a 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.Bethesda.dll and b/jackify/engine/Wabbajack.Downloaders.Bethesda.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.Dispatcher.dll b/jackify/engine/Wabbajack.Downloaders.Dispatcher.dll index d4b1a8d..128e8e5 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.Dispatcher.dll and b/jackify/engine/Wabbajack.Downloaders.Dispatcher.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.GameFile.dll b/jackify/engine/Wabbajack.Downloaders.GameFile.dll index 74b1b1e..d7ebd53 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.GameFile.dll and b/jackify/engine/Wabbajack.Downloaders.GameFile.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.GoogleDrive.dll b/jackify/engine/Wabbajack.Downloaders.GoogleDrive.dll index a9a0ace..3dc4574 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.GoogleDrive.dll and b/jackify/engine/Wabbajack.Downloaders.GoogleDrive.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.Http.dll b/jackify/engine/Wabbajack.Downloaders.Http.dll index 77daa95..c31bfc8 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.Http.dll and b/jackify/engine/Wabbajack.Downloaders.Http.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.IPS4OAuth2Downloader.dll b/jackify/engine/Wabbajack.Downloaders.IPS4OAuth2Downloader.dll index 6d79858..3bf3d99 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.IPS4OAuth2Downloader.dll and b/jackify/engine/Wabbajack.Downloaders.IPS4OAuth2Downloader.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.Interfaces.dll b/jackify/engine/Wabbajack.Downloaders.Interfaces.dll index e564627..32fe921 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.Interfaces.dll and b/jackify/engine/Wabbajack.Downloaders.Interfaces.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.Manual.dll b/jackify/engine/Wabbajack.Downloaders.Manual.dll index a625138..07907fa 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.Manual.dll and b/jackify/engine/Wabbajack.Downloaders.Manual.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.MediaFire.dll b/jackify/engine/Wabbajack.Downloaders.MediaFire.dll index 97de475..289333d 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.MediaFire.dll and b/jackify/engine/Wabbajack.Downloaders.MediaFire.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.Mega.dll b/jackify/engine/Wabbajack.Downloaders.Mega.dll index d8bbadf..98ba2e2 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.Mega.dll and b/jackify/engine/Wabbajack.Downloaders.Mega.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.ModDB.dll b/jackify/engine/Wabbajack.Downloaders.ModDB.dll index 722a44d..56b5a97 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.ModDB.dll and b/jackify/engine/Wabbajack.Downloaders.ModDB.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.Nexus.dll b/jackify/engine/Wabbajack.Downloaders.Nexus.dll index 4b12caa..db535b9 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.Nexus.dll and b/jackify/engine/Wabbajack.Downloaders.Nexus.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.VerificationCache.dll b/jackify/engine/Wabbajack.Downloaders.VerificationCache.dll index aeb3cac..e9ccb61 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.VerificationCache.dll and b/jackify/engine/Wabbajack.Downloaders.VerificationCache.dll differ diff --git a/jackify/engine/Wabbajack.Downloaders.WabbajackCDN.dll b/jackify/engine/Wabbajack.Downloaders.WabbajackCDN.dll index 12811fe..353cf74 100644 Binary files a/jackify/engine/Wabbajack.Downloaders.WabbajackCDN.dll and b/jackify/engine/Wabbajack.Downloaders.WabbajackCDN.dll differ diff --git a/jackify/engine/Wabbajack.FileExtractor.dll b/jackify/engine/Wabbajack.FileExtractor.dll index 6fab5c4..7164ed1 100644 Binary files a/jackify/engine/Wabbajack.FileExtractor.dll and b/jackify/engine/Wabbajack.FileExtractor.dll differ diff --git a/jackify/engine/Wabbajack.Hashing.PHash.dll b/jackify/engine/Wabbajack.Hashing.PHash.dll index 408f4dc..0545efe 100644 Binary files a/jackify/engine/Wabbajack.Hashing.PHash.dll and b/jackify/engine/Wabbajack.Hashing.PHash.dll differ diff --git a/jackify/engine/Wabbajack.Hashing.xxHash64.dll b/jackify/engine/Wabbajack.Hashing.xxHash64.dll index ca9139e..10a0184 100644 Binary files a/jackify/engine/Wabbajack.Hashing.xxHash64.dll and b/jackify/engine/Wabbajack.Hashing.xxHash64.dll differ diff --git a/jackify/engine/Wabbajack.IO.Async.dll b/jackify/engine/Wabbajack.IO.Async.dll index b825e78..e8f1d72 100644 Binary files a/jackify/engine/Wabbajack.IO.Async.dll and b/jackify/engine/Wabbajack.IO.Async.dll differ diff --git a/jackify/engine/Wabbajack.Installer.dll b/jackify/engine/Wabbajack.Installer.dll index b917f00..df52c15 100644 Binary files a/jackify/engine/Wabbajack.Installer.dll and b/jackify/engine/Wabbajack.Installer.dll differ diff --git a/jackify/engine/Wabbajack.Networking.BethesdaNet.dll b/jackify/engine/Wabbajack.Networking.BethesdaNet.dll index 0048376..e02375e 100644 Binary files a/jackify/engine/Wabbajack.Networking.BethesdaNet.dll and b/jackify/engine/Wabbajack.Networking.BethesdaNet.dll differ diff --git a/jackify/engine/Wabbajack.Networking.Discord.dll b/jackify/engine/Wabbajack.Networking.Discord.dll index 975e2fd..15b2a46 100644 Binary files a/jackify/engine/Wabbajack.Networking.Discord.dll and b/jackify/engine/Wabbajack.Networking.Discord.dll differ diff --git a/jackify/engine/Wabbajack.Networking.GitHub.dll b/jackify/engine/Wabbajack.Networking.GitHub.dll index 07c460e..eaed690 100644 Binary files a/jackify/engine/Wabbajack.Networking.GitHub.dll and b/jackify/engine/Wabbajack.Networking.GitHub.dll differ diff --git a/jackify/engine/Wabbajack.Networking.Http.Interfaces.dll b/jackify/engine/Wabbajack.Networking.Http.Interfaces.dll index 74a1eb5..083b854 100644 Binary files a/jackify/engine/Wabbajack.Networking.Http.Interfaces.dll and b/jackify/engine/Wabbajack.Networking.Http.Interfaces.dll differ diff --git a/jackify/engine/Wabbajack.Networking.Http.dll b/jackify/engine/Wabbajack.Networking.Http.dll index 7f66945..4b1474e 100644 Binary files a/jackify/engine/Wabbajack.Networking.Http.dll and b/jackify/engine/Wabbajack.Networking.Http.dll differ diff --git a/jackify/engine/Wabbajack.Networking.NexusApi.dll b/jackify/engine/Wabbajack.Networking.NexusApi.dll index b1ddfb2..2caf923 100644 Binary files a/jackify/engine/Wabbajack.Networking.NexusApi.dll and b/jackify/engine/Wabbajack.Networking.NexusApi.dll differ diff --git a/jackify/engine/Wabbajack.Networking.WabbajackClientApi.dll b/jackify/engine/Wabbajack.Networking.WabbajackClientApi.dll index bed29c0..56bf0df 100644 Binary files a/jackify/engine/Wabbajack.Networking.WabbajackClientApi.dll and b/jackify/engine/Wabbajack.Networking.WabbajackClientApi.dll differ diff --git a/jackify/engine/Wabbajack.Paths.IO.dll b/jackify/engine/Wabbajack.Paths.IO.dll index ecc6b29..1de8ecf 100644 Binary files a/jackify/engine/Wabbajack.Paths.IO.dll and b/jackify/engine/Wabbajack.Paths.IO.dll differ diff --git a/jackify/engine/Wabbajack.Paths.dll b/jackify/engine/Wabbajack.Paths.dll index 8914b4d..b67a3cb 100644 Binary files a/jackify/engine/Wabbajack.Paths.dll and b/jackify/engine/Wabbajack.Paths.dll differ diff --git a/jackify/engine/Wabbajack.RateLimiter.dll b/jackify/engine/Wabbajack.RateLimiter.dll index f7fd12f..172f3db 100644 Binary files a/jackify/engine/Wabbajack.RateLimiter.dll and b/jackify/engine/Wabbajack.RateLimiter.dll differ diff --git a/jackify/engine/Wabbajack.Server.Lib.dll b/jackify/engine/Wabbajack.Server.Lib.dll index 5e1530c..8bf2f44 100644 Binary files a/jackify/engine/Wabbajack.Server.Lib.dll and b/jackify/engine/Wabbajack.Server.Lib.dll differ diff --git a/jackify/engine/Wabbajack.Services.OSIntegrated.dll b/jackify/engine/Wabbajack.Services.OSIntegrated.dll index 7894a81..54a846c 100644 Binary files a/jackify/engine/Wabbajack.Services.OSIntegrated.dll and b/jackify/engine/Wabbajack.Services.OSIntegrated.dll differ diff --git a/jackify/engine/Wabbajack.VFS.Interfaces.dll b/jackify/engine/Wabbajack.VFS.Interfaces.dll index 3a08f14..0438c90 100644 Binary files a/jackify/engine/Wabbajack.VFS.Interfaces.dll and b/jackify/engine/Wabbajack.VFS.Interfaces.dll differ diff --git a/jackify/engine/Wabbajack.VFS.dll b/jackify/engine/Wabbajack.VFS.dll index 6e7301c..eb34e2b 100644 Binary files a/jackify/engine/Wabbajack.VFS.dll and b/jackify/engine/Wabbajack.VFS.dll differ diff --git a/jackify/engine/jackify-engine.deps.json b/jackify/engine/jackify-engine.deps.json index 0ecd450..918a38d 100644 --- a/jackify/engine/jackify-engine.deps.json +++ b/jackify/engine/jackify-engine.deps.json @@ -7,7 +7,7 @@ "targets": { ".NETCoreApp,Version=v8.0": {}, ".NETCoreApp,Version=v8.0/linux-x64": { - "jackify-engine/0.3.12": { + "jackify-engine/0.3.13": { "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.12", - "Wabbajack.Downloaders.Bethesda": "0.3.12", - "Wabbajack.Downloaders.Dispatcher": "0.3.12", - "Wabbajack.Hashing.xxHash64": "0.3.12", - "Wabbajack.Networking.Discord": "0.3.12", - "Wabbajack.Networking.GitHub": "0.3.12", - "Wabbajack.Paths.IO": "0.3.12", - "Wabbajack.Server.Lib": "0.3.12", - "Wabbajack.Services.OSIntegrated": "0.3.12", - "Wabbajack.VFS": "0.3.12", + "Wabbajack.CLI.Builder": "0.3.13", + "Wabbajack.Downloaders.Bethesda": "0.3.13", + "Wabbajack.Downloaders.Dispatcher": "0.3.13", + "Wabbajack.Hashing.xxHash64": "0.3.13", + "Wabbajack.Networking.Discord": "0.3.13", + "Wabbajack.Networking.GitHub": "0.3.13", + "Wabbajack.Paths.IO": "0.3.13", + "Wabbajack.Server.Lib": "0.3.13", + "Wabbajack.Services.OSIntegrated": "0.3.13", + "Wabbajack.VFS": "0.3.13", "MegaApiClient": "1.0.0.0", "runtimepack.Microsoft.NETCore.App.Runtime.linux-x64": "8.0.19" }, @@ -1781,7 +1781,7 @@ } } }, - "Wabbajack.CLI.Builder/0.3.12": { + "Wabbajack.CLI.Builder/0.3.13": { "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.12" + "Wabbajack.Paths": "0.3.13" }, "runtime": { "Wabbajack.CLI.Builder.dll": {} } }, - "Wabbajack.Common/0.3.12": { + "Wabbajack.Common/0.3.13": { "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.12", - "Wabbajack.Networking.Http": "0.3.12", - "Wabbajack.Paths.IO": "0.3.12" + "Wabbajack.DTOs": "0.3.13", + "Wabbajack.Networking.Http": "0.3.13", + "Wabbajack.Paths.IO": "0.3.13" }, "runtime": { "Wabbajack.Common.dll": {} } }, - "Wabbajack.Compiler/0.3.12": { + "Wabbajack.Compiler/0.3.13": { "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.12", - "Wabbajack.Installer": "0.3.12", - "Wabbajack.VFS": "0.3.12", + "Wabbajack.Downloaders.Dispatcher": "0.3.13", + "Wabbajack.Installer": "0.3.13", + "Wabbajack.VFS": "0.3.13", "ini-parser-netstandard": "2.5.2" }, "runtime": { "Wabbajack.Compiler.dll": {} } }, - "Wabbajack.Compression.BSA/0.3.12": { + "Wabbajack.Compression.BSA/0.3.13": { "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.12", - "Wabbajack.DTOs": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.DTOs": "0.3.13" }, "runtime": { "Wabbajack.Compression.BSA.dll": {} } }, - "Wabbajack.Compression.Zip/0.3.12": { + "Wabbajack.Compression.Zip/0.3.13": { "dependencies": { - "Wabbajack.IO.Async": "0.3.12" + "Wabbajack.IO.Async": "0.3.13" }, "runtime": { "Wabbajack.Compression.Zip.dll": {} } }, - "Wabbajack.Configuration/0.3.12": { + "Wabbajack.Configuration/0.3.13": { "runtime": { "Wabbajack.Configuration.dll": {} } }, - "Wabbajack.Downloaders.Bethesda/0.3.12": { + "Wabbajack.Downloaders.Bethesda/0.3.13": { "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.12", - "Wabbajack.Downloaders.Interfaces": "0.3.12", - "Wabbajack.Networking.BethesdaNet": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.Downloaders.Interfaces": "0.3.13", + "Wabbajack.Networking.BethesdaNet": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.Bethesda.dll": {} } }, - "Wabbajack.Downloaders.Dispatcher/0.3.12": { + "Wabbajack.Downloaders.Dispatcher/0.3.13": { "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.12", - "Wabbajack.Downloaders.GameFile": "0.3.12", - "Wabbajack.Downloaders.GoogleDrive": "0.3.12", - "Wabbajack.Downloaders.Http": "0.3.12", - "Wabbajack.Downloaders.IPS4OAuth2Downloader": "0.3.12", - "Wabbajack.Downloaders.Interfaces": "0.3.12", - "Wabbajack.Downloaders.Manual": "0.3.12", - "Wabbajack.Downloaders.MediaFire": "0.3.12", - "Wabbajack.Downloaders.Mega": "0.3.12", - "Wabbajack.Downloaders.ModDB": "0.3.12", - "Wabbajack.Downloaders.Nexus": "0.3.12", - "Wabbajack.Downloaders.VerificationCache": "0.3.12", - "Wabbajack.Downloaders.WabbajackCDN": "0.3.12", - "Wabbajack.Networking.WabbajackClientApi": "0.3.12" + "Wabbajack.Downloaders.Bethesda": "0.3.13", + "Wabbajack.Downloaders.GameFile": "0.3.13", + "Wabbajack.Downloaders.GoogleDrive": "0.3.13", + "Wabbajack.Downloaders.Http": "0.3.13", + "Wabbajack.Downloaders.IPS4OAuth2Downloader": "0.3.13", + "Wabbajack.Downloaders.Interfaces": "0.3.13", + "Wabbajack.Downloaders.Manual": "0.3.13", + "Wabbajack.Downloaders.MediaFire": "0.3.13", + "Wabbajack.Downloaders.Mega": "0.3.13", + "Wabbajack.Downloaders.ModDB": "0.3.13", + "Wabbajack.Downloaders.Nexus": "0.3.13", + "Wabbajack.Downloaders.VerificationCache": "0.3.13", + "Wabbajack.Downloaders.WabbajackCDN": "0.3.13", + "Wabbajack.Networking.WabbajackClientApi": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.Dispatcher.dll": {} } }, - "Wabbajack.Downloaders.GameFile/0.3.12": { + "Wabbajack.Downloaders.GameFile/0.3.13": { "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.12", - "Wabbajack.VFS": "0.3.12" + "Wabbajack.Downloaders.Interfaces": "0.3.13", + "Wabbajack.VFS": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.GameFile.dll": {} } }, - "Wabbajack.Downloaders.GoogleDrive/0.3.12": { + "Wabbajack.Downloaders.GoogleDrive/0.3.13": { "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.12", - "Wabbajack.DTOs": "0.3.12", - "Wabbajack.Downloaders.Interfaces": "0.3.12", - "Wabbajack.Networking.Http": "0.3.12", - "Wabbajack.Networking.Http.Interfaces": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.DTOs": "0.3.13", + "Wabbajack.Downloaders.Interfaces": "0.3.13", + "Wabbajack.Networking.Http": "0.3.13", + "Wabbajack.Networking.Http.Interfaces": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.GoogleDrive.dll": {} } }, - "Wabbajack.Downloaders.Http/0.3.12": { + "Wabbajack.Downloaders.Http/0.3.13": { "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.12", - "Wabbajack.DTOs": "0.3.12", - "Wabbajack.Downloaders.Interfaces": "0.3.12", - "Wabbajack.Networking.BethesdaNet": "0.3.12", - "Wabbajack.Networking.Http.Interfaces": "0.3.12", - "Wabbajack.Paths.IO": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.DTOs": "0.3.13", + "Wabbajack.Downloaders.Interfaces": "0.3.13", + "Wabbajack.Networking.BethesdaNet": "0.3.13", + "Wabbajack.Networking.Http.Interfaces": "0.3.13", + "Wabbajack.Paths.IO": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.Http.dll": {} } }, - "Wabbajack.Downloaders.Interfaces/0.3.12": { + "Wabbajack.Downloaders.Interfaces/0.3.13": { "dependencies": { "Microsoft.Extensions.DependencyInjection": "9.0.1", "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1", - "Wabbajack.Compression.Zip": "0.3.12", - "Wabbajack.DTOs": "0.3.12", - "Wabbajack.Paths.IO": "0.3.12" + "Wabbajack.Compression.Zip": "0.3.13", + "Wabbajack.DTOs": "0.3.13", + "Wabbajack.Paths.IO": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.Interfaces.dll": {} } }, - "Wabbajack.Downloaders.IPS4OAuth2Downloader/0.3.12": { + "Wabbajack.Downloaders.IPS4OAuth2Downloader/0.3.13": { "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.12", - "Wabbajack.Downloaders.Interfaces": "0.3.12", - "Wabbajack.Networking.Http": "0.3.12", - "Wabbajack.Networking.Http.Interfaces": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.Downloaders.Interfaces": "0.3.13", + "Wabbajack.Networking.Http": "0.3.13", + "Wabbajack.Networking.Http.Interfaces": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.IPS4OAuth2Downloader.dll": {} } }, - "Wabbajack.Downloaders.Manual/0.3.12": { + "Wabbajack.Downloaders.Manual/0.3.13": { "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.12", - "Wabbajack.Downloaders.Interfaces": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.Downloaders.Interfaces": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.Manual.dll": {} } }, - "Wabbajack.Downloaders.MediaFire/0.3.12": { + "Wabbajack.Downloaders.MediaFire/0.3.13": { "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.12", - "Wabbajack.Downloaders.Interfaces": "0.3.12", - "Wabbajack.Networking.Http.Interfaces": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.Downloaders.Interfaces": "0.3.13", + "Wabbajack.Networking.Http.Interfaces": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.MediaFire.dll": {} } }, - "Wabbajack.Downloaders.Mega/0.3.12": { + "Wabbajack.Downloaders.Mega/0.3.13": { "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.12", - "Wabbajack.Downloaders.Interfaces": "0.3.12", - "Wabbajack.Paths.IO": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.Downloaders.Interfaces": "0.3.13", + "Wabbajack.Paths.IO": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.Mega.dll": {} } }, - "Wabbajack.Downloaders.ModDB/0.3.12": { + "Wabbajack.Downloaders.ModDB/0.3.13": { "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.12", - "Wabbajack.Downloaders.Interfaces": "0.3.12", - "Wabbajack.Networking.Http": "0.3.12", - "Wabbajack.Networking.Http.Interfaces": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.Downloaders.Interfaces": "0.3.13", + "Wabbajack.Networking.Http": "0.3.13", + "Wabbajack.Networking.Http.Interfaces": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.ModDB.dll": {} } }, - "Wabbajack.Downloaders.Nexus/0.3.12": { + "Wabbajack.Downloaders.Nexus/0.3.13": { "dependencies": { "Microsoft.Extensions.DependencyInjection": "9.0.1", "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1", - "Wabbajack.DTOs": "0.3.12", - "Wabbajack.Downloaders.Interfaces": "0.3.12", - "Wabbajack.Hashing.xxHash64": "0.3.12", - "Wabbajack.Networking.Http": "0.3.12", - "Wabbajack.Networking.Http.Interfaces": "0.3.12", - "Wabbajack.Networking.NexusApi": "0.3.12", - "Wabbajack.Paths": "0.3.12" + "Wabbajack.DTOs": "0.3.13", + "Wabbajack.Downloaders.Interfaces": "0.3.13", + "Wabbajack.Hashing.xxHash64": "0.3.13", + "Wabbajack.Networking.Http": "0.3.13", + "Wabbajack.Networking.Http.Interfaces": "0.3.13", + "Wabbajack.Networking.NexusApi": "0.3.13", + "Wabbajack.Paths": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.Nexus.dll": {} } }, - "Wabbajack.Downloaders.VerificationCache/0.3.12": { + "Wabbajack.Downloaders.VerificationCache/0.3.13": { "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.12", - "Wabbajack.Paths.IO": "0.3.12" + "Wabbajack.DTOs": "0.3.13", + "Wabbajack.Paths.IO": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.VerificationCache.dll": {} } }, - "Wabbajack.Downloaders.WabbajackCDN/0.3.12": { + "Wabbajack.Downloaders.WabbajackCDN/0.3.13": { "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.12", - "Wabbajack.Downloaders.Interfaces": "0.3.12", - "Wabbajack.Networking.Http": "0.3.12", - "Wabbajack.RateLimiter": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.Downloaders.Interfaces": "0.3.13", + "Wabbajack.Networking.Http": "0.3.13", + "Wabbajack.RateLimiter": "0.3.13" }, "runtime": { "Wabbajack.Downloaders.WabbajackCDN.dll": {} } }, - "Wabbajack.DTOs/0.3.12": { + "Wabbajack.DTOs/0.3.13": { "dependencies": { "Microsoft.Extensions.DependencyInjection": "9.0.1", "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1", - "Wabbajack.Hashing.xxHash64": "0.3.12", - "Wabbajack.Paths": "0.3.12" + "Wabbajack.Hashing.xxHash64": "0.3.13", + "Wabbajack.Paths": "0.3.13" }, "runtime": { "Wabbajack.DTOs.dll": {} } }, - "Wabbajack.FileExtractor/0.3.12": { + "Wabbajack.FileExtractor/0.3.13": { "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.12", - "Wabbajack.Compression.BSA": "0.3.12", - "Wabbajack.Hashing.PHash": "0.3.12", - "Wabbajack.Paths": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.Compression.BSA": "0.3.13", + "Wabbajack.Hashing.PHash": "0.3.13", + "Wabbajack.Paths": "0.3.13" }, "runtime": { "Wabbajack.FileExtractor.dll": {} } }, - "Wabbajack.Hashing.PHash/0.3.12": { + "Wabbajack.Hashing.PHash/0.3.13": { "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.12", - "Wabbajack.DTOs": "0.3.12", - "Wabbajack.Paths": "0.3.12", - "Wabbajack.Paths.IO": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.DTOs": "0.3.13", + "Wabbajack.Paths": "0.3.13", + "Wabbajack.Paths.IO": "0.3.13" }, "runtime": { "Wabbajack.Hashing.PHash.dll": {} } }, - "Wabbajack.Hashing.xxHash64/0.3.12": { + "Wabbajack.Hashing.xxHash64/0.3.13": { "dependencies": { - "Wabbajack.Paths": "0.3.12", - "Wabbajack.RateLimiter": "0.3.12" + "Wabbajack.Paths": "0.3.13", + "Wabbajack.RateLimiter": "0.3.13" }, "runtime": { "Wabbajack.Hashing.xxHash64.dll": {} } }, - "Wabbajack.Installer/0.3.12": { + "Wabbajack.Installer/0.3.13": { "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.12", - "Wabbajack.Downloaders.Dispatcher": "0.3.12", - "Wabbajack.Downloaders.GameFile": "0.3.12", - "Wabbajack.FileExtractor": "0.3.12", - "Wabbajack.Networking.WabbajackClientApi": "0.3.12", - "Wabbajack.Paths": "0.3.12", - "Wabbajack.Paths.IO": "0.3.12", - "Wabbajack.VFS": "0.3.12", + "Wabbajack.DTOs": "0.3.13", + "Wabbajack.Downloaders.Dispatcher": "0.3.13", + "Wabbajack.Downloaders.GameFile": "0.3.13", + "Wabbajack.FileExtractor": "0.3.13", + "Wabbajack.Networking.WabbajackClientApi": "0.3.13", + "Wabbajack.Paths": "0.3.13", + "Wabbajack.Paths.IO": "0.3.13", + "Wabbajack.VFS": "0.3.13", "ini-parser-netstandard": "2.5.2" }, "runtime": { "Wabbajack.Installer.dll": {} } }, - "Wabbajack.IO.Async/0.3.12": { + "Wabbajack.IO.Async/0.3.13": { "runtime": { "Wabbajack.IO.Async.dll": {} } }, - "Wabbajack.Networking.BethesdaNet/0.3.12": { + "Wabbajack.Networking.BethesdaNet/0.3.13": { "dependencies": { "Microsoft.Extensions.DependencyInjection": "9.0.1", "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1", - "Wabbajack.DTOs": "0.3.12", - "Wabbajack.Networking.Http": "0.3.12", - "Wabbajack.Networking.Http.Interfaces": "0.3.12" + "Wabbajack.DTOs": "0.3.13", + "Wabbajack.Networking.Http": "0.3.13", + "Wabbajack.Networking.Http.Interfaces": "0.3.13" }, "runtime": { "Wabbajack.Networking.BethesdaNet.dll": {} } }, - "Wabbajack.Networking.Discord/0.3.12": { + "Wabbajack.Networking.Discord/0.3.13": { "dependencies": { "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1", "Microsoft.Extensions.Logging.Abstractions": "9.0.1", - "Wabbajack.Networking.Http.Interfaces": "0.3.12" + "Wabbajack.Networking.Http.Interfaces": "0.3.13" }, "runtime": { "Wabbajack.Networking.Discord.dll": {} } }, - "Wabbajack.Networking.GitHub/0.3.12": { + "Wabbajack.Networking.GitHub/0.3.13": { "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.12", - "Wabbajack.Networking.Http.Interfaces": "0.3.12" + "Wabbajack.DTOs": "0.3.13", + "Wabbajack.Networking.Http.Interfaces": "0.3.13" }, "runtime": { "Wabbajack.Networking.GitHub.dll": {} } }, - "Wabbajack.Networking.Http/0.3.12": { + "Wabbajack.Networking.Http/0.3.13": { "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.12", - "Wabbajack.Downloaders.Interfaces": "0.3.12", - "Wabbajack.Hashing.xxHash64": "0.3.12", - "Wabbajack.Networking.Http.Interfaces": "0.3.12", - "Wabbajack.Paths": "0.3.12", - "Wabbajack.Paths.IO": "0.3.12" + "Wabbajack.Configuration": "0.3.13", + "Wabbajack.Downloaders.Interfaces": "0.3.13", + "Wabbajack.Hashing.xxHash64": "0.3.13", + "Wabbajack.Networking.Http.Interfaces": "0.3.13", + "Wabbajack.Paths": "0.3.13", + "Wabbajack.Paths.IO": "0.3.13" }, "runtime": { "Wabbajack.Networking.Http.dll": {} } }, - "Wabbajack.Networking.Http.Interfaces/0.3.12": { + "Wabbajack.Networking.Http.Interfaces/0.3.13": { "dependencies": { - "Wabbajack.Hashing.xxHash64": "0.3.12" + "Wabbajack.Hashing.xxHash64": "0.3.13" }, "runtime": { "Wabbajack.Networking.Http.Interfaces.dll": {} } }, - "Wabbajack.Networking.NexusApi/0.3.12": { + "Wabbajack.Networking.NexusApi/0.3.13": { "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.12", - "Wabbajack.Networking.Http": "0.3.12", - "Wabbajack.Networking.Http.Interfaces": "0.3.12", - "Wabbajack.Networking.WabbajackClientApi": "0.3.12" + "Wabbajack.DTOs": "0.3.13", + "Wabbajack.Networking.Http": "0.3.13", + "Wabbajack.Networking.Http.Interfaces": "0.3.13", + "Wabbajack.Networking.WabbajackClientApi": "0.3.13" }, "runtime": { "Wabbajack.Networking.NexusApi.dll": {} } }, - "Wabbajack.Networking.WabbajackClientApi/0.3.12": { + "Wabbajack.Networking.WabbajackClientApi/0.3.13": { "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.12", - "Wabbajack.DTOs": "0.3.12", - "Wabbajack.Paths.IO": "0.3.12", - "Wabbajack.VFS.Interfaces": "0.3.12", + "Wabbajack.Common": "0.3.13", + "Wabbajack.DTOs": "0.3.13", + "Wabbajack.Paths.IO": "0.3.13", + "Wabbajack.VFS.Interfaces": "0.3.13", "YamlDotNet": "16.3.0" }, "runtime": { "Wabbajack.Networking.WabbajackClientApi.dll": {} } }, - "Wabbajack.Paths/0.3.12": { + "Wabbajack.Paths/0.3.13": { "runtime": { "Wabbajack.Paths.dll": {} } }, - "Wabbajack.Paths.IO/0.3.12": { + "Wabbajack.Paths.IO/0.3.13": { "dependencies": { - "Wabbajack.Paths": "0.3.12", + "Wabbajack.Paths": "0.3.13", "shortid": "4.0.0" }, "runtime": { "Wabbajack.Paths.IO.dll": {} } }, - "Wabbajack.RateLimiter/0.3.12": { + "Wabbajack.RateLimiter/0.3.13": { "runtime": { "Wabbajack.RateLimiter.dll": {} } }, - "Wabbajack.Server.Lib/0.3.12": { + "Wabbajack.Server.Lib/0.3.13": { "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.12", - "Wabbajack.Networking.Http.Interfaces": "0.3.12", - "Wabbajack.Services.OSIntegrated": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.Networking.Http.Interfaces": "0.3.13", + "Wabbajack.Services.OSIntegrated": "0.3.13" }, "runtime": { "Wabbajack.Server.Lib.dll": {} } }, - "Wabbajack.Services.OSIntegrated/0.3.12": { + "Wabbajack.Services.OSIntegrated/0.3.13": { "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.12", - "Wabbajack.Downloaders.Dispatcher": "0.3.12", - "Wabbajack.Installer": "0.3.12", - "Wabbajack.Networking.BethesdaNet": "0.3.12", - "Wabbajack.Networking.Discord": "0.3.12", - "Wabbajack.VFS": "0.3.12" + "Wabbajack.Compiler": "0.3.13", + "Wabbajack.Downloaders.Dispatcher": "0.3.13", + "Wabbajack.Installer": "0.3.13", + "Wabbajack.Networking.BethesdaNet": "0.3.13", + "Wabbajack.Networking.Discord": "0.3.13", + "Wabbajack.VFS": "0.3.13" }, "runtime": { "Wabbajack.Services.OSIntegrated.dll": {} } }, - "Wabbajack.VFS/0.3.12": { + "Wabbajack.VFS/0.3.13": { "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.12", - "Wabbajack.FileExtractor": "0.3.12", - "Wabbajack.Hashing.PHash": "0.3.12", - "Wabbajack.Hashing.xxHash64": "0.3.12", - "Wabbajack.Paths": "0.3.12", - "Wabbajack.Paths.IO": "0.3.12", - "Wabbajack.VFS.Interfaces": "0.3.12" + "Wabbajack.Common": "0.3.13", + "Wabbajack.FileExtractor": "0.3.13", + "Wabbajack.Hashing.PHash": "0.3.13", + "Wabbajack.Hashing.xxHash64": "0.3.13", + "Wabbajack.Paths": "0.3.13", + "Wabbajack.Paths.IO": "0.3.13", + "Wabbajack.VFS.Interfaces": "0.3.13" }, "runtime": { "Wabbajack.VFS.dll": {} } }, - "Wabbajack.VFS.Interfaces/0.3.12": { + "Wabbajack.VFS.Interfaces/0.3.13": { "dependencies": { "Microsoft.Extensions.DependencyInjection": "9.0.1", "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.1", - "Wabbajack.DTOs": "0.3.12", - "Wabbajack.Hashing.xxHash64": "0.3.12", - "Wabbajack.Paths": "0.3.12" + "Wabbajack.DTOs": "0.3.13", + "Wabbajack.Hashing.xxHash64": "0.3.13", + "Wabbajack.Paths": "0.3.13" }, "runtime": { "Wabbajack.VFS.Interfaces.dll": {} @@ -2332,7 +2332,7 @@ } }, "libraries": { - "jackify-engine/0.3.12": { + "jackify-engine/0.3.13": { "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.12": { + "Wabbajack.CLI.Builder/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Common/0.3.12": { + "Wabbajack.Common/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Compiler/0.3.12": { + "Wabbajack.Compiler/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Compression.BSA/0.3.12": { + "Wabbajack.Compression.BSA/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Compression.Zip/0.3.12": { + "Wabbajack.Compression.Zip/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Configuration/0.3.12": { + "Wabbajack.Configuration/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.Bethesda/0.3.12": { + "Wabbajack.Downloaders.Bethesda/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.Dispatcher/0.3.12": { + "Wabbajack.Downloaders.Dispatcher/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.GameFile/0.3.12": { + "Wabbajack.Downloaders.GameFile/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.GoogleDrive/0.3.12": { + "Wabbajack.Downloaders.GoogleDrive/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.Http/0.3.12": { + "Wabbajack.Downloaders.Http/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.Interfaces/0.3.12": { + "Wabbajack.Downloaders.Interfaces/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.IPS4OAuth2Downloader/0.3.12": { + "Wabbajack.Downloaders.IPS4OAuth2Downloader/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.Manual/0.3.12": { + "Wabbajack.Downloaders.Manual/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.MediaFire/0.3.12": { + "Wabbajack.Downloaders.MediaFire/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.Mega/0.3.12": { + "Wabbajack.Downloaders.Mega/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.ModDB/0.3.12": { + "Wabbajack.Downloaders.ModDB/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.Nexus/0.3.12": { + "Wabbajack.Downloaders.Nexus/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.VerificationCache/0.3.12": { + "Wabbajack.Downloaders.VerificationCache/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Downloaders.WabbajackCDN/0.3.12": { + "Wabbajack.Downloaders.WabbajackCDN/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.DTOs/0.3.12": { + "Wabbajack.DTOs/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.FileExtractor/0.3.12": { + "Wabbajack.FileExtractor/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Hashing.PHash/0.3.12": { + "Wabbajack.Hashing.PHash/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Hashing.xxHash64/0.3.12": { + "Wabbajack.Hashing.xxHash64/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Installer/0.3.12": { + "Wabbajack.Installer/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.IO.Async/0.3.12": { + "Wabbajack.IO.Async/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Networking.BethesdaNet/0.3.12": { + "Wabbajack.Networking.BethesdaNet/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Networking.Discord/0.3.12": { + "Wabbajack.Networking.Discord/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Networking.GitHub/0.3.12": { + "Wabbajack.Networking.GitHub/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Networking.Http/0.3.12": { + "Wabbajack.Networking.Http/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Networking.Http.Interfaces/0.3.12": { + "Wabbajack.Networking.Http.Interfaces/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Networking.NexusApi/0.3.12": { + "Wabbajack.Networking.NexusApi/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Networking.WabbajackClientApi/0.3.12": { + "Wabbajack.Networking.WabbajackClientApi/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Paths/0.3.12": { + "Wabbajack.Paths/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Paths.IO/0.3.12": { + "Wabbajack.Paths.IO/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.RateLimiter/0.3.12": { + "Wabbajack.RateLimiter/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Server.Lib/0.3.12": { + "Wabbajack.Server.Lib/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.Services.OSIntegrated/0.3.12": { + "Wabbajack.Services.OSIntegrated/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.VFS/0.3.12": { + "Wabbajack.VFS/0.3.13": { "type": "project", "serviceable": false, "sha512": "" }, - "Wabbajack.VFS.Interfaces/0.3.12": { + "Wabbajack.VFS.Interfaces/0.3.13": { "type": "project", "serviceable": false, "sha512": "" diff --git a/jackify/engine/jackify-engine.dll b/jackify/engine/jackify-engine.dll index ebd44ec..92eb41f 100644 Binary files a/jackify/engine/jackify-engine.dll and b/jackify/engine/jackify-engine.dll differ diff --git a/jackify/frontends/gui/main.py b/jackify/frontends/gui/main.py index 409c0ac..ce1bf65 100644 --- a/jackify/frontends/gui/main.py +++ b/jackify/frontends/gui/main.py @@ -181,59 +181,76 @@ class SettingsDialog(QDialog): self.resource_edits = {} resource_row_index = 0 for resource_row_index, (k, v) in enumerate(self.resource_settings.items(), start=1): - # Create resource label with optional inline checkbox for File Extractor - if k == "File Extractor": - # Create horizontal layout for File Extractor with inline checkbox - resource_row = QHBoxLayout() - resource_label = QLabel(f"{k}:", parent=self) - resource_row.addWidget(resource_label) - resource_row.addSpacing(10) # Add some spacing + try: + # Create resource label with optional inline checkbox for File Extractor + if k == "File Extractor": + # Create horizontal layout for File Extractor with inline checkbox + resource_row = QHBoxLayout() + resource_label = QLabel(f"{k}:", parent=self) + resource_row.addWidget(resource_label) + resource_row.addSpacing(10) # Add some spacing + + multithreading_checkbox = QCheckBox("Multithreading (Experimental)") + multithreading_checkbox.setChecked(v.get('_7zzMultiThread', 'off') == 'on') + multithreading_checkbox.setToolTip("Enables multithreaded file extraction using 7-Zip. May improve extraction speed on multi-core systems but could be less stable.") + multithreading_checkbox.setStyleSheet("color: #fff;") + resource_row.addWidget(multithreading_checkbox) + resource_row.addStretch() # Push checkbox to the left + + # Add the horizontal layout to the grid + resource_layout.addLayout(resource_row, resource_row_index, 0) + else: + resource_layout.addWidget(QLabel(f"{k}:", parent=self), resource_row_index, 0, 1, 1, Qt.AlignLeft) - multithreading_checkbox = QCheckBox("Multithreading (Experimental)") - multithreading_checkbox.setChecked(v.get('_7zzMultiThread', 'off') == 'on') - multithreading_checkbox.setToolTip("Enables multithreaded file extraction using 7-Zip. May improve extraction speed on multi-core systems but could be less stable.") - multithreading_checkbox.setStyleSheet("color: #fff;") - resource_row.addWidget(multithreading_checkbox) - resource_row.addStretch() # Push checkbox to the left + max_tasks_spin = QSpinBox() + max_tasks_spin.setMinimum(1) + max_tasks_spin.setMaximum(128) + max_tasks_spin.setValue(v.get('MaxTasks', 16)) + max_tasks_spin.setToolTip("Maximum number of concurrent tasks for this resource.") + max_tasks_spin.setFixedWidth(160) + resource_layout.addWidget(max_tasks_spin, resource_row_index, 1) - # Add the horizontal layout to the grid - resource_layout.addLayout(resource_row, resource_row_index, 0) - else: - resource_layout.addWidget(QLabel(f"{k}:", parent=self), resource_row_index, 0, 1, 1, Qt.AlignLeft) - - max_tasks_spin = QSpinBox() - max_tasks_spin.setMinimum(1) - max_tasks_spin.setMaximum(128) - max_tasks_spin.setValue(v.get('MaxTasks', 16)) - max_tasks_spin.setToolTip("Maximum number of concurrent tasks for this resource.") - max_tasks_spin.setFixedWidth(160) - resource_layout.addWidget(max_tasks_spin, resource_row_index, 1) - - # Store the widgets (checkbox for File Extractor, None for others) - if k == "File Extractor": - self.resource_edits[k] = (multithreading_checkbox, max_tasks_spin) - else: - self.resource_edits[k] = (None, max_tasks_spin) - # Bandwidth limiter row - self.app_settings_path = os.path.expanduser("~/.config/jackify/app_settings.json") - self.app_settings = self._load_json(self.app_settings_path) - self.bandwidth_spin = QSpinBox() - self.bandwidth_spin.setMinimum(0) - self.bandwidth_spin.setMaximum(1000000) - self.bandwidth_spin.setValue(self.app_settings.get("MaxDownloadSpeedKBps", 0)) - self.bandwidth_spin.setSuffix(" KB/s") - self.bandwidth_spin.setFixedWidth(160) - self.bandwidth_spin.setToolTip("Set the maximum download speed for modlist downloads. 0 = unlimited.") - bandwidth_note = QLabel("(0 = unlimited)") - bandwidth_note.setStyleSheet("color: #aaa; font-size: 10pt;") - # Create horizontal layout for bandwidth row - bandwidth_row = QHBoxLayout() - bandwidth_row.addWidget(self.bandwidth_spin) - bandwidth_row.addWidget(bandwidth_note) - bandwidth_row.addStretch() # Push to the left + # Store the widgets (checkbox for File Extractor, None for others) + if k == "File Extractor": + self.resource_edits[k] = (multithreading_checkbox, max_tasks_spin) + else: + self.resource_edits[k] = (None, max_tasks_spin) + except Exception as e: + print(f"[ERROR] Failed to create widgets for resource '{k}': {e}") + continue - resource_layout.addWidget(QLabel("Bandwidth Limit:", parent=self), resource_row_index+1, 0, 1, 1, Qt.AlignLeft) - resource_layout.addLayout(bandwidth_row, resource_row_index+1, 1) + # If no resources exist, show helpful message + if not self.resource_edits: + info_label = QLabel("Resource Limit settings will be generated once a modlist install action is performed") + info_label.setStyleSheet("color: #aaa; font-style: italic; padding: 20px; font-size: 11pt;") + info_label.setWordWrap(True) + info_label.setAlignment(Qt.AlignCenter) + info_label.setMinimumHeight(60) # Ensure enough height to prevent cutoff + resource_layout.addWidget(info_label, 1, 0, 3, 2) # Span more rows for better space + + # Bandwidth limiter row (only show if Downloads resource exists) + if "Downloads" in self.resource_settings: + downloads_throughput = self.resource_settings["Downloads"].get("MaxThroughput", 0) + + self.bandwidth_spin = QSpinBox() + self.bandwidth_spin.setMinimum(0) + self.bandwidth_spin.setMaximum(1000000) + self.bandwidth_spin.setValue(downloads_throughput) + self.bandwidth_spin.setSuffix(" KB/s") + self.bandwidth_spin.setFixedWidth(160) + self.bandwidth_spin.setToolTip("Set the maximum download speed for modlist downloads. 0 = unlimited.") + bandwidth_note = QLabel("(0 = unlimited)") + bandwidth_note.setStyleSheet("color: #aaa; font-size: 10pt;") + # Create horizontal layout for bandwidth row + bandwidth_row = QHBoxLayout() + bandwidth_row.addWidget(self.bandwidth_spin) + bandwidth_row.addWidget(bandwidth_note) + bandwidth_row.addStretch() # Push to the left + + resource_layout.addWidget(QLabel("Bandwidth Limit:", parent=self), resource_row_index+1, 0, 1, 1, Qt.AlignLeft) + resource_layout.addLayout(bandwidth_row, resource_row_index+1, 1) + else: + self.bandwidth_spin = None # No bandwidth UI if Downloads resource doesn't exist main_layout.addWidget(resource_group) main_layout.addSpacing(12) @@ -328,12 +345,13 @@ class SettingsDialog(QDialog): main_layout.addLayout(btn_layout) # Set tab order for accessibility - # Get the first resource's widgets - first_resource_key = list(self.resource_edits.keys())[0] - first_multithreading, first_max_tasks = self.resource_edits[first_resource_key] - - # Set tab order starting with the first max tasks spinner - self.setTabOrder(first_max_tasks, self.bandwidth_spin) + # Get the first resource's widgets if any exist + if self.resource_edits: + first_resource_key = list(self.resource_edits.keys())[0] + first_multithreading, first_max_tasks = self.resource_edits[first_resource_key] + # Set tab order starting with the first max tasks spinner + self.setTabOrder(first_max_tasks, self.bandwidth_spin) + # Continue with bandwidth spinner regardless of resources self.setTabOrder(self.bandwidth_spin, self.debug_checkbox) self.setTabOrder(self.debug_checkbox, self.api_key_edit) self.setTabOrder(self.api_key_edit, self.api_show_btn) @@ -412,7 +430,7 @@ class SettingsDialog(QDialog): if max_tasks_spin.value() > 128: self.error_label.setText(f"Invalid value for {k}: Max Tasks must be <= 128.") return - if self.bandwidth_spin.value() > 1000000: + if self.bandwidth_spin and self.bandwidth_spin.value() > 1000000: self.error_label.setText("Bandwidth limit must be <= 1,000,000 KB/s.") return self.error_label.setText("") @@ -428,12 +446,18 @@ class SettingsDialog(QDialog): # Remove the setting if unchecked (don't add 'off') resource_data.pop('_7zzMultiThread', None) self.resource_settings[k] = resource_data + + # Save bandwidth limit to Downloads resource MaxThroughput (only if bandwidth UI exists) + if self.bandwidth_spin: + if "Downloads" not in self.resource_settings: + self.resource_settings["Downloads"] = {"MaxTasks": 16} # Provide default MaxTasks + self.resource_settings["Downloads"]["MaxThroughput"] = self.bandwidth_spin.value() + + # Save all resource settings (including bandwidth) in one operation self._save_json(self.resource_settings_path, self.resource_settings) + # Save debug mode to config self.config_handler.set('debug_mode', self.debug_checkbox.isChecked()) - # Save bandwidth limit - self.app_settings["MaxDownloadSpeedKBps"] = self.bandwidth_spin.value() - self._save_json(self.app_settings_path, self.app_settings) # Save API key api_key = self.api_key_edit.text().strip() self.config_handler.save_api_key(api_key) diff --git a/jackify/frontends/gui/screens/install_modlist.py b/jackify/frontends/gui/screens/install_modlist.py index 5bd86de..11573b4 100644 --- a/jackify/frontends/gui/screens/install_modlist.py +++ b/jackify/frontends/gui/screens/install_modlist.py @@ -745,19 +745,22 @@ class InstallModlistScreen(QWidget): self.console.setMinimumHeight(50) # Keep minimum height for usability def showEvent(self, event): - """Called when the widget becomes visible - reload saved API key only""" + """Called when the widget becomes visible - always reload saved API key""" super().showEvent(event) - # Reload saved API key if available and field is empty - if not self.api_key_edit.text().strip() or (self.api_key_is_obfuscated and not self.api_key_original_text.strip()): - saved_key = self.api_key_service.get_saved_api_key() - if saved_key: - self.api_key_original_text = saved_key - self.api_key_edit.setText(saved_key) - self.api_key_is_obfuscated = False # Start unobfuscated - # Set checkbox state - self.save_api_key_checkbox.setChecked(True) - # Start obfuscation timer - self.api_key_obfuscation_timer.start(3000) + # Always reload saved API key to pick up changes from Settings dialog + saved_key = self.api_key_service.get_saved_api_key() + if saved_key: + self.api_key_original_text = saved_key + self.api_key_edit.setText(saved_key) + self.api_key_is_obfuscated = False # Start unobfuscated + # Set checkbox state + self.save_api_key_checkbox.setChecked(True) + # Immediately obfuscate saved keys (don't wait 3 seconds) + self._obfuscate_api_key() + elif not self.api_key_edit.text().strip(): + # Only clear if no saved key and field is empty + self.api_key_original_text = "" + self.save_api_key_checkbox.setChecked(False) # Do NOT load saved parent directories def _load_saved_parent_directories(self): diff --git a/jackify/frontends/gui/screens/tuxborn_installer.py b/jackify/frontends/gui/screens/tuxborn_installer.py index d37a6e3..3a10bb4 100644 --- a/jackify/frontends/gui/screens/tuxborn_installer.py +++ b/jackify/frontends/gui/screens/tuxborn_installer.py @@ -461,19 +461,22 @@ class TuxbornInstallerScreen(QWidget): self.console.setMinimumHeight(50) # Keep minimum height for usability def showEvent(self, event): - """Called when the widget becomes visible - reload saved API key and parent directories""" + """Called when the widget becomes visible - always reload saved API key and parent directories""" super().showEvent(event) - # Reload saved API key if available and field is empty - if not self.api_key_edit.text().strip() or (self.api_key_is_obfuscated and not self.api_key_original_text.strip()): - saved_key = self.api_key_service.get_saved_api_key() - if saved_key: - self.api_key_original_text = saved_key - self.api_key_edit.setText(saved_key) - self.api_key_is_obfuscated = False # Start unobfuscated - # Set checkbox state - self.save_api_key_checkbox.setChecked(True) - # Start obfuscation timer - self.api_key_obfuscation_timer.start(3000) + # Always reload saved API key to pick up changes from Settings dialog + saved_key = self.api_key_service.get_saved_api_key() + if saved_key: + self.api_key_original_text = saved_key + self.api_key_edit.setText(saved_key) + self.api_key_is_obfuscated = False # Start unobfuscated + # Set checkbox state + self.save_api_key_checkbox.setChecked(True) + # Immediately obfuscate saved keys (don't wait 3 seconds) + self._obfuscate_api_key() + elif not self.api_key_edit.text().strip(): + # Only clear if no saved key and field is empty + self.api_key_original_text = "" + self.save_api_key_checkbox.setChecked(False) # Load saved parent directories and pre-populate fields self._load_saved_parent_directories()