From ca014969e1d8c53e1d4a179dfe17bd0b9e13bd67 Mon Sep 17 00:00:00 2001 From: tomasalias Date: Mon, 12 Oct 2026 19:44:33 +0200 Subject: [PATCH] docs: update documentation and README with smooth updater splash and new icon --- README.md | 26 +++++++++++++++----------- docs/guide/installation.md | 17 +++++++++++------ docs/index.md | 4 ++-- docs/public/logo.svg | 21 ++------------------- patcher/patcher_gui.py | 14 +++++++------- 5 files changed, 37 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 8d2e64a..f681a6b 100644 --- a/README.md +++ b/README.md @@ -65,28 +65,32 @@ # Run background watcher daemon directly .\BetterCurseForge.exe watch + +# Trigger the smooth splash updater GUI manually +.\BetterCurseForge.exe --repatch-splash ``` --- ## 🔄 How Auto-Repatch Works -Whenever CurseForge downloads an update, the Overwolf installer replaces `resources/app.asar` with a vanilla archive and restarts `CurseForge.exe`. BetterCurseForge guarantees you never lose your patch: +Whenever CurseForge downloads an official update, the Overwolf installer replaces `resources/app.asar` with an unpatched vanilla archive and automatically restarts `CurseForge.exe`. BetterCurseForge guarantees a **smooth, zero-delay transition** where you never lose your patch and the unpatched app is never shown on screen: ```mermaid flowchart TD - A[CurseForge Launcher Update] -->|Installer downloads update| B[CurseForge Quitting / Replacing Files] - B -->|Watcher Detects Update| C[Auto-Repatch Triggered] - C -->|Wait for Installer Files to Settle| D[Settle Verified] - D -->|Offline Extraction & Patch <3s| E[Dist & BetterCF Injected] - E -->|Recalculate ASAR SHA-256| F[Synchronize OWEASARSIG in CurseForge.exe] - F -->|Autonomous Relaunch| G[Modded CurseForge Launcher Ready!] + A[CurseForge Launcher Update] -->|Overwolf installer replaces files| B[Installer Attempts to Launch Vanilla App] + B -->|Active Interceptor <50ms| C[Vanilla Launcher Suppressed Silently] + C -->|Auto-Repatch Triggered| D[Dedicated Splash Updater GUI Appears] + D -->|Real-time Status & Progress| E[Offline Extraction & Patching <3s] + E -->|Synchronize OWEASARSIG| F[CurseForge.exe Integrity Signature Updated] + F -->|Autonomous Relaunch| G[Modded BetterCurseForge Launches Ready!] ``` -1. **Permanent Daemon Installation**: On first patch, BetterCurseForge installs to `%LOCALAPPDATA%\BetterCurseForge` with an autostart registry entry in `HKCU\...\Run` and a task scheduler fallback. -2. **Global Mutex Synchronization**: Uses Windows kernel named mutexes (`BetterCurseForgePatchMutex`) to guarantee atomic, single-process patching with zero race conditions. -3. **Resilient Win32 Watcher Daemon**: A silent background process monitors CurseForge's installation directory with 0% CPU consumption. If an unpatched state is detected (e.g., after an update), it waits for installer files to settle, terminates the unpatched process, reapplies the patch, and relaunches the modded client seamlessly without console window popups. -4. **100% Offline Zero-Delay ASAR Engine**: Unpacking and repacking use bundled tools combined with CurseForge's built-in Node runtime (`ELECTRON_RUN_AS_NODE=1`), completing the entire repatch cycle in 2–3 seconds without requiring an internet connection. +1. **Active Vanilla Interceptor**: When an update or unpatched state is detected, BetterCurseForge polls in tight 150ms slices using lightweight Win32 kernel process enumeration. If the installer starts `CurseForge.exe`, it is terminated within 50ms before Chromium or Electron can render a single frame—guaranteeing the unpatched client never flashes on screen. +2. **Dedicated Splash Updater GUI**: Rather than patching silently without visual feedback, BetterCurseForge displays a sleek, centered dark-themed card (`#121214`) featuring the official application icon, an animated purple progress bar, and real-time status updates (*"Waiting for installer..."*, *"Extracting application archive..."*, *"Unlocking native premium themes..."*, *"Injecting zero-ad rules..."*, *"Updating security signatures..."*). +3. **Global Mutex Synchronization**: Uses Windows kernel named mutexes (`BetterCurseForgePatchMutex`, `BetterCurseForgeSplashMutex`) to guarantee atomic, single-process patching with zero race conditions or duplicate windows. +4. **Resilient Win32 Watcher Daemon**: A silent background process monitors CurseForge's installation directory with 0% CPU consumption during idle. It triggers the splash updater whenever an update is applied and handles all persistence automatically. +5. **100% Offline Zero-Delay ASAR Engine**: Unpacking and repacking use bundled tools combined with CurseForge's built-in Node runtime (`ELECTRON_RUN_AS_NODE=1`), completing the entire repatch cycle in 2–3 seconds without requiring an internet connection. --- diff --git a/docs/guide/installation.md b/docs/guide/installation.md index ebd9970..bdca5b4 100644 --- a/docs/guide/installation.md +++ b/docs/guide/installation.md @@ -34,7 +34,7 @@ Place it in any convenient folder (e.g., Downloads, Tools, or desktop). Double-click `BetterCurseForge.exe` to launch the application. -![BetterCurseForge GUI](/logo.svg){width=64 style="display:block;margin:1rem auto;"} +![BetterCurseForge GUI](/logo.png){width=64 style="display:block;margin:1rem auto;"} The application automatically: - Detects your CurseForge installation folder from the Windows Registry. @@ -113,9 +113,9 @@ This restores `resources/app.asar` from the vanilla backup and re-verifies origi ## Auto-Repatch: Surviving CurseForge Updates -When the official CurseForge Launcher downloads an automatic update, it overwrites `app.asar` with a new version, temporarily removing client modifications. +When the official CurseForge Launcher downloads an automatic update, it overwrites `app.asar` with an unpatched version and attempts to restart. -BetterCurseForge solves this with **Auto-Repatch**: +BetterCurseForge provides an autonomous, smooth transition with **zero screen flashing**: ### Managing Auto-Repatch in the GUI - In the BetterCurseForge desktop application, simply toggle the **Auto-Repatch on Update** button (turns green when active). @@ -125,15 +125,20 @@ BetterCurseForge solves this with **Auto-Repatch**: # Run the background watcher daemon directly: .\BetterCurseForge.exe watch +# Trigger the smooth splash updater GUI manually: +.\BetterCurseForge.exe --repatch-splash + # BetterCurseForge also manages watcher persistence automatically on patch/unpatch: .\BetterCurseForge.exe patch # Applies patch and activates watcher autostart .\BetterCurseForge.exe unpatch # Restores vanilla client and stops watcher ``` ### How Auto-Repatch Works -1. **Background Watcher**: Runs silently with 0% CPU consumption via Windows directory event notifications. -2. **Global Mutex Lock**: Uses kernel named mutexes to guarantee single-instance execution and avoid race conditions. -3. **Automatic Re-Patching**: Whenever CurseForge updates, the watcher waits for the installer to finish, reapplies BetterCurseForge modifications offline in 2–3 seconds, synchronizes executable signatures, and relaunches the modded client seamlessly without popping command prompt windows. +1. **Background Watcher**: Runs silently with 0% CPU consumption via Windows directory event notifications and heartbeat checks. +2. **Active Vanilla Interceptor**: When an update or unpatched state is detected, the patcher polls every 150ms using Win32 kernel process enumeration. If the installer launches `CurseForge.exe`, it is killed within 50ms before any window or frame can appear. +3. **Dedicated Splash Updater GUI**: A modern, dark-themed `#121214` card appears on screen displaying the application icon, a purple `AUTO-UPDATE` badge, an animated progress bar, and real-time status messages while extracting, unlocking themes, removing ads, and repacking. +4. **Offline Zero-Delay Engine**: Offline ASAR extraction and repacking complete in 2–3 seconds using CurseForge's built-in Node v24 runtime (`ELECTRON_RUN_AS_NODE=1`), synchronizing the `OWEASARSIG` hash directly inside `CurseForge.exe`. +5. **Seamless Relaunch**: The patched BetterCurseForge client opens automatically, and the splash window gracefully closes. --- diff --git a/docs/index.md b/docs/index.md index b9d0359..a5e83a4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -24,8 +24,8 @@ features: title: Client Themes & Free Skins details: Integrated directly into Settings -> Themes with live hover previews, theme folder shortcuts, and all native CurseForge Premium themes unlocked for free. - icon: 🔄 - title: Auto-Repatch - details: Survives launcher updates effortlessly. The automated background task detects CurseForge updates and silently re-patches the client. + title: Auto-Repatch & Smooth Updates + details: Survives launcher updates effortlessly. The active interceptor suppresses unpatched windows, and a sleek splash GUI displays live progress while repatching in seconds. - icon: 🖥️ title: Modern GUI & CLI details: Includes an intuitive dark-themed desktop application with one-click actions, as well as a full command-line interface for power users. diff --git a/docs/public/logo.svg b/docs/public/logo.svg index 63aca00..f9ec235 100644 --- a/docs/public/logo.svg +++ b/docs/public/logo.svg @@ -1,20 +1,3 @@ - - - - - - - - - - - - - - - - - - - + + diff --git a/patcher/patcher_gui.py b/patcher/patcher_gui.py index 175d19f..9332925 100644 --- a/patcher/patcher_gui.py +++ b/patcher/patcher_gui.py @@ -720,30 +720,30 @@ if __name__ == "__main__": try: if len(sys.argv) > 1: arg = sys.argv[1].lower() - if arg == "--watch": + if arg in ("--watch", "watch"): patch_core.run_watcher_loop() sys.exit(0) - elif arg in ("--repatch-splash", "--splash"): + elif arg in ("--repatch-splash", "--splash", "splash"): pid = int(sys.argv[2]) if len(sys.argv) > 2 and sys.argv[2].isdigit() else None splash = SplashUpdaterWindow(pid) splash.run() sys.exit(0) - elif arg == "--wait-for-update": + elif arg in ("--wait-for-update", "wait-for-update"): pid = int(sys.argv[2]) if len(sys.argv) > 2 and sys.argv[2].isdigit() else None splash = SplashUpdaterWindow(pid) splash.run() sys.exit(0) - elif arg == "--ensure-watcher": + elif arg in ("--ensure-watcher", "ensure-watcher"): if not patch_core.is_watcher_running(): patch_core.start_background_watcher() sys.exit(0) - elif arg == "patch": + elif arg in ("--patch", "patch"): patch_core.patch_curseforge() sys.exit(0) - elif arg == "unpatch": + elif arg in ("--unpatch", "unpatch"): patch_core.unpatch_curseforge() sys.exit(0) - elif arg == "status": + elif arg in ("--status", "status"): cf = patch_core.get_curseforge_dir() print("CurseForge:", cf) print("Patched:", patch_core.is_curseforge_patched(cf) if cf else False)