incanto 0.72.0 → 0.74.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/incanto-check.mjs +114 -42
- package/bin/incanto-verify.mjs +9 -2
- package/dist/2d.d.ts +29 -4
- package/dist/2d.js +3 -3
- package/dist/3d.d.ts +137 -15
- package/dist/3d.js +6 -6
- package/dist/{agent8-BqZ0_O1u.js → agent8-CHTT4unP.js} +1 -1
- package/dist/{audio-player-ioZ7VKC6.d.ts → audio-player-BOrk4eQx.d.ts} +1 -1
- package/dist/{behavior-Bf9P9oB2.d.ts → behavior-J1cmVah0.d.ts} +8 -0
- package/dist/{create-game-CmFAtLZp.js → create-game-BAiA-FjP.js} +7 -7
- package/dist/{create-game-C9rWqqAC.js → create-game-ssvGvP7W.js} +7 -7
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +1 -1
- package/dist/editor.js +965 -893
- package/dist/{environment-presets-BeHoaGhy.js → environment-presets-BkqlWewf.js} +277 -60
- package/dist/{gameplay-BlQe-M07.js → gameplay-Bxe1sMVT.js} +611 -39
- package/dist/gameplay.d.ts +141 -7
- package/dist/gameplay.js +2 -2
- package/dist/index.d.ts +6 -4
- package/dist/index.js +6 -6
- package/dist/{loader-CBfQzB6S.d.ts → loader-BAeWMYfF.d.ts} +1 -1
- package/dist/net.d.ts +2 -2
- package/dist/net.js +2 -2
- package/dist/{physics-2d-DrIgTlLk.js → physics-2d-C-SfvjzH.js} +94 -11
- package/dist/{physics-3d-BzOCw1VS.js → physics-3d-rOzeg890.js} +202 -15
- package/dist/{picking-C9McVJrO.js → picking-BMV34Pjl.js} +2 -2
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{register-5IYfooAN.js → register-CjociOtt.js} +19 -4
- package/dist/{register-C8HuRkOf.js → register-DRQyZKGU.js} +45 -9
- package/dist/{replay-datiAE-b.js → replay-B6BbgGM_.js} +42 -6
- package/dist/{replay-CBEChqXq.d.ts → replay-wZK5Ok5c.d.ts} +1 -1
- package/dist/{save-slots-CEuJPUle.js → save-slots-CEUGeLuB.js} +11 -2
- package/dist/{split-screen-Bm5DTElG.js → split-screen-BxZ5rBe7.js} +4 -4
- package/dist/{split-screen-DkqLng6q.d.ts → split-screen-D6sx8z3Z.d.ts} +2 -2
- package/dist/{sprite-animation-CqR2o3SA.js → sprite-animation-Bz3DHD_4.js} +1 -1
- package/dist/{src-DRSsRleD.js → src-CqtvYtSN.js} +1 -1
- package/dist/{test-Djuq3Vhq.js → test-CEl0y2Sw.js} +162 -30
- package/dist/test.d.ts +56 -5
- package/dist/test.js +2 -2
- package/dist/{touch-BnCyPA0G.js → touch-CioTZB-y.js} +1 -1
- package/dist/vite.js +3 -3
- package/editor/assets/{agent8-CMKz2cax.js → agent8-BlzturGi.js} +1 -1
- package/editor/assets/{debug-DLrQm-az.js → debug-BMUi8usj.js} +1 -1
- package/editor/assets/{index-BEKuxYcE.js → index-CrUCQoaB.js} +53 -53
- package/editor/index.html +1 -1
- package/package.json +1 -1
- package/schemas/scene.schema.json +634 -10
- package/skills/incanto-3d-character.md +113 -5
- package/skills/incanto-assets.md +9 -3
- package/skills/incanto-behaviors-and-scripts.md +26 -2
- package/skills/incanto-building-2d-games.md +9 -0
- package/skills/incanto-building-3d-games.md +45 -0
- package/skills/incanto-editor.md +6 -1
- package/skills/incanto-environment.md +7 -2
- package/skills/incanto-game-feel.md +16 -11
- package/skills/incanto-gameplay-behaviors.md +179 -16
- package/skills/incanto-node-reference.md +124 -45
- package/skills/incanto-physics-and-input.md +67 -5
- package/skills/incanto-scene-json-authoring.md +9 -3
- package/skills/incanto-verifying-your-game.md +19 -2
- package/templates-app/beacon-isle-3d/PROJECT/Status.md +8 -0
- package/templates-app/beacon-isle-3d/PROJECT/Structure.md +3 -0
- package/templates-app/beacon-isle-3d/package.json +1 -1
- package/templates-app/beacon-isle-3d/src/game.scene.json +136 -0
- package/templates-app/beacon-isle-3d/verify.ts +144 -0
- package/templates-app/molehill-2d/package.json +1 -1
- package/templates-app/platformer-2d/PROJECT/Status.md +7 -0
- package/templates-app/platformer-2d/PROJECT/Structure.md +3 -0
- package/templates-app/platformer-2d/package.json +1 -1
- package/templates-app/platformer-2d/src/game.scene.json +126 -0
- package/templates-app/platformer-2d/verify.ts +54 -0
- package/templates-app/star-survivor/package.json +1 -1
- package/templates-app/tps-3d/PROJECT/Context.md +1 -1
- package/templates-app/tps-3d/PROJECT/Status.md +40 -1
- package/templates-app/tps-3d/PROJECT/Structure.md +19 -0
- package/templates-app/tps-3d/package.json +1 -1
- package/templates-app/tps-3d/src/behaviors.ts +9 -0
- package/templates-app/tps-3d/src/cover.scene.json +26 -0
- package/templates-app/tps-3d/src/game.scene.json +331 -75
- package/templates-app/tps-3d/src/main.ts +14 -0
- package/templates-app/tps-3d/src/pillar.scene.json +25 -0
- package/templates-app/tps-3d/verify.ts +582 -3
- package/templates-app/village-quest-3d/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Lt as Signal, b as Engine, jt as Node } from "./behavior-
|
|
1
|
+
import { Lt as Signal, b as Engine, jt as Node } from "./behavior-J1cmVah0.js";
|
|
2
2
|
import { t as DiagnosticSink } from "./diagnostics-Cu85N3tL.js";
|
|
3
3
|
import { a as SceneJson, c as JsonValue, s as JsonObject } from "./rng-Bb-IutXB.js";
|
|
4
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
4
|
+
import { t as LoadSceneOptions } from "./loader-BAeWMYfF.js";
|
|
5
5
|
|
|
6
6
|
//#region src/net/types.d.ts
|
|
7
7
|
type Unsubscribe = () => void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as jsonEquals } from "./json-CfTjpvW8.js";
|
|
2
2
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
3
|
-
import { h as didYouMean } from "./touch-
|
|
3
|
+
import { h as didYouMean } from "./touch-CioTZB-y.js";
|
|
4
4
|
//#region src/core/particle-presets.ts
|
|
5
5
|
const PARTICLE_PRESETS = {
|
|
6
6
|
fire: {
|
|
@@ -199,6 +199,6 @@ async function preloadSceneAssets(assets, title) {
|
|
|
199
199
|
//#endregion
|
|
200
200
|
//#region src/index.ts
|
|
201
201
|
/** Engine version. Kept in sync with package.json by the release pipeline. */
|
|
202
|
-
const VERSION = "0.
|
|
202
|
+
const VERSION = "0.74.0";
|
|
203
203
|
//#endregion
|
|
204
204
|
export { findPath as a, preloadUrls as i, assetUrls as n, gridFromRows as o, preloadSceneAssets as r, VERSION as t };
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { n as jsonEquals, t as jsonClone } from "./json-CfTjpvW8.js";
|
|
2
|
-
import { B as HudLayer, M as resetMemorySaves, O as resolveViewport, V as HudWidgetBase, c as isCloned, h as loadScene, ot as registerBehavior, tt as StubBehavior } from "./save-slots-
|
|
3
|
-
import { v as Engine } from "./register-
|
|
2
|
+
import { B as HudLayer, M as resetMemorySaves, O as resolveViewport, V as HudWidgetBase, c as isCloned, h as loadScene, ot as registerBehavior, tt as StubBehavior } from "./save-slots-CEUGeLuB.js";
|
|
3
|
+
import { v as Engine } from "./register-CjociOtt.js";
|
|
4
4
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
5
5
|
import { t as Rng } from "./rng-CDOMybym.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { t as registerNodes2D } from "./register-
|
|
10
|
-
import { n as registerNodes3D, t as resolveEnvironmentHdri } from "./environment-presets-
|
|
11
|
-
import { a as NetworkManager, c as readSyncKey, i as sanitizeName, n as registerNodesNet, r as NetworkSpawner, s as findOwnerNode, t as createSplitScreen } from "./split-screen-
|
|
6
|
+
import { a as LIGHT_NODE_TYPES, n as startRecording } from "./replay-B6BbgGM_.js";
|
|
7
|
+
import { c as getNodeSchema, d as mergeStaticProps, u as getNodeType } from "./touch-CioTZB-y.js";
|
|
8
|
+
import { et as worldPosition, n as registerGameplayBehaviors } from "./gameplay-Bxe1sMVT.js";
|
|
9
|
+
import { t as registerNodes2D } from "./register-DRQyZKGU.js";
|
|
10
|
+
import { n as registerNodes3D, t as resolveEnvironmentHdri } from "./environment-presets-BkqlWewf.js";
|
|
11
|
+
import { a as NetworkManager, c as readSyncKey, i as sanitizeName, n as registerNodesNet, r as NetworkSpawner, s as findOwnerNode, t as createSplitScreen } from "./split-screen-BxZ5rBe7.js";
|
|
12
12
|
import { Box3, Euler, Frustum, Matrix4, PerspectiveCamera, Quaternion, Ray, Vector3 } from "three";
|
|
13
13
|
//#region src/core/asset-urls.ts
|
|
14
14
|
/** Keys inside a `material` object that hold a texture URL. */
|
|
@@ -90,7 +90,7 @@ function sceneAssetUrls(json) {
|
|
|
90
90
|
*/
|
|
91
91
|
const DEG = Math.PI / 180;
|
|
92
92
|
const CAMERA_TYPES = new Set(["Camera3D"]);
|
|
93
|
-
const LIGHT_TYPES =
|
|
93
|
+
const LIGHT_TYPES = LIGHT_NODE_TYPES;
|
|
94
94
|
/** Screen-space subtrees: they ignore the camera, so framing has nothing to say. */
|
|
95
95
|
const SCREEN_SPACE$1 = new Set(["UILayer", "HudLayer"]);
|
|
96
96
|
/** Depth a 2D collider is given on the axis it does not have. */
|
|
@@ -846,7 +846,7 @@ function framingText(report) {
|
|
|
846
846
|
//#region src/test/picker.ts
|
|
847
847
|
const DEFAULT_VIEW = [960, 540];
|
|
848
848
|
const CAMERAS = new Set(["Camera3D"]);
|
|
849
|
-
const LIGHTS =
|
|
849
|
+
const LIGHTS = LIGHT_NODE_TYPES;
|
|
850
850
|
/**
|
|
851
851
|
* A picker over `scene`, in the scene's own units.
|
|
852
852
|
*
|
|
@@ -2759,12 +2759,14 @@ async function makeProbe(json, opts) {
|
|
|
2759
2759
|
};
|
|
2760
2760
|
const move = opts.moveAction ?? named("moveAction", "vector2") ?? moveOptions[0] ?? null;
|
|
2761
2761
|
const jump = opts.jumpAction ?? named("jumpAction", "button") ?? (declared.some((a) => a.name === "jump" && a.type === "button") ? "jump" : null);
|
|
2762
|
+
const sprint = named("sprintAction", "button") ?? (declared.some((a) => a.name === "sprint" && a.type === "button") ? "sprint" : null);
|
|
2762
2763
|
if (!player) {
|
|
2763
2764
|
session.dispose();
|
|
2764
2765
|
return {
|
|
2765
2766
|
probe: null,
|
|
2766
2767
|
move,
|
|
2767
2768
|
jump,
|
|
2769
|
+
sprint,
|
|
2768
2770
|
moveOptions
|
|
2769
2771
|
};
|
|
2770
2772
|
}
|
|
@@ -2783,10 +2785,15 @@ async function makeProbe(json, opts) {
|
|
|
2783
2785
|
speed: () => {
|
|
2784
2786
|
const v = velocityOf(player);
|
|
2785
2787
|
return Math.hypot(v[0], v[2]);
|
|
2788
|
+
},
|
|
2789
|
+
onFloor: () => {
|
|
2790
|
+
const body = player;
|
|
2791
|
+
return typeof body.isOnFloor === "function" ? body.isOnFloor() : null;
|
|
2786
2792
|
}
|
|
2787
2793
|
},
|
|
2788
2794
|
move,
|
|
2789
2795
|
jump,
|
|
2796
|
+
sprint,
|
|
2790
2797
|
moveOptions
|
|
2791
2798
|
};
|
|
2792
2799
|
}
|
|
@@ -2951,6 +2958,42 @@ function jumpShape(probe, jump, hold = false) {
|
|
|
2951
2958
|
airtimeMs: airtime
|
|
2952
2959
|
};
|
|
2953
2960
|
}
|
|
2961
|
+
/** Frames between presses in a multi-jump probe — long enough for the rise to slow. */
|
|
2962
|
+
const BETWEEN_PRESSES = 15;
|
|
2963
|
+
/**
|
|
2964
|
+
* How high the character goes with EVERY jump spent: press, let the rise slow,
|
|
2965
|
+
* press again, as many times as `maxJumps` allows.
|
|
2966
|
+
*
|
|
2967
|
+
* The presses are spaced because a second press taken at launch speed re-sets
|
|
2968
|
+
* the same velocity and reads as nothing having happened.
|
|
2969
|
+
*/
|
|
2970
|
+
function multiJumpShape(probe, jump, jumps) {
|
|
2971
|
+
settle$1(probe);
|
|
2972
|
+
const floor = probe.pos()[1];
|
|
2973
|
+
let apex = 0;
|
|
2974
|
+
let airtime = null;
|
|
2975
|
+
let pressesLeft = jumps;
|
|
2976
|
+
for (let f = 1; f <= 900; f++) {
|
|
2977
|
+
if (pressesLeft > 0 && (f - 1) % BETWEEN_PRESSES === 0) {
|
|
2978
|
+
probe.engine.input.pressAction(jump);
|
|
2979
|
+
probe.step();
|
|
2980
|
+
probe.engine.input.releaseAction(jump);
|
|
2981
|
+
pressesLeft -= 1;
|
|
2982
|
+
} else probe.step();
|
|
2983
|
+
const h = (probe.pos()[1] - floor) * probe.up;
|
|
2984
|
+
if (h > apex) apex = h;
|
|
2985
|
+
if (pressesLeft === 0 && apex > .02 && h <= .02) {
|
|
2986
|
+
airtime = Math.round(f * STEP_MS);
|
|
2987
|
+
break;
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
const noise = probe.up > 0 ? .02 : 2;
|
|
2991
|
+
if (apex <= noise) return null;
|
|
2992
|
+
return {
|
|
2993
|
+
apex: Number(apex.toFixed(3)),
|
|
2994
|
+
airtimeMs: airtime
|
|
2995
|
+
};
|
|
2996
|
+
}
|
|
2954
2997
|
/**
|
|
2955
2998
|
* How long after leaving the ground a jump still fires — measured, not read.
|
|
2956
2999
|
*
|
|
@@ -2960,7 +3003,7 @@ function jumpShape(probe, jump, hold = false) {
|
|
|
2960
3003
|
* which is the whole point — that was a real bug in this engine's 3D controller
|
|
2961
3004
|
* until 0.37 and the schema looked correct the entire time.
|
|
2962
3005
|
*/
|
|
2963
|
-
async function measureCoyote(json, opts, jump) {
|
|
3006
|
+
async function measureCoyote(json, opts, jump, jumps = 1) {
|
|
2964
3007
|
const fired = async (delayFrames) => {
|
|
2965
3008
|
const { probe } = await makeProbe(json, opts);
|
|
2966
3009
|
if (!probe) return false;
|
|
@@ -2971,16 +3014,26 @@ async function measureCoyote(json, opts, jump) {
|
|
|
2971
3014
|
p[1] + probe.lift * probe.up,
|
|
2972
3015
|
p[2]
|
|
2973
3016
|
];
|
|
3017
|
+
for (let f = 0; f < 4 && probe.onFloor() === true; f++) probe.step();
|
|
2974
3018
|
probe.step(delayFrames);
|
|
2975
|
-
const
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
3019
|
+
const pressFires = () => {
|
|
3020
|
+
const before = probe.vel()[1];
|
|
3021
|
+
probe.engine.input.pressAction(jump);
|
|
3022
|
+
probe.step();
|
|
3023
|
+
probe.engine.input.releaseAction(jump);
|
|
3024
|
+
const after = probe.vel()[1];
|
|
3025
|
+
return after * probe.up > 1 && (after - before) * probe.up > 1;
|
|
3026
|
+
};
|
|
3027
|
+
let all = pressFires();
|
|
3028
|
+
for (let extra = 1; all && extra < jumps; extra++) {
|
|
3029
|
+
probe.step(BETWEEN_PRESSES);
|
|
3030
|
+
all = pressFires();
|
|
3031
|
+
}
|
|
2979
3032
|
probe.session.dispose();
|
|
2980
|
-
return
|
|
3033
|
+
return all;
|
|
2981
3034
|
};
|
|
2982
|
-
if (!await fired(
|
|
2983
|
-
let lo =
|
|
3035
|
+
if (!await fired(0)) return 0;
|
|
3036
|
+
let lo = 0;
|
|
2984
3037
|
let hi = 60;
|
|
2985
3038
|
if (await fired(hi)) return null;
|
|
2986
3039
|
while (hi - lo > 1) {
|
|
@@ -2988,7 +3041,7 @@ async function measureCoyote(json, opts, jump) {
|
|
|
2988
3041
|
if (await fired(mid)) lo = mid;
|
|
2989
3042
|
else hi = mid;
|
|
2990
3043
|
}
|
|
2991
|
-
return Math.round(lo * STEP_MS);
|
|
3044
|
+
return Math.round((lo + 1) * STEP_MS);
|
|
2992
3045
|
}
|
|
2993
3046
|
/**
|
|
2994
3047
|
* `coyoteSeconds` as written in the scene, in ms — for CONTRAST, never instead.
|
|
@@ -3012,13 +3065,36 @@ function declaredCoyote(json) {
|
|
|
3012
3065
|
walk(json?.root);
|
|
3013
3066
|
return found;
|
|
3014
3067
|
}
|
|
3068
|
+
/** `maxJumps` as written in the scene; 1 when it says nothing. */
|
|
3069
|
+
function declaredMaxJumps(json) {
|
|
3070
|
+
let found = 1;
|
|
3071
|
+
const walk = (node) => {
|
|
3072
|
+
if (!node || typeof node !== "object") return;
|
|
3073
|
+
const n = node;
|
|
3074
|
+
if (typeof n.type === "string" && /^CharacterController[23]D$/.test(n.type)) {
|
|
3075
|
+
const value = n.props?.maxJumps;
|
|
3076
|
+
if (typeof value === "number" && value > 1) found = Math.floor(value);
|
|
3077
|
+
}
|
|
3078
|
+
for (const child of n.children ?? []) walk(child);
|
|
3079
|
+
};
|
|
3080
|
+
walk(json?.root);
|
|
3081
|
+
return found;
|
|
3082
|
+
}
|
|
3015
3083
|
/**
|
|
3016
3084
|
* How long BEFORE landing a press still survives.
|
|
3017
3085
|
*
|
|
3018
3086
|
* Same shape: drop the character, press at T frames before it would touch down,
|
|
3019
3087
|
* and check whether it left the ground again afterwards.
|
|
3020
3088
|
*/
|
|
3021
|
-
async function measureBuffer(json, opts, jump) {
|
|
3089
|
+
async function measureBuffer(json, opts, jump, jumps = 1) {
|
|
3090
|
+
const exhaust = (probe) => {
|
|
3091
|
+
for (let i = 0; i < jumps; i++) {
|
|
3092
|
+
probe.step(BETWEEN_PRESSES);
|
|
3093
|
+
probe.engine.input.pressAction(jump);
|
|
3094
|
+
probe.step();
|
|
3095
|
+
probe.engine.input.releaseAction(jump);
|
|
3096
|
+
}
|
|
3097
|
+
};
|
|
3022
3098
|
const survived = async (earlyFrames) => {
|
|
3023
3099
|
const { probe } = await makeProbe(json, opts);
|
|
3024
3100
|
if (!probe) return false;
|
|
@@ -3030,8 +3106,9 @@ async function measureBuffer(json, opts, jump) {
|
|
|
3030
3106
|
floor + drop,
|
|
3031
3107
|
probe.pos()[2]
|
|
3032
3108
|
];
|
|
3109
|
+
if (jumps > 1) exhaust(probe);
|
|
3033
3110
|
let frames = 0;
|
|
3034
|
-
while ((probe.pos()[1] - floor) * probe.up > .05 && frames <
|
|
3111
|
+
while ((probe.pos()[1] - floor) * probe.up > .05 && frames < 400) {
|
|
3035
3112
|
probe.step();
|
|
3036
3113
|
frames += 1;
|
|
3037
3114
|
}
|
|
@@ -3046,6 +3123,7 @@ async function measureBuffer(json, opts, jump) {
|
|
|
3046
3123
|
floor + drop,
|
|
3047
3124
|
p2.pos()[2]
|
|
3048
3125
|
];
|
|
3126
|
+
if (jumps > 1) exhaust(p2);
|
|
3049
3127
|
p2.step(Math.max(0, fallFrames - earlyFrames));
|
|
3050
3128
|
p2.engine.input.pressAction(jump);
|
|
3051
3129
|
p2.step();
|
|
@@ -3073,6 +3151,7 @@ async function feelReport(json, opts = {}) {
|
|
|
3073
3151
|
const first = await makeProbe(json, opts);
|
|
3074
3152
|
const move = first.move;
|
|
3075
3153
|
const jump = first.jump;
|
|
3154
|
+
const sprintAction = first.sprint;
|
|
3076
3155
|
if (!first.probe) return {
|
|
3077
3156
|
player: null,
|
|
3078
3157
|
moveAction: move,
|
|
@@ -3084,12 +3163,16 @@ async function feelReport(json, opts = {}) {
|
|
|
3084
3163
|
turnaroundMs: null,
|
|
3085
3164
|
jumpApex: null,
|
|
3086
3165
|
heldJumpApex: null,
|
|
3166
|
+
walkingJumpApex: null,
|
|
3167
|
+
sprintJumpApex: null,
|
|
3087
3168
|
heldAirtimeMs: null,
|
|
3088
3169
|
timeToApexMs: null,
|
|
3089
3170
|
airtimeMs: null,
|
|
3090
3171
|
coyoteMs: null,
|
|
3091
3172
|
jumpsInMidair: false,
|
|
3092
3173
|
declaredCoyoteMs: null,
|
|
3174
|
+
declaredMaxJumps: 1,
|
|
3175
|
+
doubleJump: null,
|
|
3093
3176
|
jumpBufferMs: null,
|
|
3094
3177
|
inputToMotionFrames: null,
|
|
3095
3178
|
moveAxis: null,
|
|
@@ -3188,8 +3271,12 @@ async function feelReport(json, opts = {}) {
|
|
|
3188
3271
|
};
|
|
3189
3272
|
let shape = NO_SHAPE;
|
|
3190
3273
|
let held = NO_SHAPE;
|
|
3274
|
+
let walking = NO_SHAPE;
|
|
3275
|
+
let sprinting = NO_SHAPE;
|
|
3191
3276
|
let coyote = null;
|
|
3192
3277
|
let buffer = null;
|
|
3278
|
+
const jumps = declaredMaxJumps(json);
|
|
3279
|
+
let doubleJump = null;
|
|
3193
3280
|
if (jump) {
|
|
3194
3281
|
const d = await fresh();
|
|
3195
3282
|
if (d) {
|
|
@@ -3203,8 +3290,33 @@ async function feelReport(json, opts = {}) {
|
|
|
3203
3290
|
collect(h);
|
|
3204
3291
|
h.session.dispose();
|
|
3205
3292
|
}
|
|
3206
|
-
|
|
3207
|
-
|
|
3293
|
+
if (action) {
|
|
3294
|
+
const w = await fresh();
|
|
3295
|
+
if (w) {
|
|
3296
|
+
w.engine.input.setActionVector(action, 1, 0);
|
|
3297
|
+
walking = jumpShape(w, jump, true);
|
|
3298
|
+
w.session.dispose();
|
|
3299
|
+
}
|
|
3300
|
+
if (sprintAction) {
|
|
3301
|
+
const sp = await fresh();
|
|
3302
|
+
if (sp) {
|
|
3303
|
+
sp.engine.input.setActionVector(action, 1, 0);
|
|
3304
|
+
sp.engine.input.pressAction(sprintAction);
|
|
3305
|
+
sprinting = jumpShape(sp, jump, true);
|
|
3306
|
+
sp.session.dispose();
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
}
|
|
3310
|
+
if (jumps > 1) {
|
|
3311
|
+
const m = await fresh();
|
|
3312
|
+
if (m) {
|
|
3313
|
+
doubleJump = multiJumpShape(m, jump, jumps);
|
|
3314
|
+
collect(m);
|
|
3315
|
+
m.session.dispose();
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
coyote = await measureCoyote(json, opts, jump, jumps);
|
|
3319
|
+
buffer = await measureBuffer(json, opts, jump, jumps);
|
|
3208
3320
|
}
|
|
3209
3321
|
return {
|
|
3210
3322
|
player: playerPath,
|
|
@@ -3218,6 +3330,8 @@ async function feelReport(json, opts = {}) {
|
|
|
3218
3330
|
jumpApex: shape.apex,
|
|
3219
3331
|
heldJumpApex: held.apex,
|
|
3220
3332
|
heldAirtimeMs: held.airtimeMs,
|
|
3333
|
+
walkingJumpApex: walking.apex,
|
|
3334
|
+
sprintJumpApex: sprinting.apex,
|
|
3221
3335
|
timeToApexMs: shape.toApexMs,
|
|
3222
3336
|
airtimeMs: shape.airtimeMs,
|
|
3223
3337
|
coyoteMs: coyote,
|
|
@@ -3225,6 +3339,8 @@ async function feelReport(json, opts = {}) {
|
|
|
3225
3339
|
declaredCoyoteMs: declaredCoyote(json),
|
|
3226
3340
|
jumpBufferMs: buffer,
|
|
3227
3341
|
inputToMotionFrames: latency,
|
|
3342
|
+
declaredMaxJumps: jumps,
|
|
3343
|
+
doubleJump,
|
|
3228
3344
|
moveAxis: axis,
|
|
3229
3345
|
moveTried: tried,
|
|
3230
3346
|
errorMessages: [...said.errors],
|
|
@@ -3260,7 +3376,12 @@ function feelText(report) {
|
|
|
3260
3376
|
lines.push("");
|
|
3261
3377
|
lines.push(` jump apex ${report.jumpApex === null ? "— (nothing left the ground)" : `${report.jumpApex} u (tapped)`}`);
|
|
3262
3378
|
const cut = report.heldJumpApex !== null && report.jumpApex !== null && Math.abs(report.heldJumpApex - report.jumpApex) > .02;
|
|
3263
|
-
if (cut) lines.push(` held apex ${report.heldJumpApex} u
|
|
3379
|
+
if (cut) lines.push(` held apex ${report.heldJumpApex} u (standing)`);
|
|
3380
|
+
if (report.walkingJumpApex !== null || report.sprintJumpApex !== null) {
|
|
3381
|
+
const parts = [report.walkingJumpApex !== null ? `${report.walkingJumpApex} u walking` : null, report.sprintJumpApex !== null ? `${report.sprintJumpApex} u sprinting` : null].filter((x) => x !== null);
|
|
3382
|
+
lines.push(` moving apex ${parts.join(" · ")} ← size your level against the LARGEST`);
|
|
3383
|
+
} else if (cut) lines.push(" (size your level against the held apex — this scene declares no move action)");
|
|
3384
|
+
if (report.doubleJump) lines.push(` ${report.declaredMaxJumps === 2 ? "double jump" : `${report.declaredMaxJumps} jumps`} ${report.doubleJump.apex} u (${report.declaredMaxJumps} TAPS, maxJumps ${report.declaredMaxJumps}${report.doubleJump.airtimeMs !== null ? `, ${ms(report.doubleJump.airtimeMs)} airtime` : ""})`);
|
|
3264
3385
|
lines.push(` time to apex ${ms(report.timeToApexMs)}`);
|
|
3265
3386
|
lines.push(` airtime ${ms(report.airtimeMs)}${cut && report.heldAirtimeMs !== null ? ` (${ms(report.heldAirtimeMs)} held)` : ""}`);
|
|
3266
3387
|
lines.push(` coyote window ${report.jumpsInMidair ? "not measurable — this character jumps in MID-AIR" : report.coyoteMs === null ? "always (no window)" : ms(report.coyoteMs)}`);
|
|
@@ -3389,8 +3510,8 @@ async function playMultiplayer(opts) {
|
|
|
3389
3510
|
*/
|
|
3390
3511
|
async function joinLate(server, first, opts) {
|
|
3391
3512
|
try {
|
|
3392
|
-
const { Engine } = await import("./register-
|
|
3393
|
-
const { loadScene } = await import("./save-slots-
|
|
3513
|
+
const { Engine } = await import("./register-CjociOtt.js").then((n) => n.y);
|
|
3514
|
+
const { loadScene } = await import("./save-slots-CEUGeLuB.js").then((n) => n.g);
|
|
3394
3515
|
const { jsonClone } = await import("./json-CfTjpvW8.js").then((n) => n.i);
|
|
3395
3516
|
const engine = new Engine(opts.seed !== void 0 ? { seed: opts.seed + 999 } : {});
|
|
3396
3517
|
engine.setScene(loadScene(jsonClone(opts.scene), opts.load));
|
|
@@ -3988,13 +4109,14 @@ async function runScript(json, opts) {
|
|
|
3988
4109
|
if (opts.locale) engine.locale.locale = opts.locale;
|
|
3989
4110
|
const physics = opts.physics ?? "auto";
|
|
3990
4111
|
if (physics === "2d" || physics === "auto" && scene.dimension === "2d") {
|
|
3991
|
-
const { enablePhysics2D } = await import("./physics-2d-
|
|
4112
|
+
const { enablePhysics2D } = await import("./physics-2d-C-SfvjzH.js").then((n) => n.r);
|
|
3992
4113
|
await enablePhysics2D(engine);
|
|
3993
4114
|
} else if (physics === "3d" || physics === "auto" && scene.dimension === "3d") {
|
|
3994
|
-
const { enablePhysics3D } = await import("./physics-3d-
|
|
4115
|
+
const { enablePhysics3D } = await import("./physics-3d-rOzeg890.js").then((n) => n.r);
|
|
3995
4116
|
await enablePhysics3D(engine);
|
|
3996
4117
|
}
|
|
3997
4118
|
const failures = [];
|
|
4119
|
+
const stalled = [];
|
|
3998
4120
|
const snapshots = [];
|
|
3999
4121
|
const live = () => engine.scene ?? scene;
|
|
4000
4122
|
const ctx = {
|
|
@@ -4004,6 +4126,7 @@ async function runScript(json, opts) {
|
|
|
4004
4126
|
},
|
|
4005
4127
|
timeMs: 0,
|
|
4006
4128
|
getNode: (path) => live().root.getNode(path),
|
|
4129
|
+
getNodeOrNull: (path) => live().root.getNodeOrNull(path),
|
|
4007
4130
|
capture: () => captureScene(live())
|
|
4008
4131
|
};
|
|
4009
4132
|
/** Is `hit` the node we aimed at, or something of its own? */
|
|
@@ -4111,6 +4234,7 @@ async function runScript(json, opts) {
|
|
|
4111
4234
|
engine.input.handleMouseButton(releaseButton, true);
|
|
4112
4235
|
releaseAt = tick + 1;
|
|
4113
4236
|
}
|
|
4237
|
+
const frozenBefore = engine.timeScale === 0;
|
|
4114
4238
|
step.do?.(ctx);
|
|
4115
4239
|
if (step.assert) try {
|
|
4116
4240
|
const verdict = assertVerdict(step.assert(ctx));
|
|
@@ -4126,6 +4250,11 @@ async function runScript(json, opts) {
|
|
|
4126
4250
|
message: e instanceof Error ? e.message : String(e)
|
|
4127
4251
|
});
|
|
4128
4252
|
}
|
|
4253
|
+
if ((step.do || step.assert) && (frozenBefore || engine.timeScale === 0)) stalled.push({
|
|
4254
|
+
atMs: step.atMs,
|
|
4255
|
+
label: step.label,
|
|
4256
|
+
before: frozenBefore
|
|
4257
|
+
});
|
|
4129
4258
|
};
|
|
4130
4259
|
const stepMs = 1e3 / (opts.fixedHz ?? 60);
|
|
4131
4260
|
const totalTicks = Math.round(opts.durationMs / stepMs);
|
|
@@ -4178,6 +4307,7 @@ async function runScript(json, opts) {
|
|
|
4178
4307
|
return {
|
|
4179
4308
|
ok,
|
|
4180
4309
|
failures,
|
|
4310
|
+
stalled,
|
|
4181
4311
|
snapshots,
|
|
4182
4312
|
logs,
|
|
4183
4313
|
finalCapture,
|
|
@@ -4186,10 +4316,12 @@ async function runScript(json, opts) {
|
|
|
4186
4316
|
const budget = Math.abs(simulatedMs - opts.durationMs) > Math.max(50, opts.durationMs * .02) ? ` (of ${opts.durationMs}ms of steps — the game clock ran slower, or stopped)` : "";
|
|
4187
4317
|
const head = `run ${ok ? "OK" : "FAILED"} — ${simulatedMs}ms simulated${budget}, ${failures.length} failure(s), ${logs.length} log(s)`;
|
|
4188
4318
|
const fails = failures.map((f) => ` ✗ at ${f.atMs}ms${f.label ? ` [${f.label}]` : ""}: ${f.message}`);
|
|
4319
|
+
const stopped = stalled.map((s) => ` ! at ${s.atMs}ms${s.label ? ` [${s.label}]` : ""}: the clock was stopped ${s.before ? "when this step ran" : "by the time this step finished"} (timeScale 0 — a terminal GameFlow state or a pause holds it), so engine.step() advanced nothing and every value read here is the last one before it stopped. Restart the flow, or measure before the game ends.`);
|
|
4189
4320
|
const noisy = engineWarnings.map((l) => ` ! ${l.level}: ${l.parts.map((p) => typeof p === "string" ? p : String(p)).join(" ")}`);
|
|
4190
4321
|
return [
|
|
4191
4322
|
head,
|
|
4192
4323
|
...fails,
|
|
4324
|
+
...stopped,
|
|
4193
4325
|
...noisy,
|
|
4194
4326
|
describeCapture(finalCapture)
|
|
4195
4327
|
].join("\n");
|
|
@@ -4218,10 +4350,10 @@ async function createPlaySession(json, opts = {}) {
|
|
|
4218
4350
|
engine.setScene(scene);
|
|
4219
4351
|
const physics = opts.physics ?? "auto";
|
|
4220
4352
|
if (physics === "2d" || physics === "auto" && scene.dimension === "2d") {
|
|
4221
|
-
const { enablePhysics2D } = await import("./physics-2d-
|
|
4353
|
+
const { enablePhysics2D } = await import("./physics-2d-C-SfvjzH.js").then((n) => n.r);
|
|
4222
4354
|
await enablePhysics2D(engine);
|
|
4223
4355
|
} else if (physics === "3d" || physics === "auto" && scene.dimension === "3d") {
|
|
4224
|
-
const { enablePhysics3D } = await import("./physics-3d-
|
|
4356
|
+
const { enablePhysics3D } = await import("./physics-3d-rOzeg890.js").then((n) => n.r);
|
|
4225
4357
|
await enablePhysics3D(engine);
|
|
4226
4358
|
}
|
|
4227
4359
|
const stepMs = 1e3 / (opts.fixedHz ?? 60);
|
package/dist/test.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { P as Scene$1, Pt as LogEntry, b as Engine, jt as Node, n as BehaviorCtor } from "./behavior-
|
|
1
|
+
import { P as Scene$1, Pt as LogEntry, b as Engine, jt as Node, n as BehaviorCtor } from "./behavior-J1cmVah0.js";
|
|
2
2
|
import { a as SceneJson, c as JsonValue, s as JsonObject } from "./rng-Bb-IutXB.js";
|
|
3
|
-
import { t as LoadSceneOptions } from "./loader-
|
|
4
|
-
import { l as auditScene, o as IncantoError, r as ReplayJson, u as instancedScenes } from "./replay-
|
|
5
|
-
import { l as LocalGameServerOptions, n as SplitScreenPlayer } from "./split-screen-
|
|
3
|
+
import { t as LoadSceneOptions } from "./loader-BAeWMYfF.js";
|
|
4
|
+
import { l as auditScene, o as IncantoError, r as ReplayJson, u as instancedScenes } from "./replay-wZK5Ok5c.js";
|
|
5
|
+
import { l as LocalGameServerOptions, n as SplitScreenPlayer } from "./split-screen-D6sx8z3Z.js";
|
|
6
6
|
import { Matrix4, Vector3 } from "three";
|
|
7
7
|
|
|
8
8
|
//#region src/core/asset-urls.d.ts
|
|
@@ -453,6 +453,16 @@ interface FeelReport {
|
|
|
453
453
|
heldJumpApex: number | null;
|
|
454
454
|
/** Airtime with the button held. */
|
|
455
455
|
heldAirtimeMs: number | null;
|
|
456
|
+
/**
|
|
457
|
+
* The held apex while WALKING and while SPRINTING. `sprintJumpMultiplier`
|
|
458
|
+
* scales with the keyboard's intensity (0.6 for any move key, 1 with sprint),
|
|
459
|
+
* so a moving jump is higher than the standing one the other rows measure —
|
|
460
|
+
* +26% walking, +44% sprinting at the defaults — and a ledge sized against
|
|
461
|
+
* the standing apex is cleared by anyone holding a direction. Null when the
|
|
462
|
+
* scene declares no move (or sprint) action.
|
|
463
|
+
*/
|
|
464
|
+
walkingJumpApex: number | null;
|
|
465
|
+
sprintJumpApex: number | null;
|
|
456
466
|
timeToApexMs: number | null;
|
|
457
467
|
/** Launch → back on the ground. */
|
|
458
468
|
airtimeMs: number | null;
|
|
@@ -492,6 +502,27 @@ interface FeelReport {
|
|
|
492
502
|
jumpBufferMs: number | null;
|
|
493
503
|
/** Frames between the press and the first movement. */
|
|
494
504
|
inputToMotionFrames: number | null;
|
|
505
|
+
/**
|
|
506
|
+
* `maxJumps` as the scene declares it (1 when it says nothing) — read, like
|
|
507
|
+
* `declaredCoyoteMs`, and for the same reason: the probes below have to know
|
|
508
|
+
* how many presses a character has before they can tell a coyote jump from
|
|
509
|
+
* an air jump.
|
|
510
|
+
*/
|
|
511
|
+
declaredMaxJumps: number;
|
|
512
|
+
/**
|
|
513
|
+
* MEASURED: the apex and airtime with EVERY declared jump spent — press,
|
|
514
|
+
* rise, press again. Null when the controller declares one jump.
|
|
515
|
+
*
|
|
516
|
+
* The moment a scene wrote `maxJumps: 2`, this report gave up on two of its
|
|
517
|
+
* numbers ("not measurable — this character jumps in MID-AIR") and called a
|
|
518
|
+
* third suspect, while the scene said exactly why in the line above. A
|
|
519
|
+
* double jump is the 3D character skill's own recommendation; the instrument
|
|
520
|
+
* has to survive it.
|
|
521
|
+
*/
|
|
522
|
+
doubleJump: {
|
|
523
|
+
apex: number;
|
|
524
|
+
airtimeMs: number | null;
|
|
525
|
+
} | null;
|
|
495
526
|
}
|
|
496
527
|
declare function feelReport(json: unknown, opts?: FeelOptions): Promise<FeelReport>;
|
|
497
528
|
/** Numbers, not grades. What "good" means here is a genre decision. */
|
|
@@ -1144,6 +1175,8 @@ interface RunContext {
|
|
|
1144
1175
|
timeMs: number;
|
|
1145
1176
|
/** Resolve a node path relative to the scene root. */
|
|
1146
1177
|
getNode(path: string): Node;
|
|
1178
|
+
/** The same lookup, null for a node that is not there — a gem already taken, a foe already dead. */
|
|
1179
|
+
getNodeOrNull(path: string): Node | null;
|
|
1147
1180
|
/** Snapshot the scene right now. */
|
|
1148
1181
|
capture(): SceneCapture;
|
|
1149
1182
|
}
|
|
@@ -1225,6 +1258,22 @@ interface RunFailure {
|
|
|
1225
1258
|
label?: string;
|
|
1226
1259
|
message: string;
|
|
1227
1260
|
}
|
|
1261
|
+
/**
|
|
1262
|
+
* A `do:`/`assert:` step that ran with the game clock STOPPED.
|
|
1263
|
+
*
|
|
1264
|
+
* `GameFlow` sets `timeScale = 0` on a win or a loss (and a pause menu does the
|
|
1265
|
+
* same), after which `engine.step()` advances nothing. A harness that lost its
|
|
1266
|
+
* player three times inside one step then measured `0.00` for everything
|
|
1267
|
+
* after — the position it had just teleported to, no travel, no apex — and
|
|
1268
|
+
* the run was `ok` with nothing said beside the zeros. `before` is whether the
|
|
1269
|
+
* clock was already stopped when the step began (every read in it was stale)
|
|
1270
|
+
* or stopped by the time it finished (the step itself ended the game).
|
|
1271
|
+
*/
|
|
1272
|
+
interface RunStalled {
|
|
1273
|
+
atMs: number;
|
|
1274
|
+
label?: string;
|
|
1275
|
+
before: boolean;
|
|
1276
|
+
}
|
|
1228
1277
|
interface RunScriptOptions {
|
|
1229
1278
|
/** Total simulated duration in ms. */
|
|
1230
1279
|
durationMs: number;
|
|
@@ -1253,6 +1302,8 @@ interface RunResult {
|
|
|
1253
1302
|
/** True when no step assertion failed. */
|
|
1254
1303
|
ok: boolean;
|
|
1255
1304
|
failures: RunFailure[];
|
|
1305
|
+
/** Steps that ran with the clock stopped — see `RunStalled`. Not failures. */
|
|
1306
|
+
stalled: RunStalled[];
|
|
1256
1307
|
snapshots: Array<{
|
|
1257
1308
|
atMs: number;
|
|
1258
1309
|
capture: SceneCapture;
|
|
@@ -1309,4 +1360,4 @@ interface PlaySession {
|
|
|
1309
1360
|
*/
|
|
1310
1361
|
declare function createPlaySession(json: unknown, opts?: PlaySessionOptions): Promise<PlaySession>;
|
|
1311
1362
|
//#endregion
|
|
1312
|
-
export { type AgreementSnapshot, type CollectionSnapshot, type Disagreement, type DisagreementKind, type FacingOptions, type FacingReport, type FeelOptions, type FeelReport, type FramingEntry, type FramingOptions, type FramingReport, GroundingIssue, GroundingOptions, type LadderVerdict, type MultiplayOptions, type MultiplayPlayer, type MultiplayReport, NodeCapture, type Outcome, type PickerOptions, PlaySession, PlaySessionOptions, type PlaytestOptions, type PlaytestReport, type PlaytestRun, RunContext, RunFailure, RunResult, RunScriptOptions, type RungResult, type RungStatus, type SceneAssetUrl, SceneCapture, ScriptStep, ValidateSceneOptions, ValidationResult, type Where, agreementProblems, auditScene, captureScene, collectionProblems, createPlaySession, describeCapture, describeFraming, facingReport, facingText, failingReplays, feelReport, feelText, feelsRung, findFloatingProps, findPlayer, firstLine, framingText, geometricPicker, geometricView, instancedScenes, ladderText, ladderVerdict, multiplayProblems, multiplayText, playMultiplayer, playtest, playtestFailed, playtestText, pointAtNode, registerAllNodes, runScript, saysRung, sceneAssetUrls, takeAgreementSnapshots, takeCollectionSnapshots, unmeasuredPlays, validateScene };
|
|
1363
|
+
export { type AgreementSnapshot, type CollectionSnapshot, type Disagreement, type DisagreementKind, type FacingOptions, type FacingReport, type FeelOptions, type FeelReport, type FramingEntry, type FramingOptions, type FramingReport, GroundingIssue, GroundingOptions, type LadderVerdict, type MultiplayOptions, type MultiplayPlayer, type MultiplayReport, NodeCapture, type Outcome, type PickerOptions, PlaySession, PlaySessionOptions, type PlaytestOptions, type PlaytestReport, type PlaytestRun, RunContext, RunFailure, RunResult, RunScriptOptions, RunStalled, type RungResult, type RungStatus, type SceneAssetUrl, SceneCapture, ScriptStep, ValidateSceneOptions, ValidationResult, type Where, agreementProblems, auditScene, captureScene, collectionProblems, createPlaySession, describeCapture, describeFraming, facingReport, facingText, failingReplays, feelReport, feelText, feelsRung, findFloatingProps, findPlayer, firstLine, framingText, geometricPicker, geometricView, instancedScenes, ladderText, ladderVerdict, multiplayProblems, multiplayText, playMultiplayer, playtest, playtestFailed, playtestText, pointAtNode, registerAllNodes, runScript, saysRung, sceneAssetUrls, takeAgreementSnapshots, takeCollectionSnapshots, unmeasuredPlays, validateScene };
|
package/dist/test.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { i as instancedScenes, r as auditScene } from "./replay-
|
|
2
|
-
import { A as geometricPicker, C as facingReport, D as playtest, E as findPlayer, F as sceneAssetUrls, M as pointAtNode, N as describeFraming, O as playtestFailed, P as framingText, S as collectionProblems, T as failingReplays, _ as feelReport, a as registerAllNodes, b as takeCollectionSnapshots, c as feelsRung, d as ladderVerdict, f as saysRung, g as playMultiplayer, h as multiplayText, i as findFloatingProps, j as geometricView, k as playtestText, l as firstLine, m as multiplayProblems, n as createPlaySession, o as runScript, p as unmeasuredPlays, r as describeCapture, s as validateScene, t as captureScene, u as ladderText, v as feelText, w as facingText, x as agreementProblems, y as takeAgreementSnapshots } from "./test-
|
|
1
|
+
import { i as instancedScenes, r as auditScene } from "./replay-B6BbgGM_.js";
|
|
2
|
+
import { A as geometricPicker, C as facingReport, D as playtest, E as findPlayer, F as sceneAssetUrls, M as pointAtNode, N as describeFraming, O as playtestFailed, P as framingText, S as collectionProblems, T as failingReplays, _ as feelReport, a as registerAllNodes, b as takeCollectionSnapshots, c as feelsRung, d as ladderVerdict, f as saysRung, g as playMultiplayer, h as multiplayText, i as findFloatingProps, j as geometricView, k as playtestText, l as firstLine, m as multiplayProblems, n as createPlaySession, o as runScript, p as unmeasuredPlays, r as describeCapture, s as validateScene, t as captureScene, u as ladderText, v as feelText, w as facingText, x as agreementProblems, y as takeAgreementSnapshots } from "./test-CEl0y2Sw.js";
|
|
3
3
|
export { agreementProblems, auditScene, captureScene, collectionProblems, createPlaySession, describeCapture, describeFraming, facingReport, facingText, failingReplays, feelReport, feelText, feelsRung, findFloatingProps, findPlayer, firstLine, framingText, geometricPicker, geometricView, instancedScenes, ladderText, ladderVerdict, multiplayProblems, multiplayText, playMultiplayer, playtest, playtestFailed, playtestText, pointAtNode, registerAllNodes, runScript, saysRung, sceneAssetUrls, takeAgreementSnapshots, takeCollectionSnapshots, unmeasuredPlays, validateScene };
|
|
@@ -116,7 +116,7 @@ function validatePropValue(value, def, at, options, kinds) {
|
|
|
116
116
|
validOptions: [...options]
|
|
117
117
|
});
|
|
118
118
|
const expected = jsonKind(def);
|
|
119
|
-
if (expected === "null") return;
|
|
119
|
+
if (expected === "null" && !kinds) return;
|
|
120
120
|
const actual = jsonKind(value);
|
|
121
121
|
const accepted = kinds ?? [expected];
|
|
122
122
|
if (!accepted.includes(actual)) throw new IncantoError("PROP_TYPE_MISMATCH", `Prop '${at}' expects ${listKinds(accepted)} (default ${JSON.stringify(def)}), got ${actual} (${JSON.stringify(value)}).`, { prop: at });
|
package/dist/vite.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { a as parseJsonText } from "./json-CfTjpvW8.js";
|
|
2
|
-
import { k as newUid } from "./save-slots-
|
|
2
|
+
import { k as newUid } from "./save-slots-CEUGeLuB.js";
|
|
3
3
|
import { t as IncantoError } from "./errors-BpWbnbb_.js";
|
|
4
|
-
import { t as VERSION } from "./src-
|
|
4
|
+
import { t as VERSION } from "./src-CqtvYtSN.js";
|
|
5
5
|
import { n as diffSignatures } from "./frame-report-D-_7YF2G.js";
|
|
6
|
-
import { s as validateScene } from "./test-
|
|
6
|
+
import { s as validateScene } from "./test-CEl0y2Sw.js";
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { basename, dirname, extname, join, normalize, relative, resolve, sep } from "node:path";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{i as e,n as t}from"./index-
|
|
1
|
+
import{i as e,n as t}from"./index-CrUCQoaB.js";async function n(e,n){return new a((await t(()=>import(`./GameServer-C56iOUgF.js`),[],import.meta.url)).GameServer,e,{diagnostics:n})}var r=[500,1e3,2e3,4e3,8e3],i=8,a=class{raw;active=new Map;reconnecting=!1;disposed=!1;diagnostics;wait;constructor(e,t,n){this.diagnostics=n?.diagnostics??null,this.wait=n?.wait??(e=>new Promise(t=>{setTimeout(t,e)})),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{for(let t=0;t<i;t++){let n=!1,i=null;try{n=await this.rawConnect()!==!1}catch(e){i=e}if(this.disposed)return;if(n){for(let e of this.active.values())e.off(),e.off=e.make();t>0&&e(this.diagnostics,`info`,`[incanto] multiplayer reconnected after ${t+1} attempts.`);return}t===0&&e(this.diagnostics,`warn`,`[incanto] the multiplayer connection dropped and the server would not take it back${i?` (${i instanceof Error?i.message:String(i)})`:``}. Retrying — other players cannot see this one until it comes back.`);let a=r[Math.min(t,r.length-1)]??8e3;if(await this.wait(a),this.disposed)return}e(this.diagnostics,`error`,`[incanto] multiplayer gave up after ${i} reconnect attempts — this client is offline and the others cannot see it. Call connect() again to retry.`)}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{n as createAgent8Server};
|