Player statistics, economy graphs and loss windows
Available in SDK 4.6. These optional fields require a matching recorder and platform deployment; handle their absence when connected to older clients.
In self-play, statistics, loss counters and outcomes are restricted to the actual local player. Observer/replay matches may expose all participants. Existing grants apply independently on the API and local-recorder paths. Missing means unavailable or ungranted; zero and empty collections mean observed values.
| Field | Content | Grant |
|---|---|---|
match.outcomes |
Explicit won, lost, draw by participant ID |
match:read |
match.gameName |
Observed lobby name | match:read |
player.statistics economy |
Gross goldMined, goldCredited, goldUpkeepLost, goldDiversionTax, lumberCredited, lumberUpkeepLost, lumberDiversionTax |
resources:read |
player.statistics metadata |
Native handicapPercent, realTimeApm, slotState, aiDifficulty, racePreference, playerRace, ten timeInUpkeepMs entries |
resources:read |
player.statistics.items[typeId] |
Cumulative collected, purchased, sold, used, destroyed, damageDealt, healingDone |
heroes:read |
player.statistics.heroes[instanceId] |
typeId, level, nextLevelExperience, deaths, total/hero/self/building kills, timeAliveMs, and abilities |
heroes:read |
heroStatistics.abilities[typeId] |
Damage/healing, learned level, native hero classification and an observed active cooldown timer |
heroes:read |
player.statistics.units[typeId] |
currentAmount, totalAmount, isPeon, isFunctionalPeon, damage dealt/received and healing |
units:read |
player.losses.units / .buildings |
Sampled deaths by type, game time and completeness | units:read / buildings:read |
poi.ownerSlot |
Native owner slot, including neutral slots 24–27 | pois:read |
Existing hero, inventory, resource, research, building and POI snapshots remain
canonical for their live values. Resolve names, icons, configured ability cooldowns,
item levels, upgrade maximum levels and standard stock limits through the exact
match.gameDataId catalog. These definitions describe the standard ruleset;
custom-map overrides must not be presented as measured standard catalog values.
goldMined is the gross JASS score: credited gold plus upkeep loss. Resource totals
are actual resource units. The engine also increments destroyed when an item's
last charge is consumed; destruction is diagnostic and must not add a second loss.
A sale is a distinct native event, never inferred from an empty inventory slot.
Hero IDs preserve full instance identity. Ability timers use TimedProgress and
are omitted when inactive or unreadable. Ability classification uses loaded native
data, including available instance overrides. timeAliveMs uses the engine's
wall clock, so replay pause/speed affects its relation to match time. Upkeep tier
length and timing likewise preserve engine semantics.
Unit totalAmount counts retained engine instances, including corpses. It is not
an ever-trained counter. Unit-type damage/healing sums those retained instances
and can decrease when corpses disappear. isFunctionalPeon is Warcraft's worker
predicate, not an idle-worker estimate.
Death counters count observed alive-to-dead transitions. They ignore heroes,
illusions, transfers, type changes and unreadable/disappearing instances. They
currently carry complete: false: attachment time and sampling can miss deaths.
Outcomes use explicit native results only. Leaving a replay, closing Warcraft or
a player departure never implies a winner. Rewinds reset observations; known
results survive the terminal snapshot. The existing own-player match.result
contract is preserved.
Graphs and rolling loss windows
The optional @w3booster/sdk/analytics entry has no transport, timer, or persistence.
Push each state from your existing subscription. Reset the history on a disconnect
or known delivery gap; it automatically resets on match, mode, scope, catalog, or
backward-clock changes. Initial counters establish a baseline: they do not invent
past event timestamps. New consumers collect their own history.
import type { MatchState } from '@w3booster/sdk';
import type { GameData } from '@w3booster/sdk/game-data';
import { createMatchHistory } from '@w3booster/sdk/analytics';
export const history = createMatchHistory({ maxSeconds: 7200 });
// Call once for each synchronized state from your existing subscription.
export function observe(state: MatchState, playerId: string, catalog?: GameData) {
history.push(state);
const economy = history.economy(playerId);
// Supply the exact match.gameDataId catalog; mismatched revisions are rejected.
const recent = history.window(playerId, 30, catalog, {
kinds: ['unit-lost', 'building-lost', 'item-used'],
});
return { economy, recent }; // Render covered, complete and boundaryUncertain too.
}
// Call on disconnect, known delivery gaps, or session disposal.
export function resetHistory() { history.reset(); }
Use the exact catalog revision named by this match; mismatched catalogs are
rejected. Costs are standard-melee estimates, not actual measured expenditures;
custom maps can override them. Missing cost data yields null instead of zero.
Item-use costs are apportioned across the catalog's starting charges. Sold-item
costs require an explicit soldItemRefundRate (for example, 0.5 if that is your
ruleset), and use purchase price minus proceeds. Never label every missing item
as sold or consumed. Filter with kinds to choose which loss categories to show.
Each event has a (fromGameTime, gameTime] observation interval. boundaryUncertain
means an event's interval straddles the selected window start. covered means the
window is retained and observed for every requested category; it does not promise
complete death detection. Check complete separately. Use those flags in the app
when presenting partial comparisons.
Default retention is 7,200 game seconds, 15,000 economy samples per player, and
20,000 loss events total. Limits are configurable and bounded. Missing feeds reset
counter baselines so reconnects do not manufacture events during a gap. Call
reset() when disposing the app session. Returned arrays, events, and summaries
are immutable. Scoreboard persistence and one-point-per-map deduplication remain
app policy; deduplicate using the match ID and account for replay seeks.
Production entries additionally expose optional buildType: research, unit,
or reviving, under the existing production permission. Revival classification
uses the native queue's full unit reference; ordinary categories use the exact
match catalog. Unknown or stale references omit the kind. Progress and timers
retain their existing semantics, including cancellation and restart.