[CmdletBinding()] param( [string]$DataPath = '', [string]$IconPath = '', [string]$PatchSource = '', [string]$AuthHost = '', [string]$EnvFile = '', [string]$PackagePath = '', [string]$BinaryPath = '', [string]$VcRuntimePath = '', [string]$Prefix = 'World of Warcraft 1.12.1', [string]$ManifestKey = 'manifest-1.12.1.json', [switch]$Publish, [switch]$DryRun, [switch]$SkipClientBuild ) $ErrorActionPreference = 'Stop' $repoRoot = Split-Path $PSScriptRoot -Parent if (-not $EnvFile) { $EnvFile = Join-Path (Split-Path $repoRoot -Parent) 'MoonWellClientSources\.env' } if (-not $PackagePath) { $PackagePath = Join-Path $repoRoot ('dist\moonwell-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) } if (-not $BinaryPath) { $BinaryPath = Join-Path $repoRoot 'target\release\MoonWell.exe' } if ($BinaryPath.EndsWith('.exe', [StringComparison]::OrdinalIgnoreCase)) { if (-not $VcRuntimePath) { $vswherePath = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe' $vsInstall = (& $vswherePath -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath).Trim() if ($LASTEXITCODE -ne 0 -or -not $vsInstall) { throw 'Visual Studio C++ runtime was not found; pass -VcRuntimePath.' } $redistVersion = Get-ChildItem -LiteralPath (Join-Path $vsInstall 'VC\Redist\MSVC') -Directory | Where-Object { $_.Name -match '^\d+\.\d+\.\d+$' } | Sort-Object { [version]$_.Name } -Descending | Select-Object -First 1 $VcRuntimePath = Join-Path $redistVersion.FullName 'x64\Microsoft.VC143.CRT' } if (-not (Test-Path -LiteralPath (Join-Path $VcRuntimePath 'vcruntime140.dll') -PathType Leaf)) { throw 'The x64 Visual C++ redistributable vcruntime140.dll was not found.' } } if (-not $DataPath -or -not $AuthHost) { throw 'Pass -DataPath pointing to WoW 1.12.1 Data and -AuthHost host[:port]. WOW_HOME from the old .env is deliberately not used.' } if ($Publish -and $DryRun) { throw 'Choose -Publish or -DryRun.' } if (Test-Path -LiteralPath $PackagePath) { throw 'PackagePath already exists; choose a new staging directory.' } if (($Publish -or $DryRun) -and -not (Test-Path -LiteralPath $EnvFile -PathType Leaf)) { throw 'Deployment .env was not found.' } Push-Location $repoRoot try { if (-not $SkipClientBuild) { $embeddedIcon = Join-Path $repoRoot 'crates\moonwell\assets\moonwell.ico' if ($IconPath) { $sourceIcon = (Resolve-Path -LiteralPath $IconPath).Path New-Item -ItemType Directory -Path (Split-Path $embeddedIcon -Parent) -Force | Out-Null if ($sourceIcon -ne $embeddedIcon) { Copy-Item -LiteralPath $sourceIcon -Destination $embeddedIcon } } if (-not (Test-Path -LiteralPath $embeddedIcon -PathType Leaf)) { throw 'Provide the MoonWell icon with -IconPath or place it in crates/moonwell/assets/moonwell.ico.' } & cargo build -p moonwell --release --no-default-features --locked if ($LASTEXITCODE -ne 0) { throw 'MoonWell player build failed.' } } & cargo build -p moonwell-deploy --release --locked if ($LASTEXITCODE -ne 0) { throw 'Rust deployment tool build failed.' } $toolPath = Join-Path $repoRoot 'target\release\moonwell-deploy.exe' $stageArguments = @('stage', '--binary', $BinaryPath, '--data', $DataPath, '--output', $PackagePath, '--auth-host', $AuthHost) if ($PatchSource) { $stageArguments += @('--source', $PatchSource) } & $toolPath @stageArguments if ($LASTEXITCODE -ne 0) { throw 'Package staging failed.' } if ($BinaryPath.EndsWith('.exe', [StringComparison]::OrdinalIgnoreCase)) { Copy-Item -LiteralPath (Join-Path $VcRuntimePath 'vcruntime140.dll') -Destination (Join-Path $PackagePath 'vcruntime140.dll') } # The local inventory lives outside the package, so it cannot list itself. $inventoryPath = $PackagePath + '.manifest.json' & $toolPath manifest --dir $PackagePath --output $inventoryPath if ($LASTEXITCODE -ne 0) { throw 'Manifest generation failed.' } if ($Publish -or $DryRun) { $publishArguments = @('publish', '--dir', $PackagePath, '--env-file', $EnvFile, '--prefix', $Prefix, '--manifest-key', $ManifestKey) if ($DryRun) { $publishArguments += '--dry-run' } & $toolPath @publishArguments if ($LASTEXITCODE -ne 0) { throw 'S3 publication failed.' } } Write-Host "Package: $PackagePath" Write-Host "Local manifest: $inventoryPath" } finally { Pop-Location }