@moku-labs/game 0.7.1 → 0.9.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 (40) hide show
  1. package/README.md +12 -8
  2. package/dist/assets.d.mts +97 -33
  3. package/dist/assets.mjs +350 -110
  4. package/dist/{commands-mzE9PX0H.d.mts → commands-DuwCxK5t.d.mts} +5 -4
  5. package/dist/control.d.mts +4 -3
  6. package/dist/control.mjs +2 -2
  7. package/dist/{define-BbgXv4cy.d.mts → define-B6pHpdBi.d.mts} +4 -3
  8. package/dist/headless-BsNdJs9W.mjs +186 -0
  9. package/dist/headless-SCQXJxQf.d.mts +181 -0
  10. package/dist/hot.d.mts +4 -2
  11. package/dist/hot.mjs +8 -6
  12. package/dist/index-BO9kZzY3.d.mts +1611 -0
  13. package/dist/index.d.mts +6 -1596
  14. package/dist/index.mjs +4 -34334
  15. package/dist/{input-CK4nxBO1.mjs → input-z_35Jwfn.mjs} +2 -2
  16. package/dist/inspect.d.mts +7 -6
  17. package/dist/inspect.mjs +2 -2
  18. package/dist/jsx-dev-runtime.d.mts +1 -1
  19. package/dist/jsx-runtime.d.mts +1 -1
  20. package/dist/lint.d.mts +55 -4
  21. package/dist/lint.mjs +993 -40
  22. package/dist/project.d.mts +57 -41
  23. package/dist/project.mjs +994 -505
  24. package/dist/{run-Bcyg32M5.mjs → run-CofJEdYx.mjs} +4 -187
  25. package/dist/{runtime-HTlmRb81.d.mts → runtime-CdNJ0UBm.d.mts} +1 -1
  26. package/dist/{sources-DVWJ8nfr.mjs → sources-DNnzyCYf.mjs} +2 -2
  27. package/dist/src-536arXjV.mjs +34644 -0
  28. package/dist/testing.d.mts +85 -283
  29. package/dist/testing.mjs +158 -2109
  30. package/dist/{types-BMEn0tSC.d.mts → types-B0v5VVa3.d.mts} +10 -9
  31. package/dist/{types-ClF8say0.d.mts → types-CQueODzo.d.mts} +2 -2
  32. package/dist/{types-CYYKjvLn.d.mts → types-DUMoYPYe.d.mts} +5 -182
  33. package/dist/{types-CXyipKhE.d.mts → types-VZVWwqCg.d.mts} +42 -4
  34. package/dist/{types-BaUUcIaN.d.mts → types-xXfyk56Q.d.mts} +1 -1
  35. package/dist/{visual-DUvvPPCt.mjs → visual-dMW8iqAE.mjs} +8 -4
  36. package/dist/visual.d.mts +330 -0
  37. package/dist/visual.mjs +2142 -0
  38. package/llms.txt +59 -21
  39. package/package.json +7 -8
  40. package/dist/memory-CvgdnsQO.mjs +0 -259
