incanto 0.10.0 → 0.12.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/dist/2d.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
2
- import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-CdWhP6ve.js";
2
+ import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-C_xf4gm9.js";
3
3
  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-BD6zgrv_.js";
4
- import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-DweTURFt.js";
4
+ import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-B6D864oZ.js";
5
5
  //#region src/2d/library-sprite.ts
6
6
  /**
7
7
  * Turn a library sprite-animation JSON into a scene-ready spritesheet asset
package/dist/3d.d.ts CHANGED
@@ -2,7 +2,7 @@ import { s as JsonObject } from "./schema-CcoWb32N.js";
2
2
  import { $ as Node, C as RendererStats, S as GameStats, b as Scheduler, l as PropSchema, n as BehaviorCtor, v as Engine, w as Scene$1 } from "./behavior-Bod1AyJS.js";
3
3
  import { t as LoadSceneOptions } from "./loader-BcUDfNHn.js";
4
4
  import { t as ParticleSim } from "./particle-sim-CwJ5rI_P.js";
5
- import { r as SpatialPose } from "./audio-player-Dyjg5k92.js";
5
+ import { n as PathGrid, s as SpatialPose } from "./pathfinding-BSiXjd6W.js";
6
6
  import { AnimationClip, BufferGeometry, Color, DirectionalLight, InstancedMesh, MeshPhysicalMaterial, Object3D, PerspectiveCamera, Scene, Vector3, WebGLRenderer } from "three";
7
7
  import { VRM } from "@pixiv/three-vrm";
8
8
  import { Sky } from "three/examples/jsm/objects/Sky.js";
@@ -311,6 +311,20 @@ declare class Physics3D {
311
311
  normal: [number, number, number];
312
312
  node: PhysicsBody3D | null;
313
313
  } | null;
314
+ /**
315
+ * Sweep a sphere of `radius` from `origin` along `dir` — a THICK ray. The
316
+ * spring-arm camera probe uses this instead of `castRay`: a thin ray that
317
+ * skims 10 cm over a wall reports "clear" while the camera's near plane
318
+ * still clips the wall; the ball's radius covers that band. Same filters
319
+ * as `castRay` (sensors never hit; `staticOnly` ignores dynamic/kinematic).
320
+ * Returns the travel distance of the sphere CENTER, or null when clear.
321
+ */
322
+ castSphere(origin: [number, number, number], dir: [number, number, number], radius: number, maxLen: number, exclude?: PhysicsBody3D, opts?: {
323
+ staticOnly?: boolean;
324
+ }): {
325
+ distance: number;
326
+ node: PhysicsBody3D | null;
327
+ } | null;
314
328
  }
315
329
  //#endregion
316
330
  //#region src/3d/create-game.d.ts
@@ -460,6 +474,14 @@ interface BloomEnvironment {
460
474
  /** How strongly the blurred glow is added back (0 = off, ~1.2 = neon). */
461
475
  strength: number;
462
476
  }
