@moku-labs/game 0.13.2 → 0.13.3

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 (34) hide show
  1. package/dist/app/page.d.mts +1 -1
  2. package/dist/app/system.d.mts +3 -3
  3. package/dist/app.d.mts +2 -2
  4. package/dist/app.mjs +1 -1
  5. package/dist/assets.d.mts +1 -1
  6. package/dist/{capture-fpd83Mi5.mjs → capture-D7XvoHdH.mjs} +78 -1
  7. package/dist/{commands-BrgeMP5y.d.mts → commands-DRhJ_LIH.d.mts} +5 -5
  8. package/dist/control.d.mts +4 -4
  9. package/dist/control.mjs +1 -1
  10. package/dist/{define-ZmWbWxon.d.mts → define-Ckp70_GR.d.mts} +2 -2
  11. package/dist/{headless-BsNdJs9W.mjs → headless-BA6ffzqD.mjs} +30 -9
  12. package/dist/{headless-Dgxvp6Ym.d.mts → headless-CYgYzro0.d.mts} +1 -1
  13. package/dist/{index-CdbE_jGs.d.mts → index-CjuObHhF.d.mts} +4 -4
  14. package/dist/index.d.mts +5 -5
  15. package/dist/index.mjs +1 -1
  16. package/dist/inspect.d.mts +7 -7
  17. package/dist/jsx-dev-runtime.d.mts +1 -1
  18. package/dist/jsx-runtime.d.mts +1 -1
  19. package/dist/{memory-DJ2sPExv.d.mts → memory-DKo9rRWW.d.mts} +1 -1
  20. package/dist/{run-wYty_Lwo.mjs → run-BtyrJjmW.mjs} +130 -40
  21. package/dist/{runtime-6qakboTm.d.mts → runtime-iTxTcukZ.d.mts} +1 -1
  22. package/dist/{src-CltFFKtc.mjs → src-DlyYl_9X.mjs} +412 -122
  23. package/dist/testing.d.mts +4 -4
  24. package/dist/testing.mjs +2 -2
  25. package/dist/{types-C6y8EfEB.d.mts → types-BSMmnpFm.d.mts} +84 -24
  26. package/dist/{types-zRGJdFGX.d.mts → types-B_Bp2tWK.d.mts} +2 -2
  27. package/dist/{types-D57SntUt.d.mts → types-Bonifz5M.d.mts} +2 -2
  28. package/dist/{types-DGIkfZB7.d.mts → types-DkO3s9YX.d.mts} +4 -4
  29. package/dist/{types-CmuwAjkV.d.mts → types-Dm5Oh5bH.d.mts} +1 -1
  30. package/dist/{types-B3T2X6To.d.mts → types-dJMOXXL3.d.mts} +15 -11
  31. package/dist/visual.d.mts +6 -6
  32. package/dist/visual.mjs +1 -1
  33. package/llms.txt +4 -3
  34. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { m as StartedPage, r as GameConfig, t as AnyGameApp, u as PageOptions } from "../types-DGIkfZB7.mjs";
1
+ import { m as StartedPage, r as GameConfig, t as AnyGameApp, u as PageOptions } from "../types-DkO3s9YX.mjs";
2
2
 
3
3
  //#region src/app/page.d.ts