package/dist/index.d.mts CHANGED
@@ -1,1596 +1,6 @@
1
- import { $ as Ease, A as Config$8, B as ComponentValue, Bt as State$7, Ct as to, Dt as DefineNode, Ft as GuideOptions, G as Narrowed, Ht as types_d_exports$14, It as Hint, J as ResourceType, Jt as State$5, Kt as Json, L as ComponentHandle, M as State$8, Mt as SceneIdOf, N as types_d_exports$16, O as ViewportSize, Pt as Descriptor, Q as DescriptionNode, Rt as Api$5, S as types_d_exports$11, St as slot, Tt as FeatureDescription, W as Mut, Wt as Config$5, X as TagType, Xt as Patch, Y as SystemDefinition, Yt as types_d_exports$9, _n as Events$1, _t as State$3, a as DefineBundles, an as Api$3, at as ProjectionMotion, b as State$6, bt as defineFlow, c as LoadReason, cn as PauseReason, d as Tier, dn as Api$1, dt as BundlesOf, en as SaveUnreadableError, fn as Config$2, ft as Config$3, gn as Config$9, h as Config$6, hn as types_d_exports$3, ht as GameTypes, i as Config$1, it as NumericFields, k as Api$6, ln as State$4, m as Api$4, mn as State$2, mt as FeaturePlugin, n as BundleMap, nn as StoreApi, on as Config$4, ot as ProjectionSpec, p as types_d_exports$1, pt as EmitterIdOf, q as QueryTerm, qt as Root, r as BundleSpec, rn as RngApi, s as LoadBundles, sn as Events, t as Api, u as State$1, un as types_d_exports$8, ut as Api$2, vn as Require, vt as TextStylesOf, wt as type, xt as exit, yt as types_d_exports$5, z as ComponentType, zt as Config$7 } from "./types-BMEn0tSC.mjs";
2
- import { $ as SpriteValue, A as TextStyleInput, B as types_d_exports$6, C as Config$12, D as TextApi, E as State$11, F as Config$10, G as Display, H as InputApi, I as I18nApi, J as Parent, K as NineSlice, L as Message, M as TextValue, N as types_d_exports$13, O as TextBind, P as Argument, Q as SpriteOptions, R as State$9, S as BindOptions, T as Point, U as State$10, V as Config$11, W as types_d_exports$7, X as ShapeValue, Y as Shape, Z as Sprite, _ as Style, b as defineComponent, d as popup, et as Transform, f as defineTokens, g as ResolvedStyle, h as IsFlags, j as TextStyles, k as TextFormat, l as Box, nt as sprite, p as IntrinsicElementsFor, q as NineSliceValue, s as PopupComponent, tt as TransformValue, u as LocalWrite, w as CountdownValue, x as BindField, y as WhenFlags, z as TypedTr } from "./types-BaUUcIaN.mjs";
3
- import { A as HAPTIC_KINDS, B as sfx, C as MotionKeyframe, D as HapticKind, E as types_d_exports, F as mark, G as use, H as spawned, I as parallel, K as wait, L as play, M as external, N as frames, O as SfxDescriptor, P as haptic, R as sequence, S as FramesValue, T as Target, U as stagger, V as spawn, W as tween, _ as State$15, b as AnimApi, c as AnySceneProjection, d as SceneDefinition, f as SceneSpec, g as Config$15, h as types_d_exports$12, i as MusicOptions, j as defineAnimation, k as Step, 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, v as UiApi, w as State$12, x as Config$13, y as types_d_exports$15, z as set } from "./types-CXyipKhE.mjs";
4
- import { _ as NoiseValue, a as types_d_exports$4, c as EmitterValue, d as ColorMatrixValue, f as DisplacementValue, g as GlowValue, h as FilterValueOf, i as State$16, l as AlphaValue, m as FilterSpec, n as EffectsApi, o as EmitterConfig, p as FilterComponent, s as EmitterDefinition, t as Config$16, u as BlurValue, v as OutlineValue, y as UniformDeclaration } from "./types-ClF8say0.mjs";
5
- import { Log } from "@moku-labs/common/browser";
6
- import { PluginCtx } from "@moku-labs/core";
7
-
8
- //#region src/plugins/text/components.d.ts
9
- /**
10
- * Words on the screen: a string or a message, the style it is drawn in, and the string `text`
11
- * resolved out of it. A game writes `content`, `style`, `bind`, `anchor` and `alpha`; `resolved`
12
- * is engine-owned and `ui` and the tests read it. `alpha` (1 by default) fades the whole block and
13
- * is patched in place, so a tween on it rebuilds nothing.
14
- */
15
- declare const Text: ComponentType<TextValue>;
16
- /**
17
- * Shows a numeric component field of the label's own entity: read every frame, written to
18
- * `Text.resolved` only when the shown string changes. The field must hold a number; the format
19
- * is `"int"` (rounded) unless named. Reads the component's own name, so a renamed component
20
- * cannot drift from its label.
21
- *
22
- * @param component - The component whose field the label shows.
23
- * @param field - A numeric field of that component.
24
- * @param options - How the number is shown.
25
- * @returns The bind a `Text` carries.
26
- * @example
27
- * ```ts
28
- * const Counter = component("Counter", { value: 0 });
29
- *
30
- * bind(Counter, "value"); // { component: "Counter", field: "value", format: "int" }
31
- *
32
- * // The chest timer: the time left, as minutes and seconds.
33
- * Text({ style: "digits", bind: bind(Countdown, "left", { format: "mm:ss" }) });
34
- * // bind is { component: "Countdown", field: "left", format: "mm:ss" }; 95 s left shows "01:35"
35
- * ```
36
- */
37
- declare function bind<Value extends object>(component: ComponentHandle<Value>, field: BindField<Value>, options?: BindOptions): TextBind;
38
- /**
39
- * A moment to count down to. A game writes `until`, a moment of `clock` in epoch milliseconds;
40
- * `text` keeps `left` at the time that is left, computed from one `clock.now()` per frame on the
41
- * render side, and writes it only when the label bound to it changes. At zero both stay at zero.
42
- * Nothing of it reaches the save.
43
- *
44
- * @example
45
- * ```ts
46
- * // The chest of the board opens at a moment of the save; clock.now() is 1_790_000_000_000.
47
- * view: chest => [
48
- * Countdown({ until: chest.opensAt }), // opensAt: 1_790_000_095_000
49
- * Text({ style: "digits", bind: bind(Countdown, "left", { format: "mm:ss" }) })
50
- * ]
51
- * // after the frame that spawns it: Text.resolved is "01:35", Countdown.left is 95000
52
- * ```
53
- */
54
- declare const Countdown: ComponentType<CountdownValue>;
55
- /**
56
- * What `label` takes: the two things every label needs, and the anchor that has a default.
57
- *
58
- * @example
59
- * ```ts
60
- * const options: LabelOptions = { text: "+5", style: "board.float", at: { x: 90, y: 180 } };
61
- * ```
62
- */
63
- type LabelOptions = {
64
- text: string | Message;
65
- style: string;
66
- at: Point;
67
- anchor?: Point;
68
- };
69
- /**
70
- * Bundles the two components a label needs, so a projection `view` reads as one line. The anchor
71
- * is the point of the block that sits on the transform.
72
- *
73
- * @param options - The text, its style, where it sits, and which point of it sits there.
74
- * @returns The `Text` and the `Transform` value, in that order.
75
- * @example
76
- * ```ts
77
- * label({ text: "+5", style: "board.float", at: { x: 90, y: 180 } });
78
- * // [Text({ content: "+5", style: "board.float", bind: undefined,
79
- * // anchor: { x: 0.5, y: 0.5 }, alpha: 1, resolved: "" }),
80
- * // Transform({ x: 90, y: 180, rotation: 0, scale: 1 })]
81
- * ```
82
- */
83
- declare function label(options: LabelOptions): [ComponentValue<TextValue>, ComponentValue<TransformValue>];
84
- /**
85
- * Declares the text styles of a feature. The result goes under the `textStyles` key of the
86
- * feature description, and `text` reads it in `onStart`.
87
- *
88
- * @param map - Style name to what that style looks like.
89
- * @returns The registration a feature carries.
90
- * @throws {Error} When a style names a wrap that is not a width and not `"none"`.
91
- * @example
92
- * ```ts
93
- * defineTextStyles({ "hud.digits": { font: "ui.font-digits", size: 40, fill: 0xffe082 } });
94
- * // { kind: "textStyles", map: { "hud.digits": { font: "ui.font-digits", bold: undefined,
95
- * // italic: undefined, size: 40, fill: 0xffe082, stroke: 0x000000, strokeWidth: 0,
96
- * // letterSpacing: 0, align: "left", wrap: "none", digits: false, shadow: undefined } } }
97
- * ```
98
- */
99
- declare function defineTextStyles(map: Record<string, TextStyleInput>): TextStyles;
100
- //#endregion
101
- //#region src/plugins/world/projection/define.d.ts
102
- /**
103
- * Types a projection: keyed items of the model turned into entities. `Item` is inferred from the
104
- * return of `from` and reaches `key`, `view` and every motion hook; `layer` and `lift` stay
105
- * literal, so `defineScene` can check them against the layers of the scene.
106
- *
107
- * @param spec - Name, layer, optional lift layer, `from`, `key`, `view` and the motion hooks.
108
- * @returns The same spec, typed.
109
- * @example
110
- * ```ts
111
- * const boardItems = projection({
112
- * name: "board.items",
113
- * layer: "items",
114
- * from: (player: { items: { id: string }[] }) => player.items,
115
- * key: item => item.id,
116
- * view: () => []
117
- * });
118
- * boardItems.layer; // "items", the literal type, not string
119
- * ```
120
- */
121
- 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>;
122
- /**
123
- * The projection helper bound to one game's `player` and `session`.
124
- *
125
- * @example
126
- * ```ts
127
- * const bound: ProjectionFor<{ coins: number }, {}> = projection;
128
- * ```
129
- */
130
- 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>;
131
- //#endregion
132
- //#region src/plugins/anim/index.d.ts
133
- /**
134
- * Anim plugin: `app.anim.play(animation, slots)`, `app.anim.finishAll()`,
135
- * `app.anim.setReducedMotion(on)`.
136
- *
137
- * @example
138
- * ```ts
139
- * // Animation is text: a module next to the feature, played by a node or by a test.
140
- * const coinsFly = defineAnimation("hud.coinsFly", {
141
- * slots: { from: type<Target>(), to: type<Target>() },
142
- * build: ({ from, to }, { at }) =>
143
- * sequence(
144
- * tween(from, Transform, { x: at(to).x, y: at(to).y }, { ms: 600, ease: "inCubic" }),
145
- * mark("landed")
146
- * )
147
- * });
148
- *
149
- * const app = createApp({ plugins: [...screen, animPlugin, hudFeature] });
150
- *
151
- * app.anim.play(coinsFly, { from: purse, to: counter }).marks(); // []: the first frame is next
152
- * ```
153
- */
154
- declare const animPlugin: import("@moku-labs/core").PluginInstance<"anim", Config$13, State$12, AnimApi, {
155
- "anim:mark": {
156
- animation: string;
157
- mark: string;
158
- };
159
- "anim:finished": {
160
- animation: string;
161
- };
162
- }> & Record<never, never>;
163
- //#endregion
164
- //#region src/plugins/assets/index.d.ts
165
- /**
166
- * Assets plugin: `app.assets.load(bundle)`, `app.assets.texture(key)`, `app.assets.usage()`.
167
- *
168
- * @example
169
- * ```ts
170
- * // A game names its manifest; the graph decides from there what is loaded and when.
171
- * const app = createApp({
172
- * plugins: [...screen, boardFeature],
173
- * pluginConfigs: { assets: { manifest: "/assets/manifest.json", textureBudgetMb: 192 } }
174
- * });
175
- *
176
- * await app.start();
177
- * app.assets.usage().textureMb; // 0.188, the boot tier
178
- * ```
179
- */
180
- declare const assetsPlugin: import("@moku-labs/core").PluginInstance<"assets", Config$1, State$1, Api, {
181
- "assets:bundle-loaded": {
182
- bundle: string;
183
- tier: Tier;
184
- mb: number;
185
- reason: LoadReason;
186
- };
187
- "assets:bundle-progress": {
188
- bundle: string;
189
- loaded: number;
190
- total: number;
191
- };
192
- "assets:bundle-unloaded": {
193
- bundle: string;
194
- tier: Tier;
195
- mb: number;
196
- reason: "budget" | "request";
197
- keys: readonly string[];
198
- };
199
- }> & Record<never, never>;
200
- //#endregion
201
- //#region src/plugins/audio/index.d.ts
202
- /**
203
- * Audio plugin: `app.audio`, the handlers of the effect kinds `sfx` and `music`, and the three
204
- * buses a game drives from its player state.
205
- *
206
- * @example
207
- * ```ts
208
- * // A game composes it next to the screen set and points it at the player's settings.
209
- * createApp({
210
- * plugins: [...screen, audioPlugin, settingsFeature],
211
- * pluginConfigs: { audio: { volumes: player => player.settings.audio } }
212
- * });
213
- * ```
214
- */
215
- declare const audioPlugin: import("@moku-labs/core").PluginInstance<"audio", Config$14, State$13, AudioApi, {}> & Record<never, never>;
216
- //#endregion
217
- //#region src/plugins/clock/index.d.ts
218
- /**
219
- * Clock plugin: `app.clock.now()`, `app.clock.scheduleAt(moment)`, `app.clock.onElapsed(fn)`.
220
- *
221
- * @example
222
- * ```ts
223
- * // A game plugin that needs trusted time declares the dependency and asks for the API.
224
- * const energyPlugin = createPlugin("energy", {
225
- * depends: [clockPlugin],
226
- * api: ctx => ({ fullAt: (missing: number) => ctx.require(clockPlugin).now() + missing * 60_000 })
227
- * });
228
- * ```
229
- */
230
- declare const clockPlugin: import("@moku-labs/core").PluginInstance<"clock", Config$2, State$2, Api$1, {}> & Record<never, never>;
231
- //#endregion
232
- //#region src/plugins/effects/index.d.ts
233
- /**
234
- * Effects plugin: `app.effects.stats()`; the `Emitter` component and every filter component do
235
- * the rest as data on entities.
236
- *
237
- * @example
238
- * ```ts
239
- * // A game composes it next to the screen set; its features bring the emitters and filters.
240
- * const app = createApp({
241
- * plugins: [...screen, effectsPlugin, boardFeature],
242
- * pluginConfigs: { renderer: { mount: "#game" }, effects: { maxPasses: 16 } }
243
- * });
244
- * app.effects.stats(); // { particles: 0, emitters: 0, filters: 0, renderPasses: 0 }: nothing runs before start
245
- * ```
246
- */
247
- declare const effectsPlugin: import("@moku-labs/core").PluginInstance<"effects", Config$16, State$16, EffectsApi, {}> & Record<never, never>;
248
- //#endregion
249
- //#region src/plugins/flow/index.d.ts
250
- /**
251
- * Flow plugin: `app.flow.run()`, `app.flow.gate.answer(...)`, `app.flow.fx.handle(...)`.
252
- *
253
- * @example
254
- * ```ts
255
- * // The game starts the graph itself: an awaited loop in onStart would never let start() resolve.
256
- * createApp({
257
- * pluginConfigs: { flow: { mainFlow, safeNode: "home" } },
258
- * onStart: ctx => {
259
- * ctx.flow.run().catch(showFatal);
260
- * }
261
- * });
262
- * ```
263
- */
264
- declare const flowPlugin: import("@moku-labs/core").PluginInstance<"flow", Config$3, State$3, Api$2, {
265
- "flow:edge": {
266
- flow: string;
267
- node: string;
268
- outcome: string;
269
- payload: Json;
270
- next: string;
271
- patches: {
272
- doc: Patch[];
273
- session: Patch[];
274
- };
275
- index: number;
276
- now: number;
277
- };
278
- "flow:rest": {
279
- path: string;
280
- checkpoint: boolean;
281
- };
282
- "flow:error": {
283
- path: string;
284
- error: unknown;
285
- rolledBackTo: string;
286
- retry: boolean;
287
- };
288
- }> & Record<never, never>;
289
- //#endregion
290
- //#region src/plugins/i18n/index.d.ts
291
- /**
292
- * I18n plugin: `app.i18n.format(tr("hud.orders", { n: 3 }))`, and `tr` for the game.
293
- *
294
- * @example
295
- * ```ts
296
- * // A feature ships its compiled modules; the settings screen switches between them.
297
- * export const hudFeature = defineFeature("hud", {
298
- * projections: [hud],
299
- * strings: { ru: ruStrings, en: () => import("./generated/strings.en") }
300
- * });
301
- *
302
- * await app.i18n.setLocale("en"); // text re-resolves every message on i18n:locale-changed
303
- * ```
304
- */
305
- declare const i18nPlugin: import("@moku-labs/core").PluginInstance<"i18n", Config$10, State$9, I18nApi, {
306
- "i18n:locale-changed": {
307
- locale: string;
308
- };
309
- }> & Record<never, never>;
310
- //#endregion
311
- //#region src/plugins/input/index.d.ts
312
- /**
313
- * Input plugin: `app.input.tap(target)`, `app.input.drag(from, to)`.
314
- *
315
- * @example
316
- * ```ts
317
- * // A view declares its behaviour; the engine owns the drag and the way home.
318
- * const boardItems = projection({
319
- * name: "board.items",
320
- * layer: "items",
321
- * from: (player: Player) => player.items,
322
- * key: (item: Item) => item.id,
323
- * view: (item: Item) => [
324
- * Draggable({ payload: { from: item.cell } }),
325
- * DropTarget({ intent: "merge", payload: { to: item.cell } })
326
- * ]
327
- * });
328
- * ```
329
- */
330
- declare const inputPlugin: import("@moku-labs/core").PluginInstance<"input", Config$11, State$10, InputApi, {}> & Record<never, never>;
331
- //#endregion
332
- //#region src/plugins/lifecycle/index.d.ts
333
- /**
334
- * Lifecycle plugin: `app.lifecycle.push(reason)`, `app.lifecycle.pop(reason)`.
335
- *
336
- * @example
337
- * ```ts
338
- * // A game plugin that reacts to the pause declares the dependency and hooks the event.
339
- * const musicPlugin = createPlugin("music", {
340
- * depends: [lifecyclePlugin],
341
- * hooks: () => ({ "lifecycle:changed": ({ paused }) => music.setMuted(paused) })
342
- * });
343
- * ```
344
- */
345
- declare const lifecyclePlugin: import("@moku-labs/core").PluginInstance<"lifecycle", Config$4, State$4, Api$3, {
346
- "lifecycle:changed": {
347
- reason: PauseReason;
348
- action: "push" | "pop";
349
- reasons: readonly PauseReason[];
350
- paused: boolean;
351
- resumed: boolean;
352
- };
353
- }> & Record<never, never>;
354
- //#endregion
355
- //#region src/plugins/model/index.d.ts
356
- /**
357
- * Model plugin: `app.model.store`, `app.model.rng`.
358
- *
359
- * @example
360
- * ```ts
361
- * // A game plugin that draws from committed state declares the dependency and reads the snapshot.
362
- * const hudPlugin = createPlugin("hud", {
363
- * depends: [modelPlugin],
364
- * hooks: ctx => ({
365
- * "model:committed": () => drawCoins(ctx.require(modelPlugin).store.snapshot().player)
366
- * })
367
- * });
368
- * ```
369
- */
370
- declare const modelPlugin: import("@moku-labs/core").PluginInstance<"model", Config$5, State$5, {
371
- store: StoreApi;
372
- rng: RngApi;
373
- }, {
374
- "model:committed": {
375
- roots: readonly Root[];
376
- cause: "edge" | "rollback" | "restore" | "load";
377
- };
378
- }> & Record<never, never>;
379
- declare namespace types_d_exports$10 {
380
- export { BackResult, Config, HapticKind, KernelSlice, LifecycleChanged, PlatformApi, PlatformProvider, ProviderMethod, State };
381
- }
382
- /**
383
- * The seam a game fills, usually from `@moku-labs/system` in its own bridge. The engine never
384
- * imports a native package: the provider is built in the application layer. Every `on*` returns
385
- * its remover, which the plugin calls on stop.
386
- *
387
- * @example
388
- * ```ts
389
- * // A headless test drives the plugin with a fake of six functions.
390
- * const ticks: string[] = [];
391
- * const provider: PlatformProvider = {
392
- * onPause: () => () => undefined,
393
- * onResume: () => () => undefined,
394
- * onBack: () => () => undefined,
395
- * haptic: kind => ticks.push(kind),
396
- * keepAwake: () => undefined,
397
- * exit: () => undefined
398
- * };
399
- * createApp({ plugins: [...screen, platformPlugin], pluginConfigs: { platform: { provider } } });
400
- * ```
401
- */
402
- type PlatformProvider = {
403
- /** Calls `fn` when the app goes to the background. Returns the remover. */onPause(fn: () => void): () => void; /** Calls `fn` when the app comes back to the foreground. Returns the remover. */
404
- onResume(fn: () => void): () => void;
405
- /**
406
- * Calls `fn` on every press of the system Back button. `fn` returns whether the engine took the
407
- * press; `false` lets the provider do its default, which on Android leaves the app.
408
- */
409
- onBack(fn: () => boolean): () => void; /** Plays one haptic tick. */
410
- haptic(kind: HapticKind): void; /** Keeps the screen on while `on` is true. */
411
- keepAwake(on: boolean): void; /** Leaves the app. */
412
- exit(): void;
413
- };
414
- /**
415
- * What took one Back press: the Escape button of the top popup, the intent `back` of the resting
416
- * node, the provider leaving the app, or nothing at all because the app has no provider.
417
- *
418
- * @example
419
- * ```ts
420
- * // Home rests and does not list "back": the provider leaves the app.
421
- * const result: BackResult = app.platform.back(); // "exit"
422
- * ```
423
- */
424
- type BackResult = "popup" | "intent" | "exit" | "none";
425
- /**
426
- * What a game sets on `pluginConfigs.platform`: the provider seam its application layer fills
427
- * from the native shell, and whether the screen stays on while the game runs.
428
- *
429
- * @example
430
- * ```ts
431
- * // app.ts of a game in the native shell; `provider` is the game's own bridge to the shell.
432
- * const config: Platform.Config = { provider, keepAwake: true };
433
- * config.keepAwake; // true
434
- * ```
435
- */
436
- type Config = {
437
- /** The provider. `undefined`, the default: the plugin is inert, as on the web without a bridge and in headless tests. */provider: PlatformProvider | undefined; /** Keep the screen on while the game runs. Default `false`. */
438
- keepAwake: boolean;
439
- };
440
- /**
441
- * platform plugin state.
442
- */
443
- type State = {
444
- /** Whether `provider.keepAwake(true)` is in force. */awake: boolean; /** Removers of the provider subscriptions and of the haptic handler, called on stop. */
445
- offs: Array<() => void>; /** Haptic kinds already warned about in a dev build, so each warns once. */
446
- warned: Set<string>;
447
- };
448
- /**
449
- * platform plugin API, `app.platform`. The rest of the plugin runs on its own: the provider's
450
- * pause, resume and Back press, the `haptic` effect and keep-awake need no call.
451
- *
452
- * @example
453
- * ```ts
454
- * // An e2e test plays the Android Back button on Home, which rests without "back".
455
- * app.platform.back(); // "exit": the provider leaves the app
456
- * ```
457
- */
458
- type PlatformApi = {
459
- /**
460
- * Runs the Back chain once, exactly as a press of the system Back button does. The first step
461
- * that takes the press wins: Escape taps the `escape` button of the top ui root (`"popup"`),
462
- * then the intent `back` is answered to the resting node (`"intent"`), and otherwise the
463
- * provider leaves the app (`"exit"`). While the graph moves between nodes the gate is closed and
464
- * holds the answer for one frame, so the press answers `"intent"` and never leaves the app.
465
- * Escape also ends the editing of a ui text field, so a
466
- * press while a field is edited ends the edit and answers `"popup"`. Without a provider nothing
467
- * is pressed and the answer is `"none"`.
468
- *
469
- * @returns What took the press.
470
- * @example
471
- * ```ts
472
- * // An e2e test plays the Android Back button over the settings popup, then on Home.
473
- * app.platform.back(); // "popup": the settings popup was open and closed like Escape
474
- * // ...the runner settles on Home, which does not list "back"...
475
- * app.platform.back(); // "exit": the provider leaves the app
476
- * ```
477
- */
478
- back(): BackResult;
479
- };
480
- /**
481
- * What the kernel context offers the files of the plugin.
482
- *
483
- * `platform` owns no event, so `emit` is the kernel's and never called here.
484
- */
485
- type KernelSlice = PluginCtx<Config, State> & {
486
- readonly global: object;
487
- readonly log: Log.LogApi;
488
- readonly require: Require;
489
- };
490
- /**
491
- * Payload of the `lifecycle:changed` hook: the pause that releases keep-awake.
492
- */
493
- type LifecycleChanged = Events["lifecycle:changed"];
494
- /**
495
- * A method of the provider, named in the log when it throws.
496
- */
497
- type ProviderMethod = keyof PlatformProvider;
498
- //#endregion
499
- //#region src/plugins/platform/index.d.ts
500
- /**
501
- * Platform plugin: `app.platform`, the handler of the effect kind `haptic`, and the provider's
502
- * pause, resume and Back press. Inert without a provider.
503
- *
504
- * @example
505
- * ```ts
506
- * // A game in the native shell composes it last and hands it the bridge it built.
507
- * createApp({
508
- * plugins: [...screen, effectsPlugin, audioPlugin, platformPlugin, ...features],
509
- * pluginConfigs: { platform: { provider: fromSystem(system), keepAwake: true } }
510
- * });
511
- * ```
512
- */
513
- declare const platformPlugin: import("@moku-labs/core").PluginInstance<"platform", Config, State, PlatformApi, {}> & Record<never, never>;
514
- //#endregion
515
- //#region src/plugins/renderer/index.d.ts
516
- /**
517
- * Renderer plugin: `app.renderer.host.ready()`, `app.renderer.viewport.size()`,
518
- * `app.renderer.sync.hitTest(...)`.
519
- *
520
- * @example
521
- * ```ts
522
- * // A game with a screen names the element the canvas goes into. Nothing else is configured.
523
- * const app = createApp({
524
- * plugins: [...screen, boardFeature],
525
- * pluginConfigs: { renderer: { mount: "#game" } }
526
- * });
527
- *
528
- * await app.start();
529
- * app.renderer.host.kind(); // "webgpu" in Chrome, "webgl" on an older device
530
- * ```
531
- */
532
- declare const rendererPlugin: import("@moku-labs/core").PluginInstance<"renderer", Config$6, State$6, Api$4, {
533
- "renderer:device-lost": {
534
- kind: "webgpu" | "webgl";
535
- reason: string;
536
- };
537
- }> & Record<never, never>;
538
- //#endregion
539
- //#region src/plugins/scenes/index.d.ts
540
- /**
541
- * Scenes plugin: `app.scenes.current()`, and `defineScene` for the game.
542
- *
543
- * @example
544
- * ```ts
545
- * // features/board/view/scene.ts, and the node that shows it.
546
- * export const boardScene = defineScene("board", {
547
- * bundle: "board",
548
- * layers: { cells: {}, items: { sort: "y" }, lifted: {} },
549
- * projections: [boardCells, boardItems]
550
- * });
551
- *
552
- * export const awaitIntent = defineNode({ scene: "board", rest: true, outcomes: { merge: type() } });
553
- * ```
554
- */
555
- declare const scenesPlugin: import("@moku-labs/core").PluginInstance<"scenes", Record<string, never>, State$14, ScenesApi, {
556
- "scenes:changed": {
557
- from: string | undefined;
558
- to: string;
559
- music: string | undefined;
560
- };
561
- }> & Record<never, never>;
562
- //#endregion
563
- //#region src/plugins/text/index.d.ts
564
- /**
565
- * Text plugin: `app.text.measure(...)`, the `Text` component and the helpers `label` and
566
- * `defineTextStyles` a game writes.
567
- *
568
- * @example
569
- * ```ts
570
- * // A feature brings its styles; a projection puts a label over an item.
571
- * export const hudStyles = defineTextStyles({
572
- * "hud.digits": { font: "ui.font-digits", size: 40, fill: 0xffe082, digits: true }
573
- * });
574
- *
575
- * const app = createApp({ plugins: [...screen, hudFeature] });
576
- *
577
- * app.text.styles(); // ["body", "digits", "hud.digits"]
578
- * ```
579
- */
580
- declare const textPlugin: import("@moku-labs/core").PluginInstance<"text", Config$12, State$11, TextApi, {}> & Record<never, never>;
581
- //#endregion
582
- //#region src/plugins/time/index.d.ts
583
- /**
584
- * Time plugin: `app.time.onFrame(phase, fn)`, `app.time.step(dt)`.
585
- *
586
- * @example
587
- * ```ts
588
- * // A game plugin with frame work declares the dependency and registers a callback on start.
589
- * const sparklePlugin = createPlugin("sparkle", {
590
- * depends: [timePlugin],
591
- * onStart: ctx => void ctx.require(timePlugin).onFrame("animate", time => advance(time.delta))
592
- * });
593
- * ```
594
- */
595
- declare const timePlugin: import("@moku-labs/core").PluginInstance<"time", Config$7, State$7, Api$5, {}> & Record<never, never>;
596
- //#endregion
597
- //#region src/plugins/ui/index.d.ts
598
- /**
599
- * Ui plugin: `app.ui.tree()`, `app.ui.find(...)`, `app.ui.lint()`, `app.ui.fill(...)`, the
600
- * text field `<input local>`, the components `Box` and
601
- * `LocalWrite`, and the helpers `defineComponent`, `defineStyle`, `defineTokens` and `popup`.
602
- *
603
- * @example
604
- * ```ts
605
- * // A headless test reads the HUD and taps the button the popup opened.
606
- * const app = createApp({ plugins: [...screen, uiPlugin, hudFeature] });
607
- *
608
- * app.ui.tree().type; // "row"
609
- * app.input.tap(app.ui.find("claim") ?? 0);
610
- * ```
611
- */
612
- declare const uiPlugin: import("@moku-labs/core").PluginInstance<"ui", Config$15, State$15, UiApi, {}> & Record<never, never>;
613
- //#endregion
614
- //#region src/plugins/world/index.d.ts
615
- /**
616
- * World plugin: `app.world.ecs.query(...)`, `app.world.projection.mount(...)`.
617
- *
618
- * @example
619
- * ```ts
620
- * // A test drives the screen without a browser: mount, commit, step frames.
621
- * const app = createApp({ plugins: [worldPlugin, boardFeature] });
622
- *
623
- * app.world.projection.setLayers([{ name: "items", sort: "y" }]);
624
- * app.world.projection.mount(["board.items"], { kind: "plugin", name: "test" });
625
- * app.world.projection.entityOf("board.items", "i7"); // 1048576
626
- * ```
627
- */
628
- declare const worldPlugin: import("@moku-labs/core").PluginInstance<"world", Config$8, State$8, Api$6, {
629
- "world:reconciled": {
630
- mode: "play" | "direct";
631
- projections: number;
632
- entered: number;
633
- changed: number;
634
- exited: number;
635
- revived: number;
636
- queued: number;
637
- hintsRouted: number;
638
- hintsDropped: number;
639
- };
640
- }> & Record<never, never>;
641
- //#endregion
642
- //#region src/plugins/flow/feature.d.ts
643
- /**
644
- * Turns a feature description into a plugin that registers it with `flow.features` in `onInit`.
645
- * Throws for a name that is reserved or already a plugin. The plugin carries `logicOnly`: the
646
- * same plugin built from the V1 keys of the description, for headless tests.
647
- *
648
- * @param name - Feature name. Shares the namespace with plugin names.
649
- * @param description - What the feature brings: nodes, flows, slot contributions.
650
- * @returns The feature plugin, with its `logicOnly` twin.
651
- * @throws {Error} When the name is reserved or belongs to an engine plugin.
652
- * @example
653
- * ```ts
654
- * // The reward popup is a feature: the main flow only declares slot("afterOrder").
655
- * export const rewardFeature = defineFeature("reward", {
656
- * flows: [rewardFlow],
657
- * contribute: { afterOrder: { flow: rewardFlow, order: 10 } }
658
- * });
659
- * createApp({ plugins: [rewardFeature] }); // a headless test passes rewardFeature.logicOnly
660
- * ```
661
- */
662
- declare function defineFeature(name: string, description: FeatureDescription): FeaturePlugin;
663
- //#endregion
664
- //#region src/plugins/flow/fx/descriptors.d.ts
665
- /**
666
- * Creates a fire-and-forget cosmetic descriptor for `fx.emit`. It is dispatched only after the
667
- * commit of its transaction and dropped in fast mode.
668
- *
669
- * @param kind - Effect kind a handler is registered for.
670
- * @param payload - Plain JSON for the handler.
671
- * @returns The hint as plain data.
672
- * @example
673
- * ```ts
674
- * // Inside a node body: sparkle on the merged cell, shown once the edge has committed.
675
- * fx.emit(hint("sparkle", { cell: "c3" }));
676
- * // hint("sparkle", { cell: "c3" }) is { kind: "sparkle", payload: { cell: "c3" }, hint: true }
677
- * ```
678
- */
679
- declare function hint(kind: string, payload?: Json): Hint;
680
- /**
681
- * Creates the awaited effect that asks the clock for one `elapsed` at this moment. `undefined`
682
- * means nothing is due and leaves the `moment` key out, so the descriptor stays plain JSON. Its
683
- * handler runs in fast mode too.
684
- *
685
- * @param moment - Epoch milliseconds of the next due timer, or `undefined`.
686
- * @returns The descriptor a node awaits.
687
- * @example
688
- * ```ts
689
- * // Inside a node body, after the rules changed a timer: ask for the next `elapsed`.
690
- * await fx(schedule(1_790_000_060_000)); // payload: { moment: 1790000060000 }
691
- * await fx(schedule(undefined)); // payload: {}, the pending timer is cancelled
692
- * ```
693
- */
694
- declare function schedule(moment: number | undefined): Descriptor;
695
- /**
696
- * Creates the tutorial descriptor: it narrows the gate to one answer until the node exits. Its
697
- * visual part (`target`, highlight, hand, text) is drawn by `ui`, which dims the screen and cuts
698
- * a hole over the target element. The highlight list and the target are copied, so a later change
699
- * of the caller's objects cannot reach the descriptor.
700
- *
701
- * @param options - The allowed answer and the visual hints.
702
- * @returns The descriptor a node awaits.
703
- * @example
704
- * ```ts
705
- * // A tutorial node: the popup lists two intents, the guide lets only "ok" through.
706
- * await fx(guide({ allow: { intent: "ok" }, target: { projection: "hud", key: "play" } }));
707
- * await fx({ kind: "popup", answers: ["ok", "cancel"] });
708
- * // app.flow.gate.answer({ intent: "cancel" }) is false until the node exits
709
- * ```
710
- */
711
- declare function guide(options: GuideOptions): Descriptor;
712
- //#endregion
713
- //#region src/plugins/world/ecs/define.d.ts
714
- /**
715
- * Declares a component type. The defaults give the TypeScript type, the JSON shape and the
716
- * inspector schema; the name is the storage key and the key of `motion.change`.
717
- *
718
- * @param name - Storage name, unique per world.
719
- * @param defaults - Every field with its default value. Plain JSON only.
720
- * @param options - The fields a plugin owns: a projection view neither writes nor corrects them.
721
- * @param options.owned - Names of the owned fields.
722
- * @returns A callable component type.
723
- * @example
724
- * ```ts
725
- * const Item = component("Item", { kind: "", level: 1 });
726
- * Item({ level: 2 }); // { type: Item, value: { kind: "", level: 2 } }
727
- * Item({ level: 2 }).type.componentName; // "Item", the storage key
728
- *
729
- * // A caption whose drawn string is written by the plugin that draws it.
730
- * const Caption = component("Caption", { text: "", shown: "" }, { owned: ["shown"] });
731
- * Caption.owned; // ["shown"]
732
- * ```
733
- */
734
- declare function component<Value extends object>(name: string, defaults: Value, options?: {
735
- owned?: ReadonlyArray<keyof Value & string>;
736
- }): ComponentType<Value>;
737
- /**
738
- * Declares a tag: a component with no data, stored as `true`.
739
- *
740
- * @param name - Storage name, unique per world.
741
- * @returns A callable tag type.
742
- * @example
743
- * ```ts
744
- * const Held = tag("Held");
745
- * Held(); // { type: Held, value: true }
746
- * Held().type.componentName; // "Held"
747
- * ```
748
- */
749
- declare function tag(name: string): TagType;
750
- /**
751
- * Declares a resource: one mutable object per world, created from a deep clone of the defaults
752
- * on first read.
753
- *
754
- * @param name - Storage name, unique per world.
755
- * @param defaults - The value a fresh world starts with.
756
- * @returns The resource type.
757
- * @example
758
- * ```ts
759
- * const Pointer = resource("Pointer", { x: 0, y: 0, down: false });
760
- * Pointer.defaults; // { x: 0, y: 0, down: false }
761
- * ```
762
- */
763
- declare function resource<Value extends object>(name: string, defaults: Value): ResourceType<Value>;
764
- /**
765
- * Marks a query term as written. The only effect is change detection: every entity the query
766
- * yields is marked changed for this component.
767
- *
768
- * @param componentType - The component the system writes.
769
- * @returns The marked term.
770
- * @example
771
- * ```ts
772
- * const Transform = component("Transform", { x: 0, y: 0 });
773
- * mut(Transform).kind; // "mut"
774
- * ```
775
- */
776
- declare function mut<Value extends object>(componentType: ComponentHandle<Value>): Mut<Value>;
777
- /**
778
- * Types a system definition. It returns the same plain object; the work is the type, which reads
779
- * the query tuple and types the first argument of `run`.
780
- *
781
- * @param definition - Name, phase, query and the run function.
782
- * @returns The same definition, typed.
783
- * @example
784
- * ```ts
785
- * const Transform = component("Transform", { x: 0, y: 0 });
786
- * const drift = system({
787
- * name: "drift",
788
- * phase: "animate",
789
- * query: [mut(Transform)],
790
- * run: entities => {
791
- * for (const [, transform] of entities) transform.x += 1;
792
- * }
793
- * });
794
- * drift.phase; // "animate"
795
- * ```
796
- */
797
- declare function system<const Terms extends readonly QueryTerm[]>(definition: SystemDefinition<Terms>): SystemDefinition<Terms>;
798
- /**
799
- * The layer a view is drawn in. Written only by the projection; a `view` that returns it is
800
- * logged and the value ignored.
801
- */
802
- declare const Layer: ComponentType<{
803
- name: string;
804
- }>;
805
- /**
806
- * Explicit draw order inside a layer sorted by `"order"`.
807
- */
808
- declare const Order: ComponentType<{
809
- value: number;
810
- }>;
811
- /**
812
- * The view is in the despawn queue: still drawn, never hit-tested.
813
- */
814
- declare const Exiting: TagType;
815
- /**
816
- * The element description of a screen: a projection whose `view` returns one node gets it wrapped
817
- * as this component, and `ui` reconciles the node into child entities. The node is a foreign
818
- * object, so the world diffs it by identity and `snapshot()` leaves it out.
819
- */
820
- declare const Tree: ComponentType<{
821
- node: DescriptionNode;
822
- }>;
823
- //#endregion
824
- //#region src/plugins/input/components.d.ts
825
- /**
826
- * A gesture that names an intent. `payload` is a plain JSON object of model keys, never an
827
- * entity id: the flow graph reads it as the payload of the answer.
828
- *
829
- * @example
830
- * ```ts
831
- * const value: IntentValue = { intent: "merge", payload: { to: "c3" } };
832
- * ```
833
- */
834
- type IntentValue = {
835
- intent: string;
836
- payload: Json;
837
- };
838
- /**
839
- * A view that can be carried. It names no intent: the drop target does. `carry` lists the
840
- * projection keys of views of the same projection that ride along on top of it, such as the cards
841
- * that lie on a solitaire card.
842
- *
843
- * @example
844
- * ```ts
845
- * const value: CarryValue = { payload: { from: "c7" }, carry: ["c8", "c9"] };
846
- * ```
847
- */
848
- type CarryValue = {
849
- payload: Json;
850
- carry: readonly string[];
851
- };
852
- /**
853
- * Where the one pointer is, in reference units. `justPressed` and `justReleased` are true for
854
- * exactly one frame.
855
- *
856
- * @example
857
- * ```ts
858
- * const value: PointerValue = {
859
- * x: 540, y: 960, down: true, justPressed: false, justReleased: false
860
- * };
861
- * ```
862
- */
863
- type PointerValue = {
864
- x: number;
865
- y: number;
866
- down: boolean;
867
- justPressed: boolean;
868
- justReleased: boolean;
869
- };
870
- /**
871
- * A tap on this view answers `{ intent, payload }`.
872
- */
873
- declare const Tappable: ComponentType<IntentValue>;
874
- /**
875
- * A long press on this view answers `{ intent, payload }`.
876
- */
877
- declare const Pressable: ComponentType<IntentValue>;
878
- /**
879
- * This view can be carried by the finger. It names no intent; the drop target does. The views
880
- * whose keys `carry` lists hang under it from the grab to the release and fly home with it.
881
- */
882
- declare const Draggable: ComponentType<CarryValue>;
883
- /**
884
- * A drop on this view answers THIS intent, with the carried payload merged under it.
885
- */
886
- declare const DropTarget: ComponentType<IntentValue>;
887
- /**
888
- * A swipe on this view answers `{ intent, payload: { ...payload, direction } }`.
889
- */
890
- declare const Swipeable: ComponentType<IntentValue>;
891
- /**
892
- * A finger drawn through views that carry this answers once, on the release:
893
- * `{ intent, payload: { path } }`, the payloads of the cells in the order the finger went through
894
- * them. Going back to the cell before the last takes the last one off. It wins over every other
895
- * gesture component on the same view.
896
- */
897
- declare const Traceable: ComponentType<IntentValue>;
898
- /**
899
- * Takes a press without naming a gesture: the hit test accepts a view that carries only this tag,
900
- * and a tap on it runs the `onTap` listeners and answers nothing. `ui` tags the buttons that
901
- * write local state and name no intent.
902
- */
903
- declare const Touchable: TagType;
904
- /**
905
- * On the carried view, from grab to release.
906
- */
907
- declare const Held: TagType;
908
- /**
909
- * On the topmost drop target under the finger during a drag. At most one, never the held view.
910
- */
911
- declare const Hovered: TagType;
912
- /**
913
- * On every view of the trace in progress, from the moment the finger reaches it until it backs
914
- * off it or the trace ends. A game system draws the line through them.
915
- */
916
- declare const Traced: TagType;
917
- /**
918
- * On the pressed view, from pointer down until a tap, a long press, a grab, a swipe or a cancel.
919
- */
920
- declare const Pressed: TagType;
921
- /**
922
- * On the topmost view a press would take, while a mouse or a pen moves over it with no press. At
923
- * most one view carries it, and a touch never hovers. A touch sample, a pointer cancel, the pointer
924
- * leaving the canvas and a paused world take it away. `ui` reads it as `is.hover`. It is not
925
- * `Hovered`, which marks the drop target under a drag.
926
- */
927
- declare const PointerOver: TagType;
928
- /**
929
- * Where the one pointer is, in reference units. Written once per frame by the frame step.
930
- */
931
- declare const Pointer: ResourceType<PointerValue>;
932
- //#endregion
933
- //#region src/plugins/assets/bundles.d.ts
934
- /**
935
- * Declares the bundles of one feature. The map is copied, so a later change of the caller's
936
- * object cannot reach the scanner or the plugin. `defineGame` returns this helper typed by the
937
- * game's `BundleKey`, so a name the scanner never saw does not compile.
938
- *
939
- * @param map - Bundle name to its tier and, when it is a split bundle, its globs.
940
- * @returns The bundle map as plain data.
941
- * @example
942
- * ```ts
943
- * // features/board/assets.ts of a game: the board is a scene bundle, the chains load on demand.
944
- * export const boardAssets = defineBundles({
945
- * board: { tier: "scene" },
946
- * "board.chains": { tier: "lazy", files: ["chains/*.png"] }
947
- * });
948
- * ```
949
- */
950
- declare function defineBundles<Key extends string>(map: Partial<Record<Key, BundleSpec>>): BundleMap<Key>;
951
- /**
952
- * Creates the awaited effect that loads one or more bundles. The handler of the kind `"load"` is
953
- * registered by this plugin and runs in fast mode too, so a fast walk really loads.
954
- *
955
- * @param bundle - One bundle name, or a list of them in load order.
956
- * @returns The descriptor a loading node awaits.
957
- * @example
958
- * ```ts
959
- * // A loading node of a game: one bundle per turn, so the screen can draw progress.
960
- * await fx(load("board.chains")); // { loaded: ["board.chains"], mb: 1.25 }
961
- * await fx(load(["board", "ui"])); // both, in that order
962
- * ```
963
- */
964
- declare function load(bundle: string | readonly string[]): Descriptor;
965
- //#endregion
966
- //#region src/plugins/scenes/define.d.ts
967
- /**
968
- * Declares a scene: a bundle, named layers in draw order, the projections it mounts and optional
969
- * music. A layer `ui` is appended for the HUD and the popups unless the scene declares one. The
970
- * layer names come from the keys of `layers` and that `ui`, so a projection whose `layer` or
971
- * `lift` is not among them does not compile — and throws here for a caller without types.
972
- *
973
- * @param id - Id of the scene. A node names it with `defineNode({ scene: id })`.
974
- * @param scene - The bundle, the layers, the projections and the optional music key.
975
- * @returns The scene as frozen data, ready for the `scenes` key of a feature.
976
- * @throws {Error} For an integer-like layer name, and for a `layer` or `lift` that is not declared.
977
- * @example
978
- * ```ts
979
- * // features/board/view/scene.ts of a game.
980
- * export const boardScene = defineScene("board", {
981
- * bundle: "board",
982
- * layers: { background: {}, cells: {}, items: { sort: "y" }, lifted: {} },
983
- * projections: [boardCells, boardItems]
984
- * });
985
- *
986
- * boardScene.layers[2]; // { name: "items", sort: "y" }
987
- * boardScene.layers[4]; // { name: "ui", sort: "none" }, appended for the HUD
988
- * ```
989
- */
990
- declare function defineScene<Layers extends LayerMap, const Projections extends readonly AnySceneProjection[]>(id: string, scene: SceneSpec<Layers, Projections, string, string>): SceneDefinition;
991
- //#endregion
992
- //#region src/plugins/anim/components.d.ts
993
- /**
994
- * How many tracks and running timelines name this entity. Written by `anim` while something
995
- * moves and removed at zero; the inspector and `ui.lint` read it, `anim` itself never does.
996
- */
997
- declare const Animation: ComponentType<{
998
- playing: number;
999
- }>;
1000
- /**
1001
- * A frame loop on an entity, for as long as the entity carries it: every `1000 / fps` ms
1002
- * `Sprite.texture` becomes the next key of `keys`, after the last key it wraps to the first. No
1003
- * timeline around it, not counted by `Animation` or `app.anim.active()`. A running `frames` step on
1004
- * the same entity owns the sprite until it ends; the loop goes on from where its clock stands.
1005
- * Paused and fast world modes and reduced motion stop the clock on the frame it shows.
1006
- *
1007
- * @example
1008
- * ```ts
1009
- * // A coin spins on the board for its whole life: a projection view returns both components.
1010
- * const coinSpin = ["items.coin-0", "items.coin-1", "items.coin-2", "items.coin-3"] as const;
1011
- * const coin = [Sprite({ texture: "items.coin-0" }), Frames({ keys: coinSpin, fps: 12 })];
1012
- * Frames({ keys: coinSpin, fps: 12 }).value.loop; // true: the default
1013
- * ```
1014
- */
1015
- declare const Frames: ComponentType<FramesValue>;
1016
- //#endregion
1017
- //#region src/plugins/anim/motion.d.ts
1018
- /**
1019
- * The display components a pure `defineMotion` can name. A hook has no context, so it can only
1020
- * reach the components `anim` itself imports: the four of `renderer` that carry numeric fields.
1021
- *
1022
- * @example
1023
- * ```ts
1024
- * type Fields = MotionComponents["Transform"]; // { x: number; y: number; rotation: number; scale: number }
1025
- * ```
1026
- */
1027
- type MotionComponents = {
1028
- Transform: TransformValue;
1029
- Sprite: SpriteValue;
1030
- NineSlice: NineSliceValue;
1031
- Shape: ShapeValue;
1032
- };
1033
- /**
1034
- * One named pose: the numeric fields it gives each component it names.
1035
- *
1036
- * @example
1037
- * ```ts
1038
- * const hidden: MotionState = { Transform: { scale: 0.8 }, Shape: { alpha: 0 } };
1039
- * ```
1040
- */
1041
- type MotionState = { readonly [Name in keyof MotionComponents]?: Readonly<Partial<NumericFields<MotionComponents[Name]>>> };
1042
- /**
1043
- * What `defineMotion` is given: the named poses, the keyframe tracks, how long the way takes, and
1044
- * which hooks to build. `on.enter` and `on.exit` name a state or a track. For a track,
1045
- * `transition.ms` is the whole walk and each segment eases by its key, not by `transition.ease`.
1046
- *
1047
- * `loop.track` names a keyframe track that plays from the moment the element enters, forever,
1048
- * added over whatever else moves it: one cycle is `loop.ms` (default `transition.ms`), every
1049
- * Transform key is an offset from rest, and the last key repeats the first one. It is not part of
1050
- * the motion `enter` returns.
1051
- *
1052
- * @example
1053
- * ```ts
1054
- * const spec: MotionSpec = {
1055
- * states: { hidden: { Transform: { scale: 0.8 } } },
1056
- * keyframes: { dropIn: [{ at: 0, Transform: { dy: -780, scale: 0.8 } }, { at: 0.42, Transform: { dy: 14 } }] },
1057
- * transition: { ms: 1000 },
1058
- * on: { enter: "dropIn", exit: "hidden", change: ["Transform"] }
1059
- * };
1060
- * // An order card pops in over 250 ms and sways on its pin, one swing every 2400 ms.
1061
- * const orderCard: MotionSpec = {
1062
- * states: { small: { Transform: { scale: 0.8 } } },
1063
- * keyframes: { sway: [{ at: 0, Transform: { rotation: 0 } }, { at: 0.5, Transform: { rotation: 0.03 } }, { at: 1, Transform: { rotation: 0 } }] },
1064
- * transition: { ms: 250 },
1065
- * loop: { track: "sway", ms: 2400 },
1066
- * on: { enter: "small" }
1067
- * };
1068
- * ```
1069
- */
1070
- type MotionSpec = {
1071
- readonly states?: Readonly<Record<string, MotionState>>;
1072
- readonly keyframes?: Readonly<Record<string, readonly MotionKeyframe[]>>;
1073
- readonly transition?: {
1074
- readonly ms?: number;
1075
- readonly ease?: Ease;
1076
- };
1077
- readonly loop?: {
1078
- readonly track: string;
1079
- readonly ms?: number;
1080
- };
1081
- readonly on: {
1082
- readonly enter?: string;
1083
- readonly exit?: string;
1084
- readonly change?: readonly (keyof MotionComponents & string)[];
1085
- };
1086
- };
1087
- /**
1088
- * Builds the projection motion hooks of an element from named poses and keyframe tracks. The
1089
- * transition is resolved and every name is checked here, at definition time, so every track it
1090
- * starts carries a concrete duration and a wrong name fails where it is written. A `loop` builds
1091
- * the `loop` hook: `world` and `ui` play it wherever they play `enter`, so a projection view loops
1092
- * once it entered with motion, never after a direct reconcile, and `ui` swaps it when the motion
1093
- * prop of an element changes. One cycle of the loop is `loop.ms`, or `transition.ms` when it is
1094
- * left out.
1095
- *
1096
- * @param spec - The named poses, the keyframe tracks, the transition, the loop and the hooks to
1097
- * build.
1098
- * @returns The `enter`, `loop`, `exit` and `change` hooks. `settle` is left out: the default of
1099
- * `world` applies.
1100
- * @throws {Error} When a track is invalid, a name is both a state and a track, `on` names
1101
- * neither, `loop.track` names no track, `loop.ms` is not a finite number above 0, or the loop
1102
- * ends somewhere else than it starts.
1103
- * @example
1104
- * ```ts
1105
- * const buttonMotion = defineMotion({
1106
- * states: { hidden: { Transform: { scale: 0.8 }, Shape: { alpha: 0 } } },
1107
- * transition: { ms: 150, ease: "out" },
1108
- * on: { enter: "hidden", exit: "hidden", change: ["Transform"] }
1109
- * });
1110
- * buttonMotion.settle; // undefined
1111
- * ```
1112
- */
1113
- declare function defineMotion(spec: MotionSpec): ProjectionMotion<unknown>;
1114
- //#endregion
1115
- //#region src/plugins/i18n/tr.d.ts
1116
- /**
1117
- * Builds a message. The result is frozen and the parameters are copied, so the caller's object
1118
- * stays its own and nothing downstream can rewrite a label in place.
1119
- *
1120
- * @param key - The message key, one of the keys `compileStrings` generated.
1121
- * @param params - The parameters the message declares. An element parameter is kept as it is.
1122
- * @returns The message, frozen.
1123
- * @example
1124
- * ```ts
1125
- * tr("hud.orders", { n: 3 }); // { key: "hud.orders", params: { n: 3 } }
1126
- * tr("orders.complete"); // { key: "orders.complete" }
1127
- * ```
1128
- */
1129
- declare function tr(key: string, params?: Record<string, Argument>): Message;
1130
- //#endregion
1131
- //#region src/plugins/ui/styles/define.d.ts
1132
- /**
1133
- * Declares one style. The work is the type: a field outside the vocabulary, or a value outside
1134
- * its union, is an error where the style is written, not where it is used.
1135
- *
1136
- * @param style - The style, with its `is` and `when` variants.
1137
- * @returns The same object, frozen.
1138
- * @example
1139
- * ```ts
1140
- * defineStyle({ direction: "row", gap: 12 }).gap; // 12
1141
- * ```
1142
- */
1143
- declare function defineStyle<const Given extends Style>(style: Given): Readonly<Given>;
1144
- //#endregion
1145
- //#region src/plugins/ui/styles/resolve.d.ts
1146
- /**
1147
- * The flags one element is resolved against: the viewport flags of the frame plus its own state.
1148
- *
1149
- * @example
1150
- * ```ts
1151
- * const flags: StyleFlags = {
1152
- * portrait: true, landscape: false, tall: false, wide: false,
1153
- * pressed: false, hover: false, focus: false, disabled: false, active: true, selected: false,
1154
- * covered: false
1155
- * };
1156
- * ```
1157
- */
1158
- type StyleFlags = WhenFlags & IsFlags;
1159
- /**
1160
- * Resolves one style against the flags of the frame and the viewport.
1161
- *
1162
- * @param style - The style a game wrote, or nothing.
1163
- * @param flags - The four viewport flags and the seven state flags. While `disabled` is true the
1164
- * `hover` and `pressed` variants are skipped.
1165
- * @param viewport - What `renderer.viewport.size()` answered, for the safe-area tokens.
1166
- * @returns The frozen style the layout and the visual are written from.
1167
- * @example
1168
- * ```ts
1169
- * resolve(
1170
- * { gap: 8, is: { pressed: { gap: 4 } } },
1171
- * { portrait: true, landscape: false, tall: false, wide: false,
1172
- * pressed: true, hover: false, focus: false, disabled: false, active: false, selected: false,
1173
- * covered: false },
1174
- * { width: 1080, height: 1920, scale: 1, orientation: "portrait",
1175
- * safeArea: { top: 0, right: 0, bottom: 0, left: 0 } }
1176
- * ).gap; // 4
1177
- * ```
1178
- */
1179
- declare function resolve(style: Style | undefined, flags: StyleFlags, viewport: ViewportSize): ResolvedStyle;
1180
- //#endregion
1181
- //#region src/plugins/audio/descriptors.d.ts
1182
- /**
1183
- * Creates the awaited effect that switches the music track. The same key as the one playing does
1184
- * nothing, and `null` fades the current track out. An absent `fadeMs` leaves the key out of the
1185
- * payload, so the descriptor stays plain JSON and the plugin's `musicFadeMs` decides at play time.
1186
- *
1187
- * @param key - Asset key of an `.mp3`, or `null` to stop the music.
1188
- * @param options - `fadeMs` overrides the configured cross-fade for this switch.
1189
- * @returns The descriptor a node awaits, frozen.
1190
- * @example
1191
- * ```ts
1192
- * // A node of a game: the menu goes quiet before the ending cinematic starts.
1193
- * await fx(music(null, { fadeMs: 1500 }));
1194
- * // music("board.theme") is { kind: "music", payload: { key: "board.theme" }, cosmetic: true }
1195
- * ```
1196
- */
1197
- declare function music(key: string | null, options?: MusicOptions): Descriptor;
1198
- //#endregion
1199
- //#region src/plugins/effects/filters/builtins.d.ts
1200
- /**
1201
- * A soft halo of `color` around the opaque pixels of a view and its subtree, `distance` pixels
1202
- * wide, that follows the shape: rounded corners stay rounded. Its alpha is
1203
- * `strength × alpha ×` the share of the disc of radius `distance` around the pixel the view
1204
- * covers, so `strength: 2` is full next to a straight edge and fades to nothing at `distance`.
1205
- * It takes 64 to 256 probes, by radius in physical pixels: about 3.5 physical pixels apart up to
1206
- * a radius of 32 physical pixels. The view is padded by its live `distance`. One render pass per
1207
- * apply.
1208
- *
1209
- * @example
1210
- * ```ts
1211
- * // A merged item glows, and a motion hook tweens the glow away.
1212
- * Glow({ strength: 4 }).value; // { strength: 4, distance: 10, color: 0xffffff, alpha: 1, enabled: true, order: 0 }
1213
- * view.tween(Glow, { strength: 0 }, { ms: 200 });
1214
- * ```
1215
- */
1216
- declare const Glow: FilterComponent<GlowValue>;
1217
- /**
1218
- * A ring of `thickness` pixels in `color` around the opaque pixels of a view and its subtree; the
1219
- * view is padded by its live `thickness`. One render pass per apply.
1220
- *
1221
- * @example
1222
- * ```ts
1223
- * // The selected card is outlined in honey.
1224
- * Outline({ thickness: 4, color: 0xffc233 }).value; // { thickness: 4, color: 0xffc233, alpha: 1, enabled: true, order: 0 }
1225
- * ```
1226
- */
1227
- declare const Outline: FilterComponent<OutlineValue>;
1228
- /**
1229
- * Pixi's blur over a view and its subtree. `quality: 0` means `config.blur.quality`;
1230
- * `resolution: 0` means `config.blur.phoneResolution` on a phone, otherwise 1. `repeatEdgePixels`
1231
- * keeps the padding at 0. Costs `2 × quality` render passes per apply.
1232
- *
1233
- * @example
1234
- * ```ts
1235
- * // The board behind a popup: the filter sits on the ui slot that hosts the board.
1236
- * Blur({ strength: 6 }).value; // { strength: 6, quality: 0, resolution: 0, repeatEdgePixels: true, enabled: true, order: 0 }
1237
- * ```
1238
- */
1239
- declare const Blur: ComponentType<BlurValue>;
1240
- /**
1241
- * Pixi's colour matrix: brightness, saturation, contrast, hue in degrees and grayscale, composed
1242
- * in that order from the identity on every change. Every default is the identity.
1243
- *
1244
- * @example
1245
- * ```ts
1246
- * // A locked card goes gray.
1247
- * ColorMatrix({ grayscale: 1 }).value.grayscale; // 1
1248
- * ```
1249
- */
1250
- declare const ColorMatrix: ComponentType<ColorMatrixValue>;
1251
- /**
1252
- * Pixi's noise. The seed is always given, never Pixi's random default, so two runs draw the same
1253
- * grain.
1254
- *
1255
- * @example
1256
- * ```ts
1257
- * Noise({ amount: 0.2, seed: 7 }).value; // { amount: 0.2, seed: 7, enabled: true, order: 0 }
1258
- * ```
1259
- */
1260
- declare const Noise: ComponentType<NoiseValue>;
1261
- /**
1262
- * Pixi's displacement over the texture of the asset key `map`. Nothing is drawn while the map is
1263
- * not loaded; a missing key warns once.
1264
- *
1265
- * @example
1266
- * ```ts
1267
- * // Heat haze over the furnace.
1268
- * Displacement({ map: "fx.ripple", scaleX: 8, scaleY: 8 }).value.map; // "fx.ripple"
1269
- * ```
1270
- */
1271
- declare const Displacement: ComponentType<DisplacementValue>;
1272
- /**
1273
- * Pixi's alpha over a view and its subtree as one layer, so overlapping children do not show
1274
- * through each other.
1275
- *
1276
- * @example
1277
- * ```ts
1278
- * Alpha({ alpha: 0.5 }).value; // { alpha: 0.5, enabled: true, order: 0 }
1279
- * ```
1280
- */
1281
- declare const Alpha: ComponentType<AlphaValue>;
1282
- //#endregion
1283
- //#region src/plugins/effects/filters/define.d.ts
1284
- /**
1285
- * Turns a WGSL fragment body and its GLSL ES 3.0 twin into a filter component type; Pixi draws
1286
- * the one of the running backend. To the WGSL the engine prepends the vertex stage, the input
1287
- * bindings and a `FilterUniforms` struct in declaration order, bound as `fu`. To the GLSL it
1288
- * prepends `#version 300 es`, `vTextureCoord`, `finalColor`, `uTexture`, the global filter
1289
- * uniforms as `vec4` and one `uniform` per declared uniform under its bare name. Every number
1290
- * uniform is a number field, so the existing `tween` drives it; a colour is one hex field sent as
1291
- * a `vec3`; a tuple is an array field and not tweenable. Every filter component also carries
1292
- * `enabled: true` and `order: 0`. Register it through the `filters` key of a feature.
1293
- *
1294
- * @param id - The filter id, also the component name; unique, and not one of the built-ins.
1295
- * @param spec - Both bodies, the uniforms, the passes one apply costs and the padding.
1296
- * @returns The component type, with the frozen `filter` definition attached.
1297
- * @throws {Error} When the id is empty, the WGSL has no `mainFragment`, the GLSL no `void main(`,
1298
- * a uniform is reserved, badly named or of no known form, or the passes or the padding break
1299
- * their rules.
1300
- * @example
1301
- * ```ts
1302
- * // features/board/effects.ts: a gold tint a motion hook tweens on a merge, on WebGPU and WebGL.
1303
- * const Tint = defineFilter("fx.tint", { wgsl: tintWgsl, glsl: tintGlsl, uniforms: { amount: 0, color: { color: 0xffd700 } } });
1304
- * Tint({ amount: 1 }).value; // { amount: 1, color: 0xffd700, enabled: true, order: 0 }
1305
- * Tint.filter.glsl.includes("uniform vec3 color;"); // true
1306
- * ```
1307
- */
1308
- declare function defineFilter<Uniforms extends Record<string, UniformDeclaration> = Record<never, never>>(id: string, spec: FilterSpec<Uniforms>): FilterComponent<FilterValueOf<Uniforms>>;
1309
- //#endregion
1310
- //#region src/plugins/effects/particles/component.d.ts
1311
- /**
1312
- * A particle effect on an entity. A `burst` effect emits when the component appears or its
1313
- * `effect` changes; a `rate` effect emits while `active` is true and the entity lives. An effect in
1314
- * `"world"` space outlives the entity, one in `"local"` space moves and dies with it. `""` draws
1315
- * nothing. Plain JSON: it shows in `snapshot()`.
1316
- *
1317
- * @example
1318
- * ```ts
1319
- * // A merged item bursts stars from its enter hook; the generator steams for its whole life.
1320
- * view.set(Emitter, { effect: "fx.starsBurst" });
1321
- * Emitter({ effect: "fx.steam" }).value; // { effect: "fx.steam", active: true }
1322
- * ```
1323
- */
1324
- declare const Emitter: ComponentType<EmitterValue>;
1325
- //#endregion
1326
- //#region src/plugins/effects/particles/define.d.ts
1327
- /**
1328
- * Describes a particle effect. Every field is optional except `textures` and exactly one of
1329
- * `burst` and `rate`; the definition is frozen, registered through the `emitters` key of a feature
1330
- * and started by an `Emitter` component naming its id.
1331
- *
1332
- * @param id - The effect id, unique across the features of the game.
1333
- * @param config - The effect as data.
1334
- * @returns The frozen definition `{ id, config }`, the config with every default filled in.
1335
- * @throws {Error} When the id is empty or a field breaks its rule.
1336
- * @example
1337
- * ```ts
1338
- * // features/board/effects.ts: the steam over the generator.
1339
- * const steam = defineEmitter("fx.steam", { textures: ["fx.puff"], rate: 12, space: "local" });
1340
- * steam.config.rate; // 12
1341
- * steam.config.lifeMs; // [600, 1000], the default
1342
- * ```
1343
- */
1344
- declare function defineEmitter(id: string, config: EmitterConfig): EmitterDefinition;
1345
- //#endregion
1346
- //#region src/index.d.ts
1347
- /**
1348
- * Creates a game application.
1349
- *
1350
- * @example
1351
- * ```ts
1352
- * // The entry point of a game. The graph is started by the game, never by the plugin.
1353
- * const app = createApp({
1354
- * pluginConfigs: { flow: { mainFlow, safeNode: "home" } },
1355
- * onStart: ctx => void ctx.flow.run().catch(error => ctx.log.error("game: failed", { error }))
1356
- * });
1357
- * ```
1358
- */
1359
- declare const createApp: <const ExtraPlugins extends readonly import("@moku-labs/core").AnyPluginInstance[] = readonly []>(options?: import("@moku-labs/core").CreateAppOptions<Config$9, Events$1, (import("@moku-labs/core").PluginInstance<"time", Config$7, State$7, Api$5, {}> & Record<never, never>) | (import("@moku-labs/core").PluginInstance<"lifecycle", Config$4, State$4, Api$3, {
1360
- "lifecycle:changed": {
1361
- reason: PauseReason;
1362
- action: "push" | "pop";
1363
- reasons: readonly PauseReason[];
1364
- paused: boolean;
1365
- resumed: boolean;
1366
- };
1367
- }> & Record<never, never>) | (import("@moku-labs/core").PluginInstance<"model", Config$5, State$5, {
1368
- store: StoreApi;
1369
- rng: RngApi;
1370
- }, {
1371
- "model:committed": {
1372
- roots: readonly Root[];
1373
- cause: "edge" | "rollback" | "restore" | "load";
1374
- };
1375
- }> & Record<never, never>) | (import("@moku-labs/core").PluginInstance<"clock", Config$2, State$2, Api$1, {}> & Record<never, never>) | (import("@moku-labs/core").PluginInstance<"flow", Config$3, State$3, Api$2, {
1376
- "flow:edge": {
1377
- flow: string;
1378
- node: string;
1379
- outcome: string;
1380
- payload: Json;
1381
- next: string;
1382
- patches: {
1383
- doc: Patch[];
1384
- session: Patch[];
1385
- };
1386
- index: number;
1387
- now: number;
1388
- };
1389
- "flow:rest": {
1390
- path: string;
1391
- checkpoint: boolean;
1392
- };
1393
- "flow:error": {
1394
- path: string;
1395
- error: unknown;
1396
- rolledBackTo: string;
1397
- retry: boolean;
1398
- };
1399
- }> & Record<never, never>) | ExtraPlugins[number], [...ExtraPlugins], 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>]>, 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>> | undefined) => import("@moku-labs/core").App<Config$9, Events$1, (import("@moku-labs/core").PluginInstance<"time", Config$7, State$7, Api$5, {}> & Record<never, never>) | (import("@moku-labs/core").PluginInstance<"lifecycle", Config$4, State$4, Api$3, {
1400
- "lifecycle:changed": {
1401
- reason: PauseReason;
1402
- action: "push" | "pop";
1403
- reasons: readonly PauseReason[];
1404
- paused: boolean;
1405
- resumed: boolean;
1406
- };
1407
- }> & Record<never, never>) | (import("@moku-labs/core").PluginInstance<"model", Config$5, State$5, {
1408
- store: StoreApi;
1409
- rng: RngApi;
1410
- }, {
1411
- "model:committed": {
1412
- roots: readonly Root[];
1413
- cause: "edge" | "rollback" | "restore" | "load";
1414
- };
1415
- }> & Record<never, never>) | (import("@moku-labs/core").PluginInstance<"clock", Config$2, State$2, Api$1, {}> & Record<never, never>) | (import("@moku-labs/core").PluginInstance<"flow", Config$3, State$3, Api$2, {
1416
- "flow:edge": {
1417
- flow: string;
1418
- node: string;
1419
- outcome: string;
1420
- payload: Json;
1421
- next: string;
1422
- patches: {
1423
- doc: Patch[];
1424
- session: Patch[];
1425
- };
1426
- index: number;
1427
- now: number;
1428
- };
1429
- "flow:rest": {
1430
- path: string;
1431
- checkpoint: boolean;
1432
- };
1433
- "flow:error": {
1434
- path: string;
1435
- error: unknown;
1436
- rolledBackTo: string;
1437
- retry: boolean;
1438
- };
1439
- }> & Record<never, never>) | ExtraPlugins[number], 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>]>>;
1440
- /**
1441
- * Creates a game plugin.
1442
- *
1443
- * @example
1444
- * ```ts
1445
- * // A game plugin that writes every edge of the graph to the log.
1446
- * export const edgeLog = createPlugin("edgeLog", {
1447
- * depends: [flowPlugin],
1448
- * hooks: ctx => ({ "flow:edge": ({ node, outcome }) => ctx.log.info("edge", { node, outcome }) })
1449
- * });
1450
- * ```
1451
- */
1452
- declare const createPlugin: import("@moku-labs/core").BoundCreatePluginFunction<Config$9, Events$1, 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>]>>;
1453
- /**
1454
- * Binds the authoring helpers to the types of one game: "createApp for a game". Each plugin binds
1455
- * its own helpers (`flowFor`, `projectionFor`, `componentsFor`, `bundlesFor`, `scenesFor`); this
1456
- * only spreads them, so the kit's type is inferred and never written by hand. At run time these
1457
- * are the same functions and component objects the plugins export.
1458
- *
1459
- * @returns The helpers typed with the game's `player`, `session`, `assets`, `bundles`, `strings`
1460
- * and `emitters`.
1461
- * @example
1462
- * ```ts
1463
- * // kit.ts of a game: bound once, imported by every node, flow and view file.
1464
- * export const { defineNode, defineFlow, defineFeature, projection, sprite, Sprite, defineBundles, load, defineScene } =
1465
- * defineGame<{ player: Player; session: Session; assets: AssetKey; bundles: BundleKey; strings: StringTable }>();
1466
- * ```
1467
- */
1468
- declare function defineGame<Types extends GameTypes>(): {
1469
- defineEmitter: (id: EmitterIdOf<Types>, config: Omit<EmitterConfig, "textures"> & {
1470
- readonly textures: readonly Types["assets"][];
1471
- }) => EmitterDefinition;
1472
- Emitter: Narrowed<EmitterValue, {
1473
- effect?: EmitterIdOf<Types>;
1474
- active?: boolean;
1475
- }>;
1476
- Displacement: Narrowed<DisplacementValue, Partial<Omit<DisplacementValue, "map">> & {
1477
- map?: Types["assets"];
1478
- }>;
1479
- music: MusicDescriptor<Types["assets"]>;
1480
- defineComponent: typeof defineComponent;
1481
- defineStyle: <const Given extends Style<Types["assets"]>>(style: Given) => Readonly<Given>;
1482
- defineTokens: typeof defineTokens;
1483
- popup: <Properties extends object, Local extends object>(component: PopupComponent<Properties, Local>, props: Properties, options?: {
1484
- over?: string;
1485
- }) => Descriptor;
1486
- intrinsics: IntrinsicElementsFor<Types["assets"], TextStylesOf<Types>, Extract<keyof Types["strings"], string>>;
1487
- label: (options: Omit<LabelOptions, "style"> & {
1488
- style: TextStylesOf<Types>;
1489
- }) => ReturnType<typeof label>;
1490
- defineTextStyles: (map: Record<string, Omit<TextStyleInput, "bold" | "font" | "italic"> & {
1491
- font: Types["assets"];
1492
- } & {
1493
- bold?: Types["assets"];
1494
- italic?: Types["assets"];
1495
- }>) => TextStyles;
1496
- tr: TypedTr<Types["strings"]>;
1497
- defineAnimation: typeof defineAnimation;
1498
- frames: (target: Target, options: {
1499
- keys: readonly Types["assets"][];
1500
- fps: number;
1501
- loop?: boolean;
1502
- }) => Step;
1503
- sfx: (key: Types["assets"], options?: {
1504
- bus?: string;
1505
- }) => SfxDescriptor;
1506
- play: typeof play;
1507
- Frames: Narrowed<FramesValue, Partial<Omit<FramesValue, "keys">> & {
1508
- keys?: readonly Types["assets"][];
1509
- }>;
1510
- defineScene: DefineScene<Types["assets"], BundlesOf<Types>>;
1511
- defineBundles: DefineBundles<BundlesOf<Types>>;
1512
- load: LoadBundles<BundlesOf<Types>>;
1513
- sprite: (options: Omit<SpriteOptions, "texture"> & {
1514
- texture: Types["assets"];
1515
- }) => ReturnType<typeof sprite>;
1516
- Sprite: Narrowed<SpriteValue, Partial<Omit<SpriteValue, "texture">> & {
1517
- texture?: Types["assets"];
1518
- }>;
1519
- NineSlice: Narrowed<NineSliceValue, Partial<Omit<NineSliceValue, "texture">> & {
1520
- texture?: Types["assets"];
1521
- }>;
1522
- projection: ProjectionFor<Types["player"], Types["session"]>;
1523
- defineNode: DefineNode<{
1524
- player: Types["player"];
1525
- session: Types["session"];
1526
- scenes: SceneIdOf<Types>;
1527
- }>;
1528
- defineFlow: typeof defineFlow;
1529
- defineFeature: (name: string, description: FeatureDescription) => FeaturePlugin;
1530
- };
1531
- /**
1532
- * The screen plugins, in dependency order. A game with a screen spreads them into `plugins`;
1533
- * a headless test leaves them out. V2: `world`, `renderer`, `input`, `assets`, `scenes`. V3 appends `anim`, `i18n`, `text`, `ui`; `audio`, `effects` and `platform` stay opt-in: `[...screen, effectsPlugin, audioPlugin, platformPlugin]`.
1534
- *
1535
- * @example
1536
- * ```ts
1537
- * createApp({ plugins: [...screen, boardFeature], pluginConfigs: { renderer: { mount: "#game" } } });
1538
- * ```
1539
- */
1540
- declare const screen: readonly [import("@moku-labs/core").PluginInstance<"world", Config$8, State$8, Api$6, {
1541
- "world:reconciled": {
1542
- mode: "play" | "direct";
1543
- projections: number;
1544
- entered: number;
1545
- changed: number;
1546
- exited: number;
1547
- revived: number;
1548
- queued: number;
1549
- hintsRouted: number;
1550
- hintsDropped: number;
1551
- };
1552
- }> & Record<never, never>, import("@moku-labs/core").PluginInstance<"renderer", Config$6, State$6, Api$4, {
1553
- "renderer:device-lost": {
1554
- kind: "webgpu" | "webgl";
1555
- reason: string;
1556
- };
1557
- }> & Record<never, never>, import("@moku-labs/core").PluginInstance<"input", Config$11, State$10, InputApi, {}> & Record<never, never>, import("@moku-labs/core").PluginInstance<"assets", Config$1, State$1, Api, {
1558
- "assets:bundle-loaded": {
1559
- bundle: string;
1560
- tier: Tier;
1561
- mb: number;
1562
- reason: LoadReason;
1563
- };
1564
- "assets:bundle-progress": {
1565
- bundle: string;
1566
- loaded: number;
1567
- total: number;
1568
- };
1569
- "assets:bundle-unloaded": {
1570
- bundle: string;
1571
- tier: Tier;
1572
- mb: number;
1573
- reason: "budget" | "request";
1574
- keys: readonly string[];
1575
- };
1576
- }> & Record<never, never>, import("@moku-labs/core").PluginInstance<"scenes", Record<string, never>, State$14, ScenesApi, {
1577
- "scenes:changed": {
1578
- from: string | undefined;
1579
- to: string;
1580
- music: string | undefined;
1581
- };
1582
- }> & Record<never, never>, import("@moku-labs/core").PluginInstance<"anim", Config$13, State$12, AnimApi, {
1583
- "anim:mark": {
1584
- animation: string;
1585
- mark: string;
1586
- };
1587
- "anim:finished": {
1588
- animation: string;
1589
- };
1590
- }> & Record<never, never>, import("@moku-labs/core").PluginInstance<"i18n", Config$10, State$9, I18nApi, {
1591
- "i18n:locale-changed": {
1592
- locale: string;
1593
- };
1594
- }> & Record<never, never>, import("@moku-labs/core").PluginInstance<"text", Config$12, State$11, TextApi, {}> & Record<never, never>, import("@moku-labs/core").PluginInstance<"ui", Config$15, State$15, UiApi, {}> & Record<never, never>];
1595
- //#endregion
1596
- export { Alpha, types_d_exports as Anim, Animation, types_d_exports$1 as Assets, types_d_exports$2 as Audio, type BackResult, type BindOptions, Blur, Box, types_d_exports$3 as Clock, ColorMatrix, Countdown, type CountdownValue, type DescriptionNode, Displacement, Display, Draggable, DropTarget, types_d_exports$4 as Effects, Emitter, Exiting, types_d_exports$5 as Flow, Frames, Glow, HAPTIC_KINDS, type HapticKind, Held, Hovered, types_d_exports$6 as I18n, types_d_exports$7 as Input, Layer, types_d_exports$8 as Lifecycle, LocalWrite, types_d_exports$9 as Model, NineSlice, Noise, Order, Outline, Parent, types_d_exports$10 as Platform, type PlatformProvider, Pointer, PointerOver, Pressable, Pressed, types_d_exports$11 as Renderer, SaveUnreadableError, types_d_exports$12 as Scenes, Shape, Sprite, Swipeable, Tappable, Text, type TextFormat, types_d_exports$13 as TextTypes, types_d_exports$14 as Time, Touchable, Traceable, Traced, Transform, Tree, types_d_exports$15 as Ui, types_d_exports$16 as World, animPlugin, assetsPlugin, audioPlugin, bind, clockPlugin, component, createApp, createPlugin, defineAnimation, defineBundles, defineComponent, defineEmitter, defineFeature, defineFilter, defineGame, defineMotion, defineScene, defineStyle, defineTextStyles, defineTokens, effectsPlugin, exit, external, flowPlugin, frames, guide, haptic, hint, i18nPlugin, inputPlugin, label, lifecyclePlugin, load, mark, modelPlugin, music, mut, parallel, platformPlugin, 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 };
1
+ import { Ct as to, N as types_d_exports$16, Q as DescriptionNode, S as types_d_exports$11, St as slot, Wt as types_d_exports$14, Zt as types_d_exports$9, fn as types_d_exports$8, nn as SaveUnreadableError, p as types_d_exports$1, vn as types_d_exports$3, wt as type, xt as exit, yt as types_d_exports$5 } from "./types-B0v5VVa3.mjs";
2
+ import { B as types_d_exports$6, G as Display, J as Parent, K as NineSlice, N as types_d_exports$13, S as BindOptions, W as types_d_exports$7, Y as Shape, Z as Sprite, b as defineComponent, d as popup, et as Transform, f as defineTokens, k as TextFormat, l as Box, nt as sprite, u as LocalWrite, w as CountdownValue } from "./types-xXfyk56Q.mjs";
3
+ import { B as set, D as types_d_exports, F as haptic, G as tween, H as spawn, I as mark, K as use, L as parallel, M as defineAnimation, N as external, O as HapticKind, P as frames, R as play, U as spawned, V as sfx, W as stagger, h as types_d_exports$12, j as HAPTIC_KINDS, q as wait, s as types_d_exports$2, y as types_d_exports$15, z as sequence } from "./types-VZVWwqCg.mjs";
4
+ import { a as types_d_exports$4 } from "./types-CQueODzo.mjs";
5
+ import { $ as uiPlugin, A as Pointer, B as Layer, C as defineScene, Ct as label, D as DropTarget, E as Draggable, F as Tappable, G as resource, H as Tree, I as Touchable, J as guide, K as system, L as Traceable, M as Pressable, N as Pressed, O as Held, P as Swipeable, Q as worldPlugin, R as Traced, S as Frames, St as defineTextStyles, T as load, U as component, V as Order, W as mut, X as schedule, Y as hint, Z as defineFeature, _ as defineStyle, _t as animPlugin, a as defineEmitter, at as BackResult, b as AnimPlayer, bt as Text, c as Alpha, ct as modelPlugin, d as Displacement, dt as i18nPlugin, et as timePlugin, f as Glow, ft as flowPlugin, g as resolve, gt as assetsPlugin, h as music, ht as audioPlugin, i as screen, it as platformPlugin, j as PointerOver, k as Hovered, l as Blur, lt as lifecyclePlugin, m as Outline, mt as clockPlugin, n as createPlugin, nt as scenesPlugin, o as Emitter, ot as PlatformProvider, p as Noise, pt as effectsPlugin, q as tag, r as defineGame, rt as rendererPlugin, s as defineFilter, st as types_d_exports$10, t as createApp, tt as textPlugin, u as ColorMatrix, ut as inputPlugin, v as tr, vt as projection, w as defineBundles, x as Animation, xt as bind, y as defineMotion, yt as Countdown, z as Exiting } from "./index-BO9kZzY3.mjs";
6
+ export { Alpha, types_d_exports as Anim, AnimPlayer, Animation, types_d_exports$1 as Assets, types_d_exports$2 as Audio, type BackResult, type BindOptions, Blur, Box, types_d_exports$3 as Clock, ColorMatrix, Countdown, type CountdownValue, type DescriptionNode, Displacement, Display, Draggable, DropTarget, types_d_exports$4 as Effects, Emitter, Exiting, types_d_exports$5 as Flow, Frames, Glow, HAPTIC_KINDS, type HapticKind, Held, Hovered, types_d_exports$6 as I18n, types_d_exports$7 as Input, Layer, types_d_exports$8 as Lifecycle, LocalWrite, types_d_exports$9 as Model, NineSlice, Noise, Order, Outline, Parent, types_d_exports$10 as Platform, type PlatformProvider, Pointer, PointerOver, Pressable, Pressed, types_d_exports$11 as Renderer, SaveUnreadableError, types_d_exports$12 as Scenes, Shape, Sprite, Swipeable, Tappable, Text, type TextFormat, types_d_exports$13 as TextTypes, types_d_exports$14 as Time, Touchable, Traceable, Traced, Transform, Tree, types_d_exports$15 as Ui, types_d_exports$16 as World, animPlugin, assetsPlugin, audioPlugin, bind, clockPlugin, component, createApp, createPlugin, defineAnimation, defineBundles, defineComponent, defineEmitter, defineFeature, defineFilter, defineGame, defineMotion, defineScene, defineStyle, defineTextStyles, defineTokens, effectsPlugin, exit, external, flowPlugin, frames, guide, haptic, hint, i18nPlugin, inputPlugin, label, lifecyclePlugin, load, mark, modelPlugin, music, mut, parallel, platformPlugin, 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 };