AdminStealth/README.md
Astra 33feda8179 AdminStealth 0.3.12: keep hidden admins off the team select screen
Hidden admins skip the team screen on reconnect (moved to spectators until re-hidden), never
receive the server's team menu message, and a pick from the screen M opens is answered by
telling only their client they joined spectators. The restore runs css_hide at most once, since
it toggles. Each command listener gets its own delegate: CSS keys listeners by handler, and
reusing one orphaned the first registration, which then swallowed its command.
2026-09-28 11:23:10 +01:00

69 lines
3.9 KiB
Markdown

# AdminStealth
A companion to CS2-SimpleAdmin's `css_hide` (`!hide`, `@css/kick`). SimpleAdmin's hide moves the
admin off the scoreboard. This plugin makes it look like they left the server:
- When an admin hides, every other player gets a `player_disconnect` event for them, sent to each
client only. The server and other plugins never see it, so the admin stays connected.
- While an admin is hidden, their team changes, their death and their real disconnect are not
broadcast to clients.
- Hiding lasts until the admin unhides. Hidden admins are saved by SteamID in
`configs/plugins/AdminStealth/hidden.json`. When one reconnects, or on a map change (SimpleAdmin
forgets hidden admins on both), their join isn't announced, the plugin runs `css_hide` for them
again once SimpleAdmin has loaded their permissions, and tells them they're still hidden. After
five tries (about 12 seconds) it gives up, forgets them and tells them they're visible.
- A hidden admin can't join a team or go to spectators (`jointeam` and `spectate` are blocked
with a chat message). If the game or another plugin puts them on a team anyway, which makes
SimpleAdmin unhide them, they're hidden again straight away.
- On reconnect or map change, a hidden admin is moved to spectators 0.1 s after connecting, so
the team select screen doesn't open, until the restore hides them again.
- The team select screen: the server's "team" menu message (`CS_UM_VGUIMenu`) is never sent to
a hidden admin. M opens it on the client regardless, and a player with no team can't close it
without picking, so a pick is answered by telling only that client it joined spectators
(with `sv_disable_teamselect_menu` on around it); nobody else sees a team change.
- Restoring runs `css_hide` at most once: it toggles, so a second run could unhide them.
Needs our SimpleAdmin fork (1.8.2b-zio2 or later), where moving to spectators doesn't unhide a
hidden admin. Never hot-reload CS2-SimpleAdmin while this runs: CSS keeps handing out the old
instance's API until the server restarts.
- `status` from a player's console is blocked and prints nothing. It still works from the server
console and RCON.
The plugin listens for `css_hide` under whatever aliases SimpleAdmin's
`configs/plugins/CS2-SimpleAdmin/Commands.json` gives it (by default `css_hide` and `css_stealth`),
so adding aliases there (e.g. `css_invis`) works here too after a restart.
WebPanelBridge leaves hidden admins out of `css_webpanel_status`, so simpleadmin-web doesn't show
them either.
Built for CounterStrikeSharp **1.0.376** (`net10.0`) on Metamod:Source 2.0.0.1469, and needs
CS2-SimpleAdmin 1.8.2b's shared API (`CS2-SimpleAdminApi`). `lib/CS2-SimpleAdminApi.dll` is a
compile-time copy of the server's `shared/` one and isn't shipped. Without SimpleAdmin loaded, only
the `status` block works.
## Limits
- After a reconnect or map change, the admin is visible to SimpleAdmin (and so on the web panel) for
the few seconds it takes to hide them again.
- Unhiding doesn't announce the admin as joining again.
- The server browser and trackers get the player list from a separate server query, which this
doesn't touch, so they still list a hidden admin.
- Reloading CS2-SimpleAdmin on its own leaves this plugin (and WebPanelBridge) talking to the old
instance until a server restart.
## Install
Build with `cd plugins/AdminStealth && ../../build.sh`. Then copy the contents of
`compiled/AdminStealth/` to `game/csgo/addons/counterstrikesharp/plugins/AdminStealth/` on the
server.
Or install a release, which unpacks into `game/csgo/`:
```
tar -xzf AdminStealth-<tag>.tar.gz -C /srv/cs2/game/csgo
```
To publish one, commit, bump `ModuleVersion`, then run
`FORGEJO_TOKEN=... ./release.sh v<ModuleVersion>`. It rebuilds the plugin from the committed
source in the SDK container, tags HEAD, and uploads `AdminStealth-<tag>.tar.gz` to the git.zio.sh
release. The plugin has no config. The release never includes `hidden.json`.