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.
Files changed (147) hide show
  1. package/bin/_behaviors-loader.mjs +22 -0
  2. package/bin/_read-json.mjs +28 -0
  3. package/bin/incanto-assets.mjs +5 -4
  4. package/bin/incanto-check.mjs +58 -31
  5. package/bin/incanto-editor.mjs +128 -5
  6. package/bin/incanto-env.mjs +3 -2
  7. package/bin/incanto-feel.mjs +24 -13
  8. package/bin/incanto-frame.mjs +8 -1
  9. package/bin/incanto-multiplay.mjs +11 -9
  10. package/bin/incanto-new.mjs +105 -10
  11. package/bin/incanto-play.mjs +158 -16
  12. package/bin/incanto-playtest.mjs +66 -23
  13. package/bin/incanto-skills.mjs +14 -2
  14. package/bin/incanto-verify.mjs +121 -102
  15. package/bin/incanto.mjs +3 -2
  16. package/dist/2d.d.ts +296 -34
  17. package/dist/2d.js +4 -4
  18. package/dist/3d.d.ts +157 -9
  19. package/dist/3d.js +8 -8
  20. package/dist/{agent8-CvsfVskX.js → agent8-Cfmd3ar_.js} +61 -8
  21. package/dist/{audio-player-C0j2k-yB.d.ts → audio-player-L8yccdMP.d.ts} +2 -2
  22. package/dist/{behavior-rm8vVzu_.d.ts → behavior-Dcz0fr1S.d.ts} +755 -46
  23. package/dist/{create-game-CwxEDlCm.js → create-game-CH4kt78v.js} +143 -60
  24. package/dist/{create-game-CvJ1wSRP.js → create-game-LCHBLfA4.js} +98 -48
  25. package/dist/debug.d.ts +1 -1
  26. package/dist/debug.js +2 -3
  27. package/dist/diagnostics-Cu85N3tL.d.ts +12 -0
  28. package/dist/{editor-switch-CnIOiyNJ.d.ts → editor-switch-CFU9mCec.d.ts} +22 -13
  29. package/dist/editor.js +1088 -882
  30. package/dist/env.d.ts +1 -1
  31. package/dist/env.js +5 -3
  32. package/dist/{environment-presets-BO-7XoFV.js → environment-presets-99BzP_L-.js} +298 -45
  33. package/dist/{frame-report-Dlq13Gyj.js → frame-report-D-_7YF2G.js} +1 -1
  34. package/dist/{gameplay-D1KixWK8.js → gameplay-CNULJvwh.js} +914 -214
  35. package/dist/gameplay.d.ts +254 -10
  36. package/dist/gameplay.js +2 -2
  37. package/dist/{heightmap-CRK0M4jT.js → heightmap-BYgD5Edk.js} +1 -1
  38. package/dist/index.d.ts +179 -13
  39. package/dist/index.js +10 -12
  40. package/dist/json-CfTjpvW8.js +67 -0
  41. package/dist/{loader-DadV2QCT.d.ts → loader-8-IHvbKD.d.ts} +2 -2
  42. package/dist/net.d.ts +27 -3
  43. package/dist/net.js +2 -2
  44. package/dist/{noise-CGUMx44x.js → noise-D3nPpmFg.js} +1 -1
  45. package/dist/{physics-2d-CF5yyjbj.js → physics-2d-FhrXUc6B.js} +136 -11
  46. package/dist/{physics-3d-DbYaEcZy.js → physics-3d-CFEGxBXZ.js} +104 -23
  47. package/dist/{teardown-CMqFVxO9.js → picking-DVo7fI13.js} +104 -13
  48. package/dist/react.d.ts +2 -2
  49. package/dist/react.js +2 -2
  50. package/dist/{register-DbVArsns.js → register-BYQCBySi.js} +429 -28
  51. package/dist/{register-mmfugpaQ.js → register-DuVdzxbq.js} +594 -831
  52. package/dist/{replay-BEHLDcQV.js → replay-DEvp3kyV.js} +224 -14
  53. package/dist/{replay-BQfkX4x7.d.ts → replay-F7IZHdFR.d.ts} +20 -3
  54. package/dist/{schema-B6ugCV1Q.d.ts → rng-Bb-IutXB.d.ts} +38 -21
  55. package/dist/{rng-DP-SR7eg.js → rng-CDOMybym.js} +22 -0
  56. package/dist/{loader-DZE7B07H.js → save-slots-Bvuh2p_r.js} +4619 -2318
  57. package/dist/{split-screen-Cg76MCV5.d.ts → split-screen-CIYf1zSf.d.ts} +36 -4
  58. package/dist/{split-screen-CauMwu6y.js → split-screen-eULetcg-.js} +159 -26
  59. package/dist/{sprite-animation-CY-mrr1L.js → sprite-animation-CqR2o3SA.js} +39 -8
  60. package/dist/{src-CYEu-_S9.js → src-_jk0qLsS.js} +2 -17
  61. package/dist/test-CmN54kWv.js +4264 -0
  62. package/dist/test.d.ts +639 -30
  63. package/dist/test.js +3 -3
  64. package/dist/touch-BnCyPA0G.js +519 -0
  65. package/dist/vite.d.ts +20 -37
  66. package/dist/vite.js +177 -7
  67. package/dist/{webgl-unavailable-Z5_g8x9H.js → webgl-unavailable-C8aDbGmR.js} +44 -0
  68. package/editor/assets/agent8-yLIEYHbd.js +1 -0
  69. package/editor/assets/{debug-CMULinBW.js → debug-u31w_yhq.js} +2 -2
  70. package/editor/assets/index-DK9xMGpW.js +11046 -0
  71. package/editor/index.html +1 -1
  72. package/package.json +4 -14
  73. package/schemas/scene.schema.json +34 -3
  74. package/skills/incanto-3d-character.md +14 -1
  75. package/skills/incanto-3d-models.md +12 -0
  76. package/skills/incanto-assets.md +9 -1
  77. package/skills/incanto-audio.md +8 -2
  78. package/skills/incanto-behaviors-and-scripts.md +105 -7
  79. package/skills/incanto-building-2d-games.md +97 -10
  80. package/skills/incanto-building-3d-games.md +58 -4
  81. package/skills/incanto-editor.md +46 -7
  82. package/skills/incanto-environment.md +19 -1
  83. package/skills/incanto-game-feel.md +70 -0
  84. package/skills/incanto-gameplay-behaviors.md +172 -20
  85. package/skills/incanto-hud.md +142 -7
  86. package/skills/incanto-localization.md +13 -5
  87. package/skills/incanto-multiplayer.md +83 -3
  88. package/skills/incanto-node-reference.md +239 -59
  89. package/skills/incanto-performance.md +52 -0
  90. package/skills/incanto-physics-and-input.md +123 -24
  91. package/skills/incanto-playtesting.md +112 -2
  92. package/skills/incanto-save-slots.md +217 -7
  93. package/skills/incanto-scene-json-authoring.md +69 -12
  94. package/skills/incanto-verifying-your-game.md +207 -10
  95. package/skills/incanto-web-integration.md +28 -0
  96. package/skills/incanto-your-first-game.md +3 -1
  97. package/templates-app/beacon-isle-3d/generate-world.ts +77 -9
  98. package/templates-app/beacon-isle-3d/package.json +2 -2
  99. package/templates-app/beacon-isle-3d/src/behaviors.ts +22 -0
  100. package/templates-app/beacon-isle-3d/src/game.scene.json +143 -600
  101. package/templates-app/beacon-isle-3d/src/main.ts +11 -1
  102. package/templates-app/beacon-isle-3d/tsconfig.json +1 -1
  103. package/templates-app/beacon-isle-3d/verify.ts +3 -1
  104. package/templates-app/molehill-2d/.incanto/playtest/lost-seed1.json +4277 -0
  105. package/templates-app/molehill-2d/PROJECT/Context.md +58 -0
  106. package/templates-app/molehill-2d/PROJECT/Requirements.md +39 -0
  107. package/templates-app/molehill-2d/PROJECT/Status.md +27 -0
  108. package/templates-app/molehill-2d/PROJECT/Structure.md +48 -0
  109. package/templates-app/molehill-2d/docs/project-2d-rules.md +44 -0
  110. package/templates-app/molehill-2d/index.html +73 -0
  111. package/templates-app/molehill-2d/package.json +23 -0
  112. package/templates-app/molehill-2d/src/behaviors.ts +198 -0
  113. package/templates-app/molehill-2d/src/game.scene.json +1205 -0
  114. package/templates-app/molehill-2d/src/main.ts +41 -0
  115. package/templates-app/molehill-2d/tsconfig.json +13 -0
  116. package/templates-app/molehill-2d/verify.ts +247 -0
  117. package/templates-app/molehill-2d/vite.config.ts +12 -0
  118. package/templates-app/platformer-2d/package.json +2 -2
  119. package/templates-app/platformer-2d/src/game.scene.json +178 -986
  120. package/templates-app/platformer-2d/src/main.ts +11 -1
  121. package/templates-app/platformer-2d/tsconfig.json +1 -1
  122. package/templates-app/star-survivor/package.json +2 -2
  123. package/templates-app/star-survivor/src/game.scene.json +43 -216
  124. package/templates-app/star-survivor/src/main.ts +11 -1
  125. package/templates-app/star-survivor/tsconfig.json +1 -1
  126. package/templates-app/tps-3d/PROJECT/Context.md +1 -1
  127. package/templates-app/tps-3d/package.json +2 -2
  128. package/templates-app/tps-3d/src/behaviors.ts +19 -1
  129. package/templates-app/tps-3d/src/game.scene.json +66 -263
  130. package/templates-app/tps-3d/src/main.ts +13 -2
  131. package/templates-app/tps-3d/tsconfig.json +1 -1
  132. package/templates-app/village-quest-3d/.incanto/playtest/swapped-seed1.json +1735 -0
  133. package/templates-app/village-quest-3d/package.json +2 -2
  134. package/templates-app/village-quest-3d/src/behaviors.ts +42 -4
  135. package/templates-app/village-quest-3d/src/grove.scene.json +68 -306
  136. package/templates-app/village-quest-3d/src/main.ts +11 -1
  137. package/templates-app/village-quest-3d/src/village.scene.json +202 -863
  138. package/templates-app/village-quest-3d/tsconfig.json +1 -1
  139. package/templates-app/village-quest-3d/verify.ts +14 -1
  140. package/dist/duplicate-Dj4L-5AA.js +0 -22
  141. package/dist/json-CwwhxQgb.js +0 -36
  142. package/dist/registry-CF70EArN.js +0 -212
  143. package/dist/rolldown-runtime-D7D4PA-g.js +0 -13
  144. package/dist/test-D6ISmuFE.js +0 -2383
  145. package/dist/touch-DEAmqGdf.js +0 -225
  146. package/editor/assets/agent8-BDvaZMQJ.js +0 -1
  147. package/editor/assets/index-CZIRr5EL.js +0 -10958
