@jgengine/assets 0.11.0 → 0.13.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.
- package/CHANGELOG.md +52 -0
- package/README.md +2 -2
- package/dist/catalogs/build.d.ts +27 -0
- package/dist/catalogs/build.js +21 -2
- package/dist/cli/pull.js +7 -11
- package/dist/collisionMeshAssets.d.ts +2 -0
- package/dist/collisionMeshAssets.js +6 -0
- package/dist/dims.d.ts +14 -0
- package/dist/dims.js +175 -0
- package/dist/download.d.ts +26 -10
- package/dist/download.js +140 -43
- package/dist/generated/kaykit-adventurers.json +459 -37
- package/dist/generated/kaykit-city-builder.json +82 -41
- package/dist/generated/kaykit-dungeon.json +940 -203
- package/dist/generated/kaykit-furniture.json +106 -53
- package/dist/generated/kaykit-skeletons.json +426 -21
- package/dist/generated/kaykit-space-base.json +114 -57
- package/dist/generated/quaternius-medieval-village.json +352 -176
- package/dist/generated/quaternius-modular-scifi.json +405 -196
- package/dist/generated/quaternius-stylized-nature.json +136 -68
- package/dist/indexGen.d.ts +2 -2
- package/dist/indexGen.js +36 -5
- package/dist/manifest.d.ts +6 -0
- package/dist/registry-catalog.json +0 -5
- package/package.json +2 -2
- package/skills/jgengine/SKILL.md +8 -4
- package/skills/jgengine/api.md +182 -81
- package/skills/jgengine/capabilities.md +104 -2
- package/skills/jgengine/recipes/minimal-game.md +88 -0
- package/skills/jgengine-assets/SKILL.md +8 -0
- package/skills/jgengine-assets/api.md +14 -4
- package/skills/jgengine-assets/capabilities.md +4 -0
- package/skills/jgengine/reference-cartridge.md +0 -72
package/dist/indexGen.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { COLLISION_MESH_ASSET_IDS } from "./collisionMeshAssets.js";
|
|
4
|
+
import { readGlbClips, readGlbCollisionMesh, readGlbDims } from "./dims.js";
|
|
4
5
|
import { sourceById } from "./sources/index.js";
|
|
5
6
|
export function keyFromFile(file) {
|
|
6
7
|
return file.replace(/\.gltf\.glb$/i, "").replace(/\.glb$/i, "");
|
|
7
8
|
}
|
|
8
|
-
export function entryForFile(source, file, dims) {
|
|
9
|
+
export function entryForFile(source, file, dims, collisionMesh, clips) {
|
|
9
10
|
return {
|
|
10
11
|
id: `${source.id}/${keyFromFile(file)}`,
|
|
11
12
|
source: source.id,
|
|
12
13
|
categories: source.categories,
|
|
13
14
|
file,
|
|
14
15
|
...(dims === undefined ? {} : { dims }),
|
|
16
|
+
...(collisionMesh === undefined ? {} : { collisionMesh }),
|
|
17
|
+
...(clips === undefined ? {} : { clips }),
|
|
15
18
|
};
|
|
16
19
|
}
|
|
17
20
|
function collectGlbFiles(dir) {
|
|
@@ -27,14 +30,42 @@ function collectGlbFiles(dir) {
|
|
|
27
30
|
}
|
|
28
31
|
return found;
|
|
29
32
|
}
|
|
30
|
-
function measureDims(
|
|
33
|
+
function measureDims(bytes) {
|
|
31
34
|
try {
|
|
32
|
-
return readGlbDims(
|
|
35
|
+
return readGlbDims(bytes) ?? undefined;
|
|
33
36
|
}
|
|
34
37
|
catch {
|
|
35
38
|
return undefined;
|
|
36
39
|
}
|
|
37
40
|
}
|
|
41
|
+
function measureCollisionMesh(bytes) {
|
|
42
|
+
try {
|
|
43
|
+
return readGlbCollisionMesh(bytes) ?? undefined;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function measureClips(bytes) {
|
|
50
|
+
try {
|
|
51
|
+
return readGlbClips(bytes) ?? undefined;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function entryFromGlb(source, file, full) {
|
|
58
|
+
let bytes;
|
|
59
|
+
try {
|
|
60
|
+
bytes = readFileSync(full);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return entryForFile(source, file);
|
|
64
|
+
}
|
|
65
|
+
const id = `${source.id}/${keyFromFile(file)}`;
|
|
66
|
+
const collisionMesh = COLLISION_MESH_ASSET_IDS.has(id) ? measureCollisionMesh(bytes) : undefined;
|
|
67
|
+
return entryForFile(source, file, measureDims(bytes), collisionMesh, measureClips(bytes));
|
|
68
|
+
}
|
|
38
69
|
export function indexSourceDir(source, dir) {
|
|
39
70
|
const seen = new Set();
|
|
40
71
|
const entries = [];
|
|
@@ -42,7 +73,7 @@ export function indexSourceDir(source, dir) {
|
|
|
42
73
|
if (seen.has(file))
|
|
43
74
|
continue;
|
|
44
75
|
seen.add(file);
|
|
45
|
-
entries.push(
|
|
76
|
+
entries.push(entryFromGlb(source, file, full));
|
|
46
77
|
}
|
|
47
78
|
return entries;
|
|
48
79
|
}
|
package/dist/manifest.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { ModelDims } from "@jgengine/core/scene/assetCatalog";
|
|
2
2
|
import type { AssetSpace } from "@jgengine/core/scene/assetSpace";
|
|
3
|
+
import type { CollisionMeshData } from "@jgengine/core/scene/collisionMesh";
|
|
3
4
|
export type { ModelDims };
|
|
4
5
|
export type { AssetSpace };
|
|
6
|
+
export type { CollisionMeshData };
|
|
5
7
|
export type AssetProvider = "quaternius" | "kaykit" | "polypizza" | "itch" | "ambientcg" | "gameicons" | "custom";
|
|
6
8
|
/**
|
|
7
9
|
* What a source's archive contains: GLB models (default), one PBR material's
|
|
@@ -38,6 +40,10 @@ export interface IndexEntry {
|
|
|
38
40
|
file: string;
|
|
39
41
|
/** Footprint/center/minY measured from the GLB at reindex; absent when the model could not be read. */
|
|
40
42
|
dims?: ModelDims;
|
|
43
|
+
/** Opt-in compact triangle mesh extracted at reindex (see {@link "@jgengine/core/scene/collisionMesh".CollisionMeshData}); present only for ids in `COLLISION_MESH_ASSET_IDS` whose geometry extracted. */
|
|
44
|
+
collisionMesh?: CollisionMeshData;
|
|
45
|
+
/** Animation clip names read from the GLB at reindex; absent for unrigged/unreadable models. */
|
|
46
|
+
clips?: readonly string[];
|
|
41
47
|
/** Authored asset-space metadata (canonical facing, unit scale, footprint, anchor, bounds, rotation policy); absent unless a curator overrides the measured defaults. */
|
|
42
48
|
space?: AssetSpace;
|
|
43
49
|
}
|
|
@@ -51,11 +51,6 @@
|
|
|
51
51
|
"title": "Buff Tray",
|
|
52
52
|
"description": "Row of chamfered buff/debuff chips with stack counts and a remaining-duration underline, driven by a plain chip array."
|
|
53
53
|
},
|
|
54
|
-
{
|
|
55
|
-
"name": "cartridge-panels",
|
|
56
|
-
"title": "Cartridge Panels",
|
|
57
|
-
"description": "Standard panel bindings for @jgengine/shell/cartridge: vital/xp/timer/score/ability-bar HUD items, upgrade-draft modal, and win/lose screens composed from the jgengine UI kit."
|
|
58
|
-
},
|
|
59
54
|
{
|
|
60
55
|
"name": "cast-bar",
|
|
61
56
|
"title": "Cast Bar",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jgengine/assets",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Self-generating, license-verified index of thousands of CC0 3D models for JGengine. Sources fetch from providers' own CDNs at pull time; the npm tarball ships only the typed index and CLI (no GLB bytes).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"test": "bun test src"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@jgengine/core": "^0.
|
|
38
|
+
"@jgengine/core": "^0.13.0",
|
|
39
39
|
"fflate": "^0.8.2"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
package/skills/jgengine/SKILL.md
CHANGED
|
@@ -9,16 +9,16 @@ Read the repository [README](../../../README.md) for package truth, commands, la
|
|
|
9
9
|
|
|
10
10
|
## 1. Establish the target
|
|
11
11
|
|
|
12
|
-
Capture only decisions that change architecture:
|
|
12
|
+
Treat the pitch as a unique composition of needs, not a genre to fill in — never reach for a genre kit, preset, archetype, or class template ("default sports car", "default RPG", "default FPS") in the SDK or skills (see [AGENTS.md](../../../AGENTS.md)). Use `game-design` to turn the pitch into a testable player promise, verbs, loops, progression, failure, and completion scenario. Use `level-design` when play depends on authored spaces, routes, encounters, exploration, or spatial pacing. Capture only decisions that change architecture:
|
|
13
13
|
|
|
14
14
|
- player point of view and controls
|
|
15
15
|
- world shape and authored content
|
|
16
16
|
- core loop, interaction, combat, and progression
|
|
17
17
|
- solo, local, hosted, or persistent multiplayer
|
|
18
|
-
- HUD/menu states and art direction
|
|
18
|
+
- HUD/menu states and **custom** UI art direction (every game owns its presentation — no stock drop-in face)
|
|
19
19
|
- one observable completion scenario
|
|
20
20
|
|
|
21
|
-
For a new in-repo game, scaffold with `bun run new:game <id>
|
|
21
|
+
For a new in-repo game, scaffold with `bun run new:game "<id-or-title>"` (thin script alias for `jgengine create`, auto-detects the in-repo variant). Outside this monorepo, start with `npx jgengine create`; never copy `Games/*`.
|
|
22
22
|
|
|
23
23
|
## 2. Select domains
|
|
24
24
|
|
|
@@ -26,6 +26,8 @@ Load only rows the target needs. Do not preload every domain.
|
|
|
26
26
|
|
|
27
27
|
| Need | Skill | Owner |
|
|
28
28
|
| --- | --- | --- |
|
|
29
|
+
| player promise, pillars, verbs, loops, economy, progression, balance | `game-design` | experience and rule intent |
|
|
30
|
+
| metrics, topology, encounters, navigation, spatial pacing | `level-design` | playable space intent |
|
|
29
31
|
| scene placement, terrain painting, paths, asset authoring | `jgengine-editor` | editor document and authoring tools |
|
|
30
32
|
| runtime world, movement, input, interaction, AI, navigation, audio | `jgengine-world` | spatial simulation and world runtime |
|
|
31
33
|
| game state, systems, inventory, crafting, quests, economy, turns | `jgengine-gameplay` | non-combat rules and state |
|
|
@@ -34,15 +36,17 @@ Load only rows the target needs. Do not preload every domain.
|
|
|
34
36
|
| models, sprites, materials, audio files, source licensing | `jgengine-assets` | asset discovery and catalogs |
|
|
35
37
|
| authority, transport, replication, sessions, host persistence | `jgengine-multiplayer` | network topology and persistence adapters |
|
|
36
38
|
|
|
37
|
-
Scenes normally require both `jgengine-editor` for authoring and `jgengine-world` for runtime consumption. Combat and multiplayer are opt-in, not default intake.
|
|
39
|
+
World content routes editor-first: any request that adds, moves, restyles, or removes something visible in the world — however phrased ("design this world", "place the enemies", "make it look better") — starts in `jgengine-editor`; the other domains consume the authored document. Scenes normally require both `jgengine-editor` for authoring and `jgengine-world` for runtime consumption. Combat and multiplayer are opt-in, not default intake.
|
|
38
40
|
|
|
39
41
|
## 3. Discover before designing
|
|
40
42
|
|
|
41
43
|
Within each selected domain:
|
|
42
44
|
|
|
45
|
+
0. Fastest start for a common composition: `npx jgengine recipe <name>` prints a vetted, SDK-typechecked snippet (imports + wired code) for `combat-loop`, `boss-telegraph`, `loot`, `quest`, `coop-presence`, `third-person-camera`; `npx jgengine recipe` lists them. Copy that instead of reconning per-file.
|
|
43
46
|
1. Search `capabilities.md` by intent; it maps needs to imports.
|
|
44
47
|
2. Open `api.md` only when exact signatures or export inventory are needed.
|
|
45
48
|
3. Open the linked reference only for a deeper recipe or trap.
|
|
49
|
+
4. For how several primitives wire into a running loop, read the domain's `recipes/` — connected, genre-free walkthroughs organized by composition seam; this skill's own [recipes/minimal-game.md](recipes/minimal-game.md) is the default whole-game walkthrough. Prefer a recipe over reading a game's source; the games under `Games/*` are not templates or references, and a hybrid game is just a different composition of the same primitives.
|
|
46
50
|
|
|
47
51
|
If no capability fits, identify the upstream package seam before writing game-local code. In this repository, implement a reusable primitive with its first adopter; if editor-owned content cannot be expressed, file the editor gap first.
|
|
48
52
|
|