Skip to content

feat(csgoserver): support the standalone CS:GO client (App ID 4465480) with configurable clientappid and the NoLobbyReservation mod - #4963

Merged
dgibbs64 merged 3 commits into
GameServerManagers:developfrom
borzaka:feat/support-standalone-csgo-client
Oct 3, 2026
Merged

dgibbs64 merged 3 commits into
GameServerManagers:developfrom
borzaka:feat/support-standalone-csgo-client

Conversation

@borzaka

@borzaka borzaka commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Description

Valve re-released Counter-Strike: Global Offensive as a standalone Steam app (App ID 4465480) in March 2026. The dedicated server is still downloaded with App ID 740, but the standalone client only connects when the server runs with App ID 4465480 and the NoLobbyReservation SourceMod plugin is loaded. This PR adds that support to csgoserver using the existing LinuxGSM fix and mod mechanisms.

Runtime App ID

  • New runtimeappid="4465480" setting in csgoserver/_default.cfg (730 keeps CS2 csgo_legacy branch clients). appid="740" stays the SteamCMD download App ID.
  • fix_csgo.sh writes runtimeappid into steam_appid.txt and csgo/steam.inf (appID=) before every start, so values reverted by SteamCMD update/validate are restored. The fix is idempotent, keeps the CRLF line endings of steam.inf, reports write errors and ignores the trailing NUL byte the server writes into steam_appid.txt.
  • GSLT: the config comment and the install prompt (install_gslt.sh) state that the token must be created using the App ID set in runtimeappid.

Mods

  • New nolobbyreservation mod (eldoradoel fork, required for standalone clients to connect), listed right after SourceMod. It is installed into csgo like other mods (modsubdirs="NoLobbyReservation-master/csgo").
  • The repository only ships the .sp source. fn_mod_compile_sourcemod_plugin compiles it with the installed SourceMod spcomp into the staged mod files before the file list is built, so the .smx is installed, updated and removed with the mod. A compile failure aborts the install.
  • mods-install requires SourceMod first (fn_mod_exist "sourcemod", same as AMX Mod X requiring Metamod). mods-update recompiles the plugin.
  • modsubdirs now also accepts a path; single-level values behave as before.
  • mods-remove nolobbyreservation keeps SourceMod's shared directories, including gamedata.
  • SourceMod is pinned to 1.12 for CS:GO (1.13 does not work with CS:GO, see SourceMod Required Versions Wiki). Other games keep 1.13.

Mods are not installed automatically. Install order: metamodsource → sourcemod → nolobbyreservation.

Known limitation (pre-existing): with updateonstart enabled, if SteamCMD rewrites steam.inf during the update-on-start, the runtime App ID is restored on the next start. This applies to all pre-start fixes (e.g. the existing libgcc fix).

Fixes #4883

Type of change

  • Bug fix (a change which fixes an issue).
  • New feature (a change which adds functionality).
  • New Server (new server added).
  • Refactor (restructures existing code).
  • Comment update (typo, spelling, explanation, examples, etc).

Testing

Please list the exact validation you performed and the outcome.

  • Commands/tests run:
    • ./csgoserver install (SteamCMD download of App ID 740, GSLT prompt)
    • ./csgoserver mods-install: metamodsource, sourcemod, nolobbyreservation
    • ./csgoserver start
    • meta list, sm plugins list, client connection, update, validate
  • Result:
    • SourceMod 1.13 current dev build does not work with CS:GO, SourceMod 1.12 works, so CS:GO is pinned to SourceMod 1.12.
    • After start, steam_appid.txt contains 4465480. The server rewrites the file as 4465480\n\0; the trailing NUL byte caused a Bash warning (ignored null byte in input) in fix_csgo.sh, fixed by stripping NUL bytes before comparing.
    • The original csgo/steam.inf from the App ID 740 depot uses CRLF line endings and appID=730; the fix replaces only the value and keeps the line ending.
    • meta list
  Listing 3 plugins:
  [01] SourceMod (1.12.0.7253) by AlliedModders LLC
  [02] CS Tools (1.12.0.7253) by AlliedModders LLC
  [03] SDK Tools (1.12.0.7253) by AlliedModders LLC
  • sm plugins list
[SM] Listing 18 plugins:
  ...
  16 "No Lobby Reservation" (0.0.2) by vanz
  ...
  • successful client connection
  • after update/validate and restart, still successful client connection
  • Environment used (distro/version): Debian 12.15 (bookworm)

Risk and rollback

  • Risk level: medium
  • Rollback plan: set runtimeappid="730" in common.cfg to restore the previous runtime App ID (and keep using the existing App ID 730 GSLT). Remove the plugin with ./csgoserver mods-remove (nolobbyreservation).

Breaking changes

  • No breaking changes.

  • Breaking changes included (describe below).

  • Existing csgoserver instances switch to runtime App ID 4465480 on the next start after update-lgsm. GSLTs created for App ID 730 must be replaced with a GSLT created for App ID 4465480. CS2 csgo_legacy branch (App ID 730) clients can no longer connect unless runtimeappid="730" is set (in common.cfg, as all instances share serverfiles).

  • SourceMod for CS:GO is now 1.12. Instances that already have SourceMod 1.13 installed should run mods-remove (sourcemod), mods-install (sourcemod), then mods-update to recompile NoLobbyReservation.

Documentation impact

  • No documentation update required.
  • User documentation update required.
  • Developer documentation update required.

Checklist

PR will not be merged until all steps are complete.

  • This pull request links to an issue.
  • This pull request uses the develop branch as its base.
  • This pull request subject follows the Conventional Commits standard.
  • This code follows the style guidelines of this project.
  • I have performed a self-review of my code.
  • I have provided a detailed enough description of this PR.

Documentation

Thank you for your Pull Request!

…) with configurable runtimeappid and the NoLobbyReservation mod
@borzaka

borzaka commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor Author

The new client's store page: https://store.steampowered.com/app/4465480/CounterStrikeGlobal_Offensive/

  • The main reason to move server support toward AppID 4465480 is that it is the new standalone CS:GO release, and the community is already adopting it for dedicated servers. Current community setup guides use the existing AppID 740 server files but configure the running server/GSLT around 4465480.
  • It also provides a much cleaner user experience: CS2 and CS:GO can be installed side-by-side as separate Steam applications, so players no longer need to switch CS2 back and forth to the csgo_legacy beta branch just to play CS:GO.
  • Supporting 4465480 therefore aligns LinuxGSM with the direction the CS:GO community is moving toward, while support for the older 730 csgo_legacy client can potentially remain as a compatibility option. There are already community configurations that allow both the standalone 4465480 client and CS2's 730 legacy branch to connect to the same server.
                         CS:GO server binaries
                                  │
                         SteamCMD AppID 740
                                  │
                    ┌─────────────┴─────────────┐
                    │                           │
            Runtime identity 730       Runtime identity 4465480
                    │                           │
            GSLT created for 730       GSLT created for 4465480
                    │                           │
        730 csgo_legacy client       4465480 standalone client

@github-actions github-actions Bot added engine: source engine: source2 Issues related to source2 engine game: Counter-Strike: Global Offensive Issues related to Counter-Strike: Global Offensive game: Counter-Strike 2 Issues related to Counter-Strike 2 labels Oct 2, 2026
dgibbs64 and others added 2 commits October 3, 2026 22:07
…rvation, prefer spcomp64

- Rename runtimeappid to clientappid and reword the comments: appid is
  the SteamCMD download ID (740), clientappid is the App ID the server
  advertises and players' clients connect with (4465480 or 730).
- Pin NoLobbyReservation to commit 003ab19f. It has no releases and is
  compiled from source on install, so do not follow master.
- Prefer spcomp64 and fall back to spcomp, so compiling does not rely
  on i386 libraries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dgibbs64 dgibbs64 changed the title feat(csgoserver): support the standalone CS:GO client (App ID 4465480) with configurable runtimeappid and the NoLobbyReservation mod feat(csgoserver): support the standalone CS:GO client (App ID 4465480) with configurable clientappid and the NoLobbyReservation mod Oct 3, 2026
@dgibbs64

dgibbs64 commented Oct 3, 2026

Copy link
Copy Markdown
Member

Thanks @borzaka, this is a solid piece of work and the explanation above helped a lot. I've pushed a merge of develop (it conflicted with #4961 in mods_list.sh) and a follow-up commit to your branch:

  1. runtimeappid is now clientappid. Having two settings both called "App ID" was the confusing part, so the name now says what it controls: the App ID that players' clients connect with. I reworded the config comments to separate the two:
    • appid="740": the App ID SteamCMD downloads the server files from. Do not change.
    • clientappid="4465480": the App ID the server advertises. Only clients of this App ID can connect, and the GSLT must be created for it. Options: 4465480 standalone CS:GO, 730 CS2 csgo_legacy, "" leaves steam_appid.txt/steam.inf unmanaged.
  2. NoLobbyReservation is pinned to commit 003ab19f instead of master. The repo has no releases or licence, hasn't changed since 2023, and gets compiled and loaded into the server, so pinning means a future push can't change what LinuxGSM installs.
  3. spcomp64 is preferred, falling back to spcomp, so compiling doesn't depend on i386 libraries.

What I tested:

  • fix_csgo.sh with a trailing NUL in steam_appid.txt and CRLF steam.inf: rewrites to 4465480, keeps all line endings, does nothing on the next start, switches back to 730, recreates a missing file, and does nothing when clientappid is empty.
  • The NoLobbyReservation install path using the real fn_mod_install_files and fn_mod_compile_sourcemod_plugin with SourceMod 1.12: the pinned archive downloads, the nested modsubdirs path extracts correctly, and nolobbyreservation.smx compiles with spcomp64.

One question: you mentioned community configurations that let both the 4465480 and 730 clients connect to the same server. Do you have a link? For now the docs will say one client type per server, and I'd like to mention the other option if it's reliable.

I'm also adding a docs section explaining appid vs clientappid and the GSLT requirement, plus a release note for existing servers. After update-lgsm they switch to 4465480, so admins serving csgo_legacy players or holding a 730 GSLT need to act.

@dgibbs64 dgibbs64 added this to the v26.3.0 milestone Oct 3, 2026
@dgibbs64
dgibbs64 enabled auto-merge (squash) October 3, 2026 21:15
@dgibbs64
dgibbs64 merged commit 22f84b3 into GameServerManagers:develop Oct 3, 2026
4 of 5 checks passed
@dgibbs64 dgibbs64 mentioned this pull request Oct 3, 2026
@borzaka

borzaka commented Oct 4, 2026

Copy link
Copy Markdown
Contributor Author

Thx @dgibbs64 😊 !

These are the sources I found; I haven't tested them myself:

  • eonexdev/csgo-sv-fix-engine: a SourceMod extension (csgo_steamfix.ext.so / .dll + .autoload) that patches the engine at runtime so auth tickets issued for a different App ID ("Client connected with ticket for the wrong game") are accepted. The server stays on App ID 730 with a 730 GSLT.
  • FNScence/CSGO-Legacy-Server and the Steam guide based on it (Windows setup, March 2026) use that extension ("CSGOEngineFix") together with NoLobbyReservation, and state that players can join from both the standalone app and the CS2 csgo_legacy branch.

Caveats: the extension is binary-only (no source, no licence), the repo was created in March 2026 and hasn't changed since, and it effectively disables the App ID check on client auth tickets. So I'd document "one client type per server" as the supported setup and, if at all, mention this only as an unofficial community workaround.

