@energy8platform/game-engine 0.34.2 → 0.35.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.
- package/dist/audio.cjs.js +114 -59
- package/dist/audio.cjs.js.map +1 -1
- package/dist/audio.d.ts +25 -0
- package/dist/audio.esm.js +114 -59
- package/dist/audio.esm.js.map +1 -1
- package/dist/core.cjs.js +222 -66
- package/dist/core.cjs.js.map +1 -1
- package/dist/core.d.ts +25 -0
- package/dist/core.esm.js +223 -67
- package/dist/core.esm.js.map +1 -1
- package/dist/flow.cjs.js +246 -0
- package/dist/flow.cjs.js.map +1 -1
- package/dist/flow.d.ts +192 -33
- package/dist/flow.esm.js +238 -1
- package/dist/flow.esm.js.map +1 -1
- package/dist/host.cjs.js +343 -82
- package/dist/host.cjs.js.map +1 -1
- package/dist/host.d.ts +82 -2
- package/dist/host.esm.js +344 -83
- package/dist/host.esm.js.map +1 -1
- package/dist/index.cjs.js +222 -66
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +72 -0
- package/dist/index.esm.js +223 -67
- package/dist/index.esm.js.map +1 -1
- package/dist/scene-devtools.cjs.js +529 -115
- package/dist/scene-devtools.cjs.js.map +1 -1
- package/dist/scene-devtools.d.ts +187 -34
- package/dist/scene-devtools.esm.js +529 -115
- package/dist/scene-devtools.esm.js.map +1 -1
- package/dist/scene.cjs.js +704 -46
- package/dist/scene.cjs.js.map +1 -1
- package/dist/scene.d.ts +228 -41
- package/dist/scene.esm.js +698 -47
- package/dist/scene.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/audio/AudioManager.ts +111 -53
- package/src/core/GameApplication.ts +47 -5
- package/src/host/buildConfig.ts +17 -4
- package/src/host/createSlotGame.ts +114 -12
- package/src/host/index.ts +3 -0
- package/src/host/types.ts +58 -0
- package/src/loading/LoadingScene.ts +76 -2
- package/src/loading/index.ts +6 -0
- package/src/types.ts +2 -0
package/dist/scene.d.ts
CHANGED
|
@@ -6,13 +6,17 @@ interface SceneDoc {
|
|
|
6
6
|
version: 1;
|
|
7
7
|
/** Stable document id (usually the game id). */
|
|
8
8
|
id: string;
|
|
9
|
+
/**
|
|
10
|
+
* Another scene this one builds on. The resolved doc is base ⊕ this, merged by node id,
|
|
11
|
+
* so a per-mode scene carries only its delta instead of a copy of the whole board.
|
|
12
|
+
* Resolved by `resolveExtends` before the doc reaches the engine.
|
|
13
|
+
*/
|
|
14
|
+
extends?: string;
|
|
9
15
|
/** Design space the layout rules are authored in (viewport arrives in these units). */
|
|
10
16
|
design: {
|
|
11
17
|
width: number;
|
|
12
18
|
height: number;
|
|
13
19
|
};
|
|
14
|
-
/** Authoring modes the scene has views for (e.g. ['base','free_spins']); base is implicit. */
|
|
15
|
-
modes?: string[];
|
|
16
20
|
root: SceneNode;
|
|
17
21
|
}
|
|
18
22
|
interface SceneNode {
|
|
@@ -32,13 +36,6 @@ interface SceneNode {
|
|
|
32
36
|
* frame's `anticipation` / `bonus` looks. A state is an override, not a new node.
|
|
33
37
|
*/
|
|
34
38
|
states?: Record<string, NodeOverride>;
|
|
35
|
-
/**
|
|
36
|
-
* Per-GAME-MODE override, applied automatically when the runtime `mode` var matches
|
|
37
|
-
* (base / free_spins / …). This is why base and free_spins are ONE scene, not two: a
|
|
38
|
-
* node re-poses per mode instead of being duplicated into a separate scene. Layered
|
|
39
|
-
* after orientation, before the active state.
|
|
40
|
-
*/
|
|
41
|
-
modes?: Record<string, NodeOverride>;
|
|
42
39
|
/** Id of another node in this doc used as this node's mask. */
|
|
43
40
|
mask?: string;
|
|
44
41
|
/** Filters applied to the node's view; kinds resolve through the registry (core: blur). */
|
|
@@ -158,21 +155,26 @@ interface PinLayout extends LayoutCommon {
|
|
|
158
155
|
}
|
|
159
156
|
type PinEdge = 'top-left' | 'top-center' | 'top-right' | 'center-left' | 'center' | 'center-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
|
|
160
157
|
type LayoutRule = AbsoluteLayout | ViewportFractionLayout | CoverLayout | FrameFractionLayout | GridCellLayout | PinLayout;
|
|
161
|
-
type ScenePatch =
|
|
162
|
-
/** `mode` targets that mode's override (node.modes[mode].props); else base props. */
|
|
163
|
-
{
|
|
158
|
+
type ScenePatch = {
|
|
164
159
|
op: 'set-props';
|
|
165
160
|
id: string;
|
|
166
161
|
props: Record<string, unknown>;
|
|
167
|
-
mode?: string;
|
|
168
162
|
}
|
|
169
|
-
/**
|
|
163
|
+
/**
|
|
164
|
+
* Targets `orientation` (responsive) when given, else the base rule. `layout: null` clears
|
|
165
|
+
* that slot — which is how undo removes an override the edit created.
|
|
166
|
+
*/
|
|
170
167
|
| {
|
|
171
168
|
op: 'set-layout';
|
|
172
169
|
id: string;
|
|
173
|
-
layout: LayoutRule;
|
|
170
|
+
layout: LayoutRule | null;
|
|
174
171
|
orientation?: Orientation;
|
|
175
|
-
|
|
172
|
+
}
|
|
173
|
+
/** Rename the outliner label. `name` is presentation only — addressing is always by id. */
|
|
174
|
+
| {
|
|
175
|
+
op: 'set-name';
|
|
176
|
+
id: string;
|
|
177
|
+
name: string | undefined;
|
|
176
178
|
} | {
|
|
177
179
|
op: 'set-state';
|
|
178
180
|
id: string;
|
|
@@ -204,6 +206,22 @@ type ScenePatch =
|
|
|
204
206
|
op: 'duplicate-node';
|
|
205
207
|
id: string;
|
|
206
208
|
};
|
|
209
|
+
/**
|
|
210
|
+
* Outcome of applying a patch. Rejections used to be console-only warnings inside the
|
|
211
|
+
* game, so an editor (or agent) saw "ok" for a patch that never applied — the reason now
|
|
212
|
+
* travels back to the caller.
|
|
213
|
+
*/
|
|
214
|
+
type PatchResult = {
|
|
215
|
+
ok: true;
|
|
216
|
+
/**
|
|
217
|
+
* The patch that undoes this one. Applying it restores the pre-patch state exactly,
|
|
218
|
+
* which is what the editor's undo stack replays. Absent only when the op had no effect.
|
|
219
|
+
*/
|
|
220
|
+
inverse?: ScenePatch;
|
|
221
|
+
} | {
|
|
222
|
+
ok: false;
|
|
223
|
+
error: string;
|
|
224
|
+
};
|
|
207
225
|
/** Outliner row — the tree the inspector and the agent both read. */
|
|
208
226
|
interface OutlineNode {
|
|
209
227
|
id: string;
|
|
@@ -215,6 +233,91 @@ interface OutlineNode {
|
|
|
215
233
|
children: OutlineNode[];
|
|
216
234
|
}
|
|
217
235
|
|
|
236
|
+
/** A node in an extending doc may delete an inherited node instead of overriding it. */
|
|
237
|
+
declare const REMOVE_MARKER = "$remove";
|
|
238
|
+
interface ExtendOptions {
|
|
239
|
+
/** Resolve a parent reference (a path, an id — whatever the host uses) to its doc. */
|
|
240
|
+
load: (ref: string) => SceneDoc | undefined;
|
|
241
|
+
/** Guards against a cycle; also the practical depth limit for a chain of modes. */
|
|
242
|
+
maxDepth?: number;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Resolve a doc's `extends` chain into a single self-contained doc. Docs without `extends`
|
|
246
|
+
* are returned as-is (cloned), so this is safe to call on everything.
|
|
247
|
+
*/
|
|
248
|
+
declare function resolveExtends(doc: SceneDoc, opts: ExtendOptions): SceneDoc;
|
|
249
|
+
/**
|
|
250
|
+
* The patches that turn `from` into `to`. Used to switch game modes without rebuilding: a
|
|
251
|
+
* node both docs share and agree on is never touched, so the reel system, its symbols and
|
|
252
|
+
* any running animation survive the transition.
|
|
253
|
+
*
|
|
254
|
+
* Order matters — removals first (ids can be reused), then additions parent-before-child,
|
|
255
|
+
* then property updates.
|
|
256
|
+
*/
|
|
257
|
+
declare function diffDocs(from: SceneDoc, to: SceneDoc): ScenePatch[];
|
|
258
|
+
|
|
259
|
+
type FieldKind = 'number' | 'text' | 'boolean' | 'color'
|
|
260
|
+
/** One of `options`. */
|
|
261
|
+
| 'enum'
|
|
262
|
+
/** A texture/audio alias from the game's asset manifest — the editor offers a picker. */
|
|
263
|
+
| 'asset'
|
|
264
|
+
/** The id of another node in this doc — the editor offers the node list. */
|
|
265
|
+
| 'nodeRef'
|
|
266
|
+
/** Nested record described by `fields`. */
|
|
267
|
+
| 'object'
|
|
268
|
+
/** Anything else: edited as raw JSON. */
|
|
269
|
+
| 'json';
|
|
270
|
+
interface FieldSchema {
|
|
271
|
+
kind: FieldKind;
|
|
272
|
+
/** Human label (defaults to the key). */
|
|
273
|
+
label?: string;
|
|
274
|
+
/** What the field does — inspector tooltip AND the agent's documentation. */
|
|
275
|
+
doc?: string;
|
|
276
|
+
/**
|
|
277
|
+
* Value the runtime uses when the field is absent. The inspector shows it as the
|
|
278
|
+
* effective value so "not set" never looks like "zero".
|
|
279
|
+
*/
|
|
280
|
+
default?: unknown;
|
|
281
|
+
/** `enum`: the allowed values. */
|
|
282
|
+
options?: readonly string[];
|
|
283
|
+
/** `number`: bounds and input step. */
|
|
284
|
+
min?: number;
|
|
285
|
+
max?: number;
|
|
286
|
+
step?: number;
|
|
287
|
+
/** `asset`: which kind of media this field accepts (filters the picker). */
|
|
288
|
+
accept?: 'image' | 'audio' | 'spritesheet';
|
|
289
|
+
/** `nodeRef`: restrict the picker to nodes of this type (e.g. `reelFrame`). */
|
|
290
|
+
ofType?: string;
|
|
291
|
+
/** `object`: the nested fields. */
|
|
292
|
+
fields?: PropsSchema;
|
|
293
|
+
/** Lower sorts first in the inspector; unordered fields follow, alphabetically. */
|
|
294
|
+
order?: number;
|
|
295
|
+
}
|
|
296
|
+
/** A node type's (or prefab's) authorable props, keyed by prop name. */
|
|
297
|
+
type PropsSchema = Record<string, FieldSchema>;
|
|
298
|
+
/** Shared field definitions, so every kind describes `alpha` the same way. */
|
|
299
|
+
declare const ALPHA_FIELD: FieldSchema;
|
|
300
|
+
/** Fractions of a texture (0..1), used for both `region` (crop) and `inner` (frame hollow). */
|
|
301
|
+
declare const fracBoxFields: (doc: string) => FieldSchema;
|
|
302
|
+
/**
|
|
303
|
+
* Flatten a schema into dot-path rows, pairing each with the value currently in `props`
|
|
304
|
+
* (`undefined` when unset). Nested `object` fields expand to `parent.child`, matching how
|
|
305
|
+
* layout rules are already flattened for the inspector.
|
|
306
|
+
*/
|
|
307
|
+
interface SchemaFieldRow {
|
|
308
|
+
/** Dot-path into props ('src', 'sheet.alias'). */
|
|
309
|
+
path: string;
|
|
310
|
+
label: string;
|
|
311
|
+
schema: FieldSchema;
|
|
312
|
+
/** Current value, or `undefined` when the prop is not set. */
|
|
313
|
+
value: unknown;
|
|
314
|
+
/** True when the value comes from the schema default rather than the doc. */
|
|
315
|
+
unset: boolean;
|
|
316
|
+
}
|
|
317
|
+
declare function schemaFieldRows(schema: PropsSchema | undefined, props: Record<string, unknown>): SchemaFieldRow[];
|
|
318
|
+
/** Props present on the node that the schema doesn't describe (plugin extras, hand-written). */
|
|
319
|
+
declare function extraPropKeys(schema: PropsSchema | undefined, props: Record<string, unknown>): string[];
|
|
320
|
+
|
|
218
321
|
interface Rect {
|
|
219
322
|
x: number;
|
|
220
323
|
y: number;
|
|
@@ -263,7 +366,7 @@ type LayoutResolution = {
|
|
|
263
366
|
};
|
|
264
367
|
declare function orientationOf(width: number, height: number, portraitFactor?: number): Orientation;
|
|
265
368
|
/** Base node + orientation override + active state override (state wins), for one frame. */
|
|
266
|
-
declare function effectiveNode(node: SceneNode, orientation: Orientation, state: string | null
|
|
369
|
+
declare function effectiveNode(node: SceneNode, orientation: Orientation, state: string | null): {
|
|
267
370
|
layout?: LayoutRule;
|
|
268
371
|
props: Record<string, unknown>;
|
|
269
372
|
visible: boolean;
|
|
@@ -351,8 +454,8 @@ interface NodeDefaults {
|
|
|
351
454
|
}
|
|
352
455
|
interface NodeTypeContribution {
|
|
353
456
|
kind: string;
|
|
354
|
-
/**
|
|
355
|
-
schema?:
|
|
457
|
+
/** Authorable `props` — drives the inspector's controls, validation and the agent's docs. */
|
|
458
|
+
schema?: PropsSchema;
|
|
356
459
|
/** 3–10 lines for the agent: when to use this kind, patterns, anti-patterns. */
|
|
357
460
|
agentDoc?: string;
|
|
358
461
|
/** Palette skeleton — omit to hide the kind from the add-menu (e.g. `prefab` dispatch). */
|
|
@@ -362,7 +465,7 @@ interface NodeTypeContribution {
|
|
|
362
465
|
/** Reusable game component (meters, HUDs) addressed as `{type:'prefab', props:{prefab:'name'}}`. */
|
|
363
466
|
interface PrefabContribution {
|
|
364
467
|
name: string;
|
|
365
|
-
schema?:
|
|
468
|
+
schema?: PropsSchema;
|
|
366
469
|
agentDoc?: string;
|
|
367
470
|
/** Palette skeleton (props merged onto `{prefab:name}`, plus a starter layout). */
|
|
368
471
|
defaults?: NodeDefaults;
|
|
@@ -371,7 +474,7 @@ interface PrefabContribution {
|
|
|
371
474
|
/** A filter kind: `{kind:'blur', strength: 3}` in a node's `filters` resolves through this. */
|
|
372
475
|
interface FilterKindContribution {
|
|
373
476
|
kind: string;
|
|
374
|
-
schema?:
|
|
477
|
+
schema?: PropsSchema;
|
|
375
478
|
agentDoc?: string;
|
|
376
479
|
create(spec: FilterSpec): Filter;
|
|
377
480
|
}
|
|
@@ -435,11 +538,17 @@ interface SceneHandle {
|
|
|
435
538
|
layout(width: number, height: number): void;
|
|
436
539
|
setVar(name: string, value: unknown): void;
|
|
437
540
|
setState(id: string, state: string | null): void;
|
|
438
|
-
|
|
541
|
+
/** Apply an edit. Returns `{ok:false, error}` when the patch was rejected. */
|
|
542
|
+
patch(patch: ScenePatch): PatchResult;
|
|
439
543
|
/** The live doc (mutated by patches) — serialize this to persist the scene. */
|
|
440
544
|
doc(): SceneDoc;
|
|
441
545
|
/** Spawnable palette (node kinds with defaults + prefabs) — feeds the editor add-menu. */
|
|
442
546
|
palette(): PaletteEntry[];
|
|
547
|
+
/**
|
|
548
|
+
* Props schemas by node kind (prefabs keyed `prefab:<name>`) — what the inspector renders
|
|
549
|
+
* its controls from, and what an agent reads as the authoring contract.
|
|
550
|
+
*/
|
|
551
|
+
schemas(): Record<string, PropsSchema>;
|
|
443
552
|
/**
|
|
444
553
|
* Re-apply every node's doc-effective props, wiping transient presentation writes
|
|
445
554
|
* (flow tweens/count-ups). "Settle = the doc" — scrub replays call this first.
|
|
@@ -514,15 +623,26 @@ interface TransformGizmoOptions {
|
|
|
514
623
|
app: Application;
|
|
515
624
|
applyPatch?: (patch: ScenePatch) => void;
|
|
516
625
|
getOrientation?: () => Orientation;
|
|
517
|
-
/** Current authoring mode; when set and not 'base', edits target that mode's override. */
|
|
518
|
-
getMode?: () => string | null;
|
|
519
626
|
/** Override screen→design conversion for move drags. Default: the node's parent world scale. */
|
|
520
627
|
designPerPixel?: (nodeId: string) => number;
|
|
628
|
+
/**
|
|
629
|
+
* Gesture boundaries. A drag emits a patch per pointer frame, so undo needs to know that
|
|
630
|
+
* the whole gesture is ONE edit — otherwise ⌘Z rewinds a drag one mouse-move at a time.
|
|
631
|
+
*/
|
|
632
|
+
onGestureStart?: () => void;
|
|
633
|
+
onGestureEnd?: () => void;
|
|
634
|
+
/**
|
|
635
|
+
* A press inside the selection box that never moved. The body covers the whole selected
|
|
636
|
+
* node so it can be dragged, which also made it swallow every click there — overlapping
|
|
637
|
+
* siblings and deeper children became unreachable once anything was selected. The host
|
|
638
|
+
* re-picks at this point instead.
|
|
639
|
+
*/
|
|
640
|
+
onBodyClick?: (globalX: number, globalY: number, altKey: boolean) => void;
|
|
521
641
|
}
|
|
522
642
|
interface TransformGizmo {
|
|
523
643
|
attach(nodeId: string | null): void;
|
|
524
644
|
refresh(): void;
|
|
525
|
-
/** Run a full handle drag programmatically (
|
|
645
|
+
/** Run a full handle drag programmatically (agent/tests). Screen coords. */
|
|
526
646
|
drag(handle: HandleId, from: {
|
|
527
647
|
x: number;
|
|
528
648
|
y: number;
|
|
@@ -530,6 +650,11 @@ interface TransformGizmo {
|
|
|
530
650
|
x: number;
|
|
531
651
|
y: number;
|
|
532
652
|
}): void;
|
|
653
|
+
/**
|
|
654
|
+
* Move the selection by a discrete amount (arrow keys). Deliberately NOT a synthetic drag:
|
|
655
|
+
* a drag ignores travel below the click/drag threshold, which would swallow a 1px nudge.
|
|
656
|
+
*/
|
|
657
|
+
nudge(dxScreen: number, dyScreen: number): void;
|
|
533
658
|
destroy(): void;
|
|
534
659
|
}
|
|
535
660
|
declare function createTransformGizmo(opts: TransformGizmoOptions): TransformGizmo;
|
|
@@ -748,9 +873,27 @@ interface CueDef {
|
|
|
748
873
|
jitter?: number;
|
|
749
874
|
volume?: number;
|
|
750
875
|
}
|
|
876
|
+
/**
|
|
877
|
+
* Fields every step carries regardless of kind.
|
|
878
|
+
*
|
|
879
|
+
* `id` exists because steps used to be addressed purely by position — three different
|
|
880
|
+
* positional schemes across the codebase — so any insert or delete invalidated every
|
|
881
|
+
* sibling's path, and a trace entry could not say WHICH step it came from. It lives on the
|
|
882
|
+
* step rather than in a document-level map on purpose: the editor→game doc push copies only
|
|
883
|
+
* `on` and `cues`, so a new top-level key would be silently dropped and never saved.
|
|
884
|
+
*/
|
|
885
|
+
interface StepCommon {
|
|
886
|
+
/** Stable identity. Assigned by `ensureStepIds` when a hand-written doc omits it. */
|
|
887
|
+
id?: string;
|
|
888
|
+
/** Editor-only: where the node sits on the flow canvas. Absent → auto-laid-out. */
|
|
889
|
+
ui?: {
|
|
890
|
+
x: number;
|
|
891
|
+
y: number;
|
|
892
|
+
};
|
|
893
|
+
}
|
|
751
894
|
/** Core step vocabulary; plugins contribute additional `do` kinds through the registry. */
|
|
752
895
|
type Step = TweenStep | SoundStep | SetStateStep | SetVarStep | SetPropsStep | CountUpStep | WaitStep | IfStep | ParallelStep | SeqStep | ForEachStep | CodeStep | PluginStep;
|
|
753
|
-
interface TweenStep {
|
|
896
|
+
interface TweenStep extends StepCommon {
|
|
754
897
|
do: 'tween';
|
|
755
898
|
node: string;
|
|
756
899
|
/** Target numeric view properties (alpha, x, y, scale, rotation, …). */
|
|
@@ -758,28 +901,28 @@ interface TweenStep {
|
|
|
758
901
|
ms: number;
|
|
759
902
|
ease?: string;
|
|
760
903
|
}
|
|
761
|
-
interface SoundStep {
|
|
904
|
+
interface SoundStep extends StepCommon {
|
|
762
905
|
do: 'sound';
|
|
763
906
|
cue: string;
|
|
764
907
|
action?: 'play' | 'stop';
|
|
765
908
|
}
|
|
766
|
-
interface SetStateStep {
|
|
909
|
+
interface SetStateStep extends StepCommon {
|
|
767
910
|
do: 'setState';
|
|
768
911
|
node: string;
|
|
769
912
|
state: string | null;
|
|
770
913
|
}
|
|
771
|
-
interface SetVarStep {
|
|
914
|
+
interface SetVarStep extends StepCommon {
|
|
772
915
|
do: 'setVar';
|
|
773
916
|
name: string;
|
|
774
917
|
value: unknown;
|
|
775
918
|
}
|
|
776
919
|
/** Transient prop write on the live instance (presentation) — does NOT touch the doc. */
|
|
777
|
-
interface SetPropsStep {
|
|
920
|
+
interface SetPropsStep extends StepCommon {
|
|
778
921
|
do: 'setProps';
|
|
779
922
|
node: string;
|
|
780
923
|
props: Record<string, unknown>;
|
|
781
924
|
}
|
|
782
|
-
interface CountUpStep {
|
|
925
|
+
interface CountUpStep extends StepCommon {
|
|
783
926
|
do: 'countUp';
|
|
784
927
|
node: string;
|
|
785
928
|
/** Instance prop receiving the formatted value (default 'value' — badge prefabs). */
|
|
@@ -790,24 +933,24 @@ interface CountUpStep {
|
|
|
790
933
|
ms?: number;
|
|
791
934
|
format?: 'int' | 'space';
|
|
792
935
|
}
|
|
793
|
-
interface WaitStep {
|
|
936
|
+
interface WaitStep extends StepCommon {
|
|
794
937
|
do: 'wait';
|
|
795
938
|
ms?: number;
|
|
796
939
|
until?: 'tap';
|
|
797
940
|
}
|
|
798
|
-
interface IfStep {
|
|
941
|
+
interface IfStep extends StepCommon {
|
|
799
942
|
do: 'if';
|
|
800
943
|
/** Micro-expression over the fire() ctx: `win >= 100`, `mode === 'fs'`, or a bare truthy name. */
|
|
801
944
|
when: string;
|
|
802
945
|
then: Step[];
|
|
803
946
|
else?: Step[];
|
|
804
947
|
}
|
|
805
|
-
interface ParallelStep {
|
|
948
|
+
interface ParallelStep extends StepCommon {
|
|
806
949
|
do: 'parallel';
|
|
807
950
|
/** Independent tracks, awaited together. */
|
|
808
951
|
steps: Step[][];
|
|
809
952
|
}
|
|
810
|
-
interface SeqStep {
|
|
953
|
+
interface SeqStep extends StepCommon {
|
|
811
954
|
do: 'seq';
|
|
812
955
|
steps: Step[];
|
|
813
956
|
}
|
|
@@ -816,7 +959,7 @@ interface SeqStep {
|
|
|
816
959
|
* flights, per-cell transmutes, cascade histories). Nested steps see the current element
|
|
817
960
|
* as `$<as>` (default `$item`) and its index as `$<as>Index`.
|
|
818
961
|
*/
|
|
819
|
-
interface ForEachStep {
|
|
962
|
+
interface ForEachStep extends StepCommon {
|
|
820
963
|
do: 'forEach';
|
|
821
964
|
/** '$path' into the ctx (or an inline array). */
|
|
822
965
|
items: string | unknown[];
|
|
@@ -827,12 +970,13 @@ interface ForEachStep {
|
|
|
827
970
|
steps: Step[];
|
|
828
971
|
}
|
|
829
972
|
/** Escape hatch: a named code choreography registered on the runner. */
|
|
830
|
-
interface CodeStep {
|
|
973
|
+
interface CodeStep extends StepCommon {
|
|
831
974
|
do: 'code';
|
|
832
975
|
ref: string;
|
|
833
976
|
args?: Record<string, unknown>;
|
|
834
977
|
}
|
|
835
|
-
|
|
978
|
+
/** A plugin-contributed kind: open shape, but it still carries the common fields. */
|
|
979
|
+
interface PluginStep extends StepCommon {
|
|
836
980
|
do: string;
|
|
837
981
|
[key: string]: unknown;
|
|
838
982
|
}
|
|
@@ -840,6 +984,12 @@ interface TraceEntry {
|
|
|
840
984
|
/** ms since fire() (real time, unscaled). */
|
|
841
985
|
t: number;
|
|
842
986
|
do: string;
|
|
987
|
+
/**
|
|
988
|
+
* Which step produced this entry. Without it the trace only says a `tween` ran — two
|
|
989
|
+
* identical tweens are indistinguishable — so a canvas cannot highlight what is running
|
|
990
|
+
* and a scrub cannot point at a step.
|
|
991
|
+
*/
|
|
992
|
+
stepId?: string;
|
|
843
993
|
node?: string;
|
|
844
994
|
info?: string;
|
|
845
995
|
}
|
|
@@ -893,6 +1043,16 @@ interface FlowRunner {
|
|
|
893
1043
|
/** Host reports a user tap (releases `wait until:'tap'`). */
|
|
894
1044
|
tap(): void;
|
|
895
1045
|
events(): string[];
|
|
1046
|
+
/**
|
|
1047
|
+
* The step kinds this runner accepts, with their authoring metadata. The editor lives in
|
|
1048
|
+
* another origin and cannot reach the registry, so the contract travels through here —
|
|
1049
|
+
* before this, field lists were hardcoded in the editor (twice, and already drifting).
|
|
1050
|
+
*/
|
|
1051
|
+
stepKinds(): Array<{
|
|
1052
|
+
kind: string;
|
|
1053
|
+
schema?: PropsSchema;
|
|
1054
|
+
agentDoc?: string;
|
|
1055
|
+
}>;
|
|
896
1056
|
destroy(): void;
|
|
897
1057
|
}
|
|
898
1058
|
/** Per-run runtime handed to step executors (core and plugin alike). */
|
|
@@ -926,7 +1086,8 @@ interface FlowRuntime {
|
|
|
926
1086
|
|
|
927
1087
|
interface FlowStepContribution {
|
|
928
1088
|
kind: string;
|
|
929
|
-
|
|
1089
|
+
/** Authorable fields — drives the editor's controls and documents the step for an agent. */
|
|
1090
|
+
schema?: PropsSchema;
|
|
930
1091
|
/** 3–10 lines for the agent: when to use the step, patterns, anti-patterns. */
|
|
931
1092
|
agentDoc?: string;
|
|
932
1093
|
run(step: Step, rt: FlowRuntime): Promise<void> | void;
|
|
@@ -943,6 +1104,13 @@ interface StageDoc {
|
|
|
943
1104
|
key: string;
|
|
944
1105
|
scene: SceneDoc;
|
|
945
1106
|
flow?: FlowDoc;
|
|
1107
|
+
/**
|
|
1108
|
+
* The game mode this scene is the view for (`free_spins`, `bonus`, …). Such a scene is
|
|
1109
|
+
* NOT a separate host scene: it is folded into the scene it extends and applied as a
|
|
1110
|
+
* diff when the mode starts, so the board is not rebuilt. Omit for real screens (intro,
|
|
1111
|
+
* an adventure map) — those stay their own host scene.
|
|
1112
|
+
*/
|
|
1113
|
+
mode?: string;
|
|
946
1114
|
/** Host skips this scene on replay launches (intro idiom). */
|
|
947
1115
|
skipOnReplay?: boolean;
|
|
948
1116
|
/** A tap anywhere advances to this scene key (intro → game). */
|
|
@@ -957,6 +1125,14 @@ declare function buildDocScenes<T extends SlotSpinResultBase = SlotSpinResultBas
|
|
|
957
1125
|
}>;
|
|
958
1126
|
interface DocSceneOptions<T extends SlotSpinResultBase = SlotSpinResultBase> {
|
|
959
1127
|
scene: SceneDoc;
|
|
1128
|
+
/**
|
|
1129
|
+
* A scene doc per game mode (`free_spins`, `bonus`, …) — each authored as its own file,
|
|
1130
|
+
* usually `extends`-ing this one so it carries only its delta. Entering a mode applies
|
|
1131
|
+
* the DIFF to the live scene: shared nodes are never touched, so the reel system, its
|
|
1132
|
+
* symbols and any running animation survive the transition. (No game in the surveyed set
|
|
1133
|
+
* rebuilds its board on mode entry, and rebuilding mid-spin would be visible.)
|
|
1134
|
+
*/
|
|
1135
|
+
modeScenes?: Record<string, SceneDoc>;
|
|
960
1136
|
flow?: FlowDoc;
|
|
961
1137
|
/** A tap anywhere advances to this scene key (uses the host-injected goto). */
|
|
962
1138
|
advanceOnTap?: string;
|
|
@@ -995,14 +1171,25 @@ declare class DocScene<T extends SlotSpinResultBase = SlotSpinResultBase> extend
|
|
|
995
1171
|
private ctxOf;
|
|
996
1172
|
onCreate(api: SceneApi): void;
|
|
997
1173
|
onSpinStart(): void;
|
|
1174
|
+
/** The resolved doc currently on screen, so a mode switch diffs from the right baseline. */
|
|
1175
|
+
private activeDoc_;
|
|
1176
|
+
private activeDocId_;
|
|
998
1177
|
onSpin(result: T, ctx: RenderContext): Promise<void>;
|
|
999
1178
|
onEnterMode(result: T, ctx: RenderContext): Promise<void>;
|
|
1000
1179
|
onExitMode(result: T, ctx: RenderContext): Promise<void>;
|
|
1180
|
+
/**
|
|
1181
|
+
* Move the live scene to the doc for `mode` (null = the base scene) by applying the diff.
|
|
1182
|
+
* A no-op when the mode has no scene of its own, which is the common case: most modes
|
|
1183
|
+
* differ only in what flow does.
|
|
1184
|
+
*/
|
|
1185
|
+
private applySceneFor;
|
|
1186
|
+
/** Fold a doc's `extends` chain, looking parents up among the scenes this game declared. */
|
|
1187
|
+
private resolveDoc;
|
|
1001
1188
|
onSpinEnd(result: T, ctx: RenderContext): void;
|
|
1002
1189
|
onSkip(): void;
|
|
1003
1190
|
onTurboChanged(level: number): void;
|
|
1004
1191
|
}
|
|
1005
1192
|
declare function createDocScene<T extends SlotSpinResultBase = SlotSpinResultBase>(opts: DocSceneOptions<T>): DocScene<T>;
|
|
1006
1193
|
|
|
1007
|
-
export { BUILTIN_FILTER_KINDS, BUILTIN_NODE_TYPES, DocScene, buildDocScenes, createDocScene, createInnerCalibrator, createSceneFromDoc, createSceneRegistry, createTransformGizmo, dependencyOf, dragInnerEdge, edgePoint, effectiveNode, evalVisibleWhen, handlePoint, nudgeRule, orientationOf, placementBounds, resizeFactors, resizeRule, resolveLayoutRule, setRuleRotation, sizeLever, validateSceneDoc };
|
|
1008
|
-
export type { AbsoluteLayout, Box, CoverLayout, CreateSceneOptions, DocSceneOptions, FilterKindContribution, FilterSpec, FrameFractionLayout, GridCellLayout, HandleId, InnerCalibrator, InnerCalibratorOptions, InnerEdge, InnerFracs, LayoutContext, LayoutResolution, LayoutRule, NodeCreateContext, NodeDefaults, NodeInstance, NodeOverride, NodeTypeContribution, Orientation, OutlineNode, PaletteEntry, PinEdge, PinLayout, Placement, PrefabContribution, Rect, SceneDoc, SceneHandle, SceneNode, ScenePatch, ScenePlugin, SceneRegistry, SceneValidationError, Size, StageDoc, TransformGizmo, TransformGizmoOptions, ViewportFractionLayout };
|
|
1194
|
+
export { ALPHA_FIELD, BUILTIN_FILTER_KINDS, BUILTIN_NODE_TYPES, DocScene, REMOVE_MARKER, buildDocScenes, createDocScene, createInnerCalibrator, createSceneFromDoc, createSceneRegistry, createTransformGizmo, dependencyOf, diffDocs, dragInnerEdge, edgePoint, effectiveNode, evalVisibleWhen, extraPropKeys, fracBoxFields, handlePoint, nudgeRule, orientationOf, placementBounds, resizeFactors, resizeRule, resolveExtends, resolveLayoutRule, schemaFieldRows, setRuleRotation, sizeLever, validateSceneDoc };
|
|
1195
|
+
export type { AbsoluteLayout, Box, CoverLayout, CreateSceneOptions, DocSceneOptions, ExtendOptions, FieldKind, FieldSchema, FilterKindContribution, FilterSpec, FrameFractionLayout, GridCellLayout, HandleId, InnerCalibrator, InnerCalibratorOptions, InnerEdge, InnerFracs, LayoutContext, LayoutResolution, LayoutRule, NodeCreateContext, NodeDefaults, NodeInstance, NodeOverride, NodeTypeContribution, Orientation, OutlineNode, PaletteEntry, PatchResult, PinEdge, PinLayout, Placement, PrefabContribution, PropsSchema, Rect, SceneDoc, SceneHandle, SceneNode, ScenePatch, ScenePlugin, SceneRegistry, SceneValidationError, SchemaFieldRow, Size, StageDoc, TransformGizmo, TransformGizmoOptions, ViewportFractionLayout };
|