4
4
  /**
@@ -1,6 +1,6 @@
1
- import { tn as PlayerStateProvider } from "../types-C6y8EfEB.mjs";
2
- import { ct as PlatformProvider } from "../index-CdbE_jGs.mjs";
3
- import { _ as SystemShellFactory, g as SystemName, h as SystemModules } from "../types-DGIkfZB7.mjs";
1
+ import { tn as PlayerStateProvider } from "../types-BSMmnpFm.mjs";
2
+ import { ct as PlatformProvider } from "../index-CjuObHhF.mjs";
3
+ import { _ as SystemShellFactory, g as SystemName, h as SystemModules } from "../types-DkO3s9YX.mjs";
4
4
  import { Back, Haptics, KeepAwake, Lifecycle, Store } from "@moku-labs/system";
5
5
 
6
6
  //#region src/app/system.d.ts
package/dist/app.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { Xt as Json } from "./types-C6y8EfEB.mjs";
2
- import { a as GameHandle, c as MemoryProvider, d as SaveKind, f as Scenario, g as SystemName, i as GameDefinition, l as PageAgent, n as GameApp, o as GamePluginConfigs, p as ScreenSeams, r as GameConfig, s as HeadlessSeams } from "./types-DGIkfZB7.mjs";
1
+ import { Xt as Json } from "./types-BSMmnpFm.mjs";
2
+ import { a as GameHandle, c as MemoryProvider, d as SaveKind, f as Scenario, g as SystemName, i as GameDefinition, l as PageAgent, n as GameApp, o as GamePluginConfigs, p as ScreenSeams, r as GameConfig, s as HeadlessSeams } from "./types-DkO3s9YX.mjs";
3
3
  import { AnyPluginInstance } from "@moku-labs/core";
4
4
 
5
5
  //#region src/app/define.d.ts
package/dist/app.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { Ct as effectsPlugin, H as platformPlugin, Nt as audioPlugin, i as screen, t as createApp } from "./src-CltFFKtc.mjs";
1
+ import { Ct as effectsPlugin, H as platformPlugin, Nt as audioPlugin, i as screen, t as createApp } from "./src-DlyYl_9X.mjs";
2
2
  import { t as memory } from "./memory-CWlqhS7l.mjs";
3
3
  import { t as fakeClock } from "./fake-MpzwZhIZ.mjs";
4
4
  //#region src/app/define.ts
package/dist/assets.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { u as Manifest } from "./types-C6y8EfEB.mjs";
1
+ import { u as Manifest } from "./types-BSMmnpFm.mjs";
2
2
 
3
3
  //#region src/plugins/assets/scan/cli.d.ts
4
4
  /**
@@ -197,6 +197,24 @@ function findNode(main, path, contributionsOf = noContributions) {
197
197
  }
198
198
  }
199
199
  /**
200
+ * Tells whether an entry of a flow is a rest checkpoint: a rest node that carries the checkpoint
201
+ * flag, a place a save may stand on. A sub-flow and a slot are no nodes. A transit node is never
202
+ * one, whatever its flag says: it is a place inside a transition.
203
+ *
204
+ * @param entry - A node, a sub-flow or a slot of a flow.
205
+ * @returns True for a node with both `rest` and `checkpoint`.
206
+ * @example
207
+ * ```ts
208
+ * // `home` rests and is a checkpoint. `boot` is a transit node that carries the flag too.
209
+ * isRestCheckpoint(home); // true
210
+ * isRestCheckpoint(boot); // false
211
+ * isRestCheckpoint(boardFlow); // false: a sub-flow is no node
212
+ * ```
213
+ */
214
+ function isRestCheckpoint(entry) {
215
+ return entry.kind === "node" && entry.rest && entry.checkpoint;
216
+ }
217
+ /**
200
218
  * Renders an edge target as a string: a node name, `"exit:win"` or `"map:node"`.
201
219
  *
202
220
  * @param target - The target as the edge table holds it.
@@ -336,6 +354,65 @@ function describeGraph(flows, features) {
336
354
  };
337
355
  }
338
356
  /**
357
+ * Reads one node of a described flow by name. Own keys only: `nodes.constructor` is defined on
358
+ * every object.
359
+ *
360
+ * @param flow - The described flow, or `undefined` when the graph does not hold it.
361
+ * @param name - Name of the node.
362
+ * @returns The described node, or `undefined` when the flow has none of that name.
363
+ * @example
364
+ * ```ts
365
+ * ownNode({ nodes: {}, start: "home", edges: {} }, "constructor"); // undefined
366
+ * ```
367
+ */
368
+ function ownNode(flow, name) {
369
+ return flow !== void 0 && Object.hasOwn(flow.nodes, name) ? flow.nodes[name] : void 0;
370
+ }
371
+ /**
372
+ * Picks the described flow a path continues in after one node: the sub-flow it enters, or, behind
373
+ * a slot, the first contribution in order that has the next segment as a node. The same choice
374
+ * `findNode` makes on the flows themselves.
375
+ *
376
+ * @param graph - Result of `describeGraph`.
377
+ * @param node - The described node the path just passed.
378
+ * @param next - The next segment of the path.
379
+ * @returns The flow to go on in, or `undefined` when the path ends here.
380
+ * @example
381
+ * ```ts
382
+ * // In a graph whose main flow uses the sub-flow "board" as its node "board":
383
+ * describedFlowBehind(graph, graph.flows.main.nodes.board, "awaitIntent")?.start; // "awaitIntent"
384
+ * ```
385
+ */
386
+ function describedFlowBehind(graph, node, next) {
387
+ if (node.subFlow !== void 0) return graph.flows[node.subFlow];
388
+ if (node.slot === void 0) return void 0;
389
+ return (graph.slots[node.slot] ?? []).map((contribution) => graph.flows[contribution.flow]).find((flow) => ownNode(flow, next) !== void 0);
390
+ }
391
+ /**
392
+ * Finds the node a path names in a described graph, the way `findNode` finds it in the flows: one
393
+ * sub-flow per segment, and through a slot into the contribution that has the next segment. For a
394
+ * caller that holds only `flow.describe()`, such as a headless helper.
395
+ *
396
+ * @param graph - Result of `describeGraph`.
397
+ * @param path - A path as `framePath` renders it.
398
+ * @returns The described node, sub-flow or slot, or `undefined` when the path names nothing.
399
+ * @example
400
+ * ```ts
401
+ * describedNode(app.flow.describe(), "board/awaitIntent")?.rest; // true: a rest node
402
+ * describedNode(app.flow.describe(), "board")?.subFlow; // "board": a sub-flow, no rest node
403
+ * ```
404
+ */
405
+ function describedNode(graph, path) {
406
+ const names = path.split("/").filter(Boolean);
407
+ let flow = graph.flows[graph.main];
408
+ for (const [step, name] of names.entries()) {
409
+ const node = ownNode(flow, name);
410
+ const next = names[step + 1];
411
+ if (node === void 0 || next === void 0) return node;
412
+ flow = describedFlowBehind(graph, node, next);
413
+ }
414
+ }
415
+ /**
339
416
  * Compares two object keys without a locale, so the rendering is the same everywhere.
340
417
  *
341
418
  * @param first - First key.
@@ -1151,4 +1228,4 @@ async function captureFrame(mctx, options) {
1151
1228
  return shot === void 0 ? void 0 : answerOf(mctx, shot, options.against);
1152
1229
  }
1153
1230
  //#endregion
1154
- export { sheetAlone as a, findNode as c, slotNames as d, compact as f, servePaused as i, framePath as l, captureFrame as n, collectFlows as o, pushEntry as p, serveCaptures as r, describeGraph as s, cancelCaptures as t, graphHash as u };
1231
+ export { sheetAlone as a, describedNode as c, graphHash as d, isRestCheckpoint as f, pushEntry as h, servePaused as i, findNode as l, compact as m, captureFrame as n, collectFlows as o, slotNames as p, serveCaptures as r, describeGraph as s, cancelCaptures as t, framePath as u };
@@ -1,8 +1,8 @@
1
- import { A as Api$2, E as DebugSwitches, Ot as Bookmark, h as Api$1, jt as FlowState, ln as Api, vn as Time, w as Captured } from "./types-C6y8EfEB.mjs";
2
- import { a as AudioApi, r as UiApi, v as ScenesApi, x as AnimApi } from "./types-B3T2X6To.mjs";
3
- import { A as InputApi } from "./types-CmuwAjkV.mjs";
4
- import { t as HeadlessApp } from "./headless-Dgxvp6Ym.mjs";
5
- import { n as Command, r as ControlApp } from "./types-D57SntUt.mjs";
1
+ import { A as Api$2, E as DebugSwitches, Ot as Bookmark, h as Api$1, jt as FlowState, ln as Api, vn as Time, w as Captured } from "./types-BSMmnpFm.mjs";
2
+ import { a as AudioApi, r as UiApi, v as ScenesApi, x as AnimApi } from "./types-dJMOXXL3.mjs";
3
+ import { A as InputApi } from "./types-Dm5Oh5bH.mjs";
4
+ import { t as HeadlessApp } from "./headless-CYgYzro0.mjs";
5
+ import { n as Command, r as ControlApp } from "./types-Bonifz5M.mjs";
6
6
 
7
7
  //#region src/plugins/flow/doors/commands.d.ts
8
8
  /**
@@ -1,7 +1,7 @@
1
- import { t as HeadlessApp } from "./headless-Dgxvp6Ym.mjs";
2
- import { i as InputArguments, n as Command, o as InputSchema, s as Ran } from "./types-D57SntUt.mjs";
3
- import { t as commands } from "./commands-BrgeMP5y.mjs";
4
- import { t as defineCommand } from "./define-ZmWbWxon.mjs";
1
+ import { t as HeadlessApp } from "./headless-CYgYzro0.mjs";
2
+ import { i as InputArguments, n as Command, o as InputSchema, s as Ran } from "./types-Bonifz5M.mjs";
3
+ import { t as commands } from "./commands-DRhJ_LIH.mjs";
4
+ import { t as defineCommand } from "./define-Ckp70_GR.mjs";
5
5
 
6
6
  //#region src/plugins/flow/doors/dev.d.ts
7
7
  /**
package/dist/control.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  import { t as controlRefused } from "./dev-Cc50Dk7H.mjs";
2
2
  import { s as defineCommand } from "./session-DgukhR_7.mjs";
3
- import { n as commands, t as run } from "./run-wYty_Lwo.mjs";
3
+ import { n as commands, t as run } from "./run-BtyrJjmW.mjs";
4
4
  export { commands, controlRefused, defineCommand, run };
@@ -1,5 +1,5 @@
1
- import { t as HeadlessApp } from "./headless-Dgxvp6Ym.mjs";
2
- import { c as Source, n as Command, o as InputSchema } from "./types-D57SntUt.mjs";
1
+ import { t as HeadlessApp } from "./headless-CYgYzro0.mjs";
2
+ import { c as Source, n as Command, o as InputSchema } from "./types-Bonifz5M.mjs";
3
3
 
4
4
  //#region src/plugins/flow/doors/define.d.ts
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { u as graphHash } from "./capture-fpd83Mi5.mjs";
1
+ import { c as describedNode, d as graphHash } from "./capture-D7XvoHdH.mjs";
2
2
  //#region src/plugins/flow/headless.ts
3
3
  const noPayload = null;
4
4
  /** Seed of a repro that pins no rng state, the seed `saveOf` writes. */
@@ -91,29 +91,50 @@ async function createHeadless(app) {
91
91
  };
92
92
  }
93
93
  /**
94
- * Reads the rest node a repro starts at: its checkpoint, or the start of the main flow.
94
+ * Names a checkpoint of a described graph, for the message of a refused repro: the first rest
95
+ * node that is one, or the start of the main flow when the graph has none.
96
+ *
97
+ * @param graph - The described graph.
98
+ * @returns The path of a checkpoint to suggest.
99
+ * @example
100
+ * ```ts
101
+ * someCheckpoint({ main: "main", flows: {}, slots: {} }); // "": an empty graph suggests nothing
102
+ * ```
103
+ */
104
+ function someCheckpoint(graph) {
105
+ for (const [id, flow] of Object.entries(graph.flows)) for (const [name, node] of Object.entries(flow.nodes)) if (node.rest && node.checkpoint) return id === graph.main ? name : `${id}/${name}`;
106
+ return graph.flows[graph.main]?.start ?? "";
107
+ }
108
+ /**
109
+ * Reads the rest node a repro starts at: its checkpoint, or the start of the main flow. A repro
110
+ * starts at a rest node only. `flow.restore` also enters a transit node while the graph is
111
+ * unchanged, and a repro carries the hash of the graph that runs now, so the path is checked here.
95
112
  *
96
113
  * @param app - The started app.
97
114
  * @param repro - Starting state, optional checkpoint and the route.
98
115
  * @returns The path of the node the repro enters.
99
- * @throws {Error} When the graph has no main flow to start from.
116
+ * @throws {Error} When the graph has no main flow to start from, and when the path names a node
117
+ * that is not a rest node.
100
118
  */
101
119
  function reproPath(app, repro) {
102
- if (repro.checkpoint !== void 0) return repro.checkpoint;
103
120
  const graph = app.flow.describe();
104
- const start = graph.flows[graph.main]?.start;
105
- if (start === void 0) throw new Error(`[game] runRepro() found no flow "${graph.main}" to start from.\n Name the checkpoint the repro was taken at.`);
106
- return start;
121
+ const path = repro.checkpoint ?? graph.flows[graph.main]?.start;
122
+ if (path === void 0) throw new Error(`[game] runRepro() found no flow "${graph.main}" to start from.\n Name the checkpoint the repro was taken at.`);
123
+ const node = describedNode(graph, path);
124
+ if (node !== void 0 && !node.rest) throw new Error(`[game] The bookmark "${path}" is not a rest node of the graph.\n Restore a rest node, for example the checkpoint "${someCheckpoint(graph)}".`);
125
+ return path;
107
126
  }
