@storylet-studio/runtime 0.3.0 → 0.4.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/dist/index.cjs +11 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/storyletengine.min.js +0 -2
- package/dist/storyletengine.min.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -24,6 +24,16 @@ interface EngineOptions {
|
|
|
24
24
|
* once, each engine saves its own envelope (design/flows.md).
|
|
25
25
|
*/
|
|
26
26
|
world?: ScopeResolver;
|
|
27
|
+
/**
|
|
28
|
+
* Diagnostics hook (opt-in, dev tooling only): fired when `openFlow` REPLACES
|
|
29
|
+
* a flow that still had cards dealt, with the flow id and how many. The
|
|
30
|
+
* behaviour is unchanged - replacing is deliberate and the same in Patter -
|
|
31
|
+
* this only makes it observable, because the case it catches is a host
|
|
32
|
+
* calling `openFlow` straight after `loadGame` to "re-take" its handle and
|
|
33
|
+
* silently discarding the hand the save just restored (`getFlow` is the
|
|
34
|
+
* call). Zero cost when unset; leave it unset in shipped games.
|
|
35
|
+
*/
|
|
36
|
+
onReplacedFlow?: (id: string, dealt: number) => void;
|
|
27
37
|
}
|
|
28
38
|
interface OpenFlowOptions {
|
|
29
39
|
/** Seed for this flow's PRNG (defaults to the engine's `seed`). */
|
|
@@ -224,6 +234,9 @@ interface Internals {
|
|
|
224
234
|
shared: Partition;
|
|
225
235
|
/** @world: the host's resolver, or the self-backed bag's. */
|
|
226
236
|
worldResolver: ScopeResolver;
|
|
237
|
+
/** @world names declared `writable: false`: the story's promise, kept at
|
|
238
|
+
* runtime as the compiler keeps it at publish (Reboot.md 10). */
|
|
239
|
+
worldReadOnly: Set<string>;
|
|
227
240
|
/** `turn` is the box clock the event happened on, where the caller knows it
|
|
228
241
|
* - the same stamp the flow's own log carries. Unity and Unreal passed it
|
|
229
242
|
* from the start; JS and Godot dropped it, so their examiners printed "[-]"
|
|
@@ -235,6 +248,7 @@ interface Internals {
|
|
|
235
248
|
declare class Engine {
|
|
236
249
|
private readonly internals;
|
|
237
250
|
private readonly seed;
|
|
251
|
+
private readonly onReplacedFlow;
|
|
238
252
|
private readonly flowsById;
|
|
239
253
|
private readonly engineTraceHandlers;
|
|
240
254
|
/** The host's @world binding, if the engine was built with one: it
|
package/dist/index.d.ts
CHANGED
|
@@ -24,6 +24,16 @@ interface EngineOptions {
|
|
|
24
24
|
* once, each engine saves its own envelope (design/flows.md).
|
|
25
25
|
*/
|
|
26
26
|
world?: ScopeResolver;
|
|
27
|
+
/**
|
|
28
|
+
* Diagnostics hook (opt-in, dev tooling only): fired when `openFlow` REPLACES
|
|
29
|
+
* a flow that still had cards dealt, with the flow id and how many. The
|
|
30
|
+
* behaviour is unchanged - replacing is deliberate and the same in Patter -
|
|
31
|
+
* this only makes it observable, because the case it catches is a host
|
|
32
|
+
* calling `openFlow` straight after `loadGame` to "re-take" its handle and
|
|
33
|
+
* silently discarding the hand the save just restored (`getFlow` is the
|
|
34
|
+
* call). Zero cost when unset; leave it unset in shipped games.
|
|
35
|
+
*/
|
|
36
|
+
onReplacedFlow?: (id: string, dealt: number) => void;
|
|
27
37
|
}
|
|
28
38
|
interface OpenFlowOptions {
|
|
29
39
|
/** Seed for this flow's PRNG (defaults to the engine's `seed`). */
|
|
@@ -224,6 +234,9 @@ interface Internals {
|
|
|
224
234
|
shared: Partition;
|
|
225
235
|
/** @world: the host's resolver, or the self-backed bag's. */
|
|
226
236
|
worldResolver: ScopeResolver;
|
|
237
|
+
/** @world names declared `writable: false`: the story's promise, kept at
|
|
238
|
+
* runtime as the compiler keeps it at publish (Reboot.md 10). */
|
|
239
|
+
worldReadOnly: Set<string>;
|
|
227
240
|
/** `turn` is the box clock the event happened on, where the caller knows it
|
|
228
241
|
* - the same stamp the flow's own log carries. Unity and Unreal passed it
|
|
229
242
|
* from the start; JS and Godot dropped it, so their examiners printed "[-]"
|
|
@@ -235,6 +248,7 @@ interface Internals {
|
|
|
235
248
|
declare class Engine {
|
|
236
249
|
private readonly internals;
|
|
237
250
|
private readonly seed;
|
|
251
|
+
private readonly onReplacedFlow;
|
|
238
252
|
private readonly flowsById;
|
|
239
253
|
private readonly engineTraceHandlers;
|
|
240
254
|
/** The host's @world binding, if the engine was built with one: it
|
package/dist/index.js
CHANGED
|
@@ -603,6 +603,7 @@ var loadPartition = (p, values) => {
|
|
|
603
603
|
var Engine = class {
|
|
604
604
|
internals;
|
|
605
605
|
seed;
|
|
606
|
+
onReplacedFlow;
|
|
606
607
|
flowsById = /* @__PURE__ */ new Map();
|
|
607
608
|
engineTraceHandlers = /* @__PURE__ */ new Set();
|
|
608
609
|
/** The host's @world binding, if the engine was built with one: it
|
|
@@ -611,6 +612,7 @@ var Engine = class {
|
|
|
611
612
|
hostWorld;
|
|
612
613
|
constructor(bundle, opts = {}) {
|
|
613
614
|
this.seed = opts.seed ?? 0;
|
|
615
|
+
this.onReplacedFlow = opts.onReplacedFlow;
|
|
614
616
|
if (opts.world !== void 0) this.hostWorld = opts.world;
|
|
615
617
|
const internals = {
|
|
616
618
|
bundle,
|
|
@@ -631,6 +633,7 @@ var Engine = class {
|
|
|
631
633
|
flowDecls: { story: [], box: /* @__PURE__ */ new Map(), deck: /* @__PURE__ */ new Map(), hand: /* @__PURE__ */ new Map(), value: /* @__PURE__ */ new Map() },
|
|
632
634
|
shared: void 0,
|
|
633
635
|
worldResolver: void 0,
|
|
636
|
+
worldReadOnly: /* @__PURE__ */ new Set(),
|
|
634
637
|
emitEngine: (flow, event, turn) => {
|
|
635
638
|
if (this.internals.logCap !== void 0) {
|
|
636
639
|
this.engineLog.push({ ...event, flow, seq: this.engineSeq++, ...turn !== void 0 ? { turn } : {} });
|
|
@@ -688,6 +691,7 @@ var Engine = class {
|
|
|
688
691
|
initShared(hostWorld) {
|
|
689
692
|
const internals = this.internals;
|
|
690
693
|
internals.shared = buildPartition(internals, sharedHalf);
|
|
694
|
+
internals.worldReadOnly = new Set(internals.bundle.world.properties.filter((d) => d.writable === false).map((d) => d.name));
|
|
691
695
|
if (hostWorld !== void 0) {
|
|
692
696
|
internals.worldResolver = hostWorld;
|
|
693
697
|
} else {
|
|
@@ -731,7 +735,12 @@ var Engine = class {
|
|
|
731
735
|
* state; shared state is untouched. There is no default flow: "main" is
|
|
732
736
|
* a caller convention, not an engine rule. */
|
|
733
737
|
openFlow(id, opts = {}) {
|
|
734
|
-
this.flowsById.get(id)
|
|
738
|
+
const existing = this.flowsById.get(id);
|
|
739
|
+
if (existing) {
|
|
740
|
+
const dealt = existing.heldCardIds().length;
|
|
741
|
+
if (dealt > 0) this.onReplacedFlow?.(id, dealt);
|
|
742
|
+
existing.markClosed();
|
|
743
|
+
}
|
|
735
744
|
const flow = new Flow(this, this.internals, id, opts.seed ?? this.seed);
|
|
736
745
|
this.flowsById.set(id, flow);
|
|
737
746
|
return flow;
|
|
@@ -1697,6 +1706,7 @@ var Flow = class {
|
|
|
1697
1706
|
case "world": {
|
|
1698
1707
|
const resolver = this.internals.worldResolver;
|
|
1699
1708
|
if (!resolver.set) throw new Error(`@world.${name} cannot be written: the host bound @world read-only`);
|
|
1709
|
+
if (this.internals.worldReadOnly.has(name)) throw new Error(`'@world.${name}' is read-only (writable: false)`);
|
|
1700
1710
|
const prev = resolver.get(name);
|
|
1701
1711
|
resolver.set(name, value);
|
|
1702
1712
|
return { path: `world.${name}`, ...prev !== void 0 ? { prev } : {} };
|