incanto 0.17.3 → 0.19.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/3d.d.ts +15 -1
- package/dist/3d.js +4 -4
- package/dist/{create-game-BLcN2mt4.js → create-game-Ct6RC4LF.js} +2 -2
- package/dist/env.js +1 -1
- package/dist/{heightmap-CroQPEER.js → heightmap-DgX-Opav.js} +5 -2
- package/dist/index.js +1 -1
- package/dist/{physics-3d-CO4HLs-q.js → physics-3d-JPdedRAB.js} +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-DCbeSC2t.js → register-Cv5GNiVo.js} +86 -17
- package/dist/test.js +3 -3
- package/editor/assets/{agent8-GDZPslB-.js → agent8-CcfBcssq.js} +1 -1
- package/editor/assets/{index-CLqRCrOl.js → index-B7gj1VII.js} +54 -16
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +3 -0
- package/skills/incanto-environment.md +33 -1
- package/skills/incanto-node-reference.md +1 -0
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/village-quest-3d/package.json +1 -1
package/dist/3d.d.ts
CHANGED
|
@@ -1552,6 +1552,7 @@ interface BasinSpec {
|
|
|
1552
1552
|
x: number;
|
|
1553
1553
|
z: number;
|
|
1554
1554
|
radius: number;
|
|
1555
|
+
/** > 0 carves a bowl; < 0 RAISES a smooth dome mound of that height. */
|
|
1555
1556
|
depth: number;
|
|
1556
1557
|
}
|
|
1557
1558
|
interface HeightmapOptions {
|
|
@@ -1705,8 +1706,21 @@ declare class Terrain3D extends Node3D {
|
|
|
1705
1706
|
/** CDN base for theme textures: `<base>/<name>.png` (+`_normal`). */
|
|
1706
1707
|
textureBase: string;
|
|
1707
1708
|
/** Lake/pond bowls carved into the surface — smooth radial depressions the
|
|
1708
|
-
* collider + heightAt + dressing all see (place a Water3D in each).
|
|
1709
|
+
* collider + heightAt + dressing all see (place a Water3D in each).
|
|
1710
|
+
* NEGATIVE depth raises a smooth dome MOUND instead (a hill, an islet). */
|
|
1709
1711
|
basins: BasinSpec[];
|
|
1712
|
+
/**
|
|
1713
|
+
* WET SAND band: `{ y, band? }` darkens + glosses the splat in a noisy,
|
|
1714
|
+
* breathing band just above height `y` (a waterline) — the trace of the
|
|
1715
|
+
* last swash runup. `band` is the max height above `y` that reads wet
|
|
1716
|
+
* (default 1.1 m). null (default) = off.
|
|
1717
|
+
*/
|
|
1718
|
+
wetline: JsonObject | null;
|
|
1719
|
+
private splatUniforms;
|
|
1720
|
+
/** Per-frame wetline clock + prop write — lives in update() so a `static`
|
|
1721
|
+
* subtree keeps the wet edge breathing (the frozen-sync lesson). */
|
|
1722
|
+
private wetTime;
|
|
1723
|
+
override update(dt: number): void;
|
|
1710
1724
|
/** Loader hook: bad themes/layers/grids fail at LOAD, not at render. */
|
|
1711
1725
|
static validateJson(node: Node): void;
|
|
1712
1726
|
private heightmap;
|
package/dist/3d.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
2
|
-
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-
|
|
3
|
-
import { A as Joint3D, B as keyboardIntensity, C as BoneLookAt3D, D as DEFAULT_TERRAIN_TEXTURE_BASE, E as Terrain3D, F as StaticBody3D, H as rigPose, I as Node3D, M as CharacterBody3D, N as PhysicsBody3D, O as TERRAIN_THEMES, P as RigidBody3D, R as QUARTER_PITCH, S as Camera3D, T as Billboard3D, V as movementState, _ as DENSITY_PRESETS, a as VOXEL_PALETTE, b as FLOWER_VARIETIES, c as Trail3D, d as LoftMesh3D, f as DirectionalLight3D, g as Foliage3D, h as MeshInstance3D, i as WATER_MAX_RIPPLES, j as Area3D, k as terrainThemeLayers, l as Particles3D, m as InstancedMesh3D, n as Water3D, o as VoxelGrid3D, p as OmniLight3D, s as Tree3D, t as registerNodes3D, u as ModelInstance3D, v as Flowers3D, w as BoneAttachment3D, x as CharacterController3D, y as resolveFlowerDensity, z as cameraRelative } from "./register-
|
|
4
|
-
import { n as splatWeights, t as buildHeightmap } from "./heightmap-
|
|
5
|
-
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-
|
|
2
|
+
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-Ct6RC4LF.js";
|
|
3
|
+
import { A as Joint3D, B as keyboardIntensity, C as BoneLookAt3D, D as DEFAULT_TERRAIN_TEXTURE_BASE, E as Terrain3D, F as StaticBody3D, H as rigPose, I as Node3D, M as CharacterBody3D, N as PhysicsBody3D, O as TERRAIN_THEMES, P as RigidBody3D, R as QUARTER_PITCH, S as Camera3D, T as Billboard3D, V as movementState, _ as DENSITY_PRESETS, a as VOXEL_PALETTE, b as FLOWER_VARIETIES, c as Trail3D, d as LoftMesh3D, f as DirectionalLight3D, g as Foliage3D, h as MeshInstance3D, i as WATER_MAX_RIPPLES, j as Area3D, k as terrainThemeLayers, l as Particles3D, m as InstancedMesh3D, n as Water3D, o as VoxelGrid3D, p as OmniLight3D, s as Tree3D, t as registerNodes3D, u as ModelInstance3D, v as Flowers3D, w as BoneAttachment3D, x as CharacterController3D, y as resolveFlowerDensity, z as cameraRelative } from "./register-Cv5GNiVo.js";
|
|
4
|
+
import { n as splatWeights, t as buildHeightmap } from "./heightmap-DgX-Opav.js";
|
|
5
|
+
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-JPdedRAB.js";
|
|
6
6
|
//#region src/3d/environment-runtime.ts
|
|
7
7
|
/**
|
|
8
8
|
* Live environment editing — the renderer re-applies `scene.environment`
|
|
@@ -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-sSqrUcnz.js";
|
|
7
7
|
import { t as debugSources } from "./debug-draw-CZmOYjL2.js";
|
|
8
|
-
import { I as Node3D, N as PhysicsBody3D, S as Camera3D, f as DirectionalLight3D, r as createCausticsQuad, t as registerNodes3D, u as ModelInstance3D } from "./register-
|
|
9
|
-
import { n as enablePhysics3D } from "./physics-3d-
|
|
8
|
+
import { I as Node3D, N as PhysicsBody3D, S as Camera3D, f as DirectionalLight3D, r as createCausticsQuad, t as registerNodes3D, u as ModelInstance3D } from "./register-Cv5GNiVo.js";
|
|
9
|
+
import { n as enablePhysics3D } from "./physics-3d-JPdedRAB.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";
|
package/dist/env.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
2
2
|
import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
3
3
|
import { t as createNoise2D } from "./noise-CGUMx44x.js";
|
|
4
|
-
import { t as buildHeightmap } from "./heightmap-
|
|
4
|
+
import { t as buildHeightmap } from "./heightmap-DgX-Opav.js";
|
|
5
5
|
//#region src/env/round.ts
|
|
6
6
|
/** 2-decimal rounding — keeps generated JSON readable without hurting determinism. */
|
|
7
7
|
function round2(value) {
|
|
@@ -64,14 +64,17 @@ function buildHeightmap(opts) {
|
|
|
64
64
|
if (Math.abs(final - flatHeight) < FLAT_RANGE) final = flatHeight;
|
|
65
65
|
if (basins.length > 0) {
|
|
66
66
|
let carve = 0;
|
|
67
|
+
let lift = 0;
|
|
67
68
|
for (const b of basins) {
|
|
68
69
|
const d = Math.hypot(x - b.cx, z - b.cz);
|
|
69
70
|
if (d < b.radius) {
|
|
70
71
|
const t = d / b.radius;
|
|
71
|
-
|
|
72
|
+
const s = 1 - t * t * (3 - 2 * t);
|
|
73
|
+
if (b.depth >= 0) carve = Math.max(carve, b.depth * s);
|
|
74
|
+
else lift = Math.max(lift, -b.depth * s);
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
|
-
final
|
|
77
|
+
final += lift - carve;
|
|
75
78
|
}
|
|
76
79
|
return final;
|
|
77
80
|
};
|
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.
|
|
298
|
+
const VERSION = "0.19.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,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 Joint3D, E as Terrain3D, I as Node3D, L as validateCollider3D, M as CharacterBody3D, N as PhysicsBody3D, P as RigidBody3D, j as Area3D } from "./register-
|
|
4
|
+
import { A as Joint3D, E as Terrain3D, I as Node3D, L as validateCollider3D, M as CharacterBody3D, N as PhysicsBody3D, P as RigidBody3D, j as Area3D } from "./register-Cv5GNiVo.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({
|
package/dist/react.js
CHANGED
|
@@ -156,7 +156,7 @@ function IncantoCanvas(props) {
|
|
|
156
156
|
pointer: latest.pointer,
|
|
157
157
|
...keyboard !== void 0 ? { keyboard } : {}
|
|
158
158
|
};
|
|
159
|
-
const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-
|
|
159
|
+
const next = await (_gameFactory ?? (mode === "3d" ? async (o) => (await import("./create-game-Ct6RC4LF.js").then((n) => n.n)).createGame3D(o) : async (o) => (await import("./create-game-Ct86zczq.js").then((n) => n.n)).createGame2D(o)))(opts);
|
|
160
160
|
if (disposed) {
|
|
161
161
|
next.dispose();
|
|
162
162
|
return;
|
|
@@ -5,7 +5,7 @@ import { t as Rng } from "./rng-DP-SR7eg.js";
|
|
|
5
5
|
import { i as getNodeSchema, l as registerNode } from "./registry-BVJ2HbCn.js";
|
|
6
6
|
import { t as createNoise2D } from "./noise-CGUMx44x.js";
|
|
7
7
|
import { i as applyParticlePreset, o as effectiveOrder, r as PARTICLE_PRESET_NAMES, t as ParticleSim } from "./particle-sim-CyUU7HVU.js";
|
|
8
|
-
import { n as splatWeights, t as buildHeightmap } from "./heightmap-
|
|
8
|
+
import { n as splatWeights, t as buildHeightmap } from "./heightmap-DgX-Opav.js";
|
|
9
9
|
import { AdditiveBlending, AnimationClip, AnimationMixer, Box3, BoxGeometry, BufferAttribute, BufferGeometry, CanvasTexture, CapsuleGeometry, Color, ConeGeometry, CubeCamera, CylinderGeometry, DataTexture, DepthTexture, DirectionalLight, DoubleSide, DynamicDrawUsage, Euler, FloatType, Frustum, Group, HalfFloatType, IcosahedronGeometry, ImageBitmapLoader, InstancedBufferAttribute, InstancedMesh, LinearFilter, LinearMipmapLinearFilter, LoopOnce, LoopRepeat, MathUtils, Matrix4, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshPhysicalMaterial, MeshStandardMaterial, NearestFilter, NoBlending, NormalBlending, Object3D, PerspectiveCamera, Plane, PlaneGeometry, PointLight, Points, PointsMaterial, Quaternion, QuaternionKeyframeTrack, RGBADepthPacking, RGBAFormat, RepeatWrapping, SRGBColorSpace, ShaderChunk, ShaderMaterial, Sphere, SphereGeometry, Texture, TextureLoader, UniformsLib, UniformsUtils, Vector2, Vector3, Vector4, VectorKeyframeTrack, WebGLCubeRenderTarget, WebGLRenderTarget } from "three";
|
|
10
10
|
import { clone } from "three/addons/utils/SkeletonUtils.js";
|
|
11
11
|
//#region src/3d/camera-rig.ts
|
|
@@ -546,6 +546,13 @@ varying vec3 vWorldPosition;
|
|
|
546
546
|
varying vec2 vUvSplat;
|
|
547
547
|
|
|
548
548
|
// Noise functions - for naturalizing tiling patterns
|
|
549
|
+
// incanto wetline: WET SAND — a darkened, slightly glossy band hugging the
|
|
550
|
+
// waterline (uWetlineY), its upper edge noisy and breathing with the swash.
|
|
551
|
+
// uWetlineY <= -1e8 disables (the default).
|
|
552
|
+
uniform float uWetlineY;
|
|
553
|
+
uniform float uWetlineBand;
|
|
554
|
+
uniform float uWetTime;
|
|
555
|
+
|
|
549
556
|
float splatHash(vec2 p) {
|
|
550
557
|
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
|
|
551
558
|
}
|
|
@@ -709,6 +716,22 @@ if(splatTextureCount > 1.0) blendedMetalness += splatMetalness2 * smoothWeight2;
|
|
|
709
716
|
if(splatTextureCount > 2.0) blendedMetalness += splatMetalness3 * smoothWeight3;
|
|
710
717
|
if(splatTextureCount > 3.0) blendedMetalness += splatMetalness4 * smoothWeight4;
|
|
711
718
|
|
|
719
|
+
// incanto wetline: darken + gloss the sand just above the waterline. The
|
|
720
|
+
// upper edge is fbm-ragged and BREATHES (slow sin synced roughly to the
|
|
721
|
+
// water's swash cadence) so the wet band reads as the trace of the last
|
|
722
|
+
// runup, not a painted stripe.
|
|
723
|
+
if (uWetlineY > -1.0e8) {
|
|
724
|
+
float above = vWorldPosition.y - uWetlineY;
|
|
725
|
+
float breathe = 0.5 + 0.5 * sin(uWetTime * 0.42 + vWorldPosition.x * 0.03 + vWorldPosition.z * 0.021);
|
|
726
|
+
float top = uWetlineBand * (0.5 + 0.5 * breathe);
|
|
727
|
+
float ragged = top + (fbm(vec2(vWorldPosition.x, vWorldPosition.z) * 0.35) - 0.5) * uWetlineBand * 0.8;
|
|
728
|
+
float wet = smoothstep(ragged, ragged * 0.25, above) * smoothstep(-uWetlineBand, -uWetlineBand * 0.2, above);
|
|
729
|
+
// wet sand is first and foremost DARKER; the gleam is mild — a hard
|
|
730
|
+
// roughness cut mirrored the sky and read as white glare from the air
|
|
731
|
+
splatColor.rgb *= 1.0 - wet * 0.38;
|
|
732
|
+
blendedRoughness = mix(blendedRoughness, blendedRoughness * 0.78, wet);
|
|
733
|
+
}
|
|
734
|
+
|
|
712
735
|
diffuseColor = vec4(splatColor.rgb, diffuseColor.a);
|
|
713
736
|
`;
|
|
714
737
|
const FRAG_ROUGHNESS = `
|
|
@@ -793,6 +816,9 @@ function injectTerrainSplatShader(shader, cfg) {
|
|
|
793
816
|
shader.uniforms[`uvNoiseIntensity${n}`] = { value: cfg.uvNoiseIntensity[i] ?? .15 };
|
|
794
817
|
}
|
|
795
818
|
shader.uniforms.splatTextureCount = { value: Math.min(4, cfg.layerCount) };
|
|
819
|
+
shader.uniforms.uWetlineY = { value: -1e9 };
|
|
820
|
+
shader.uniforms.uWetlineBand = { value: 1.1 };
|
|
821
|
+
shader.uniforms.uWetTime = { value: 0 };
|
|
796
822
|
shader.uniforms.splatEnvCut = { value: cfg.envCut };
|
|
797
823
|
shader.vertexShader = injectAfter(shader.vertexShader, "#include <common>", VERT_COMMON);
|
|
798
824
|
shader.vertexShader = injectAfter(shader.vertexShader, "#include <begin_vertex>", VERT_BEGIN);
|
|
@@ -1184,7 +1210,8 @@ var Terrain3D = class extends Node3D {
|
|
|
1184
1210
|
islandEdge: { default: null },
|
|
1185
1211
|
layers: { default: [] },
|
|
1186
1212
|
textureBase: { default: DEFAULT_TERRAIN_TEXTURE_BASE },
|
|
1187
|
-
basins: { default: [] }
|
|
1213
|
+
basins: { default: [] },
|
|
1214
|
+
wetline: { default: null }
|
|
1188
1215
|
};
|
|
1189
1216
|
/** [width, depth] extent in meters, centered on the node. */
|
|
1190
1217
|
size = [200, 200];
|
|
@@ -1209,8 +1236,29 @@ var Terrain3D = class extends Node3D {
|
|
|
1209
1236
|
/** CDN base for theme textures: `<base>/<name>.png` (+`_normal`). */
|
|
1210
1237
|
textureBase = DEFAULT_TERRAIN_TEXTURE_BASE;
|
|
1211
1238
|
/** Lake/pond bowls carved into the surface — smooth radial depressions the
|
|
1212
|
-
* collider + heightAt + dressing all see (place a Water3D in each).
|
|
1239
|
+
* collider + heightAt + dressing all see (place a Water3D in each).
|
|
1240
|
+
* NEGATIVE depth raises a smooth dome MOUND instead (a hill, an islet). */
|
|
1213
1241
|
basins = [];
|
|
1242
|
+
/**
|
|
1243
|
+
* WET SAND band: `{ y, band? }` darkens + glosses the splat in a noisy,
|
|
1244
|
+
* breathing band just above height `y` (a waterline) — the trace of the
|
|
1245
|
+
* last swash runup. `band` is the max height above `y` that reads wet
|
|
1246
|
+
* (default 1.1 m). null (default) = off.
|
|
1247
|
+
*/
|
|
1248
|
+
wetline = null;
|
|
1249
|
+
splatUniforms = null;
|
|
1250
|
+
/** Per-frame wetline clock + prop write — lives in update() so a `static`
|
|
1251
|
+
* subtree keeps the wet edge breathing (the frozen-sync lesson). */
|
|
1252
|
+
wetTime = 0;
|
|
1253
|
+
update(dt) {
|
|
1254
|
+
this.wetTime += dt;
|
|
1255
|
+
const u = this.splatUniforms;
|
|
1256
|
+
if (!u) return;
|
|
1257
|
+
const w = this.wetline;
|
|
1258
|
+
if (u.uWetlineY) u.uWetlineY.value = typeof w?.y === "number" ? w.y : -1e9;
|
|
1259
|
+
if (u.uWetlineBand) u.uWetlineBand.value = typeof w?.band === "number" ? w.band : 1.1;
|
|
1260
|
+
if (u.uWetTime) u.uWetTime.value = this.wetTime;
|
|
1261
|
+
}
|
|
1214
1262
|
/** Loader hook: bad themes/layers/grids fail at LOAD, not at render. */
|
|
1215
1263
|
static validateJson(node) {
|
|
1216
1264
|
const t = node;
|
|
@@ -1225,9 +1273,14 @@ var Terrain3D = class extends Node3D {
|
|
|
1225
1273
|
if (!Number.isInteger(t.detail) || t.detail < 0) throw new IncantoError("BAD_FORMAT", `Terrain3D '${node.name}' detail must be an integer ≥ 0 (octave count), got ${t.detail}.`, { prop: "detail" });
|
|
1226
1274
|
if (!(t.flatThreshold >= 0) || !Number.isFinite(t.flatThreshold)) throw new IncantoError("BAD_FORMAT", `Terrain3D '${node.name}' flatThreshold must be a finite number ≥ 0, got ${t.flatThreshold}.`, { prop: "flatThreshold" });
|
|
1227
1275
|
if (t.islandEdge !== null && typeof t.islandEdge !== "boolean") throw new IncantoError("BAD_FORMAT", `Terrain3D '${node.name}' islandEdge must be true, false or null (null = theme default), got ${JSON.stringify(t.islandEdge)}.`, { prop: "islandEdge" });
|
|
1276
|
+
const wl = t.wetline;
|
|
1277
|
+
if (wl !== null) {
|
|
1278
|
+
if (typeof wl !== "object" || Array.isArray(wl) || !Number.isFinite(wl.y)) throw new IncantoError("BAD_FORMAT", `Terrain3D '${node.name}' wetline must be null or { y, band? } with a finite y, got ${JSON.stringify(t.wetline)}.`, { prop: "wetline" });
|
|
1279
|
+
if (wl.band !== void 0 && !(wl.band > 0)) throw new IncantoError("BAD_FORMAT", `Terrain3D '${node.name}' wetline.band must be > 0 meters, got ${JSON.stringify(wl.band)}.`, { prop: "wetline" });
|
|
1280
|
+
}
|
|
1228
1281
|
if (!Array.isArray(t.basins)) throw new IncantoError("BAD_FORMAT", `Terrain3D '${node.name}' basins must be an array of { x, z, radius, depth }, got ${JSON.stringify(t.basins)}.`, { prop: "basins" });
|
|
1229
1282
|
t.basins.forEach((b, i) => {
|
|
1230
|
-
if (!b || typeof b !== "object" || !Number.isFinite(b.x) || !Number.isFinite(b.z) || !(b.radius > 0) || !(b.depth
|
|
1283
|
+
if (!b || typeof b !== "object" || !Number.isFinite(b.x) || !Number.isFinite(b.z) || !(b.radius > 0) || !Number.isFinite(b.depth) || b.depth === 0) throw new IncantoError("BAD_FORMAT", `Terrain3D '${node.name}' basins[${i}] needs finite x, z, positive radius and nonzero depth (negative = mound), got ${JSON.stringify(b)}.`, { prop: "basins" });
|
|
1231
1284
|
});
|
|
1232
1285
|
if (t.theme === "custom") {
|
|
1233
1286
|
if (!Array.isArray(t.layers) || t.layers.length < 1 || t.layers.length > 4) throw new IncantoError("BAD_FORMAT", `Terrain3D '${node.name}' theme 'custom' needs 1–4 layers, got ${Array.isArray(t.layers) ? t.layers.length : typeof t.layers}.`, { prop: "layers" });
|
|
@@ -1397,6 +1450,7 @@ var Terrain3D = class extends Node3D {
|
|
|
1397
1450
|
};
|
|
1398
1451
|
material.onBeforeCompile = (shader) => {
|
|
1399
1452
|
injectTerrainSplatShader(shader, cfg);
|
|
1453
|
+
this.splatUniforms = shader.uniforms;
|
|
1400
1454
|
};
|
|
1401
1455
|
material.customProgramCacheKey = () => `incanto-terrain-splat:${hasNormalMaps ? 1 : 0}`;
|
|
1402
1456
|
return material;
|
|
@@ -11028,15 +11082,24 @@ void main() {
|
|
|
11028
11082
|
float depthDiff = linearWaterDepth - linearSceneDepth;
|
|
11029
11083
|
waterViewDepth = max(-depthDiff, 0.0);
|
|
11030
11084
|
|
|
11085
|
+
// waterline dither: on a near-flat beach one half-res depth texel spans a
|
|
11086
|
+
// wide screen block at grazing view, so these thresholds cut staircase
|
|
11087
|
+
// notches along the swash edge — jitter the boundary with world noise and
|
|
11088
|
+
// the seam breaks organic. Two octaves at LOW amplitude: a flat slope
|
|
11089
|
+
// multiplies vertical jitter into horizontal metres, so a single strong
|
|
11090
|
+
// octave carved angular value-noise chunks (the diced-radish waterline bug).
|
|
11091
|
+
float seamJitter =
|
|
11092
|
+
(noise(vWorldPosition.xz * 3.1) * 0.65 + noise(vWorldPosition.xz * 8.7) * 0.35 - 0.5) * 0.035;
|
|
11093
|
+
|
|
11031
11094
|
// 🎯 Two-step approach
|
|
11032
11095
|
// Step 1: Discard completely overlapping parts
|
|
11033
|
-
float hardDiscardThreshold = 0.1;
|
|
11096
|
+
float hardDiscardThreshold = 0.1 + seamJitter;
|
|
11034
11097
|
if (depthDiff > hardDiscardThreshold) {
|
|
11035
11098
|
discard; // Completely remove definitively overlapping pixels
|
|
11036
11099
|
}
|
|
11037
11100
|
|
|
11038
11101
|
// Step 2: Gradual transparency for border parts
|
|
11039
|
-
float softDiscardStart = -0.05; // Start fade slightly ahead
|
|
11102
|
+
float softDiscardStart = -0.05 + seamJitter; // Start fade slightly ahead
|
|
11040
11103
|
float softDiscardEnd = hardDiscardThreshold;
|
|
11041
11104
|
|
|
11042
11105
|
if (depthDiff > softDiscardStart) {
|
|
@@ -11193,15 +11256,16 @@ void main() {
|
|
|
11193
11256
|
vec3 sceneColor = texture2D(uSceneColor, refractedUV, 1.75).rgb;
|
|
11194
11257
|
// incanto presets: above-water caustics — reconstruct the sampled
|
|
11195
11258
|
// bottom's world position along the view ray and light it with the
|
|
11196
|
-
// shared caustic web.
|
|
11197
|
-
//
|
|
11198
|
-
//
|
|
11259
|
+
// shared caustic web. Needs a focusing column of water (a centimeters-
|
|
11260
|
+
// deep swash film shows no web) and a close viewer: past ~30m each
|
|
11261
|
+
// pixel integrates many caustic cells and the additive web averages
|
|
11262
|
+
// into a solid white sheet over any flat shallow (aerial sandbar bug).
|
|
11199
11263
|
if (uCausticsAbove > 0.0) {
|
|
11200
11264
|
vec3 bottomWorld = cameraPosition + viewDirection * refrT;
|
|
11201
11265
|
float below = uWaterCenter.y - bottomWorld.y;
|
|
11202
11266
|
if (below > 0.05) {
|
|
11203
|
-
float reach = 1.0 - smoothstep(0.2, 9.0, below);
|
|
11204
|
-
float causticFade = 1.0 - smoothstep(
|
|
11267
|
+
float reach = smoothstep(0.05, 0.5, below) * (1.0 - smoothstep(0.2, 9.0, below));
|
|
11268
|
+
float causticFade = 1.0 - smoothstep(28.0, 90.0, camDist);
|
|
11205
11269
|
float cw = caustic(bottomWorld.xz * 0.42, uTime * 0.7) * 0.65
|
|
11206
11270
|
+ caustic(bottomWorld.xz * 0.72 + 30.0, uTime * 0.55) * 0.35;
|
|
11207
11271
|
sceneColor += vec3(0.87, 0.96, 1.0) * (cw * uCausticsAbove * reach * causticFade);
|
|
@@ -11319,13 +11383,18 @@ void main() {
|
|
|
11319
11383
|
float breakup = noise(vWorldPosition.xz * 0.3 + uTime * vec2(0.06, 0.04));
|
|
11320
11384
|
float lace = noise(vWorldPosition.xz * 2.2 - uTime * vec2(0.18, 0.1));
|
|
11321
11385
|
front *= (0.45 + 0.55 * breakup) * (0.55 + 0.45 * lace) * (0.35 + 0.65 * sets);
|
|
11322
|
-
|
|
11386
|
+
// no fronts in the centimeters-deep SHEET-FLOW film (an enclosed flat
|
|
11387
|
+
// fizzed solid white from the air) — breakers need ~knee depth to form
|
|
11388
|
+
float zone = smoothstep(3.4, 1.2, vertDepth) * smoothstep(0.12, 0.38, vertDepth);
|
|
11323
11389
|
foamAmount = max(foamAmount, clamp(uShoreWaves * front * zone * 1.5, 0.0, 1.0));
|
|
11324
|
-
// waterline LACE —
|
|
11325
|
-
//
|
|
11326
|
-
|
|
11390
|
+
// waterline LACE — fizzing bubbles where the runup meets sand. On a
|
|
11391
|
+
// near-FLAT bar the 0–30 cm depth band is tens of meters wide, so an
|
|
11392
|
+
// ungated lace carpeted whole flats in white — a slow patch gate keeps
|
|
11393
|
+
// it as drifting foam streaks instead (real tidal-flat scum lines).
|
|
11394
|
+
float lacePatch = smoothstep(0.4, 0.8, noise(vWorldPosition.xz * 0.5 + uTime * vec2(0.06, 0.045)));
|
|
11395
|
+
float lace2 = smoothstep(0.24, 0.02, vertDepth) *
|
|
11327
11396
|
(0.35 + 0.65 * noise(vWorldPosition.xz * 3.1 + uTime * vec2(0.5, 0.35)));
|
|
11328
|
-
foamAmount = max(foamAmount, clamp(uShoreWaves * lace2 * 0.
|
|
11397
|
+
foamAmount = max(foamAmount, clamp(uShoreWaves * lace2 * lacePatch * 0.4, 0.0, 1.0));
|
|
11329
11398
|
}
|
|
11330
11399
|
}
|
|
11331
11400
|
// incanto swell: whitecaps — foam eats the TOPS of the tallest crests in
|
|
@@ -11648,7 +11717,7 @@ const WATER_PRESETS = {
|
|
|
11648
11717
|
_look: {
|
|
11649
11718
|
fresnelScale: 1.15,
|
|
11650
11719
|
reflectivityMax: .93,
|
|
11651
|
-
foamRangeScale:
|
|
11720
|
+
foamRangeScale: .35,
|
|
11652
11721
|
foamIntensity: .55
|
|
11653
11722
|
}
|
|
11654
11723
|
},
|
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-sSqrUcnz.js";
|
|
8
8
|
import { t as registerNodes2D } from "./register-Djwckzgx.js";
|
|
9
|
-
import { t as registerNodes3D } from "./register-
|
|
9
|
+
import { t as registerNodes3D } from "./register-Cv5GNiVo.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-BiIdl51r.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-
|
|
130
|
+
const { enablePhysics3D } = await import("./physics-3d-JPdedRAB.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-BiIdl51r.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-
|
|
235
|
+
const { enablePhysics3D } = await import("./physics-3d-JPdedRAB.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-
|
|
1
|
+
import{t as e}from"./index-B7gj1VII.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};
|