incanto 0.27.0 → 0.28.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.
@@ -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, F as PhysicsBody3D, H as colliderFootDrop, I as RigidBody3D, L as StaticBody3D, M as WaterCutout3D, N as Area3D, P as CharacterBody3D, R as Node3D } from "./gameplay-Ddk13pQ6.js";
7
+ import { A as Water3D, F as PhysicsBody3D, H as colliderFootDrop, I as RigidBody3D, L as StaticBody3D, M as WaterCutout3D, N as Area3D, P as CharacterBody3D, R as Node3D } from "./gameplay-DEG-TP7D.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";
@@ -2832,6 +2832,37 @@ function firstTerrain(node) {
2832
2832
  return null;
2833
2833
  }
2834
2834
  //#endregion
2835
+ //#region src/3d/water/wet-ground.ts
2836
+ function isWetSurface(node) {
2837
+ return typeof node?._waterYAt === "function";
2838
+ }
2839
+ /** Every water surface in the tree the node belongs to. */
2840
+ function collectWetSurfaces(from) {
2841
+ let root = from;
2842
+ while (root.parent) root = root.parent;
2843
+ const out = [];
2844
+ const walk = (node) => {
2845
+ if (node.visible !== false && isWetSurface(node)) out.push(node);
2846
+ for (const child of node.children) walk(child);
2847
+ };
2848
+ walk(root);
2849
+ return out;
2850
+ }
2851
+ /**
2852
+ * Is this spot under water deep enough to drown a plant?
2853
+ *
2854
+ * `margin` is the depth a blade tolerates — a wet edge is still a bank, and
2855
+ * culling everything the water so much as touches leaves a bald halo around
2856
+ * every stream.
2857
+ */
2858
+ function isUnderWater(surfaces, x, z, groundY, margin = .06) {
2859
+ for (let i = 0; i < surfaces.length; i++) {
2860
+ const y = surfaces[i]?._waterYAt(x, z);
2861
+ if (y !== null && y !== void 0 && y - groundY > margin) return true;
2862
+ }
2863
+ return false;
2864
+ }
2865
+ //#endregion
2835
2866
  //#region src/3d/nodes/flowers-3d.ts
2836
2867
  /** Named density presets, plants per m² — the vibe-coding dial (풍성하게 /
2837
2868
  * 듬성듬성 / 없게). Numbers are accepted too. */
@@ -2900,6 +2931,7 @@ var Flowers3D = class extends Node3D {
2900
2931
  clustering: { default: .6 },
2901
2932
  sway: { default: .5 },
2902
2933
  drape: { default: null },
2934
+ avoidWater: { default: true },
2903
2935
  terrain: { default: "" }
2904
2936
  };
2905
2937
  /** 'lush' | 'sparse' | 'none' | plants per m² (load-time check + budget). */
