@moku-labs/game 0.0.1 → 0.0.2

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.
package/dist/index.d.mts CHANGED
@@ -1,12 +1,191 @@
1
- import { A as Patch, B as PauseReason, C as State, D as Root, E as Json, F as StoreApi, G as State$4, H as types_d_exports$2, I as RngApi, J as Events, K as types_d_exports$4, O as State$3, P as SaveUnreadableError, R as Api$2, T as Config$3, U as Api$3, V as State$2, W as Config$4, _ as GuideOptions, a as Kit, b as Api, c as exit, d as type, f as FeatureDescription, g as Descriptor, i as GameTypes, k as types_d_exports$3, l as slot, n as Config$1, o as State$1, q as Config$5, r as FeaturePlugin, s as types_d_exports$1, t as Api$1, u as to, v as Hint, w as types_d_exports, x as Config, z as Config$2 } from "./types-BfsmUzLC.mjs";
1
+ import { $ as PauseReason, A as Config$4, B as types_d_exports$8, C as SceneIdOf, D as Hint, E as GuideOptions, F as Config$3, G as SaveUnreadableError, J as RngApi, L as Json, N as types_d_exports$12, R as Root, T as Descriptor, V as Patch, X as Api$2, Z as Config$2, _ as DefineNode, a as GameTypes, at as State, c as TextStylesOf, ct as Events, d as exit, et as State$2, f as slot, h as FeatureDescription, i as FeaturePlugin, j as State$4, k as Api$3, l as types_d_exports$4, m as type, n as BundlesOf, nt as Api, ot as types_d_exports$3, p as to, q as StoreApi, r as Config$1, rt as Config, s as State$1, st as Config$5, t as Api$1, tt as types_d_exports$7, u as defineFlow, z as State$3 } from "./types-JNc_UQBo.mjs";
2
+ import { A as ComponentHandle, B as SystemDefinition, C as ProjectionSpec, F as Mut, I as Narrowed, M as ComponentValue, R as QueryTerm, S as ProjectionMotion, V as TagType, a as types_d_exports$9, d as Config$7, f as State$6, g as Ease, h as DescriptionNode, i as State$5, j as ComponentType, k as AnyComponentValue, l as ViewportSize, n as Config$6, p as types_d_exports$14, t as Api$4, u as Api$5, x as NumericFields, z as ResourceType } from "./types-BxkNNYul.mjs";
3
+ import { a as DefineBundles, c as LoadReason, d as Tier, i as Config$8, n as BundleMap, p as types_d_exports$1, r as BundleSpec, s as LoadBundles, t as Api$6, u as State$7 } from "./types-DWILGrPn.mjs";
4
+ import { A as Transform, B as types_d_exports$5, C as NineSliceValue, D as Sprite, E as ShapeValue, H as InputApi, I as I18nApi, L as Message, M as sprite, N as Argument, O as SpriteOptions, P as Config$9, R as State$8, S as NineSlice, T as Shape, U as State$9, V as Config$10, W as types_d_exports$6, _ as Style, b as defineComponent, d as popup, f as defineTokens, g as ResolvedStyle, h as IsFlags, j as TransformValue, k as SpriteValue, l as Box, p as IntrinsicElementsFor, s as PopupComponent, u as LocalWrite, w as Parent, x as Display, y as WhenFlags, z as TypedTr } from "./types-yg_ywtT-.mjs";
5
+ import { a as Config$11, c as TextApi, d as TextValue, f as types_d_exports$11, i as types_d_exports$13, l as TextStyleInput, n as State$11, o as Point, r as UiApi, s as State$10, t as Config$12, u as TextStyles } from "./types-DD-QrG_z.mjs";
6
+ import { a as Config$13, c as SlotValues, d as types_d_exports, f as ExternalPlayer, g as Step, h as SfxDescriptor, i as BuildTools, l as State$12, m as PlayDescriptor, n as AnimationDefinition, o as MotionKeyframe, p as HapticDescriptor, r as AnimationSpec, s as SlotTags, t as AnimApi, u as Target } from "./types-CTPS9GBu.mjs";
7
+ import { c as AnySceneProjection, d as SceneDefinition, f as SceneSpec, h as types_d_exports$10, i as MusicOptions, l as DefineScene, m as State$14, n as Config$14, o as State$13, p as ScenesApi, r as MusicDescriptor, s as types_d_exports$2, t as AudioApi, u as LayerMap } from "./types-DYLnSgMI.mjs";
2
8
 
9
+ //#region src/plugins/text/components.d.ts
10
+ /**
11
+ * Words on the screen: a string or a message, the style it is drawn in, and the string `text`
12
+ * resolved out of it. A game writes `content`, `style`, `bind` and `anchor`; `resolved` is
13
+ * engine-owned and `ui` and the tests read it.
14
+ */
15
+ declare const Text: ComponentType<TextValue>;
16
+ /**
17
+ * What `label` takes: the two things every label needs, and the anchor that has a default.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const options: LabelOptions = { text: "+5", style: "board.float", at: { x: 90, y: 180 } };
22
+ * ```
23
+ */
24
+ type LabelOptions = {
25
+ text: string | Message;
26
+ style: string;
27
+ at: Point;
28
+ anchor?: Point;
29
+ };
30
+ /**
31
+ * Bundles the two components a label needs, so a projection `view` reads as one line. The anchor
32
+ * is the point of the block that sits on the transform.
33
+ *
34
+ * @param options - The text, its style, where it sits, and which point of it sits there.
35
+ * @returns The `Text` and the `Transform` value, in that order.
36
+ * @example
37
+ * ```ts
38
+ * label({ text: "+5", style: "board.float", at: { x: 90, y: 180 } });
39
+ * // [Text({ content: "+5", style: "board.float", bind: undefined,
40
+ * // anchor: { x: 0.5, y: 0.5 }, resolved: "" }),
41
+ * // Transform({ x: 90, y: 180, rotation: 0, scale: 1 })]
42
+ * ```
43
+ */
44
+ declare function label(options: LabelOptions): [ComponentValue<TextValue>, ComponentValue<TransformValue>];
45
+ /**
46
+ * Declares the text styles of a feature. The result goes under the `textStyles` key of the
47
+ * feature description, and `text` reads it in `onStart`.
48
+ *
49
+ * @param map - Style name to what that style looks like.
50
+ * @returns The registration a feature carries.
51
+ * @throws {Error} When a style names a wrap that is not a width and not `"none"`.
52
+ * @example
53
+ * ```ts
54
+ * defineTextStyles({ "hud.digits": { font: "ui.font-digits", size: 40, fill: 0xffe082 } });
55
+ * // { kind: "textStyles", map: { "hud.digits": { font: "ui.font-digits", bold: undefined,
56
+ * // italic: undefined, size: 40, fill: 0xffe082, stroke: 0x000000, strokeWidth: 0,
57
+ * // letterSpacing: 0, align: "left", wrap: "none", digits: false, shadow: undefined } } }
58
+ * ```
59
+ */
60
+ declare function defineTextStyles(map: Record<string, TextStyleInput>): TextStyles;
61
+ //#endregion
62
+ //#region src/plugins/world/projection/define.d.ts
63
+ /**
64
+ * Types a projection: keyed items of the model turned into entities. `Item` is inferred from the
65
+ * return of `from` and reaches `key`, `view` and every motion hook; `layer` and `lift` stay
66
+ * literal, so `defineScene` can check them against the layers of the scene.
67
+ *
68
+ * @param spec - Name, layer, optional lift layer, `from`, `key`, `view` and the motion hooks.
69
+ * @returns The same spec, typed.
70
+ * @example
71
+ * ```ts
72
+ * const boardItems = projection({
73
+ * name: "board.items",
74
+ * layer: "items",
75
+ * from: (player: { items: { id: string }[] }) => player.items,
76
+ * key: item => item.id,
77
+ * view: () => []
78
+ * });
79
+ * boardItems.layer; // "items", the literal type, not string
80
+ * ```
81
+ */
82
+ declare function projection<const LayerName extends string, const LiftName extends string, Item, Player = Json, Session = Json>(spec: ProjectionSpec<Item, LayerName, LiftName, Player, Session>): ProjectionSpec<Item, LayerName, LiftName, Player, Session>;
83
+ /**
84
+ * The projection helper bound to one game's `player` and `session`.
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * const bound: ProjectionFor<{ coins: number }, {}> = projection;
89
+ * ```
90
+ */
91
+ type ProjectionFor<Player, Session> = <const LayerName extends string, const LiftName extends string, Item>(spec: ProjectionSpec<Item, LayerName, LiftName, Player, Session>) => ProjectionSpec<Item, LayerName, LiftName, Player, Session>;
92
+ //#endregion
93
+ //#region src/plugins/anim/index.d.ts
94
+ /**
95
+ * Anim plugin: `app.anim.play(animation, slots)`, `app.anim.finishAll()`,
96
+ * `app.anim.setReducedMotion(on)`.
97
+ *
98
+ * @example
99
+ * ```ts
100
+ * // Animation is text: a module next to the feature, played by a node or by a test.
101
+ * const coinsFly = defineAnimation("hud.coinsFly", {
102
+ * slots: { from: type<Target>(), to: type<Target>() },
103
+ * build: ({ from, to }, { at }) =>
104
+ * sequence(
105
+ * tween(from, Transform, { x: at(to).x, y: at(to).y }, { ms: 600, ease: "inCubic" }),
106
+ * mark("landed")
107
+ * )
108
+ * });
109
+ *
110
+ * const app = createApp({ plugins: [...screen, animPlugin, hudFeature] });
111
+ *
112
+ * app.anim.play(coinsFly, { from: purse, to: counter }).marks(); // []: the first frame is next
113
+ * ```
114
+ */
115
+ declare const animPlugin: import("@moku-labs/core").PluginInstance<"anim", Config$13, State$12, AnimApi, {
116
+ "anim:mark": {
117
+ animation: string;
118
+ mark: string;
119
+ };
120
+ "anim:finished": {
121
+ animation: string;
122
+ };
123
+ }> & Record<never, never>;
124
+ //#endregion
125
+ //#region src/plugins/assets/index.d.ts
126
+ /**
127
+ * Assets plugin: `app.assets.load(bundle)`, `app.assets.texture(key)`, `app.assets.usage()`.
128
+ *
129
+ * @example
130
+ * ```ts
131
+ * // A game names its manifest; the graph decides from there what is loaded and when.
132
+ * const app = createApp({
133
+ * plugins: [...screen, boardFeature],
134
+ * pluginConfigs: { assets: { manifest: "/assets/manifest.json", textureBudgetMb: 192 } }
135
+ * });
136
+ *
137
+ * await app.start();
138
+ * app.assets.usage().textureMb; // 0.188, the boot tier
139
+ * ```
140
+ */
141
+ declare const assetsPlugin: import("@moku-labs/core").PluginInstance<"assets", Config$8, State$7, Api$6, {
142
+ "assets:bundle-loaded": {
143
+ bundle: string;
144
+ tier: Tier;
145
+ mb: number;
146
+ reason: LoadReason;
147
+ };
148
+ "assets:bundle-progress": {
149
+ bundle: string;
150
+ loaded: number;
151
+ total: number;
152
+ };
153
+ "assets:bundle-unloaded": {
154
+ bundle: string;
155
+ tier: Tier;
156
+ mb: number;
157
+ reason: "budget" | "request";
158
+ keys: readonly string[];
159
+ };
160
+ }> & Record<never, never>;
161
+ //#endregion
162
+ //#region src/plugins/audio/index.d.ts
163
+ /**
164
+ * Audio plugin: `app.audio`, the handlers of the effect kinds `sfx` and `music`, and the three
165
+ * buses a game drives from its player state.
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * // A game composes it next to the screen set and points it at the player's settings.
170
+ * createApp({
171
+ * plugins: [...screen, audioPlugin, settingsFeature],
172
+ * pluginConfigs: { audio: { volumes: player => player.settings.audio } }
173
+ * });
174
+ * ```
175
+ */
176
+ declare const audioPlugin: import("@moku-labs/core").PluginInstance<"audio", Config$14, State$13, AudioApi, {}> & Record<never, never>;
177
+ //#endregion
3
178
  //#region src/plugins/clock/index.d.ts
