param( [switch]$RunGodotImport ) $ErrorActionPreference = "Stop" $Root = Split-Path -Parent $PSScriptRoot $Failures = New-Object System.Collections.Generic.List[string] $Warnings = New-Object System.Collections.Generic.List[string] function Add-Failure([string]$Message) { $Failures.Add($Message) | Out-Null Write-Host "[FAIL] $Message" } function Add-Warning([string]$Message) { $Warnings.Add($Message) | Out-Null Write-Host "[WARN] $Message" } function Add-Pass([string]$Message) { Write-Host "[ OK ] $Message" } function Find-Godot { if (-not [string]::IsNullOrWhiteSpace($env:GODOT_BIN) -and (Test-Path $env:GODOT_BIN)) { return (Resolve-Path $env:GODOT_BIN).Path } $command = Get-Command godot -ErrorAction SilentlyContinue if ($null -ne $command) { return $command.Source } $commonCandidates = @( (Join-Path $env:USERPROFILE "Downloads\Godot_v4.6-stable_win64.exe"), (Join-Path $env:USERPROFILE "Desktop\Godot_v4.6-stable_win64.exe"), (Join-Path $env:LOCALAPPDATA "Programs\Godot\Godot_v4.6-stable_win64.exe"), "C:\Program Files\Godot\Godot_v4.6-stable_win64.exe" ) foreach ($candidate in $commonCandidates) { if (Test-Path $candidate) { return (Resolve-Path $candidate).Path } } return "" } Push-Location $Root try { $validateScript = Join-Path $PSScriptRoot "validate_data.ps1" if (Test-Path $validateScript) { try { & $validateScript | Out-Host Add-Pass "data validation script passed" } catch { Add-Failure "data validation failed: $($_.Exception.Message)" } } else { Add-Failure "missing tools\validate_data.ps1" } $jsonFiles = Get-ChildItem -Path (Join-Path $Root "data") -Filter "*.json" -Recurse foreach ($file in $jsonFiles) { try { Get-Content $file.FullName -Raw | ConvertFrom-Json | Out-Null } catch { Add-Failure "invalid JSON: $($file.FullName) - $($_.Exception.Message)" } } if ($Failures.Count -eq 0) { Add-Pass "all data JSON files parsed" } $projectPath = Join-Path $Root "project.godot" if (Test-Path $projectPath) { $projectText = Get-Content $projectPath -Raw if ($projectText -match 'config/features=PackedStringArray\("([^"]+)"\)') { $featureVersion = $Matches[1] if ($featureVersion -ne "4.6") { Add-Warning "project feature tag is $featureVersion; expect Godot 4.6 editor migration to update it" } else { Add-Pass "project feature tag is 4.6" } } else { Add-Warning "project feature tag was not found" } if ($projectText -match 'renderer/rendering_method="gl_compatibility"') { Add-Pass "project keeps the compatibility renderer explicit" } else { Add-Warning "rendering method is not explicitly gl_compatibility" } } else { Add-Failure "missing project.godot" } $riskPatterns = [ordered]@{ "Godot 3 yield syntax" = '\byield\s*\(' "Godot 3 File.new API" = '\bFile\.new\s*\(' "Godot 3 Directory.new API" = '\bDirectory\.new\s*\(' "Godot 3 Pool*Array type" = '\bPool[A-Za-z]+Array\b' "Godot 3 KinematicBody node" = '\bKinematicBody(2D|3D)?\b' "legacy TileMap set_cellv call" = '\bset_cellv\s*\(' } $gdFiles = Get-ChildItem -Path (Join-Path $Root "scripts") -Filter "*.gd" -Recurse foreach ($entry in $riskPatterns.GetEnumerator()) { $matches = @() foreach ($file in $gdFiles) { $fileMatches = Select-String -Path $file.FullName -Pattern $entry.Value -AllMatches if ($null -ne $fileMatches) { $matches += $fileMatches } } if ($matches.Count -gt 0) { Add-Warning "$($entry.Key) found in $($matches.Count) location(s)" } } Add-Pass "static Godot 3 API risk scan completed" $godotBin = Find-Godot if ([string]::IsNullOrWhiteSpace($godotBin)) { Add-Warning "Godot executable not found. Set GODOT_BIN or add godot to PATH for engine checks." } else { try { $version = & $godotBin --version Add-Pass "Godot executable found: $godotBin ($version)" if ($version -notmatch '^4\.6') { Add-Warning "detected Godot version is not 4.6: $version" } if ($RunGodotImport) { & $godotBin --headless --path $Root --quit Add-Pass "Godot headless project open completed" } } catch { Add-Failure "Godot command failed: $($_.Exception.Message)" } } } finally { Pop-Location } Write-Host "" Write-Host "Summary: $($Failures.Count) failure(s), $($Warnings.Count) warning(s)" if ($Failures.Count -gt 0) { exit 1 } exit 0