@scm-js/plugin-api 1.2.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.d.ts +358 -3
  2. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -271,6 +271,225 @@ export interface TriggerRecord {
271
271
  /** The game's bookkeeping byte (offset 2399); StarEdit writes 0. */
272
272
  currentAction: number;
273
273
  }
274
+ declare const ConditionType: {
275
+ readonly None: 0;
276
+ readonly CountdownTimer: 1;
277
+ readonly Command: 2;
278
+ readonly Bring: 3;
279
+ readonly Accumulate: 4;
280
+ readonly Kill: 5;
281
+ readonly CommandTheMost: 6;
282
+ readonly CommandTheMostAt: 7;
283
+ readonly MostKills: 8;
284
+ readonly HighestScore: 9;
285
+ readonly MostResources: 10;
286
+ readonly Switch: 11;
287
+ readonly ElapsedTime: 12;
288
+ readonly Briefing: 13;
289
+ readonly Opponents: 14;
290
+ readonly Deaths: 15;
291
+ readonly CommandTheLeast: 16;
292
+ readonly CommandTheLeastAt: 17;
293
+ readonly LeastKills: 18;
294
+ readonly LowestScore: 19;
295
+ readonly LeastResources: 20;
296
+ readonly Score: 21;
297
+ readonly Always: 22;
298
+ readonly Never: 23;
299
+ };
300
+ declare const ActionType: {
301
+ readonly None: 0;
302
+ readonly Victory: 1;
303
+ readonly Defeat: 2;
304
+ readonly PreserveTrigger: 3;
305
+ readonly Wait: 4;
306
+ readonly PauseGame: 5;
307
+ readonly UnpauseGame: 6;
308
+ readonly Transmission: 7;
309
+ readonly PlayWav: 8;
310
+ readonly DisplayText: 9;
311
+ readonly CenterView: 10;
312
+ readonly CreateUnitWithProperties: 11;
313
+ readonly SetMissionObjectives: 12;
314
+ readonly SetSwitch: 13;
315
+ readonly SetCountdownTimer: 14;
316
+ readonly RunAiScript: 15;
317
+ readonly RunAiScriptAt: 16;
318
+ readonly LeaderboardControl: 17;
319
+ readonly LeaderboardControlAt: 18;
320
+ readonly LeaderboardResources: 19;
321
+ readonly LeaderboardKills: 20;
322
+ readonly LeaderboardPoints: 21;
323
+ readonly KillUnit: 22;
324
+ readonly KillUnitAt: 23;
325
+ readonly RemoveUnit: 24;
326
+ readonly RemoveUnitAt: 25;
327
+ readonly SetResources: 26;
328
+ readonly SetScore: 27;
329
+ readonly MinimapPing: 28;
330
+ readonly TalkingPortrait: 29;
331
+ readonly MuteUnitSpeech: 30;
332
+ readonly UnmuteUnitSpeech: 31;
333
+ readonly LeaderboardComputerPlayers: 32;
334
+ readonly LeaderboardGoalControl: 33;
335
+ readonly LeaderboardGoalControlAt: 34;
336
+ readonly LeaderboardGoalResources: 35;
337
+ readonly LeaderboardGoalKills: 36;
338
+ readonly LeaderboardGoalPoints: 37;
339
+ readonly MoveLocation: 38;
340
+ readonly MoveUnit: 39;
341
+ readonly LeaderboardGreed: 40;
342
+ readonly SetNextScenario: 41;
343
+ readonly SetDoodadState: 42;
344
+ readonly SetInvincibility: 43;
345
+ readonly CreateUnit: 44;
346
+ readonly SetDeaths: 45;
347
+ readonly Order: 46;
348
+ readonly Comment: 47;
349
+ readonly GiveUnits: 48;
350
+ readonly ModifyHitPoints: 49;
351
+ readonly ModifyEnergy: 50;
352
+ readonly ModifyShields: 51;
353
+ readonly ModifyResourceAmount: 52;
354
+ readonly ModifyHangarCount: 53;
355
+ readonly PauseTimer: 54;
356
+ readonly UnpauseTimer: 55;
357
+ readonly Draw: 56;
358
+ readonly SetAllianceStatus: 57;
359
+ readonly DisableDebugMode: 58;
360
+ readonly EnableDebugMode: 59;
361
+ };
362
+ declare const BriefingActionType: {
363
+ readonly None: 0;
364
+ readonly Wait: 1;
365
+ readonly PlayWav: 2;
366
+ readonly TextMessage: 3;
367
+ readonly MissionObjectives: 4;
368
+ readonly ShowPortrait: 5;
369
+ readonly HidePortrait: 6;
370
+ readonly DisplaySpeakingPortrait: 7;
371
+ readonly Transmission: 8;
372
+ readonly SkipTutorialEnabled: 9;
373
+ };
374
+ declare const PlayerGroup: {
375
+ readonly Player1: 0;
376
+ readonly Player2: 1;
377
+ readonly Player3: 2;
378
+ readonly Player4: 3;
379
+ readonly Player5: 4;
380
+ readonly Player6: 5;
381
+ readonly Player7: 6;
382
+ readonly Player8: 7;
383
+ readonly Player9: 8;
384
+ readonly Player10: 9;
385
+ readonly Player11: 10;
386
+ readonly Player12: 11;
387
+ readonly None: 12;
388
+ readonly CurrentPlayer: 13;
389
+ readonly Foes: 14;
390
+ readonly Allies: 15;
391
+ readonly NeutralPlayers: 16;
392
+ readonly AllPlayers: 17;
393
+ readonly Force1: 18;
394
+ readonly Force2: 19;
395
+ readonly Force3: 20;
396
+ readonly Force4: 21;
397
+ readonly Unused1: 22;
398
+ readonly Unused2: 23;
399
+ readonly Unused3: 24;
400
+ readonly Unused4: 25;
401
+ readonly NonAlliedVictoryPlayers: 26;
402
+ };
403
+ declare const Comparison: {
404
+ readonly AtLeast: 0;
405
+ readonly AtMost: 1;
406
+ readonly Exactly: 10;
407
+ };
408
+ declare const SwitchState: {
409
+ readonly Set: 2;
410
+ readonly Cleared: 3;
411
+ };
412
+ declare const SwitchAction: {
413
+ readonly Set: 4;
414
+ readonly Clear: 5;
415
+ readonly Toggle: 6;
416
+ readonly Randomize: 11;
417
+ };
418
+ declare const SetModifier: {
419
+ readonly SetTo: 7;
420
+ readonly Add: 8;
421
+ readonly Subtract: 9;
422
+ };
423
+ declare const UnitState: {
424
+ readonly Enable: 4;
425
+ readonly Disable: 5;
426
+ readonly Toggle: 6;
427
+ };
428
+ declare const Order: {
429
+ readonly Move: 0;
430
+ readonly Patrol: 1;
431
+ readonly Attack: 2;
432
+ };
433
+ declare const AllianceStatus: {
434
+ readonly Enemy: 0;
435
+ readonly Ally: 1;
436
+ readonly AlliedVictory: 2;
437
+ };
438
+ declare const ResourceType: {
439
+ readonly Ore: 0;
440
+ readonly Gas: 1;
441
+ readonly OreAndGas: 2;
442
+ };
443
+ declare const ScoreType: {
444
+ readonly Total: 0;
445
+ readonly Units: 1;
446
+ readonly Buildings: 2;
447
+ readonly UnitsAndBuildings: 3;
448
+ readonly Kills: 4;
449
+ readonly Razings: 5;
450
+ readonly KillsAndRazings: 6;
451
+ readonly Custom: 7;
452
+ };
453
+ declare const UnitClass: {
454
+ readonly Any: 228;
455
+ readonly Men: 229;
456
+ readonly Buildings: 230;
457
+ readonly Factories: 231;
458
+ };
459
+ declare const ConditionFlag: {
460
+ /** Game bookkeeping. */
461
+ readonly Unknown: 1;
462
+ readonly Disabled: 2;
463
+ readonly AlwaysDisplay: 4;
464
+ readonly UnitPropertiesUsed: 8;
465
+ readonly UnitTypeUsed: 16;
466
+ readonly UnitIdUsed: 32;
467
+ };
468
+ declare const ActionFlag: {
469
+ /** Ignore a Wait / Transmission once (game bookkeeping). */
470
+ readonly IgnoreWaitOnce: 1;
471
+ readonly Disabled: 2;
472
+ readonly AlwaysDisplay: 4;
473
+ readonly UnitPropertiesUsed: 8;
474
+ readonly UnitTypeUsed: 16;
475
+ readonly UnitIdUsed: 32;
476
+ };
477
+ declare const TriggerFlag: {
478
+ /** Game bookkeeping: every condition was met this cycle. */
479
+ readonly ConditionsMet: 1;
480
+ /** Ignore Defeat / Draw for this trigger. */
481
+ readonly IgnoreGameEnd: 2;
482
+ /** Same as a Preserve Trigger action. */
483
+ readonly Preserve: 4;
484
+ /** The trigger never runs. */
485
+ readonly Disabled: 8;
486
+ /** Skip Wait / text / view actions for the rest of this loop (game bookkeeping). */
487
+ readonly IgnoreDisplay: 16;
488
+ /** Game bookkeeping. */
489
+ readonly Paused: 32;
490
+ /** Game bookkeeping. */
491
+ readonly WaitSkipDisabled: 64;
492
+ };
274
493
  /**
275
494
  * A parsed scenario.
276
495
  *
@@ -1538,6 +1757,13 @@ export interface Preferences {
1538
1757
  */
