Files
MoonBridge/testing/smoke/local-uranium.ps1
T
layue13andClaude Opus 5.5 afea023bce build: 代理发行包改为单个可运行的 moonbridge.jar
发行包去掉 bin/ 启动脚本和 lib/ 下的 42 个依赖 jar,改为与其他代理服务端一样
用 java -jar moonbridge.jar 启动:
- proxy-core 用 shadow 打出含全部依赖的 moonbridge.jar(合并 META-INF/services,
  清单写入 Main-Class、Multi-Release 与 Enable-Native-Access: ALL-UNNAMED)
- 泄漏检测默认关闭改由 ProxyMain 在加载 Netty 前设置,显式 -D 仍优先
- 移除不再使用的 application 约定插件
- 安装包检查、烟测与基准脚本改用发行包根目录作 classpath;文档同步

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 15:00:14 +08:00

200 lines
9.1 KiB
PowerShell

#Requires -Version 7.0
param(
[Parameter(Mandatory)][string]$BundlePath,
[string]$ProbeClassesPath,
[string]$Java8Path = 'C:\Program Files\Zulu\zulu-8\bin\java.exe',
[switch]$PrismClient,
[string]$PrismInstance = '1.7.10',
[string]$PrismInstanceFolder,
[string]$PrismPath = (Join-Path $env:LOCALAPPDATA 'Programs\PrismLauncher\prismlauncher.exe')
)
$ErrorActionPreference = 'Stop'
if (-not $PrismInstanceFolder) { $PrismInstanceFolder = $PrismInstance }
function IsPrismInstanceProcess([object]$process) {
if (-not $process.CommandLine) { return $false }
$line = $process.CommandLine.Replace('/', '\')
return $line.IndexOf('PrismLauncher', [StringComparison]::OrdinalIgnoreCase) -ge 0 -and
$line.IndexOf("\instances\$PrismInstanceFolder\", [StringComparison]::OrdinalIgnoreCase) -ge 0
}
$repoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
$bundle = (Resolve-Path -LiteralPath $BundlePath).Path
$probeClasses = if ($PrismClient) { $null } else {
if (-not $ProbeClassesPath) { throw 'ProbeClassesPath is required without -PrismClient' }
(Resolve-Path -LiteralPath $ProbeClassesPath).Path
}
$proxyLib = Join-Path $repoRoot 'proxy\core\build\install\moonbridge'
if (-not (Test-Path -LiteralPath $Java8Path) -or -not (Test-Path -LiteralPath $proxyLib)) {
throw 'Java 8 and the installed MoonBridge distribution are required'
}
if ((Get-Content -LiteralPath (Join-Path $bundle 'eula.txt') -Raw).Trim() -ne 'eula=true') {
throw 'The supplied Uranium bundle must already contain eula=true'
}
function FreePort {
$listener = [System.Net.Sockets.TcpListener]::new([System.Net.IPAddress]::Loopback, 0)
$listener.Start()
try { return ([System.Net.IPEndPoint]$listener.LocalEndpoint).Port }
finally { $listener.Stop() }
}
function WaitForPort([int]$port, [System.Diagnostics.Process]$process, [int]$timeoutSeconds) {
$deadline = [DateTime]::UtcNow.AddSeconds($timeoutSeconds)
while ([DateTime]::UtcNow -lt $deadline) {
if ($process.HasExited) { throw "Process exited before port $port opened: $($process.ExitCode)" }
$client = [System.Net.Sockets.TcpClient]::new()
try {
$client.Connect([System.Net.IPAddress]::Loopback, $port)
return
} catch [System.Net.Sockets.SocketException] {
Start-Sleep -Milliseconds 200
} finally { $client.Dispose() }
}
throw "Port $port did not open within $timeoutSeconds seconds"
}
$runDir = Join-Path $repoRoot ('build\local-uranium-proxy-' + [guid]::NewGuid().ToString('N'))
Copy-Item -LiteralPath $bundle -Destination $runDir -Recurse
$serverJar = @(Get-ChildItem -LiteralPath $runDir -Filter '*-server.jar')
if ($serverJar.Count -ne 1) { throw "Expected one Uranium server JAR in $runDir" }
$serverPort = FreePort
$proxyPort = FreePort
while ($proxyPort -eq $serverPort) { $proxyPort = FreePort }
@"
server-port=$serverPort
server-ip=127.0.0.1
online-mode=false
level-name=world
motd=MoonBridge local Uranium smoke
"@ | Set-Content -LiteralPath (Join-Path $runDir 'server.properties') -Encoding utf8
$serverInfo = [System.Diagnostics.ProcessStartInfo]::new()
$serverInfo.FileName = $Java8Path
$serverInfo.WorkingDirectory = $runDir
$serverInfo.UseShellExecute = $false
$serverInfo.CreateNoWindow = $true
$serverInfo.RedirectStandardInput = $true
$serverInfo.RedirectStandardOutput = $true
$serverInfo.RedirectStandardError = $true
foreach ($argument in @('-Xms512m', '-Xmx1024m', '-jar', $serverJar[0].Name, 'nogui')) {
$serverInfo.ArgumentList.Add($argument)
}
$server = [System.Diagnostics.Process]::Start($serverInfo)
$serverOutput = $server.StandardOutput.ReadToEndAsync()
$serverErrors = $server.StandardError.ReadToEndAsync()
$proxy = $null
$initialJavawIds = @()
$clientLaunchAttempted = $false
try {
WaitForPort $serverPort $server 120
$readyLog = Join-Path $runDir 'logs\latest.log'
$readyDeadline = [DateTime]::UtcNow.AddSeconds(120)
while ([DateTime]::UtcNow -lt $readyDeadline) {
if ($server.HasExited) { throw "Uranium exited during startup: $($server.ExitCode)" }
if ((Test-Path -LiteralPath $readyLog) -and
(Select-String -LiteralPath $readyLog -Pattern 'Done \(' -Quiet)) { break }
Start-Sleep -Milliseconds 250
}
if (-not (Test-Path -LiteralPath $readyLog) -or
-not (Select-String -LiteralPath $readyLog -Pattern 'Done \(' -Quiet)) {
throw 'Uranium did not report ready within 120 seconds'
}
$config = Join-Path $runDir 'moonbridge.yml'
@"
listen: "127.0.0.1:$proxyPort"
authentication: OFFLINE
initialRouting:
servers: [uranium]
timeoutSeconds: 15
plugins:
directory: "proxy-plugins"
enabled: {}
backends:
- name: uranium
address: "127.0.0.1:$serverPort"
"@ | Set-Content -LiteralPath $config -Encoding utf8
$java = (Get-Command java.exe -ErrorAction Stop).Source
$classpath = Join-Path $proxyLib '*'
$proxy = Start-Process -FilePath $java -ArgumentList @(
'-cp', ('"{0}"' -f $classpath), 'dev.moonbridge.app.ProxyMain',
'--config', ('"{0}"' -f $config)
) -WindowStyle Hidden -PassThru -RedirectStandardOutput (Join-Path $runDir 'proxy.stdout.log') `
-RedirectStandardError (Join-Path $runDir 'proxy.stderr.log')
WaitForPort $proxyPort $proxy 15
if ($PrismClient) {
if (-not (Test-Path -LiteralPath $PrismPath)) { throw "Prism Launcher not found: $PrismPath" }
$initialJavawIds = @(Get-CimInstance Win32_Process -Filter "Name = 'javaw.exe'" |
Select-Object -ExpandProperty ProcessId)
Start-Process -FilePath $PrismPath -ArgumentList @(
'--launch', $PrismInstance, '--offline', 'PrismSmoke',
'--server', "127.0.0.1:$proxyPort"
) -WindowStyle Hidden | Out-Null
$clientLaunchAttempted = $true
$deadline = [DateTime]::UtcNow.AddSeconds(120)
$serverLog = Join-Path $runDir 'logs\latest.log'
while ([DateTime]::UtcNow -lt $deadline) {
if ((Select-String -LiteralPath $serverLog -Pattern 'PrismSmoke.*logged in' -Quiet)) { break }
if ($proxy.HasExited) { throw "Proxy exited while Prism was connecting: $($proxy.ExitCode)" }
if ($server.HasExited) { throw "Uranium exited while Prism was connecting: $($server.ExitCode)" }
Start-Sleep -Milliseconds 500
}
if (-not (Select-String -LiteralPath $serverLog -Pattern 'PrismSmoke.*logged in' -Quiet)) {
throw 'Prism Forge client did not log into Uranium within 120 seconds'
}
Start-Sleep -Seconds 10
if ((Select-String -LiteralPath $serverLog -Pattern 'PrismSmoke lost connection' -Quiet)) {
throw 'Prism Forge client disconnected during the 10-second hold'
}
$newClient = @(Get-CimInstance Win32_Process -Filter "Name = 'javaw.exe'" |
Where-Object { $_.ProcessId -notin $initialJavawIds -and (IsPrismInstanceProcess $_) })
if ($newClient.Count -ne 1) {
throw "Expected one new Prism Java client, found $($newClient.Count)"
}
Write-Output "REAL_PRISM_URANIUM_PASS serverPort=$serverPort proxyPort=$proxyPort holdSeconds=10"
} else {
$sourceDir = Join-Path $runDir 'probe-src\cc\uraniummc\rfg\smoke'
New-Item -ItemType Directory -Path $sourceDir -Force | Out-Null
$source = Join-Path $sourceDir 'RunThroughProxy.java'
@'
package cc.uraniummc.rfg.smoke;
public final class RunThroughProxy {
public static void main(String[] args) throws Exception {
MinecraftProtocolProbe.run(Integer.parseInt(args[0]));
}
}
'@ | Set-Content -LiteralPath $source -Encoding utf8
$probeOutput = Join-Path $runDir 'probe-classes'
New-Item -ItemType Directory -Path $probeOutput -Force | Out-Null
& javac -cp $probeClasses -d $probeOutput $source
if ($LASTEXITCODE -ne 0) { throw 'Could not compile Uranium protocol probe wrapper' }
& java -cp "$probeOutput;$probeClasses" cc.uraniummc.rfg.smoke.RunThroughProxy $proxyPort
if ($LASTEXITCODE -ne 0) { throw "Protocol probe failed through MoonBridge: $LASTEXITCODE" }
Write-Output "REAL_URANIUM_PROXY_PASS serverPort=$serverPort proxyPort=$proxyPort"
}
} finally {
if ($clientLaunchAttempted) {
Get-CimInstance Win32_Process -Filter "Name = 'javaw.exe'" |
Where-Object { $_.ProcessId -notin $initialJavawIds -and (IsPrismInstanceProcess $_) } |
ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
}
if ($proxy -and -not $proxy.HasExited) {
Stop-Process -Id $proxy.Id -Force
Wait-Process -Id $proxy.Id -ErrorAction SilentlyContinue
}
if (-not $server.HasExited) {
$server.StandardInput.WriteLine('stop')
$server.StandardInput.Flush()
if (-not $server.WaitForExit(30000)) {
$server.Kill()
$server.WaitForExit()
}
}
$serverOutput.GetAwaiter().GetResult() | Set-Content -LiteralPath (Join-Path $runDir 'server.stdout.log')
$serverErrors.GetAwaiter().GetResult() | Set-Content -LiteralPath (Join-Path $runDir 'server.stderr.log')
Write-Output "Runtime logs: $runDir"
}