Skip to content

fix(servers): filter empty-name A2S entries so first-player ctxmenu works (#1396) - #1401

Merged
rumblefrog merged 2 commits into
mainfrom
fix/1396-first-player-context-menu
May 17, 2026
Merged

fix(servers): filter empty-name A2S entries so first-player ctxmenu works (#1396)#1401
rumblefrog merged 2 commits into
mainfrom
fix/1396-first-player-context-menu

Conversation

@rumblefrog

Copy link
Copy Markdown
Member

Fixes #1396.

Summary

  • Root cause: some Source-engine variants and SourceMod plugins emit a "host slot" / "console" entry at the start of A2S GetPlayers with Name = '', Frags = 0, Time = 0. Pre-fix api_servers_host_players passed it through verbatim to player_list, and the JS rendered a phantom <li data-testid="server-player"> above the first named player (the empty name fails the SteamID-match gate, so no data-context-menu hooks; visually a thin border-bottom strip with a misleading "0 · " meta on the right). Users perceived the next real player as "the first player of the list" and right-clicks landing in the phantom row silently no-op'd. The reporter's screenshot showed "Fletcher" as the first visible player with the menu only opening on "kovka" below him.
  • Fix: one-line continue inside the $playerList build loop in api_servers_host_players, matching the same $name === '' skip the SteamID-by-name lookup already applies upstream. The redundant && $name !== '' guard in the SteamID match gate is removed (the loop now skips empty names entirely). The JS contract stays simple: every row in player_list has a displayable name. Bots, real players whose A2S name didn't match the RCON status output, and anonymous callers all still render — the filter is strictly "name is empty string".
  • AGENTS.md updated to document the new player_list contract under the existing "Add or extend the server-player right-click context menu" row in "Where to find what".

Test plan

Quality gates run locally before pushing:

  • ./sbpp.sh phpstan — OK, no errors
  • ./sbpp.sh test — 643 tests, 2610 assertions (includes 2 new regression tests + 1 reused, plus 15-test host_players group all green)
  • ./sbpp.sh ts-check — clean
  • ./sbpp.sh composer api-contract — no diff
  • CI=1 ./sbpp.sh e2e — 265 passed (full suite; 277 skipped per per-spec project filters)

New regression tests

  • web/tests/api/ServersTest.php::testHostPlayersFiltersEmptyNameEntries — A2S response with an empty-name entry at index 0 followed by Fletcher + kovka. Asserts player_list has 2 rows (not 3), Fletcher is at index 0 with the SteamID the menu needs, no row has an empty name. Fails on 568c46b with actual size 3 matches expected size 2 — proved before applying the fix.
  • web/tests/api/ServersTest.php::testHostPlayersFiltersAllEmptyNameEntries — all-empty-name A2S response yields an empty player_list; the A2S-reported players count is independent of the rendered list (a SourceMod plugin can legitimately inflate the count). Fails on 568c46b with actual size 3 matches expected size 0.
  • web/tests/e2e/specs/flows/server-player-context-menu.spec.ts::first named player accepts right-click (#1396 end-to-end) — new E2E test using real page.mouse.click({button: 'right'}) against the visual centre of the first rendered row. Asserts the menu opens with Fletcher's SteamID in the kick URL (not the second player's). Pins the END-USER outcome — load-bearing coverage for the filter itself lives in the two PHP tests above.

Files changed

  • web/api/handlers/servers.php — the fix (+19 lines, -1 line; +17 lines are the explanatory comment block above the loop).
  • web/tests/api/ServersTest.php — two new regression tests.
  • web/tests/e2e/specs/flows/server-player-context-menu.spec.ts — one new E2E test.
  • AGENTS.md — contract documentation update in the existing right-click-context-menu row.

…orks (#1396)

Some Source-engine variants and SourceMod plugins emit a "host slot"
/ "console" entry at the start of `GetPlayers` with `Name = ''`,
`Frags = 0`, `Time = 0`. Pre-fix `api_servers_host_players` passed
the entry through to `player_list` verbatim, and the JS rendered
it as a phantom `<li data-testid="server-player">` above the first
named player — an invisible thin row with a misleading "0 · " meta
on the right and no `data-context-menu` hooks (the empty name fails
the SteamID match gate). Users perceived the next real player as
"the first player of the list", and right-clicks landing in the
phantom row's area silently no-op'd. The user's screenshot showed
"Fletcher" as the first visible player with no menu opening; the
menu opened normally on every other player below him.

The fix is one line inside the `$playerList` build loop: skip
entries with `name === ''`, matching the same gate the SteamID-
by-name lookup already applies upstream. The redundant
`&& $name !== ''` guard in the SteamID match gate is removed since
the loop now skips empty names entirely. The JS contract stays
simple: every row in `player_list` has a displayable name.

Regression coverage:
- `ServersTest::testHostPlayersFiltersEmptyNameEntries` — handler
  receives an A2S response with an empty-name entry first; asserts
  `player_list` has 2 rows (not 3), Fletcher is at index 0 with
  the steamid the menu needs, no row has an empty name.
- `ServersTest::testHostPlayersFiltersAllEmptyNameEntries` —
  all-empty-name A2S response yields an empty `player_list`; the
  A2S-reported `players` count is independent of the rendered list.
- `server-player-context-menu.spec.ts` — new E2E test using real
  `page.mouse.click({button: 'right'})` against the visual centre
  of the first rendered row, asserting the menu opens with
  Fletcher's SteamID in the kick URL (not the second player's).

Both PHP tests fail on 568c46b (proved before applying the fix:
"actual size 3 matches expected size 2" / "expected size 0").
@rumblefrog
rumblefrog added this pull request to the merge queue May 17, 2026
Merged via the queue into main with commit f97b4eb May 17, 2026
8 checks passed
@rumblefrog
rumblefrog deleted the fix/1396-first-player-context-menu branch May 17, 2026 20:21
@github-actions github-actions Bot locked and limited conversation to collaborators May 17, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2.0 rc3 - Server List - expanded card opening on first player of the list

1 participant