Skip to content

Fix bots inflating list server populations by fully supporting ComputerPlayer observers - #391

Open
tainn wants to merge 2 commits into
BZFlag-Dev:2.4from
tainn:fix/bot-server-list-inflation
Open

tainn wants to merge 2 commits into
BZFlag-Dev:2.4from
tainn:fix/bot-server-list-inflation

Conversation

@tainn

@tainn tainn commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Currently, bots (most notably bzadmin and plugins utilizing ServerSidePlayer) artificially inflate the server's player counts on the master list server. This causes inaccurate server population statistics and forces server administrators to manually configure or run third-party plugins to hide their bots and comply with list server policies.

Historically, bots were forced to spoof their connection type as TankPlayer (human) due to two hardcoded roadblocks in the bzfs engine:

  1. bzfs explicitly rejected any ComputerPlayer that attempted to join the ObserverTeam.
  2. bzfs intentionally skipped sending the initial game state (existing players, teams, and flags) to ComputerPlayers to save bandwidth for legacy -solo dummy bots.

Because network bots (like bzadmin) need to join as observers and require game state to function, developers had no choice but to lie and identify them as TankPlayers (as noted by the ancient // because we like to lie :) comment in ServerSidePlayer.cxx). Consequently, they were continually caught by the isHuman() checks, which appended them to the list server PingPacket and prevented servers from correctly idling/sleeping.

This PR untangles these legacy workarounds by allowing bots to natively function as bots, eliminating the need to spoof humans:

  • src/bzfs/bzfs.cxx:
    • Removed the block that rejects ComputerPlayers on the ObserverTeam.
    • Removed the !isBot() exclusion block during MsgEnter processing, allowing network bots to receive the initial game state payload. (Also refactored this iteration loop using early continues to reduce nesting).
  • src/bzadmin/BZAdminClient.cxx:
    • Corrected the client to honestly send its MsgEnter as a ComputerPlayer.
  • src/bzfs/ServerSidePlayer.cxx:
    • Corrected the plugin API to initialize server-side bots as ComputerPlayer, removing the TankPlayer spoofing hack.

Compiled cleanly against Alpine/musl. End-to-end testing confirms that bzadmin successfully connects, correctly authenticates as a ComputerPlayer observer, receives full game state (e.g., /playerlist works perfectly), and is entirely ignored by bzfs's list server ping payload.

@blast007

Copy link
Copy Markdown
Member

Observers do not count when sorting the list of servers. So you don't need to change how bzadmin joins, which I believe makes the changes to bzfs.cxx unnecessary as well.

For SSPs, changing the player type to ComputerPlayer might make sense, but I'd have to check if there's any side-effects there. But in 2.4, I don't know if anyone joins an SSP as something other than observer. I don't think SSPs are functional enough to play as an actual player, so it's mostly used by bzfscron to run server commands.

@tainn

tainn commented Aug 30, 2026 •

Copy link
Copy Markdown
Contributor Author

bzadmin and bzfs.cxx changes reverted. Their change would allow us to not have to spoof, but it is otherwise not a functional change.

A server owner can write a short custom plugin that creates bots via bz_addServerSidePlayer() and calls bot->setPlayerData("FakePlayer", "", eRogueTeam). Because ServerSidePlayer.cxx historically hardcoded TankPlayer for these bots, they trick getTeamCounts() into counting them as active humans. The current active fix in ServerSidePlayer.cxx destroys this vector.

@blast007

Copy link
Copy Markdown
Member

The recent issue was with normal game clients running autopilot, which this PR doesn't address. One way to solve this when counting player is to check if a player is a bot or if they're running autopilot. There would be a delay until you sent a list server update once the autopilot state was updated. However, I'd also not want an update sent every time the state changed, since someone could toggle the state a bunch. So, maybe some sort of "this player used autopilot in the last X minutes" kind of tracking in bzfs, and just update if that state changes.

@tainn

tainn commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor Author

We could be stricter. A single change to the [auto] state and roger taking control could invalidate that player from counting to the player count for the entirety of their session, until they reconnect. Otherwise we have to track all of the events or do that periodically, neither of which sound too good. Fire on the first occurance and forget.

Sure, this then cuts out the viable situation of a legit player going autopilot and then coming back for the remainder of the session, but realistically, how often does that happen? Mostly people either idle before coming back to play, or they join the observers and then join back in as the players, potentially restoring their previous score if the plugin is used.

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