Skip to content

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

Merged
dgibbs64 merged 3 commits into
developfrom
fix/rsdw-install-config
Oct 4, 2026
Merged

dgibbs64 merged 3 commits into
developfrom
fix/rsdw-install-config

Conversation

@dgibbs64

@dgibbs64 dgibbs64 commented Oct 4, 2026

Copy link
Copy Markdown
Member

Description

RuneScape: Dragonwilds (#4921) had no install_config.sh block, so no DedicatedServer.ini was created on install. The details-check (rsdw) CI job also fails, because it downloads the default config from Game-Server-Configs and gets a 404.

This adds the standard block: download DedicatedServer.ini from Game-Server-Configs, set the server name and world name to LinuxGSM, generate an admin password, and list the config location.

Needs GameServerManagers/Game-Server-Configs#157 merged first, which adds the template.

Note: the server will not start until OwnerId (the owner's in-game Player ID) is set in DedicatedServer.ini. LinuxGSM can't fill that in.

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

Ubuntu 24.04 (Docker), with the module pointed at the Game-Server-Configs branch:

  • ./rsdwserver auto-install: downloads and copies DedicatedServer.ini, sets the hostname and generates an admin password.
  • ./rsdwserver details: shows Server name LinuxGSM, World name LinuxGSM, the generated Admin password, and Owner ID NOT SET.
  • ./rsdwserver start with the template in place: the server keeps the settings and listens on 7777. It removes the AdminPassword line from the INI when it rewrites it on start, so details shows the admin password as NOT SET after the first start. That's server behaviour, also present without this PR.

bash -n passes.

Copilot AI balanced review requested due to automatic review settings October 4, 2026 13:15
@dgibbs64 dgibbs64 added this to the v26.3.0 milestone Oct 4, 2026
@github-actions github-actions Bot added the game: RuneScape: Dragonwilds Issues related to RuneScape: Dragonwilds label Oct 4, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The functional change follows the established installation pattern; only a minor documentation correction remains.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
What changed in this PR

Adds installation-time provisioning of RuneScape: Dragonwilds’ default configuration.

Changes:

  • Downloads DedicatedServer.ini.
  • Sets default server/world names and generates an admin password.
  • Reports the configuration location.

The dependent Game-Server-Configs PR #157 must merge first. One minor stale documentation reference remains.

File Description
lgsm/​modules/​install_config.sh Adds the standard rsdw configuration installation flow.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lgsm/modules/install_config.sh
@dgibbs64
dgibbs64 merged commit bf864f0 into develop Oct 4, 2026
7 checks passed
@dgibbs64
dgibbs64 deleted the fix/rsdw-install-config branch October 4, 2026 13:34
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

game: RuneScape: Dragonwilds Issues related to RuneScape: Dragonwilds

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants