scmJS docs

Shared types

The declarations more than one group names — everything else is documented on the page of the group that uses it.

ChkSectioninterface

interface ChkSection

CHK is a flat stream of chunks: 4-byte name, int32 length, then that many bytes.

StarCraft applies chunks sequentially into fixed-size buffers, so a section that appears twice is not "last one wins" — the later copy overwrites only as many bytes as it carries. Protected maps lean on this constantly, so the reader keeps every occurrence in file order and layer() reproduces the overwrite semantics.

name: string

4-character chunk name, latin1. May contain junk in protected maps.

offset: number

Byte offset of the chunk's name within the CHK.

declaredSize: number

Length field as written, which may disagree with data.length when truncated.

data: Uint8Array
truncated?: boolean

Set when the declared size ran past the end of the file.

ChkFileinterface

interface ChkFile
sections: ChkSection[]
trailing?: Uint8Array

Bytes after the last parseable chunk header, if any.

StringTableinterface

interface StringTable

STR/STRx string table.

Index 0 means "no string" and is never stored. Indices are referenced from TRIG, MRGN, SPRP and friends — several of which we round-trip as raw bytes — so the table must keep its index space stable across a save. Entries are therefore addressed by position, never renumbered.

strings: (string | null)[]

strings[i] is string index i; slot 0 is always null.

extended: boolean

True when the source section was STRx (Remastered, 32-bit count and offsets).

UnitRecordinterface

interface UnitRecord
serial: number
x: number
y: number
unitId: number
relationType: number
validProperties: number

Bit set of which "special properties" fields below are meaningful.

validStates: number
owner: number
hitPointsPercent: number
shieldPercent: number
energyPercent: number
resourceAmount: number
hangarUnits: number
stateFlags: number
unused: number
relatedSerial: number

SpriteRecordinterface

interface SpriteRecord
spriteId: number

sprites.dat id for a pure sprite, units.dat id for a unit sprite (see SpriteFlag.PureSprite).

x: number
y: number
owner: number
unused: number
flags: number

SpriteFlag bits. StarEdit writes a doodad's overlay sprite with the doodad's whole CV5 flag word here, so real maps carry the terrain bits (0x80, 0x100, …) too.

DoodadRecordinterface

interface DoodadRecord

