@auraindustry/aurajs 0.1.3 → 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 (108) 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/authored-project.mjs +498 -2
  6. package/src/build-contract/capabilities.mjs +87 -1
  7. package/src/build-contract/constants.mjs +1 -0
  8. package/src/build-contract.mjs +2 -0
  9. package/src/bundler.mjs +143 -13
  10. package/src/cli.mjs +681 -13
  11. package/src/commands/packs.mjs +741 -0
  12. package/src/commands/project-authoring.mjs +128 -1
  13. package/src/conformance/cases/app-and-ui-runtime-cases.mjs +1 -2
  14. package/src/conformance/cases/core-runtime-cases.mjs +6 -2
  15. package/src/conformance/cases/scene3d-and-media-cases.mjs +238 -0
  16. package/src/conformance/cases/systems-and-gameplay-cases.mjs +265 -4
  17. package/src/conformance-mobile.mjs +166 -0
  18. package/src/conformance.mjs +89 -30
  19. package/src/evidence-bundle.mjs +242 -0
  20. package/src/headless-test/runtime-coordinator.mjs +186 -33
  21. package/src/headless-test.mjs +2 -0
  22. package/src/helpers/2d/index.mjs +183 -0
  23. package/src/helpers/index.mjs +26 -0
  24. package/src/helpers/starter-utils/adventure-objectives.js +102 -0
  25. package/src/helpers/starter-utils/adventure-world-2d.js +221 -0
  26. package/src/helpers/starter-utils/animation-2d.js +337 -0
  27. package/src/helpers/starter-utils/animation-packaging-2d.js +203 -0
  28. package/src/helpers/starter-utils/atlas-assets-2d.js +111 -0
  29. package/src/helpers/starter-utils/autoplay-debug-2d.js +215 -0
  30. package/src/helpers/starter-utils/avatar-3d.js +404 -0
  31. package/src/helpers/starter-utils/combat-feedback-2d.js +320 -0
  32. package/src/helpers/starter-utils/combat-runtime-2d.js +290 -0
  33. package/src/helpers/starter-utils/core.js +150 -0
  34. package/src/helpers/starter-utils/dialogue-2d.js +351 -0
  35. package/src/helpers/starter-utils/enemy-archetypes-2d.js +68 -0
  36. package/src/helpers/starter-utils/index.js +26 -0
  37. package/src/helpers/starter-utils/inventory-2d.js +268 -0
  38. package/src/helpers/starter-utils/journal-2d.js +267 -0
  39. package/src/helpers/starter-utils/platformer-3d.js +132 -0
  40. package/src/helpers/starter-utils/scene-audio-2d.js +236 -0
  41. package/src/helpers/starter-utils/streamed-world-2d.js +378 -0
  42. package/src/helpers/starter-utils/tilemap-nav-2d.js +499 -0
  43. package/src/helpers/starter-utils/tilemap-world-2d.js +205 -0
  44. package/src/helpers/starter-utils/triggers.js +662 -0
  45. package/src/helpers/starter-utils/tween-2d.js +615 -0
  46. package/src/helpers/starter-utils/wave-director.js +101 -0
  47. package/src/helpers/starter-utils/world-compositor-2d.js +253 -0
  48. package/src/helpers/starter-utils/world-persistence-2d.js +180 -0
  49. package/src/mobile/android/build.mjs +606 -0
  50. package/src/mobile/android/host-artifact.mjs +280 -0
  51. package/src/mobile/ios/build.mjs +1323 -0
  52. package/src/mobile/ios/host-artifact.mjs +819 -0
  53. package/src/mobile/shared/capabilities.mjs +174 -0
  54. package/src/packs/catalog.mjs +259 -0
  55. package/src/perf-benchmark-runner.mjs +17 -12
  56. package/src/perf-benchmark.mjs +408 -4
  57. package/src/publish-command.mjs +303 -6
  58. package/src/replay-runtime.mjs +257 -0
  59. package/src/scaffold/config.mjs +2 -0
  60. package/src/scaffold/fs.mjs +8 -1
  61. package/src/scaffold/project-docs.mjs +43 -1
  62. package/src/scaffold.mjs +4 -0
  63. package/src/session-runtime.mjs +4 -3
  64. package/src/web-conformance.mjs +0 -36
  65. package/templates/create/2d-adventure/config/gameplay/adventure.config.js +9 -6
  66. package/templates/create/2d-adventure/content/gameplay/dialogue.js +85 -0
  67. package/templates/create/2d-adventure/content/gameplay/world.js +32 -36
  68. package/templates/create/2d-adventure/content/gameplay/world.tilemap.json +273 -0
  69. package/templates/create/2d-adventure/docs/design/loop.md +4 -3
  70. package/templates/create/2d-adventure/prefabs/relic.prefab.js +10 -10
  71. package/templates/create/2d-adventure/prefabs/world.prefab.js +127 -74
  72. package/templates/create/2d-adventure/scenes/gameplay.scene.js +603 -112
  73. package/templates/create/2d-adventure/src/runtime/capabilities.js +16 -0
  74. package/templates/create/2d-adventure/ui/hud.screen.js +187 -4
  75. package/templates/create/2d-adventure/ui/journal.screen.js +183 -0
  76. package/templates/create/3d/scenes/gameplay.scene.js +30 -3
  77. package/templates/create/3d/src/runtime/capabilities.js +5 -0
  78. package/templates/create/3d/src/runtime/materials.js +10 -0
  79. package/templates/create/3d-adventure/scenes/gameplay.scene.js +30 -3
  80. package/templates/create/3d-adventure/src/runtime/capabilities.js +5 -0
  81. package/templates/create/3d-adventure/src/runtime/materials.js +11 -0
  82. package/templates/create/3d-collectathon/scenes/gameplay.scene.js +30 -3
  83. package/templates/create/3d-collectathon/src/runtime/capabilities.js +5 -0
  84. package/templates/create/3d-collectathon/src/runtime/materials.js +10 -0
  85. package/templates/create/shared/src/runtime/ui-forms.js +552 -0
  86. package/templates/create/shared/src/starter-utils/adventure-world-2d.js +221 -0
  87. package/templates/create/shared/src/starter-utils/animation-packaging-2d.js +203 -0
  88. package/templates/create/shared/src/starter-utils/atlas-assets-2d.js +111 -0
  89. package/templates/create/shared/src/starter-utils/autoplay-debug-2d.js +215 -0
  90. package/templates/create/shared/src/starter-utils/combat-runtime-2d.js +290 -0
  91. package/templates/create/shared/src/starter-utils/dialogue-2d.js +351 -0
  92. package/templates/create/shared/src/starter-utils/index.js +15 -1
  93. package/templates/create/shared/src/starter-utils/inventory-2d.js +268 -0
  94. package/templates/create/shared/src/starter-utils/journal-2d.js +267 -0
  95. package/templates/create/shared/src/starter-utils/scene-audio-2d.js +236 -0
  96. package/templates/create/shared/src/starter-utils/streamed-world-2d.js +378 -0
  97. package/templates/create/shared/src/starter-utils/tilemap-nav-2d.js +499 -0
  98. package/templates/create/shared/src/starter-utils/tilemap-world-2d.js +205 -0
  99. package/templates/create/shared/src/starter-utils/world-compositor-2d.js +253 -0
  100. package/templates/create/shared/src/starter-utils/world-persistence-2d.js +180 -0
  101. package/templates/create-bin/play.js +36 -7
  102. package/templates/skills/auramaxx/SKILL.md +46 -0
  103. package/templates/skills/auramaxx/project-requirements.md +68 -0
  104. package/templates/skills/auramaxx/starter-recipes.md +104 -0
  105. package/templates/skills/auramaxx/validation-checklist.md +49 -0
  106. package/templates/skills/aurajs/SKILL.md +0 -96
  107. package/templates/skills/aurajs/api-contract-3d.md +0 -7
  108. package/templates/skills/aurajs/api-contract.md +0 -7
