@echo off setlocal EnableExtensions EnableDelayedExpansion title AetherForge Control Deck cd /d "%~dp0" :: Portable deck root = folder that contains AetherForge.exe (repo usb\ or copied USB drive) if exist "%CD%\AetherForge.exe" ( set "ROOT=!CD!" ) else if exist "%CD%\usb\AetherForge.exe" ( cd /d "%CD%\usb" set "ROOT=!CD!" ) else ( echo. echo ERROR: AetherForge.exe not found. echo Expected next to this script, or in usb\AetherForge.exe echo Run pack-usb.bat from the repo to build the portable bundle. echo. pause exit /b 1 ) if not exist "%ROOT%\AetherForge.exe" ( echo ERROR: AetherForge.exe missing in %ROOT% pause exit /b 1 ) echo ================================================================ echo AetherForge - Portable Control Deck echo ================================================================ echo Deck: %ROOT% echo. :: ---------------------------------------------------------------- :: 1. Locate Go - prefer bundled toolchain, fall back to system Go :: ---------------------------------------------------------------- set "BUNDLED_GO=%ROOT%\toolchain\go\bin\go.exe" set "GO_BIN=" if exist "%ROOT%\toolchain\go" if not exist "%BUNDLED_GO%" ( echo [Go] Incomplete toolchain folder - removing broken install... rd /s /q "%ROOT%\toolchain\go" 2>nul ) if exist "%BUNDLED_GO%" ( echo [Go] Using bundled toolchain: %ROOT%\toolchain\go set "GO_BIN=%ROOT%\toolchain\go\bin\go.exe" set "GOROOT=%ROOT%\toolchain\go" set "PATH=%ROOT%\toolchain\go\bin;%ROOT%\toolchain\gopath\bin;%PATH%" goto go_ready ) :: Check if Go is installed system-wide where go >nul 2>nul if not errorlevel 1 ( echo [Go] Using system Go installation. set "GO_BIN=go" goto go_ready ) :: Go not found anywhere - skip optional tools, proceed directly to server echo. echo [Go] Go not found - Forge obfuscation tools unavailable. Running server without them. echo. goto server_launch :go_ready :: ---------------------------------------------------------------- :: 2. Pin all Go caches to the USB so module downloads travel with you :: ---------------------------------------------------------------- set "GOPATH=%ROOT%\toolchain\gopath" set "GOMODCACHE=%ROOT%\toolchain\gopath\pkg\mod" set "GOCACHE=%ROOT%\toolchain\gocache" set "GOENV=off" :: ---------------------------------------------------------------- :: 3. Install optional Forge tools if missing (non-fatal) :: ---------------------------------------------------------------- if /i not "%AF_INSTALL_TOOLS%"=="0" ( if not exist "%ROOT%\toolchain\gopath\bin\garble.exe" ( echo [Tools] Installing garble... "%GO_BIN%" install mvdan.cc/garble@latest if errorlevel 1 echo [Tools] WARN: garble install failed. ) if not exist "%ROOT%\toolchain\gopath\bin\go-winres.exe" ( echo [Tools] Installing go-winres... "%GO_BIN%" install github.com/tc-hib/go-winres@v0.3.1 if errorlevel 1 echo [Tools] WARN: go-winres install failed. ) ) else ( echo [Tools] Auto-install disabled ^(AF_INSTALL_TOOLS=0^). ) :server_launch :: ---------------------------------------------------------------- :: 4. Ensure data directories exist :: ---------------------------------------------------------------- if not exist "%ROOT%\data\builds" mkdir "%ROOT%\data\builds" if not exist "%ROOT%\data\logs" mkdir "%ROOT%\data\logs" if not exist "%ROOT%\data\spread-kits" mkdir "%ROOT%\data\spread-kits" if not exist "%ROOT%\data\uploads" mkdir "%ROOT%\data\uploads" if not exist "%ROOT%\data\blueprints" mkdir "%ROOT%\data\blueprints" if not exist "%ROOT%\data\preps" mkdir "%ROOT%\data\preps" :: ---------------------------------------------------------------- :: 5. Configure optional Cloudflare tunnel (foreground process, no service) :: ---------------------------------------------------------------- set "CLOUDFLARED_BIN=%ROOT%\tools\cloudflared.exe" set "CF_PID_FILE=%ROOT%\data\cloudflared.pid" set "CF_TUNNEL_TOKEN=" if defined AF_TUNNEL_TOKEN set "CF_TUNNEL_TOKEN=%AF_TUNNEL_TOKEN%" if not defined CF_TUNNEL_TOKEN if exist "%ROOT%\data\cloudflared-token.txt" ( set /p CF_TUNNEL_TOKEN=<"%ROOT%\data\cloudflared-token.txt" ) :: ---------------------------------------------------------------- :: 6. Detect LAN IP for display :: ---------------------------------------------------------------- set "SERVER_PORT=8989" for /f "tokens=2 delims=:" %%I in ('ipconfig ^| findstr /i "IPv4" ^| findstr /v "127.0.0.1"') do ( set "LAN_IP=%%I" goto lan_done ) set "LAN_IP=localhost" :lan_done set "LAN_IP=%LAN_IP: =%" :: ---------------------------------------------------------------- :: 7. Kill any stale server and tunnel processes :: ---------------------------------------------------------------- taskkill /F /IM AetherForge.exe >nul 2>nul taskkill /F /IM cloudflared.exe >nul 2>nul ping -n 2 127.0.0.1 >nul echo. echo ================================================================ echo STARTING CONTROL DECK echo ================================================================ echo Local: http://localhost:%SERVER_PORT% echo LAN: http://%LAN_IP%:%SERVER_PORT% echo Data: %ROOT%\data\ echo. echo First-run credentials will appear below after server starts. echo Press Ctrl+C to stop. echo ================================================================ echo. :: Start optional Cloudflare tunnel for this launcher session only. if defined CF_TUNNEL_TOKEN ( if not exist "%ROOT%\tools" mkdir "%ROOT%\tools" if not exist "%CLOUDFLARED_BIN%" ( echo [Tunnel] Downloading cloudflared.exe... powershell -NoProfile -ExecutionPolicy Bypass -Command "& { [Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri 'https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe' -OutFile $env:CLOUDFLARED_BIN }" ) if exist "%CLOUDFLARED_BIN%" ( del "%CF_PID_FILE%" 2>nul echo [Tunnel] Starting Cloudflare tunnel for this session ^(no service install^). powershell -NoProfile -ExecutionPolicy Bypass -Command "$p = Start-Process -FilePath $env:CLOUDFLARED_BIN -ArgumentList @('tunnel','--no-autoupdate','run','--token',$env:CF_TUNNEL_TOKEN) -WindowStyle Hidden -PassThru; Set-Content -LiteralPath $env:CF_PID_FILE -Value $p.Id" if errorlevel 1 ( echo [Tunnel] WARNING: cloudflared failed to start. ) else ( echo [Tunnel] Tunnel process started. It will stop when this launcher exits. ) ) else ( echo [Tunnel] WARNING: cloudflared.exe unavailable; tunnel skipped. ) ) else ( echo [Tunnel] Disabled. Add token to data\cloudflared-token.txt or set AF_TUNNEL_TOKEN. ) echo. :: Open browser after short delay start "" powershell -NoProfile -WindowStyle Hidden -Command "Start-Sleep -Seconds 3; Start-Process 'http://localhost:%SERVER_PORT%/'" :: Launch server "%ROOT%\AetherForge.exe" -port %SERVER_PORT% -data "%ROOT%\data" set "EC=!ERRORLEVEL!" if exist "%CF_PID_FILE%" ( for /f "usebackq" %%P in ("%CF_PID_FILE%") do ( powershell -NoProfile -ExecutionPolicy Bypass -Command "Stop-Process -Id %%P -Force -ErrorAction SilentlyContinue" >nul 2>nul ) del "%CF_PID_FILE%" 2>nul ) echo. if "!EC!"=="0" ( echo [Server] Stopped normally. ) else ( echo [Server] Exited with code !EC!. echo If port %SERVER_PORT% is in use, close other AetherForge windows and retry. ) echo. pause endlocal