<# .SYNOPSIS Copies overlay/ into a ServUO server root. .DESCRIPTION overlay/ mirrors the server root exactly, so deployment is a straight file copy. Nothing is deleted from the server; this only adds or overwrites. Run with -Verify first. It reports what would change and touches nothing. .EXAMPLE .\deploy.ps1 -ServerPath C:\Users\colby\Desktop\servuo -Verify .\deploy.ps1 -ServerPath C:\Users\colby\Desktop\servuo #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string] $ServerPath, [switch] $Verify ) $ErrorActionPreference = 'Stop' $overlay = Join-Path $PSScriptRoot 'overlay' if (-not (Test-Path $overlay)) { throw "overlay/ not found next to deploy.ps1" } if (-not (Test-Path $ServerPath)) { throw "server path not found: $ServerPath" } # ServUO.exe holds a lock on Scripts.dll and writes Saves/ on exit. Never deploy under it. if (Get-Process -Name ServUO -ErrorAction SilentlyContinue) { throw "ServUO is running. Stop it before deploying." } function Get-Sha([string] $path) { if (-not (Test-Path $path)) { return $null } return (Get-FileHash $path -Algorithm SHA256).Hash } $added = 0; $changed = 0; $same = 0 Get-ChildItem $overlay -Recurse -File | ForEach-Object { $rel = $_.FullName.Substring($overlay.Length + 1) $dst = Join-Path $ServerPath $rel $srcHash = Get-Sha $_.FullName $dstHash = Get-Sha $dst if ($null -eq $dstHash) { $state = 'ADD '; $added++ } elseif ($srcHash -ne $dstHash) { $state = 'CHANGE '; $changed++ } else { $state = 'same '; $same++ } if ($state -ne 'same ') { Write-Output "$state $rel" } if (-not $Verify -and $state -ne 'same ') { $parent = Split-Path $dst -Parent if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Force -Path $parent | Out-Null } Copy-Item $_.FullName -Destination $dst -Force } } Write-Output "" if ($Verify) { Write-Output "VERIFY only. add=$added change=$changed unchanged=$same (nothing written)" } else { Write-Output "deployed. add=$added change=$changed unchanged=$same" Write-Output "" Write-Output "Scripts.csproj changed => next boot rebuilds Scripts.dll (Compiler.cfg Dynamic=True)." }