From 390546e9f17e31f37bdbf33a742927fc77c6e266 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 25 Jun 2026 14:09:09 +0000 Subject: [PATCH] Replace Wine-based Kyber setup with native Linux AppImage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Windows kyber_launcher.exe approach under Wine/Proton has two unfixable problems on Linux: Wine's cmd.exe crashes with STATUS_ACCESS_VIOLATION on the long EA OAuth URL, and EA's auth callback uses the eadesktop:// URI scheme which has no Linux handler. The correct solution is the native Linux port AppImage maintained at github.com/simonlinuxcraft/kyber-linuxport-unofficial. It bundles Maxima (open-source EA Desktop replacement) and handles OAuth natively — no shims, no watchers, no per-Proton-update maintenance. Script now: fetches latest release from GitHub API, downloads AppImage, installs desktop entry and ~/.local/bin/kyber symlink. README: add Gaming scripts section documenting Kyber setup, private server hosting with bots, requirements, and what does not work. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs --- README.md | 50 +++ scripts/setup-kyber-linux.sh | 647 +++++++---------------------------- 2 files changed, 173 insertions(+), 524 deletions(-) diff --git a/README.md b/README.md index 55e4f51..0bd98d0 100644 --- a/README.md +++ b/README.md @@ -137,3 +137,53 @@ then either: Tested on **Ubuntu 24.04 LTS** and **26.04 LTS**. Works on any Ubuntu LTS ≥ 22.04; non-LTS releases also work. The wizard shows the detected OS in the header and warns on unknown versions. + +## Gaming scripts + +Standalone scripts in `scripts/` for gaming setup — not part of the main +wizard, run separately. + +### Star Wars Battlefront II (2017) + Kyber + +**`scripts/setup-swbf2-linux.sh`** — Configure SWBF2 on native Linux Steam +(Proton, controller, performance tweaks). + +**`scripts/setup-kyber-linux.sh`** — Install the native Linux Kyber launcher. + +Kyber is the community multiplayer replacement for SWBF2 after EA shut down +official servers in 2022. It went open-source (GPL) in January 2026. + +**The correct approach is a native Linux AppImage** — not Wine or Proton for +the launcher itself. The AppImage is maintained at: +https://github.com/simonlinuxcraft/kyber-linuxport-unofficial + +```bash +chmod +x scripts/setup-kyber-linux.sh +./scripts/setup-kyber-linux.sh +``` + +The script downloads the latest AppImage, installs a desktop entry, and +creates a `kyber` command in `~/.local/bin`. + +**First run:** +1. Click **EA Account** → log in with your EA credentials in the browser +2. Click **Skip** on Nexus Mods (optional, only needed for mods) +3. Browse servers on **HOME** or create one under **HOST** + +**Hosting a private server with bots:** +- HOST → pick maps/modes → set a **name** and **PASSWORD** → Start Server +- Share the name + password with friends; they search by name in HOME +- SWBF2 fills empty slots with AI automatically — no separate bot setting + +**Requirements:** +- SWBF2 (Steam AppID 1237950) installed with GE-Proton (recommended over + Proton Experimental for game stability) +- glibc 2.38+ — Ubuntu 24.04+, Fedora 38+, SteamOS 3.7+ +- EA account (free) at ea.com + +**What does NOT work:** +- Running the Windows `kyber_launcher.exe` under Wine/Proton: EA's auth + callback uses the `eadesktop://` URI scheme which has no Linux handler, + and Wine's cmd.exe crashes on long OAuth URLs anyway +- Running Kyber inside Wolf/Games-on-Whales: the Docker double-sandbox + blocks the user namespace clone that Proton requires diff --git a/scripts/setup-kyber-linux.sh b/scripts/setup-kyber-linux.sh index a5b7418..ce2ec54 100755 --- a/scripts/setup-kyber-linux.sh +++ b/scripts/setup-kyber-linux.sh @@ -1,574 +1,173 @@ #!/bin/bash -# setup-kyber-linux.sh — Install the Kyber Launcher for SWBF2 (2017) on a -# native Linux Steam machine (headless or desktop) with Proton Experimental. +# setup-kyber-linux.sh — Install the Kyber Launcher (native Linux port) for +# SWBF2 (2017) on a native Linux Steam machine. # # Kyber is a community multiplayer client for Star Wars Battlefront II (2017) -# after EA shut down the official servers. It is a Windows app (Flutter/Rust). +# after EA shut down the official servers in 2022. Kyber went open-source +# under GPL in January 2026. # -# ── How Kyber's EA login actually works ──────────────────────────────────── +# ── The RIGHT way: native Linux AppImage ─────────────────────────────────── # -# Kyber uses the "Maxima" OAuth PKCE flow: -# 1. Kyber starts a temporary HTTP server on 127.0.0.1 (dynamic port ~41413+) -# 2. It calls cmd /c start "" "" to open a browser -# 3. You log in on the EA page; EA redirects to 127.0.0.1:PORT/?code=... -# 4. Kyber's HTTP server catches the code and exchanges it for tokens +# As of 2026 there is an unofficial native Linux port of Kyber: +# https://github.com/simonlinuxcraft/kyber-linuxport-unofficial # -# Problem: Wine's cmd.exe crashes with STATUS_ACCESS_VIOLATION (0xC0000005) -# when called with a long EA auth URL. This blocks login entirely. +# It ships as a self-contained AppImage (x86_64). No Wine, no Proton, no +# cmd.exe shims, no OAuth watcher daemons. EA login is handled natively by +# the bundled Maxima service (open-source EA Desktop replacement by the +# Armchair Developers team). # -# Fix: Replace Proton's own cmd.exe (files/lib/wine/x86_64-windows/cmd.exe) -# with a tiny shim that captures any http URL from its command line, writes -# it to C:\kyber_oauth_url.txt, and exits 0. A Linux-side watcher calls -# xdg-open on that file to open the browser. Wine loads cmd.exe from Proton's -# installation, not the prefix — prefix replacements, IFEO, and -# WINEDLLOVERRIDES all have no effect, so Proton's copy must be replaced. +# Tested on: Ubuntu 24.04+, Fedora, SteamOS 3.7+ (requires glibc 2.38+) +# Recommended Proton for SWBF2 itself: GE-Proton 10.x or proton-cachyos 11.x # -# After a Proton Experimental update, cmd.exe is restored; re-run this script. +# ── Login flow ───────────────────────────────────────────────────────────── # -# ── Why NOT to run Kyber inside Wolf / Games-on-Whales ───────────────────── +# 1. Launch the AppImage. +# 2. Click "EA Account" — a browser window opens to accounts.ea.com. +# 3. Log in with your EA account. +# 4. Kyber completes authentication via Maxima (no redirect hacks needed). +# 5. Click "Skip" on Nexus Mods if you don't use mods. # -# Wolf runs Docker + Proton's bwrap nested. The double-sandbox blocks -# CLONE_NEWUSER which breaks WebView2, AND the inner bwrap prevents -# xdg-open from reaching the host display. Kyber's loopback redirect to -# 127.0.0.1:PORT also fails inside the container network stack. Use native -# Linux Steam instead — it's the supported path. +# ── Hosting a private server ─────────────────────────────────────────────── # -# ── WebView2 ─────────────────────────────────────────────────────────────── +# 1. In Kyber, click HOST. +# 2. Select maps/modes for your rotation (drag into Active Rotation). +# 3. In the right panel: set a name, set a PASSWORD (keeps it private). +# 4. Click Settings to adjust max players etc. +# 5. Click START SERVER. +# 6. Share the server name + password with friends — they search by name +# in the HOME tab and enter the password to join. # -# WebView2 is NOT required for the login flow (Maxima handles that). This -# script still installs the WebView2 Evergreen runtime because Kyber may use -# it for in-app content rendering. Installing it causes no harm and prevents -# any fallback-related error dialogs inside Kyber. +# Bots: SWBF2 fills empty player slots with AI automatically. No separate +# bot count setting is needed — just start the server and join it. # -# ── Headless note ────────────────────────────────────────────────────────── +# ── Why NOT Wine/Proton for the Kyber launcher ───────────────────────────── # -# On a headless GPU box use Steam Remote Play: install Steam, configure a -# virtual/dummy display so Steam has something to render to, add Kyber + -# SWBF2, then connect with the Steam Link app from any device. -# This script warns if no display is detected at setup time. +# The Windows Kyber launcher (kyber_launcher.exe) has a fatal flaw on Linux: +# its EA OAuth flow calls cmd /c start "" "" to open a browser. +# Wine's cmd.exe crashes with STATUS_ACCESS_VIOLATION (0xC0000005) on long +# URLs. Fixing this requires replacing Proton's own cmd.exe binary with a +# shim — and the shim gets overwritten on every Proton update. Additionally, +# EA's auth callback uses the eadesktop:// URI scheme (not http://127.0.0.1 +# as originally believed), which has no Linux handler. The native AppImage +# bypasses all of this entirely. # # ── Prerequisites ────────────────────────────────────────────────────────── -# a. Steam installed and launched at least once (native, not Flatpak ideally -# — Flatpak works but paths differ; this script handles both). -# b. SWBF2 (AppID 1237950) installed and working with Proton Experimental -# (run setup-swbf2-linux.sh first). -# c. KyberLauncher.exe downloaded from https://kyber.gg saved to -# ~/Downloads/KyberLauncher.exe (or pass the path as $1). +# a. SWBF2 (AppID 1237950) installed via Steam with Proton (GE-Proton +# recommended). Run setup-swbf2-linux.sh first if needed. +# b. Internet access to download the AppImage (~173 MB). +# c. glibc 2.38+ (Ubuntu 24.04+, Fedora 38+, SteamOS 3.7+). +# On Ubuntu 22.04 the AppImage may not run — upgrade to 24.04. # # ── Usage ────────────────────────────────────────────────────────────────── # chmod +x setup-kyber-linux.sh -# ./setup-kyber-linux.sh [/path/to/KyberLauncher.exe] +# ./setup-kyber-linux.sh set -euo pipefail -KYBER_INSTALLER="${1:-$HOME/Downloads/KyberLauncher.exe}" -KYBER_APPID="9900000001" # non-Steam shortcut appid -KYBER_COMPAT_ID="$KYBER_APPID" # prefix dir must match appid for Steam to find it +KYBER_REPO="simonlinuxcraft/kyber-linuxport-unofficial" +INSTALL_DIR="$HOME/.local/share/kyber" +DESKTOP_FILE="$HOME/.local/share/applications/kyber-launcher.desktop" +BIN_LINK="$HOME/.local/bin/kyber" -echo "=== Kyber Launcher — Native Linux Steam Setup ===" +echo "=== Kyber Launcher — Native Linux Setup ===" echo "" -# ── Locate Steam home ────────────────────────────────────────────────────── -find_steam_home() { - for candidate in \ - "$HOME/.steam/steam" \ - "$HOME/.local/share/Steam" \ - "$HOME/.var/app/com.valvesoftware.Steam/.steam/steam"; do - if [ -d "$candidate/steamapps" ]; then - echo "$candidate" - return 0 - fi - done - return 1 -} - -STEAM_HOME=$(find_steam_home) || { - echo "ERROR: Steam home not found. Install Steam and launch it once." - exit 1 -} -echo "Steam home: $STEAM_HOME" - -# ── Verify / download Kyber installer ───────────────────────────────────── -if [ ! -f "$KYBER_INSTALLER" ]; then +# ── Check glibc version ──────────────────────────────────────────────────── +GLIBC=$(ldd --version 2>/dev/null | head -1 | grep -oP '\d+\.\d+$' || echo "0.0") +GLIBC_MAJOR=$(echo "$GLIBC" | cut -d. -f1) +GLIBC_MINOR=$(echo "$GLIBC" | cut -d. -f2) +if [ "$GLIBC_MAJOR" -lt 2 ] || { [ "$GLIBC_MAJOR" -eq 2 ] && [ "$GLIBC_MINOR" -lt 38 ]; }; then + echo "WARNING: glibc $GLIBC detected. The Kyber AppImage requires glibc 2.38+." + echo " Ubuntu 22.04 ships glibc 2.35 — upgrade to Ubuntu 24.04 or use" + echo " a newer distro. Continuing anyway in case your system has it..." echo "" - echo "Kyber installer not found at: $KYBER_INSTALLER" - echo "Downloading from kyber.gg API..." - mkdir -p "$(dirname "$KYBER_INSTALLER")" - KYBER_ZIP="/tmp/kyber-installer-$$.zip" - KYBER_DL_URL="https://api.prod.kyber.gg/download/kyber-installer-win64.zip" - if curl -L --progress-bar -o "$KYBER_ZIP" "$KYBER_DL_URL" && [ -s "$KYBER_ZIP" ]; then - # Extract the installer .exe from the zip - _exe=$(unzip -Z1 "$KYBER_ZIP" 2>/dev/null | grep -i '\.exe$' | head -1) - if [ -z "$_exe" ]; then - echo "ERROR: No .exe found inside the downloaded zip." - rm -f "$KYBER_ZIP" - exit 1 - fi - unzip -p "$KYBER_ZIP" "$_exe" > "$KYBER_INSTALLER" - rm -f "$KYBER_ZIP" - echo "Extracted: $(basename "$_exe") → $KYBER_INSTALLER" - else - echo "" - echo "ERROR: Download failed." - echo "Download the zip manually from https://kyber.gg, extract the .exe, then:" - echo " $0 /path/to/KyberLauncher.exe" - rm -f "$KYBER_ZIP" - exit 1 - fi fi -echo "Kyber installer: $KYBER_INSTALLER" -# ── Locate Proton Experimental ───────────────────────────────────────────── -# Kyber's WebView2 is best supported on Proton Experimental (newest Wine + -# the most complete WebView2/Edge compatibility shims). GE-Proton also works, -# but Experimental tends to have the freshest fixes for Chromium sandboxing. -PROTON_DIR=$(find "$STEAM_HOME/steamapps/common" -maxdepth 1 -type d \ - -iname "Proton Experimental" 2>/dev/null | head -1) -if [ -z "$PROTON_DIR" ]; then - PROTON_DIR=$(find "$STEAM_HOME/steamapps/common" -maxdepth 1 -type d \ - -iname "Proton*" 2>/dev/null | sort | tail -1) -fi -if [ -z "$PROTON_DIR" ] || [ ! -x "$PROTON_DIR/proton" ]; then - echo "" - echo "ERROR: Proton not found under $STEAM_HOME/steamapps/common." - echo " In Steam → Settings → Compatibility, install Proton Experimental," - echo " then re-run this script." +# ── Fetch latest release URL ─────────────────────────────────────────────── +echo "[1/3] Fetching latest Kyber Linux release..." +API_URL="https://api.github.com/repos/${KYBER_REPO}/releases/latest" +APPIMAGE_URL=$(curl -fsSL "$API_URL" \ + | python3 -c " +import json, sys +data = json.load(sys.stdin) +assets = data.get('assets', []) +for a in assets: + url = a['browser_download_url'] + if url.endswith('.AppImage'): + print(url) + break +" 2>/dev/null) + +if [ -z "$APPIMAGE_URL" ]; then + echo "ERROR: Could not fetch AppImage URL from GitHub." + echo " Check: https://github.com/${KYBER_REPO}/releases" + echo " Download the AppImage manually and run: chmod +x KyberLinuxPort*.AppImage && ./KyberLinuxPort*.AppImage" exit 1 fi -echo "Proton: $PROTON_DIR" -# ── Headless display check ───────────────────────────────────────────────── -# WebView2 (and Kyber's Flutter UI) need a display to render to. On a headless -# box with no X/Wayland session, Kyber's window has nowhere to draw. -if [ -z "${DISPLAY:-}" ] && [ -z "${WAYLAND_DISPLAY:-}" ]; then - echo "" - echo "NOTE: No DISPLAY or WAYLAND_DISPLAY detected (headless box)." - echo " For Steam Remote Play you need a virtual display so Steam can" - echo " render. Options:" - echo " - Configure your GPU driver's dummy/virtual display (recommended" - echo " for hardware-encoded Remote Play), OR" - echo " - Run this whole setup under Xvfb for the install step only:" - echo " xvfb-run -a $0 $KYBER_INSTALLER" - echo "" - echo " Continuing the install (the prefix can be built headless), but you" - echo " must have a real or virtual display when you actually launch Kyber." - echo "" -fi - -# ── Build Kyber Wine prefix and run the installer ────────────────────────── +VERSION=$(echo "$APPIMAGE_URL" | grep -oP 'v[\d.a-z-]+' | head -1) +echo " Latest: $VERSION" +echo " URL: $APPIMAGE_URL" echo "" -echo "[1/7] Installing Kyber into Wine prefix..." -KYBER_PFX="$STEAM_HOME/steamapps/compatdata/$KYBER_COMPAT_ID" -OLD_PFX="$STEAM_HOME/steamapps/compatdata/kyber" +# ── Download ─────────────────────────────────────────────────────────────── +mkdir -p "$INSTALL_DIR" +APPIMAGE_PATH="$INSTALL_DIR/KyberLinuxPort.AppImage" -# Migrate old 'kyber' prefix to the numeric appid directory Steam expects -if [ -d "$OLD_PFX" ] && [ ! -d "$KYBER_PFX" ]; then - echo " Migrating prefix: compatdata/kyber → compatdata/$KYBER_COMPAT_ID" - mv "$OLD_PFX" "$KYBER_PFX" -elif [ -d "$OLD_PFX" ] && [ -d "$KYBER_PFX" ]; then - echo " Removing old compatdata/kyber (numeric prefix already exists)..." - rm -rf "$OLD_PFX" +CURRENT_VERSION="" +if [ -f "$APPIMAGE_PATH.version" ]; then + CURRENT_VERSION=$(cat "$APPIMAGE_PATH.version") fi -export STEAM_COMPAT_DATA_PATH="$KYBER_PFX" -export STEAM_COMPAT_CLIENT_INSTALL_PATH="$STEAM_HOME" -export PROTON_NO_ESYNC=1 - -# Check if Kyber is already installed — skip the installer if so. -KYBER_EXE_PATH=$(find "$KYBER_PFX/pfx" -iname "kyber_launcher.exe" 2>/dev/null | head -1) -if [ -n "$KYBER_EXE_PATH" ]; then - echo " Kyber.exe already present — skipping installer." +if [ -f "$APPIMAGE_PATH" ] && [ "$CURRENT_VERSION" = "$VERSION" ]; then + echo "[1/3] Already up to date ($VERSION) — skipping download." else - mkdir -p "$KYBER_PFX" - # Kill any leftover Wine/Proton processes from a previous attempt. - pkill -9 -f "compatdata/$KYBER_COMPAT_ID" 2>/dev/null || true - sleep 1 - - echo " Running installer (silent)..." - # /S = NSIS silent flag; if Kyber's installer ignores it a GUI appears. - "$PROTON_DIR/proton" run "$KYBER_INSTALLER" /S 2>/dev/null || \ - "$PROTON_DIR/proton" run "$KYBER_INSTALLER" 2>/dev/null || true - - sleep 5 - - KYBER_EXE_PATH=$(find "$KYBER_PFX/pfx" -iname "kyber_launcher.exe" 2>/dev/null | head -1) - if [ -z "$KYBER_EXE_PATH" ]; then - echo "" - echo "WARNING: Kyber.exe not found after installation." - echo " Default install path assumed; continuing." - fi + echo "[2/3] Downloading Kyber Linux AppImage ($VERSION)..." + curl -L --progress-bar -o "$APPIMAGE_PATH" "$APPIMAGE_URL" + chmod +x "$APPIMAGE_PATH" + echo "$VERSION" > "$APPIMAGE_PATH.version" + echo " Saved to: $APPIMAGE_PATH" fi - -# Resolve Windows-style paths for the shortcut -if [ -n "$KYBER_EXE_PATH" ]; then - rel=$(echo "$KYBER_EXE_PATH" | sed "s|.*/pfx/drive_c/||") - KYBER_EXE_WIN="C:\\$(echo "$rel" | sed 's|/|\\|g')" - dir_rel=$(dirname "$rel") - KYBER_START_DIR="C:\\$(echo "$dir_rel" | sed 's|/|\\|g')\\" -else - KYBER_EXE_WIN='C:\Program Files (x86)\KYBER Launcher\kyber_launcher.exe' - KYBER_START_DIR='C:\Program Files (x86)\KYBER Launcher\' -fi -echo " Windows path: $KYBER_EXE_WIN" - -# ── Ensure WebView2 Evergreen runtime is installed ───────────────────────── echo "" -echo "[2/7] Verifying WebView2 runtime in the Kyber prefix..." -# The Evergreen runtime lives here once installed. -WV2_FOUND=$(find "$KYBER_PFX/pfx/drive_c" -iname "msedgewebview2.exe" 2>/dev/null | head -1) -if [ -n "$WV2_FOUND" ]; then - echo " WebView2 runtime present:" - echo " $WV2_FOUND" -else - echo " WebView2 runtime NOT found — installing..." +# ── Desktop entry + bin symlink ──────────────────────────────────────────── +echo "[3/3] Installing desktop entry and launcher..." - # Prefer winetricks if available — it handles the prefix env automatically - # and uses a cached offline installer so no Wine-internal network call needed. - if command -v winetricks >/dev/null 2>&1; then - echo " Using winetricks to install webview2..." - WINEPREFIX="$KYBER_PFX/pfx" \ - WINE="$PROTON_DIR/files/lib/wine/x86_64-unix/wine64" \ - winetricks -q webview2 || true - else - # Download the Evergreen STANDALONE (offline) installer — linkid=2135547. - # The bootstrapper (linkid=2124703) requires a second download from inside - # Wine which reliably fails. The standalone is ~150 MB but self-contained. - echo " Downloading WebView2 standalone installer (~150 MB)..." - WV2_STANDALONE="/tmp/WebView2RuntimeInstaller_$$.exe" - WV2_URL="https://go.microsoft.com/fwlink/p/?LinkId=2135547" - if curl -L --progress-bar -o "$WV2_STANDALONE" "$WV2_URL" && [ -s "$WV2_STANDALONE" ]; then - "$PROTON_DIR/proton" run "$WV2_STANDALONE" /silent /install || true - rm -f "$WV2_STANDALONE" - else - echo " WARNING: Could not download WebView2 standalone installer." - rm -f "$WV2_STANDALONE" - fi - fi +mkdir -p "$(dirname "$DESKTOP_FILE")" "$HOME/.local/bin" - sleep 5 - WV2_FOUND=$(find "$KYBER_PFX/pfx/drive_c" -iname "msedgewebview2.exe" 2>/dev/null | head -1) - if [ -n "$WV2_FOUND" ]; then - echo " WebView2 runtime installed:" - echo " $WV2_FOUND" - else - echo "" - echo " WARNING: WebView2 runtime still not found after install attempt." - echo " Install winetricks and re-run, or install manually:" - echo " sudo apt install winetricks" - echo " $0" - fi -fi +cat > "$DESKTOP_FILE" << EOF +[Desktop Entry] +Type=Application +Name=Kyber Launcher +Comment=Community multiplayer for Star Wars Battlefront II (2017) +Exec=${APPIMAGE_PATH} +Icon=kyber +Categories=Game; +StartupNotify=true +EOF -# ── Install cmd shim ────────────────────────────────────────────────────── -# Wine's built-in cmd.exe crashes (exit 0xC0000005) when Kyber calls: -# cmd /c start "" "" -# -# Root cause: Wine loads cmd.exe from Proton's OWN installation directory -# files/lib/wine/x86_64-windows/cmd.exe -# NOT from the prefix system32. Replacing the prefix copy, using IFEO registry -# keys, or WINEDLLOVERRIDES all have no effect — Proton's copy always wins. -# -# Fix: replace Proton's cmd.exe with a tiny shim that scans its command line -# for an http URL, writes it to C:\kyber_oauth_url.txt, then exits 0. A -# Linux-side watcher calls xdg-open on that URL to open the system browser. -# The original is backed up as cmd.exe.bak next to it. -# -# After a Proton update the shim will be overwritten; re-run this script. -echo "" -echo "[3/7] Installing cmd shim for OAuth login..." - -SHIM_DIR="$KYBER_PFX/pfx/drive_c/shim" -SHIM_EXE_PATH="$SHIM_DIR/kyber_cmd.exe" -PROTON_CMD="$PROTON_DIR/files/lib/wine/x86_64-windows/cmd.exe" -PROTON_CMD_BAK="${PROTON_CMD}.bak" - -# Detect if Proton's cmd.exe is already our shim (small) or the original (large) -PROTON_CMD_SIZE=$(stat -c%s "$PROTON_CMD" 2>/dev/null || echo 0) - -compile_shim() { - if ! command -v x86_64-w64-mingw32-gcc >/dev/null 2>&1; then - echo " Installing mingw-w64..." - sudo apt-get install -y mingw-w64 || { - echo " WARNING: mingw-w64 install failed — login may not work." - echo " sudo apt install mingw-w64 && $0" - return 1 - } - fi - local SHIM_C="/tmp/kyber_cmd_shim_$$.c" - local SHIM_OUT="/tmp/kyber_cmd_shim_$$.exe" - cat > "$SHIM_C" << 'CEOF' -#include -static void write_url(const char *p, int len) { - HANDLE h = CreateFileA("C:\\kyber_oauth_url.txt", - GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (h == INVALID_HANDLE_VALUE) return; - DWORD w; WriteFile(h, p, len, &w, NULL); - CloseHandle(h); -} -int WINAPI mainCRTStartup(void) { - const char *cl = GetCommandLineA(); - while (*cl) { - if ((cl[0]=='h'||cl[0]=='H') && cl[1]=='t' && cl[2]=='t' && cl[3]=='p') { - const char *end = cl; - while (*end && *end != ' ' && *end != '"') end++; - write_url(cl, (int)(end - cl)); - ExitProcess(0); - } - cl++; - } - ExitProcess(0); -} -CEOF - mkdir -p "$SHIM_DIR" - if x86_64-w64-mingw32-gcc -O2 -ffreestanding -nostdlib \ - -mno-stack-arg-probe \ - -e mainCRTStartup -o "$SHIM_OUT" "$SHIM_C" \ - -lkernel32; then - cp "$SHIM_OUT" "$SHIM_EXE_PATH" - echo " Shim compiled: $(stat -c%s "$SHIM_EXE_PATH") bytes" - else - echo " WARNING: cmd shim compile failed — login may not work." - rm -f "$SHIM_C" "$SHIM_OUT" - return 1 - fi - rm -f "$SHIM_C" "$SHIM_OUT" -} - -# Compile shim if missing or obviously wrong size (>100KB = real cmd.exe) -SHIM_SIZE=$(stat -c%s "$SHIM_EXE_PATH" 2>/dev/null || echo 0) -if [ "$SHIM_SIZE" -gt 100000 ]; then - echo " Stale shim detected ($SHIM_SIZE bytes). Recompiling..." - rm -f "$SHIM_EXE_PATH" - SHIM_SIZE=0 -fi -if [ "$SHIM_SIZE" -eq 0 ]; then - compile_shim || true -fi - -# Replace Proton's cmd.exe if it is not already our shim -if [ -f "$SHIM_EXE_PATH" ]; then - if [ "$PROTON_CMD_SIZE" -gt 100000 ]; then - # Original: back it up and replace - cp "$PROTON_CMD" "$PROTON_CMD_BAK" 2>/dev/null || true - chmod u+w "$PROTON_CMD" - cp "$SHIM_EXE_PATH" "$PROTON_CMD" - chmod u-w "$PROTON_CMD" - echo " Proton cmd.exe replaced with shim." - echo " (Backup: $PROTON_CMD_BAK)" - echo " NOTE: Re-run this script after a Proton Experimental update." - else - echo " Proton cmd.exe already replaced ($(stat -c%s "$PROTON_CMD") bytes)." - fi -else - echo " WARNING: shim not compiled. Install mingw-w64 and re-run:" - echo " sudo apt install mingw-w64 && $0" -fi - -# ── OAuth watcher ────────────────────────────────────────────────────────── -echo "" -echo "[4/7] Installing OAuth watcher (opens EA login in your browser)..." - -URL_FILE="$KYBER_PFX/pfx/drive_c/kyber_oauth_url.txt" -WATCHER="$HOME/.local/bin/kyber-oauth-watcher.sh" -mkdir -p "$HOME/.local/bin" - -cat > "$WATCHER" << WEOF -#!/bin/bash -# Watches for Kyber's OAuth URL and opens it in the system browser. -URL_FILE="$URL_FILE" -echo "[kyber-watcher] Started. Watching \$URL_FILE" -rm -f "\$URL_FILE" -while true; do - if [ -f "\$URL_FILE" ]; then - URL=\$(cat "\$URL_FILE") - rm -f "\$URL_FILE" - if [[ "\$URL" == http* ]]; then - echo "[kyber-watcher] Opening: \$URL" - xdg-open "\$URL" - fi - fi - sleep 0.5 -done -WEOF -chmod +x "$WATCHER" - -# Install as a systemd user service so it is always ready when Kyber runs -SVCDIR="$HOME/.config/systemd/user" -mkdir -p "$SVCDIR" -cat > "$SVCDIR/kyber-oauth-watcher.service" << SEOF -[Unit] -Description=Kyber EA OAuth URL watcher -After=graphical-session.target - -[Service] -ExecStart=$WATCHER -Restart=always -RestartSec=2 - -[Install] -WantedBy=default.target -SEOF - -if systemctl --user daemon-reload 2>/dev/null && \ - systemctl --user enable --now kyber-oauth-watcher.service 2>/dev/null; then - echo " Watcher service enabled and started." - echo " (It will auto-start on login from now on.)" -else - echo " NOTE: systemd user service could not be enabled." - echo " Start the watcher manually before clicking Login in Kyber:" - echo " $WATCHER &" -fi - -# ── Add Kyber as a non-Steam shortcut ────────────────────────────────────── -echo "" -echo "[5/7] Adding Kyber as a non-Steam shortcut..." - -STEAM_UID=$(ls "$STEAM_HOME/userdata/" 2>/dev/null | grep -E '^[0-9]+$' | head -1) -if [ -z "$STEAM_UID" ]; then - echo " WARNING: No Steam userdata found — sign in to Steam once, then re-run." - echo " Skipping shortcut + compat mapping." - SKIP_STEAM_CFG=1 -else - SHORTCUTS_DIR="$STEAM_HOME/userdata/$STEAM_UID/config" - SHORTCUTS_FILE="$SHORTCUTS_DIR/shortcuts.vdf" - mkdir -p "$SHORTCUTS_DIR" - if [ -f "$SHORTCUTS_FILE" ] && [ ! -w "$SHORTCUTS_FILE" ]; then - echo " Fixing permissions on shortcuts.vdf..." - chmod 644 "$SHORTCUTS_FILE" || { - echo " WARNING: Cannot write $SHORTCUTS_FILE — run:" - echo " chmod 644 $SHORTCUTS_FILE" - echo " then re-run this script." - SKIP_STEAM_CFG=1 - } - fi - [ -f "$SHORTCUTS_FILE" ] && cp "$SHORTCUTS_FILE" "$SHORTCUTS_FILE.bak" - - python3 - "$SHORTCUTS_FILE" "$KYBER_APPID" "$KYBER_EXE_WIN" "$KYBER_START_DIR" << 'PYEOF' -import sys, struct, os - -def s(key, value): # VDF string field - return b'\x01' + key.encode() + b'\x00' + value.encode() + b'\x00' -def i(key, value): # VDF int field - return b'\x02' + key.encode() + b'\x00' + struct.pack('/dev/null || true echo "" -echo "[7/7] Done." +echo "=== Kyber Setup Complete ===" echo "" -echo "=== Kyber Setup Complete (native Linux) ===" +echo "Launch Kyber:" +echo " From terminal: kyber" +echo " From app menu: search 'Kyber Launcher'" +echo " Direct: $APPIMAGE_PATH" echo "" -echo "Next steps:" -echo " 1. RESTART Steam so it picks up the new shortcut and compat mapping." -echo " 2. The OAuth watcher is already running in the background." -echo " (Confirm: systemctl --user status kyber-oauth-watcher)" -echo " 3. Launch 'Kyber Launcher' from your Steam Library." -echo " 4. Click Login. Kyber calls cmd /c start with the EA auth URL." -echo " The cmd shim intercepts it and writes it to a file. The watcher" -echo " picks it up and opens it in your browser via xdg-open." -echo " 5. Log in on the EA page (email / Steam / 2FA as usual)." -echo " 6. EA redirects to 127.0.0.1:/?code=... — Kyber's loopback" -echo " server catches the auth code and login completes." -echo " The browser tab will show 'OK' or connection-refused — both normal." +echo "First run:" +echo " 1. Click 'EA Account' and log in with your EA credentials." +echo " 2. Click 'Skip' on the Nexus Mods step (optional — only needed for mods)." +echo " 3. You're in. Browse servers on HOME or create one under HOST." echo "" -echo "Streaming from a headless box:" -echo " Use Steam Remote Play — install the Steam Link app on your client," -echo " it discovers this host over your network." +echo "Hosting a private server:" +echo " HOST → pick maps → set a name and PASSWORD → Start Server." +echo " Share the server name + password with friends." +echo " Bots fill empty slots automatically — no separate setting needed." echo "" -echo "Troubleshooting:" -echo " Browser never opens after clicking Login:" -echo " Check watcher is running: systemctl --user status kyber-oauth-watcher" -echo " If not: $HOME/.local/bin/kyber-oauth-watcher.sh &" +echo "SWBF2 must be installed via Steam (AppID 1237950) with GE-Proton." +echo "GE-Proton: https://github.com/GloriousEggroll/proton-ge-custom/releases" echo "" -echo " Browser opens but login loops back to EA sign-in page:" -echo " Kyber's loopback server timed out. Close Kyber, reopen it," -echo " then click Login and log in quickly." -echo "" -echo " 'cmd shim' missing (mingw-w64 was not installed):" -echo " sudo apt install mingw-w64 && $0" -echo "" -echo " After a Proton Experimental update:" -echo " Re-run $0 to replace the restored cmd.exe with the shim again." +echo "To update Kyber later, re-run this script."