incanto 0.69.0 → 0.71.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/bin/_behaviors-loader.mjs +22 -0
- package/bin/_read-json.mjs +28 -0
- package/bin/incanto-assets.mjs +5 -4
- package/bin/incanto-check.mjs +58 -31
- package/bin/incanto-editor.mjs +128 -5
- package/bin/incanto-env.mjs +3 -2
- package/bin/incanto-feel.mjs +24 -13
- package/bin/incanto-frame.mjs +8 -1
- package/bin/incanto-multiplay.mjs +11 -9
- package/bin/incanto-new.mjs +105 -10
- package/bin/incanto-play.mjs +158 -16
- package/bin/incanto-playtest.mjs +66 -23
- package/bin/incanto-skills.mjs +14 -2
- package/bin/incanto-verify.mjs +121 -102
- package/bin/incanto.mjs +3 -2
- package/dist/2d.d.ts +296 -34
- package/dist/2d.js +4 -4
- package/dist/3d.d.ts +157 -9
- package/dist/3d.js +8 -8
- package/dist/{agent8-CvsfVskX.js → agent8-Cfmd3ar_.js} +61 -8
- package/dist/{audio-player-C0j2k-yB.d.ts → audio-player-L8yccdMP.d.ts} +2 -2
- package/dist/{behavior-rm8vVzu_.d.ts → behavior-Dcz0fr1S.d.ts} +755 -46
- package/dist/{create-game-CwxEDlCm.js → create-game-CH4kt78v.js} +143 -60
- package/dist/{create-game-CvJ1wSRP.js → create-game-LCHBLfA4.js} +98 -48
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +2 -3
- package/dist/diagnostics-Cu85N3tL.d.ts +12 -0
- package/dist/{editor-switch-CnIOiyNJ.d.ts → editor-switch-CFU9mCec.d.ts} +22 -13
- package/dist/editor.js +1088 -882
- package/dist/env.d.ts +1 -1
- package/dist/env.js +5 -3
- package/dist/{environment-presets-BO-7XoFV.js → environment-presets-99BzP_L-.js} +298 -45
- package/dist/{frame-report-Dlq13Gyj.js → frame-report-D-_7YF2G.js} +1 -1
- package/dist/{gameplay-D1KixWK8.js → gameplay-CNULJvwh.js} +914 -214
- package/dist/gameplay.d.ts +254 -10
- package/dist/gameplay.js +2 -2
- package/dist/{heightmap-CRK0M4jT.js → heightmap-BYgD5Edk.js} +1 -1
- package/dist/index.d.ts +179 -13
- package/dist/index.js +10 -12
- package/dist/json-CfTjpvW8.js +67 -0
- package/dist/{loader-DadV2QCT.d.ts → loader-8-IHvbKD.d.ts} +2 -2
- package/dist/net.d.ts +27 -3
- package/dist/net.js +2 -2
- package/dist/{noise-CGUMx44x.js → noise-D3nPpmFg.js} +1 -1
- package/dist/{physics-2d-CF5yyjbj.js → physics-2d-FhrXUc6B.js} +136 -11
- package/dist/{physics-3d-DbYaEcZy.js → physics-3d-CFEGxBXZ.js} +104 -23
- package/dist/{teardown-CMqFVxO9.js → picking-DVo7fI13.js} +104 -13
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/dist/{register-DbVArsns.js → register-BYQCBySi.js} +429 -28
- package/dist/{register-mmfugpaQ.js → register-DuVdzxbq.js} +594 -831
- package/dist/{replay-BEHLDcQV.js → replay-DEvp3kyV.js} +224 -14
- package/dist/{replay-BQfkX4x7.d.ts → replay-F7IZHdFR.d.ts} +20 -3
- package/dist/{schema-B6ugCV1Q.d.ts → rng-Bb-IutXB.d.ts} +38 -21
- package/dist/{rng-DP-SR7eg.js → rng-CDOMybym.js} +22 -0
- package/dist/{loader-DZE7B07H.js → save-slots-Bvuh2p_r.js} +4619 -2318
- package/dist/{split-screen-Cg76MCV5.d.ts → split-screen-CIYf1zSf.d.ts} +36 -4
- package/dist/{split-screen-CauMwu6y.js → split-screen-eULetcg-.js} +159 -26
- package/dist/{sprite-animation-CY-mrr1L.js → sprite-animation-CqR2o3SA.js} +39 -8
- package/dist/{src-CYEu-_S9.js → src-_jk0qLsS.js} +2 -17
- package/dist/test-CmN54kWv.js +4264 -0
- package/dist/test.d.ts +639 -30
- package/dist/test.js +3 -3
- package/dist/touch-BnCyPA0G.js +519 -0
- package/dist/vite.d.ts +20 -37
- package/dist/vite.js +177 -7
- package/dist/{webgl-unavailable-Z5_g8x9H.js → webgl-unavailable-C8aDbGmR.js} +44 -0
- package/editor/assets/agent8-yLIEYHbd.js +1 -0
- package/editor/assets/{debug-CMULinBW.js → debug-u31w_yhq.js} +2 -2
- package/editor/assets/index-DK9xMGpW.js +11046 -0
- package/editor/index.html +1 -1
- package/package.json +4 -14
- package/schemas/scene.schema.json +34 -3
- package/skills/incanto-3d-character.md +14 -1
- package/skills/incanto-3d-models.md +12 -0
- package/skills/incanto-assets.md +9 -1
- package/skills/incanto-audio.md +8 -2
- package/skills/incanto-behaviors-and-scripts.md +105 -7
- package/skills/incanto-building-2d-games.md +97 -10
- package/skills/incanto-building-3d-games.md +58 -4
- package/skills/incanto-editor.md +46 -7
- package/skills/incanto-environment.md +19 -1
- package/skills/incanto-game-feel.md +70 -0
- package/skills/incanto-gameplay-behaviors.md +172 -20
- package/skills/incanto-hud.md +142 -7
- package/skills/incanto-localization.md +13 -5
- package/skills/incanto-multiplayer.md +83 -3
- package/skills/incanto-node-reference.md +239 -59
- package/skills/incanto-performance.md +52 -0
- package/skills/incanto-physics-and-input.md +123 -24
- package/skills/incanto-playtesting.md +112 -2
- package/skills/incanto-save-slots.md +217 -7
- package/skills/incanto-scene-json-authoring.md +69 -12
- package/skills/incanto-verifying-your-game.md +207 -10
- package/skills/incanto-web-integration.md +28 -0
- package/skills/incanto-your-first-game.md +3 -1
- package/templates-app/beacon-isle-3d/generate-world.ts +77 -9
- package/templates-app/beacon-isle-3d/package.json +2 -2
- package/templates-app/beacon-isle-3d/src/behaviors.ts +22 -0
- package/templates-app/beacon-isle-3d/src/game.scene.json +143 -600
- package/templates-app/beacon-isle-3d/src/main.ts +11 -1
- package/templates-app/beacon-isle-3d/tsconfig.json +1 -1
- package/templates-app/beacon-isle-3d/verify.ts +3 -1
- package/templates-app/molehill-2d/.incanto/playtest/lost-seed1.json +4277 -0
- package/templates-app/molehill-2d/PROJECT/Context.md +58 -0
- package/templates-app/molehill-2d/PROJECT/Requirements.md +39 -0
- package/templates-app/molehill-2d/PROJECT/Status.md +27 -0
- package/templates-app/molehill-2d/PROJECT/Structure.md +48 -0
- package/templates-app/molehill-2d/docs/project-2d-rules.md +44 -0
- package/templates-app/molehill-2d/index.html +73 -0
- package/templates-app/molehill-2d/package.json +23 -0
- package/templates-app/molehill-2d/src/behaviors.ts +198 -0
- package/templates-app/molehill-2d/src/game.scene.json +1205 -0
- package/templates-app/molehill-2d/src/main.ts +41 -0
- package/templates-app/molehill-2d/tsconfig.json +13 -0
- package/templates-app/molehill-2d/verify.ts +247 -0
- package/templates-app/molehill-2d/vite.config.ts +12 -0
- package/templates-app/platformer-2d/package.json +2 -2
- package/templates-app/platformer-2d/src/game.scene.json +178 -986
- package/templates-app/platformer-2d/src/main.ts +11 -1
- package/templates-app/platformer-2d/tsconfig.json +1 -1
- package/templates-app/star-survivor/package.json +2 -2
- package/templates-app/star-survivor/src/game.scene.json +43 -216
- package/templates-app/star-survivor/src/main.ts +11 -1
- package/templates-app/star-survivor/tsconfig.json +1 -1
- package/templates-app/tps-3d/PROJECT/Context.md +1 -1
- package/templates-app/tps-3d/package.json +2 -2
- package/templates-app/tps-3d/src/behaviors.ts +19 -1
- package/templates-app/tps-3d/src/game.scene.json +66 -263
- package/templates-app/tps-3d/src/main.ts +13 -2
- package/templates-app/tps-3d/tsconfig.json +1 -1
- package/templates-app/village-quest-3d/.incanto/playtest/swapped-seed1.json +1735 -0
- package/templates-app/village-quest-3d/package.json +2 -2
- package/templates-app/village-quest-3d/src/behaviors.ts +42 -4
- package/templates-app/village-quest-3d/src/grove.scene.json +68 -306
- package/templates-app/village-quest-3d/src/main.ts +11 -1
- package/templates-app/village-quest-3d/src/village.scene.json +202 -863
- package/templates-app/village-quest-3d/tsconfig.json +1 -1
- package/templates-app/village-quest-3d/verify.ts +14 -1
- package/dist/duplicate-Dj4L-5AA.js +0 -22
- package/dist/json-CwwhxQgb.js +0 -36
- package/dist/registry-CF70EArN.js +0 -212
- package/dist/rolldown-runtime-D7D4PA-g.js +0 -13
- package/dist/test-D6ISmuFE.js +0 -2383
- package/dist/touch-DEAmqGdf.js +0 -225
- package/editor/assets/agent8-BDvaZMQJ.js +0 -1
- package/editor/assets/index-CZIRr5EL.js +0 -10958
package/dist/3d.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { c as showBootFailure, i as ParticleSim, o as ParticleView, r as SpatialPose, s as isWebGLAvailable } from "./audio-player-
|
|
2
|
-
import { D as QualityCaps, P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats, x as EngineOptions } from "./behavior-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { c as showBootFailure, i as ParticleSim, o as ParticleView, r as SpatialPose, s as isWebGLAvailable } from "./audio-player-L8yccdMP.js";
|
|
2
|
+
import { D as QualityCaps, P as Scene$1, S as Scheduler, T as RendererStats, b as Engine, d as PropSchema, jt as Node, n as BehaviorCtor, w as GameStats, x as EngineOptions } from "./behavior-Dcz0fr1S.js";
|
|
3
|
+
import { t as DiagnosticSink } from "./diagnostics-Cu85N3tL.js";
|
|
4
|
+
import { a as SceneJson$1, s as JsonObject } from "./rng-Bb-IutXB.js";
|
|
5
|
+
import { t as EditorSwitchOptions } from "./editor-switch-CFU9mCec.js";
|
|
5
6
|
import { a as GridCell, c as diffText, d as frameText, i as FrameStatsOptions, l as frameSignature, n as FrameSignature, o as SIGNATURE_GRID, r as FrameStats, s as diffSignatures, t as FrameDiff, u as frameStats } from "./frame-report-DNxDAb1w.js";
|
|
6
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
7
|
+
import { t as LoadSceneOptions } from "./loader-8-IHvbKD.js";
|
|
7
8
|
import { n as PathGrid } from "./pathfinding-_fGrCFmH.js";
|
|
8
9
|
import { AnimationClip, AnimationMixer, BufferGeometry, Color, DirectionalLight, Group, InstancedMesh, Mesh, MeshPhysicalMaterial, Object3D, PerspectiveCamera, Scene, ShaderMaterial, Texture, Vector3, WebGLRenderer } from "three";
|
|
9
10
|
import { VRM } from "@pixiv/three-vrm";
|
|
@@ -341,6 +342,20 @@ declare class Node3D extends Node {
|
|
|
341
342
|
* error rather than a silent per-node decode; overrides that do not need it
|
|
342
343
|
* simply keep the one-argument signature. Null in a headless test or a
|
|
343
344
|
* detached probe, where the node falls back to loading uncached. */
|
|
345
|
+
/**
|
|
346
|
+
* Is there anything left to wait for before this node can be FROZEN?
|
|
347
|
+
*
|
|
348
|
+
* The static latch fired unconditionally, while `Renderer3D.render()` calls
|
|
349
|
+
* `assets.load()` and `syncTree()` in the SAME frame — so a
|
|
350
|
+
* `ModelInstance3D` frozen by its own or an ancestor group's `static` never
|
|
351
|
+
* mounted its GLB at all, permanently and silently: the asset loaded fine, so
|
|
352
|
+
* `assetErrors()` is empty and `stats().errors` is 0, and `framing` reads
|
|
353
|
+
* props rather than pixels and still calls the node on-screen.
|
|
354
|
+
*
|
|
355
|
+
* The 2D adapter already had exactly this gate (`Node2D._staticReady`); this
|
|
356
|
+
* is its twin. A node with nothing to wait for is ready by definition.
|
|
357
|
+
*/
|
|
358
|
+
_staticReady(_assets: AssetStore3D | null): boolean;
|
|
344
359
|
_syncObject3D(alpha?: number, _assets?: AssetStore3D | null): void;
|
|
345
360
|
override free(): void;
|
|
346
361
|
}
|
|
@@ -409,7 +424,7 @@ declare class Area3D extends PhysicsBody3D {
|
|
|
409
424
|
*
|
|
410
425
|
* Empty in a scene with no physics world.
|
|
411
426
|
*/
|
|
412
|
-
overlapping(group?: string): PhysicsBody3D[];
|
|
427
|
+
overlapping(group?: string | undefined): PhysicsBody3D[];
|
|
413
428
|
}
|
|
414
429
|
/** Dynamic simulated body. */
|
|
415
430
|
declare class RigidBody3D extends PhysicsBody3D {
|
|
@@ -430,6 +445,13 @@ declare class RigidBody3D extends PhysicsBody3D {
|
|
|
430
445
|
* no counterpart to `linearVelocity`. `fixedRotation` pins it at zero.
|
|
431
446
|
*/
|
|
432
447
|
angularVelocity: number[];
|
|
448
|
+
/**
|
|
449
|
+
* The other name for `linearVelocity` — see `RigidBody2D.velocity`. On a
|
|
450
|
+
* plain TS class `body.velocity = [...]` succeeds silently and does nothing,
|
|
451
|
+
* and that is the spelling the physics skill taught.
|
|
452
|
+
*/
|
|
453
|
+
get velocity(): number[];
|
|
454
|
+
set velocity(v: number[]);
|
|
433
455
|
/** @internal set by Physics3D */
|
|
434
456
|
_physics3d: Physics3D | null;
|
|
435
457
|
/** World-space impulse (kg·m/s) — the floating-capsule controller's verb. */
|
|
@@ -491,6 +513,31 @@ declare class CharacterBody3D extends PhysicsBody3D {
|
|
|
491
513
|
/** @internal Updated by Physics3D.moveAndSlide. */
|
|
492
514
|
_grounded: boolean;
|
|
493
515
|
moveAndSlide(): void;
|
|
516
|
+
/** @internal Set by the physics step from the KCC's resolved collisions. */
|
|
517
|
+
_onWall: [number, number, number] | null;
|
|
518
|
+
/** @internal */
|
|
519
|
+
_onCeiling: boolean;
|
|
520
|
+
/**
|
|
521
|
+
* Touching a wall.
|
|
522
|
+
*
|
|
523
|
+
* `CharacterBody2D` has had this since wall jump and wall slide turned out to
|
|
524
|
+
* be not merely awkward to write in 2D but IMPOSSIBLE — `isOnFloor()` was the
|
|
525
|
+
* only surface a character could report, so even a hand-written behavior had
|
|
526
|
+
* nothing to ask. 3D was left with exactly that problem: a 3D platformer
|
|
527
|
+
* could not wall-jump, and nothing said why.
|
|
528
|
+
*/
|
|
529
|
+
isOnWall(): boolean;
|
|
530
|
+
/**
|
|
531
|
+
* The wall's normal, pointing AWAY from it (toward the character) — the
|
|
532
|
+
* vector a wall jump pushes along. `null` when not touching one.
|
|
533
|
+
*
|
|
534
|
+
* 2D answers this as `wallSide()`, a -1/+1 scalar, because a 2D character
|
|
535
|
+
* has only two horizontal directions. In three dimensions the honest answer
|
|
536
|
+
* is the normal itself.
|
|
537
|
+
*/
|
|
538
|
+
wallNormal(): [number, number, number] | null;
|
|
539
|
+
/** Head hit something — cut the jump short, the way every platformer does. */
|
|
540
|
+
isOnCeiling(): boolean;
|
|
494
541
|
isOnFloor(): boolean;
|
|
495
542
|
}
|
|
496
543
|
//#endregion
|
|
@@ -557,6 +604,14 @@ declare class Physics3D {
|
|
|
557
604
|
*/
|
|
558
605
|
private poseFromTree;
|
|
559
606
|
/** @internal Called by CharacterBody3D.moveAndSlide (during tree fixedUpdate). */
|
|
607
|
+
/**
|
|
608
|
+
* May `candidate` carry `rider`? — see the 2D twin.
|
|
609
|
+
*
|
|
610
|
+
* "Never a CharacterBody3D" is the whole CLASS, and a CharacterBody3D
|
|
611
|
+
* animated by position writes is the documented moving-platform path. What
|
|
612
|
+
* the guard was really for is a carry CYCLE, so that is what it tests.
|
|
613
|
+
*/
|
|
614
|
+
private canCarry;
|
|
560
615
|
moveAndSlide(node: CharacterBody3D): void;
|
|
561
616
|
/** Rapier debug segments (meters). Null while debugDraw is off. */
|
|
562
617
|
debugLines(): Float32Array | null;
|
|
@@ -582,6 +637,16 @@ declare class Physics3D {
|
|
|
582
637
|
* off ONE fixed body — they never move, so there is nothing to step — and the
|
|
583
638
|
* whole set is rebuilt only when the tree's shape changes.
|
|
584
639
|
*/
|
|
640
|
+
/** Where each live scatter field was when its colliders were built. */
|
|
641
|
+
private readonly scatterState;
|
|
642
|
+
/**
|
|
643
|
+
* Has any scatter field moved, or had its rows replaced, since the build?
|
|
644
|
+
*
|
|
645
|
+
* `transforms` is compared by IDENTITY, which is the operation the skill
|
|
646
|
+
* teaches ("replace the whole array"); the world position catches the field
|
|
647
|
+
* itself or an ancestor being moved.
|
|
648
|
+
*/
|
|
649
|
+
private scattersMoved;
|
|
585
650
|
private syncScatters;
|
|
586
651
|
private syncBodies;
|
|
587
652
|
/**
|
|
@@ -621,7 +686,8 @@ declare class Physics3D {
|
|
|
621
686
|
*/
|
|
622
687
|
overlapping(node: PhysicsBody3D): PhysicsBody3D[];
|
|
623
688
|
/**
|
|
624
|
-
* World-space raycast (meters). `
|
|
689
|
+
* World-space raycast (meters). `dir` may be any length (it is normalized),
|
|
690
|
+
* so `distance` and `maxLen` are metres. `exclude` skips that body's collider —
|
|
625
691
|
* ground probes from inside a capsule need it. `opts.staticOnly` hits ONLY the
|
|
626
692
|
* fixed/static world (excludes both dynamic AND kinematic bodies): the camera
|
|
627
693
|
* spring arm uses it so neither a dynamic projectile nor a KINEMATIC enemy
|
|
@@ -633,6 +699,7 @@ declare class Physics3D {
|
|
|
633
699
|
distance: number;
|
|
634
700
|
normal: [number, number, number];
|
|
635
701
|
node: PhysicsBody3D | null;
|
|
702
|
+
point: [number, number, number];
|
|
636
703
|
} | null;
|
|
637
704
|
/**
|
|
638
705
|
* Sweep a sphere of `radius` from `origin` along `dir` — a THICK ray. The
|
|
@@ -669,6 +736,12 @@ interface CreateGame3DOptions {
|
|
|
669
736
|
/** Keyboard source (default: window when available). `false` disables. */
|
|
670
737
|
keyboard?: KeyboardTarget | false;
|
|
671
738
|
/** Pointer-look on the canvas (FPS pattern). Default false. */
|
|
739
|
+
/**
|
|
740
|
+
* Omitted, this is AUTO: the pointer is attached when the scene contains a
|
|
741
|
+
* `Clickable`, the same way `physics: 'auto'` turns Rapier on for a scene
|
|
742
|
+
* with bodies. Pass `true` for mouse-look (it also requests pointer lock on
|
|
743
|
+
* click here), or when a behaviour of your own reads `pointerPosition()`.
|
|
744
|
+
*/
|
|
672
745
|
pointer?: boolean | {
|
|
673
746
|
lockOnClick?: boolean;
|
|
674
747
|
};
|
|
@@ -1343,16 +1416,37 @@ declare class BoneLookAt3D extends Node3D {
|
|
|
1343
1416
|
declare class Camera3D extends Node3D {
|
|
1344
1417
|
static override readonly typeName: string;
|
|
1345
1418
|
static override readonly props: PropSchema;
|
|
1419
|
+
/** A frustum whose planes are the wrong way round draws nothing at all. */
|
|
1420
|
+
static validateJson(node: Node): void;
|
|
1346
1421
|
fov: number;
|
|
1347
1422
|
near: number;
|
|
1348
1423
|
far: number;
|
|
1349
1424
|
current: boolean;
|
|
1425
|
+
lookAt: string;
|
|
1426
|
+
/**
|
|
1427
|
+
* Aim, every frame, whenever `lookAt` names something.
|
|
1428
|
+
*
|
|
1429
|
+
* In `update` and not `_syncObject3D`: the second is the renderer's copy pass
|
|
1430
|
+
* and a static node is pruned from it, which silently freezes anything driven
|
|
1431
|
+
* there. `rotation` is written as an ordinary prop, so the editor, the
|
|
1432
|
+
* serializer and `describeFraming` all see what the camera is actually doing.
|
|
1433
|
+
*/
|
|
1434
|
+
/** The `lookAt` path already reported as unlookable — cleared by a new one. */
|
|
1435
|
+
private warnedLookAt;
|
|
1436
|
+
override update(_dt: number): void;
|
|
1350
1437
|
protected override _createObject3D(): Object3D;
|
|
1351
1438
|
override _syncObject3D(): void;
|
|
1352
1439
|
}
|
|
1353
1440
|
//#endregion
|
|
1354
1441
|
//#region src/3d/nodes/character-controller-3d.d.ts
|
|
1355
1442
|
/**
|
|
1443
|
+
* The states this controller enters, and therefore the only keys its
|
|
1444
|
+
* `animations` map may carry.
|
|
1445
|
+
*/
|
|
1446
|
+
declare const MOVEMENT_STATES: readonly ["idle", "walk", "run", "fastRun", "airborne"];
|
|
1447
|
+
/** One of {@link MOVEMENT_STATES}. */
|
|
1448
|
+
type MovementState = (typeof MOVEMENT_STATES)[number];
|
|
1449
|
+
/**
|
|
1356
1450
|
* The floating-capsule character controller behind every agent8 3D template
|
|
1357
1451
|
* (vibe-starter-3d parity, same numbers): put it UNDER a dynamic RigidBody3D
|
|
1358
1452
|
* with a capsule collider and it gives you impulse-based movement with
|
|
@@ -1449,11 +1543,23 @@ declare class CharacterController3D extends Node3D {
|
|
|
1449
1543
|
* "walk": "$walk", "airborne": "$jump" }
|
|
1450
1544
|
*/
|
|
1451
1545
|
animations: Record<string, string>;
|
|
1546
|
+
/**
|
|
1547
|
+
* Scene-load validation: an animation keyed by a state this controller never
|
|
1548
|
+
* enters is a clip that never plays.
|
|
1549
|
+
*
|
|
1550
|
+
* The five state names live in one place in one skill, and `jumping`,
|
|
1551
|
+
* `sprint`, `walking` and `falling` are what they are called in most other
|
|
1552
|
+
* engines — `jump` is even the ACTION name in every template here. A wrong
|
|
1553
|
+
* key was accepted and never looked at again, so the character walked and
|
|
1554
|
+
* idled correctly and never animated its jump, which reads as broken
|
|
1555
|
+
* animation rather than a wrong key.
|
|
1556
|
+
*/
|
|
1557
|
+
static validateJson(node: Node): void;
|
|
1452
1558
|
/** Camera yaw/pitch in radians (mouse look mutates these). */
|
|
1453
1559
|
yaw: number;
|
|
1454
1560
|
pitch: number;
|
|
1455
1561
|
/** idle | walk | run | fastRun | airborne — drive animations from this. */
|
|
1456
|
-
state:
|
|
1562
|
+
state: MovementState;
|
|
1457
1563
|
grounded: boolean;
|
|
1458
1564
|
/** @internal Feel timers — see the jump block for what each one buys. */
|
|
1459
1565
|
private coyoteLeft;
|
|
@@ -2247,6 +2353,11 @@ declare class ModelInstance3D extends Node3D {
|
|
|
2247
2353
|
/** Embedded clip names + the scene's animation `$key`s (editor dropdown). */
|
|
2248
2354
|
availableAnimations(): string[];
|
|
2249
2355
|
/** Called by the 3D sync pass with the renderer's asset store. */
|
|
2356
|
+
/**
|
|
2357
|
+
* A model is ready when its GLB is. Freezing before that mounts nothing —
|
|
2358
|
+
* see `Node3D._staticReady`.
|
|
2359
|
+
*/
|
|
2360
|
+
override _staticReady(assets: AssetStore3D | null): boolean;
|
|
2250
2361
|
_syncModel(assets: AssetStore3D): void;
|
|
2251
2362
|
/**
|
|
2252
2363
|
* Scale the model so it stands `targetHeight` tall, measured ONCE.
|
|
@@ -2957,7 +3068,32 @@ declare class Terrain3D extends Node3D {
|
|
|
2957
3068
|
roughness: number;
|
|
2958
3069
|
/** Detail octave count. */
|
|
2959
3070
|
detail: number;
|
|
2960
|
-
/**
|
|
3071
|
+
/**
|
|
3072
|
+
* Snap-flatten a plateau within ±0.6 m of maxHeight·flatThreshold.
|
|
3073
|
+
*
|
|
3074
|
+
* A fraction of `maxHeight`, which is a SCALE and not the peak: heights
|
|
3075
|
+
* realize at roughly 3.5–8× it, so the default 0.95 puts the plateau near the
|
|
3076
|
+
* BOTTOM of the range rather than at the summit the name suggests. Measured
|
|
3077
|
+
* on an alpine 200 m terrain, seed 3:
|
|
3078
|
+
*
|
|
3079
|
+
* ```
|
|
3080
|
+
* maxHeight 28 realized 25..150 band at 26.6 = 18% of peak, 28 cells on it
|
|
3081
|
+
* maxHeight 8 realized 8..43 band at 7.6 = 18% of peak, 99 cells on it
|
|
3082
|
+
* ```
|
|
3083
|
+
*
|
|
3084
|
+
* It is doing something — that is a real terrace, and the ±0.6 m boundary
|
|
3085
|
+
* between snapped and unsnapped cells is what `examples/water-ocean-3d` calls
|
|
3086
|
+
* "a sawtooth band across the underwater flat". Read `heightAt` before
|
|
3087
|
+
* choosing a value, the way `maxHeight`'s own note says to.
|
|
3088
|
+
*
|
|
3089
|
+
* 0..1 is the useful range, and anything ABOVE 1 turns the snap off, because
|
|
3090
|
+
* the band then sits over every height the terrain realizes. `examples/water-ocean-3d` uses `20` for exactly that,
|
|
3091
|
+
* with a comment explaining why, which is how a `max: 1` on this prop was
|
|
3092
|
+
* caught the moment it was declared: at `maxHeight 0.1` the ±0.6 m band
|
|
3093
|
+
* swallows the whole field and rips a sawtooth across the underwater flat.
|
|
3094
|
+
* So the bound is `min: 0` and "off" is a documented idiom rather than an
|
|
3095
|
+
* accident.
|
|
3096
|
+
*/
|
|
2961
3097
|
flatThreshold: number;
|
|
2962
3098
|
/** Wrap edges down into an island rim. null = theme decides (island: on). */
|
|
2963
3099
|
islandEdge: boolean | null;
|
|
@@ -3249,9 +3385,21 @@ declare class VoxelGrid3D extends Node3D {
|
|
|
3249
3385
|
static override readonly typeName: string;
|
|
3250
3386
|
static override readonly signals: readonly string[];
|
|
3251
3387
|
static override readonly props: PropSchema;
|
|
3388
|
+
/**
|
|
3389
|
+
* Hard-fail an authored grid that cannot all be DRAWN.
|
|
3390
|
+
*
|
|
3391
|
+
* The draw loop stops at `MAX_INSTANCES` and the excess blocks stay in the
|
|
3392
|
+
* map — so `tileAt()` still reports them and a chunk collider builder still
|
|
3393
|
+
* makes them solid. The world past the cap was invisible AND you walked into
|
|
3394
|
+
* it. Every other 3D node whose instance count comes from authored data
|
|
3395
|
+
* hard-fails at load; this one silently truncated.
|
|
3396
|
+
*/
|
|
3397
|
+
static validateJson(node: Node): void;
|
|
3252
3398
|
/** JSON-authored blocks as [x, y, z, tile] tuples (generated terrains bake these). */
|
|
3253
3399
|
voxels: number[][];
|
|
3254
3400
|
private appliedVoxels;
|
|
3401
|
+
/** Said once per node: a runtime overflow must not spam a frame loop. */
|
|
3402
|
+
private reportedOverflow;
|
|
3255
3403
|
private readonly map;
|
|
3256
3404
|
private mesh;
|
|
3257
3405
|
private dirty;
|
package/dist/3d.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as sunDirectionFromSky, S as sunDirectionFromElevationAzimuth, b as horizonColorFromSky, x as parseEnvironment3D } from "./save-slots-Bvuh2p_r.js";
|
|
2
2
|
import { t as showBootFailure } from "./boot-failure-CKYrEcGF.js";
|
|
3
|
-
import { t as isWebGLAvailable } from "./webgl-unavailable-
|
|
4
|
-
import { a as frameSignature, n as diffSignatures, o as frameStats, r as diffText, s as frameText, t as SIGNATURE_GRID } from "./frame-report-
|
|
5
|
-
import { G as StaticBody3D, H as CharacterBody3D, K as Node3D, L as Water3D, R as WATER_CUTOUT_MAX, U as PhysicsBody3D, V as Area3D, W as RigidBody3D, Y as WATER_MAX_RIPPLES, z as WaterCutout3D } from "./gameplay-
|
|
6
|
-
import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-
|
|
7
|
-
import { a as Environment3D, c as AssetStore3D, i as syncTree, o as applyQualityTier3D, r as Renderer3D, s as setEnvironment3D, t as createGame3D } from "./create-game-
|
|
8
|
-
import { n as splatWeights, t as buildHeightmap } from "./heightmap-
|
|
9
|
-
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-
|
|
3
|
+
import { t as isWebGLAvailable } from "./webgl-unavailable-C8aDbGmR.js";
|
|
4
|
+
import { a as frameSignature, n as diffSignatures, o as frameStats, r as diffText, s as frameText, t as SIGNATURE_GRID } from "./frame-report-D-_7YF2G.js";
|
|
5
|
+
import { G as StaticBody3D, H as CharacterBody3D, K as Node3D, L as Water3D, R as WATER_CUTOUT_MAX, U as PhysicsBody3D, V as Area3D, W as RigidBody3D, Y as WATER_MAX_RIPPLES, z as WaterCutout3D } from "./gameplay-CNULJvwh.js";
|
|
6
|
+
import { A as Terrain3D, B as keyboardIntensity, C as resolveFlowerDensity, D as BoneLookAt3D, E as Camera3D, F as InstancedMesh3D, G as acquireTexture, H as rigPose, I as MeshInstance3D, M as TERRAIN_THEMES, N as terrainThemeLayers, O as BoneAttachment3D, P as Joint3D, R as QUARTER_PITCH, S as Flowers3D, T as CharacterController3D, U as TextureCache3D, V as movementState, W as acquireOwnTexture, _ as LoftMesh3D, a as Tree3D, b as Foliage3D, c as buildRiverRings, d as riverCarveChannels, f as riverStepFor, g as ModelInstance3D, h as Particles3D, i as VoxelGrid3D, j as DEFAULT_TERRAIN_TEXTURE_BASE, k as Billboard3D, l as findRiverCoverageGaps, m as traceDownhillPath, n as registerNodes3D, o as Trail3D, p as smoothCourse, r as VOXEL_PALETTE, s as River3D, u as projectToRiver, v as DirectionalLight3D, w as FLOWER_VARIETIES, x as DENSITY_PRESETS, y as OmniLight3D, z as cameraRelative } from "./environment-presets-99BzP_L-.js";
|
|
7
|
+
import { a as Environment3D, c as AssetStore3D, i as syncTree, o as applyQualityTier3D, r as Renderer3D, s as setEnvironment3D, t as createGame3D } from "./create-game-LCHBLfA4.js";
|
|
8
|
+
import { n as splatWeights, t as buildHeightmap } from "./heightmap-BYgD5Edk.js";
|
|
9
|
+
import { n as enablePhysics3D, t as Physics3D } from "./physics-3d-CFEGxBXZ.js";
|
|
10
10
|
//#region src/3d/model-verdict.ts
|
|
11
11
|
/** Mixamo exports every bone as `mixamorigX`; the retargeter binds by that name. */
|
|
12
12
|
const MIXAMO = /^mixamorig[:_]?/i;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { o as __exportAll } from "./json-CfTjpvW8.js";
|
|
2
|
+
import { Y as diagnose } from "./save-slots-Bvuh2p_r.js";
|
|
2
3
|
//#region src/net/agent8.ts
|
|
3
4
|
var agent8_exports = /* @__PURE__ */ __exportAll({
|
|
4
5
|
Agent8TransportForTest: () => Agent8Transport,
|
|
@@ -20,9 +21,19 @@ var agent8_exports = /* @__PURE__ */ __exportAll({
|
|
|
20
21
|
* 3. Reconnect: the SDK clears pending subscriptions on disconnect and never
|
|
21
22
|
* restores them — we re-issue every active subscription after reconnect.
|
|
22
23
|
*/
|
|
23
|
-
async function createAgent8Server(config) {
|
|
24
|
-
return new Agent8Transport((await import("@agent8/gameserver/dist/src/server/GameServer.js")).GameServer, config);
|
|
24
|
+
async function createAgent8Server(config, diagnostics) {
|
|
25
|
+
return new Agent8Transport((await import("@agent8/gameserver/dist/src/server/GameServer.js")).GameServer, config, { diagnostics });
|
|
25
26
|
}
|
|
27
|
+
/** Backoff for a dropped socket: 0.5s, 1, 2, 4, 8, 8, … — see `reconnect`. */
|
|
28
|
+
const RECONNECT_DELAYS_MS = [
|
|
29
|
+
500,
|
|
30
|
+
1e3,
|
|
31
|
+
2e3,
|
|
32
|
+
4e3,
|
|
33
|
+
8e3
|
|
34
|
+
];
|
|
35
|
+
/** ~40 seconds of trying before it says it has given up. */
|
|
36
|
+
const RECONNECT_ATTEMPTS = 8;
|
|
26
37
|
var Agent8Transport = class {
|
|
27
38
|
raw;
|
|
28
39
|
active = /* @__PURE__ */ new Map();
|
|
@@ -31,7 +42,14 @@ var Agent8Transport = class {
|
|
|
31
42
|
/** Set by disconnect(): the closing socket may still fire onDisconnect — that
|
|
32
43
|
* must not resurrect the connection after an intentional teardown. */
|
|
33
44
|
disposed = false;
|
|
34
|
-
|
|
45
|
+
diagnostics;
|
|
46
|
+
/** Injectable so a test does not really wait 40 seconds. */
|
|
47
|
+
wait;
|
|
48
|
+
constructor(GameServer, config, opts) {
|
|
49
|
+
this.diagnostics = opts?.diagnostics ?? null;
|
|
50
|
+
this.wait = opts?.wait ?? ((ms) => new Promise((resolve) => {
|
|
51
|
+
setTimeout(resolve, ms);
|
|
52
|
+
}));
|
|
35
53
|
this.raw = new GameServer({ ...config });
|
|
36
54
|
}
|
|
37
55
|
get account() {
|
|
@@ -70,16 +88,51 @@ var Agent8Transport = class {
|
|
|
70
88
|
this.active.delete(key);
|
|
71
89
|
};
|
|
72
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Get back on the wire after the socket dropped, and keep trying.
|
|
93
|
+
*
|
|
94
|
+
* This used to be one `await this.rawConnect()` with no catch. A server that
|
|
95
|
+
* is still restarting REJECTS that connect, and since the caller is
|
|
96
|
+
* `void this.reconnect()` the rejection escaped as an unhandled promise, the
|
|
97
|
+
* re-issue loop below it never ran, and nothing scheduled a second attempt:
|
|
98
|
+
* every subscription the SDK dropped stayed dropped and there was no path
|
|
99
|
+
* back for the session. A resolved `false` was worse still — it counted as
|
|
100
|
+
* success and re-issued every subscription onto a socket that was not
|
|
101
|
+
* connected.
|
|
102
|
+
*
|
|
103
|
+
* A dropped connection is the one multiplayer failure that is nobody's fault
|
|
104
|
+
* and fixes itself, so the answer is to wait and try again — and to SAY so,
|
|
105
|
+
* because a game that has gone quiet looks identical to one where nothing is
|
|
106
|
+
* happening.
|
|
107
|
+
*/
|
|
73
108
|
async reconnect() {
|
|
74
109
|
if (this.disposed) return;
|
|
75
110
|
if (this.reconnecting) return;
|
|
76
111
|
this.reconnecting = true;
|
|
77
112
|
try {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
113
|
+
for (let attempt = 0; attempt < RECONNECT_ATTEMPTS; attempt++) {
|
|
114
|
+
let connected = false;
|
|
115
|
+
let why = null;
|
|
116
|
+
try {
|
|
117
|
+
connected = await this.rawConnect() !== false;
|
|
118
|
+
} catch (error) {
|
|
119
|
+
why = error;
|
|
120
|
+
}
|
|
121
|
+
if (this.disposed) return;
|
|
122
|
+
if (connected) {
|
|
123
|
+
for (const entry of this.active.values()) {
|
|
124
|
+
entry.off();
|
|
125
|
+
entry.off = entry.make();
|
|
126
|
+
}
|
|
127
|
+
if (attempt > 0) diagnose(this.diagnostics, "info", `[incanto] multiplayer reconnected after ${attempt + 1} attempts.`);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (attempt === 0) diagnose(this.diagnostics, "warn", `[incanto] the multiplayer connection dropped and the server would not take it back${why ? ` (${why instanceof Error ? why.message : String(why)})` : ""}. Retrying — other players cannot see this one until it comes back.`);
|
|
131
|
+
const delay = RECONNECT_DELAYS_MS[Math.min(attempt, RECONNECT_DELAYS_MS.length - 1)] ?? 8e3;
|
|
132
|
+
await this.wait(delay);
|
|
133
|
+
if (this.disposed) return;
|
|
82
134
|
}
|
|
135
|
+
diagnose(this.diagnostics, "error", `[incanto] multiplayer gave up after ${RECONNECT_ATTEMPTS} reconnect attempts — this client is offline and the others cannot see it. Call connect() again to retry.`);
|
|
83
136
|
} finally {
|
|
84
137
|
this.reconnecting = false;
|
|
85
138
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as PropSchema, dt as Listener, jt as Node } from "./behavior-
|
|
2
|
-
import {
|
|
1
|
+
import { d as PropSchema, dt as Listener, jt as Node } from "./behavior-Dcz0fr1S.js";
|
|
2
|
+
import { t as Rng } from "./rng-Bb-IutXB.js";
|
|
3
3
|
|
|
4
4
|
//#region src/core/boot-failure.d.ts
|
|
5
5
|
/**
|