@moku-labs/game 0.9.0 → 0.10.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/README.md +81 -22
- package/bin/moku-game.mjs +4 -0
- package/dist/app/page.d.mts +41 -0
- package/dist/app/page.mjs +376 -0
- package/dist/app/system.d.mts +129 -0
- package/dist/app/system.mjs +307 -0
- package/dist/app.d.mts +37 -0
- package/dist/app.mjs +235 -0
- package/dist/assets-BHwTLVta.mjs +7391 -0
- package/dist/assets.d.mts +1 -1
- package/dist/assets.mjs +1 -7390
- package/dist/cli.d.mts +70 -0
- package/dist/cli.mjs +1650 -0
- package/dist/{commands-DuwCxK5t.d.mts → commands-C4QlqijJ.d.mts} +5 -5
- package/dist/config-CdARrrhU.mjs +81 -0
- package/dist/control.d.mts +11 -10
- package/dist/control.mjs +3 -3
- package/dist/{define-B6pHpdBi.d.mts → define-CCc0ozKe.d.mts} +2 -2
- package/dist/{dev-wKLgOw7c.mjs → dev-Cc50Dk7H.mjs} +1 -1
- package/dist/drafts-BawpSaVp.mjs +156 -0
- package/dist/fake-MpzwZhIZ.mjs +87 -0
- package/dist/{headless-SCQXJxQf.d.mts → headless-G4nuZ-xz.d.mts} +1 -1
- package/dist/hot.d.mts +4 -6
- package/dist/hot.mjs +8 -9
- package/dist/{index-BO9kZzY3.d.mts → index-xxSxKJJW.d.mts} +17 -17
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +1 -1
- package/dist/inspect-la_KkjCS.mjs +1 -0
- package/dist/inspect.d.mts +7 -7
- package/dist/inspect.mjs +3 -2
- package/dist/jsx-dev-runtime.d.mts +1 -1
- package/dist/jsx-runtime.d.mts +1 -1
- package/dist/lint.mjs +10 -6
- package/dist/memory-CWlqhS7l.mjs +136 -0
- package/dist/memory-DwDhfFWK.d.mts +50 -0
- package/dist/project.mjs +3 -3
- package/dist/{run-CofJEdYx.mjs → run-wYty_Lwo.mjs} +2 -2
- package/dist/{runtime-CdNJ0UBm.d.mts → runtime-DOBYM6g4.d.mts} +1 -1
- package/dist/{input-z_35Jwfn.mjs → session-DgukhR_7.mjs} +20 -20
- package/dist/{sources-DNnzyCYf.mjs → sources-Duzj6lhV.mjs} +2 -2
- package/dist/{src-536arXjV.mjs → src-DSl1eNB1.mjs} +14 -292
- package/dist/testing.d.mts +4 -50
- package/dist/testing.mjs +3 -87
- package/dist/{types-VZVWwqCg.d.mts → types-BM4shh8K.d.mts} +259 -259
- package/dist/{types-xXfyk56Q.d.mts → types-BUwDHKXm.d.mts} +1377 -1377
- package/dist/{types-CQueODzo.d.mts → types-CefgYzFt.d.mts} +2 -2
- package/dist/{types-DUMoYPYe.d.mts → types-DAdwEJMp.d.mts} +2 -2
- package/dist/{types-B0v5VVa3.d.mts → types-ZQLYXo5X.d.mts} +304 -304
- package/dist/types-hQgI_wrq.d.mts +544 -0
- package/dist/visual.d.mts +6 -6
- package/dist/visual.mjs +5 -5
- package/llms.txt +119 -43
- package/package.json +30 -2
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
|
|
2
|
+
import { r as systemSource, t as memory } from "./memory-CWlqhS7l.mjs";
|
|
3
|
+
import { a as finishDrafts, i as enableDraftPatches, n as deepFreeze, o as openDrafts, r as dropDrafts } from "./drafts-BawpSaVp.mjs";
|
|
2
4
|
import { c as findNode, d as slotNames, f as compact, i as servePaused, l as framePath, n as captureFrame, o as collectFlows, p as pushEntry, r as serveCaptures, s as describeGraph, t as cancelCaptures, u as graphHash } from "./capture-fpd83Mi5.mjs";
|
|
3
5
|
import { A as system, C as Exiting, D as component, E as Tree, T as Order, _ as Parent, a as visualOf$1, b as Transform, c as Text, g as NineSlice, h as Display, j as tag, k as resource, m as textFor, n as fitScaleOf, o as visualRectOf, p as readStyle, r as samePose, s as Countdown, t as CONTENT, u as builtInStyles, v as Shape, w as Layer, x as componentsFor, y as Sprite } from "./visual-dMW8iqAE.mjs";
|
|
4
|
-
import { n as isDev } from "./dev-
|
|
6
|
+
import { n as isDev } from "./dev-Cc50Dk7H.mjs";
|
|
5
7
|
import { i as isComponentDefinition, n as flatten, r as defineComponent } from "./flatten-BkXuscAV.mjs";
|
|
6
8
|
import { envPlugin, logPlugin } from "@moku-labs/common/browser";
|
|
7
9
|
import { createCoreConfig } from "@moku-labs/core";
|
|
8
|
-
import { applyPatches, createDraft, enablePatches, finishDraft } from "immer";
|
|
9
10
|
/**
|
|
10
11
|
* Core config of the engine: `log` and `env` on every plugin context.
|
|
11
12
|
*/
|
|
@@ -127,37 +128,6 @@ function createClockApi(ctx) {
|
|
|
127
128
|
};
|
|
128
129
|
}
|
|
129
130
|
//#endregion
|
|
130
|
-
//#region src/plugins/clock/system.ts
|
|
131
|
-
/**
|
|
132
|
-
* Tells whether a handle was produced by this source.
|
|
133
|
-
*
|
|
134
|
-
* @param handle - Handle given back to `clearTimer`.
|
|
135
|
-
* @returns `true` when the handle carries a platform timer.
|
|
136
|
-
* @example
|
|
137
|
-
* ```ts
|
|
138
|
-
* isSystemTimer({ timer: 7 }); // true
|
|
139
|
-
* isSystemTimer(7); // false: a handle of another source is ignored
|
|
140
|
-
* ```
|
|
141
|
-
*/
|
|
142
|
-
function isSystemTimer(handle) {
|
|
143
|
-
return typeof handle === "object" && handle !== null && "timer" in handle;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Creates the system source: epoch milliseconds from the device clock and real timers.
|
|
147
|
-
*
|
|
148
|
-
* @returns A source reading `Date.now` and scheduling with `setTimeout`.
|
|
149
|
-
*/
|
|
150
|
-
function systemSource() {
|
|
151
|
-
return {
|
|
152
|
-
now: () => Date.now(),
|
|
153
|
-
setTimer: (callback, delayMs) => ({ timer: setTimeout(callback, delayMs) }),
|
|
154
|
-
clearTimer: (handle) => {
|
|
155
|
-
if (!isSystemTimer(handle)) return;
|
|
156
|
-
clearTimeout(handle.timer);
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
//#endregion
|
|
161
131
|
//#region src/plugins/clock/state.ts
|
|
162
132
|
/**
|
|
163
133
|
* @file clock plugin — state factory.
|
|
@@ -765,263 +735,6 @@ function createRngState() {
|
|
|
765
735
|
return {};
|
|
766
736
|
}
|
|
767
737
|
//#endregion
|
|
768
|
-
//#region src/plugins/model/store/drafts.ts
|
|
769
|
-
/** Root order of a commit result, so two commits never report the same roots in another order. */
|
|
770
|
-
const rootOrder = Object.freeze([
|
|
771
|
-
"player",
|
|
772
|
-
"session",
|
|
773
|
-
"rng"
|
|
774
|
-
]);
|
|
775
|
-
/**
|
|
776
|
-
* Turns on Immer's patch recording. Idempotent, and called from the state factory rather than at
|
|
777
|
-
* module scope: a module-scope call would run on import, even when no app is created.
|
|
778
|
-
*
|
|
779
|
-
*/
|
|
780
|
-
function enableDraftPatches() {
|
|
781
|
-
enablePatches();
|
|
782
|
-
}
|
|
783
|
-
/**
|
|
784
|
-
* Freezes a tree and every branch of it. Immer freezes what it produces; this covers the trees
|
|
785
|
-
* that never went through a draft — the initial trees and the ones handed to `restore()`.
|
|
786
|
-
*
|
|
787
|
-
* @param tree - The tree to freeze, in place.
|
|
788
|
-
* @returns The same reference, now frozen.
|
|
789
|
-
* @example
|
|
790
|
-
* ```ts
|
|
791
|
-
* const tree = deepFreeze({ player: { bag: ["key"] } });
|
|
792
|
-
* Object.isFrozen(tree.player.bag); // true
|
|
793
|
-
* ```
|
|
794
|
-
*/
|
|
795
|
-
function deepFreeze(tree) {
|
|
796
|
-
if (!tree || typeof tree !== "object") return tree;
|
|
797
|
-
for (const branch of Object.values(tree)) deepFreeze(branch);
|
|
798
|
-
return Object.freeze(tree);
|
|
799
|
-
}
|
|
800
|
-
/**
|
|
801
|
-
* Maps one Immer patch to our own structural patch, so no Immer type reaches a public type.
|
|
802
|
-
* A removal carries no value, and `exactOptionalPropertyTypes` forbids an explicit `undefined`.
|
|
803
|
-
*
|
|
804
|
-
* @param patch - The Immer patch.
|
|
805
|
-
* @param path - Path of the patch inside its own tree, without the container segment.
|
|
806
|
-
* @returns The structural patch.
|
|
807
|
-
* @example
|
|
808
|
-
* ```ts
|
|
809
|
-
* toPatch({ op: "remove", path: ["doc", "player", "key"] }, ["player", "key"]);
|
|
810
|
-
* // { op: "remove", path: ["player", "key"] }
|
|
811
|
-
* ```
|
|
812
|
-
*/
|
|
813
|
-
function toPatch(patch, path) {
|
|
814
|
-
if (patch.op === "remove") return {
|
|
815
|
-
op: patch.op,
|
|
816
|
-
path
|
|
817
|
-
};
|
|
818
|
-
return {
|
|
819
|
-
op: patch.op,
|
|
820
|
-
path,
|
|
821
|
-
value: patch.value
|
|
822
|
-
};
|
|
823
|
-
}
|
|
824
|
-
/**
|
|
825
|
-
* Derives the touched roots from the patches of one commit, in a fixed order.
|
|
826
|
-
*
|
|
827
|
-
* @param docPatches - Patches of the save document.
|
|
828
|
-
* @param sessionPatches - Patches of the session tree.
|
|
829
|
-
* @returns The roots a listener has to reconcile.
|
|
830
|
-
* @example
|
|
831
|
-
* ```ts
|
|
832
|
-
* rootsOf([{ op: "add", path: ["rng", "streams", "dice"], value: 7 }], []); // ["rng"]
|
|
833
|
-
* rootsOf([], [{ op: "replace", path: ["rolls"], value: 1 }]); // ["session"]
|
|
834
|
-
* ```
|
|
835
|
-
*/
|
|
836
|
-
function rootsOf(docPatches, sessionPatches) {
|
|
837
|
-
const touched = /* @__PURE__ */ new Set();
|
|
838
|
-
for (const patch of docPatches) {
|
|
839
|
-
const [head] = patch.path;
|
|
840
|
-
if (head === "player" || head === "rng") touched.add(head);
|
|
841
|
-
}
|
|
842
|
-
if (sessionPatches.length > 0) touched.add("session");
|
|
843
|
-
return rootOrder.filter((root) => touched.has(root));
|
|
844
|
-
}
|
|
845
|
-
/**
|
|
846
|
-
* Opens mutable drafts of the frozen save document and session tree.
|
|
847
|
-
* Both live in one draft container, so one `finishDraft` closes the transaction and the patches
|
|
848
|
-
* arrive in one list, tagged by their container key.
|
|
849
|
-
*
|
|
850
|
-
* @param doc - Frozen save document.
|
|
851
|
-
* @param session - Frozen session tree.
|
|
852
|
-
* @returns The open drafts of one transaction.
|
|
853
|
-
* @example
|
|
854
|
-
* ```ts
|
|
855
|
-
* const pair = openDrafts({ player: { coins: 1 }, rng: { seed: 7, streams: {} } }, { rolls: 0 });
|
|
856
|
-
* pair.session; // a mutable draft of { rolls: 0 }: a write never reaches the frozen input
|
|
857
|
-
* ```
|
|
858
|
-
*/
|
|
859
|
-
function openDrafts(doc, session) {
|
|
860
|
-
return createDraft({
|
|
861
|
-
doc,
|
|
862
|
-
session
|
|
863
|
-
});
|
|
864
|
-
}
|
|
865
|
-
/**
|
|
866
|
-
* Finishes the drafts: the new frozen trees, the patches per tree and the touched roots.
|
|
867
|
-
* The drafts are revoked, so a draft that leaked into a view throws on the next touch instead of
|
|
868
|
-
* corrupting the committed tree in silence.
|
|
869
|
-
*
|
|
870
|
-
* @param pair - Open drafts of one transaction.
|
|
871
|
-
* @returns The frozen trees, the patches split by tree, and the touched roots.
|
|
872
|
-
*/
|
|
873
|
-
function finishDrafts(pair) {
|
|
874
|
-
const collected = [];
|
|
875
|
-
const finished = finishDraft(pair, (patches) => {
|
|
876
|
-
collected.push(...patches);
|
|
877
|
-
});
|
|
878
|
-
const docPatches = [];
|
|
879
|
-
const sessionPatches = [];
|
|
880
|
-
for (const patch of collected) {
|
|
881
|
-
const [container, ...path] = patch.path;
|
|
882
|
-
(container === "doc" ? docPatches : sessionPatches).push(toPatch(patch, path));
|
|
883
|
-
}
|
|
884
|
-
return {
|
|
885
|
-
doc: finished.doc,
|
|
886
|
-
session: finished.session,
|
|
887
|
-
patches: {
|
|
888
|
-
doc: docPatches,
|
|
889
|
-
session: sessionPatches
|
|
890
|
-
},
|
|
891
|
-
roots: rootsOf(docPatches, sessionPatches)
|
|
892
|
-
};
|
|
893
|
-
}
|
|
894
|
-
/**
|
|
895
|
-
* Applies the patches of one commit to a document, the way a save seam stores what it was handed.
|
|
896
|
-
* A whole-document patch carries the path `[]` and replaces the document. The input is left as it
|
|
897
|
-
* is: the result is a new frozen document.
|
|
898
|
-
*
|
|
899
|
-
* @param document - The document the patches apply to.
|
|
900
|
-
* @param patches - The patches of one commit, in order.
|
|
901
|
-
* @returns The document after the patches.
|
|
902
|
-
* @throws {Error} When a patch names a path the document does not have.
|
|
903
|
-
* @example
|
|
904
|
-
* ```ts
|
|
905
|
-
* applyTo({ player: { coins: 0 } }, [{ op: "replace", path: ["player", "coins"], value: 4 }]);
|
|
906
|
-
* // { player: { coins: 4 } }
|
|
907
|
-
* ```
|
|
908
|
-
*/
|
|
909
|
-
function applyTo(document, patches) {
|
|
910
|
-
enablePatches();
|
|
911
|
-
return applyPatches(document, patches);
|
|
912
|
-
}
|
|
913
|
-
/**
|
|
914
|
-
* Drops the drafts without a result: the base trees stay as they are and the drafts are revoked.
|
|
915
|
-
*
|
|
916
|
-
* @param pair - Open drafts of one transaction.
|
|
917
|
-
*/
|
|
918
|
-
function dropDrafts(pair) {
|
|
919
|
-
finishDraft(pair);
|
|
920
|
-
}
|
|
921
|
-
//#endregion
|
|
922
|
-
//#region src/plugins/model/store/providers/memory.ts
|
|
923
|
-
/** Seed of a save built by `saveOf` when the caller does not pin one. */
|
|
924
|
-
const defaultSeed = 1;
|
|
925
|
-
/** The base a patch applies to when the provider was never handed a document. */
|
|
926
|
-
const noDocument = {};
|
|
927
|
-
/**
|
|
928
|
-
* Creates an in-memory provider that keeps what it was committed and records every call.
|
|
929
|
-
* It is the default when a game configures no `playerProvider`, and the double every test uses:
|
|
930
|
-
* `provider.calls` is the whole persistence protocol of one run, in order. The document lives as
|
|
931
|
-
* long as the provider does, so a second app over the same instance reads what the first one
|
|
932
|
-
* wrote, and nothing survives the process.
|
|
933
|
-
*
|
|
934
|
-
* `load()` reads the fixture, or everything committed since; without either, the player is new.
|
|
935
|
-
* `commitDurable()` resolves at once: there is no disk behind it.
|
|
936
|
-
*
|
|
937
|
-
* @param fixture - The save `load()` starts from. Omitted: a new player.
|
|
938
|
-
* @param fixture.state - The saved document.
|
|
939
|
-
* @param fixture.version - Schema version of the saved document.
|
|
940
|
-
* @returns A provider that keeps its document and records its calls.
|
|
941
|
-
* @example
|
|
942
|
-
* ```ts
|
|
943
|
-
* // A new player is saved at once. One roll reaches the provider at the next rest node.
|
|
944
|
-
* const provider = memory();
|
|
945
|
-
* const game = await createHeadless(createGame(provider));
|
|
946
|
-
*
|
|
947
|
-
* await game.walk([{ at: "home", intent: "roll" }]);
|
|
948
|
-
* provider.calls.map(call => call.method); // ["load", "commit", "commit"]
|
|
949
|
-
* ```
|
|
950
|
-
*/
|
|
951
|
-
function memory(fixture) {
|
|
952
|
-
const calls = [];
|
|
953
|
-
const held = {
|
|
954
|
-
document: fixture?.state,
|
|
955
|
-
version: fixture?.version ?? 0
|
|
956
|
-
};
|
|
957
|
-
/**
|
|
958
|
-
* Applies the patches of one commit to the held document.
|
|
959
|
-
*
|
|
960
|
-
* @param patches - Doc patches since the last commit.
|
|
961
|
-
* @param version - Schema version this build writes.
|
|
962
|
-
* @throws {Error} When a patch names a path the held document does not have.
|
|
963
|
-
*/
|
|
964
|
-
const hold = (patches, version) => {
|
|
965
|
-
held.document = applyTo(held.document ?? noDocument, patches);
|
|
966
|
-
held.version = version;
|
|
967
|
-
};
|
|
968
|
-
return {
|
|
969
|
-
calls,
|
|
970
|
-
load: async () => {
|
|
971
|
-
calls.push({ method: "load" });
|
|
972
|
-
const document = held.document;
|
|
973
|
-
if (document === void 0) return null;
|
|
974
|
-
return {
|
|
975
|
-
state: document,
|
|
976
|
-
version: held.version
|
|
977
|
-
};
|
|
978
|
-
},
|
|
979
|
-
commit: (patches, version) => {
|
|
980
|
-
calls.push({
|
|
981
|
-
method: "commit",
|
|
982
|
-
patches,
|
|
983
|
-
version
|
|
984
|
-
});
|
|
985
|
-
hold(patches, version);
|
|
986
|
-
},
|
|
987
|
-
commitDurable: async (patches, txId, version) => {
|
|
988
|
-
calls.push({
|
|
989
|
-
method: "commitDurable",
|
|
990
|
-
patches,
|
|
991
|
-
txId,
|
|
992
|
-
version
|
|
993
|
-
});
|
|
994
|
-
hold(patches, version);
|
|
995
|
-
},
|
|
996
|
-
flush: async () => {
|
|
997
|
-
calls.push({ method: "flush" });
|
|
998
|
-
}
|
|
999
|
-
};
|
|
1000
|
-
}
|
|
1001
|
-
/**
|
|
1002
|
-
* Builds a save document from a player tree, with no rng streams drawn yet.
|
|
1003
|
-
* Short fixtures in tests read as `saveOf({ coins: 5 })` instead of spelling out the rng branch.
|
|
1004
|
-
*
|
|
1005
|
-
* @param player - Player tree of the save.
|
|
1006
|
-
* @param seed - Rng seed of the save.
|
|
1007
|
-
* @returns The save document.
|
|
1008
|
-
* @example
|
|
1009
|
-
* ```ts
|
|
1010
|
-
* // A returning player with 5 coins. The test starts from this save, not from `initialPlayer`.
|
|
1011
|
-
* saveOf({ coins: 5 }, 42); // { player: { coins: 5 }, rng: { seed: 42, streams: {} } }
|
|
1012
|
-
* const provider = memory({ state: saveOf({ coins: 5 }, 42), version: 1 });
|
|
1013
|
-
* ```
|
|
1014
|
-
*/
|
|
1015
|
-
function saveOf(player, seed = defaultSeed) {
|
|
1016
|
-
return {
|
|
1017
|
-
player,
|
|
1018
|
-
rng: {
|
|
1019
|
-
seed,
|
|
1020
|
-
streams: {}
|
|
1021
|
-
}
|
|
1022
|
-
};
|
|
1023
|
-
}
|
|
1024
|
-
//#endregion
|
|
1025
738
|
//#region src/plugins/model/store/state.ts
|
|
1026
739
|
/** Seed of the trees that exist before `load()` ran. A save or a new player replaces it. */
|
|
1027
740
|
const preloadSeed = 0;
|
|
@@ -34532,21 +34245,30 @@ function defineMotion(spec) {
|
|
|
34532
34245
|
* | effects | maxPasses | 24, render passes per frame above which one dev warning fires per crossing |
|
|
34533
34246
|
* | effects | phone | "auto", a coarse pointer and a short side of at most 820 CSS px |
|
|
34534
34247
|
* | effects | blur | { quality: 2, phoneResolution: 0.5 }, what a Blur with quality 0 and resolution 0 resolves to; shallow merge: a game that sets `blur` gives both fields |
|
|
34535
|
-
* | platform | provider | undefined, inert: no subscription, no haptic handler, `back()` answers "none" |
|
|
34248
|
+
* | platform | provider | undefined, inert: no subscription, no haptic handler, `back()` answers "none"; the engine page passes the system shell's provider |
|
|
34536
34249
|
* | platform | keepAwake | false |
|
|
34537
34250
|
*
|
|
34538
34251
|
* Subpaths next to the root:
|
|
34539
34252
|
*
|
|
34540
34253
|
* | Subpath | What |
|
|
34541
34254
|
* |---|---|
|
|
34255
|
+
* | `@moku-labs/game/app` | `defineGameApp`, the game as one data object with `headless()` and `screen()`; `startMoment`; the types of `index.ts` and `config.ts` (`GameConfig`) |
|
|
34256
|
+
* | `@moku-labs/game/app/page` | `startPage`, the page the generated `.moku/main.ts` calls: `?player=` scenarios, the system shell, the dev agents |
|
|
34257
|
+
* | `@moku-labs/game/app/system` | the system shell over the optional peer `@moku-labs/system`: `systemShell`, `fromSystem`, `storeSave`, `createSystemApp` |
|
|
34258
|
+
* | `@moku-labs/game/cli` | `runCli` of the bin `moku-game` and `preparePage` for the editor, node and bun only |
|
|
34542
34259
|
* | `@moku-labs/game/testing` | headless play, repro runs, isolated feature tests (`isolate`, `stub`), the in-memory save, the fake clock |
|
|
34543
34260
|
* | `@moku-labs/game/visual` | the visual tests, node and bun only |
|
|
34544
34261
|
* | `@moku-labs/game/assets` | the build-time asset key scanner and the production packer (`packAssets`, `--pack <dir>`), node and bun only |
|
|
34545
34262
|
* | `@moku-labs/game/inspect` | the editor's read door: `read`, `watch`, `defineSource`, the `sources` catalogue |
|
|
34546
34263
|
* | `@moku-labs/game/control` | the editor's write door, dev builds only: `run`, `defineCommand`, the `commands` catalogue |
|
|
34264
|
+
* | `@moku-labs/game/hot` | the Bun plugin that hot swaps views; `moku-game dev` lists it in its bunfig |
|
|
34265
|
+
* | `@moku-labs/game/lint` | the oxlint JS plugin `moku-game` with the game lint rules |
|
|
34266
|
+
* | `@moku-labs/game/project` | the project index of a game's sources, node and bun only |
|
|
34547
34267
|
* | `@moku-labs/game/jsx-runtime`, `/jsx-dev-runtime` | the JSX runtimes `jsxImportSource: "@moku-labs/game"` names |
|
|
34548
34268
|
* | `@moku-labs/game/fonts/*` | the MSDF body font `font-body.fnt` + `.png` and its OFL licence; a game copies them into `features/ui/assets/` |
|
|
34269
|
+
* | bin `moku-game` | `dev`, `build`, `native <verb>`, `keys`, `pack`: serves, builds, packages and packs a game folder, bun only |
|
|
34549
34270
|
* | bin `moku-game-assets` | the asset scanner CLI, bun only |
|
|
34271
|
+
* | bin `moku-game-index` | the project index CLI, bun only |
|
|
34550
34272
|
*
|
|
34551
34273
|
* @file The package root: the composed framework and its public exports.
|
|
34552
34274
|
* @example
|
|
@@ -34641,4 +34363,4 @@ const screen = [
|
|
|
34641
34363
|
uiPlugin
|
|
34642
34364
|
];
|
|
34643
34365
|
//#endregion
|
|
34644
|
-
export { sfx as $, types_exports$13 as A, defineFilter as At, defineStyle as B, flowPlugin as Bt, types_exports$6 as C, Alpha as Ct, types_exports$10 as D, Glow as Dt, types_exports$9 as E, Displacement as Et, resolve as F, AnimPlayer as Ft, external as G, modelPlugin as Gt, platformPlugin as H, slot as Ht, Box as I, Animation as It, mark as J,
|
|
34366
|
+
export { sfx as $, types_exports$13 as A, defineFilter as At, defineStyle as B, flowPlugin as Bt, types_exports$6 as C, Alpha as Ct, types_exports$10 as D, Glow as Dt, types_exports$9 as E, Displacement as Et, resolve as F, AnimPlayer as Ft, external as G, modelPlugin as Gt, platformPlugin as H, slot as Ht, Box as I, Animation as It, mark as J, timePlugin as Jt, frames as K, SaveUnreadableError as Kt, LocalWrite as L, Frames as Lt, types_exports$15 as M, scenesPlugin as Mt, types_exports$16 as N, assetsPlugin as Nt, types_exports$11 as O, Noise as Ot, uiPlugin as P, animPlugin as Pt, set as Q, popup as R, rendererPlugin as Rt, types_exports$5 as S, Emitter as St, types_exports$8 as T, ColorMatrix as Tt, HAPTIC_KINDS as U, to as Ut, textPlugin as V, exit as Vt, defineAnimation as W, type as Wt, play$1 as X, parallel as Y, clockPlugin as Yt, sequence as Z, types_exports as _, Touchable as _t, defineMotion as a, wait as at, types_exports$3 as b, i18nPlugin as bt, schedule as c, DropTarget as ct, tr as d, Pointer as dt, spawn as et, defineFeature as f, PointerOver as ft, load as g, Tappable as gt, defineBundles as h, Swipeable as ht, screen as i, use as it, types_exports$14 as j, audioPlugin as jt, types_exports$12 as k, Outline as kt, projection as l, Held as lt, music as m, Pressed as mt, createPlugin as n, stagger as nt, guide as o, inputPlugin as ot, defineEmitter as p, Pressable as pt, haptic as q, lifecyclePlugin as qt, defineGame as r, tween as rt, hint as s, Draggable as st, createApp as t, spawned as tt, defineScene as u, Hovered as ut, types_exports$1 as v, Traceable as vt, types_exports$7 as w, Blur as wt, types_exports$4 as x, effectsPlugin as xt, types_exports$2 as y, Traced as yt, defineTokens as z, worldPlugin as zt };
|
package/dist/testing.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { t as
|
|
1
|
+
import { Dt as AnyFlow, Ht as ClockSource, Nt as NodeTable, Wt as FakeClock, Xt as Json, ht as FeaturePlugin } from "./types-ZQLYXo5X.mjs";
|
|
2
|
+
import { t as createApp } from "./index-xxSxKJJW.mjs";
|
|
3
|
+
import { n as saveOf, t as memory } from "./memory-DwDhfFWK.mjs";
|
|
4
|
+
import { a as createHeadless, i as ReproResult, n as HeadlessGame, o as runRepro, r as Repro, s as stepFrames, t as HeadlessApp } from "./headless-G4nuZ-xz.mjs";
|
|
4
5
|
import { AnyPluginInstance } from "@moku-labs/core";
|
|
5
6
|
|
|
6
7
|
//#region src/plugins/clock/fake.d.ts
|
|
@@ -25,53 +26,6 @@ import { AnyPluginInstance } from "@moku-labs/core";
|
|
|
25
26
|
*/
|
|
26
27
|
declare function fakeClock(start?: number): FakeClock;
|
|
27
28
|
//#endregion
|
|
28
|
-
//#region src/plugins/model/store/providers/memory.d.ts
|
|
29
|
-
/**
|
|
30
|
-
* Creates an in-memory provider that keeps what it was committed and records every call.
|
|
31
|
-
* It is the default when a game configures no `playerProvider`, and the double every test uses:
|
|
32
|
-
* `provider.calls` is the whole persistence protocol of one run, in order. The document lives as
|
|
33
|
-
* long as the provider does, so a second app over the same instance reads what the first one
|
|
34
|
-
* wrote, and nothing survives the process.
|
|
35
|
-
*
|
|
36
|
-
* `load()` reads the fixture, or everything committed since; without either, the player is new.
|
|
37
|
-
* `commitDurable()` resolves at once: there is no disk behind it.
|
|
38
|
-
*
|
|
39
|
-
* @param fixture - The save `load()` starts from. Omitted: a new player.
|
|
40
|
-
* @param fixture.state - The saved document.
|
|
41
|
-
* @param fixture.version - Schema version of the saved document.
|
|
42
|
-
* @returns A provider that keeps its document and records its calls.
|
|
43
|
-
* @example
|
|
44
|
-
* ```ts
|
|
45
|
-
* // A new player is saved at once. One roll reaches the provider at the next rest node.
|
|
46
|
-
* const provider = memory();
|
|
47
|
-
* const game = await createHeadless(createGame(provider));
|
|
48
|
-
*
|
|
49
|
-
* await game.walk([{ at: "home", intent: "roll" }]);
|
|
50
|
-
* provider.calls.map(call => call.method); // ["load", "commit", "commit"]
|
|
51
|
-
* ```
|
|
52
|
-
*/
|
|
53
|
-
declare function memory(fixture?: {
|
|
54
|
-
state: SaveDoc;
|
|
55
|
-
version: number;
|
|
56
|
-
}): PlayerStateProvider & {
|
|
57
|
-
calls: ProviderCall[];
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* Builds a save document from a player tree, with no rng streams drawn yet.
|
|
61
|
-
* Short fixtures in tests read as `saveOf({ coins: 5 })` instead of spelling out the rng branch.
|
|
62
|
-
*
|
|
63
|
-
* @param player - Player tree of the save.
|
|
64
|
-
* @param seed - Rng seed of the save.
|
|
65
|
-
* @returns The save document.
|
|
66
|
-
* @example
|
|
67
|
-
* ```ts
|
|
68
|
-
* // A returning player with 5 coins. The test starts from this save, not from `initialPlayer`.
|
|
69
|
-
* saveOf({ coins: 5 }, 42); // { player: { coins: 5 }, rng: { seed: 42, streams: {} } }
|
|
70
|
-
* const provider = memory({ state: saveOf({ coins: 5 }, 42), version: 1 });
|
|
71
|
-
* ```
|
|
72
|
-
*/
|
|
73
|
-
declare function saveOf(player: Json, seed?: number): SaveDoc;
|
|
74
|
-
//#endregion
|
|
75
29
|
//#region src/testing/isolate.d.ts
|
|
76
30
|
/**
|
|
77
31
|
* A stub for one node or sub-flow of the isolated flow: the outcome it ends with, and its payload.
|
package/dist/testing.mjs
CHANGED
|
@@ -1,91 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Vt as exit, Wt as type, t as createApp } from "./src-DSl1eNB1.mjs";
|
|
2
|
+
import { n as saveOf, t as memory } from "./memory-CWlqhS7l.mjs";
|
|
3
|
+
import { t as fakeClock } from "./fake-MpzwZhIZ.mjs";
|
|
2
4
|
import { i as stepFrames, r as runRepro, t as createHeadless } from "./headless-BsNdJs9W.mjs";
|
|
3
|
-
//#region src/plugins/clock/fake.ts
|
|
4
|
-
/**
|
|
5
|
-
* Removes and returns the timer that is due first, up to and including `until`.
|
|
6
|
-
* Timers due at the same moment come out in the order they were scheduled.
|
|
7
|
-
*
|
|
8
|
-
* @param state - Innards of the fake clock.
|
|
9
|
-
* @param until - Latest moment that counts as due.
|
|
10
|
-
* @returns The timer to fire, or `undefined` when nothing is due.
|
|
11
|
-
*/
|
|
12
|
-
function takeDue(state, until) {
|
|
13
|
-
let earliest;
|
|
14
|
-
for (const timer of state.timers) {
|
|
15
|
-
if (timer.at > until) continue;
|
|
16
|
-
if (earliest === void 0 || timer.at < earliest.at) earliest = timer;
|
|
17
|
-
}
|
|
18
|
-
if (earliest === void 0) return void 0;
|
|
19
|
-
const due = earliest;
|
|
20
|
-
state.timers = state.timers.filter((timer) => timer !== due);
|
|
21
|
-
return due;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Moves the clock to `until`, firing every timer that falls due on the way, in due order.
|
|
25
|
-
* A timer scheduled inside a callback fires in the same run when it is due before `until`.
|
|
26
|
-
*
|
|
27
|
-
* @param state - Innards of the fake clock.
|
|
28
|
-
* @param until - Moment to stop at.
|
|
29
|
-
*/
|
|
30
|
-
function runDue(state, until) {
|
|
31
|
-
let due = takeDue(state, until);
|
|
32
|
-
while (due !== void 0) {
|
|
33
|
-
state.now = Math.max(state.now, due.at);
|
|
34
|
-
due.callback();
|
|
35
|
-
due = takeDue(state, until);
|
|
36
|
-
}
|
|
37
|
-
state.now = Math.max(state.now, until);
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Creates a fake source for tests. Timers fire synchronously inside `advance`, in due order. A
|
|
41
|
-
* negative delay counts as zero and an unknown handle is ignored.
|
|
42
|
-
*
|
|
43
|
-
* @param start - Starting moment in epoch milliseconds. Defaults to 0.
|
|
44
|
-
* @returns A clock source with the test-only controls `advance` and `set`.
|
|
45
|
-
* @example
|
|
46
|
-
* ```ts
|
|
47
|
-
* // An energy point refills 60 s after it was spent. The test moves the clock, not the minute.
|
|
48
|
-
* const clock = fakeClock(1000);
|
|
49
|
-
* const app = createApp({ pluginConfigs: { clock: { source: clock } } });
|
|
50
|
-
* const seen: number[] = [];
|
|
51
|
-
*
|
|
52
|
-
* app.clock.onElapsed(({ now }) => seen.push(now));
|
|
53
|
-
* app.clock.scheduleAt(61_000);
|
|
54
|
-
* clock.advance(60_000); // the timer fires inside advance, nothing waits
|
|
55
|
-
* seen; // [61000]
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
function fakeClock(start = 0) {
|
|
59
|
-
const state = {
|
|
60
|
-
now: start,
|
|
61
|
-
nextId: 1,
|
|
62
|
-
timers: []
|
|
63
|
-
};
|
|
64
|
-
return {
|
|
65
|
-
now: () => state.now,
|
|
66
|
-
setTimer: (callback, delayMs) => {
|
|
67
|
-
const id = state.nextId;
|
|
68
|
-
state.nextId += 1;
|
|
69
|
-
state.timers.push({
|
|
70
|
-
id,
|
|
71
|
-
at: state.now + Math.max(0, delayMs),
|
|
72
|
-
callback
|
|
73
|
-
});
|
|
74
|
-
return id;
|
|
75
|
-
},
|
|
76
|
-
clearTimer: (handle) => {
|
|
77
|
-
if (typeof handle !== "number") return;
|
|
78
|
-
state.timers = state.timers.filter((timer) => timer.id !== handle);
|
|
79
|
-
},
|
|
80
|
-
advance: (ms) => {
|
|
81
|
-
runDue(state, state.now + Math.max(0, ms));
|
|
82
|
-
},
|
|
83
|
-
set: (moment) => {
|
|
84
|
-
state.now = moment;
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
//#endregion
|
|
89
5
|
//#region src/testing/isolate.ts
|
|
90
6
|
const noPayload = null;
|
|
91
7
|
/** Id of the harness main flow. */
|