@moku-labs/game 0.12.0 → 0.13.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/README.md +4 -4
- package/dist/app/page.d.mts +1 -0
- package/dist/app/page.mjs +1 -0
- package/dist/cli.d.mts +67 -3
- package/dist/cli.mjs +455 -60
- package/dist/project.d.mts +1 -1
- package/dist/project.mjs +7 -2954
- package/dist/watch-CB8IWDBi.mjs +2960 -0
- package/llms.txt +8 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -134,7 +134,7 @@ app.model.store.snapshot().session; // { rolls: 2 }
|
|
|
134
134
|
|
|
135
135
|
`bunx moku-game dev` serves it with hot reload on `http://localhost:3000/`. The full version, with a reset node and a vitest file, is in [docs/quick-start.md](./docs/quick-start.md). A bigger game, the merge game, lives in [moku-labs/demos](https://github.com/moku-labs/demos) with its tests.
|
|
136
136
|
|
|
137
|
-
A game with a screen gets two more things from the package. The body font `fonts/font-body.*` (Pangolin, SIL OFL 1.1) is the default of the built-in text style `body` once copied into `features/ui/assets/`. `moku-game keys` writes the typed asset keys, the manifest and the strings. Both are in [docs/quick-start.md](./docs/quick-start.md#a-screen-the-body-font-and-the-asset-keys).
|
|
137
|
+
A game with a screen gets two more things from the package. The body font `fonts/font-body.*` (Pangolin, SIL OFL 1.1) is the default of the built-in text style `body` once copied into `features/ui/assets/`. `moku-game keys` writes the typed asset keys, the manifest and the strings, and `moku-game dev` writes them again when an asset or a strings file is saved. Both are in [docs/quick-start.md](./docs/quick-start.md#a-screen-the-body-font-and-the-asset-keys).
|
|
138
138
|
|
|
139
139
|
## Game shell
|
|
140
140
|
|
|
@@ -160,12 +160,12 @@ The engine bin `moku-game` serves, builds and packs a game folder. A game writes
|
|
|
160
160
|
|
|
161
161
|
| Command | Does |
|
|
162
162
|
|---|---|
|
|
163
|
-
| `moku-game dev [--port 3000] [--packed]` | Serves the game with hot reload. Prints the bound URL, also for `--port 0` |
|
|
163
|
+
| `moku-game dev [--port 3000] [--packed]` | Serves the game with hot reload. Prints the bound URL, also for `--port 0`. On the raw files it runs the scan of `keys` at start and on a save of an asset or a strings file |
|
|
164
164
|
| `moku-game build [--out dist/web]` | Packs the assets and builds the production page |
|
|
165
165
|
| `moku-game native build <target> [--simulator]` | Builds the native app: `ios`, `macos`, `android` |
|
|
166
166
|
| `moku-game native dev <target>` | Runs the native shell on the dev server |
|
|
167
167
|
| `moku-game native doctor`, `native clean` | Checks or removes the native project |
|
|
168
|
-
| `moku-game keys [--check]` | Writes `generated/assets.ts`, the strings and `manifest.json` |
|
|
168
|
+
| `moku-game keys [--check]` | Writes `generated/assets.ts`, the strings and `generated/manifest.json` |
|
|
169
169
|
| `moku-game pack [--no-cache]` | Packs the assets into `dist/assets` |
|
|
170
170
|
| `moku-game visual [--update] [--only <name>] [--no-pixels]` | Runs the visual tests of `tests/visual/index.ts` against `tests/visual/baselines/`. The pixel leg runs on a Mac, on a page served for the run. Exit 1 when a checkpoint differs |
|
|
171
171
|
|
|
@@ -245,7 +245,7 @@ createApp({ plugins: [...screen, effectsPlugin, audioPlugin, platformPlugin] });
|
|
|
245
245
|
| `@moku-labs/game/app` | anywhere | `defineGameApp`, `startMoment` and the types of `index.ts` and `config.ts`. See [The game shell](./docs/shell.md) |
|
|
246
246
|
| `@moku-labs/game/app/page` | the browser | `startPage`, the page the generated `.moku/main.ts` calls |
|
|
247
247
|
| `@moku-labs/game/app/system` | the browser, the native shell | The system shell over the optional peer `@moku-labs/system` |
|
|
248
|
-
| `@moku-labs/game/cli` | Node and Bun | `runCli`, the bin `moku-game`; `preparePage`, the dev page for the editor |
|
|
248
|
+
| `@moku-labs/game/cli` | Node and Bun | `runCli`, the bin `moku-game`; `preparePage`, the dev page for the editor; `watchKeys`, which keeps `generated/` fresh next to it |
|
|
249
249
|
| `@moku-labs/game/testing` | anywhere | Headless and isolated games, the fake clock, the in-memory save |
|
|
250
250
|
| `@moku-labs/game/visual` | Node and Bun | Visual tests: baselines of state, describe and pixels |
|
|
251
251
|
| `@moku-labs/game/assets` | Node and Bun | Asset keys, the manifest, strings, the pack |
|
package/dist/app/page.d.mts
CHANGED
|
@@ -19,6 +19,7 @@ import { m as StartedPage, r as GameConfig, t as AnyGameApp, u as PageOptions }
|
|
|
19
19
|
* ```ts
|
|
20
20
|
* // Written by moku-game dev. Do not edit.
|
|
21
21
|
* import "./dev.ts";
|
|
22
|
+
* import "./assets-stamp.ts";
|
|
22
23
|
* import { startPage } from "@moku-labs/game/app/page";
|
|
23
24
|
* import { systemShellOf } from "@moku-labs/game/app/system";
|
|
24
25
|
* import game from "../index.ts";
|
package/dist/app/page.mjs
CHANGED
|
@@ -321,6 +321,7 @@ async function startAgents(app, settings, options) {
|
|
|
321
321
|
* ```ts
|
|
322
322
|
* // Written by moku-game dev. Do not edit.
|
|
323
323
|
* import "./dev.ts";
|
|
324
|
+
* import "./assets-stamp.ts";
|
|
324
325
|
* import { startPage } from "@moku-labs/game/app/page";
|
|
325
326
|
* import { systemShellOf } from "@moku-labs/game/app/system";
|
|
326
327
|
* import game from "../index.ts";
|
package/dist/cli.d.mts
CHANGED
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
//#region src/app/keys.d.ts
|
|
2
|
+
/** The running keys watch of one game folder, as `watchKeys` answers it. */
|
|
3
|
+
type KeysWatcher = {
|
|
4
|
+
/**
|
|
5
|
+
* Stops watching. A scan that is running finishes; no later one starts. A second call does
|
|
6
|
+
* nothing.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* // The editor closes the game it has open.
|
|
11
|
+
* const keys = await watchKeys("games/timber");
|
|
12
|
+
* keys.close(); // a later save of features/home/strings/en.json rewrites nothing in generated/
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
close(): void;
|
|
16
|
+
};
|
|
17
|
+
/** What `watchKeys` is started with. */
|
|
18
|
+
type WatchKeysOptions = {
|
|
19
|
+
/**
|
|
20
|
+
* Called with the scanner's message when a scan fails: bad JSON in a strings file, a key two
|
|
21
|
+
* files claim, a refused file. The watch goes on and the next save scans again. It is the only
|
|
22
|
+
* printer of a scan error. Default: a warning on the branded console, `[game] keys: <message>`.
|
|
23
|
+
*
|
|
24
|
+
* @param message - The message of the scanner; one line per problem when it found several.
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* // The editor shows a failed scan in its own log, not in the terminal.
|
|
28
|
+
* const keys = await watchKeys("games/timber", { onError: message => log.warn(message) });
|
|
29
|
+
* // features/home/strings/en.json saved without its closing brace: under Bun log.warn gets
|
|
30
|
+
* // "[game] i18n: features/home/strings/en.json could not be read: JSON Parse error: Expected '}'.\n Fix the message or use a supported ICU feature."
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
onError?: (message: string) => void;
|
|
34
|
+
};
|
|
35
|
+
//#endregion
|
|
1
36
|
//#region src/cli.d.ts
|
|
2
37
|
/**
|
|
3
38
|
* What the dev page of `preparePage` is written with besides the game.
|
|
@@ -50,8 +85,10 @@ declare function runCli(argv: readonly string[]): Promise<number>;
|
|
|
50
85
|
/**
|
|
51
86
|
* Writes a game's dev page into `<root>/.moku/` for a server the caller starts: `index.html`,
|
|
52
87
|
* `dev.ts`, `main.ts` with the scenarios of `tests/scenarios/` (and, with agents, the agents and
|
|
53
|
-
* the game's `.dev` modules), and `bunfig.toml` with the engine's hot plugin. It
|
|
54
|
-
*
|
|
88
|
+
* the game's `.dev` modules), and `bunfig.toml` with the engine's hot plugin. It also writes the
|
|
89
|
+
* first `assets-stamp.ts`, the empty one, when the game has none: `main.ts` imports it, and
|
|
90
|
+
* `watchKeys` rewrites it when an asset file changes. It starts no server and no watcher, and
|
|
91
|
+
* throws the `[game]` errors of `moku-game dev`.
|
|
55
92
|
*
|
|
56
93
|
* @param root - The game folder, relative to the cwd or absolute.
|
|
57
94
|
* @param options - The agents, the preloads and the extra bundler plugins.
|
|
@@ -67,5 +104,32 @@ declare function runCli(argv: readonly string[]): Promise<number>;
|
|
|
67
104
|
* ```
|
|
68
105
|
*/
|
|
69
106
|
declare function preparePage(root: string, options?: PreparePageOptions): Promise<PreparedPage>;
|
|
107
|
+
/**
|
|
108
|
+
* Keeps `generated/` of a game fresh while its dev page is open, for a server the caller runs:
|
|
109
|
+
* the editor calls it next to `preparePage`, and raw `moku-game dev` runs the same watch itself.
|
|
110
|
+
* It watches the game folder, runs the scan of `moku-game keys` once and resolves after it. Then
|
|
111
|
+
* a save of an asset file (`.png`, `.webp`, `.fnt`, `.mp3`, `.m4a`) or of a
|
|
112
|
+
* `strings/<locale>.json` scans again, with the same flags, outputs and layers; an output that
|
|
113
|
+
* did not change is not rewritten. On the page a rewritten `generated/strings.<locale>.ts` hot
|
|
114
|
+
* swaps. An asset file that is new, gone or saved again rewrites `.moku/assets-stamp.ts`, which
|
|
115
|
+
* the page imports, so the page reloads and shows the new image or the new bytes of an old one. A
|
|
116
|
+
* failed scan goes to `onError` and the watch goes on, the first scan too. The layers of
|
|
117
|
+
* `config.ts` are read once: a changed layer needs a new `watchKeys`.
|
|
118
|
+
*
|
|
119
|
+
* @param root - The game folder, relative to the cwd or absolute.
|
|
120
|
+
* @param options - Where the message of a failed scan goes.
|
|
121
|
+
* @returns The running watch; `close()` stops it.
|
|
122
|
+
* @throws {Error} When the game has no `config.ts` or `index.ts`, or a config value is refused.
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* // The editor bin, next to preparePage, started with --root games/timber:
|
|
126
|
+
* const { preparePage, watchKeys } = await import(Bun.resolveSync("@moku-labs/game/cli", root));
|
|
127
|
+
* await preparePage("games/timber", { agents: ["@moku-labs/editor/agent/page"] });
|
|
128
|
+
* const keys = await watchKeys("games/timber", { onError: message => log.warn(message) });
|
|
129
|
+
* // generated/ is fresh; a save of features/home/strings/en.json rewrites generated/strings.en.ts
|
|
130
|
+
* keys.close(); // when the editor closes the game
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
declare function watchKeys(root: string, options?: WatchKeysOptions): Promise<KeysWatcher>;
|
|
70
134
|
//#endregion
|
|
71
|
-
export { PreparePageOptions, PreparedPage, preparePage, runCli };
|
|
135
|
+
export { type KeysWatcher, PreparePageOptions, PreparedPage, type WatchKeysOptions, preparePage, runCli, watchKeys };
|