incanto 0.1.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 (138) hide show
  1. package/LICENSE +30 -0
  2. package/README.md +36 -0
  3. package/THIRD-PARTY-NOTICES.md +88 -0
  4. package/assets/audio/attacked.mp3 +0 -0
  5. package/assets/audio/explosion.mp3 +0 -0
  6. package/assets/audio/gold_loot.mp3 +0 -0
  7. package/assets/audio/heal.mp3 +0 -0
  8. package/assets/audio/hit_metal_bang.mp3 +0 -0
  9. package/assets/audio/ice_spear.mp3 +0 -0
  10. package/assets/audio/monster_died.mp3 +0 -0
  11. package/assets/audio/slash.mp3 +0 -0
  12. package/assets/audio/smite.mp3 +0 -0
  13. package/assets/audio/spells_cast.mp3 +0 -0
  14. package/assets/audio/ui_click.wav +0 -0
  15. package/assets/audio/walk.mp3 +0 -0
  16. package/assets/catalog.json +390 -0
  17. package/assets/characters/2dbasic.json +41 -0
  18. package/assets/characters/2dbasic.png +0 -0
  19. package/assets/characters/ghost.json +46 -0
  20. package/assets/characters/ghost.png +0 -0
  21. package/assets/characters/goblin.json +40 -0
  22. package/assets/characters/goblin.png +0 -0
  23. package/assets/characters/medieval-knight.json +41 -0
  24. package/assets/characters/medieval-knight.png +0 -0
  25. package/assets/effects/swoosh.png +0 -0
  26. package/assets/items/box.png +0 -0
  27. package/assets/items/buff_potion.png +0 -0
  28. package/assets/items/coin.png +0 -0
  29. package/assets/items/gem.png +0 -0
  30. package/assets/items/gold.png +0 -0
  31. package/assets/items/hp_potion.png +0 -0
  32. package/assets/items/locked_item_box.png +0 -0
  33. package/assets/items/map.png +0 -0
  34. package/assets/items/resurrection_potion.png +0 -0
  35. package/assets/items/super_box.png +0 -0
  36. package/assets/items/trap.png +0 -0
  37. package/assets/tiles/floor00.jpg +0 -0
  38. package/assets/tiles/minecraft-tiles.png +0 -0
  39. package/assets/tiles/wall00.jpg +0 -0
  40. package/assets/vegetation/ash_color.png +0 -0
  41. package/assets/vegetation/aspen_color.png +0 -0
  42. package/assets/vegetation/bark/birch_color_1k.jpg +0 -0
  43. package/assets/vegetation/bark/birch_normal_1k.jpg +0 -0
  44. package/assets/vegetation/bark/birch_roughness_1k.jpg +0 -0
  45. package/assets/vegetation/bark/oak_color_1k.jpg +0 -0
  46. package/assets/vegetation/bark/oak_normal_1k.jpg +0 -0
  47. package/assets/vegetation/bark/oak_roughness_1k.jpg +0 -0
  48. package/assets/vegetation/bark/pine_color_1k.jpg +0 -0
  49. package/assets/vegetation/bark/pine_normal_1k.jpg +0 -0
  50. package/assets/vegetation/bark/pine_roughness_1k.jpg +0 -0
  51. package/assets/vegetation/ground/dirt_color.jpg +0 -0
  52. package/assets/vegetation/ground/dirt_normal.jpg +0 -0
  53. package/assets/vegetation/ground/grass.jpg +0 -0
  54. package/assets/vegetation/oak_color.png +0 -0
  55. package/assets/vegetation/pine_color.png +0 -0
  56. package/bin/incanto-assets.mjs +107 -0
  57. package/bin/incanto-check.mjs +107 -0
  58. package/bin/incanto-editor.mjs +343 -0
  59. package/bin/incanto-env.mjs +144 -0
  60. package/bin/incanto-model.mjs +296 -0
  61. package/bin/incanto-play.mjs +219 -0
  62. package/bin/incanto-skills.mjs +71 -0
  63. package/dist/2d.d.ts +642 -0
  64. package/dist/2d.js +44 -0
  65. package/dist/3d.d.ts +1860 -0
  66. package/dist/3d.js +5 -0
  67. package/dist/agent8-DzU2fFyH.js +129 -0
  68. package/dist/audio-player-DqUR3XFs.d.ts +110 -0
  69. package/dist/behavior-BAQq7HGM.d.ts +851 -0
  70. package/dist/create-game-BdjpTHrW.js +1725 -0
  71. package/dist/create-game-CZHROKcT.js +527 -0
  72. package/dist/debug-draw-CZmOYjL2.js +13 -0
  73. package/dist/debug.d.ts +66 -0
  74. package/dist/debug.js +658 -0
  75. package/dist/duplicate-DP2WPYom.js +22 -0
  76. package/dist/env.d.ts +430 -0
  77. package/dist/env.js +3152 -0
  78. package/dist/errors-BMFaY68Q.d.ts +33 -0
  79. package/dist/errors-BpWbnbb_.js +13 -0
  80. package/dist/gameplay-Ccruc3Wd.js +1501 -0
  81. package/dist/gameplay.d.ts +543 -0
  82. package/dist/gameplay.js +2 -0
  83. package/dist/heightmap-CroQPEER.js +185 -0
  84. package/dist/index.d.ts +305 -0
  85. package/dist/index.js +62 -0
  86. package/dist/json-BLk7H2Qa.js +30 -0
  87. package/dist/loader-CGs_G-r0.js +919 -0
  88. package/dist/loader-Mo0KghCv.d.ts +41 -0
  89. package/dist/net.d.ts +427 -0
  90. package/dist/net.js +772 -0
  91. package/dist/noise-CGUMx44x.js +82 -0
  92. package/dist/particle-sim-CbN4YUuH.d.ts +63 -0
  93. package/dist/particle-sim-DYuSUxvK.js +1319 -0
  94. package/dist/physics-2d-KuMWPTf6.js +288 -0
  95. package/dist/physics-3d-Dl67vOLT.js +434 -0
  96. package/dist/react.d.ts +65 -0
  97. package/dist/react.js +209 -0
  98. package/dist/register-BuUV1_KB.js +561 -0
  99. package/dist/register-CNlYAS1_.js +10634 -0
  100. package/dist/register-DPEV9_9t.js +851 -0
  101. package/dist/register-Dasmnurl.js +374 -0
  102. package/dist/registry-BVJ2HbCn.js +132 -0
  103. package/dist/rng-DP-SR7eg.js +38 -0
  104. package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
  105. package/dist/schema-CcoWb32N.d.ts +104 -0
  106. package/dist/test.d.ts +158 -0
  107. package/dist/test.js +275 -0
  108. package/dist/touch-031PxtCR.js +208 -0
  109. package/dist/vite.d.ts +26 -0
  110. package/dist/vite.js +57 -0
  111. package/editor/assets/GameServer-C56iOUgF.js +1 -0
  112. package/editor/assets/agent8-Bp7QFI7v.js +1 -0
  113. package/editor/assets/index-DF3tMeKJ.css +1 -0
  114. package/editor/assets/index-Dl2pjA8e.js +7365 -0
  115. package/editor/assets/rapier-CEuLKeCu.js +1 -0
  116. package/editor/assets/rapier-DE6a0vmv.js +1 -0
  117. package/editor/index.html +169 -0
  118. package/package.json +97 -0
  119. package/schemas/scene.schema.json +4254 -0
  120. package/skills/README.md +9 -0
  121. package/skills/incanto-3d-character.md +229 -0
  122. package/skills/incanto-3d-models.md +151 -0
  123. package/skills/incanto-assets.md +118 -0
  124. package/skills/incanto-audio.md +309 -0
  125. package/skills/incanto-behaviors-and-scripts.md +169 -0
  126. package/skills/incanto-building-2d-games.md +242 -0
  127. package/skills/incanto-building-3d-games.md +245 -0
  128. package/skills/incanto-editor.md +163 -0
  129. package/skills/incanto-environment.md +743 -0
  130. package/skills/incanto-gameplay-behaviors.md +707 -0
  131. package/skills/incanto-multiplayer.md +264 -0
  132. package/skills/incanto-node-reference.md +797 -0
  133. package/skills/incanto-physics-and-input.md +164 -0
  134. package/skills/incanto-scene-json-authoring.md +325 -0
  135. package/skills/incanto-verifying-your-game.md +191 -0
  136. package/skills/incanto-web-integration.md +96 -0
  137. package/templates/agent8-server.js +84 -0
  138. package/templates/agent8-server.ts +138 -0
