136 lines
4.9 KiB
PowerShell
136 lines
4.9 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[string]$ClientPath = '',
|
|
[string]$PackagePath = '',
|
|
[ValidateSet('Debug', 'Release')]
|
|
[string]$Configuration = 'Release',
|
|
[switch]$SkipDataBuild,
|
|
[switch]$SkipManifest,
|
|
[switch]$NativeRenderer,
|
|
[switch]$StopClient,
|
|
[switch]$Launch
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
$repoRoot = $PSScriptRoot
|
|
|
|
function Import-ProjectEnvironment {
|
|
$envFile = Join-Path $repoRoot '.env'
|
|
if (-not (Test-Path -LiteralPath $envFile -PathType Leaf)) { return }
|
|
|
|
foreach ($line in Get-Content -LiteralPath $envFile -Encoding UTF8) {
|
|
if ($line -notmatch '^\s*([^#][^=]+)=(.*)$') { continue }
|
|
$name = $matches[1].Trim()
|
|
$value = $matches[2].Trim().Trim('"').Trim("'")
|
|
if ($name -and -not (Test-Path "Env:$name")) {
|
|
Set-Item -Path "Env:$name" -Value $value
|
|
}
|
|
}
|
|
}
|
|
|
|
Import-ProjectEnvironment
|
|
|
|
if ([string]::IsNullOrWhiteSpace($ClientPath)) {
|
|
$ClientPath = if ($env:WOW_HOME) {
|
|
$env:WOW_HOME
|
|
} else {
|
|
'C:\Program Files (x86)\World of Warcraft'
|
|
}
|
|
}
|
|
if ([string]::IsNullOrWhiteSpace($PackagePath)) {
|
|
$PackagePath = Join-Path $repoRoot 'dist'
|
|
}
|
|
|
|
$ClientPath = [System.IO.Path]::GetFullPath($ClientPath)
|
|
$PackagePath = [System.IO.Path]::GetFullPath($PackagePath)
|
|
if (-not (Test-Path -LiteralPath $ClientPath -PathType Container)) {
|
|
throw "Client directory was not found: $ClientPath"
|
|
}
|
|
|
|
$runningClients = @(Get-Process Wow -ErrorAction SilentlyContinue | Where-Object {
|
|
$_.Path -and $_.Path.StartsWith($ClientPath, [System.StringComparison]::OrdinalIgnoreCase)
|
|
})
|
|
if ($runningClients.Count) {
|
|
if (-not $StopClient) {
|
|
throw 'Wow.exe is running. Close the client or repeat deployment with -StopClient.'
|
|
}
|
|
|
|
Write-Host 'Stopping the running WoW client...'
|
|
$runningClients | Stop-Process -Force
|
|
Start-Sleep -Seconds 2
|
|
Get-Process WarcraftXLHost -ErrorAction SilentlyContinue | Where-Object {
|
|
$_.Path -and $_.Path.StartsWith($ClientPath, [System.StringComparison]::OrdinalIgnoreCase)
|
|
} | Stop-Process -Force
|
|
}
|
|
|
|
$env:WOW_HOME = $ClientPath
|
|
Write-Host "MoonWell client: $ClientPath"
|
|
Write-Host "Package staging: $PackagePath"
|
|
|
|
Write-Host '[1/5] Initializing WarcraftXL dependencies...'
|
|
& git -C $repoRoot submodule update --init --recursive
|
|
if ($LASTEXITCODE -ne 0) { throw 'Git submodule initialization failed.' }
|
|
|
|
New-Item -ItemType Directory -Path $PackagePath -Force | Out-Null
|
|
|
|
if (-not $SkipDataBuild) {
|
|
Write-Host '[2/5] Building MPQ patches...'
|
|
$tool = Join-Path $repoRoot 'tool\target\release\tool.exe'
|
|
if (-not (Test-Path -LiteralPath $tool -PathType Leaf)) {
|
|
$cargo = Get-Command cargo -ErrorAction SilentlyContinue
|
|
if (-not $cargo) { throw 'Cargo was not found and the MPQ builder is not compiled.' }
|
|
& $cargo.Source build --release --manifest-path (Join-Path $repoRoot 'tool\Cargo.toml')
|
|
if ($LASTEXITCODE -ne 0) { throw 'MPQ builder compilation failed.' }
|
|
}
|
|
|
|
& $tool (Join-Path $repoRoot 'src') $PackagePath
|
|
if ($LASTEXITCODE -ne 0) { throw 'MPQ patch build failed.' }
|
|
} else {
|
|
Write-Host '[2/5] MPQ build skipped.'
|
|
}
|
|
|
|
Write-Host '[3/5] Building and installing WarcraftXL...'
|
|
$buildArguments = @{
|
|
Configuration = $Configuration
|
|
ClientPath = $ClientPath
|
|
PackagePath = $PackagePath
|
|
Deploy = $true
|
|
}
|
|
if ($NativeRenderer) { $buildArguments.NativeRenderer = $true }
|
|
& (Join-Path $repoRoot 'build-warcraftxl.ps1') @buildArguments
|
|
if ($LASTEXITCODE -ne 0) { throw 'WarcraftXL deployment failed.' }
|
|
|
|
Write-Host '[4/5] Synchronizing package files...'
|
|
& robocopy $PackagePath $ClientPath /E /R:2 /W:1 /NFL /NDL /NJH /NJS /NP
|
|
$robocopyExitCode = $LASTEXITCODE
|
|
if ($robocopyExitCode -ge 8) {
|
|
throw "Package synchronization failed with robocopy exit code $robocopyExitCode."
|
|
}
|
|
|
|
if (-not $SkipManifest) {
|
|
Write-Host '[5/5] Building launcher manifest...'
|
|
$python = Get-Command python -ErrorAction SilentlyContinue
|
|
if (-not $python) { throw 'Python was not found; launcher manifest was not generated.' }
|
|
& $python.Source (Join-Path $repoRoot 'build_manifest.py') `
|
|
--dir $PackagePath --output (Join-Path $repoRoot 'manifest.json')
|
|
if ($LASTEXITCODE -ne 0) { throw 'Launcher manifest generation failed.' }
|
|
} else {
|
|
Write-Host '[5/5] Manifest generation skipped.'
|
|
}
|
|
|
|
$wowHash = (Get-FileHash -LiteralPath (Join-Path $ClientPath 'Wow.exe') -Algorithm SHA256).Hash
|
|
$renderer = if ($NativeRenderer) { 'native D3D9 recovery proxy' } else { 'WarcraftXL D3D9On12' }
|
|
Write-Host ''
|
|
Write-Host 'Deployment complete.'
|
|
Write-Host " Renderer: $renderer"
|
|
Write-Host " Wow.exe SHA-256: $wowHash"
|
|
Write-Host " Host: $(Join-Path $ClientPath 'Utils\WarcraftXLHost.exe')"
|
|
|
|
if ($Launch) {
|
|
Write-Host 'Launching Wow.exe...'
|
|
Start-Process -FilePath (Join-Path $ClientPath 'Wow.exe') -WorkingDirectory $ClientPath
|
|
}
|
|
|
|
# robocopy uses successful non-zero exit codes; do not leak one to callers.
|
|
$global:LASTEXITCODE = 0
|