One placed doodad, as StarEdit records it (the game never reads this section: it sees only the doodad's tiles in MTXM and its overlay in THG2). doodadId is the index into the tileset's dddata.bin, not a CV5 group; x/y are the pixel centre of the footprint, so the top-left tile is x / 32 - width / 2.

doodadId: number
x: number
y: number
owner: number
disabled: number

0 = enabled (every doodad in Blizzard's maps), 1 = disabled.

LocationRecordinterface

interface LocationRecord
left: number
top: number
right: number
bottom: number
nameIndex: number
elevationFlags: number

Bit 0 low ground, 1 medium, 2 high, 3 low air, 4 medium air, 5 high air.

Forcesinterface

interface Forces
playerForce: number[]

Force index (0-3) each of the 8 playable slots belongs to.

nameIndex: number[]

String index of each force's name.

flags: number[]

Bit 0 random start, 1 allied, 2 allied victory, 3 shared vision.

PlayerRgbinterface

interface PlayerRgb
rgb: [ number, number, number ][]

[r, g, b] for each of the 8 playable slots; only read when mode is Custom.

mode: number[]

A ColorMode per slot.

UnitSettingsinterface

interface UnitSettings
useDefault: Uint8Array

1 = the game uses units.dat / weapons.dat for this type and ignores the columns below.

hitPoints: Uint32Array

Fixed point: hit points × 256, like units.dat.

shields: Uint16Array
armor: Uint8Array
buildTime: Uint16Array

Game frames (15 per second at Fastest).

mineralCost: Uint16Array
gasCost: Uint16Array
nameIndex: Uint16Array

String index of the custom name, 0 for the default one.

weaponDamage: Uint16Array

Per weapons.dat id, always WEAPONS_BW long; UNIS only stores the first 100.

weaponBonus: Uint16Array

UnitAvailabilityinterface

interface UnitAvailability

Which players may build which unit types. Three tables, player-major (puniIndex): a per-player answer, the global default, and whether each player defers to it.

playerAvailable: Uint8Array

1 = the player can build the type; read only where playerUsesDefault is 0.

defaultAvailable: Uint8Array

1 = the type is available to every player that uses the default.

playerUsesDefault: Uint8Array

1 = the player takes defaultAvailable for the type.

UpgradeSettingsinterface

interface UpgradeSettings

Research cost per upgrade: a base and a per-level factor for minerals, gas and time. Struct of arrays over 61 upgrades; the original sections only store the first 46.

useDefault: Uint8Array

1 = the game uses upgrades.dat for this upgrade and ignores the columns below.

mineralCost: Uint16Array
mineralFactor: Uint16Array
gasCost: Uint16Array
gasFactor: Uint16Array
timeCost: Uint16Array

Game frames.

timeFactor: Uint16Array

UpgradeRestrictionsinterface

interface UpgradeRestrictions

How far each player may research each upgrade and where they start. Player-major tables (upgradeIndex), a global default pair, and a per-player "use the default" flag.

playerMax: Uint8Array
playerStart: Uint8Array
defaultMax: Uint8Array
defaultStart: Uint8Array
playerUsesDefault: Uint8Array

TechSettingsinterface

interface TechSettings
useDefault: Uint8Array

1 = the game uses techdata.dat for this ability.

mineralCost: Uint16Array
gasCost: Uint16Array
researchTime: Uint16Array

Game frames.

energyCost: Uint16Array

TechRestrictionsinterface

interface TechRestrictions

Whether each player may research each ability and whether they start with it. Same shape as UpgradeRestrictions.

playerAvailable: Uint8Array
playerResearched: Uint8Array
defaultAvailable: Uint8Array
defaultResearched: Uint8Array
playerUsesDefault: Uint8Array

CuwpSlotinterface

interface CuwpSlot
validProperties: number

CuwpValid bits.

validFields: number

CuwpField bits.

owner: number

Unused by the game; StarEdit writes 0.

hitPointsPercent: number
shieldsPercent: number
energyPercent: number
resources: number
hangar: number
stateFlags: number

CuwpState bits.

unused: number

The record's last four bytes, kept for fidelity.

ConditionRecordinterface

interface ConditionRecord
location: number

1-based location number, 0 = none.

player: number

PlayerGroup.

amount: number
unitId: number
comparison: number

Comparison for numeric conditions; SwitchState for Switch.

type: number

ConditionType.

resource: number

ResourceType / ScoreType / switch number, per type.

flags: number

ConditionFlag bits.

mask: number

EUD mask word; 0 in ordinary maps.

ActionRecordinterface

interface ActionRecord
location: number

1-based source location, 0 = none.

text: number

String index for text / comment / leaderboard label, 0 = none.

wav: number

String index of the WAV file name, 0 = none.

time: number

Milliseconds for Wait / Transmission / Talking Portrait; WAV duration for Play WAV.

player: number

PlayerGroup (first).

target: number

Second player / destination location / amount / AI script code, per type.

unitId: number

Unit id / ScoreType / ResourceType / AllianceStatus, per type.

type: number

ActionType (or BriefingActionType in MBRF).

modifier: number

Unit count (0 = all) / SetModifier / SwitchAction / Order / UnitState, per type.

flags: number

ActionFlag bits.

padding: number
mask: number

EUD mask word; 0 in ordinary maps.

TriggerRecordinterface

interface TriggerRecord
conditions: ConditionRecord[]
actions: ActionRecord[]
flags: number

TriggerFlag bits.

players: number[]

27 bytes, one per PlayerGroup; non-zero = the trigger runs for that group.

currentAction: number

The game's bookkeeping byte (offset 2399); StarEdit writes 0.

Scenariointerface

interface Scenario

A parsed scenario.

chk holds every original section in file order and is the fidelity anchor: sections we do not model are re-emitted byte for byte, so opening and saving a map we only partly understand does not destroy the parts we don't. Only names listed in dirty are re-encoded on save.

chk: ChkFile
dirty: Set<string>
warnings: string[]
type: string

TYPE, e.g. "RAWB" for Brood War.

fileVersion: number

VER: 59 original, 63 hybrid, 205 Brood War, 206 Remastered.

width: number
height: number
era: number

ERA value as stored; the meaningful tileset is tilesetId.

strings: StringTable
nameIndex: number
descriptionIndex: number
playerTypes: number[]
editorPlayerTypes: number[] | null

IOWN: StarEdit's own copy of the player types — what its Player Settings dialog shows, where the game reads OWNR. The editor keeps the two in step; a file where they differ (another tool wrote one and not the other) is flagged by Check Map. Null when the file has no section.

playerRaces: number[]
playerColors: number[]
playerRgb: PlayerRgb | null

CRGB, Remastered's per-slot colour choice; null when the file has none (every client then reads COLR).

forces: Forces
unitSettings: UnitSettings | null

UNIx if the file has one, else UNIS; null when it has neither (every type on its dat defaults).

unitAvailability: UnitAvailability | null

PUNI; null when the file has none (everything buildable by everyone).

upgradeSettings: UpgradeSettings | null

UPGx if the file has one, else UPGS; null when it has neither (every upgrade on its dat costs).

upgradeRestrictions: UpgradeRestrictions | null

PUPx else UPGR; null when absent (every player on the dat level caps, starting at 0).

techSettings: TechSettings | null

TECx else TECS; null when absent.

techRestrictions: TechRestrictions | null

PTEx else PTEC; null when absent (everything researchable, nothing researched).

wavs: number[] | null

WAV: 512 string indices of the map's sound paths; null when the file has no section.

cuwp: CuwpSlot[] | null

UPRP: the 64 Create Unit with Properties slots (the action names one 1-based); null when the file has no section.

cuwpUsed: boolean[] | null

UPUS: StarEdit's "slot in use" byte per CUWP slot; null when the file has no section.

tiles: Uint16Array

MTXM: what the game draws — terrain with the doodads stamped over it.

editorTiles: Uint16Array

TILE: StarEdit's copy of the terrain without doodads (a doodad's cells hold the ground it was placed on). Terrain brushes write both arrays; placing a doodad writes only tiles, and removing one restores its cells from here. A file without TILE starts with a copy of MTXM.

isom: Uint16Array | null
mask: Uint8Array | null
units: UnitRecord[]
sprites: SpriteRecord[]
doodads: DoodadRecord[]
locations: LocationRecord[]
triggers: TriggerRecord[]

TRIG, in execution order.

briefing: TriggerRecord[]

MBRF: mission briefings, same record layout with briefing action types.

switchNames: number[] | null

SWNM: string index per switch (0 = unnamed); null when the file has no section.

MapVersiontype

type MapVersion = "original" | "hybrid" | "broodwar" | "remastered";

TilesetIdtype

type TilesetId = "badlands" | "platform" | "install" | "ashworld" | "jungle" | "desert" | "ice" | "twilight";

StarCraft tileset reference data.

TerrainNameinterface

interface TerrainName

One ISOM terrain type: its id is the CV5 index of the flat left/right group pair that draws it, and the value the ISOM section stores for it.

id: number
name: string

Rectinterface

interface Rect
x0: number
y0: number
x1: number

Exclusive.

y1: number

Diamondinterface

interface Diamond
x: number
y: number

IsomCheckinterface

interface IsomCheck
rects: number

Rects that have tiles under them.

mismatched: number

Rects whose tiles are not what their ISOM resolves to (doodad tiles are excused).

FogModetype

type FogMode = "fog" | "clear";

SpriteKindtype

type SpriteKind = "pure" | "unit";

EditorLayertype

type EditorLayer = "terrain" | "doodads" | "units" | "sprites" | "locations" | "fog" | "clipboard";

The classic SCMDraft layer combo; "clipboard" is Cut / Copy / Paste.

TerrainModetype

type TerrainMode = "isom" | "rect" | "tile" | "blend";

DialogIdtype

type DialogId = "newMap" | "openMap" | "saveAs" | "exportImage" | "mapProperties" | "resizeMap" | "mapRevision" | "playerSettings" | "forceSettings" | "playerColors" | "unitSettings" | "upgradeSettings" | "techSettings" | "stringEditor" | "soundEditor" | "switches" | "locationList" | "unitProperties" | "locationProperties" | "spriteProperties" | "triggerEditor" | "textTriggerEditor" | "missionBriefing" | "cuwpEditor" | "replaceTerrain" | "autoStarts" | "testMap" | "symmetry" | "gridSettings" | "preferences" | "shortcuts" | "validateMap" | "statistics" | "importTriggers" | "exportTriggers" | "importStrings" | "exportStrings" | "find" | "about" | "confirmClose" | "plugins" | "confirmPlugin" | "pluginDialog" | "gameData" | "update";

Every built-in dialog, by the id openDialogAtom takes; DialogHost maps each to its component.

MapImageOptionsinterface

interface MapImageOptions
pixelsPerTile: number

Output pixels per map tile. 32 matches the game's art 1:1; 1 is a minimap.

units: boolean
sprites: boolean
locations: boolean
locationNames: boolean
startLocations: boolean
fog: boolean
fogPlayer: number

Whose fog is drawn (0-based player), when fog is on.

grid: number

Grid spacing in map pixels (32 = one tile); 0 for no grid.

rect?: Rect | null

The part of the map to draw, in tiles (exclusive x1 / y1). The whole map when absent. Everything is drawn in map coordinates and the canvas is translated, so a region looks exactly like that part of the full picture — a unit half outside the region still leans in.

UnitChangeinterface

interface UnitChange

Unit edits as invertible change lists, in the same spirit as terrain's TileChange. before/after are whole records: null before is an insertion at index, null after a removal, both set a replacement. Removals are listed highest index first so that applying them in order keeps the remaining indices valid; undo walks the list backwards and so re-inserts lowest first.

index: number
before: UnitRecord | null
after: UnitRecord | null

PlayerSlotViewinterface

interface PlayerSlotView
slot: number

0-based; the chrome shows it as slot + 1.

type: number
typeName: string
race: number
raceName: string
color: number | null

COLR index; null for the four unplayable slots.

colorHex: string | null

The colour the chrome shows for the slot (CRGB-aware).

rgb: [ number, number, number ] | null

The CRGB custom triple when one is in effect.

force: number | null

0-based force; null for the unplayable slots.

forceName: string | null

ForceViewinterface

interface ForceView
force: number

0-based.

name: string
flags: number
allied: boolean
alliedVictory: boolean
sharedVision: boolean
randomStart: boolean
players: number[]

0-based playable slots in the force.

WeaponViewinterface

interface WeaponView
id: number
name: string
damage: number
bonus: number

UnitTypeViewinterface

interface UnitTypeView
id: number
name: string

The game's name (or the custom one when the map sets it).

customName: string

The custom name the map sets, "" for the default.

useDefault: boolean
hitPoints: number

Whole hit points.

shields: number
armor: number
buildTime: number

Game frames.

mineralCost: number
gasCost: number
weapons: WeaponView[]

The type's ground and air weapons (a turreted vehicle's are its turret's), with the effective damage.

defaults: { hitPoints: number; shields: number; armor: number; buildTime: number; mineralCost: number; gasCost: number; weapons: WeaponView[]; } | null

units.dat / weapons.dat, null without the game data.

availability: { defaultAvailable: boolean; players: (boolean | "default")[]; }

PUNI: whether the type can be built by default, and per player ("default" where the player follows the default).

UpgradeLevelsViewinterface

interface UpgradeLevelsView
start: number
max: number
usesDefault: boolean

UpgradeViewinterface

interface UpgradeView
id: number
name: string
useDefault: boolean
mineralCost: number
mineralFactor: number
gasCost: number
gasFactor: number
timeCost: number

Game frames.

timeFactor: number
defaults: { mineralCost: number; mineralFactor: number; gasCost: number; gasFactor: number; timeCost: number; timeFactor: number; maxLevel: number; } | null

upgrades.dat, null without the game data.

levels: { defaultStart: number; defaultMax: number; players: UpgradeLevelsView[]; }

UPGR / PUPx: the default start and cap, and each of the 12 players' (effective, with usesDefault).

TechStateViewinterface

interface TechStateView
available: boolean
researched: boolean
usesDefault: boolean

TechViewinterface

interface TechView
id: number
name: string
useDefault: boolean
mineralCost: number
gasCost: number
researchTime: number

Game frames.

energyCost: number
defaults: { mineralCost: number; gasCost: number; researchTime: number; energyCost: number; } | null
state: { defaultAvailable: boolean; defaultResearched: boolean; players: TechStateView[]; }

PTEC / PTEx: the default column and each of the 12 players' effective state.

SoundRowinterface

interface SoundRow
slot: number
stringIndex: number
path: string

The path as the string table has it.

present: boolean

Whether the archive carries a member at that path.

size: number

Bytes in the archive, 0 when absent.

member: string | null

The archive member's name as stored (case may differ from the path).

usedBy: string[]

CuwpSlotViewinterface

interface CuwpSlotView

The slot as a patch-shaped view: null where the unit's default applies.

index: number
used: boolean
references: number

How many Create Unit with Properties actions name the slot.

hitPointsPercent: number | null
shieldsPercent: number | null
energyPercent: number | null
resources: number | null
hangar: number | null
cloaked: boolean | null
burrowed: boolean | null
inTransit: boolean | null
hallucinated: boolean | null
invincible: boolean | null
summary: string

Sidetype

type Side = "left" | "top" | "right" | "bottom";

PLUGIN_API_VERSIONconst

const PLUGIN_API_VERSION = 1

The version a host provides; a manifest that asks for a newer one is refused. It stays at 1 while the API is only used by the plugins in the scm-js organisation and grows with them — the first incompatible change after outside plugins exist bumps it.

Disposableinterface

interface Disposable
dispose(): void

PluginManifestinterface

interface PluginManifest

plugin.json, next to the entry file. Only name is required.

name: string
id?: string

Stable identifier (storage prefix, log prefix); derived from the name when absent.

version?: string
description?: string
author?: string
homepage?: string
entry?: string

Entry file relative to the manifest; plugin.ts by default, then plugin.js.

build?: string

A built, self-contained JavaScript bundle of the plugin, relative to the manifest ("dist/plugin.js"). When there is one the editor loads it and never entry: one fetch, no TypeScript compiler, no import graph to walk — and the plugin may use npm dependencies, which the source path cannot (bundleModule refuses a bare specifier because it has no resolver).

entry stays the source of truth and stays in the manifest: it is what a person reads, what npm run typecheck checks, and what loads when there is no build. A repository that publishes one builds it in CI at the tag it is loaded from — see docs/plugins.md.

icon?: string

The plugin's face in Manage Plugins and on its own dialogs: an emoji ("🗺️"), a data:image/… URI, an https://… image, or an image file beside the manifest ("icon.svg"). Anything else is ignored — see resolveIcon in loader.ts.

api?: number

The PLUGIN_API_VERSION the plugin was written against.

Deactivatetype

type Deactivate = void | (() => void) | Disposable;

What activate may hand back: nothing, a cleanup function, or a Disposable.

PluginActivatetype

type PluginActivate = (api: PluginApi) => Deactivate | Promise<Deactivate>;

PluginModuleinterface

interface PluginModule

The shape of the entry module: export default function activate(api) {…}, or export default { activate }, or export function activate(api) {…}.

activate: PluginActivate

PluginInfointerface

interface PluginInfo
id: string

Manifest id (or slug of the name).

name: string
source: string

The spec the plugin was installed from (builtin:…, github:…, a URL).

version?: string
icon?: PluginIcon

The manifest's icon, resolved; absent when it declared none (or an unusable one).

WidgetOptionsinterface

interface WidgetOptions
className?: string
title?: string
disabled?: boolean

pluginIdOffunction

function pluginIdOf(manifest: {
	id?: string;
	name: string;
}): string;

A slug for storage keys and log prefixes.

scmJS 0.1.0 · Generated from the repository. StarCraft and Brood War are trademarks of Blizzard Entertainment; this project ships none of their data.