#!/usr/bin/env bash # # battlenet-umu-setup.sh # # Installs the Battle.net launcher on Arch Linux via umu-launcher. # Idempotent: safe to re-run. Skips steps that are already done. # # Usage: # ./battlenet-umu-setup.sh # interactive # ./battlenet-umu-setup.sh --yes # non-interactive, assume yes # ./battlenet-umu-setup.sh --reinstall # wipe prefix and reinstall # # Does NOT run itself as root. It will call sudo only for pacman. set -euo pipefail # ---------- config ---------- PREFIX_DIR="${BATTLENET_PREFIX:-$HOME/Games/battlenet-umu}" GAMEID="umu-battlenet" PROTONPATH="${PROTONPATH:-GE-Proton}" INSTALLER_URL="https://downloader.battle.net/download/getInstaller?os=win&installer=Battle.net-Setup.exe" INSTALLER_PATH="$HOME/Downloads/Battle.net-Setup.exe" LAUNCHER_EXE_REL="drive_c/Program Files (x86)/Battle.net/Battle.net Launcher.exe" BIN_DIR="$HOME/.local/bin" DESKTOP_DIR="$HOME/.local/share/applications" LAUNCH_SCRIPT="$BIN_DIR/battlenet" KILL_SCRIPT="$BIN_DIR/battlenetkill" DESKTOP_FILE="$DESKTOP_DIR/battlenet.desktop" ASSUME_YES=0 REINSTALL=0 # ---------- helpers ---------- c_reset=$'\033[0m'; c_blue=$'\033[1;34m'; c_green=$'\033[1;32m' c_yellow=$'\033[1;33m'; c_red=$'\033[1;31m'; c_dim=$'\033[2m' log() { printf '%s==>%s %s\n' "$c_blue" "$c_reset" "$*"; } ok() { printf '%s✓%s %s\n' "$c_green" "$c_reset" "$*"; } warn() { printf '%s!%s %s\n' "$c_yellow" "$c_reset" "$*"; } err() { printf '%s✗%s %s\n' "$c_red" "$c_reset" "$*" >&2; } skip() { printf ' %s(skip) %s%s\n' "$c_dim" "$*" "$c_reset"; } confirm() { # confirm "Question?" -> returns 0 for yes, 1 for no if [[ $ASSUME_YES -eq 1 ]]; then return 0; fi local prompt="$1 [Y/n] " local reply read -r -p "$prompt" reply [[ -z "$reply" || "$reply" =~ ^[Yy] ]] } die() { err "$*"; exit 1; } # ---------- arg parsing ---------- for arg in "$@"; do case "$arg" in -y|--yes) ASSUME_YES=1 ;; --reinstall) REINSTALL=1 ;; -h|--help) sed -n '2,12p' "$0" | sed 's/^# \{0,1\}//' exit 0 ;; *) die "Unknown argument: $arg" ;; esac done # ---------- preflight ---------- log "Preflight checks" [[ $EUID -ne 0 ]] || die "Do not run this script as root. It will sudo when it needs to." command -v pacman >/dev/null || die "pacman not found — this script is for Arch Linux." command -v curl >/dev/null || die "curl not installed. sudo pacman -S curl" # multilib check if ! pacman -Sl multilib >/dev/null 2>&1; then err "[multilib] repository is not enabled in /etc/pacman.conf." err "Edit /etc/pacman.conf, uncomment the [multilib] section, then run:" err " sudo pacman -Syu" exit 1 fi ok "[multilib] is enabled" # ---------- install umu-launcher ---------- log "Installing umu-launcher" if pacman -Qi umu-launcher >/dev/null 2>&1; then skip "umu-launcher already installed" else confirm "Install umu-launcher via pacman?" || die "Aborted." sudo pacman -S --needed --noconfirm umu-launcher ok "umu-launcher installed" fi command -v umu-run >/dev/null || die "umu-run not on PATH after install — something went wrong." # ---------- download installer ---------- log "Fetching Battle.net installer" mkdir -p "$(dirname "$INSTALLER_PATH")" if [[ -f "$INSTALLER_PATH" ]]; then skip "Installer already at $INSTALLER_PATH" if confirm "Re-download to get the latest?"; then curl -L --fail -o "$INSTALLER_PATH" "$INSTALLER_URL" ok "Installer re-downloaded" fi else curl -L --fail -o "$INSTALLER_PATH" "$INSTALLER_URL" ok "Installer saved to $INSTALLER_PATH" fi # ---------- prefix ---------- log "Preparing prefix at $PREFIX_DIR" if [[ -d "$PREFIX_DIR" ]]; then if [[ $REINSTALL -eq 1 ]]; then warn "Reinstall requested — removing existing prefix" if confirm "Really delete $PREFIX_DIR ?"; then rm -rf "$PREFIX_DIR" ok "Prefix removed" else die "Aborted." fi else skip "Prefix already exists (use --reinstall to wipe)" fi fi mkdir -p "$PREFIX_DIR" # ---------- run installer ---------- LAUNCHER_PATH="$PREFIX_DIR/$LAUNCHER_EXE_REL" if [[ -f "$LAUNCHER_PATH" ]]; then skip "Battle.net Launcher.exe already present in prefix" else log "Running Battle.net installer through umu (this takes a few minutes)" warn "The Battle.net installer window will appear. Accept the defaults" warn "and let it finish. The installer may auto-close — that's fine." confirm "Continue?" || die "Aborted." WINEPREFIX="$PREFIX_DIR" \ GAMEID="$GAMEID" \ PROTONPATH="$PROTONPATH" \ umu-run "$INSTALLER_PATH" || { warn "umu-run exited non-zero. That's often normal for the Battle.net installer." } # The installer sometimes drops the launcher even if it exits weirdly. # Give it a moment, then check. sleep 2 if [[ ! -f "$LAUNCHER_PATH" ]]; then err "Battle.net Launcher.exe not found at expected path:" err " $LAUNCHER_PATH" err "The installer may not have completed. Re-run with --reinstall." exit 1 fi ok "Battle.net installed into prefix" fi # ---------- launch scripts ---------- log "Installing launch scripts to $BIN_DIR" mkdir -p "$BIN_DIR" cat > "$LAUNCH_SCRIPT" < "$KILL_SCRIPT" </dev/null || true pkill -9 -f 'Agent\\.exe' 2>/dev/null || true pkill -9 -f 'Blizzard' 2>/dev/null || true # wineserver may not be on PATH in umu environments; try both. if command -v wineserver >/dev/null; then wineserver -k 2>/dev/null || true fi EOF chmod +x "$KILL_SCRIPT" ok "Wrote $KILL_SCRIPT" # PATH check case ":$PATH:" in *":$BIN_DIR:"*) ok "$BIN_DIR is on PATH" ;; *) warn "$BIN_DIR is not on your PATH. Add this to your shell rc:" warn " export PATH=\"\$HOME/.local/bin:\$PATH\"" ;; esac # ---------- desktop entry ---------- log "Installing desktop entry" mkdir -p "$DESKTOP_DIR" cat > "$DESKTOP_FILE" </dev/null; then update-desktop-database "$DESKTOP_DIR" 2>/dev/null || true fi # ---------- done ---------- echo ok "Setup complete." echo echo " Prefix: $PREFIX_DIR" echo " Launcher: $LAUNCH_SCRIPT" echo " Kill: $KILL_SCRIPT" echo " Desktop: $DESKTOP_FILE" echo echo "Run 'battlenet' to start it, or launch from your app menu." echo "If it hangs on 'Update Agent went to sleep', run: battlenetkill && battlenet"