<# .SYNOPSIS Packages The Descent as a Windows 64-bit game (TheDescent.exe plus its content) and prints one PASS/FAIL line. .DESCRIPTION Runs Unreal's packaging tool (RunUAT BuildCookRun). In one go it: build compiles the game module in the chosen configuration (always 64-bit: UE5 has no 32-bit Windows target), cook converts the assets the game needs into the format a packaged game reads, stage collects the .exe, the engine files and the cooked content into one folder, pak packs the content into TheDescent-Windows.pak/.utoc/.ucas (IoStore, compressed), archive copies the finished game to the output folder. Shipping is the release build: optimised, no console, no logs. Development is the same game with the console and the log kept, for testing a package (the Descent.* debug commands and the scenario runner work in it). Which maps are cooked and which folders are always cooked (assets the code loads by name, which no map references) is set in Config\DefaultGame.ini, [/Script/UnrealEd.ProjectPackagingSettings]. The editor's own Platforms > Windows > Package Project uses the same settings. This PC has no registered Visual Studio, so UE_SDKS_ROOT is set for the child process, as in build.ps1. The full output goes to Saved\Logs\package_last.log; pass -Verbose to also stream it to the console. .EXAMPLE powershell -NoProfile -ExecutionPolicy Bypass -File Tools\package.ps1 Shipping build into \Builds\Win64-Shipping. Exit code 0 = PASS, 1 = FAIL. .EXAMPLE powershell -NoProfile -ExecutionPolicy Bypass -File Tools\package.ps1 -Config Development -Out "D:\Somewhere" #> [CmdletBinding()] param( [ValidateSet('Shipping', 'Development')] [string]$Config = 'Shipping', # Where the finished game goes. Default: \Builds\Win64- (replaced by the next package). [string]$Out = '', # Maps to cook, '+' separated, e.g. /Game/Maps/Descent_Main. Default: MapsToCook in Config\DefaultGame.ini. [string]$Map = '', # Reuse the last cook instead of cooking again (only when no asset changed since). [switch]$SkipCook ) $ErrorActionPreference = 'Stop' $ProjectRoot = Split-Path -Parent $PSScriptRoot # ...\TheDescentUE $Uproject = Join-Path $ProjectRoot 'TheDescent.uproject' $EngineRoot = 'E:\Tools\UE_5.8' $RunUat = Join-Path $EngineRoot 'Engine\Build\BatchFiles\RunUAT.bat' $LogDir = Join-Path $ProjectRoot 'Saved\Logs' $LogFile = Join-Path $LogDir 'package_last.log' if ($Out -eq '') { $Out = Join-Path (Split-Path -Parent $ProjectRoot) "Builds\Win64-$Config" } if (-not (Test-Path $RunUat)) { Write-Host "PACKAGE FAIL: RunUAT.bat not found at $RunUat"; exit 1 } New-Item -ItemType Directory -Force -Path $LogDir | Out-Null $env:UE_SDKS_ROOT = 'D:\HADAL - The Descent\.tools\AutoSDK' $uatArgs = @( 'BuildCookRun', "-project=`"$Uproject`"", '-noP4', '-platform=Win64', "-clientconfig=$Config", '-build', '-stage', '-pak', '-iostore', '-compressed', '-prereqs', '-nodebuginfo', '-archive', "-archivedirectory=`"$Out`"", '-unattended', '-utf8output' ) if ($SkipCook) { $uatArgs += '-skipcook' } else { $uatArgs += '-cook' } if ($Map -ne '') { $uatArgs += "-map=$Map" } $sw = [System.Diagnostics.Stopwatch]::StartNew() # cmd /c keeps the batch file's own exit code and lets us merge stderr without PowerShell turning lines into errors. $cmdLine = '"' + $RunUat + '" ' + ($uatArgs -join ' ') + ' > "' + $LogFile + '" 2>&1' cmd.exe /c $cmdLine $exit = $LASTEXITCODE $sw.Stop() $lines = Get-Content -Path $LogFile -ErrorAction SilentlyContinue if ($VerbosePreference -eq 'Continue') { $lines | ForEach-Object { Write-Host $_ } } # Compiler, linker, cook and UAT error shapes. $errorLines = $lines | Where-Object { $_ -match ': (fatal )?error [A-Z]*\d+|\berror LNK\d+|^ERROR:|LogCook: Error:|Error: |BUILD FAILED' } | Select-Object -Unique $cookWarn = ($lines | Where-Object { $_ -match 'LogCook: Warning:' } | Measure-Object).Count $mins = [math]::Round($sw.Elapsed.TotalMinutes, 1) $exe = Get-ChildItem -Path $Out -Recurse -Filter 'TheDescent.exe' -ErrorAction SilentlyContinue | Select-Object -First 1 if ($exit -eq 0 -and $exe) { $gb = [math]::Round(((Get-ChildItem -Path $exe.DirectoryName -Recurse -File | Measure-Object Length -Sum).Sum) / 1GB, 2) Write-Host ("PACKAGE PASS Win64 {0} {1} min {2} GB cook warnings={3}" -f $Config, $mins, $gb, $cookWarn) Write-Host (" Start the game with: {0}" -f $exe.FullName) exit 0 } else { $errorLines | Select-Object -First 40 | ForEach-Object { Write-Host $_ } Write-Host ("PACKAGE FAIL exit={0} {1} min errors={2} log={3}" -f $exit, $mins, @($errorLines).Count, $LogFile) exit 1 }