0.2.0: log kills, bomb plants and defuses as they happen; leave warmup out of match stats

This commit is contained in:
Astra 2026-10-04 21:36:31 +01:00
parent 905acd8f1d
commit bba0471f20
5 changed files with 144 additions and 9 deletions

View file

@ -7,12 +7,16 @@ Records every player's time on the server in its own MySQL/MariaDB database:
- **Segments** inside each session: stretches where the player's team (unassigned, spectator, T,
CT) and alive/dead state didn't change. Per-hour, per-team, alive/dead and spectator time all come
from these with SQL; see [Queries](#queries).
- **Events**, as they happen: every kill (weapon, headshot, no-scope, through smoke, wallbang,
blind, victim), bomb plant and bomb defuse (0.2.0+).
- Running totals per player, nickname history, and a count of players online every 5 minutes.
It replaces ConnectHistory. Player IPs are never stored: the IP is only used, on join, to look up a
country and city.
Warmup counts like any other time. Bots and SourceTV are ignored.
Warmup counts as playtime like any other time, but not toward match stats (kills, deaths, assists,
headshots, damage, MVPs, score, rounds) or events (0.2.0+; before that it counted for everything).
Bots and SourceTV are ignored, except that a kill of a bot is logged with `victim_bot` 1.
## Setup
@ -90,6 +94,11 @@ Every second, and right after `player_team`, `player_spawn`, `player_death` and
change closes the current segment and opens the next, so segment times are exact to the second.
Sessions close on `player_disconnect` (with the reason), on map end and on unload.
Match stats come from the game's own per-player counters, read every second. Only what they gain
outside warmup counts, so the session's totals leave warmup out. `player_death`, `bomb_planted` and
`bomb_defused` are logged to `pt_events` the moment they happen, except in warmup. A kill is logged
for a tracked killer; suicides and team kills aren't.
Database writes run in order on one background task, never on the game thread. When the database is
unreachable (or refuses the login), writes go to `plugins/PlaytimeHistory/spool.jsonl` and are sent,
in order, once it's back; `css_pt_status` shows how many are waiting. Writes are keyed, so sending
@ -111,6 +120,7 @@ All times are UTC (`UTC_TIMESTAMP()`, not `NOW()`, when comparing).
| `pt_nicknames` | Every name a SteamID has used, with first/last seen and times seen. |
| `pt_servers` | `id`, `address`, `hostname`, first/last seen. |
| `pt_online_snapshots` | Players (humans), bots and slots online, every `OnlineSnapshotIntervalSeconds`. |
| `pt_events` | `kind` 1 kill, 2 bomb planted, 3 bomb defused; `steamid64` is who did it, with `at`, `map`, `team` and `session_key`. Kills add `weapon` (as the game names it: `taser` is the Zeus, knives are `knife`, `knife_t`, `bayonet` or `knife_<skin>`), `headshot`, `noscope`, `thrusmoke`, `wallbang`, `blind`, `victim_steamid64` and `victim_bot`. Plants and defuses add `site`. |
| `pt_migrations` | Applied migrations. |
## Queries
@ -180,6 +190,22 @@ WHERE steamid64 = ? AND ended_at IS NOT NULL
AND started_at >= '2026-10-01' AND started_at < '2026-11-01';
```
The most bomb plants, defuses, knife kills, Zeus kills and headshots in the last 7 days (kills of
bots left out):
```sql
SELECT p.last_nickname, e.steamid64,
SUM(e.kind = 2) AS plants, SUM(e.kind = 3) AS defuses,
SUM(e.kind = 1 AND (e.weapon LIKE 'knife%' OR e.weapon = 'bayonet') AND NOT e.victim_bot) AS knife_kills,
SUM(e.kind = 1 AND e.weapon = 'taser' AND NOT e.victim_bot) AS zeus_kills,
SUM(e.kind = 1 AND e.headshot AND NOT e.victim_bot) AS headshots
FROM pt_events e JOIN pt_players p USING (steamid64)
WHERE e.at >= UTC_TIMESTAMP() - INTERVAL 7 DAY
GROUP BY e.steamid64
ORDER BY plants DESC
LIMIT 10;
```
Who's online now:
```sql