@vgai/engine 0.5.12 → 0.5.14
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/adapter/adapter-module.d.ts +447 -0
- package/dist/adapter/adapter-module.d.ts.map +1 -0
- package/dist/adapter/adapter-module.js +308 -0
- package/dist/adapter/authoring.d.ts +357 -10
- package/dist/adapter/authoring.d.ts.map +1 -1
- package/dist/adapter/authoring.js +87 -1
- package/dist/adapter/constraint.d.ts +9 -3
- package/dist/adapter/constraint.d.ts.map +1 -1
- package/dist/adapter/finders/finder-result.d.ts +28 -0
- package/dist/adapter/finders/finder-result.d.ts.map +1 -0
- package/dist/adapter/finders/finder-result.js +10 -0
- package/dist/adapter/finders/index.d.ts +38 -0
- package/dist/adapter/finders/index.d.ts.map +1 -0
- package/dist/adapter/finders/index.js +41 -0
- package/dist/adapter/finders/prefabs-from-stories.d.ts +64 -0
- package/dist/adapter/finders/prefabs-from-stories.d.ts.map +1 -0
- package/dist/adapter/finders/prefabs-from-stories.js +92 -0
- package/dist/adapter/finders/scenes-from-entrypoint-selection.d.ts +67 -0
- package/dist/adapter/finders/scenes-from-entrypoint-selection.d.ts.map +1 -0
- package/dist/adapter/finders/scenes-from-entrypoint-selection.js +226 -0
- package/dist/adapter/first-party-systems.d.ts.map +1 -1
- package/dist/adapter/first-party-systems.js +29 -0
- package/dist/adapter/index.d.ts +7 -3
- package/dist/adapter/index.d.ts.map +1 -1
- package/dist/adapter/index.js +5 -2
- package/dist/adapter/ingest/contract-system-adapters.d.ts +24 -1
- package/dist/adapter/ingest/contract-system-adapters.d.ts.map +1 -1
- package/dist/adapter/ingest/contract-system-adapters.js +100 -34
- package/dist/adapter/ingest/game-contract.d.ts +188 -2
- package/dist/adapter/ingest/game-contract.d.ts.map +1 -1
- package/dist/adapter/ingest/game-contract.js +107 -0
- package/dist/adapter/ingest/mount-readiness.d.ts +84 -0
- package/dist/adapter/ingest/mount-readiness.d.ts.map +1 -0
- package/dist/adapter/ingest/mount-readiness.js +81 -0
- package/dist/adapter/ingest/scene-capture.d.ts +91 -2
- package/dist/adapter/ingest/scene-capture.d.ts.map +1 -1
- package/dist/adapter/ingest/scene-capture.js +110 -18
- package/dist/adapter/ingest/structural-ids.d.ts +11 -5
- package/dist/adapter/ingest/structural-ids.d.ts.map +1 -1
- package/dist/adapter/ingest/structural-ids.js +18 -9
- package/dist/adapter/ingest/upstream-pin.d.ts +4 -2
- package/dist/adapter/ingest/upstream-pin.d.ts.map +1 -1
- package/dist/adapter/ingest/upstream-pin.js +4 -2
- package/dist/adapter/ingest/visible-capture-window.d.ts +116 -0
- package/dist/adapter/ingest/visible-capture-window.d.ts.map +1 -0
- package/dist/adapter/ingest/visible-capture-window.js +141 -0
- package/dist/adapter/loop-gate-report.d.ts +3 -4
- package/dist/adapter/loop-gate-report.d.ts.map +1 -1
- package/dist/adapter/loop-gate-report.js +3 -4
- package/dist/adapter/root-adapter.d.ts +22 -2
- package/dist/adapter/root-adapter.d.ts.map +1 -1
- package/dist/adapter/setup-three-root-adapter.d.ts.map +1 -1
- package/dist/adapter/setup-three-root-adapter.js +15 -0
- package/dist/adapter/system-adapter.d.ts +161 -2
- package/dist/adapter/system-adapter.d.ts.map +1 -1
- package/dist/adapter/system-adapter.js +18 -1
- package/dist/animation/camera-ownership.d.ts +4 -2
- package/dist/animation/camera-ownership.d.ts.map +1 -1
- package/dist/animation/camera-ownership.js +58 -1
- package/dist/animation/runtime-inspection.d.ts +70 -0
- package/dist/animation/runtime-inspection.d.ts.map +1 -0
- package/dist/animation/runtime-inspection.js +25 -0
- package/dist/animation/xstate-animation-binding.d.ts +9 -1
- package/dist/animation/xstate-animation-binding.d.ts.map +1 -1
- package/dist/animation/xstate-animation-binding.js +48 -1
- package/dist/asset-formats/material.d.ts +1 -1
- package/dist/asset-formats/mesh.d.ts +1 -1
- package/dist/asset-formats/particles.d.ts +13 -0
- package/dist/asset-formats/particles.d.ts.map +1 -1
- package/dist/asset-formats/particles.js +28 -0
- package/dist/behavior/xstate-inspection.d.ts +24 -0
- package/dist/behavior/xstate-inspection.d.ts.map +1 -0
- package/dist/behavior/xstate-inspection.js +25 -0
- package/dist/core/game-loop.d.ts +7 -5
- package/dist/core/game-loop.d.ts.map +1 -1
- package/dist/core/game-loop.js +39 -18
- package/dist/core/types.d.ts +11 -12
- package/dist/core/types.d.ts.map +1 -1
- package/dist/data/data-asset.js +1 -1
- package/dist/dev/instruments.d.ts.map +1 -1
- package/dist/dev/instruments.js +5 -1
- package/dist/dev/render-debug-adapter.d.ts +19 -2
- package/dist/dev/render-debug-adapter.d.ts.map +1 -1
- package/dist/dev/render-debug-adapter.js +10 -0
- package/dist/ecs/user-data.d.ts +10 -2
- package/dist/ecs/user-data.d.ts.map +1 -1
- package/dist/ecs/user-data.js +6 -2
- package/dist/input/binding-identity.d.ts +10 -0
- package/dist/input/binding-identity.d.ts.map +1 -0
- package/dist/input/binding-identity.js +36 -0
- package/dist/input/input-manager.d.ts +18 -185
- package/dist/input/input-manager.d.ts.map +1 -1
- package/dist/input/input-manager.js +78 -68
- package/dist/manifest/load.d.ts +14 -0
- package/dist/manifest/load.d.ts.map +1 -1
- package/dist/manifest/load.js +6 -1
- package/dist/manifest/schema.d.ts +18 -0
- package/dist/manifest/schema.d.ts.map +1 -1
- package/dist/manifest/schema.js +64 -7
- package/dist/pixi/authoring.d.ts +27 -0
- package/dist/pixi/authoring.d.ts.map +1 -1
- package/dist/pixi/authoring.js +10 -3
- package/dist/pixi/index.d.ts +1 -1
- package/dist/pixi/index.d.ts.map +1 -1
- package/dist/pixi/index.js +1 -1
- package/dist/pixi/ingest.d.ts +8 -0
- package/dist/pixi/ingest.d.ts.map +1 -1
- package/dist/pixi/ingest.js +10 -1
- package/dist/pixi/render-pass-bracket.d.ts +56 -0
- package/dist/pixi/render-pass-bracket.d.ts.map +1 -0
- package/dist/pixi/render-pass-bracket.js +98 -0
- package/dist/pixi/scene-capture.d.ts +32 -1
- package/dist/pixi/scene-capture.d.ts.map +1 -1
- package/dist/pixi/scene-capture.js +21 -9
- package/dist/pixi/system-adapters.d.ts +29 -0
- package/dist/pixi/system-adapters.d.ts.map +1 -1
- package/dist/pixi/system-adapters.js +27 -0
- package/dist/render/particles-factory.d.ts +16 -2
- package/dist/render/particles-factory.d.ts.map +1 -1
- package/dist/render/particles-factory.js +88 -5
- package/dist/render/soft-particle-depth.d.ts +149 -0
- package/dist/render/soft-particle-depth.d.ts.map +1 -0
- package/dist/render/soft-particle-depth.js +305 -0
- package/dist/render/voxel-surface.d.ts +117 -0
- package/dist/render/voxel-surface.d.ts.map +1 -0
- package/dist/render/voxel-surface.js +263 -0
- package/dist/runtime/create-runtime.js +7 -0
- package/dist/runtime/debug-bridge.d.ts +15 -15
- package/dist/runtime/debug-bridge.d.ts.map +1 -1
- package/dist/runtime/debug-bridge.js +27 -26
- package/dist/runtime/game.d.ts.map +1 -1
- package/dist/runtime/game.js +1 -2
- package/dist/setup/setup-particles.d.ts.map +1 -1
- package/dist/setup/setup-particles.js +9 -0
- package/dist/world3d-react/r3f-adapter.d.ts.map +1 -1
- package/dist/world3d-react/r3f-adapter.js +42 -3
- package/dist/world3d-react/rapier-physics-bridge.d.ts.map +1 -1
- package/dist/world3d-react/rapier-physics-bridge.js +201 -11
- package/dist-config/config.js.map +1 -1
- package/package.json +4 -2
- package/schemas/engine-capabilities.json +12 -12
- package/schemas/vgai-project.schema.json +41 -2
- package/src/adapter/adapter-module.ts +607 -0
- package/src/adapter/authoring.ts +440 -10
- package/src/adapter/constraint.ts +10 -3
- package/src/adapter/finders/finder-result.ts +29 -0
- package/src/adapter/finders/index.ts +62 -0
- package/src/adapter/finders/prefabs-from-stories.ts +142 -0
- package/src/adapter/finders/scenes-from-entrypoint-selection.ts +304 -0
- package/src/adapter/first-party-systems.ts +30 -0
- package/src/adapter/index.ts +32 -1
- package/src/adapter/ingest/contract-system-adapters.ts +116 -32
- package/src/adapter/ingest/game-contract.ts +265 -2
- package/src/adapter/ingest/mount-readiness.ts +140 -0
- package/src/adapter/ingest/scene-capture.ts +199 -22
- package/src/adapter/ingest/structural-ids.ts +21 -9
- package/src/adapter/ingest/upstream-pin.ts +4 -2
- package/src/adapter/ingest/visible-capture-window.ts +213 -0
- package/src/adapter/loop-gate-report.ts +3 -4
- package/src/adapter/root-adapter.ts +22 -2
- package/src/adapter/setup-three-root-adapter.ts +16 -0
- package/src/adapter/system-adapter.ts +188 -2
- package/src/animation/camera-ownership.ts +68 -3
- package/src/animation/runtime-inspection.ts +104 -0
- package/src/animation/xstate-animation-binding.ts +53 -1
- package/src/asset-formats/particles.ts +31 -0
- package/src/behavior/xstate-inspection.ts +51 -0
- package/src/core/game-loop.ts +39 -17
- package/src/core/types.ts +11 -12
- package/src/data/data-asset.ts +1 -1
- package/src/dev/instruments.ts +5 -1
- package/src/dev/render-debug-adapter.ts +22 -2
- package/src/ecs/user-data.ts +10 -2
- package/src/input/binding-identity.ts +37 -0
- package/src/input/input-manager.ts +93 -68
- package/src/manifest/load.ts +23 -2
- package/src/manifest/schema.ts +76 -7
- package/src/pixi/authoring.ts +37 -5
- package/src/pixi/index.ts +2 -0
- package/src/pixi/ingest.ts +15 -2
- package/src/pixi/render-pass-bracket.ts +117 -0
- package/src/pixi/scene-capture.ts +63 -13
- package/src/pixi/system-adapters.ts +41 -0
- package/src/render/particles-factory.ts +89 -6
- package/src/render/soft-particle-depth.ts +336 -0
- package/src/render/voxel-surface.ts +358 -0
- package/src/runtime/create-runtime.ts +7 -0
- package/src/runtime/debug-bridge.ts +32 -31
- package/src/runtime/game.ts +1 -2
- package/src/setup/setup-particles.ts +9 -0
- package/src/world3d-react/r3f-adapter.tsx +48 -2
- package/src/world3d-react/rapier-physics-bridge.tsx +249 -11
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A face-culled surface mesh for a dense grid of cubic cells, as one real `THREE.BufferGeometry`.
|
|
3
|
+
*
|
|
4
|
+
* A game that stores its world as a grid of cubes — terrain a player digs, a builder's block
|
|
5
|
+
* palette, a level authored as a 3D tilemap — cannot draw a `BoxGeometry` per cell: a modest
|
|
6
|
+
* 80×7×80 volume is 44 800 boxes, and the ones buried inside the solid are invisible forever. The
|
|
7
|
+
* fix is a single surface built from only the faces that touch an empty neighbour. That is what
|
|
8
|
+
* this file is, and it is the whole of it.
|
|
9
|
+
*
|
|
10
|
+
* ## It is a HELPER, not a wrapper
|
|
11
|
+
*
|
|
12
|
+
* `buildVoxelSurface` takes plain arrays and hands back three's own `BufferGeometry`. Every call
|
|
13
|
+
* after it is three's API — pick your own material, wrap it in a `Mesh` or an `InstancedMesh`,
|
|
14
|
+
* `.translate()` it, hand it to Rapier's trimesh collider. Nothing here holds a scene, a camera, a
|
|
15
|
+
* frame loop or a cache, and nothing here is a class you inherit from.
|
|
16
|
+
*
|
|
17
|
+
* ## The rung audit that put ~200 lines here instead of a dependency (2026-08-14)
|
|
18
|
+
*
|
|
19
|
+
* Checked against the npm registry on the day this landed, not from memory:
|
|
20
|
+
*
|
|
21
|
+
* - **`voxel-mesh` 0.3.0** (voxel.js) — last publish **2013-06-13**. Its `index.js` builds a
|
|
22
|
+
* `THREE.Geometry` out of `THREE.Face3`, both REMOVED from three in r125. It cannot run against
|
|
23
|
+
* this repo's three at all.
|
|
24
|
+
* - **`voxel-mesher` 0.14.4** (2016-03-26) and **`greedy-mesher` 1.0.3** (2016-02-12) — the
|
|
25
|
+
* voxel.js meshing pair. Both are `ndarray`-shaped, untyped, and stop at a list of quads: the
|
|
26
|
+
* `BufferGeometry` is still yours to write. `voxel-mesher` additionally pulls a WebGL1 buffer
|
|
27
|
+
* stack (`gl-buffer`, `gl-vao`) that has nothing to do with three.
|
|
28
|
+
* - **`voxel-engine` 0.20.2** (2015-04-11) — a whole game framework (20 dependencies, its own
|
|
29
|
+
* camera, controls and physics). The thing this rule bans.
|
|
30
|
+
* - **`@voxelize/core` 3.0.0** (2026-08-03) — the one MAINTAINED option, and the one to say no to
|
|
31
|
+
* deliberately. It is a client for a multiplayer voxel platform: `socket.io-client`, its own
|
|
32
|
+
* wire protocol, its own physics engine and a WASM mesher fed by its own chunk/world objects.
|
|
33
|
+
* You do not call its mesher; you build your game inside it. Adopting it to draw a static grid
|
|
34
|
+
* would put a platform between the game and three.
|
|
35
|
+
*
|
|
36
|
+
* So: every maintained option is an ENGINE you build inside, and every option that is a helper died
|
|
37
|
+
* with voxel.js a decade ago against a three that no longer exists. The general shape *is* ready —
|
|
38
|
+
* "cull the hidden faces of a dense grid" has been settled since 2012 — it is the packaging that is
|
|
39
|
+
* not. Hence a helper here, in host vocabulary, that hands back three's own object.
|
|
40
|
+
*
|
|
41
|
+
* ## What is deliberately NOT here
|
|
42
|
+
*
|
|
43
|
+
* **Greedy meshing.** Merging coplanar same-type faces into larger quads is the standard next step
|
|
44
|
+
* and it does not fall out of this one: it needs a per-slice sweep with its own visited mask and
|
|
45
|
+
* its own bugs, and it changes the vertex↔cell relationship that per-face culling keeps exact.
|
|
46
|
+
* Per-face culling already removes the interior, which is the order-of-magnitude win. Add greedy
|
|
47
|
+
* meshing the day a measured frame budget asks for it, as its own function beside this one.
|
|
48
|
+
*
|
|
49
|
+
* **Lighting, ambient occlusion, textures, atlases, transparency sorting and chunking.** Each is a
|
|
50
|
+
* real decision a game makes for itself; this returns geometry and gets out of the way.
|
|
51
|
+
*/
|
|
52
|
+
import { BufferGeometry } from 'three';
|
|
53
|
+
/**
|
|
54
|
+
* A dense grid of cubic cells.
|
|
55
|
+
*
|
|
56
|
+
* `cells` is indexed **Y-major, then Z, then X** — `((y * sizeZ) + z) * sizeX + x`. Y outermost is
|
|
57
|
+
* the ordering that makes each horizontal LAYER contiguous, which is what lets a mostly-flat world
|
|
58
|
+
* ship as a handful of runs (see {@link expandVoxelRuns}) instead of a megabyte of literals.
|
|
59
|
+
*/
|
|
60
|
+
export interface VoxelVolume {
|
|
61
|
+
/** Cell counts along X, Y and Z. */
|
|
62
|
+
readonly size: readonly [number, number, number];
|
|
63
|
+
/** `sizeX * sizeY * sizeZ` type ids. `0` is empty unless {@link VoxelSurfaceOptions.emptyType}. */
|
|
64
|
+
readonly cells: ArrayLike<number>;
|
|
65
|
+
/** World position of the volume's minimum corner. Defaults to the origin. */
|
|
66
|
+
readonly origin?: readonly [number, number, number];
|
|
67
|
+
/** World edge length of one cell. Defaults to 1. */
|
|
68
|
+
readonly cellSize?: number;
|
|
69
|
+
}
|
|
70
|
+
export interface VoxelSurfaceOptions {
|
|
71
|
+
/**
|
|
72
|
+
* Type id → `0xRRGGBB`, written into the geometry's `color` attribute. Supply it and the mesh
|
|
73
|
+
* draws with `vertexColors: true` in one draw call; omit it and the geometry carries no colour
|
|
74
|
+
* attribute at all. A solid type absent from the map is an ERROR, not a silent default: a
|
|
75
|
+
* missing colour is the shape of a forgotten row, and a mesh that quietly paints it white looks
|
|
76
|
+
* like a lighting bug three files away.
|
|
77
|
+
*/
|
|
78
|
+
readonly colors?: ReadonlyMap<number, number>;
|
|
79
|
+
/** The type id that means "no cell here". Defaults to `0`. */
|
|
80
|
+
readonly emptyType?: number;
|
|
81
|
+
/**
|
|
82
|
+
* Whether cells just outside the volume count as solid. `false` (the default) walls the volume
|
|
83
|
+
* in — the right answer for a standalone model. `true` leaves the boundary open, which is what a
|
|
84
|
+
* chunk meshed beside its neighbours wants.
|
|
85
|
+
*/
|
|
86
|
+
readonly closedBoundary?: boolean;
|
|
87
|
+
}
|
|
88
|
+
export interface VoxelSurface {
|
|
89
|
+
/** Indexed, with `position`, `normal` and (when colours were supplied) `color`. */
|
|
90
|
+
readonly geometry: BufferGeometry;
|
|
91
|
+
/** Faces that survived culling. `vertices` is `4 ×` this, `triangles` `2 ×`. */
|
|
92
|
+
readonly quads: number;
|
|
93
|
+
readonly vertices: number;
|
|
94
|
+
readonly triangles: number;
|
|
95
|
+
/** Cells whose type is not the empty type — the input's own size, for a sanity check. */
|
|
96
|
+
readonly solidCells: number;
|
|
97
|
+
/** Faces contributed per type id, in ascending id order. */
|
|
98
|
+
readonly quadsByType: ReadonlyMap<number, number>;
|
|
99
|
+
}
|
|
100
|
+
export declare class VoxelSurfaceError extends Error {
|
|
101
|
+
constructor(message: string);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Expand `[count, type, count, type, …]` run pairs into a dense cell array.
|
|
105
|
+
*
|
|
106
|
+
* A voxel volume is enormous and almost entirely repetitive, so the compact form is what a game
|
|
107
|
+
* SHIPS — in a source file, in a save, over the wire — and the dense form is what it meshes. The
|
|
108
|
+
* total of the counts must be exactly `cellCount`: a short or long run list is a corrupt volume,
|
|
109
|
+
* and silently padding it with empties would mesh a plausible wrong world.
|
|
110
|
+
*/
|
|
111
|
+
export declare function expandVoxelRuns(runs: ArrayLike<number>, cellCount: number): Uint16Array | Uint32Array;
|
|
112
|
+
/**
|
|
113
|
+
* Build the visible surface of a voxel volume: one indexed `BufferGeometry` carrying every face
|
|
114
|
+
* that touches an empty neighbour, and nothing else.
|
|
115
|
+
*/
|
|
116
|
+
export declare function buildVoxelSurface(volume: VoxelVolume, options?: VoxelSurfaceOptions): VoxelSurface;
|
|
117
|
+
//# sourceMappingURL=voxel-surface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voxel-surface.d.ts","sourceRoot":"","sources":["../../src/render/voxel-surface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,OAAO,EAAmB,cAAc,EAAS,MAAM,OAAO,CAAC;AAE/D;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,mGAAmG;IACnG,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAClC,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACpD,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,YAAY;IAC3B,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,yFAAyF;IACzF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4DAA4D;IAC5D,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnD;AAED,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAkED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EACvB,SAAS,EAAE,MAAM,GAChB,WAAW,GAAG,WAAW,CA2B3B;AA2ED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,mBAAwB,GAChC,YAAY,CA+Dd"}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A face-culled surface mesh for a dense grid of cubic cells, as one real `THREE.BufferGeometry`.
|
|
3
|
+
*
|
|
4
|
+
* A game that stores its world as a grid of cubes — terrain a player digs, a builder's block
|
|
5
|
+
* palette, a level authored as a 3D tilemap — cannot draw a `BoxGeometry` per cell: a modest
|
|
6
|
+
* 80×7×80 volume is 44 800 boxes, and the ones buried inside the solid are invisible forever. The
|
|
7
|
+
* fix is a single surface built from only the faces that touch an empty neighbour. That is what
|
|
8
|
+
* this file is, and it is the whole of it.
|
|
9
|
+
*
|
|
10
|
+
* ## It is a HELPER, not a wrapper
|
|
11
|
+
*
|
|
12
|
+
* `buildVoxelSurface` takes plain arrays and hands back three's own `BufferGeometry`. Every call
|
|
13
|
+
* after it is three's API — pick your own material, wrap it in a `Mesh` or an `InstancedMesh`,
|
|
14
|
+
* `.translate()` it, hand it to Rapier's trimesh collider. Nothing here holds a scene, a camera, a
|
|
15
|
+
* frame loop or a cache, and nothing here is a class you inherit from.
|
|
16
|
+
*
|
|
17
|
+
* ## The rung audit that put ~200 lines here instead of a dependency (2026-08-14)
|
|
18
|
+
*
|
|
19
|
+
* Checked against the npm registry on the day this landed, not from memory:
|
|
20
|
+
*
|
|
21
|
+
* - **`voxel-mesh` 0.3.0** (voxel.js) — last publish **2013-06-13**. Its `index.js` builds a
|
|
22
|
+
* `THREE.Geometry` out of `THREE.Face3`, both REMOVED from three in r125. It cannot run against
|
|
23
|
+
* this repo's three at all.
|
|
24
|
+
* - **`voxel-mesher` 0.14.4** (2016-03-26) and **`greedy-mesher` 1.0.3** (2016-02-12) — the
|
|
25
|
+
* voxel.js meshing pair. Both are `ndarray`-shaped, untyped, and stop at a list of quads: the
|
|
26
|
+
* `BufferGeometry` is still yours to write. `voxel-mesher` additionally pulls a WebGL1 buffer
|
|
27
|
+
* stack (`gl-buffer`, `gl-vao`) that has nothing to do with three.
|
|
28
|
+
* - **`voxel-engine` 0.20.2** (2015-04-11) — a whole game framework (20 dependencies, its own
|
|
29
|
+
* camera, controls and physics). The thing this rule bans.
|
|
30
|
+
* - **`@voxelize/core` 3.0.0** (2026-08-03) — the one MAINTAINED option, and the one to say no to
|
|
31
|
+
* deliberately. It is a client for a multiplayer voxel platform: `socket.io-client`, its own
|
|
32
|
+
* wire protocol, its own physics engine and a WASM mesher fed by its own chunk/world objects.
|
|
33
|
+
* You do not call its mesher; you build your game inside it. Adopting it to draw a static grid
|
|
34
|
+
* would put a platform between the game and three.
|
|
35
|
+
*
|
|
36
|
+
* So: every maintained option is an ENGINE you build inside, and every option that is a helper died
|
|
37
|
+
* with voxel.js a decade ago against a three that no longer exists. The general shape *is* ready —
|
|
38
|
+
* "cull the hidden faces of a dense grid" has been settled since 2012 — it is the packaging that is
|
|
39
|
+
* not. Hence a helper here, in host vocabulary, that hands back three's own object.
|
|
40
|
+
*
|
|
41
|
+
* ## What is deliberately NOT here
|
|
42
|
+
*
|
|
43
|
+
* **Greedy meshing.** Merging coplanar same-type faces into larger quads is the standard next step
|
|
44
|
+
* and it does not fall out of this one: it needs a per-slice sweep with its own visited mask and
|
|
45
|
+
* its own bugs, and it changes the vertex↔cell relationship that per-face culling keeps exact.
|
|
46
|
+
* Per-face culling already removes the interior, which is the order-of-magnitude win. Add greedy
|
|
47
|
+
* meshing the day a measured frame budget asks for it, as its own function beside this one.
|
|
48
|
+
*
|
|
49
|
+
* **Lighting, ambient occlusion, textures, atlases, transparency sorting and chunking.** Each is a
|
|
50
|
+
* real decision a game makes for itself; this returns geometry and gets out of the way.
|
|
51
|
+
*/
|
|
52
|
+
import { BufferAttribute, BufferGeometry, Color } from 'three';
|
|
53
|
+
export class VoxelSurfaceError extends Error {
|
|
54
|
+
constructor(message) {
|
|
55
|
+
super(message);
|
|
56
|
+
this.name = 'VoxelSurfaceError';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The six faces of the unit cell, each as four corners in counter-clockwise order seen from
|
|
61
|
+
* OUTSIDE — which is the winding three's default `FrontSide` draws.
|
|
62
|
+
*/
|
|
63
|
+
const FACES = [
|
|
64
|
+
{
|
|
65
|
+
normal: [1, 0, 0],
|
|
66
|
+
corners: [
|
|
67
|
+
[1, 0, 1],
|
|
68
|
+
[1, 0, 0],
|
|
69
|
+
[1, 1, 0],
|
|
70
|
+
[1, 1, 1],
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
normal: [-1, 0, 0],
|
|
75
|
+
corners: [
|
|
76
|
+
[0, 0, 0],
|
|
77
|
+
[0, 0, 1],
|
|
78
|
+
[0, 1, 1],
|
|
79
|
+
[0, 1, 0],
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
normal: [0, 1, 0],
|
|
84
|
+
corners: [
|
|
85
|
+
[0, 1, 1],
|
|
86
|
+
[1, 1, 1],
|
|
87
|
+
[1, 1, 0],
|
|
88
|
+
[0, 1, 0],
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
normal: [0, -1, 0],
|
|
93
|
+
corners: [
|
|
94
|
+
[0, 0, 0],
|
|
95
|
+
[1, 0, 0],
|
|
96
|
+
[1, 0, 1],
|
|
97
|
+
[0, 0, 1],
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
normal: [0, 0, 1],
|
|
102
|
+
corners: [
|
|
103
|
+
[0, 0, 1],
|
|
104
|
+
[1, 0, 1],
|
|
105
|
+
[1, 1, 1],
|
|
106
|
+
[0, 1, 1],
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
normal: [0, 0, -1],
|
|
111
|
+
corners: [
|
|
112
|
+
[1, 0, 0],
|
|
113
|
+
[0, 0, 0],
|
|
114
|
+
[0, 1, 0],
|
|
115
|
+
[1, 1, 0],
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
/**
|
|
120
|
+
* Expand `[count, type, count, type, …]` run pairs into a dense cell array.
|
|
121
|
+
*
|
|
122
|
+
* A voxel volume is enormous and almost entirely repetitive, so the compact form is what a game
|
|
123
|
+
* SHIPS — in a source file, in a save, over the wire — and the dense form is what it meshes. The
|
|
124
|
+
* total of the counts must be exactly `cellCount`: a short or long run list is a corrupt volume,
|
|
125
|
+
* and silently padding it with empties would mesh a plausible wrong world.
|
|
126
|
+
*/
|
|
127
|
+
export function expandVoxelRuns(runs, cellCount) {
|
|
128
|
+
if (runs.length % 2 !== 0) {
|
|
129
|
+
throw new VoxelSurfaceError(`a run list is [count, type] pairs, so its length must be even; got ${runs.length}`);
|
|
130
|
+
}
|
|
131
|
+
let widest = 0;
|
|
132
|
+
let total = 0;
|
|
133
|
+
for (let pair = 0; pair < runs.length; pair += 2) {
|
|
134
|
+
const count = runs[pair];
|
|
135
|
+
if (!Number.isInteger(count) || count <= 0) {
|
|
136
|
+
throw new VoxelSurfaceError(`run ${pair / 2} has a count of ${count}; counts are positive`);
|
|
137
|
+
}
|
|
138
|
+
total += count;
|
|
139
|
+
widest = Math.max(widest, runs[pair + 1]);
|
|
140
|
+
}
|
|
141
|
+
if (total !== cellCount) {
|
|
142
|
+
throw new VoxelSurfaceError(`the runs cover ${total} cells; the volume holds ${cellCount}`);
|
|
143
|
+
}
|
|
144
|
+
const cells = widest > 0xffff ? new Uint32Array(cellCount) : new Uint16Array(cellCount);
|
|
145
|
+
let at = 0;
|
|
146
|
+
for (let pair = 0; pair < runs.length; pair += 2) {
|
|
147
|
+
const count = runs[pair];
|
|
148
|
+
cells.fill(runs[pair + 1], at, at + count);
|
|
149
|
+
at += count;
|
|
150
|
+
}
|
|
151
|
+
return cells;
|
|
152
|
+
}
|
|
153
|
+
/** The volume's size, after checking that the cell array is exactly the size it claims. */
|
|
154
|
+
function assertVolumeShape(volume) {
|
|
155
|
+
const [sizeX, sizeY, sizeZ] = volume.size;
|
|
156
|
+
if (sizeX <= 0 || sizeY <= 0 || sizeZ <= 0) {
|
|
157
|
+
throw new VoxelSurfaceError(`a volume needs a positive size on every axis; got ${volume.size}`);
|
|
158
|
+
}
|
|
159
|
+
const cellCount = sizeX * sizeY * sizeZ;
|
|
160
|
+
if (volume.cells.length !== cellCount) {
|
|
161
|
+
throw new VoxelSurfaceError(`a ${sizeX}×${sizeY}×${sizeZ} volume holds ${cellCount} cells; got ${volume.cells.length}`);
|
|
162
|
+
}
|
|
163
|
+
return [sizeX, sizeY, sizeZ];
|
|
164
|
+
}
|
|
165
|
+
/** The linear-space vertex colour for one type, or `undefined` when colours were not asked for. */
|
|
166
|
+
function vertexColor(colors, type, where, into) {
|
|
167
|
+
if (colors === undefined)
|
|
168
|
+
return undefined;
|
|
169
|
+
const hex = colors.get(type);
|
|
170
|
+
if (hex === undefined) {
|
|
171
|
+
throw new VoxelSurfaceError(`no colour for type ${type}, which cell ${where} holds — every solid type in the volume ` +
|
|
172
|
+
'needs a row, so a forgotten one fails here rather than drawing white');
|
|
173
|
+
}
|
|
174
|
+
// `setHex` defaults to `SRGBColorSpace` and converts INTO the working space itself, which is
|
|
175
|
+
// exactly what a material does with a colour uniform. Do not convert again on top of it: an
|
|
176
|
+
// extra `convertSRGBToLinear()` here squared the conversion and drew a mid-green world in near
|
|
177
|
+
// black, with every channel still plausible enough to read as a lighting problem.
|
|
178
|
+
return into.setHex(hex);
|
|
179
|
+
}
|
|
180
|
+
/** Append the faces of one solid cell that face an empty neighbour. Returns how many. */
|
|
181
|
+
function emitCellFaces(buffers, cell, type, color, solidAt, place) {
|
|
182
|
+
const [x, y, z] = cell;
|
|
183
|
+
let emitted = 0;
|
|
184
|
+
for (const face of FACES) {
|
|
185
|
+
const [nx, ny, nz] = face.normal;
|
|
186
|
+
if (solidAt(x + nx, y + ny, z + nz))
|
|
187
|
+
continue;
|
|
188
|
+
const base = buffers.positions.length / 3;
|
|
189
|
+
for (const [cx, cy, cz] of face.corners) {
|
|
190
|
+
buffers.positions.push(...place(x + cx, y + cy, z + cz));
|
|
191
|
+
buffers.normals.push(nx, ny, nz);
|
|
192
|
+
if (color !== undefined)
|
|
193
|
+
buffers.colors.push(color.r, color.g, color.b);
|
|
194
|
+
}
|
|
195
|
+
buffers.indices.push(base, base + 1, base + 2, base, base + 2, base + 3);
|
|
196
|
+
buffers.quadsByType.set(type, (buffers.quadsByType.get(type) ?? 0) + 1);
|
|
197
|
+
emitted += 1;
|
|
198
|
+
}
|
|
199
|
+
return emitted;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Build the visible surface of a voxel volume: one indexed `BufferGeometry` carrying every face
|
|
203
|
+
* that touches an empty neighbour, and nothing else.
|
|
204
|
+
*/
|
|
205
|
+
export function buildVoxelSurface(volume, options = {}) {
|
|
206
|
+
const [sizeX, sizeY, sizeZ] = assertVolumeShape(volume);
|
|
207
|
+
const empty = options.emptyType ?? 0;
|
|
208
|
+
const openBoundary = options.closedBoundary !== true;
|
|
209
|
+
const scale = volume.cellSize ?? 1;
|
|
210
|
+
const [originX, originY, originZ] = volume.origin ?? [0, 0, 0];
|
|
211
|
+
const cells = volume.cells;
|
|
212
|
+
const at = (x, y, z) => cells[(y * sizeZ + z) * sizeX + x];
|
|
213
|
+
const solidAt = (x, y, z) => {
|
|
214
|
+
const outsideVolume = x < 0 || y < 0 || z < 0 || x >= sizeX || y >= sizeY || z >= sizeZ;
|
|
215
|
+
return outsideVolume ? !openBoundary : at(x, y, z) !== empty;
|
|
216
|
+
};
|
|
217
|
+
const place = (x, y, z) => [
|
|
218
|
+
originX + x * scale,
|
|
219
|
+
originY + y * scale,
|
|
220
|
+
originZ + z * scale,
|
|
221
|
+
];
|
|
222
|
+
const buffers = {
|
|
223
|
+
positions: [],
|
|
224
|
+
normals: [],
|
|
225
|
+
colors: [],
|
|
226
|
+
indices: [],
|
|
227
|
+
quadsByType: new Map(),
|
|
228
|
+
};
|
|
229
|
+
const scratch = new Color();
|
|
230
|
+
let solidCells = 0;
|
|
231
|
+
let quads = 0;
|
|
232
|
+
for (let y = 0; y < sizeY; y += 1) {
|
|
233
|
+
for (let z = 0; z < sizeZ; z += 1) {
|
|
234
|
+
for (let x = 0; x < sizeX; x += 1) {
|
|
235
|
+
const type = at(x, y, z);
|
|
236
|
+
if (type === empty)
|
|
237
|
+
continue;
|
|
238
|
+
solidCells += 1;
|
|
239
|
+
const color = vertexColor(options.colors, type, `(${x}, ${y}, ${z})`, scratch);
|
|
240
|
+
quads += emitCellFaces(buffers, [x, y, z], type, color, solidAt, place);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const geometry = new BufferGeometry();
|
|
245
|
+
geometry.setAttribute('position', new BufferAttribute(new Float32Array(buffers.positions), 3));
|
|
246
|
+
geometry.setAttribute('normal', new BufferAttribute(new Float32Array(buffers.normals), 3));
|
|
247
|
+
if (options.colors !== undefined) {
|
|
248
|
+
geometry.setAttribute('color', new BufferAttribute(new Float32Array(buffers.colors), 3));
|
|
249
|
+
}
|
|
250
|
+
const vertices = buffers.positions.length / 3;
|
|
251
|
+
const indices = vertices > 0xffff ? new Uint32Array(buffers.indices) : new Uint16Array(buffers.indices);
|
|
252
|
+
geometry.setIndex(new BufferAttribute(indices, 1));
|
|
253
|
+
geometry.computeBoundingSphere();
|
|
254
|
+
geometry.computeBoundingBox();
|
|
255
|
+
return {
|
|
256
|
+
geometry,
|
|
257
|
+
quads,
|
|
258
|
+
vertices,
|
|
259
|
+
triangles: quads * 2,
|
|
260
|
+
solidCells,
|
|
261
|
+
quadsByType: new Map([...buffers.quadsByType].sort(([a], [b]) => a - b)),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
@@ -478,6 +478,13 @@ async function createRootsGameRuntime(config) {
|
|
|
478
478
|
const isReact = kindById.get(entry.id) === 'dom';
|
|
479
479
|
const surface = document.createElement(isReact ? 'div' : 'canvas');
|
|
480
480
|
surface.dataset['vgaiRootSurface'] = 'true';
|
|
481
|
+
// WHICH ROOT THIS SURFACE PRESENTS — the host mounted it, so the host
|
|
482
|
+
// knows, and stamping it here is the difference between a declaration and
|
|
483
|
+
// the guess every late reader had to make instead ("the first <canvas> in
|
|
484
|
+
// DOM order is the game's"). Read by `packages/editor/src/presentation-
|
|
485
|
+
// surface.ts`, which is the one door the capture/staleness/screenshot
|
|
486
|
+
// sites now ask (ARCHITECTURE-CORE §The editor protocol, zero inference).
|
|
487
|
+
surface.dataset['vgaiRootId'] = entry.id;
|
|
481
488
|
// The capture's marker (`composite-screenshot.ts` reads exactly this
|
|
482
489
|
// attribute): a dev layer is excluded from a play capture unless the
|
|
483
490
|
// capture asks for it, because a contaminated "does the game look right"
|
|
@@ -110,10 +110,10 @@ export interface VgaiDebugInputHandle {
|
|
|
110
110
|
* `state` from another). */
|
|
111
111
|
export interface VgaiDebugSnapshot {
|
|
112
112
|
/** `loopLiveness` (issue #175): the REAL `GameLoop.liveness` behind this
|
|
113
|
-
* session — `'
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
113
|
+
* session — `'loop-starved'` when no recent host rAF progress was observed,
|
|
114
|
+
* `null` only when no loop is wired at all (a bare debug-registry test
|
|
115
|
+
* stand-in with no real `Game`). Never a fabricated `'running'` and never
|
|
116
|
+
* a conclusion about tab visibility. */
|
|
117
117
|
time: {
|
|
118
118
|
simSeconds: number;
|
|
119
119
|
tick: number;
|
|
@@ -227,13 +227,13 @@ export interface MaybeInstallDebugBridgeOptions {
|
|
|
227
227
|
* touching (or requiring) the global object. */
|
|
228
228
|
readonly window?: DebugBridgeWindowTarget | undefined;
|
|
229
229
|
}
|
|
230
|
-
/** The message a hold gets when the loop is
|
|
230
|
+
/** The message a hold gets when the loop is loop-starved and NOTHING can
|
|
231
231
|
* drive it — the one case where the platform genuinely prevents the verb
|
|
232
232
|
* from working. Names the cause and the fix rather than expiring into a
|
|
233
233
|
* generic stall (which reported the wrong cause: "play stopped during
|
|
234
234
|
* hold"). One exported constant so both doors and their tests read the same
|
|
235
235
|
* string. */
|
|
236
|
-
export declare const
|
|
236
|
+
export declare const HOLD_STARVED_NO_DRIVER_REASON: string;
|
|
237
237
|
/**
|
|
238
238
|
* Resolves once `simSeconds` of sim time has elapsed since the call, or once
|
|
239
239
|
* the wait provably cannot make progress. Never rejects. Exported (not just
|
|
@@ -249,8 +249,8 @@ export declare const HOLD_HIDDEN_NO_DRIVER_REASON: string;
|
|
|
249
249
|
* `HOLD_FOR_POLL_MS` and gives up after `HOLD_FOR_STALL_POLL_LIMIT`
|
|
250
250
|
* consecutive unchanged-tick polls (`stalled: true` — play stopped/paused).
|
|
251
251
|
*
|
|
252
|
-
* - **
|
|
253
|
-
*
|
|
252
|
+
* - **Loop-starved**: no recent host rAF progress is observable, so sim time
|
|
253
|
+
* only moves reliably if this drives it. It therefore drives
|
|
254
254
|
* the WHOLE remaining budget in synchronous batches, yielding a MICROTASK
|
|
255
255
|
* between them — never a timer. That distinction is load-bearing, not
|
|
256
256
|
* stylistic: a hidden tab clamps `setTimeout` to ~1s (and to ~1/minute under
|
|
@@ -263,18 +263,18 @@ export declare const HOLD_HIDDEN_NO_DRIVER_REASON: string;
|
|
|
263
263
|
* are not throttled, so the hidden path now costs sim-work time and nothing
|
|
264
264
|
* else.
|
|
265
265
|
*
|
|
266
|
-
* The regime is re-read every iteration, so
|
|
267
|
-
* mid-hold crosses over without restarting the budget.
|
|
266
|
+
* The regime is re-read every iteration, so an rAF chain that resumes or
|
|
267
|
+
* becomes starved mid-hold crosses over without restarting the budget.
|
|
268
268
|
*
|
|
269
|
-
* `
|
|
270
|
-
* no `
|
|
269
|
+
* `starvedWithoutDriver: true` is the one honest refusal: loop-starved with
|
|
270
|
+
* no `driveStarvedTicks` hook means nothing in this process can advance the
|
|
271
271
|
* clock, so it reports that IMMEDIATELY (see
|
|
272
|
-
* {@link
|
|
272
|
+
* {@link HOLD_STARVED_NO_DRIVER_REASON}) instead of burning the stall guard
|
|
273
273
|
* and then blaming a stopped game.
|
|
274
274
|
*/
|
|
275
|
-
export declare function waitForHoldBudget(adapter: DebugAdapter, simSeconds: number,
|
|
275
|
+
export declare function waitForHoldBudget(adapter: DebugAdapter, simSeconds: number, driveStarvedTicks?: (n: number) => void): Promise<{
|
|
276
276
|
stalled: boolean;
|
|
277
|
-
|
|
277
|
+
starvedWithoutDriver?: boolean;
|
|
278
278
|
}>;
|
|
279
279
|
/**
|
|
280
280
|
* Install `window.__vgai` iff the page opted in (`?vgai-debug=1`) AND D18's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug-bridge.d.ts","sourceRoot":"","sources":["../../src/runtime/debug-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAc,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExF;;yEAEyE;AACzE,eAAO,MAAM,sBAAsB,eAAe,CAAC;AAEnD;;;kBAGkB;AAClB,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;CACtE;AAED;;;;;;;;2EAQ2E;AAC3E,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,CACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EAClD,OAAO,CAAC,EAAE,MAAM,GACf;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5F,mBAAmB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C;;;;;;;;;;;;;;;;;;OAkBG;IACH,oBAAoB,CAClB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EAClD,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAAC;IACR;;;+CAG2C;IAC3C,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,oEAAoE;IACpE,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,+CAA+C;IAC/C,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC;;;;;mDAK+C;IAC/C,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9F;;;;iFAI6E;IAC7E,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClG;AAED;;;6BAG6B;AAC7B,MAAM,WAAW,iBAAiB;IAChC;;;;
|
|
1
|
+
{"version":3,"file":"debug-bridge.d.ts","sourceRoot":"","sources":["../../src/runtime/debug-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,25 +31,26 @@ const HOLD_FOR_POLL_MS = 50;
|
|
|
31
31
|
* faster in-process interval so the wall-clock grace period (~5s) lands in
|
|
32
32
|
* the same neighborhood. */
|
|
33
33
|
const HOLD_FOR_STALL_POLL_LIMIT = 100;
|
|
34
|
-
/** Ticks driven per synchronous
|
|
34
|
+
/** Ticks driven per synchronous starved-loop batch. Sized like
|
|
35
35
|
* `fast-forward.ts`'s own batching rationale: big enough that per-batch
|
|
36
36
|
* bookkeeping is negligible, small enough that one batch of a complex game's
|
|
37
37
|
* phases stays a short synchronous burst. */
|
|
38
|
-
const
|
|
39
|
-
/** Hard ceiling on
|
|
38
|
+
const STARVED_DRIVE_BATCH_TICKS = 60;
|
|
39
|
+
/** Hard ceiling on starved-drive batches for ONE hold — `STARVED_DRIVE_BATCH_TICKS
|
|
40
40
|
* * this` ≈ 33 sim-minutes. A bound, not a timeout: it exists so a
|
|
41
41
|
* `runTicks` target that advances the tick counter without advancing the sim
|
|
42
42
|
* clock can never spin forever, and it is far past any honest hold. */
|
|
43
|
-
const
|
|
44
|
-
/** The message a hold gets when the loop is
|
|
43
|
+
const STARVED_DRIVE_MAX_BATCHES = 2000;
|
|
44
|
+
/** The message a hold gets when the loop is loop-starved and NOTHING can
|
|
45
45
|
* drive it — the one case where the platform genuinely prevents the verb
|
|
46
46
|
* from working. Names the cause and the fix rather than expiring into a
|
|
47
47
|
* generic stall (which reported the wrong cause: "play stopped during
|
|
48
48
|
* hold"). One exported constant so both doors and their tests read the same
|
|
49
49
|
* string. */
|
|
50
|
-
export const
|
|
51
|
-
'
|
|
52
|
-
'
|
|
50
|
+
export const HOLD_STARVED_NO_DRIVER_REASON = "the host loop reported liveness 'loop-starved' and this session has no way to drive " +
|
|
51
|
+
'ticks — no recent rAF progress was observed. Check `vgai status` for the separate ' +
|
|
52
|
+
'visibility readings; foreground/reload the editor, or start play to wire the run-ticks ' +
|
|
53
|
+
'target, then retry.';
|
|
53
54
|
/**
|
|
54
55
|
* Resolves once `simSeconds` of sim time has elapsed since the call, or once
|
|
55
56
|
* the wait provably cannot make progress. Never rejects. Exported (not just
|
|
@@ -65,8 +66,8 @@ export const HOLD_HIDDEN_NO_DRIVER_REASON = 'the editor tab is hidden and this s
|
|
|
65
66
|
* `HOLD_FOR_POLL_MS` and gives up after `HOLD_FOR_STALL_POLL_LIMIT`
|
|
66
67
|
* consecutive unchanged-tick polls (`stalled: true` — play stopped/paused).
|
|
67
68
|
*
|
|
68
|
-
* - **
|
|
69
|
-
*
|
|
69
|
+
* - **Loop-starved**: no recent host rAF progress is observable, so sim time
|
|
70
|
+
* only moves reliably if this drives it. It therefore drives
|
|
70
71
|
* the WHOLE remaining budget in synchronous batches, yielding a MICROTASK
|
|
71
72
|
* between them — never a timer. That distinction is load-bearing, not
|
|
72
73
|
* stylistic: a hidden tab clamps `setTimeout` to ~1s (and to ~1/minute under
|
|
@@ -79,32 +80,32 @@ export const HOLD_HIDDEN_NO_DRIVER_REASON = 'the editor tab is hidden and this s
|
|
|
79
80
|
* are not throttled, so the hidden path now costs sim-work time and nothing
|
|
80
81
|
* else.
|
|
81
82
|
*
|
|
82
|
-
* The regime is re-read every iteration, so
|
|
83
|
-
* mid-hold crosses over without restarting the budget.
|
|
83
|
+
* The regime is re-read every iteration, so an rAF chain that resumes or
|
|
84
|
+
* becomes starved mid-hold crosses over without restarting the budget.
|
|
84
85
|
*
|
|
85
|
-
* `
|
|
86
|
-
* no `
|
|
86
|
+
* `starvedWithoutDriver: true` is the one honest refusal: loop-starved with
|
|
87
|
+
* no `driveStarvedTicks` hook means nothing in this process can advance the
|
|
87
88
|
* clock, so it reports that IMMEDIATELY (see
|
|
88
|
-
* {@link
|
|
89
|
+
* {@link HOLD_STARVED_NO_DRIVER_REASON}) instead of burning the stall guard
|
|
89
90
|
* and then blaming a stopped game.
|
|
90
91
|
*/
|
|
91
|
-
export async function waitForHoldBudget(adapter, simSeconds,
|
|
92
|
+
export async function waitForHoldBudget(adapter, simSeconds, driveStarvedTicks) {
|
|
92
93
|
const readTime = () => adapter.state('time');
|
|
93
94
|
const start = readTime();
|
|
94
95
|
let lastTick = start.tick;
|
|
95
96
|
let stalledPolls = 0;
|
|
96
|
-
let
|
|
97
|
+
let starvedBatches = 0;
|
|
97
98
|
for (;;) {
|
|
98
99
|
const current = readTime();
|
|
99
100
|
if (current.simSeconds - start.simSeconds >= simSeconds)
|
|
100
101
|
return { stalled: false };
|
|
101
|
-
if (current.loopLiveness === '
|
|
102
|
-
if (!
|
|
103
|
-
return { stalled: true,
|
|
104
|
-
if (
|
|
102
|
+
if (current.loopLiveness === 'loop-starved') {
|
|
103
|
+
if (!driveStarvedTicks)
|
|
104
|
+
return { stalled: true, starvedWithoutDriver: true };
|
|
105
|
+
if (starvedBatches >= STARVED_DRIVE_MAX_BATCHES)
|
|
105
106
|
return { stalled: true };
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
starvedBatches += 1;
|
|
108
|
+
driveStarvedTicks(STARVED_DRIVE_BATCH_TICKS);
|
|
108
109
|
const after = readTime();
|
|
109
110
|
// A batch that moved neither the tick counter nor the sim clock means
|
|
110
111
|
// the drive is a no-op (paused game, torn-down runtime) — the same
|
|
@@ -116,7 +117,7 @@ export async function waitForHoldBudget(adapter, simSeconds, driveHiddenTicks) {
|
|
|
116
117
|
lastTick = after.tick;
|
|
117
118
|
stalledPolls = 0;
|
|
118
119
|
// Yield so the page can service other work between batches, WITHOUT
|
|
119
|
-
// handing control to
|
|
120
|
+
// handing control to the same timer lane the browser may be starving.
|
|
120
121
|
await Promise.resolve();
|
|
121
122
|
continue;
|
|
122
123
|
}
|
|
@@ -229,13 +230,13 @@ function buildDebugHandle(opts) {
|
|
|
229
230
|
: { delivered: false };
|
|
230
231
|
}
|
|
231
232
|
const runTicksTarget = registry.getRunTicksTarget();
|
|
232
|
-
const { stalled,
|
|
233
|
+
const { stalled, starvedWithoutDriver } = await waitForHoldBudget(adapter, simSeconds, runTicksTarget ? (n) => runTicksTarget.runTicks(n, { render: 'last' }) : undefined);
|
|
233
234
|
target.clearVirtualActions();
|
|
234
235
|
if (!stalled)
|
|
235
236
|
return { delivered: true };
|
|
236
237
|
return {
|
|
237
238
|
delivered: false,
|
|
238
|
-
reason:
|
|
239
|
+
reason: starvedWithoutDriver ? HOLD_STARVED_NO_DRIVER_REASON : 'play stopped during hold',
|
|
239
240
|
};
|
|
240
241
|
},
|
|
241
242
|
uninstall() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../src/runtime/game.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../src/runtime/game.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime/game.js
CHANGED
|
@@ -416,8 +416,7 @@ export function createGame(opts) {
|
|
|
416
416
|
// Other native `console.warn`/`console.error` call sites in this file are
|
|
417
417
|
// unsuppressed and already counted in the lint baseline (see `runFrame`'s
|
|
418
418
|
// impl below); this one is a NEW site, so it's suppressed to keep this
|
|
419
|
-
// task's diff at zero NEW warnings
|
|
420
|
-
// identical suppression).
|
|
419
|
+
// task's diff at zero NEW warnings.
|
|
421
420
|
// biome-ignore lint/suspicious/noConsole: see comment above
|
|
422
421
|
console.warn(message);
|
|
423
422
|
}
|