@@ -1,3 +1,5 @@
1
+ import { describeProjectAiGuidance } from '../ai-guidance.mjs';
2
+
1
3
  export function renderProjectReadme({ name, projectTitle, template, templateMetadata }) {
2
4
  if (templateMetadata?.runtimeFamily === 'retro') {
3
5
  return renderRetroProjectReadme({ name, projectTitle, template, templateMetadata });
@@ -7,6 +9,7 @@ export function renderProjectReadme({ name, projectTitle, template, templateMeta
7
9
  const workflowSection = renderTemplateWorkflowSection(templateMetadata);
8
10
  const projectMap = renderProjectMapSection(template);
9
11
  const generateFilesSection = renderGenerateFilesSection(template);
12
+ const aiWorkflowSection = renderAiWorkflowSection(template);
10
13
  const stateOwnershipSection = renderStateOwnershipSection();
11
14
  const continuityOwnershipSection = renderContinuityOwnershipSection();
12
15
  const largeAssetSection = renderLargeAssetSection();
@@ -46,6 +49,7 @@ before the first \`auramaxx publish\`.
46
49
 
47
50
  ${largeAssetSection}
48
51
  ${workflowSection}
52
+ ${aiWorkflowSection}
49
53
  ${generateFilesSection}
50
54
  ${stateOwnershipSection}
51
55
  ${continuityOwnershipSection}
@@ -77,6 +81,7 @@ export function renderProjectRunbook({ projectTitle, template, templateMetadata
77
81
  const workflowSection = renderTemplateWorkflowSection(templateMetadata);
78
82
  const firstThirtyMinutes = renderFirstThirtyMinutesSteps(template);
79
83
  const generateFilesSection = renderGenerateFilesSection(template);
84
+ const aiWorkflowSection = renderAiWorkflowSection(template);
80
85
  const stateOwnershipSection = renderStateOwnershipSection();
81
86
  const continuityOwnershipSection = renderContinuityOwnershipSection();
82
87
  const largeAssetSection = renderLargeAssetSection();
@@ -93,6 +98,7 @@ ${stateOwnershipSection}
93
98
  ${continuityOwnershipSection}
94
99
 
95
100
  ${workflowSection}
101
+ ${aiWorkflowSection}
96
102
  ${generateFilesSection}
97
103
 
98
104
  ## First-Hour Implementation Pass
@@ -131,6 +137,36 @@ ${steps.map((line) => `1. ${line}`).join('\n')}
131
137
  `;
132
138
  }
133
139
 
140
+ function renderAiWorkflowSection(template) {
141
+ const aiGuidance = describeProjectAiGuidance({
142
+ template,
143
+ starterUtils: template === 'blank'
144
+ ? null
145
+ : {
146
+ available: true,
147
+ recommendedImportPath: './src/starter-utils/index.js',
148
+ },
149
+ });
150
+
151
+ const importHint = aiGuidance.recommendedImportPath || aiGuidance.preferredPackageSpecifier || '(none)';
152
+ const modules = Array.isArray(aiGuidance.recommendedModules) && aiGuidance.recommendedModules.length > 0
153
+ ? aiGuidance.recommendedModules.map((entry) => `- \`${entry.id}\` via \`${importHint}\``).join('\n')
154
+ : '- no starter helper lane is preselected; build outward from `src/runtime/`, `scenes/`, and `content/`';
155
+
156
+ return `## AI Workflow
157
+
158
+ - run \`auramaxx explain --json\` before moving files so the current source boundary, starter helper lane, and paved-road guidance stay explicit
159
+ - run \`auramaxx check --json\` after edits when you want machine-readable import and registry validation
160
+ - keep authored gameplay code inside \`src/\`, \`scenes/\`, \`ui/\`, \`prefabs/\`, \`config/\`, and \`content/\`
161
+ - preferred helper import: \`${importHint}\`
162
+ - AI paved road lane: \`${aiGuidance.laneId}\`
163
+
164
+ Recommended starter modules:
165
+
166
+ ${modules}
167
+ `;
168
+ }
169
+
134
170
  function renderRetroProjectReadme({ name, projectTitle, template, templateMetadata }) {
135
171
  const controls = templateMetadata.controls.map((line) => `- ${line}`).join('\n');
136
172
  const firstEdits = templateMetadata.firstEdits.map((line) => `1. ${line}`).join('\n');
@@ -352,7 +388,13 @@ export function renderProjectMapSection(template) {
352
388
  - \`config/\` - editable defaults and tuning payloads.
353
389
  - \`content/\` - authored definitions, levels, registries, and progression content.
354
390
  - \`content/registries/\` - starter-owned registry files for cards, enemies, relics, and encounters.
355
- - \`src/starter-utils/\` - reusable helpers copied for non-blank templates.
391
+ - \`src/starter-utils/\` - local copies of reusable authored helper modules
392
+ shipped with AuraJS for non-blank templates. Keep imports local here for
393
+ starter-facing gameplay code; use the published
394
+ \`@auraindustry/aurajs/helpers\` lane only when you want the shared
395
+ package-backed helper surface directly. Run \`auramaxx vendor helpers\` when
396
+ you want to seed or resync the local helper lane in a project that does not
397
+ already have it.
356
398
  - \`assets/starter/\` - starter asset pack and editable design payloads.
357
399
  - \`aura.config.json\` - identity/window/build/modules.
358
400
  - \`aura.capabilities.json\` - canonical runtime API declaration for this scaffold.
package/src/scaffold.mjs CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  CREATE_TEMPLATE_DIRS,
8
8
  GITIGNORE_TEMPLATE,
9
9
  LEGACY_STARTER_TEMPLATE_DIR,
10
+ PACKAGED_STARTER_UTILS_DIR,
10
11
  PLAY_BIN_TEMPLATE,
11
12
  applyTemplateConfigOverrides,
12
13
  buildCapabilitiesDeclaration,
@@ -106,6 +107,9 @@ export function scaffoldGame(options) {
106
107
  copyTree(templateDir, dest, replacements);
107
108
  if (shouldCopyCreateSharedTemplate(normalizedTemplate, templateMetadata) && existsSync(CREATE_SHARED_TEMPLATE_DIR)) {
108
109
  copyTree(CREATE_SHARED_TEMPLATE_DIR, dest, replacements);
110
+ if (existsSync(PACKAGED_STARTER_UTILS_DIR)) {
111
+ copyTree(PACKAGED_STARTER_UTILS_DIR, join(dest, 'src', 'starter-utils'), replacements);
112
+ }
109
113
  }
110
114
 
111
115
  mkdirSync(join(dest, 'assets'), { recursive: true });
@@ -74,8 +74,10 @@ export async function bootSessionRuntime(options = {}) {
74
74
  });
75
75
 
76
76
  const testState = createSessionTestState();
77
- const aura = createHeadlessAura({ width, height, testState });
78
- const context = vm.createContext(createRuntimeContext(aura, testState));
77
+ const aura = createHeadlessAura({ width, height, testState, projectRoot });
78
+ const context = vm.createContext(createRuntimeContext(aura, testState, {
79
+ math: options.math,
80
+ }));
79
81
 
80
82
  const source = readFileSync(bundle.outFile, 'utf8');
81
83
  const script = new vm.Script(source, {
@@ -318,4 +320,3 @@ export async function exportSessionInspect(runtime, options = {}) {
318
320
  };
319
321
  }
320
322
  }
321
-
@@ -16,15 +16,6 @@ export const DEFAULT_WEB_SMOKE_CASES = Object.freeze([
16
16
  testName: 'web loader installs browser-backed aura surface for 2d examples',
17
17
  examples: [],
18
18
  }),
19
- Object.freeze({
20
- id: 'web-supported-render-2d-proof-example',
21
- bucket: 'supported',
22
- expectation: 'supported',
23
- title: 'web-render-2d-proof runs on the committed advanced draw2d browser floor',
24
- file: DEFAULT_TEST_FILE,
25
- testName: 'web loader browser smoke: web-render-2d-proof runs on the committed advanced draw2d browser floor',
26
- examples: ['examples/web-render-2d-proof'],
27
- }),
28
19
  Object.freeze({
29
20
  id: 'web-partial-auramon-example',
30
21
  bucket: 'partial',
@@ -34,33 +25,6 @@ export const DEFAULT_WEB_SMOKE_CASES = Object.freeze([
34
25
  testName: 'web loader browser smoke: auramon runs on the supported 2d subset with input and resize evidence',
35
26
  examples: ['examples/auramon'],
36
27
  }),
37
- Object.freeze({
38
- id: 'web-supported-starter-3d-example',
39
- bucket: 'supported',
40
- expectation: 'supported',
41
- title: 'starter-3d runs on the committed browser 3d floor',
42
- file: DEFAULT_TEST_FILE,
43
- testName: 'web loader browser smoke: starter-3d runs on the committed browser 3d floor',
44
- examples: ['examples/starter-3d'],
45
- }),
46
- Object.freeze({
47
- id: 'web-unsupported-multiplayer-examples',
48
- bucket: 'unsupported',
49
- expectation: 'unsupported',
50
- title: 'multiplayer examples fail before setup with stable capability diagnostics',
51
- file: DEFAULT_TEST_FILE,
52
- testName: 'web loader browser smoke: multiplayer examples fail before setup with stable capability diagnostics',
53
- examples: ['examples/multiplayer-room-client', 'examples/multiplayer-room-host'],
54
- }),
55
- Object.freeze({
56
- id: 'web-unsupported-advanced-3d-example',
57
- bucket: 'unsupported',
58
- expectation: 'unsupported',
59
- title: 'advanced 3d examples outside the committed browser floor fail before setup with stable capability diagnostics',
60
- file: DEFAULT_TEST_FILE,
61
- testName: 'web loader browser smoke: advanced 3d examples still fail before setup with stable capability diagnostics',
62
- examples: ['examples/custom-shader-material-proof'],
63
- }),
64
28
  ]);
65
29
 
66
30
  export class WebConformanceSuiteError extends Error {
@@ -1,14 +1,17 @@
1
1
  export const ADVENTURE_CONFIG = {
2
2
  playerSize: 28,
3
- playerSpeed: 232,
4
- relicRadius: 20,
5
- beaconRadius: 42,
6
- exitPadding: 18,
3
+ playerSpeed: 216,
4
+ pickupSize: 28,
5
+ checkpointSize: 48,
6
+ gateGlowSize: 96,
7
7
  };
8
8
 
9
9
  export const ADVENTURE_TEXT = {
10
10
  started: '{{PROJECT_TITLE}} started (2D adventure template)',
11
- controls: 'Move: Arrows/WASD Interact: E or Enter Hint: H',
12
- clearedTitle: 'RUINS SURVEY COMPLETE',
11
+ controls: 'Move: Arrows/WASD Interact: E or Enter Inventory: I or Tab Journal: J Hint: H',
12
+ inventoryControls: 'Inventory: A/D or Left/Right tabs W/S or Up/Down items I or Tab closes',
13
+ journalControls: 'Journal: A/D or Left/Right sections W/S or Up/Down entries J closes',
14
+ dialogueControls: 'Dialogue: W/S or Up/Down choices E, Enter, or Space confirms',
15
+ clearedTitle: 'ARCHIVE ROUTE SECURED',
13
16
  clearedPrompt: 'Press Enter to restart the route',
14
17
  };
@@ -0,0 +1,85 @@
1
+ export const ARCHIVE_CONSOLE_DIALOGUE_ID = 'archive-console-link';
2
+
3
+ export const JOURNAL_ENTRY_IDS = Object.freeze({
4
+ routeBrief: 'route-brief',
5
+ consoleLog: 'archive-console-log',
6
+ moonGate: 'moon-gate-route',
7
+ });
8
+
9
+ export const JOURNAL_CATEGORIES = [
10
+ { id: 'route', label: 'Route' },
11
+ { id: 'intel', label: 'Archive Intel' },
12
+ ];
13
+
14
+ export const STARTING_JOURNAL_ENTRIES = [
15
+ {
16
+ id: JOURNAL_ENTRY_IDS.routeBrief,
17
+ label: 'Route Brief',
18
+ categoryId: 'route',
19
+ categoryLabel: 'Route',
20
+ description: 'Sweep the Moon Archive, recover the route note, then reopen the Moon Gate.',
21
+ detail: 'The archive console should reveal the final route once the relic anchors are back online.',
22
+ status: 'active',
23
+ badge: 'Active',
24
+ updatedAt: 'Initial route objective',
25
+ },
26
+ ];
27
+
28
+ export const ADVENTURE_DIALOGUES = [
29
+ {
30
+ id: ARCHIVE_CONSOLE_DIALOGUE_ID,
31
+ title: 'Archive Console Link',
32
+ speaker: 'Archivist Sol',
33
+ startNodeId: 'handshake',
34
+ nodes: [
35
+ {
36
+ id: 'handshake',
37
+ lines: [
38
+ 'Moon Archive relay restored. I can mark the exit route once you choose what to review.',
39
+ ],
40
+ nextNodeId: 'prompt',
41
+ },
42
+ {
43
+ id: 'prompt',
44
+ lines: [
45
+ 'Ask for the route or confirm what still blocks the gate.',
46
+ ],
47
+ choices: [
48
+ {
49
+ id: 'ask-route',
50
+ label: 'Ask for the route',
51
+ detail: 'Request the marked path through the lower gallery.',
52
+ nextNodeId: 'route',
53
+ },
54
+ {
55
+ id: 'ask-key',
56
+ label: 'Ask about the Dawn Key',
57
+ detail: 'Confirm what the Moon Gate still needs.',
58
+ nextNodeId: 'key',
59
+ },
60
+ ],
61
+ },
62
+ {
63
+ id: 'route',
64
+ lines: [
65
+ 'The final route runs south, then doubles back to the Moon Gate once the key is recovered.',
66
+ ],
67
+ nextNodeId: 'briefing',
68
+ },
69
+ {
70
+ id: 'key',
71
+ lines: [
72
+ 'The Moon Gate still listens for the Dawn Key. Recover it from the south gallery and the route will hold.',
73
+ ],
74
+ nextNodeId: 'briefing',
75
+ },
76
+ {
77
+ id: 'briefing',
78
+ lines: [
79
+ 'Route note transmitted. Check your journal and carry the Dawn Key back to the gate.',
80
+ ],
81
+ outcomeId: 'route-briefed',
82
+ },
83
+ ],
84
+ },
85
+ ];
@@ -1,46 +1,42 @@
1
- export const WORLD_BOUNDS = { x: 72, y: 72, width: 1136, height: 576 };
1
+ import WORLD_TILEMAP_SOURCE from './world.tilemap.json' with { type: 'json' };
2
2
 
3
- export const PLAYER_SPAWN = { x: 156, y: 584 };
3
+ export const WORLD_ORIGIN = { x: 128, y: 72 };
4
4
 
5
- export const WORLD_OBSTACLES = [
6
- { id: 'fallen-arch', x: 312, y: 236, w: 220, h: 40 },
7
- { id: 'mirror-pool', x: 694, y: 172, w: 164, h: 104 },
8
- { id: 'collapsed-hall', x: 530, y: 422, w: 268, h: 42 },
9
- ];
5
+ export const WORLD_TILEMAP = WORLD_TILEMAP_SOURCE;
6
+
7
+ export const WORLD_OBJECT_LAYERS = Object.freeze({
8
+ markers: 'markers',
9
+ pickups: 'pickups',
10
+ checkpoints: 'checkpoints',
11
+ props: 'props',
12
+ locks: 'locks',
13
+ scenery: 'scenery',
14
+ });
10
15
 
11
- export const RELIC_SPAWNS = [
12
- { id: 'survey-lens', label: 'Survey Lens', x: 214, y: 190, radius: 20 },
13
- { id: 'signal-reel', label: 'Signal Reel', x: 546, y: 152, radius: 20 },
14
- { id: 'chorus-map', label: 'Chorus Map', x: 930, y: 352, radius: 20 },
15
- { id: 'dawn-key', label: 'Dawn Key', x: 792, y: 548, radius: 20 },
16
+ export const INVENTORY_CATEGORIES = [
17
+ { id: 'relics', label: 'Relics' },
18
+ { id: 'keys', label: 'Access Keys' },
19
+ { id: 'field', label: 'Field Notes' },
16
20
  ];
17
21
 
18
- export const BEACON_SITES = [
19
- {
20
- id: 'north-brazier',
21
- label: 'North Brazier',
22
- x: 246,
23
- y: 150,
24
- size: 34,
25
- radius: 42,
26
- requiredRelics: 1,
27
- },
22
+ export const STARTING_INVENTORY_ITEMS = [
28
23
  {
29
- id: 'east-brazier',
30
- label: 'East Brazier',
31
- x: 1034,
32
- y: 276,
33
- size: 34,
34
- radius: 42,
35
- requiredRelics: 3,
24
+ id: 'route-brief',
25
+ label: 'Route Brief',
26
+ categoryId: 'field',
27
+ categoryLabel: 'Field Notes',
28
+ quantity: 1,
29
+ badge: 'BRIEF',
30
+ description: 'Survey the Moon Archive and restore the exit route.',
31
+ detail: 'Recover three relics, inspect the archive console, then use the Dawn Key on the Moon Gate.',
36
32
  },
37
33
  ];
38
34
 
39
- export const EXIT_GATE = {
40
- id: 'moon-gate',
41
- label: 'Moon Gate',
42
- x: 1028,
43
- y: 526,
44
- w: 118,
45
- h: 88,
35
+ export const WORLD_TEXT = {
36
+ zoneLabel: 'Moon Archive',
37
+ objective: 'Recover the relics, inspect the archive console, and leave through the Moon Gate.',
38
+ inventoryHint: 'Inventory stays on the HUD while the journal and dialogue proof move through the overlay screen lane.',
39
+ journalHint: 'Journal tracks route progress and archive intel through one shared starter-owned log surface.',
40
+ consoleNoteTitle: 'Archive Console Log',
41
+ consoleNoteDetail: 'The route seal listens for the Dawn Key. The relic anchors simply restore power to the archive floor.',
46
42
  };
@@ -0,0 +1,273 @@
1
+ {
2
+ "width": 16,
3
+ "height": 9,
4
+ "tilewidth": 64,
5
+ "tileheight": 64,
6
+ "solidLayerNames": [
7
+ "collision"
8
+ ],
9
+ "layers": [
10
+ {
11
+ "name": "ground",
12
+ "type": "tilelayer",
13
+ "width": 16,
14
+ "height": 9,
15
+ "data": [
16
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
17
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
18
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
19
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
20
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
21
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
22
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
23
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
24
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
25
+ ]
26
+ },
27
+ {
28
+ "name": "collision",
29
+ "type": "tilelayer",
30
+ "width": 16,
31
+ "height": 9,
32
+ "data": [
33
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
34
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
35
+ 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
36
+ 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1,
37
+ 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1,
38
+ 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1,
39
+ 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1,
40
+ 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
41
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
42
+ ]
43
+ },
44
+ {
45
+ "name": "markers",
46
+ "type": "objectgroup",
47
+ "objects": [
48
+ {
49
+ "id": 1,
50
+ "name": "player-start",
51
+ "type": "spawn",
52
+ "x": 128,
53
+ "y": 128,
54
+ "point": true
55
+ },
56
+ {
57
+ "id": 2,
58
+ "name": "camp-west",
59
+ "type": "spawn",
60
+ "x": 320,
61
+ "y": 448,
62
+ "point": true
63
+ }
64
+ ]
65
+ },
66
+ {
67
+ "name": "pickups",
68
+ "type": "objectgroup",
69
+ "objects": [
70
+ {
71
+ "id": 101,
72
+ "name": "Survey Lens",
73
+ "type": "pickup",
74
+ "x": 168,
75
+ "y": 168,
76
+ "width": 28,
77
+ "height": 28,
78
+ "properties": {
79
+ "promptText": "Press E to secure the Survey Lens",
80
+ "grantItemId": "survey-lens",
81
+ "grantCategoryId": "relics",
82
+ "grantCategoryLabel": "Relics",
83
+ "grantDescription": "Calibrates the archive's survey route.",
84
+ "grantDetail": "The brass housing still hums with lunar static.",
85
+ "grantBadge": "RELIC"
86
+ }
87
+ },
88
+ {
89
+ "id": 102,
90
+ "name": "Signal Reel",
91
+ "type": "pickup",
92
+ "x": 456,
93
+ "y": 152,
94
+ "width": 28,
95
+ "height": 28,
96
+ "properties": {
97
+ "promptText": "Press E to pocket the Signal Reel",
98
+ "grantItemId": "signal-reel",
99
+ "grantCategoryId": "relics",
100
+ "grantCategoryLabel": "Relics",
101
+ "grantDescription": "Restores the relay sequence for the east hall.",
102
+ "grantDetail": "Stamped with route marks from the first survey team.",
103
+ "grantBadge": "RELIC"
104
+ }
105
+ },
106
+ {
107
+ "id": 103,
108
+ "name": "Chorus Map",
109
+ "type": "pickup",
110
+ "x": 760,
111
+ "y": 344,
112
+ "width": 28,
113
+ "height": 28,
114
+ "properties": {
115
+ "promptText": "Press E to collect the Chorus Map",
116
+ "grantItemId": "chorus-map",
117
+ "grantCategoryId": "relics",
118
+ "grantCategoryLabel": "Relics",
119
+ "grantDescription": "Pins the resonant floor and old service ducts.",
120
+ "grantDetail": "Enough of it survived to restore the final route.",
121
+ "grantBadge": "RELIC"
122
+ }
123
+ },
124
+ {
125
+ "id": 104,
126
+ "name": "Dawn Key",
127
+ "type": "pickup",
128
+ "x": 888,
129
+ "y": 456,
130
+ "width": 28,
131
+ "height": 28,
132
+ "properties": {
133
+ "promptText": "Press E to recover the Dawn Key",
134
+ "grantItemId": "dawn-key",
135
+ "grantCategoryId": "keys",
136
+ "grantCategoryLabel": "Access Keys",
137
+ "grantDescription": "Still accepted by the Moon Gate lock.",
138
+ "grantDetail": "The key teeth match the seal at the archive exit.",
139
+ "grantBadge": "KEY"
140
+ }
141
+ }
142
+ ]
143
+ },
144
+ {
145
+ "name": "checkpoints",
146
+ "type": "objectgroup",
147
+ "objects": [
148
+ {
149
+ "id": 201,
150
+ "name": "Camp Lantern",
151
+ "type": "checkpoint",
152
+ "x": 288,
153
+ "y": 416,
154
+ "width": 48,
155
+ "height": 48,
156
+ "properties": {
157
+ "promptText": "Press E to mark the west camp checkpoint",
158
+ "checkpointId": "camp-west"
159
+ }
160
+ }
161
+ ]
162
+ },
163
+ {
164
+ "name": "props",
165
+ "type": "objectgroup",
166
+ "objects": [
167
+ {
168
+ "id": 301,
169
+ "name": "Archive Console",
170
+ "type": "prop",
171
+ "x": 616,
172
+ "y": 192,
173
+ "width": 56,
174
+ "height": 40,
175
+ "properties": {
176
+ "promptText": "Press E to inspect the archive console"
177
+ }
178
+ }
179
+ ]
180
+ },
181
+ {
182
+ "name": "locks",
183
+ "type": "objectgroup",
184
+ "objects": [
185
+ {
186
+ "id": 401,
187
+ "name": "Moon Gate",
188
+ "type": "lock",
189
+ "x": 896,
190
+ "y": 448,
191
+ "width": 96,
192
+ "height": 88,
193
+ "properties": {
194
+ "promptText": "Press E to unlock the Moon Gate",
195
+ "lockedPromptText": "Recover the Dawn Key before opening the Moon Gate",
196
+ "openedPromptText": "The Moon Gate is online",
197
+ "requiredItemId": "dawn-key",
198
+ "requiredQuantity": 1,
199
+ "consumeRequiredItem": false
200
+ }
201
+ }
202
+ ]
203
+ },
204
+ {
205
+ "name": "scenery",
206
+ "type": "objectgroup",
207
+ "objects": [
208
+ {
209
+ "id": 501,
210
+ "name": "Central Court",
211
+ "type": "plaza",
212
+ "x": 64,
213
+ "y": 64,
214
+ "width": 896,
215
+ "height": 448,
216
+ "properties": {
217
+ "fill": "#14211b",
218
+ "border": "#294436"
219
+ }
220
+ },
221
+ {
222
+ "id": 502,
223
+ "name": "Mirror Pool",
224
+ "type": "pool",
225
+ "x": 704,
226
+ "y": 128,
227
+ "width": 160,
228
+ "height": 96,
229
+ "properties": {
230
+ "fill": "#173949",
231
+ "border": "#3a728c"
232
+ }
233
+ },
234
+ {
235
+ "id": 503,
236
+ "name": "Collapsed Hall",
237
+ "type": "ruin",
238
+ "x": 256,
239
+ "y": 224,
240
+ "width": 192,
241
+ "height": 48,
242
+ "properties": {
243
+ "fill": "#28302d",
244
+ "border": "#4c5b57"
245
+ }
246
+ },
247
+ {
248
+ "id": 504,
249
+ "name": "South Gallery",
250
+ "type": "ruin",
251
+ "x": 512,
252
+ "y": 384,
253
+ "width": 224,
254
+ "height": 48,
255
+ "properties": {
256
+ "fill": "#242a29",
257
+ "border": "#48504c"
258
+ }
259
+ }
260
+ ]
261
+ }
262
+ ],
263
+ "tilesets": [
264
+ {
265
+ "firstgid": 1,
266
+ "image": "ruins-placeholder.png",
267
+ "tilewidth": 64,
268
+ "tileheight": 64,
269
+ "tilecount": 1,
270
+ "columns": 1
271
+ }
272
+ ]
273
+ }
@@ -1,5 +1,6 @@
1
1
  # 2D Adventure Loop
2
2
 
3
- 1. Sweep the ruin, collect four relics, and light the route beacons.
4
- 1. Keep tuning knobs in `config/gameplay/adventure.config.js` and authored room nouns in `content/gameplay/world.js`.
5
- 1. Extend the loop by adding more relic families, gate rules, or room variants before introducing heavier systems.
3
+ 1. Sweep the Moon Archive, recover the route relics, inspect the archive console, and leave through the Moon Gate.
4
+ 1. Keep authored room nouns in `content/gameplay/world.js`, `content/gameplay/world.tilemap.json`, and `content/gameplay/dialogue.js`, then keep starter-specific render/collision wrappers in `prefabs/world.prefab.js`.
5
+ 1. Use the archive console beat to prove the shared dialogue helper lane plus the shared journal/log owner before widening into heavier narrative or quest systems.
6
+ 1. Extend the loop by adding more object layers, item categories, checkpoints, or lock rules once the dialogue and journal proof still fits in one readable starter scene.