@@ -0,0 +1,40 @@
1
+ {
2
+ "frame": {
3
+ "width": 192,
4
+ "height": 192
5
+ },
6
+ "origin": {
7
+ "x": 0.5,
8
+ "y": 0.6
9
+ },
10
+ "body": {
11
+ "size": {
12
+ "width": 60,
13
+ "height": 60
14
+ },
15
+ "offset": {
16
+ "x": 66,
17
+ "y": 76
18
+ }
19
+ },
20
+ "animations": {
21
+ "idle": {
22
+ "start": 0,
23
+ "end": 6,
24
+ "frameRate": 10,
25
+ "repeat": -1
26
+ },
27
+ "move": {
28
+ "start": 7,
29
+ "end": 12,
30
+ "frameRate": 10,
31
+ "repeat": -1
32
+ },
33
+ "attack": {
34
+ "start": 14,
35
+ "end": 19,
36
+ "frameRate": 10,
37
+ "repeat": 0
38
+ }
39
+ }
40
+ }
Binary file
@@ -0,0 +1,41 @@
1
+ {
2
+ "frame": {
3
+ "width": 192,
4
+ "height": 192
5
+ },
6
+ "direction": "right",
7
+ "origin": {
8
+ "x": 0.5,
9
+ "y": 0.61
10
+ },
11
+ "body": {
12
+ "size": {
13
+ "width": 60,
14
+ "height": 60
15
+ },
16
+ "offset": {
17
+ "x": 66,
18
+ "y": 76
19
+ }
20
+ },
21
+ "animations": {
22
+ "idle": {
23
+ "start": 0,
24
+ "end": 5,
25
+ "frameRate": 10,
26
+ "repeat": -1
27
+ },
28
+ "move": {
29
+ "start": 6,
30
+ "end": 11,
31
+ "frameRate": 10,
32
+ "repeat": -1
33
+ },
34
+ "attack": {
35
+ "start": 12,
36
+ "end": 17,
37
+ "frameRate": 10,
38
+ "repeat": 0
39
+ }
40
+ }
41
+ }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * incanto-assets — the built-in asset catalog (shipped IN the package, no
4
+ * network, owner-licensed). Find art, copy it into your project, and get the
5
+ * ready-to-paste scene JSON.
6
+ *
7
+ * npx incanto-assets list [--json] what ships (characters/tiles/items/effects)
8
+ * npx incanto-assets info <name> description + animation details
9
+ * npx incanto-assets copy <name> --out public/assets
10
+ * copy the file(s) + print the scene snippet
11
+ *
12
+ * External art still works the usual way (any URL in scene assets{}) — this
13
+ * is the zero-setup starting set.
14
+ */
15
+ import { copyFileSync, mkdirSync, readFileSync } from 'node:fs';
16
+ import { basename, dirname, join, resolve } from 'node:path';
17
+ import { fileURLToPath, pathToFileURL } from 'node:url';
18
+
19
+ const PKG = join(dirname(fileURLToPath(import.meta.url)), '..');
20
+ const ASSETS = join(PKG, 'assets');
21
+
22
+ function catalog() {
23
+ return JSON.parse(readFileSync(join(ASSETS, 'catalog.json'), 'utf-8'));
24
+ }
25
+
26
+ const [command, ...rest] = process.argv.slice(2);
27
+
28
+ if (!command || command === '--help' || command === '-h') {
29
+ console.log(`Usage:
30
+ incanto-assets list [--json]
31
+ incanto-assets info <name>
32
+ incanto-assets copy <name> --out <dir>`);
33
+ process.exit(command ? 0 : 1);
34
+ }
35
+
36
+ if (command === 'list') {
37
+ const entries = catalog();
38
+ if (rest.includes('--json')) {
39
+ console.log(JSON.stringify(entries, null, 2));
40
+ } else {
41
+ for (const e of entries) {
42
+ const anim = e.animation ? ' [animated]' : '';
43
+ console.log(
44
+ `${e.name.padEnd(20)} ${e.kind.padEnd(10)}${anim.padEnd(11)} ${e.description.slice(0, 80)}`,
45
+ );
46
+ }
47
+ console.log(`\n${entries.length} built-in asset(s) — incanto-assets info <name> for details`);
48
+ }
49
+ // NO process.exit() here: piped stdout flushes asynchronously on POSIX, so
50
+ // exit() truncates any output past one ~8 KB pipe buffer (the catalog
51
+ // crossed that line when the bark/ground textures joined it). Falling off
52
+ // the end of the script lets node drain stdout before exiting.
53
+ process.exitCode = 0;
54
+ } else {
55
+ const name = rest.find((a) => !a.startsWith('--'));
56
+ const entry = catalog().find((e) => e.name === name);
57
+ if (!entry) {
58
+ const names = catalog().map((e) => e.name);
59
+ console.error(`unknown asset '${name ?? ''}'. Available: [${names.join(', ')}]`);
60
+ process.exit(1);
61
+ }
62
+
63
+ if (command === 'info') {
64
+ console.log(JSON.stringify(entry, null, 2));
65
+ if (entry.animation) {
66
+ const meta = JSON.parse(readFileSync(join(ASSETS, entry.animation), 'utf-8'));
67
+ console.log('\nanimations:', Object.keys(meta.animations ?? {}).join(', '));
68
+ }
69
+ process.exitCode = 0; // see the list note — exit() truncates piped stdout
70
+ } else if (command === 'copy') {
71
+ const outFlag = rest.indexOf('--out');
72
+ const outDir = resolve(outFlag !== -1 ? rest[outFlag + 1] : 'public/assets');
73
+ mkdirSync(outDir, { recursive: true });
74
+ const copied = [];
75
+ for (const file of [entry.file, entry.animation].filter(Boolean)) {
76
+ const target = join(outDir, basename(file));
77
+ copyFileSync(join(ASSETS, file), target);
78
+ copied.push(target);
79
+ }
80
+ for (const t of copied) console.log(`copied ${t}`);
81
+
82
+ // Ready-to-paste scene JSON (sheet assets get full animation wiring).
83
+ const url = `assets/${basename(entry.file)}`;
84
+ if (entry.animation) {
85
+ const { spriteFromLibraryMeta } = await import(
86
+ pathToFileURL(join(PKG, 'dist', '2d.js')).href
87
+ );
88
+ const meta = JSON.parse(readFileSync(join(ASSETS, entry.animation), 'utf-8'));
89
+ const { asset, props } = spriteFromLibraryMeta(meta, { url, assetKey: entry.name });
90
+ console.log(`\nscene assets entry:\n "${entry.name}": ${JSON.stringify(asset)}`);
91
+ console.log(
92
+ `\nnode:\n ${JSON.stringify({ name: entry.name, type: 'AnimatedSprite2D', props }, null, 2)}`,
93
+ );
94
+ } else {
95
+ console.log(
96
+ `\nscene assets entry:\n "${entry.name}": ${JSON.stringify({ type: 'texture', url })}`,
97
+ );
98
+ console.log(
99
+ `\nnode:\n ${JSON.stringify({ name: entry.name, type: 'Sprite2D', props: { texture: `$${entry.name}` } })}`,
100
+ );
101
+ }
102
+ process.exitCode = 0;
103
+ } else {
104
+ console.error(`unknown command '${command}'`);
105
+ process.exit(1);
106
+ }
107
+ }
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * incanto-check — headless scene validation. Every hard load error the engine
4
+ * would throw in the browser, on the command line instead (the agent's
5
+ * after-every-edit check; production VMs have no browser).
6
+ *
7
+ * npx incanto-check → validates every *.scene.json under cwd
8
+ * npx incanto-check src/game.scene.json → specific files (or directories)
9
+ * npx incanto-check --json → machine-readable report
10
+ * npx incanto-check --strict-behaviors → unregistered script names fail too
11
+ *
12
+ * Unregistered behaviors are STUBBED by default: structure-only validation
13
+ * that needs no TypeScript. Sub-scene `instance` paths resolve relative to
14
+ * each scene file.
15
+ */
16
+ import { existsSync, lstatSync, readdirSync, readFileSync, statSync } from 'node:fs';
17
+ import { dirname, join, resolve } from 'node:path';
18
+ import { fileURLToPath, pathToFileURL } from 'node:url';
19
+
20
+ const DIST = join(dirname(fileURLToPath(import.meta.url)), '..', 'dist');
21
+
22
+ function parseArgs(argv) {
23
+ const args = { files: [], json: false, strict: false, help: false, invalid: false };
24
+ for (const a of argv) {
25
+ if (a === '--json') args.json = true;
26
+ else if (a === '--strict-behaviors') args.strict = true;
27
+ else if (a === '--help' || a === '-h') args.help = true;
28
+ else if (a.startsWith('--')) {
29
+ console.error(`unknown flag: ${a}`);
30
+ args.invalid = true;
31
+ } else args.files.push(a);
32
+ }
33
+ return args;
34
+ }
35
+
36
+ const args = parseArgs(process.argv.slice(2));
37
+ if (args.help || args.invalid) {
38
+ console.log(`Usage: npx incanto-check [files|dirs...] [--json] [--strict-behaviors]
39
+
40
+ Validates *.scene.json files headlessly with the installed engine.
41
+ With no arguments, scans the current directory recursively
42
+ (skipping node_modules and dist).`);
43
+ process.exit(args.invalid ? 1 : 0);
44
+ }
45
+
46
+ function collectScenes(entry) {
47
+ const stat = statSync(entry);
48
+ if (stat.isFile()) return entry.endsWith('.scene.json') ? [entry] : [];
49
+ const out = [];
50
+ for (const item of readdirSync(entry, { withFileTypes: true })) {
51
+ if (item.name === 'node_modules' || item.name === 'dist' || item.name.startsWith('.')) {
52
+ continue;
53
+ }
54
+ const full = join(entry, item.name);
55
+ if (lstatSync(full).isSymbolicLink()) continue; // no symlink-loop recursion
56
+ out.push(...collectScenes(full));
57
+ }
58
+ return out;
59
+ }
60
+
61
+ const roots = args.files.length > 0 ? args.files : ['.'];
62
+ for (const r of roots) {
63
+ if (!existsSync(resolve(r))) {
64
+ console.error(`no such file or directory: ${r}`);
65
+ process.exit(1);
66
+ }
67
+ }
68
+ const files = roots.flatMap((r) => collectScenes(resolve(r)));
69
+ if (files.length === 0) {
70
+ console.error('no *.scene.json files found');
71
+ process.exit(1);
72
+ }
73
+
74
+ const { validateScene } = await import(pathToFileURL(join(DIST, 'test.js')).href);
75
+
76
+ const results = files.map((file) => {
77
+ let json;
78
+ try {
79
+ json = JSON.parse(readFileSync(file, 'utf-8'));
80
+ } catch (e) {
81
+ return { file, ok: false, code: 'BAD_JSON', message: String(e?.message ?? e) };
82
+ }
83
+ const res = validateScene(json, {
84
+ strictBehaviors: args.strict,
85
+ resolveScene: (p) => JSON.parse(readFileSync(resolve(dirname(file), p), 'utf-8')),
86
+ });
87
+ if (res.ok) return { file, ok: true };
88
+ return {
89
+ file,
90
+ ok: false,
91
+ code: res.error?.code,
92
+ message: res.error?.message,
93
+ details: res.error?.details,
94
+ };
95
+ });
96
+
97
+ const failed = results.filter((r) => !r.ok);
98
+ if (args.json) {
99
+ console.log(JSON.stringify({ ok: failed.length === 0, results }, null, 2));
100
+ } else {
101
+ for (const r of results) {
102
+ if (r.ok) console.log(` ok ${r.file}`);
103
+ else console.log(`FAIL ${r.file}\n [${r.code}] ${r.message}`);
104
+ }
105
+ console.log(`\n${results.length - failed.length}/${results.length} scene(s) valid`);
106
+ }
107
+ process.exit(failed.length === 0 ? 0 : 1);