1539
1758
  animateWaterSpeed: number;
1540
1759
  animateUnitsSpeed: number;
1760
+ /**
1761
+ * Preview the `<XX>` colour codes in strings the way **1.16.1** drew them: the colour
1762
+ * resets at every line break. Off is Remastered's rule, which carries a colour onto the
1763
+ * next line — see `editor/textColors.ts`. It changes only what the editor draws, never
1764
+ * the map, and every preview in the chrome reads it.
1765
+ */
1766
+ classicText: boolean;
1541
1767
  /**
1542
1768
  * Tools ▸ Test Map: whether to start the game after writing the map (desktop build), and
1543
1769
  * the game folder to use when the desktop build should not search ("" = search). The
@@ -1652,17 +1878,32 @@ export interface PluginInfo {
1652
1878
  export interface PluginApi {
1653
1879
  readonly apiVersion: number;
1654
1880
  readonly plugin: PluginInfo;
1881
+ /**
1882
+ * The open map: what it says, and the three ways of writing to it — `edit` (terrain and
1883
+ * objects, one undo entry), `update` (the tables every dialog's OK writes) and
1884
+ * `sections` (raw bytes). Opening, saving, exporting and closing are here too.
1885
+ */
1655
1886
  readonly document: DocumentApi;
1656
1887
  /** The settings dialogs' tables, read-only; `document.update` writes them. */
