fix(launcher): drop patch-Z.MPQ from default files and migrate old configs

- default-launcher.json files: only Wow-patched.exe from release.
- config-store: strip deprecated patch-Z.MPQ from merged files; rewrite
  launcher.json on load if user still had that entry.
- Docs/scripts examples updated; version 1.0.4.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Docker Build
2026-05-10 21:36:50 -05:00
parent 1fb284cb5c
commit b455db0db8
6 changed files with 31 additions and 16 deletions
+2 -2
View File
@@ -134,7 +134,7 @@ Do **not** embed a shared admin PAT in a shipped `launcher.json`. Prefer read-on
## Patch versions (same filenames, different bytes)
The launcher does **not** read Git commits. For **turn-key** updates when asset names stay fixed (`patch-Z.MPQ`, `Wow-patched.exe`, …):
The launcher does **not** read Git commits. For **turn-key** updates when asset names stay fixed (e.g. **`Wow-patched.exe`** — add more **`files`** entries for any extra MPQs you ship):
1. Ship **`patch-manifest.json`** next to those files on **every** release (Gitea/GitHub attachment). It lists a **`version`** label (any string you bump per release, e.g. `v0.9.0-client`) and a **`sha256`** per **`files[].source`** name.
2. With **`patch_manifest.enabled`**: true (default in **`default-launcher.json`**), **Download updates** first fetches the manifest from the same release channel. If the files already on disk match those checksums, the player sees **“already match build … (nothing to download)”** — no redundant downloads.
@@ -146,7 +146,7 @@ If **`patch-manifest.json`** is missing on a release, the launcher falls back to
```bash
cd /path/to/staging
node tools/fractured-launcher-electron/scripts/generate-patch-manifest.js v0.9.0-client patch-Z.MPQ Wow-patched.exe > patch-manifest.json
node tools/fractured-launcher-electron/scripts/generate-patch-manifest.js v0.9.0-client Wow-patched.exe > patch-manifest.json
```
Attach **`patch-manifest.json`** together with the MPQ/exe to the GitHub release (CI sync copies it to Gitea with everything else).
@@ -22,12 +22,6 @@
"from_release": true
},
"files": [
{
"source": "patch-Z.MPQ",
"dest": "Data/patch-Z.MPQ",
"backup": true,
"from_release": true
},
{
"source": "Wow-patched.exe",
"dest": "Wow.exe",
@@ -3,6 +3,23 @@
const path = require('path');
const fs = require('fs').promises;
/** Sources no longer shipped; drop from merged files so old launcher.json does not keep fetching them. */
const DEPRECATED_FILE_SOURCES = new Set(['patch-Z.MPQ']);
function mergeFilesList(defaults, user) {
const raw =
Array.isArray(user.files) && user.files.length ? user.files.map((e) => ({ ...e })) : defaults.files.map((e) => ({ ...e }));
const filtered = raw.filter((e) => !DEPRECATED_FILE_SOURCES.has(String(e && e.source ? e.source : '').trim()));
if (filtered.length) return filtered;
return defaults.files.map((e) => ({ ...e }));
}
function userFilesContainDeprecated(user) {
const files = user && user.files;
if (!Array.isArray(files)) return false;
return files.some((e) => DEPRECATED_FILE_SOURCES.has(String(e && e.source ? e.source : '').trim()));
}
function mergeConfig(defaults, user) {
return {
...defaults,
@@ -21,7 +38,7 @@ function mergeConfig(defaults, user) {
launch: { ...defaults.launch, ...(user.launch || {}) },
auth: user.auth != null ? { ...defaults.auth, ...user.auth } : defaults.auth,
realmlist: user.realmlist != null ? { ...defaults.realmlist, ...user.realmlist } : defaults.realmlist,
files: Array.isArray(user.files) && user.files.length ? user.files : defaults.files,
files: mergeFilesList(defaults, user),
};
}
@@ -60,7 +77,11 @@ async function loadConfig(app) {
const defaults = JSON.parse(await fs.readFile(defPath, 'utf8'));
try {
const user = JSON.parse(await fs.readFile(p, 'utf8'));
return { configPath: p, config: applyBakedGitea(mergeConfig(defaults, user)) };
const config = applyBakedGitea(mergeConfig(defaults, user));
if (userFilesContainDeprecated(user)) {
await fs.writeFile(p, JSON.stringify(config, null, 2), 'utf8');
}
return { configPath: p, config };
} catch (e) {
if (e.code === 'ENOENT') {
const initial = applyBakedGitea(mergeConfig(defaults, {}));
@@ -1,6 +1,6 @@
{
"name": "fractured-launcher-electron",
"version": "1.0.3",
"version": "1.0.4",
"description": "Fractured WoW launcher (Electron) — no console window, native folder picker, auto-update",
"main": "main.js",
"repository": {
@@ -2,11 +2,11 @@
/**
* Build patch-manifest.json for a release (same names as files[].source in launcher.json).
*
* Usage (from a folder containing the patch binaries):
* node generate-patch-manifest.js v0.9.0-client patch-Z.MPQ Wow-patched.exe
* Usage (from a folder containing the patch binaries — list every files[].source name):
* node generate-patch-manifest.js v0.9.0-client Wow-patched.exe
*
* Prints JSON to stdout — redirect to file:
* node generate-patch-manifest.js v0.9.0-client patch-Z.MPQ Wow-patched.exe > patch-manifest.json
* node generate-patch-manifest.js v0.9.0-client Wow-patched.exe > patch-manifest.json
*/
'use strict';
@@ -18,7 +18,7 @@ const version = process.argv[2];
const names = process.argv.slice(3);
if (!version || names.length === 0) {
console.error('Usage: generate-patch-manifest.js <version-label> <file1> [file2 ...]');
console.error(' Example: generate-patch-manifest.js v0.9.0-client patch-Z.MPQ Wow-patched.exe');
console.error(' Example: generate-patch-manifest.js v0.9.0-client Wow-patched.exe');
process.exit(1);
}
@@ -3,7 +3,7 @@
#
# Usage (from repo root or this directory):
# export GH_TOKEN=ghp_... # PAT with repo/releases on the distro repo
# ./tools/fractured-launcher-electron/scripts/publish-to-distro.sh v1.0.0 patch-Z.MPQ Wow-patched.exe
# ./tools/fractured-launcher-electron/scripts/publish-to-distro.sh v1.0.0 Wow-patched.exe
#
# Optional:
# DISTRO_REPO=YourOrg/Fratured-Distro # if your GitHub slug differs