@@ -9,5 +9,5 @@
9
9
  "resolveJsonModule": true,
10
10
  "types": ["vite/client", "node"]
11
11
  },
12
- "include": ["src", "verify.ts"]
12
+ "include": ["src", "verify.ts", "vite.config.ts"]
13
13
  }
@@ -62,6 +62,16 @@ function walkTo(
62
62
  const inputToWorld = Math.atan2(after[1] - before[1], after[0] - before[0]);
63
63
 
64
64
  for (let f = 0; f < budget && dist() > within; f++) {
65
+ /*
66
+ * A frozen clock is an ANSWER, not a slow walk.
67
+ *
68
+ * `GameFlow` sets `timeScale = 0` the moment the run is won or lost, and
69
+ * `engine.step()` then advances nothing. Without this the loop burns its
70
+ * whole budget on no-ops and the harness reports "the player cannot reach
71
+ * it on foot" about a player who has already WON — measured, 1100 of 1200
72
+ * steps were no-ops and the run ended `flow=won` one metre short.
73
+ */
74
+ if (ctx.engine.timeScale === 0) break;
65
75
  const here = at();
66
76
  const want = Math.atan2(target[1] - here[1], target[0] - here[0]);
67
77
  const aim = want - inputToWorld;
@@ -69,6 +79,7 @@ function walkTo(
69
79
  ctx.engine.step();
70
80
  }
71
81
  ctx.engine.input.setActionVector('move', 0, 0);
82
+ if (ctx.engine.timeScale === 0) return; // the run ended while we were walking
72
83
  for (let i = 0; i < 10; i++) ctx.engine.step();
73
84
  if (dist() > within) {
74
85
  throw new Error(
@@ -273,7 +284,9 @@ const ok = (label: string, cond: boolean): void => {
273
284
  resetQuest();
274
285
  const boot = async (): Promise<Engine> => {
275
286
  const engine = new Engine({ seed: 42, scheduler: () => () => {} });
276
- engine.setScene(loadScene(structuredClone(villageJson) as Parameters<typeof loadScene>[0]));
287
+ engine.setScene(
288
+ loadScene(structuredClone(villageJson) as Parameters<typeof loadScene>[0], { engine }),
289
+ );
277
290
  await enablePhysics3D(engine);
278
291
  return engine;
279
292
  };
@@ -1,22 +0,0 @@
1
- import { a as serializeNode, t as buildNodeJson } from "./loader-DZE7B07H.js";
2
- //#region src/core/scene/duplicate.ts
3
- function stripUids(json) {
4
- const { uid: _uid, ...rest } = json;
5
- return {
6
- ...rest,
7
- children: json.children?.map(stripUids)
8
- };
9
- }
10
- /**
11
- * Deep-clone a node subtree (detached — add it wherever you like; sibling
12
- * auto-rename applies on attach). Implemented as serialize → rebuild so a
13
- * duplicate is exactly what would survive a save/load round-trip — EXCEPT
14
- * uids: clones are new entities and get a fresh identity (no uid), so
15
- * duplicating a uid'd template can never mint colliding ids. Names ARE
16
- * kept — rename clones you need to look up individually.
17
- */
18
- function duplicateNode(node) {
19
- return buildNodeJson(stripUids(serializeNode(node)));
20
- }
21
- //#endregion
22
- export { duplicateNode as t };
@@ -1,36 +0,0 @@
1
- import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- //#region src/core/json.ts
3
- var json_exports = /* @__PURE__ */ __exportAll({
4
- jsonClone: () => jsonClone,
5
- jsonEquals: () => jsonEquals,
6
- jsonKind: () => jsonKind
7
- });
8
- function jsonKind(value) {
9
- if (value === null) return "null";
10
- if (Array.isArray(value)) return "array";
11
- const t = typeof value;
12
- if (t === "string" || t === "number" || t === "boolean") return t;
13
- return "object";
14
- }
15
- /** Deep structural equality over JSON values (used for delta-only serialization). */
16
- function jsonEquals(a, b) {
17
- if (a === b) return true;
18
- if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((v, i) => jsonEquals(v, b[i]));
19
- if (a !== null && b !== null && typeof a === "object" && typeof b === "object") {
20
- if (Array.isArray(a) || Array.isArray(b)) return false;
21
- const ka = Object.keys(a);
22
- const kb = Object.keys(b);
23
- return ka.length === kb.length && ka.every((k) => k in b && jsonEquals(a[k], b[k]));
24
- }
25
- return false;
26
- }
27
- /**
28
- * Deep clone of JSON-safe data (defaults must never be shared between
29
- * instances). The value must contain only JSON types.
30
- */
31
- function jsonClone(value) {
32
- if (value === null || typeof value !== "object") return value;
33
- return JSON.parse(JSON.stringify(value));
34
- }
35
- //#endregion
36
- export { json_exports as i, jsonEquals as n, jsonKind as r, jsonClone as t };
@@ -1,212 +0,0 @@
1
- import { t as IncantoError } from "./errors-BpWbnbb_.js";
2
- import { r as jsonKind, t as jsonClone } from "./json-CwwhxQgb.js";
3
- //#region src/core/prop-range.ts
4
- function describe(range) {
5
- const { min, max, exclusiveMin, allow } = range;
6
- let body;
7
- if (min !== void 0 && max !== void 0) body = `${min}..${max}`;
8
- else if (min !== void 0) body = exclusiveMin ? `greater than ${min}` : `at least ${min}`;
9
- else if (max !== void 0) body = `at most ${max}`;
10
- else body = "a finite number";
11
- return allow && allow.length > 0 ? `${body} (or ${allow.join(", ")})` : body;
12
- }
13
- /**
14
- * Throws `PROP_TYPE_MISMATCH` when a number falls outside its documented range.
15
- *
16
- * A non-number is ignored: the kind check has already run and reporting the
17
- * same value twice, under two codes, tells its reader nothing new.
18
- *
19
- * @param value the authored value
20
- * @param label `Type.prop`, for the message
21
- * @param range what the prop documents
22
- */
23
- function validatePropRange(value, label, range) {
24
- if (typeof value !== "number") return;
25
- if (range.allow?.includes(value)) return;
26
- if (!Number.isFinite(value)) throw new IncantoError("PROP_TYPE_MISMATCH", `Prop '${label}' must be a finite number, got ${value}.`, { prop: label });
27
- const belowMin = range.min !== void 0 && (range.exclusiveMin ? value <= range.min : value < range.min);
28
- const aboveMax = range.max !== void 0 && value > range.max;
29
- if (!belowMin && !aboveMax) return;
30
- throw new IncantoError("PROP_TYPE_MISMATCH", `Prop '${label}' must be ${describe(range)}, got ${value}.`, { prop: label });
31
- }
32
- //#endregion
33
- //#region src/core/registry.ts
34
- /**
35
- * Validate a prop value against its schema default:
36
- * - JSON kind must match (unless the default is null = "any")
37
- * - numbers must be finite (NaN/Infinity corrupt JSON files)
38
- * - non-empty default arrays are FIXED templates: same length, element-wise match
39
- * (empty default arrays are unconstrained — variable-length lists)
40
- */
41
- function validatePropValue(value, def, at, options) {
42
- if (options && typeof value === "string" && !options.includes(value)) throw new IncantoError("PROP_TYPE_MISMATCH", `Prop '${at}' is ${JSON.stringify(value)}, which is not one of: ${options.map((o) => JSON.stringify(o)).join(", ")}.`, {
43
- prop: at,
44
- validOptions: [...options]
45
- });
46
- const expected = jsonKind(def);
47
- if (expected === "null") return;
48
- const actual = jsonKind(value);
49
- if (actual !== expected) throw new IncantoError("PROP_TYPE_MISMATCH", `Prop '${at}' expects ${expected} (default ${JSON.stringify(def)}), got ${actual} (${JSON.stringify(value)}).`, { prop: at });
50
- if (typeof value === "number" && !Number.isFinite(value)) throw new IncantoError("PROP_TYPE_MISMATCH", `Prop '${at}' is ${value} — props must be finite numbers.`, { prop: at });
51
- if (Array.isArray(def) && Array.isArray(value) && def.length > 0) {
52
- if (value.length !== def.length) throw new IncantoError("PROP_TYPE_MISMATCH", `Prop '${at}' expects an array of length ${def.length} (default ${JSON.stringify(def)}), got length ${value.length}.`, { prop: at });
53
- for (let i = 0; i < def.length; i++) validatePropValue(value[i], def[i], `${at}[${i}]`);
54
- }
55
- }
56
- /**
57
- * Global node-type registry (Godot's ClassDB role).
58
- *
59
- * Registration is EXPLICIT — never an import-time side effect, so
60
- * `sideEffects: false` tree-shaking can never silently drop node types.
61
- */
62
- const types = /* @__PURE__ */ new Map();
63
- function registerNode(ctor, opts) {
64
- const existing = types.get(ctor.typeName);
65
- if (existing && existing !== ctor && !opts?.replace) throw new IncantoError("DUPLICATE_NODE_TYPE", `Node type '${ctor.typeName}' is already registered by a different class. Replacing an implementation (e.g. under hot reload) needs registerNode(ctor, { replace: true }).`, { nodeType: ctor.typeName });
66
- types.set(ctor.typeName, ctor);
67
- }
68
- function getNodeType(typeName) {
69
- const ctor = types.get(typeName);
70
- if (!ctor) {
71
- const registered = [...types.keys()];
72
- throw new IncantoError("UNKNOWN_NODE_TYPE", `Unknown node type '${typeName}'. Registered types: [${registered.join(", ")}].` + missingRegistrarHint(typeName), {
73
- nodeType: typeName,
74
- validOptions: registered
75
- });
76
- }
77
- return ctor;
78
- }
79
- /**
80
- * "Unknown node type 'Node2D'" next to a list with no 2D types in it is the
81
- * most confusing error this engine can produce: the type is not misspelled and
82
- * not missing — a REGISTRAR was never called. Say which one.
83
- *
84
- * The case that produced this: the multiplayer boot registers `registerNodesNet()`
85
- * and loads a 2D scene, which dies on its own root node.
86
- */
87
- function missingRegistrarHint(typeName) {
88
- const suffix = typeName.endsWith("2D") ? "2D" : typeName.endsWith("3D") ? "3D" : "";
89
- if (!suffix || types.has(`Node${suffix}`)) return "";
90
- const dim = suffix.toLowerCase();
91
- return ` '${typeName}' is a ${dim} node and no ${dim} type is registered: call registerNodes${suffix}() (from 'incanto/${dim}') before loading the scene — createGame${suffix}() does it for you. Registrars compose: a multiplayer game calls registerNodes${suffix}() AND registerNodesNet().`;
92
- }
93
- function registeredTypes() {
94
- return [...types.keys()];
95
- }
96
- /** Test isolation helper. */
97
- function clearRegistry() {
98
- types.clear();
99
- }
100
- /**
101
- * Effective prop schema for a type: own static `props` merged over every
102
- * ancestor's (subclass keys win).
103
- */
104
- function getNodeSchema(typeName) {
105
- return mergeStaticProps(getNodeType(typeName));
106
- }
107
- /** Walk a constructor's prototype chain collecting static `signals` (deduped). */
108
- function mergeStaticSignals(ctor) {
109
- const out = [];
110
- let current = ctor;
111
- while (current) {
112
- if (Object.hasOwn(current, "signals") && current.signals) out.unshift(...current.signals);
113
- const parent = Object.getPrototypeOf(current);
114
- current = typeof parent === "function" ? parent : null;
115
- }
116
- return [...new Set(out)];
117
- }
118
- /** Every signal a registered type declares (its own + inherited). */
119
- function getNodeSignals(typeName) {
120
- return mergeStaticSignals(getNodeType(typeName));
121
- }
122
- /** Walk a constructor's prototype chain merging static `props` (subclass wins). */
123
- function mergeStaticProps(ctor) {
124
- const chain = [];
125
- let current = ctor;
126
- while (current) {
127
- if (Object.hasOwn(current, "props") && current.props) chain.unshift(current.props);
128
- const parent = Object.getPrototypeOf(current);
129
- current = typeof parent === "function" ? parent : null;
130
- }
131
- return Object.assign({}, ...chain);
132
- }
133
- /** Walk a constructor's prototype chain merging static `propAliases` (legacy
134
- * prop key → its current canonical key; subclass wins). Lets a renamed prop keep
135
- * loading old scenes (e.g. 2D `zIndex` → `renderOrder`) without a format bump. */
136
- function mergeStaticAliases(ctor) {
137
- const chain = [];
138
- let current = ctor;
139
- while (current) {
140
- if (Object.hasOwn(current, "propAliases") && current.propAliases) chain.unshift(current.propAliases);
141
- const parent = Object.getPrototypeOf(current);
142
- current = typeof parent === "function" ? parent : null;
143
- }
144
- return Object.assign({}, ...chain);
145
- }
146
- /**
147
- * Assign schema defaults (cloned) then the given props onto a target,
148
- * hard-validating every key and JSON kind. Shared by nodes and behaviors.
149
- * `aliases` maps legacy keys onto current ones (back-compat for renamed props).
150
- */
151
- function applySchemaProps(target, schema, props, label, aliases = {}, extraOptions = {}) {
152
- for (const [key, def] of Object.entries(schema)) target[key] = jsonClone(def.default);
153
- if (props) applyGivenProps(target, schema, props, label, aliases, extraOptions);
154
- requireNonEmpty(target, schema, label);
155
- }
156
- function applyGivenProps(target, schema, props, label, aliases, extraOptions) {
157
- for (const [rawKey, value] of Object.entries(props)) {
158
- const key = schema[rawKey] ? rawKey : aliases[rawKey] ?? rawKey;
159
- const def = schema[key];
160
- if (!def) {
161
- const valid = Object.keys(schema);
162
- throw new IncantoError("UNKNOWN_PROP", `Unknown prop '${rawKey}' on '${label}'. Valid props: [${valid.join(", ")}].`, {
163
- prop: rawKey,
164
- nodeType: label,
165
- validOptions: valid
166
- });
167
- }
168
- const extra = extraOptions[key];
169
- const options = def.options && extra && extra.length > 0 ? [...def.options, ...extra] : def.options;
170
- validatePropValue(value, def.default, `${label}.${key}`, options);
171
- if (def.range) validatePropRange(value, `${label}.${key}`, def.range);
172
- target[key] = jsonClone(value);
173
- }
174
- }
175
- function requireNonEmpty(target, schema, label) {
176
- for (const [key, def] of Object.entries(schema)) {
177
- if (!def.required) continue;
178
- if (!isEmptyValue(target[key])) continue;
179
- throw new IncantoError("PROP_TYPE_MISMATCH", `'${label}' needs a "${key}" — it is empty.`, {
180
- prop: key,
181
- nodeType: label
182
- });
183
- }
184
- }
185
- /**
186
- * "Not a configuration" — what `required` refuses.
187
- *
188
- * The first cut only knew about `''`, which is what the two props that
189
- * introduced the flag hold. Three of the ones declared since default to an
190
- * ARRAY — `MoveTo.to`, `Patrol.points`, `WaveSpawner.waves` — and for those the
191
- * flag was inert: a `MoveTo` with no `to` loaded clean and moved nowhere, which
192
- * is exactly the failure the flag was added to stop. Found by running the
193
- * shipped package as a consumer instead of trusting the declaration.
194
- */
195
- function isEmptyValue(value) {
196
- if (value === "" || value === void 0 || value === null) return true;
197
- if (Array.isArray(value)) return value.length === 0;
198
- if (typeof value === "object") return Object.keys(value).length === 0;
199
- return false;
200
- }
201
- /**
202
- * Instantiate a registered type, assign schema defaults (cloned), then the
203
- * given props — validating every key and its JSON kind against the default.
204
- */
205
- function createNode(typeName, props, extraOptions) {
206
- const ctor = getNodeType(typeName);
207
- const node = new ctor();
208
- applySchemaProps(node, getNodeSchema(typeName), props, typeName, mergeStaticAliases(ctor), extraOptions);
209
- return node;
210
- }
211
- //#endregion
212
- export { getNodeSignals as a, mergeStaticSignals as c, getNodeSchema as i, registerNode as l, clearRegistry as n, getNodeType as o, createNode as r, mergeStaticProps as s, applySchemaProps as t, registeredTypes as u };
@@ -1,13 +0,0 @@
1
- //#region \0rolldown/runtime.js
2
- var __defProp = Object.defineProperty;
3
- var __exportAll = (all, no_symbols) => {
4
- let target = {};
5
- for (var name in all) __defProp(target, name, {
6
- get: all[name],
7
- enumerable: true
8
- });
9
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
- return target;
11
- };
12
- //#endregion
13
- export { __exportAll as t };