#!/usr/bin/env bash # Magic Civilization — Task Runner # Usage: ./run [args...] # # Naming convention: `` for global actions; `:` for subcommands. # Examples: lint / lint:rust, build / build:wasm, install:osx, smoke:linux. set -uo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Source all run modules for _script in "$REPO_ROOT/scripts/run/"*.sh; do source "$_script" done unset _script usage() { echo -e "${BLUE}Magic Civilization${NC} — Task Runner" echo "" echo "Usage: ./run [args...]" echo "" echo -e "${YELLOW}Development${NC}" echo " play Launch the game locally" echo " editor Open Godot editor" echo " guide Start guide dev server (port 5800)" echo " lint Lint all (GDScript + Rust + TypeScript)" echo " lint:gd GDScript only (gdlint + gdformat --check)" echo " lint:rust Rust only (fmt --check + clippy + machete)" echo " lint:ts TypeScript only (ESLint + tsc typecheck)" echo " format Format all (GDScript + Rust + TypeScript)" echo " format:gd GDScript only (gdformat)" echo " format:rust Rust only (cargo fmt)" echo " format:ts TypeScript only (ESLint --fix)" echo " typecheck pnpm -r typecheck (all TS packages)" echo " validate Validate game data JSON files against schemas" echo " test Run GUT + Rust (nextest if available) + vitest" echo " test:golden Cross-language golden-vector parity (Rust + WASM + GDExt)" echo " coverage Coverage reports (cargo llvm-cov + pnpm test:coverage)" echo " verify Full pipeline: schemas + build + tests + lint + docs + LOC cap" echo " screenshot [name] [scene] [delay] Capture screenshot" echo " autoplay [seed] Run single seeded auto_play game + report (opt-in)" echo " autoplay-batch [count] Run N seeded games + aggregate report (opt-in)" echo "" echo -e "${YELLOW}Build${NC}" echo " build Build WASM + GDExtension" echo " build:wasm Build WASM only (src/simulator → pkg/)" echo " build:gdext Build GDExtension only (src/simulator → src/game/addons/)" echo "" echo -e "${YELLOW}Export${NC}" echo " export [version] Export all platforms (parallel)" echo " export:macos [version] Export macOS only" echo " export:linux [version] Export Linux only" echo " export:windows [version] Export Windows only" echo " export:android [version] Export Android APK" echo " export:ios [version] Export iOS Xcode project" echo "" echo -e "${YELLOW}Install (deploy + launch on target)${NC}" echo " install:osx [version] [--dev] Export + install .app on \$OSX_HOST (default: plum)" echo " install:linux [version] [--dev] Export + install binary on \$LINUX_HOST" echo " install:iphone [version] [--dev] Export + xcodebuild + devicectl install via \$OSX_HOST" echo " install:android [version] [--dev] Export + adb install on connected Android device" echo "" echo -e "${YELLOW}Remote control${NC}" echo " start:osx Launch installed app on \$OSX_HOST" echo " start:linux Launch installed binary on \$LINUX_HOST" echo " start:ios Launch app on connected iPhone (via \$OSX_HOST)" echo " stop:osx Kill running app on \$OSX_HOST" echo " stop:linux Kill running binary on \$LINUX_HOST" echo " smoke:osx Full smoke test (macOS — export → ship → launch → screenshot)" echo " smoke:linux [boot-secs] Full smoke test (Linux — default 20s boot wait)" echo "" echo -e "${YELLOW}Tools${NC}" echo " tools:spritegen Sprite generation pipeline" echo " setup Install/verify all dev dependencies (auto-detects OS)" } # ── Install args parser (shared by install:* targets) ──────────────── # Separates --dev from positional args; echoes them as # "DEV_MODE|pos1 pos2 ..." for callers to split. _parse_install_args() { local dev_flag="" local pos=() for arg in "$@"; do case "$arg" in --dev) dev_flag="--dev" ;; *) pos+=("$arg") ;; esac done echo "$dev_flag|${pos[*]}" } _dispatch_install() { local target="$1"; shift local parsed dev_flag pos_args parsed="$(_parse_install_args "$@")" dev_flag="${parsed%%|*}" pos_args="${parsed#*|}" # shellcheck disable=SC2086 case "$target" in osx) cmd_install_osx $dev_flag $pos_args ;; linux) cmd_install_linux $dev_flag $pos_args ;; iphone) cmd_install_ios iphone $dev_flag $pos_args ;; sim) cmd_install_ios sim $dev_flag $pos_args ;; android) cmd_install_android $dev_flag $pos_args ;; *) echo -e "${RED}Unknown install target: $target${NC}"; echo "Available: osx, linux, iphone, android"; return 1 ;; esac } COMMAND="${1:-}" shift 2>/dev/null || true case "$COMMAND" in # ── Development ────────────────────────────────────────────────── play) cmd_play "$@" ;; editor) cmd_editor "$@" ;; guide) cmd_guide "$@" ;; lint) cmd_lint "$@" ;; lint:gd) cmd_lint_gd "$@" ;; lint:rust) cmd_lint_rust "$@" ;; lint:ts) cmd_lint_ts "$@" ;; format) cmd_format "$@" ;; format:gd) cmd_format_gd "$@" ;; format:rust) cmd_format_rust "$@" ;; format:ts) cmd_format_ts "$@" ;; typecheck) cmd_typecheck "$@" ;; validate) cmd_validate "$@" ;; test) cmd_test "$@" ;; test:golden) cmd_test_golden "$@" ;; coverage) cmd_coverage "$@" ;; verify) cmd_verify "$@" ;; screenshot) cmd_screenshot "$@" ;; autoplay) cmd_autoplay "$@" ;; autoplay-batch) cmd_autoplay_batch "$@" ;; # ── Build ──────────────────────────────────────────────────────── build) cmd_build "$@" ;; build:wasm) cmd_build_wasm "$@" ;; build:gdext) cmd_build_gdext "$@" ;; # ── Export ─────────────────────────────────────────────────────── export) cmd_export "$@" ;; export:windows) cmd_export_single windows "$@" ;; export:macos) cmd_export_single macos "$@" ;; export:linux) cmd_export_single linux "$@" ;; export:android) cmd_export_single android "$@" ;; export:ios) cmd_export_single ios "$@" ;; # ── Install (colon form — canonical) ──────────────────────────── install:osx|install:macos) _dispatch_install osx "$@" ;; install:linux) _dispatch_install linux "$@" ;; install:iphone|install:ios) _dispatch_install iphone "$@" ;; install:sim) _dispatch_install sim "$@" ;; install:android) _dispatch_install android "$@" ;; # ── Start / Stop / Smoke (colon form — canonical) ─────────────── start:osx|start:macos) cmd_start_osx "$@" ;; start:linux) cmd_start_linux "$@" ;; start:ios|start:iphone) cmd_start_ios "$@" ;; stop:osx|stop:macos) cmd_stop_osx "$@" ;; stop:linux) cmd_stop_linux "$@" ;; smoke:osx|smoke:macos) cmd_smoke_osx "$@" ;; smoke:linux) cmd_smoke_linux "$@" ;; # ── Tools (colon form — canonical) ────────────────────────────── tools:spritegen) cmd_tools_spritegen "$@" ;; # ── Legacy space-form aliases (for muscle memory — undocumented) # install|start|stop|smoke|tools all accept a positional subtarget. install) TARGET=""; POS=() for arg in "$@"; do case "$arg" in --dev) POS+=("$arg") ;; osx|macos|linux|iphone|ios|sim|android) TARGET="$arg" ;; *) POS+=("$arg") ;; esac done [ -n "$TARGET" ] || { echo -e "${RED}install requires a target (use install:)${NC}"; exit 1; } _dispatch_install "${TARGET/macos/osx}" "${POS[@]+"${POS[@]}"}" ;; start|stop|smoke) VERB="$COMMAND" TARGET="${1:-}"; shift 2>/dev/null || true [ -n "$TARGET" ] || { echo -e "${RED}$VERB requires a target (use $VERB:)${NC}"; exit 1; } # Recurse using canonical colon form exec "$0" "$VERB:$TARGET" "$@" ;; tools) SUB="${1:-}"; shift 2>/dev/null || true [ -n "$SUB" ] || { echo -e "${RED}tools requires a subcommand (use tools:)${NC}"; exit 1; } exec "$0" "tools:$SUB" "$@" ;; # ── Misc ───────────────────────────────────────────────────────── setup) cmd_setup "$@" ;; help|--help|-h|"") usage ;; *) echo -e "${RED}Unknown command: $COMMAND${NC}"; echo ""; usage; exit 1 ;; esac