# Runs the server and the client together, in the session that starts it. # # tools\watch-game.ps1 [-Port 25599] [-User Player] [-ServerOnly] # # The point of the script is a remote desktop: the game window appears on the # desktop of whoever runs the script, so the game can be watched as it is # played. The server gets its own console window, so its log is visible too. # # ASCII only: PowerShell 5.1 reads a .ps1 without a byte order mark using the # system ANSI code page. param( [int]$Port = 25599, [string]$User = 'Player', [switch]$ServerOnly, [switch]$Fresh ) $ErrorActionPreference = 'Stop' $Root = Split-Path -Parent $PSScriptRoot if (-not $Root) { $Root = 'G:\RustNotMC' } $LogDir = Join-Path $Root 'logs' New-Item -ItemType Directory -Force -Path $LogDir | Out-Null $ServerLog = Join-Path $LogDir 'server.log' $ClientLog = Join-Path $LogDir 'client.log' # the classpath of the server: the protocol, the accounts, the plugins and the # server itself $serverCp = @( (Join-Path $Root 'rsx-protocol\build\classes') (Join-Path $Root 'rsx-auth\build\classes') (Join-Path $Root 'rsx-plugin-api\build\classes') (Join-Path $Root 'rsx-server-core\build\classes') ) -join ';' # the old server goes first, and only the one that holds the port $line = netstat -ano | Select-String ":$Port" | Select-String 'LISTENING' | Select-Object -First 1 if ($line) { Write-Host "stopping the old server on $Port" Stop-Process -Id (($line -split '\s+')[-1]) -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 2 } $tokenFile = Join-Path $Root 'rsx-server-core\world\dev-token.txt' # The server makes a new secret every time it starts, so the token of the # last run is of no use to it. It has to go, or the client will be given a # token the server does not know and will be turned away at the door. if (Test-Path $tokenFile) { Remove-Item $tokenFile -Force } Write-Host 'starting the server' # The server runs in its own visible console window, so the log lies in view # and whoever is sitting at the machine can speak to it: type list, say, # op, deop, kick, ban, unban, save or stop and press Enter there. $java = 'D:\jdk-21\bin\java.exe' if (-not (Test-Path $java)) { $java = (Get-Command java).Source } $serverCommand = "& '$java' -cp '$serverCp' net.rustnotmc.server.ServerMain" + " --port $Port" + " --accounts '$(Join-Path $Root 'rsx-server-core\accounts.txt')'" + " --world '$(Join-Path $Root 'rsx-server-core\world')'" + " --dev-token $User" + " --bind 127.0.0.1" + " *>&1 | Tee-Object -FilePath '$ServerLog'" $server = Start-Process -FilePath 'powershell.exe' -ArgumentList @( '-NoExit', '-ExecutionPolicy', 'Bypass', '-Command', $serverCommand ) -PassThru Write-Host "server window pid $($server.Id), log $ServerLog" # The server writes its own token, and the client needs it. The file has to be # the one this run wrote, not the one of the run before. $token = $null $started = Get-Date for ($i = 0; $i -lt 60; $i++) { Start-Sleep -Milliseconds 500 if (Test-Path $tokenFile) { $written = (Get-Item $tokenFile).LastWriteTime if ($written -lt $started) { continue } $token = (Get-Content $tokenFile -Raw).Trim() if ($token) { break } } } if (-not $token) { Write-Host 'the server did not write its token - look at the server log' exit 1 } Write-Host "token ready for $User" if ($ServerOnly) { Write-Host 'server only, the client is not started. Ctrl+C stops nothing here.' while ($true) { Start-Sleep -Seconds 5 } } Write-Host 'starting the client' $runGame = Join-Path $Root 'rsx-client\scripts\run-game.ps1' $clientArgs = @('-NoExit', '-Command', "& '$runGame' -Token '$token'") Start-Process -FilePath 'powershell.exe' -ArgumentList $clientArgs -PassThru | Out-Null Write-Host 'the client is starting in its own window' Write-Host "the client log is in $ClientLog" # stay alive while the server window does; the game has its own window and # its own life while ($true) { Start-Sleep -Seconds 5 if ($server.HasExited) { Write-Host 'the server window has closed' break } }