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.
Files changed (70) hide show
  1. package/bin/_pick-server.mjs +48 -0
  2. package/bin/incanto-check.mjs +16 -2
  3. package/bin/incanto-frame.mjs +10 -25
  4. package/bin/incanto-logs.mjs +8 -18
  5. package/dist/2d.d.ts +6 -6
  6. package/dist/2d.js +6 -4
  7. package/dist/3d.d.ts +30 -6
  8. package/dist/3d.js +8 -6
  9. package/dist/{audio-player-BNUHo0JF.d.ts → audio-player-DOrq7sP-.d.ts} +62 -4
  10. package/dist/{behavior-ZnfzKDo3.d.ts → behavior-DoFPYrgo.d.ts} +78 -1
  11. package/dist/boot-failure-CKYrEcGF.js +47 -0
  12. package/dist/{create-game-FAXdHta3.js → create-game-DbWtVTxD.js} +21 -25
  13. package/dist/{create-game-DMetd3vR.js → create-game-IZIydDwI.js} +9 -9
  14. package/dist/debug.d.ts +1 -1
  15. package/dist/{duplicate-B8QnX2-r.js → duplicate-IWIqk0HJ.js} +1 -1
  16. package/dist/{editor-switch-DAvWQeld.d.ts → editor-switch-CnIOiyNJ.d.ts} +1 -1
  17. package/dist/editor.js +11 -5
  18. package/dist/env.d.ts +1 -1
  19. package/dist/{environment-presets-C-5g2pMh.js → environment-presets-CybQXNqS.js} +57 -8
  20. package/dist/{gameplay-CGSv-9XR.js → gameplay-DM1eu_cV.js} +20 -2
  21. package/dist/gameplay.d.ts +51 -3
  22. package/dist/gameplay.js +2 -2
  23. package/dist/index.d.ts +6 -6
  24. package/dist/index.js +8 -7
  25. package/dist/{loader-KZESOZmE.js → loader-BC4PNtJX.js} +26 -1
  26. package/dist/{loader-DyT30ArB.d.ts → loader-CcB533FR.d.ts} +2 -2
  27. package/dist/net.d.ts +2 -2
  28. package/dist/net.js +1 -1
  29. package/dist/{physics-2d-_B6zj3zU.js → physics-2d-B7Y6dPZO.js} +2 -2
  30. package/dist/{physics-3d-i1IeAY0F.js → physics-3d-bG3n70Ky.js} +3 -3
  31. package/dist/react.d.ts +2 -2
  32. package/dist/react.js +1 -1
  33. package/dist/{register-Cs53CY7s.js → register-3ta-2Xig.js} +68 -7
  34. package/dist/{register-vIxU3Xbv.js → register-ibCjm-wH.js} +3 -3
  35. package/dist/{replay-BkpDV51O.js → replay-CYvhVHHN.js} +28 -5
  36. package/dist/{replay-D0GcEHYU.d.ts → replay-Dvn8aeBd.d.ts} +38 -4
  37. package/dist/{schema-CFeioQRE.d.ts → schema-B6ugCV1Q.d.ts} +11 -0
  38. package/dist/{split-screen-DS8RaUV_.js → split-screen-CYwDkbLF.js} +2 -2
  39. package/dist/{split-screen-DD5eYIgW.d.ts → split-screen-DhrSzZIB.d.ts} +3 -3
  40. package/dist/{src-BLlsGJW9.js → src-D7RIqXYF.js} +1 -1
  41. package/dist/{teardown-LB9cTnXJ.js → teardown-D2NEmxPB.js} +2 -2
  42. package/dist/{test-81uZ967a.js → test-8hoHeRmo.js} +26 -21
  43. package/dist/test.d.ts +6 -6
  44. package/dist/test.js +3 -3
  45. package/dist/vite.js +2 -2
  46. package/dist/{rendering-options-ByAdi8PF.js → webgl-unavailable-N9nQqesw.js} +45 -1
  47. package/editor/assets/{agent8-C2jtNKbx.js → agent8-BrrHOjMJ.js} +1 -1
  48. package/editor/assets/{debug-DoU3KeqS.js → debug-BBhKuBNV.js} +1 -1
  49. package/editor/assets/{index-CNqHojcC.js → index-eVd0BToA.js} +92 -92
  50. package/editor/index.html +1 -1
  51. package/package.json +1 -1
  52. package/schemas/scene.schema.json +4 -0
  53. package/skills/incanto-3d-character.md +1 -0
  54. package/skills/incanto-audio.md +49 -0
  55. package/skills/incanto-building-2d-games.md +37 -0
  56. package/skills/incanto-building-3d-games.md +37 -0
  57. package/skills/incanto-gameplay-behaviors.md +28 -1
  58. package/skills/incanto-node-reference.md +1 -0
  59. package/skills/incanto-physics-and-input.md +23 -0
  60. package/skills/incanto-scene-json-authoring.md +12 -1
  61. package/templates-app/beacon-isle-3d/package.json +1 -1
  62. package/templates-app/beacon-isle-3d/src/main.ts +8 -1
  63. package/templates-app/platformer-2d/package.json +1 -1
  64. package/templates-app/platformer-2d/src/main.ts +8 -1
  65. package/templates-app/star-survivor/package.json +1 -1
  66. package/templates-app/star-survivor/src/main.ts +8 -1
  67. package/templates-app/tps-3d/package.json +1 -1
  68. package/templates-app/tps-3d/src/main.ts +8 -1
  69. package/templates-app/village-quest-3d/package.json +1 -1
  70. 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-KZESOZmE.js";
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-vIxU3Xbv.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-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-KZESOZmE.js";
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-CGSv-9XR.js";
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-C-5g2pMh.js";
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-ZnfzKDo3.js";
2
- import { c as JsonValue } from "./schema-CFeioQRE.js";
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-FAXdHta3.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-DMetd3vR.js").then((n) => n.n)).createGame2D(o)))(opts);
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-KZESOZmE.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-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
- play() {
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-KZESOZmE.js";
2
- import { L as translateOn, t as registerCoreNodes } from "./register-Cs53CY7s.js";
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-CGSv-9XR.js";
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-KZESOZmE.js";
2
- import { R as translationKey, k as HudWidgetBase } from "./register-Cs53CY7s.js";
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 = cameras === 0;
170
- 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\": \"...\" }.");
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-ZnfzKDo3.js";
2
- import { s as JsonObject } from "./schema-CFeioQRE.js";
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-KZESOZmE.js";
2
- import { t as registerCoreNodes, v as Engine } from "./register-Cs53CY7s.js";
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-ZnfzKDo3.js";
2
- import { c as JsonValue, i as SceneJson, s as JsonObject } from "./schema-CFeioQRE.js";
3
- import { t as LoadSceneOptions } from "./loader-DyT30ArB.js";
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.67.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-Cs53CY7s.js";
2
- import { i as parseDrive, n as logReport } from "./rendering-options-ByAdi8PF.js";
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-KZESOZmE.js";
2
- import { v as Engine } from "./register-Cs53CY7s.js";
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-BkpDV51O.js";
7
- import { n as registerGameplayBehaviors } from "./gameplay-CGSv-9XR.js";
8
- import { t as registerNodes2D } from "./register-vIxU3Xbv.js";
9
- import { n as registerNodes3D, t as resolveEnvironmentHdri } from "./environment-presets-C-5g2pMh.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-DS8RaUV_.js";
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-Cs53CY7s.js").then((n) => n.y);
1816
- const { loadScene } = await import("./loader-KZESOZmE.js").then((n) => n.r);
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-_B6zj3zU.js").then((n) => n.r);
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-i1IeAY0F.js").then((n) => n.r);
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) => scene.root.getNode(path),
2191
- capture: () => captureScene(scene)
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(scene)
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(scene);
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-_B6zj3zU.js").then((n) => n.r);
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-i1IeAY0F.js").then((n) => n.r);
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-ZnfzKDo3.js";
2
- import { c as JsonValue, i as SceneJson, s as JsonObject } from "./schema-CFeioQRE.js";
3
- import { t as LoadSceneOptions } from "./loader-DyT30ArB.js";
4
- import { l as auditScene, o as IncantoError, r as ReplayJson } from "./replay-D0GcEHYU.js";
5
- import { l as LocalGameServerOptions, n as SplitScreenPlayer } from "./split-screen-DD5eYIgW.js";
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-BkpDV51O.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-81uZ967a.js";
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-BLlsGJW9.js";
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-81uZ967a.js";
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
- export { parseDrive as i, logReport as n, logText as r, resolveRendering as t };
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-CNqHojcC.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};
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};