4
179
  /**
5
180
  * Clock plugin: `app.clock.now()`, `app.clock.scheduleAt(moment)`, `app.clock.onElapsed(fn)`.
6
181
  *
7
182
  * @example
8
183
  * ```ts
9
- * ctx.require(clockPlugin).scheduleAt(nextDue);
184
+ * // A game plugin that needs trusted time declares the dependency and asks for the API.
185
+ * const energyPlugin = createPlugin("energy", {
186
+ * depends: [clockPlugin],
187
+ * api: ctx => ({ fullAt: (missing: number) => ctx.require(clockPlugin).now() + missing * 60_000 })
188
+ * });
10
189
  * ```
11
190
  */
12
191
  declare const clockPlugin: import("@moku-labs/core").PluginInstance<"clock", Config, State, Api, {}> & Record<never, never>;
@@ -17,7 +196,13 @@ declare const clockPlugin: import("@moku-labs/core").PluginInstance<"clock", Con
17
196
  *
18
197
  * @example
19
198
  * ```ts
20
- * createApp({ pluginConfigs: { flow: { mainFlow } }, onStart: startGraph });
199
+ * // The game starts the graph itself: an awaited loop in onStart would never let start() resolve.
200
+ * createApp({
201
+ * pluginConfigs: { flow: { mainFlow, safeNode: "home" } },
202
+ * onStart: ctx => {
203
+ * ctx.flow.run().catch(showFatal);
204
+ * }
205
+ * });
21
206
  * ```
22
207
  */
23
208
  declare const flowPlugin: import("@moku-labs/core").PluginInstance<"flow", Config$1, State$1, Api$1, {
@@ -46,13 +231,59 @@ declare const flowPlugin: import("@moku-labs/core").PluginInstance<"flow", Confi
46
231
  };
47
232
  }> & Record<never, never>;
48
233
  //#endregion
234
+ //#region src/plugins/i18n/index.d.ts
235
+ /**
236
+ * I18n plugin: `app.i18n.format(tr("hud.orders", { n: 3 }))`, and `tr` for the game.
237
+ *
238
+ * @example
239
+ * ```ts
240
+ * // A feature ships its compiled modules; the settings screen switches between them.
241
+ * export const hudFeature = defineFeature("hud", {
242
+ * projections: [hud],
243
+ * strings: { ru: ruStrings, en: () => import("./generated/strings.en") }
244
+ * });
245
+ *
246
+ * await app.i18n.setLocale("en"); // text re-resolves every message on i18n:locale-changed
247
+ * ```
248
+ */
249
+ declare const i18nPlugin: import("@moku-labs/core").PluginInstance<"i18n", Config$9, State$8, I18nApi, {
250
+ "i18n:locale-changed": {
251
+ locale: string;
252
+ };
253
+ }> & Record<never, never>;
254
+ //#endregion
255
+ //#region src/plugins/input/index.d.ts
256
+ /**
257
+ * Input plugin: `app.input.tap(target)`, `app.input.drag(from, to)`.
258
+ *
259
+ * @example
260
+ * ```ts
261
+ * // A view declares its behaviour; the engine owns the drag and the way home.
262
+ * const boardItems = projection({
263
+ * name: "board.items",
264
+ * layer: "items",
265
+ * from: (player: Player) => player.items,
266
+ * key: (item: Item) => item.id,
267
+ * view: (item: Item) => [
268
+ * Draggable({ payload: { from: item.cell } }),
269
+ * DropTarget({ intent: "merge", payload: { to: item.cell } })
270
+ * ]
271
+ * });
272
+ * ```
273
+ */
274
+ declare const inputPlugin: import("@moku-labs/core").PluginInstance<"input", Config$10, State$9, InputApi, {}> & Record<never, never>;
275
+ //#endregion
49
276
  //#region src/plugins/lifecycle/index.d.ts
50
277
  /**
51
278
  * Lifecycle plugin: `app.lifecycle.push(reason)`, `app.lifecycle.pop(reason)`.
52
279
  *
53
280
  * @example
54
281
  * ```ts
55
- * ctx.require(lifecyclePlugin).push("background");
282
+ * // A game plugin that reacts to the pause declares the dependency and hooks the event.
283
+ * const musicPlugin = createPlugin("music", {
284
+ * depends: [lifecyclePlugin],
285
+ * hooks: () => ({ "lifecycle:changed": ({ paused }) => music.setMuted(paused) })
286
+ * });
56
287
  * ```
57
288
  */
58
289
  declare const lifecyclePlugin: import("@moku-labs/core").PluginInstance<"lifecycle", Config$2, State$2, Api$2, {
@@ -71,7 +302,13 @@ declare const lifecyclePlugin: import("@moku-labs/core").PluginInstance<"lifecyc
71
302
  *
72
303
  * @example
73
304
  * ```ts
74
- * const transaction = ctx.require(modelPlugin).store.begin();
305
+ * // A game plugin that draws from committed state declares the dependency and reads the snapshot.
306
+ * const hudPlugin = createPlugin("hud", {
307
+ * depends: [modelPlugin],
308
+ * hooks: ctx => ({
309
+ * "model:committed": () => drawCoins(ctx.require(modelPlugin).store.snapshot().player)
310
+ * })
311
+ * });
75
312
  * ```
76
313
  */
77
314
  declare const modelPlugin: import("@moku-labs/core").PluginInstance<"model", Config$3, State$3, {
@@ -84,17 +321,132 @@ declare const modelPlugin: import("@moku-labs/core").PluginInstance<"model", Con
84
321
  };
85
322
  }> & Record<never, never>;
86
323
  //#endregion
