W3 / DevelopersSDK 4.6.0Source & examples ↗

SDK 4: Warcraft catalogs and migration

SDK 4 connects live match objects to the Warcraft configuration and artwork for that exact patch. Import the optional @w3booster/sdk/game-data entry point. Catalogs and images are loaded from the static service; they are not bundled into your app or the SDK npm package.

SDK 4 uses protocol 4. Update the recorder, API, compositor and application bundles together. SDK 3 bundles cannot consume the changed contract. Install @w3booster/sdk@4, update your lockfile, rebuild your app and run its tests. Your generated application binding needs regeneration if its definition changed.

Instance, type and catalog identities

Value Meaning Join
match.id + unit.id One observed instance in one match UI keys and live updates
unit.typeId Case-sensitive unit or hero rawcode data.units.get(unit.typeId)
ability.typeId Actual ability rawcode, including variants data.abilities.get(ability.typeId)
upgrade.typeId + upgrade.level Upgrade rawcode and one-based level data.upgrades.get(typeId)?.levels[level - 1]
hero.inventory[index] Item rawcode in that inventory slot; empty string means empty data.items.get(typeId)
match.gameDataId Exact immutable generated dataset loadGameData(id)
match.gameVersion Observed Warcraft build version Display and diagnostics

Treat IDs as strings. Preserve rawcode case; do not strip ability variants or append a research level to an upgrade rawcode. Level zero is unlearned, not an alternative encoding for an ultimate ability.

Load once for the current revision

Load match.gameDataId when the revision changes, rather than on every state tick. Use an AbortController for your component/runtime lifetime. When a request finishes, verify that its revision still matches the current match before rendering it. The loader caches successful immutable results; failed and aborted loads can be retried. It validates the manifest, catalog checksum and game identity.

An absent revision or failed load does not make live state invalid. Retain live health, mana, queues and other observations, and omit unavailable static decoration. Never load current.json or a nearby patch as a fallback. Custom maps may override standard melee configuration; observed values remain authoritative.

import type { MatchState, Unit, ActiveUpgrade } from '@w3booster/sdk';
import { loadGameData, abilityCooldownsForState } from '@w3booster/sdk/game-data';

export async function catalogPanel(state: MatchState, unit: Unit, upgrade: ActiveUpgrade) {
    if (!state.match.gameDataId) return undefined;
    const data = await loadGameData(state.match.gameDataId);
    const graphics = state.match.isReforged ? 'reforged' : 'classic';
    return {
        cost: data.units.get(unit.typeId)?.cost,
        supply: data.units.get(unit.typeId)?.supply,
        icon: data.assets.unitIcon(unit.typeId, { graphics }),
        research: data.upgrades.get(upgrade.typeId)?.levels[upgrade.level - 1],
        researchIcon: data.assets.upgradeIcon(upgrade.typeId, { graphics, level: upgrade.level }),
        cooldowns: abilityCooldownsForState(state, data),
        // Current observed values stay authoritative.
        hitpoints: unit.hitpoints
    };
}

// Sort a copy; SDK arrays and objects are immutable. Unknown cost stays last.
export function unitsByCost(units: readonly Unit[], data: import('@w3booster/sdk/game-data').GameData): Unit[] {
    const compareCost = (left: number | undefined, right: number | undefined) =>
        left === undefined ? (right === undefined ? 0 : 1)
            : right === undefined ? -1 : right - left;
    return [...units].sort((a, b) => {
        const left = data.units.get(a.typeId)?.cost;
        const right = data.units.get(b.typeId)?.cost;
        return compareCost(left?.gold, right?.gold)
            || compareCost(left?.lumber, right?.lumber)
            || (a.typeId < b.typeId ? -1 : a.typeId > b.typeId ? 1 : 0);
    });
}

Costs, supply and default stats

A unit definition exposes cost.gold, cost.lumber, supply.used, supply.provided, baseStats, buildTimeSeconds, isBuilding, and relationships in abilities, heroAbilities, upgrades, trains and builds. Fields such as cost or a base-stat value can be absent. Unknown is different from zero: a valid zero-supply unit must not be treated as missing.

Choose a sorting policy explicitly. The checked example above sorts by gold, then lumber, with unknown costs last and typeId as a deterministic tie-breaker. There is no universal gold-to-lumber conversion. For group totals, multiply known per-unit costs by group size; do not silently turn missing costs into free units.

await data.unitGameplay(typeId) separately loads the broader retained source configuration. It returns source-section dictionaries of strings. It is optional, not a second live-stat source or a promise of every World Editor field. The retained field policy describes the extraction and size budgets.

Artwork, upgrade levels and cooldowns

Choose graphics: 'classic' | 'reforged' from match.isReforged. Use data.assets.unitIcon, abilityIcon, itemIcon or upgradeIcon with the exact rawcode. Upgrade icon options take a one-based level; levels arrays use level - 1. The research and inactive roles select source-configured art. Single source frames may be shared across levels; ordered source frames retain their level-specific selection. Do not construct filenames or force a level suffix.

Unknown objects and objects without configured art return undefined. Hide the image when there is no URL; do not emit <img src="undefined"> or guess a Cancel icon. Country flags and Battle.net badges remain in @w3booster/sdk/assets.

Upgrade definitions supply category, maxLevel and per-level name, gold/lumber cost and research time. Use those values instead of a manual weapon/armor table. Ability definitions supply per-level cooldown, mana cost, cast time and range. abilityCooldown(ability, match.gameTime, data) and abilityCooldownsForState(state, data) derive standard-game cooldown estimates from the actual ability level and observed activation. Use game time so pauses and replay speed remain correct. Buffs or custom-map modifications can differ from the base configuration; unknown cooldowns remain unavailable.

Breaking API changes

SDK 3 SDK 4
HeroAbility.name HeroAbility.typeId
Upgrade name, aliases or level suffixes typeId plus separate level
/standard-game/icons, icon filename tables /game-data and data.assets
/standard-game/cooldowns Cooldown helpers in /game-data, requiring the exact catalog
normalizeUpgradeRawcode Preserve the actual typeId
isWeaponOrArmorUpgrade, weaponOrArmorUpgradeRawcodes Catalog upgrade category and maxLevel

/standard-game still supplies game conventions such as race/mode information, hero experience, game-time formatting and team ordering. It no longer supplies manual object configuration. Native applied HUD scale is forwarded as the 0.5–1.0 multiplier in gameContext.hudScale; apps must not reinterpret it as the retired raw 0–128 value.

See the API reference for every exported type and method. Test catalog load failures, unknown art, ability variants and multi-level upgrades when migrating an existing app.

SDK 4.1: item cooldowns and building upgrades

SDK 4.1 adds two optional live fields without changing protocol 4.0. Hero.inventoryCooldowns matches inventory slots by index and contains direct game timer observations or null. Building.upgrade contains the destination typeId plus the existing TimedProgress fields. The current building keeps its typeId until completion; cancellation or completion removes upgrade. These additions are available through both cloud and local transports. Existing SDK 4.0 consumers can continue running.

Use the destination ID with the current catalog to get its name and artwork. Progress is a completed fraction from zero to one; remaining and total seconds are game-time snapshots and can be null when unreadable. Do not advance them with wall-clock time. Inventory cooldowns follow hero visibility; building upgrade progress requires building and production access.

SDK 4.2 observations

APM, mana recovery, hero combat totals, local-player resources and stats provenance are additive in SDK 4.2. The guide also summarizes every change since the SDK 3 announcement.