incanto 0.22.0 → 0.23.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,5 +1,5 @@
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-B-M1zune.js";
2
+ import { a as AssetStore2D, i as syncTree2D, r as Renderer2D, t as createGame2D } from "./create-game-DrcEgRup.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-CvpSUU3O.js";
4
4
  import { n as enablePhysics2D, t as Physics2D } from "./physics-2d-DiVFFlH3.js";
5
5
  //#region src/2d/library-sprite.ts
package/dist/3d.d.ts CHANGED
@@ -2285,6 +2285,12 @@ declare class Water3D extends Node3D implements RenderHook3D, SunConsumer3D {
2285
2285
  * render per frame, so it is off by default; a still lake earns it.
2286
2286
  */
2287
2287
  mirror: boolean;
2288
+ /**
2289
+ * Milliseconds between planar-mirror re-renders. A reflection seen through a
2290
+ * rippling surface does not need 60 Hz — 33 ms halves the pass's cost and
2291
+ * nobody can tell. 0 re-renders every frame.
2292
+ */
2293
+ mirrorInterval: number;
2288
2294
  /** ms between reflection (and foam depth) re-renders. */
2289
2295
  reflectionInterval: number;
2290
2296
  /** Depth-texture shoreline foam — rides the always-on fancy scene pass. */
@@ -2378,6 +2384,8 @@ declare class Water3D extends Node3D implements RenderHook3D, SunConsumer3D {
2378
2384
  private readonly _scratchA;
2379
2385
  private readonly _scratchB;
2380
2386
  private readonly _bodies;
2387
+ /** Scratch for the side-pass cull (no per-frame allocation). */
2388
+ private readonly _passHidden;
2381
2389
  private cubeTarget;
2382
2390
  private cubeCamera;
2383
2391
  /** Reflection near plane (max half extent) — recreate the camera on resize. */
@@ -2388,6 +2396,7 @@ declare class Water3D extends Node3D implements RenderHook3D, SunConsumer3D {
2388
2396
  private mirrorTarget;
2389
2397
  private readonly mirrorCamera;
2390
2398
  private readonly mirrorMatrix;
2399
+ private lastMirrorAt;
2391
2400
  protected override _createObject3D(): Object3D;
2392
2401
  override update(dt: number): void;
2393
2402
  override _syncObject3D(): void;
package/dist/3d.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
2
- import { A as Water3D, F as StaticBody3D, I as Node3D, M as CharacterBody3D, N as PhysicsBody3D, P as RigidBody3D, j as Area3D, z as WATER_MAX_RIPPLES } from "./gameplay-Dib5mNFD.js";
3
- 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-C3uiw80V.js";
4
- import { A as QUARTER_PITCH, C as BoneAttachment3D, D as TERRAIN_THEMES, E as DEFAULT_TERRAIN_TEXTURE_BASE, M as keyboardIntensity, N as movementState, O as terrainThemeLayers, P as rigPose, S as BoneLookAt3D, T as Terrain3D, _ as Flowers3D, a as Trail3D, b as CharacterController3D, c as Particles3D, d as DirectionalLight3D, f as OmniLight3D, g as DENSITY_PRESETS, h as Foliage3D, i as Tree3D, j as cameraRelative, k as Joint3D, l as ModelInstance3D, m as MeshInstance3D, n as VOXEL_PALETTE, o as River3D, p as InstancedMesh3D, r as VoxelGrid3D, s as traceDownhillPath, t as registerNodes3D, u as LoftMesh3D, v as resolveFlowerDensity, w as Billboard3D, x as Camera3D, y as FLOWER_VARIETIES } from "./register-CHgVdSbp.js";
2
+ import { A as Water3D, F as StaticBody3D, I as Node3D, M as CharacterBody3D, N as PhysicsBody3D, P as RigidBody3D, j as Area3D, z as WATER_MAX_RIPPLES } from "./gameplay-BJ5gXIks.js";
3
+ 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-OyjhYUL3.js";
4
+ import { A as QUARTER_PITCH, C as BoneAttachment3D, D as TERRAIN_THEMES, E as DEFAULT_TERRAIN_TEXTURE_BASE, M as keyboardIntensity, N as movementState, O as terrainThemeLayers, P as rigPose, S as BoneLookAt3D, T as Terrain3D, _ as Flowers3D, a as Trail3D, b as CharacterController3D, c as Particles3D, d as DirectionalLight3D, f as OmniLight3D, g as DENSITY_PRESETS, h as Foliage3D, i as Tree3D, j as cameraRelative, k as Joint3D, l as ModelInstance3D, m as MeshInstance3D, n as VOXEL_PALETTE, o as River3D, p as InstancedMesh3D, r as VoxelGrid3D, s as traceDownhillPath, t as registerNodes3D, u as LoftMesh3D, v as resolveFlowerDensity, w as Billboard3D, x as Camera3D, y as FLOWER_VARIETIES } from "./register-CpJORtm4.js";
5
5
  import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
6
- import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-DLPPRNu4.js";
6
+ import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-CpIB9C-F.js";
7
7
  //#region src/3d/environment-runtime.ts
8
8
  /**
9
9
  * Live environment editing — the renderer re-applies `scene.environment`
@@ -3,7 +3,7 @@ import { _ as registerBehavior, n as loadScene, o as computeViewport, s as resol
3
3
  import { l as AudioPlayer, u as Engine } from "./register-nObreUQR.js";
4
4
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
5
5
  import { i as resolveRendering, n as attachTouchControls } from "./touch-031PxtCR.js";
6
- import { n as registerGameplayBehaviors } from "./gameplay-Dib5mNFD.js";
6
+ import { n as registerGameplayBehaviors } from "./gameplay-BJ5gXIks.js";
7
7
  import { g as PhysicsBody2D, n as UILayer, t as registerNodes2D, u as Camera2D, y as Node2D } from "./register-CvpSUU3O.js";
8
8
  import { t as debugSources } from "./debug-draw-CZmOYjL2.js";
9
9
  import { n as enablePhysics2D } from "./physics-2d-DiVFFlH3.js";
@@ -3,10 +3,10 @@ import { _ as registerBehavior, n as loadScene } from "./loader-BZqOKfI2.js";
3
3
  import { l as AudioPlayer, u as Engine } from "./register-nObreUQR.js";
4
4
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
5
5
  import { i as resolveRendering, n as attachTouchControls } from "./touch-031PxtCR.js";
6
- import { I as Node3D, N as PhysicsBody3D, R as createCausticsQuad, n as registerGameplayBehaviors } from "./gameplay-Dib5mNFD.js";
6
+ import { I as Node3D, N as PhysicsBody3D, R as createCausticsQuad, n as registerGameplayBehaviors } from "./gameplay-BJ5gXIks.js";
7
7
  import { t as debugSources } from "./debug-draw-CZmOYjL2.js";
8
- import { d as DirectionalLight3D, l as ModelInstance3D, t as registerNodes3D, x as Camera3D } from "./register-CHgVdSbp.js";
9
- import { n as enablePhysics3D } from "./physics-3d-DLPPRNu4.js";
8
+ import { d as DirectionalLight3D, l as ModelInstance3D, t as registerNodes3D, x as Camera3D } from "./register-CpJORtm4.js";
9
+ import { n as enablePhysics3D } from "./physics-3d-CpIB9C-F.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";
@@ -398,6 +398,55 @@ void main() {
398
398
  }
399
399
  `;
400
400
  //#endregion
401
+ //#region src/3d/water/pass-cull.ts
402
+ /**
403
+ * What a water side-pass is allowed to skip.
404
+ *
405
+ * Water costs extra SCENE RENDERS — the refraction/depth grab, the planar
406
+ * mirror — and each one re-submits the whole world. On a meadow lake the world
407
+ * is mostly GRASS: tens of thousands of blade triangles that contribute
408
+ * nothing a player can name in a reflection or a depth mask, and everything to
409
+ * the frame budget. These node types are therefore dropped from the side
410
+ * passes; the main render is untouched, so nothing disappears from the scene
411
+ * the player is actually looking at.
412
+ *
413
+ * Foliage/flowers additionally BELONG out of the depth pass: alpha-cutout
414
+ * quads depth-write their full rectangle and wind-displaced blades render
415
+ * unposed, so their depth was always a lie the foam mask had to survive.
416
+ */
417
+ const SKIPPED_IN_WATER_PASSES = new Set([
418
+ "Foliage3D",
419
+ "Flowers3D",
420
+ "Particles3D",
421
+ "Trail3D"
422
+ ]);
423
+ /**
424
+ * Hide the auxiliary nodes for one pass. Returns the objects that were hidden
425
+ * so the caller can restore them — pass the array to {@link restoreForPass}.
426
+ * Allocation-free in the common case: the caller owns the scratch array.
427
+ */
428
+ function hideForWaterPass(root, out) {
429
+ out.length = 0;
430
+ if (typeof root?.traverse !== "function") return out;
431
+ root.traverse((obj) => {
432
+ if (!obj.visible) return;
433
+ const type = (obj.userData?.incantoNode)?.constructor?.typeName;
434
+ if (type && SKIPPED_IN_WATER_PASSES.has(type)) {
435
+ obj.visible = false;
436
+ out.push(obj);
437
+ }
438
+ });
439
+ return out;
440
+ }
441
+ /** Undo {@link hideForWaterPass}. */
442
+ function restoreForWaterPass(hidden) {
443
+ for (let i = 0; i < hidden.length; i++) {
444
+ const obj = hidden[i];
445
+ if (obj) obj.visible = true;
446
+ }
447
+ hidden.length = 0;
448
+ }
449
+ //#endregion
401
450
  //#region src/3d/water/caustics.ts
402
451
  /**
403
452
  * Underwater caustics — the dancing refracted-light pattern the water surface
@@ -1696,8 +1745,26 @@ void main() {
1696
1745
  foamOpacity = max(foamOpacity, mix(baseOpacity, min(baseOpacity + 0.3, 1.0), splashFoam));
1697
1746
  }
1698
1747
 
1748
+ // ── the waterline ───────────────────────────────────────────────────────
1749
+ // Water does not END; it runs out. Without this the surface stays fully
1750
+ // opaque right up to the geometric intersection and the shore reads as a
1751
+ // sheet of vinyl laid on the sand — the single most common tell of game
1752
+ // water. Fade over the last ~18 cm of VERTICAL column (not view depth: at a
1753
+ // grazing angle the view ray is metres long in ankle-deep water), so the
1754
+ // last hand's breadth of wash dissolves into wet ground. Independent of the
1755
+ // foam toggle — a beach without foam still has a waterline.
1756
+ float shoreDissolve = 1.0;
1757
+ if (uUseSceneDepth > 0.5 && waterViewDepth >= 0.0) {
1758
+ float shoreT = camDist * (linearSceneDepth / max(linearWaterDepth, 1e-4));
1759
+ float bedY = cameraPosition.y + viewDirection.y * shoreT;
1760
+ float column = max(uWaterCenter.y - bedY, 0.0);
1761
+ // ragged, so the dissolve edge is a wash line and not a contour
1762
+ float lacy = noise(vWorldPosition.xz * 1.9) * 0.4 + noise(vWorldPosition.xz * 5.3) * 0.2;
1763
+ shoreDissolve = smoothstep(0.0, 0.18 + lacy * 0.12, column);
1764
+ }
1765
+
1699
1766
  // 🔥 Final fundamental solution: Apply depth mask
1700
- float finalOpacity = foamOpacity * depthMask;
1767
+ float finalOpacity = foamOpacity * depthMask * shoreDissolve;
1701
1768
 
1702
1769
  // ── seen from BELOW ─────────────────────────────────────────────────────
1703
1770
  // The underside of water is not the top with the colours swapped. Light can
@@ -2371,8 +2438,14 @@ const WAVE_WORLD_REF = 128;
2371
2438
  const AMPLITUDE_PER_WAVE_HEIGHT = REFERENCE_AMPLITUDE / REFERENCE_WAVE_HEIGHT;
2372
2439
  /** Cube-map reflection resolution (source: reflectionQuality = 256). */
2373
2440
  const REFLECTION_RESOLUTION = 256;
2374
- /** Planar-mirror target size cap (per side) half the drawing buffer, clamped. */
2375
- const MIRROR_PASS_MAX = 1024;
2441
+ /** Cube-map refresh floor while a planar mirror is on it is only the
2442
+ * off-screen fallback then, so six faces a second is already generous. */
2443
+ const MIRRORED_CUBE_INTERVAL = 2e3;
2444
+ /** Planar-mirror target: a THIRD of the drawing buffer, capped. A mirror is
2445
+ * seen through a rippled surface — the resolution nobody can tell apart from
2446
+ * full-res is far lower than the resolution that costs a frame. */
2447
+ const MIRROR_PASS_SCALE = 3;
2448
+ const MIRROR_PASS_MAX = 640;
2376
2449
  /** How far a wavelet's tilt slides the mirror sample, in UV per unit of normal lean. */
2377
2450
  const MIRROR_DISTORT = .06;
2378
2451
  /** Scene pre-pass (depth for absorption/foam + color grab for refraction):
@@ -2389,9 +2462,9 @@ const SCENE_PASS_MAX = 1024;
2389
2462
  const WATERLINE_CLIP_SLACK = .02;
2390
2463
  /** Fancy vertex density: the FBM displaces per vertex, so density scales with
2391
2464
  * extent (the source's formula degenerated to always-256; ours ramps to it). */
2392
- const FANCY_SEGMENTS_PER_M = 4;
2393
- const FANCY_SEGMENTS_MIN = 32;
2394
- const FANCY_SEGMENTS_MAX = 256;
2465
+ const FANCY_SEGMENTS_PER_M = 1.5;
2466
+ const FANCY_SEGMENTS_MIN = 24;
2467
+ const FANCY_SEGMENTS_MAX = 160;
2395
2468
  /** Simple quality: coarse enough to animate every vertex on the CPU. */
2396
2469
  const SIMPLE_SEGMENTS = 32;
2397
2470
  /** Bodies must rise this far above the waterline to 'exit' (no surface flicker). */
@@ -2461,6 +2534,7 @@ var Water3D = class Water3D extends Node3D {
2461
2534
  reflection: { default: true },
2462
2535
  reflectionInterval: { default: 1e3 },
2463
2536
  mirror: { default: false },
2537
+ mirrorInterval: { default: 33 },
2464
2538
  swellSteepness: { default: .35 },
2465
2539
  foam: { default: true },
2466
2540
  interaction: { default: true },
@@ -2512,6 +2586,12 @@ var Water3D = class Water3D extends Node3D {
2512
2586
  * render per frame, so it is off by default; a still lake earns it.
2513
2587
  */
2514
2588
  mirror = false;
2589
+ /**
2590
+ * Milliseconds between planar-mirror re-renders. A reflection seen through a
2591
+ * rippling surface does not need 60 Hz — 33 ms halves the pass's cost and
2592
+ * nobody can tell. 0 re-renders every frame.
2593
+ */
2594
+ mirrorInterval = 33;
2515
2595
  /** ms between reflection (and foam depth) re-renders. */
2516
2596
  reflectionInterval = 1e3;
2517
2597
  /** Depth-texture shoreline foam — rides the always-on fancy scene pass. */
@@ -2671,6 +2751,8 @@ var Water3D = class Water3D extends Node3D {
2671
2751
  z: 0
2672
2752
  };
2673
2753
  _bodies = [];
2754
+ /** Scratch for the side-pass cull (no per-frame allocation). */
2755
+ _passHidden = [];
2674
2756
  cubeTarget = null;
2675
2757
  cubeCamera = null;
2676
2758
  /** Reflection near plane (max half extent) — recreate the camera on resize. */
@@ -2681,6 +2763,7 @@ var Water3D = class Water3D extends Node3D {
2681
2763
  mirrorTarget = null;
2682
2764
  mirrorCamera = new PerspectiveCamera();
2683
2765
  mirrorMatrix = new Matrix4();
2766
+ lastMirrorAt = 0;
2684
2767
  _createObject3D() {
2685
2768
  return new Mesh();
2686
2769
  }
@@ -2736,7 +2819,8 @@ var Water3D = class Water3D extends Node3D {
2736
2819
  this.cubeCamera = new CubeCamera(near, 1e3, this.cubeTarget);
2737
2820
  this.lastReflectionAt = 0;
2738
2821
  }
2739
- if (this.lastReflectionAt === 0 || now - this.lastReflectionAt >= this.rp("reflectionInterval")) {
2822
+ const cubeInterval = this.mirror ? Math.max(this.rp("reflectionInterval"), MIRRORED_CUBE_INTERVAL) : this.rp("reflectionInterval");
2823
+ if (this.lastReflectionAt === 0 || now - this.lastReflectionAt >= cubeInterval) {
2740
2824
  this.lastReflectionAt = now;
2741
2825
  const center = worldTranslationOf(this);
2742
2826
  const cam = this.cubeCamera;
@@ -2753,8 +2837,8 @@ var Water3D = class Water3D extends Node3D {
2753
2837
  }
2754
2838
  if (this.mirror && u.uMirrorMap && u.uMirrorMatrix && u.uUseMirror) {
2755
2839
  ctx.gl.getDrawingBufferSize(drawingBufferScratch);
2756
- const mirrorW = Math.max(1, Math.min(Math.round(drawingBufferScratch.x / 2), MIRROR_PASS_MAX));
2757
- const mirrorH = Math.max(1, Math.min(Math.round(drawingBufferScratch.y / 2), MIRROR_PASS_MAX));
2840
+ const mirrorW = Math.max(1, Math.min(Math.round(drawingBufferScratch.x / MIRROR_PASS_SCALE), MIRROR_PASS_MAX));
2841
+ const mirrorH = Math.max(1, Math.min(Math.round(drawingBufferScratch.y / MIRROR_PASS_SCALE), MIRROR_PASS_MAX));
2758
2842
  if (this.mirrorTarget && (this.mirrorTarget.width !== mirrorW || this.mirrorTarget.height !== mirrorH)) {
2759
2843
  this.mirrorTarget.dispose();
2760
2844
  this.mirrorTarget = null;
@@ -2786,18 +2870,23 @@ var Water3D = class Water3D extends Node3D {
2786
2870
  this.mirrorMatrix.set(.5, 0, 0, .5, 0, .5, 0, .5, 0, 0, .5, .5, 0, 0, 0, 1);
2787
2871
  this.mirrorMatrix.multiply(mirrorCam.projectionMatrix);
2788
2872
  this.mirrorMatrix.multiply(mirrorCam.matrixWorldInverse);
2789
- const prevMirrorTarget = ctx.gl.getRenderTarget();
2790
- const prevMirrorClip = ctx.gl.clippingPlanes;
2791
- const wasMirrorVisible = mesh.visible;
2792
- mesh.visible = false;
2793
- mirrorClipPlane.constant = -(surfaceY - WATERLINE_CLIP_SLACK);
2794
- ctx.gl.clippingPlanes = mirrorClipPlanes;
2795
- ctx.gl.setRenderTarget(this.mirrorTarget);
2796
- ctx.gl.clear(true, true, false);
2797
- ctx.gl.render(ctx.scene, mirrorCam);
2798
- ctx.gl.setRenderTarget(prevMirrorTarget);
2799
- ctx.gl.clippingPlanes = prevMirrorClip;
2800
- mesh.visible = wasMirrorVisible;
2873
+ if (this.lastMirrorAt === 0 || now - this.lastMirrorAt >= this.rp("mirrorInterval")) {
2874
+ this.lastMirrorAt = now;
2875
+ const prevMirrorTarget = ctx.gl.getRenderTarget();
2876
+ const prevMirrorClip = ctx.gl.clippingPlanes;
2877
+ const wasMirrorVisible = mesh.visible;
2878
+ mesh.visible = false;
2879
+ mirrorClipPlane.constant = -(surfaceY - WATERLINE_CLIP_SLACK);
2880
+ ctx.gl.clippingPlanes = mirrorClipPlanes;
2881
+ ctx.gl.setRenderTarget(this.mirrorTarget);
2882
+ ctx.gl.clear(true, true, false);
2883
+ hideForWaterPass(ctx.scene, this._passHidden);
2884
+ ctx.gl.render(ctx.scene, mirrorCam);
2885
+ restoreForWaterPass(this._passHidden);
2886
+ ctx.gl.setRenderTarget(prevMirrorTarget);
2887
+ ctx.gl.clippingPlanes = prevMirrorClip;
2888
+ mesh.visible = wasMirrorVisible;
2889
+ }
2801
2890
  u.uMirrorMap.value = this.mirrorTarget.texture;
2802
2891
  u.uMirrorMatrix.value.copy(this.mirrorMatrix);
2803
2892
  u.uUseMirror.value = 1;
@@ -2840,7 +2929,9 @@ var Water3D = class Water3D extends Node3D {
2840
2929
  ctx.scene.overrideMaterial = depthOnlyMaterial;
2841
2930
  ctx.scene.background = null;
2842
2931
  ctx.gl.autoClear = false;
2932
+ hideForWaterPass(ctx.scene, this._passHidden);
2843
2933
  ctx.gl.render(ctx.scene, ctx.camera);
2934
+ restoreForWaterPass(this._passHidden);
2844
2935
  ctx.scene.overrideMaterial = prevOverride;
2845
2936
  ctx.scene.background = prevBackground;
2846
2937
  ctx.gl.setRenderTarget(prevTarget);
package/dist/gameplay.js CHANGED
@@ -1,2 +1,2 @@
1
- import { C as FollowCamera, D as Health, E as DamageOnContact, O as Collector, S as restartScene, T as phaseOf, _ as hitStop, a as Wander, b as GameFlow, c as Projectile, d as PathFollow, f as Oscillate, g as Cooldown, h as CameraShake, i as WaveSpawner, k as Chase, l as Pickup, m as Lifetime, n as registerGameplayBehaviors, o as Spawner, p as MoveTo, r as ZombieAI, s as ScoreKeeper, t as GAMEPLAY_BEHAVIORS, u as Patrol, v as screenFlash, w as DayNight, x as goToScene, y as Interactable } from "./gameplay-Dib5mNFD.js";
1
+ import { C as FollowCamera, D as Health, E as DamageOnContact, O as Collector, S as restartScene, T as phaseOf, _ as hitStop, a as Wander, b as GameFlow, c as Projectile, d as PathFollow, f as Oscillate, g as Cooldown, h as CameraShake, i as WaveSpawner, k as Chase, l as Pickup, m as Lifetime, n as registerGameplayBehaviors, o as Spawner, p as MoveTo, r as ZombieAI, s as ScoreKeeper, t as GAMEPLAY_BEHAVIORS, u as Patrol, v as screenFlash, w as DayNight, x as goToScene, y as Interactable } from "./gameplay-BJ5gXIks.js";
2
2
  export { CameraShake, Chase, Collector, Cooldown, DamageOnContact, DayNight, FollowCamera, GAMEPLAY_BEHAVIORS, GameFlow, Health, Interactable, Lifetime, MoveTo, Oscillate, PathFollow, Patrol, Pickup, Projectile, ScoreKeeper, Spawner, Wander, WaveSpawner, ZombieAI, goToScene, hitStop, phaseOf, registerGameplayBehaviors, restartScene, screenFlash };
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.22.0";
298
+ const VERSION = "0.23.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 };
@@ -1,8 +1,8 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
2
  import { t as IncantoError } from "./errors-BpWbnbb_.js";
3
- import { I as Node3D, L as validateCollider3D, M as CharacterBody3D, N as PhysicsBody3D, P as RigidBody3D, j as Area3D } from "./gameplay-Dib5mNFD.js";
3
+ import { I as Node3D, L as validateCollider3D, M as CharacterBody3D, N as PhysicsBody3D, P as RigidBody3D, j as Area3D } from "./gameplay-BJ5gXIks.js";
4
4
  import { n as registerDebugSource } from "./debug-draw-CZmOYjL2.js";
5
- import { T as Terrain3D, k as Joint3D } from "./register-CHgVdSbp.js";
5
+ import { T as Terrain3D, k as Joint3D } from "./register-CpJORtm4.js";
6
6
  import { Euler, Quaternion } from "three";
7
7
  //#region src/3d/physics/physics-3d.ts
8
8
  var physics_3d_exports = /* @__PURE__ */ __exportAll({
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-C3uiw80V.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-B-M1zune.js").then((n) => n.n)).createGame2D(o)))(opts);
159
+ const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-OyjhYUL3.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-DrcEgRup.js").then((n) => n.n)).createGame2D(o)))(opts);
160
160
  if (disposed) {
161
161
  next.dispose();
162
162
  return;
@@ -4,7 +4,7 @@ import { t as Rng } from "./rng-DP-SR7eg.js";
4
4
  import { i as getNodeSchema, l as registerNode } from "./registry-BVJ2HbCn.js";
5
5
  import { t as createNoise2D } from "./noise-CGUMx44x.js";
6
6
  import { i as applyParticlePreset, r as PARTICLE_PRESET_NAMES, t as ParticleSim } from "./particle-sim-Bw7hB93B.js";
7
- import { A as Water3D, B as colliderFootDrop, F as StaticBody3D, I as Node3D, M as CharacterBody3D, N as PhysicsBody3D, P as RigidBody3D, j as Area3D } from "./gameplay-Dib5mNFD.js";
7
+ import { A as Water3D, B as colliderFootDrop, F as StaticBody3D, I as Node3D, M as CharacterBody3D, N as PhysicsBody3D, P as RigidBody3D, j as Area3D } from "./gameplay-BJ5gXIks.js";
8
8
  import { n as splatWeights, t as buildHeightmap } from "./heightmap-CRK0M4jT.js";
9
9
  import { AdditiveBlending, AnimationClip, AnimationMixer, Box3, BoxGeometry, BufferAttribute, BufferGeometry, CanvasTexture, CapsuleGeometry, Color, ConeGeometry, CylinderGeometry, DataTexture, DirectionalLight, DoubleSide, DynamicDrawUsage, Euler, Group, IcosahedronGeometry, ImageBitmapLoader, InstancedBufferAttribute, InstancedMesh, LinearFilter, LoopOnce, LoopRepeat, Matrix4, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshPhysicalMaterial, MeshStandardMaterial, NearestFilter, NoBlending, NormalBlending, PerspectiveCamera, PlaneGeometry, PointLight, Points, PointsMaterial, Quaternion, QuaternionKeyframeTrack, RGBADepthPacking, RGBAFormat, RepeatWrapping, SRGBColorSpace, ShaderChunk, ShaderMaterial, SphereGeometry, Texture, TextureLoader, UniformsLib, UniformsUtils, Vector3, Vector4, VectorKeyframeTrack } from "three";
10
10
  import { clone } from "three/addons/utils/SkeletonUtils.js";
@@ -7100,7 +7100,11 @@ void main() {
7100
7100
  // ── edges ───────────────────────────────────────────────────────────────
7101
7101
  // the ribbon is built wider than the channel; what makes its outline is the
7102
7102
  // water running out, so bars and boulders cut it exactly like the ground does
7103
- float edge = smoothstep(0.0, 0.06, column) * (1.0 - smoothstep(0.84, 1.0, abs(across)));
7103
+ // The bank is where the water RUNS OUT, and it runs out over centimetres of
7104
+ // depth spread across metres of ground — a 6 cm ramp cut a hard line that
7105
+ // read as vinyl laid on the grass. Fade over a real wading depth instead, and
7106
+ // let the across-fade start earlier so the ribbon never ends on an edge.
7107
+ float edge = smoothstep(0.0, 0.22, column) * (1.0 - smoothstep(0.7, 1.0, abs(across)));
7104
7108
  float alpha = clamp(max(hide * uOpacity, fresnel * 0.85), 0.0, 1.0);
7105
7109
  alpha = clamp(max(alpha, foam * 0.95) * edge, 0.0, 1.0);
7106
7110
 
@@ -7465,9 +7469,6 @@ var River3D = class River3D extends Node3D {
7465
7469
  transparent: true,
7466
7470
  depthTest: true,
7467
7471
  depthWrite: false,
7468
- polygonOffset: true,
7469
- polygonOffsetFactor: -2,
7470
- polygonOffsetUnits: -4,
7471
7472
  side: DoubleSide
7472
7473
  });
7473
7474
  }
package/dist/test.js CHANGED
@@ -4,9 +4,9 @@ import { t as IncantoError } from "./errors-BpWbnbb_.js";
4
4
  import { t as auditScene } from "./audit-C6rMyict.js";
5
5
  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
- import { n as registerGameplayBehaviors } from "./gameplay-Dib5mNFD.js";
7
+ import { n as registerGameplayBehaviors } from "./gameplay-BJ5gXIks.js";
8
8
  import { t as registerNodes2D } from "./register-CvpSUU3O.js";
9
- import { t as registerNodes3D } from "./register-CHgVdSbp.js";
9
+ import { t as registerNodes3D } from "./register-CpJORtm4.js";
10
10
  import { t as registerNodesNet } from "./register-BFFE1Mh1.js";
11
11
  //#region src/test/index.ts
12
12
  /**
@@ -127,7 +127,7 @@ async function runScript(json, opts) {
127
127
  const { enablePhysics2D } = await import("./physics-2d-DiVFFlH3.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-DLPPRNu4.js").then((n) => n.r);
130
+ const { enablePhysics3D } = await import("./physics-3d-CpIB9C-F.js").then((n) => n.r);
131
131
  await enablePhysics3D(engine);
132
132
  }
133
133
  const failures = [];
@@ -232,7 +232,7 @@ async function createPlaySession(json, opts = {}) {
232
232
  const { enablePhysics2D } = await import("./physics-2d-DiVFFlH3.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-DLPPRNu4.js").then((n) => n.r);
235
+ const { enablePhysics3D } = await import("./physics-3d-CpIB9C-F.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-DAzNRDSQ.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-D-bWhSDj.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};