dgibbs64 added a commit that referenced this pull request Oct 10, 2026
* chore(deps): bump actions/add-to-project from 1.0.2 to 2.0.0 (#4926)

Bumps [actions/add-to-project](https://github.com/actions/add-to-project) from 1.0.2 to 2.0.0.
- [Release notes](https://github.com/actions/add-to-project/releases)
- [Commits](actions/add-to-project@v1.0.2...v2.0.0)

---
updated-dependencies:
- dependency-name: actions/add-to-project
  dependency-version: 2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>

* chore(deps): bump actions/checkout from 5 to 7 (#4933)

Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v5...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>
Co-authored-by: unknown <unknown@example.com>
Co-authored-by: LinuxGSM <dev@linuxgsm.com>
Co-authored-by: Knoxed <1338733+knoxed@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: WildPenguin <ville.aakko@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Jacob Gerega <22921310+jgerega107@users.noreply.github.com>
Co-authored-by: dgibbs64 <dgibbs64@users.noreply.github.com>
Co-authored-by: Nikolay Asenov <10465782+nasenov@users.noreply.github.com>
Co-authored-by: Fabian Raab <fabian@raab.link>
Co-authored-by: yourfate <2371889-youRFate@users.noreply.gitlab.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: fwillo <37631375+fwillo@users.noreply.github.com>
Co-authored-by: Silas J. Matson <sjmatson01@gmail.com>

* chore(deps): bump actions/cache from 4 to 6 (#4945)

Bumps [actions/cache](https://github.com/actions/cache) from 4 to 6.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](actions/cache@v4...v6)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>
Co-authored-by: unknown <unknown@example.com>
Co-authored-by: LinuxGSM <dev@linuxgsm.com>
Co-authored-by: Knoxed <1338733+knoxed@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: WildPenguin <ville.aakko@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Jacob Gerega <22921310+jgerega107@users.noreply.github.com>
Co-authored-by: dgibbs64 <dgibbs64@users.noreply.github.com>
Co-authored-by: Nikolay Asenov <10465782+nasenov@users.noreply.github.com>
Co-authored-by: Fabian Raab <fabian@raab.link>
Co-authored-by: yourfate <2371889-youRFate@users.noreply.gitlab.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: fwillo <37631375+fwillo@users.noreply.github.com>
Co-authored-by: Silas J. Matson <sjmatson01@gmail.com>

* chore(deps): bump actions/github-script from 7 to 9 (#4946)

Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 9.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@v7...v9)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '9'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>
Co-authored-by: unknown <unknown@example.com>
Co-authored-by: LinuxGSM <dev@linuxgsm.com>
Co-authored-by: Knoxed <1338733+knoxed@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: WildPenguin <ville.aakko@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Jacob Gerega <22921310+jgerega107@users.noreply.github.com>
Co-authored-by: dgibbs64 <dgibbs64@users.noreply.github.com>
Co-authored-by: Nikolay Asenov <10465782+nasenov@users.noreply.github.com>
Co-authored-by: Fabian Raab <fabian@raab.link>
Co-authored-by: yourfate <2371889-youRFate@users.noreply.gitlab.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: fwillo <37631375+fwillo@users.noreply.github.com>
Co-authored-by: Silas J. Matson <sjmatson01@gmail.com>

* chore(sync): synced file(s) with dgibbs64/repo-sync (#4949)

* chore(sync): synced local '.github/' with remote 'general/.github/'

Synced from dgibbs64/repo-sync@a9c3090 — Merge pull request #18 from dgibbs64/chore/remove-dependabot-automerge

chore(workflows): remove dependabot auto-merge workflow

* chore(sync): synced local './' with remote 'bash/'

Synced from dgibbs64/repo-sync@a9c3090 — Merge pull request #18 from dgibbs64/chore/remove-dependabot-automerge

chore(workflows): remove dependabot auto-merge workflow

* Add permissions for pull-requests in workflow

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix(modules): make update_bb.sh executable (#4965)

update_bb.sh was the only module committed as 100644; all others are
100755.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(sdtd): read telnet password into telnetpassword (#4968)

fn_info_game_sdtd stored TelnetPassword in ${telnetpass}, but
command_stop.sh, info_messages.sh and the localhost check in the same
function all read ${telnetpassword}. The graceful telnet shutdown never
sent the password, and the telnet IP was always forced to 127.0.0.1,
so stop fell back to killing the tmux session without a world save.

Fixes #4957

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(vh): document how to disable crossplay (#4969)

* fix(vh): add crossplay setting to control -crossplay

-crossplay was hard-coded in vhserver's startparameters, so Steam-only
servers could not turn off the PlayFab relay without overriding the
whole startparameters line. Add crossplay="true" (default unchanged)
and only pass -crossplay when it is "true".

Fixes #4930

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(vh): document how to disable crossplay instead of adding a toggle

Drop the crossplay setting and the conditional in startparameters.
Keep -crossplay in the defaults, consistent with arkserver, and explain
how Steam-only servers remove it by overriding startparameters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(steamcmd): improve missing configuration diagnostics (#4951)

* fix: [Factorio] Update startparameters to load the latest server autosave (#4960)

* chore(sync): synced local '.github/' with remote 'general/.github/' (#4947)

Synced from dgibbs64/repo-sync@0a4246d — Merge pull request #12 from dgibbs64/dependabot/npm_and_yarn/brace-expansion-5.0.7

chore(deps): bump brace-expansion from 5.0.6 to 5.0.7

* Update startparameters to load the latest server autosave

Swap --start-server ${serverfiles}/save1.zip with --start-server-load-latest

* fix(fctr): create initial save in saves/ so load-latest finds it

--start-server-load-latest only searches the saves directory. The
initial save was created at ${serverfiles}/save1.zip, so a fresh install
had no saves/ directory and failed to host ("cannot open directory").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>
Co-authored-by: unknown <unknown@example.com>
Co-authored-by: LinuxGSM <dev@linuxgsm.com>
Co-authored-by: Knoxed <1338733+knoxed@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: WildPenguin <ville.aakko@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Jacob Gerega <22921310+jgerega107@users.noreply.github.com>
Co-authored-by: dgibbs64 <dgibbs64@users.noreply.github.com>
Co-authored-by: Nikolay Asenov <10465782+nasenov@users.noreply.github.com>
Co-authored-by: Fabian Raab <fabian@raab.link>
Co-authored-by: yourfate <2371889-youRFate@users.noreply.gitlab.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: fwillo <37631375+fwillo@users.noreply.github.com>
Co-authored-by: Silas J. Matson <sjmatson01@gmail.com>

* fix(deps): support deb822 apt sources on Debian (#4952)

* fix(deps): support deb822 apt sources on Debian

* fix(deps): ignore commented-out non-free entries in apt sources

The non-free check matched commented lines, so a disabled non-free
entry (more likely now that sources.list.d is searched) made LinuxGSM
try the unavailable steamcmd package instead of the tar fallback.
Only count lines whose first non-space character is not #.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: BreezeDelegate <271538431+BreezeDelegate@users.noreply.github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(fastdl): include Source resource files (#4953)

Co-authored-by: BreezeDelegate <271538431+BreezeDelegate@users.noreply.github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>

* feat(cs2server): add Metamod:Source 2.0 and CounterStrikeSharp mod support (#4961)

- Enable mod installation, updates and removal for CS2
- Add Metamod:Source 2.0 dev builds with gameinfo.gi configuration
- Add CounterStrikeSharp using the latest Linux release with runtime
- Require Metamod:Source 2.0 before installing CounterStrikeSharp
- Preserve the shared Metamod directory when removing CounterStrikeSharp

Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>

* fix(ci): label fork PRs and skip empty Details Check matrix (#4971)

- pr-labeler ran on pull_request, which gets a read-only token for PRs
  from forks, so it failed on every contributor PR ("Could not add
  label(s)"). Run it on pull_request_target with job-scoped write
  permissions; no job checks out or runs PR code on that event.
- details-check failed the whole run when create-matrix produced an
  empty matrix (PR touches no server configs). Skip the job instead.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(csgoserver): support the standalone CS:GO client (App ID 4465480) with configurable clientappid and the NoLobbyReservation mod (#4963)

* feat(csgoserver): support the standalone CS:GO client (App ID 4465480) with configurable runtimeappid and the NoLobbyReservation mod

* feat(csgoserver): rename runtimeappid to clientappid, pin NoLobbyReservation, prefer spcomp64

- Rename runtimeappid to clientappid and reword the comments: appid is
  the SteamCMD download ID (740), clientappid is the App ID the server
  advertises and players' clients connect with (4465480 or 730).
- Pin NoLobbyReservation to commit 003ab19f. It has no releases and is
  compiled from source on install, so do not follow master.
- Prefer spcomp64 and fall back to spcomp, so compiling does not rely
  on i386 libraries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(rsdwserver): add RuneScape: Dragonwilds server (#4921)

* feat(rsdwserver): add RuneScape: Dragonwilds server

* fix(rsdwserver): correct servercfgdir to LinuxServer

* feat(rsdwserver): show world name, owner id, and ini path in details

* fix(rsdwserver): point port edit guidance to start parameters

The rsdw port is set via -Port=${port} in startparameters, not in
DedicatedServer.ini, so move rsdw to the start parameters list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012svZAWTbYDdo2WuT2BZxQo

* feat(rsdwserver): add distro dependency entries and OwnerId guidance

- Add rsdw to every distro dependency CSV; without it the Server List
  Validation check fails once merged. No extra packages are needed,
  like other Unreal servers.
- Add Owner ID to dev-parse-game-details, as info_game.sh requires for
  new variables.
- State in _default.cfg that the server does not finish starting until
  OwnerId is set in DedicatedServer.ini, and drop the unused servername
  setting (the server reads its name from DedicatedServer.ini).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(rsdwserver): add game icon

32x32 RGB PNG from the Steam community app icon for RuneScape: Dragonwilds (app 1374490), matching the other game icons. Required by serverlist-validate-game-icons.sh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>

* fix(sm): convert sm-icon.png from JPEG to PNG (#4973)

sm-icon.png was JPEG data with a .png extension; every other game icon
is a 32x32 RGB PNG. Re-encoded as PNG with no visual change.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(core): fall back to 80 columns when no terminal width is available (#4974)

Separators and centred text used the width from tput cols. Without a
terminal (cron, Docker, post-details), tput prints an error and returns
nothing. bash 5.3 (Ubuntu 26.04) also rejects the empty printf width
("printf: : invalid number"). Hide tput's error and fall back to 80
columns. Terminal widths are still used when available.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(deps): check passwordless sudo before prompting with sudo -v (#4980)

sudo -v asks for a password with sudo-rs (Ubuntu 25.10+) even with
NOPASSWD, and with classic sudo when the user also matches the default
%sudo rule. Try sudo -n true first and only fall back to the sudo -v
prompt when passwordless sudo is not available.

* fix(core): handle bootstrap before logging and exit modules are loaded (#4981)

Bootstrap downloads and the Ctrl+C trap called logging, message and core_exit.sh functions before the modules defining them were loaded. This caused spurious "fn_script_log_pass: command not found" errors after the module cache was emptied, and a failed or cancelled early download carried on instead of exiting.

- Guard bootstrap log calls on the logging function existing.
- Add fn_bootstrap_exit: uses core_exit.sh once available, otherwise a plain exit.
- Make the download trap bootstrap-safe (removes the partial file, exits 130).

* fix(rsdwserver): download default DedicatedServer.ini on install (#4982)

RuneScape: Dragonwilds had no install_config.sh block, so no DedicatedServer.ini was created on install and the details-check (rsdw) CI job failed downloading the default config.

- Download DedicatedServer.ini from Game-Server-Configs (GameServerManagers/Game-Server-Configs#157), set the server and world name, and generate an admin password.
- Update the rsdwserver _default.cfg comment: the INI is now created during install, so OwnerId can be set before the first start.

* feat(newserver): add Hytale server support (#4928)

Adds the Hytale server (hyt): install, default config from Game-Server-Configs, Java 25 dependency check and first-start server login.

* fix(deps): add libatomic for American Truck Simulator and Euro Truck Simulator 2 (#4990)

The amtrucks_server and eurotrucks2_server binaries link libatomic.so.1,
which is not installed by default, so both servers failed to start.

* fix(ci): run apt-get update before installing Details Check dependencies (#4992)

The runner image's package index goes stale. Ubuntu replaced the
libxml2-utils build it lists, so apt-get install got a 404 and the
details-check job failed before any LinuxGSM code ran.

* fix(pz): pass the admin password as a start parameter (#4991)

Project Zomboid prompts for an admin password on first start when none is
given, and the server waits there forever because LinuxGSM runs it in
tmux (and Docker has no terminal at all).

* fix(ts3): query the ServerQuery address set in query_ip (#4975)

The monitor connects to the query port on each address in queryips.
When voice_ip was set to a specific address, queryips only held that
address and the public IP, so a ServerQuery bound to localhost
(query_ip=127.0.0.1) was never tried and monitor restarted the server.

Read query_ip from ts3server.ini (first address if several) and, when
it is a specific IPv4 address not already listed, query it first.

Fixes #4966

* ci(details-check): run servers in shards from the checkout (#4993)

* ci(details-check): run servers in shards from the checkout

- Check servers in 12 shards instead of one job per server, so jobs no
  longer queue behind the concurrency limit.
- Seed lgsm/modules, config-default and data from the checkout, so each
  server takes about 20s instead of about 80s and the PR's own code is
  what gets checked.
- Run bf1942, bfv, btl and onset in an ubuntu:20.04 container. The
  ubuntu-20.04 runner is retired, so btl and onset never started.
- Changes to the details-check workflow or scripts trigger a full run.

* ci(details-check): use the config filename for the Game-Server-Configs URL

servercfgdefault can include a directory variable (xnt uses
${systemdir}/server.cfg). Game-Server-Configs stores files flat per
game, so use only the filename.

* ci(details-check): keep config subdirectories in the Game-Server-Configs URL

Only drop a leading ${variable}/ (xnt). pc2's config lives in
config_sample/ in Game-Server-Configs.

* ci(details-check): fix the Game-Server-Configs path expansion

Strip a leading ${variable}/ with a pattern test instead of a nested
parameter expansion, which bash mangled. Keeps pc2's config_sample/.

* fix(sf): drop ServerQueryPort and BeaconPort removed in Satisfactory 1.0 (#4976)

* fix(sf): drop ServerQueryPort and BeaconPort removed in Satisfactory 1.0

Satisfactory 1.0+ uses port for the game (UDP) and the server API
(TCP), plus ReliablePort (TCP). -ServerQueryPort and -BeaconPort are no
longer used, but LinuxGSM still passed them and listed their ports in
details, so admins opened ports nothing listens on.

- Remove queryport/beaconport from sfserver _default.cfg and
  startparameters.
- details: list Game (UDP), Server API (TCP) and ReliableMessaging (TCP).
- queryport now follows port. Monitoring is session-only (querymode 1),
  so this doesn't change it.

Fixes #4967

* fix(sf): drop code comment

* fix(col): monitor Colony Survival with a TCP query (#4977)

* fix(col): monitor Colony Survival with a TCP query

Colony Survival hosts with SteamOnline networking and doesn't answer
A2S (protocol-valve) queries on its UDP game port. Monitor always
failed the query and restarted a working server every few minutes.
The query port listens on TCP (details already shows it as TCP), so
use query mode 5 (TCP).

* fix(col): keep querytype set for the gamedig query modes

querytype is ignored by the TCP query, but an empty value would break
monitoring if querymode is switched back to a gamedig mode.

* fix(steamcmd): work around Invalid platform errors (L4D2) (#4979)

* fix(steamcmd): work around Invalid platform errors (L4D2)

SteamCMD fails some app installs on Linux with "Failed to install app
'222860' (Invalid platform)", a long-standing SteamCMD bug
(ValveSoftware/steam-for-linux#11522) that breaks every new Left 4 Dead
2 install. The known workaround is to download the Windows depot once,
then update and validate as Linux.

When SteamCMD reports Invalid platform, run app_update once with
+@sSteamCmdForcePlatformType windows, then retry the normal Linux
update with validate. The workaround runs at most once per download.

Fixes #4754

* fix(steamcmd): run the Invalid platform workaround before the fatal check

The existing Invalid platform branch exits, and it came first in the
chain, so the workaround was never reached. Move the workaround above
it; the fatal branch still catches a repeat or forced-Windows case.

* fix(steamcmd): keep the Invalid platform workaround to one attempt per download

Make invalidplatformworkaround local to fn_dl_steamcmd. Manifest repair
calls the downloader several times, and a global flag stopped later
downloads from trying the workaround.

* chore(sync): synced file(s) with dgibbs64/repo-sync (#4978)

Synced from dgibbs64/repo-sync@71ef736 — fix(workflows): restore pull-requests: write for the copyright-year workflow (#21)

action-update-license-year opens its update as a pull request, which
needs pull-requests: write. It was removed with the auto-merge step.

Co-authored-by: dgibbs64 <dgibbs64@users.noreply.github.com>

* fix(monitor): anchor tmux session checks to avoid matching other instances (#4989)

* fix(monitor): anchor tmux session checks to avoid matching other instances

The monitor's session migration checks used unanchored pgrep/pkill
patterns. With multiple instances under one user where one session name
is a prefix of another (e.g. vhserver and vhserver-2), the shorter
instance's "old type tmux session" check matched the other instance's
concurrently running pgrep command line, causing spurious restarts
whenever both monitors ran at the same time.

Anchor the patterns to the start of the command line and require the
session name to be followed by a space or end of line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(monitor): drop code comment

---------

Co-authored-by: yourfate <2371889-youRFate@users.noreply.gitlab.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>

* fix(mods): only look up mod URLs for the game the server runs (#4983)

* fix(mods): only look up mod URLs for the game the server runs

mods_list.sh ran every mod lookup on each mods command regardless of the game, so a Counter-Strike 2 server also queried the CS:GO, Rust, Hurtworld, 7 Days To Die and Valheim mod releases. That is 11 GitHub API requests per command, which exhausts the unauthenticated limit of 60 requests per hour per IP address after five mods-install runs, and even sooner when several servers share an address. Once it is gone, curl returns a rate limit error body, the jq filters yield empty strings, and the mod URL and filename end up blank, which reaches the user only as a generic "An issue occurred downloading" failure.

Guard each lookup with the ${gamename} or ${engine} it belongs to, the non-GitHub ones (Metamod:Source, Metamod:Source 2.0, SourceMod, SteamWorks and BepInEx) included. Both variables are set from _default.cfg before mods_core.sh sources this file, and the conditions match the compatibility filters already declared in the mod_info arrays, so the set of mods offered to the user is unchanged.

* fix(mods): guard lookups by shortname and drop code comment

---------

Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>

* fix(install): stop when a server has no download configuration (#4996)

fn_install_server_files logged the failure but carried on, then tried to
fetch and extract with an empty URL. Exit after the failure instead.

Found in #4155 by @jusito.

* chore(lint): fix Super Linter errors on develop (#5001)

- Make .github/scripts/sync-game-labels.sh executable (BASH_EXEC).
- Don't check indent width in Markdown: list continuation lines are
  indented to the list marker (3 spaces for "1. "), as Prettier formats
  them (EDITORCONFIG, CODE_OF_CONDUCT.md).
- Quote $shortnames in the Details Check targeted-server step (actionlint
  SC2086). The file content is unchanged.

* fix(monitor): detect update, start and stop run with their short aliases (#5002)

Monitor checked for the u alias of update nowhere, and checked s
(sponsor) instead of st and sp for start and stop. An update started
with ./gameserver u was not detected, so monitor restarted the server
mid-update. Fixes #4997 and #4999.

* chore(lint): fix Ruff errors in query_gsquery.py (#5003)

- Add .github/linters/.ruff.toml with line-length 88 to match Black.
  Super Linter's default Ruff config uses 120, so ruff format and Black
  disagreed about the same file. target-version py38 keeps Ruff from
  suggesting changes that need a newer Python than Ubuntu 20.04 has.
- query_gsquery.py: make executable (EXE001), drop the redundant coding
  declaration (UP009) and an empty comment (PLR2044), and catch OSError
  instead of its alias socket.error (UP024).

* Release v26.3.0

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: unknown <unknown@example.com>
Co-authored-by: LinuxGSM <dev@linuxgsm.com>
Co-authored-by: Knoxed <1338733+knoxed@users.noreply.github.com>
Co-authored-by: WildPenguin <ville.aakko@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Jacob Gerega <22921310+jgerega107@users.noreply.github.com>
Co-authored-by: dgibbs64 <dgibbs64@users.noreply.github.com>
Co-authored-by: Nikolay Asenov <10465782+nasenov@users.noreply.github.com>
Co-authored-by: Fabian Raab <fabian@raab.link>
Co-authored-by: yourfate <2371889-youRFate@users.noreply.gitlab.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: fwillo <37631375+fwillo@users.noreply.github.com>
Co-authored-by: Silas J. Matson <sjmatson01@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Doug Murphy <1383347+Doug-Murphy@users.noreply.github.com>
Co-authored-by: Breeze <joeabysseyes+2@gmail.com>
Co-authored-by: BreezeDelegate <271538431+BreezeDelegate@users.noreply.github.com>
Co-authored-by: Attila <1230402+borzaka@users.noreply.github.com>
Co-authored-by: Josh Saterdalen <josh@saterdalen.me>
Co-authored-by: Andrew Quenehen <56467992+andrewqsantos@users.noreply.github.com>
Co-authored-by: yourfate <47528796+yourfate@users.noreply.github.com>
dgibbs64 added a commit that referenced this pull request Oct 10, 2026
* chore(deps): bump actions/add-to-project from 1.0.2 to 2.0.0 (#4926)

Bumps [actions/add-to-project](https://github.com/actions/add-to-project) from 1.0.2 to 2.0.0.
- [Release notes](https://github.com/actions/add-to-project/releases)
- [Commits](actions/add-to-project@v1.0.2...v2.0.0)

---
updated-dependencies:
- dependency-name: actions/add-to-project
  dependency-version: 2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>

* chore(deps): bump actions/checkout from 5 to 7 (#4933)

Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v5...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>
Co-authored-by: unknown <unknown@example.com>
Co-authored-by: LinuxGSM <dev@linuxgsm.com>
Co-authored-by: Knoxed <1338733+knoxed@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: WildPenguin <ville.aakko@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Jacob Gerega <22921310+jgerega107@users.noreply.github.com>
Co-authored-by: dgibbs64 <dgibbs64@users.noreply.github.com>
Co-authored-by: Nikolay Asenov <10465782+nasenov@users.noreply.github.com>
Co-authored-by: Fabian Raab <fabian@raab.link>
Co-authored-by: yourfate <2371889-youRFate@users.noreply.gitlab.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: fwillo <37631375+fwillo@users.noreply.github.com>
Co-authored-by: Silas J. Matson <sjmatson01@gmail.com>

* chore(deps): bump actions/cache from 4 to 6 (#4945)

Bumps [actions/cache](https://github.com/actions/cache) from 4 to 6.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](actions/cache@v4...v6)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>
Co-authored-by: unknown <unknown@example.com>
Co-authored-by: LinuxGSM <dev@linuxgsm.com>
Co-authored-by: Knoxed <1338733+knoxed@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: WildPenguin <ville.aakko@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Jacob Gerega <22921310+jgerega107@users.noreply.github.com>
Co-authored-by: dgibbs64 <dgibbs64@users.noreply.github.com>
Co-authored-by: Nikolay Asenov <10465782+nasenov@users.noreply.github.com>
Co-authored-by: Fabian Raab <fabian@raab.link>
Co-authored-by: yourfate <2371889-youRFate@users.noreply.gitlab.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: fwillo <37631375+fwillo@users.noreply.github.com>
Co-authored-by: Silas J. Matson <sjmatson01@gmail.com>

* chore(deps): bump actions/github-script from 7 to 9 (#4946)

Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 9.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@v7...v9)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '9'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>
Co-authored-by: unknown <unknown@example.com>
Co-authored-by: LinuxGSM <dev@linuxgsm.com>
Co-authored-by: Knoxed <1338733+knoxed@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: WildPenguin <ville.aakko@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Jacob Gerega <22921310+jgerega107@users.noreply.github.com>
Co-authored-by: dgibbs64 <dgibbs64@users.noreply.github.com>
Co-authored-by: Nikolay Asenov <10465782+nasenov@users.noreply.github.com>
Co-authored-by: Fabian Raab <fabian@raab.link>
Co-authored-by: yourfate <2371889-youRFate@users.noreply.gitlab.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: fwillo <37631375+fwillo@users.noreply.github.com>
Co-authored-by: Silas J. Matson <sjmatson01@gmail.com>

* chore(sync): synced file(s) with dgibbs64/repo-sync (#4949)

* chore(sync): synced local '.github/' with remote 'general/.github/'

Synced from dgibbs64/repo-sync@a9c3090 — Merge pull request #18 from dgibbs64/chore/remove-dependabot-automerge

chore(workflows): remove dependabot auto-merge workflow

* chore(sync): synced local './' with remote 'bash/'

Synced from dgibbs64/repo-sync@a9c3090 — Merge pull request #18 from dgibbs64/chore/remove-dependabot-automerge

chore(workflows): remove dependabot auto-merge workflow

* Add permissions for pull-requests in workflow

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix(modules): make update_bb.sh executable (#4965)

update_bb.sh was the only module committed as 100644; all others are
100755.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(sdtd): read telnet password into telnetpassword (#4968)

fn_info_game_sdtd stored TelnetPassword in ${telnetpass}, but
command_stop.sh, info_messages.sh and the localhost check in the same
function all read ${telnetpassword}. The graceful telnet shutdown never
sent the password, and the telnet IP was always forced to 127.0.0.1,
so stop fell back to killing the tmux session without a world save.

Fixes #4957

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(vh): document how to disable crossplay (#4969)

* fix(vh): add crossplay setting to control -crossplay

-crossplay was hard-coded in vhserver's startparameters, so Steam-only
servers could not turn off the PlayFab relay without overriding the
whole startparameters line. Add crossplay="true" (default unchanged)
and only pass -crossplay when it is "true".

Fixes #4930

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(vh): document how to disable crossplay instead of adding a toggle

Drop the crossplay setting and the conditional in startparameters.
Keep -crossplay in the defaults, consistent with arkserver, and explain
how Steam-only servers remove it by overriding startparameters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(steamcmd): improve missing configuration diagnostics (#4951)

* fix: [Factorio] Update startparameters to load the latest server autosave (#4960)

* chore(sync): synced local '.github/' with remote 'general/.github/' (#4947)

Synced from dgibbs64/repo-sync@0a4246d — Merge pull request #12 from dgibbs64/dependabot/npm_and_yarn/brace-expansion-5.0.7

chore(deps): bump brace-expansion from 5.0.6 to 5.0.7

* Update startparameters to load the latest server autosave

Swap --start-server ${serverfiles}/save1.zip with --start-server-load-latest

* fix(fctr): create initial save in saves/ so load-latest finds it

--start-server-load-latest only searches the saves directory. The
initial save was created at ${serverfiles}/save1.zip, so a fresh install
had no saves/ directory and failed to host ("cannot open directory").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>
Co-authored-by: unknown <unknown@example.com>
Co-authored-by: LinuxGSM <dev@linuxgsm.com>
Co-authored-by: Knoxed <1338733+knoxed@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: WildPenguin <ville.aakko@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Jacob Gerega <22921310+jgerega107@users.noreply.github.com>
Co-authored-by: dgibbs64 <dgibbs64@users.noreply.github.com>
Co-authored-by: Nikolay Asenov <10465782+nasenov@users.noreply.github.com>
Co-authored-by: Fabian Raab <fabian@raab.link>
Co-authored-by: yourfate <2371889-youRFate@users.noreply.gitlab.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: fwillo <37631375+fwillo@users.noreply.github.com>
Co-authored-by: Silas J. Matson <sjmatson01@gmail.com>

* fix(deps): support deb822 apt sources on Debian (#4952)

* fix(deps): support deb822 apt sources on Debian

* fix(deps): ignore commented-out non-free entries in apt sources

The non-free check matched commented lines, so a disabled non-free
entry (more likely now that sources.list.d is searched) made LinuxGSM
try the unavailable steamcmd package instead of the tar fallback.
Only count lines whose first non-space character is not #.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: BreezeDelegate <271538431+BreezeDelegate@users.noreply.github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(fastdl): include Source resource files (#4953)

Co-authored-by: BreezeDelegate <271538431+BreezeDelegate@users.noreply.github.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>

* feat(cs2server): add Metamod:Source 2.0 and CounterStrikeSharp mod support (#4961)

- Enable mod installation, updates and removal for CS2
- Add Metamod:Source 2.0 dev builds with gameinfo.gi configuration
- Add CounterStrikeSharp using the latest Linux release with runtime
- Require Metamod:Source 2.0 before installing CounterStrikeSharp
- Preserve the shared Metamod directory when removing CounterStrikeSharp

Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>

* fix(ci): label fork PRs and skip empty Details Check matrix (#4971)

- pr-labeler ran on pull_request, which gets a read-only token for PRs
  from forks, so it failed on every contributor PR ("Could not add
  label(s)"). Run it on pull_request_target with job-scoped write
  permissions; no job checks out or runs PR code on that event.
- details-check failed the whole run when create-matrix produced an
  empty matrix (PR touches no server configs). Skip the job instead.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(csgoserver): support the standalone CS:GO client (App ID 4465480) with configurable clientappid and the NoLobbyReservation mod (#4963)

* feat(csgoserver): support the standalone CS:GO client (App ID 4465480) with configurable runtimeappid and the NoLobbyReservation mod

* feat(csgoserver): rename runtimeappid to clientappid, pin NoLobbyReservation, prefer spcomp64

- Rename runtimeappid to clientappid and reword the comments: appid is
  the SteamCMD download ID (740), clientappid is the App ID the server
  advertises and players' clients connect with (4465480 or 730).
- Pin NoLobbyReservation to commit 003ab19f. It has no releases and is
  compiled from source on install, so do not follow master.
- Prefer spcomp64 and fall back to spcomp, so compiling does not rely
  on i386 libraries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(rsdwserver): add RuneScape: Dragonwilds server (#4921)

* feat(rsdwserver): add RuneScape: Dragonwilds server

* fix(rsdwserver): correct servercfgdir to LinuxServer

* feat(rsdwserver): show world name, owner id, and ini path in details

* fix(rsdwserver): point port edit guidance to start parameters

The rsdw port is set via -Port=${port} in startparameters, not in
DedicatedServer.ini, so move rsdw to the start parameters list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012svZAWTbYDdo2WuT2BZxQo

* feat(rsdwserver): add distro dependency entries and OwnerId guidance

- Add rsdw to every distro dependency CSV; without it the Server List
  Validation check fails once merged. No extra packages are needed,
  like other Unreal servers.
- Add Owner ID to dev-parse-game-details, as info_game.sh requires for
  new variables.
- State in _default.cfg that the server does not finish starting until
  OwnerId is set in DedicatedServer.ini, and drop the unused servername
  setting (the server reads its name from DedicatedServer.ini).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(rsdwserver): add game icon

32x32 RGB PNG from the Steam community app icon for RuneScape: Dragonwilds (app 1374490), matching the other game icons. Required by serverlist-validate-game-icons.sh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>

* fix(sm): convert sm-icon.png from JPEG to PNG (#4973)

sm-icon.png was JPEG data with a .png extension; every other game icon
is a 32x32 RGB PNG. Re-encoded as PNG with no visual change.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(core): fall back to 80 columns when no terminal width is available (#4974)

Separators and centred text used the width from tput cols. Without a
terminal (cron, Docker, post-details), tput prints an error and returns
nothing. bash 5.3 (Ubuntu 26.04) also rejects the empty printf width
("printf: : invalid number"). Hide tput's error and fall back to 80
columns. Terminal widths are still used when available.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(deps): check passwordless sudo before prompting with sudo -v (#4980)

sudo -v asks for a password with sudo-rs (Ubuntu 25.10+) even with
NOPASSWD, and with classic sudo when the user also matches the default
%sudo rule. Try sudo -n true first and only fall back to the sudo -v
prompt when passwordless sudo is not available.

* fix(core): handle bootstrap before logging and exit modules are loaded (#4981)

Bootstrap downloads and the Ctrl+C trap called logging, message and core_exit.sh functions before the modules defining them were loaded. This caused spurious "fn_script_log_pass: command not found" errors after the module cache was emptied, and a failed or cancelled early download carried on instead of exiting.

- Guard bootstrap log calls on the logging function existing.
- Add fn_bootstrap_exit: uses core_exit.sh once available, otherwise a plain exit.
- Make the download trap bootstrap-safe (removes the partial file, exits 130).

* fix(rsdwserver): download default DedicatedServer.ini on install (#4982)

RuneScape: Dragonwilds had no install_config.sh block, so no DedicatedServer.ini was created on install and the details-check (rsdw) CI job failed downloading the default config.

- Download DedicatedServer.ini from Game-Server-Configs (GameServerManagers/Game-Server-Configs#157), set the server and world name, and generate an admin password.
- Update the rsdwserver _default.cfg comment: the INI is now created during install, so OwnerId can be set before the first start.

* feat(newserver): add Hytale server support (#4928)

Adds the Hytale server (hyt): install, default config from Game-Server-Configs, Java 25 dependency check and first-start server login.

* fix(deps): add libatomic for American Truck Simulator and Euro Truck Simulator 2 (#4990)

The amtrucks_server and eurotrucks2_server binaries link libatomic.so.1,
which is not installed by default, so both servers failed to start.

* fix(ci): run apt-get update before installing Details Check dependencies (#4992)

The runner image's package index goes stale. Ubuntu replaced the
libxml2-utils build it lists, so apt-get install got a 404 and the
details-check job failed before any LinuxGSM code ran.

* fix(pz): pass the admin password as a start parameter (#4991)

Project Zomboid prompts for an admin password on first start when none is
given, and the server waits there forever because LinuxGSM runs it in
tmux (and Docker has no terminal at all).

* fix(ts3): query the ServerQuery address set in query_ip (#4975)

The monitor connects to the query port on each address in queryips.
When voice_ip was set to a specific address, queryips only held that
address and the public IP, so a ServerQuery bound to localhost
(query_ip=127.0.0.1) was never tried and monitor restarted the server.

Read query_ip from ts3server.ini (first address if several) and, when
it is a specific IPv4 address not already listed, query it first.

Fixes #4966

* ci(details-check): run servers in shards from the checkout (#4993)

* ci(details-check): run servers in shards from the checkout

- Check servers in 12 shards instead of one job per server, so jobs no
  longer queue behind the concurrency limit.
- Seed lgsm/modules, config-default and data from the checkout, so each
  server takes about 20s instead of about 80s and the PR's own code is
  what gets checked.
- Run bf1942, bfv, btl and onset in an ubuntu:20.04 container. The
  ubuntu-20.04 runner is retired, so btl and onset never started.
- Changes to the details-check workflow or scripts trigger a full run.

* ci(details-check): use the config filename for the Game-Server-Configs URL

servercfgdefault can include a directory variable (xnt uses
${systemdir}/server.cfg). Game-Server-Configs stores files flat per
game, so use only the filename.

* ci(details-check): keep config subdirectories in the Game-Server-Configs URL

Only drop a leading ${variable}/ (xnt). pc2's config lives in
config_sample/ in Game-Server-Configs.

* ci(details-check): fix the Game-Server-Configs path expansion

Strip a leading ${variable}/ with a pattern test instead of a nested
parameter expansion, which bash mangled. Keeps pc2's config_sample/.

* fix(sf): drop ServerQueryPort and BeaconPort removed in Satisfactory 1.0 (#4976)

* fix(sf): drop ServerQueryPort and BeaconPort removed in Satisfactory 1.0

Satisfactory 1.0+ uses port for the game (UDP) and the server API
(TCP), plus ReliablePort (TCP). -ServerQueryPort and -BeaconPort are no
longer used, but LinuxGSM still passed them and listed their ports in
details, so admins opened ports nothing listens on.

- Remove queryport/beaconport from sfserver _default.cfg and
  startparameters.
- details: list Game (UDP), Server API (TCP) and ReliableMessaging (TCP).
- queryport now follows port. Monitoring is session-only (querymode 1),
  so this doesn't change it.

Fixes #4967

* fix(sf): drop code comment

* fix(col): monitor Colony Survival with a TCP query (#4977)

* fix(col): monitor Colony Survival with a TCP query

Colony Survival hosts with SteamOnline networking and doesn't answer
A2S (protocol-valve) queries on its UDP game port. Monitor always
failed the query and restarted a working server every few minutes.
The query port listens on TCP (details already shows it as TCP), so
use query mode 5 (TCP).

* fix(col): keep querytype set for the gamedig query modes

querytype is ignored by the TCP query, but an empty value would break
monitoring if querymode is switched back to a gamedig mode.

* fix(steamcmd): work around Invalid platform errors (L4D2) (#4979)

* fix(steamcmd): work around Invalid platform errors (L4D2)

SteamCMD fails some app installs on Linux with "Failed to install app
'222860' (Invalid platform)", a long-standing SteamCMD bug
(ValveSoftware/steam-for-linux#11522) that breaks every new Left 4 Dead
2 install. The known workaround is to download the Windows depot once,
then update and validate as Linux.

When SteamCMD reports Invalid platform, run app_update once with
+@sSteamCmdForcePlatformType windows, then retry the normal Linux
update with validate. The workaround runs at most once per download.

Fixes #4754

* fix(steamcmd): run the Invalid platform workaround before the fatal check

The existing Invalid platform branch exits, and it came first in the
chain, so the workaround was never reached. Move the workaround above
it; the fatal branch still catches a repeat or forced-Windows case.

* fix(steamcmd): keep the Invalid platform workaround to one attempt per download

Make invalidplatformworkaround local to fn_dl_steamcmd. Manifest repair
calls the downloader several times, and a global flag stopped later
downloads from trying the workaround.

* chore(sync): synced file(s) with dgibbs64/repo-sync (#4978)

Synced from dgibbs64/repo-sync@71ef736 — fix(workflows): restore pull-requests: write for the copyright-year workflow (#21)

action-update-license-year opens its update as a pull request, which
needs pull-requests: write. It was removed with the auto-merge step.

Co-authored-by: dgibbs64 <dgibbs64@users.noreply.github.com>

* fix(monitor): anchor tmux session checks to avoid matching other instances (#4989)

* fix(monitor): anchor tmux session checks to avoid matching other instances

The monitor's session migration checks used unanchored pgrep/pkill
patterns. With multiple instances under one user where one session name
is a prefix of another (e.g. vhserver and vhserver-2), the shorter
instance's "old type tmux session" check matched the other instance's
concurrently running pgrep command line, causing spurious restarts
whenever both monitors ran at the same time.

Anchor the patterns to the start of the command line and require the
session name to be followed by a space or end of line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(monitor): drop code comment

---------

Co-authored-by: yourfate <2371889-youRFate@users.noreply.gitlab.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>

* fix(mods): only look up mod URLs for the game the server runs (#4983)

* fix(mods): only look up mod URLs for the game the server runs

mods_list.sh ran every mod lookup on each mods command regardless of the game, so a Counter-Strike 2 server also queried the CS:GO, Rust, Hurtworld, 7 Days To Die and Valheim mod releases. That is 11 GitHub API requests per command, which exhausts the unauthenticated limit of 60 requests per hour per IP address after five mods-install runs, and even sooner when several servers share an address. Once it is gone, curl returns a rate limit error body, the jq filters yield empty strings, and the mod URL and filename end up blank, which reaches the user only as a generic "An issue occurred downloading" failure.

Guard each lookup with the ${gamename} or ${engine} it belongs to, the non-GitHub ones (Metamod:Source, Metamod:Source 2.0, SourceMod, SteamWorks and BepInEx) included. Both variables are set from _default.cfg before mods_core.sh sources this file, and the conditions match the compatibility filters already declared in the mod_info arrays, so the set of mods offered to the user is unchanged.

* fix(mods): guard lookups by shortname and drop code comment

---------

Co-authored-by: Daniel Gibbs <me@danielgibbs.co.uk>

* fix(install): stop when a server has no download configuration (#4996)

fn_install_server_files logged the failure but carried on, then tried to
fetch and extract with an empty URL. Exit after the failure instead.

Found in #4155 by @jusito.

* chore(lint): fix Super Linter errors on develop (#5001)

- Make .github/scripts/sync-game-labels.sh executable (BASH_EXEC).
- Don't check indent width in Markdown: list continuation lines are
  indented to the list marker (3 spaces for "1. "), as Prettier formats
  them (EDITORCONFIG, CODE_OF_CONDUCT.md).
- Quote $shortnames in the Details Check targeted-server step (actionlint
  SC2086). The file content is unchanged.

* fix(monitor): detect update, start and stop run with their short aliases (#5002)

Monitor checked for the u alias of update nowhere, and checked s
(sponsor) instead of st and sp for start and stop. An update started
with ./gameserver u was not detected, so monitor restarted the server
mid-update. Fixes #4997 and #4999.

* chore(lint): fix Ruff errors in query_gsquery.py (#5003)

- Add .github/linters/.ruff.toml with line-length 88 to match Black.
  Super Linter's default Ruff config uses 120, so ruff format and Black
  disagreed about the same file. target-version py38 keeps Ruff from
  suggesting changes that need a newer Python than Ubuntu 20.04 has.
- query_gsquery.py: make executable (EXE001), drop the redundant coding
  declaration (UP009) and an empty comment (PLR2044), and catch OSError
  instead of its alias socket.error (UP024).

* fix(monitor): show the queried address on the DELAY and WAIT lines (#5006)

fn_monitor_query loops over queryips, but the DELAY print and log line
and the WAIT countdown still used ${ip}. With no IP set this is 0.0.0.0,
so monitor printed and logged an address it never queried.

Fixes #5004

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Release v26.3.0

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: unknown <unknown@example.com>
Co-authored-by: LinuxGSM <dev@linuxgsm.com>
Co-authored-by: Knoxed <1338733+knoxed@users.noreply.github.com>
Co-authored-by: WildPenguin <ville.aakko@gmail.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Jacob Gerega <22921310+jgerega107@users.noreply.github.com>
Co-authored-by: dgibbs64 <dgibbs64@users.noreply.github.com>
Co-authored-by: Nikolay Asenov <10465782+nasenov@users.noreply.github.com>
Co-authored-by: Fabian Raab <fabian@raab.link>
Co-authored-by: yourfate <2371889-youRFate@users.noreply.gitlab.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: fwillo <37631375+fwillo@users.noreply.github.com>
Co-authored-by: Silas J. Matson <sjmatson01@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Doug Murphy <1383347+Doug-Murphy@users.noreply.github.com>
Co-authored-by: Breeze <joeabysseyes+2@gmail.com>
Co-authored-by: BreezeDelegate <271538431+BreezeDelegate@users.noreply.github.com>
Co-authored-by: Attila <1230402+borzaka@users.noreply.github.com>
Co-authored-by: Josh Saterdalen <josh@saterdalen.me>
Co-authored-by: Andrew Quenehen <56467992+andrewqsantos@users.noreply.github.com>
Co-authored-by: yourfate <47528796+yourfate@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

engine: source engine: source2 Issues related to source2 engine game: Counter-Strike: Global Offensive Issues related to Counter-Strike: Global Offensive game: Counter-Strike 2 Issues related to Counter-Strike 2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants