Skip to content

fix: deterministic status ordering, connecting-player ping, header alignment - #37

Merged
Rushaway merged 2 commits into
masterfrom
improve/status-sort-and-state-consistency
Sep 11, 2026
Merged

fix: deterministic status ordering, connecting-player ping, header alignment#37
Rushaway merged 2 commits into
masterfrom
improve/status-sort-and-state-consistency

Conversation

@Rushaway

Copy link
Copy Markdown
Member

Summary

Bug fixes and small polish for the status output, found while reading through Status.sp. No new cvars, no new dependencies. Verified with spcomp 1.12.0.7253 (0 warnings) with and without the optional PlayerManager / serverfps includes.

Bugs fixed

1. Non-deterministic row order on ties

SortCustom1D is not a stable sort. When two players compared equal on the active key (same ping, same connection time, same state, or a duplicate name) their relative order was whatever the quicksort happened to leave behind, so repeated status calls could shuffle rows around.
The comparator now falls back to an ascending-userid tie-breaker, so equal keys always produce the same, predictable order.

2. -1000 ping / -100 loss for players who are still connecting

The player loop called GetClientLatency() / GetClientAvgLoss() for every non-bot client, including ones that are connected but not yet in-game. Those natives return -1 in that window, which was rounded and printed as -1000 / -100.
Ping/loss are now only queried once the client is actually in-game (matching how bots are already handled — the column is simply left blank). The same players are also given PING_UNAVAILABLE as their sort key so they land at the bottom of a ping-ordered list instead of at the very top.

3. State label and state sort rank could drift apart

GetPlayerStateSortRank() and GetPlayerStateLabel() each re-implemented the same IsClientInGame / PM_IsPlayerSteam logic with hard-coded 0/1/2. If one was ever updated without the other, a row could be shown as nosteam while sorting as active.
Both now derive from a single GetPlayerState() function returning a PlayerState enum.

Polish

  • Header alignmenttags, map, edicts and tickrate labels used inconsistent padding, so the colons didn't line up. They're now aligned to a common width like vanilla status.
  • State column – widened from %7s to %8s so spawning (8 chars) isn't clipped against the next column.
  • Dead codesTitleFmt and sRowFmt were byte-for-byte identical; collapsed to one. The sm_status_authid_type convar is now read once instead of twice.
  • IsFakeClient() / IsClientInGame() are cached per row instead of being called 3× each.

Version bumped to 2.2.2.

Test plan

  • spcomp clean (0 warnings) with geoip + PlayerManager + serverfps (CI-equivalent)
  • spcomp clean with geoip only (no PlayerManager, no serverfps)
  • spcomp clean with geoip + serverfps, no PlayerManager
  • In-game: status from client console and server console, with a player mid-connection, across each sm_status_order_by value

🤖 Generated with Claude Code

… align header

- Add a stable userid tie-breaker to the sort comparator so rows with equal
  keys (same ping/time/state/name) keep a deterministic order instead of
  whatever the unstable SortCustom1D pass produces.
- Skip GetClientLatency/GetClientAvgLoss for players that are connected but
  not yet in-game: those calls return -1 and printed "-1000" ping / "-100"
  loss. Such players now also sort to the bottom of a ping-ordered list
  (PING_UNAVAILABLE) rather than jumping to the top.
- Collapse GetPlayerStateSortRank/GetPlayerStateLabel into a single
  GetPlayerState() source of truth (new PlayerState enum) so the displayed
  label and the sort rank can never diverge.
- Align the header labels to a common width (tags/map/edicts/tickrate) so the
  colons line up like vanilla "status".
- Widen the state column to %8s so "spawning" is not clipped against the
  next column; drop the duplicate title/row format string; read the
  AuthIdType convar once.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 10, 2026 20:53

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Per-row string buffers (time/ping/loss/addr) are not initialized, so bots and connecting players can print garbage values in the status table output.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates the SourceMod Status Fixer plugin to make status output more predictable and polished, primarily by improving sort determinism, handling connecting-player ping/loss safely, and tightening table/header formatting.

Changes:

  • Make player row ordering deterministic on sort-key ties by adding an ascending-userid tie-breaker in the comparator.
  • Avoid querying latency/loss for clients not yet in-game, and ensure those players sort to the bottom in ping-ordered lists.
  • Unify state labeling/sort ranking via a PlayerState enum + GetPlayerState(), and adjust header/row formatting alignment.
File summaries
File Description
addons/sourcemod/scripting/Status.sp Adds deterministic tie-break sorting, consolidates player state logic, adjusts ping/loss handling for connecting players, and refines output formatting.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

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

Comment thread addons/sourcemod/scripting/Status.sp
sPlayerTime/sPlayerPing/sPlayerLoss/sPlayerAddr were left uninitialized
for bots (which skip the !bFakeClient block) and for still-connecting
players (bInGame == false), so stack garbage could end up printed in
the status row.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@Rushaway
Rushaway merged commit 8531da3 into master Sep 11, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants