@waica/cli 0.3.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 (231) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +64 -0
  3. package/dist/cli.js +184 -0
  4. package/dist/editor/assets/abap-08VXUWAP.js +1 -0
  5. package/dist/editor/assets/apex-BWPQTe0t.js +1 -0
  6. package/dist/editor/assets/azcli-Bc_sGQ0U.js +1 -0
  7. package/dist/editor/assets/bat-i0X4ZdIN.js +1 -0
  8. package/dist/editor/assets/bicep-B5-_aFwp.js +2 -0
  9. package/dist/editor/assets/cameligo-DMUM7wLl.js +1 -0
  10. package/dist/editor/assets/clojure-Cm7r79vr.js +1 -0
  11. package/dist/editor/assets/codicon-DCmgc-ay.ttf +0 -0
  12. package/dist/editor/assets/coffee-Ba7i2nA0.js +1 -0
  13. package/dist/editor/assets/cpp-C7h46wYY.js +1 -0
  14. package/dist/editor/assets/csharp-BKxtCVv1.js +1 -0
  15. package/dist/editor/assets/csp-bTuwJoIa.js +1 -0
  16. package/dist/editor/assets/css-DIMkf-bt.js +3 -0
  17. package/dist/editor/assets/css.worker-Fwwr_HdT.js +88 -0
  18. package/dist/editor/assets/cssMode-CQE-WdwL.js +4 -0
  19. package/dist/editor/assets/cypher-CVaqCwHa.js +1 -0
  20. package/dist/editor/assets/dart-onAF5SnQ.js +1 -0
  21. package/dist/editor/assets/dockerfile-DZFCIeNp.js +1 -0
  22. package/dist/editor/assets/ecl-D05T4iGw.js +1 -0
  23. package/dist/editor/assets/editor.worker-DsBDrWS5.js +12 -0
  24. package/dist/editor/assets/elixir-6RTg0lbw.js +1 -0
  25. package/dist/editor/assets/flow9-C5_-GSwl.js +1 -0
  26. package/dist/editor/assets/freemarker2-CYgdVabn.js +3 -0
  27. package/dist/editor/assets/fsharp-C8Ef5oNN.js +1 -0
  28. package/dist/editor/assets/go-C-y9NEjX.js +1 -0
  29. package/dist/editor/assets/graphql-fmXr3nnJ.js +1 -0
  30. package/dist/editor/assets/handlebars-DdeORCJD.js +1 -0
  31. package/dist/editor/assets/hcl-CpzslTdj.js +1 -0
  32. package/dist/editor/assets/html-DTIAGV84.js +1 -0
  33. package/dist/editor/assets/html.worker-B3Ztmmz2.js +495 -0
  34. package/dist/editor/assets/htmlMode-CRV3iBih.js +4 -0
  35. package/dist/editor/assets/index-Btzc6zxr.css +1 -0
  36. package/dist/editor/assets/index-Dhkqk31v.js +11016 -0
  37. package/dist/editor/assets/ini-sBoK_t0W.js +1 -0
  38. package/dist/editor/assets/java-BEtHBSE6.js +1 -0
  39. package/dist/editor/assets/javascript-dxBW86cl.js +1 -0
  40. package/dist/editor/assets/json.worker-PWQxM7ZO.js +51 -0
  41. package/dist/editor/assets/jsonMode-DFA5-FFK.js +10 -0
  42. package/dist/editor/assets/julia-Bri6UV-V.js +1 -0
  43. package/dist/editor/assets/kotlin-B0qVs-E9.js +1 -0
  44. package/dist/editor/assets/less-B9JPFI3C.js +2 -0
  45. package/dist/editor/assets/lexon-CfSJPG6W.js +1 -0
  46. package/dist/editor/assets/liquid-CScWaXYV.js +1 -0
  47. package/dist/editor/assets/lua-CsQS60Ue.js +1 -0
  48. package/dist/editor/assets/m3-D-oSqn_W.js +1 -0
  49. package/dist/editor/assets/markdown-Cimd5fb3.js +1 -0
  50. package/dist/editor/assets/mdx-Bvp84SqA.js +1 -0
  51. package/dist/editor/assets/mips-CIPQ_RoX.js +1 -0
  52. package/dist/editor/assets/msdax-DauUninz.js +1 -0
  53. package/dist/editor/assets/mysql-SOo6toE5.js +1 -0
  54. package/dist/editor/assets/objective-c-FvmIjYaQ.js +1 -0
  55. package/dist/editor/assets/pascal-DrH0SRf2.js +1 -0
  56. package/dist/editor/assets/pascaligo-D-ptJ9y-.js +1 -0
  57. package/dist/editor/assets/perl-oz_6vUea.js +1 -0
  58. package/dist/editor/assets/pgsql-DTj74zXo.js +1 -0
  59. package/dist/editor/assets/php-nr791fC2.js +1 -0
  60. package/dist/editor/assets/pla-CopQ2nXW.js +1 -0
  61. package/dist/editor/assets/postiats-43DmfD33.js +1 -0
  62. package/dist/editor/assets/powerquery-D3hlyOfw.js +1 -0
  63. package/dist/editor/assets/powershell-DmHpPYUd.js +1 -0
  64. package/dist/editor/assets/protobuf-C531GsRP.js +2 -0
  65. package/dist/editor/assets/pug-Z5eAx3Zn.js +1 -0
  66. package/dist/editor/assets/python-CG-OtvFa.js +1 -0
  67. package/dist/editor/assets/qsharp-DkqhCAOL.js +1 -0
  68. package/dist/editor/assets/r-BwWrilGY.js +1 -0
  69. package/dist/editor/assets/razor-r-iUEZPj.js +1 -0
  70. package/dist/editor/assets/redis-ClamHrr6.js +1 -0
  71. package/dist/editor/assets/redshift-DT7zqm-g.js +1 -0
  72. package/dist/editor/assets/restructuredtext-BYgofb2h.js +1 -0
  73. package/dist/editor/assets/ruby-DezsRK8O.js +1 -0
  74. package/dist/editor/assets/rust-DdL9SqIa.js +1 -0
  75. package/dist/editor/assets/sb-CcwsVR0C.js +1 -0
  76. package/dist/editor/assets/scala-DHpiXF5c.js +1 -0
  77. package/dist/editor/assets/scheme-BeGwcela.js +1 -0
  78. package/dist/editor/assets/scss-gp-XZpBa.js +3 -0
  79. package/dist/editor/assets/shell-CC2rA5mh.js +1 -0
  80. package/dist/editor/assets/solidity-BEEn4gHE.js +1 -0
  81. package/dist/editor/assets/sophia-CRfGWb83.js +1 -0
  82. package/dist/editor/assets/sparql-D_Lu-MrJ.js +1 -0
  83. package/dist/editor/assets/sql-NEE52Syq.js +1 -0
  84. package/dist/editor/assets/st-DbInun42.js +1 -0
  85. package/dist/editor/assets/swift-Bxkupp3x.js +1 -0
  86. package/dist/editor/assets/systemverilog-Bz4Y3fRF.js +1 -0
  87. package/dist/editor/assets/tcl-DISqw1ZD.js +1 -0
  88. package/dist/editor/assets/ts.worker-0mEyHVru.js +51339 -0
  89. package/dist/editor/assets/tsMode-Bth1rJwM.js +11 -0
  90. package/dist/editor/assets/twig-De2hgUGE.js +1 -0
  91. package/dist/editor/assets/typescript-tNRuHsoe.js +1 -0
  92. package/dist/editor/assets/typespec-B8J7ngcE.js +1 -0
  93. package/dist/editor/assets/vb-DV3o63ZY.js +1 -0
  94. package/dist/editor/assets/wgsl-DpFanUEy.js +298 -0
  95. package/dist/editor/assets/xml-BCx9e6CK.js +1 -0
  96. package/dist/editor/assets/yaml-Bb-peGP_.js +1 -0
  97. package/dist/editor/index.html +14 -0
  98. package/dist/mcp/archetypes.js +103 -0
  99. package/dist/mcp/cli.js +6 -0
  100. package/dist/mcp/create-project.js +151 -0
  101. package/dist/mcp/introspection.js +201 -0
  102. package/dist/mcp/node_modules/@waica/archetype-platformer/assets/waica-coin.png +0 -0
  103. package/dist/mcp/node_modules/@waica/archetype-platformer/assets/waica-dog.png +0 -0
  104. package/dist/mcp/node_modules/@waica/archetype-platformer/assets/waica-slime.png +0 -0
  105. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/art.d.ts +10 -0
  106. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/art.js +13 -0
  107. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/bundle.d.ts +3 -0
  108. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/bundle.js +10 -0
  109. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/controls.d.ts +5 -0
  110. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/controls.js +12 -0
  111. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/index.d.ts +38 -0
  112. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/index.js +34 -0
  113. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/manifest.d.ts +15 -0
  114. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/manifest.js +26 -0
  115. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/prefabs.d.ts +7 -0
  116. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/prefabs.js +97 -0
  117. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/registry-data.d.ts +5 -0
  118. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/registry-data.js +45 -0
  119. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/registry.d.ts +6 -0
  120. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/registry.js +15 -0
  121. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/scene-default.d.ts +40 -0
  122. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/scene-default.js +93 -0
  123. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/ui.d.ts +10 -0
  124. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/ui.js +24 -0
  125. package/dist/mcp/node_modules/@waica/archetype-platformer/package.json +30 -0
  126. package/dist/mcp/node_modules/@waica/behaviors/dist/chaser.d.ts +59 -0
  127. package/dist/mcp/node_modules/@waica/behaviors/dist/chaser.js +127 -0
  128. package/dist/mcp/node_modules/@waica/behaviors/dist/collectible.d.ts +25 -0
  129. package/dist/mcp/node_modules/@waica/behaviors/dist/collectible.js +27 -0
  130. package/dist/mcp/node_modules/@waica/behaviors/dist/hazard.d.ts +29 -0
  131. package/dist/mcp/node_modules/@waica/behaviors/dist/hazard.js +42 -0
  132. package/dist/mcp/node_modules/@waica/behaviors/dist/index.d.ts +9 -0
  133. package/dist/mcp/node_modules/@waica/behaviors/dist/index.js +9 -0
  134. package/dist/mcp/node_modules/@waica/behaviors/dist/lifetime.d.ts +16 -0
  135. package/dist/mcp/node_modules/@waica/behaviors/dist/lifetime.js +19 -0
  136. package/dist/mcp/node_modules/@waica/behaviors/dist/npc.d.ts +4 -0
  137. package/dist/mcp/node_modules/@waica/behaviors/dist/npc.js +14 -0
  138. package/dist/mcp/node_modules/@waica/behaviors/dist/patrol.d.ts +43 -0
  139. package/dist/mcp/node_modules/@waica/behaviors/dist/patrol.js +68 -0
  140. package/dist/mcp/node_modules/@waica/behaviors/dist/platformer-motor.d.ts +124 -0
  141. package/dist/mcp/node_modules/@waica/behaviors/dist/platformer-motor.js +146 -0
  142. package/dist/mcp/node_modules/@waica/behaviors/dist/player-identity.d.ts +3 -0
  143. package/dist/mcp/node_modules/@waica/behaviors/dist/player-identity.js +5 -0
  144. package/dist/mcp/node_modules/@waica/behaviors/dist/player-states.d.ts +18 -0
  145. package/dist/mcp/node_modules/@waica/behaviors/dist/player-states.js +95 -0
  146. package/dist/mcp/node_modules/@waica/behaviors/dist/respawnable.d.ts +23 -0
  147. package/dist/mcp/node_modules/@waica/behaviors/dist/respawnable.js +27 -0
  148. package/dist/mcp/node_modules/@waica/behaviors/package.json +24 -0
  149. package/dist/mcp/node_modules/@waica/engine/dist/aabb.d.ts +2 -0
  150. package/dist/mcp/node_modules/@waica/engine/dist/aabb.js +4 -0
  151. package/dist/mcp/node_modules/@waica/engine/dist/animation/clip-player.d.ts +20 -0
  152. package/dist/mcp/node_modules/@waica/engine/dist/animation/clip-player.js +24 -0
  153. package/dist/mcp/node_modules/@waica/engine/dist/animation/contract.d.ts +21 -0
  154. package/dist/mcp/node_modules/@waica/engine/dist/animation/contract.js +23 -0
  155. package/dist/mcp/node_modules/@waica/engine/dist/animation/sheet.d.ts +65 -0
  156. package/dist/mcp/node_modules/@waica/engine/dist/animation/sheet.js +44 -0
  157. package/dist/mcp/node_modules/@waica/engine/dist/archetype.d.ts +37 -0
  158. package/dist/mcp/node_modules/@waica/engine/dist/archetype.js +1 -0
  159. package/dist/mcp/node_modules/@waica/engine/dist/camera.d.ts +71 -0
  160. package/dist/mcp/node_modules/@waica/engine/dist/camera.js +59 -0
  161. package/dist/mcp/node_modules/@waica/engine/dist/collision-shape.d.ts +26 -0
  162. package/dist/mcp/node_modules/@waica/engine/dist/collision-shape.js +136 -0
  163. package/dist/mcp/node_modules/@waica/engine/dist/component-registry.d.ts +16 -0
  164. package/dist/mcp/node_modules/@waica/engine/dist/component-registry.js +44 -0
  165. package/dist/mcp/node_modules/@waica/engine/dist/component.d.ts +58 -0
  166. package/dist/mcp/node_modules/@waica/engine/dist/component.js +11 -0
  167. package/dist/mcp/node_modules/@waica/engine/dist/components/animated-sprite.d.ts +80 -0
  168. package/dist/mcp/node_modules/@waica/engine/dist/components/animated-sprite.js +210 -0
  169. package/dist/mcp/node_modules/@waica/engine/dist/components/dynamic-body.d.ts +68 -0
  170. package/dist/mcp/node_modules/@waica/engine/dist/components/dynamic-body.js +189 -0
  171. package/dist/mcp/node_modules/@waica/engine/dist/components/hitbox.d.ts +25 -0
  172. package/dist/mcp/node_modules/@waica/engine/dist/components/hitbox.js +21 -0
  173. package/dist/mcp/node_modules/@waica/engine/dist/components/solid.d.ts +32 -0
  174. package/dist/mcp/node_modules/@waica/engine/dist/components/solid.js +45 -0
  175. package/dist/mcp/node_modules/@waica/engine/dist/components/sprite.d.ts +51 -0
  176. package/dist/mcp/node_modules/@waica/engine/dist/components/sprite.js +112 -0
  177. package/dist/mcp/node_modules/@waica/engine/dist/entity.d.ts +22 -0
  178. package/dist/mcp/node_modules/@waica/engine/dist/entity.js +52 -0
  179. package/dist/mcp/node_modules/@waica/engine/dist/events.d.ts +8 -0
  180. package/dist/mcp/node_modules/@waica/engine/dist/events.js +20 -0
  181. package/dist/mcp/node_modules/@waica/engine/dist/game.d.ts +95 -0
  182. package/dist/mcp/node_modules/@waica/engine/dist/game.js +263 -0
  183. package/dist/mcp/node_modules/@waica/engine/dist/index.d.ts +39 -0
  184. package/dist/mcp/node_modules/@waica/engine/dist/index.js +26 -0
  185. package/dist/mcp/node_modules/@waica/engine/dist/input.d.ts +40 -0
  186. package/dist/mcp/node_modules/@waica/engine/dist/input.js +84 -0
  187. package/dist/mcp/node_modules/@waica/engine/dist/scene.d.ts +80 -0
  188. package/dist/mcp/node_modules/@waica/engine/dist/scene.js +93 -0
  189. package/dist/mcp/node_modules/@waica/engine/dist/solid-axis.d.ts +21 -0
  190. package/dist/mcp/node_modules/@waica/engine/dist/solid-axis.js +77 -0
  191. package/dist/mcp/node_modules/@waica/engine/dist/state/hooks.d.ts +90 -0
  192. package/dist/mcp/node_modules/@waica/engine/dist/state/hooks.js +81 -0
  193. package/dist/mcp/node_modules/@waica/engine/dist/state/state-machine.d.ts +83 -0
  194. package/dist/mcp/node_modules/@waica/engine/dist/state/state-machine.js +173 -0
  195. package/dist/mcp/node_modules/@waica/engine/dist/stats.d.ts +27 -0
  196. package/dist/mcp/node_modules/@waica/engine/dist/stats.js +54 -0
  197. package/dist/mcp/node_modules/@waica/engine/dist/ui.d.ts +47 -0
  198. package/dist/mcp/node_modules/@waica/engine/dist/ui.js +175 -0
  199. package/dist/mcp/node_modules/@waica/engine/package.json +25 -0
  200. package/dist/mcp/package-resolver.js +240 -0
  201. package/dist/mcp/project-path.js +86 -0
  202. package/dist/mcp/scaffolds.js +153 -0
  203. package/dist/mcp/server.js +217 -0
  204. package/dist/mcp/stdio.js +13 -0
  205. package/dist/mcp/template/README.md +22 -0
  206. package/dist/mcp/template/_gitignore +5 -0
  207. package/dist/mcp/template/index.html +25 -0
  208. package/dist/mcp/template/package.json.tpl +20 -0
  209. package/dist/mcp/template/public/waica.params.json +1 -0
  210. package/dist/mcp/template/src/art/waica-coin.png +0 -0
  211. package/dist/mcp/template/src/art/waica-dog.png +0 -0
  212. package/dist/mcp/template/src/art/waica-slime.png +0 -0
  213. package/dist/mcp/template/src/characters/player.character.json +133 -0
  214. package/dist/mcp/template/src/characters/slime.character.json +61 -0
  215. package/dist/mcp/template/src/controls.json +8 -0
  216. package/dist/mcp/template/src/game.json +10 -0
  217. package/dist/mcp/template/src/main.ts +105 -0
  218. package/dist/mcp/template/src/objects/coin.object.json +41 -0
  219. package/dist/mcp/template/src/scenes/main.scene.json +217 -0
  220. package/dist/mcp/template/src/stats.json +7 -0
  221. package/dist/mcp/template/src/tiles/block.tile.json +21 -0
  222. package/dist/mcp/template/src/tiles/decor.tile.json +14 -0
  223. package/dist/mcp/template/src/tiles/platform.tile.json +21 -0
  224. package/dist/mcp/template/src/ui/coin-counter.html +12 -0
  225. package/dist/mcp/template/tsconfig.json +15 -0
  226. package/dist/mcp/template/vite.config.ts +3 -0
  227. package/dist/mcp/validation.js +323 -0
  228. package/dist/mcp/workspace-loader.js +14 -0
  229. package/dist/mcp/workspace-runtime.js +109 -0
  230. package/dist/server.js +210 -0
  231. package/package.json +38 -0
@@ -0,0 +1,151 @@
1
+ import { access, mkdir, readFile, readdir, stat, writeFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { PackageResolver, mixedSourceWarnings, provenanceRows, } from './package-resolver.js';
5
+ import { assertAbsoluteProjectPath } from './project-path.js';
6
+ const moduleDirectory = path.dirname(fileURLToPath(import.meta.url));
7
+ async function exists(target) {
8
+ try {
9
+ await access(target);
10
+ return true;
11
+ }
12
+ catch (error) {
13
+ if (error.code === 'ENOENT')
14
+ return false;
15
+ throw error;
16
+ }
17
+ }
18
+ async function templateRoot() {
19
+ const built = path.join(moduleDirectory, 'template');
20
+ if (await exists(path.join(built, 'package.json.tpl')))
21
+ return built;
22
+ const source = path.resolve(moduleDirectory, '../../editor/template');
23
+ if (await exists(path.join(source, 'package.json.tpl')))
24
+ return source;
25
+ throw new Error('Waica project template is missing from this MCP installation.');
26
+ }
27
+ function projectUriMap(archetype) {
28
+ return Object.fromEntries(archetype.art.map((art) => [art.uri, `src/art/${art.file}`]));
29
+ }
30
+ function projectJson(value, archetype) {
31
+ const uris = projectUriMap(archetype);
32
+ return (JSON.stringify(value, (_key, entry) => typeof entry === 'string' ? (uris[entry] ?? entry) : entry, 2) + '\n');
33
+ }
34
+ async function chassisFiles(root, name, start, version, archetype) {
35
+ const read = (relative) => readFile(path.join(root, relative), 'utf8');
36
+ const [pkgTpl, indexHtml, mainTs, controlsText, statsJson, gameText, tsconfig, vite, readme, gitignore, params] = await Promise.all([
37
+ read('package.json.tpl'),
38
+ read('index.html'),
39
+ read('src/main.ts'),
40
+ read('src/controls.json'),
41
+ read('src/stats.json'),
42
+ read('src/game.json'),
43
+ read('tsconfig.json'),
44
+ read('vite.config.ts'),
45
+ read('README.md'),
46
+ read('_gitignore'),
47
+ read('public/waica.params.json'),
48
+ ]);
49
+ const controls = {
50
+ ...JSON.parse(controlsText),
51
+ bindings: archetype.bindings,
52
+ };
53
+ const game = {
54
+ ...JSON.parse(gameText),
55
+ archetype: archetype.id,
56
+ };
57
+ const scene = start === 'demo' ? archetype.scene : archetype.blankScene;
58
+ return {
59
+ 'package.json': pkgTpl
60
+ .replaceAll('__PROJECT_NAME__', name)
61
+ .replaceAll('__WAICA_VERSION__', version),
62
+ 'index.html': indexHtml,
63
+ 'tsconfig.json': tsconfig,
64
+ 'vite.config.ts': vite,
65
+ 'README.md': readme,
66
+ '.gitignore': gitignore,
67
+ 'src/main.ts': mainTs,
68
+ 'src/controls.json': JSON.stringify(controls, null, 2) + '\n',
69
+ 'src/stats.json': statsJson,
70
+ 'src/game.json': JSON.stringify(game, null, 2) + '\n',
71
+ 'src/scenes/main.scene.json': projectJson(scene, archetype),
72
+ 'public/waica.params.json': params,
73
+ };
74
+ }
75
+ async function validateTarget(target) {
76
+ assertAbsoluteProjectPath(target);
77
+ const name = path.basename(path.normalize(target));
78
+ if (!/^[a-z0-9][a-z0-9-_.]*$/.test(name)) {
79
+ throw new Error(`Project name "${name}" is invalid; it must match /^[a-z0-9][a-z0-9-_.]*$/.`);
80
+ }
81
+ const parent = path.dirname(target);
82
+ let parentInfo;
83
+ try {
84
+ parentInfo = await stat(parent);
85
+ }
86
+ catch (error) {
87
+ if (error.code === 'ENOENT') {
88
+ throw new Error(`Project parent directory does not exist: ${parent}`);
89
+ }
90
+ throw error;
91
+ }
92
+ if (!parentInfo.isDirectory())
93
+ throw new Error(`Project parent is not a directory: ${parent}`);
94
+ try {
95
+ const targetInfo = await stat(target);
96
+ if (!targetInfo.isDirectory())
97
+ throw new Error(`Project target is a file: ${target}`);
98
+ const found = (await readdir(target)).sort();
99
+ if (found.length) {
100
+ throw new Error(`Project target is not empty; found: ${found.join(', ')}`);
101
+ }
102
+ return { exists: true, name };
103
+ }
104
+ catch (error) {
105
+ if (error.code === 'ENOENT')
106
+ return { exists: false, name };
107
+ throw error;
108
+ }
109
+ }
110
+ /** Creates one project without installing dependencies or overwriting files. */
111
+ export async function createProject(projectPath, start = 'demo') {
112
+ if (start !== 'demo' && start !== 'blank')
113
+ throw new Error('start must be "demo" or "blank"');
114
+ const target = await validateTarget(projectPath);
115
+ const resolver = new PackageResolver();
116
+ const [engine, behaviors, archetypePackage] = await Promise.all([
117
+ resolver.load('@waica/engine'),
118
+ resolver.load('@waica/behaviors'),
119
+ resolver.load('@waica/archetype-platformer', './manifest'),
120
+ ]);
121
+ const archetype = archetypePackage.module.ARCHETYPE;
122
+ const files = await chassisFiles(await templateRoot(), target.name, start, engine.provenance.version, archetype);
123
+ if (start === 'demo') {
124
+ for (const [ref, prefab] of Object.entries(archetype.prefabs)) {
125
+ files[`src/${ref}.${prefab.type}.json`] = projectJson(prefab, archetype);
126
+ }
127
+ for (const [name, html] of Object.entries(archetype.registry.ui ?? {})) {
128
+ files[`src/ui/${name}.html`] = html;
129
+ }
130
+ for (const art of archetype.art) {
131
+ files[`src/art/${art.file}`] = await readFile(path.join(archetypePackage.packageRoot, 'assets', art.file));
132
+ }
133
+ }
134
+ if (!target.exists)
135
+ await mkdir(projectPath);
136
+ for (const [relative, contents] of Object.entries(files)) {
137
+ const destination = path.join(projectPath, relative);
138
+ await mkdir(path.dirname(destination), { recursive: true });
139
+ await writeFile(destination, contents);
140
+ }
141
+ const provenance = provenanceRows([engine, behaviors, archetypePackage]);
142
+ return {
143
+ projectPath,
144
+ name: target.name,
145
+ start,
146
+ createdFiles: Object.keys(files).sort(),
147
+ nextSteps: `cd ${target.name}\nnpm install\nnpm run dev`,
148
+ provenance,
149
+ warnings: mixedSourceWarnings(provenance),
150
+ };
151
+ }
@@ -0,0 +1,201 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { activeArchetypeId, discoverArchetypes, pickArchetype, } from './archetypes.js';
4
+ import { PackageResolver, mixedSourceWarnings, provenanceRows, } from './package-resolver.js';
5
+ import { directFiles, requireWaicaProject } from './project-path.js';
6
+ /**
7
+ * Deliberately mirrors the editor's classDefaults/CA-B2 contract: enumerable
8
+ * own fields from a fresh instance. It is not a general public-property
9
+ * reflection API; changing that model belongs to engine/editor design.
10
+ */
11
+ function ownDefaults(Class) {
12
+ try {
13
+ return Object.fromEntries(Object.entries(new Class()).filter(([, value]) => value !== undefined));
14
+ }
15
+ catch {
16
+ return {};
17
+ }
18
+ }
19
+ function moduleDeclaresComponent(module, Class) {
20
+ return Object.values(module).some((candidate) => {
21
+ if (candidate === Class)
22
+ return true;
23
+ if (typeof candidate !== 'function')
24
+ return false;
25
+ return candidate.componentName === Class.componentName;
26
+ });
27
+ }
28
+ function sourcePackage(Class, engineModule, behaviorModule, archetypePackage) {
29
+ if (moduleDeclaresComponent(engineModule, Class))
30
+ return '@waica/engine';
31
+ if (moduleDeclaresComponent(behaviorModule, Class))
32
+ return '@waica/behaviors';
33
+ return archetypePackage;
34
+ }
35
+ export async function listComponents(projectPath) {
36
+ const check = await requireWaicaProject(projectPath);
37
+ const resolver = new PackageResolver(projectPath);
38
+ const discoveryWarnings = [];
39
+ const activeId = await activeArchetypeId(projectPath);
40
+ const [engine, behaviors, archetypes] = await Promise.all([
41
+ resolver.load('@waica/engine'),
42
+ resolver.load('@waica/behaviors'),
43
+ discoverArchetypes(projectPath, resolver, discoveryWarnings, activeId ? [activeId] : []),
44
+ ]);
45
+ const active = pickArchetype(archetypes, activeId, projectPath);
46
+ const components = Object.values(active.manifest.registry.components).map((Class) => {
47
+ const description = {
48
+ componentName: Class.componentName,
49
+ params: (Class.params ?? {}),
50
+ defaults: ownDefaults(Class),
51
+ sourcePackage: sourcePackage(Class, engine.module, behaviors.module, active.packageName),
52
+ };
53
+ if (Object.hasOwn(Class, 'displayName') && typeof Class.displayName === 'string') {
54
+ description.displayName = Class.displayName;
55
+ }
56
+ return description;
57
+ });
58
+ const projectOwned = (await Promise.all(['components', 'roles', 'states'].map(async (directory) => (await directFiles(path.join(projectPath, 'src', directory), '.ts')).map((file) => ({
59
+ path: `src/${directory}/${file}`,
60
+ validated: false,
61
+ })))))
62
+ .flat()
63
+ .sort((a, b) => a.path.localeCompare(b.path));
64
+ const provenance = provenanceRows([engine, behaviors, ...archetypes.map((entry) => entry.loaded)]);
65
+ return {
66
+ components,
67
+ projectOwned,
68
+ notes: check.notes,
69
+ provenance,
70
+ warnings: [...discoveryWarnings, ...mixedSourceWarnings(provenance)],
71
+ };
72
+ }
73
+ function componentNames(components) {
74
+ return (components ?? []).map((component) => component.type);
75
+ }
76
+ function paletteComponents(template, prefabs) {
77
+ const entity = template.make();
78
+ const fromPrefab = entity.prefab ? prefabs[entity.prefab]?.components : undefined;
79
+ return [...componentNames(fromPrefab), ...componentNames(entity.components)];
80
+ }
81
+ function roleDescription(name, role) {
82
+ return {
83
+ name,
84
+ description: role.description,
85
+ driver: role.driver ?? null,
86
+ signals: role.signals ?? {},
87
+ graph: role.graph ?? null,
88
+ };
89
+ }
90
+ export async function describeArchetype(projectPath, requestedId) {
91
+ const check = await requireWaicaProject(projectPath);
92
+ const resolver = new PackageResolver(projectPath);
93
+ const discoveryWarnings = [];
94
+ const activeId = await activeArchetypeId(projectPath);
95
+ const requiredIds = [activeId, requestedId].filter((id) => typeof id === 'string');
96
+ const [engine, behaviors, available] = await Promise.all([
97
+ resolver.load('@waica/engine'),
98
+ resolver.load('@waica/behaviors'),
99
+ discoverArchetypes(projectPath, resolver, discoveryWarnings, requiredIds),
100
+ ]);
101
+ // The active id must be known even when another archetype was requested:
102
+ // the response cannot truthfully name an active archetype otherwise.
103
+ const active = pickArchetype(available, activeId, projectPath);
104
+ const selected = requestedId
105
+ ? pickArchetype(available, requestedId, projectPath)
106
+ : active;
107
+ const manifest = selected.manifest;
108
+ const archetype = {
109
+ id: manifest.id,
110
+ label: manifest.label,
111
+ palette: manifest.palette.map((template) => ({
112
+ name: template.label,
113
+ components: paletteComponents(template, manifest.prefabs),
114
+ })),
115
+ prefabs: Object.entries(manifest.prefabs).map(([ref, prefab]) => ({
116
+ ref,
117
+ type: prefab.type,
118
+ components: componentNames(prefab.components),
119
+ })),
120
+ roles: Object.entries(manifest.bundle.roles).map(([name, role]) => roleDescription(name, role)),
121
+ bindings: manifest.bindings,
122
+ actionLabels: manifest.actionLabels,
123
+ ui: Object.keys(manifest.registry.ui ?? {}).sort(),
124
+ art: manifest.art,
125
+ entityIcons: manifest.entityIcons,
126
+ };
127
+ const installedArchetypes = available
128
+ .filter((entry) => entry.manifest.id !== active.manifest.id)
129
+ .map((entry) => ({
130
+ id: entry.manifest.id,
131
+ label: entry.manifest.label,
132
+ status: 'installed, not active',
133
+ }))
134
+ .sort((a, b) => a.id.localeCompare(b.id));
135
+ const provenance = provenanceRows([engine, behaviors, ...available.map((entry) => entry.loaded)]);
136
+ return {
137
+ activeArchetype: active.manifest.id,
138
+ archetype,
139
+ installedArchetypes,
140
+ notes: check.notes,
141
+ provenance,
142
+ warnings: [...discoveryWarnings, ...mixedSourceWarnings(provenance)],
143
+ };
144
+ }
145
+ async function tolerantJson(file) {
146
+ try {
147
+ const parsed = JSON.parse(await readFile(file, 'utf8'));
148
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
149
+ ? parsed
150
+ : {};
151
+ }
152
+ catch {
153
+ return {};
154
+ }
155
+ }
156
+ export async function projectSummary(projectPath) {
157
+ const check = await requireWaicaProject(projectPath);
158
+ const [game, statsFile, controlsFile] = await Promise.all([
159
+ tolerantJson(path.join(projectPath, 'src/game.json')),
160
+ tolerantJson(path.join(projectPath, 'src/stats.json')),
161
+ tolerantJson(path.join(projectPath, 'src/controls.json')),
162
+ ]);
163
+ const prefabs = [];
164
+ for (const [directory, type] of [
165
+ ['characters', 'character'],
166
+ ['objects', 'object'],
167
+ ['tiles', 'tile'],
168
+ ]) {
169
+ const suffix = `.${type}.json`;
170
+ for (const file of await directFiles(path.join(projectPath, 'src', directory), suffix)) {
171
+ prefabs.push({ ref: `${directory}/${file.slice(0, -suffix.length)}`, type });
172
+ }
173
+ }
174
+ const rawStats = statsFile.stats && typeof statsFile.stats === 'object'
175
+ ? statsFile.stats
176
+ : {};
177
+ const rawBindings = controlsFile.bindings && typeof controlsFile.bindings === 'object'
178
+ ? controlsFile.bindings
179
+ : {};
180
+ const controls = {};
181
+ for (const action of Object.keys(rawBindings).sort()) {
182
+ const value = rawBindings[action];
183
+ if (Array.isArray(value) && value.every((entry) => typeof entry === 'string')) {
184
+ controls[action] = value;
185
+ }
186
+ }
187
+ return {
188
+ archetype: typeof game.archetype === 'string' ? game.archetype : null,
189
+ scenes: await directFiles(path.join(projectPath, 'src/scenes'), '.scene.json'),
190
+ prefabs: prefabs.sort((a, b) => a.ref.localeCompare(b.ref)),
191
+ components: await directFiles(path.join(projectPath, 'src/components'), '.ts'),
192
+ roles: await directFiles(path.join(projectPath, 'src/roles'), '.ts'),
193
+ states: await directFiles(path.join(projectPath, 'src/states'), '.ts'),
194
+ ui: await directFiles(path.join(projectPath, 'src/ui'), '.html'),
195
+ stats: Object.keys(rawStats).sort(),
196
+ controls,
197
+ notes: check.notes,
198
+ provenance: [],
199
+ warnings: [],
200
+ };
201
+ }
@@ -0,0 +1,10 @@
1
+ import type { ArchetypeArt } from '@waica/engine';
2
+ /**
3
+ * The archetype's stock art, as pure data (no asset imports: node tooling
4
+ * like scripts/sync-scene.mjs imports this module directly).
5
+ *
6
+ * Demo projects materialize each sheet as a real file at `src/art/<file>`
7
+ * and reference that path; `uri` is the legacy registry key that in-package
8
+ * prefab defaults (and old projects) still use.
9
+ */
10
+ export declare const PLATFORMER_ART: ArchetypeArt[];
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The archetype's stock art, as pure data (no asset imports: node tooling
3
+ * like scripts/sync-scene.mjs imports this module directly).
4
+ *
5
+ * Demo projects materialize each sheet as a real file at `src/art/<file>`
6
+ * and reference that path; `uri` is the legacy registry key that in-package
7
+ * prefab defaults (and old projects) still use.
8
+ */
9
+ export const PLATFORMER_ART = [
10
+ { file: 'waica-dog.png', uri: 'waica:dog' },
11
+ { file: 'waica-coin.png', uri: 'waica:coin' },
12
+ { file: 'waica-slime.png', uri: 'waica:slime' },
13
+ ];
@@ -0,0 +1,3 @@
1
+ import type { ArchetypeBundle } from '@waica/engine';
2
+ /** Role and state-code baseline installed for a platformer project. */
3
+ export declare const PLATFORMER_BUNDLE: ArchetypeBundle;
@@ -0,0 +1,10 @@
1
+ import { CHASER_ROLE, NPC_ROLE, PATROLLER_ROLE, PLAYER_ROLE, } from '@waica/behaviors';
2
+ /** Role and state-code baseline installed for a platformer project. */
3
+ export const PLATFORMER_BUNDLE = {
4
+ roles: {
5
+ player: PLAYER_ROLE,
6
+ patroller: PATROLLER_ROLE,
7
+ chaser: CHASER_ROLE,
8
+ npc: NPC_ROLE,
9
+ },
10
+ };
@@ -0,0 +1,5 @@
1
+ import type { InputBindings } from '@waica/engine';
2
+ /** Platformer actions and the exact legacy keyboard defaults. */
3
+ export declare const PLATFORMER_BINDINGS: Readonly<InputBindings>;
4
+ /** Friendly labels shown by the editor's controls panel. */
5
+ export declare const PLATFORMER_ACTION_LABELS: Readonly<Record<string, string>>;
@@ -0,0 +1,12 @@
1
+ /** Platformer actions and the exact legacy keyboard defaults. */
2
+ export const PLATFORMER_BINDINGS = {
3
+ left: ['ArrowLeft', 'KeyA'],
4
+ right: ['ArrowRight', 'KeyD'],
5
+ jump: ['Space', 'ArrowUp', 'KeyW'],
6
+ };
7
+ /** Friendly labels shown by the editor's controls panel. */
8
+ export const PLATFORMER_ACTION_LABELS = {
9
+ left: 'Move left',
10
+ right: 'Move right',
11
+ jump: 'Jump',
12
+ };
@@ -0,0 +1,38 @@
1
+ import { Game, type Entity } from '@waica/engine';
2
+ export { PLATFORMER_BUNDLE } from './bundle.js';
3
+ export { PLATFORMER_ACTION_LABELS, PLATFORMER_BINDINGS } from './controls.js';
4
+ export { PLATFORMER_SCENE, PLATFORMER_BLANK_SCENE, DOG_SPRITE } from './scene-default.js';
5
+ export { PLATFORMER_PREFABS } from './prefabs.js';
6
+ export { PLATFORMER_UI } from './ui.js';
7
+ export { PLATFORMER_ART } from './art.js';
8
+ export { PLATFORMER_REGISTRY, PLATFORMER_PALETTE, PLATFORMER_ART_URLS } from './registry.js';
9
+ /** Browser-complete manifest exported by the package root. */
10
+ export declare const ARCHETYPE: {
11
+ id: string;
12
+ label: string;
13
+ scene: import("@waica/engine").SceneJson;
14
+ blankScene: import("@waica/engine").SceneJson;
15
+ palette: import("@waica/engine").EntityTemplate[];
16
+ prefabs: Record<string, import("@waica/engine").PrefabJson>;
17
+ art: import("@waica/engine").ArchetypeArt[];
18
+ entityIcons: Readonly<Record<string, string>>;
19
+ bindings: Readonly<import("@waica/engine").InputBindings>;
20
+ actionLabels: Readonly<Record<string, string>>;
21
+ bundle: import("@waica/engine").ArchetypeBundle;
22
+ registry: import("@waica/engine").SceneRegistry;
23
+ artUrls: Record<string, string>;
24
+ };
25
+ export interface PlatformerSetup {
26
+ player: Entity;
27
+ /** Collected-coin counter, for the HUD and tests. */
28
+ score: {
29
+ coins: number;
30
+ };
31
+ }
32
+ /**
33
+ * Sets up the platformer archetype's base scene by loading the default
34
+ * scene (real projects load their own src/scenes/*.json). The scene's
35
+ * 'coin-counter' UI piece renders the counter; the returned score just
36
+ * tracks it.
37
+ */
38
+ export declare function setupPlatformer(game: Game): PlatformerSetup;
@@ -0,0 +1,34 @@
1
+ import { Game, loadScene, } from '@waica/engine';
2
+ import { ARCHETYPE as DATA_ARCHETYPE } from './manifest.js';
3
+ import { PLATFORMER_REGISTRY, PLATFORMER_ART_URLS } from './registry.js';
4
+ import { PLATFORMER_SCENE } from './scene-default.js';
5
+ export { PLATFORMER_BUNDLE } from './bundle.js';
6
+ export { PLATFORMER_ACTION_LABELS, PLATFORMER_BINDINGS } from './controls.js';
7
+ export { PLATFORMER_SCENE, PLATFORMER_BLANK_SCENE, DOG_SPRITE } from './scene-default.js';
8
+ export { PLATFORMER_PREFABS } from './prefabs.js';
9
+ export { PLATFORMER_UI } from './ui.js';
10
+ export { PLATFORMER_ART } from './art.js';
11
+ export { PLATFORMER_REGISTRY, PLATFORMER_PALETTE, PLATFORMER_ART_URLS } from './registry.js';
12
+ /** Browser-complete manifest exported by the package root. */
13
+ export const ARCHETYPE = {
14
+ ...DATA_ARCHETYPE,
15
+ registry: PLATFORMER_REGISTRY,
16
+ artUrls: PLATFORMER_ART_URLS,
17
+ };
18
+ /**
19
+ * Sets up the platformer archetype's base scene by loading the default
20
+ * scene (real projects load their own src/scenes/*.json). The scene's
21
+ * 'coin-counter' UI piece renders the counter; the returned score just
22
+ * tracks it.
23
+ */
24
+ export function setupPlatformer(game) {
25
+ loadScene(game, PLATFORMER_SCENE, PLATFORMER_REGISTRY);
26
+ const score = { coins: 0 };
27
+ game.events.on('collect', (value) => {
28
+ score.coins += typeof value === 'number' ? value : 1;
29
+ });
30
+ const player = game.find('Player');
31
+ if (!player)
32
+ throw new Error('default scene has no Player');
33
+ return { player, score };
34
+ }
@@ -0,0 +1,15 @@
1
+ /** Asset-import-free manifest for Node tooling. */
2
+ export declare const ARCHETYPE: {
3
+ id: string;
4
+ label: string;
5
+ scene: import("@waica/engine").SceneJson;
6
+ blankScene: import("@waica/engine").SceneJson;
7
+ registry: import("@waica/engine").SceneRegistry;
8
+ palette: import("@waica/engine").EntityTemplate[];
9
+ prefabs: Record<string, import("@waica/engine").PrefabJson>;
10
+ art: import("@waica/engine").ArchetypeArt[];
11
+ entityIcons: Readonly<Record<string, string>>;
12
+ bindings: Readonly<import("@waica/engine").InputBindings>;
13
+ actionLabels: Readonly<Record<string, string>>;
14
+ bundle: import("@waica/engine").ArchetypeBundle;
15
+ };
@@ -0,0 +1,26 @@
1
+ import { PLATFORMER_ART } from './art.js';
2
+ import { PLATFORMER_BUNDLE } from './bundle.js';
3
+ import { PLATFORMER_ACTION_LABELS, PLATFORMER_BINDINGS } from './controls.js';
4
+ import { PLATFORMER_PREFABS } from './prefabs.js';
5
+ import { PLATFORMER_PALETTE, PLATFORMER_REGISTRY_DATA } from './registry-data.js';
6
+ import { PLATFORMER_BLANK_SCENE, PLATFORMER_SCENE } from './scene-default.js';
7
+ const PLATFORMER_ENTITY_ICONS = {
8
+ PlatformerMotor: '🐕',
9
+ Collectible: '🪙',
10
+ Hazard: '👾',
11
+ };
12
+ /** Asset-import-free manifest for Node tooling. */
13
+ export const ARCHETYPE = {
14
+ id: 'platformer',
15
+ label: 'Platformer',
16
+ scene: PLATFORMER_SCENE,
17
+ blankScene: PLATFORMER_BLANK_SCENE,
18
+ registry: PLATFORMER_REGISTRY_DATA,
19
+ palette: PLATFORMER_PALETTE,
20
+ prefabs: PLATFORMER_PREFABS,
21
+ art: PLATFORMER_ART,
22
+ entityIcons: PLATFORMER_ENTITY_ICONS,
23
+ bindings: PLATFORMER_BINDINGS,
24
+ actionLabels: PLATFORMER_ACTION_LABELS,
25
+ bundle: PLATFORMER_BUNDLE,
26
+ };
@@ -0,0 +1,7 @@
1
+ import type { PrefabJson } from '@waica/engine';
2
+ /**
3
+ * The archetype's reusable entity templates, keyed by ref ('characters/slime').
4
+ * Scenes reference these and override per-entity props; the palette derives
5
+ * its pieces from this catalog.
6
+ */
7
+ export declare const PLATFORMER_PREFABS: Record<string, PrefabJson>;
@@ -0,0 +1,97 @@
1
+ import { PLAYER_STATE_GRAPH } from '@waica/behaviors';
2
+ import { DOG_SPRITE } from './scene-default.js';
3
+ /**
4
+ * The archetype's reusable entity templates, keyed by ref ('characters/slime').
5
+ * Scenes reference these and override per-entity props; the palette derives
6
+ * its pieces from this catalog.
7
+ */
8
+ export const PLATFORMER_PREFABS = {
9
+ 'characters/player': {
10
+ waicaPrefab: 1,
11
+ type: 'character',
12
+ components: [
13
+ { type: 'AnimatedSprite', props: DOG_SPRITE },
14
+ { type: 'PlatformerMotor' },
15
+ {
16
+ type: 'StateMachine',
17
+ props: {
18
+ role: 'player',
19
+ initial: PLAYER_STATE_GRAPH.initial,
20
+ states: PLAYER_STATE_GRAPH.states,
21
+ },
22
+ },
23
+ { type: 'Hitbox', props: { width: 0.9, height: 0.95 } },
24
+ { type: 'Respawnable', props: { killY: -12 } },
25
+ ],
26
+ },
27
+ 'characters/slime': {
28
+ waicaPrefab: 1,
29
+ type: 'character',
30
+ components: [
31
+ {
32
+ type: 'AnimatedSprite',
33
+ props: {
34
+ texture: 'waica:slime',
35
+ cols: 4,
36
+ rows: 1,
37
+ width: 1.1,
38
+ height: 1.1,
39
+ clips: { idle: { frames: [0, 1, 2, 3], fps: 6 } },
40
+ initialClip: 'idle',
41
+ },
42
+ },
43
+ { type: 'Patrol', props: { distance: 2, speed: 2 } },
44
+ {
45
+ type: 'StateMachine',
46
+ props: {
47
+ role: 'patroller',
48
+ initial: 'walk',
49
+ states: { walk: { clip: 'idle' } },
50
+ },
51
+ },
52
+ { type: 'Hitbox', props: { width: 0.9, height: 0.6 } },
53
+ { type: 'Hazard', props: { stompable: true, bounce: 10 } },
54
+ ],
55
+ },
56
+ 'objects/coin': {
57
+ waicaPrefab: 1,
58
+ type: 'object',
59
+ components: [
60
+ {
61
+ type: 'AnimatedSprite',
62
+ props: {
63
+ texture: 'waica:coin',
64
+ cols: 4,
65
+ rows: 1,
66
+ width: 0.6,
67
+ height: 0.6,
68
+ clips: { spin: { frames: [0, 1, 2, 3], fps: 8 } },
69
+ initialClip: 'spin',
70
+ },
71
+ },
72
+ { type: 'Hitbox', props: { width: 0.5, height: 0.5 } },
73
+ { type: 'Collectible', props: { value: 1 } },
74
+ ],
75
+ },
76
+ 'tiles/platform': {
77
+ waicaPrefab: 1,
78
+ type: 'tile',
79
+ components: [
80
+ { type: 'Sprite', props: { width: 3, height: 0.5, color: 0x2a9d8f } },
81
+ { type: 'Solid', props: { width: 3, height: 0.5 } },
82
+ ],
83
+ },
84
+ 'tiles/block': {
85
+ waicaPrefab: 1,
86
+ type: 'tile',
87
+ components: [
88
+ { type: 'Sprite', props: { width: 2, height: 2, color: 0x264653 } },
89
+ { type: 'Solid', props: { width: 2, height: 2 } },
90
+ ],
91
+ },
92
+ 'tiles/decor': {
93
+ waicaPrefab: 1,
94
+ type: 'tile',
95
+ components: [{ type: 'Sprite', props: { width: 1, height: 1, color: 0x8ecae6 } }],
96
+ },
97
+ };
@@ -0,0 +1,5 @@
1
+ import { type EntityTemplate, type SceneRegistry } from '@waica/engine';
2
+ /** Asset-import-free registry. Browser URL resolution is layered on separately. */
3
+ export declare const PLATFORMER_REGISTRY_DATA: SceneRegistry;
4
+ /** The editor palette: pieces you can drag into the viewport, one per prefab. */
5
+ export declare const PLATFORMER_PALETTE: EntityTemplate[];