@auraindustry/aurajs 0.1.1 → 0.1.5

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 (144) hide show
  1. package/README.md +7 -0
  2. package/benchmarks/perf-thresholds.json +27 -0
  3. package/package.json +6 -1
  4. package/src/ai-guidance.mjs +302 -0
  5. package/src/asset-pack.mjs +2 -1
  6. package/src/authored-project.mjs +498 -2
  7. package/src/authored-runtime.mjs +14 -0
  8. package/src/bin-integrity.mjs +33 -26
  9. package/src/build-contract/capabilities.mjs +87 -1
  10. package/src/build-contract/constants.mjs +1 -0
  11. package/src/build-contract.mjs +2 -0
  12. package/src/bundler.mjs +143 -13
  13. package/src/cli.mjs +681 -13
  14. package/src/commands/packs.mjs +741 -0
  15. package/src/commands/project-authoring.mjs +128 -1
  16. package/src/conformance/cases/app-and-ui-runtime-cases.mjs +1 -2
  17. package/src/conformance/cases/core-runtime-cases.mjs +6 -2
  18. package/src/conformance/cases/scene3d-and-media-cases.mjs +238 -0
  19. package/src/conformance/cases/systems-and-gameplay-cases.mjs +1126 -10
  20. package/src/conformance-mobile.mjs +166 -0
  21. package/src/conformance.mjs +89 -30
  22. package/src/evidence-bundle.mjs +242 -0
  23. package/src/external-package-surface.mjs +1 -1
  24. package/src/headless-test/runtime-coordinator.mjs +186 -33
  25. package/src/headless-test.mjs +2 -0
  26. package/src/helpers/2d/index.mjs +183 -0
  27. package/src/helpers/index.mjs +26 -0
  28. package/src/helpers/starter-utils/adventure-objectives.js +102 -0
  29. package/src/helpers/starter-utils/adventure-world-2d.js +221 -0
  30. package/src/helpers/starter-utils/animation-2d.js +337 -0
  31. package/src/helpers/starter-utils/animation-packaging-2d.js +203 -0
  32. package/src/helpers/starter-utils/atlas-assets-2d.js +111 -0
  33. package/src/helpers/starter-utils/autoplay-debug-2d.js +215 -0
  34. package/src/helpers/starter-utils/avatar-3d.js +404 -0
  35. package/src/helpers/starter-utils/combat-feedback-2d.js +320 -0
  36. package/src/helpers/starter-utils/combat-runtime-2d.js +290 -0
  37. package/src/helpers/starter-utils/core.js +150 -0
  38. package/src/helpers/starter-utils/dialogue-2d.js +351 -0
  39. package/src/helpers/starter-utils/enemy-archetypes-2d.js +68 -0
  40. package/src/helpers/starter-utils/index.js +26 -0
  41. package/src/helpers/starter-utils/inventory-2d.js +268 -0
  42. package/src/helpers/starter-utils/journal-2d.js +267 -0
  43. package/src/helpers/starter-utils/platformer-3d.js +132 -0
  44. package/src/helpers/starter-utils/scene-audio-2d.js +236 -0
  45. package/src/helpers/starter-utils/streamed-world-2d.js +378 -0
  46. package/src/helpers/starter-utils/tilemap-nav-2d.js +499 -0
  47. package/src/helpers/starter-utils/tilemap-world-2d.js +205 -0
  48. package/src/helpers/starter-utils/triggers.js +662 -0
  49. package/src/helpers/starter-utils/tween-2d.js +615 -0
  50. package/src/helpers/starter-utils/wave-director.js +101 -0
  51. package/src/helpers/starter-utils/world-compositor-2d.js +253 -0
  52. package/src/helpers/starter-utils/world-persistence-2d.js +180 -0
  53. package/src/mobile/android/build.mjs +606 -0
  54. package/src/mobile/android/host-artifact.mjs +280 -0
  55. package/src/mobile/ios/build.mjs +1323 -0
  56. package/src/mobile/ios/host-artifact.mjs +819 -0
  57. package/src/mobile/shared/capabilities.mjs +174 -0
  58. package/src/package-integrity.mjs +18 -4
  59. package/src/packs/catalog.mjs +259 -0
  60. package/src/perf-benchmark-runner.mjs +17 -12
  61. package/src/perf-benchmark.mjs +408 -4
  62. package/src/publish-command.mjs +434 -17
  63. package/src/publish-validation.mjs +22 -11
  64. package/src/replay-runtime.mjs +257 -0
  65. package/src/scaffold/config.mjs +2 -0
  66. package/src/scaffold/fs.mjs +8 -1
  67. package/src/scaffold/project-docs.mjs +101 -41
  68. package/src/scaffold.mjs +4 -0
  69. package/src/session-runtime.mjs +4 -3
  70. package/src/web-conformance.mjs +0 -36
  71. package/templates/create/2d/src/runtime/app.js +4 -0
  72. package/templates/create/2d-adventure/config/gameplay/adventure.config.js +9 -6
  73. package/templates/create/2d-adventure/content/gameplay/dialogue.js +85 -0
  74. package/templates/create/2d-adventure/content/gameplay/world.js +32 -36
  75. package/templates/create/2d-adventure/content/gameplay/world.tilemap.json +273 -0
  76. package/templates/create/2d-adventure/docs/design/loop.md +4 -3
  77. package/templates/create/2d-adventure/prefabs/relic.prefab.js +10 -10
  78. package/templates/create/2d-adventure/prefabs/world.prefab.js +127 -74
  79. package/templates/create/2d-adventure/scenes/gameplay.scene.js +603 -112
  80. package/templates/create/2d-adventure/src/runtime/capabilities.js +16 -0
  81. package/templates/create/2d-adventure/ui/hud.screen.js +187 -4
  82. package/templates/create/2d-adventure/ui/journal.screen.js +183 -0
  83. package/templates/create/2d-survivor/src/runtime/app.js +4 -0
  84. package/templates/create/3d/scenes/gameplay.scene.js +30 -3
  85. package/templates/create/3d/src/runtime/app.js +4 -0
  86. package/templates/create/3d/src/runtime/capabilities.js +5 -0
  87. package/templates/create/3d/src/runtime/materials.js +10 -0
  88. package/templates/create/3d-adventure/scenes/gameplay.scene.js +30 -3
  89. package/templates/create/3d-adventure/src/runtime/capabilities.js +5 -0
  90. package/templates/create/3d-adventure/src/runtime/materials.js +11 -0
  91. package/templates/create/3d-collectathon/scenes/gameplay.scene.js +30 -3
  92. package/templates/create/3d-collectathon/src/runtime/app.js +4 -0
  93. package/templates/create/3d-collectathon/src/runtime/capabilities.js +5 -0
  94. package/templates/create/3d-collectathon/src/runtime/materials.js +10 -0
  95. package/templates/create/blank/assets/splash/aurajs-gg-wordmark.webp +0 -0
  96. package/templates/create/blank/assets/splash/bg.webp +0 -0
  97. package/templates/create/blank/assets/splash/boot-loop.wav +0 -0
  98. package/templates/create/blank/assets/splash/boot-sting.wav +0 -0
  99. package/templates/create/blank/assets/splash/logo-mascot-sheet.webp +0 -0
  100. package/templates/create/blank/assets/splash/logoholo.webp +0 -0
  101. package/templates/create/blank/src/main.js +5 -1
  102. package/templates/create/blank/src/runtime/splash.js +305 -0
  103. package/templates/create/local-multiplayer/scenes/gameplay.scene.js +186 -12
  104. package/templates/create/local-multiplayer/src/runtime/capabilities.js +8 -1
  105. package/templates/create/shared/assets/splash/aurajs-gg-wordmark.webp +0 -0
  106. package/templates/create/shared/assets/splash/bg.webp +0 -0
  107. package/templates/create/shared/assets/splash/boot-loop.wav +0 -0
  108. package/templates/create/shared/assets/splash/boot-sting.wav +0 -0
  109. package/templates/create/shared/assets/splash/logo-mascot-sheet.webp +0 -0
  110. package/templates/create/shared/assets/splash/logoholo.webp +0 -0
  111. package/templates/create/shared/src/runtime/splash.js +305 -0
  112. package/templates/create/shared/src/runtime/ui-forms.js +552 -0
  113. package/templates/create/shared/src/starter-utils/adventure-world-2d.js +221 -0
  114. package/templates/create/shared/src/starter-utils/animation-packaging-2d.js +203 -0
  115. package/templates/create/shared/src/starter-utils/atlas-assets-2d.js +111 -0
  116. package/templates/create/shared/src/starter-utils/autoplay-debug-2d.js +215 -0
  117. package/templates/create/shared/src/starter-utils/combat-runtime-2d.js +290 -0
  118. package/templates/create/shared/src/starter-utils/dialogue-2d.js +351 -0
  119. package/templates/create/shared/src/starter-utils/index.js +15 -1
  120. package/templates/create/shared/src/starter-utils/inventory-2d.js +268 -0
  121. package/templates/create/shared/src/starter-utils/journal-2d.js +267 -0
  122. package/templates/create/shared/src/starter-utils/scene-audio-2d.js +236 -0
  123. package/templates/create/shared/src/starter-utils/streamed-world-2d.js +378 -0
  124. package/templates/create/shared/src/starter-utils/tilemap-nav-2d.js +499 -0
  125. package/templates/create/shared/src/starter-utils/tilemap-world-2d.js +205 -0
  126. package/templates/create/shared/src/starter-utils/world-compositor-2d.js +253 -0
  127. package/templates/create/shared/src/starter-utils/world-persistence-2d.js +180 -0
  128. package/templates/create/video-cutscene/src/runtime/app.js +4 -0
  129. package/templates/create-bin/play.js +148 -7
  130. package/templates/skills/auramaxx/SKILL.md +46 -0
  131. package/templates/skills/auramaxx/project-requirements.md +68 -0
  132. package/templates/skills/auramaxx/starter-recipes.md +104 -0
  133. package/templates/skills/auramaxx/validation-checklist.md +49 -0
  134. package/templates/starter/assets/splash/aurajs-gg-wordmark.webp +0 -0
  135. package/templates/starter/assets/splash/bg.webp +0 -0
  136. package/templates/starter/assets/splash/boot-loop.wav +0 -0
  137. package/templates/starter/assets/splash/boot-sting.wav +0 -0
  138. package/templates/starter/assets/splash/logo-mascot-sheet.webp +0 -0
  139. package/templates/starter/assets/splash/logoholo.webp +0 -0
  140. package/templates/starter/src/main.js +4 -0
  141. package/templates/starter/src/runtime/splash.js +305 -0
  142. package/templates/skills/aurajs/SKILL.md +0 -96
  143. package/templates/skills/aurajs/api-contract-3d.md +0 -7
  144. package/templates/skills/aurajs/api-contract.md +0 -7