@@ -2927,6 +2959,12 @@ var Flowers3D = class extends Node3D {
2927
2959
  * draping entirely.
2928
2960
  */
2929
2961
  drape = null;
2962
+ /**
2963
+ * Keep plants out of standing and running water (default true) — a meadow a
2964
+ * stream runs through has a bank of flowers, not flowers in the current.
2965
+ * Set false for water lilies and marsh planting.
2966
+ */
2967
+ avoidWater = true;
2930
2968
  /** Drape target: a node path to the Terrain3D. Empty = auto-find the first
2931
2969
  * Terrain3D in the tree (the zero-config default when `drape` is on). */
2932
2970
  terrain = "";
@@ -3026,13 +3064,20 @@ var Flowers3D = class extends Node3D {
3026
3064
  const density = resolveFlowerDensity(this.density);
3027
3065
  const count = Math.min(Math.floor((this.area[0] ?? 0) * (this.area[1] ?? 0) * density), MAX_PLANTS);
3028
3066
  if (count <= 0) return;
3029
- const placements = placeFlowerPlants({
3067
+ let placements = placeFlowerPlants({
3030
3068
  seed: this.seed,
3031
3069
  areaX: this.area[0] ?? 0,
3032
3070
  areaZ: this.area[1] ?? 0,
3033
3071
  count,
3034
3072
  clustering: this.clustering
3035
3073
  });
3074
+ if (this.avoidWater) {
3075
+ const surfaces = collectWetSurfaces(this);
3076
+ if (surfaces.length > 0) {
3077
+ const [ox, oy, oz] = worldXZY(this);
3078
+ placements = placements.filter((p) => !isUnderWater(surfaces, p.x + ox, p.z + oz, this.bedY(p.x, p.z) + oy));
3079
+ }
3080
+ }
3036
3081
  const varieties = this.varieties.length > 0 ? this.varieties : FLOWER_VARIETIES;
3037
3082
  const buckets = varieties.map(() => []);
3038
3083
  for (const p of placements) buckets[Math.min(Math.floor(p.variety01 * varieties.length), varieties.length - 1)].push(p);
@@ -4287,6 +4332,7 @@ var Foliage3D = class Foliage3D extends Node3D {
4287
4332
  flowers: { default: 0 },
4288
4333
  seed: { default: 1 },
4289
4334
  drape: { default: null },
4335
+ avoidWater: { default: true },
4290
4336
  terrain: { default: "" },
4291
4337
  renderOrder: { default: 2 }
4292
4338
  };
@@ -4353,6 +4399,14 @@ var Foliage3D = class Foliage3D extends Node3D {
4353
4399
  * a terrain appears), false disables draping entirely.
4354
4400
  */
4355
4401
  drape = null;
4402
+ /**
4403
+ * Keep blades out of standing and running water (default true). Grass does
4404
+ * not grow in a stream: any instance whose ground sits under a `Water3D` or
4405
+ * `River3D` surface is dropped, which is what stops a creek that cut its bed
4406
+ * through a meadow from filling with waving blades. Set false for reeds and
4407
+ * paddy fields, where the plant IS in the water.
4408
+ */
4409
+ avoidWater = true;
4356
4410
  /** Drape target: a node path to the Terrain3D. Empty = auto-find the first
4357
4411
  * Terrain3D in the tree (the zero-config default when `drape` is on). */
4358
4412
  terrain = "";
@@ -4582,6 +4636,22 @@ var Foliage3D = class Foliage3D extends Node3D {
4582
4636
  * fraction of instances into a SECOND InstancedMesh of 5-vertex flower
4583
4637
  * heads (white/yellow/violet per instance).
4584
4638
  */
4639
+ /**
4640
+ * Drop the instances standing in water. The ground each blade drapes onto is
4641
+ * already known here, so the test is one question per candidate — and only
4642
+ * the ones a water surface actually covers pay for it.
4643
+ */
4644
+ dryOnly(placements) {
4645
+ if (!this.avoidWater) return placements;
4646
+ const surfaces = collectWetSurfaces(this);
4647
+ if (surfaces.length === 0) return placements;
4648
+ const [ox, , oz] = worldXZY(this);
4649
+ return placements.filter((p) => !isUnderWater(surfaces, p.x + ox, p.z + oz, this.bedY(p.x, p.z) + this.worldY()));
4650
+ }
4651
+ /** This field's own world height (the bed sampler works in local Y). */
4652
+ worldY() {
4653
+ return worldXZY(this)[1];
4654
+ }
4585
4655
  buildMeshField(count) {
4586
4656
  const placements = placeGrass({
4587
4657
  seed: this.seed,
@@ -4590,7 +4660,7 @@ var Foliage3D = class Foliage3D extends Node3D {
4590
4660
  count,
4591
4661
  density: this.density * MESH_DENSITY_MULT
4592
4662
  });
4593
- const kept = this.coverage >= 1 ? placements : placements.filter((p) => coverageNoiseAt(p.x, p.z, this.seed) <= this.coverage);
4663
+ const kept = this.dryOnly(this.coverage >= 1 ? placements : placements.filter((p) => coverageNoiseAt(p.x, p.z, this.seed) <= this.coverage));
4594
4664
  const flowerCount = this.flowers > 0 ? Math.floor(kept.length * this.flowers) : 0;
4595
4665
  const flowerSlots = /* @__PURE__ */ new Set();
4596
4666
  for (let k = 0; k < flowerCount; k++) flowerSlots.add(Math.floor((k + .5) * kept.length / flowerCount));
@@ -4700,7 +4770,7 @@ var Foliage3D = class Foliage3D extends Node3D {
4700
4770
  count,
4701
4771
  density: this.density * TUFT_DENSITY_MULT
4702
4772
  });
4703
- const kept = this.coverage >= 1 ? placements : placements.filter((p) => coverageNoiseAt(p.x, p.z, this.seed) <= this.coverage);
4773
+ const kept = this.dryOnly(this.coverage >= 1 ? placements : placements.filter((p) => coverageNoiseAt(p.x, p.z, this.seed) <= this.coverage));
4704
4774
  this.tuftTime = { value: this.time };
4705
4775
  this.tuftStrength = { value: this.sway * TUFT_SWAY_TO_WIND };
4706
4776
  const material = new MeshStandardMaterial({
@@ -4803,23 +4873,32 @@ var Foliage3D = class Foliage3D extends Node3D {
4803
4873
  roughness: 1
4804
4874
  });
4805
4875
  const mesh = new InstancedMesh(buildBladeGeometry(BLADE_WIDTH[this.kind] ?? .08), material, Math.max(count, 1));
4806
- mesh.count = count;
4807
4876
  mesh.receiveShadow = true;
4808
4877
  const rng = new Rng(this.seed);
4809
4878
  const halfX = (this.area[0] ?? 0) / 2;
4810
4879
  const halfZ = (this.area[1] ?? 0) / 2;
4811
4880
  const colorA = colorScratchA$1.set(this.colorA);
4812
4881
  const colorB = colorScratchB$1.set(this.colorB);
4882
+ const wet = this.avoidWater ? collectWetSurfaces(this) : [];
4883
+ const [ox, oy, oz] = worldXZY(this);
4884
+ let placed = 0;
4813
4885
  for (let i = 0; i < count; i++) {
4814
4886
  const sx = rng.range(-halfX, halfX);
4815
4887
  const sz = rng.range(-halfZ, halfZ);
4816
- positionScratch$1.set(sx, this.bedY(sx, sz), sz);
4817
- quaternionScratch$1.setFromAxisAngle(Y_AXIS$1, rng.range(0, Math.PI * 2));
4818
- scaleScratch$2.set(1, this.height * rng.range(HEIGHT_JITTER$1[0], HEIGHT_JITTER$1[1]), 1);
4888
+ const rotY = rng.range(0, Math.PI * 2);
4889
+ const jitter = rng.range(HEIGHT_JITTER$1[0], HEIGHT_JITTER$1[1]);
4890
+ const tint = rng.next();
4891
+ const bed = this.bedY(sx, sz);
4892
+ if (wet.length > 0 && isUnderWater(wet, sx + ox, sz + oz, bed + oy)) continue;
4893
+ positionScratch$1.set(sx, bed, sz);
4894
+ quaternionScratch$1.setFromAxisAngle(Y_AXIS$1, rotY);
4895
+ scaleScratch$2.set(1, this.height * jitter, 1);
4819
4896
  matrixScratch$1.compose(positionScratch$1, quaternionScratch$1, scaleScratch$2);
4820
- mesh.setMatrixAt(i, matrixScratch$1);
4821
- mesh.setColorAt(i, colorScratchC$1.copy(colorA).lerp(colorB, rng.next()));
4897
+ mesh.setMatrixAt(placed, matrixScratch$1);
4898
+ mesh.setColorAt(placed, colorScratchC$1.copy(colorA).lerp(colorB, tint));
4899
+ placed++;
4822
4900
  }
4901
+ mesh.count = placed;
4823
4902
  mesh.instanceMatrix.needsUpdate = true;
4824
4903
  if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true;
4825
4904
  this.meshes = [mesh];
@@ -6452,6 +6531,81 @@ function softSprite() {
6452
6531
  }
6453
6532
  //#endregion
6454
6533
  //#region src/3d/water/river.ts
6534
+ /**
6535
+ * Self-carved bed. Sized off the WATER COLUMN, never off the width: a channel's
6536
+ * banks are as steep as banks are, and a taper scaled to width turns a wide
6537
+ * river into a shallow saucer the water floods far past its edge.
6538
+ */
6539
+ /** Trench depth, in water columns. */
6540
+ const CARVE_DEPTH = 2.2;
6541
+ /** Bank blend beyond the flat bed, in water columns. */
6542
+ const CARVE_BANK = 2;
6543
+ /** Where the waterline crosses that blend — smoothstep(t) = 1 − 1/CARVE_DEPTH.
6544
+ * Knowing it is what lets the floor be narrowed so the WATER ends up the
6545
+ * authored width instead of the bed doing so. */
6546
+ const CARVE_WATERLINE_T = .52;
6547
+ /** Never cut the floor away entirely, however steep the bank works out. */
6548
+ const CARVE_FLOOR_MIN = .3;
6549
+ /** A trench thinner than this many terrain cells cannot survive the grid it is
6550
+ * sampled on — it smooths away to nothing and the creek is back on raw ground.
6551
+ * Widening it is the honest failure: better a bed too wide than no bed. */
6552
+ const CARVE_MIN_CELLS = 1.5;
6553
+ /** Deepest the bed may be cut, in water columns — the budget for digging
6554
+ * THROUGH a rise so the water keeps flowing, before it reads as a canyon. */
6555
+ const CARVE_MAX_DEPTH = 7;
6556
+ /** The fall the carved floor keeps even where the ground does not (m per m). */
6557
+ const CARVE_MIN_GRADE = .004;
6558
+ /**
6559
+ * The trench a river digs for itself, as {@link ChannelSpec}s for Terrain3D.
6560
+ *
6561
+ * Shared on purpose: `River3D` cuts this at load, and anything that has to
6562
+ * PLACE things against the result — a scene generator putting a player, a
6563
+ * bridge and a boulder field on the ground — computes the identical cut
6564
+ * instead of approximating it. A generator that guesses differently spawns the
6565
+ * player inside a hill.
6566
+ *
6567
+ * The floor only ever FALLS. Water does not climb, so a bed that climbs is a
6568
+ * river that stops and buries itself; carrying the running minimum downstream
6569
+ * digs through a rise instead, and the cap keeps that from turning a hill into
6570
+ * a canyon.
6571
+ */
6572
+ function riverCarveChannels(opts) {
6573
+ if (opts.path.length < 2) return [];
6574
+ const line = resamplePath(opts.path, Math.max(opts.cell, opts.depth));
6575
+ if (line.length < 2) return [];
6576
+ const total = line[line.length - 1].along || 1;
6577
+ const ground = line.map((s) => opts.groundAt(s.x, s.z));
6578
+ const baseCut = opts.depth * CARVE_DEPTH;
6579
+ const maxCut = opts.depth * CARVE_MAX_DEPTH;
6580
+ const floor = new Array(line.length);
6581
+ for (let i = 0; i < line.length; i++) {
6582
+ const wanted = ground[i] - baseCut;
6583
+ if (i === 0) {
6584
+ floor[i] = wanted;
6585
+ continue;
6586
+ }
6587
+ const run = line[i].along - line[i - 1].along;
6588
+ const carried = floor[i - 1] - run * CARVE_MIN_GRADE;
6589
+ floor[i] = Math.max(Math.min(wanted, carried), ground[i] - maxCut);
6590
+ }
6591
+ const out = [];
6592
+ for (let i = 1; i < line.length; i++) {
6593
+ const a = line[i - 1];
6594
+ const b = line[i];
6595
+ const cut = Math.max((ground[i - 1] + ground[i]) / 2 - (floor[i - 1] + floor[i]) / 2, 0);
6596
+ if (cut <= .001) continue;
6597
+ const half = widthAlong(opts.widths, a.along / total) / 2;
6598
+ const bank = Math.max(opts.depth * CARVE_BANK, opts.cell * CARVE_MIN_CELLS);
6599
+ const floorHalf = Math.max(half - bank * CARVE_WATERLINE_T, half * CARVE_FLOOR_MIN, opts.cell * .5);
6600
+ out.push({
6601
+ path: [[a.x, a.z], [b.x, b.z]],
6602
+ width: floorHalf * 2,
6603
+ depth: cut,
6604
+ taper: bank
6605
+ });
6606
+ }
6607
+ return out;
6608
+ }
6455
6609
  /** Dense Catmull-Rom taps per control segment before arc-length resampling. */
6456
6610
  const SPLINE_TAPS = 24;
6457
6611
  /** Box-filter half-window (samples) that irons kinks out of the bed profile. */
@@ -7327,30 +7481,6 @@ const METERS_PER_ACROSS_SEGMENT = 1.5;
7327
7481
  * flow over it, wide enough that terrain grain does not fizz the whole river. */
7328
7482
  const COLUMN_BLUR_PER_HALF_WIDTH = .35;
7329
7483
  const COLUMN_BLUR_MAX = 1.2;
7330
- /**
7331
- * Self-carved bed. The cut is sized off the WATER COLUMN, not off the width:
7332
- * a channel's banks are as steep as its banks are, and a taper scaled to width
7333
- * turns a wide river into a shallow saucer the water floods far past its edge.
7334
- *
7335
- * `depth` is the trench in water columns; `bank` the smoothstep blend beyond
7336
- * the flat bed, also in columns. The waterline crosses that blend at
7337
- * {@link CARVE_WATERLINE_T} of its width (smoothstep(t) = 1 − 1/depth), which
7338
- * is what lets the floor be narrowed so the WATER ends up the authored width.
7339
- */
7340
- const CARVE_DEPTH = 2.2;
7341
- const CARVE_BANK = 2;
7342
- const CARVE_WATERLINE_T = .52;
7343
- /** Never cut the floor away entirely, however steep the bank works out. */
7344
- const CARVE_FLOOR_MIN = .3;
7345
- /** A trench thinner than this many terrain cells cannot survive the grid it is
7346
- * sampled on — it smooths away to nothing and the creek is back on raw ground.
7347
- * Widening it is the honest failure: better a bed too wide than no bed. */
7348
- const CARVE_MIN_CELLS = 1.5;
7349
- /** Deepest the bed may be cut, in water columns — the budget for digging
7350
- * THROUGH a rise so the water keeps flowing, before it would read as a canyon. */
7351
- const CARVE_MAX_DEPTH = 7;
7352
- /** The fall the carved floor keeps even where the ground does not (m per m). */
7353
- const CARVE_MIN_GRADE = .004;
7354
7484
  /** Rocks the shader can carry at once (the nearest ones win). */
7355
7485
  const ROCK_SLOTS = 8;
7356
7486
  /** How often the tree is re-scanned for things standing in the water (s). */
@@ -7571,6 +7701,17 @@ var River3D = class River3D extends Node3D {
7571
7701
  this.syncRocks(u, ctx.camera.getWorldPosition(rockCamScratch));
7572
7702
  }
7573
7703
  /**
7704
+ * @internal Water surface height over a world point, or null where this
7705
+ * river does not run — the question scattered vegetation asks before it
7706
+ * plants a blade (see {@link WetSurface}).
7707
+ */
7708
+ _waterYAt(x, z) {
7709
+ if (this.rings.length === 0) return null;
7710
+ const [wx, wy, wz] = this.world;
7711
+ const hit = projectToRiver(this.rings, x - wx, z - wz);
7712
+ return hit?.inside ? hit.surfaceY + wy : null;
7713
+ }
7714
+ /**
7574
7715
  * Where a WORLD point sits in the channel — the query gameplay scripts run
7575
7716
  * (steer a raft, drown a torch, decide a ford is too fast to cross). `null`
7576
7717
  * until the river has been built.
@@ -7638,46 +7779,14 @@ var River3D = class River3D extends Node3D {
7638
7779
  terrain._setExternalChannel(this, null);
7639
7780
  const [wx, , wz] = worldXZY(this);
7640
7781
  const [tx, , tz] = worldXZY(terrain);
7641
- const widths = this.widthProfile();
7642
7782
  const hm = terrain._heightmap();
7643
- const cell = (terrain.size[0] ?? 1) / Math.max(1, hm.segsX);
7644
- const line = resamplePath(this.path.map((p) => [(p[0] ?? 0) + wx - tx, (p[1] ?? 0) + wz - tz]), Math.max(cell, this.depth));
7645
- if (line.length < 2) {
7646
- terrain._setExternalChannel(this, null);
7647
- return;
7648
- }
7649
- const total = line[line.length - 1].along || 1;
7650
- const ground = line.map((s) => terrain._heightmap().heightAt(s.x, s.z));
7651
- const baseCut = this.depth * CARVE_DEPTH;
7652
- const maxCut = this.depth * CARVE_MAX_DEPTH;
7653
- const floor = new Array(line.length);
7654
- for (let i = 0; i < line.length; i++) {
7655
- const wanted = ground[i] - baseCut;
7656
- if (i === 0) {
7657
- floor[i] = wanted;
7658
- continue;
7659
- }
7660
- const run = line[i].along - line[i - 1].along;
7661
- const carried = floor[i - 1] - run * CARVE_MIN_GRADE;
7662
- floor[i] = Math.max(Math.min(wanted, carried), ground[i] - maxCut);
7663
- }
7664
- const specs = [];
7665
- for (let i = 1; i < line.length; i++) {
7666
- const a = line[i - 1];
7667
- const b = line[i];
7668
- const cut = Math.max((ground[i - 1] + ground[i]) / 2 - (floor[i - 1] + floor[i]) / 2, 0);
7669
- if (cut <= .001) continue;
7670
- const half = widthAlong(widths, a.along / total) / 2;
7671
- const bank = Math.max(this.depth * CARVE_BANK, cell * CARVE_MIN_CELLS);
7672
- const floorHalf = Math.max(half - bank * CARVE_WATERLINE_T, half * CARVE_FLOOR_MIN, cell * .5);
7673
- specs.push({
7674
- path: [[a.x, a.z], [b.x, b.z]],
7675
- width: floorHalf * 2,
7676
- depth: cut,
7677
- taper: bank
7678
- });
7679
- }
7680
- terrain._setExternalChannel(this, specs);
7783
+ terrain._setExternalChannel(this, riverCarveChannels({
7784
+ path: this.path.map((p) => [(p[0] ?? 0) + wx - tx, (p[1] ?? 0) + wz - tz]),
7785
+ widths: this.widthProfile(),
7786
+ depth: this.depth,
7787
+ cell: (terrain.size[0] ?? 1) / Math.max(1, hm.segsX),
7788
+ groundAt: (x, z) => hm.heightAt(x, z)
7789
+ }));
7681
7790
  }
7682
7791
  /** Resolve the drape terrain; an explicit path that misses is a hard error. */
7683
7792
  resolveTerrain() {
@@ -11292,4 +11401,4 @@ function registerNodes3D() {
11292
11401
  registerNode(CharacterBody3D);
11293
11402
  }
11294
11403
  //#endregion
11295
- export { QUARTER_PITCH as A, BoneAttachment3D as C, TERRAIN_THEMES as D, DEFAULT_TERRAIN_TEXTURE_BASE as E, keyboardIntensity as M, movementState as N, terrainThemeLayers as O, rigPose as P, BoneLookAt3D as S, Terrain3D as T, Flowers3D as _, Trail3D as a, CharacterController3D as b, Particles3D as c, DirectionalLight3D as d, OmniLight3D as f, DENSITY_PRESETS as g, Foliage3D as h, Tree3D as i, cameraRelative as j, Joint3D as k, ModelInstance3D as l, MeshInstance3D as m, VOXEL_PALETTE as n, River3D as o, InstancedMesh3D as p, VoxelGrid3D as r, traceDownhillPath as s, registerNodes3D as t, LoftMesh3D as u, resolveFlowerDensity as v, Billboard3D as w, Camera3D as x, FLOWER_VARIETIES as y };
11404
+ export { Joint3D as A, BoneLookAt3D as C, DEFAULT_TERRAIN_TEXTURE_BASE as D, Terrain3D as E, rigPose as F, cameraRelative as M, keyboardIntensity as N, TERRAIN_THEMES as O, movementState as P, Camera3D as S, Billboard3D as T, DENSITY_PRESETS as _, Trail3D as a, FLOWER_VARIETIES as b, traceDownhillPath as c, LoftMesh3D as d, DirectionalLight3D as f, Foliage3D as g, MeshInstance3D as h, Tree3D as i, QUARTER_PITCH as j, terrainThemeLayers as k, Particles3D as l, InstancedMesh3D as m, VOXEL_PALETTE as n, River3D as o, OmniLight3D as p, VoxelGrid3D as r, riverCarveChannels as s, registerNodes3D as t, ModelInstance3D as u, Flowers3D as v, BoneAttachment3D as w, CharacterController3D as x, resolveFlowerDensity as y };
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-Ddk13pQ6.js";
7
+ import { n as registerGameplayBehaviors } from "./gameplay-DEG-TP7D.js";
8
8
  import { t as registerNodes2D } from "./register-CvpSUU3O.js";
9
- import { t as registerNodes3D } from "./register-DcHXS1MA.js";
9
+ import { t as registerNodes3D } from "./register-6R75AC7-.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-4mGzOZ2J.js").then((n) => n.r);
130
+ const { enablePhysics3D } = await import("./physics-3d--y5clE2j.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-4mGzOZ2J.js").then((n) => n.r);
235
+ const { enablePhysics3D } = await import("./physics-3d--y5clE2j.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-BrneVqN0.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-D6RQgROR.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};