324
+ //#region src/plugins/renderer/index.d.ts
325
+ /**
326
+ * Renderer plugin: `app.renderer.host.ready()`, `app.renderer.viewport.size()`,
327
+ * `app.renderer.sync.hitTest(...)`.
328
+ *
329
+ * @example
330
+ * ```ts
331
+ * // A game with a screen names the element the canvas goes into. Nothing else is configured.
332
+ * const app = createApp({
333
+ * plugins: [...screen, boardFeature],
334
+ * pluginConfigs: { renderer: { mount: "#game" } }
335
+ * });
336
+ *
337
+ * await app.start();
338
+ * app.renderer.host.kind(); // "webgpu" in Chrome, "webgl" on an older device
339
+ * ```
340
+ */
341
+ declare const rendererPlugin: import("@moku-labs/core").PluginInstance<"renderer", Config$6, State$5, Api$4, {
342
+ "renderer:device-lost": {
343
+ kind: "webgpu" | "webgl";
344
+ reason: string;
345
+ };
346
+ }> & Record<never, never>;
347
+ //#endregion
348
+ //#region src/plugins/scenes/index.d.ts
349
+ /**
350
+ * Scenes plugin: `app.scenes.current()`, and `defineScene` for the game.
351
+ *
352
+ * @example
353
+ * ```ts
354
+ * // features/board/view/scene.ts, and the node that shows it.
355
+ * export const boardScene = defineScene("board", {
356
+ * bundle: "board",
357
+ * layers: { cells: {}, items: { sort: "y" }, lifted: {} },
358
+ * projections: [boardCells, boardItems]
359
+ * });
360
+ *
361
+ * export const awaitIntent = defineNode({ scene: "board", rest: true, outcomes: { merge: type() } });
362
+ * ```
363
+ */
364
+ declare const scenesPlugin: import("@moku-labs/core").PluginInstance<"scenes", Record<string, never>, State$14, ScenesApi, {
365
+ "scenes:changed": {
366
+ from: string | undefined;
367
+ to: string;
368
+ music: string | undefined;
369
+ };
370
+ }> & Record<never, never>;
371
+ //#endregion
372
+ //#region src/plugins/text/index.d.ts
373
+ /**
374
+ * Text plugin: `app.text.measure(...)`, the `Text` component and the helpers `label` and
375
+ * `defineTextStyles` a game writes.
376
+ *
377
+ * @example
378
+ * ```ts
379
+ * // A feature brings its styles; a projection puts a label over an item.
380
+ * export const hudStyles = defineTextStyles({
381
+ * "hud.digits": { font: "ui.font-digits", size: 40, fill: 0xffe082, digits: true }
382
+ * });
383
+ *
384
+ * const app = createApp({ plugins: [...screen, hudFeature] });
385
+ *
386
+ * app.text.styles(); // ["body", "digits", "hud.digits"]
387
+ * ```
388
+ */
389
+ declare const textPlugin: import("@moku-labs/core").PluginInstance<"text", Config$11, State$10, TextApi, {}> & Record<never, never>;
390
+ //#endregion
87
391
  //#region src/plugins/time/index.d.ts
88
392
  /**
89
393
  * Time plugin: `app.time.onFrame(phase, fn)`, `app.time.step(dt)`.
90
394
  *
91
395
  * @example
92
396
  * ```ts
93
- * ctx.require(timePlugin).onFrame("animate", advanceTweens);
397
+ * // A game plugin with frame work declares the dependency and registers a callback on start.
398
+ * const sparklePlugin = createPlugin("sparkle", {
399
+ * depends: [timePlugin],
400
+ * onStart: ctx => void ctx.require(timePlugin).onFrame("animate", time => advance(time.delta))
401
+ * });
94
402
  * ```
95
403
  */
96
404
  declare const timePlugin: import("@moku-labs/core").PluginInstance<"time", Config$4, State$4, Api$3, {}> & Record<never, never>;
97
405
  //#endregion
406
+ //#region src/plugins/ui/index.d.ts
407
+ /**
408
+ * Ui plugin: `app.ui.tree()`, `app.ui.find(...)`, `app.ui.lint()`, the components `Box` and
409
+ * `LocalWrite`, and the helpers `defineComponent`, `defineStyle`, `defineTokens` and `popup`.
410
+ *
411
+ * @example
412
+ * ```ts
413
+ * // A headless test reads the HUD and taps the button the popup opened.
414
+ * const app = createApp({ plugins: [...screen, uiPlugin, hudFeature] });
415
+ *
416
+ * app.ui.tree().type; // "row"
417
+ * app.input.tap(app.ui.find("claim") ?? 0);
418
+ * ```
419
+ */
420
+ declare const uiPlugin: import("@moku-labs/core").PluginInstance<"ui", Config$12, State$11, UiApi, {}> & Record<never, never>;
421
+ //#endregion
422
+ //#region src/plugins/world/index.d.ts
423
+ /**
424
+ * World plugin: `app.world.ecs.query(...)`, `app.world.projection.mount(...)`.
425
+ *
426
+ * @example
427
+ * ```ts
428
+ * // A test drives the screen without a browser: mount, commit, step frames.
429
+ * const app = createApp({ plugins: [worldPlugin, boardFeature] });
430
+ *
431
+ * app.world.projection.setLayers([{ name: "items", sort: "y" }]);
432
+ * app.world.projection.mount(["board.items"], { kind: "plugin", name: "test" });
433
+ * app.world.projection.entityOf("board.items", "i7"); // 1048576
434
+ * ```
435
+ */
436
+ declare const worldPlugin: import("@moku-labs/core").PluginInstance<"world", Config$7, State$6, Api$5, {
437
+ "world:reconciled": {
438
+ mode: "play" | "direct";
439
+ projections: number;
440
+ entered: number;
441
+ changed: number;
442
+ exited: number;
443
+ revived: number;
444
+ queued: number;
445
+ hintsRouted: number;
446
+ hintsDropped: number;
447
+ };
448
+ }> & Record<never, never>;
449
+ //#endregion
98
450
  //#region src/plugins/flow/feature.d.ts
99
451
  /**
100
452
  * Turns a feature description into a plugin that registers it with `flow.features` in `onInit`.
@@ -107,10 +459,12 @@ declare const timePlugin: import("@moku-labs/core").PluginInstance<"time", Confi
107
459
  * @throws {Error} When the name is reserved or belongs to an engine plugin.
108
460
  * @example
109
461
  * ```ts
110
- * export const boardFeature = defineFeature("board", {
111
- * flows: [boardFlow],
112
- * contribute: { afterWin: { flow: rewardFlow, order: 10 } }
462
+ * // The reward popup is a feature: the main flow only declares slot("afterOrder").
463
+ * export const rewardFeature = defineFeature("reward", {
464
+ * flows: [rewardFlow],
465
+ * contribute: { afterOrder: { flow: rewardFlow, order: 10 } }
113
466
  * });
467
+ * createApp({ plugins: [rewardFeature] }); // a headless test passes rewardFeature.logicOnly
114
468
  * ```
115
469
  */
116
470
  declare function defineFeature(name: string, description: FeatureDescription): FeaturePlugin;
@@ -125,7 +479,9 @@ declare function defineFeature(name: string, description: FeatureDescription): F
125
479
  * @returns The hint as plain data.
126
480
  * @example
127
481
  * ```ts
482
+ * // Inside a node body: sparkle on the merged cell, shown once the edge has committed.
128
483
  * fx.emit(hint("sparkle", { cell: "c3" }));
484
+ * // hint("sparkle", { cell: "c3" }) is { kind: "sparkle", payload: { cell: "c3" }, hint: true }
129
485
  * ```
130
486
  */
131
487
  declare function hint(kind: string, payload?: Json): Hint;
@@ -138,74 +494,753 @@ declare function hint(kind: string, payload?: Json): Hint;
138
494
  * @returns The descriptor a node awaits.
139
495
  * @example
140
496
  * ```ts
141
- * await fx(schedule(rules.nextDue(player, tables)));
497
+ * // Inside a node body, after the rules changed a timer: ask for the next `elapsed`.
498
+ * await fx(schedule(1_790_000_060_000)); // payload: { moment: 1790000060000 }
499
+ * await fx(schedule(undefined)); // payload: {}, the pending timer is cancelled
142
500
  * ```
143
501
  */
144
502
  declare function schedule(moment: number | undefined): Descriptor;
145
503
  /**
146
504
  * Creates the tutorial descriptor: it narrows the gate to one answer until the node exits. Its
147
- * visual part (highlight, hand, text) is handled by `ui` later. The highlight list is copied, so
148
- * a later change of the caller's array cannot reach the descriptor.
505
+ * visual part (`target`, highlight, hand, text) is drawn by `ui`, which dims the screen and cuts
506
+ * a hole over the target element. The highlight list and the target are copied, so a later change
507
+ * of the caller's objects cannot reach the descriptor.
149
508
  *
150
509
  * @param options - The allowed answer and the visual hints.
151
510
  * @returns The descriptor a node awaits.
152
511
  * @example
153
512
  * ```ts
154
- * await fx(guide({ allow: { intent: "merge", payload: { from: "c2", to: "c3" } }, hand: "drag" }));
513
+ * // A tutorial node: the popup lists two intents, the guide lets only "ok" through.
514
+ * await fx(guide({ allow: { intent: "ok" }, target: { projection: "hud", key: "play" } }));
515
+ * await fx({ kind: "popup", answers: ["ok", "cancel"] });
516
+ * // app.flow.gate.answer({ intent: "cancel" }) is false until the node exits
155
517
  * ```
156
518
  */
157
519
  declare function guide(options: GuideOptions): Descriptor;
158
520
  //#endregion
159
- //#region src/teardown.d.ts
521
+ //#region src/plugins/world/ecs/define.d.ts
160
522
  /**
161
- * @file Teardown registry — the single allowlisted module-scope state of the package.
523
+ * Declares a component type. The defaults give the TypeScript type, the JSON shape and the
524
+ * inspector schema; the name is the storage key and the key of `motion.change`.
525
+ *
526
+ * @param name - Storage name, unique per world.
527
+ * @param defaults - Every field with its default value. Plain JSON only.
528
+ * @param options - The fields a plugin owns: a projection view neither writes nor corrects them.
529
+ * @param options.owned - Names of the owned fields.
530
+ * @returns A callable component type.
531
+ * @example
532
+ * ```ts
533
+ * const Item = component("Item", { kind: "", level: 1 });
534
+ * Item({ level: 2 }); // { type: Item, value: { kind: "", level: 2 } }
535
+ * Item({ level: 2 }).type.componentName; // "Item", the storage key
536
+ *
537
+ * // A caption whose drawn string is written by the plugin that draws it.
538
+ * const Caption = component("Caption", { text: "", shown: "" }, { owned: ["shown"] });
539
+ * Caption.owned; // ["shown"]
540
+ * ```
162
541
  */