1657
1888
  readonly settings: SettingsApi;
1658
1889
  readonly triggers: TriggersApi;
1890
+ /**
1891
+ * Reading the terrain: the tileset's paintable types, the ISOM lattice, flood regions,
1892
+ * blend candidates and the symmetry mode. Painting goes through `document.edit`.
1893
+ */
1659
1894
  readonly terrain: TerrainApi;
1895
+ /** The loaded tileset graphics: whether they are there, and the decoded files behind them. */
1660
1896
  readonly tileset: TilesetApi;
1897
+ /** What is selected on each object layer, the marked area, the active layer and the locked ones. */
1661
1898
  readonly selection: SelectionApi;
1662
1899
  /** Cut / Copy / Paste: the clip, its parts, and pasting — what the clipboard layer does. */
1663
1900
  readonly clipboard: ClipboardApi;
1664
1901
  /** The file formats behind File ▸ Import / Export: `.trg` and the strings text. */
1665
1902
  readonly exchange: ExchangeApi;
1903
+ /**
1904
+ * The palettes' current picks — the terrain brush, the unit, sprite and doodad, the fog
1905
+ * mode — and the placement options a plugin that places things should honour.
1906
+ */
1666
1907
  readonly palette: PaletteApi;
1667
1908
  readonly names: NamesApi;
