# rojo-guard.ps1 -- keep Rojo alive for Tokyo Wangan Racing. # Idempotent: starts Rojo only if it is not already listening on 34872. # Safe to run every few minutes from Task Scheduler. $ErrorActionPreference = "SilentlyContinue" $repo = Join-Path $env:USERPROFILE "roblox\tokyo-wangan-racing" $exe = Join-Path $env:USERPROFILE ".local\bin\rojo.exe" $port = 34872 $log = Join-Path $env:USERPROFILE "rojo-guard.log" function Log($m) { "$(Get-Date -f 'yyyy-MM-dd HH:mm:ss') $m" | Add-Content $log } # Is something already LISTENING on the port? $listening = netstat -ano | Select-String ":$port\s.*LISTENING" if ($listening) { $ownerPid = ($listening[0] -split "\s+")[-1] $owner = (Get-Process -Id $ownerPid).ProcessName if ($owner -eq "rojo") { exit 0 } # healthy, nothing to do Log "PORT HIJACKED by '$owner' (pid $ownerPid) -- not starting. Kill it first." exit 1 # sshd tunnel or similar: do NOT mask it } # Dependencies must exist or rojo exits instantly. if (-not (Test-Path (Join-Path $repo "ServerPackages"))) { Log "ServerPackages MISSING -- rojo would exit on startup. Run 'wally install'." exit 1 } # Launch DETACHED via Task Scheduler. # Do NOT use Start-Process here: if this script is ever invoked over SSH, # Windows OpenSSH kills the whole process tree on session exit and rojo dies # seconds later. schtasks hands ownership to the scheduler, which survives. schtasks /Run /TN "RojoTWR" | Out-Null Start-Sleep -Seconds 4 if (Get-Process rojo -EA SilentlyContinue) { Log "started rojo on $port" } else { Log "FAILED to start rojo" }