542
+ declare function component<Value extends object>(name: string, defaults: Value, options?: {
543
+ owned?: ReadonlyArray<keyof Value & string>;
544
+ }): ComponentType<Value>;
163
545
  /**
164
- * Function that frees one plugin's resources.
546
+ * Declares a tag: a component with no data, stored as `true`.
165
547
  *
548
+ * @param name - Storage name, unique per world.
549
+ * @returns A callable tag type.
166
550
  * @example
167
551
  * ```ts
168
- * const dispose: Disposer = () => cancelAnimationFrame(handle);
552
+ * const Held = tag("Held");
553
+ * Held(); // { type: Held, value: true }
554
+ * Held().type.componentName; // "Held"
169
555
  * ```
170
556
  */
171
- type Disposer = () => void | Promise<void>;
557
+ declare function tag(name: string): TagType;
172
558
  /**
173
- * Registers a disposer for one plugin of one app. A second call with the same key replaces the first.
559
+ * Declares a resource: one mutable object per world, created from a deep clone of the defaults
560
+ * on first read.
174
561
  *
175
- * @param global - The app's frozen global config object, used as identity.
176
- * @param key - Plugin name.
177
- * @param dispose - Function that frees the plugin's resources.
562
+ * @param name - Storage name, unique per world.
563
+ * @param defaults - The value a fresh world starts with.
564
+ * @returns The resource type.
178
565
  * @example
179
566
  * ```ts
180
- * teardown.register(ctx.global, "time", stopLoop);
567
+ * const Pointer = resource("Pointer", { x: 0, y: 0, down: false });
568
+ * Pointer.defaults; // { x: 0, y: 0, down: false }
181
569
  * ```
182
570
  */
183
- declare function register(global: object, key: string, dispose: Disposer): void;
571
+ declare function resource<Value extends object>(name: string, defaults: Value): ResourceType<Value>;
184
572
  /**
185
- * Runs and removes the disposer of one plugin. A missing key is a no-op.
186
- * A throwing disposer is reported and never rethrown, so one plugin cannot block the stop of the others.
573
+ * Marks a query term as written. The only effect is change detection: every entity the query
574
+ * yields is marked changed for this component.
187
575
  *
188
- * @param global - The app's global config object.
189
- * @param key - Plugin name.
190
- * @returns Resolves when the disposer has finished.
576
+ * @param componentType - The component the system writes.
577
+ * @returns The marked term.
191
578
  * @example
192
579
  * ```ts
193
- * await teardown.run(global, "time");
580
+ * const Transform = component("Transform", { x: 0, y: 0 });
581
+ * mut(Transform).kind; // "mut"
194
582
  * ```
195
583
  */
196
- declare function run(global: object, key: string): Promise<void>;
584
+ declare function mut<Value extends object>(componentType: ComponentHandle<Value>): Mut<Value>;
197
585
  /**
198
- * Teardown registry keyed by `ctx.global`.
586
+ * Types a system definition. It returns the same plain object; the work is the type, which reads
587
+ * the query tuple and types the first argument of `run`.
199
588
  *
589
+ * @param definition - Name, phase, query and the run function.
590
+ * @returns The same definition, typed.
200
591
  * @example
201
592
  * ```ts
202
- * onStop: ({ global }) => teardown.run(global, "time")
593
+ * const Transform = component("Transform", { x: 0, y: 0 });
594
+ * const drift = system({
595
+ * name: "drift",
596
+ * phase: "animate",
597
+ * query: [mut(Transform)],
598
+ * run: entities => {
599
+ * for (const [, transform] of entities) transform.x += 1;
600
+ * }
601
+ * });
602
+ * drift.phase; // "animate"
203
603
  * ```
204
604
  */
