forked from Timmy_Foundation/the-nexus
- scripts/bannerlord_launcher.sh: Mac launcher detects Whisky/CrossOver/Wine and GOG Bannerlord install - nexus/bannerlord_local.py: Python module for programmatic readiness check, launch, and stop - nexus/bannerlord_harness.py: Added --local and --launch-local CLI flags - portals.json: Updated bannerlord portal with local_launch metadata and environment=local - docs/BANNERLORD_LOCAL_MAC.md: Full documentation of local Mac setup
224 lines
8.1 KiB
Bash
Executable File
224 lines
8.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Bannerlord Local Launcher for macOS
|
|
# Detects Wine/Whisky/CrossOver, finds GOG Bannerlord install, launches it.
|
|
#
|
|
# Usage:
|
|
# ./scripts/bannerlord_launcher.sh [--check] [--launch] [--verbose]
|
|
#
|
|
# Modes:
|
|
# --check Check environment only (no launch). Exits 0 if ready.
|
|
# --launch Launch the game (default if no flags)
|
|
# --verbose Print detailed diagnostic info
|
|
|
|
set -euo pipefail
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# CONFIGURATION
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
BANNERLORD_EXE="bin/Generic/Bannerlord.exe"
|
|
GOG_PATHS=(
|
|
"/Applications/Games/Mount & Blade II Bannerlord"
|
|
"$HOME/GOG Games/Mount and Blade II Bannerlord"
|
|
"$HOME/Games/Mount & Blade II Bannerlord"
|
|
"/Applications/Mount & Blade II Bannerlord"
|
|
)
|
|
# Also check common GOG Galaxy paths
|
|
GOG_GALAXY_PATHS=(
|
|
"$HOME/Library/Application Support/GOG.com/Galaxy/Applications/*/Mount & Blade II Bannerlord"
|
|
)
|
|
|
|
# Emulator priority: Whisky > CrossOver > Homebrew Wine > system wine
|
|
EMULATOR_NAMES=("Whisky" "CrossOver" "Wine" "wine64" "wine")
|
|
|
|
VERBOSE=0
|
|
CHECK_ONLY=0
|
|
LAUNCH=0
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# ARGUMENT PARSING
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--check) CHECK_ONLY=1 ;;
|
|
--launch) LAUNCH=1 ;;
|
|
--verbose) VERBOSE=1 ;;
|
|
*) echo "Unknown arg: $arg"; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
if [ "$CHECK_ONLY" -eq 0 ] && [ "$LAUNCH" -eq 0 ]; then
|
|
LAUNCH=1 # Default to launch mode
|
|
fi
|
|
|
|
log() { echo "[bannerlord] $*"; }
|
|
vlog() { [ "$VERBOSE" -eq 1 ] && echo "[bannerlord:debug] $*" || true; }
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# EMULATOR DETECTION
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
find_emulator() {
|
|
local emulator_path=""
|
|
local emulator_name=""
|
|
local emulator_type=""
|
|
|
|
# Check for Whisky (macOS Wine wrapper)
|
|
if [ -d "/Applications/Whisky.app" ]; then
|
|
emulator_path="/Applications/Whisky.app/Contents/Resources/Libraries/wine/bin/wine64"
|
|
if [ -x "$emulator_path" ]; then
|
|
emulator_name="Whisky"
|
|
emulator_type="whisky"
|
|
fi
|
|
fi
|
|
|
|
# Check for CrossOver
|
|
if [ -z "$emulator_path" ] && [ -d "/Applications/CrossOver.app" ]; then
|
|
emulator_path="/Applications/CrossOver.app/Contents/SharedSupport/CrossOver/bin/wine"
|
|
if [ -x "$emulator_path" ]; then
|
|
emulator_name="CrossOver"
|
|
emulator_type="crossover"
|
|
fi
|
|
fi
|
|
|
|
# Check for Homebrew wine
|
|
if [ -z "$emulator_path" ]; then
|
|
for candidate in wine64 wine; do
|
|
if command -v "$candidate" >/dev/null 2>&1; then
|
|
emulator_path="$(command -v "$candidate")"
|
|
emulator_name="$candidate"
|
|
emulator_type="wine"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [ -n "$emulator_path" ]; then
|
|
EMULATOR_PATH="$emulator_path"
|
|
EMULATOR_NAME="$emulator_name"
|
|
EMULATOR_TYPE="$emulator_type"
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# GAME DETECTION
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
find_bannerlord() {
|
|
# Check standard GOG paths
|
|
for path in "${GOG_PATHS[@]}"; do
|
|
if [ -f "$path/$BANNERLORD_EXE" ]; then
|
|
GAME_DIR="$path"
|
|
GAME_EXE="$path/$BANNERLORD_EXE"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
# Check GOG Galaxy paths (glob expansion)
|
|
for pattern in "${GOG_GALAXY_PATHS[@]}"; do
|
|
# shellcheck disable=SC2086
|
|
for path in $pattern; do
|
|
if [ -d "$path" ] && [ -f "$path/$BANNERLORD_EXE" ]; then
|
|
GAME_DIR="$path"
|
|
GAME_EXE="$path/$BANNERLORD_EXE"
|
|
return 0
|
|
fi
|
|
done
|
|
done
|
|
|
|
# Search with find as last resort
|
|
local found
|
|
found=$(find /Applications "$HOME/GOG Games" "$HOME/Games" -name "Bannerlord.exe" -type f 2>/dev/null | head -1)
|
|
if [ -n "$found" ]; then
|
|
GAME_EXE="$found"
|
|
GAME_DIR="$(dirname "$(dirname "$found")")"
|
|
return 0
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# STATUS REPORTING
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
emit_status() {
|
|
local status="$1"
|
|
local message="$2"
|
|
# JSON output for harness consumption
|
|
echo "{\"status\":\"$status\",\"emulator\":\"${EMULATOR_NAME:-none}\",\"emulator_type\":\"${EMULATOR_TYPE:-none}\",\"game_dir\":\"${GAME_DIR:-}\",\"game_exe\":\"${GAME_EXE:-}\",\"message\":\"$message\"}"
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# MAIN
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
main() {
|
|
# Verify macOS
|
|
if [ "$(uname)" != "Darwin" ]; then
|
|
emit_status "error" "Not macOS — this launcher is Mac-only"
|
|
exit 1
|
|
fi
|
|
|
|
log "Bannerlord Local Launcher — macOS"
|
|
|
|
# Find emulator
|
|
if find_emulator; then
|
|
log "Emulator found: $EMULATOR_NAME ($EMULATOR_PATH)"
|
|
vlog " Type: $EMULATOR_TYPE"
|
|
else
|
|
log "ERROR: No Windows emulator found."
|
|
log "Install one of: Whisky, CrossOver, or wine (brew install --cask wine-stable)"
|
|
emit_status "missing_emulator" "No Windows emulator installed"
|
|
exit 1
|
|
fi
|
|
|
|
# Find game
|
|
if find_bannerlord; then
|
|
log "Bannerlord found: $GAME_DIR"
|
|
vlog " Exe: $GAME_EXE"
|
|
else
|
|
log "ERROR: Bannerlord not found in known GOG paths."
|
|
log "Checked: ${GOG_PATHS[*]}"
|
|
emit_status "missing_game" "Bannerlord GOG installation not found"
|
|
exit 1
|
|
fi
|
|
|
|
# Check mode
|
|
if [ "$CHECK_ONLY" -eq 1 ]; then
|
|
log "Check passed. Ready to launch."
|
|
emit_status "ready" "Emulator and game both found"
|
|
exit 0
|
|
fi
|
|
|
|
# Launch
|
|
if [ "$LAUNCH" -eq 1 ]; then
|
|
log "Launching Bannerlord via $EMULATOR_NAME..."
|
|
emit_status "launching" "Starting Bannerlord through $EMULATOR_NAME"
|
|
|
|
cd "$GAME_DIR"
|
|
# Launch in background, redirect output
|
|
"$EMULATOR_PATH" "$GAME_EXE" "$@" >/dev/null 2>&1 &
|
|
local pid=$!
|
|
log "Bannerlord started (PID: $pid)"
|
|
echo "$pid" > /tmp/bannerlord.pid
|
|
|
|
# Wait a moment and check it's still running
|
|
sleep 2
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
log "Bannerlord is running."
|
|
emit_status "running" "Bannerlord PID $pid"
|
|
exit 0
|
|
else
|
|
log "WARNING: Bannerlord process exited quickly. Check Wine logs."
|
|
emit_status "crashed" "Process exited within 2 seconds"
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
main "$@"
|