@jgengine/assets 0.19.0 → 0.21.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 +346 -0
- package/README.md +22 -3
- package/dist/assetBudget.d.ts +36 -0
- package/dist/assetBudget.js +110 -0
- package/dist/catalogs/build.d.ts +1 -0
- package/dist/catalogs/build.js +1 -0
- package/dist/cli/pull.js +56 -1
- package/dist/glbMetrics.d.ts +24 -0
- package/dist/glbMetrics.js +291 -0
- package/dist/gltfMaterials.d.ts +79 -0
- package/dist/gltfMaterials.js +183 -0
- package/dist/importSpec.d.ts +15 -6
- package/dist/importSpec.js +217 -45
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/indexGen.d.ts +3 -1
- package/dist/indexGen.js +14 -4
- package/dist/manifest.d.ts +7 -0
- package/dist/materials.d.ts +3 -3
- package/dist/materials.js +3 -3
- package/dist/snippet.js +1 -1
- package/dist/sources/ambientcg.js +37 -31
- package/dist/staticPrefabBake.d.ts +58 -0
- package/dist/staticPrefabBake.js +315 -0
- package/dist/verify.js +2 -2
- package/package.json +5 -2
- package/skills/ce-handoff/SKILL.md +1 -1
- package/skills/jgengine/SKILL.md +22 -2
- package/skills/jgengine/api.md +28 -17
- package/skills/jgengine/recipes/minimal-game.md +7 -2
- package/skills/jgengine-assets/SKILL.md +24 -3
- package/skills/jgengine-assets/api.md +90 -15
- package/skills/jgengine-assets/capabilities.md +41 -0
- package/skills/jgengine-assets/references/custom-imports.md +55 -0
package/skills/jgengine/api.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
- `CHANGELOG` (const): const CHANGELOG: Record<string, ChangelogEntry> — Per-version engine changelog keyed by semver string (e.g. `"0.10.0"`).
|
|
8
8
|
- `ChangelogEntry` (interface): interface ChangelogEntry — One release's migrate steps plus added/changed/removed notes (typed mirror of CHANGELOG.md).
|
|
9
|
-
- `VERSION` (const): const VERSION: "0.
|
|
9
|
+
- `VERSION` (const): const VERSION: "0.21.0" — Installed `@jgengine/core` semver — compare against {@link CHANGELOG} keys when migrating.
|
|
10
10
|
|
|
11
11
|
## @jgengine/core/authoring
|
|
12
12
|
|
|
@@ -232,7 +232,7 @@
|
|
|
232
232
|
|
|
233
233
|
- `CHANGELOG` (const): const CHANGELOG: Record<string, ChangelogEntry> — Per-version engine changelog keyed by semver string (e.g. `"0.10.0"`).
|
|
234
234
|
- `ChangelogEntry` (interface): interface ChangelogEntry — One release's migrate steps plus added/changed/removed notes (typed mirror of CHANGELOG.md).
|
|
235
|
-
- `VERSION` (const): const VERSION: "0.
|
|
235
|
+
- `VERSION` (const): const VERSION: "0.21.0" — Installed `@jgengine/core` semver — compare against {@link CHANGELOG} keys when migrating.
|
|
236
236
|
|
|
237
237
|
## @jgengine/core/runtime/adapter
|
|
238
238
|
|
|
@@ -260,10 +260,20 @@
|
|
|
260
260
|
## @jgengine/core/runtime/cameraDirector
|
|
261
261
|
|
|
262
262
|
- `CHASE_VIEWS` (const): const CHASE_VIEWS: readonly ChaseView[] — Default order {@link nextChaseView} cycles through.
|
|
263
|
-
- `CameraDirector` (interface): interface CameraDirector { follow(entityId: string | null): void; followedEntityId(): string | null | undefined;
|
|
264
|
-
- `
|
|
263
|
+
- `CameraDirector` (interface): interface CameraDirector { follow(entityId: string | null): void; followedEntityId(): string | null | undefined; setRig(kind: CameraRigKind | null, config?: CameraRigConfig): void; rig(): CameraRigOverride | null; setCinematic(config: CinematicCameraConfig | null):… — ⚠ undocumented
|
|
264
|
+
- `CameraDirectorSnapshot` (type): type CameraDirectorSnapshot = CameraSerialized<CameraDirectorState> — JSON-safe camera policy; documented instant chase responses use an explicit Infinity marker.
|
|
265
|
+
- `CameraDirectorState` (interface): interface CameraDirectorState — Camera policy state before the JSON-safe snapshot number encoding.
|
|
266
|
+
- `CameraRigConfig` (type): type CameraRigConfig = Omit<GameCameraConfig, "rig" | "projection" | "pixelPerfect" | "frustum" | "playerFov" | "weapon" | "onCameraFollow"> — Data overlay for an existing rig; callbacks and Canvas projection/preferences remain configured by the game.
|
|
267
|
+
- `CameraRigOverride` (interface): interface CameraRigOverride — Runtime rig selection and detached data overlay over the configured camera.
|
|
268
|
+
- `ChaseCameraTuning` (type): type ChaseCameraTuning = Partial< Pick< ChaseCameraConfig, | "distance" | "height" | "lookHeight" | "springDamping" | "fov" | "lead" | "bank" | "shakePerSpeed" | "velocityYaw" | "yawResponse" | "headingSource" | "distanceBySpeed" | "pitchFollow" | "fovKick" | "lookBackAction" | "collision" | "view" … — Runtime patch over the static `camera.chase` config — distance/height/fov retuning from gameplay events (#286.11), a whole driving-feel overlay applied only while a vehicle is piloted (#1299), or a `view` switch between chase and seat cameras.
|
|
265
269
|
- `nextChaseView` (function): function nextChaseView(current: ChaseView, views: readonly ChaseView[] = CHASE_VIEWS): ChaseView — The view after `current` in `views`, wrapping at the end; a view missing from the list starts the cycle over. Pair with `setChaseTuning` to bind a "change camera" key: `ctx.camera.setChaseTuning({ ...ctx.camera.chaseTuning(), view: nextChaseView(view) })`.
|
|
266
270
|
|
|
271
|
+
## @jgengine/core/runtime/commandDispatch
|
|
272
|
+
|
|
273
|
+
- `DispatchedCommandResult` (type): type DispatchedCommandResult = CommandResult<GameContext> | Promise<CommandResult<GameContext>> — A UI command completes locally or after its authoritative host acknowledges it.
|
|
274
|
+
- `bindCommandTransport` (function): function bindCommandTransport(ctx: GameContext, route: Route): () => void — Bind UI command dispatch to the host for this context. A missing join rejects; it never mutates the local replica.
|
|
275
|
+
- `dispatchCommand` (function): function dispatchCommand(ctx: GameContext, name: string, input: unknown): DispatchedCommandResult — Dispatch a player's command through the bound host, or locally for an unbound offline context. Await the result before showing success.
|
|
276
|
+
|
|
267
277
|
## @jgengine/core/runtime/commandInput
|
|
268
278
|
|
|
269
279
|
- `QuantityResult` (type): type QuantityResult = { ok: true; quantity: number } | { ok: false; reason: "invalid-quantity" } — Validated integer quantity or a stable input rejection.
|
|
@@ -318,7 +328,7 @@
|
|
|
318
328
|
- `GameContextWorld` (interface): interface GameContextWorld { ground: TerrainField; groundHeightAt(x: number, z: number): number; solids: WorldSolids } — ⚠ undocumented
|
|
319
329
|
- `HitReactionInput` (interface): interface HitReactionInput — ⚠ undocumented · used by `resolveHitReaction` (@jgengine/core/combat): Resolves hit feel (hitstop, knockback impulse, camera shake) from either a named `impactPresets` event (`resolveHitReaction("explosion", inp…
|
|
320
330
|
- `MoveTowardCommitOptions` (interface): interface MoveTowardCommitOptions extends MoveTowardOptions — Options for {@link SceneEntityContext.moveTowardCommit}: {@link MoveTowardOptions} plus an optional facing turn.
|
|
321
|
-
- `SceneEntityContext` (interface): interface SceneEntityContext { spawn(name: string, options?: SpawnOptions): string; despawn(instanceId: string): boolean; update: EntityStore["update"]; setPose(instanceId: string, pose: EntityPose): boolean;
|
|
331
|
+
- `SceneEntityContext` (interface): interface SceneEntityContext { spawn(name: string, options?: SpawnOptions): string; despawn(instanceId: string): boolean; update: EntityStore["update"]; setPose(instanceId: string, pose: EntityPose): boolean; setVelocity: EntityStore["setVelocity"]; setPoseConstraint: … — ⚠ undocumented
|
|
322
332
|
- `SceneObjectContext` (interface): interface SceneObjectContext extends ObjectStore { catalog(instanceId: string): GameContextObjectEntry | null; raycast(input: ObjectRaycastInput): ObjectRaycastHit | null; raycastAll(input: ObjectRaycastInput): readonly ObjectRaycastHit[]; setColliders(instanceId: string, colliders: Entit… — ⚠ undocumented
|
|
323
333
|
- `SceneWorldItemContext` (interface): interface SceneWorldItemContext — `ctx.scene.worldItem`: items lying in the world — spawn, list, find the nearest, and pick up into a player's bag.
|
|
324
334
|
- `TelegraphInput` (interface): interface TelegraphInput { from: string; shape: TelegraphShape; at: [number, number, number]; dir?: number; windupMs: number; kind?: string; effect?: {effect: string; via?: EffectVia; radius?: number; falloff?: "linear" | "none"; los?: boolean;} } — ⚠ undocumented
|
|
@@ -349,7 +359,7 @@
|
|
|
349
359
|
- `GameContextWorld` (interface): interface GameContextWorld { ground: TerrainField; groundHeightAt(x: number, z: number): number; solids: WorldSolids } — ⚠ undocumented
|
|
350
360
|
- `HitReactionInput` (interface): interface HitReactionInput { from: string; to: string; config: HitReactionConfig | ImpactPresetName; power?: number } — ⚠ undocumented · used by `resolveHitReaction` (@jgengine/core/combat): Resolves hit feel (hitstop, knockback impulse, camera shake) from either a named `impactPresets` event (`resolveHitReaction("explosion", inp…
|
|
351
361
|
- `MoveTowardCommitOptions` (interface): interface MoveTowardCommitOptions extends MoveTowardOptions — Options for {@link SceneEntityContext.moveTowardCommit}: {@link MoveTowardOptions} plus an optional facing turn.
|
|
352
|
-
- `SceneEntityContext` (interface): interface SceneEntityContext { spawn(name: string, options?: SpawnOptions): string; despawn(instanceId: string): boolean; update: EntityStore["update"]; setPose(instanceId: string, pose: EntityPose): boolean;
|
|
362
|
+
- `SceneEntityContext` (interface): interface SceneEntityContext { spawn(name: string, options?: SpawnOptions): string; despawn(instanceId: string): boolean; update: EntityStore["update"]; setPose(instanceId: string, pose: EntityPose): boolean; setVelocity: EntityStore["setVelocity"]; setPoseConstraint: … — ⚠ undocumented
|
|
353
363
|
- `SceneObjectContext` (interface): interface SceneObjectContext extends ObjectStore { catalog(instanceId: string): GameContextObjectEntry | null; raycast(input: ObjectRaycastInput): ObjectRaycastHit | null; raycastAll(input: ObjectRaycastInput): readonly ObjectRaycastHit[]; setColliders(instanceId: string, colliders: Entit… — ⚠ undocumented
|
|
354
364
|
- `SceneWorldItemContext` (interface): interface SceneWorldItemContext — `ctx.scene.worldItem`: items lying in the world — spawn, list, find the nearest, and pick up into a player's bag.
|
|
355
365
|
- `TelegraphInput` (interface): interface TelegraphInput { from: string; shape: TelegraphShape; at: [number, number, number]; dir?: number; windupMs: number; kind?: string; effect?: {effect: string; via?: EffectVia; radius?: number; falloff?: "linear" | "none"; los?: boolean;} } — ⚠ undocumented
|
|
@@ -420,7 +430,7 @@
|
|
|
420
430
|
- `HostedGameRunner` (interface): interface HostedGameRunner — The GameContext-loop equivalent of the pure-reducer `createGameHost`: one authoritative `createGameContext` per world, driven server-side. `onInit` runs once at construction; `onNewPlayer`/`onPlayerLeave` fire per join/leave; `tick` advances `onTick` then commits a revision. Clients pull a full {@link WorldSnapshot} baseline once, then per-tick {@link WorldDiff}s from their last revision. Games ship only normal GameContext code — the runner adds no per-game surface.
|
|
421
431
|
- `HostedGameRunnerOptions` (interface): interface HostedGameRunnerOptions<TAssetRef extends ModelAssetRef, TMultiplayer> — Config for {@link createHostedGameRunner}: the game definition, its content lookup, and an optional host identity.
|
|
422
432
|
- `INPUT_COMMAND` (const): const INPUT_COMMAND: "engine.input" — Reserved command name the authoritative host intercepts on the existing `runCommand` transport to route a client's {@link InputFrame} to `session.input`, so per-tick input needs no separate wire.
|
|
423
|
-
- `InputFrame` (interface): interface InputFrame — One client's
|
|
433
|
+
- `InputFrame` (interface): interface InputFrame — One client's serializable held state and discrete edges for a simulation tick.
|
|
424
434
|
|
|
425
435
|
## @jgengine/core/runtime/hostedWorldSession
|
|
426
436
|
|
|
@@ -429,7 +439,7 @@
|
|
|
429
439
|
- `HostedWorldSessionOptions` (interface): interface HostedWorldSessionOptions<TAssetRef extends ModelAssetRef, TMultiplayer> — Config for {@link createHostedWorldSession}: the game, its persistence store, and the auto-save cadence.
|
|
430
440
|
- `HostedWorldStore` (interface): interface HostedWorldStore — Narrow persistence seam for a hosted world — the {@link HostedWorldRecord} counterpart of `HostPersistence`. Backends implement it (memory/file/sql/convex); the session never names one. A stateful host loads once and saves on a cadence; a stateless host reconstructs from `load()` each invocation.
|
|
431
441
|
- `HostedWorldSync` (type): type HostedWorldSync = | { kind: "baseline"; revision: number; snapshot: WorldSnapshot } | { kind: "diff"; diff: WorldDiff } — A client replication pull: a full baseline (first sync / fell behind) or a diff since the client's cursor.
|
|
432
|
-
- `SyncHostedWorldStore` (interface): interface SyncHostedWorldStore —
|
|
442
|
+
- `SyncHostedWorldStore` (interface): interface SyncHostedWorldStore — Already-loaded store adapter: synchronous reads, with synchronous or asynchronous writes.
|
|
433
443
|
- `asyncMemoryWorldStore` (function): function asyncMemoryWorldStore(seed?: HostedWorldRecord): HostedWorldStore — Async in-process store for callers exercising the production persistence contract.
|
|
434
444
|
- `createHostedWorldSessionAsync` (function): function createHostedWorldSessionAsync<TAssetRef extends ModelAssetRef, TMultiplayer>(options: Omit<HostedWorldSessionOptions<TAssetRef, TMultiplayer>, "store"> & { store: HostedWorldStore }): Promise<HostedWorldSession> — Build a hosted session from an asynchronous persistence backend.
|
|
435
445
|
|
|
@@ -437,7 +447,7 @@
|
|
|
437
447
|
|
|
438
448
|
- `HostedWorldRecord` (interface): interface HostedWorldRecord — One hosted world's persisted authoritative state — the unit a {@link HostedWorldStore} loads and saves.
|
|
439
449
|
- `HostedWorldStore` (interface): interface HostedWorldStore — Narrow persistence seam for a hosted world — the {@link HostedWorldRecord} counterpart of `HostPersistence`. Backends implement it (memory/file/sql/convex); the session never names one. A stateful host loads once and saves on a cadence; a stateless host reconstructs from `load()` each invocation.
|
|
440
|
-
- `SyncHostedWorldStore` (interface): interface SyncHostedWorldStore —
|
|
450
|
+
- `SyncHostedWorldStore` (interface): interface SyncHostedWorldStore — Already-loaded store adapter: synchronous reads, with synchronous or asynchronous writes.
|
|
441
451
|
|
|
442
452
|
## @jgengine/core/runtime/inputRecorder
|
|
443
453
|
|
|
@@ -448,8 +458,9 @@
|
|
|
448
458
|
|
|
449
459
|
## @jgengine/core/runtime/inputSnapshot
|
|
450
460
|
|
|
451
|
-
- `InputFrame` (interface): interface InputFrame — One client's
|
|
452
|
-
- `
|
|
461
|
+
- `InputFrame` (interface): interface InputFrame — One client's serializable held state and discrete edges for a simulation tick.
|
|
462
|
+
- `InputPress` (interface): interface InputPress — One discrete press, identified across retransmitted live input frames.
|
|
463
|
+
- `InputSnapshot` (interface): interface InputSnapshot { rumble(userId: string, options: {strong: number; weak: number; ms: number}): Promise<boolean>; haptics(userId: string): HapticChannels; publish(held: readonly string[], edges?: {pressed?: readonly string[]; reset?: boolean}): void; beginS… — ⚠ undocumented · used by `GamepadSource` (@jgengine/shell/input/gamepadSource): Poll browser gamepads and feed semantic actions into the shell tracker.
|
|
453
464
|
- `createInputSnapshot` (function): function createInputSnapshot(): InputSnapshot — ⚠ undocumented
|
|
454
465
|
|
|
455
466
|
## @jgengine/core/runtime/localPlayers
|
|
@@ -509,11 +520,11 @@
|
|
|
509
520
|
|
|
510
521
|
## @jgengine/core/runtime/runtimeSave
|
|
511
522
|
|
|
512
|
-
- `RuntimeSave` (interface): interface RuntimeSave — Whole-world save/load bound to a live world and a pluggable backend. `save()` captures `target.
|
|
523
|
+
- `RuntimeSave` (interface): interface RuntimeSave — Whole-world save/load bound to a live world and a pluggable backend. `save()` captures `target.state()` and writes it; `load()` reads it back and calls `target.restore()`. Older targets use `snapshot()`/`hydrate()`. In `autosave` mode it also writes on a trailing timer while the world keeps changing. Named slots, versioned migration, and offline↔cloud (backend swap) all come for free from the underlying save store.
|
|
513
524
|
- `RuntimeSaveConfig` (interface): interface RuntimeSaveConfig — How {@link createRuntimeSave} is wired — the live world `target`, the `backend` it persists through, and optional mode/slot/versioning/cadence knobs.
|
|
514
525
|
- `RuntimeSaveMode` (type): type RuntimeSaveMode = "autosave" | "manual" — `"autosave"` writes a fresh capture on a trailing timer while the world changes (at most once per `autosaveMs`, so a never-idle world still persists); `"manual"` writes only on an explicit `save()`/`checkpoint()` — the save-point / quest-trigger model.
|
|
515
526
|
- `RuntimeSaveOptions` (type): type RuntimeSaveOptions = Omit<RuntimeSaveConfig, "target"> — {@link RuntimeSaveConfig} without `target` — what a host (`createGameContext`) accepts to build `ctx.game.save` and bind it to the context itself.
|
|
516
|
-
- `RuntimeSaveTarget` (interface): interface RuntimeSaveTarget — The narrow slice of a live `GameContext` a runtime save reads and writes — a `GameContext` satisfies it directly (`ctx.
|
|
527
|
+
- `RuntimeSaveTarget` (interface): interface RuntimeSaveTarget — The narrow slice of a live `GameContext` a runtime save reads and writes — a `GameContext` satisfies it directly (`ctx.state`/`ctx.restore`/`ctx.subscribe`). Depending on this instead of the full context keeps the save controller a deep, decoupled module: it captures and restores the *whole* opted-in world without knowing any subsystem.
|
|
517
528
|
- `createRuntimeSave` (function): function createRuntimeSave(config: RuntimeSaveConfig): RuntimeSave — Bridge a live world to a pluggable save backend: whole-state capture/restore with autosave, save points, named slots, and versioned migration — the same call for offline (localStorage) and cloud (Convex), only the `backend` differs. The game keeps control of *when* it saves (the `mode` plus explicit `checkpoint()` calls from quests/areas) and *when* it restores (`load()` on boot), so any save mechanic — continuous autosave, manual save points, checkpoint triggers — is expressible without new engine code.
|
|
518
529
|
|
|
519
530
|
## @jgengine/core/runtime/save
|
|
@@ -527,7 +538,7 @@
|
|
|
527
538
|
- `SimContextState` (interface): interface SimContextState — Serializable `ctx.sim` state: loop position plus the interpolation pose history.
|
|
528
539
|
- `SimStage` (interface): interface SimStage — Extra work a game or engine seam (a physics backend, a netcode buffer) runs inside every simulation step.
|
|
529
540
|
- `SimStagePhase` (type): type SimStagePhase = "beforeMovement" | "afterMovement" | "afterTick" — Where a registered stage runs inside one simulation step.
|
|
530
|
-
- `createSimContext` (function): function createSimContext(options: { config?: SimulationConfig; entities: EntityStore }): SimContext — Build `ctx.sim` for a context; `createGameContext` calls this from `definition.simulation`.
|
|
541
|
+
- `createSimContext` (function): function createSimContext(options: { config?: SimulationConfig; entities: EntityStore; time?: Pick<SimClock, "advance"> }): SimContext — Build `ctx.sim` for a context; `createGameContext` calls this from `definition.simulation`.
|
|
531
542
|
|
|
532
543
|
## @jgengine/core/runtime/simLoop
|
|
533
544
|
|
|
@@ -640,7 +651,7 @@
|
|
|
640
651
|
## @jgengine/shell/GameHost
|
|
641
652
|
|
|
642
653
|
- `EditorSummonModule` (interface): interface EditorSummonModule — Structural shape of the module `GameHost`'s `editor` loader resolves — `import("@jgengine/editor")` satisfies it.
|
|
643
|
-
- `GameHost` (function): function GameHost({ playable, gameId, wsUrl, multiplayer, resolveMultiplayer, editor }: GameHostProps): React.JSX.Element — The one documented mount: resolves multiplayer for the playable and renders the shell. With the `editor` loader prop it also owns the whole editor summon (F2+E, `?mode=editor`, dev save endpoint).
|
|
654
|
+
- `GameHost` (function): function GameHost({ playable, gameId, wsUrl, multiplayer, resolveMultiplayer, editor, creator, creatorOpen = false, onCreatorOpenChange }: GameHostProps): React.JSX.Element — The one documented mount: resolves multiplayer for the playable and renders the shell. With the `editor` loader prop it also owns the whole editor summon (F2+E, `?mode=editor`, dev save endpoint).
|
|
644
655
|
- `GameHostProps` (interface): interface GameHostProps — Props for {@link GameHost}: the playable, optional multiplayer overrides, and the optional editor loader that enables the engine-owned F2+E summon.
|
|
645
656
|
|
|
646
657
|
## @jgengine/shell/defineGame
|
|
@@ -659,7 +670,7 @@
|
|
|
659
670
|
- `GameCameraConfig` (interface): interface GameCameraConfig — Camera tuning for the shell's rig stack: pick the rig via `rig`, then tune it through its matching config block. All fields optional — the default is the third-person orbit rig.
|
|
660
671
|
- `GameConfig` (type): type GameConfig<TAssetRef extends ModelAssetRef = ModelAssetRef> = EngineFields<TAssetRef> & PresentationFields — ⚠ undocumented · used by `defineGame`: The one public authoring entry point: compose engine fields (systems, world, physics, input) and presentation fields (camera, HUD, audio, au…
|
|
661
672
|
- `GameContext` (interface): interface GameContext — The live engine handle a game's loop, systems, commands, and UI read and mutate — entities, objects, the reactive store, opted-in `game.*` subsystems, world queries, and the sim clock. One context = one running world.
|
|
662
|
-
- `GameHost` (function): function GameHost({ playable, gameId, wsUrl, multiplayer, resolveMultiplayer, editor }: GameHostProps): React.JSX.Element — The one documented mount: resolves multiplayer for the playable and renders the shell. With the `editor` loader prop it also owns the whole editor summon (F2+E, `?mode=editor`, dev save endpoint).
|
|
673
|
+
- `GameHost` (function): function GameHost({ playable, gameId, wsUrl, multiplayer, resolveMultiplayer, editor, creator, creatorOpen = false, onCreatorOpenChange }: GameHostProps): React.JSX.Element — The one documented mount: resolves multiplayer for the playable and renders the shell. With the `editor` loader prop it also owns the whole editor summon (F2+E, `?mode=editor`, dev save endpoint).
|
|
663
674
|
- `GameHostProps` (interface): interface GameHostProps — Props for {@link GameHost}: the playable, optional multiplayer overrides, and the optional editor loader that enables the engine-owned F2+E summon.
|
|
664
675
|
- `GameLoop` (interface): interface GameLoop<TContext = unknown> — Lifecycle hooks a game implements to drive init, per-tick simulation, and player join/leave.
|
|
665
676
|
- `Hotbar` (function): function Hotbar({ inventoryId, activeSlot, keys, slotSize, itemIcon, style, className, }: { inventoryId: string; activeSlot?: number; keys?: readonly string[]; slotSize?: number; /** Caller-supplied item id → icon registry; return null/undefined to fall back to the default glyph. */ itemIcon?: (item… — A numbered hotbar bound to an inventory — painted iconed slots (a `GameIcon` glyph over a school-keyed gradient with a count badge, #1035), an active-slot highlight, and a keycap per slot. Place it and pass the `inventoryId`; `activeSlot` highlights the equipped one. Supply `itemIcon` to map your item ids to your own glyphs — the default resolves a `GameIcon` from the item id.
|
|
@@ -673,7 +684,7 @@
|
|
|
673
684
|
- `collectAuthoredTriggers` (function): function collectAuthoredTriggers(document: SceneDocumentLike): AuthoredTrigger[] — Collect every authored trigger on a document's markers and volumes. Pure — no runtime state. Action params use the live {@link registerTriggerAction} registry when present.
|
|
674
685
|
- `defineGame` (function): function defineGame<TAssetRef extends ModelAssetRef = ModelAssetRef>(config: GameConfig<TAssetRef>): PlayableGame — The one public authoring entry point: compose engine fields (systems, world, physics, input) and presentation fields (camera, HUD, audio, authored scene) into a `PlayableGame` ready for `GameHost`. Defaults to solo/offline multiplayer; `editorLayers` auto-mounts the authored scene document.
|
|
675
686
|
- `defineKeyedStore` (function): function defineKeyedStore<T>(keyFor: (id: string) => string, initial: T | (() => T)): KeyedStoreHandle<T> — Define a typed per-owner keyed family on the game store: game code expresses `read(ctx, userId)`/`write(ctx, userId, v)`/`update(...)` with the value type it means, and both the `` `prefix:${id}` `` key composition and the `unknown → T` cast live once, here, behind the boundary. Reach for this over N separate `defineStore` calls whenever the owning id varies at runtime (per-user class, per-instance auras) — `defineStore` stays the right call for a single fixed slot.
|
|
676
|
-
- `defineStore` (function): function defineStore<T>(key: string, initial: T | (() => T)): StoreHandle<T> — Define a typed slot on the game store: game code expresses `read(ctx)`/`write(ctx, v)`/`update(...)` with the value type it means, and the `unknown → T` cast lives once, here, behind the boundary. Pass a factory for `initial` when the fallback is a fresh mutable object; the factory runs at most once and its result is reused, so an unwritten slot keeps a stable identity across reads (no per-read churn for a React selector, no allocation on a hot path).
|
|
687
|
+
- `defineStore` (function): function defineStore<T>(key: string, initial: T | (() => T)): StoreHandle<T> — Define a typed slot on the game store: game code expresses `read(ctx)`/`write(ctx, v)`/`update(...)` with the value type it means, and the `unknown → T` cast lives once, here, behind the boundary. Pass a factory for `initial` when the fallback is a fresh mutable object; the factory runs at most once and its result is reused, so an unwritten slot keeps a stable identity across reads (no per-read churn for a React selector, no allocation on a hot path). A value that carries functions (a closure-based run store, an input handle) is runtime-only: snapshots, saves and replication skip it and hydration keeps it in place. Hold such objects with `perContext` when they need no store notifications.
|
|
677
688
|
- `defineSystem` (function): function defineSystem(definition: SystemDefinition): SystemDefinition — Declare a composable game system. Pure data + hooks — the engine compiles the schedule and installs lifecycle when the game boots.
|
|
678
689
|
- `environment` (function): function environment(config?: EnvironmentWorldConfig): EnvironmentWorldFeature — Composes an `environment()` feature from terrain, sky, weather, vegetation, water, structures, roads, and pads.
|
|
679
690
|
- `environmentContentFromDocument` (function): function environmentContentFromDocument(doc: EditorDocument, options?: EnvironmentContentOptions): EnvironmentContent — Derives the coordinate/placement content of an `environment()` world from its scene document: terrain footprint (via {@link terrainBoundsFromDocument}), ground clearings under authored spawns/POIs (via `clearanceZonesFrom`), and the document's sculpt snapshot. This is the seam that lets a game author its world footprint and flatten regions in the editor instead of hardcoding them — the `world.ts` that consumes it carries only engine tuning.
|
|
@@ -6,6 +6,11 @@ authored scene edited in the browser, one system, one store slot, an empty-canva
|
|
|
6
6
|
and a win condition. Every new game starts here; add combat, multiplayer, or deeper
|
|
7
7
|
world features only after this loop plays.
|
|
8
8
|
|
|
9
|
+
Every extension follows the [framework-first decision](../SKILL.md#framework-first-decisions):
|
|
10
|
+
compose an installed SDK capability, improve its upstream contract if needed, then
|
|
11
|
+
remove superseded game glue after published adoption. The game owns its rules and art;
|
|
12
|
+
it should not recreate input, model lifecycle, storage or UI accessibility machinery.
|
|
13
|
+
|
|
9
14
|
## 1. Scaffold
|
|
10
15
|
|
|
11
16
|
`npx jgengine create <name>` (inside the engine monorepo: `bun run new:game "<id-or-title>"`).
|
|
@@ -80,8 +85,8 @@ direction. Compose the shipped building blocks the moment you need them (`StatBa
|
|
|
80
85
|
`Coins`, `InventoryGrid`, `CharacterSheet`, window shells from `jgengine-ui`), then reskin via
|
|
81
86
|
`HudTheme` tokens. Reaching for those is using the engine correctly, not incomplete work. What
|
|
82
87
|
the engine does not ship is a whole finished game *face* or genre theme preset — do not leave an
|
|
83
|
-
unarranged, unskinned generic dashboard as the product.
|
|
84
|
-
|
|
88
|
+
unarranged, unskinned generic dashboard as the product. Custom markup can use headless
|
|
89
|
+
SDK behavior; a missing reusable behavior is an upstream gap (see `jgengine-ui`).
|
|
85
90
|
|
|
86
91
|
## 3. Author, play, win
|
|
87
92
|
|
|
@@ -13,27 +13,49 @@ Search [capabilities.md](capabilities.md) before adding a resolver or catalog pa
|
|
|
13
13
|
|
|
14
14
|
## Canonical workflow
|
|
15
15
|
|
|
16
|
-
1.
|
|
16
|
+
1. Choose a palette from the game's art direction: silhouette, materials, scale, era, and visual language. Search existing catalog entries and typed asset refs against that palette; catalog availability does not choose the game's look.
|
|
17
17
|
2. Verify source license and attribution requirements before download.
|
|
18
18
|
3. Record canonical facing, source units, pivot, footprint, bounds, and placement policy in metadata.
|
|
19
19
|
4. Pull/index through shared tooling; do not commit remote-library bulk bytes when the catalog is designed to resolve them.
|
|
20
20
|
5. Preview through the same resolver runtime will use.
|
|
21
21
|
6. Add required credit in the same PR.
|
|
22
22
|
|
|
23
|
+
Reuse import, validation, catalog, and rendering tools to save time. Each game owns its asset selection and visual identity. Source or import licensed assets when the catalog does not fit; do not substitute the same convenient pack into every game. Validate a representative set in the actual scene before filling the world with it. Keep that reviewed palette consistent within the game without treating it as an SDK preset.
|
|
24
|
+
|
|
23
25
|
## Reference integrity
|
|
24
26
|
|
|
25
27
|
Every logical asset id has a declared owner: `committed` (a single's shipped URL, resolves on a clean clone), `provisioned` (a pack index entry whose GLB is fetched by `assets pull <source>`), or `dangling` (nothing owns it — a broken contract). Resolve one id with `resolveProvenance(id)`; gate a set of references with `validateAssetReferences(refs)`, which fails on any dangling reference and reports the exact `assets pull <source>` steps a clean checkout still needs. `assets provenance <id>...` exposes the same contract on the CLI and exits non-zero on a dangling id. This resolves references structurally against the catalog — never grep source text as the long-term contract.
|
|
26
28
|
|
|
27
|
-
A game's catalog is `buildCatalog(...)` over the generated pack index, singles, and aliases; `extras` is its durable escape hatch for assets that aren't in a pack. An editor asset import into a **promoted** game project writes into that `extras` array in `src/game/assets.ts` (bytes land in `public/<basePath>/imported/`), registered after packs (last-writer-wins) and before aliases (so an alias can target one — see `jgengine-editor`). At runtime
|
|
29
|
+
A game's catalog is `buildCatalog(...)` over the generated pack index, singles, and aliases; `extras` is its durable escape hatch for assets that aren't in a pack. An editor asset import into a **promoted** game project writes into that `extras` array in `src/game/assets.ts` (bytes land in `public/<basePath>/imported/`), registered after packs (last-writer-wins) and before aliases (so an alias can target one — see `jgengine-editor`). At runtime a model extra resolves to its URL and authored `dims`, `space`, `clips` and `collisionMesh`; the `label` is human-facing only and never enters the catalog.
|
|
30
|
+
|
|
31
|
+
For game-owned media, validate `AssetImportSpec` from untrusted input and classify complete bytes with `classifyAssetFile` before choosing a loader. Preserve relative paths, custom roles and JSON metadata; use the [custom import recipe](references/custom-imports.md) for models, textures, sprites, materials, audio, fonts and HDRI. Classification is a format check, not an image/audio/font decoder.
|
|
28
32
|
|
|
29
33
|
At load time the shell classifies a model fetch before parsing via `classifyAssetResponse` (`@jgengine/core/scene/assetDiagnostics`), so a missing file, a dev-server HTML fallback, corrupt bytes, or a non-model format surface as an actionable diagnostic naming the URL — not an opaque GLTF parse error.
|
|
30
34
|
|
|
31
35
|
Reindex measures every GLB's `dims`; assets listed in `COLLISION_MESH_ASSET_IDS` (`collisionMeshAssets.ts`) additionally ship a compact quantized triangle mesh (`collisionMesh` on the index entry) that collider auto-fit raycasts instead of the fitted box — opt in only concave models whose box lies (archways, rings, frames), because each entry adds real index bytes and per-ray BVH cost. Reindex also records every GLB's animation `clips` (names read from the JSON chunk via `readGlbClips`), which flow through `buildCatalog` onto the resolved `ModelAssetRef` — the editor's browser badges rigged assets from it.
|
|
32
36
|
|
|
37
|
+
## Offline asset budgets
|
|
38
|
+
|
|
39
|
+
Run `assets budget <file|directory> --max-bytes <n> --max-triangles <n> --max-texture-dimension <n> --json` on the game's own GLBs before wiring imports. The directory can contain custom art, editor imports, or provisioned packs; it need not be a declared source. Limits belong to the game and apply per model; omit them to inspect. A failing report names each file and exceeded limit, and exits non-zero for CI. Missing GLBs, unreadable geometry/images, remote resources, or required geometry compression fail inspection instead of appearing as zero cost.
|
|
40
|
+
|
|
41
|
+
`readGlbMetrics` measures stored mesh primitives once, not scene instances or GPU memory. PNG, JPEG, WebP, and KTX2 dimensions come from image headers. Model bytes include the GLB and unique external resource URIs; local resources must stay inside the scanned directory. Reindex records successful inspection under `IndexEntry.metrics`; old entries remain valid, so gate the actual served bytes rather than assuming every index entry has measurements. This reports cost and never changes art, encodes compression, or generates LODs.
|
|
42
|
+
|
|
43
|
+
## Editor-authored static prefab exports
|
|
44
|
+
|
|
45
|
+
Keep composition parts and visible placements in `editor.scene.json`. Add `staticBake` settings to the editable prefab through editor commands, then call `bakeStaticPrefab` in Node/Bun through `@jgengine/assets/staticPrefabBake`. Pin every original GLB by catalog id, absolute read path, byte count and SHA-256. Pin external textures by their exact source URI and full runtime URL; basename matching loses ownership when different art uses the same filename. Paths are only I/O inputs; output reports contain portable hashes and logical ids.
|
|
46
|
+
|
|
47
|
+
The exporter retains source geometry, PBR surfaces, UVs and image URLs, applies each prop's local position, radian yaw and `meta.verticalOffset`, and combines static parts by source material. It rejects animations, skins, morph targets, interactive markers, unsupported transforms and non-model fragment content. Keep such content outside a static artifact. Material overrides also remain outside this bake; an authored assignment must not silently disappear into the source surface.
|
|
48
|
+
|
|
49
|
+
Register the output GLB with its returned `dims`, `space`, `anchor: "origin"` and `collisionMesh`. Origin anchoring preserves the prefab's frame; fitted centering or target-height normalization changes authored placement. Omitted `collisionBoxes` produce a conservative closed exterior; author explicit solid boxes and clearance boxes to preserve openings. Export fails when a clearance overlaps a movement solid. Reports include source-fragment and bake-settings hashes, GLB bytes, total GLB plus unique external-image bytes (`byteLength`), triangles, material submissions, bounds and verified source pins. Repeated export of the same authored data and pinned bytes must match.
|
|
50
|
+
|
|
51
|
+
After package publication and the shared consumer upgrade, delete the equivalent game-local exporter and runtime composition arrays or rendering glue. Keep each game's original catalog selection, credits and art; a prefab export is not a game template.
|
|
52
|
+
|
|
33
53
|
## Rigged assets animate by default
|
|
34
54
|
|
|
35
55
|
A model resolved from a catalog string id is stamped `animation: "auto"`: the shell derives speed-driven `idle`/`walk`/`run` states plus `hit`/`death`/`attack` one-shots from the loaded GLB's own clip names via semantic clip roles (`@jgengine/core/game/clipRoles` — `classifyClip`, `defaultAnimationForClips`, exported `DEFAULT_CLIP_ROLE_TABLE` covering KayKit/Quaternius/Mixamo naming). No game-side clip strings needed; a clipless model is unaffected. An explicit `ModelConfig.animation`/`style.animation` always wins, and `animation: "none"` opts a placement back to the bind pose. Games rendering cloned scenes themselves get the same driver from `@jgengine/shell/render/useModelAnimation` instead of hand-rolling an `AnimationMixer`.
|
|
36
56
|
|
|
57
|
+
Material sources declare the map roles in their pinned archive through `AssetSource.materialMaps`; `pull` checks those declarations before writing. `buildMaterialCatalog` omits absent `ao`, `roughness`, and `ktx2` URLs. Pass the returned maps directly to model, building, or terrain seams, or explicitly supply a game-owned map. Do not construct optional map filenames or fill every material with synthetic AO. Check the actual archive when changing availability; ambientCG API map metadata covers the catalog, while byte verification covers the downloaded variants.
|
|
58
|
+
|
|
37
59
|
## Source rules
|
|
38
60
|
|
|
39
61
|
- Never use or reference Kenney.nl assets.
|
|
@@ -46,4 +68,3 @@ A model resolved from a catalog string id is stamped `animation: "auto"`: the sh
|
|
|
46
68
|
- Fix wrong scale/facing/pivot upstream in catalog metadata, never with per-game corrective transforms.
|
|
47
69
|
- Asset ids and metadata are stable data contracts; filenames and URLs are implementation details.
|
|
48
70
|
- Missing attribution is a release blocker even when the code works.
|
|
49
|
-
|
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
- `AssetAlias` (interface): interface AssetAlias { key: string; target: string } — ⚠ undocumented · used by `aliases`: Semantic keys → live catalog ids.
|
|
8
8
|
- `AssetDownload` (type): type AssetDownload = PinnedDownload | ScrapeDownload — ⚠ undocumented
|
|
9
9
|
- `AssetImportKind` (type): type AssetImportKind = "model" | "texture" | "material" | "sprite" | "spriteSheet" | "audio" | "font" | "hdri" — Supported logical kinds for user-supplied assets.
|
|
10
|
-
- `AssetImportSpec` (interface): interface AssetImportSpec — A
|
|
10
|
+
- `AssetImportSpec` (interface): interface AssetImportSpec — A game-owned import description; paths are relative POSIX paths, roles are authored labels.
|
|
11
11
|
- `AssetKind` (type): type AssetKind = "model" | "pack" | "material" | "component" | "icon" | "sprite" | "spritePack" — ⚠ undocumented
|
|
12
12
|
- `AssetMatch` (type): type AssetMatch = | { kind: "model"; id: string; source: string; file?: string; via: "index" | "alias" | "single" } | { kind: "pack"; source: string; title: string; categories: readonly string[] } | { kind: "material"; id: string; title: string; categories: readonly string[] } | { kind: "component";… — ⚠ undocumented · used by `findAssets`: The ranked matches for a query — models, packs, HUD components, and icons in one list.
|
|
13
13
|
- `AssetProvenance` (interface): interface AssetProvenance — The resolved ownership of one logical asset id — the provisioning contract for that id.
|
|
14
14
|
- `AssetProvenanceKind` (type): type AssetProvenanceKind = "committed" | "provisioned" | "dangling" — How an asset id's bytes reach a clean checkout: - `committed` — resolves to a self-hosted / remote URL carried in the shipped index (a {@link SingleAsset}); no pull step, available immediately. - `provisioned` — a pack {@link IndexEntry}; the id is declared but its GLB is fetched on demand by `assets pull <source>` into the consumer's served dir. - `dangling` — nothing in the index, singles, or aliases owns the id, so no provisioning step exists and it can never resolve on a clean clone.
|
|
15
15
|
- `AssetProvider` (type): type AssetProvider = | "quaternius" | "kaykit" | "polypizza" | "itch" | "ambientcg" | "gameicons" | "custom" — ⚠ undocumented
|
|
16
16
|
- `AssetReference` (interface): interface AssetReference — A logical asset id referenced by some consumer (a game, scene, or config), for validation.
|
|
17
|
-
- `AssetSource` (interface): interface AssetSource { id: string; kind?: AssetSourceKind; provider: AssetProvider; title: string; license: string; author: string; categories: readonly string[]; download: AssetDownload; homepage?: string;
|
|
17
|
+
- `AssetSource` (interface): interface AssetSource { id: string; kind?: AssetSourceKind; provider: AssetProvider; title: string; license: string; author: string; categories: readonly string[]; download: AssetDownload; homepage?: string; materialMaps?: readonly MaterialMapRole[]; mirror?: st… — ⚠ undocumented · used by `ambientcgSources`: Every ambientCG material source, generated per family (`ambientcg-grass001` … ).
|
|
18
18
|
- `AssetSourceKind` (type): type AssetSourceKind = "model" | "material" | "sprite" — What a source's archive contains: GLB models (default), one PBR material's texture maps, or a pack of individual 2D sprite/icon files (SVG/PNG).
|
|
19
19
|
- `AssetSpace` (interface): interface AssetSpace — Catalog-level asset-space metadata: how a model is authored relative to the engine, owned by the catalog entry rather than re-derived per game. Every field is optional so an unmeasured asset stays valid; {@link resolveFacingRotationY}/{@link assetUnitScale}/{@link resolveAnchorOffset} supply the documented defaults.
|
|
20
20
|
- `BuildCatalogOptions` (interface): interface BuildCatalogOptions { basePath?: string; sources?: readonly string[]; includeAliases?: boolean; includeSingles?: boolean; extras?: readonly CatalogExtra[] } — ⚠ undocumented · used by `buildCatalog`: Builds a game's asset catalog from the generated CC0 pack index plus singles, extras, and aliases.
|
|
@@ -24,12 +24,14 @@
|
|
|
24
24
|
- `ExtractedMaterialMap` (interface): interface ExtractedMaterialMap — One normalized map pulled out of a material archive by `extractMaterialMaps`.
|
|
25
25
|
- `ExtractedSpriteFile` (interface): interface ExtractedSpriteFile — One SVG/PNG file pulled out of a sprite/icon-pack archive by `extractSpriteFiles`.
|
|
26
26
|
- `FindOptions` (interface): interface FindOptions { kind?: AssetKind; limit?: number } — ⚠ undocumented · used by `findAssets`: The ranked matches for a query — models, packs, HUD components, and icons in one list.
|
|
27
|
-
- `
|
|
28
|
-
- `
|
|
27
|
+
- `GlbMetrics` (interface): interface GlbMetrics — Stored geometry and image inventory; triangles count mesh primitives once, regardless of scene instances.
|
|
28
|
+
- `GlbTextureMetrics` (interface): interface GlbTextureMetrics — Dimensions and encoded bytes for one glTF image, including images referenced by texture extensions.
|
|
29
|
+
- `ImportSpecValidation` (type): type ImportSpecValidation = { ok: true; entry: AssetImportSpec } | { ok: false; reason: string } — Result of validating an import description; a successful entry is an independent JSON snapshot.
|
|
30
|
+
- `IndexEntry` (interface): interface IndexEntry — A source-owned model or sprite id, with optional offline model measurements.
|
|
29
31
|
- `MATERIAL_MAP_FILES` (const): const MATERIAL_MAP_FILES: { readonly color: "color.jpg"; readonly normal: "normal.jpg"; readonly roughness: "roughness.jpg"; readonly ao: "ao.jpg"; readonly displacement: "displacement.jpg"; readonly ktx2: "material.ktx2"; } — Normalized filenames a pulled material directory contains, keyed by map role.
|
|
30
32
|
- `MaterialCatalog` (interface): interface MaterialCatalog — Resolves material ids and `material/…` aliases to `MaterialRef`s.
|
|
31
33
|
- `MaterialMapRole` (type): type MaterialMapRole = keyof typeof MATERIAL_MAP_FILES — One PBR map's role within a material, including an optional compressed KTX2 asset.
|
|
32
|
-
- `MaterialMaps` (interface): interface MaterialMaps — URLs of one material's PBR maps; `ao`/`
|
|
34
|
+
- `MaterialMaps` (interface): interface MaterialMaps — URLs of one material's PBR maps; `ao`/`roughness`/`ktx2` appear only when declared by its source.
|
|
33
35
|
- `MaterialRef` (interface): interface MaterialRef — A resolved material: identity, attribution, and its normalized map URLs.
|
|
34
36
|
- `ModelDims` (interface): interface ModelDims — Measured horizontal footprint, footprint center, and lowest Y of a model in model space.
|
|
35
37
|
- `ModelSnippetOptions` (interface): interface ModelSnippetOptions { basePath?: string; seam?: "objectModels" | "entityModels" } — ⚠ undocumented · used by `modelWiringSnippet`: Copy-paste wiring for a pulled GLB id: resolve through the catalog, drop into a model seam.
|
|
@@ -56,7 +58,7 @@
|
|
|
56
58
|
- `buildCatalog` (function): function buildCatalog(options: BuildCatalogOptions = {}): AssetCatalog — Builds a game's asset catalog from the generated CC0 pack index plus singles, extras, and aliases. Registration order is packs → singles → {@link BuildCatalogOptions.extras | extras} → aliases: packs and singles come first, extras override them last-writer-wins, and aliases resolve last so they can target an extra. See {@link BuildCatalogOptions} for filtering and opt-outs.
|
|
57
59
|
- `buildMaterialCatalog` (function): function buildMaterialCatalog(options: BuildMaterialCatalogOptions = {}): MaterialCatalog — A resolvable catalog over every `kind: "material"` source. Ids are source ids (`ambientcg-grass001`) plus the `material/…` aliases; every resolve returns the normalized map URLs under `basePath`, matching what `assets pull` writes into `<dir>/materials/<id>/`.
|
|
58
60
|
- `buildSpriteCatalog` (function): function buildSpriteCatalog(options: BuildSpriteCatalogOptions = {}): AssetCatalog — Resolves individual pulled sprite/icon ids (e.g. `gameicons-icons/sword`) to `{ url }`.
|
|
59
|
-
- `classifyAssetFile` (function): function classifyAssetFile(bytes: Uint8Array,
|
|
61
|
+
- `classifyAssetFile` (function): function classifyAssetFile(bytes: Uint8Array, _filename: string): AssetImportKind | null — Classify supported container headers from complete file bytes; filenames never override bytes. Recognizes GLB/glTF, PNG/JPEG/KTX2, Ogg/WAV/MP3, TTF/OTF/WOFF/WOFF2, HDR/EXR and JSON sprite sheets. This is format detection, not decoder validation. Images classify as texture; authors choose sprite/material in the spec.
|
|
60
62
|
- `componentInstallUrl` (function): function componentInstallUrl(name: string): string — The `shadcn add` URL for a HUD component, e.g. `https://jgengine.com/r/vital-bar.json`.
|
|
61
63
|
- `componentWiringSnippet` (function): function componentWiringSnippet(component: RegistryComponent): string — Copy-paste wiring for a HUD component: the `shadcn add` command plus import + usage.
|
|
62
64
|
- `createStarterCatalog` (function): function createStarterCatalog(options: BuildCatalogOptions = {}): AssetCatalog<ModelAssetRef> — Catalog restricted to the curated starter packs (people/props/nature/urban). Prefer this for scaffolds and probes so `asset:person_casual` etc. resolve without pulling the whole library. Full index: {@link buildCatalog}.
|
|
@@ -82,6 +84,7 @@
|
|
|
82
84
|
- `quaterniusSources` (const): const quaterniusSources: readonly AssetSource[] — ⚠ undocumented
|
|
83
85
|
- `rankAssets` (function): function rankAssets(query: string, options: FindOptions = {}): RankedMatch[] — Rank every catalog entry — models, packs, HUD components, icons — against one query.
|
|
84
86
|
- `readGlbDims` (function): function readGlbDims(bytes: Uint8Array): ModelDims | null — ⚠ undocumented
|
|
87
|
+
- `readGlbMetrics` (function): function readGlbMetrics(bytes: Uint8Array, readResource?: (uri: string) => Uint8Array): GlbMetrics — Inspect GLB v2 geometry accessors and image headers offline. Throws on unreadable resources, malformed geometry, or required geometry compression; never silently reports missing data as zero. External resources are supplied by the caller; this function never fetches or decompresses bytes.
|
|
85
88
|
- `registryCatalog` (const): const registryCatalog: RegistryCatalog — ⚠ undocumented
|
|
86
89
|
- `reindexSprites` (function): function reindexSprites(spritesDir: string, outDir: string): ReindexSpritesResult — Same shape as `reindex` (models) but walks SVG/PNG files and skips dims measurement — sprites have no footprint.
|
|
87
90
|
- `resolveProvenance` (function): function resolveProvenance(id: string, options: ResolveProvenanceOptions = {}): AssetProvenance — Resolve one logical asset id (a pack id, a single id, or an alias key) to its {@link AssetProvenance}. Aliases are followed one hop to their target. An id that matches no declared owner is `dangling` — the signal a clean-clone gate turns into a hard failure, because no provisioning step can ever satisfy it.
|
|
@@ -91,13 +94,22 @@
|
|
|
91
94
|
- `spriteSources` (const): const spriteSources: readonly AssetSource[] — Every `kind: "sprite"` source — a pack of individual 2D icon/UI files, resolvable via `buildSpriteCatalog`.
|
|
92
95
|
- `spriteWiringSnippet` (function): function spriteWiringSnippet(id: string, basePath = "/sprites"): string — Copy-paste wiring for a pulled sprite/icon-pack file: resolve through the sprite catalog.
|
|
93
96
|
- `validateAssetReferences` (function): function validateAssetReferences(references: readonly AssetReference[], options: ValidateAssetReferencesOptions = {}): ValidateAssetReferencesResult — Validate that every {@link AssetReference} resolves against the declared provisioning contract — not by grepping source text, but by resolving each logical id to its committed / provisioned / dangling owner. A `dangling` reference fails with the referencing consumer, the logical id, the (null) resolved path, and the missing provisioning step; a `provisioned` reference passes and contributes its `assets pull <source>` step to `provisioning` (unless `present` is supplied and reports the bytes absent).
|
|
94
|
-
- `validateImportSpec` (function): function validateImportSpec(spec:
|
|
97
|
+
- `validateImportSpec` (function): function validateImportSpec(spec: unknown): ImportSpecValidation — Validate untrusted import descriptions without filesystem access or path rewriting. Requires unique relative files, printable non-empty roles and plain JSON metadata (maximum depth 64).
|
|
95
98
|
- `verifyManifest` (function): function verifyManifest(): VerifyResult — ⚠ undocumented
|
|
96
99
|
|
|
97
100
|
## @jgengine/assets/aliases
|
|
98
101
|
|
|
99
102
|
- `aliases` (const): const aliases: readonly AssetAlias[] — Semantic keys → live catalog ids. Prefer these in games so re-homes only touch this table. Never point at kenney-*. Curated starter theme ids (`asset:person_casual`, `nature_tree`, …) come from {@link starterAliases}.
|
|
100
103
|
|
|
104
|
+
## @jgengine/assets/assetBudget
|
|
105
|
+
|
|
106
|
+
- `AssetBudget` (interface): interface AssetBudget — Per-model limits chosen by the game; equality passes and omitted limits only report.
|
|
107
|
+
- `AssetBudgetEntry` (interface): interface AssetBudgetEntry — One model's measured inventory or actionable inspection/budget errors.
|
|
108
|
+
- `AssetBudgetReport` (interface): interface AssetBudgetReport — Deterministic offline report; an empty directory or any unreadable model fails.
|
|
109
|
+
- `checkAssetBudget` (function): function checkAssetBudget(metrics: GlbMetrics, budget: AssetBudget): string[] — Check measured per-model bytes, stored triangles, and maximum image dimension against caller-owned limits.
|
|
110
|
+
- `createAssetBudgetReport` (function): function createAssetBudgetReport(target: string, budget: AssetBudget = {}): AssetBudgetReport — Scan a file or directory recursively for GLBs without changing their bytes or the catalog. Paths are relative to the scanned directory, sorted lexically; unknown/custom asset folders work equally.
|
|
111
|
+
- `readGlbFileMetrics` (function): function readGlbFileMetrics(file: string, resourceRoot = dirname(file)): GlbMetrics — Read a GLB plus local resources under `resourceRoot`; remote URLs and symlink escapes fail without fetching.
|
|
112
|
+
|
|
101
113
|
## @jgengine/assets/catalogs/build
|
|
102
114
|
|
|
103
115
|
- `BuildCatalogOptions` (interface): interface BuildCatalogOptions { basePath?: string; sources?: readonly string[]; includeAliases?: boolean; includeSingles?: boolean; extras?: readonly CatalogExtra[] } — ⚠ undocumented · used by `buildCatalog`: Builds a game's asset catalog from the generated CC0 pack index plus singles, extras, and aliases.
|
|
@@ -175,18 +187,35 @@
|
|
|
175
187
|
- `generatedSpriteBySource` (const): const generatedSpriteBySource: Record<string, IndexEntry[]> — Pulled sprite/icon entries grouped by source id.
|
|
176
188
|
- `generatedSpriteIndex` (const): const generatedSpriteIndex: IndexEntry[] — Every pulled sprite/icon entry across all sources, flattened.
|
|
177
189
|
|
|
190
|
+
## @jgengine/assets/glbMetrics
|
|
191
|
+
|
|
192
|
+
- `GlbMetrics` (interface): interface GlbMetrics — Stored geometry and image inventory; triangles count mesh primitives once, regardless of scene instances.
|
|
193
|
+
- `GlbTextureMetrics` (interface): interface GlbTextureMetrics — Dimensions and encoded bytes for one glTF image, including images referenced by texture extensions.
|
|
194
|
+
- `readGlbMetrics` (function): function readGlbMetrics(bytes: Uint8Array, readResource?: (uri: string) => Uint8Array): GlbMetrics — Inspect GLB v2 geometry accessors and image headers offline. Throws on unreadable resources, malformed geometry, or required geometry compression; never silently reports missing data as zero. External resources are supplied by the caller; this function never fetches or decompresses bytes.
|
|
195
|
+
|
|
196
|
+
## @jgengine/assets/gltfMaterials
|
|
197
|
+
|
|
198
|
+
- `GLTF_MATERIAL_EXTENSIONS_R182` (const): const GLTF_MATERIAL_EXTENSIONS_R182: readonly string[] — Native material/texture extensions implemented by Three.js GLTFLoader r182. Decoders are still required.
|
|
199
|
+
- `GltfImportedMaterial` (interface): interface GltfImportedMaterial — One imported material with the native definition retained as an independent JSON snapshot.
|
|
200
|
+
- `GltfMaterialDiagnostic` (interface): interface GltfMaterialDiagnostic — Actionable fidelity warning or error; this inspector never changes imported surfaces.
|
|
201
|
+
- `GltfMaterialInspection` (interface): interface GltfMaterialInspection — Native material inventory, primitive selectors, attribution, and renderer compatibility diagnostics.
|
|
202
|
+
- `GltfMaterialSlot` (interface): interface GltfMaterialSlot — A primitive slot retains mesh and material indices even when display names collide.
|
|
203
|
+
- `GltfMaterialTexture` (interface): interface GltfMaterialTexture — A native glTF texture use; embedded images retain their source index instead of an invented URL.
|
|
204
|
+
- `inspectGlbMaterials` (function): function inspectGlbMaterials(bytes: Uint8Array, assetId: string): GltfMaterialInspection — Inspect the JSON chunk of complete GLB v2 bytes, including models with compressed geometry. This measures material metadata only; it never decodes geometry or resolves image URLs.
|
|
205
|
+
- `inspectGltfMaterials` (function): function inspectGltfMaterials(json: GLTF.IGLTF, assetId: string): GltfMaterialInspection — Inventory validated glTF JSON without flattening slots, decoding compressed geometry, or changing materials. IDs use the supplied model namespace plus source indices, and remain stable while its pinned bytes remain stable.
|
|
206
|
+
|
|
178
207
|
## @jgengine/assets/importSpec
|
|
179
208
|
|
|
180
209
|
- `AssetImportKind` (type): type AssetImportKind = "model" | "texture" | "material" | "sprite" | "spriteSheet" | "audio" | "font" | "hdri" — Supported logical kinds for user-supplied assets.
|
|
181
|
-
- `AssetImportSpec` (interface): interface AssetImportSpec — A
|
|
182
|
-
- `ImportSpecValidation` (type): type ImportSpecValidation = { ok: true; entry: AssetImportSpec } | { ok: false; reason: string } — Result of validating an import description.
|
|
183
|
-
- `classifyAssetFile` (function): function classifyAssetFile(bytes: Uint8Array,
|
|
184
|
-
- `validateImportSpec` (function): function validateImportSpec(spec:
|
|
210
|
+
- `AssetImportSpec` (interface): interface AssetImportSpec — A game-owned import description; paths are relative POSIX paths, roles are authored labels.
|
|
211
|
+
- `ImportSpecValidation` (type): type ImportSpecValidation = { ok: true; entry: AssetImportSpec } | { ok: false; reason: string } — Result of validating an import description; a successful entry is an independent JSON snapshot.
|
|
212
|
+
- `classifyAssetFile` (function): function classifyAssetFile(bytes: Uint8Array, _filename: string): AssetImportKind | null — Classify supported container headers from complete file bytes; filenames never override bytes. Recognizes GLB/glTF, PNG/JPEG/KTX2, Ogg/WAV/MP3, TTF/OTF/WOFF/WOFF2, HDR/EXR and JSON sprite sheets. This is format detection, not decoder validation. Images classify as texture; authors choose sprite/material in the spec.
|
|
213
|
+
- `validateImportSpec` (function): function validateImportSpec(spec: unknown): ImportSpecValidation — Validate untrusted import descriptions without filesystem access or path rewriting. Requires unique relative files, printable non-empty roles and plain JSON metadata (maximum depth 64).
|
|
185
214
|
|
|
186
215
|
## @jgengine/assets/indexGen
|
|
187
216
|
|
|
188
217
|
- `ReindexResult` (interface): interface ReindexResult { perSource: {source: string; count: number}[]; total: number } — ⚠ undocumented
|
|
189
|
-
- `entryForFile` (function): function entryForFile(source: AssetSource, file: string, dims?: ModelDims, collisionMesh?: CollisionMeshData, clips?: readonly string[]): IndexEntry —
|
|
218
|
+
- `entryForFile` (function): function entryForFile(source: AssetSource, file: string, dims?: ModelDims, collisionMesh?: CollisionMeshData, clips?: readonly string[], metrics?: GlbMetrics): IndexEntry — Build a source-owned model entry, preserving optional measured bounds, collision, clips, and inventory.
|
|
190
219
|
- `indexSourceDir` (function): function indexSourceDir(source: AssetSource, dir: string): IndexEntry[] — ⚠ undocumented
|
|
191
220
|
- `keyFromFile` (function): function keyFromFile(file: string): string — ⚠ undocumented
|
|
192
221
|
- `reindex` (function): function reindex(modelsDir: string, outDir: string): ReindexResult — ⚠ undocumented
|
|
@@ -196,11 +225,11 @@
|
|
|
196
225
|
- `AssetAlias` (interface): interface AssetAlias { key: string; target: string } — ⚠ undocumented · used by `aliases` (@jgengine/assets): Semantic keys → live catalog ids.
|
|
197
226
|
- `AssetDownload` (type): type AssetDownload = PinnedDownload | ScrapeDownload — ⚠ undocumented
|
|
198
227
|
- `AssetProvider` (type): type AssetProvider = | "quaternius" | "kaykit" | "polypizza" | "itch" | "ambientcg" | "gameicons" | "custom" — ⚠ undocumented
|
|
199
|
-
- `AssetSource` (interface): interface AssetSource { id: string; kind?: AssetSourceKind; provider: AssetProvider; title: string; license: string; author: string; categories: readonly string[]; download: AssetDownload; homepage?: string;
|
|
228
|
+
- `AssetSource` (interface): interface AssetSource { id: string; kind?: AssetSourceKind; provider: AssetProvider; title: string; license: string; author: string; categories: readonly string[]; download: AssetDownload; homepage?: string; materialMaps?: readonly MaterialMapRole[]; mirror?: st… — ⚠ undocumented · used by `ambientcgSources` (@jgengine/assets): Every ambientCG material source, generated per family (`ambientcg-grass001` … ).
|
|
200
229
|
- `AssetSourceKind` (type): type AssetSourceKind = "model" | "material" | "sprite" — What a source's archive contains: GLB models (default), one PBR material's texture maps, or a pack of individual 2D sprite/icon files (SVG/PNG).
|
|
201
230
|
- `AssetSpace` (interface): interface AssetSpace — Catalog-level asset-space metadata: how a model is authored relative to the engine, owned by the catalog entry rather than re-derived per game. Every field is optional so an unmeasured asset stays valid; {@link resolveFacingRotationY}/{@link assetUnitScale}/{@link resolveAnchorOffset} supply the documented defaults.
|
|
202
231
|
- `CollisionMeshData` (interface): interface CollisionMeshData — Compact, serializable triangle collision mesh measured at asset reindex — the renderer-free source of mesh-accurate hitboxes. Positions are welded onto a 16-bit grid spanning `min`..`max` (model space) and stored base64-encoded, so an opted-in catalog asset ships its collision triangles inside the generated index without the runtime ever touching the rendered scene graph.
|
|
203
|
-
- `IndexEntry` (interface): interface IndexEntry
|
|
232
|
+
- `IndexEntry` (interface): interface IndexEntry — A source-owned model or sprite id, with optional offline model measurements.
|
|
204
233
|
- `ModelDims` (interface): interface ModelDims — Measured horizontal footprint, footprint center, and lowest Y of a model in model space.
|
|
205
234
|
- `PinnedDownload` (interface): interface PinnedDownload { url: string; sha256?: string } — ⚠ undocumented
|
|
206
235
|
- `ScrapeDownload` (interface): interface ScrapeDownload { scrape: string } — ⚠ undocumented
|
|
@@ -214,7 +243,7 @@
|
|
|
214
243
|
- `MATERIAL_MAP_FILES` (const): const MATERIAL_MAP_FILES: { readonly color: "color.jpg"; readonly normal: "normal.jpg"; readonly roughness: "roughness.jpg"; readonly ao: "ao.jpg"; readonly displacement: "displacement.jpg"; readonly ktx2: "material.ktx2"; } — Normalized filenames a pulled material directory contains, keyed by map role.
|
|
215
244
|
- `MaterialCatalog` (interface): interface MaterialCatalog — Resolves material ids and `material/…` aliases to `MaterialRef`s.
|
|
216
245
|
- `MaterialMapRole` (type): type MaterialMapRole = keyof typeof MATERIAL_MAP_FILES — One PBR map's role within a material, including an optional compressed KTX2 asset.
|
|
217
|
-
- `MaterialMaps` (interface): interface MaterialMaps — URLs of one material's PBR maps; `ao`/`
|
|
246
|
+
- `MaterialMaps` (interface): interface MaterialMaps — URLs of one material's PBR maps; `ao`/`roughness`/`ktx2` appear only when declared by its source.
|
|
218
247
|
- `MaterialRef` (interface): interface MaterialRef — A resolved material: identity, attribution, and its normalized map URLs.
|
|
219
248
|
- `buildMaterialCatalog` (function): function buildMaterialCatalog(options: BuildMaterialCatalogOptions = {}): MaterialCatalog — A resolvable catalog over every `kind: "material"` source. Ids are source ids (`ambientcg-grass001`) plus the `material/…` aliases; every resolve returns the normalized map URLs under `basePath`, matching what `assets pull` writes into `<dir>/materials/<id>/`.
|
|
220
249
|
- `extractMaterialMaps` (function): function extractMaterialMaps(archive: Uint8Array): ExtractedMaterialMap[] — Pulls the recognized PBR maps out of a material archive (ambientCG's flat `<Asset>_<Res>_<Map>.jpg` layout) and normalizes their names so resolved URLs never depend on the provider's naming or the pulled resolution.
|
|
@@ -298,9 +327,55 @@
|
|
|
298
327
|
- `keyFromSpriteFile` (function): function keyFromSpriteFile(file: string): string — Strips the `.svg`/`.png` extension off a pulled sprite/icon filename to get its id suffix.
|
|
299
328
|
- `reindexSprites` (function): function reindexSprites(spritesDir: string, outDir: string): ReindexSpritesResult — Same shape as `reindex` (models) but walks SVG/PNG files and skips dims measurement — sprites have no footprint.
|
|
300
329
|
|
|
330
|
+
## @jgengine/assets/staticPrefabBake
|
|
331
|
+
|
|
332
|
+
- `StaticPrefabBakeReport` (interface): interface StaticPrefabBakeReport — Deterministic inventory and provenance for an editor-authored static artifact.
|
|
333
|
+
- `StaticPrefabBakeResult` (interface): interface StaticPrefabBakeResult — GLB bytes and catalog-ready metadata; origin anchoring preserves the editable fragment's local frame.
|
|
334
|
+
- `StaticPrefabSource` (interface): interface StaticPrefabSource — Original static model bytes; paths are absolute and every external image must have a pin.
|
|
335
|
+
- `StaticPrefabTextureSource` (interface): interface StaticPrefabTextureSource — A verified external source image and its complete runtime URL. URI matches the source GLB exactly.
|
|
336
|
+
- `bakeStaticPrefab` (function): function bakeStaticPrefab(prefab: EditorPrefab, sources: readonly StaticPrefabSource[]): Promise<StaticPrefabBakeResult> — Bake pinned static source art in an editor prefab's local frame. Node-only; never mutates authored data.
|
|
337
|
+
|
|
301
338
|
## @jgengine/assets/verify
|
|
302
339
|
|
|
303
340
|
- `VerifyInput` (interface): interface VerifyInput { sources: readonly AssetSource[]; singles: readonly SingleAsset[]; aliases: readonly AssetAlias[]; index: readonly IndexEntry[]; materialAliases?: readonly AssetAlias[] } — ⚠ undocumented
|
|
304
341
|
- `VerifyResult` (interface): interface VerifyResult { ok: boolean; errors: string[] } — ⚠ undocumented
|
|
305
342
|
- `verifyData` (function): function verifyData(input: VerifyInput): VerifyResult — ⚠ undocumented
|
|
306
343
|
- `verifyManifest` (function): function verifyManifest(): VerifyResult — ⚠ undocumented
|
|
344
|
+
|
|
345
|
+
## @jgengine/core/material/hairCards
|
|
346
|
+
|
|
347
|
+
- `HAIR_CARD_STRAND_ROTATION` (const): const HAIR_CARD_STRAND_ROTATION: number — Tangents follow card width (UV U); strand length follows UV V. Angles are radians.
|
|
348
|
+
- `HairCardAuthoring` (interface): interface HairCardAuthoring — Serializable geometry authoring, independent of materials, grooming physics and collisions.
|
|
349
|
+
- `HairCardGuide` (interface): interface HairCardGuide — An authored centreline, in model-local metres, with root-to-tip points.
|
|
350
|
+
- `HairCardMesh` (interface): interface HairCardMesh — Renderer-neutral indexed ribbons with an explicit tangent frame and guide ranges.
|
|
351
|
+
- `buildHairCards` (function): function buildHairCards(input: HairCardAuthoring): HairCardMesh — Build deterministic model-local ribbon geometry; guides remain separately editable source data.
|
|
352
|
+
- `validateHairCardAuthoring` (function): function validateHairCardAuthoring(value: unknown): MaterialDiagnostic[] — Validate finite guides, tangent frames and bounded generation; crossing/collision is not solved.
|
|
353
|
+
|
|
354
|
+
## @jgengine/core/material/materialAsset
|
|
355
|
+
|
|
356
|
+
- `FabricAppearance` (interface): interface FabricAppearance — Procedural cloth surface response; this does not create or bend cloth geometry.
|
|
357
|
+
- `HairAppearance` (interface): interface HairAppearance — Anisotropic surface approximation for existing hair cards or strand meshes, without grooming.
|
|
358
|
+
- `MATERIAL_SURFACE_CAPABILITIES` (const): const MATERIAL_SURFACE_CAPABILITIES: Partial<Record<keyof MaterialSurfaceParameters, MaterialCapability>> — Feature declarations required by each sparse physical parameter.
|
|
359
|
+
- `MATERIAL_TEXTURE_CAPABILITIES` (const): const MATERIAL_TEXTURE_CAPABILITIES: Readonly<Partial<Record<MaterialTextureRole, MaterialCapability>>> — Feature declarations required by authored texture roles.
|
|
360
|
+
- `MATERIAL_TEXTURE_SEMANTICS` (const): const MATERIAL_TEXTURE_SEMANTICS: Readonly<Record<MaterialTextureRole, { colorSpace: "srgb" | "linear"; channel: MaterialTextureChannel }>> — Shader channel defaults; standalone alpha maps use green, base-color alpha stays in its color map.
|
|
361
|
+
- `MaterialAsset` (interface): interface MaterialAsset — Shared, versioned authoring data. IDs survive rename, save and export.
|
|
362
|
+
- `MaterialAssignment` (interface): interface MaterialAssignment — A reusable asset reference with an optional instance-only sparse edit.
|
|
363
|
+
- `MaterialAssignmentValidationOptions` (interface): interface MaterialAssignmentValidationOptions — Optional renderer limits; ordinary model assignment accepts every supported texture role.
|
|
364
|
+
- `MaterialCapability` (type): type MaterialCapability = "pbr" | "sheen" | "anisotropy" | "clearcoat" | "specular" | "transmission" | "volume" | "iridescence" | "alpha" — Renderer features an authored material explicitly requires.
|
|
365
|
+
- `MaterialDiagnostic` (interface): interface MaterialDiagnostic — An actionable authoring/import diagnostic.
|
|
366
|
+
- `MaterialFamily` (type): type MaterialFamily = "standard" | "fabric" | "hair" | "glass" | "metal" | "skin" | "stone" | "plastic" — Physical surface families; these describe appearance, never geometry or simulation.
|
|
367
|
+
- `MaterialProvenance` (interface): interface MaterialProvenance — Portable material or image authorship.
|
|
368
|
+
- `MaterialSelector` (interface): interface MaterialSelector — Names constrain mesh and imported material slot independently; all provided tests must match.
|
|
369
|
+
- `MaterialSurfaceParameters` (interface): interface MaterialSurfaceParameters — Sparse surface edits. Omitted values preserve the imported material. Angles are radians.
|
|
370
|
+
- `MaterialTemplate` (type): type MaterialTemplate = "wool" | "cotton" | "silk" | "brushed-metal" | "glass" | "coated-plastic" | "stone" | "hair-cards" — Editable engine-authored surface starting points, independent of any game's palette or assets.
|
|
371
|
+
- `MaterialTextureChannel` (type): type MaterialTextureChannel = "r" | "g" | "b" | "a" | "rgb" | "rgba" — Texture channels used by the pinned standard/physical shader path.
|
|
372
|
+
- `MaterialTextureMetadata` (interface): interface MaterialTextureMetadata — Serializable sampling and UV metadata; metres are descriptive, UV transforms drive rendering.
|
|
373
|
+
- `MaterialTextureRole` (type): type MaterialTextureRole = "color" | "normal" | "roughness" | "metalness" | "ao" | "emissive" | "alpha" | "height" | "sheenColor" | "sheenRoughness" | "anisotropy" | "clearcoat" | "clearcoatRoughness" | "clearcoatNormal" | "specularIntensity" | "specularColor" | "transmission" | "thickness" | "iride… — Supported texture semantics; packed channels follow glTF and Three's PBR shaders.
|
|
374
|
+
- `createMaterialTemplate` (function): function createMaterialTemplate(template: MaterialTemplate, id: string, name = template): MaterialAsset — Create fresh, serializable material data with provenance; templates create no textures or geometry.
|
|
375
|
+
- `matchesMaterialSelector` (function): function matchesMaterialSelector(selector: MaterialSelector, mesh: string, slot: string, slotIndex: number): boolean — Exact name/index selector matching shared by authoring and rendering.
|
|
376
|
+
- `materialCapabilitiesForAsset` (function): function materialCapabilitiesForAsset(asset: Pick<MaterialAsset, "surface" | "textures" | "fabric" | "hair">): MaterialCapability[] — Determine required shader features from surface fields, maps and appearance adapters without editing them.
|
|
377
|
+
- `materialCapabilitiesForSurface` (function): function materialCapabilitiesForSurface(surface: MaterialSurfaceParameters): MaterialCapability[] — Determine feature requirements from authored fields, including intentional zero values.
|
|
378
|
+
- `parseMaterialAssignments` (function): function parseMaterialAssignments(value: unknown): MaterialAssignment[] — Parse assignment JSON at editor/RPC boundaries. Invalid data fails with an actionable path.
|
|
379
|
+
- `validateMaterialAsset` (function): function validateMaterialAsset(value: unknown): MaterialDiagnostic[] — Validate material JSON and renderer prerequisites before saving or assigning it.
|
|
380
|
+
- `validateMaterialAssignments` (function): function validateMaterialAssignments(assignments: readonly MaterialAssignment[], assets: readonly MaterialAsset[], options: MaterialAssignmentValidationOptions = {}): MaterialDiagnostic[] — Validate references and selectors without accepting accidental whole-model assignment.
|
|
381
|
+
- `validateMaterialSurface` (function): function validateMaterialSurface(value: unknown, path = "surface"): MaterialDiagnostic[] — Validate sparse surface edits without mutating them or guessing unsupported fields.
|
|
@@ -4,6 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
Reach for these before hand-rolling. Each row is *the thing you need* → *the primitive that already does it*.
|
|
6
6
|
|
|
7
|
+
## asset-budgets — enforce game-owned per-model byte, triangle, and texture-dimension limits
|
|
8
|
+
|
|
9
|
+
- `checkAssetBudget` (function) · `import { checkAssetBudget } from "@jgengine/assets/assetBudget"`
|
|
10
|
+
- `createAssetBudgetReport` (function) · `import { createAssetBudgetReport } from "@jgengine/assets/assetBudget"`
|
|
11
|
+
- `readGlbFileMetrics` (function) · `import { readGlbFileMetrics } from "@jgengine/assets/assetBudget"`
|
|
12
|
+
- `readGlbMetrics` (function) · `import { readGlbMetrics } from "@jgengine/assets"`
|
|
13
|
+
|
|
14
|
+
## asset-byte-classification — identify custom asset formats from bytes instead of filename extensions
|
|
15
|
+
|
|
16
|
+
- `classifyAssetFile` (function) · `import { classifyAssetFile } from "@jgengine/assets"`
|
|
17
|
+
|
|
18
|
+
## asset-import-validation — validate game-owned multi-file asset descriptions before ingest
|
|
19
|
+
|
|
20
|
+
- `validateImportSpec` (function) · `import { validateImportSpec } from "@jgengine/assets"`
|
|
21
|
+
|
|
7
22
|
## asset-reference-integrity — validate asset references against the provisioning contract (dangling / committed / provisioned)
|
|
8
23
|
|
|
9
24
|
- `validateAssetReferences` (function) · `import { validateAssetReferences } from "@jgengine/assets"`
|
|
@@ -24,6 +39,28 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
24
39
|
|
|
25
40
|
- `creditsForSources` (function) · `import { creditsForSources } from "@jgengine/assets/credits"`
|
|
26
41
|
|
|
42
|
+
## gltf-material-inspection — inspect material slots and texture metadata directly from complete GLB bytes
|
|
43
|
+
|
|
44
|
+
- `inspectGlbMaterials` (function) · `import { inspectGlbMaterials } from "@jgengine/assets/gltfMaterials"`
|
|
45
|
+
- `inspectGltfMaterials` (function) · `import { inspectGltfMaterials } from "@jgengine/assets/gltfMaterials"`
|
|
46
|
+
|
|
47
|
+
## hair-card-geometry — validate authored ribbon guides and their vertex allocation ceiling
|
|
48
|
+
|
|
49
|
+
- `validateHairCardAuthoring` (function) · `import { validateHairCardAuthoring } from "@jgengine/core/material/hairCards"`
|
|
50
|
+
|
|
51
|
+
## material-feature-requirements — Declare material shader requirements when authors add maps or appearance adapters.
|
|
52
|
+
|
|
53
|
+
- `materialCapabilitiesForAsset` (function) · `import { materialCapabilitiesForAsset } from "@jgengine/core/material/materialAsset"`
|
|
54
|
+
|
|
55
|
+
## material-slot-selection — match named meshes and imported material slots independently
|
|
56
|
+
|
|
57
|
+
- `matchesMaterialSelector` (function) · `import { matchesMaterialSelector } from "@jgengine/core/material/materialAsset"`
|
|
58
|
+
- `validateMaterialAssignments` (function) · `import { validateMaterialAssignments } from "@jgengine/core/material/materialAsset"`
|
|
59
|
+
|
|
60
|
+
## material-surface-validation — diagnose unsupported or physically invalid sparse surface edits
|
|
61
|
+
|
|
62
|
+
- `validateMaterialSurface` (function) · `import { validateMaterialSurface } from "@jgengine/core/material/materialAsset"`
|
|
63
|
+
|
|
27
64
|
## sources-for-asset-ids — resolve the asset packs behind the ids a game actually ships
|
|
28
65
|
|
|
29
66
|
- `sourcesForAssetIds` (function) · `import { sourcesForAssetIds } from "@jgengine/assets/credits"`
|
|
@@ -35,3 +72,7 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
35
72
|
## starter-packs — themed CC0 model ids (people/props/nature/urban) ready for entityModels
|
|
36
73
|
|
|
37
74
|
- `StarterTheme` (type) · `import { StarterTheme } from "@jgengine/assets"`
|
|
75
|
+
|
|
76
|
+
## static-prefab-export — export editable prefab compositions with source materials and collision metadata
|
|
77
|
+
|
|
78
|
+
- `bakeStaticPrefab` (function) · `import { bakeStaticPrefab } from "@jgengine/assets/staticPrefabBake"`
|