1668
1909
  /** StarCraft's `<XX>` text control codes: what they mean, and what a string looks like drawn. */
@@ -1673,12 +1914,24 @@ export interface PluginApi {
1673
1914
  readonly consts: ConstsApi;
1674
1915
  readonly graphics: GraphicsApi;
1675
1916
  readonly view: ViewApi;
1917
+ /**
1918
+ * Everything a plugin puts on the screen: the status line, toasts, dialogs, floating
1919
+ * panels, `confirm` / `alert` / `prompt` / `progress`, a map tool that owns the pointer,
1920
+ * a passive overlay drawn over the map, and picking an area or a tile.
1921
+ */
1676
1922
  readonly ui: UiApi;
1923
+ /** Items in the editor's menu bar. A path whose last segment names no submenu makes one. */
1677
1924
  readonly menu: MenuApi;
1925
+ /** Items in the right-click menus of the map and the terrain palette. */
1678
1926
  readonly contextMenu: ContextMenuApi;
1927
+ /** Key combinations, tried before the editor's own and never while a text field has focus. */
1679
1928
  readonly hotkeys: HotkeyApi;
1680
1929
  readonly commands: CommandsApi;
1681
1930
  readonly events: EventsApi;
1931
+ /**
1932
+ * A small key-value store of the plugin's own, kept in the browser's local storage under
1933
+ * the plugin's id and listed with everything else in Preferences ▸ Browser storage.
1934
+ */
1682
1935
  readonly storage: StorageApi;
1683
1936
  /** `console.log` with the plugin's name in front. */
1684
1937
  log(...args: unknown[]): void;
@@ -1797,6 +2050,14 @@ export interface DocumentApi {
1797
2050
  *
1798
2051
  * `build` is synchronous — see `Sync`. Await what you need (graphics, a pick, a
1799
2052
  * fetch) before the call, then write in one go.
2053
+ *
2054
+ * @example
2055
+ * // One undo entry called "Fill", however many operations it takes.
2056
+ * const result = api.document.edit("Fill", (tx) => {
2057
+ * tx.stampTerrain({ x0: 0, y0: 0, x1: 8, y1: 8 }, terrainId);
2058
+ * tx.placeUnit(api.consts.unit.startLocation, 0, 4 * api.consts.tile, 4 * api.consts.tile);
2059
+ * });
2060
+ * api.ui.status(`${result.tiles} tiles, ${result.units} units`);
1800
2061
  */
1801
2062
  edit<R>(label: string, build: (tx: EditTransaction) => Sync<R>): EditResult;
1802
2063
  /**
@@ -1806,6 +2067,11 @@ export interface DocumentApi {
1806
2067
  * Operations apply as they are called; the commit marks the map modified and bumps
1807
2068
  * what the chrome reads. There is no undo entry: keep your own if you need one.
1808
2069
  * `build` is synchronous, as `edit`'s is.
2070
+ *
2071
+ * @example
2072
+ * api.document.update("Rename", (tx) => {
2073
+ * tx.properties({ name: "Lost Temple", description: "Four players." });
2074
+ * });
1809
2075
  */
1810
2076
  update<R>(label: string, build: (tx: UpdateTransaction) => Sync<R>): UpdateResult;
1811
2077
  undo(): string | null;
@@ -2580,8 +2846,9 @@ export interface DataApi {
2580
2846
  }
2581
2847
  /**
2582
2848
  * The constants a plugin needs to *write* a record rather than read one: the bit masks in
2583
- * a UNIT / THG2 / MRGN record, the few unit ids the game itself treats specially, and the
2584
- * one conversion — 32 pixels to a tile — every object position goes through.
2849
+ * a UNIT / THG2 / MRGN record, the condition, action and argument numbers of a TRIG /
2850
+ * MBRF one, the few unit ids the game itself treats specially, and the one conversion —
2851
+ * 32 pixels to a tile — every object position goes through.
2585
2852
  *
2586
2853
  * They are the editor's own (`sections/objects.ts`, `editor/units.ts`) and they arrive
2587
2854
  * here at run time rather than in the typings on purpose: `@scm-js/plugin-api` is erased
@@ -2593,9 +2860,14 @@ export interface DataApi {
2593
2860
  export interface ConstsApi {
2594
2861
  /** Map pixels to a tile. UNIT and THG2 store pixels; MTXM, MRGN and the brushes count tiles. */
2595
2862
  readonly tile: 32;
2863
+ /** UNIT: the special unit ids, the default resource amounts, and the record's four bit masks. */
2596
2864
  readonly unit: UnitConsts;
2865
+ /** THG2: the sprite record's flag word. */
2597
2866
  readonly sprite: SpriteConsts;
2867
+ /** MRGN: the Anywhere slot, and the elevation bits. */
2598
2868
  readonly location: LocationConsts;
2869
+ /** TRIG / MBRF: the condition and action types, and the enumerated arguments. */
2870
+ readonly triggers: TriggerConsts;
2599
2871
  /** Whether a unit type is a mineral field or a vespene geyser. */
2600
2872
  isResource(unitId: number): boolean;
2601
2873
  }
@@ -2673,6 +2945,56 @@ export interface LocationConsts {
2673
2945
  readonly HighAir: 32;
2674
2946
  };
2675
2947
  }
