Busiest hours and the heatmap count the different players on T or CT in
each hour, open segments included, instead of averaging player-hours, so
one player for part of an hour is 1, not 0.38. Their descriptions end in
the span covered (Last 30 days, or Since <date>). Side-by-side chart panels
match heights, and Players per day notes its busiest day.
Dropped the page descriptions on Bans, Gags & mutes, Staff and Playtime,
and the Verified badges on the staff Overview scoreboard and drawer header;
the Verification page and the drawer's Verification section still show it.
The GroupVerify DB test now checks the staff drawer, since the public site
says nothing about verification.
K/D, headshot %, kills and deaths (drawer, Top players, staff session
lists) now come from pt_events, so kills of bots and deaths to bots don't
count, as in Records; damage per round and MVPs are gone, since only the
game's counters have them and those include bots. Average ping and the
record count footnote are no longer shown. The server header's grid now
runs behind the whole page.
Busiest hours and the heatmap averaged over 30 days (4 weeks) even when
recording began yesterday; they now use only the days since it began, and
say so. Bars capped their scale at 1, so a leader with 0.5 h got half a
bar. The hours tile keeps a decimal under 10, and K/D shows - with no
kills or deaths yet.
Records: the most bomb plants, defuses, knife, Zeus and headshot kills for
the last 7 days, 30 days or all time, and each player's counts, when
PlaytimeHistory 0.2.0's pt_events is there. The public site's top bar now
sticks the whole way down, Playtime comes after Server, and only the
player drawer scrolls while it's open.
A public Playtime tab and player-drawer playtime, and staff-only figures
(who's on, staff activity, disconnect reasons, countries, names, sessions)
for @css/generic on the staff panel and on the public site when signed in.
Hidden unless SAW_PT_DSN is set and its tables are there.
Notifications: staff turn them on per device from a new Notifications page,
pick each type (bans, gags, mutes and silences added or lifted, server down
and back up) and quiet hours. A watcher polls SimpleAdmin's tables, so in-game
penalties are sent too. Web Push with VAPID and RFC 8291 encryption in
internal/push, standard library only. Tables in sql/push.sql, created at
startup; the VAPID key is made on first start and kept in saw_settings.
Penalty notifications link to the public list searching for the player
(#bans?q=<steamid64>). The Android app delegates notifications (versionCode 3).
Caching: pages, scripts and styles are served with Cache-Control: no-cache
and an ETag, so a deploy shows up at once instead of after Cloudflare's
default 4-hour browser cache.
- Server settings > Console sends a raw console command for staff with @css/rcon
(POST /api/admin/rcon). It doesn't wait for the server; the output is only logged.
- Staff & ranks and Server settings panels fold up by clicking their heads. All but
Ranks and Server start folded; a folded Ranks panel shows the selected rank.
- The Members panel has an Add button that opens Add staff with that rank picked.
- The public rank log shows a rank being given as Promoted and taken away as Demoted.
The help text sat inside each field, so the buttons lined up with it rather than the inputs, and
its long unbroken URL made the page too wide on phones. It's now one short line under the row.
Root sets GroupVerify's clan_tag (the scoreboard tag CS2-Tags gives verified players without a
rank) next to the Steam group. Validated like the plugin (12 UTF-16 units, no quotes, ; or \),
saved to gv_settings and sent as css_gv_clantag when the plugin is loaded. Only changed fields
are sent.
GroupVerify 0.3.0 checks players with the Steam Web API as they join, so the group list is now
"Confirmed group members" with first/last confirmed dates.
Shown only where GroupVerify is: staff get the Verification page once its gv_* tables are in
the database, and the public site shows "Verified" only while it's on (enabled, with a group)
and not missing from css_plugins list, which the poller reads once a minute over RCON.
- Verification page: plugin state and version, Steam group, saved member list, overrides.
- Overrides (@zio/verify, not on yourself unless Root): give, change, remove; player drawer
shows why a player is or isn't verified.
- Root sets the group and turns it on/off: saved to gv_settings, and sent as css_gv_* when the
plugin is loaded so it applies at once.
- gv_* times use GroupVerify's own timezone setting.
- MySQL integration test (SAW_TEST_DSN), unit tests for plugin list parsing and the show rule.
Staff without @zio/webpanel (or @css/root) no longer see the page: the API refuses it and the
panel leaves it out of the sidebar. The flag is offered in the rank editor.
The rank editor only listed @css/... flags, so a @zio/ flag showed up only on a rank that
already held it and couldn't be added to others. List the flags admin_overrides.json uses, plus
@zio/penalties from our SimpleAdmin fork.
The public staff page, the staff panel's staff list and the signed-in badge show each member's
Steam avatar over their initial. The panel fetches it from the profile XML (no Web API key),
keeps it in memory for a day (failures for an hour, one shared fetch per player) and serves it
from /avatar/<steamid> with a day's browser caching, so the CSP stays img-src 'self' and
visitors never contact Steam. Only SimpleAdmin admins are served; anything else falls back to the
initial.
Bans and comms saved without a player name (SimpleAdmin's offline css_addban etc.) show the
player's latest name from sa_players_ips, and the panel writes that name onto new rows it claims.
The mobile sidebar closes from a Close button, the backdrop or Escape, since it covers the Menu
button. The public player drawer drops "Right now" and "Free to play and talk." and puts the
Steam profile link after the SteamID. Adds @css/bypassipban to the permission checkboxes.
The score caption says "Warmup, no rounds yet" during warmup and "Rounds
won, T vs CT" otherwise. Each team panel on the public page shows its
player and bot count, and its score as rounds won, or a Warmup label
during warmup. The top navigation scrolls sideways on narrow screens
instead of overflowing.
CS2 tags a command's output with the id of the empty end packet when both
arrive together, and replies to the end packet with a bare \x00\x01. The
client dropped the output as stale, so the panel reported WebPanelBridge as
missing. Also log each new kind of poll failure once, and recovery.