@patterkit/runtime 0.13.0 → 0.14.1
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/CHANGELOG.md +43 -0
- package/README.md +25 -6
- package/dist/index.cjs +259 -122
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -25
- package/dist/index.d.ts +77 -25
- package/dist/index.js +256 -119
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ScalarValue } from '@wildwinter/expr';
|
|
2
|
-
import { ScopeResolver, ScopeRegistry,
|
|
2
|
+
import { ScopeResolver, ScopeRegistry, PropertyBag, ScopeDeclaration, LogMount, PropertyRow } from '@wildwinter/scoperegistry';
|
|
3
3
|
export { PropertyRow } from '@wildwinter/scoperegistry';
|
|
4
|
-
import { GameData, Bundle, CompiledGroup, CompiledSnippet, CompiledBlock, FlowSnapshot, EngineSave, SaveGame, PropertyType, ScalarValue as ScalarValue$1, GameDataNodeKind, GameDataField } from '@patterkit/model';
|
|
4
|
+
import { GameData, Bundle, CompiledGroup, CompiledSnippet, CompiledBlock, FlowSnapshot, EngineSave, SaveGame, SaveGameV2, PropertyType, ScalarValue as ScalarValue$1, GameDataNodeKind, GameDataField } from '@patterkit/model';
|
|
5
5
|
export { Bundle, EngineSave, FlowCursor, FlowSnapshot, SaveEnvelope, SaveGame, SavedChoice, SavedChoiceOption, SavedChoicePrompt, SelectorSnapshot, StackFrame } from '@patterkit/model';
|
|
6
6
|
|
|
7
7
|
type SelectableNode = CompiledGroup | CompiledSnippet;
|
|
@@ -224,8 +224,18 @@ interface EngineOptions {
|
|
|
224
224
|
* Ignored by an "ids" bundle, which emits beat IDs for the game to localise itself. */
|
|
225
225
|
locale?: string;
|
|
226
226
|
/** The host's resolver for **World Properties** (`@world.*`): the values the game owns and the story
|
|
227
|
-
* reads. Omit it and the runtime self-backs `@world` from the declared defaults
|
|
227
|
+
* reads. Omit it and the runtime self-backs `@world` from the declared defaults, as a property the
|
|
228
|
+
* registry stores and saves. Shared by all flows. A game running several engines registers `@world`
|
|
229
|
+
* in its registry itself instead, and no engine is given a resolver. */
|
|
228
230
|
world?: WorldResolver;
|
|
231
|
+
/** The game's registry: ONE per game, holding every engine's properties except those the game keeps
|
|
232
|
+
* itself, saved once. Given one, the engine registers its own scopes in it (`@patter` under `patter`,
|
|
233
|
+
* its per-flow and per-scene bags under keys starting `patter/`, and `@world` if `world` is passed),
|
|
234
|
+
* reads every other scope from it, and `saveGame()` leaves the property values to the game. Host
|
|
235
|
+
* scopes the bundle declares (`@world`) are then the game's to register: owned if the registry should
|
|
236
|
+
* store them, foreign if the game keeps them. Omit it and the engine makes its own registry and acts as
|
|
237
|
+
* its own game: it self-backs `@world`, and `saveGame()` carries the registry's values too. */
|
|
238
|
+
registry?: ScopeRegistry;
|
|
229
239
|
/**
|
|
230
240
|
* Replay a chosen option's `prompt` as its first played beat (spec §5). Default `false`:
|
|
231
241
|
* the prompt is a label only and `choose()` plays just the option's content. `true`: the
|
|
@@ -291,8 +301,14 @@ interface FlowHost {
|
|
|
291
301
|
blockGameIdToId: Map<string, Map<string, string>>;
|
|
292
302
|
/** Author tags (#215): node id -> accumulated tags (own + every ancestor's, deduped). Built once. */
|
|
293
303
|
tagIndex: Map<string, string[]>;
|
|
294
|
-
/** The
|
|
295
|
-
|
|
304
|
+
/** The game's one registry: `@patter` (the SHARED globals), host scopes, every instance bag. */
|
|
305
|
+
registry: ScopeRegistry;
|
|
306
|
+
/** True when the engine made the registry (a standalone game): `saveGame()` then carries its values. */
|
|
307
|
+
readonly ownsRegistry: boolean;
|
|
308
|
+
/** The SHARED `@patter` globals' bag, registered under `patter`. */
|
|
309
|
+
patterBag: PropertyBag;
|
|
310
|
+
/** Host scopes this engine self-backed and registered (the game bound none, nobody else had). */
|
|
311
|
+
hostScopes: string[];
|
|
296
312
|
/** Decls for the shared `@patter` globals - (re)seed on `engine.reset()`. */
|
|
297
313
|
patterSharedDecls: ScopeDeclaration[];
|
|
298
314
|
/** Decls for the per-flow `@patter` globals - seed each flow's local registry. */
|
|
@@ -305,11 +321,8 @@ interface FlowHost {
|
|
|
305
321
|
sharedVisits: Map<string, number>;
|
|
306
322
|
/** Shared selector cursors (node id -> SelectorState) for `shared` memoried selectors. */
|
|
307
323
|
sharedSelectors: Map<string, SelectorState>;
|
|
308
|
-
/**
|
|
309
|
-
|
|
310
|
-
* 2026-09-02: seeding, name normalisation and the mutable-default clone were all
|
|
311
|
-
* written out by hand here, and the shared bag already had them. The SAVE is
|
|
312
|
-
* unchanged - bag.save() is a bare record, which is what the envelope carries. */
|
|
324
|
+
/** Per-scene SHARED scene props, each registered under `keys.stage(sceneId)`. Made the first time any
|
|
325
|
+
* flow needs the scene, so a bag loaded before then waits in the registry and is claimed here. */
|
|
313
326
|
stageBags: Map<string, PropertyBag>;
|
|
314
327
|
customRng?: () => number;
|
|
315
328
|
/** Play a chosen option's prompt as its first beat (spec §5); default false. */
|
|
@@ -327,12 +340,13 @@ interface FlowHost {
|
|
|
327
340
|
* fallback - so it falls through and the flow continues past it. Zero cost when unset; the coverage
|
|
328
341
|
* harness passes it to surface silent fall-throughs. Not a gameplay signal (the behaviour is unchanged). */
|
|
329
342
|
onDryChoice?: (groupId: string) => void;
|
|
330
|
-
/** Memoised `splitRef` results (ref string -> {scope,name}). The split depends only on
|
|
331
|
-
* set,
|
|
343
|
+
/** Memoised `splitRef` results (ref string -> {scope,name}). The split depends only on the registry's
|
|
344
|
+
* scope set, so the cache is dropped whenever that moves (`refSplitRevision`). */
|
|
332
345
|
refSplitCache: Map<string, {
|
|
333
346
|
scope: string;
|
|
334
347
|
name: string;
|
|
335
348
|
}>;
|
|
349
|
+
refSplitRevision: number;
|
|
336
350
|
}
|
|
337
351
|
declare class Engine {
|
|
338
352
|
private readonly host;
|
|
@@ -390,10 +404,12 @@ declare class Engine {
|
|
|
390
404
|
* content-drift policy (§9.8) resolves edits under the cursor: stack frames re-find their next
|
|
391
405
|
* child by id, drifted options drop, a vanished snippet is skipped.
|
|
392
406
|
*
|
|
393
|
-
* Returns the REPLACEMENT engine
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
407
|
+
* Returns the REPLACEMENT engine, on the same registry. This one hands its bags over (each is
|
|
408
|
+
* removed from the registry with its values kept, and the replacement claims them as it
|
|
409
|
+
* registers), its flows are closed, and it should be discarded. Hosts re-bind their flow handles
|
|
410
|
+
* via `next.getFlow(id)`. If the restore throws (defensive - §9.8 makes this unreachable for
|
|
411
|
+
* ordinary edits), the swap falls back to a fresh engine with each saved flow restarted from the
|
|
412
|
+
* top of the scene it was in; the shared properties carry over.
|
|
397
413
|
*/
|
|
398
414
|
hotSwap(bundle: Bundle): Engine;
|
|
399
415
|
/** Whether closed captions are currently shown (full dialogue text). */
|
|
@@ -444,6 +460,11 @@ declare class Engine {
|
|
|
444
460
|
* fetch it with `engine.getFlow(name)?.getChoices()`.
|
|
445
461
|
*/
|
|
446
462
|
runFlow(flow: string, scene: string, block?: string): AdvanceToStopResult["played"];
|
|
463
|
+
/** Content that names another engine's scope (`@story.act`) runs only where that engine is on this
|
|
464
|
+
* registry: without it every read would answer false and every write fail, so the flow is refused as
|
|
465
|
+
* it opens (or the save as it loads), before anything changes. By then a game has built all of its
|
|
466
|
+
* engines, whatever order it built them in. The same message on every runtime. */
|
|
467
|
+
private assertExternalScopes;
|
|
447
468
|
/** Resolve a scene reference (a gameId address OR an internal id) to its internal id. */
|
|
448
469
|
private resolveSceneRef;
|
|
449
470
|
/** Resolve a block reference (a scene-scoped gameId OR an internal id) to its internal id. */
|
|
@@ -523,6 +544,9 @@ declare class Engine {
|
|
|
523
544
|
* After reset, open fresh flows with `openFlow`.
|
|
524
545
|
*/
|
|
525
546
|
reset(): void;
|
|
547
|
+
/** Remove every bag this engine registered, keeping the values parked when `keep` (a live reload
|
|
548
|
+
* handing its state to a replacement), and close its flows. The engine is inert afterwards. */
|
|
549
|
+
private release;
|
|
526
550
|
/** Read a shared (`@patter` / foreign) property by ref. `@scene` refs are rejected (flow-level). */
|
|
527
551
|
getProperty(ref: string): ScalarValue | undefined;
|
|
528
552
|
/** Write a shared (`@patter` / foreign) property by ref. `@scene` refs are rejected (flow-level).
|
|
@@ -548,19 +572,33 @@ declare class Engine {
|
|
|
548
572
|
private emitEngine;
|
|
549
573
|
listProperties(): PropertyRow[];
|
|
550
574
|
private splitShared;
|
|
551
|
-
/**
|
|
575
|
+
/** The shared `@patter` values alone, as `{ patter: {...} }`.
|
|
576
|
+
* @deprecated The registry holds every property now: a game saves `registry.save()` once, and a
|
|
577
|
+
* standalone engine's `saveGame()` carries its registry's values. Removed at the next breaking release. */
|
|
552
578
|
save(): EngineSave;
|
|
553
|
-
/**
|
|
579
|
+
/** Lay a `{ patter: {...} }` section over the shared `@patter` values; anything else is ignored.
|
|
580
|
+
* @deprecated See `save`. Removed at the next breaking release. */
|
|
554
581
|
load(blob: EngineSave): void;
|
|
555
|
-
/** Snapshot the whole game
|
|
582
|
+
/** Snapshot the whole game's NON-property state: visit counts, shared selector cursors, and every
|
|
583
|
+
* live flow's cursor and PRNG. The property values are the registry's: a standalone engine (one that
|
|
584
|
+
* made its own registry) carries them here under `registry`; a game that passed a registry saves it
|
|
585
|
+
* once itself, beside each engine's `saveGame()`. */
|
|
556
586
|
saveGame(): SaveGame;
|
|
557
|
-
/**
|
|
558
|
-
|
|
587
|
+
/**
|
|
588
|
+
* Restore a `saveGame()`: visit counts, shared selector cursors, and every flow. Property values come
|
|
589
|
+
* from the registry. A save that carries them (a standalone engine's, or a version 2 save from before
|
|
590
|
+
* the registry held them) has them moved into the registry here; otherwise the game loads its
|
|
591
|
+
* registry itself, before or after this call. Either order works: this engine's bags are handed back
|
|
592
|
+
* to the registry (values kept) and the restored flows claim them as they register.
|
|
593
|
+
*/
|
|
594
|
+
loadGame(save: SaveGame | SaveGameV2): void;
|
|
559
595
|
}
|
|
560
596
|
declare class Flow {
|
|
561
597
|
readonly id: string;
|
|
562
598
|
private readonly host;
|
|
563
599
|
private local;
|
|
600
|
+
/** The registry keys this flow has registered (its globals and each scene bag). */
|
|
601
|
+
private readonly registered;
|
|
564
602
|
private rngState;
|
|
565
603
|
private started;
|
|
566
604
|
private flowEnded;
|
|
@@ -585,10 +623,14 @@ declare class Flow {
|
|
|
585
623
|
private readonly patterResolver;
|
|
586
624
|
private readonly sceneResolver;
|
|
587
625
|
private readonly evalCtx;
|
|
626
|
+
private ctxRevision;
|
|
627
|
+
private registryQualities;
|
|
588
628
|
private readonly flowLog;
|
|
589
629
|
/** Monotonic across the flow's life; survives clearLog so two reads agree on order. */
|
|
590
630
|
private flowSeq;
|
|
591
631
|
constructor(id: string, host: FlowHost, seed: number);
|
|
632
|
+
/** The eval context, its scopes refreshed if the registry's set of scopes has moved since. */
|
|
633
|
+
private context;
|
|
592
634
|
/** The stage ladder of `@scope.name` when it is a declared quality, else undefined. Names compare
|
|
593
635
|
* lowercase, as the compiler emits references (the selfBackedResolver lesson). */
|
|
594
636
|
private stagesFor;
|
|
@@ -681,7 +723,7 @@ declare class Flow {
|
|
|
681
723
|
/** The write itself. `host` says WHO is writing, which is the only thing `writable: false` cares
|
|
682
724
|
* about: the story is refused, the game is not. */
|
|
683
725
|
private writeProperty;
|
|
684
|
-
/** @internal Snapshot this flow's cursor +
|
|
726
|
+
/** @internal Snapshot this flow's cursor + PRNG + visits. Its properties are the registry's. */
|
|
685
727
|
snapshot(): FlowSnapshot;
|
|
686
728
|
/** @internal Restore this flow from a snapshot. */
|
|
687
729
|
restore(snap: FlowSnapshot): void;
|
|
@@ -793,10 +835,20 @@ declare class Flow {
|
|
|
793
835
|
* locale, else the authoring `displayName`. Undefined when the character has no display name at all
|
|
794
836
|
* (the host falls back to the `character` token itself). */
|
|
795
837
|
private resolveCharacterName;
|
|
796
|
-
/** Split a ref into scope + name. Tokens: `@scene`,
|
|
838
|
+
/** Split a ref into scope + name. Tokens: `@scene`, registered tokens, else `@patter` (incl. bare `@name`). */
|
|
797
839
|
private splitRef;
|
|
798
|
-
/**
|
|
799
|
-
private
|
|
840
|
+
/** A fresh, unregistered bag for the NOT-shared `@patter` globals (the shared ones live on the host). */
|
|
841
|
+
private newLocal;
|
|
842
|
+
/** Register a fresh globals bag under this flow's key; it claims any values waiting there. */
|
|
843
|
+
private mountLocal;
|
|
844
|
+
/** @internal Remove every bag this flow registered; with `keep`, their values wait in the registry for
|
|
845
|
+
* the flow that replaces this one. Engine-driven (close, loadGame, hotSwap). */
|
|
846
|
+
releaseBags(keep: boolean): void;
|
|
847
|
+
/** The bag a `@scene` property of scene `s` lives in (stage or this flow's), made if missing. */
|
|
848
|
+
private sceneBagFor;
|
|
849
|
+
/** Make (and register) scene `s`'s stage bag and this flow's bag for it, if not made yet. A bag made
|
|
850
|
+
* here claims whatever values the registry holds for its key: that is how a loaded save reaches it. */
|
|
851
|
+
private ensureSceneBags;
|
|
800
852
|
/**
|
|
801
853
|
* Seed a scene's `@scene` props (spec §7). The not-shared props seed THIS flow's
|
|
802
854
|
* bag the first time it enters (persist across re-entries thereafter); the shared
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ScalarValue } from '@wildwinter/expr';
|
|
2
|
-
import { ScopeResolver, ScopeRegistry,
|
|
2
|
+
import { ScopeResolver, ScopeRegistry, PropertyBag, ScopeDeclaration, LogMount, PropertyRow } from '@wildwinter/scoperegistry';
|
|
3
3
|
export { PropertyRow } from '@wildwinter/scoperegistry';
|
|
4
|
-
import { GameData, Bundle, CompiledGroup, CompiledSnippet, CompiledBlock, FlowSnapshot, EngineSave, SaveGame, PropertyType, ScalarValue as ScalarValue$1, GameDataNodeKind, GameDataField } from '@patterkit/model';
|
|
4
|
+
import { GameData, Bundle, CompiledGroup, CompiledSnippet, CompiledBlock, FlowSnapshot, EngineSave, SaveGame, SaveGameV2, PropertyType, ScalarValue as ScalarValue$1, GameDataNodeKind, GameDataField } from '@patterkit/model';
|
|
5
5
|
export { Bundle, EngineSave, FlowCursor, FlowSnapshot, SaveEnvelope, SaveGame, SavedChoice, SavedChoiceOption, SavedChoicePrompt, SelectorSnapshot, StackFrame } from '@patterkit/model';
|
|
6
6
|
|
|
7
7
|
type SelectableNode = CompiledGroup | CompiledSnippet;
|
|
@@ -224,8 +224,18 @@ interface EngineOptions {
|
|
|
224
224
|
* Ignored by an "ids" bundle, which emits beat IDs for the game to localise itself. */
|
|
225
225
|
locale?: string;
|
|
226
226
|
/** The host's resolver for **World Properties** (`@world.*`): the values the game owns and the story
|
|
227
|
-
* reads. Omit it and the runtime self-backs `@world` from the declared defaults
|
|
227
|
+
* reads. Omit it and the runtime self-backs `@world` from the declared defaults, as a property the
|
|
228
|
+
* registry stores and saves. Shared by all flows. A game running several engines registers `@world`
|
|
229
|
+
* in its registry itself instead, and no engine is given a resolver. */
|
|
228
230
|
world?: WorldResolver;
|
|
231
|
+
/** The game's registry: ONE per game, holding every engine's properties except those the game keeps
|
|
232
|
+
* itself, saved once. Given one, the engine registers its own scopes in it (`@patter` under `patter`,
|
|
233
|
+
* its per-flow and per-scene bags under keys starting `patter/`, and `@world` if `world` is passed),
|
|
234
|
+
* reads every other scope from it, and `saveGame()` leaves the property values to the game. Host
|
|
235
|
+
* scopes the bundle declares (`@world`) are then the game's to register: owned if the registry should
|
|
236
|
+
* store them, foreign if the game keeps them. Omit it and the engine makes its own registry and acts as
|
|
237
|
+
* its own game: it self-backs `@world`, and `saveGame()` carries the registry's values too. */
|
|
238
|
+
registry?: ScopeRegistry;
|
|
229
239
|
/**
|
|
230
240
|
* Replay a chosen option's `prompt` as its first played beat (spec §5). Default `false`:
|
|
231
241
|
* the prompt is a label only and `choose()` plays just the option's content. `true`: the
|
|
@@ -291,8 +301,14 @@ interface FlowHost {
|
|
|
291
301
|
blockGameIdToId: Map<string, Map<string, string>>;
|
|
292
302
|
/** Author tags (#215): node id -> accumulated tags (own + every ancestor's, deduped). Built once. */
|
|
293
303
|
tagIndex: Map<string, string[]>;
|
|
294
|
-
/** The
|
|
295
|
-
|
|
304
|
+
/** The game's one registry: `@patter` (the SHARED globals), host scopes, every instance bag. */
|
|
305
|
+
registry: ScopeRegistry;
|
|
306
|
+
/** True when the engine made the registry (a standalone game): `saveGame()` then carries its values. */
|
|
307
|
+
readonly ownsRegistry: boolean;
|
|
308
|
+
/** The SHARED `@patter` globals' bag, registered under `patter`. */
|
|
309
|
+
patterBag: PropertyBag;
|
|
310
|
+
/** Host scopes this engine self-backed and registered (the game bound none, nobody else had). */
|
|
311
|
+
hostScopes: string[];
|
|
296
312
|
/** Decls for the shared `@patter` globals - (re)seed on `engine.reset()`. */
|
|
297
313
|
patterSharedDecls: ScopeDeclaration[];
|
|
298
314
|
/** Decls for the per-flow `@patter` globals - seed each flow's local registry. */
|
|
@@ -305,11 +321,8 @@ interface FlowHost {
|
|
|
305
321
|
sharedVisits: Map<string, number>;
|
|
306
322
|
/** Shared selector cursors (node id -> SelectorState) for `shared` memoried selectors. */
|
|
307
323
|
sharedSelectors: Map<string, SelectorState>;
|
|
308
|
-
/**
|
|
309
|
-
|
|
310
|
-
* 2026-09-02: seeding, name normalisation and the mutable-default clone were all
|
|
311
|
-
* written out by hand here, and the shared bag already had them. The SAVE is
|
|
312
|
-
* unchanged - bag.save() is a bare record, which is what the envelope carries. */
|
|
324
|
+
/** Per-scene SHARED scene props, each registered under `keys.stage(sceneId)`. Made the first time any
|
|
325
|
+
* flow needs the scene, so a bag loaded before then waits in the registry and is claimed here. */
|
|
313
326
|
stageBags: Map<string, PropertyBag>;
|
|
314
327
|
customRng?: () => number;
|
|
315
328
|
/** Play a chosen option's prompt as its first beat (spec §5); default false. */
|
|
@@ -327,12 +340,13 @@ interface FlowHost {
|
|
|
327
340
|
* fallback - so it falls through and the flow continues past it. Zero cost when unset; the coverage
|
|
328
341
|
* harness passes it to surface silent fall-throughs. Not a gameplay signal (the behaviour is unchanged). */
|
|
329
342
|
onDryChoice?: (groupId: string) => void;
|
|
330
|
-
/** Memoised `splitRef` results (ref string -> {scope,name}). The split depends only on
|
|
331
|
-
* set,
|
|
343
|
+
/** Memoised `splitRef` results (ref string -> {scope,name}). The split depends only on the registry's
|
|
344
|
+
* scope set, so the cache is dropped whenever that moves (`refSplitRevision`). */
|
|
332
345
|
refSplitCache: Map<string, {
|
|
333
346
|
scope: string;
|
|
334
347
|
name: string;
|
|
335
348
|
}>;
|
|
349
|
+
refSplitRevision: number;
|
|
336
350
|
}
|
|
337
351
|
declare class Engine {
|
|
338
352
|
private readonly host;
|
|
@@ -390,10 +404,12 @@ declare class Engine {
|
|
|
390
404
|
* content-drift policy (§9.8) resolves edits under the cursor: stack frames re-find their next
|
|
391
405
|
* child by id, drifted options drop, a vanished snippet is skipped.
|
|
392
406
|
*
|
|
393
|
-
* Returns the REPLACEMENT engine
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
407
|
+
* Returns the REPLACEMENT engine, on the same registry. This one hands its bags over (each is
|
|
408
|
+
* removed from the registry with its values kept, and the replacement claims them as it
|
|
409
|
+
* registers), its flows are closed, and it should be discarded. Hosts re-bind their flow handles
|
|
410
|
+
* via `next.getFlow(id)`. If the restore throws (defensive - §9.8 makes this unreachable for
|
|
411
|
+
* ordinary edits), the swap falls back to a fresh engine with each saved flow restarted from the
|
|
412
|
+
* top of the scene it was in; the shared properties carry over.
|
|
397
413
|
*/
|
|
398
414
|
hotSwap(bundle: Bundle): Engine;
|
|
399
415
|
/** Whether closed captions are currently shown (full dialogue text). */
|
|
@@ -444,6 +460,11 @@ declare class Engine {
|
|
|
444
460
|
* fetch it with `engine.getFlow(name)?.getChoices()`.
|
|
445
461
|
*/
|
|
446
462
|
runFlow(flow: string, scene: string, block?: string): AdvanceToStopResult["played"];
|
|
463
|
+
/** Content that names another engine's scope (`@story.act`) runs only where that engine is on this
|
|
464
|
+
* registry: without it every read would answer false and every write fail, so the flow is refused as
|
|
465
|
+
* it opens (or the save as it loads), before anything changes. By then a game has built all of its
|
|
466
|
+
* engines, whatever order it built them in. The same message on every runtime. */
|
|
467
|
+
private assertExternalScopes;
|
|
447
468
|
/** Resolve a scene reference (a gameId address OR an internal id) to its internal id. */
|
|
448
469
|
private resolveSceneRef;
|
|
449
470
|
/** Resolve a block reference (a scene-scoped gameId OR an internal id) to its internal id. */
|
|
@@ -523,6 +544,9 @@ declare class Engine {
|
|
|
523
544
|
* After reset, open fresh flows with `openFlow`.
|
|
524
545
|
*/
|
|
525
546
|
reset(): void;
|
|
547
|
+
/** Remove every bag this engine registered, keeping the values parked when `keep` (a live reload
|
|
548
|
+
* handing its state to a replacement), and close its flows. The engine is inert afterwards. */
|
|
549
|
+
private release;
|
|
526
550
|
/** Read a shared (`@patter` / foreign) property by ref. `@scene` refs are rejected (flow-level). */
|
|
527
551
|
getProperty(ref: string): ScalarValue | undefined;
|
|
528
552
|
/** Write a shared (`@patter` / foreign) property by ref. `@scene` refs are rejected (flow-level).
|
|
@@ -548,19 +572,33 @@ declare class Engine {
|
|
|
548
572
|
private emitEngine;
|
|
549
573
|
listProperties(): PropertyRow[];
|
|
550
574
|
private splitShared;
|
|
551
|
-
/**
|
|
575
|
+
/** The shared `@patter` values alone, as `{ patter: {...} }`.
|
|
576
|
+
* @deprecated The registry holds every property now: a game saves `registry.save()` once, and a
|
|
577
|
+
* standalone engine's `saveGame()` carries its registry's values. Removed at the next breaking release. */
|
|
552
578
|
save(): EngineSave;
|
|
553
|
-
/**
|
|
579
|
+
/** Lay a `{ patter: {...} }` section over the shared `@patter` values; anything else is ignored.
|
|
580
|
+
* @deprecated See `save`. Removed at the next breaking release. */
|
|
554
581
|
load(blob: EngineSave): void;
|
|
555
|
-
/** Snapshot the whole game
|
|
582
|
+
/** Snapshot the whole game's NON-property state: visit counts, shared selector cursors, and every
|
|
583
|
+
* live flow's cursor and PRNG. The property values are the registry's: a standalone engine (one that
|
|
584
|
+
* made its own registry) carries them here under `registry`; a game that passed a registry saves it
|
|
585
|
+
* once itself, beside each engine's `saveGame()`. */
|
|
556
586
|
saveGame(): SaveGame;
|
|
557
|
-
/**
|
|
558
|
-
|
|
587
|
+
/**
|
|
588
|
+
* Restore a `saveGame()`: visit counts, shared selector cursors, and every flow. Property values come
|
|
589
|
+
* from the registry. A save that carries them (a standalone engine's, or a version 2 save from before
|
|
590
|
+
* the registry held them) has them moved into the registry here; otherwise the game loads its
|
|
591
|
+
* registry itself, before or after this call. Either order works: this engine's bags are handed back
|
|
592
|
+
* to the registry (values kept) and the restored flows claim them as they register.
|
|
593
|
+
*/
|
|
594
|
+
loadGame(save: SaveGame | SaveGameV2): void;
|
|
559
595
|
}
|
|
560
596
|
declare class Flow {
|
|
561
597
|
readonly id: string;
|
|
562
598
|
private readonly host;
|
|
563
599
|
private local;
|
|
600
|
+
/** The registry keys this flow has registered (its globals and each scene bag). */
|
|
601
|
+
private readonly registered;
|
|
564
602
|
private rngState;
|
|
565
603
|
private started;
|
|
566
604
|
private flowEnded;
|
|
@@ -585,10 +623,14 @@ declare class Flow {
|
|
|
585
623
|
private readonly patterResolver;
|
|
586
624
|
private readonly sceneResolver;
|
|
587
625
|
private readonly evalCtx;
|
|
626
|
+
private ctxRevision;
|
|
627
|
+
private registryQualities;
|
|
588
628
|
private readonly flowLog;
|
|
589
629
|
/** Monotonic across the flow's life; survives clearLog so two reads agree on order. */
|
|
590
630
|
private flowSeq;
|
|
591
631
|
constructor(id: string, host: FlowHost, seed: number);
|
|
632
|
+
/** The eval context, its scopes refreshed if the registry's set of scopes has moved since. */
|
|
633
|
+
private context;
|
|
592
634
|
/** The stage ladder of `@scope.name` when it is a declared quality, else undefined. Names compare
|
|
593
635
|
* lowercase, as the compiler emits references (the selfBackedResolver lesson). */
|
|
594
636
|
private stagesFor;
|
|
@@ -681,7 +723,7 @@ declare class Flow {
|
|
|
681
723
|
/** The write itself. `host` says WHO is writing, which is the only thing `writable: false` cares
|
|
682
724
|
* about: the story is refused, the game is not. */
|
|
683
725
|
private writeProperty;
|
|
684
|
-
/** @internal Snapshot this flow's cursor +
|
|
726
|
+
/** @internal Snapshot this flow's cursor + PRNG + visits. Its properties are the registry's. */
|
|
685
727
|
snapshot(): FlowSnapshot;
|
|
686
728
|
/** @internal Restore this flow from a snapshot. */
|
|
687
729
|
restore(snap: FlowSnapshot): void;
|
|
@@ -793,10 +835,20 @@ declare class Flow {
|
|
|
793
835
|
* locale, else the authoring `displayName`. Undefined when the character has no display name at all
|
|
794
836
|
* (the host falls back to the `character` token itself). */
|
|
795
837
|
private resolveCharacterName;
|
|
796
|
-
/** Split a ref into scope + name. Tokens: `@scene`,
|
|
838
|
+
/** Split a ref into scope + name. Tokens: `@scene`, registered tokens, else `@patter` (incl. bare `@name`). */
|
|
797
839
|
private splitRef;
|
|
798
|
-
/**
|
|
799
|
-
private
|
|
840
|
+
/** A fresh, unregistered bag for the NOT-shared `@patter` globals (the shared ones live on the host). */
|
|
841
|
+
private newLocal;
|
|
842
|
+
/** Register a fresh globals bag under this flow's key; it claims any values waiting there. */
|
|
843
|
+
private mountLocal;
|
|
844
|
+
/** @internal Remove every bag this flow registered; with `keep`, their values wait in the registry for
|
|
845
|
+
* the flow that replaces this one. Engine-driven (close, loadGame, hotSwap). */
|
|
846
|
+
releaseBags(keep: boolean): void;
|
|
847
|
+
/** The bag a `@scene` property of scene `s` lives in (stage or this flow's), made if missing. */
|
|
848
|
+
private sceneBagFor;
|
|
849
|
+
/** Make (and register) scene `s`'s stage bag and this flow's bag for it, if not made yet. A bag made
|
|
850
|
+
* here claims whatever values the registry holds for its key: that is how a loaded save reaches it. */
|
|
851
|
+
private ensureSceneBags;
|
|
800
852
|
/**
|
|
801
853
|
* Seed a scene's `@scene` props (spec §7). The not-shared props seed THIS flow's
|
|
802
854
|
* bag the first time it enters (persist across re-entries thereafter); the shared
|