@volter/play 0.5.212 → 0.5.213

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 CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  A Cyclotron game is a [volter-ai/std](https://github.com/volter-ai/std) game: three.js, React Three Fiber, Rapier and
4
4
  Colyseus, used as their own docs describe them, with std adding only what they lack. This repository pins std as
5
- `external/std`. Play runs the game itself, on its own dev server: each player is one of the game's pages, a std device,
6
- standing in the model document's stage.
5
+ `external/std`. Play is the project's, as an engine's Play button is, whatever document is in front: it runs the game
6
+ itself, on its own dev server, each player one of the game's pages, a std device, in the Game view.
7
7
 
8
8
  ## A std game
9
9
 
@@ -12,20 +12,35 @@ A project with `std.json` that depends on `@volter-ai/std-dev` is a std game (`s
12
12
  runs `std new` into an existing project and moves its `src/models/*.blend` into `levels/`. Either installs the game's
13
13
  dependencies with pnpm, as std's README does; the editor hears `std.json` arrive and needs no reload.
14
14
 
15
- Pressing Play on a level saves its `.blend` first (editor-blender's `modelDocument.flush`) and waits for std's export of
16
- it (`src/std-level.ts`), so the game plays the current edit. Play then starts the game's dev server where none runs
17
- (`npm run dev -- --no-open`, owned by the session and ended with it), finds it by the record std writes in Vite's
18
- cacheDir (`node_modules/.vite/std-dev.json`, whose token stays in the session), and stands each player in the stage
19
- as an iframe.
20
-
21
- - **The view bar**, over the viewport: Edit, Player N (each "you" or "autopilot"), Grid (Edit and every player tiled,
22
- each player's tile its whole view scaled down, as its page lays out at the stage's size in every view; a tile clicked
23
- opens it) and Players [-][+], each one a client joining or leaving. Edit brings the level's own area
24
- back, live for editing, while the game runs on.
25
- - **The keys** 1 to 4 open Player N, Tab the next view and Escape Edit (Escape in Edit stops the game), whenever the
26
- editor holds the keyboard: in Edit, in Grid, or after a press on the view bar. A viewed player's page holds the
27
- keyboard, and its keys, 1 to 4 included, are the game's, as Unity's Multiplayer Play Mode and Unreal's Play In
28
- Editor treat a focused game window.
15
+ The project opens on its main level (`levels/MainLevel.tsx`, else the level last worked on), a document that stays
16
+ the level as authored. Play, in the Game panel under every document, saves the edit Blender holds first
17
+ (editor-blender's `modelDocument.flush`) and waits for std's export of it (`src/std-level.ts`), so the game plays the
18
+ current edit (`src/game-controls.ts`). It then opens the Game view (`src/game-view.tsx`) as a tab of the editor,
19
+ in front, starts the game's dev server where none runs (`npm run dev -- --no-open`, owned by the session and ended with
20
+ it), finds it by the record std writes in Vite's cacheDir (`node_modules/.vite/std-dev.json`, whose token stays in the
21
+ session), and stands each player in the Game view as an iframe. Another tab in front never stops the game; Stop, or the
22
+ Game view closed, does, and brings back the tab that was in front. The players' pages draw in the Game view's
23
+ retained layer (`@volter/sdk/document-layer`), mounted in the workbench's container and laid over the Game view's box
24
+ while that box is shown (hidden, and its pages throttled, while it is not), as Code-OSS keeps a webview that retains
25
+ its context: a tab's box is parked out of the page while it is behind another, and a frame moved with it would load
26
+ again.
27
+
28
+ - **The view bar**, at the top of the Game view: Scene, Player N (each "you" or "autopilot"), and Grid (Scene and every
29
+ player tiled, each player's tile its whole view scaled down, as its page lays out at the view's size in every view;
30
+ a tile clicked opens it).
31
+ - **Scene** is the current level (the level document in front last) live: the same level view, drawn again in the Game
32
+ view and put each frame on the game's running scene, read where it runs (std-dev's `GET /__std/scene`, through
33
+ `GET /__editor/play/std/scene`: the world the game's server runs, else the scene the viewed player's page renders, a
34
+ game of one player's among them) by std's node put (`contributions/std-level.document.tsx`'s `useRunningScene`,
35
+ `serving/std-scene-runtime.js`'s `SceneNodes`); an object the copy lacks (a character) stands as an empty of its name.
36
+ The level's own document stays the level as authored, beside it.
37
+ - **Players [-][+]**, in the Game panel beside Play: how many play, the project's setting `volter.play.players` (one
38
+ where it is unset), which it writes to the project's settings; a running game's players join or leave to match
39
+ whenever the setting changes.
40
+ - **The keys** 1 to 4 open Player N and Tab the next view, while the Game view is in front and the editor holds the
41
+ keyboard: in Scene, in Grid, or after a press on the view bar. A viewed player's page holds the keyboard, and its
42
+ keys, 1 to 4 included, are the game's, as Unity's Multiplayer Play Mode and Unreal's Play In Editor treat a focused
43
+ game window.
29
44
  - **Each player's page** is told apart by the slot its address names (`?slot=<run>-<n>`), which its trace's first
30
45
  line says; a page that loads again is found again by it. A player whose page never joins is taken out, and its
31
46
  failure stands.
@@ -41,7 +56,7 @@ through `src/std-controls.ts` and the session's route, which holds the dev serve
41
56
  | `clock` (`pause`, `resume`, `step`, `speed`) | The Game panel's pause, step and speed, sent to every joined player's page; the panel shows the clock std answers |
42
57
  | `autoplay`, `manual` | Who drives the viewed player: its bot, with its slot and goal, or the person |
43
58
  | `inspect` | `editor.inspect` while a player is in view: the page's live three.js objects and labelled screen nodes |
44
- | `act` | `editor.document.key` with no selector, and `editor.document.click('role=<role>[name="<name>"]')` (the page's labelled node pressed at its middle), while a player is in view: std-driver/2 actions through the page's own input |
59
+ | `act` | `editor.document.key` with no selector, and `editor.document.click('role=<role>[name="<name>"]')` (the page's labelled node pressed at its middle), while a player is in view: std-driver/3 actions through the page's own input |
45
60
  | `capture` | `capture --region play`: the viewed page's next frame, written by std's receiver |
46
61
 
47
62
  `editor.document.query` answers the editor's DOM as always and, beside it, the viewed page's labelled nodes
@@ -54,27 +69,40 @@ keeps running while the pages are paused.
54
69
 
55
70
  The game's bot is its own program, `autopilot/index.ts`, whose goals are named by words (std's `autopilot({ goals })`).
56
71
  Play lists them from the session's route `/__editor/play/std/goals`, which loads that program in Node as std does.
57
- The Game panel's Autoplay turns the viewed player's bot on with the goal the panel picks, and armed while stopped turns
58
- it on as the run starts; the person's own key or click in its page takes over. `cyclotron play autoplay on [<goal>]` is
59
- std's own headless play of that goal (`/__std/play`): its bot pages, out of view, play the goal to its end whether or not
60
- the editor is seen, the viewed player and the panel's goal untouched, and `play state`'s `autoplay.state` and the play
61
- log's `autoplay-end` say how it ended. Every other player is a bot from the start.
72
+ Autoplay, the Game panel's and `cyclotron play autoplay on [<goal>]` alike, is std's own play of a goal
73
+ (`/__std/play`), recorded and checked, on the device std's play takes where one is linked: the viewed player's page
74
+ while the Game view is on screen, which std drives as it is and hands back to the person as the goal ends, and std's
75
+ headless device otherwise (the editor not seen, or the Game view behind another tab; an agent's, or an arm's, also
76
+ while no player is viewed, where the panel's waits for one). The person's
77
+ own key or click in the page takes it over, which ends the goal there, failed, as Autoplay off does; armed while
78
+ stopped, Autoplay plays as the run starts. One plays at a time. `play state`'s `autoplay.state` (with how the goal's
79
+ checks went, as std said it) and the play log's `autoplay-end` say how it ended; `autoplay.report` is its report.
80
+ Every other player is the game's bot from the start, playing the run's goal.
62
81
 
63
82
  ## The play log
64
83
 
65
84
  Each player's page traces its run (std's trace, `build/runs/<run>/<page>.jsonl`), and the run reads each trace into
66
- the document's play log, each entry tagged with its player's slot (`source: 'script'`). Play adds its own entries
85
+ the play log, each entry tagged with its player's slot (`source: 'script'`). Play adds its own entries
67
86
  (`source: 'play'`): `play-start`, `running`, `player-joined`, `player-page-loaded`, `player-left`, `view`,
68
87
  `autoplay-on` and `autoplay-off` (with `by`), `pause`, `resume`, `step` and `speed` (each with the clock std answered),
69
- `capture`, `script-error` (with its `phase`) and `play-stop`. Entries carry the run's clock as std last answered it.
70
-
71
- A room's exceptions are not in any page's trace: Colyseus logs them on the dev server's error output (stderr), with
72
- Vite's errors and warnings. Of a dev server Play started, each run reads that output from the run's start
73
- (`/__editor/play/std/errors`) in blocks, a line and the indented lines under it: a block that names an `Error` or
74
- carries a stack is a `script-error` with the phase `server` and an error in the console, once by its first line; any
75
- other is a `server-output` entry.
76
-
77
- One log per model document, each its latest run's; each Play replaces it, and it outlives Stop. The newest entries are
88
+ `capture`, `script-error` (with its `phase`) and `play-stop`. A page's entry carries its trace's step as `tick`
89
+ (std's trace format 3, `s`: sixty a game second from the trace's start, since std's live clock is the page's
90
+ `performance.now`) and that step in seconds as `simT`; Play's own carry the run's elapsed seconds and the newest step
91
+ heard. A page writes a trace line only as something happens on it (an input, a word said, its bot's intent; a clock
92
+ control writes none), so its step is when it last traced, not its clock now. `play state`'s clock says which reading it
93
+ gives (`from`): while the game is held, `std-answer`, std's exact answer to the `pause` or `step`, the same clock its
94
+ play-log entry records; while it runs, `newest-traced-step`, the newest step the viewed player's page traced, which
95
+ holds while that page is idle. After Stop it keeps the run's last reading and its `from`, with `running` false, so
96
+ `play state` still says how far the run got (the panel says only that it stopped).
97
+
98
+ What a room says is not in any page's trace: the room runs in the dev server's process, so its own `console.log` is on
99
+ that server's stdout, with Vite's notices, and the exceptions Colyseus logs on its stderr, with Vite's errors and
100
+ warnings. Of a dev server Play started, each run reads both streams from the run's start (`/__editor/play/std/output`),
101
+ each kept apart: each stdout line is a `server-output` entry; stderr is read in blocks, a line and the indented lines
102
+ under it, and a block that names an `Error` or carries a stack is a `script-error` with the phase `server` and an
103
+ error in the console, once by its first line, any other a `server-output` entry.
104
+
105
+ One log, the latest run's: each Play replaces it, and it outlives Stop. The newest entries are
78
106
  kept in a bounded ring (older ones counted as `dropped`). `console.log` does not reach the session's console feed;
79
107
  the play log does.
80
108
 
@@ -82,18 +110,17 @@ the play log does.
82
110
  cyclotron play-log # every kept entry, one per line
83
111
  cyclotron play-log --kind coin # one kind
84
112
  cyclotron play-log --since 12.5 --json # entries at or after 12.5 s, as JSON
85
- cyclotron play-log --document <id> # another model document's log
86
113
  ```
87
114
 
88
115
  ## Controls
89
116
 
90
- The model document's Play is registered through editor-blender's API (`registerModelPlay`) from play's page half
91
- (`contributions/play.page.tsx`), and drawn by play's Game panel in the bottom area. The panel's controls are also
92
- commands, so an agent drives the same run the person sees: `cyclotron play play|stop|pause|resume|restart`,
117
+ play's page half (`contributions/play.page.tsx`) registers its Game panel through editor-blender's API
118
+ (`registerPlay`), whose bottom area shows it under every document, and below a model in its Game mode (a model's
119
+ Animation mode is Blender's animation editors). The panel's controls are also commands (`volter.play.<verb>`), so an agent drives the same run the person sees: `cyclotron play play|stop|pause|resume|restart`,
93
120
  `play step [count]`, `play speed <0.25|0.5|1|2|4>`, `play mode [game|animation]` and `play autoplay on [<goal>]|off`,
94
121
  each answering with the panel's state.
95
122
 
96
- A std game's Export (the panel's button and menu; `volter.model-play.export { target, add? }` under `eval`) builds the
123
+ A std game's Export (the panel's button and menu; `volter.play.export { target, add? }` under `eval`) builds the
97
124
  game for the web (`std build`, into `dist/`) or exports it to an engine (`std export --target <engine>`). An engine not
98
125
  yet one of the game's targets is offered as "Add Roblox and export", which adds it first (`std target add <engine>`: its
99
126
  package installed, its `std.json` settings and its scripts); the verb refuses one unless `add` is true. A game is built
@@ -104,7 +131,8 @@ std prints goes to the console, and the panel says how the export stands and whe
104
131
 
105
132
  A std game carries no editor code. Play supplies its adapter (`src/std-game-adapter.ts`, declared in
106
133
  `contributes.volter.projectAdapters` for a project with `std.json`): Blender's layout, keymap and properties inspector,
107
- with every `.blend` under `levels/` as a document. A project's own `editor/volter.adapter.ts` wins over it.
134
+ with every `.blend` under `levels/` and `prefabs/`, and each level, as a document, the main level the one it opens
135
+ on. A project's own `editor/volter.adapter.ts` wins over it.
108
136
 
109
137
  ## A level's export
110
138
 
@@ -113,26 +141,29 @@ Blender half, std-dev's `blender/blend-to-scene.py`, is the save's own script (e
113
141
  `modelDocument.setSaveScript`): it runs in the save's turn, on the very scene that save wrote, and the save's answer
114
142
  carries the files it wrote (`levels/<name>.glb`, its description, a copied sky image, a baked `<name>.view.cube`).
115
143
  Then, one save after another, those files are carried into the project and the Node half,
116
- `std level <levels/name.glb> --description <levels/name.level.json>`, runs in the game's folder at the session route
144
+ `std level-scene <levels/name.glb>`, runs in the game's folder at the session route
117
145
  `/__editor/play/std/level`, by the game's own std, and writes `<Name>Level.tsx`, `<name>.canvas.ts`, the environment
118
- and grading. std's dev server takes the level by its own hot reload. Both halves' output is the console's
119
- (`std-level`); a half that fails is an error there.
146
+ and grading. std's dev server takes the level from there, its rooms reloaded by Colyseus's own dev mode. Both halves'
147
+ output is the console's (`std-level`); a half that fails is an error there.
120
148
 
121
149
  The game's `prefabs/` folder is a Blender asset library named Prefabs whose import method is Link
122
150
  (editor-blender's `setAssetLibrary`), so a prefab dragged from it is linked, not appended.
123
151
 
124
- ## A level's Scene view
152
+ ## A level's document
125
153
 
126
- "Play: Open Scene View" (`volter.std-scene { level? }`) opens the std level whose `.blend` was active last, or the
127
- `levels/<name>.blend` it names, drawn as the game draws it: its generated component, its environment, its canvas's tone
128
- mapping and shadows and its view transform, with the game's own React Three Fiber, react-three-rapier and std, in
129
- editor-threejs's viewport (`contributions/std-scene.document.tsx`; its module, `/@volter-std-scene/<levels/name.blend>`,
130
- is `serving/std-scene.ts`). Overlays draws colliders and sensors and signs each std marker with its name. The view edits
131
- nothing: the `.blend` is the level's source, and the view draws the level again as each save exports it
132
- (`docs/adr/std-scene-view.md`).
154
+ A level is the document an engine opens. Each level component, `levels/<Name>Level.tsx`, is a document of its own
155
+ (`std-level`, listed by `contributions/levels.finder.ts`), named as its component is less `Level` (`MainLevel` is Main)
156
+ and drawn as the game draws it, by its own component and the game's own React Three Fiber, react-three-rapier and std,
157
+ in editor-threejs's viewport (`contributions/std-level.document.tsx`; its module, `/@volter-std-scene/<source>`, is
158
+ `serving/std-scene.ts`). Its
159
+ source is its own code, or the `levels/<name>.blend` std's export writes it from (a Blender level's environment, canvas
160
+ and grading drawn with it), which stays the Blender document it is authored in. Overlays draws colliders and sensors
161
+ and signs each std marker with its name. The view edits nothing, and draws the level again as anything it depends on
162
+ changes (`docs/adr/std-scene-view.md`). It is the level as authored, while the game runs too; the Game view's Scene is
163
+ the same view, live.
133
164
 
134
165
  ## Outside the editor
135
166
 
136
167
  `cyclotron export web|roblox|unreal` runs the game's own `std build` or `std export --target <engine>`, which refuses an
137
- engine that is not one of the game's targets, naming `std target add` (std's guide,
138
- `node_modules/@volter-ai/std-dev/docs/03-targets.md`).
168
+ engine that is not one of the game's targets, naming `std target add` (std's guide in
169
+ `node_modules/@volter-ai/std-dev/docs/`, "Targets").