Files
gzw-eac-fix/setup.sh
2026-04-17 14:24:53 +02:00

238 lines
8.0 KiB
Bash

#!/usr/bin/env bash
set -uo pipefail
# Configuration:
# Edit these if needed.
# Everything else is derived from these values.
STEAM_APP_ID="2479810"
SERVICE_NAME="gzw-eac-fix"
INSTALL_DIR="$HOME/.local/share/gzw-eac-fix"
NOTIFY="false" # set to true to enable desktop notifications via notify-send
LOG_MAX_LINES="200" # max lines kept in the log file
POLL_INTERVAL="3" # seconds between file-exists checks after steam validate
POST_RESTORE_WAIT="2" # seconds to wait after files reappear before chmod
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m'
PREFIX="[${SERVICE_NAME}]"
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_FILE="$INSTALL_DIR/${SERVICE_NAME}.log"
# create install dir early so we can log immediately
mkdir -p "$INSTALL_DIR"
_ts() { date "+%Y-%m-%d %H:%M:%S"; }
log_info() {
local msg="$1"
printf "${BLUE}${PREFIX}${NC} %s\n" "$msg"
echo "[$(_ts)] [INFO] $msg" >> "$LOG_FILE"
}
log_warn() {
local msg="$1"
printf "${BLUE}${PREFIX}${NC} ⚠ %s\n" "$msg"
echo "[$(_ts)] [WARN] $msg" >> "$LOG_FILE"
}
log_error() {
local msg="$1"
printf "${RED}${PREFIX} Error: %s${NC}\n" "$msg" >&2
echo "[$(_ts)] [ERROR] $msg" >> "$LOG_FILE"
}
die() { log_error "$1"; exit 1; }
{
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " [Gray Zone Warfare EAC Fix] Setup - $(_ts)"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
} >> "$LOG_FILE"
# Guard against downloading individual files instead of cloning the repo
for required_dir in scripts init; do
[[ -d "$REPO_DIR/$required_dir" ]] || die \
"Directory '$required_dir/' not found in $REPO_DIR. " \
"Please clone the full repository rather than downloading files individually."
done
command -v steam &>/dev/null || die "'steam' not found in PATH - is Steam installed?"
command -v awk &>/dev/null || die "'awk' not found"
command -v sed &>/dev/null || die "'sed' not found"
find_manifest() {
local bases=(
"$HOME/.local/share/Steam"
"$HOME/.steam/steam"
"$HOME/.var/app/com.valvesoftware.Steam/.local/share/Steam"
)
declare -A seen
local all=()
for base in "${bases[@]}"; do
[[ ! -d "$base/steamapps" ]] && continue
local real; real=$(realpath "$base" 2>/dev/null || echo "$base")
[[ "${seen[$real]+x}" ]] && continue
seen["$real"]=1
all+=("$base/steamapps")
local vdf="$base/steamapps/libraryfolders.vdf"
[[ ! -f "$vdf" ]] && continue
while IFS= read -r line; do
local p; p=$(awk -F'"' '/"path"/{print $4}' <<< "$line")
[[ -n "$p" && -d "$p/steamapps" ]] && all+=("$p/steamapps")
done < "$vdf"
done
[[ ${#all[@]} -eq 0 ]] && return 1
for lib in "${all[@]}"; do
local m="$lib/appmanifest_${STEAM_APP_ID}.acf"
[[ -f "$m" ]] && echo "$m" && return 0
done
return 1
}
MANIFEST_PATH=$(find_manifest) || die \
"appmanifest_${STEAM_APP_ID}.acf not found. " \
"Is Gray Zone Warfare installed? Try: steam://install/${STEAM_APP_ID}"
log_info "Found manifest: $MANIFEST_PATH"
# Replaces all @@TOKEN@@ placeholders in a source file and writes the result
# to a destination. This is the single place all config values are baked in.
substitute() {
local src="$1"
local dst="$2"
sed \
-e "s|@@INSTALL_DIR@@|${INSTALL_DIR}|g" \
-e "s|@@STEAM_APP_ID@@|${STEAM_APP_ID}|g" \
-e "s|@@MANIFEST_PATH@@|${MANIFEST_PATH}|g" \
-e "s|@@SERVICE_NAME@@|${SERVICE_NAME}|g" \
-e "s|@@NOTIFY@@|${NOTIFY}|g" \
-e "s|@@LOG_MAX_LINES@@|${LOG_MAX_LINES}|g" \
-e "s|@@POLL_INTERVAL@@|${POLL_INTERVAL}|g" \
-e "s|@@POST_RESTORE_WAIT@@|${POST_RESTORE_WAIT}|g" \
"$src" > "$dst"
}
log_info "Installing scripts to $INSTALL_DIR..."
for script in fix.sh watch.sh; do
substitute "$REPO_DIR/scripts/$script" "$INSTALL_DIR/$script"
chmod +x "$INSTALL_DIR/$script"
log_info " Installed $script"
done
detect_init() {
[[ -d /run/systemd/system ]] || systemctl --version &>/dev/null 2>&1 && { echo "systemd"; return; }
command -v rc-service &>/dev/null || [[ -x /sbin/openrc ]] && { echo "openrc"; return; }
command -v runit &>/dev/null || [[ -d /run/runit ]] && { echo "runit"; return; }
command -v s6-svscan &>/dev/null && { echo "s6"; return; }
echo "unknown"
}
INIT_SYSTEM=$(detect_init)
log_info "Detected init system: $INIT_SYSTEM"
INIT_SRC="$REPO_DIR/init/$INIT_SYSTEM"
case "$INIT_SYSTEM" in
systemd)
SYSTEMD_USER_DIR="$HOME/.config/systemd/user"
mkdir -p "$SYSTEMD_USER_DIR"
for unit in "${SERVICE_NAME}.path" "${SERVICE_NAME}.service"; do
substitute "$INIT_SRC/$unit" "$SYSTEMD_USER_DIR/$unit"
log_info " Installed $unit"
done
systemctl --user daemon-reload
systemctl --user enable --now "${SERVICE_NAME}.path"
log_info "systemd path watcher enabled."
echo ""
systemctl --user status "${SERVICE_NAME}.path" --no-pager
echo ""
log_info "Logs: journalctl --user -u ${SERVICE_NAME}.service"
log_info " or: $LOG_FILE"
;;
openrc)
command -v inotifywait &>/dev/null || \
log_warn "inotifywait not found - install inotify-tools"
XDG_AUTOSTART_DIR="$HOME/.config/autostart"
mkdir -p "$XDG_AUTOSTART_DIR"
substitute "$INIT_SRC/${SERVICE_NAME}.desktop" \
"$XDG_AUTOSTART_DIR/${SERVICE_NAME}.desktop"
log_info "XDG autostart entry written."
log_warn "Watcher starts on next desktop login."
log_info "Logs: $LOG_FILE"
;;
runit)
command -v inotifywait &>/dev/null || \
log_warn "inotifywait not found - install inotify-tools"
SV_DIR="$HOME/sv/${SERVICE_NAME}"
mkdir -p "$SV_DIR/log"
substitute "$INIT_SRC/run" "$SV_DIR/run"
substitute "$INIT_SRC/log/run" "$SV_DIR/log/run"
chmod +x "$SV_DIR/run" "$SV_DIR/log/run"
mkdir -p "$INSTALL_DIR/log"
log_info "Runit service written to $SV_DIR"
log_warn "Link it into your supervision tree to activate, e.g.:"
log_warn " ln -s $SV_DIR ~/.local/share/runit/sv/${SERVICE_NAME} (Void Linux)"
log_info "Logs: $INSTALL_DIR/log/"
;;
s6)
command -v inotifywait &>/dev/null || \
log_warn "inotifywait not found - install inotify-tools"
S6_DIR="$HOME/.config/s6/sv/${SERVICE_NAME}"
mkdir -p "$S6_DIR"
substitute "$INIT_SRC/run" "$S6_DIR/run"
chmod +x "$S6_DIR/run"
log_info "s6 service written to $S6_DIR"
log_warn "Link into your scan directory and reload, e.g.:"
log_warn " ln -s $S6_DIR \$S6_SCAN_DIR/${SERVICE_NAME}"
log_warn " s6-svscanctl -a \$S6_SCAN_DIR"
log_info "Logs: $LOG_FILE"
;;
*)
command -v inotifywait &>/dev/null || \
log_warn "inotifywait not found - install inotify-tools"
XDG_AUTOSTART_DIR="$HOME/.config/autostart"
mkdir -p "$XDG_AUTOSTART_DIR"
# No matching init/ template - write a generic desktop entry directly
cat > "$XDG_AUTOSTART_DIR/${SERVICE_NAME}.desktop" << EOF
[Desktop Entry]
Type=Application
Name=GZW EAC Fix Watcher
Exec=${INSTALL_DIR}/watch.sh
Terminal=false
X-GNOME-Autostart-enabled=true
EOF
log_warn "Unrecognized init system - fell back to XDG autostart."
log_warn "Watcher starts on next desktop login."
log_info "Logs: $LOG_FILE"
;;
esac
echo ""
log_info "Setup complete."
log_info "Running initial fix..."
bash "$INSTALL_DIR/fix.sh"