#!/usr/bin/env bash # # battlenet-update-proton.sh # # Lists available GE-Proton releases from GitHub, downloads the chosen version # into ~/.local/share/Steam/compatibilitytools.d/, and updates the battlenet # launch script to point at it. # # Usage: # ./battlenet-update-proton.sh # interactive picker # ./battlenet-update-proton.sh --latest # auto-install the latest release # ./battlenet-update-proton.sh --list # list available releases and exit # ./battlenet-update-proton.sh --version=GE-Proton9-20 # install a specific release # END_HELP set -euo pipefail # ---------- config ---------- PROTON_DIR="${PROTON_INSTALL_DIR:-$HOME/.local/share/Steam/compatibilitytools.d}" LAUNCH_SCRIPT="${BATTLENET_LAUNCH_SCRIPT:-$HOME/.local/bin/battlenet}" GITHUB_API="https://api.github.com/repos/GloriousEggroll/proton-ge-custom/releases" LIST_COUNT=10 # how many recent releases to show in the picker ASSUME_LATEST=0 LIST_ONLY=0 PINNED_VERSION="" # ---------- 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"; } die() { err "$*"; exit 1; } # ---------- arg parsing ---------- for arg in "$@"; do case "$arg" in --latest) ASSUME_LATEST=1 ;; --list) LIST_ONLY=1 ;; --version=*) PINNED_VERSION="${arg#*=}" ;; -h|--help) sed -n '/^# Usage:/,/^# END_HELP/p' "$0" | sed 's/^# \{0,1\}//' exit 0 ;; *) die "Unknown argument: $arg" ;; esac done # ---------- preflight ---------- command -v curl >/dev/null || die "curl not installed. Run: sudo pacman -S curl" command -v tar >/dev/null || die "tar not installed." # ---------- fetch release list ---------- log "Fetching GE-Proton release list from GitHub" RELEASES_JSON=$(curl -fsSL "$GITHUB_API?per_page=$LIST_COUNT") # Extract tag names (GE-ProtonX-Y format) mapfile -t RELEASE_TAGS < <( printf '%s' "$RELEASES_JSON" \ | grep '"tag_name"' \ | sed 's/.*"tag_name": *"\([^"]*\)".*/\1/' ) [[ ${#RELEASE_TAGS[@]} -gt 0 ]] || die "No releases found — GitHub API may be rate-limited. Try again shortly." if [[ $LIST_ONLY -eq 1 ]]; then echo "Recent GE-Proton releases:" for tag in "${RELEASE_TAGS[@]}"; do installed="" [[ -d "$PROTON_DIR/$tag" ]] && installed=" ${c_green}(installed)${c_reset}" printf " %s%s\n" "$tag" "$installed" done exit 0 fi # ---------- choose version ---------- if [[ -n "$PINNED_VERSION" ]]; then TARGET="$PINNED_VERSION" elif [[ $ASSUME_LATEST -eq 1 ]]; then TARGET="${RELEASE_TAGS[0]}" log "Latest release: $TARGET" else echo echo "Recent GE-Proton releases (${c_green}green = already installed${c_reset}):" i=1 for tag in "${RELEASE_TAGS[@]}"; do installed="" [[ -d "$PROTON_DIR/$tag" ]] && installed=" ${c_green}✓${c_reset}" printf " %2d) %s%s\n" "$i" "$tag" "$installed" (( i++ )) done echo printf "Enter number (1-%d) or a version tag [default: 1 = %s]: " "${#RELEASE_TAGS[@]}" "${RELEASE_TAGS[0]}" read -r choice if [[ -z "$choice" ]]; then TARGET="${RELEASE_TAGS[0]}" elif [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= ${#RELEASE_TAGS[@]} )); then TARGET="${RELEASE_TAGS[$(( choice - 1 ))]}" else TARGET="$choice" fi fi log "Target: $TARGET" # ---------- download ---------- INSTALL_PATH="$PROTON_DIR/$TARGET" if [[ -d "$INSTALL_PATH" ]]; then skip "$TARGET already installed at $INSTALL_PATH" else # Find the .tar.gz asset URL for this release log "Resolving download URL for $TARGET" ASSET_URL=$( curl -fsSL "$GITHUB_API/tags/$TARGET" \ | grep '"browser_download_url"' \ | grep '\.tar\.gz"' \ | head -1 \ | sed 's/.*"browser_download_url": *"\([^"]*\)".*/\1/' ) [[ -n "$ASSET_URL" ]] || die "Could not find a .tar.gz asset for $TARGET. Check the version name." log "Downloading $TARGET" TMPFILE=$(mktemp --suffix=.tar.gz) trap 'rm -f "$TMPFILE"' EXIT curl -L --fail --progress-bar -o "$TMPFILE" "$ASSET_URL" log "Extracting to $PROTON_DIR" mkdir -p "$PROTON_DIR" tar -xzf "$TMPFILE" -C "$PROTON_DIR" ok "$TARGET installed to $INSTALL_PATH" fi # ---------- update launch script ---------- if [[ ! -f "$LAUNCH_SCRIPT" ]]; then warn "Launch script not found at $LAUNCH_SCRIPT — skipping update." warn "Run battlenet-umu-setup.sh first, or set BATTLENET_LAUNCH_SCRIPT." else CURRENT=$(grep '^export PROTONPATH=' "$LAUNCH_SCRIPT" 2>/dev/null | head -1 | sed 's/.*="\?\([^"]*\)"\?.*/\1/' || echo "(not set)") if [[ "$CURRENT" == "$TARGET" ]]; then skip "Launch script already points to $TARGET" else log "Updating launch script: $CURRENT → $TARGET" sed -i \ -e "s|^# Proton version:.*|# Proton version: $TARGET|" \ -e "s|^export PROTONPATH=.*|export PROTONPATH=\"$TARGET\"|" \ "$LAUNCH_SCRIPT" ok "Launch script updated" fi fi # ---------- done ---------- echo ok "Done. Active Proton: $TARGET" echo echo " Installed at: $INSTALL_PATH" echo " Launch script: $LAUNCH_SCRIPT" echo echo "Restart Battle.net to use the new Proton version." echo "If anything regresses, re-run with --version= to roll back."