@@ -14,7 +14,8 @@ import { createHeadlessAnimationRuntime } from './runtime-animation.mjs';
14
14
  import { createHeadlessPrimitiveRuntime } from './runtime-primitives.mjs';
15
15
  import { createHeadlessWorldRuntime } from './runtime-world.mjs';
16
16
 
17
- export function createRuntimeContext(aura, testState) {
17
+ export function createRuntimeContext(aura, testState, options = {}) {
18
+ const mathRef = options && typeof options === 'object' && options.math ? options.math : Math;
18
19
  const consoleShim = {
19
20
  log: (...args) => {
20
21
  testState.logs.push(['log', ...args]);
@@ -33,7 +34,7 @@ export function createRuntimeContext(aura, testState) {
33
34
  return {
34
35
  aura,
35
36
  console: consoleShim,
36
- Math,
37
+ Math: mathRef,
37
38
  Date,
38
39
  setTimeout,
39
40
  clearTimeout,
@@ -49,6 +50,22 @@ const draw2dRenderTargets = new Map();
49
50
  const draw2dClipStack = [];
50
51
  let activeDraw2dRenderTarget = null;
51
52
  let activeDraw2dMaskCapture = null;
53
+ const inputNormalize = (value) => String(value || '').trim().toLowerCase();
54
+ const keyboardDown = new Set();
55
+ const keyboardPressed = new Set();
56
+ const keyboardReleased = new Set();
57
+ const mouseButtonsDown = new Set();
58
+ const mouseButtonsPressed = new Set();
59
+ const mouseButtonsReleased = new Set();
60
+ const gamepadButtonsDown = new Set();
61
+ const gamepadButtonsPressed = new Set();
62
+ const gamepadButtonsReleased = new Set();
63
+ const gamepadAxes = Object.create(null);
64
+ let mouseX = 0;
65
+ let mouseY = 0;
66
+ let mouseDeltaX = 0;
67
+ let mouseDeltaY = 0;
68
+ let mouseScroll = 0;
52
69
 
53
70
  const drawNoop = () => {
54
71
  testState.drawCalls += 1;
@@ -60,6 +77,119 @@ const drawNoop = () => {
60
77
  }
61
78
  };
62
79
  const stateNoop = () => {};
80
+ const clearInputFrameTransitions = () => {
81
+ keyboardPressed.clear();
82
+ keyboardReleased.clear();
83
+ mouseButtonsPressed.clear();
84
+ mouseButtonsReleased.clear();
85
+ gamepadButtonsPressed.clear();
86
+ gamepadButtonsReleased.clear();
87
+ mouseDeltaX = 0;
88
+ mouseDeltaY = 0;
89
+ mouseScroll = 0;
90
+ };
91
+ const applyDownTransitions = (targetDown, targetPressed, values) => {
92
+ for (const value of Array.isArray(values) ? values : []) {
93
+ const normalized = inputNormalize(value);
94
+ if (!normalized) continue;
95
+ if (!targetDown.has(normalized)) {
96
+ targetPressed.add(normalized);
97
+ }
98
+ targetDown.add(normalized);
99
+ }
100
+ };
101
+ const applyUpTransitions = (targetDown, targetReleased, values) => {
102
+ for (const value of Array.isArray(values) ? values : []) {
103
+ const normalized = inputNormalize(value);
104
+ if (!normalized) continue;
105
+ if (targetDown.delete(normalized)) {
106
+ targetReleased.add(normalized);
107
+ }
108
+ }
109
+ };
110
+ const applyHeadlessInputFrame = (frame = {}) => {
111
+ clearInputFrameTransitions();
112
+ const input = frame && typeof frame === 'object' && !Array.isArray(frame) ? frame : {};
113
+ if (input.reset === true) {
114
+ keyboardDown.clear();
115
+ mouseButtonsDown.clear();
116
+ gamepadButtonsDown.clear();
117
+ for (const key of Object.keys(gamepadAxes)) {
118
+ delete gamepadAxes[key];
119
+ }
120
+ }
121
+
122
+ applyDownTransitions(keyboardDown, keyboardPressed, input.keysDown);
123
+ applyUpTransitions(keyboardDown, keyboardReleased, input.keysUp);
124
+
125
+ const mouse = input.mouse && typeof input.mouse === 'object' && !Array.isArray(input.mouse)
126
+ ? input.mouse
127
+ : null;
128
+ if (mouse) {
129
+ if (Number.isFinite(Number(mouse.x))) {
130
+ const nextX = Number(mouse.x);
131
+ mouseDeltaX = nextX - mouseX;
132
+ mouseX = nextX;
133
+ }
134
+ if (Number.isFinite(Number(mouse.y))) {
135
+ const nextY = Number(mouse.y);
136
+ mouseDeltaY = nextY - mouseY;
137
+ mouseY = nextY;
138
+ }
139
+ if (Number.isFinite(Number(mouse.scrollDelta))) {
140
+ mouseScroll = Number(mouse.scrollDelta);
141
+ } else if (Number.isFinite(Number(mouse.scroll))) {
142
+ mouseScroll = Number(mouse.scroll);
143
+ }
144
+ applyDownTransitions(mouseButtonsDown, mouseButtonsPressed, mouse.buttonsDown);
145
+ applyUpTransitions(mouseButtonsDown, mouseButtonsReleased, mouse.buttonsUp);
146
+ }
147
+
148
+ const gamepad = input.gamepad && typeof input.gamepad === 'object' && !Array.isArray(input.gamepad)
149
+ ? input.gamepad
150
+ : null;
151
+ if (gamepad) {
152
+ if (typeof gamepad.connected === 'boolean' && gamepad.connected !== true) {
153
+ gamepadButtonsDown.clear();
154
+ for (const key of Object.keys(gamepadAxes)) {
155
+ delete gamepadAxes[key];
156
+ }
157
+ }
158
+ if (gamepad.axes && typeof gamepad.axes === 'object' && !Array.isArray(gamepad.axes)) {
159
+ for (const [axis, value] of Object.entries(gamepad.axes)) {
160
+ const normalizedAxis = inputNormalize(axis);
161
+ if (!normalizedAxis) continue;
162
+ const numeric = Number(value);
163
+ if (!Number.isFinite(numeric)) continue;
164
+ gamepadAxes[normalizedAxis] = numeric;
165
+ }
166
+ }
167
+ applyDownTransitions(gamepadButtonsDown, gamepadButtonsPressed, gamepad.buttonsDown);
168
+ applyUpTransitions(gamepadButtonsDown, gamepadButtonsReleased, gamepad.buttonsUp);
169
+ }
170
+ };
171
+ const snapshotHeadlessInput = () => ({
172
+ keysDown: [...keyboardDown].sort(),
173
+ keysPressed: [...keyboardPressed].sort(),
174
+ keysReleased: [...keyboardReleased].sort(),
175
+ mouse: {
176
+ x: mouseX,
177
+ y: mouseY,
178
+ deltaX: mouseDeltaX,
179
+ deltaY: mouseDeltaY,
180
+ scroll: mouseScroll,
181
+ buttonsDown: [...mouseButtonsDown].sort(),
182
+ buttonsPressed: [...mouseButtonsPressed].sort(),
183
+ buttonsReleased: [...mouseButtonsReleased].sort(),
184
+ },
185
+ gamepad: {
186
+ connected: gamepadButtonsDown.size > 0 || Object.keys(gamepadAxes).length > 0,
187
+ axes: { ...gamepadAxes },
188
+ buttonsDown: [...gamepadButtonsDown].sort(),
189
+ buttonsPressed: [...gamepadButtonsPressed].sort(),
190
+ buttonsReleased: [...gamepadButtonsReleased].sort(),
191
+ },
192
+ });
63
193
 
64
194
  const {
65
195
  resolveHeadlessAssetPath,
@@ -1088,8 +1218,10 @@ const aura = {
1088
1218
  draw2d: {
1089
1219
  clear: drawNoop,
1090
1220
  rect: drawNoop,
1221
+ rectFill: drawNoop,
1091
1222
  rectOutline: drawNoop,
1092
1223
  circle: drawNoop,
1224
+ circleFill: drawNoop,
1093
1225
  circleOutline: drawNoop,
1094
1226
  line: drawNoop,
1095
1227
  triangle: drawNoop,
@@ -1293,9 +1425,9 @@ const aura = {
1293
1425
  },
1294
1426
 
1295
1427
  input: {
1296
- isDown: () => false,
1297
- isPressed: () => false,
1298
- isReleased: () => false,
1428
+ isDown: (key) => keyboardDown.has(inputNormalize(key)),
1429
+ isPressed: (key) => keyboardPressed.has(inputNormalize(key)),
1430
+ isReleased: (key) => keyboardReleased.has(inputNormalize(key)),
1299
1431
  isKeyDown: (...args) => aura.input.isDown(...args),
1300
1432
  isKeyPressed: (...args) => aura.input.isPressed(...args),
1301
1433
  isKeyReleased: (...args) => aura.input.isReleased(...args),
@@ -1303,24 +1435,42 @@ const aura = {
1303
1435
  isMousePressed: (...args) => aura.input.mouse.isPressed(...args),
1304
1436
  isMouseReleased: (...args) => aura.input.mouse.isReleased(...args),
1305
1437
  getMousePosition: () => ({ x: aura.input.mouse.x, y: aura.input.mouse.y }),
1306
- getMouseDelta: () => ({ x: 0, y: 0 }),
1438
+ getMouseDelta: () => ({ x: mouseDeltaX, y: mouseDeltaY }),
1307
1439
  isGamepadConnected: () => Boolean(aura.input.gamepad.connected),
1308
1440
  mouse: {
1309
- x: 0,
1310
- y: 0,
1311
- scroll: 0,
1312
- isDown: () => false,
1313
- isPressed: () => false,
1314
- isReleased: () => false,
1441
+ get x() {
1442
+ return mouseX;
1443
+ },
1444
+ get y() {
1445
+ return mouseY;
1446
+ },
1447
+ get scroll() {
1448
+ return mouseScroll;
1449
+ },
1450
+ isDown: (button) => mouseButtonsDown.has(inputNormalize(button)),
1451
+ isPressed: (button) => mouseButtonsPressed.has(inputNormalize(button)),
1452
+ isReleased: (button) => mouseButtonsReleased.has(inputNormalize(button)),
1315
1453
  },
1316
1454
  gamepad: {
1317
- connected: false,
1318
- axis: () => 0,
1319
- isDown: () => false,
1320
- isPressed: () => false,
1321
- isReleased: () => false,
1455
+ get connected() {
1456
+ return gamepadButtonsDown.size > 0 || Object.keys(gamepadAxes).length > 0;
1457
+ },
1458
+ axis: (axis) => {
1459
+ const normalized = inputNormalize(axis);
1460
+ return normalized && Object.prototype.hasOwnProperty.call(gamepadAxes, normalized)
1461
+ ? gamepadAxes[normalized]
1462
+ : 0;
1463
+ },
1464
+ isDown: (button) => gamepadButtonsDown.has(inputNormalize(button)),
1465
+ isPressed: (button) => gamepadButtonsPressed.has(inputNormalize(button)),
1466
+ isReleased: (button) => gamepadButtonsReleased.has(inputNormalize(button)),
1322
1467
  rumble: () => {},
1323
1468
  },
1469
+ __headless: {
1470
+ applyFrame: applyHeadlessInputFrame,
1471
+ clearFrameTransitions: clearInputFrameTransitions,
1472
+ snapshot: snapshotHeadlessInput,
1473
+ },
1324
1474
  },
1325
1475
 
1326
1476
  storage: {
@@ -1492,23 +1642,26 @@ export async function executeSetup(aura) {
1492
1642
  }
1493
1643
  }
1494
1644
 
1645
+ export async function executeFrame(aura, dt = 1 / 60) {
1646
+ if (aura.debug && typeof aura.debug.__inspectorTick === 'function') {
1647
+ aura.debug.__inspectorTick(dt);
1648
+ }
1649
+ if (aura.anim2d && typeof aura.anim2d.update === 'function') {
1650
+ await Promise.resolve(aura.anim2d.update(dt));
1651
+ }
1652
+ if (aura.ecs && typeof aura.ecs.run === 'function') {
1653
+ await Promise.resolve(aura.ecs.run(dt));
1654
+ }
1655
+ if (typeof aura.update === 'function') {
1656
+ await Promise.resolve(aura.update(dt));
1657
+ }
1658
+ if (typeof aura.draw === 'function') {
1659
+ await Promise.resolve(aura.draw());
1660
+ }
1661
+ }
1662
+
1495
1663
  export async function executeFrameSteps(aura, frames) {
1496
1664
  for (let i = 0; i < frames; i += 1) {
1497
- const dt = 1 / 60;
1498
- if (aura.debug && typeof aura.debug.__inspectorTick === 'function') {
1499
- aura.debug.__inspectorTick(dt);
1500
- }
1501
- if (aura.anim2d && typeof aura.anim2d.update === 'function') {
1502
- await Promise.resolve(aura.anim2d.update(dt));
1503
- }
1504
- if (aura.ecs && typeof aura.ecs.run === 'function') {
1505
- await Promise.resolve(aura.ecs.run(dt));
1506
- }
1507
- if (typeof aura.update === 'function') {
1508
- await Promise.resolve(aura.update(dt));
1509
- }
1510
- if (typeof aura.draw === 'function') {
1511
- await Promise.resolve(aura.draw());
1512
- }
1665
+ await executeFrame(aura, 1 / 60);
1513
1666
  }
1514
1667
  }
@@ -11,6 +11,7 @@ import {
11
11
  import {
12
12
  createHeadlessAura,
13
13
  createRuntimeContext,
14
+ executeFrame,
14
15
  executeFrameSteps,
15
16
  executeSetup,
16
17
  } from './headless-test/runtime-coordinator.mjs';
@@ -18,6 +19,7 @@ import {
18
19
  export {
19
20
  createHeadlessAura,
20
21
  createRuntimeContext,
22
+ executeFrame,
21
23
  executeFrameSteps,
22
24
  executeSetup,
23
25
  };
@@ -0,0 +1,183 @@
1
+ import {
2
+ clamp,
3
+ axisFromKeys,
4
+ createCooldown,
5
+ tickCooldown,
6
+ consumeCooldown,
7
+ createIntervalSpawner,
8
+ tickIntervalSpawner,
9
+ centeredRect,
10
+ rectsOverlap,
11
+ removeWhere,
12
+ distanceSquared2D,
13
+ createSpriteAnimationLibrary2D,
14
+ hasSpriteAnimationState2D,
15
+ createSpriteAnimationRuntime2D,
16
+ registerSpriteAnimationLibrary2D,
17
+ createSpriteAnimator2D,
18
+ playSpriteAnimator2D,
19
+ syncSpriteAnimatorState2D,
20
+ stepSpriteAnimationRuntime2D,
21
+ getSpriteAnimatorState2D,
22
+ resolveSpriteAnimatorFrame2D,
23
+ drawSpriteAnimator2D,
24
+ resolveSpriteFrameRect2D,
25
+ createAnimationPackage2D,
26
+ hasAnimationPackageState2D,
27
+ registerAnimationPackage2D,
28
+ createPackagedSpriteAnimator2D,
29
+ getAnimationPackageLibrary2D,
30
+ getAnimationPackageState2D,
31
+ createAtlasAssetManifest2D,
32
+ createAnimationPackageFromAtlasAsset2D,
33
+ createSceneAudio2D,
34
+ configureSceneAudio2D,
35
+ ensureSceneMusic2D,
36
+ setSceneMusicVolume2D,
37
+ duckSceneMusic2D,
38
+ playSceneStinger2D,
39
+ pauseSceneAudio2D,
40
+ resumeSceneAudio2D,
41
+ syncSceneAudio2D,
42
+ stopSceneAudio2D,
43
+ propertyTween2D,
44
+ delayTween2D,
45
+ sequenceTweens2D,
46
+ parallelTweens2D,
47
+ repeatTween2D,
48
+ yoyoTween2D,
49
+ moveTo2D,
50
+ driftTo2D,
51
+ fadeTo2D,
52
+ scaleTo2D,
53
+ rotateTo2D,
54
+ pulse2D,
55
+ punch2D,
56
+ settleTo2D,
57
+ createTweenComposer2D,
58
+ playTweenPlan2D,
59
+ cancelTweenPlan2D,
60
+ stepTweenComposer2D,
61
+ getTweenHandleState2D,
62
+ isTweenHandleActive2D,
63
+ createFloatingTextLayer2D,
64
+ spawnFloatingText2D,
65
+ stepFloatingTextLayer2D,
66
+ getFloatingTextRenderState2D,
67
+ drawFloatingTextLayer2D,
68
+ createHitFlash2D,
69
+ triggerHitFlash2D,
70
+ stepHitFlash2D,
71
+ isHitFlashVisible2D,
72
+ createHitSparkLayer2D,
73
+ spawnHitSpark2D,
74
+ stepHitSparkLayer2D,
75
+ drawHitSparkLayer2D,
76
+ createHoverLift2D,
77
+ setHoverLiftActive2D,
78
+ stepHoverLift2D,
79
+ getHoverLiftOffset2D,
80
+ applyShieldedDamage2D,
81
+ stepShieldRecharge2D,
82
+ restoreShieldedHealth2D,
83
+ createWeightedDropTable2D,
84
+ rollWeightedDrop2D,
85
+ createEncounterPressure2D,
86
+ recordEncounterKill2D,
87
+ stepEncounterPressure2D,
88
+ advanceBossPhase2D,
89
+ createAutoplayController2D,
90
+ setAutoplayEnabled2D,
91
+ toggleAutoplayEnabled2D,
92
+ resolveAutoplayControl2D,
93
+ createRenderTargetExportState2D,
94
+ queueRenderTargetExport2D,
95
+ flushRenderTargetExport2D,
96
+ createRectTrigger2D,
97
+ createTriggerTracker,
98
+ getTriggerTrackerSnapshot,
99
+ stepRectTriggers2D,
100
+ stepTriggerTracker,
101
+ resolveTriggerInteraction,
102
+ createInteractionPromptState,
103
+ updateInteractionPromptState,
104
+ createWaveDirector,
105
+ activeWave,
106
+ stepWaveDirector,
107
+ listEnemyArchetypeIds2D,
108
+ getEnemyArchetype2D,
109
+ pickEnemyArchetypeForWave2D,
110
+ spawnEnemy2D,
111
+ createInventory2D,
112
+ addInventoryItem2D,
113
+ removeInventoryItem2D,
114
+ hasInventoryItem2D,
115
+ listInventoryItems2D,
116
+ selectInventoryCategory2D,
117
+ selectInventoryItem2D,
118
+ getSelectedInventoryItem2D,
119
+ setInventoryItemEquipped2D,
120
+ getInventoryView2D,
121
+ createDialogueState2D,
122
+ registerDialogueConversation2D,
123
+ startDialogueConversation2D,
124
+ advanceDialogueConversation2D,
125
+ chooseDialogueChoice2D,
126
+ completeDialogueConversation2D,
127
+ getDialogueView2D,
128
+ createJournal2D,
129
+ upsertJournalEntry2D,
130
+ setJournalEntryStatus2D,
131
+ listJournalEntries2D,
132
+ selectJournalCategory2D,
133
+ selectJournalEntry2D,
134
+ getSelectedJournalEntry2D,
135
+ getJournalView2D,
136
+ createTilemapWorld2D,
137
+ ensureTilemapWorldLoaded2D,
138
+ unloadTilemapWorld2D,
139
+ drawTilemapWorld2D,
140
+ listTilemapWorldObjects2D,
141
+ findTilemapWorldObject2D,
142
+ resolveTilemapSpawn2D,
143
+ queryTilemapWorldPoint2D,
144
+ queryTilemapWorldAABB2D,
145
+ isTilemapPointBlocked2D,
146
+ moveActorThroughTilemapWorld2D,
147
+ createStreamedWorld2D,
148
+ listLoadedStreamedWorldRegions2D,
149
+ findStreamedWorldRegionAtPoint2D,
150
+ syncStreamedWorldFocus2D,
151
+ queryStreamedWorldPoint2D,
152
+ queryStreamedWorldAABB2D,
153
+ queryStreamedWorldRay2D,
154
+ unloadStreamedWorld2D,
155
+ captureStreamedWorldSnapshot2D,
156
+ applyStreamedWorldSnapshot2D,
157
+ saveStreamedWorldSnapshot2D,
158
+ loadStreamedWorldSnapshot2D,
159
+ deleteStreamedWorldSnapshot2D,
160
+ createTilemapNav2D,
161
+ rebuildTilemapNav2D,
162
+ invalidateTilemapNav2D,
163
+ collectTilemapOccupiedCells2D,
164
+ setTilemapNavOccupiedCells2D,
165
+ findTilemapPath2D,
166
+ resolveTilemapStep2D,
167
+ createWorldCompositor2D,
168
+ ensureWorldCompositorTargets2D,
169
+ destroyWorldCompositor2D,
170
+ runWorldCompositor2D,
171
+ createAdventureInteractable2D,
172
+ createAdventureInteractablesFromTilemapObjects2D,
173
+ createAdventureInteractionState2D,
174
+ stepAdventureInteractables2D,
175
+ createAdventureObjectives,
176
+ resetAdventureObjectives,
177
+ countCompletedObjectives,
178
+ objectivesComplete,
179
+ firstPendingObjective,
180
+ collectAdventureObjectives2D,
181
+ } from '../index.mjs';
182
+
183
+ export { clamp, axisFromKeys, createCooldown, tickCooldown, consumeCooldown, createIntervalSpawner, tickIntervalSpawner, centeredRect, rectsOverlap, removeWhere, distanceSquared2D, createSpriteAnimationLibrary2D, hasSpriteAnimationState2D, createSpriteAnimationRuntime2D, registerSpriteAnimationLibrary2D, createSpriteAnimator2D, playSpriteAnimator2D, syncSpriteAnimatorState2D, stepSpriteAnimationRuntime2D, getSpriteAnimatorState2D, resolveSpriteAnimatorFrame2D, drawSpriteAnimator2D, resolveSpriteFrameRect2D, createAnimationPackage2D, hasAnimationPackageState2D, registerAnimationPackage2D, createPackagedSpriteAnimator2D, getAnimationPackageLibrary2D, getAnimationPackageState2D, createAtlasAssetManifest2D, createAnimationPackageFromAtlasAsset2D, createSceneAudio2D, configureSceneAudio2D, ensureSceneMusic2D, setSceneMusicVolume2D, duckSceneMusic2D, playSceneStinger2D, pauseSceneAudio2D, resumeSceneAudio2D, syncSceneAudio2D, stopSceneAudio2D, propertyTween2D, delayTween2D, sequenceTweens2D, parallelTweens2D, repeatTween2D, yoyoTween2D, moveTo2D, driftTo2D, fadeTo2D, scaleTo2D, rotateTo2D, pulse2D, punch2D, settleTo2D, createTweenComposer2D, playTweenPlan2D, cancelTweenPlan2D, stepTweenComposer2D, getTweenHandleState2D, isTweenHandleActive2D, createFloatingTextLayer2D, spawnFloatingText2D, stepFloatingTextLayer2D, getFloatingTextRenderState2D, drawFloatingTextLayer2D, createHitFlash2D, triggerHitFlash2D, stepHitFlash2D, isHitFlashVisible2D, createHitSparkLayer2D, spawnHitSpark2D, stepHitSparkLayer2D, drawHitSparkLayer2D, createHoverLift2D, setHoverLiftActive2D, stepHoverLift2D, getHoverLiftOffset2D, applyShieldedDamage2D, stepShieldRecharge2D, restoreShieldedHealth2D, createWeightedDropTable2D, rollWeightedDrop2D, createEncounterPressure2D, recordEncounterKill2D, stepEncounterPressure2D, advanceBossPhase2D, createAutoplayController2D, setAutoplayEnabled2D, toggleAutoplayEnabled2D, resolveAutoplayControl2D, createRenderTargetExportState2D, queueRenderTargetExport2D, flushRenderTargetExport2D, createRectTrigger2D, createTriggerTracker, getTriggerTrackerSnapshot, stepRectTriggers2D, stepTriggerTracker, resolveTriggerInteraction, createInteractionPromptState, updateInteractionPromptState, createWaveDirector, activeWave, stepWaveDirector, listEnemyArchetypeIds2D, getEnemyArchetype2D, pickEnemyArchetypeForWave2D, spawnEnemy2D, createInventory2D, addInventoryItem2D, removeInventoryItem2D, hasInventoryItem2D, listInventoryItems2D, selectInventoryCategory2D, selectInventoryItem2D, getSelectedInventoryItem2D, setInventoryItemEquipped2D, getInventoryView2D, createDialogueState2D, registerDialogueConversation2D, startDialogueConversation2D, advanceDialogueConversation2D, chooseDialogueChoice2D, completeDialogueConversation2D, getDialogueView2D, createJournal2D, upsertJournalEntry2D, setJournalEntryStatus2D, listJournalEntries2D, selectJournalCategory2D, selectJournalEntry2D, getSelectedJournalEntry2D, getJournalView2D, createTilemapWorld2D, ensureTilemapWorldLoaded2D, unloadTilemapWorld2D, drawTilemapWorld2D, listTilemapWorldObjects2D, findTilemapWorldObject2D, resolveTilemapSpawn2D, queryTilemapWorldPoint2D, queryTilemapWorldAABB2D, isTilemapPointBlocked2D, moveActorThroughTilemapWorld2D, createStreamedWorld2D, listLoadedStreamedWorldRegions2D, findStreamedWorldRegionAtPoint2D, syncStreamedWorldFocus2D, queryStreamedWorldPoint2D, queryStreamedWorldAABB2D, queryStreamedWorldRay2D, unloadStreamedWorld2D, captureStreamedWorldSnapshot2D, applyStreamedWorldSnapshot2D, saveStreamedWorldSnapshot2D, loadStreamedWorldSnapshot2D, deleteStreamedWorldSnapshot2D, createTilemapNav2D, rebuildTilemapNav2D, invalidateTilemapNav2D, collectTilemapOccupiedCells2D, setTilemapNavOccupiedCells2D, findTilemapPath2D, resolveTilemapStep2D, createWorldCompositor2D, ensureWorldCompositorTargets2D, destroyWorldCompositor2D, runWorldCompositor2D, createAdventureInteractable2D, createAdventureInteractablesFromTilemapObjects2D, createAdventureInteractionState2D, stepAdventureInteractables2D, createAdventureObjectives, resetAdventureObjectives, countCompletedObjectives, objectivesComplete, firstPendingObjective, collectAdventureObjectives2D };
@@ -0,0 +1,26 @@
1
+ import { clamp, axisFromKeys, createCooldown, tickCooldown, consumeCooldown, createIntervalSpawner, tickIntervalSpawner, centeredRect, rectsOverlap, removeWhere, distanceSquared2D, distanceSquared3D, tryJump, stepVerticalMotion } from './starter-utils/core.js';
2
+ import { createSpriteAnimationLibrary2D, hasSpriteAnimationState2D, createSpriteAnimationRuntime2D, registerSpriteAnimationLibrary2D, createSpriteAnimator2D, playSpriteAnimator2D, syncSpriteAnimatorState2D, stepSpriteAnimationRuntime2D, getSpriteAnimatorState2D, resolveSpriteAnimatorFrame2D, drawSpriteAnimator2D, resolveSpriteFrameRect2D } from './starter-utils/animation-2d.js';
3
+ import { createAnimationPackage2D, hasAnimationPackageState2D, registerAnimationPackage2D, createPackagedSpriteAnimator2D, getAnimationPackageLibrary2D, getAnimationPackageState2D } from './starter-utils/animation-packaging-2d.js';
4
+ import { createAtlasAssetManifest2D, createAnimationPackageFromAtlasAsset2D } from './starter-utils/atlas-assets-2d.js';
5
+ import { createSceneAudio2D, configureSceneAudio2D, ensureSceneMusic2D, setSceneMusicVolume2D, duckSceneMusic2D, playSceneStinger2D, pauseSceneAudio2D, resumeSceneAudio2D, syncSceneAudio2D, stopSceneAudio2D } from './starter-utils/scene-audio-2d.js';
6
+ import { propertyTween2D, delayTween2D, sequenceTweens2D, parallelTweens2D, repeatTween2D, yoyoTween2D, moveTo2D, driftTo2D, fadeTo2D, scaleTo2D, rotateTo2D, pulse2D, punch2D, settleTo2D, createTweenComposer2D, playTweenPlan2D, cancelTweenPlan2D, stepTweenComposer2D, getTweenHandleState2D, isTweenHandleActive2D } from './starter-utils/tween-2d.js';
7
+ import { createFloatingTextLayer2D, spawnFloatingText2D, stepFloatingTextLayer2D, getFloatingTextRenderState2D, drawFloatingTextLayer2D, createHitFlash2D, triggerHitFlash2D, stepHitFlash2D, isHitFlashVisible2D, createHitSparkLayer2D, spawnHitSpark2D, stepHitSparkLayer2D, drawHitSparkLayer2D, createHoverLift2D, setHoverLiftActive2D, stepHoverLift2D, getHoverLiftOffset2D } from './starter-utils/combat-feedback-2d.js';
8
+ import { applyShieldedDamage2D, stepShieldRecharge2D, restoreShieldedHealth2D, createWeightedDropTable2D, rollWeightedDrop2D, createEncounterPressure2D, recordEncounterKill2D, stepEncounterPressure2D, advanceBossPhase2D } from './starter-utils/combat-runtime-2d.js';
9
+ import { createRectTrigger2D, createProximityTrigger3D, createVolumeTrigger3D, createTriggerTracker, getTriggerTrackerSnapshot, stepRectTriggers2D, stepVolumeTriggers3D, stepTriggerTracker, resolveTriggerInteraction, createInteractionPromptState, updateInteractionPromptState } from './starter-utils/triggers.js';
10
+ import { createWaveDirector, activeWave, stepWaveDirector } from './starter-utils/wave-director.js';
11
+ import { listEnemyArchetypeIds2D, getEnemyArchetype2D, pickEnemyArchetypeForWave2D, spawnEnemy2D } from './starter-utils/enemy-archetypes-2d.js';
12
+ import { createAutoplayController2D, setAutoplayEnabled2D, toggleAutoplayEnabled2D, resolveAutoplayControl2D, createRenderTargetExportState2D, queueRenderTargetExport2D, flushRenderTargetExport2D } from './starter-utils/autoplay-debug-2d.js';
13
+ import { createInventory2D, addInventoryItem2D, removeInventoryItem2D, hasInventoryItem2D, listInventoryItems2D, selectInventoryCategory2D, selectInventoryItem2D, getSelectedInventoryItem2D, setInventoryItemEquipped2D, getInventoryView2D } from './starter-utils/inventory-2d.js';
14
+ import { createDialogueState2D, registerDialogueConversation2D, startDialogueConversation2D, advanceDialogueConversation2D, chooseDialogueChoice2D, completeDialogueConversation2D, getDialogueView2D } from './starter-utils/dialogue-2d.js';
15
+ import { createJournal2D, upsertJournalEntry2D, setJournalEntryStatus2D, listJournalEntries2D, selectJournalCategory2D, selectJournalEntry2D, getSelectedJournalEntry2D, getJournalView2D } from './starter-utils/journal-2d.js';
16
+ import { createTilemapWorld2D, ensureTilemapWorldLoaded2D, unloadTilemapWorld2D, drawTilemapWorld2D, listTilemapWorldObjects2D, findTilemapWorldObject2D, resolveTilemapSpawn2D, queryTilemapWorldPoint2D, queryTilemapWorldAABB2D, isTilemapPointBlocked2D, moveActorThroughTilemapWorld2D } from './starter-utils/tilemap-world-2d.js';
17
+ import { createStreamedWorld2D, listLoadedStreamedWorldRegions2D, findStreamedWorldRegionAtPoint2D, syncStreamedWorldFocus2D, queryStreamedWorldPoint2D, queryStreamedWorldAABB2D, queryStreamedWorldRay2D, unloadStreamedWorld2D } from './starter-utils/streamed-world-2d.js';
18
+ import { captureStreamedWorldSnapshot2D, applyStreamedWorldSnapshot2D, saveStreamedWorldSnapshot2D, loadStreamedWorldSnapshot2D, deleteStreamedWorldSnapshot2D } from './starter-utils/world-persistence-2d.js';
19
+ import { createTilemapNav2D, rebuildTilemapNav2D, invalidateTilemapNav2D, collectTilemapOccupiedCells2D, setTilemapNavOccupiedCells2D, findTilemapPath2D, resolveTilemapStep2D } from './starter-utils/tilemap-nav-2d.js';
20
+ import { createWorldCompositor2D, ensureWorldCompositorTargets2D, destroyWorldCompositor2D, runWorldCompositor2D } from './starter-utils/world-compositor-2d.js';
21
+ import { createAdventureInteractable2D, createAdventureInteractablesFromTilemapObjects2D, createAdventureInteractionState2D, stepAdventureInteractables2D } from './starter-utils/adventure-world-2d.js';
22
+ import { createCheckpointSystem, updateCheckpointProgress, activeCheckpoint, respawnAtCheckpoint, createGoalZone, isGoalReached, createMovingPlatform3D, stepMovingPlatform3D } from './starter-utils/platformer-3d.js';
23
+ import { createCharacterAvatar3D, setAvatarInput3D, setAvatarVisual3D, spawnCharacterAvatar3D, tickCharacterAvatar3D, getAvatarState3D, getAvatarRenderTransform3D } from './starter-utils/avatar-3d.js';
24
+ import { createAdventureObjectives, resetAdventureObjectives, countCompletedObjectives, objectivesComplete, firstPendingObjective, collectAdventureObjectives2D, collectAdventureObjectives3D } from './starter-utils/adventure-objectives.js';
25
+
26
+ export { clamp, axisFromKeys, createCooldown, tickCooldown, consumeCooldown, createIntervalSpawner, tickIntervalSpawner, centeredRect, rectsOverlap, removeWhere, distanceSquared2D, distanceSquared3D, tryJump, stepVerticalMotion, createSpriteAnimationLibrary2D, hasSpriteAnimationState2D, createSpriteAnimationRuntime2D, registerSpriteAnimationLibrary2D, createSpriteAnimator2D, playSpriteAnimator2D, syncSpriteAnimatorState2D, stepSpriteAnimationRuntime2D, getSpriteAnimatorState2D, resolveSpriteAnimatorFrame2D, drawSpriteAnimator2D, resolveSpriteFrameRect2D, createAnimationPackage2D, hasAnimationPackageState2D, registerAnimationPackage2D, createPackagedSpriteAnimator2D, getAnimationPackageLibrary2D, getAnimationPackageState2D, createAtlasAssetManifest2D, createAnimationPackageFromAtlasAsset2D, createSceneAudio2D, configureSceneAudio2D, ensureSceneMusic2D, setSceneMusicVolume2D, duckSceneMusic2D, playSceneStinger2D, pauseSceneAudio2D, resumeSceneAudio2D, syncSceneAudio2D, stopSceneAudio2D, propertyTween2D, delayTween2D, sequenceTweens2D, parallelTweens2D, repeatTween2D, yoyoTween2D, moveTo2D, driftTo2D, fadeTo2D, scaleTo2D, rotateTo2D, pulse2D, punch2D, settleTo2D, createTweenComposer2D, playTweenPlan2D, cancelTweenPlan2D, stepTweenComposer2D, getTweenHandleState2D, isTweenHandleActive2D, createFloatingTextLayer2D, spawnFloatingText2D, stepFloatingTextLayer2D, getFloatingTextRenderState2D, drawFloatingTextLayer2D, createHitFlash2D, triggerHitFlash2D, stepHitFlash2D, isHitFlashVisible2D, createHitSparkLayer2D, spawnHitSpark2D, stepHitSparkLayer2D, drawHitSparkLayer2D, createHoverLift2D, setHoverLiftActive2D, stepHoverLift2D, getHoverLiftOffset2D, applyShieldedDamage2D, stepShieldRecharge2D, restoreShieldedHealth2D, createWeightedDropTable2D, rollWeightedDrop2D, createEncounterPressure2D, recordEncounterKill2D, stepEncounterPressure2D, advanceBossPhase2D, createRectTrigger2D, createProximityTrigger3D, createVolumeTrigger3D, createTriggerTracker, getTriggerTrackerSnapshot, stepRectTriggers2D, stepVolumeTriggers3D, stepTriggerTracker, resolveTriggerInteraction, createInteractionPromptState, updateInteractionPromptState, createWaveDirector, activeWave, stepWaveDirector, listEnemyArchetypeIds2D, getEnemyArchetype2D, pickEnemyArchetypeForWave2D, spawnEnemy2D, createAutoplayController2D, setAutoplayEnabled2D, toggleAutoplayEnabled2D, resolveAutoplayControl2D, createRenderTargetExportState2D, queueRenderTargetExport2D, flushRenderTargetExport2D, createInventory2D, addInventoryItem2D, removeInventoryItem2D, hasInventoryItem2D, listInventoryItems2D, selectInventoryCategory2D, selectInventoryItem2D, getSelectedInventoryItem2D, setInventoryItemEquipped2D, getInventoryView2D, createDialogueState2D, registerDialogueConversation2D, startDialogueConversation2D, advanceDialogueConversation2D, chooseDialogueChoice2D, completeDialogueConversation2D, getDialogueView2D, createJournal2D, upsertJournalEntry2D, setJournalEntryStatus2D, listJournalEntries2D, selectJournalCategory2D, selectJournalEntry2D, getSelectedJournalEntry2D, getJournalView2D, createTilemapWorld2D, ensureTilemapWorldLoaded2D, unloadTilemapWorld2D, drawTilemapWorld2D, listTilemapWorldObjects2D, findTilemapWorldObject2D, resolveTilemapSpawn2D, queryTilemapWorldPoint2D, queryTilemapWorldAABB2D, isTilemapPointBlocked2D, moveActorThroughTilemapWorld2D, createStreamedWorld2D, listLoadedStreamedWorldRegions2D, findStreamedWorldRegionAtPoint2D, syncStreamedWorldFocus2D, queryStreamedWorldPoint2D, queryStreamedWorldAABB2D, queryStreamedWorldRay2D, unloadStreamedWorld2D, captureStreamedWorldSnapshot2D, applyStreamedWorldSnapshot2D, saveStreamedWorldSnapshot2D, loadStreamedWorldSnapshot2D, deleteStreamedWorldSnapshot2D, createTilemapNav2D, rebuildTilemapNav2D, invalidateTilemapNav2D, collectTilemapOccupiedCells2D, setTilemapNavOccupiedCells2D, findTilemapPath2D, resolveTilemapStep2D, createWorldCompositor2D, ensureWorldCompositorTargets2D, destroyWorldCompositor2D, runWorldCompositor2D, createAdventureInteractable2D, createAdventureInteractablesFromTilemapObjects2D, createAdventureInteractionState2D, stepAdventureInteractables2D, createCheckpointSystem, updateCheckpointProgress, activeCheckpoint, respawnAtCheckpoint, createGoalZone, isGoalReached, createMovingPlatform3D, stepMovingPlatform3D, createCharacterAvatar3D, setAvatarInput3D, setAvatarVisual3D, spawnCharacterAvatar3D, tickCharacterAvatar3D, getAvatarState3D, getAvatarRenderTransform3D, createAdventureObjectives, resetAdventureObjectives, countCompletedObjectives, objectivesComplete, firstPendingObjective, collectAdventureObjectives2D, collectAdventureObjectives3D };
@@ -0,0 +1,102 @@
1
+ import { distanceSquared2D, distanceSquared3D } from './core.js';
2
+
3
+ function finite(value, fallback = 0) {
4
+ const numeric = Number(value);
5
+ return Number.isFinite(numeric) ? numeric : fallback;
6
+ }
7
+
8
+ function normalizeId(value, fallback) {
9
+ if (typeof value === 'string' && value.trim().length > 0) {
10
+ return value.trim();
11
+ }
12
+ return fallback;
13
+ }
14
+
15
+ function normalizeLabel(value, fallback) {
16
+ if (typeof value === 'string' && value.trim().length > 0) {
17
+ return value.trim();
18
+ }
19
+ return fallback;
20
+ }
21
+
22
+ function normalizeObjectiveEntry(entry, index, options = {}) {
23
+ const dimension = options.dimension === '3d' ? '3d' : '2d';
24
+ const fallbackId = `objective-${index + 1}`;
25
+ const fallbackLabel = `Objective ${index + 1}`;
26
+ return {
27
+ id: normalizeId(entry?.id, fallbackId),
28
+ label: normalizeLabel(entry?.label ?? entry?.name, fallbackLabel),
29
+ x: finite(entry?.x),
30
+ y: finite(entry?.y),
31
+ z: dimension === '3d' ? finite(entry?.z) : 0,
32
+ radius: Math.max(0.1, finite(entry?.radius, finite(options.defaultRadius, 1))),
33
+ value: Math.max(1, Math.round(finite(entry?.value, 1))),
34
+ collected: entry?.collected === true,
35
+ };
36
+ }
37
+
38
+ export function createAdventureObjectives(entries = [], options = {}) {
39
+ return (Array.isArray(entries) ? entries : []).map((entry, index) => normalizeObjectiveEntry(entry, index, options));
40
+ }
41
+
42
+ export function resetAdventureObjectives(objectives) {
43
+ for (const objective of Array.isArray(objectives) ? objectives : []) {
44
+ objective.collected = false;
45
+ }
46
+ return objectives;
47
+ }
48
+
49
+ export function countCompletedObjectives(objectives) {
50
+ return (Array.isArray(objectives) ? objectives : []).reduce(
51
+ (total, objective) => total + (objective?.collected === true ? 1 : 0),
52
+ 0,
53
+ );
54
+ }
55
+
56
+ export function objectivesComplete(objectives, requiredCount = null) {
57
+ const totalObjectives = Array.isArray(objectives) ? objectives.length : 0;
58
+ const threshold = Number.isFinite(Number(requiredCount))
59
+ ? Math.max(0, Math.min(totalObjectives, Number(requiredCount)))
60
+ : totalObjectives;
61
+ return countCompletedObjectives(objectives) >= threshold;
62
+ }
63
+
64
+ export function firstPendingObjective(objectives) {
65
+ return (Array.isArray(objectives) ? objectives : []).find((objective) => objective?.collected !== true) || null;
66
+ }
67
+
68
+ function collectAdventureObjectives(subject, objectives, pickupRadius, measureDistanceSquared) {
69
+ const collected = [];
70
+ const extraRadius = Math.max(0, finite(pickupRadius, 0));
71
+ let scoreDelta = 0;
72
+
73
+ for (const objective of Array.isArray(objectives) ? objectives : []) {
74
+ if (!objective || objective.collected === true) continue;
75
+ const threshold = objective.radius + extraRadius;
76
+ if (measureDistanceSquared(subject, objective) > (threshold * threshold)) continue;
77
+ objective.collected = true;
78
+ scoreDelta += objective.value;
79
+ collected.push({
80
+ id: objective.id,
81
+ label: objective.label,
82
+ value: objective.value,
83
+ });
84
+ }
85
+
86
+ return {
87
+ changed: collected.length > 0,
88
+ collected,
89
+ collectedCount: collected.length,
90
+ scoreDelta,
91
+ completedObjectives: countCompletedObjectives(objectives),
92
+ totalObjectives: Array.isArray(objectives) ? objectives.length : 0,
93
+ };
94
+ }
95
+
96
+ export function collectAdventureObjectives2D(subject, objectives, pickupRadius = 0) {
97
+ return collectAdventureObjectives(subject, objectives, pickupRadius, distanceSquared2D);
98
+ }
99
+
100
+ export function collectAdventureObjectives3D(subject, objectives, pickupRadius = 0) {
101
+ return collectAdventureObjectives(subject, objectives, pickupRadius, distanceSquared3D);
102
+ }