@vgai/engine 0.5.11 → 0.5.13
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 +6 -5
- package/dist/adapter/authoring.d.ts +51 -28
- package/dist/adapter/authoring.d.ts.map +1 -1
- package/dist/adapter/body-marks.d.ts +59 -0
- package/dist/adapter/body-marks.d.ts.map +1 -0
- package/dist/adapter/body-marks.js +62 -0
- package/dist/adapter/constraint.d.ts +41 -0
- package/dist/adapter/constraint.d.ts.map +1 -0
- package/dist/adapter/constraint.js +27 -0
- package/dist/adapter/hierarchy-marks.d.ts +138 -0
- package/dist/adapter/hierarchy-marks.d.ts.map +1 -0
- package/dist/adapter/hierarchy-marks.js +148 -0
- package/dist/adapter/index.d.ts +1 -1
- package/dist/adapter/index.d.ts.map +1 -1
- package/dist/adapter/ingest/contract-system-adapters.d.ts +64 -0
- package/dist/adapter/ingest/contract-system-adapters.d.ts.map +1 -0
- package/dist/adapter/ingest/contract-system-adapters.js +134 -0
- package/dist/adapter/ingest/game-contract.d.ts +87 -9
- package/dist/adapter/ingest/game-contract.d.ts.map +1 -1
- package/dist/adapter/ingest/game-contract.js +7 -6
- package/dist/adapter/ingest/scene-capture.d.ts +31 -4
- package/dist/adapter/ingest/scene-capture.d.ts.map +1 -1
- package/dist/adapter/ingest/scene-capture.js +29 -7
- package/dist/adapter/ingest/structural-ids.d.ts +1 -1
- package/dist/adapter/ingest/structural-ids.js +2 -2
- package/dist/adapter/reflection-probe.d.ts +53 -0
- package/dist/adapter/reflection-probe.d.ts.map +1 -0
- package/dist/adapter/reflection-probe.js +18 -0
- package/dist/asset-formats/index.d.ts +4 -10
- package/dist/asset-formats/index.d.ts.map +1 -1
- package/dist/asset-formats/index.js +3 -8
- package/dist/asset-formats/material.d.ts +0 -66
- package/dist/asset-formats/material.d.ts.map +1 -1
- package/dist/asset-formats/material.js +0 -8
- package/dist/asset-formats/mesh.d.ts +1 -2
- package/dist/asset-formats/mesh.d.ts.map +1 -1
- package/dist/asset-formats/mesh.js +3 -13
- package/dist/asset-formats/render-env.d.ts +2 -2
- package/dist/asset-parse-error.d.ts +4 -5
- package/dist/asset-parse-error.d.ts.map +1 -1
- package/dist/asset-parse-error.js +4 -5
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -0
- package/dist/data/curve.d.ts +116 -0
- package/dist/data/curve.d.ts.map +1 -0
- package/dist/data/curve.js +230 -0
- package/dist/data/vite-plugin-data.d.ts +2 -2
- package/dist/data/vite-plugin-data.d.ts.map +1 -1
- package/dist/data/vite-plugin-data.js +24 -15
- package/dist/dev/performance-profiler.d.ts +1 -0
- package/dist/dev/performance-profiler.d.ts.map +1 -1
- package/dist/dev/performance-profiler.js +25 -2
- package/dist/ecs/user-data.d.ts +49 -1
- package/dist/ecs/user-data.d.ts.map +1 -1
- package/dist/ecs/user-data.js +34 -0
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/manifest/index.d.ts +3 -3
- package/dist/manifest/index.d.ts.map +1 -1
- package/dist/manifest/index.js +2 -2
- package/dist/manifest/load.d.ts +15 -67
- package/dist/manifest/load.d.ts.map +1 -1
- package/dist/manifest/load.js +11 -103
- package/dist/manifest/schema.d.ts +18 -103
- package/dist/manifest/schema.d.ts.map +1 -1
- package/dist/manifest/schema.js +59 -179
- package/dist/pixi/index.d.ts +2 -3
- package/dist/pixi/index.d.ts.map +1 -1
- package/dist/pixi/index.js +2 -3
- package/dist/pixi/ingest.d.ts +7 -75
- package/dist/pixi/ingest.d.ts.map +1 -1
- package/dist/pixi/ingest.js +6 -14
- package/dist/pixi/scene-capture.d.ts +2 -2
- package/dist/pixi/scene-capture.js +2 -2
- package/dist/react/use-data.d.ts +10 -5
- package/dist/react/use-data.d.ts.map +1 -1
- package/dist/react/use-data.js +15 -15
- package/dist/render/viewport-shading.d.ts +1 -1
- package/dist/render/viewport-shading.d.ts.map +1 -1
- package/dist/render/viewport-shading.js +14 -0
- package/dist/runtime/create-runtime.d.ts +12 -0
- package/dist/runtime/create-runtime.d.ts.map +1 -1
- package/dist/runtime/create-runtime.js +7 -2
- package/dist/runtime/mount-game.d.ts +1 -1
- package/dist/runtime/mount-game.d.ts.map +1 -1
- package/dist/runtime/mount-manifest.d.ts.map +1 -1
- package/dist/runtime/mount-manifest.js +5 -1
- package/dist/world3d-react/r3f-adapter.d.ts.map +1 -1
- package/dist/world3d-react/r3f-adapter.js +69 -39
- package/dist/world3d-react/renderer-config.d.ts +15 -0
- package/dist/world3d-react/renderer-config.d.ts.map +1 -1
- package/dist/world3d-react/renderer-config.js +15 -0
- package/dist/world3d-react/world-context.d.ts +2 -1
- package/dist/world3d-react/world-context.d.ts.map +1 -1
- package/dist-config/config.js +140 -20
- package/dist-config/config.js.map +4 -4
- package/package.json +1 -1
- package/schemas/engine-capabilities.json +10 -10
- package/schemas/vgai-project.schema.json +21 -76
- package/src/adapter/authoring.ts +54 -31
- package/src/adapter/body-marks.ts +69 -0
- package/src/adapter/constraint.ts +71 -0
- package/src/adapter/hierarchy-marks.ts +155 -0
- package/src/adapter/index.ts +2 -3
- package/src/adapter/ingest/contract-system-adapters.ts +174 -0
- package/src/adapter/ingest/game-contract.ts +98 -9
- package/src/adapter/ingest/scene-capture.ts +61 -11
- package/src/adapter/ingest/structural-ids.ts +2 -2
- package/src/adapter/reflection-probe.ts +75 -0
- package/src/asset-formats/index.ts +4 -10
- package/src/asset-formats/material.ts +0 -11
- package/src/asset-formats/mesh.ts +3 -16
- package/src/asset-parse-error.ts +4 -5
- package/src/config.ts +13 -0
- package/src/data/curve.ts +263 -0
- package/src/data/vite-plugin-data.ts +48 -14
- package/src/dev/performance-profiler.ts +21 -2
- package/src/ecs/user-data.ts +50 -0
- package/src/index.ts +2 -3
- package/src/manifest/index.ts +3 -15
- package/src/manifest/load.ts +27 -143
- package/src/manifest/schema.ts +65 -223
- package/src/pixi/index.ts +2 -15
- package/src/pixi/ingest.ts +13 -87
- package/src/pixi/scene-capture.ts +2 -2
- package/src/react/use-data.ts +15 -20
- package/src/render/viewport-shading.ts +16 -1
- package/src/runtime/create-runtime.ts +30 -5
- package/src/runtime/mount-game.ts +1 -1
- package/src/runtime/mount-manifest.ts +5 -1
- package/src/world3d-react/r3f-adapter.tsx +73 -39
- package/src/world3d-react/renderer-config.ts +31 -0
- package/src/world3d-react/world-context.ts +2 -1
- package/dist/asset-formats/instances.d.ts +0 -17
- package/dist/asset-formats/instances.d.ts.map +0 -1
- package/dist/asset-formats/instances.js +0 -31
- package/dist/asset-formats/parse.d.ts +0 -20
- package/dist/asset-formats/parse.d.ts.map +0 -1
- package/dist/asset-formats/parse.js +0 -34
- package/dist/pixi/ingest-iframe.d.ts +0 -82
- package/dist/pixi/ingest-iframe.d.ts.map +0 -1
- package/dist/pixi/ingest-iframe.js +0 -166
- package/dist/render/instance-mesh.d.ts +0 -5
- package/dist/render/instance-mesh.d.ts.map +0 -1
- package/dist/render/instance-mesh.js +0 -19
- package/schemas/mat.schema.json +0 -255
- package/src/asset-formats/instances.ts +0 -38
- package/src/asset-formats/parse.ts +0 -39
- package/src/pixi/ingest-iframe.ts +0 -255
- package/src/render/instance-mesh.ts +0 -25
package/dist/manifest/schema.js
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
//
|
|
10
10
|
// Naming: this file follows the repo's `XxxSchema` (Zod schema) / `Xxx`
|
|
11
11
|
// (inferred type) convention used throughout `scene/schema/` — the design
|
|
12
|
-
// doc's §3 sketch names the bare consts (`
|
|
13
|
-
// `
|
|
12
|
+
// doc's §3 sketch names the bare consts (`AdapterRoot`) without the
|
|
13
|
+
// `Schema` suffix; that sketch is explicitly a
|
|
14
14
|
// "Zod sketch" the doc tells implementers to adapt to real code style
|
|
15
15
|
// ("mirror the style in scene/schema/scene-file.ts" per CLAUDE.md), so the
|
|
16
16
|
// schema consts here are suffixed and the bare names are reserved for the
|
|
@@ -26,26 +26,6 @@ import { z } from 'zod';
|
|
|
26
26
|
*/
|
|
27
27
|
export const GAME_MANIFEST_VERSION = 2;
|
|
28
28
|
// ---------------------------------------------------------------------------
|
|
29
|
-
// Ingest capture strategy (the general vocabulary D6/§4 names)
|
|
30
|
-
// ---------------------------------------------------------------------------
|
|
31
|
-
export const IngestStrategySchema = z.enum([
|
|
32
|
-
'shared', // game imports host-served ESM three — full in-realm capture
|
|
33
|
-
'deduped', // game source built by OUR pipeline, bundler dedupe — full capture
|
|
34
|
-
'iframe-reachable', // prebuilt bundle in iframe, three reachable — cross-realm capture
|
|
35
|
-
'opaque-embed', // prebuilt bundle, nothing reachable — host lifecycle only
|
|
36
|
-
]);
|
|
37
|
-
// ---------------------------------------------------------------------------
|
|
38
|
-
// Capability tier — one ordered enum, declared per delivery context (§4)
|
|
39
|
-
// ---------------------------------------------------------------------------
|
|
40
|
-
export const TierSchema = z.enum([
|
|
41
|
-
'first-party', // vgai-native root: full editor, full loop control
|
|
42
|
-
'shared', // = IngestStrategy 'shared' rung
|
|
43
|
-
'deduped', // = IngestStrategy 'deduped' rung
|
|
44
|
-
'iframe-reachable', // = IngestStrategy 'iframe-reachable' rung
|
|
45
|
-
'opaque-embed', // = IngestStrategy 'opaque-embed' rung
|
|
46
|
-
'unsupported', // this root does not function in this delivery context
|
|
47
|
-
]);
|
|
48
|
-
// ---------------------------------------------------------------------------
|
|
49
29
|
// Root adapter identity. The adapter is the sole discriminator: a root never
|
|
50
30
|
// repeats its rendering substrate in a sibling `kind` field. Module and ingest
|
|
51
31
|
// adapters carry the surface their adapter contract exposes because the host
|
|
@@ -141,34 +121,48 @@ export const RootAdapterSchema = z
|
|
|
141
121
|
.describe('Native surface captured from the unmodified game'),
|
|
142
122
|
ingest: z
|
|
143
123
|
.object({
|
|
144
|
-
strategy: IngestStrategySchema.describe('Capture mechanics rung this ingested root uses (§4) — also the root`s natural local capability tier'),
|
|
145
|
-
entryHtml: z
|
|
146
|
-
.string()
|
|
147
|
-
.optional()
|
|
148
|
-
.describe('Entry HTML path, project-relative. WIRED for opaque-embed (D-W2): ' +
|
|
149
|
-
'the file`s bytes are read verbatim through ' +
|
|
150
|
-
'the project-static route and hosted in a sandboxed iframe (embed-only, no scene ' +
|
|
151
|
-
'introspection), for both canvas and three roots. Legal but NOT wired to a ' +
|
|
152
|
-
'mount for iframe-reachable (a named error at resolve names this — use `bundleUrl` ' +
|
|
153
|
-
'instead, the wired reachable route).'),
|
|
154
124
|
contractShim: z
|
|
155
125
|
.string()
|
|
156
126
|
.optional()
|
|
157
127
|
.describe("Project-relative path to a HOST-ADDED ES module that declares this game's " +
|
|
158
128
|
'`window.vgaiGame` contract (adapter/ingest/game-contract.ts) WITHOUT editing a ' +
|
|
159
|
-
'vendored byte — the pristine-copy door. The host
|
|
160
|
-
|
|
161
|
-
'importmap (moving a module load ahead of an import map invalidates the map) and ' +
|
|
162
|
-
'BEFORE the game`s entry module, so deferred module scripts run it first. ' +
|
|
129
|
+
'vendored byte — the pristine-copy door. The host imports it immediately BEFORE ' +
|
|
130
|
+
"the game's own entry module, in the editor's realm. " +
|
|
163
131
|
'TIMING CONTRACT, which a shim author must obey: because it runs before the ' +
|
|
164
|
-
'game`s entry, it MUST assign `window.vgaiGame` SYNCHRONOUSLY at top level
|
|
165
|
-
'host waits for that assignment and fails the mount by name if it never arrives. ' +
|
|
132
|
+
'game`s entry, it MUST assign `window.vgaiGame` SYNCHRONOUSLY at top level. ' +
|
|
166
133
|
'Anything that needs the game`s own modules must be LAZY: a dynamic `import()` ' +
|
|
167
134
|
'INSIDE each verb/provider closure, resolved at call time. Importing a game module ' +
|
|
168
135
|
'eagerly from the shim would evaluate it ahead of the game`s own entry and reorder ' +
|
|
169
|
-
'its module side effects.
|
|
170
|
-
'
|
|
171
|
-
'
|
|
136
|
+
'its module side effects. ' +
|
|
137
|
+
'Every such `import()` MUST take a STRING LITERAL, never a variable/table lookup. ' +
|
|
138
|
+
'A variable specifier is not statically analyzable, so the dev server leaves it ' +
|
|
139
|
+
'alone and it resolves at runtime against the shim`s own `/@fs/` url — while the ' +
|
|
140
|
+
'game`s entry has had ITS relative imports rewritten to whatever url the server ' +
|
|
141
|
+
'considers canonical for those files. Module identity is per-url, so the shim ' +
|
|
142
|
+
'silently binds a SECOND, freshly-evaluated copy of the whole game and every ' +
|
|
143
|
+
'provider reports a game that never started. Measured on three-descent: 285 ' +
|
|
144
|
+
'segments through the game`s graph, 0 through the shim`s, and no error anywhere.'),
|
|
145
|
+
dataWriter: z
|
|
146
|
+
.string()
|
|
147
|
+
.optional()
|
|
148
|
+
.describe("Project-relative path to a HOST-ADDED ES module that writes this game's own " +
|
|
149
|
+
'DATA file back — the sibling of a source write for a game whose authorable ' +
|
|
150
|
+
'truth is not source. Descent places its robots, powerups and hostages in ' +
|
|
151
|
+
'binary records inside `descent.hog`, reaching no source literal, so an ' +
|
|
152
|
+
'authored move of one is an edit to that file and nothing else can write it. ' +
|
|
153
|
+
'The module declares two exports and the host knows nothing else about it: ' +
|
|
154
|
+
'`dataFile` (a project-relative string — the ONE file this writer edits) and ' +
|
|
155
|
+
'`planDataEdit(bytes, {record, property, baseline, next})`, which returns ' +
|
|
156
|
+
'`{changed: true, bytes}` or `{changed: false, reason}` and may be async. ' +
|
|
157
|
+
'It is loaded in the editor realm beside the game, so it may `import()` the ' +
|
|
158
|
+
"game's own modules to resolve what only a running game knows (Descent's " +
|
|
159
|
+
'writer asks the game`s own `find_point_seg` which segment a moved object ' +
|
|
160
|
+
'landed in, and refuses "outside the mine" rather than writing data the game ' +
|
|
161
|
+
'would read back wrong). It NEVER fabricates: a record it cannot address, or ' +
|
|
162
|
+
'a property it does not model, is a named refusal. ' +
|
|
163
|
+
'An object is anchored to a record by carrying `userData.vgaiRecordIndex` — ' +
|
|
164
|
+
'the game declares that identity itself (a recorded patch or a shim); the ' +
|
|
165
|
+
'host never infers one.'),
|
|
172
166
|
assets: z
|
|
173
167
|
.record(z.string(), z.string())
|
|
174
168
|
.optional()
|
|
@@ -180,137 +174,13 @@ export const RootAdapterSchema = z
|
|
|
180
174
|
captureTimeoutMs: z
|
|
181
175
|
.number()
|
|
182
176
|
.optional()
|
|
183
|
-
.describe(
|
|
184
|
-
'
|
|
185
|
-
'
|
|
186
|
-
'reported-embed-only mount in place; the host clamps this value so a long ' +
|
|
187
|
-
'one cannot block the editor on a question the upgrade path answers anyway.'),
|
|
188
|
-
// The six iframe-reachable-multi mount fields
|
|
189
|
-
// (`ingest-iframe-2d.ts`'s `IframeReachableMultiOpts`), legal
|
|
190
|
-
// ONLY when `strategy` is 'iframe-reachable' (enforced by the
|
|
191
|
-
// `.superRefine` below).
|
|
192
|
-
bundleUrl: z
|
|
193
|
-
.string()
|
|
194
|
-
.optional()
|
|
195
|
-
.describe('Absolute URL of the externalized built game bundle — the WIRED iframe-reachable ' +
|
|
196
|
-
'mount route (iframe-reachable only), for BOTH canvas (Track P, ' +
|
|
197
|
-
"ingest-iframe-2d.ts's mountIngestGame2DIframeReachableMulti) and three (D-W1, " +
|
|
198
|
-
"ingest-iframe-reachable-adapter.ts's mountIngestGameIframeReachableBundle). " +
|
|
199
|
-
'PRECONDITION: the bundle must externalize its root`s own runtime as a bare, ' +
|
|
200
|
-
'un-rewritten import (`pixi.js` for canvas, `three` for three — `vgai bundle` ' +
|
|
201
|
-
'does this for you) so it resolves through the iframe importmap to the HOST ' +
|
|
202
|
-
'instance the capture trap is installed on; a bundle with an inlined runtime is ' +
|
|
203
|
-
'unreachable and degrades to the embed-only floor. Exactly one of bundleUrl/' +
|
|
204
|
-
'entryHtml is required when strategy is iframe-reachable.'),
|
|
205
|
-
baseHref: z
|
|
206
|
-
.string()
|
|
207
|
-
.optional()
|
|
208
|
-
.describe("Iframe <base href> so the game's relative asset URLs resolve (iframe-reachable only)."),
|
|
209
|
-
assetBaseUrl: z
|
|
210
|
-
.string()
|
|
211
|
-
.optional()
|
|
212
|
-
.describe("Host-side basePath forced onto the trapped runtime's own asset resolution — " +
|
|
213
|
-
"pixi's `Assets.init` for a canvas root, three's " +
|
|
214
|
-
'`DefaultLoadingManager.setURLModifier` for a three root (D-W1) — absolute, or ' +
|
|
215
|
-
"root-relative (resolved against the editor page's own origin at mount time, " +
|
|
216
|
-
'ingest-mode.ts, so a static manifest never has to know the dev-server port) ' +
|
|
217
|
-
'(iframe-reachable only — a document.write iframe keeps the parent window.location).'),
|
|
218
|
-
extraDeps: z
|
|
219
|
-
.array(z.string())
|
|
220
|
-
.optional()
|
|
221
|
-
.describe("Bare specifiers of this root's externalized deps beyond its own runtime " +
|
|
222
|
-
"(pixi.js/three — e.g. '@pixi/sound', 'gsap'). Resolved by the editor's " +
|
|
223
|
-
'host-namespace registry into module namespaces when known (D-P1 — the manifest ' +
|
|
224
|
-
'carries data, not code); an unregistered specifier falls back to the open ' +
|
|
225
|
-
"project's own node_modules (D-Z3), served " +
|
|
226
|
-
'as a verbatim iframe importmap URL. Throws a named error if neither resolves it ' +
|
|
227
|
-
'(iframe-reachable only).'),
|
|
228
|
-
pixiModuleUrl: z
|
|
229
|
-
.string()
|
|
230
|
-
.optional()
|
|
231
|
-
.describe('PIXI-ONLY: standalone matching-major pixi ESM URL to trap instead of the host ' +
|
|
232
|
-
"pixi, for version-skewed games (e.g. a v6 game on a v8 host); this field's " +
|
|
233
|
-
'PRESENCE is how the skew is expressed (D-P2 — no separate strategy/tier for ' +
|
|
234
|
-
'version skew) (iframe-reachable only). Declaring this on a `kind: "three"` ' +
|
|
235
|
-
'root is schema-legal (this field is kind-agnostic here) but throws a NAMED ' +
|
|
236
|
-
'not-supported error at resolve — three has no version-skew mount this wave ' +
|
|
237
|
-
'(D-W7: a hypothetical `threeModuleUrl` is explicitly parked, no consumer ' +
|
|
238
|
-
'exists).'),
|
|
239
|
-
bodyHtml: z
|
|
240
|
-
.string()
|
|
241
|
-
.optional()
|
|
242
|
-
.describe('HTML injected into the iframe body before the game script boots (e.g. a ' +
|
|
243
|
-
'`<div id="game-root">` the game expects to find) (iframe-reachable only).'),
|
|
177
|
+
.describe("How long the host waits for this game's first captured frame before the mount " +
|
|
178
|
+
'FAILS by name. A game that needs a long boot (streamed world assets, a menu ' +
|
|
179
|
+
'the player must clear) raises it; the default is 10s.'),
|
|
244
180
|
})
|
|
181
|
+
.strict()
|
|
245
182
|
.describe('Ingest adapter configuration for an unmodified game (a repo-vendored game or your ' +
|
|
246
|
-
'own external folder)')
|
|
247
|
-
// `contractShim` is injected into the assembled ENTRY DOCUMENT, so
|
|
248
|
-
// the ONLY route that can read it is the self-hosted one
|
|
249
|
-
// (`iframe-reachable` + `entryHtml`,
|
|
250
|
-
// ingest-self-hosted-three-adapter.ts). An `opaque-embed` entry
|
|
251
|
-
// document is hosted sandboxed with no host wiring, and a `bundleUrl`
|
|
252
|
-
// mount has no game document at all — under either, a declared shim
|
|
253
|
-
// would be a silently dead declaration, the exact failure the
|
|
254
|
-
// dead-field-under-wrong-variant checks below exist to prevent. Its
|
|
255
|
-
// own `.superRefine` rather than a branch inside the next one: they
|
|
256
|
-
// check unrelated invariants, and folding them together only made
|
|
257
|
-
// one function harder to read.
|
|
258
|
-
.superRefine((ingest, ctx) => {
|
|
259
|
-
if (ingest.contractShim === undefined ||
|
|
260
|
-
(ingest.strategy === 'iframe-reachable' && ingest.entryHtml !== undefined)) {
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
ctx.addIssue({
|
|
264
|
-
code: z.ZodIssueCode.custom,
|
|
265
|
-
message: '`contractShim` is read ONLY by the self-hosted entry-document route, so it ' +
|
|
266
|
-
"requires strategy 'iframe-reachable' together with `entryHtml` (got strategy " +
|
|
267
|
-
`"${ingest.strategy}"${ingest.entryHtml === undefined ? ' and no `entryHtml`' : ''}) — ` +
|
|
268
|
-
"the host injects the shim module into the GAME'S OWN entry HTML " +
|
|
269
|
-
'(ingest-self-hosted-three-adapter.ts), and no other mount has such a document.',
|
|
270
|
-
path: ['contractShim'],
|
|
271
|
-
});
|
|
272
|
-
})
|
|
273
|
-
.superRefine((ingest, ctx) => {
|
|
274
|
-
// The six iframe-reachable-multi fields only make sense for the
|
|
275
|
-
// iframe-reachable-multi mount — reject them under any other
|
|
276
|
-
// strategy (mirrors ui.ts's dead-field-under-wrong-variant pattern).
|
|
277
|
-
const iframeOnlyFields = [
|
|
278
|
-
['bundleUrl', ingest.bundleUrl !== undefined],
|
|
279
|
-
['baseHref', ingest.baseHref !== undefined],
|
|
280
|
-
['assetBaseUrl', ingest.assetBaseUrl !== undefined],
|
|
281
|
-
['extraDeps', ingest.extraDeps !== undefined],
|
|
282
|
-
['pixiModuleUrl', ingest.pixiModuleUrl !== undefined],
|
|
283
|
-
['bodyHtml', ingest.bodyHtml !== undefined],
|
|
284
|
-
];
|
|
285
|
-
if (ingest.strategy !== 'iframe-reachable') {
|
|
286
|
-
for (const [key, present] of iframeOnlyFields) {
|
|
287
|
-
if (present) {
|
|
288
|
-
ctx.addIssue({
|
|
289
|
-
code: z.ZodIssueCode.custom,
|
|
290
|
-
message: `\`${key}\` is only legal when strategy is 'iframe-reachable' (got ` +
|
|
291
|
-
`"${ingest.strategy}") — bundleUrl/baseHref/assetBaseUrl/extraDeps/` +
|
|
292
|
-
"pixiModuleUrl/bodyHtml are the iframe-reachable-multi mount's options " +
|
|
293
|
-
'(canvas: ingest-iframe-2d.ts IframeReachableMultiOpts; three, D-W1: ' +
|
|
294
|
-
'ingest-iframe-reachable-adapter.ts IframeReachableBundleOpts) and have no ' +
|
|
295
|
-
'meaning under any other strategy.',
|
|
296
|
-
path: [key],
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
const hasBundleUrl = ingest.bundleUrl !== undefined;
|
|
303
|
-
const hasEntryHtml = ingest.entryHtml !== undefined;
|
|
304
|
-
if (hasBundleUrl === hasEntryHtml) {
|
|
305
|
-
ctx.addIssue({
|
|
306
|
-
code: z.ZodIssueCode.custom,
|
|
307
|
-
message: "strategy 'iframe-reachable' requires EXACTLY ONE of `bundleUrl` (externalized " +
|
|
308
|
-
'multi-file bundle, the iframe-reachable-multi mount) or `entryHtml` (single-' +
|
|
309
|
-
`file/legacy iframe entry) — ${hasBundleUrl ? 'both are present' : 'neither is present'}.`,
|
|
310
|
-
path: hasBundleUrl ? ['bundleUrl'] : ['entryHtml'],
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
}),
|
|
183
|
+
'own external folder)'),
|
|
314
184
|
})
|
|
315
185
|
.strict(),
|
|
316
186
|
]))
|
|
@@ -361,15 +231,7 @@ export const AdapterRootSchema = z
|
|
|
361
231
|
.enum(['gated', 'self-driven'])
|
|
362
232
|
.default('gated')
|
|
363
233
|
.describe('gated: host-driven loop (default). self-driven: this root drives its own loop ' +
|
|
364
|
-
'(
|
|
365
|
-
capabilities: z
|
|
366
|
-
.object({
|
|
367
|
-
local: TierSchema.optional().describe('Declared capability tier when served via the local CLI (Vite pipeline); omitted -> derived (§4)'),
|
|
368
|
-
hosted: TierSchema.optional().describe('Declared capability tier when served hosted (no bundler: esbuild-wasm + externals only); omitted -> derived (§4)'),
|
|
369
|
-
})
|
|
370
|
-
.optional()
|
|
371
|
-
.describe("Per-delivery-context capability tier declarations (§4). Declaring above the adapter's " +
|
|
372
|
-
'ceiling for that context is an error; declaring at or below it (including `unsupported`) is legal.'),
|
|
234
|
+
'(composited, unsynchronized)'),
|
|
373
235
|
})
|
|
374
236
|
.strict();
|
|
375
237
|
/**
|
|
@@ -580,6 +442,24 @@ export const GameManifestSchema = z
|
|
|
580
442
|
})
|
|
581
443
|
.optional()
|
|
582
444
|
.describe('Canvas resolution'),
|
|
445
|
+
rendering: z
|
|
446
|
+
.object({
|
|
447
|
+
antialias: z
|
|
448
|
+
.boolean()
|
|
449
|
+
.describe('Whether every three root is built with a multisampled drawing buffer. This is the ' +
|
|
450
|
+
'ONE render property a world cannot declare for itself (world3d-react/' +
|
|
451
|
+
'renderer-config.ts): a WebGL context fixes its sample count at CREATION from this ' +
|
|
452
|
+
'boolean, long before a world mounts, so it belongs to the PROJECT. The runtime ' +
|
|
453
|
+
'reader is mount-manifest.ts, which threads it into createHostRenderer for each ' +
|
|
454
|
+
'three root. WebGL exposes no sample COUNT — the implementation picks one (4x on ' +
|
|
455
|
+
'every desktop browser measured), so a source engine that authored 8x/16x gets ' +
|
|
456
|
+
'multisampling but not its exact count.'),
|
|
457
|
+
})
|
|
458
|
+
.strict()
|
|
459
|
+
.optional()
|
|
460
|
+
.describe('Construction-time renderer properties, which no world can declare after the fact. ' +
|
|
461
|
+
'Everything a world CAN declare (tone mapping, output colour space, clear colour, ' +
|
|
462
|
+
"shadow filter) lives on the world's own renderer config instead."),
|
|
583
463
|
debug: z
|
|
584
464
|
.object({
|
|
585
465
|
allowInProduction: z
|
package/dist/pixi/index.d.ts
CHANGED
|
@@ -4,12 +4,11 @@
|
|
|
4
4
|
* PixiJS is opt-in: the engine core never imports it, so a three-only bundle
|
|
5
5
|
* never pays for it. What lives here is what the host needs to mount and
|
|
6
6
|
* inspect a PixiJS game it did not write — the render-call capture trap, the
|
|
7
|
-
* in-realm
|
|
7
|
+
* in-realm mount, the live display-tree authoring adapter, and the
|
|
8
8
|
* Rapier-2D handle registry the editor's transform coordination reads.
|
|
9
9
|
*/
|
|
10
10
|
export { AuthoringAdapter2D, type EditorNode2D, type Overlay2D, type Override2D, type Property2D, type Transform2DValue, } from './authoring';
|
|
11
|
-
export { type
|
|
12
|
-
export { type EmbedMount2D, type IframeReachableMount2D, type IframeReachableMultiOpts, mountIngestGame2DEmbed, mountIngestGame2DIframeReachable, mountIngestGame2DIframeReachableMulti, } from './ingest-iframe';
|
|
11
|
+
export { type IngestGame2D, type IngestMount2D, mountIngestGame2D } from './ingest';
|
|
13
12
|
export { createPhysics2DRegistry, type Physics2DRefs, type Physics2DRegistry, } from './physics-registry';
|
|
14
13
|
export { type CapturedRuntime2D, installSceneCapture2D, type SceneCapture2DHandle, } from './scene-capture';
|
|
15
14
|
export { createPhysicsAdapter2D, type PhysicsAdapter2D } from './system-adapters';
|
package/dist/pixi/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pixi/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pixi/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AACpF,OAAO,EACL,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,iBAAiB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,KAAK,iBAAiB,EACtB,qBAAqB,EACrB,KAAK,oBAAoB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/pixi/index.js
CHANGED
|
@@ -4,12 +4,11 @@
|
|
|
4
4
|
* PixiJS is opt-in: the engine core never imports it, so a three-only bundle
|
|
5
5
|
* never pays for it. What lives here is what the host needs to mount and
|
|
6
6
|
* inspect a PixiJS game it did not write — the render-call capture trap, the
|
|
7
|
-
* in-realm
|
|
7
|
+
* in-realm mount, the live display-tree authoring adapter, and the
|
|
8
8
|
* Rapier-2D handle registry the editor's transform coordination reads.
|
|
9
9
|
*/
|
|
10
10
|
export { AuthoringAdapter2D, } from './authoring';
|
|
11
|
-
export { mountIngestGame2D
|
|
12
|
-
export { mountIngestGame2DEmbed, mountIngestGame2DIframeReachable, mountIngestGame2DIframeReachableMulti, } from './ingest-iframe';
|
|
11
|
+
export { mountIngestGame2D } from './ingest';
|
|
13
12
|
export { createPhysics2DRegistry, } from './physics-registry';
|
|
14
13
|
export { installSceneCapture2D, } from './scene-capture';
|
|
15
14
|
export { createPhysicsAdapter2D } from './system-adapters';
|
package/dist/pixi/ingest.d.ts
CHANGED
|
@@ -1,85 +1,18 @@
|
|
|
1
1
|
import { type SceneCapture2DHandle } from './scene-capture';
|
|
2
|
-
/**
|
|
3
|
-
* A manifest's `extraDeps` resolve to TWO kinds of importmap entry:
|
|
4
|
-
* `namespaces` are today's registry-known bare specifiers
|
|
5
|
-
* (host-namespace-registry.ts), re-exported via a blob module
|
|
6
|
-
* (`ingest-iframe-2d.ts`'s `makeHostNamespaceReexportUrl`); `urls` are the
|
|
7
|
-
* D-Z3 fallback — a specifier that isn't registered but IS present in the
|
|
8
|
-
* open project's own `node_modules`, mapped DIRECTLY to its
|
|
9
|
-
* `/project-game-static/node_modules/<spec>/<esm entry>` URL (no host-side
|
|
10
|
-
* import, no blob — the dep executes in the iframe realm and its own
|
|
11
|
-
* transitive `import 'pixi.js'` resolves through the same importmap back to
|
|
12
|
-
* the host pixi trap). All probing/decision logic (which kind a specifier
|
|
13
|
-
* resolves to, exports-map parsing, anti-shim throws) lives editor-side
|
|
14
|
-
* (`host-namespace-registry.ts`) — this engine module only carries the
|
|
15
|
-
* ALREADY-DECIDED shape; `ingest-iframe-2d.ts` stays decision-free and just
|
|
16
|
-
* merges both maps into the iframe importmap.
|
|
17
|
-
*/
|
|
18
|
-
export interface ExtraDepsResolution2D {
|
|
19
|
-
namespaces: Record<string, Record<string, unknown>>;
|
|
20
|
-
urls: Record<string, string>;
|
|
21
|
-
}
|
|
22
2
|
/** A registered unmodified PixiJS game (the Pixi analog of `IngestGame`). */
|
|
23
3
|
export interface IngestGame2D {
|
|
24
4
|
id: string;
|
|
25
5
|
name: string;
|
|
26
6
|
description: string;
|
|
27
|
-
/**
|
|
28
|
-
load
|
|
29
|
-
/**
|
|
30
|
-
tier?: 'shared' | 'iframe-reachable' | 'opaque-embed';
|
|
7
|
+
/** Import + run the unmodified game module in the host's own realm. */
|
|
8
|
+
load: () => Promise<unknown>;
|
|
9
|
+
/** How long to wait for the game's first captured frame before failing. */
|
|
31
10
|
captureTimeoutMs?: number;
|
|
32
|
-
/**
|
|
33
|
-
* IFRAME-REACHABLE-MULTI fields (Track P): an externalized built bundle
|
|
34
|
-
* mounted via `mountIngestGame2DIframeReachableMulti`
|
|
35
|
-
* (`./ingest-iframe-2d.ts`) instead of `load()` — populated only when `tier`
|
|
36
|
-
* is `'iframe-reachable'` AND `load` is absent. Mirror
|
|
37
|
-
* `IframeReachableMultiOpts`'s fields, EXCEPT `extraDeps`/`pixiNamespace` are
|
|
38
|
-
* THUNKS here, not resolved values — the same "lazy, only invoked at mount
|
|
39
|
-
* time" shape `load` already uses, so building this descriptor
|
|
40
|
-
* (`resolveIngest2DDescriptor` / the canvas surface's
|
|
41
|
-
* `ingest/surface-canvas.ts`, editor-side — Wave 0.6 replaced the three
|
|
42
|
-
* per-surface `discovery*.ts` modules with one manifest-driven registry) never
|
|
43
|
-
* has to be async just to wire up which specifiers/ version-skew URL a game
|
|
44
|
-
* needs; only actually MOUNTING it (the ingest-mode mount bridge) pays for the
|
|
45
|
-
* dynamic import of `@pixi/sound`/`gsap`/spine/ a standalone pixi build.
|
|
46
|
-
*/
|
|
47
|
-
bundleUrl?: string;
|
|
48
|
-
/** <base href> for the iframe (see `IframeReachableMultiOpts.baseHref`). */
|
|
49
|
-
baseHref?: string;
|
|
50
|
-
/** Host-side Assets.init basePath remap (see `IframeReachableMultiOpts.assetBaseUrl`). */
|
|
51
|
-
assetBaseUrl?: string;
|
|
52
|
-
/**
|
|
53
|
-
* Lazily resolve this game's bare-specifier -> extraDeps resolution via the
|
|
54
|
-
* editor's host-namespace registry. Absent (or omitted) means no extra deps
|
|
55
|
-
* beyond pixi.js.
|
|
56
|
-
*/
|
|
57
|
-
extraDeps?: () => Promise<ExtraDepsResolution2D>;
|
|
58
|
-
/**
|
|
59
|
-
* Lazily resolve the trapped-pixi namespace for version-skewed games (a
|
|
60
|
-
* dynamic `import()` of the manifest's `pixiModuleUrl`) — absent means
|
|
61
|
-
* "mount against the host's own `pixi.js`" (no skew).
|
|
62
|
-
*/
|
|
63
|
-
pixiNamespace?: () => Promise<unknown>;
|
|
64
|
-
/** DOM the game expects before boot (see `IframeReachableMultiOpts.bodyHtml`). */
|
|
65
|
-
bodyHtml?: string;
|
|
66
|
-
/**
|
|
67
|
-
* Lazily read an OPAQUE prebuilt bundle's self-contained HTML (D-W2) — the pixi
|
|
68
|
-
* twin of `IngestGame.embedHtml`. Always a lazy thunk here (no in-tree Pixi
|
|
69
|
-
* opaque-embed fixture exists yet to need a plain-string form, unlike the three
|
|
70
|
-
* side): `resolveIngest2DDescriptor` (adapter-resolver.ts) builds one that reads
|
|
71
|
-
* the declared `entryHtml` file's bytes through the `/project-game-static/`
|
|
72
|
-
* route, only when the game is actually mounted. The host runs the resolved HTML
|
|
73
|
-
* in a sandboxed iframe at the embed-only floor (Tier 0-1),
|
|
74
|
-
* `mountIngestGame2DEmbed` (`./ingest-iframe-2d.ts`).
|
|
75
|
-
*/
|
|
76
|
-
embedHtml?: () => Promise<string>;
|
|
77
11
|
}
|
|
78
12
|
export interface IngestMount2D {
|
|
79
|
-
/** The captured live stage Container
|
|
80
|
-
stage: unknown
|
|
13
|
+
/** The captured live stage Container. */
|
|
14
|
+
stage: unknown;
|
|
81
15
|
capture: SceneCapture2DHandle;
|
|
82
|
-
embedOnly: boolean;
|
|
83
16
|
setPaused(paused: boolean): void;
|
|
84
17
|
dispose(): void;
|
|
85
18
|
}
|
|
@@ -87,9 +20,8 @@ export interface IngestMount2D {
|
|
|
87
20
|
* Mount an UNMODIFIED PixiJS game via the shared-instance capture path — the 2D
|
|
88
21
|
* analog of `mountIngestGame`. Installs the render trap on the host's pixi
|
|
89
22
|
* instance, runs the game's `load()`, waits for the game to render its first
|
|
90
|
-
* frame (capturing its live stage), and exposes loop gating + cleanup.
|
|
91
|
-
*
|
|
92
|
-
* never a silent failure.
|
|
23
|
+
* frame (capturing its live stage), and exposes loop gating + cleanup. A game
|
|
24
|
+
* whose pixi the trap cannot reach never captures, and the mount FAILS by name.
|
|
93
25
|
*/
|
|
94
26
|
export declare function mountIngestGame2D(pixiNamespace: unknown, game: IngestGame2D, opts?: {
|
|
95
27
|
captureTimeoutMs?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../src/pixi/ingest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEnF
|
|
1
|
+
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../src/pixi/ingest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEnF,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,oBAAoB,CAAC;IAC9B,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,aAAa,EAAE,OAAO,EACtB,IAAI,EAAE,YAAY,EAClB,IAAI,GAAE;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAO,GACvC,OAAO,CAAC,aAAa,CAAC,CAwBxB"}
|
package/dist/pixi/ingest.js
CHANGED
|
@@ -3,14 +3,13 @@ import { installSceneCapture2D } from './scene-capture';
|
|
|
3
3
|
* Mount an UNMODIFIED PixiJS game via the shared-instance capture path — the 2D
|
|
4
4
|
* analog of `mountIngestGame`. Installs the render trap on the host's pixi
|
|
5
5
|
* instance, runs the game's `load()`, waits for the game to render its first
|
|
6
|
-
* frame (capturing its live stage), and exposes loop gating + cleanup.
|
|
7
|
-
*
|
|
8
|
-
* never a silent failure.
|
|
6
|
+
* frame (capturing its live stage), and exposes loop gating + cleanup. A game
|
|
7
|
+
* whose pixi the trap cannot reach never captures, and the mount FAILS by name.
|
|
9
8
|
*/
|
|
10
9
|
export async function mountIngestGame2D(pixiNamespace, game, opts = {}) {
|
|
11
10
|
const capture = installSceneCapture2D(pixiNamespace);
|
|
12
11
|
try {
|
|
13
|
-
await game.load
|
|
12
|
+
await game.load();
|
|
14
13
|
}
|
|
15
14
|
catch (err) {
|
|
16
15
|
capture.uninstall();
|
|
@@ -22,19 +21,12 @@ export async function mountIngestGame2D(pixiNamespace, game, opts = {}) {
|
|
|
22
21
|
return {
|
|
23
22
|
stage: rt.stage,
|
|
24
23
|
capture,
|
|
25
|
-
embedOnly: false,
|
|
26
24
|
setPaused: (p) => capture.setPaused(p),
|
|
27
25
|
dispose: () => capture.uninstall(),
|
|
28
26
|
};
|
|
29
27
|
}
|
|
30
|
-
catch {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
stage: null,
|
|
34
|
-
capture,
|
|
35
|
-
embedOnly: true,
|
|
36
|
-
setPaused: () => { },
|
|
37
|
-
dispose: () => capture.uninstall(),
|
|
38
|
-
};
|
|
28
|
+
catch (err) {
|
|
29
|
+
capture.uninstall();
|
|
30
|
+
throw new Error(`pixi ingest: game "${game.id}" rendered no capturable frame within ${timeout}ms: ${err}`);
|
|
39
31
|
}
|
|
40
32
|
}
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* CRITICAL (same module-identity gatekeeper as the 3D path): the trap must be
|
|
15
15
|
* installed on the SAME `pixi.js` module instance the game uses. A bundler/dev-server
|
|
16
16
|
* that dedupes `pixi.js` makes an ESM game's `import 'pixi.js'` resolve to the host
|
|
17
|
-
* instance, so it is trapped; a game bundling its own pixi cannot be captured
|
|
18
|
-
*
|
|
17
|
+
* instance, so it is trapped; a game bundling its own pixi cannot be captured at
|
|
18
|
+
* all, and its mount fails by name.
|
|
19
19
|
*/
|
|
20
20
|
/** A live Pixi runtime captured from an external PixiJS game. */
|
|
21
21
|
export interface CapturedRuntime2D {
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* CRITICAL (same module-identity gatekeeper as the 3D path): the trap must be
|
|
15
15
|
* installed on the SAME `pixi.js` module instance the game uses. A bundler/dev-server
|
|
16
16
|
* that dedupes `pixi.js` makes an ESM game's `import 'pixi.js'` resolve to the host
|
|
17
|
-
* instance, so it is trapped; a game bundling its own pixi cannot be captured
|
|
18
|
-
*
|
|
17
|
+
* instance, so it is trapped; a game bundling its own pixi cannot be captured at
|
|
18
|
+
* all, and its mount fails by name.
|
|
19
19
|
*/
|
|
20
20
|
/**
|
|
21
21
|
* Install the render trap on `pixiNamespace.Application.prototype.render`. Pass the
|
package/dist/react/use-data.d.ts
CHANGED
|
@@ -50,11 +50,16 @@ export declare function useData<T>(handle: DataHandle<T>): T;
|
|
|
50
50
|
* this rejects with a teaching error (a shipped game could never reach the
|
|
51
51
|
* route anyway — builds strip `src/tools/` entirely, §4).
|
|
52
52
|
*
|
|
53
|
-
*
|
|
54
|
-
* `
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
53
|
+
* The body is PARSED VALUES, never serialized text: the dev server's fold
|
|
54
|
+
* (`packages/editor/server/data-file-serialize.ts`) owns key order and the
|
|
55
|
+
* `"$schema"`-first diff-minimal serialization, and it must — a parsed JS
|
|
56
|
+
* object has already reindexed integer-like keys ("1","2","10"), so only the
|
|
57
|
+
* server, which still has the file's raw text, can keep a one-field write a
|
|
58
|
+
* one-line diff. When `value` carries no `"$schema"` key (the common case —
|
|
59
|
+
* `DataHandle.get()` strips it), the conventional sibling reference
|
|
60
|
+
* (`./<name>.schema.json`, §2.1) is restored so a tool write never silently
|
|
61
|
+
* drops VS Code validation from the file. Undo for data writes is git;
|
|
62
|
+
* every accepted write is recorded server-side as a project revision.
|
|
58
63
|
*/
|
|
59
64
|
export declare function writeData(projectRelativePath: string, value: Record<string, unknown>): Promise<void>;
|
|
60
65
|
//# sourceMappingURL=use-data.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-data.d.ts","sourceRoot":"","sources":["../../src/react/use-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAKnD;AAED
|
|
1
|
+
{"version":3,"file":"use-data.d.ts","sourceRoot":"","sources":["../../src/react/use-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAKnD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,SAAS,CAC7B,mBAAmB,EAAE,MAAM,EAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC,CA2Cf"}
|
package/dist/react/use-data.js
CHANGED
|
@@ -52,11 +52,16 @@ export function useData(handle) {
|
|
|
52
52
|
* this rejects with a teaching error (a shipped game could never reach the
|
|
53
53
|
* route anyway — builds strip `src/tools/` entirely, §4).
|
|
54
54
|
*
|
|
55
|
-
*
|
|
56
|
-
* `
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
55
|
+
* The body is PARSED VALUES, never serialized text: the dev server's fold
|
|
56
|
+
* (`packages/editor/server/data-file-serialize.ts`) owns key order and the
|
|
57
|
+
* `"$schema"`-first diff-minimal serialization, and it must — a parsed JS
|
|
58
|
+
* object has already reindexed integer-like keys ("1","2","10"), so only the
|
|
59
|
+
* server, which still has the file's raw text, can keep a one-field write a
|
|
60
|
+
* one-line diff. When `value` carries no `"$schema"` key (the common case —
|
|
61
|
+
* `DataHandle.get()` strips it), the conventional sibling reference
|
|
62
|
+
* (`./<name>.schema.json`, §2.1) is restored so a tool write never silently
|
|
63
|
+
* drops VS Code validation from the file. Undo for data writes is git;
|
|
64
|
+
* every accepted write is recorded server-side as a project revision.
|
|
60
65
|
*/
|
|
61
66
|
export async function writeData(projectRelativePath, value) {
|
|
62
67
|
if (!projectRelativePath.startsWith('src/data/') || !projectRelativePath.endsWith('.data.json')) {
|
|
@@ -64,27 +69,22 @@ export async function writeData(projectRelativePath, value) {
|
|
|
64
69
|
'src/data/**/*.data.json, addressed project-relative, ' +
|
|
65
70
|
"e.g. writeData('src/data/tuning.data.json', next).");
|
|
66
71
|
}
|
|
67
|
-
// "$schema"
|
|
68
|
-
//
|
|
69
|
-
//
|
|
72
|
+
// Restore the conventional sibling "$schema" reference when the caller's
|
|
73
|
+
// object (typically `{ ...handle.get() }`, which never carries it) omits
|
|
74
|
+
// it; the server fold serializes it first.
|
|
70
75
|
const { $schema, ...rest } = value;
|
|
71
76
|
const schemaRef = $schema ??
|
|
72
77
|
`./${projectRelativePath
|
|
73
78
|
.split('/')
|
|
74
79
|
.pop()
|
|
75
80
|
?.replace(/\.data\.json$/, '')}.schema.json`;
|
|
76
|
-
const
|
|
77
|
-
const transactionalWriter = globalThis.__vgaiHistoryWriteData;
|
|
78
|
-
if (transactionalWriter) {
|
|
79
|
-
await transactionalWriter(projectRelativePath, content);
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
81
|
+
const values = { $schema: schemaRef, ...rest };
|
|
82
82
|
let res;
|
|
83
83
|
try {
|
|
84
84
|
res = await fetch('/__editor/data-file', {
|
|
85
85
|
method: 'POST',
|
|
86
86
|
headers: { 'Content-Type': 'application/json' },
|
|
87
|
-
body: JSON.stringify({ path: projectRelativePath,
|
|
87
|
+
body: JSON.stringify({ path: projectRelativePath, values }),
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
90
|
catch (err) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
/** Temporary developer-facing shading modes. These never become scene data. */
|
|
3
|
-
export type ViewportShadingMode = 'solid' | 'unlit' | 'wireframe' | 'normals' | 'overdraw';
|
|
3
|
+
export type ViewportShadingMode = 'solid' | 'clay' | 'unlit' | 'wireframe' | 'normals' | 'overdraw';
|
|
4
4
|
/**
|
|
5
5
|
* Applies a render-only material view and restores every native material in a
|
|
6
6
|
* `finally` block. Gameplay and authoring therefore always observe the real
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"viewport-shading.d.ts","sourceRoot":"","sources":["../../src/render/viewport-shading.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,+EAA+E;AAC/E,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"viewport-shading.d.ts","sourceRoot":"","sources":["../../src/render/viewport-shading.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,+EAA+E;AAC/E,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;AAqBpG;;;;GAIG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2C;IACpE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CASvB;IAEH,MAAM,CACJ,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,IAAI,EAAE,mBAAmB,EACzB,IAAI,EAAE,MAAM,IAAI,EAChB,OAAO,GAAE,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,OAAoB,GAClD,IAAI;IA0BP,OAAO,IAAI,IAAI;IAWf,OAAO,CAAC,YAAY;CA6CrB"}
|