A leaderboard is one number per player, ordered. Most of what a game counts is not that: kills, deaths, jumps, metres, seconds played, a top speed, a level. Those are many numbers per player, accumulated.
Requires dot-core. dot-auth is optional and is never imported.
The only thing every party has to agree on is how a new reading meets an old one. So a stat declares a kind — add, replace, keep the higher, keep the lower — and that rule is applied identically by the game counting, the reporter coalescing and the site storing.
var schema := DotStatsSchema.new()
schema.define(&"kills").publish = true
schema.define(&"top_speed", DotStatsDef.Kind.BEST, "Top speed").publish = true
schema.define(&"level", DotStatsDef.Kind.GAUGE) # kept, never reported
var tracker := DotStatsTracker.new()
tracker.schema = schema
tracker.report_to_backbone = true
tracker.reporter.client = backbone # dot-auth's DotBackboneClient
add_child(tracker)
tracker.begin(player_key, display_name) # the SCOPED key, never the account id
tracker.record(player_key, &"kills")
tracker.record(player_key, &"top_speed", 41.2)
tracker.end(player_key)
Every 30 seconds — and once more on the way down — the tracker sends each player’s delta since the last report. What crosses the wire is a delta, which is what lets two servers report one player without either overwriting the other.
The other surface
A player’s own client files its own figures, with the player’s token and no integration credential anywhere near it:
var mine := DotStatsClient.new()
mine.schema = schema
mine.client = auth_client # dot-auth's DotAuthClient
add_child(mine)
mine.record(&"launches")
var held := await mine.fetch_mine()
Both land on the same rows, because a client files under the member’s key for the app’s own scope. Keep anything competitive on the server; this surface is for a diary.
Where a game plugs in
- DotStatsSchema / DotStatsDef
Declare each stat once: an id, a
Kind(COUNTER,GAUGE,BEST,LOWEST), a display name, andpublish. A stat withpublishoff is kept locally and never reported.- DotStatsTracker
The server surface.
begin,record,end, and a reporter you point at aDotBackboneClient.- DotStatsClient
The player surface, on
DotAuthClient.- DotStatsValues
The accumulated set, and the merge that
DotStatsDef.mergedefines.- Signals
recorded,refused,reported.
It refuses an account id as a player key
Before it leaves the server. The key must be the scoped derivation — see
dot-user.
The merge rule is deliberately duplicated
DotStatsDef.merge in the addon and the site’s own merge are the same function,
on purpose: a rule that lives only in the game is one the site cannot apply to a
batch, and any disagreement between them is a wrong number with nothing failing.
Both sides test it directly.
