Files
metin-launcher/scripts/build-wine-bundle.sh
Jan Nedbal e6b4060e5c launcher: wine bundle layout, richer progress, path shortening
After Jan's colleague hit "wine: failed to open" on the single-file
Metin2Launcher.exe (downloaded as Metin2Launcher(3).exe by Brave) and
then a separate case where the self-contained single-file host crashes
under Wine before Program.Main() even runs, we pivoted to a bundle
layout that actually works under Wine: a non-single-file .NET publish
placed in launcher/ alongside a sibling client/ directory.

Changes:

- InstallDir.Resolve() adds a special case for the Wine bundle layout.
  If the running exe lives in a directory literally named "launcher"
  (see LauncherConfig.WineLauncherDirName) AND a sibling "client" dir
  exists (WineClientDirName), the install dir resolves to that sibling.
  This keeps launcher runtime files (Avalonia DLLs, Skia, etc.) out of
  the install dir so the orchestrator's apply/prune never clobbers the
  launcher's own files.
- LauncherConfig: WineLauncherDirName / WineClientDirName constants.
- UpdateOrchestrator: report InstallRoot, StagingRoot, DownloadedBytes,
  TotalBytes on every progress event so the GUI can display them.
- MainWindowViewModel: cache install/staging paths and transferred
  bytes, expose TransferText and InstallPathText with shortened-home
  (~/...) and middle-elided path strings so long Wine Z: paths remain
  readable.
- MainWindow.axaml: render the new transfer / path lines under the
  progress bar.
- cs.json / en.json: new localized status strings.
- README.md: document the Wine bundle layout.
- scripts/build-wine-bundle.sh: reproducible builder that runs
  `dotnet publish -r win-x64 --self-contained -p:PublishSingleFile=false`
  into launcher/, creates sibling client/, writes start-launcher.sh
  that sets METIN2_INSTALL_DIR=./client and execs wine, then tars the
  whole tree into Metin2Launcher-wine.tar.gz.

Verified:
- dotnet build -c Release — clean
- dotnet test -c Release — 93/93 pass
- build-wine-bundle.sh produces a 45 MB tar.gz; tree contents check
  out, launcher/Metin2Launcher.exe is the non-single-file variant
- bundle uploaded to https://updates.jakubkadlec.dev/launcher/Metin2Launcher-wine.tar.gz

The single-file exe path remains broken under Wine (debugging track
tracked outside this commit — candidate root cause is the
self-extraction + unmanaged host startup path under Wine's PE
loader). For Windows users the single-file build still works; for
Linux+Wine users the bundle is the canonical distribution format.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 18:09:43 +02:00

72 lines
1.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
die() { echo "error: $*" >&2; exit 1; }
say() { echo "[build-wine-bundle] $*"; }
REPO_ROOT=$(cd "$(dirname "$0")/.." && pwd)
CSPROJ="$REPO_ROOT/src/Metin2Launcher/Metin2Launcher.csproj"
OUT_ROOT="${1:-$REPO_ROOT/release-wine}"
PUBLISH_DIR="$OUT_ROOT/publish-win-x64"
BUNDLE_ROOT="$OUT_ROOT/Metin2Launcher-wine"
LAUNCHER_DIR="$BUNDLE_ROOT/launcher"
CLIENT_DIR="$BUNDLE_ROOT/client"
ARCHIVE="$OUT_ROOT/Metin2Launcher-wine.tar.gz"
[[ -f "$CSPROJ" ]] || die "csproj not found: $CSPROJ"
say "repo: $REPO_ROOT"
say "output root: $OUT_ROOT"
rm -rf "$PUBLISH_DIR" "$BUNDLE_ROOT"
mkdir -p "$LAUNCHER_DIR" "$CLIENT_DIR"
say "[1/4] publish win-x64 non-single-file launcher"
dotnet publish "$CSPROJ" \
-c Release \
-r win-x64 \
--self-contained \
-p:PublishSingleFile=false \
-p:IncludeNativeLibrariesForSelfExtract=false \
-o "$PUBLISH_DIR"
[[ -f "$PUBLISH_DIR/Metin2Launcher.exe" ]] || die "publish output missing Metin2Launcher.exe"
say "[2/4] assemble Wine bundle layout"
rsync -a --delete "$PUBLISH_DIR"/ "$LAUNCHER_DIR"/
cat > "$BUNDLE_ROOT/start-launcher.sh" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
ROOT=$(cd "$(dirname "$0")" && pwd)
export METIN2_INSTALL_DIR="$ROOT/client"
cd "$ROOT/launcher"
exec wine ./Metin2Launcher.exe "$@"
EOF
cat > "$BUNDLE_ROOT/README.txt" <<'EOF'
Metin2Launcher Wine bundle
Layout:
- launcher/ launcher runtime (.exe + DLLs)
- client/ final game install dir and .updates/ state
Run:
./start-launcher.sh
The launcher installs into client/, not into launcher/.
EOF
chmod +x "$BUNDLE_ROOT/start-launcher.sh"
say "[3/4] archive bundle"
mkdir -p "$OUT_ROOT"
tar -C "$OUT_ROOT" -czf "$ARCHIVE" "$(basename "$BUNDLE_ROOT")"
say "[4/4] done"
du -sh "$BUNDLE_ROOT" "$ARCHIVE"
printf '%s\n' "$BUNDLE_ROOT"
printf '%s\n' "$ARCHIVE"