param( [switch] $SelfTest, [switch] $PauseOnError ) $ErrorActionPreference = "Stop" $projectRoot = $PSScriptRoot $errorLogPath = Join-Path $projectRoot "launcher-last-error.txt" try { $bundledNodePath = Join-Path $env:USERPROFILE ".cache\codex-runtimes\codex-primary-runtime\dependencies\node\bin\node.exe" $nodeCommand = Get-Command node -ErrorAction SilentlyContinue $nodePath = if (Test-Path -LiteralPath $bundledNodePath) { $bundledNodePath } elseif ($nodeCommand) { $nodeCommand.Source } else { $bundledNodePath } if (-not (Test-Path -LiteralPath $nodePath)) { throw "未找到 Node.js。请安装 Node.js 20+,或从 Codex 桌面环境运行。" } Set-Location -LiteralPath $projectRoot $tscPath = Join-Path $projectRoot "node_modules\typescript\bin\tsc" if (Test-Path -LiteralPath $tscPath) { & $nodePath $tscPath -p tsconfig.json if ($LASTEXITCODE -ne 0) { throw "TypeScript 编译失败。" } } elseif (-not (Test-Path -LiteralPath (Join-Path $projectRoot "dist\main.js"))) { throw "没有可用的 dist 构建,也未安装 TypeScript。请先执行 pnpm install。" } $server = Start-Process -FilePath $nodePath -ArgumentList @("tools/server.mjs", "--parent-pid", $PID) -WorkingDirectory $projectRoot -WindowStyle Hidden -PassThru $url = "http://127.0.0.1:4173/mvp/" try { $ready = $false for ($attempt = 0; $attempt -lt 30; $attempt += 1) { if ($server.HasExited) { throw "本地服务器启动失败,可能是 4173 端口被占用。" } try { $response = Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 1 if ($response.StatusCode -eq 200) { $ready = $true; break } } catch { Start-Sleep -Milliseconds 100 } } if (-not $ready) { throw "本地服务器未在预期时间内就绪。" } if (Test-Path -LiteralPath $errorLogPath) { Remove-Item -LiteralPath $errorLogPath -Force -ErrorAction SilentlyContinue } if ($SelfTest) { Write-Host "SELF-TEST PASS: TypeScript compiled and $url returned HTTP 200." -ForegroundColor Green return } Write-Host "HEROLL 玩法验证 MVP 已启动:$url" -ForegroundColor Green Write-Host "保持此窗口打开;关闭本窗口或按 Ctrl+C 即可结束本地服务器。" try { Start-Process $url } catch { Write-Host "浏览器未能自动打开,但游戏服务器仍在正常运行。请复制上面的地址到浏览器。" -ForegroundColor Yellow } while (-not $server.HasExited) { Start-Sleep -Seconds 1 $server.Refresh() } } finally { if (-not $server.HasExited) { Stop-Process -Id $server.Id -Force } } } catch { $details = ($_ | Out-String).Trim() $details | Set-Content -LiteralPath $errorLogPath -Encoding UTF8 Write-Host "HEROLL MVP 启动失败:" -ForegroundColor Red Write-Host $details -ForegroundColor Red Write-Host "错误日志:$errorLogPath" -ForegroundColor Yellow if ($PauseOnError) { Read-Host "按 Enter 关闭窗口" | Out-Null } exit 1 }