2948
+ /**
2949
+ * The numbers a TRIG / MBRF record is written in: the condition and action types, and the
2950
+ * enumerated arguments the game stores as bare bytes.
2951
+ *
2952
+ * A trigger record is sixteen conditions and sixty-four actions of plain numbers — the
2953
+ * codec knows no types — so writing one field by field means knowing that a Countdown
2954
+ * Timer condition is type 1 and `AtLeast` is 0. `triggers.defs` says which *field* an
2955
+ * argument lives in; this says what to put in it.
2956
+ *
2957
+ * The keys of the argument groups are `ArgDef.kind`, so a generic argument editor can
2958
+ * look one up by the kind the def gave it (`api.consts.triggers[arg.kind]`).
2959
+ *
2960
+ * Generating a whole run of triggers is usually better done through
2961
+ * `tx.triggers.fromText`, which resolves names against the open map; these are for
2962
+ * editing a field of an existing record, and for reading one back.
2963
+ */
2964
+ export interface TriggerConsts {
2965
+ /** Condition `type`. */
2966
+ readonly condition: typeof ConditionType;
2967
+ /** Action `type` in TRIG. */
2968
+ readonly action: typeof ActionType;
2969
+ /** Action `type` in MBRF, where the same byte means something else. */
2970
+ readonly briefingAction: typeof BriefingActionType;
2971
+ /** The 27 player-group values, which are also the indices of a trigger's `players`. */
2972
+ readonly player: typeof PlayerGroup;
2973
+ readonly comparison: typeof Comparison;
2974
+ readonly switchState: typeof SwitchState;
2975
+ readonly switchAction: typeof SwitchAction;
2976
+ /** Set Resources / Set Score / Modify …: `SetTo`, `Add`, `Subtract`. */
2977
+ readonly modifier: typeof SetModifier;
2978
+ /** Set Doodad State / Set Invincibility: `Enable`, `Disable`, `Toggle`. */
2979
+ readonly unitState: typeof UnitState;
2980
+ readonly order: typeof Order;
2981
+ readonly alliance: typeof AllianceStatus;
2982
+ readonly resource: typeof ResourceType;
2983
+ readonly score: typeof ScoreType;
2984
+ /** The unit ids past units.dat that a condition or action accepts: *Any unit*, *Men*, *Buildings*, *Factories*. */
2985
+ readonly unitClass: typeof UnitClass;
2986
+ /** A condition's `flags`. `UnitTypeUsed` is the hint bit the text format cannot carry. */
2987
+ readonly conditionFlags: typeof ConditionFlag;
2988
+ /** An action's `flags`. */
2989
+ readonly actionFlags: typeof ActionFlag;
2990
+ /** A trigger's `flags`; `Preserve` is what `triggers.isPreserved` reads. */
2991
+ readonly triggerFlags: typeof TriggerFlag;
2992
+ /**
2993
+ * The address of the game's death table, which is the base an EUD player value is
2994
+ * counted from: `epd = (address - deathsTable) / 4 + 0x2000`.
2995
+ */
2996
+ readonly deathsTable: number;
2997
+ }
2676
2998
  export interface ActiveBrush {
2677
2999
  mode: TerrainMode;
2678
3000
  /** The Rect / isometric brush's terrain id. */
@@ -3415,6 +3737,20 @@ export interface MenuItemSpec {
3415
3737
  command?: string;
3416
3738
  }
3417
3739
  export interface MenuApi {
3740
+ /**
3741
+ * Items in the editor's menu bar.
3742
+ *
3743
+ * @example
3744
+ * api.menu.add("Tools", {
3745
+ * label: "Count units\u2026",
3746
+ * icon: "plugin",
3747
+ * run: () => api.ui.alert(`Player 1 has ${api.query.unitsOf(0).length} units.`),
3748
+ * });
3749
+ *
3750
+ * @example
3751
+ * // A path whose last segment names no submenu makes one, at the end of that menu.
3752
+ * api.menu.add("Tools/My plugin", { label: "Settings\u2026", command: "settings" });
3753
+ */
3418
3754
  add(path: MenuPath, item: MenuItemSpec): Disposable;
3419
3755
  }
3420
3756
  export type ContextSurface = "viewport" | "terrainPalette";
@@ -3448,7 +3784,10 @@ export interface ContextMenuApi {
3448
3784
  add(surface: ContextSurface, item: ContextItemSpec): Disposable;
3449
3785
  }
3450
3786
  export interface HotkeyApi {
3451
- /** `"Ctrl+Shift+I"`, `"Alt+F9"`, `"F8"` — modifiers in any order, then a key name. */
3787
+ /** `"Ctrl+Shift+I"`, `"Alt+F9"`, `"F8"` — modifiers in any order, then a key name. *
3788
+ * @example
3789
+ * api.hotkeys.add("Ctrl+Shift+W", () => handle.setVisible(!handle.visible()));
3790
+ */
3452
3791
  add(combo: string, run: (() => void) | {
3453
3792
  command: string;
3454
3793
  }): Disposable;
@@ -3497,10 +3836,26 @@ export interface DocumentEvent {
3497
3836
  * reason `"replace"`, which every other listener sees in turn.
3498
3837
  */
3499
3838
  export interface EventsApi {
3839
+ /**
3840
+ * @example
3841
+ * // Notifications, in activation order; a listener never intercepts what it hears.
3842
+ * api.events.on("document", (e) => {
3843
+ * if (e.reason === "open") check(e.fileName);
3844
+ * });
3845
+ * api.events.on("terrain", () => redraw());
3846
+ */
3500
3847
  on(event: "document", listener: (event: DocumentEvent) => void): Disposable;
3501
3848
  on(event: PluginEvent, listener: () => void): Disposable;
3502
3849
  }
3503
3850
  export interface StorageApi {
3851
+ /**
3852
+ * A small key-value store of the plugin's own, under its id in the browser's local
3853
+ * storage and listed in Preferences \u25b8 Browser storage.
3854
+ *
3855
+ * @example
3856
+ * const opts = api.storage.get("options", { showGrid: true });
3857
+ * api.storage.set("options", { ...opts, showGrid: false });
3858
+ */
3504
3859
  get<T>(key: string, fallback: T): T;
3505
3860
  set(key: string, value: unknown): void;
3506
3861
  remove(key: string): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scm-js/plugin-api",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "Type declarations for the scmJS plugin API",
5
5
  "license": "MIT",
6
6
  "types": "index.d.ts",