HoldfastCensusLite
Privacy-friendly stats tracker for Holdfast: Nations At War - passively captures only YOUR per-round statistics and reports them to a stats backend of your choice.Holdfast Census Lite
Holdfast Census Lite is a privacy friendly statistics tracker for Holdfast: Nations At War. It passively records your own per round performance stats like shots, accuracy, damage, kills, deaths, score, classes, weapons and reports one summary per round to the stats backend of your choice.
It is built for any player or regiment who wants round data: point it at your community's stats backend and every member who installs the mod contributes their own numbers to your leaderboard. It reads the same game events the client already receives during normal play, no gameplay advantage, no server-side installation, no game-file changes.
This is the self-only variant: it never records other players. The full Census mod did alredy finished development and will be released after i now that its allowed. Never install both mods at the same time, they would report every round twice.
What data does it collect?
Everything comes from data the game client already receives while you play (the official script-mod event bus, the server-replicated scoreboard, and health-change packets). The mod only reads.
Collected (your data only):
- Your per-round stats: shots fired, dry shots, hits, accuracy
(
hits_from_damage / shots_fired), damage dealt/received, kills, deaths, teamkills, suicides, score, classes played, weapons used, plus the server-authoritative scoreboard row for you - Your 1-based leaderboard place on your faction/team when a round completes
- Kill records you took part in: your kills and deaths store the opponent's name and Steam id so your kills/deaths stay attributable on a leaderboard
- Match metadata: round id, server name, map, factions, game mode/type, friendly-fire and stats-tracking flags, round start/end times
- Your Steam id and in-game name; how many players were on the server
Never collected: text chat, voice, admin actions, blocks, ping/IP addresses, hardware or OS info, positions or camera data and nothing about other players beyond the opponent name/id inside your own kill records.
Where is the data sent?
At the end of every played round (round end, map change, or when you leave the
server) the mod builds one JSON document and sends it with a plain HTTP
POST to the URL configured in Tracker.EndpointUrl.
- The payload is plaintext JSON not encrypted. You can audit every byte:
with default settings each payload is also written to
BepInEx/plugins/dev.gmrrh.census.lite/cache/dumps/before sending. - Requests carry an
X-Census-Signatureheader (HMAC-SHA256 over the body) so a backend can reject edited/forged payloads. - Out of the box the mod sends nothing: the default endpoint is a local
testing address (
http://127.0.0.1:8000/...). SetTracker.EndpointUrlto your community's stats backend to enable reporting. Any regiment can run their own backend the contract is a single POST endpoint per round. - If the backend is unreachable, payloads are cached on disk and retried
automatically later (up to
Tracker.CacheMaxFilesfiles). - Rounds played on servers you blacklist, or on servers with stats tracking disabled (if you enable that option), produce no payload at all.
Install
- Install Thunderstore Mod Manager or r2modman for Holdfast: Nations At War.
- Install Holdfast Census Lite from this page the required BepInEx pack is installed automatically as a dependency.
- Play. Round summaries are reported automatically; nothing else to do.
Kurzanleitung (Deutsch)
- Thunderstore Mod Manager oder r2modman für Holdfast: Nations At War installieren.
- Diese Mod installieren das benötigte BepInEx-Pack wird als Abhängigkeit automatisch mitinstalliert.
- In
BepInEx/config/dev.gmrrh.census.lite.cfgdieTracker.EndpointUrlauf die Stats-Backend-Adresse eurer Community setzen (Standard ist eine lokale Testadresse, d. h. es wird nichts gesendet). - Spielen: nach jeder Runde wird automatisch eine Zusammenfassung gemeldet.
First launch check
After a modded launch, BepInEx/LogOutput.log should contain:
[Census] Hook applied: map-init anchor (round details)
[Census] Hook applied: mods-loaded anchor (event registration)
[Census] Hook applied: scoreboard snapshot
[Census] Hook applied: damage attribution (optional)
[Census] Hook applied: client disconnect (local-left flush)
[Census] Hook applied: round-end leaderboard rank
[Census] Hook applied: non-melee kill distance
[Census] Payload signing self-test: ok
[Census] Holdfast Census Lite v1.7.0 (self-only) ready. Endpoint: …
After finishing a round you should see
[Census] Round payload queued (cause=round-end, …) — or
[Census] Server filter: '<name>' blocked (…) — recording disabled for this map.
when the server matched your blacklist/whitelist settings.
Configuration reference
Config file (created on first launch):
BepInEx/config/dev.gmrrh.census.lite.cfg
(your mod manager's config editor can edit it too — changes apply from the
next map load).
[Tracker] — capture & reporting
| Key | Type | Default | Effect |
|---|---|---|---|
Enabled |
Bool | true |
Master switch. false = nothing is captured, nothing reported. |
EndpointUrl |
String | http://127.0.0.1:8000/api/ingest/mod |
URL the round payloads are POSTed to. The default is a local testing address nothing leaves your machine until you change this. Set it to your regiment/community stats backend to enable reporting. |
IngestToken |
String | (empty) | Optional shared token, sent as X-Ingest-Token header. Backends use it for routing/rate-limiting; it is not a secret (the mod is public). |
BearerToken |
String | (empty) | Optional JWT, sent as Authorization: Bearer <token> in addition to the ingest token for backends that require authentication. |
ReporterSecret |
String | (empty) | Personal per-reporter secret, sent as X-Reporter-Secret header. Obtained from your stats backend admin; binds your Steam ID so reports cannot be forged. |
MinPlayers |
Int | 1 |
Rounds with fewer players on the server are not reported (records still exist locally in test mode). Raise this to skip quiet/practice rounds e.g. 10 reports only rounds with at least 10 players. |
SkipServersWithStatsTrackingDisabled |
Bool | false |
Many official servers run with stats tracking off. false (default) = record anyway, the payload notes the server's flag. true = capture nothing on such servers. |
UseServerBlacklist |
Bool | false |
Enables the server-name blacklist: no round on a matching server is captured or reported. The blacklist wins over the whitelist. |
ServerBlacklist |
String | (empty) | Comma- or semicolon-separated server-name fragments (see below). |
UseServerWhitelist |
Bool | false |
Enables the server-name whitelist: rounds are captured only on matching servers. Leave false to record everywhere. |
ServerWhitelist |
String | (empty) | Comma- or semicolon-separated fragments (see below). An empty list with the whitelist enabled allows every server fill it or leave the whitelist off. |
CacheMaxFiles |
Int | 200 |
How many unsent payloads are kept on disk (cache/pending_*.json) when the backend is unreachable, for automatic retry. Oldest files beyond the cap are dropped. |
[Debug] — diagnostics
| Key | Type | Default | Effect |
|---|---|---|---|
DebugDumpPayload |
Bool | true |
Writes every payload JSON to cache/dumps/dump_<time>_<cause>.json before sending, your built-in audit log of exactly what leaves your machine. Set false to disable. |
TestMode |
Bool | false |
Full test mode: journals every captured event to cache/dumps/testrun_*.log, always dumps payloads, and disables network sending entirely. Use to try the mod without any data leaving your PC. |
VerboseEvents |
Bool | false |
Logs every captured game event to LogOutput.log (very spammy, debugging only). Implied by TestMode. |
Server blacklist / whitelist
Matching is case-insensitive "contains": an entry matches when the full server name contains it anywhere. Entries are separated by commas or semicolons. The filter is evaluated once per map load; a blocked server logs one line and produces no payload.
[Tracker]
UseServerBlacklist = true
ServerBlacklist = Training, DuelsOnly
UseServerWhitelist = true
ServerWhitelist = MyCommunity EU, MyCommunity US
UseServerBlacklist = true+ServerBlacklist = Training→ never records on servers with "Training" anywhere in the name.UseServerWhitelist = true+ServerWhitelist = MyCommunity EU, MyCommunity US→ records only on those servers.- Both enabled → a server matching both is blocked (blacklist wins).
Privacy
- Only your own gameplay statistics are captured and sent. Other players appear solely as Steam ids inside your own kill records.
- Everything is stored locally in readable JSON first (
DebugDumpPayload/TestMode), audit any payload before it is ever sent. - The payload and signature are tamper-evidence for the backend, not encryption; the backend you point the mod at receives exactly what you can read in your dumps.
- Uninstalling removes the DLL; leftover config/cache folders under
BepInEx/plugins/dev.gmrrh.census.lite/can simply be deleted.
Links
- Full variant will (hopefully) follow soon
