Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d8aa4a029 | ||
|
|
1cf0032927 |
No files matched your search
@@ -68,7 +68,7 @@ More for players (Steam and non-Steam): [docs/PLAYERS.md](docs/PLAYERS.md).
|
||||
|
||||
- **Setup stopped with an error.** Fix what it says (usually the internet connection) and run it again. It continues where it stopped.
|
||||
- **Friends can't connect, but you can.** On Windows, run `cs.cmd` → 10 → 1 and accept the admin prompt so the firewall lets them in. If they're not in your house, check the playit tunnel or the port forward.
|
||||
- **"Unable to initialize Steam" (Windows).** Start the server from `cs.cmd`, not by opening `hlds.exe` directly.
|
||||
- **"Unable to initialize Steam" (Windows).** This can happen once, on the first start after installing; `cs.cmd` and setup retry by themselves. If you started `hlds.exe` yourself, close the box and start the server with `cs.cmd` → 9.
|
||||
- **The server window closes right away, or setup says files are missing.** Your antivirus probably removed a file. Allow the install folder in it and run `setup.cmd` again.
|
||||
- **The port is taken.** Setup offers the next free port. Your friends then need that port in the address.
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ The same stack, native instead of Docker: the win32 builds of every part, `hlds.
|
||||
|
||||
Things that differ from Linux:
|
||||
|
||||
- **Steam installed on the same PC.** The server's `steam_api.dll` finds the Steam client's `steamclient.dll` through `HKCU\Software\Valve\Steam\ActiveProcess\SteamClientDll` and loads that instead of its own, which ends in "Unable to initialize Steam". `Start-CsServer` renames that value until the server answers queries (a few seconds), then puts it back. Steam rewrites it at every start anyway, and every script repairs it on load if a start was interrupted.
|
||||
- **First start after an install.** The server's Steam part sets itself up on its first run (`hlds\appcache`, `hlds\config`) and the server stops with a "Fatal error: Unable to initialize Steam" box. Every start after that works, with or without the Steam client running. `Start-CsServer` notices that box (window title "Fatal error"), closes the server and starts it once more.
|
||||
- **Firewall.** Setup adds an allow rule for `hlds\hlds.exe` on all network types (admin prompt) before the first start, so Windows' own popup doesn't appear, and removes block rules Windows made if that popup was ever cancelled. Normal users often can't read firewall rules, so the result is remembered in `secrets\firewall-rule.txt`.
|
||||
- **Install folder.** `Documents\cs16`, or `%USERPROFILE%\cs16` when Documents is synced by OneDrive, or `C:\cs16` when the user folder has non-ASCII characters (SteamCMD and HLDS can't handle them). The folder is remembered in `%LOCALAPPDATA%\cs16-dm-server\install-folder.txt`, so running a newly downloaded `setup.cmd` updates the existing install.
|
||||
- **Console log.** `-condebug` writes `hlds\qconsole.log`; setup shows its end when the server doesn't come up.
|
||||
|
||||
+44
-20
@@ -334,31 +334,55 @@ function Start-CsServer($root) {
|
||||
$y = $y -replace '(?m)^yb_difficulty ".*"', ('yb_difficulty "' + [int]$s.CS_BOT_DIFFICULTY + '"')
|
||||
Write-TextFile $ycfg $y
|
||||
$hargs = "-console -condebug -game cstrike -port $([int]$s.CS_PORT) +maxplayers $([int]$s.CS_MAXPLAYERS) +map $($s.CS_MAP) +log on"
|
||||
Restore-SteamClientSetting
|
||||
# With Steam installed, the server's steam_api.dll loads the Steam client's steamclient.dll
|
||||
# (found through this registry value) instead of its own, and stops with "Unable to initialize
|
||||
# Steam". So the value is hidden until the server answers queries (Steam is set up by then:
|
||||
# a few seconds) or gives up. Steam writes it again at every start, and
|
||||
# Restore-SteamClientSetting (run whenever a script loads this file) repairs an interrupted run.
|
||||
# (A 64-bit PowerShell can't see the 32-bit server's DLLs, so the query is the signal.)
|
||||
$hidden = $false
|
||||
if ((Get-ItemProperty -Path $Script:SteamKey -ErrorAction SilentlyContinue).SteamClientDll) {
|
||||
Rename-ItemProperty -Path $Script:SteamKey -Name SteamClientDll -NewName $Script:SteamHidden
|
||||
$hidden = $true
|
||||
}
|
||||
try {
|
||||
# On the first start after an install, the server's Steam part sets itself up and the server
|
||||
# stops with a "Fatal error: Unable to initialize Steam" box. A new start works, so that box
|
||||
# gets the server closed and started again.
|
||||
for ($try = 1; $try -le 3; $try++) {
|
||||
$p = Start-Process -FilePath (Join-Path $h 'hlds.exe') -WorkingDirectory $h -ArgumentList $hargs -PassThru
|
||||
if ($hidden) {
|
||||
$end = (Get-Date).AddSeconds(90)
|
||||
while ((Get-Date) -lt $end -and -not $p.HasExited) {
|
||||
if (Get-A2SInfo '127.0.0.1' ([int]$s.CS_PORT) 1000) { break }
|
||||
Start-Sleep -Milliseconds 500
|
||||
if (-not (Test-SteamFailure $p ([int]$s.CS_PORT))) { break }
|
||||
Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue
|
||||
Start-Sleep -Seconds 2
|
||||
Write-Host " (Steam wasn't ready yet, starting again)"
|
||||
}
|
||||
}
|
||||
} finally { if ($hidden) { Restore-SteamClientSetting } }
|
||||
return $true
|
||||
}
|
||||
|
||||
# Waits up to 40 s for the server to answer or to show its "Fatal error" box.
|
||||
# Returns $true for that box.
|
||||
function Test-SteamFailure($p, [int]$port) {
|
||||
$end = (Get-Date).AddSeconds(40)
|
||||
while ((Get-Date) -lt $end -and -not $p.HasExited) {
|
||||
if (Get-A2SInfo '127.0.0.1' $port 1000) { return $false }
|
||||
if (@(Get-ProcessWindowTitles $p.Id | Where-Object { $_ -like 'Fatal error*' }).Count) { return $true }
|
||||
Start-Sleep -Milliseconds 500
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
# Titles of all top-level windows of a process (the error box is not always its main window)
|
||||
function Get-ProcessWindowTitles([int]$processId) {
|
||||
if (-not ('Cs16Win' -as [type])) {
|
||||
Add-Type @'
|
||||
using System; using System.Text; using System.Collections.Generic; using System.Runtime.InteropServices;
|
||||
public static class Cs16Win {
|
||||
delegate bool EnumProc(IntPtr h, IntPtr l);
|
||||
[DllImport("user32.dll")] static extern bool EnumWindows(EnumProc f, IntPtr l);
|
||||
[DllImport("user32.dll")] static extern int GetWindowThreadProcessId(IntPtr h, out int pid);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)] static extern int GetWindowText(IntPtr h, StringBuilder s, int n);
|
||||
public static string[] Titles(int want) {
|
||||
var r = new List<string>();
|
||||
EnumWindows((h, l) => { int pid; GetWindowThreadProcessId(h, out pid);
|
||||
if (pid == want) { var t = new StringBuilder(256); GetWindowText(h, t, 256); r.Add(t.ToString()); } return true; }, IntPtr.Zero);
|
||||
return r.ToArray();
|
||||
}
|
||||
}
|
||||
'@
|
||||
}
|
||||
[Cs16Win]::Titles($processId)
|
||||
}
|
||||
|
||||
# An earlier version (2026-10-15) hid this Steam setting while starting the server; this puts it
|
||||
# back if a start was interrupted then. Harmless otherwise.
|
||||
$Script:SteamKey = 'HKCU:\Software\Valve\Steam\ActiveProcess'
|
||||
$Script:SteamHidden = 'SteamClientDll_hidden_by_cs16'
|
||||
|
||||
|
||||
Reference in new issue
Block a user