205
- declare const teardown: {
206
- register: typeof register;
207
- run: typeof run;
605
+ declare function system<const Terms extends readonly QueryTerm[]>(definition: SystemDefinition<Terms>): SystemDefinition<Terms>;
606
+ /**
607
+ * The layer a view is drawn in. Written only by the projection; a `view` that returns it is
608
+ * logged and the value ignored.
609
+ */
610
+ declare const Layer: ComponentType<{
611
+ name: string;
612
+ }>;
613
+ /**
614
+ * Explicit draw order inside a layer sorted by `"order"`.
615
+ */
616
+ declare const Order: ComponentType<{
617
+ value: number;
618
+ }>;
619
+ /**
620
+ * The view is in the despawn queue: still drawn, never hit-tested.
621
+ */
622
+ declare const Exiting: TagType;
623
+ /**
624
+ * The element description of a screen: a projection whose `view` returns one node gets it wrapped
625
+ * as this component, and `ui` reconciles the node into child entities. The node is a foreign
626
+ * object, so the world diffs it by identity and `snapshot()` leaves it out.
627
+ */
628
+ declare const Tree: ComponentType<{
629
+ node: DescriptionNode;
630
+ }>;
631
+ //#endregion
632
+ //#region src/plugins/input/components.d.ts
633
+ /**
634
+ * A gesture that names an intent. `payload` is a plain JSON object of model keys, never an
635
+ * entity id: the flow graph reads it as the payload of the answer.
636
+ *
637
+ * @example
638
+ * ```ts
639
+ * const value: IntentValue = { intent: "merge", payload: { to: "c3" } };
640
+ * ```
641
+ */
642
+ type IntentValue = {
643
+ intent: string;
644
+ payload: Json;
645
+ };
646
+ /**
647
+ * A view that can be carried. It names no intent: the drop target does.
648
+ *
649
+ * @example
650
+ * ```ts
651
+ * const value: CarryValue = { payload: { from: "c2" } };
652
+ * ```
653
+ */
654
+ type CarryValue = {
655
+ payload: Json;
208
656
  };
657
+ /**
658
+ * Where the one pointer is, in reference units. `justPressed` and `justReleased` are true for
659
+ * exactly one frame.
660
+ *
661
+ * @example
662
+ * ```ts
663
+ * const value: PointerValue = {
664
+ * x: 540, y: 960, down: true, justPressed: false, justReleased: false
665
+ * };
666
+ * ```
667
+ */
668
+ type PointerValue = {
669
+ x: number;
670
+ y: number;
671
+ down: boolean;
672
+ justPressed: boolean;
673
+ justReleased: boolean;
674
+ };
675
+ /**
676
+ * A tap on this view answers `{ intent, payload }`.
677
+ */
678
+ declare const Tappable: ComponentType<IntentValue>;
679
+ /**
680
+ * A long press on this view answers `{ intent, payload }`.
681
+ */
682
+ declare const Pressable: ComponentType<IntentValue>;
683
+ /**
684
+ * This view can be carried by the finger. It names no intent; the drop target does.
685
+ */
686
+ declare const Draggable: ComponentType<CarryValue>;
687
+ /**
688
+ * A drop on this view answers THIS intent, with the carried payload merged under it.
689
+ */
690
+ declare const DropTarget: ComponentType<IntentValue>;
691
+ /**
692
+ * A swipe on this view answers `{ intent, payload: { ...payload, direction } }`.
693
+ */
694
+ declare const Swipeable: ComponentType<IntentValue>;
695
+ /**
696
+ * Takes a press without naming a gesture: the hit test accepts a view that carries only this tag,
697
+ * and a tap on it runs the `onTap` listeners and answers nothing. `ui` tags the buttons that
698
+ * write local state and name no intent.
699
+ */
700
+ declare const Touchable: TagType;
701
+ /**
702
+ * On the carried view, from grab to release.
703
+ */
704
+ declare const Held: TagType;
705
+ /**
706
+ * On the topmost drop target under the finger during a drag. At most one, never the held view.
707
+ */
708
+ declare const Hovered: TagType;
709
+ /**
710
+ * On the pressed view, from pointer down until a tap, a long press, a grab, a swipe or a cancel.
711
+ */
712
+ declare const Pressed: TagType;
713
+ /**
714
+ * On the topmost view a press would take, while a mouse or a pen moves over it with no press. At
715
+ * most one view carries it, and a touch never hovers. A touch sample, a pointer cancel, the pointer
716
+ * leaving the canvas and a paused world take it away. `ui` reads it as `is.hover`. It is not
717
+ * `Hovered`, which marks the drop target under a drag.
718
+ */
719
+ declare const PointerOver: TagType;
720
+ /**
721
+ * Where the one pointer is, in reference units. Written once per frame by the frame step.
722
+ */
723
+ declare const Pointer: ResourceType<PointerValue>;
724
+ //#endregion
725
+ //#region src/plugins/assets/bundles.d.ts
726
+ /**
727
+ * Declares the bundles of one feature. The map is copied, so a later change of the caller's
728
+ * object cannot reach the scanner or the plugin. `defineGame` returns this helper typed by the
729
+ * game's `BundleKey`, so a name the scanner never saw does not compile.
730
+ *
731
+ * @param map - Bundle name to its tier and, when it is a split bundle, its globs.
732
+ * @returns The bundle map as plain data.
733
+ * @example
734
+ * ```ts
735
+ * // features/board/assets.ts of a game: the board is a scene bundle, the chains load on demand.
736
+ * export const boardAssets = defineBundles({
737
+ * board: { tier: "scene" },
738
+ * "board.chains": { tier: "lazy", files: ["chains/*.png"] }
739
+ * });
740
+ * ```
741
+ */
742
+ declare function defineBundles<Key extends string>(map: Partial<Record<Key, BundleSpec>>): BundleMap<Key>;
743
+ /**
744
+ * Creates the awaited effect that loads one or more bundles. The handler of the kind `"load"` is
745
+ * registered by this plugin and runs in fast mode too, so a fast walk really loads.
746
+ *
747
+ * @param bundle - One bundle name, or a list of them in load order.
748
+ * @returns The descriptor a loading node awaits.
749
+ * @example
750
+ * ```ts
751
+ * // A loading node of a game: one bundle per turn, so the screen can draw progress.
752
+ * await fx(load("board.chains")); // { loaded: ["board.chains"], mb: 1.25 }
753
+ * await fx(load(["board", "ui"])); // both, in that order
754
+ * ```
755
+ */
756
+ declare function load(bundle: string | readonly string[]): Descriptor;
757
+ //#endregion
758
+ //#region src/plugins/scenes/define.d.ts
759
+ /**
760
+ * Declares a scene: a bundle, named layers in draw order, the projections it mounts and optional
761
+ * music. A layer `ui` is appended for the HUD and the popups unless the scene declares one. The
762
+ * layer names come from the keys of `layers` and that `ui`, so a projection whose `layer` or
763
+ * `lift` is not among them does not compile — and throws here for a caller without types.
764
+ *
765
+ * @param id - Id of the scene. A node names it with `defineNode({ scene: id })`.
766
+ * @param scene - The bundle, the layers, the projections and the optional music key.
767
+ * @returns The scene as frozen data, ready for the `scenes` key of a feature.
768
+ * @throws {Error} For an integer-like layer name, and for a `layer` or `lift` that is not declared.
769
+ * @example
770
+ * ```ts
771
+ * // features/board/view/scene.ts of a game.
772
+ * export const boardScene = defineScene("board", {
773
+ * bundle: "board",
774
+ * layers: { background: {}, cells: {}, items: { sort: "y" }, lifted: {} },
775
+ * projections: [boardCells, boardItems]
776
+ * });
777
+ *
778
+ * boardScene.layers[2]; // { name: "items", sort: "y" }
779
+ * boardScene.layers[4]; // { name: "ui", sort: "none" }, appended for the HUD
780
+ * ```
781
+ */
782
+ declare function defineScene<Layers extends LayerMap, const Projections extends readonly AnySceneProjection[]>(id: string, scene: SceneSpec<Layers, Projections, string, string>): SceneDefinition;
783
+ //#endregion
784
+ //#region src/plugins/anim/components.d.ts
785
+ /**
786
+ * How many tracks and running timelines name this entity. Written by `anim` while something
787
+ * moves and removed at zero; the inspector and `ui.lint` read it, `anim` itself never does.
788
+ */
789
+ declare const Animation: ComponentType<{
790
+ playing: number;
791
+ }>;
792
+ //#endregion
793
+ //#region src/plugins/anim/motion.d.ts
794
+ /**
795
+ * The display components a pure `defineMotion` can name. A hook has no context, so it can only
796
+ * reach the components `anim` itself imports: the four of `renderer` that carry numeric fields.
797
+ *
798
+ * @example
799
+ * ```ts
800
+ * type Fields = MotionComponents["Transform"]; // { x: number; y: number; rotation: number; scale: number }
801
+ * ```
802
+ */
803
+ type MotionComponents = {
804
+ Transform: TransformValue;
805
+ Sprite: SpriteValue;
806
+ NineSlice: NineSliceValue;
807
+ Shape: ShapeValue;
808
+ };
809
+ /**
810
+ * One named pose: the numeric fields it gives each component it names.
811
+ *
812
+ * @example
813
+ * ```ts
814
+ * const hidden: MotionState = { Transform: { scale: 0.8 }, Shape: { alpha: 0 } };
815
+ * ```
816
+ */
817
+ type MotionState = { readonly [Name in keyof MotionComponents]?: Readonly<Partial<NumericFields<MotionComponents[Name]>>> };
818
+ /**
819
+ * What `defineMotion` is given: the named poses, the keyframe tracks, how long the way takes, and
820
+ * which hooks to build. `on.enter` and `on.exit` name a state or a track. For a track,
821
+ * `transition.ms` is the whole walk and each segment eases by its key, not by `transition.ease`.
822
+ *
823
+ * `loop.track` names a keyframe track that plays from the moment the element enters, forever,
824
+ * added over whatever else moves it: one cycle is `loop.ms` (default `transition.ms`), every
825
+ * Transform key is an offset from rest, and the last key repeats the first one. It is not part of
826
+ * the motion `enter` returns.
827
+ *
828
+ * @example
829
+ * ```ts
830
+ * const spec: MotionSpec = {
831
+ * states: { hidden: { Transform: { scale: 0.8 } } },
832
+ * keyframes: { dropIn: [{ at: 0, Transform: { dy: -780, scale: 0.8 } }, { at: 0.42, Transform: { dy: 14 } }] },
833
+ * transition: { ms: 1000 },
834
+ * on: { enter: "dropIn", exit: "hidden", change: ["Transform"] }
835
+ * };
836
+ * // An order card pops in over 250 ms and sways on its pin, one swing every 2400 ms.
837
+ * const orderCard: MotionSpec = {
838
+ * states: { small: { Transform: { scale: 0.8 } } },
839
+ * keyframes: { sway: [{ at: 0, Transform: { rotation: 0 } }, { at: 0.5, Transform: { rotation: 0.03 } }, { at: 1, Transform: { rotation: 0 } }] },
840
+ * transition: { ms: 250 },
841
+ * loop: { track: "sway", ms: 2400 },
842
+ * on: { enter: "small" }
843
+ * };
844
+ * ```
845
+ */
846
+ type MotionSpec = {
847
+ readonly states?: Readonly<Record<string, MotionState>>;
848
+ readonly keyframes?: Readonly<Record<string, readonly MotionKeyframe[]>>;
849
+ readonly transition?: {
850
+ readonly ms?: number;
851
+ readonly ease?: Ease;
852
+ };
853
+ readonly loop?: {
854
+ readonly track: string;
855
+ readonly ms?: number;
856
+ };
857
+ readonly on: {
858
+ readonly enter?: string;
859
+ readonly exit?: string;
860
+ readonly change?: readonly (keyof MotionComponents & string)[];
861
+ };
862
+ };
863
+ /**
864
+ * Builds the projection motion hooks of an element from named poses and keyframe tracks. The
865
+ * transition is resolved and every name is checked here, at definition time, so every track it
866
+ * starts carries a concrete duration and a wrong name fails where it is written. A `loop` builds
867
+ * the `loop` hook: `world` and `ui` play it wherever they play `enter`, so a projection view loops
868
+ * once it entered with motion, never after a direct reconcile, and `ui` swaps it when the motion
869
+ * prop of an element changes. One cycle of the loop is `loop.ms`, or `transition.ms` when it is
870
+ * left out.
871
+ *
872
+ * @param spec - The named poses, the keyframe tracks, the transition, the loop and the hooks to
873
+ * build.
874
+ * @returns The `enter`, `loop`, `exit` and `change` hooks. `settle` is left out: the default of
875
+ * `world` applies.
876
+ * @throws {Error} When a track is invalid, a name is both a state and a track, `on` names
877
+ * neither, `loop.track` names no track, `loop.ms` is not a finite number above 0, or the loop
878
+ * ends somewhere else than it starts.
879
+ * @example
880
+ * ```ts
881
+ * const buttonMotion = defineMotion({
882
+ * states: { hidden: { Transform: { scale: 0.8 }, Shape: { alpha: 0 } } },
883
+ * transition: { ms: 150, ease: "out" },
884
+ * on: { enter: "hidden", exit: "hidden", change: ["Transform"] }
885
+ * });
886
+ * buttonMotion.settle; // undefined
887
+ * ```
888
+ */
889
+ declare function defineMotion(spec: MotionSpec): ProjectionMotion<unknown>;
890
+ //#endregion
891
+ //#region src/plugins/anim/timeline/steps.d.ts
892
+ /**
893
+ * Runs the steps one after another. The remainder past a step's end reaches the next step in the
894
+ * same frame, so the tree takes exactly the sum of its durations.
895
+ *
896
+ * @param steps - The steps, in order.
897
+ * @returns The sequence step.
898
+ * @example
899
+ * ```ts
900
+ * sequence(wait(100), mark("done"));
901
+ * // { kind: "sequence", steps: [{ kind: "wait", ms: 100 }, { kind: "mark", name: "done" }] }
902
+ * ```
903
+ */
904
+ declare function sequence(...steps: readonly Step[]): Step;
905
+ /**
906
+ * Runs every step at once and ends with the longest one.
907
+ *
908
+ * @param steps - The steps.
909
+ * @returns The parallel step.
910
+ * @example
911
+ * ```ts
912
+ * parallel(wait(100), wait(300)); // ends after 300 ms
913
+ * ```
914
+ */
915
+ declare function parallel(...steps: readonly Step[]): Step;
916
+ /**
917
+ * Builds one step per item and starts each one `staggerMs` later than the one before. The build
918
+ * function runs here, so no function survives in the data.
919
+ *
920
+ * @param items - What to build a step for.
921
+ * @param staggerMs - Delay between two neighbouring items, in game milliseconds.
922
+ * @param build - Builds the step of one item.
923
+ * @returns The parallel of delayed sequences.
924
+ * @example
925
+ * ```ts
926
+ * stagger(["a", "b"], 60, item => mark(item));
927
+ * // parallel(sequence(wait(0), mark("a")), sequence(wait(60), mark("b")))
928
+ * ```
929
+ */
930
+ declare function stagger<Item>(items: readonly Item[], staggerMs: number, build: (item: Item, index: number) => Step): Step;
931
+ /**
932
+ * Holds still for a while.
933
+ *
934
+ * @param durationMs - How long to wait, in game milliseconds.
935
+ * @returns The wait step.
936
+ * @example
937
+ * ```ts
938
+ * wait(120); // { kind: "wait", ms: 120 }
939
+ * ```
940
+ */
941
+ declare function wait(durationMs: number): Step;
942
+ /**
943
+ * Names a point in the choreography. Reaching it emits `anim:mark`, calls the `onMark` listeners
944
+ * and appends the name to `marks()`. It is the only way out of a timeline.
945
+ *
946
+ * @param name - Name of the mark.
947
+ * @returns The mark step.
948
+ * @example
949
+ * ```ts
950
+ * mark("landed"); // { kind: "mark", name: "landed" }
951
+ * ```
952
+ */
953
+ declare function mark(name: string): Step;
954
+ /**
955
+ * Moves the numeric fields of one component of one target to an exact target value. The component
956
+ * is any handle `world.ecs` takes, so the kit's `Sprite` and `NineSlice` of `defineGame` pass as
957
+ * they are.
958
+ *
959
+ * By default the fields are local: they are written into the target's own `Transform`. With
960
+ * `space: "root"` the `x`, `y`, `rotation` and `scale` of a `Transform` are a root pose, the space
961
+ * `at()` answers in, and are turned into the space of the target's `Parent` when the track starts.
962
+ * That aims a hosted view, such as a board item inside the board slot, at another element. A
963
+ * field the step does not name stays where it is, so under a turned parent name `x` and `y`
964
+ * together. A target without a parent, and a component other than `Transform`, move as in the
965
+ * local space.
966
+ *
967
+ * @param target - The projection key or the entity to animate.
968
+ * @param component - The component to animate.
969
+ * @param to - The numeric target fields.
970
+ * @param options - Duration, easing, delay, the additive flag and the space of the fields.
971
+ * @param options.ms - Duration in game milliseconds.
972
+ * @param options.ease - Easing curve; `"out"` when omitted.
973
+ * @param options.delayMs - How long the track waits before it reads its start values.
974
+ * @param options.additive - `true` adds an offset instead of owning the fields.
975
+ * @param options.space - `"root"` reads the `Transform` fields as a root pose; `"local"` when
976
+ * omitted.
977
+ * @returns The tween step.
978
+ * @example
979
+ * ```ts
980
+ * // An order is delivered: the board item flies out of the scaled board slot onto the order card.
981
+ * const deliverFly = defineAnimation("orders.deliverFly", {
982
+ * slots: { item: type<Target>(), card: type<Target>() },
983
+ * build: ({ item, card }, { at }) =>
984
+ * tween(item, Transform, { x: at(card).x, y: at(card).y, scale: at(card).scale }, {
985
+ * ms: 400, ease: "inCubic", space: "root"
986
+ * })
987
+ * });
988
+ * app.anim.play(deliverFly, {
989
+ * item: { projection: "board.items", key: "i1" },
990
+ * card: { projection: "hud", key: "card0" }
991
+ * });
992
+ * // 400 ms later the item covers the card at the card's size; its Transform stays slot-local
993
+ * ```
994
+ */
995
+ declare function tween<Value extends object>(target: Target, component: ComponentHandle<Value>, to: Partial<NumericFields<Value>>, options: {
996
+ ms: number;
997
+ ease?: Ease;
998
+ delayMs?: number;
999
+ additive?: boolean;
1000
+ space?: "local" | "root";
1001
+ }): Step;
1002
+ /**
1003
+ * Writes a component patch at once. Any field may be written, not only the numeric ones. The
1004
+ * component is any handle `world.ecs` takes, the kit's `Sprite` and `NineSlice` included.
1005
+ *
1006
+ * @param target - The projection key or the entity to write.
1007
+ * @param component - The component to write.
1008
+ * @param patch - The fields to overwrite.
1009
+ * @returns The set step.
1010
+ * @example
1011
+ * ```ts
1012
+ * set({ projection: "hud", key: "coins" }, Sprite, { texture: "hud.coin-gold" });
1013
+ * // { kind: "set", patch: { texture: "hud.coin-gold" }, ... }
1014
+ * ```
1015
+ */
1016
+ declare function set<Value extends object>(target: Target, component: ComponentHandle<Value>, patch: Partial<Value>): Step;
1017
+ /**
1018
+ * Plays a frame sprite: one texture key of the list per frame of `fps`, written into `Sprite`.
1019
+ *
1020
+ * @param target - The projection key or the entity to animate.
1021
+ * @param options - The keys, the frame rate and whether the list repeats.
1022
+ * @param options.keys - The texture keys, in play order.
1023
+ * @param options.fps - Frames per second of the list.
1024
+ * @param options.loop - `true` repeats the list until the step is finished.
1025
+ * @returns The frames step.
1026
+ * @example
1027
+ * ```ts
1028
+ * frames({ projection: "board", key: "c3" }, { keys: ["fx.pop-1", "fx.pop-2"], fps: 12 });
1029
+ * // { kind: "frames", keys: ["fx.pop-1", "fx.pop-2"], fps: 12, loop: false, ... }
1030
+ * ```
1031
+ */
1032
+ declare function frames(target: Target, options: {
1033
+ keys: readonly string[];
1034
+ fps: number;
1035
+ loop?: boolean;
1036
+ }): Step;
1037
+ /**
1038
+ * Makes a temporary entity when the step is reached: a flying coin, a toast sign, a sparkle. The
1039
+ * entity is owned by `anim`, drawn in `layer` at `order`, and despawned when the timeline ends, is
1040
+ * finished or is cancelled. Later steps of the same timeline aim at it with `spawned(id)`.
1041
+ *
1042
+ * @param id - Name of the entity inside this timeline; one timeline spawns each id once.
1043
+ * @param components - The component values the entity starts with, as `world.ecs.spawn` takes.
1044
+ * @param options - Where the entity is drawn.
1045
+ * @param options.layer - The layer; `"ui"` when omitted.
1046
+ * @param options.order - The draw order inside the layer; `0` when omitted.
1047
+ * @returns The spawn step.
1048
+ * @example
1049
+ * ```ts
1050
+ * spawn("coin1", [Sprite({ texture: "ui.icon-coin" }), Transform({ x: 540, y: 900 })], { order: 50 });
1051
+ * // { kind: "spawn", id: "coin1", components: [...], layer: "ui", order: 50 }
1052
+ * ```
1053
+ */
1054
+ declare function spawn(id: string, components: readonly AnyComponentValue[], options?: {
1055
+ layer?: string;
1056
+ order?: number;
1057
+ }): Step;
1058
+ /**
1059
+ * Aims a later step at the entity a `spawn` step of the same timeline made. Before that step is
1060
+ * reached nothing answers the id, so a step aimed at it ends silently.
1061
+ *
1062
+ * @param id - The id the `spawn` step was given.
1063
+ * @returns The target.
1064
+ * @example
1065
+ * ```ts
1066
+ * tween(spawned("coin1"), Transform, { x: 40, y: 120 }, { ms: 600, ease: "inCubic" });
1067
+ * // { kind: "tween", target: { spawned: "coin1" }, ... }
1068
+ * ```
1069
+ */
1070
+ declare function spawned(id: string): {
1071
+ spawned: string;
1072
+ };
1073
+ /**
1074
+ * A sound. `anim` owns the descriptor because it sits below `audio`; `audio` owns the handler,
1075
+ * and a game without `audio` plays nothing and hears no error.
1076
+ *
1077
+ * @param key - Asset key of the sound.
1078
+ * @param options - The bus to play it on.
1079
+ * @param options.bus - `"sfx"` when omitted.
1080
+ * @returns The descriptor, usable as a timeline step and as `fx(...)` in a node.
1081
+ * @example
1082
+ * ```ts
1083
+ * sfx("board.merge"); // { kind: "sfx", payload: { key: "board.merge", bus: "sfx" }, cosmetic: true }
1084
+ * ```
1085
+ */
1086
+ declare function sfx(key: string, options?: {
1087
+ bus?: string;
1088
+ }): SfxDescriptor;
1089
+ /**
1090
+ * A haptic tick. `platform` owns the handler; a device without one stays still.
1091
+ *
1092
+ * @param kind - Which tick to play, for example `"light"`.
1093
+ * @returns The descriptor, usable as a timeline step and as `fx(...)` in a node.
1094
+ * @example
1095
+ * ```ts
1096
+ * haptic("light"); // { kind: "haptic", payload: { kind: "light" }, cosmetic: true }
1097
+ * ```
1098
+ */
1099
+ declare function haptic(kind: string): HapticDescriptor;
1100
+ /**
1101
+ * Reserved for Spine and the other external players. It throws until one arrives, so nobody
1102
+ * builds a choreography on a door that is not open yet.
1103
+ *
1104
+ * @param _player - The player that would run the clip.
1105
+ * @param _clip - Name of the clip.
1106
+ * @throws {Error} Always.
1107
+ * @example
1108
+ * ```ts
1109
+ * external(spine, "idle"); // throws: External players arrive with Spine.
1110
+ * ```
1111
+ */
1112
+ declare function external(_player: ExternalPlayer, _clip: string): never;
1113
+ /**
1114
+ * Nests one animation inside another. The nested tree is built here, so its marks are reported
1115
+ * under the nested id and no function survives in the data. Pass the outer `tools` when the
1116
+ * nested `build` reads `at`.
1117
+ *
1118
+ * @param animation - The animation to nest.
1119
+ * @param slots - One target, or a list of targets, per slot of the nested animation.
1120
+ * @param tools - The build tools of the outer animation; without them `at` is the identity pose.
1121
+ * @returns The use step.
1122
+ * @example
1123
+ * ```ts
1124
+ * use(popCard, { card: { projection: "hud", key: "order" } });
1125
+ * // { kind: "use", id: "hud.popCard", step: { kind: "sequence", ... } }
1126
+ * ```
1127
+ */
1128
+ declare function use<Tags extends SlotTags>(animation: AnimationDefinition<Tags>, slots: SlotValues<Tags>, tools?: BuildTools): Step;
1129
+ /**
1130
+ * The effect descriptor a node awaits to play a choreography. The payload names the animation,
1131
+ * so the handler resolves the definition from the registry the features filled.
1132
+ *
1133
+ * @param animation - The animation to play.
1134
+ * @param slots - One target, or a list of targets, per slot.
1135
+ * @returns The descriptor, cosmetic, so a failing build never breaks the node.
1136
+ * @example
1137
+ * ```ts
1138
+ * play(coinsFly, { from: { projection: "hud", key: "purse" } });
1139
+ * // { kind: "play", payload: { animation: "hud.coinsFly", slots: { from: { ... } } }, cosmetic: true }
1140
+ * ```
1141
+ */
1142
+ declare function play<Tags extends SlotTags>(animation: AnimationDefinition<Tags>, slots: SlotValues<Tags>): PlayDescriptor;
1143
+ /**
1144
+ * Declares one animation: an id, the slots it takes and the pure function that builds its step
1145
+ * tree. `build` runs once per play, so the same animation may play twice at once.
1146
+ *
1147
+ * @param id - Animation id, unique across the features of a game.
1148
+ * @param spec - The slots and the build function.
1149
+ * @returns The animation as frozen plain data.
1150
+ * @example
1151
+ * ```ts
1152
+ * const coinsFly = defineAnimation("hud.coinsFly", {
1153
+ * slots: { from: type<Target>() },
1154
+ * build: ({ from }) => tween(from, Transform, { scale: 0.4 }, { ms: 600 })
1155
+ * });
1156
+ * coinsFly.id; // "hud.coinsFly"
1157
+ * ```
1158
+ */
1159
+ declare function defineAnimation<Tags extends SlotTags>(id: string, spec: AnimationSpec<Tags>): AnimationDefinition<Tags>;
1160
+ //#endregion
1161
+ //#region src/plugins/i18n/tr.d.ts
1162
+ /**
1163
+ * Builds a message. The result is frozen and the parameters are copied, so the caller's object
1164
+ * stays its own and nothing downstream can rewrite a label in place.
1165
+ *
1166
+ * @param key - The message key, one of the keys `compileStrings` generated.
1167
+ * @param params - The parameters the message declares. An element parameter is kept as it is.
1168
+ * @returns The message, frozen.
1169
+ * @example
1170
+ * ```ts
1171
+ * tr("hud.orders", { n: 3 }); // { key: "hud.orders", params: { n: 3 } }
1172
+ * tr("orders.complete"); // { key: "orders.complete" }
1173
+ * ```
1174
+ */
1175
+ declare function tr(key: string, params?: Record<string, Argument>): Message;
1176
+ //#endregion
1177
+ //#region src/plugins/ui/styles/define.d.ts
1178
+ /**
1179
+ * Declares one style. The work is the type: a field outside the vocabulary, or a value outside
1180
+ * its union, is an error where the style is written, not where it is used.
1181
+ *
1182
+ * @param style - The style, with its `is` and `when` variants.
1183
+ * @returns The same object, frozen.
1184
+ * @example
1185
+ * ```ts
1186
+ * defineStyle({ direction: "row", gap: 12 }).gap; // 12
1187
+ * ```
1188
+ */
1189
+ declare function defineStyle<const Given extends Style>(style: Given): Readonly<Given>;
1190
+ //#endregion
1191
+ //#region src/plugins/ui/styles/resolve.d.ts
1192
+ /**
1193
+ * The flags one element is resolved against: the viewport flags of the frame plus its own state.
1194
+ *
1195
+ * @example
1196
+ * ```ts
1197
+ * const flags: StyleFlags = {
1198
+ * portrait: true, landscape: false, tall: false, wide: false,
1199
+ * pressed: false, hover: false, focus: false, disabled: false, active: true, selected: false,
1200
+ * covered: false
1201
+ * };
1202
+ * ```
1203
+ */
1204
+ type StyleFlags = WhenFlags & IsFlags;
1205
+ /**
1206
+ * Resolves one style against the flags of the frame and the viewport.
1207
+ *
1208
+ * @param style - The style a game wrote, or nothing.
1209
+ * @param flags - The four viewport flags and the seven state flags. While `disabled` is true the
1210
+ * `hover` and `pressed` variants are skipped.
1211
+ * @param viewport - What `renderer.viewport.size()` answered, for the safe-area tokens.
1212
+ * @returns The frozen style the layout and the visual are written from.
1213
+ * @example
1214
+ * ```ts
1215
+ * resolve(
1216
+ * { gap: 8, is: { pressed: { gap: 4 } } },
1217
+ * { portrait: true, landscape: false, tall: false, wide: false,
1218
+ * pressed: true, hover: false, focus: false, disabled: false, active: false, selected: false,
1219
+ * covered: false },
1220
+ * { width: 1080, height: 1920, scale: 1, orientation: "portrait",
1221
+ * safeArea: { top: 0, right: 0, bottom: 0, left: 0 } }
1222
+ * ).gap; // 4
1223
+ * ```
1224
+ */
1225
+ declare function resolve(style: Style | undefined, flags: StyleFlags, viewport: ViewportSize): ResolvedStyle;
1226
+ //#endregion
1227
+ //#region src/plugins/audio/descriptors.d.ts
1228
+ /**
1229
+ * Creates the awaited effect that switches the music track. The same key as the one playing does
1230
+ * nothing, and `null` fades the current track out. An absent `fadeMs` leaves the key out of the
1231
+ * payload, so the descriptor stays plain JSON and the plugin's `musicFadeMs` decides at play time.
1232
+ *
1233
+ * @param key - Asset key of an `.mp3`, or `null` to stop the music.
1234
+ * @param options - `fadeMs` overrides the configured cross-fade for this switch.
1235
+ * @returns The descriptor a node awaits, frozen.
1236
+ * @example
1237
+ * ```ts
1238
+ * // A node of a game: the menu goes quiet before the ending cinematic starts.
1239
+ * await fx(music(null, { fadeMs: 1500 }));
1240
+ * // music("board.theme") is { kind: "music", payload: { key: "board.theme" }, cosmetic: true }
1241
+ * ```
1242
+ */
1243
+ declare function music(key: string | null, options?: MusicOptions): Descriptor;
209
1244
  //#endregion
210
1245
  //#region src/index.d.ts
211
1246
  /**
@@ -213,7 +1248,11 @@ declare const teardown: {
213
1248
  *
214
1249
  * @example
215
1250
  * ```ts
216
- * const app = createApp({ plugins: [boardFeature] });
1251
+ * // The entry point of a game. The graph is started by the game, never by the plugin.
1252
+ * const app = createApp({
1253
+ * pluginConfigs: { flow: { mainFlow, safeNode: "home" } },
1254
+ * onStart: ctx => void ctx.flow.run().catch(error => ctx.log.error("game: failed", { error }))
1255
+ * });
217
1256
  * ```
218
1257
  */
219
1258
  declare const createApp: <const ExtraPlugins extends readonly import("@moku-labs/core").AnyPluginInstance[] = readonly []>(options?: import("@moku-labs/core").CreateAppOptions<Config$5, Events, (import("@moku-labs/core").PluginInstance<"time", Config$4, State$4, Api$3, {}> & Record<never, never>) | (import("@moku-labs/core").PluginInstance<"lifecycle", Config$2, State$2, Api$2, {
@@ -302,26 +1341,141 @@ declare const createApp: <const ExtraPlugins extends readonly import("@moku-labs
302
1341
  *
303
1342
  * @example
304
1343
  * ```ts
305
- * export const scorePlugin = createPlugin("score", { api: createScoreApi });
1344
+ * // A game plugin that writes every edge of the graph to the log.
1345
+ * export const edgeLog = createPlugin("edgeLog", {
1346
+ * depends: [flowPlugin],
1347
+ * hooks: ctx => ({ "flow:edge": ({ node, outcome }) => ctx.log.info("edge", { node, outcome }) })
1348
+ * });
306
1349
  * ```
307
1350
  */
308
1351
  declare const createPlugin: import("@moku-labs/core").BoundCreatePluginFunction<Config$5, Events, import("@moku-labs/core").CoreApisFromTuple<[import("@moku-labs/core").CorePluginInstance<"log", import("@moku-labs/common/browser").LogConfig, import("@moku-labs/common/browser").LogState, import("@moku-labs/common/browser").LogApi>, import("@moku-labs/core").CorePluginInstance<"env", import("@moku-labs/common/browser").EnvConfig, import("@moku-labs/common/browser").EnvState, import("@moku-labs/common/browser").EnvApi>]>>;
309
1352
  /**
310
- * Binds the authoring helpers to the types of one game: "createApp for a game". The binding is
311
- * type-only; at run time these are the same functions the plugins export. One line per helper,
312
- * no logic: anything a single plugin can own lives in that plugin.
1353
+ * Binds the authoring helpers to the types of one game: "createApp for a game". Each plugin binds
1354
+ * its own helpers (`flowFor`, `projectionFor`, `componentsFor`, `bundlesFor`, `scenesFor`); this
1355
+ * only spreads them, so the kit's type is inferred and never written by hand. At run time these
1356
+ * are the same functions and component objects the plugins export.
313
1357
  *
314
- * @returns The helpers typed with the game's `player` and `session`.
1358
+ * @returns The helpers typed with the game's `player`, `session`, `assets`, `bundles` and `strings`.
315
1359
  * @example
316
1360
  * ```ts
317
- * export const { defineNode, defineFlow, defineFeature } = defineGame<{
318
- * player: Player;
319
- * session: Session;
320
- * assets: AssetKey;
321
- * strings: StringTable;
322
- * }>();
1361
+ * // kit.ts of a game: bound once, imported by every node, flow and view file.
1362
+ * export const { defineNode, defineFlow, defineFeature, projection, sprite, Sprite, defineBundles, load, defineScene } =
1363
+ * defineGame<{ player: Player; session: Session; assets: AssetKey; bundles: BundleKey; strings: StringTable }>();
323
1364
  * ```
324
1365
  */
325
- declare function defineGame<Types extends GameTypes>(): Kit<Types>;
1366
+ declare function defineGame<Types extends GameTypes>(): {
1367
+ music: MusicDescriptor<Types["assets"]>;
1368
+ defineComponent: typeof defineComponent;
1369
+ defineStyle: <const Given extends Style<Types["assets"]>>(style: Given) => Readonly<Given>;
1370
+ defineTokens: typeof defineTokens;
1371
+ popup: <Properties extends object, Local extends object>(component: PopupComponent<Properties, Local>, props: Properties, options?: {
1372
+ over?: string;
1373
+ }) => Descriptor;
1374
+ intrinsics: IntrinsicElementsFor<Types["assets"], TextStylesOf<Types>, Extract<keyof Types["strings"], string>>;
1375
+ label: (options: Omit<LabelOptions, "style"> & {
1376
+ style: TextStylesOf<Types>;
1377
+ }) => ReturnType<typeof label>;
1378
+ defineTextStyles: (map: Record<string, Omit<TextStyleInput, "bold" | "font" | "italic"> & {
1379
+ font: Types["assets"];
1380
+ } & {
1381
+ bold?: Types["assets"];
1382
+ italic?: Types["assets"];
1383
+ }>) => TextStyles;
1384
+ tr: TypedTr<Types["strings"]>;
1385
+ defineAnimation: typeof defineAnimation;
1386
+ frames: (target: Target, options: {
1387
+ keys: readonly Types["assets"][];
1388
+ fps: number;
1389
+ loop?: boolean;
1390
+ }) => Step;
1391
+ sfx: (key: Types["assets"], options?: {
1392
+ bus?: string;
1393
+ }) => SfxDescriptor;
1394
+ play: typeof play;
1395
+ defineScene: DefineScene<Types["assets"], BundlesOf<Types>>;
1396
+ defineBundles: DefineBundles<BundlesOf<Types>>;
1397
+ load: LoadBundles<BundlesOf<Types>>;
1398
+ sprite: (options: Omit<SpriteOptions, "texture"> & {
1399
+ texture: Types["assets"];
1400
+ }) => ReturnType<typeof sprite>;
1401
+ Sprite: Narrowed<SpriteValue, Partial<Omit<SpriteValue, "texture">> & {
1402
+ texture?: Types["assets"];
1403
+ }>;
1404
+ NineSlice: Narrowed<NineSliceValue, Partial<Omit<NineSliceValue, "texture">> & {
1405
+ texture?: Types["assets"];
1406
+ }>;
1407
+ projection: ProjectionFor<Types["player"], Types["session"]>;
1408
+ defineNode: DefineNode<{
1409
+ player: Types["player"];
1410
+ session: Types["session"];
1411
+ scenes: SceneIdOf<Types>;
1412
+ }>;
1413
+ defineFlow: typeof defineFlow;
1414
+ defineFeature: (name: string, description: FeatureDescription) => FeaturePlugin;
1415
+ };
1416
+ /**
1417
+ * The screen plugins, in dependency order. A game with a screen spreads them into `plugins`;
1418
+ * a headless test leaves them out. V2: `world`, `renderer`, `input`, `assets`, `scenes`. V3 appends `anim`, `i18n`, `text`, `ui`; `audio` stays opt-in: `[...screen, audioPlugin]`.
1419
+ *
1420
+ * @example
1421
+ * ```ts
1422
+ * createApp({ plugins: [...screen, boardFeature], pluginConfigs: { renderer: { mount: "#game" } } });
1423
+ * ```
1424
+ */
1425
+ declare const screen: readonly [import("@moku-labs/core").PluginInstance<"world", Config$7, State$6, Api$5, {
1426
+ "world:reconciled": {
1427
+ mode: "play" | "direct";
1428
+ projections: number;
1429
+ entered: number;
1430
+ changed: number;
1431
+ exited: number;
1432
+ revived: number;
1433
+ queued: number;
1434
+ hintsRouted: number;
1435
+ hintsDropped: number;
1436
+ };
1437
+ }> & Record<never, never>, import("@moku-labs/core").PluginInstance<"renderer", Config$6, State$5, Api$4, {
1438
+ "renderer:device-lost": {
1439
+ kind: "webgpu" | "webgl";
1440
+ reason: string;
1441
+ };
1442
+ }> & Record<never, never>, import("@moku-labs/core").PluginInstance<"input", Config$10, State$9, InputApi, {}> & Record<never, never>, import("@moku-labs/core").PluginInstance<"assets", Config$8, State$7, Api$6, {
1443
+ "assets:bundle-loaded": {
1444
+ bundle: string;
1445
+ tier: Tier;
1446
+ mb: number;
1447
+ reason: LoadReason;
1448
+ };
1449
+ "assets:bundle-progress": {
1450
+ bundle: string;
1451
+ loaded: number;
1452
+ total: number;
1453
+ };
1454
+ "assets:bundle-unloaded": {
1455
+ bundle: string;
1456
+ tier: Tier;
1457
+ mb: number;
1458
+ reason: "budget" | "request";
1459
+ keys: readonly string[];
1460
+ };
1461
+ }> & Record<never, never>, import("@moku-labs/core").PluginInstance<"scenes", Record<string, never>, State$14, ScenesApi, {
1462
+ "scenes:changed": {
1463
+ from: string | undefined;
1464
+ to: string;
1465
+ music: string | undefined;
1466
+ };
1467
+ }> & Record<never, never>, import("@moku-labs/core").PluginInstance<"anim", Config$13, State$12, AnimApi, {
1468
+ "anim:mark": {
1469
+ animation: string;
1470
+ mark: string;
1471
+ };
1472
+ "anim:finished": {
1473
+ animation: string;
1474
+ };
1475
+ }> & Record<never, never>, import("@moku-labs/core").PluginInstance<"i18n", Config$9, State$8, I18nApi, {
1476
+ "i18n:locale-changed": {
1477
+ locale: string;
1478
+ };
1479
+ }> & Record<never, never>, import("@moku-labs/core").PluginInstance<"text", Config$11, State$10, TextApi, {}> & Record<never, never>, import("@moku-labs/core").PluginInstance<"ui", Config$12, State$11, UiApi, {}> & Record<never, never>];
326
1480
  //#endregion
327
- export { types_d_exports as Clock, types_d_exports$1 as Flow, types_d_exports$2 as Lifecycle, types_d_exports$3 as Model, SaveUnreadableError, types_d_exports$4 as Time, clockPlugin, createApp, createPlugin, defineFeature, defineGame, exit, flowPlugin, guide, hint, lifecyclePlugin, modelPlugin, schedule, slot, teardown, timePlugin, to, type };
1481
+ export { types_d_exports as Anim, Animation, types_d_exports$1 as Assets, types_d_exports$2 as Audio, Box, types_d_exports$3 as Clock, type DescriptionNode, Display, Draggable, DropTarget, Exiting, types_d_exports$4 as Flow, Held, Hovered, types_d_exports$5 as I18n, types_d_exports$6 as Input, Layer, types_d_exports$7 as Lifecycle, LocalWrite, types_d_exports$8 as Model, NineSlice, Order, Parent, Pointer, PointerOver, Pressable, Pressed, types_d_exports$9 as Renderer, SaveUnreadableError, types_d_exports$10 as Scenes, Shape, Sprite, Swipeable, Tappable, Text, types_d_exports$11 as TextTypes, types_d_exports$12 as Time, Touchable, Transform, Tree, types_d_exports$13 as Ui, types_d_exports$14 as World, animPlugin, assetsPlugin, audioPlugin, clockPlugin, component, createApp, createPlugin, defineAnimation, defineBundles, defineComponent, defineFeature, defineGame, defineMotion, defineScene, defineStyle, defineTextStyles, defineTokens, exit, external, flowPlugin, frames, guide, haptic, hint, i18nPlugin, inputPlugin, label, lifecyclePlugin, load, mark, modelPlugin, music, mut, parallel, play, popup, projection, rendererPlugin, resolve, resource, scenesPlugin, schedule, screen, sequence, set, sfx, slot, spawn, spawned, sprite, stagger, system, tag, textPlugin, timePlugin, to, tr, tween, type, uiPlugin, use, wait, worldPlugin };