477
+ interface PostEnvironment {
478
+ /** Corner darkening, 0 (off) … 1 (heavy). Default 0. */
479
+ vignette: number;
480
+ /** Color saturation multiplier: 0 = grayscale, 1 = neutral. Default 1. */
481
+ saturation: number;
482
+ /** Contrast around mid-gray: 1 = neutral. Default 1. */
483
+ contrast: number;
484
+ }
463
485
  interface Environment3DConfig {
464
486
  /** Tone-mapping exposure (ACES), default 1. */
465
487
  exposure: number;
@@ -471,6 +493,8 @@ interface Environment3DConfig {
471
493
  clouds: CloudsEnvironment | null;
472
494
  /** Bloom post pass (bright-pass → blur → additive composite), or null. */
473
495
  bloom: BloomEnvironment | null;
496
+ /** Color grade + vignette (tone-mapped composite tail), or null. */
497
+ post: PostEnvironment | null;
474
498
  /**
475
499
  * `null` = not declared (shadow maps stay available, free until a light
476
500
  * casts), `false` = force-disabled, object = declared ON with quality knobs
@@ -553,6 +577,8 @@ declare class Environment3D {
553
577
  get clouds(): CloudsEnvironment | null;
554
578
  /** Parsed bloom config, or null when no bloom pass is declared. */
555
579
  get bloom(): BloomEnvironment | null;
580
+ /** Parsed color-grade/vignette config, or null when not declared. */
581
+ get post(): PostEnvironment | null;
556
582
  /** The live scene fog (color/near/far) the cloud composite fades into, or null. */
557
583
  get sceneFog(): {
558
584
  color: Color;
@@ -2193,4 +2219,44 @@ interface WalkState {
2193
2219
  ignoreStatic: boolean;
2194
2220
  }
2195
2221
  //#endregion
2196
- export { Area3D, AssetStore3D, Billboard3D, type BillboardGroupMode, BoneAttachment3D, Camera3D, CharacterBody3D, CharacterController3D, type CreateGame3DOptions, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, Environment3D, type Environment3DConfig, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, type FlowerVariety, Flowers3D, type FogEnvironment, Foliage3D, type FoliageKind, type FoliageStyle, type Game3D, type Heightmap, type HeightmapOptions, Joint3D, type JointType3D, LoftMesh3D, type LoftSection, MeshInstance3D, type MeshKind, type MeshMaterialProps, type ModelEntry, ModelInstance3D, Node3D, OmniLight3D, Particles3D, Physics3D, type Physics3DOptions, PhysicsBody3D, QUARTER_PITCH, type RenderContext3D, type RenderHook3D, Renderer3D, type Renderer3DOptions, type RigView, RigidBody3D, type Ripple, type ShadowsEnvironment, type SkyEnvironment, StaticBody3D, type SunConsumer3D, type SyncOptions, type SyncResult, TERRAIN_THEMES, Terrain3D, type TerrainLayer, type TerrainTheme, Trail3D, Tree3D, type TreeTier, type TreeType, VOXEL_PALETTE, type VoxelBlock, VoxelGrid3D, WATER_MAX_RIPPLES, Water3D, buildHeightmap, cameraRelative, createGame3D, enablePhysics3D, horizonColorFromSky, keyboardIntensity, movementState, parseEnvironment3D, registerNodes3D, resolveFlowerDensity, rigPose, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers };
2222
+ //#region src/3d/terrain-nav.d.ts
2223
+ /**
2224
+ * Terrain navigation — the bridge from a `Terrain3D` heightfield to the grid
2225
+ * A* (`findPath`). Sample the surface into walkable cells (slope- and
2226
+ * height-limited), path on the grid, then lift waypoints back onto the
2227
+ * surface with `toWorld` (its y IS the terrain height):
2228
+ *
2229
+ * const nav = buildTerrainNav(terrain, { cellSize: 2, maxSlopeDeg: 40 });
2230
+ * const cells = findPath(nav.grid, nav.toCell(wolfX, wolfZ), nav.toCell(px, pz));
2231
+ * follow.setPath(cells.map(([cx, cy]) => nav.toWorld(cx, cy)));
2232
+ *
2233
+ * Trees/rocks/buildings aren't in the heightfield — stamp them out with
2234
+ * `setSolid(...nav.toCell(x, z))` after building.
2235
+ */
2236
+ interface TerrainNav {
2237
+ /** Feed this straight into `findPath`. */
2238
+ grid: PathGrid;
2239
+ cellSize: number;
2240
+ /** World x/z → cell coords (unclamped — check bounds via grid width/height). */
2241
+ toCell(x: number, z: number): [number, number];
2242
+ /** Cell → world position AT THE SURFACE ([x, terrainHeight, z], cell center). */
2243
+ toWorld(cx: number, cy: number): [number, number, number];
2244
+ /** Mark a cell unwalkable (props, buildings, no-go zones). */
2245
+ setSolid(cx: number, cy: number): void;
2246
+ }
2247
+ /** What we need from the terrain — Terrain3D satisfies this. */
2248
+ interface HeightSampler extends Node {
2249
+ size: number[];
2250
+ heightAt(x: number, z: number): number;
2251
+ }
2252
+ interface TerrainNavOptions {
2253
+ /** Meters per cell (default 2 — character-scale corridors). */
2254
+ cellSize?: number;
2255
+ /** Steepest walkable slope, degrees (default 40). */
2256
+ maxSlopeDeg?: number;
2257
+ /** Cells whose surface is BELOW this world y are unwalkable (sea level). */
2258
+ minHeight?: number;
2259
+ }
2260
+ declare function buildTerrainNav(terrain: HeightSampler, opts?: TerrainNavOptions): TerrainNav;
2261
+ //#endregion
2262
+ export { Area3D, AssetStore3D, Billboard3D, type BillboardGroupMode, BoneAttachment3D, Camera3D, CharacterBody3D, CharacterController3D, type CreateGame3DOptions, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, Environment3D, type Environment3DConfig, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, type FlowerVariety, Flowers3D, type FogEnvironment, Foliage3D, type FoliageKind, type FoliageStyle, type Game3D, type HeightSampler, type Heightmap, type HeightmapOptions, Joint3D, type JointType3D, LoftMesh3D, type LoftSection, MeshInstance3D, type MeshKind, type MeshMaterialProps, type ModelEntry, ModelInstance3D, Node3D, OmniLight3D, Particles3D, Physics3D, type Physics3DOptions, PhysicsBody3D, QUARTER_PITCH, type RenderContext3D, type RenderHook3D, Renderer3D, type Renderer3DOptions, type RigView, RigidBody3D, type Ripple, type ShadowsEnvironment, type SkyEnvironment, StaticBody3D, type SunConsumer3D, type SyncOptions, type SyncResult, TERRAIN_THEMES, Terrain3D, type TerrainLayer, type TerrainNav, type TerrainNavOptions, type TerrainTheme, Trail3D, Tree3D, type TreeTier, type TreeType, VOXEL_PALETTE, type VoxelBlock, VoxelGrid3D, WATER_MAX_RIPPLES, Water3D, buildHeightmap, buildTerrainNav, cameraRelative, createGame3D, enablePhysics3D, horizonColorFromSky, keyboardIntensity, movementState, parseEnvironment3D, registerNodes3D, resolveFlowerDensity, rigPose, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers };
package/dist/3d.js CHANGED
@@ -1,5 +1,74 @@
1
- import { a as Environment3D, c as sunDirectionFromElevationAzimuth, i as syncTree, l as sunDirectionFromSky, o as horizonColorFromSky, r as Renderer3D, s as parseEnvironment3D, t as createGame3D, u as AssetStore3D } from "./create-game-Cq0Z41EQ.js";
2
- import { A as PhysicsBody3D, C as Terrain3D, D as Joint3D, E as terrainThemeLayers, F as QUARTER_PITCH, I as cameraRelative, L as keyboardIntensity, M as StaticBody3D, N as Node3D, O as Area3D, R as movementState, S as Billboard3D, T as TERRAIN_THEMES, _ as resolveFlowerDensity, a as VoxelGrid3D, b as Camera3D, c as Particles3D, d as MeshInstance3D, f as DirectionalLight3D, g as Flowers3D, h as DENSITY_PRESETS, i as VOXEL_PALETTE, j as RigidBody3D, k as CharacterBody3D, l as ModelInstance3D, m as Foliage3D, n as Water3D, o as Tree3D, p as OmniLight3D, r as WATER_MAX_RIPPLES, s as Trail3D, t as registerNodes3D, u as LoftMesh3D, v as FLOWER_VARIETIES, w as DEFAULT_TERRAIN_TEXTURE_BASE, x as BoneAttachment3D, y as CharacterController3D, z as rigPose } from "./register-BP-kbijm.js";
1
+ import { a as Environment3D, c as sunDirectionFromElevationAzimuth, i as syncTree, l as sunDirectionFromSky, o as horizonColorFromSky, r as Renderer3D, s as parseEnvironment3D, t as createGame3D, u as AssetStore3D } from "./create-game-B2fewJUy.js";
2
+ import { A as PhysicsBody3D, C as Terrain3D, D as Joint3D, E as terrainThemeLayers, F as QUARTER_PITCH, I as cameraRelative, L as keyboardIntensity, M as StaticBody3D, N as Node3D, O as Area3D, R as movementState, S as Billboard3D, T as TERRAIN_THEMES, _ as resolveFlowerDensity, a as VoxelGrid3D, b as Camera3D, c as Particles3D, d as MeshInstance3D, f as DirectionalLight3D, g as Flowers3D, h as DENSITY_PRESETS, i as VOXEL_PALETTE, j as RigidBody3D, k as CharacterBody3D, l as ModelInstance3D, m as Foliage3D, n as Water3D, o as Tree3D, p as OmniLight3D, r as WATER_MAX_RIPPLES, s as Trail3D, t as registerNodes3D, u as LoftMesh3D, v as FLOWER_VARIETIES, w as DEFAULT_TERRAIN_TEXTURE_BASE, x as BoneAttachment3D, y as CharacterController3D, z as rigPose } from "./register-ysLR3WQS.js";
3
3
  import { n as splatWeights, t as buildHeightmap } from "./heightmap-CroQPEER.js";
4
- import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-D8m2Hd-q.js";
5
- export { Area3D, AssetStore3D, Billboard3D, BoneAttachment3D, Camera3D, CharacterBody3D, CharacterController3D, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, Environment3D, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, Flowers3D, Foliage3D, Joint3D, LoftMesh3D, MeshInstance3D, ModelInstance3D, Node3D, OmniLight3D, Particles3D, Physics3D, PhysicsBody3D, QUARTER_PITCH, Renderer3D, RigidBody3D, StaticBody3D, TERRAIN_THEMES, Terrain3D, Trail3D, Tree3D, VOXEL_PALETTE, VoxelGrid3D, WATER_MAX_RIPPLES, Water3D, buildHeightmap, cameraRelative, createGame3D, enablePhysics3D, horizonColorFromSky, keyboardIntensity, movementState, parseEnvironment3D, registerNodes3D, resolveFlowerDensity, rigPose, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers };
4
+ import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-RLNaxRyw.js";
5
+ //#region src/3d/terrain-nav.ts
6
+ function buildTerrainNav(terrain, opts) {
7
+ const cellSize = opts?.cellSize ?? 2;
8
+ const maxSlopeDeg = opts?.maxSlopeDeg ?? 40;
9
+ const minHeight = opts?.minHeight ?? Number.NEGATIVE_INFINITY;
10
+ let ox = 0;
11
+ let oz = 0;
12
+ for (let n = terrain; n; n = n.parent) if (n instanceof Node3D) {
13
+ ox += n.position[0] ?? 0;
14
+ oz += n.position[2] ?? 0;
15
+ }
16
+ const sizeX = terrain.size[0] ?? 200;
17
+ const sizeZ = terrain.size[1] ?? 200;
18
+ const width = Math.max(1, Math.round(sizeX / cellSize));
19
+ const height = Math.max(1, Math.round(sizeZ / cellSize));
20
+ const minX = ox - sizeX / 2;
21
+ const minZ = oz - sizeZ / 2;
22
+ const centerX = (cx) => minX + (cx + .5) * cellSize;
23
+ const centerZ = (cy) => minZ + (cy + .5) * cellSize;
24
+ const tanLimit = Math.tan(maxSlopeDeg * Math.PI / 180);
25
+ const halfDiag = cellSize / 2 * Math.SQRT2;
26
+ const solidBits = new Uint8Array(width * height);
27
+ for (let cy = 0; cy < height; cy++) for (let cx = 0; cx < width; cx++) {
28
+ const i = cy * width + cx;
29
+ const x = centerX(cx);
30
+ const z = centerZ(cy);
31
+ const h = terrain.heightAt(x, z);
32
+ if (h < minHeight) {
33
+ solidBits[i] = 1;
34
+ continue;
35
+ }
36
+ const half = cellSize / 2;
37
+ for (const [dx, dz] of CORNERS) {
38
+ const hc = terrain.heightAt(x + dx * half, z + dz * half);
39
+ if (Math.abs(hc - h) / halfDiag > tanLimit) {
40
+ solidBits[i] = 1;
41
+ break;
42
+ }
43
+ }
44
+ }
45
+ return {
46
+ grid: {
47
+ width,
48
+ height,
49
+ solid: (x, y) => x < 0 || y < 0 || x >= width || y >= height || solidBits[y * width + x] === 1
50
+ },
51
+ cellSize,
52
+ toCell: (x, z) => [Math.floor((x - minX) / cellSize), Math.floor((z - minZ) / cellSize)],
53
+ toWorld: (cx, cy) => {
54
+ const x = centerX(cx);
55
+ const z = centerZ(cy);
56
+ return [
57
+ x,
58
+ terrain.heightAt(x, z),
59
+ z
60
+ ];
61
+ },
62
+ setSolid: (cx, cy) => {
63
+ if (cx >= 0 && cy >= 0 && cx < width && cy < height) solidBits[cy * width + cx] = 1;
64
+ }
65
+ };
66
+ }
67
+ const CORNERS = [
68
+ [1, 1],
69
+ [1, -1],
70
+ [-1, 1],
71
+ [-1, -1]
72
+ ];
73
+ //#endregion
74
+ export { Area3D, AssetStore3D, Billboard3D, BoneAttachment3D, Camera3D, CharacterBody3D, CharacterController3D, DEFAULT_TERRAIN_TEXTURE_BASE, DirectionalLight3D, Environment3D, DENSITY_PRESETS as FLOWER_DENSITY_PRESETS, FLOWER_VARIETIES, Flowers3D, Foliage3D, Joint3D, LoftMesh3D, MeshInstance3D, ModelInstance3D, Node3D, OmniLight3D, Particles3D, Physics3D, PhysicsBody3D, QUARTER_PITCH, Renderer3D, RigidBody3D, StaticBody3D, TERRAIN_THEMES, Terrain3D, Trail3D, Tree3D, VOXEL_PALETTE, VoxelGrid3D, WATER_MAX_RIPPLES, Water3D, buildHeightmap, buildTerrainNav, cameraRelative, createGame3D, enablePhysics3D, horizonColorFromSky, keyboardIntensity, movementState, parseEnvironment3D, registerNodes3D, resolveFlowerDensity, rigPose, splatWeights, sunDirectionFromElevationAzimuth, sunDirectionFromSky, syncTree, terrainThemeLayers };
@@ -5,8 +5,8 @@ import { t as IncantoError } from "./errors-BpWbnbb_.js";
5
5
  import { i as resolveRendering, n as attachTouchControls } from "./touch-031PxtCR.js";
6
6
  import { n as registerGameplayBehaviors } from "./gameplay-Dn3yidJw.js";
7
7
  import { t as debugSources } from "./debug-draw-CZmOYjL2.js";
8
- import { A as PhysicsBody3D, N as Node3D, b as Camera3D, f as DirectionalLight3D, l as ModelInstance3D, t as registerNodes3D } from "./register-BP-kbijm.js";
9
- import { n as enablePhysics3D } from "./physics-3d-D8m2Hd-q.js";
8
+ import { A as PhysicsBody3D, N as Node3D, b as Camera3D, f as DirectionalLight3D, l as ModelInstance3D, t as registerNodes3D } from "./register-ysLR3WQS.js";
9
+ import { n as enablePhysics3D } from "./physics-3d-RLNaxRyw.js";
10
10
  import { ACESFilmicToneMapping, AmbientLight, Box3, BufferAttribute, BufferGeometry, Color, DepthTexture, EquirectangularReflectionMapping, FloatType, Fog, HalfFloatType, LineBasicMaterial, LineSegments, Matrix4, Mesh, PCFShadowMap, PMREMGenerator, PerspectiveCamera, PlaneGeometry, Quaternion, Raycaster, Scene, ShaderMaterial, Vector2, Vector3, WebGLRenderTarget, WebGLRenderer } from "three";
11
11
  import { VRMLoaderPlugin, VRMUtils } from "@pixiv/three-vrm";
12
12
  import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
@@ -182,6 +182,9 @@ varying vec2 vUv;
182
182
  uniform sampler2D tScene;
183
183
  uniform sampler2D tBloom;
184
184
  uniform float uStrength;
185
+ uniform float uVignette;
186
+ uniform float uSaturation;
187
+ uniform float uContrast;
185
188
  void main() {
186
189
  vec3 base = texture2D(tScene, vUv).rgb;
187
190
  vec3 glow = texture2D(tBloom, vUv).rgb;
@@ -192,6 +195,15 @@ void main() {
192
195
  // tail here (ACES then linear→sRGB); without it the frame comes out dark
193
196
  // and oversaturated (the volumetric-clouds pipeline bug, root-caused).
194
197
  #include <tonemapping_fragment>
198
+ // color grade AFTER tone mapping (values are display-referred now) and
199
+ // BEFORE the colorspace transform: saturation → contrast → vignette
200
+ vec3 graded = gl_FragColor.rgb;
201
+ float luma = dot(graded, vec3(0.2126, 0.7152, 0.0722));
202
+ graded = mix(vec3(luma), graded, uSaturation);
203
+ graded = (graded - 0.5) * uContrast + 0.5;
204
+ float dist = distance(vUv, vec2(0.5));
205
+ graded *= 1.0 - uVignette * smoothstep(0.3, 0.78, dist);
206
+ gl_FragColor.rgb = max(graded, 0.0);
195
207
  #include <colorspace_fragment>
196
208
  }
197
209
  `;
@@ -234,7 +246,10 @@ function createBloomCompositeQuad() {
234
246
  const mesh = quad(COMPOSITE_FRAG, {
235
247
  tScene: { value: null },
236
248
  tBloom: { value: null },
237
- uStrength: { value: .85 }
249
+ uStrength: { value: .85 },
250
+ uVignette: { value: 0 },
251
+ uSaturation: { value: 1 },
252
+ uContrast: { value: 1 }
238
253
  });
239
254
  return {
240
255
  mesh,
@@ -562,6 +577,11 @@ const CLOUD_KEYS = [
562
577
  "scale"
563
578
  ];
564
579
  const BLOOM_KEYS = ["threshold", "strength"];
580
+ const POST_KEYS = [
581
+ "vignette",
582
+ "saturation",
583
+ "contrast"
584
+ ];
565
585
  const SHADOW_KEYS = [
566
586
  "mapSize",
567
587
  "radius",
@@ -583,6 +603,7 @@ function parseEnvironment3D(env) {
583
603
  fog: parseFog(env?.fog, env?.sky !== void 0),
584
604
  clouds: parseClouds(env?.clouds),
585
605
  bloom: parseBloom(env?.bloom),
606
+ post: parsePost(env?.post),
586
607
  shadows: parseShadows(env?.shadows)
587
608
  };
588
609
  }
@@ -754,6 +775,26 @@ function parseBloom(value) {
754
775
  strength
755
776
  };
756
777
  }
778
+ function parsePost(value) {
779
+ if (value === void 0) return null;
780
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw new IncantoError("BAD_FORMAT", `environment.post must be an object ({ vignette?, saturation?, contrast? }), got ${JSON.stringify(value)}.`, { prop: "post" });
781
+ const p = value;
782
+ for (const key of Object.keys(p)) if (!POST_KEYS.includes(key)) throw new IncantoError("BAD_FORMAT", `environment.post has unknown key '${key}'. Valid keys: [${POST_KEYS.join(", ")}].`, {
783
+ prop: "post",
784
+ validOptions: POST_KEYS
785
+ });
786
+ const vignette = numberOr(p.vignette, 0, "post.vignette");
787
+ if (vignette < 0 || vignette > 1) throw new IncantoError("BAD_FORMAT", `environment.post.vignette must be in [0, 1], got ${vignette}.`, { prop: "post" });
788
+ const saturation = numberOr(p.saturation, 1, "post.saturation");
789
+ if (saturation < 0 || saturation > 4) throw new IncantoError("BAD_FORMAT", `environment.post.saturation must be in [0, 4] (1 = neutral), got ${saturation}.`, { prop: "post" });
790
+ const contrast = numberOr(p.contrast, 1, "post.contrast");
791
+ if (contrast < .2 || contrast > 3) throw new IncantoError("BAD_FORMAT", `environment.post.contrast must be in [0.2, 3] (1 = neutral), got ${contrast}.`, { prop: "post" });
792
+ return {
793
+ vignette,
794
+ saturation,
795
+ contrast
796
+ };
797
+ }
757
798
  function parseShadows(value) {
758
799
  if (value === void 0) return null;
759
800
  if (value === false) return false;
@@ -876,6 +917,10 @@ var Environment3D = class {
876
917
  get bloom() {
877
918
  return this.config.bloom;
878
919
  }
920
+ /** Parsed color-grade/vignette config, or null when not declared. */
921
+ get post() {
922
+ return this.config.post;
923
+ }
879
924
  /** The live scene fog (color/near/far) the cloud composite fades into, or null. */
880
925
  get sceneFog() {
881
926
  return this.scene.fog instanceof Fog ? this.scene.fog : null;
@@ -1601,9 +1646,10 @@ var Renderer3D = class {
1601
1646
  this.environment.applyUnderwater(underwater);
1602
1647
  const clouds = this.environment.clouds;
1603
1648
  const bloom = this.environment.bloom;
1649
+ const post = this.environment.post;
1604
1650
  if (underwater?.caustics.enabled) this.renderWithCaustics(activeCamera, underwater);
1605
1651
  else if (clouds && !underwater) this.renderWithClouds(activeCamera, clouds, threeLight);
1606
- else if (bloom && !underwater) this.renderWithBloom(activeCamera, bloom);
1652
+ else if ((bloom || post) && !underwater) this.renderWithBloom(activeCamera, bloom, post);
1607
1653
  else this.webgl.render(this.threeScene, activeCamera);
1608
1654
  }
1609
1655
  /**
@@ -1615,7 +1661,7 @@ var Renderer3D = class {
1615
1661
  * the scene's tone; the clouds pipeline taught us that lesson)
1616
1662
  * Caustics/clouds paths take precedence (composite pipelines don't stack yet).
1617
1663
  */
1618
- renderWithBloom(camera, bloom) {
1664
+ renderWithBloom(camera, bloom, post = null) {
1619
1665
  const buf = this.webgl.getDrawingBufferSize(sizeScratch);
1620
1666
  const w = Math.max(1, buf.x);
1621
1667
  const h = Math.max(1, buf.y);
@@ -1652,24 +1698,29 @@ var Renderer3D = class {
1652
1698
  const blurTarget = this.bloomBlurTarget;
1653
1699
  this.webgl.setRenderTarget(this.bloomTarget);
1654
1700
  this.webgl.render(this.threeScene, camera);
1655
- const bu = this.bloomBrightUniforms;
1656
- bu.tScene.value = this.bloomTarget.texture;
1657
- bu.uThreshold.value = bloom.threshold;
1658
- this.webgl.setRenderTarget(brightTarget);
1659
- this.webgl.render(this.bloomBrightScene, camera);
1660
- const blu = this.bloomBlurUniforms;
1661
- blu.tTex.value = brightTarget.texture;
1662
- blu.uDir.value.set(1 / hw, 0);
1663
- this.webgl.setRenderTarget(blurTarget);
1664
- this.webgl.render(this.bloomBlurScene, camera);
1665
- blu.tTex.value = blurTarget.texture;
1666
- blu.uDir.value.set(0, 1 / hh);
1667
- this.webgl.setRenderTarget(brightTarget);
1668
- this.webgl.render(this.bloomBlurScene, camera);
1701
+ if (bloom) {
1702
+ const bu = this.bloomBrightUniforms;
1703
+ bu.tScene.value = this.bloomTarget.texture;
1704
+ bu.uThreshold.value = bloom.threshold;
1705
+ this.webgl.setRenderTarget(brightTarget);
1706
+ this.webgl.render(this.bloomBrightScene, camera);
1707
+ const blu = this.bloomBlurUniforms;
1708
+ blu.tTex.value = brightTarget.texture;
1709
+ blu.uDir.value.set(1 / hw, 0);
1710
+ this.webgl.setRenderTarget(blurTarget);
1711
+ this.webgl.render(this.bloomBlurScene, camera);
1712
+ blu.tTex.value = blurTarget.texture;
1713
+ blu.uDir.value.set(0, 1 / hh);
1714
+ this.webgl.setRenderTarget(brightTarget);
1715
+ this.webgl.render(this.bloomBlurScene, camera);
1716
+ }
1669
1717
  const cu = this.bloomCompositeUniforms;
1670
1718
  cu.tScene.value = this.bloomTarget.texture;
1671
- cu.tBloom.value = brightTarget.texture;
1672
- cu.uStrength.value = bloom.strength;
1719
+ cu.tBloom.value = bloom ? brightTarget.texture : this.bloomTarget.texture;
1720
+ cu.uStrength.value = bloom ? bloom.strength : 0;
1721
+ cu.uVignette.value = post?.vignette ?? 0;
1722
+ cu.uSaturation.value = post?.saturation ?? 1;
1723
+ cu.uContrast.value = post?.contrast ?? 1;
1673
1724
  this.webgl.setRenderTarget(null);
1674
1725
  this.webgl.render(this.bloomCompositeScene, camera);
1675
1726
  }
@@ -6,7 +6,7 @@ import { i as resolveRendering, n as attachTouchControls } from "./touch-031PxtC
6
6
  import { n as registerGameplayBehaviors } from "./gameplay-Dn3yidJw.js";
7
7
  import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-BD6zgrv_.js";
8
8
  import { t as debugSources } from "./debug-draw-CZmOYjL2.js";
9
- import { n as enablePhysics2D } from "./physics-2d-DweTURFt.js";
9
+ import { n as enablePhysics2D } from "./physics-2d-B6D864oZ.js";
10
10
  import { Box3, BufferAttribute, BufferGeometry, Color, LineBasicMaterial, LineSegments, LinearFilter, NearestFilter, OrthographicCamera, Raycaster, SRGBColorSpace, Scene, TextureLoader, Vector2, Vector3, WebGLRenderer } from "three";
11
11
  //#region src/2d/assets.ts
12
12
  /**
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { a as Rng, c as JsonValue, d as jsonKind, i as SceneJson, l as jsonClone
2
2
  import { $ as Node, A as SfxPlayOptions, B as spatialPan, C as RendererStats, D as LogManager, E as LogLevel, F as ROLLOFF_MODELS, G as SynthOptions, H as SFX_PRESET_NAMES, I as RolloffModel, J as MusicManager, K as synthSfx, L as SpatialParams, M as Voice, N as VoicePreset, O as InputMap, P as Listener, Q as BusName, R as Vec3, S as GameStats, T as LogEntry, U as SfxParams, V as SFX_PRESETS, W as SfxWave, X as PlayMusicOptions, Y as MusicTrack, Z as AudioBuses, _ as registeredTypes, a as registerBehavior, b as Scheduler, c as PropDef, d as createNode, et as NodeLifecycle, f as getNodeSchema, g as registerNode, h as mergeStaticSignals, i as getBehavior, j as isAudioContextAvailable, k as SfxEngine, l as PropSchema, m as getNodeType, n as BehaviorCtor, nt as SignalListener, o as registeredBehaviors, p as getNodeSignals, q as MusicBackend, r as clearBehaviors, rt as SceneTree, s as NodeCtor, t as Behavior, tt as Signal, u as clearRegistry, v as Engine, w as Scene, x as EngineStats, y as EngineOptions, z as spatialGain } from "./behavior-Bod1AyJS.js";
3
3
  import { n as loadScene, t as LoadSceneOptions } from "./loader-BcUDfNHn.js";
4
4
  import { n as ParticleSimConfig, r as ParticleView, t as ParticleSim } from "./particle-sim-CwJ5rI_P.js";
5
- import { n as AudioPlayer, t as AudioElementLike } from "./audio-player-Dyjg5k92.js";
5
+ import { a as AudioElementLike, i as gridFromRows, n as PathGrid, o as AudioPlayer, r as findPath, t as FindPathOptions } from "./pathfinding-BSiXjd6W.js";
6
6
  import { i as auditScene, n as IncantoErrorCode, r as IncantoErrorDetails, t as IncantoError } from "./errors-1dXlIwoR.js";
7
7
 
8
8
  //#region src/core/audio/crossfade.d.ts
@@ -336,33 +336,6 @@ declare const PARTICLE_PRESET_NAMES: readonly string[];
336
336
  */
337
337
  declare function applyParticlePreset(target: Record<string, unknown>, presetName: string, schema: PropSchema): void;
338
338
  //#endregion
339
- //#region src/core/pathfinding.d.ts
340
- /**
341
- * Grid A* — the pathfinding every top-down/RPG/tower-defense asks for and
342
- * agents keep re-inventing badly. Pure and dimension-free: cells in, cells
343
- * out; the caller maps cells to world units (px, meters, tiles).
344
- */
345
- interface PathGrid {
346
- width: number;
347
- height: number;
348
- /** True = impassable. Out-of-bounds is always solid. */
349
- solid(x: number, y: number): boolean;
350
- }
351
- interface FindPathOptions {
352
- /** Allow diagonal steps (blocked from cutting corners). Default true. */
353
- diagonal?: boolean;
354
- /** Abort guard for huge/impossible searches. Default 20000 nodes. */
355
- maxExpansions?: number;
356
- }
357
- /**
358
- * A* from `from` to `to` (inclusive cell coords). Returns the cell path
359
- * INCLUDING both endpoints, or null when unreachable. Straight steps cost
360
- * 1, diagonals √2; the heuristic is octile (admissible for both modes).
361
- */
362
- declare function findPath(grid: PathGrid, from: [number, number], to: [number, number], opts?: FindPathOptions): [number, number][] | null;
363
- /** Build a PathGrid from row-strings ('#' = solid) — tests and tile games. */
364
- declare function gridFromRows(rows: readonly string[]): PathGrid;
365
- //#endregion
366
339
  //#region src/core/preload.d.ts
367
340
  interface PreloadResult {
368
341
  /** Urls whose fetch failed — show an error UI instead of pretending success. */
package/dist/index.js CHANGED
@@ -295,6 +295,6 @@ function newUid() {
295
295
  //#endregion
296
296
  //#region src/index.ts
297
297
  /** Engine version. Kept in sync with package.json by the release pipeline. */
298
- const VERSION = "0.10.0";
298
+ const VERSION = "0.12.0";
299
299
  //#endregion
300
300
  export { AudioBuses, AudioPlayer, Behavior, CONST_REF_KEY, Engine, HudLayer, IncantoError, InputMap, LogManager, MusicManager, Node, ORDER_GROUP_BASE, PARTICLE_PRESETS, PARTICLE_PRESET_NAMES, ParticleSim, ROLLOFF_MODELS, Rng, SCENE_FORMAT, SFX_PRESETS, SFX_PRESET_NAMES, Scene, SceneTree, SfxEngine, Signal, Timer, TouchControls, UiBanner, UiBar, UiButton, UiDialogue, UiText, VERSION, WebAudioMusicBackend, applyParticlePreset, assetUrls, attachTouchControls, auditScene, clearBehaviors, clearRegistry, computeViewport, createNode, createNoise2D, createSaveStore, crossfadeGains, duplicateNode, effectiveOrder, fadeGain, findPath, getBehavior, getNodeSchema, getNodeSignals, getNodeType, gridFromRows, isAudioContextAvailable, isConstRef, joystickVector, jsonClone, jsonEquals, jsonKind, loadScene, mergeStaticSignals, newUid, parseNodePath, preloadUrls, registerBehavior, registerCoreNodes, registerNode, registeredBehaviors, registeredTypes, replay, resolveConstants, resolveRendering, resolveViewport, serializeNode, spatialGain, spatialPan, startRecording, synthSfx };
@@ -107,4 +107,31 @@ declare class AudioPlayer extends Node {
107
107
  override update(_dt: number): void;
108
108
  }
109
109
  //#endregion
110
- export { AudioPlayer as n, SpatialPose as r, AudioElementLike as t };
110
+ //#region src/core/pathfinding.d.ts
111
+ /**
112
+ * Grid A* — the pathfinding every top-down/RPG/tower-defense asks for and
113
+ * agents keep re-inventing badly. Pure and dimension-free: cells in, cells
114
+ * out; the caller maps cells to world units (px, meters, tiles).
115
+ */
116
+ interface PathGrid {
117
+ width: number;
118
+ height: number;
119
+ /** True = impassable. Out-of-bounds is always solid. */
120
+ solid(x: number, y: number): boolean;
121
+ }
122
+ interface FindPathOptions {
123
+ /** Allow diagonal steps (blocked from cutting corners). Default true. */
124
+ diagonal?: boolean;
125
+ /** Abort guard for huge/impossible searches. Default 20000 nodes. */
126
+ maxExpansions?: number;
127
+ }
128
+ /**
129
+ * A* from `from` to `to` (inclusive cell coords). Returns the cell path
130
+ * INCLUDING both endpoints, or null when unreachable. Straight steps cost
131
+ * 1, diagonals √2; the heuristic is octile (admissible for both modes).
132
+ */
133
+ declare function findPath(grid: PathGrid, from: [number, number], to: [number, number], opts?: FindPathOptions): [number, number][] | null;
134
+ /** Build a PathGrid from row-strings ('#' = solid) — tests and tile games. */
135
+ declare function gridFromRows(rows: readonly string[]): PathGrid;
136
+ //#endregion
137
+ export { AudioElementLike as a, gridFromRows as i, PathGrid as n, AudioPlayer as o, findPath as r, SpatialPose as s, FindPathOptions as t };
@@ -99,8 +99,12 @@ var Physics2D = class {
99
99
  const b = this.byColliderHandle.get(h2);
100
100
  if (!a || !b) return;
101
101
  const sig = started ? "triggerEnter" : "triggerExit";
102
- a.emit(sig, b);
103
- b.emit(sig, a);
102
+ try {
103
+ a.emit(sig, b);
104
+ b.emit(sig, a);
105
+ } catch (error) {
106
+ console.error(`incanto: error in a '${sig}' handler (${a.name} ↔ ${b.name}):`, error);
107
+ }
104
108
  });
105
109
  }
106
110
  /** @internal Called by CharacterBody2D.moveAndSlide (during tree fixedUpdate). */
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
3
3
  import { n as registerDebugSource } from "./debug-draw-CZmOYjL2.js";
4
- import { A as PhysicsBody3D, C as Terrain3D, D as Joint3D, N as Node3D, O as Area3D, P as validateCollider3D, j as RigidBody3D, k as CharacterBody3D } from "./register-BP-kbijm.js";
4
+ import { A as PhysicsBody3D, C as Terrain3D, D as Joint3D, N as Node3D, O as Area3D, P as validateCollider3D, j as RigidBody3D, k as CharacterBody3D } from "./register-ysLR3WQS.js";
5
5
  import { Euler, Quaternion } from "three";
6
6
  //#region src/3d/physics/physics-3d.ts
7
7
  var physics_3d_exports = /* @__PURE__ */ __exportAll({
@@ -124,8 +124,12 @@ var Physics3D = class {
124
124
  const b = this.byColliderHandle.get(h2);
125
125
  if (!a || !b) return;
126
126
  const sig = started ? "triggerEnter" : "triggerExit";
127
- a.emit(sig, b);
128
- b.emit(sig, a);
127
+ try {
128
+ a.emit(sig, b);
129
+ b.emit(sig, a);
130
+ } catch (error) {
131
+ console.error(`incanto: error in a '${sig}' handler (${a.name} ↔ ${b.name}):`, error);
132
+ }
129
133
  });
130
134
  }
131
135
  /** @internal Called by CharacterBody3D.moveAndSlide (during tree fixedUpdate). */
@@ -399,6 +403,38 @@ var Physics3D = class {
399
403
  node: this.byColliderHandle.get(hit.collider.handle) ?? null
400
404
  };
401
405
  }
406
+ /**
407
+ * Sweep a sphere of `radius` from `origin` along `dir` — a THICK ray. The
408
+ * spring-arm camera probe uses this instead of `castRay`: a thin ray that
409
+ * skims 10 cm over a wall reports "clear" while the camera's near plane
410
+ * still clips the wall; the ball's radius covers that band. Same filters
411
+ * as `castRay` (sensors never hit; `staticOnly` ignores dynamic/kinematic).
412
+ * Returns the travel distance of the sphere CENTER, or null when clear.
413
+ */
414
+ castSphere(origin, dir, radius, maxLen, exclude, opts) {
415
+ const R = this.R;
416
+ const excludeEntry = exclude ? this.entries.get(exclude) : void 0;
417
+ const flags = opts?.staticOnly ? R.QueryFilterFlags.EXCLUDE_DYNAMIC | R.QueryFilterFlags.EXCLUDE_KINEMATIC : void 0;
418
+ const hit = this.world.castShape({
419
+ x: origin[0],
420
+ y: origin[1],
421
+ z: origin[2]
422
+ }, {
423
+ x: 0,
424
+ y: 0,
425
+ z: 0,
426
+ w: 1
427
+ }, {
428
+ x: dir[0],
429
+ y: dir[1],
430
+ z: dir[2]
431
+ }, new R.Ball(radius), 0, maxLen, true, flags, void 0, excludeEntry?.collider, excludeEntry?.body, (collider) => !collider.isSensor());
432
+ if (!hit) return null;
433
+ return {
434
+ distance: hit.time_of_impact,
435
+ node: this.byColliderHandle.get(hit.collider.handle) ?? null
436
+ };
437
+ }
402
438
  };
403
439
  const quatScratch = new Quaternion();
404
440
  const eulerScratch = new Euler();
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-Cq0Z41EQ.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-CdWhP6ve.js").then((n) => n.n)).createGame2D(o)))(opts);
159
+ const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-B2fewJUy.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-C_xf4gm9.js").then((n) => n.n)).createGame2D(o)))(opts);
160
160
  if (disposed) {
161
161
  next.dispose();
162
162
  return;
@@ -2017,6 +2017,10 @@ const CAM_COLLISION_MARGIN = .3;
2017
2017
  const CAM_COLLISION_MIN_DIST = .4;
2018
2018
  /** Ground backstop: keep the camera at least this high above whatever is below it. */
2019
2019
  const CAM_GROUND_CLEARANCE = .3;
2020
+ /** Spring-arm probe thickness: a THIN ray that skims 10 cm above a wall reports
2021
+ * "clear" while the wall still fills the frame — the sphere's radius covers the
2022
+ * near-plane band around the boom (the Emberwood hedge-maze lesson). */
2023
+ const CAM_PROBE_RADIUS = .25;
2020
2024
  const eulerScratch = new Euler();
2021
2025
  const quatScratch = new Quaternion();
2022
2026
  const matrixScratch$3 = new Matrix4();
@@ -2285,7 +2289,7 @@ var CharacterController3D = class extends Node3D {
2285
2289
  if (this.cameraCollision && this.view !== "firstPerson") {
2286
2290
  const physics = body._physics3d;
2287
2291
  if (physics) {
2288
- target = springArmCamera(eye, target, (o, dr, len) => physics.castRay(o, dr, len, body, { staticOnly: true })?.distance ?? null, CAM_COLLISION_MARGIN, CAM_COLLISION_MIN_DIST);
2292
+ target = springArmCamera(eye, target, (o, dr, len) => physics.castSphere(o, dr, CAM_PROBE_RADIUS, len, body, { staticOnly: true })?.distance ?? null, CAM_COLLISION_MARGIN, CAM_COLLISION_MIN_DIST);
2289
2293
  target = clampCameraAboveGround(target, (o, len) => physics.castRay(o, [
2290
2294
  0,
2291
2295
  -1,
package/dist/test.js CHANGED
@@ -6,7 +6,7 @@ import { n as jsonEquals, t as jsonClone } from "./json-BLk7H2Qa.js";
6
6
  import { i as getNodeSchema, s as mergeStaticProps } from "./registry-BVJ2HbCn.js";
7
7
  import { n as registerGameplayBehaviors } from "./gameplay-Dn3yidJw.js";
8
8
  import { t as registerNodes2D } from "./register-BD6zgrv_.js";
9
- import { t as registerNodes3D } from "./register-BP-kbijm.js";
9
+ import { t as registerNodes3D } from "./register-ysLR3WQS.js";
10
10
  import { t as registerNodesNet } from "./register-Cwc-yCYx.js";
11
11
  //#region src/test/index.ts
12
12
  /**
@@ -124,10 +124,10 @@ async function runScript(json, opts) {
124
124
  engine.setScene(scene);
125
125
  const physics = opts.physics ?? "auto";
126
126
  if (physics === "2d" || physics === "auto" && scene.dimension === "2d") {
127
- const { enablePhysics2D } = await import("./physics-2d-DweTURFt.js").then((n) => n.r);
127
+ const { enablePhysics2D } = await import("./physics-2d-B6D864oZ.js").then((n) => n.r);
128
128
  await enablePhysics2D(engine);
129
129
  } else if (physics === "3d" || physics === "auto" && scene.dimension === "3d") {
130
- const { enablePhysics3D } = await import("./physics-3d-D8m2Hd-q.js").then((n) => n.r);
130
+ const { enablePhysics3D } = await import("./physics-3d-RLNaxRyw.js").then((n) => n.r);
131
131
  await enablePhysics3D(engine);
132
132
  }
133
133
  const failures = [];
@@ -229,10 +229,10 @@ async function createPlaySession(json, opts = {}) {
229
229
  engine.setScene(scene);
230
230
  const physics = opts.physics ?? "auto";
231
231
  if (physics === "2d" || physics === "auto" && scene.dimension === "2d") {
232
- const { enablePhysics2D } = await import("./physics-2d-DweTURFt.js").then((n) => n.r);
232
+ const { enablePhysics2D } = await import("./physics-2d-B6D864oZ.js").then((n) => n.r);
233
233
  await enablePhysics2D(engine);
234
234
  } else if (physics === "3d" || physics === "auto" && scene.dimension === "3d") {
235
- const { enablePhysics3D } = await import("./physics-3d-D8m2Hd-q.js").then((n) => n.r);
235
+ const { enablePhysics3D } = await import("./physics-3d-RLNaxRyw.js").then((n) => n.r);
236
236
  await enablePhysics3D(engine);
237
237
  }
238
238
  const stepMs = 1e3 / (opts.fixedHz ?? 60);
@@ -1 +1 @@
1
- import{t as e}from"./index-Dp_cYQx1.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{t as e}from"./index-s0DZuroe.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};