This repository has been archived on 2026-10-29. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
EveUnity/scripts/run-interactive-aetheria.ps1
2026-07-19 01:06:04 +01:00

121 lines
5.9 KiB
PowerShell

param(
[string] $UnityExe = "C:\Program Files\Unity\Hub\Editor\6000.4.2f1\Editor\Unity.exe",
[string] $AetheriaRoot = "E:\Projects\Aetheria",
[string] $CultLibRoot = "E:\Projects\CultLib-release",
[string] $EveUnityRoot = "E:\Projects\EveUnity",
[string] $YmirRoot = "E:\Projects\Ymir",
[int] $Port = 3076,
[string] $OutputDirectory = "artifacts\interactive",
[switch] $SkipBuild
)
$ErrorActionPreference = "Stop"
$root = Split-Path -Parent $PSScriptRoot
$project = Join-Path $root "ReleaseConsumerProject"
$outputRoot = if ([IO.Path]::IsPathRooted($OutputDirectory)) { $OutputDirectory } else { Join-Path $root $OutputDirectory }
$buildLog = Join-Path $outputRoot "build.log"
$bundleBuildLog = Join-Path $outputRoot "asset-bundle-build.log"
$daemonLog = Join-Path $outputRoot "daemon.log"
$importLog = Join-Path $outputRoot "import.log"
$importErrorLog = Join-Path $outputRoot "import.error.log"
$state = Join-Path $outputRoot "aetheria.cc"
$replica = Join-Path $outputRoot "eve-unity-replica.cc"
$assetCache = Join-Path $outputRoot "asset-cache"
$exe = Join-Path $project "Build\Windows\EveUnity.exe"
$importProject = Join-Path $AetheriaRoot "Aetheria.State.Import\Aetheria.State.Import.csproj"
$daemonProject = Join-Path $AetheriaRoot "Aetheria.State.Daemon\Aetheria.State.Daemon.csproj"
foreach ($required in @($UnityExe, $project, $importProject, $daemonProject, (Join-Path $YmirRoot "src\Ymir.Core\Ymir.Core.csproj"))) {
if (-not (Test-Path -LiteralPath $required)) { throw "Required interactive witness path not found: $required" }
}
if (Get-NetUDPEndpoint -LocalPort $Port -ErrorAction SilentlyContinue) {
throw "UDP port $Port is already occupied."
}
New-Item -ItemType Directory -Force $outputRoot, $assetCache | Out-Null
foreach ($ephemeralPath in @($state, "$state.records", "$state.cultmesh", $replica, "$replica.records", "$replica.cultmesh")) {
$resolved = [IO.Path]::GetFullPath($ephemeralPath)
if (-not $resolved.StartsWith([IO.Path]::GetFullPath($outputRoot), [StringComparison]::OrdinalIgnoreCase)) {
throw "Interactive cleanup escaped its artifact directory: $resolved"
}
if (Test-Path -LiteralPath $resolved) { Remove-Item -LiteralPath $resolved -Recurse -Force }
}
if (-not $SkipBuild -or -not (Test-Path $exe)) {
$build = Start-Process $UnityExe -ArgumentList @("-batchmode", "-quit", "-projectPath", $project, "-executeMethod", "GenericEveUnityBuild.BuildWindows", "-logFile", $buildLog) -PassThru -WindowStyle Hidden
Write-Host "Build PID: $($build.Id)"
Write-Host "Build log: $buildLog"
if (-not $build.WaitForExit(300000)) { Stop-Process $build.Id -Force; throw "EveUnity build timed out." }
if ($build.ExitCode -ne 0 -or -not (Test-Path $exe) -or (Select-String $buildLog -Pattern "Scripts have compiler errors|Build completed with a result of 'Failed'" -Quiet)) { Get-Content $buildLog -Tail 120; throw "EveUnity build failed." }
}
if (-not $SkipBuild) {
$bundleBuilder = Start-Process $UnityExe -ArgumentList @(
"-batchmode", "-quit", "-projectPath", ".",
"-executeMethod", "Aetheria.Editor.EveAssetBundleBuilder.BuildWindows",
"-logFile", $bundleBuildLog
) -WorkingDirectory $AetheriaRoot -PassThru -WindowStyle Hidden
Write-Host "AssetBundle build PID: $($bundleBuilder.Id)"
Write-Host "AssetBundle build log: $bundleBuildLog"
if (-not $bundleBuilder.WaitForExit(240000)) { Stop-Process $bundleBuilder.Id -Force; throw "Aetheria AssetBundle build timed out." }
if ($bundleBuilder.ExitCode -ne 0) { Get-Content $bundleBuildLog -Tail 120; throw "Aetheria AssetBundle build failed." }
}
$importArguments = @(
"run", "--project", $importProject,
"-p:CultLibRoot=$CultLibRoot", "-p:EveUnityRoot=$EveUnityRoot", "-p:YmirRoot=$YmirRoot",
"--", $AetheriaRoot, $state
)
$previousErrorActionPreference = $ErrorActionPreference
try {
$ErrorActionPreference = "Continue"
& dotnet @importArguments 1> $importLog 2> $importErrorLog
$importExitCode = $LASTEXITCODE
}
finally {
$ErrorActionPreference = $previousErrorActionPreference
}
if ($importExitCode -ne 0) { throw "Aetheria state import failed. See $importErrorLog" }
$daemon = Start-Process dotnet -ArgumentList @(
"run", "--project", $daemonProject,
"-p:CultLibRoot=$CultLibRoot", "-p:EveUnityRoot=$EveUnityRoot", "-p:YmirRoot=$YmirRoot",
"--",
"--root", $AetheriaRoot,
"--state", $state,
"--client-cultmesh-host", "127.0.0.1",
"--client-cultmesh-advertise-host", "127.0.0.1",
"--client-cultmesh-port", $Port,
"--tick-interval-ms", 20,
"--fixed-delta-ms", 20,
"--no-odin-announcements"
) -PassThru -WindowStyle Hidden -RedirectStandardOutput $daemonLog -RedirectStandardError "$daemonLog.error"
Write-Host "Daemon PID: $($daemon.Id)"
Write-Host "Daemon log: $daemonLog"
try {
$ready = $false
for ($i=0; $i -lt 240; $i++) {
if ($daemon.HasExited) { throw "Aetheria daemon exited. See $daemonLog" }
if ((Test-Path $daemonLog) -and
(Select-String $daemonLog -Pattern "Aetheria client CultMesh endpoint: rudp://127.0.0.1:$Port" -Quiet)) {
$ready = $true
break
}
Start-Sleep -Milliseconds 500
}
if (-not $ready) { throw "Aetheria daemon did not open CultMesh port $Port within 120 seconds. See $daemonLog" }
$env:EVEUNITY_RENDEZVOUS_ENDPOINT = "rudp://127.0.0.1:$Port"
$env:EVEUNITY_PROVIDER_ID = "aetheria"
$env:EVEUNITY_REPLICA_PATH = $replica
$env:EVEUNITY_ASSET_CACHE_PATH = $assetCache
Remove-Item Env:EVEUNITY_SURFACE_ID -ErrorAction SilentlyContinue
$client = Start-Process $exe -ArgumentList "-force-d3d11" -PassThru
Write-Host "Client PID: $($client.Id)"
Write-Host "Asset cache: $assetCache"
Write-Host "Close the EveUnity window when finished."
$client.WaitForExit()
}
finally {
if ($null -ne $daemon -and -not $daemon.HasExited) { Stop-Process $daemon.Id -Force }
Remove-Item Env:EVEUNITY_RENDEZVOUS_ENDPOINT, Env:EVEUNITY_PROVIDER_ENDPOINT, Env:EVEUNITY_PROVIDER_ID, Env:EVEUNITY_SURFACE_ID, Env:EVEUNITY_REPLICA_PATH, Env:EVEUNITY_ASSET_CACHE_PATH -ErrorAction SilentlyContinue
}