incanto 0.67.0 → 0.68.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/_pick-server.mjs +48 -0
- package/bin/incanto-check.mjs +16 -2
- package/bin/incanto-frame.mjs +10 -25
- package/bin/incanto-logs.mjs +8 -18
- package/dist/2d.d.ts +6 -6
- package/dist/2d.js +6 -4
- package/dist/3d.d.ts +30 -6
- package/dist/3d.js +8 -6
- package/dist/{audio-player-BNUHo0JF.d.ts → audio-player-DOrq7sP-.d.ts} +62 -4
- package/dist/{behavior-ZnfzKDo3.d.ts → behavior-DoFPYrgo.d.ts} +78 -1
- package/dist/boot-failure-CKYrEcGF.js +47 -0
- package/dist/{create-game-FAXdHta3.js → create-game-DbWtVTxD.js} +21 -25
- package/dist/{create-game-DMetd3vR.js → create-game-IZIydDwI.js} +9 -9
- package/dist/debug.d.ts +1 -1
- package/dist/{duplicate-B8QnX2-r.js → duplicate-IWIqk0HJ.js} +1 -1
- package/dist/{editor-switch-DAvWQeld.d.ts → editor-switch-CnIOiyNJ.d.ts} +1 -1
- package/dist/editor.js +11 -5
- package/dist/env.d.ts +1 -1
- package/dist/{environment-presets-C-5g2pMh.js → environment-presets-CybQXNqS.js} +57 -8
- package/dist/{gameplay-CGSv-9XR.js → gameplay-DM1eu_cV.js} +20 -2
- package/dist/gameplay.d.ts +51 -3
- package/dist/gameplay.js +2 -2
- package/dist/index.d.ts +6 -6
- package/dist/index.js +8 -7
- package/dist/{loader-KZESOZmE.js → loader-BC4PNtJX.js} +26 -1
- package/dist/{loader-DyT30ArB.d.ts → loader-CcB533FR.d.ts} +2 -2
- package/dist/net.d.ts +2 -2
- package/dist/net.js +1 -1
- package/dist/{physics-2d-_B6zj3zU.js → physics-2d-B7Y6dPZO.js} +2 -2
- package/dist/{physics-3d-i1IeAY0F.js → physics-3d-bG3n70Ky.js} +3 -3
- package/dist/react.d.ts +2 -2
- package/dist/react.js +1 -1
- package/dist/{register-Cs53CY7s.js → register-3ta-2Xig.js} +68 -7
- package/dist/{register-vIxU3Xbv.js → register-ibCjm-wH.js} +3 -3
- package/dist/{replay-BkpDV51O.js → replay-CYvhVHHN.js} +28 -5
- package/dist/{replay-D0GcEHYU.d.ts → replay-Dvn8aeBd.d.ts} +38 -4
- package/dist/{schema-CFeioQRE.d.ts → schema-B6ugCV1Q.d.ts} +11 -0
- package/dist/{split-screen-DS8RaUV_.js → split-screen-CYwDkbLF.js} +2 -2
- package/dist/{split-screen-DD5eYIgW.d.ts → split-screen-DhrSzZIB.d.ts} +3 -3
- package/dist/{src-BLlsGJW9.js → src-D7RIqXYF.js} +1 -1
- package/dist/{teardown-LB9cTnXJ.js → teardown-D2NEmxPB.js} +2 -2
- package/dist/{test-81uZ967a.js → test-8hoHeRmo.js} +26 -21
- package/dist/test.d.ts +6 -6
- package/dist/test.js +3 -3
- package/dist/vite.js +2 -2
- package/dist/{rendering-options-ByAdi8PF.js → webgl-unavailable-N9nQqesw.js} +45 -1
- package/editor/assets/{agent8-C2jtNKbx.js → agent8-BrrHOjMJ.js} +1 -1
- package/editor/assets/{debug-DoU3KeqS.js → debug-BBhKuBNV.js} +1 -1
- package/editor/assets/{index-CNqHojcC.js → index-eVd0BToA.js} +92 -92
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +4 -0
- package/skills/incanto-3d-character.md +1 -0
- package/skills/incanto-audio.md +49 -0
- package/skills/incanto-building-2d-games.md +37 -0
- package/skills/incanto-building-3d-games.md +37 -0
- package/skills/incanto-gameplay-behaviors.md +28 -1
- package/skills/incanto-node-reference.md +1 -0
- package/skills/incanto-physics-and-input.md +23 -0
- package/skills/incanto-scene-json-authoring.md +12 -1
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/beacon-isle-3d/src/main.ts +8 -1
- package/templates-app/platformer-2d/package.json +1 -1
- package/templates-app/platformer-2d/src/main.ts +8 -1
- package/templates-app/star-survivor/package.json +1 -1
- package/templates-app/star-survivor/src/main.ts +8 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/tps-3d/src/main.ts +8 -1
- package/templates-app/village-quest-3d/package.json +1 -1
- package/templates-app/village-quest-3d/src/main.ts +8 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { k as diagnose } from "./loader-
|
|
2
|
+
import { k as diagnose } from "./loader-BC4PNtJX.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
|
-
import { _ as RigidBody2D, b as validateCollider2D, g as PhysicsBody2D, h as CharacterBody2D, m as Area2D, p as Joint2D, y as Node2D } from "./register-
|
|
4
|
+
import { _ as RigidBody2D, b as validateCollider2D, g as PhysicsBody2D, h as CharacterBody2D, m as Area2D, p as Joint2D, y as Node2D } from "./register-ibCjm-wH.js";
|
|
5
5
|
import { n as registerDebugSource } from "./debug-draw-BM3DsvtT.js";
|
|
6
6
|
import { n as jointContacts, t as withoutRapierInitNoise } from "./quiet-rapier-C6fW4zcW.js";
|
|
7
7
|
//#region src/2d/physics/physics-2d.ts
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { k as diagnose } from "./loader-
|
|
2
|
+
import { k as diagnose } from "./loader-BC4PNtJX.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
|
-
import { H as CharacterBody3D, K as Node3D, U as PhysicsBody3D, V as Area3D, W as RigidBody3D, q as validateCollider3D } from "./gameplay-
|
|
4
|
+
import { H as CharacterBody3D, K as Node3D, U as PhysicsBody3D, V as Area3D, W as RigidBody3D, q as validateCollider3D } from "./gameplay-DM1eu_cV.js";
|
|
5
5
|
import { n as registerDebugSource } from "./debug-draw-BM3DsvtT.js";
|
|
6
6
|
import { n as jointContacts, t as withoutRapierInitNoise } from "./quiet-rapier-C6fW4zcW.js";
|
|
7
|
-
import { A as Terrain3D, F as InstancedMesh3D, L as buildMeshGeometry, P as Joint3D } from "./environment-presets-
|
|
7
|
+
import { A as Terrain3D, F as InstancedMesh3D, L as buildMeshGeometry, P as Joint3D } from "./environment-presets-CybQXNqS.js";
|
|
8
8
|
import { Euler, Matrix4, Quaternion, Vector3 } from "three";
|
|
9
9
|
//#region src/3d/physics/collider-lines.ts
|
|
10
10
|
/**
|
package/dist/react.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as Scene, b as Engine, n as BehaviorCtor } from "./behavior-
|
|
2
|
-
import { c as JsonValue } from "./schema-
|
|
1
|
+
import { P as Scene, b as Engine, n as BehaviorCtor } from "./behavior-DoFPYrgo.js";
|
|
2
|
+
import { c as JsonValue } from "./schema-B6ugCV1Q.js";
|
|
3
3
|
import { CSSProperties, ReactNode } from "react";
|
|
4
4
|
|
|
5
5
|
//#region src/react/index.d.ts
|
package/dist/react.js
CHANGED
|
@@ -156,7 +156,7 @@ function IncantoCanvas(props) {
|
|
|
156
156
|
pointer: latest.pointer,
|
|
157
157
|
...keyboard !== void 0 ? { keyboard } : {}
|
|
158
158
|
};
|
|
159
|
-
const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-
|
|
159
|
+
const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-DbWtVTxD.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-IZIydDwI.js").then((n) => n.n)).createGame2D(o)))(opts);
|
|
160
160
|
if (disposed) {
|
|
161
161
|
next.dispose();
|
|
162
162
|
return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { C as ORDER_GROUP_BASE, E as InputMap, O as Node, S as createSaveStore, T as resolveOrderGroups, V as Signal, b as restoreBehaviors, k as diagnose, y as captureBehaviors } from "./loader-
|
|
2
|
+
import { C as ORDER_GROUP_BASE, E as InputMap, O as Node, S as createSaveStore, T as resolveOrderGroups, V as Signal, b as restoreBehaviors, k as diagnose, y as captureBehaviors } from "./loader-BC4PNtJX.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
5
5
|
import { l as registerNode } from "./registry-CF70EArN.js";
|
|
@@ -179,6 +179,11 @@ var WebAudioTrack = class {
|
|
|
179
179
|
setLoop(loop) {
|
|
180
180
|
this.el.loop = loop;
|
|
181
181
|
}
|
|
182
|
+
/** The element's own playhead — the clock the sound is actually on. */
|
|
183
|
+
playhead() {
|
|
184
|
+
const at = this.el.currentTime;
|
|
185
|
+
return typeof at === "number" && Number.isFinite(at) ? at : null;
|
|
186
|
+
}
|
|
182
187
|
play() {
|
|
183
188
|
this.el.play().catch((error) => {
|
|
184
189
|
const name = error?.name ?? "";
|
|
@@ -243,7 +248,8 @@ const SILENT_BACKEND = {
|
|
|
243
248
|
setGain() {},
|
|
244
249
|
setLoop() {},
|
|
245
250
|
play() {},
|
|
246
|
-
stop() {}
|
|
251
|
+
stop() {},
|
|
252
|
+
playhead: () => null
|
|
247
253
|
}),
|
|
248
254
|
unlock() {}
|
|
249
255
|
};
|
|
@@ -283,6 +289,24 @@ var MusicManager = class {
|
|
|
283
289
|
get current() {
|
|
284
290
|
return this.active?.track.src ?? null;
|
|
285
291
|
}
|
|
292
|
+
/**
|
|
293
|
+
* Seconds into the current track — the playhead of the thing you can HEAR.
|
|
294
|
+
*
|
|
295
|
+
* `null` when nothing is playing, or when the backend has no clock (headless,
|
|
296
|
+
* or a custom backend that does not implement it).
|
|
297
|
+
*
|
|
298
|
+
* A game charted to a soundtrack needs this and there was no way to get it:
|
|
299
|
+
* `current` gave the src and the backend was private, so the only option was
|
|
300
|
+
* an `engine.time` counter started next to `music.play()` — a different clock
|
|
301
|
+
* from the one the audio is on, and one that keeps counting through a
|
|
302
|
+
* gesture-block, a stall or a seek. This is the audio's own answer.
|
|
303
|
+
*
|
|
304
|
+
* It is the RAW element time, so a looping track wraps to 0 at each pass:
|
|
305
|
+
* that is a loop boundary you can chart against, not a fault.
|
|
306
|
+
*/
|
|
307
|
+
get playhead() {
|
|
308
|
+
return this.active?.track.playhead?.() ?? null;
|
|
309
|
+
}
|
|
286
310
|
/** Per-manager volume (0..1), on top of the bus gain. */
|
|
287
311
|
get volume() {
|
|
288
312
|
return this._volume;
|
|
@@ -1036,6 +1060,16 @@ var SfxEngine = class {
|
|
|
1036
1060
|
if (ctx && ctx.state === "suspended") ctx.resume();
|
|
1037
1061
|
}
|
|
1038
1062
|
/**
|
|
1063
|
+
* The AUDIO clock, in seconds — the one a sound is actually scheduled
|
|
1064
|
+
* against, and the only clock that does not drift relative to what you hear.
|
|
1065
|
+
*
|
|
1066
|
+
* `0` headless and before the first sound, since there is no context yet.
|
|
1067
|
+
* Schedule with a lead: `sfx.play(params, 1, { when: sfx.now + 0.08 })`.
|
|
1068
|
+
*/
|
|
1069
|
+
get now() {
|
|
1070
|
+
return this.ctx?.currentTime ?? 0;
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1039
1073
|
* Play a preset at `gain` (0..1, already bus-multiplied by the caller). Each
|
|
1040
1074
|
* call spawns its own source so rapid repeats overlap instead of cutting off.
|
|
1041
1075
|
* Headless → no-op.
|
|
@@ -1077,7 +1111,7 @@ var SfxEngine = class {
|
|
|
1077
1111
|
const source = ctx.createBufferSource();
|
|
1078
1112
|
source.buffer = buffer;
|
|
1079
1113
|
source.connect(gainNode);
|
|
1080
|
-
source.start();
|
|
1114
|
+
source.start(opts.when === void 0 ? 0 : Math.max(0, opts.when));
|
|
1081
1115
|
}
|
|
1082
1116
|
};
|
|
1083
1117
|
//#endregion
|
|
@@ -3005,10 +3039,32 @@ var AudioPlayer = class extends Node {
|
|
|
3005
3039
|
rolloff: this.rolloff
|
|
3006
3040
|
};
|
|
3007
3041
|
}
|
|
3008
|
-
|
|
3042
|
+
/**
|
|
3043
|
+
* Start the sound. `at` schedules it on the AUDIO clock instead of now.
|
|
3044
|
+
*
|
|
3045
|
+
* A frame is a 16.67 ms grid at 60 Hz and 33.33 ms at 30, so a sound fired
|
|
3046
|
+
* from `update()` cannot land closer than one frame to where a chart wants
|
|
3047
|
+
* it — measured 0 of 64 notes scheduled on the documented path. Queue it a
|
|
3048
|
+
* lead ahead of `engine.sfx.now` and the same notes land at |mean| 0.000000
|
|
3049
|
+
* ms:
|
|
3050
|
+
*
|
|
3051
|
+
* ```ts
|
|
3052
|
+
* const lead = 0.08; // schedule this far ahead
|
|
3053
|
+
* for (const note of dueSoon(engine.sfx.now + lead)) {
|
|
3054
|
+
* hit.play(engine.sfx.now + (note.atSec - songSeconds));
|
|
3055
|
+
* }
|
|
3056
|
+
* ```
|
|
3057
|
+
*
|
|
3058
|
+
* PRESETS only — a `src` clip goes through an `<audio>` element, which has no
|
|
3059
|
+
* scheduling clock, and passing `at` for one is ignored rather than silently
|
|
3060
|
+
* approximated. Everything else is unchanged: the bus gain applies, the sound
|
|
3061
|
+
* lands in `engine.audio.recent()`, and `muted` still silences it, none of
|
|
3062
|
+
* which a hand-rolled `AudioContext` scheduler keeps.
|
|
3063
|
+
*/
|
|
3064
|
+
play(at) {
|
|
3009
3065
|
if (this.preset !== "custom") {
|
|
3010
3066
|
this.note("preset", this.preset);
|
|
3011
|
-
this.playPreset();
|
|
3067
|
+
this.playPreset(at);
|
|
3012
3068
|
return;
|
|
3013
3069
|
}
|
|
3014
3070
|
if (!this.src) return;
|
|
@@ -3052,7 +3108,7 @@ var AudioPlayer = class extends Node {
|
|
|
3052
3108
|
* the length is arithmetic, not a device. WebAudio needs a gesture; a
|
|
3053
3109
|
* suspended context is resumed by the same unlock listener as `src` players.
|
|
3054
3110
|
*/
|
|
3055
|
-
playPreset() {
|
|
3111
|
+
playPreset(at) {
|
|
3056
3112
|
const params = SFX_PRESETS[this.preset];
|
|
3057
3113
|
if (!params) return;
|
|
3058
3114
|
const engine = this.tree?.engine;
|
|
@@ -3063,7 +3119,8 @@ var AudioPlayer = class extends Node {
|
|
|
3063
3119
|
sfx.play(params, this.gain(), {
|
|
3064
3120
|
pitch: this.pitch,
|
|
3065
3121
|
seed: this.seed,
|
|
3066
|
-
spatial: this.spatialPlay()
|
|
3122
|
+
spatial: this.spatialPlay(),
|
|
3123
|
+
when: at
|
|
3067
3124
|
});
|
|
3068
3125
|
}
|
|
3069
3126
|
/**
|
|
@@ -3099,6 +3156,10 @@ var AudioPlayer = class extends Node {
|
|
|
3099
3156
|
}
|
|
3100
3157
|
if (this.presetEndsAt !== null) {
|
|
3101
3158
|
if ((this.tree?.engine?.unscaledTime ?? 0) >= this.presetEndsAt) {
|
|
3159
|
+
if (this.loop) {
|
|
3160
|
+
this.playPreset();
|
|
3161
|
+
return;
|
|
3162
|
+
}
|
|
3102
3163
|
this.presetEndsAt = null;
|
|
3103
3164
|
this._playing = false;
|
|
3104
3165
|
this.emit("finished");
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { O as Node, k as diagnose, w as effectiveOrder } from "./loader-
|
|
2
|
-
import { L as translateOn, t as registerCoreNodes } from "./register-
|
|
1
|
+
import { O as Node, k as diagnose, w as effectiveOrder } from "./loader-BC4PNtJX.js";
|
|
2
|
+
import { L as translateOn, t as registerCoreNodes } from "./register-3ta-2Xig.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
5
5
|
import { i as getNodeSchema, l as registerNode } from "./registry-CF70EArN.js";
|
|
6
6
|
import { i as ParticleSim, n as resolveFrames, o as PARTICLE_PRESET_NAMES, r as validateAnimationAliases, s as applyParticlePreset, t as resolveAnimation } from "./sprite-animation-CY-mrr1L.js";
|
|
7
|
-
import { F as localFromWorld, I as worldPosition } from "./gameplay-
|
|
7
|
+
import { F as localFromWorld, I as worldPosition } from "./gameplay-DM1eu_cV.js";
|
|
8
8
|
import { t as checkSheetGrid } from "./sheet-grid-BT6N_Bjs.js";
|
|
9
9
|
import { AdditiveBlending, BufferAttribute, BufferGeometry, CanvasTexture, Color, DynamicDrawUsage, Group, InstancedMesh, MathUtils, Matrix4, Mesh, MeshBasicMaterial, NearestFilter, NormalBlending, Object3D, PlaneGeometry, SRGBColorSpace } from "three";
|
|
10
10
|
//#region src/2d/physics/collider-validate.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as handlerShadowWarnings, j as nodeRefWarnings } from "./loader-
|
|
2
|
-
import { R as translationKey, k as HudWidgetBase } from "./register-
|
|
1
|
+
import { D as handlerShadowWarnings, j as nodeRefWarnings } from "./loader-BC4PNtJX.js";
|
|
2
|
+
import { R as translationKey, k as HudWidgetBase } from "./register-3ta-2Xig.js";
|
|
3
3
|
import { o as getNodeType } from "./registry-CF70EArN.js";
|
|
4
4
|
//#region src/core/audit.ts
|
|
5
5
|
const ANIMATED_TYPES = new Set([
|
|
@@ -104,6 +104,28 @@ function transformOf(props) {
|
|
|
104
104
|
if (scaled) return "scale";
|
|
105
105
|
return null;
|
|
106
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Which files in a corpus some OTHER scene embeds with `instance`.
|
|
109
|
+
*
|
|
110
|
+
* A fragment cannot be recognised by looking at itself — `enemy.scene.json` and
|
|
111
|
+
* a broken first level are the same file shape. It is recognised by the project
|
|
112
|
+
* around it, which every tool that audits more than one scene already walks.
|
|
113
|
+
*
|
|
114
|
+
* `resolveRef(fromFile, ref)` turns a scene-relative `instance` path into the
|
|
115
|
+
* same spelling the corpus uses for that file, so the caller owns all path
|
|
116
|
+
* logic and this stays runnable in a browser.
|
|
117
|
+
*/
|
|
118
|
+
function instancedScenes(corpus, resolveRef) {
|
|
119
|
+
const instanced = /* @__PURE__ */ new Set();
|
|
120
|
+
const walk = (node, from) => {
|
|
121
|
+
if (!node || typeof node !== "object") return;
|
|
122
|
+
const ref = node.instance;
|
|
123
|
+
if (typeof ref === "string" && ref) instanced.add(resolveRef(from, ref));
|
|
124
|
+
for (const child of node.children ?? []) walk(child, from);
|
|
125
|
+
};
|
|
126
|
+
for (const { path, json } of corpus) walk(json.root, path);
|
|
127
|
+
return instanced;
|
|
128
|
+
}
|
|
107
129
|
function auditScene(scene, opts = {}) {
|
|
108
130
|
const warnings = [];
|
|
109
131
|
const root = scene.root;
|
|
@@ -166,8 +188,9 @@ function auditScene(scene, opts = {}) {
|
|
|
166
188
|
if (cameraDrivers.length > 0 && followedCameras.length > 0) warnings.push(`${followedCameras.join(", ")}: a FollowCamera writes this camera's position every frame, and so does the CharacterController3D at ${cameraDrivers.join(", ")} — the controller owns the camera in every view it has. Drop one of them: use the controller's own \`view\`/\`camDistance\`, or take the controller off the camera duty.`);
|
|
167
189
|
if (cameras > 0 && currentCameras === 0) warnings.push("no camera has \"current\": true — the screen renders from a default view, probably not what you framed.");
|
|
168
190
|
if (currentCameras > 1) warnings.push(`${currentCameras} cameras claim "current": true — only the first found wins.`);
|
|
169
|
-
const isFragment =
|
|
170
|
-
if (scene.dimension === "3d" && !isFragment &&
|
|
191
|
+
const isFragment = opts.instanced === true || scene.fragment === true;
|
|
192
|
+
if (scene.dimension === "3d" && !isFragment && cameras === 0) warnings.push("this 3D scene has no camera — the screen renders from a default view, which is almost never the shot you want. Add a Camera3D with \"current\": true, or set \"fragment\": true in the scene header if this file is a prefab another scene drops in.");
|
|
193
|
+
if (scene.dimension === "3d" && !isFragment && lights === 0 && !isLit(scene.environment)) warnings.push("nothing lights this 3D scene — no light node, no environment sky/hdri, and no ambient intensity. It will render black. Add a DirectionalLight3D, or an \"environment\": { \"sky\": { \"type\": \"atmosphere\" } } / { \"preset\": \"...\" } — or set \"fragment\": true if another scene lights this one.");
|
|
171
194
|
if (damageGroups.length > 0) {
|
|
172
195
|
const hurtable = hurtableGroups(root);
|
|
173
196
|
for (const { path, group } of damageGroups) {
|
|
@@ -359,4 +382,4 @@ function replay(engine, recording, opts) {
|
|
|
359
382
|
}
|
|
360
383
|
}
|
|
361
384
|
//#endregion
|
|
362
|
-
export { startRecording as n, auditScene as r, replay as t };
|
|
385
|
+
export { instancedScenes as i, startRecording as n, auditScene as r, replay as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { b as Engine } from "./behavior-
|
|
2
|
-
import { s as JsonObject } from "./schema-
|
|
1
|
+
import { b as Engine } from "./behavior-DoFPYrgo.js";
|
|
2
|
+
import { s as JsonObject } from "./schema-B6ugCV1Q.js";
|
|
3
3
|
|
|
4
4
|
//#region src/core/audit.d.ts
|
|
5
5
|
/** Human-readable warnings (empty = clean). Pure JSON walk, no registry. */
|
|
@@ -15,7 +15,41 @@ interface AuditOptions {
|
|
|
15
15
|
* has one.
|
|
16
16
|
*/
|
|
17
17
|
declaredElsewhere?: Record<string, Record<string, string>>;
|
|
18
|
+
/**
|
|
19
|
+
* Another scene in this project embeds this file with `instance`.
|
|
20
|
+
*
|
|
21
|
+
* That, and only that, makes a scene a FRAGMENT — a thing lit and framed by
|
|
22
|
+
* whatever drops it in, which must not be told it will render black.
|
|
23
|
+
*
|
|
24
|
+
* The discriminator used to be "it has no camera", which is the same shape a
|
|
25
|
+
* beginner's FIRST 3D scene has. Measured on a ground plane and a capsule
|
|
26
|
+
* with no camera and no light — a guaranteed black screen:
|
|
27
|
+
*
|
|
28
|
+
* $ incanto-check
|
|
29
|
+
* ok src/game.scene.json
|
|
30
|
+
* 1/1 scene(s) valid
|
|
31
|
+
*
|
|
32
|
+
* Not the lighting warning, and not the camera one either. The checker walks
|
|
33
|
+
* the whole project already (it unions `strings` and `assets` the same way),
|
|
34
|
+
* so it can answer this by looking instead of guessing.
|
|
35
|
+
*/
|
|
36
|
+
instanced?: boolean;
|
|
18
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Which files in a corpus some OTHER scene embeds with `instance`.
|
|
40
|
+
*
|
|
41
|
+
* A fragment cannot be recognised by looking at itself — `enemy.scene.json` and
|
|
42
|
+
* a broken first level are the same file shape. It is recognised by the project
|
|
43
|
+
* around it, which every tool that audits more than one scene already walks.
|
|
44
|
+
*
|
|
45
|
+
* `resolveRef(fromFile, ref)` turns a scene-relative `instance` path into the
|
|
46
|
+
* same spelling the corpus uses for that file, so the caller owns all path
|
|
47
|
+
* logic and this stays runnable in a browser.
|
|
48
|
+
*/
|
|
49
|
+
declare function instancedScenes(corpus: {
|
|
50
|
+
path: string;
|
|
51
|
+
json: JsonObject;
|
|
52
|
+
}[], resolveRef: (fromFile: string, ref: string) => string): Set<string>;
|
|
19
53
|
declare function auditScene(scene: JsonObject, opts?: AuditOptions): string[];
|
|
20
54
|
//#endregion
|
|
21
55
|
//#region src/core/errors.d.ts
|
|
@@ -25,7 +59,7 @@ declare function auditScene(scene: JsonObject, opts?: AuditOptions): string[];
|
|
|
25
59
|
* Incanto fails loudly with machine-readable codes and messages that list valid
|
|
26
60
|
* alternatives — AI agents self-correct on hard failures, not warnings.
|
|
27
61
|
*/
|
|
28
|
-
type IncantoErrorCode = "AMBIGUOUS_HANDLER" | "BAD_FORMAT" | "BAD_NODE_PATH" | "DANGLING_CONNECTION" | "DUPLICATE_BEHAVIOR" | "DUPLICATE_NODE_TYPE" | "DUPLICATE_UNIQUE_NAME" | "DUPLICATE_UID" | "NODE_NOT_FOUND" | "PROP_TYPE_MISMATCH" | "TREE_VIOLATION" | "UNKNOWN_ANIMATION" | "UNKNOWN_ASSET" | "UNKNOWN_CONSTANT" | "UNKNOWN_BEHAVIOR" | "UNKNOWN_HANDLER" | "UNKNOWN_NODE_TYPE" | "UNKNOWN_PROP" | "UNKNOWN_SIGNAL" | "UNRESOLVED_INSTANCE";
|
|
62
|
+
type IncantoErrorCode = "AMBIGUOUS_HANDLER" | "BAD_FORMAT" | "BAD_NODE_PATH" | "DANGLING_CONNECTION" | "DUPLICATE_BEHAVIOR" | "DUPLICATE_NODE_TYPE" | "DUPLICATE_UNIQUE_NAME" | "DUPLICATE_UID" | "NODE_NOT_FOUND" | "PROP_TYPE_MISMATCH" | "TREE_VIOLATION" | "UNKNOWN_ANIMATION" | "UNKNOWN_ASSET" | "UNKNOWN_CONSTANT" | "UNKNOWN_BEHAVIOR" | "UNKNOWN_HANDLER" | "UNKNOWN_NODE_TYPE" | "UNKNOWN_PROP" | "UNKNOWN_SIGNAL" | "UNRESOLVED_INSTANCE" | "WEBGL_UNAVAILABLE";
|
|
29
63
|
/**
|
|
30
64
|
* Structured context mirrored from the prose message — tools and agents parse
|
|
31
65
|
* THESE instead of regexing the message (which is for humans and may reword).
|
|
@@ -100,4 +134,4 @@ declare function replay(engine: Engine, recording: ReplayJson, opts?: {
|
|
|
100
134
|
onTick?: (index: number) => void;
|
|
101
135
|
}): void;
|
|
102
136
|
//#endregion
|
|
103
|
-
export { startRecording as a, IncantoErrorDetails as c, replay as i, auditScene as l, ReplayEvent as n, IncantoError as o, ReplayJson as r, IncantoErrorCode as s, Recorder as t };
|
|
137
|
+
export { startRecording as a, IncantoErrorDetails as c, replay as i, auditScene as l, ReplayEvent as n, IncantoError as o, ReplayJson as r, IncantoErrorCode as s, Recorder as t, instancedScenes as u };
|
|
@@ -74,6 +74,17 @@ interface SceneJson {
|
|
|
74
74
|
input?: JsonObject;
|
|
75
75
|
/** Physics config — `{gravity: [x,y]}` (2D px/s²) or `{gravity: [x,y,z]}` (3D m/s²). */
|
|
76
76
|
physics?: JsonObject;
|
|
77
|
+
/**
|
|
78
|
+
* This scene is a PIECE of another one — a spawner's prefab, an instanced
|
|
79
|
+
* sub-scene — and is never rendered on its own.
|
|
80
|
+
*
|
|
81
|
+
* It exists because no tool can tell a prefab from a broken first level by
|
|
82
|
+
* looking at the file: both are a small tree with no camera and no light. The
|
|
83
|
+
* audit used to guess ("no camera means fragment") and so went silent on the
|
|
84
|
+
* commonest beginner mistake there is. One key, written by the author who
|
|
85
|
+
* knows, is the honest version. It changes nothing at runtime.
|
|
86
|
+
*/
|
|
87
|
+
fragment?: boolean;
|
|
77
88
|
/** Multiplayer config (interpreted in M6; preserved verbatim until then). */
|
|
78
89
|
multiplayer?: JsonObject;
|
|
79
90
|
/** Scene-level rendering environment (ambient light, background — interpreted by renderers). */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { O as Node, V as Signal, k as diagnose, n as loadScene, t as buildNodeJson } from "./loader-
|
|
2
|
-
import { t as registerCoreNodes, v as Engine } from "./register-
|
|
1
|
+
import { O as Node, V as Signal, k as diagnose, n as loadScene, t as buildNodeJson } from "./loader-BC4PNtJX.js";
|
|
2
|
+
import { t as registerCoreNodes, v as Engine } from "./register-3ta-2Xig.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { n as jsonEquals, t as jsonClone } from "./json-CwwhxQgb.js";
|
|
5
5
|
import { l as registerNode } from "./registry-CF70EArN.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Lt as Signal, b as Engine, jt as Node } from "./behavior-
|
|
2
|
-
import { c as JsonValue, i as SceneJson, s as JsonObject } from "./schema-
|
|
3
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
1
|
+
import { Lt as Signal, b as Engine, jt as Node } from "./behavior-DoFPYrgo.js";
|
|
2
|
+
import { c as JsonValue, i as SceneJson, s as JsonObject } from "./schema-B6ugCV1Q.js";
|
|
3
|
+
import { t as LoadSceneOptions } from "./loader-CcB533FR.js";
|
|
4
4
|
|
|
5
5
|
//#region src/net/types.d.ts
|
|
6
6
|
type Unsubscribe = () => void;
|
|
@@ -214,6 +214,6 @@ function newUid() {
|
|
|
214
214
|
//#endregion
|
|
215
215
|
//#region src/index.ts
|
|
216
216
|
/** Engine version. Kept in sync with package.json by the release pipeline. */
|
|
217
|
-
const VERSION = "0.
|
|
217
|
+
const VERSION = "0.68.0";
|
|
218
218
|
//#endregion
|
|
219
219
|
export { preloadUrls as a, preloadSceneAssets as i, newUid as n, findPath as o, assetUrls as r, gridFromRows as s, VERSION as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { _ as AudioPlayer } from "./register-
|
|
2
|
-
import { i as
|
|
1
|
+
import { _ as AudioPlayer } from "./register-3ta-2Xig.js";
|
|
2
|
+
import { i as logReport, o as parseDrive } from "./webgl-unavailable-N9nQqesw.js";
|
|
3
3
|
import { a as frameSignature, i as frameImage, o as frameStats } from "./frame-report-BSMny7oe.js";
|
|
4
4
|
//#region src/core/audio-errors.ts
|
|
5
5
|
/** Every AudioPlayer under `root` whose source could not be played. */
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { f as resolveViewport, n as loadScene, z as registerBehavior } from "./loader-
|
|
2
|
-
import { v as Engine } from "./register-
|
|
1
|
+
import { f as resolveViewport, n as loadScene, z as registerBehavior } from "./loader-BC4PNtJX.js";
|
|
2
|
+
import { v as Engine } from "./register-3ta-2Xig.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
4
|
import { n as jsonEquals, t as jsonClone } from "./json-CwwhxQgb.js";
|
|
5
5
|
import { i as getNodeSchema, s as mergeStaticProps } from "./registry-CF70EArN.js";
|
|
6
|
-
import { n as startRecording } from "./replay-
|
|
7
|
-
import { n as registerGameplayBehaviors } from "./gameplay-
|
|
8
|
-
import { t as registerNodes2D } from "./register-
|
|
9
|
-
import { n as registerNodes3D, t as resolveEnvironmentHdri } from "./environment-presets-
|
|
10
|
-
import { a as NetworkManager, c as readSyncKey, i as sanitizeName, n as registerNodesNet, r as NetworkSpawner, s as findOwnerNode, t as createSplitScreen } from "./split-screen-
|
|
6
|
+
import { n as startRecording } from "./replay-CYvhVHHN.js";
|
|
7
|
+
import { n as registerGameplayBehaviors } from "./gameplay-DM1eu_cV.js";
|
|
8
|
+
import { t as registerNodes2D } from "./register-ibCjm-wH.js";
|
|
9
|
+
import { n as registerNodes3D, t as resolveEnvironmentHdri } from "./environment-presets-CybQXNqS.js";
|
|
10
|
+
import { a as NetworkManager, c as readSyncKey, i as sanitizeName, n as registerNodesNet, r as NetworkSpawner, s as findOwnerNode, t as createSplitScreen } from "./split-screen-CYwDkbLF.js";
|
|
11
11
|
import { Box3, Euler, Matrix4, PerspectiveCamera, Quaternion, Vector3 } from "three";
|
|
12
12
|
//#region src/test/framing.ts
|
|
13
13
|
/**
|
|
@@ -1812,8 +1812,8 @@ async function playMultiplayer(opts) {
|
|
|
1812
1812
|
*/
|
|
1813
1813
|
async function joinLate(server, first, opts) {
|
|
1814
1814
|
try {
|
|
1815
|
-
const { Engine } = await import("./register-
|
|
1816
|
-
const { loadScene } = await import("./loader-
|
|
1815
|
+
const { Engine } = await import("./register-3ta-2Xig.js").then((n) => n.y);
|
|
1816
|
+
const { loadScene } = await import("./loader-BC4PNtJX.js").then((n) => n.r);
|
|
1817
1817
|
const { jsonClone } = await import("./json-CwwhxQgb.js").then((n) => n.i);
|
|
1818
1818
|
const engine = new Engine(opts.seed !== void 0 ? { seed: opts.seed + 999 } : {});
|
|
1819
1819
|
engine.setScene(loadScene(jsonClone(opts.scene), opts.load));
|
|
@@ -2175,20 +2175,23 @@ async function runScript(json, opts) {
|
|
|
2175
2175
|
if (opts.locale) engine.locale.locale = opts.locale;
|
|
2176
2176
|
const physics = opts.physics ?? "auto";
|
|
2177
2177
|
if (physics === "2d" || physics === "auto" && scene.dimension === "2d") {
|
|
2178
|
-
const { enablePhysics2D } = await import("./physics-2d-
|
|
2178
|
+
const { enablePhysics2D } = await import("./physics-2d-B7Y6dPZO.js").then((n) => n.r);
|
|
2179
2179
|
await enablePhysics2D(engine);
|
|
2180
2180
|
} else if (physics === "3d" || physics === "auto" && scene.dimension === "3d") {
|
|
2181
|
-
const { enablePhysics3D } = await import("./physics-3d-
|
|
2181
|
+
const { enablePhysics3D } = await import("./physics-3d-bG3n70Ky.js").then((n) => n.r);
|
|
2182
2182
|
await enablePhysics3D(engine);
|
|
2183
2183
|
}
|
|
2184
2184
|
const failures = [];
|
|
2185
2185
|
const snapshots = [];
|
|
2186
|
+
const live = () => engine.scene ?? scene;
|
|
2186
2187
|
const ctx = {
|
|
2187
2188
|
engine,
|
|
2188
|
-
scene
|
|
2189
|
+
get scene() {
|
|
2190
|
+
return live();
|
|
2191
|
+
},
|
|
2189
2192
|
timeMs: 0,
|
|
2190
|
-
getNode: (path) =>
|
|
2191
|
-
capture: () => captureScene(
|
|
2193
|
+
getNode: (path) => live().root.getNode(path),
|
|
2194
|
+
capture: () => captureScene(live())
|
|
2192
2195
|
};
|
|
2193
2196
|
const applyStep = (step) => {
|
|
2194
2197
|
if (step.press) engine.input.pressAction(step.press);
|
|
@@ -2226,7 +2229,7 @@ async function runScript(json, opts) {
|
|
|
2226
2229
|
if (t >= nextSnapshot - 1e-6) {
|
|
2227
2230
|
snapshots.push({
|
|
2228
2231
|
atMs: Math.round(t),
|
|
2229
|
-
capture: captureScene(
|
|
2232
|
+
capture: captureScene(live())
|
|
2230
2233
|
});
|
|
2231
2234
|
nextSnapshot += opts.snapshotEveryMs;
|
|
2232
2235
|
}
|
|
@@ -2239,7 +2242,7 @@ async function runScript(json, opts) {
|
|
|
2239
2242
|
message: `step never executed — atMs ${missed.atMs} is beyond the ${opts.durationMs}ms run`
|
|
2240
2243
|
});
|
|
2241
2244
|
}
|
|
2242
|
-
const finalCapture = captureScene(
|
|
2245
|
+
const finalCapture = captureScene(live());
|
|
2243
2246
|
const logs = [...engine.log.entries()];
|
|
2244
2247
|
const swallowed = engine.stats().errors;
|
|
2245
2248
|
if (swallowed > 0) failures.push({
|
|
@@ -2291,10 +2294,10 @@ async function createPlaySession(json, opts = {}) {
|
|
|
2291
2294
|
engine.setScene(scene);
|
|
2292
2295
|
const physics = opts.physics ?? "auto";
|
|
2293
2296
|
if (physics === "2d" || physics === "auto" && scene.dimension === "2d") {
|
|
2294
|
-
const { enablePhysics2D } = await import("./physics-2d-
|
|
2297
|
+
const { enablePhysics2D } = await import("./physics-2d-B7Y6dPZO.js").then((n) => n.r);
|
|
2295
2298
|
await enablePhysics2D(engine);
|
|
2296
2299
|
} else if (physics === "3d" || physics === "auto" && scene.dimension === "3d") {
|
|
2297
|
-
const { enablePhysics3D } = await import("./physics-3d-
|
|
2300
|
+
const { enablePhysics3D } = await import("./physics-3d-bG3n70Ky.js").then((n) => n.r);
|
|
2298
2301
|
await enablePhysics3D(engine);
|
|
2299
2302
|
}
|
|
2300
2303
|
const stepMs = 1e3 / (opts.fixedHz ?? 60);
|
|
@@ -2302,7 +2305,9 @@ async function createPlaySession(json, opts = {}) {
|
|
|
2302
2305
|
let logCursor = 0;
|
|
2303
2306
|
return {
|
|
2304
2307
|
engine,
|
|
2305
|
-
scene
|
|
2308
|
+
get scene() {
|
|
2309
|
+
return engine.scene ?? scene;
|
|
2310
|
+
},
|
|
2306
2311
|
get timeMs() {
|
|
2307
2312
|
return timeMs;
|
|
2308
2313
|
},
|
|
@@ -2315,10 +2320,10 @@ async function createPlaySession(json, opts = {}) {
|
|
|
2315
2320
|
return scene.toJSON();
|
|
2316
2321
|
},
|
|
2317
2322
|
describe() {
|
|
2318
|
-
return describeCapture(captureScene(scene));
|
|
2323
|
+
return describeCapture(captureScene(engine.scene ?? scene));
|
|
2319
2324
|
},
|
|
2320
2325
|
framing() {
|
|
2321
|
-
return framingText(describeFraming(scene));
|
|
2326
|
+
return framingText(describeFraming(engine.scene ?? scene));
|
|
2322
2327
|
},
|
|
2323
2328
|
drainLogs() {
|
|
2324
2329
|
const all = engine.log.entries();
|
package/dist/test.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { P as Scene, Pt as LogEntry, b as Engine, jt as Node, n as BehaviorCtor } from "./behavior-
|
|
2
|
-
import { c as JsonValue, i as SceneJson, s as JsonObject } from "./schema-
|
|
3
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
4
|
-
import { l as auditScene, o as IncantoError, r as ReplayJson } from "./replay-
|
|
5
|
-
import { l as LocalGameServerOptions, n as SplitScreenPlayer } from "./split-screen-
|
|
1
|
+
import { P as Scene, Pt as LogEntry, b as Engine, jt as Node, n as BehaviorCtor } from "./behavior-DoFPYrgo.js";
|
|
2
|
+
import { c as JsonValue, i as SceneJson, s as JsonObject } from "./schema-B6ugCV1Q.js";
|
|
3
|
+
import { t as LoadSceneOptions } from "./loader-CcB533FR.js";
|
|
4
|
+
import { l as auditScene, o as IncantoError, r as ReplayJson, u as instancedScenes } from "./replay-Dvn8aeBd.js";
|
|
5
|
+
import { l as LocalGameServerOptions, n as SplitScreenPlayer } from "./split-screen-DhrSzZIB.js";
|
|
6
6
|
|
|
7
7
|
//#region src/test/facing.d.ts
|
|
8
8
|
interface FacingOptions {
|
|
@@ -689,4 +689,4 @@ interface PlaySession {
|
|
|
689
689
|
*/
|
|
690
690
|
declare function createPlaySession(json: unknown, opts?: PlaySessionOptions): Promise<PlaySession>;
|
|
691
691
|
//#endregion
|
|
692
|
-
export { type AgreementSnapshot, type Disagreement, type DisagreementKind, type FacingOptions, type FacingReport, type FeelOptions, type FeelReport, type FramingEntry, type FramingOptions, type FramingReport, GroundingIssue, GroundingOptions, type LadderVerdict, type MultiplayOptions, type MultiplayPlayer, type MultiplayReport, NodeCapture, type Outcome, PlaySession, PlaySessionOptions, type PlaytestOptions, type PlaytestReport, type PlaytestRun, RunContext, RunFailure, RunResult, RunScriptOptions, type RungResult, type RungStatus, SceneCapture, ScriptStep, ValidateSceneOptions, ValidationResult, type Where, agreementProblems, auditScene, captureScene, createPlaySession, describeCapture, describeFraming, facingReport, facingText, failingReplays, feelReport, feelText, findFloatingProps, findPlayer, framingText, ladderText, ladderVerdict, multiplayProblems, multiplayText, playMultiplayer, playtest, playtestText, registerAllNodes, runScript, takeAgreementSnapshots, validateScene };
|
|
692
|
+
export { type AgreementSnapshot, type Disagreement, type DisagreementKind, type FacingOptions, type FacingReport, type FeelOptions, type FeelReport, type FramingEntry, type FramingOptions, type FramingReport, GroundingIssue, GroundingOptions, type LadderVerdict, type MultiplayOptions, type MultiplayPlayer, type MultiplayReport, NodeCapture, type Outcome, PlaySession, PlaySessionOptions, type PlaytestOptions, type PlaytestReport, type PlaytestRun, RunContext, RunFailure, RunResult, RunScriptOptions, type RungResult, type RungStatus, SceneCapture, ScriptStep, ValidateSceneOptions, ValidationResult, type Where, agreementProblems, auditScene, captureScene, createPlaySession, describeCapture, describeFraming, facingReport, facingText, failingReplays, feelReport, feelText, findFloatingProps, findPlayer, framingText, instancedScenes, ladderText, ladderVerdict, multiplayProblems, multiplayText, playMultiplayer, playtest, playtestText, registerAllNodes, runScript, takeAgreementSnapshots, validateScene };
|
package/dist/test.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { r as auditScene } from "./replay-
|
|
2
|
-
import { C as describeFraming, S as playtestText, _ as facingReport, a as registerAllNodes, b as findPlayer, c as ladderText, d as multiplayText, f as playMultiplayer, g as agreementProblems, h as takeAgreementSnapshots, i as findFloatingProps, l as ladderVerdict, m as feelText, n as createPlaySession, o as runScript, p as feelReport, r as describeCapture, s as validateScene, t as captureScene, u as multiplayProblems, v as facingText, w as framingText, x as playtest, y as failingReplays } from "./test-
|
|
3
|
-
export { agreementProblems, auditScene, captureScene, createPlaySession, describeCapture, describeFraming, facingReport, facingText, failingReplays, feelReport, feelText, findFloatingProps, findPlayer, framingText, ladderText, ladderVerdict, multiplayProblems, multiplayText, playMultiplayer, playtest, playtestText, registerAllNodes, runScript, takeAgreementSnapshots, validateScene };
|
|
1
|
+
import { i as instancedScenes, r as auditScene } from "./replay-CYvhVHHN.js";
|
|
2
|
+
import { C as describeFraming, S as playtestText, _ as facingReport, a as registerAllNodes, b as findPlayer, c as ladderText, d as multiplayText, f as playMultiplayer, g as agreementProblems, h as takeAgreementSnapshots, i as findFloatingProps, l as ladderVerdict, m as feelText, n as createPlaySession, o as runScript, p as feelReport, r as describeCapture, s as validateScene, t as captureScene, u as multiplayProblems, v as facingText, w as framingText, x as playtest, y as failingReplays } from "./test-8hoHeRmo.js";
|
|
3
|
+
export { agreementProblems, auditScene, captureScene, createPlaySession, describeCapture, describeFraming, facingReport, facingText, failingReplays, feelReport, feelText, findFloatingProps, findPlayer, framingText, instancedScenes, ladderText, ladderVerdict, multiplayProblems, multiplayText, playMultiplayer, playtest, playtestText, registerAllNodes, runScript, takeAgreementSnapshots, validateScene };
|
package/dist/vite.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as VERSION } from "./src-
|
|
1
|
+
import { t as VERSION } from "./src-D7RIqXYF.js";
|
|
2
2
|
import { n as diffSignatures } from "./frame-report-BSMny7oe.js";
|
|
3
|
-
import { s as validateScene } from "./test-
|
|
3
|
+
import { s as validateScene } from "./test-8hoHeRmo.js";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { basename, dirname, join, normalize, relative, resolve, sep } from "node:path";
|
|
6
6
|
//#region src/vite/frame-endpoint.ts
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
1
2
|
//#region src/core/drive-script.ts
|
|
2
3
|
const num = (raw) => {
|
|
3
4
|
if (raw === void 0) return null;
|
|
@@ -181,4 +182,47 @@ function resolveRendering(environment, fallback, devicePixelRatio, explicit) {
|
|
|
181
182
|
};
|
|
182
183
|
}
|
|
183
184
|
//#endregion
|
|
184
|
-
|
|
185
|
+
//#region src/core/webgl-unavailable.ts
|
|
186
|
+
/**
|
|
187
|
+
* Turn three's bare "Error creating WebGL context." into something a game can
|
|
188
|
+
* act on.
|
|
189
|
+
*
|
|
190
|
+
* A machine with no GPU acceleration, a locked-down or headless browser, a
|
|
191
|
+
* driver on the blocklist, or simply too many live contexts already: the call
|
|
192
|
+
* throws synchronously from inside `new WebGLRenderer`, and three's message
|
|
193
|
+
* says only that it failed. `createGame2D`/`createGame3D` did not catch it, and
|
|
194
|
+
* every shipped starter removes its `#loading` overlay on the line AFTER the
|
|
195
|
+
* await — so the player watched "100%" forever while the console held a
|
|
196
|
+
* sentence nobody was looking at.
|
|
197
|
+
*
|
|
198
|
+
* Wrapping it costs nothing when WebGL works and gives the failure a code, so a
|
|
199
|
+
* game can tell "this browser cannot run me" apart from "your scene is wrong"
|
|
200
|
+
* without matching on three's wording.
|
|
201
|
+
*/
|
|
202
|
+
function withWebGLContext(make) {
|
|
203
|
+
try {
|
|
204
|
+
return make();
|
|
205
|
+
} catch (cause) {
|
|
206
|
+
if (cause instanceof IncantoError) throw cause;
|
|
207
|
+
throw new IncantoError("WEBGL_UNAVAILABLE", `this browser would not give the canvas a WebGL context. Usually one of: hardware acceleration is off, the GPU or driver is blocklisted, the page is running in a headless or locked-down browser, or too many WebGL contexts are already open on this page. Tell the player — a game that cannot draw should say so rather than wait. (three: ${String(cause?.message ?? cause)})`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Can this document make a WebGL context at all?
|
|
212
|
+
*
|
|
213
|
+
* The question a game wants BEFORE it boots, so the answer can be a screen
|
|
214
|
+
* instead of an exception. Uses a throwaway canvas and never touches yours;
|
|
215
|
+
* `false` outside a browser, where the question is not meaningful.
|
|
216
|
+
*/
|
|
217
|
+
function isWebGLAvailable() {
|
|
218
|
+
const doc = globalThis.document;
|
|
219
|
+
if (!doc) return false;
|
|
220
|
+
try {
|
|
221
|
+
const probe = doc.createElement("canvas");
|
|
222
|
+
return Boolean(probe.getContext("webgl2") ?? probe.getContext("webgl"));
|
|
223
|
+
} catch {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//#endregion
|
|
228
|
+
export { logText as a, logReport as i, withWebGLContext as n, parseDrive as o, resolveRendering as r, isWebGLAvailable as t };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e}from"./index-
|
|
1
|
+
import{n as e}from"./index-eVd0BToA.js";async function t(t){return new n((await e(()=>import(`./GameServer-C56iOUgF.js`),[],import.meta.url)).GameServer,t)}var n=class{raw;active=new Map;reconnecting=!1;disposed=!1;constructor(e,t){this.raw=new e({...t})}get account(){return this.raw.account}get connected(){return this.raw.connected}connect(){return this.raw.connected?Promise.resolve(!0):(this.disposed=!1,this.rawConnect())}rawConnect(){return this.raw.connect({onDisconnect:()=>void this.reconnect()})}disconnect(){this.disposed=!0;for(let e of this.active.values())e.off();return this.active.clear(),this.raw.disconnect()}remoteFunction(e,t,n){return this.raw.remoteFunction(e,t,n)}track(e){let t=Symbol(`sub`),n={make:e,off:e()};return this.active.set(t,n),()=>{n.off(),this.active.delete(t)}}async reconnect(){if(!this.disposed&&!this.reconnecting){this.reconnecting=!0;try{await this.rawConnect();for(let e of this.active.values())e.off(),e.off=e.make()}finally{this.reconnecting=!1}}}subscribeRoomState(e,t){return this.track(()=>this.raw.subscribeRoomState(e,t))}subscribeRoomMyState(e,t){return this.track(()=>this.raw.subscribeRoomMyState(e,t))}subscribeRoomAllUserStates(e,t){return this.track(()=>this.raw.subscribeRoomAllUserStates(e,e=>{let n={};for(let t of e??[]){if(!t||typeof t.account!=`string`||t.__leaved)continue;let{account:e,__updated:r,__leaved:i,...a}=t;n[e]=a}t(n)}))}subscribeRoomCollection(e,t,n){return this.track(()=>this.raw.subscribeRoomCollection(e,t,({items:e})=>{let t={};for(let n of e??[])n&&typeof n.__id==`string`&&(t[n.__id]=n);n(t)}))}onRoomMessage(e,t,n){return this.track(()=>this.raw.onRoomMessage(e,t,n))}onRoomUserJoin(e,t){return this.track(()=>this.raw.onRoomUserJoin(e,t))}onRoomUserLeave(e,t){return this.track(()=>this.raw.onRoomUserLeave(e,t))}subscribeGlobalState(e){return this.track(()=>this.raw.subscribeGlobalState(e))}subscribeGlobalMyState(e){return this.track(()=>this.raw.subscribeGlobalMyState(e))}subscribeGlobalUserState(e,t){return this.track(()=>this.raw.subscribeGlobalUserState(e,t))}subscribeGlobalCollection(e,t){return this.track(()=>this.raw.subscribeGlobalCollection(e,({items:e})=>{let n={};for(let t of e??[])t&&typeof t.__id==`string`&&(n[t.__id]=t);t(n)}))}subscribeAsset(e,t){return this.track(()=>this.raw.subscribeAsset(e,t))}onGlobalMessage(e,t){return this.track(()=>this.raw.onGlobalMessage(e,t))}};export{t as createAgent8Server};
|