param( [string]$PackageRoot = 'C:\HyperTwist\packaged\higher-dimensional', [string]$MapUrl = '/Game/HyperTwistTraining/Maps/L_HyperTwist_Magic120CellTraining', [int]$SmokeSeconds = 10, [int]$ResX = 1600, [int]$ResY = 900, [string]$ReportPath = '', [switch]$KeepRunning ) $ErrorActionPreference = 'Stop' function Write-Utf8JsonFile { param( [Parameter(Mandatory = $true)] [string]$Path, [Parameter(Mandatory = $true)] [object]$Value ) $ParentPath = Split-Path -Parent $Path if (-not [string]::IsNullOrWhiteSpace($ParentPath)) { New-Item -ItemType Directory -Force -Path $ParentPath | Out-Null } $Json = $Value | ConvertTo-Json -Depth 8 $Utf8NoBom = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText($Path, $Json, $Utf8NoBom) } $CandidateExecutablePaths = @( (Join-Path $PackageRoot 'Windows\UnrealHyperTwist.exe'), (Join-Path $PackageRoot 'WindowsNoEditor\UnrealHyperTwist.exe'), (Join-Path $PackageRoot 'UnrealHyperTwist.exe') ) $ExecutablePath = $CandidateExecutablePaths | Where-Object { Test-Path $_ } | Select-Object -First 1 if ($null -eq $ExecutablePath) { throw "No packaged UnrealHyperTwist executable was found beneath '$PackageRoot'." } $ArgumentList = @( $MapUrl, "-ResX=$ResX", "-ResY=$ResY", '-windowed', '-log' ) Write-Host "Launching packaged higher-dimensional validation lane from '$ExecutablePath'..." $ResolvedPackageRoot = (Resolve-Path -LiteralPath $PackageRoot).Path $GeneratedAtUtc = [DateTime]::UtcNow.ToString('o') $Process = $null $Report = [ordered]@{ reportVersion = 'ht-higher-dimensional-package-smoke/v1' generatedAtUtc = $GeneratedAtUtc packageRoot = $ResolvedPackageRoot executablePath = $ExecutablePath mapUrl = $MapUrl smokeSeconds = $SmokeSeconds resolution = [ordered]@{ width = $ResX height = $ResY } keepRunning = [bool]$KeepRunning result = 'failed' processId = $null processStopped = $false exitCode = $null error = $null } try { $Process = Start-Process -FilePath $ExecutablePath -ArgumentList $ArgumentList -PassThru Start-Sleep -Seconds $SmokeSeconds $Process.Refresh() $Report.processId = $Process.Id if ($Process.HasExited) { $Report.exitCode = $Process.ExitCode throw "Packaged higher-dimensional executable exited early with code $($Process.ExitCode)." } $Report.result = 'passed' } catch { $Report.error = $_.Exception.Message if ($null -ne $Process) { $Process.Refresh() if ($Process.HasExited) { $Report.exitCode = $Process.ExitCode } elseif (-not $KeepRunning) { Stop-Process -Id $Process.Id -Force $Report.processStopped = $true } } if (-not [string]::IsNullOrWhiteSpace($ReportPath)) { Write-Utf8JsonFile -Path $ReportPath -Value $Report } throw } Write-Host "Packaged higher-dimensional smoke launch succeeded (PID $($Process.Id))." if (-not $KeepRunning) { Stop-Process -Id $Process.Id -Force $Report.processStopped = $true Write-Host 'Stopped packaged higher-dimensional smoke process after successful launch validation.' } if (-not [string]::IsNullOrWhiteSpace($ReportPath)) { Write-Utf8JsonFile -Path $ReportPath -Value $Report }