108
127
  /**
109
128
  * Builds the bookmark a repro is entered with: its state, its checkpoint and the hash of the
110
129
  * graph that runs now, so a checkpoint is accepted and any other rest node is checked. The route
111
- * is not part of it: the caller walks it after the restore.
130
+ * is not part of it: the caller walks it after the restore. A repro starts at a rest node: a
131
+ * checkpoint that names a transit node is refused here, although `flow.restore` enters one.
112
132
  *
113
133
  * @param app - The started app.
114
134
  * @param repro - Starting state, optional checkpoint and the route.
115
135
  * @returns The bookmark to restore.
116
- * @throws {Error} When the repro names no checkpoint and the graph has no main flow.
136
+ * @throws {Error} When the repro names no checkpoint and the graph has no main flow, and when
137
+ * the node it starts at is not a rest node.
117
138
  * @example
118
139
  * ```ts
119
140
  * // The game.restore command loads a bug report taken at the "home" checkpoint.
@@ -1,4 +1,4 @@
1
- import { Bt as Answer, Mt as JournalEntry, Pt as RouteStep, Xt as Json, cn as RngState, dt as Api$1, hn as Api, jt as FlowState } from "./types-C6y8EfEB.mjs";
1
+ import { Bt as Answer, Mt as JournalEntry, Pt as RouteStep, Xt as Json, cn as RngState, dt as Api$1, hn as Api, jt as FlowState } from "./types-BSMmnpFm.mjs";
2
2
 
3
3
  //#region src/plugins/flow/headless.d.ts
4
4
  /**
@@ -1,7 +1,7 @@
1
- import { $ as DescriptionNode, A as Api$6, B as ComponentType, Et as FeatureDescription, Ft as SceneIdOf, G as Mut, Gt as State$2, J as QueryTerm, Jt as Config$5, K as Narrowed, Lt as Descriptor, N as State$8, Qt as State$5, R as ComponentHandle, Rt as GuideOptions, Sn as Require, Ut as Config$2, V as ComponentValue, Vt as Api$1, X as SystemDefinition, Xt as Json, Y as ResourceType, Z as TagType, Zt as Root, _n as State$7, a as Config$1, at as NumericFields, bn as Config$9, c as LoadBundles, d as State$1, dn as Events, dt as Api$2, en as Patch, et as Ease, f as Tier, fn as PauseReason, ft as BundlesOf, g as Config$6, gn as Config$7, gt as GameTypes, h as Api$4, hn as Api$5, ht as FeaturePlugin, i as BundleSpec, j as Config$8, k as ViewportSize, kt as DefineNode, l as LoadReason, ln as Api$3, mt as EmitterIdOf, o as DefineBundles, on as StoreApi, ot as ProjectionMotion, pn as State$4, pt as Config$3, r as BundleMap, sn as RngApi, st as ProjectionSpec, t as Api, un as Config$4, vt as State$3, x as State$6, xn as Events$1, xt as defineFlow, yt as TextStylesOf, zt as Hint } from "./types-C6y8EfEB.mjs";
2
- import { A as SfxDescriptor, C as Config$10, D as Target, E as State$9, N as defineAnimation, S as AnimPlayerValue, T as MotionKeyframe, _ as SceneSpec, a as AudioApi, c as MusicDescriptor, d as State$10, g as SceneDefinition, h as LayerMap, j as Step, k as HapticKind, l as MusicOptions, m as DefineScene, n as State$12, p as AnySceneProjection, r as UiApi, s as Config$11, t as Config$12, v as ScenesApi, w as FramesValue, x as AnimApi, y as State$11, z as play } from "./types-B3T2X6To.mjs";
3
- import { _ as NoiseValue, c as EmitterValue, d as ColorMatrixValue, f as DisplacementValue, g as GlowValue, h as FilterValueOf, i as State$13, l as AlphaValue, m as FilterSpec, n as EffectsApi, o as EmitterConfig, p as FilterComponent, s as EmitterDefinition, t as Config$13, u as BlurValue, v as OutlineValue, y as UniformDeclaration } from "./types-zRGJdFGX.mjs";
4
- import { A as InputApi, B as SpriteOptions, E as TextValue, F as NineSliceValue, G as Argument, J as IntlKit, K as Config$14, O as defineComponent, Q as TypedTr, R as ShapeValue, S as TextBind, T as TextStyles, U as TransformValue, V as SpriteValue, W as sprite, X as Part, Y as Message, Z as State$14, _ as Config$16, b as State$16, et as IsFlags, f as defineTokens, g as BindOptions, h as BindField, it as WhenFlags, j as State$15, k as Config$15, nt as Style, p as IntrinsicElementsFor, q as I18nApi, s as PopupComponent, tt as ResolvedStyle, v as CountdownValue, w as TextStyleInput, x as TextApi, y as Point } from "./types-CmuwAjkV.mjs";
1
+ import { $ as DescriptionNode, A as Api$6, B as ComponentType, Et as FeatureDescription, Ft as SceneIdOf, G as Mut, Gt as State$2, J as QueryTerm, Jt as Config$5, K as Narrowed, Lt as Descriptor, N as State$8, Qt as State$5, R as ComponentHandle, Rt as GuideOptions, Sn as Require, Ut as Config$2, V as ComponentValue, Vt as Api$1, X as SystemDefinition, Xt as Json, Y as ResourceType, Z as TagType, Zt as Root, _n as State$7, a as Config$1, at as NumericFields, bn as Config$9, c as LoadBundles, d as State$1, dn as Events, dt as Api$2, en as Patch, et as Ease, f as Tier, fn as PauseReason, ft as BundlesOf, g as Config$6, gn as Config$7, gt as GameTypes, h as Api$4, hn as Api$5, ht as FeaturePlugin, i as BundleSpec, j as Config$8, k as ViewportSize, kt as DefineNode, l as LoadReason, ln as Api$3, mt as EmitterIdOf, o as DefineBundles, on as StoreApi, ot as ProjectionMotion, pn as State$4, pt as Config$3, r as BundleMap, sn as RngApi, st as ProjectionSpec, t as Api, un as Config$4, vt as State$3, x as State$6, xn as Events$1, xt as defineFlow, yt as TextStylesOf, zt as Hint } from "./types-BSMmnpFm.mjs";
2
+ import { A as SfxDescriptor, C as Config$10, D as Target, E as State$9, N as defineAnimation, S as AnimPlayerValue, T as MotionKeyframe, _ as SceneSpec, a as AudioApi, c as MusicDescriptor, d as State$10, g as SceneDefinition, h as LayerMap, j as Step, k as HapticKind, l as MusicOptions, m as DefineScene, n as State$12, p as AnySceneProjection, r as UiApi, s as Config$11, t as Config$12, v as ScenesApi, w as FramesValue, x as AnimApi, y as State$11, z as play } from "./types-dJMOXXL3.mjs";
3
+ import { _ as NoiseValue, c as EmitterValue, d as ColorMatrixValue, f as DisplacementValue, g as GlowValue, h as FilterValueOf, i as State$13, l as AlphaValue, m as FilterSpec, n as EffectsApi, o as EmitterConfig, p as FilterComponent, s as EmitterDefinition, t as Config$13, u as BlurValue, v as OutlineValue, y as UniformDeclaration } from "./types-B_Bp2tWK.mjs";
4
+ import { A as InputApi, B as SpriteOptions, E as TextValue, F as NineSliceValue, G as Argument, J as IntlKit, K as Config$14, O as defineComponent, Q as TypedTr, R as ShapeValue, S as TextBind, T as TextStyles, U as TransformValue, V as SpriteValue, W as sprite, X as Part, Y as Message, Z as State$14, _ as Config$16, b as State$16, et as IsFlags, f as defineTokens, g as BindOptions, h as BindField, it as WhenFlags, j as State$15, k as Config$15, nt as Style, p as IntrinsicElementsFor, q as I18nApi, s as PopupComponent, tt as ResolvedStyle, v as CountdownValue, w as TextStyleInput, x as TextApi, y as Point } from "./types-Dm5Oh5bH.mjs";
5
5
  import { Log } from "@moku-labs/common/browser";
6
6
  import { PluginCtx } from "@moku-labs/core";
7
7
 
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { $ as DescriptionNode, $t as types_d_exports$9, C as types_d_exports$11, Ct as slot, Kt as types_d_exports$3, P as types_d_exports$16, St as exit, Tt as type, bt as types_d_exports$5, in as SaveUnreadableError, m as types_d_exports$1, mn as types_d_exports$8, wt as to, yn as types_d_exports$14 } from "./types-C6y8EfEB.mjs";
2
- import { B as sequence, F as frames, G as stagger, H as sfx, I as haptic, J as wait, K as tween, L as mark, M as HAPTIC_KINDS, N as defineAnimation, O as types_d_exports, P as external, R as parallel, U as spawn, V as set, W as spawned, b as types_d_exports$12, f as types_d_exports$2, i as types_d_exports$15, k as HapticKind, q as use, z as play } from "./types-B3T2X6To.mjs";
3
- import { a as types_d_exports$4 } from "./types-zRGJdFGX.mjs";
4
- import { $ as types_d_exports$6, C as TextFormat, D as types_d_exports$13, H as Transform, I as Parent, L as Shape, M as types_d_exports$7, N as Display, O as defineComponent, P as NineSlice, W as sprite, d as popup, f as defineTokens, g as BindOptions, l as Box, u as LocalWrite, v as CountdownValue, z as Sprite } from "./types-CmuwAjkV.mjs";
5
- import { $ as defineFeature, A as Held, B as Traced, C as Animation, Ct as bind, D as load, E as defineBundles, F as Pressed, G as component, H as Layer, I as Swipeable, J as system, K as mut, L as Tappable, M as Pointer, N as PointerOver, O as Draggable, P as Pressable, Q as schedule, R as Touchable, S as AnimPlayer, St as Text, T as defineScene, Tt as label, U as Order, V as Exiting, W as Tree, X as guide, Y as tag, Z as hint, _ as defineStyle, _t as audioPlugin, a as defineEmitter, at as rendererPlugin, b as messageDuration, bt as projection, c as Alpha, ct as PlatformProvider, d as Displacement, dt as lifecyclePlugin, et as worldPlugin, f as Glow, ft as inputPlugin, g as resolve, gt as clockPlugin, h as music, ht as effectsPlugin, i as screen, it as scenesPlugin, j as Hovered, k as DropTarget, l as Blur, lt as types_d_exports$10, m as Outline, mt as flowPlugin, n as createPlugin, nt as timePlugin, o as Emitter, ot as platformPlugin, p as Noise, pt as i18nPlugin, q as resource, r as defineGame, rt as textPlugin, s as defineFilter, st as BackResult, t as createApp, tt as uiPlugin, u as ColorMatrix, ut as modelPlugin, v as tr, vt as assetsPlugin, w as Frames, wt as defineTextStyles, x as defineMotion, xt as Countdown, y as messageArgument, yt as animPlugin, z as Traceable } from "./index-CdbE_jGs.mjs";
1
+ import { $ as DescriptionNode, $t as types_d_exports$9, C as types_d_exports$11, Ct as slot, Kt as types_d_exports$3, P as types_d_exports$16, St as exit, Tt as type, bt as types_d_exports$5, in as SaveUnreadableError, m as types_d_exports$1, mn as types_d_exports$8, wt as to, yn as types_d_exports$14 } from "./types-BSMmnpFm.mjs";
2
+ import { B as sequence, F as frames, G as stagger, H as sfx, I as haptic, J as wait, K as tween, L as mark, M as HAPTIC_KINDS, N as defineAnimation, O as types_d_exports, P as external, R as parallel, U as spawn, V as set, W as spawned, b as types_d_exports$12, f as types_d_exports$2, i as types_d_exports$15, k as HapticKind, q as use, z as play } from "./types-dJMOXXL3.mjs";
3
+ import { a as types_d_exports$4 } from "./types-B_Bp2tWK.mjs";
4
+ import { $ as types_d_exports$6, C as TextFormat, D as types_d_exports$13, H as Transform, I as Parent, L as Shape, M as types_d_exports$7, N as Display, O as defineComponent, P as NineSlice, W as sprite, d as popup, f as defineTokens, g as BindOptions, l as Box, u as LocalWrite, v as CountdownValue, z as Sprite } from "./types-Dm5Oh5bH.mjs";
5
+ import { $ as defineFeature, A as Held, B as Traced, C as Animation, Ct as bind, D as load, E as defineBundles, F as Pressed, G as component, H as Layer, I as Swipeable, J as system, K as mut, L as Tappable, M as Pointer, N as PointerOver, O as Draggable, P as Pressable, Q as schedule, R as Touchable, S as AnimPlayer, St as Text, T as defineScene, Tt as label, U as Order, V as Exiting, W as Tree, X as guide, Y as tag, Z as hint, _ as defineStyle, _t as audioPlugin, a as defineEmitter, at as rendererPlugin, b as messageDuration, bt as projection, c as Alpha, ct as PlatformProvider, d as Displacement, dt as lifecyclePlugin, et as worldPlugin, f as Glow, ft as inputPlugin, g as resolve, gt as clockPlugin, h as music, ht as effectsPlugin, i as screen, it as scenesPlugin, j as Hovered, k as DropTarget, l as Blur, lt as types_d_exports$10, m as Outline, mt as flowPlugin, n as createPlugin, nt as timePlugin, o as Emitter, ot as platformPlugin, p as Noise, pt as i18nPlugin, q as resource, r as defineGame, rt as textPlugin, s as defineFilter, st as BackResult, t as createApp, tt as uiPlugin, u as ColorMatrix, ut as modelPlugin, v as tr, vt as assetsPlugin, w as Frames, wt as defineTextStyles, x as defineMotion, xt as Countdown, y as messageArgument, yt as animPlugin, z as Traceable } from "./index-CjuObHhF.mjs";
6
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, messageArgument, messageDuration, 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 };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as sfx, A as types_exports$3, At as Noise, B as defineStyle, Bt as rendererPlugin, C as types_exports$10, Ct as effectsPlugin, D as types_exports$6, Dt as ColorMatrix, E as types_exports$7, Et as Blur, F as resolve, Ft as assetsPlugin, G as external, Gt as to, H as platformPlugin, Ht as flowPlugin, I as Box, It as animPlugin, J as mark, Jt as SaveUnreadableError, K as frames, Kt as type, L as LocalWrite, Lt as AnimPlayer, M as types_exports$1, Mt as defineFilter, N as types_exports, Nt as audioPlugin, O as types_exports$5, Ot as Displacement, P as uiPlugin, Pt as scenesPlugin, Q as set, R as popup, Rt as Animation, S as types_exports$11, St as messageDuration, T as types_exports$8, Tt as Alpha, U as HAPTIC_KINDS, Ut as exit, V as textPlugin, Vt as worldPlugin, W as defineAnimation, Wt as slot, X as play, Xt as timePlugin, Y as parallel, Yt as lifecyclePlugin, Z as sequence, Zt as clockPlugin, _ as types_exports$16, _t as Touchable, a as defineMotion, at as wait, b as types_exports$13, bt as i18nPlugin, c as schedule, ct as DropTarget, d as tr, dt as Pointer, et as spawn, f as defineFeature, ft as PointerOver, g as load, gt as Tappable, h as defineBundles, ht as Swipeable, i as screen, it as use, j as types_exports$2, jt as Outline, k as types_exports$4, kt as Glow, l as projection, lt as Held, m as music, mt as Pressed, n as createPlugin, nt as stagger, o as guide, ot as inputPlugin, p as defineEmitter, pt as Pressable, q as haptic, qt as modelPlugin, r as defineGame, rt as tween, s as hint, st as Draggable, t as createApp, tt as spawned, u as defineScene, ut as Hovered, v as types_exports$15, vt as Traceable, w as types_exports$9, wt as Emitter, x as types_exports$12, xt as messageArgument, y as types_exports$14, yt as Traced, z as defineTokens, zt as Frames } from "./src-CltFFKtc.mjs";
1
+ import { $ as sfx, A as types_exports$3, At as Noise, B as defineStyle, Bt as rendererPlugin, C as types_exports$10, Ct as effectsPlugin, D as types_exports$6, Dt as ColorMatrix, E as types_exports$7, Et as Blur, F as resolve, Ft as assetsPlugin, G as external, Gt as to, H as platformPlugin, Ht as flowPlugin, I as Box, It as animPlugin, J as mark, Jt as SaveUnreadableError, K as frames, Kt as type, L as LocalWrite, Lt as AnimPlayer, M as types_exports$1, Mt as defineFilter, N as types_exports, Nt as audioPlugin, O as types_exports$5, Ot as Displacement, P as uiPlugin, Pt as scenesPlugin, Q as set, R as popup, Rt as Animation, S as types_exports$11, St as messageDuration, T as types_exports$8, Tt as Alpha, U as HAPTIC_KINDS, Ut as exit, V as textPlugin, Vt as worldPlugin, W as defineAnimation, Wt as slot, X as play, Xt as timePlugin, Y as parallel, Yt as lifecyclePlugin, Z as sequence, Zt as clockPlugin, _ as types_exports$16, _t as Touchable, a as defineMotion, at as wait, b as types_exports$13, bt as i18nPlugin, c as schedule, ct as DropTarget, d as tr, dt as Pointer, et as spawn, f as defineFeature, ft as PointerOver, g as load, gt as Tappable, h as defineBundles, ht as Swipeable, i as screen, it as use, j as types_exports$2, jt as Outline, k as types_exports$4, kt as Glow, l as projection, lt as Held, m as music, mt as Pressed, n as createPlugin, nt as stagger, o as guide, ot as inputPlugin, p as defineEmitter, pt as Pressable, q as haptic, qt as modelPlugin, r as defineGame, rt as tween, s as hint, st as Draggable, t as createApp, tt as spawned, u as defineScene, ut as Hovered, v as types_exports$15, vt as Traceable, w as types_exports$9, wt as Emitter, x as types_exports$12, xt as messageArgument, y as types_exports$14, yt as Traced, z as defineTokens, zt as Frames } from "./src-DlyYl_9X.mjs";
2
2
  import { A as system, C as Exiting, D as component, E as Tree, O as mut, S as sprite, T as Order, _ as Parent, b as Transform, c as Text, d as defineTextStyles, f as label, g as NineSlice, h as Display, j as tag, k as resource, l as bind, s as Countdown, v as Shape, w as Layer, y as Sprite } from "./visual-dMW8iqAE.mjs";
3
3
  import { r as defineComponent } from "./flatten-BkXuscAV.mjs";
4
4
  export { Alpha, types_exports as Anim, AnimPlayer, Animation, types_exports$1 as Assets, types_exports$2 as Audio, Blur, Box, types_exports$3 as Clock, ColorMatrix, Countdown, Displacement, Display, Draggable, DropTarget, types_exports$4 as Effects, Emitter, Exiting, types_exports$5 as Flow, Frames, Glow, HAPTIC_KINDS, Held, Hovered, types_exports$6 as I18n, types_exports$7 as Input, Layer, types_exports$8 as Lifecycle, LocalWrite, types_exports$9 as Model, NineSlice, Noise, Order, Outline, Parent, types_exports$10 as Platform, Pointer, PointerOver, Pressable, Pressed, types_exports$11 as Renderer, SaveUnreadableError, types_exports$12 as Scenes, Shape, Sprite, Swipeable, Tappable, Text, types_exports$13 as TextTypes, types_exports$14 as Time, Touchable, Traceable, Traced, Transform, Tree, types_exports$15 as Ui, types_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, messageArgument, messageDuration, 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,10 +1,10 @@
1
- import { A as Api$1, At as FlowGraph, M as Explained, Mt as JournalEntry, S as Under, T as RenderStats, U as EntitySnapshot, W as FrameDiff, _t as Position, an as Snapshot, h as Api$2, p as Usage, qt as Api, t as Api$3, z as ComponentSchema } from "./types-C6y8EfEB.mjs";
2
- import { a as AudioApi, r as UiApi, u as SoundEntry } from "./types-B3T2X6To.mjs";
3
- import { n as EffectsApi, r as EffectsStats } from "./types-zRGJdFGX.mjs";
4
- import { c as UiNode } from "./types-CmuwAjkV.mjs";
5
- import { t as HeadlessApp } from "./headless-Dgxvp6Ym.mjs";
6
- import { a as InputOf, c as Source, i as InputArguments, l as WatchApp, o as InputSchema, t as CheatEntry, u as WatchInput } from "./types-D57SntUt.mjs";
7
- import { n as defineSource } from "./define-ZmWbWxon.mjs";
1
+ import { A as Api$1, At as FlowGraph, M as Explained, Mt as JournalEntry, S as Under, T as RenderStats, U as EntitySnapshot, W as FrameDiff, _t as Position, an as Snapshot, h as Api$2, p as Usage, qt as Api, t as Api$3, z as ComponentSchema } from "./types-BSMmnpFm.mjs";
2
+ import { a as AudioApi, r as UiApi, u as SoundEntry } from "./types-dJMOXXL3.mjs";
3
+ import { n as EffectsApi, r as EffectsStats } from "./types-B_Bp2tWK.mjs";
4
+ import { c as UiNode } from "./types-Dm5Oh5bH.mjs";
5
+ import { t as HeadlessApp } from "./headless-CYgYzro0.mjs";
6
+ import { a as InputOf, c as Source, i as InputArguments, l as WatchApp, o as InputSchema, t as CheatEntry, u as WatchInput } from "./types-Bonifz5M.mjs";
7
+ import { n as defineSource } from "./define-Ckp70_GR.mjs";
8
8
 
9
9
  //#region src/plugins/flow/doors/read.d.ts
10
10
  /**
@@ -1,2 +1,2 @@
1
- import { a as jsxs, i as jsxDEV, n as JSX, r as jsx, t as Fragment } from "./runtime-6qakboTm.mjs";
1
+ import { a as jsxs, i as jsxDEV, n as JSX, r as jsx, t as Fragment } from "./runtime-iTxTcukZ.mjs";
2
2
  export { Fragment, type JSX, jsx, jsxDEV, jsxs };
@@ -1,2 +1,2 @@
1
- import { a as jsxs, n as JSX, r as jsx, t as Fragment } from "./runtime-6qakboTm.mjs";
1
+ import { a as jsxs, n as JSX, r as jsx, t as Fragment } from "./runtime-iTxTcukZ.mjs";
2
2
  export { Fragment, type JSX, jsx, jsxs };
@@ -1,4 +1,4 @@
1
- import { Xt as Json, nn as ProviderCall, rn as SaveDoc, tn as PlayerStateProvider } from "./types-C6y8EfEB.mjs";
1
+ import { Xt as Json, nn as ProviderCall, rn as SaveDoc, tn as PlayerStateProvider } from "./types-BSMmnpFm.mjs";
2
2
 
3
3
  //#region src/plugins/model/store/providers/memory.d.ts
4
4
  /**
@@ -1,6 +1,6 @@
1
- import { a as sheetAlone } from "./capture-fpd83Mi5.mjs";
1
+ import { a as sheetAlone } from "./capture-D7XvoHdH.mjs";
2
2
  import { n as isDev, r as notInstalled, t as controlRefused } from "./dev-Cc50Dk7H.mjs";
3
- import { n as reproBookmark } from "./headless-BsNdJs9W.mjs";
3
+ import { n as reproBookmark } from "./headless-BA6ffzqD.mjs";
4
4
  import { a as readTarget, i as isProjectionTarget, n as isTainted, o as inputOrEmpty, r as recordCheat, s as defineCommand } from "./session-DgukhR_7.mjs";
5
5
  //#region src/plugins/anim/control.ts
6
6
  /**
@@ -342,8 +342,61 @@ function invalidBookmark() {
342
342
  return /* @__PURE__ */ new Error("[game] The bookmark is not a flow.bookmark() value.\n Pass the JSON that game.bookmark returned.");
