Windows version: host the server from your own PC
setup.cmd installs the same DM/GunGame server natively on Windows 10/11 (no Docker or Python) into Documents\cs16, then helps set up how friends join (LAN, playit.gg, port forwarding, VPN). cs.cmd is the menu. Also: setup falls back to backup copies of the freely licensed mod downloads on this Gitea when a main site is down (tools/make-mirror.sh fills them), and the README is rewritten as a plain guide. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
7e9cbee14d
commit
4b7fdcaa23
16 files changed
+1412
-72
No files matched your search
+123
@@ -0,0 +1,123 @@
|
||||
# Control menu for Windows: double-click cs.cmd (pick a number)
|
||||
# or directly: cs.cmd status | start | stop | restart | map <name> | mode dm|gg | bots <n> | kills
|
||||
# | say <text> | join | console | update
|
||||
param([Parameter(ValueFromRemainingArguments = $true)][string[]]$Cmd)
|
||||
. (Join-Path $PSScriptRoot 'common.ps1')
|
||||
trap { Write-Host "error: $($_.Exception.Message)" -ForegroundColor Red; exit 1 }
|
||||
|
||||
$Root = Split-Path -Parent $PSScriptRoot
|
||||
$settingsFile = Join-Path $Root 'settings.txt'
|
||||
if (-not (Test-Path -LiteralPath $settingsFile)) { throw 'not set up yet: double-click setup.cmd first' }
|
||||
$H = Join-Path $Root 'hlds'; $C = Join-Path $H 'cstrike'
|
||||
|
||||
function Port { [int](Read-Settings $settingsFile).CS_PORT }
|
||||
function Rcon($command) { Invoke-Rcon (Port) (Get-RconPassword $Root) $command }
|
||||
function Answered($reply) { -not $reply.StartsWith('(no answer') }
|
||||
|
||||
function Show-Status {
|
||||
if (-not (Get-ServerProcess $H)) { Write-Host ' server is stopped (start it: 9)'; return }
|
||||
$i = Get-A2SInfo '127.0.0.1' (Port) 2000
|
||||
if ($i) { Write-Host " $(Format-A2SInfo $i)" } else { Write-Host ' server window open, not answering yet (starting or changing map?)' }
|
||||
Write-Host " mode: $(Get-ServerMode $Root)"
|
||||
}
|
||||
function Show-Players {
|
||||
Show-Status
|
||||
if (Get-ServerProcess $H) { (Rcon 'status') -split "`n" | Where-Object { $_ -match '^(#|map|players)' } | ForEach-Object { Write-Host " $_" } }
|
||||
}
|
||||
function Set-Map($m) {
|
||||
$maps = @(Get-ChildItem -LiteralPath "$C\maps" -Filter *.bsp -ErrorAction SilentlyContinue | ForEach-Object { $_.BaseName } | Sort-Object)
|
||||
if (-not $m) {
|
||||
Write-Host ' Maps on this server:'
|
||||
for ($i = 0; $i -lt $maps.Count; $i++) { Write-Host (' {0,3}) {1}' -f ($i + 1), $maps[$i]) }
|
||||
$m = (Read-Host ' map name or number').Trim()
|
||||
if ($m -match '^\d+$' -and [int]$m -ge 1 -and [int]$m -le $maps.Count) { $m = $maps[[int]$m - 1] }
|
||||
}
|
||||
if (-not $m) { return }
|
||||
if ($maps -notcontains $m) { Write-Host " no map called '$m' in $C\maps"; return }
|
||||
$r = Rcon "changelevel $m"
|
||||
if (Answered $r) { Write-Host " changing to $m" } else { Write-Host " $r" }
|
||||
}
|
||||
function Set-Mode($m) {
|
||||
if (-not $m) { $m = (Read-Host ' mode: dm = deathmatch, gg = GunGame').Trim() }
|
||||
if ($m -ne 'dm' -and $m -ne 'gg') { Write-Host ' use dm or gg'; return }
|
||||
$r = Rcon "esef_mode $m"
|
||||
if (Answered $r) { ($r -split "`n" | Where-Object { $_ -match 'esef_mode' }) | ForEach-Object { Write-Host " $_" } } else { Write-Host " $r" }
|
||||
}
|
||||
function Set-Bots($n) {
|
||||
$s = Read-Settings $settingsFile
|
||||
if (-not $n) { $n = (Read-Host " fill the server up to how many players with bots? (0 = no bots, now $($s.CS_BOTS))").Trim() }
|
||||
if ($n -notmatch '^\d+$') { Write-Host ' give a number'; return }
|
||||
Write-Setting $settingsFile 'CS_BOTS' $n # remembered for the next start
|
||||
$r = Rcon "yb_quota $n"
|
||||
if (Answered $r) { Write-Host " bots: up to $n players (saved)" } else { Write-Host " saved, applies when the server runs" }
|
||||
}
|
||||
function Show-Kills {
|
||||
$t = Update-KillTally "$C\logs" (Join-Path $Root 'kills-tally.json')
|
||||
Write-Host ''
|
||||
Write-Host (' ALL-TIME KILLS: {0:N0} ({1} days of carnage, {2} maps played)' -f $t.Total, $t.Days.Count, $t.Maps)
|
||||
Write-Host ''; Write-Host ' top fraggers:'
|
||||
$i = 0
|
||||
foreach ($e in ($t.Who.GetEnumerator() | Sort-Object Value -Descending | Select-Object -First 5)) { $i++; Write-Host (' {0}. {1,-18} {2:N0}' -f $i, $e.Key, $e.Value) }
|
||||
Write-Host ''; Write-Host ' weapons of choice:'
|
||||
foreach ($e in ($t.Weapons.GetEnumerator() | Sort-Object Value -Descending | Select-Object -First 5)) { Write-Host (' {0,-18} {1:N0}' -f $e.Key, $e.Value) }
|
||||
}
|
||||
function Start-Server {
|
||||
if (Start-CsServer $Root) {
|
||||
Write-Host -NoNewline ' starting'
|
||||
$i = Wait-CsServer (Port) 60
|
||||
Write-Host ''
|
||||
if ($i) { Write-Host " up: $(Format-A2SInfo $i)" } else { Write-Host ' no answer after 60 s, last lines:'; Get-ConsoleTail $Root 20 | ForEach-Object { Write-Host " $_" } }
|
||||
}
|
||||
}
|
||||
function Stop-Server { if (Stop-CsServer $Root) { Write-Host ' stopped' } else { Write-Host ' the server is not running' } }
|
||||
function Open-Console {
|
||||
Write-Host ' CS 1.6 console: status, changelevel de_nuke, yb_quota 6, esef_mode gg, say hi. Empty line or exit to leave.'
|
||||
while ($true) {
|
||||
$l = (Read-Host 'cs16').Trim()
|
||||
if ($l -eq '' -or $l -eq 'exit' -or $l -eq 'quit') { break }
|
||||
Write-Host (Rcon $l)
|
||||
}
|
||||
}
|
||||
|
||||
function Run($choice, $rest) {
|
||||
switch ($choice) {
|
||||
{ $_ -in 'status', '1' } { Show-Players }
|
||||
{ $_ -in 'map', '2' } { Set-Map $rest }
|
||||
{ $_ -in 'mode', '3' } { Set-Mode $rest }
|
||||
{ $_ -in 'bots', '4' } { Set-Bots $rest }
|
||||
{ $_ -in 'kills', '5' } { Show-Kills }
|
||||
{ $_ -in 'say', '6' } {
|
||||
$t = $rest; if (-not $t) { $t = (Read-Host ' message').Trim() }
|
||||
if ($t) { [void](Rcon "say $t"); Write-Host ' sent' }
|
||||
}
|
||||
{ $_ -in 'restart', '7' } { [void](Stop-CsServer $Root); Start-Server }
|
||||
{ $_ -in 'stop', '8' } { Stop-Server }
|
||||
{ $_ -in 'start', '9' } { Start-Server }
|
||||
{ $_ -in 'join', '10' } { & (Join-Path $PSScriptRoot 'join.ps1') -Root $Root }
|
||||
{ $_ -in 'console', '11' } { Open-Console }
|
||||
{ $_ -in 'update', '12' } { & (Join-Path $PSScriptRoot 'setup.ps1') -Yes -Update }
|
||||
default { Write-Host " unknown: $choice" }
|
||||
}
|
||||
}
|
||||
|
||||
if ($Cmd.Count -gt 0) { Run $Cmd[0] (($Cmd | Select-Object -Skip 1) -join ' '); exit 0 }
|
||||
|
||||
while ($true) {
|
||||
$s = Read-Settings $settingsFile
|
||||
Write-Host ''
|
||||
Write-Host "== $($s.CS_HOSTNAME) == (UDP $($s.CS_PORT))" -ForegroundColor Cyan
|
||||
Show-Status
|
||||
Write-Host @'
|
||||
|
||||
1) who's playing 7) restart server
|
||||
2) change map 8) stop server
|
||||
3) game mode (DM / GG) 9) start server
|
||||
4) bots 10) how friends join
|
||||
5) kill counter 11) console (type server commands)
|
||||
6) message to players 12) update game + mods
|
||||
0) quit
|
||||
'@
|
||||
$choice = (Read-Host '>').Trim()
|
||||
if ($choice -eq '' -or $choice -eq '0' -or $choice -eq 'q') { break }
|
||||
Run $choice ''
|
||||
}
|
||||
Reference in new issue
Block a user