incanto 0.70.0 → 0.72.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/incanto-editor.mjs +15 -9
- package/bin/incanto-feel.mjs +11 -1
- package/bin/incanto-play.mjs +11 -1
- package/bin/incanto-playtest.mjs +11 -1
- package/bin/incanto-verify.mjs +36 -98
- package/dist/2d.d.ts +18 -3
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +3 -3
- package/dist/3d.js +6 -6
- package/dist/{agent8-CmNF01gA.js → agent8-BqZ0_O1u.js} +1 -1
- package/dist/{audio-player-DaMxqfNE.d.ts → audio-player-ioZ7VKC6.d.ts} +1 -1
- package/dist/{behavior-DZExDn9o.d.ts → behavior-Bf9P9oB2.d.ts} +12 -1
- package/dist/{create-game-Bwvh6q8A.js → create-game-C9rWqqAC.js} +37 -13
- package/dist/{create-game-C7ffQWW7.js → create-game-CmFAtLZp.js} +8 -7
- package/dist/debug.d.ts +1 -1
- package/dist/editor.js +1083 -1045
- package/dist/{environment-presets-D6Q5BxeE.js → environment-presets-BeHoaGhy.js} +3 -3
- package/dist/{frame-report-Dlq13Gyj.js → frame-report-D-_7YF2G.js} +1 -1
- package/dist/{gameplay-BfHkuzVb.js → gameplay-BlQe-M07.js} +108 -6
- package/dist/gameplay.d.ts +68 -4
- package/dist/gameplay.js +2 -2
- package/dist/index.d.ts +27 -4
- package/dist/index.js +4 -4
- package/dist/{loader-Cff09LMm.d.ts → loader-CBfQzB6S.d.ts} +10 -3
- package/dist/net.d.ts +2 -2
- package/dist/net.js +2 -2
- package/dist/{physics-2d-CE0Qvy3V.js → physics-2d-DrIgTlLk.js} +2 -2
- package/dist/{physics-3d-CpH-2gn5.js → physics-3d-BzOCw1VS.js} +3 -3
- package/dist/{picking-CQJ_PJKh.js → picking-C9McVJrO.js} +3 -3
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-6DYnKZcy.js → register-5IYfooAN.js} +49 -15
- package/dist/{register-Bkk0wSDB.js → register-C8HuRkOf.js} +100 -8
- package/dist/{replay-Dmw-PKQu.d.ts → replay-CBEChqXq.d.ts} +2 -2
- package/dist/{replay-DjAkAzMq.js → replay-datiAE-b.js} +15 -8
- package/dist/{save-slots-BXVg148r.js → save-slots-CEuJPUle.js} +102 -4
- package/dist/{split-screen-PL78oVXP.js → split-screen-Bm5DTElG.js} +3 -3
- package/dist/{split-screen--k-XpBjr.d.ts → split-screen-DkqLng6q.d.ts} +2 -2
- package/dist/{src-Cxfiv1Hg.js → src-DRSsRleD.js} +1 -1
- package/dist/{test-iHYVUcDK.js → test-Djuq3Vhq.js} +252 -24
- package/dist/test.d.ts +113 -5
- package/dist/test.js +3 -3
- package/dist/vite.d.ts +8 -1
- package/dist/vite.js +23 -6
- package/editor/assets/{agent8-D0MS174y.js → agent8-CMKz2cax.js} +1 -1
- package/editor/assets/{debug-BnXkKuYu.js → debug-DLrQm-az.js} +1 -1
- package/editor/assets/{index-CIu3uc3l.js → index-BEKuxYcE.js} +94 -94
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +4 -0
- package/skills/incanto-behaviors-and-scripts.md +30 -9
- package/skills/incanto-building-2d-games.md +26 -2
- package/skills/incanto-editor.md +4 -0
- package/skills/incanto-gameplay-behaviors.md +63 -1
- package/skills/incanto-hud.md +14 -0
- package/skills/incanto-node-reference.md +18 -2
- package/skills/incanto-playtesting.md +34 -0
- package/skills/incanto-save-slots.md +56 -1
- package/skills/incanto-scene-json-authoring.md +30 -0
- package/skills/incanto-verifying-your-game.md +11 -0
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/beacon-isle-3d/src/game.scene.json +396 -386
- package/templates-app/molehill-2d/package.json +1 -1
- package/templates-app/molehill-2d/src/game.scene.json +10 -60
- package/templates-app/platformer-2d/package.json +1 -1
- package/templates-app/platformer-2d/src/game.scene.json +268 -504
- package/templates-app/star-survivor/package.json +1 -1
- package/templates-app/star-survivor/src/game.scene.json +23 -33
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/tps-3d/src/game.scene.json +90 -105
- package/templates-app/village-quest-3d/package.json +1 -1
- package/templates-app/village-quest-3d/src/behaviors.ts +21 -4
- package/templates-app/village-quest-3d/src/grove.scene.json +99 -118
- package/templates-app/village-quest-3d/src/village.scene.json +449 -245
package/bin/incanto-editor.mjs
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
31
31
|
import { createServer } from 'node:http';
|
|
32
32
|
import { basename, dirname, extname, join, normalize, relative, resolve, sep } from 'node:path';
|
|
33
|
-
import { fileURLToPath } from 'node:url';
|
|
33
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
34
34
|
import { readJson } from './_read-json.mjs';
|
|
35
35
|
|
|
36
36
|
const PKG_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
@@ -463,7 +463,7 @@ const server = createServer((req, res) => {
|
|
|
463
463
|
if (!originAllowed(req)) {
|
|
464
464
|
return send(res, 403, JSON.stringify({ error: 'cross-origin write rejected' }));
|
|
465
465
|
}
|
|
466
|
-
readBody(req, res, (body) => {
|
|
466
|
+
readBody(req, res, async (body) => {
|
|
467
467
|
// a path with no extension means the usual thing, so `levels/arena` works
|
|
468
468
|
const wanted =
|
|
469
469
|
typeof body?.path === 'string' && body.path && !body.path.endsWith('.json')
|
|
@@ -495,14 +495,20 @@ const server = createServer((req, res) => {
|
|
|
495
495
|
*/
|
|
496
496
|
const asked = body?.dimension === '3d' || body?.dimension === '2d' ? body.dimension : null;
|
|
497
497
|
const dimension = asked ?? projectDimension() ?? '2d';
|
|
498
|
-
const scene = {
|
|
499
|
-
format: 1,
|
|
500
|
-
type: 'scene',
|
|
501
|
-
dimension,
|
|
502
|
-
name,
|
|
503
|
-
root: { name, type: dimension === '3d' ? 'Node3D' : 'Node2D' },
|
|
504
|
-
};
|
|
505
498
|
try {
|
|
499
|
+
// uid at CREATION, like every node the editor makes: without it the
|
|
500
|
+
// first save backfills one and the diff carries a line nobody wrote.
|
|
501
|
+
// Imported here rather than at the top so starting the editor never
|
|
502
|
+
// pays for `dist` it may not otherwise need — inside the try, so a
|
|
503
|
+
// missing build is a 400 and not a dead server.
|
|
504
|
+
const { newUid } = await import(pathToFileURL(join(PKG_ROOT, 'dist', 'index.js')).href);
|
|
505
|
+
const scene = {
|
|
506
|
+
format: 1,
|
|
507
|
+
type: 'scene',
|
|
508
|
+
dimension,
|
|
509
|
+
name,
|
|
510
|
+
root: { name, type: dimension === '3d' ? 'Node3D' : 'Node2D', uid: newUid() },
|
|
511
|
+
};
|
|
506
512
|
mkdirSync(dirname(abs), { recursive: true });
|
|
507
513
|
writeFileSync(abs, formatSceneJson(scene));
|
|
508
514
|
return send(res, 201, JSON.stringify({ rel: relative(ROOT, abs), abs }));
|
package/bin/incanto-feel.mjs
CHANGED
|
@@ -60,7 +60,17 @@ if (args.help || !args.scene) {
|
|
|
60
60
|
pushed +x/-y/+y/-x until the player moves)
|
|
61
61
|
--jump ACTION the button to jump with (default: "jump")
|
|
62
62
|
--json the report as JSON instead of prose`);
|
|
63
|
-
|
|
63
|
+
/*
|
|
64
|
+
* `--help` is a REQUEST, and the answer is the text above.
|
|
65
|
+
*
|
|
66
|
+
* The rule used to be "0 only if a scene was also named", so the exact thing
|
|
67
|
+
* an agent types first — `incanto-playtest --help` — printed the usage and
|
|
68
|
+
* exited 1, while thirteen sibling bins exited 0 for the same input. A
|
|
69
|
+
* non-zero exit says "you did it wrong" to someone who did the documented
|
|
70
|
+
* thing, and under `set -e` it stops the script. A typo still exits 1
|
|
71
|
+
* (`invalid`), and so does a missing scene when help was not asked for.
|
|
72
|
+
*/
|
|
73
|
+
process.exit(args.help && !args.invalid ? 0 : 1);
|
|
64
74
|
}
|
|
65
75
|
|
|
66
76
|
const { facingReport, facingText, feelReport, feelText } = await import(
|
package/bin/incanto-play.mjs
CHANGED
|
@@ -69,7 +69,17 @@ if (args.help || !args.scene) {
|
|
|
69
69
|
|
|
70
70
|
Headless play: stdin commands (step/press/release/vector/key/mouse/pointer/
|
|
71
71
|
wheel/capture/describe/framing/logs/quit), JSON-line responses on stdout.`);
|
|
72
|
-
|
|
72
|
+
/*
|
|
73
|
+
* `--help` is a REQUEST, and the answer is the text above.
|
|
74
|
+
*
|
|
75
|
+
* The rule used to be "0 only if a scene was also named", so the exact thing
|
|
76
|
+
* an agent types first — `incanto-playtest --help` — printed the usage and
|
|
77
|
+
* exited 1, while thirteen sibling bins exited 0 for the same input. A
|
|
78
|
+
* non-zero exit says "you did it wrong" to someone who did the documented
|
|
79
|
+
* thing, and under `set -e` it stops the script. A typo still exits 1
|
|
80
|
+
* (`invalid`), and so does a missing scene when help was not asked for.
|
|
81
|
+
*/
|
|
82
|
+
process.exit(args.help && !args.invalid ? 0 : 1);
|
|
73
83
|
}
|
|
74
84
|
|
|
75
85
|
const out = (obj) => process.stdout.write(`${JSON.stringify(obj)}\n`);
|
package/bin/incanto-playtest.mjs
CHANGED
|
@@ -92,7 +92,17 @@ if (args.help || !args.scene) {
|
|
|
92
92
|
Exits 1 when a run THREW or left the world, or when a win is declared and no
|
|
93
93
|
run reached it. A scene that declares no win, or has nobody to drive, exits 0 —
|
|
94
94
|
the report marks those · rather than ✗, and the exit code says the same.`);
|
|
95
|
-
|
|
95
|
+
/*
|
|
96
|
+
* `--help` is a REQUEST, and the answer is the text above.
|
|
97
|
+
*
|
|
98
|
+
* The rule used to be "0 only if a scene was also named", so the exact thing
|
|
99
|
+
* an agent types first — `incanto-playtest --help` — printed the usage and
|
|
100
|
+
* exited 1, while thirteen sibling bins exited 0 for the same input. A
|
|
101
|
+
* non-zero exit says "you did it wrong" to someone who did the documented
|
|
102
|
+
* thing, and under `set -e` it stops the script. A typo still exits 1
|
|
103
|
+
* (`invalid`), and so does a missing scene when help was not asked for.
|
|
104
|
+
*/
|
|
105
|
+
process.exit(args.help && !args.invalid ? 0 : 1);
|
|
96
106
|
}
|
|
97
107
|
|
|
98
108
|
const { playtest, playtestText, playtestFailed, failingReplays } = await import(
|
package/bin/incanto-verify.mjs
CHANGED
|
@@ -25,7 +25,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
25
25
|
import { readJson } from './_read-json.mjs';
|
|
26
26
|
|
|
27
27
|
const PKG = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
28
|
-
const { firstLine, ladderText, ladderVerdict, saysRung } = await import(
|
|
28
|
+
const { feelsRung, firstLine, ladderText, ladderVerdict, saysRung, unmeasuredPlays } = await import(
|
|
29
29
|
pathToFileURL(join(PKG, 'dist', 'test.js')).href
|
|
30
30
|
);
|
|
31
31
|
|
|
@@ -218,6 +218,9 @@ const rungs = [];
|
|
|
218
218
|
/** The playtest's JSON, shared by the `plays` and `feels` rungs. */
|
|
219
219
|
let playtestReport = null;
|
|
220
220
|
|
|
221
|
+
/** Did the bot get the game MOVING? Set by the `plays` rung, read by `feels`. */
|
|
222
|
+
let botPlayed = true;
|
|
223
|
+
|
|
221
224
|
// ---- plays ---------------------------------------------------------------
|
|
222
225
|
if (rungs[0].status === 'pass') {
|
|
223
226
|
const args = [scene, '--json', '--runs', '8'];
|
|
@@ -274,6 +277,8 @@ if (rungs[0].status === 'pass') {
|
|
|
274
277
|
const DEFECT = new Set(stuckCounts ? ['error', 'fell', 'stuck'] : ['error', 'fell']);
|
|
275
278
|
const defects = out?.runs?.filter((x) => DEFECT.has(x.outcome)) ?? [];
|
|
276
279
|
const undrivable = total > 0 && defects.length === 0 && tally('stuck') === total;
|
|
280
|
+
// …and the `feels` rung below asks the same question, so it is answered once.
|
|
281
|
+
botPlayed = !undrivable;
|
|
277
282
|
const count = (n, word) => n && `${n} ${word}`;
|
|
278
283
|
|
|
279
284
|
if (total === 0) {
|
|
@@ -343,23 +348,10 @@ if (rungs[0].status === 'pass') {
|
|
|
343
348
|
* match-3, tower defense, cards, point-and-click, RTS, board games — has no
|
|
344
349
|
* character to add, and the advice was to add one anyway.
|
|
345
350
|
*/
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
summary:
|
|
351
|
-
clicks > 0
|
|
352
|
-
? `played with the MOUSE — ${clicks} click(s) across ${total} runs, and no win to reach`
|
|
353
|
-
: out?.hasPlayer === false
|
|
354
|
-
? `nothing here is drivable — ${total} runs had nobody to move and nothing to click`
|
|
355
|
-
: `${total} runs went nowhere, and your behaviours were not loaded — that is most of what moves a character`,
|
|
356
|
-
fix:
|
|
357
|
-
clicks > 0
|
|
358
|
-
? 'a mouse game is played, not walked — emit `won`/`lost` and this rung can pass'
|
|
359
|
-
: out?.hasPlayer === false
|
|
360
|
-
? 'give the player a character controller, the `player` group, or the name Player — or `Clickable` on what the cursor drives'
|
|
361
|
-
: `name them: \`incanto-verify ${scene} --behaviors src/behaviors.ts\``,
|
|
362
|
-
});
|
|
351
|
+
// The wording lives in `verify-ladder.ts` (pure, and tested there) —
|
|
352
|
+
// this branch owns only the fact that the bot could not WALK.
|
|
353
|
+
const said = unmeasuredPlays({ ...(out ?? {}), scene });
|
|
354
|
+
rungs.push({ name: 'plays', status: 'unmeasured', summary: said.summary, fix: said.fix });
|
|
363
355
|
} else if (noGoal) {
|
|
364
356
|
rungs.push({
|
|
365
357
|
name: 'plays',
|
|
@@ -403,71 +395,10 @@ if (rungs[0].status === 'pass') {
|
|
|
403
395
|
// Sound and effects, from the same playtest that just ran. A game whose
|
|
404
396
|
// feedback is wired but never triggered plays perfectly and feels dead, and
|
|
405
397
|
// every other rung here calls it healthy.
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
if (!fb) {
|
|
411
|
-
rungs.push({
|
|
412
|
-
name: 'feels',
|
|
413
|
-
status: 'skipped',
|
|
414
|
-
summary: 'not run — the playtest did not report',
|
|
415
|
-
});
|
|
416
|
-
} else if (declared === 0) {
|
|
417
|
-
rungs.push({
|
|
418
|
-
name: 'feels',
|
|
419
|
-
status: 'skipped',
|
|
420
|
-
summary: 'this game declares no sound and no effects',
|
|
421
|
-
});
|
|
422
|
-
} else if (fired.size === 0) {
|
|
423
|
-
rungs.push({
|
|
424
|
-
name: 'feels',
|
|
425
|
-
status: 'fail',
|
|
426
|
-
summary: `${declared} sound/effect node(s) declared, and not one fired in any run`,
|
|
427
|
-
fix: 'connect them — a signal to `play` on an AudioPlayer, or `replay()` on a one-shot; `engine.audio.recent()` and `engine.effects.recent()` say what did fire',
|
|
428
|
-
});
|
|
429
|
-
} else {
|
|
430
|
-
const declaredPaths = [...(fb.declaredAudio ?? []), ...(fb.declaredEffects ?? [])];
|
|
431
|
-
const silent = declaredPaths.filter((path) => !fired.has(path));
|
|
432
|
-
// Of the nodes this rung is ABOUT, how many fired. `fired` also holds paths
|
|
433
|
-
// nobody declared — a spawned clone sounds from its own path, a procedural
|
|
434
|
-
// preset from wherever a behaviour played it — so using its size printed
|
|
435
|
-
// arithmetic that cannot be true: `✓ feels — 12 of 9 fired`. The number has
|
|
436
|
-
// to add up with the `silent` list beside it.
|
|
437
|
-
const firedDeclared = declaredPaths.length - silent.length;
|
|
438
|
-
/*
|
|
439
|
-
* A rung that exists because "wired but never triggered plays perfectly and
|
|
440
|
-
* feels dead, and every other rung here calls it healthy" — and which then
|
|
441
|
-
* called it healthy itself. `fired.size === 0` failed and ANYTHING else
|
|
442
|
-
* passed, so the flagship starter reported
|
|
443
|
-
*
|
|
444
|
-
* ✓ feels — 13 of 26 fired — silent: /Game/Ward1/ChimeSfx …
|
|
445
|
-
*
|
|
446
|
-
* A tick next to thirteen emitters nobody heard is the same claim the rung
|
|
447
|
-
* was written to stop.
|
|
448
|
-
*
|
|
449
|
-
* It is not a FAILURE either: a random bot does not light three wards, so a
|
|
450
|
-
* win chime it never reached is not a broken wire. That is exactly what
|
|
451
|
-
* `unmeasured` means in this ladder — the tool did not get to look — and it
|
|
452
|
-
* is the one status that cannot be read as approval.
|
|
453
|
-
*/
|
|
454
|
-
rungs.push({
|
|
455
|
-
name: 'feels',
|
|
456
|
-
...(silent.length === 0
|
|
457
|
-
? { status: 'pass', summary: `every one of the ${declared} sound/effect nodes fired` }
|
|
458
|
-
: {
|
|
459
|
-
status: 'unmeasured',
|
|
460
|
-
summary:
|
|
461
|
-
`${firedDeclared} of ${declared} fired — silent: ${silent.slice(0, 3).join(', ')}` +
|
|
462
|
-
`${silent.length > 3 ? ` +${silent.length - 3}` : ''}`,
|
|
463
|
-
fix:
|
|
464
|
-
'a silent emitter is either a broken wire or a moment random play never ' +
|
|
465
|
-
'reached — the two look identical from here. Reach it in a scripted run ' +
|
|
466
|
-
'(`runScript` from `incanto/test`), and this rung can tell you which.',
|
|
467
|
-
}),
|
|
468
|
-
});
|
|
469
|
-
}
|
|
470
|
-
}
|
|
398
|
+
// The wording lives in `verify-ladder.ts` (pure, and tested there).
|
|
399
|
+
// `undrivable` is the plays rung's own "the bot never got it moving", so the
|
|
400
|
+
// two never disagree about whether anything was played.
|
|
401
|
+
rungs.push(feelsRung(playtestReport?.feedback, { played: botPlayed }));
|
|
471
402
|
|
|
472
403
|
// ---- agrees --------------------------------------------------------------
|
|
473
404
|
// A desync is the purest silent failure this engine has: both clients run,
|
|
@@ -544,28 +475,27 @@ if (rungs[0].status === 'pass') {
|
|
|
544
475
|
? 'bring the preview window to the front — a hidden tab does not render, and a frame is captured inside a render'
|
|
545
476
|
: 'start your dev server, open the page, and run this again — the pixels are in the browser',
|
|
546
477
|
});
|
|
547
|
-
} else if (report.hidden) {
|
|
478
|
+
} else if (report.hidden && report.droveFrames === 0) {
|
|
548
479
|
/*
|
|
549
|
-
* A hidden page
|
|
550
|
-
*
|
|
551
|
-
* A browser stops animating a page it considers hidden — a window merely
|
|
552
|
-
* covered by another counts — and the back buffer keeps whatever it last
|
|
553
|
-
* drew. Measured at one instant, same page:
|
|
480
|
+
* A hidden page cannot be DRIVEN, and that one is still unmeasured.
|
|
554
481
|
*
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
*
|
|
482
|
+
* The rung used to refuse any hidden page, on the belief that its pixels
|
|
483
|
+
* were "whatever it last drew". They are not: `captureFrame` in both
|
|
484
|
+
* renderers waits ~120 ms for a loop that a hidden tab never runs, and then
|
|
485
|
+
* draws a frame itself. Measured — hide every node from the console and
|
|
486
|
+
* capture again: 2D `luminance 0.09 → 0.00 BLACK SCREEN`, 3D `0.64 → 0.96,
|
|
487
|
+
* subject 44.3% → 22.0%`.
|
|
559
488
|
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
* the
|
|
489
|
+
* So a plain capture is current and measurable, and the ONLY thing a hidden
|
|
490
|
+
* page cannot do is advance — which is exactly what a drive needs, and what
|
|
491
|
+
* `droveFrames: 0` reports. Refusing both cost this rung every measurement
|
|
492
|
+
* it could have made in the setup the whole toolchain is built for: a
|
|
493
|
+
* terminal in front and a browser behind it.
|
|
564
494
|
*/
|
|
565
495
|
rungs.push({
|
|
566
496
|
name: 'draws',
|
|
567
497
|
status: 'unmeasured',
|
|
568
|
-
summary: 'the
|
|
498
|
+
summary: 'the drive ran on a HIDDEN page — 0 frames drawn, so nothing it did shows here',
|
|
569
499
|
fix: 'bring the window to the front (one covered by another counts as hidden) and run this again',
|
|
570
500
|
});
|
|
571
501
|
} else if (report.black) {
|
|
@@ -598,6 +528,14 @@ if (rungs[0].status === 'pass') {
|
|
|
598
528
|
if (report.uniform) {
|
|
599
529
|
notes.push('one flat colour — the camera may be inside geometry, or only the sky is drawn');
|
|
600
530
|
}
|
|
531
|
+
// Measured, not refused — but the reader still has to know the world was
|
|
532
|
+
// not moving while it was drawn.
|
|
533
|
+
if (report.hidden) {
|
|
534
|
+
notes.push(
|
|
535
|
+
'the page is hidden, so the game is PAUSED — this frame was rendered for the ' +
|
|
536
|
+
'capture, and shows the moment it froze',
|
|
537
|
+
);
|
|
538
|
+
}
|
|
601
539
|
rungs.push({
|
|
602
540
|
name: 'draws',
|
|
603
541
|
status: 'pass',
|
package/dist/2d.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { c as showBootFailure, i as ParticleSim, o as ParticleView, r as SpatialPose, s as isWebGLAvailable } from "./audio-player-
|
|
2
|
-
import { P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats, x as EngineOptions } from "./behavior-
|
|
1
|
+
import { c as showBootFailure, i as ParticleSim, o as ParticleView, r as SpatialPose, s as isWebGLAvailable } from "./audio-player-ioZ7VKC6.js";
|
|
2
|
+
import { P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats, x as EngineOptions } from "./behavior-Bf9P9oB2.js";
|
|
3
3
|
import { t as DiagnosticSink } from "./diagnostics-Cu85N3tL.js";
|
|
4
4
|
import { a as SceneJson, s as JsonObject } from "./rng-Bb-IutXB.js";
|
|
5
5
|
import { t as EditorSwitchOptions } from "./editor-switch-CFU9mCec.js";
|
|
6
6
|
import { r as FrameStats } from "./frame-report-DNxDAb1w.js";
|
|
7
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
7
|
+
import { t as LoadSceneOptions } from "./loader-CBfQzB6S.js";
|
|
8
8
|
import { n as AnimationEntry } from "./sprite-animation-CMr6f1K2.js";
|
|
9
9
|
import { Group, Mesh, Object3D, Scene, Texture } from "three";
|
|
10
10
|
import * as RapierNs from "@dimforge/rapier2d-compat";
|
|
@@ -1151,6 +1151,21 @@ declare class TileMap2D extends Node2D {
|
|
|
1151
1151
|
set cells(value: (string | number[])[]);
|
|
1152
1152
|
get legend(): Record<string, number>;
|
|
1153
1153
|
set legend(value: Record<string, number>);
|
|
1154
|
+
private _colors;
|
|
1155
|
+
get colors(): Record<string, string>;
|
|
1156
|
+
set colors(value: Record<string, string>);
|
|
1157
|
+
/**
|
|
1158
|
+
* The colours, in declaration order — a cell's tile index is `COLOR_BASE + i`.
|
|
1159
|
+
*
|
|
1160
|
+
* A synthetic index rather than a second grid: everything downstream (the
|
|
1161
|
+
* collider merge, `tileAt`, `setTile`, the editor's paint tool) already
|
|
1162
|
+
* speaks in indices, and one number per cell keeps it that way.
|
|
1163
|
+
*/
|
|
1164
|
+
private palette;
|
|
1165
|
+
/** `legend` plus the colour chars, which is what every cell lookup wants. */
|
|
1166
|
+
private allChars;
|
|
1167
|
+
/** `solid` as INDICES: an entry may name the char that painted the cell. */
|
|
1168
|
+
private solidIndices;
|
|
1154
1169
|
get solid(): number[];
|
|
1155
1170
|
set solid(value: number[]);
|
|
1156
1171
|
opacity: number;
|
package/dist/2d.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
2
2
|
import { t as showBootFailure } from "./boot-failure-CKYrEcGF.js";
|
|
3
3
|
import { t as isWebGLAvailable } from "./webgl-unavailable-C8aDbGmR.js";
|
|
4
|
-
import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-
|
|
5
|
-
import { _ as RigidBody2D, a as parseCells, c as ColorRect2D, d as AnimatedSprite2D, f as Sprite2D, g as PhysicsBody2D, h as CharacterBody2D, i as mergeSolidRects, l as CharacterController2D, m as Area2D, n as UILayer, o as Particles2D, p as Joint2D, r as TileMap2D, s as Label, t as registerNodes2D, u as Camera2D, v as StaticBody2D, y as Node2D } from "./register-
|
|
6
|
-
import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-
|
|
4
|
+
import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-C9rWqqAC.js";
|
|
5
|
+
import { _ as RigidBody2D, a as parseCells, c as ColorRect2D, d as AnimatedSprite2D, f as Sprite2D, g as PhysicsBody2D, h as CharacterBody2D, i as mergeSolidRects, l as CharacterController2D, m as Area2D, n as UILayer, o as Particles2D, p as Joint2D, r as TileMap2D, s as Label, t as registerNodes2D, u as Camera2D, v as StaticBody2D, y as Node2D } from "./register-C8HuRkOf.js";
|
|
6
|
+
import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-DrIgTlLk.js";
|
|
7
7
|
//#region src/2d/library-sprite.ts
|
|
8
8
|
/**
|
|
9
9
|
* What a `CharacterController2D`/`3D` will ask a skin to play, and the clip in
|
package/dist/3d.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { c as showBootFailure, i as ParticleSim, o as ParticleView, r as SpatialPose, s as isWebGLAvailable } from "./audio-player-
|
|
2
|
-
import { D as QualityCaps, P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats, x as EngineOptions } from "./behavior-
|
|
1
|
+
import { c as showBootFailure, i as ParticleSim, o as ParticleView, r as SpatialPose, s as isWebGLAvailable } from "./audio-player-ioZ7VKC6.js";
|
|
2
|
+
import { D as QualityCaps, P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats, x as EngineOptions } from "./behavior-Bf9P9oB2.js";
|
|
3
3
|
import { t as DiagnosticSink } from "./diagnostics-Cu85N3tL.js";
|
|
4
4
|
import { a as SceneJson$1, s as JsonObject } from "./rng-Bb-IutXB.js";
|
|
5
5
|
import { t as EditorSwitchOptions } from "./editor-switch-CFU9mCec.js";
|
|
6
6
|
import { a as GridCell, c as diffText, d as frameText, i as FrameStatsOptions, l as frameSignature, n as FrameSignature, o as SIGNATURE_GRID, r as FrameStats, s as diffSignatures, t as FrameDiff, u as frameStats } from "./frame-report-DNxDAb1w.js";
|
|
7
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
7
|
+
import { t as LoadSceneOptions } from "./loader-CBfQzB6S.js";
|
|
8
8
|
import { n as PathGrid } from "./pathfinding-_fGrCFmH.js";
|
|
9
9
|
import { AnimationClip, AnimationMixer, BufferGeometry, Color, DirectionalLight, Group, InstancedMesh, Mesh, MeshPhysicalMaterial, Object3D, PerspectiveCamera, Scene, ShaderMaterial, Texture, Vector3, WebGLRenderer } from "three";
|
|
10
10
|
import { VRM } from "@pixiv/three-vrm";
|
package/dist/3d.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as sunDirectionFromSky, S as sunDirectionFromElevationAzimuth, b as horizonColorFromSky, x as parseEnvironment3D } from "./save-slots-CEuJPUle.js";
|
|
2
2
|
import { t as showBootFailure } from "./boot-failure-CKYrEcGF.js";
|
|
3
3
|
import { t as isWebGLAvailable } from "./webgl-unavailable-C8aDbGmR.js";
|
|
4
|
-
import { a as frameSignature, n as diffSignatures, o as frameStats, r as diffText, s as frameText, t as SIGNATURE_GRID } from "./frame-report-
|
|
5
|
-
import {
|
|
6
|
-
import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-
|
|
7
|
-
import { a as Environment3D, c as AssetStore3D, i as syncTree, o as applyQualityTier3D, r as Renderer3D, s as setEnvironment3D, t as createGame3D } from "./create-game-
|
|
4
|
+
import { a as frameSignature, n as diffSignatures, o as frameStats, r as diffText, s as frameText, t as SIGNATURE_GRID } from "./frame-report-D-_7YF2G.js";
|
|
5
|
+
import { G as StaticBody3D, H as CharacterBody3D, K as Node3D, L as Water3D, R as WATER_CUTOUT_MAX, U as PhysicsBody3D, V as Area3D, W as RigidBody3D, Y as WATER_MAX_RIPPLES, z as WaterCutout3D } from "./gameplay-BlQe-M07.js";
|
|
6
|
+
import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-BeHoaGhy.js";
|
|
7
|
+
import { a as Environment3D, c as AssetStore3D, i as syncTree, o as applyQualityTier3D, r as Renderer3D, s as setEnvironment3D, t as createGame3D } from "./create-game-CmFAtLZp.js";
|
|
8
8
|
import { n as splatWeights, t as buildHeightmap } from "./heightmap-BYgD5Edk.js";
|
|
9
|
-
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-
|
|
9
|
+
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-BzOCw1VS.js";
|
|
10
10
|
//#region src/3d/model-verdict.ts
|
|
11
11
|
/** Mixamo exports every bone as `mixamorigX`; the retargeter binds by that name. */
|
|
12
12
|
const MIXAMO = /^mixamorig[:_]?/i;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { o as __exportAll } from "./json-CfTjpvW8.js";
|
|
2
|
-
import {
|
|
2
|
+
import { Y as diagnose } from "./save-slots-CEuJPUle.js";
|
|
3
3
|
//#region src/net/agent8.ts
|
|
4
4
|
var agent8_exports = /* @__PURE__ */ __exportAll({
|
|
5
5
|
Agent8TransportForTest: () => Agent8Transport,
|
|
@@ -414,6 +414,17 @@ declare class Node implements NodeLifecycle {
|
|
|
414
414
|
* SceneTree). Frees immediately when detached from any tree.
|
|
415
415
|
*/
|
|
416
416
|
queueFree(): void;
|
|
417
|
+
/**
|
|
418
|
+
* Has this node been torn down?
|
|
419
|
+
*
|
|
420
|
+
* A scene swap frees the tree it replaces, so the answer is `true` for every
|
|
421
|
+
* node of the scene you just left — which is exactly the state a behavior is
|
|
422
|
+
* in when it runs one more line after `goToScene`. Kept as a flag rather than
|
|
423
|
+
* inferred from `parent`/`tree`, because a DETACHED node (a prefab on a
|
|
424
|
+
* shelf, a clone waiting to be added) has neither and is perfectly alive.
|
|
425
|
+
*/
|
|
426
|
+
get freed(): boolean;
|
|
427
|
+
private _freed;
|
|
417
428
|
/** Immediately detach and tear down this node and its children. */
|
|
418
429
|
free(): void;
|
|
419
430
|
/**
|
|
@@ -2286,7 +2297,7 @@ declare class Engine {
|
|
|
2286
2297
|
* pass it back. Without that a game using the documented sub-scenes booted
|
|
2287
2298
|
* fine and threw `UNRESOLVED_INSTANCE` on its first restart.
|
|
2288
2299
|
*/
|
|
2289
|
-
resolveScene?: (path: string) => SceneJson;
|
|
2300
|
+
resolveScene?: (path: string) => SceneJson | null | undefined;
|
|
2290
2301
|
/**
|
|
2291
2302
|
* How the current scene was LOADED, for the rebuilds that happen later.
|
|
2292
2303
|
*
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { o as __exportAll } from "./json-CfTjpvW8.js";
|
|
2
|
-
import {
|
|
3
|
-
import { C as qualityRendering, _ as AudioPlayer, v as Engine } from "./register-
|
|
2
|
+
import { D as computeViewport, O as resolveViewport, R as sceneDimension, Y as diagnose, h as loadScene, ot as registerBehavior } from "./save-slots-CEuJPUle.js";
|
|
3
|
+
import { C as qualityRendering, _ as AudioPlayer, v as Engine } from "./register-5IYfooAN.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
5
|
import { n as attachTouchControls } from "./touch-BnCyPA0G.js";
|
|
6
6
|
import { n as withWebGLContext, r as resolveRendering } from "./webgl-unavailable-C8aDbGmR.js";
|
|
7
|
-
import { a as devServerLibrary, c as applyDriveStep, d as audioErrors, i as crossFade, l as wireDevChannel, n as teardown, o as openBundledEditor, r as pauseWhenHidden, t as nodeFromHits, u as claimCanvasGestures } from "./picking-
|
|
8
|
-
import { o as frameStats } from "./frame-report-
|
|
9
|
-
import { n as registerGameplayBehaviors } from "./gameplay-
|
|
10
|
-
import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-
|
|
7
|
+
import { a as devServerLibrary, c as applyDriveStep, d as audioErrors, i as crossFade, l as wireDevChannel, n as teardown, o as openBundledEditor, r as pauseWhenHidden, t as nodeFromHits, u as claimCanvasGestures } from "./picking-C9McVJrO.js";
|
|
8
|
+
import { o as frameStats } from "./frame-report-D-_7YF2G.js";
|
|
9
|
+
import { n as registerGameplayBehaviors } from "./gameplay-BlQe-M07.js";
|
|
10
|
+
import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-C8HuRkOf.js";
|
|
11
11
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
12
|
-
import { n as enablePhysics2D } from "./physics-2d-
|
|
12
|
+
import { n as enablePhysics2D } from "./physics-2d-DrIgTlLk.js";
|
|
13
13
|
import { Box3, BufferAttribute, BufferGeometry, Color, LineBasicMaterial, LineSegments, LinearFilter, NearestFilter, OrthographicCamera, Raycaster, SRGBColorSpace, Scene, TextureLoader, Vector2, Vector3, WebGLRenderer } from "three";
|
|
14
14
|
//#region src/2d/assets.ts
|
|
15
15
|
/**
|
|
@@ -132,6 +132,34 @@ var AssetStore2D = class {
|
|
|
132
132
|
}
|
|
133
133
|
};
|
|
134
134
|
//#endregion
|
|
135
|
+
//#region src/2d/debug-lines.ts
|
|
136
|
+
/**
|
|
137
|
+
* Physics debug segments, moved into the space the 2D renderer draws in.
|
|
138
|
+
*
|
|
139
|
+
* Two coordinate systems meet here and they disagree about Y. Engine 2D is
|
|
140
|
+
* y-DOWN (screen pixels, gravity `+980`, and Rapier's world is built the same
|
|
141
|
+
* way — `kcc.setUp({x: 0, y: -1})`). The three.js scene the renderer paints
|
|
142
|
+
* into is y-UP, which is why every node's own sync writes
|
|
143
|
+
* `o.position.set(x, -y, 0)`.
|
|
144
|
+
*
|
|
145
|
+
* `syncDebugLines` copied Rapier's vertices straight across without that
|
|
146
|
+
* negation, so every collider outline was MIRRORED about the world's y=0 line:
|
|
147
|
+
* a crate at y=120 drew its box at −120, the further from the axis the further
|
|
148
|
+
* off, and a tilemap's merged floor at y=384 drew itself off the top of the
|
|
149
|
+
* canvas entirely. The overlay whose whole promise is "the colliders the
|
|
150
|
+
* ENGINE builds… wherever physics actually puts them" was the one thing in the
|
|
151
|
+
* 2D view that was not where physics put it.
|
|
152
|
+
*/
|
|
153
|
+
function debugLinesToScene(px) {
|
|
154
|
+
const xyz = new Float32Array(px.length / 2 * 3);
|
|
155
|
+
for (let i = 0, j = 0; i < px.length; i += 2, j += 3) {
|
|
156
|
+
xyz[j] = px[i];
|
|
157
|
+
xyz[j + 1] = -px[i + 1];
|
|
158
|
+
xyz[j + 2] = 0;
|
|
159
|
+
}
|
|
160
|
+
return xyz;
|
|
161
|
+
}
|
|
162
|
+
//#endregion
|
|
135
163
|
//#region src/2d/picking.ts
|
|
136
164
|
function screenFromWorld(view, wx, wy) {
|
|
137
165
|
return {
|
|
@@ -547,12 +575,7 @@ var Renderer2D = class {
|
|
|
547
575
|
}
|
|
548
576
|
this.debugLines.visible = vertices !== null;
|
|
549
577
|
if (!vertices) return;
|
|
550
|
-
const xyz =
|
|
551
|
-
for (let i = 0, j = 0; i < vertices.length; i += 2, j += 3) {
|
|
552
|
-
xyz[j] = vertices[i];
|
|
553
|
-
xyz[j + 1] = vertices[i + 1];
|
|
554
|
-
xyz[j + 2] = 0;
|
|
555
|
-
}
|
|
578
|
+
const xyz = debugLinesToScene(vertices);
|
|
556
579
|
this.debugLines.geometry.setAttribute("position", new BufferAttribute(xyz, 3));
|
|
557
580
|
}
|
|
558
581
|
render() {
|
|
@@ -809,6 +832,7 @@ async function createGame2D(opts) {
|
|
|
809
832
|
...opts._scheduler ? { scheduler: opts._scheduler } : {}
|
|
810
833
|
});
|
|
811
834
|
const sourceJson = cloneSceneJson(opts.scene);
|
|
835
|
+
if (sceneDimension(sourceJson) === "3d") throw new IncantoError("WRONG_DIMENSION", `createGame2D was given a 3D scene ('${String(sourceJson.name ?? "scene")}'). Its nodes are never drawn by the 2D renderer and never simulated by 2D physics — you get a blank canvas. Boot it with createGame3D instead.`);
|
|
812
836
|
const scene = loadScene(cloneSceneJson(sourceJson), {
|
|
813
837
|
resolveScene: opts.resolveScene,
|
|
814
838
|
engine
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { o as __exportAll } from "./json-CfTjpvW8.js";
|
|
2
|
-
import {
|
|
3
|
-
import { C as qualityRendering, S as qualityEnvironment, _ as AudioPlayer, v as Engine, x as qualityCaps } from "./register-
|
|
2
|
+
import { C as sunDirectionFromSky, R as sceneDimension, Y as diagnose, b as horizonColorFromSky, h as loadScene, ot as registerBehavior, x as parseEnvironment3D } from "./save-slots-CEuJPUle.js";
|
|
3
|
+
import { C as qualityRendering, S as qualityEnvironment, _ as AudioPlayer, v as Engine, x as qualityCaps } from "./register-5IYfooAN.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
5
|
import { n as attachTouchControls } from "./touch-BnCyPA0G.js";
|
|
6
6
|
import { n as withWebGLContext, r as resolveRendering } from "./webgl-unavailable-C8aDbGmR.js";
|
|
7
|
-
import { a as devServerLibrary, c as applyDriveStep, d as audioErrors, i as crossFade, l as wireDevChannel, n as teardown, o as openBundledEditor, r as pauseWhenHidden, s as poseFromRenderer, t as nodeFromHits, u as claimCanvasGestures } from "./picking-
|
|
8
|
-
import { o as frameStats } from "./frame-report-
|
|
9
|
-
import {
|
|
7
|
+
import { a as devServerLibrary, c as applyDriveStep, d as audioErrors, i as crossFade, l as wireDevChannel, n as teardown, o as openBundledEditor, r as pauseWhenHidden, s as poseFromRenderer, t as nodeFromHits, u as claimCanvasGestures } from "./picking-C9McVJrO.js";
|
|
8
|
+
import { o as frameStats } from "./frame-report-D-_7YF2G.js";
|
|
9
|
+
import { J as createCausticsQuad, K as Node3D, U as PhysicsBody3D, n as registerGameplayBehaviors } from "./gameplay-BlQe-M07.js";
|
|
10
10
|
import { t as debugSources } from "./debug-draw-BM3DsvtT.js";
|
|
11
|
-
import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-
|
|
12
|
-
import { n as enablePhysics3D } from "./physics-3d-
|
|
11
|
+
import { E as Camera3D, U as TextureCache3D, g as ModelInstance3D, n as registerNodes3D, t as resolveEnvironmentHdri, v as DirectionalLight3D } from "./environment-presets-BeHoaGhy.js";
|
|
12
|
+
import { n as enablePhysics3D } from "./physics-3d-BzOCw1VS.js";
|
|
13
13
|
import { ACESFilmicToneMapping, AmbientLight, Box3, BufferAttribute, BufferGeometry, Color, DepthTexture, EquirectangularReflectionMapping, FloatType, Fog, HalfFloatType, LineBasicMaterial, LineSegments, LoadingManager, Matrix4, Mesh, PCFShadowMap, PMREMGenerator, PerspectiveCamera, PlaneGeometry, Quaternion, Raycaster, Scene, ShaderMaterial, Vector2, Vector3, WebGLRenderTarget, WebGLRenderer } from "three";
|
|
14
14
|
import { VRMLoaderPlugin, VRMUtils } from "@pixiv/three-vrm";
|
|
15
15
|
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
|
@@ -2253,6 +2253,7 @@ async function createGame3D(opts) {
|
|
|
2253
2253
|
...opts._scheduler ? { scheduler: opts._scheduler } : {}
|
|
2254
2254
|
});
|
|
2255
2255
|
const sourceJson = cloneSceneJson(opts.scene);
|
|
2256
|
+
if (sceneDimension(sourceJson) === "2d") throw new IncantoError("WRONG_DIMENSION", `createGame3D was given a 2D scene ('${String(sourceJson.name ?? "scene")}'). Its nodes are never drawn by the 3D renderer and never simulated by 3D physics — you get a blank canvas. Boot it with createGame2D instead.`);
|
|
2256
2257
|
const scene = loadScene(cloneSceneJson(sourceJson), {
|
|
2257
2258
|
resolveScene: opts.resolveScene,
|
|
2258
2259
|
engine
|
package/dist/debug.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ft as LogLevel, T as RendererStats, b as Engine } from "./behavior-
|
|
1
|
+
import { Ft as LogLevel, T as RendererStats, b as Engine } from "./behavior-Bf9P9oB2.js";
|
|
2
2
|
|
|
3
3
|
//#region src/debug/panel.d.ts
|
|
4
4
|
/** Minimal document surface the overlay needs (injectable for tests). */
|