343
343
  }
344
344
  /**
345
+ * Tells whether a JSON value has the shape of a rest point: an object with a path and an input.
346
+ *
347
+ * @param value - The `rest` field of a bookmark.
348
+ * @returns True when `path` is a string and `input` is there.
349
+ * @example
350
+ * ```ts
351
+ * isRestPoint({ path: "home", input: null }); // true
352
+ * isRestPoint({ path: "home" }); // false: a rest point has an input, `null` when it is empty
353
+ * ```
354
+ */
355
+ function isRestPoint(value) {
356
+ return isRecord(value) && typeof value.path === "string" && value.input !== void 0;
357
+ }
358
+ /**
359
+ * Reads the rest point of a bookmark taken at a transit node.
360
+ *
361
+ * @param value - The `rest` field of a bookmark.
362
+ * @returns The rest point, or `undefined` when the value is not one.
363
+ * @example
364
+ * ```ts
365
+ * readRest({ path: "home", input: null }); // { path: "home", input: null }
366
+ * readRest("home"); // undefined
367
+ * ```
368
+ */
369
+ function readRest(value) {
370
+ if (!isRestPoint(value)) return void 0;
371
+ return {
372
+ path: value.path,
373
+ input: value.input
374
+ };
375
+ }
376
+ /**
377
+ * Reads the optional fields of a bookmark onto it: the `scene` the `game.bookmark` door added and
378
+ * the `rest` point of a bookmark taken at a transit node. An absent field leaves no key.
379
+ *
380
+ * @param value - The JSON object of the bookmark.
381
+ * @param bookmark - The bookmark with its required fields.
382
+ * @returns The bookmark with its scene and its rest point.
383
+ * @throws {Error} When the scene or the rest point has the wrong shape.
384
+ */
385
+ function readBookmarkOptions(value, bookmark) {
386
+ const { scene, rest } = value;
387
+ if (scene !== void 0 && typeof scene !== "string") throw invalidBookmark();
388
+ if (scene !== void 0) bookmark.scene = scene;
389
+ if (rest !== void 0) {
390
+ const point = readRest(rest);
391
+ if (point === void 0) throw invalidBookmark();
392
+ bookmark.rest = point;
393
+ }
394
+ return bookmark;
395
+ }
396
+ /**
345
397
  * Reads a bookmark out of JSON, the value `flow.bookmark()` made and the editor kept. The
346
- * `scene` the `game.bookmark` door added is kept when present.
398
+ * `scene` the `game.bookmark` door added and the `rest` point of a bookmark taken at a transit
399
+ * node are kept when present.
347
400
  *
348
401
  * @param value - The JSON the editor sent.
349
402
  * @returns The bookmark.
@@ -358,25 +411,14 @@ function readBookmark(value) {
358
411
  const { path, input, player, session, graph } = value;
359
412
  const rng = readRng(value.rng);
360
413
  if (!(typeof path === "string" && typeof graph === "string") || !(input !== void 0 && player !== void 0 && session !== void 0) || rng === void 0) throw invalidBookmark();
361
- const { scene } = value;
362
- if (scene === void 0) return {
414
+ return readBookmarkOptions(value, {
363
415
  path,
364
416
  input,
365
417
  player,
366
418
  session,
367
419
  rng,
368
420
  graph
369
- };
370
- if (typeof scene !== "string") throw invalidBookmark();
371
- return {
372
- path,
373
- input,
374
- player,
375
- session,
376
- rng,
377
- graph,
378
- scene
379
- };
421
+ });
380
422
  }
381
423
  /**
382
424
  * Builds the error of a value that is not a repro.
@@ -577,29 +619,66 @@ function nextFrame(app) {
577
619
  });
578
620
  }
579
621
  /**
580
- * Waits on drawn frames until the graph rests at a gate: at most 600.
622
+ * Starts the restore of a bookmark and does not wait for it. Both ways it can end are marked on
623
+ * the entry, so a restore that rejects while a frame is waited on is never left unhandled.
581
624
  *
582
625
  * @param app - The app.
583
- * @returns True once it rests, false when it still does not after 600 drawn frames.
626
+ * @param bookmark - The bookmark to enter.
627
+ * @returns The restore in flight.
584
628
  */
585
- async function waitForRest(app) {
586
- for (let frame = 0; frame < REST_FRAMES; frame += 1) {
587
- if (atRest(app.flow.state())) return true;
588
- await nextFrame(app);
589
- }
590
- return atRest(app.flow.state());
629
+ function startRestore(app, bookmark) {
630
+ const entry = {
631
+ restore: app.flow.restore(bookmark),
632
+ state: "pending"
633
+ };
634
+ entry.restore.then(() => {
635
+ entry.state = "entered";
636
+ }, () => {
637
+ entry.state = "failed";
638
+ });
639
+ return entry;
640
+ }
641
+ /**
642
+ * Tells whether a restore still has frames to wait for: it has not settled, or it resolved and
643
+ * the graph does not rest at a gate yet. A gate counts only after the restore resolved: until
644
+ * then it can be the gate of the node the restore leaves. A failed restore waits for nothing.
645
+ *
646
+ * @param app - The app.
647
+ * @param entry - The restore in flight.
648
+ * @returns True while another frame is needed.
649
+ */
650
+ function waiting(app, entry) {
651
+ if (entry.state === "pending") return true;
652
+ return entry.state === "entered" && !atRest(app.flow.state());
653
+ }
654
+ /**
655
+ * Waits on drawn frames until a restore resolved and the graph rests at a gate, or the restore
656
+ * failed: at most 600.
657
+ *
658
+ * @param app - The app.
659
+ * @param entry - The restore in flight.
660
+ * @returns False when frames are still needed after 600 drawn ones.
661
+ */
662
+ async function waitForRest(app, entry) {
663
+ for (let frame = 0; frame < REST_FRAMES && waiting(app, entry); frame += 1) await nextFrame(app);
664
+ return !waiting(app, entry);
591
665
  }
592
666
  /**
593
667
  * Restores a bookmark and waits until the graph rests at a gate, then two drawn frames more, so
594
- * the screen of the gate is built and drawn.
668
+ * the screen of the gate is built and drawn. The frames run while the restore is in flight: a
669
+ * bookmark of a transit node resolves only at its gate, and on a paused clock no frame but the
670
+ * ones stepped here brings its node there.
595
671
  *
596
672
  * @param app - The app.
597
673
  * @param bookmark - The bookmark to enter.
598
- * @throws {Error} When the graph does not rest within 600 drawn frames.
674
+ * @throws {Error} When the graph does not rest within 600 drawn frames, and whatever the restore
675
+ * rejects with.
599
676
  */
600
677
  async function restoreAtRest(app, bookmark) {
601
- await app.flow.restore(bookmark);
602
- if (!await waitForRest(app)) throw new Error("[game] game.capture diff: the bookmark did not come to rest in 600 frames.\n Capture a bookmark taken at a gate.");
678
+ const entry = startRestore(app, bookmark);
679
+ const rested = await waitForRest(app, entry);
680
+ if (entry.state !== "pending") await entry.restore;
681
+ if (!rested) throw new Error("[game] game.capture diff: the bookmark did not come to rest in 600 frames.\n Capture a bookmark taken at a gate.");
603
682
  for (let frame = 0; frame < AFTER_REST_FRAMES; frame += 1) await nextFrame(app);
604
683
  }
605
684
  /**
@@ -881,7 +960,8 @@ const fillCommand = defineCommand({
881
960
  //#region src/plugins/flow/control.ts
882
961
  /**
883
962
  * Enters a bookmark, or a repro's bookmark followed by its route. A bookmark's `scene` is handed
884
- * to `scenes.expect` first, so a rest node without a scene of its own mounts it.
963
+ * to `scenes.expect` first, so a node without a scene of its own mounts it: a rest node, or the
964
+ * transit node of a bookmark taken while an effect that takes answers waited.
885
965
  *
886
966
  * @param app - The app; with `scenes`, the bookmark's scene is expected before the restore.
887
967
  * @param input - Exactly one of a bookmark and a repro, as JSON.
@@ -892,13 +972,15 @@ const fillCommand = defineCommand({
892
972
  */
893
973
  async function restoreFrom(app, input) {
894
974
  const { bookmark, repro } = input;
895
- if (bookmark !== void 0 && repro === void 0) {
975
+ const bookmarkOnly = bookmark !== void 0 && repro === void 0;
976
+ const reproOnly = repro !== void 0 && bookmark === void 0;
977
+ if (bookmarkOnly) {
896
978
  const read = readBookmark(bookmark);
897
979
  if (read.scene !== void 0) app.scenes?.expect(read.scene);
898
980
  await app.flow.restore(read);
899
981
  return app.flow.state();
900
982
  }
901
- if (repro !== void 0 && bookmark === void 0) {
983
+ if (reproOnly) {
902
984
  const parsed = readRepro(repro);
903
985
  await app.flow.restore(reproBookmark(app, parsed));
904
986
  return app.flow.walk(parsed.route);
@@ -959,15 +1041,19 @@ const walkCommand = defineCommand({
959
1041
  }
960
1042
  });
961
1043
  /**
962
- * Takes a bookmark of the rest point: the node plus the committed state, plain JSON. An app with
963
- * the screen plugins adds the mounted `scene`, so a restore in a fresh page builds it again.
1044
+ * Takes a bookmark of where the graph stands: the node plus the committed state, plain JSON. The
1045
+ * node is the last rest node, or, while a transit node waits for an effect that takes answers (a
1046
+ * `popup`, or a hand-written descriptor with `answers`), that node; `rest` then names the rest
1047
+ * point before it. An app with the screen plugins adds the mounted `scene`, so a restore in a
1048
+ * fresh page builds it again.
964
1049
  *
965
1050
  * @example
966
1051
  * ```ts
967
- * // The editor keeps the position while the Settings popup stands over Home.
1052
+ * // The editor keeps the position while the info popup of the mini game is open over Home.
968
1053
  * const { value } = await run(app, commands.bookmark);
969
- * value.path; // "settings/open"
1054
+ * value.path; // "info/show": the node that waits for the popup's answer
970
1055
  * value.scene; // "home"
1056
+ * value.rest; // { path: "home", input: null }
971
1057
  * ```
972
1058
  */
973
1059
  const bookmarkCommand = defineCommand({
@@ -990,6 +1076,10 @@ const bookmarkCommand = defineCommand({
990
1076
  * Restores a bookmark, or a repro: its state at its checkpoint, then its route. Replaces the
991
1077
  * state outside the graph, so the session is tainted and the command journaled. A bookmark's
992
1078
  * `scene` goes to `scenes.expect` first: a bookmark at a popup comes back with the scene under it.
1079
+ * A bookmark taken while a transit node waited for an effect that takes answers (a `popup`, or a
1080
+ * hand-written descriptor with `answers`) runs that node again, and the command answers once its
1081
+ * gate is open: the state it returns already lists the answers. The popup is drawn on the next
1082
+ * frame. A repro starts at a rest node only.
993
1083
  *
994
1084
  * @example
995
1085
  * ```ts
@@ -998,11 +1088,11 @@ const bookmarkCommand = defineCommand({
998
1088
  * const ran = await run(app, commands.restore, { repro });
999
1089
  * ran.state; // { path: "board/awaitIntent", frame: 12, tainted: true }
1000
1090
  *
1001
- * // A fresh page restores the bookmark game.bookmark took at the Settings popup over Home.
1002
- * bookmark.scene; // "home"
1003
- * await run(app, commands.restore, { bookmark });
1004
- * await app.flow.walk([]); // the scene stage runs after the restore resolved
1005
- * app.scenes.current(); // "home"
1091
+ * // A fresh page restores the bookmark game.bookmark took at the info popup of the mini game.
1092
+ * const { value } = await run(app, commands.restore, { bookmark });
1093
+ * value.path; // "info/show"
1094
+ * value.pending.gate; // ["ok", "close"]: the popup waits for its answer again
1095
+ * app.scenes.current(); // "home": the scene the bookmark named, under the popup
1006
1096
  * ```
1007
1097
  */
1008
1098
  const restoreCommand = defineCommand({
@@ -1,4 +1,4 @@
1
- import { a as JsxChild, m as UiIntrinsicElements, t as DescriptionNode } from "./types-CmuwAjkV.mjs";
1
+ import { a as JsxChild, m as UiIntrinsicElements, t as DescriptionNode } from "./types-Dm5Oh5bH.mjs";
2
2
 
3
3
  //#region src/plugins/ui/jsx/runtime.d.ts
4
4
  /** What the compiler passes as props: the children plus whatever the tag declared. */