@jgengine/shell 0.11.0 → 0.12.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 +26 -0
- package/dist/CombatPresentation.d.ts +5 -0
- package/dist/CombatPresentation.js +8 -0
- package/dist/GameHost.d.ts +25 -1
- package/dist/GameHost.js +60 -4
- package/dist/GamePlayer.d.ts +5 -0
- package/dist/GamePlayer.js +5 -0
- package/dist/GamePlayerShell.d.ts +5 -0
- package/dist/GamePlayerShell.js +48 -358
- package/dist/GameUiPreview.js +3 -0
- package/dist/Shell3dPresentation.d.ts +63 -0
- package/dist/Shell3dPresentation.js +302 -0
- package/dist/ShellChrome.d.ts +51 -0
- package/dist/ShellChrome.js +51 -0
- package/dist/ShellHudPresentation.d.ts +41 -0
- package/dist/ShellHudPresentation.js +22 -0
- package/dist/audio/audioEngine.d.ts +4 -0
- package/dist/audio/audioEngine.js +111 -26
- package/dist/audio/audioWire.d.ts +22 -4
- package/dist/audio/audioWire.js +46 -3
- package/dist/audio/loopParams.d.ts +20 -0
- package/dist/audio/loopParams.js +28 -0
- package/dist/camera/GameCameraRig.js +6 -1
- package/dist/camera/cameraRigs.d.ts +3 -1
- package/dist/camera/cameraRigs.js +21 -3
- package/dist/camera/rigMath.d.ts +20 -0
- package/dist/camera/rigMath.js +29 -0
- package/dist/defineGame.d.ts +15 -1
- package/dist/defineGame.js +26 -4
- package/dist/devtools/DevtoolsOverlay.d.ts +4 -4
- package/dist/devtools/DevtoolsOverlay.js +28 -12
- package/dist/devtools/agentBridge.js +4 -0
- package/dist/devtools/perfDiagnose.js +1 -1
- package/dist/diagnostics/RuntimeDiagnostics.d.ts +7 -0
- package/dist/diagnostics/RuntimeDiagnostics.js +23 -12
- package/dist/environment/EnvironmentScene.js +12 -3
- package/dist/environment/terrainGroundColor.d.ts +9 -0
- package/dist/environment/terrainGroundColor.js +22 -0
- package/dist/gameKit.d.ts +27 -0
- package/dist/gameKit.js +29 -0
- package/dist/map/MapMarkerBeacons.d.ts +3 -2
- package/dist/postfx/PostProcessing.d.ts +9 -1
- package/dist/postfx/PostProcessing.js +11 -4
- package/dist/presentationResolve.d.ts +35 -0
- package/dist/presentationResolve.js +51 -0
- package/dist/registry.d.ts +1 -0
- package/dist/render/assetBase.d.ts +17 -0
- package/dist/render/assetBase.js +35 -0
- package/dist/render/modelLoad.js +4 -1
- package/dist/render/resolveModel.d.ts +15 -0
- package/dist/render/resolveModel.js +37 -2
- package/dist/scatter/InstancedScatter.js +5 -0
- package/dist/scatter/scatterProxies.js +24 -0
- package/dist/scene/AuthoredScene.d.ts +3 -1
- package/dist/scene/AuthoredScene.js +7 -2
- package/dist/scene/CityRenderer.d.ts +2 -0
- package/dist/scene/CityRenderer.js +1031 -0
- package/dist/scene/GrassFieldRenderer.js +53 -5
- package/dist/scene/PoleLineRenderer.d.ts +2 -0
- package/dist/scene/PoleLineRenderer.js +287 -0
- package/dist/scene/SoilPatchRenderer.js +70 -7
- package/dist/scene/WaterRenderer.js +34 -10
- package/dist/scene/builtinSceneKindRenderers.js +4 -0
- package/dist/scene/cityWindowMaterial.d.ts +16 -0
- package/dist/scene/cityWindowMaterial.js +81 -0
- package/dist/scene/sceneKindRenderers.d.ts +2 -0
- package/dist/settings/appliedSettings.d.ts +2 -1
- package/dist/settings/appliedSettings.js +4 -2
- package/dist/structures/TransformGizmo.d.ts +11 -1
- package/dist/structures/TransformGizmo.js +9 -5
- package/dist/terrain/GrassField.d.ts +11 -3
- package/dist/terrain/GrassField.js +16 -6
- package/dist/terrain/grassGeometry.d.ts +33 -1
- package/dist/terrain/grassGeometry.js +83 -21
- package/dist/terrain/grassMaterial.d.ts +18 -0
- package/dist/terrain/grassMaterial.js +66 -13
- package/dist/terrain/heightfieldGeometry.d.ts +34 -0
- package/dist/terrain/heightfieldGeometry.js +109 -0
- package/dist/terrain/index.d.ts +1 -0
- package/dist/terrain/index.js +1 -0
- package/dist/terrain/soilPatchMaterial.d.ts +15 -2
- package/dist/terrain/soilPatchMaterial.js +46 -8
- package/dist/terrain/terrainDetailMaterial.js +15 -2
- package/dist/water/Ocean.d.ts +7 -1
- package/dist/water/Ocean.js +16 -3
- package/dist/water/OceanConfig.d.ts +9 -0
- package/dist/water/OceanConfig.js +6 -0
- package/dist/water/OceanMaterial.d.ts +12 -0
- package/dist/water/OceanMaterial.js +9 -0
- package/dist/water/OceanShader.d.ts +2 -2
- package/dist/water/OceanShader.js +78 -10
- package/dist/world/PlaceScene.d.ts +11 -0
- package/dist/world/PlaceScene.js +27 -0
- package/dist/world/WorldScene.js +29 -2
- package/dist/worldSky.d.ts +7 -1
- package/dist/worldSky.js +11 -1
- package/package.json +4 -4
- package/skills/game-design/SKILL.md +28 -0
- package/skills/game-design/agents/openai.yaml +4 -0
- package/skills/game-design/references/application-playbook.md +170 -0
- package/skills/game-design/references/field-guide.md +288 -0
- package/skills/jgengine/SKILL.md +7 -4
- package/skills/jgengine/api.md +172 -79
- package/skills/jgengine/capabilities.md +104 -2
- package/skills/jgengine/recipes/minimal-game.md +88 -0
- package/skills/jgengine-ui/SKILL.md +15 -10
- package/skills/jgengine-ui/api.md +202 -47
- package/skills/jgengine-ui/capabilities.md +71 -2
- package/skills/jgengine-ui/recipes/portable-minimap.md +150 -0
- package/skills/jgengine-ui/reference.md +20 -7
- package/skills/jgengine-ui/references/visual-scorecard.md +1 -1
- package/skills/jgengine-world/SKILL.md +13 -0
- package/skills/jgengine-world/api.md +419 -15
- package/skills/jgengine-world/capabilities.md +108 -2
- package/skills/jgengine-world/recipes/commanding-entities.md +128 -0
- package/skills/jgengine-world/reference.md +43 -4
- package/skills/level-design/SKILL.md +54 -0
- package/skills/level-design/agents/openai.yaml +4 -0
- package/skills/level-design/references/application-playbook.md +192 -0
- package/skills/level-design/references/field-guide.md +337 -0
- package/skills/level-design/references/live-editor-loop.md +179 -0
- package/dist/cartridge/runtime.d.ts +0 -15
- package/dist/cartridge/runtime.js +0 -556
- package/dist/cartridge/spec.d.ts +0 -188
- package/dist/cartridge/spec.js +0 -19
- package/dist/cartridge/validate.d.ts +0 -2
- package/dist/cartridge/validate.js +0 -78
- package/dist/cartridge.d.ts +0 -145
- package/dist/cartridge.js +0 -246
- package/skills/jgengine/reference-cartridge.md +0 -72
|
@@ -14,7 +14,11 @@ export function resolveModel(value, assets, context) {
|
|
|
14
14
|
const where = context === undefined ? `model asset "${value}"` : `${context.seam}["${context.key}"] → "${value}"`;
|
|
15
15
|
throw new Error(`[jgengine] missing ${where} — not in the asset catalog. Fix the id, register it, or omit the mapping to keep the deliberate primitive/sprite fallback.`);
|
|
16
16
|
}
|
|
17
|
-
return
|
|
17
|
+
return {
|
|
18
|
+
url: ref.url,
|
|
19
|
+
...(ref.dims === undefined ? {} : { dims: ref.dims }),
|
|
20
|
+
...(ref.collisionMesh === undefined ? {} : { collisionMesh: ref.collisionMesh }),
|
|
21
|
+
};
|
|
18
22
|
}
|
|
19
23
|
/** Soft lookup used when an object catalog id may double as a model asset id.
|
|
20
24
|
* @internal
|
|
@@ -23,7 +27,11 @@ export function tryResolveCatalogModel(id, assets) {
|
|
|
23
27
|
const ref = assets.resolve(id);
|
|
24
28
|
if (ref === null)
|
|
25
29
|
return undefined;
|
|
26
|
-
return
|
|
30
|
+
return {
|
|
31
|
+
url: ref.url,
|
|
32
|
+
...(ref.dims === undefined ? {} : { dims: ref.dims }),
|
|
33
|
+
...(ref.collisionMesh === undefined ? {} : { collisionMesh: ref.collisionMesh }),
|
|
34
|
+
};
|
|
27
35
|
}
|
|
28
36
|
/**
|
|
29
37
|
* Resolve an entity model plus bone-attachment / kit-of-parts models through the catalog
|
|
@@ -82,6 +90,33 @@ export function resolveModelPlan(assets, plan) {
|
|
|
82
90
|
}
|
|
83
91
|
return out;
|
|
84
92
|
}
|
|
93
|
+
function softModelLookup(map, assets) {
|
|
94
|
+
if (map === undefined)
|
|
95
|
+
return undefined;
|
|
96
|
+
return (key) => {
|
|
97
|
+
const value = map[key];
|
|
98
|
+
if (value === undefined || typeof value !== "string")
|
|
99
|
+
return value;
|
|
100
|
+
return tryResolveCatalogModel(value, assets);
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The `createGameContext` `models` lookup derived from a playable's render maps: what each entity kind /
|
|
105
|
+
* object catalog id actually renders as, so colliders auto-fit the rendered mesh. Soft-resolves string
|
|
106
|
+
* ids (a missing catalog id keeps the default collider instead of throwing — the render path already
|
|
107
|
+
* reports it), passes inline configs through. `undefined` when the playable maps no models at all.
|
|
108
|
+
* @internal
|
|
109
|
+
*/
|
|
110
|
+
export function contextModels(playable) {
|
|
111
|
+
const entity = softModelLookup(playable.entityModels, playable.game.assets);
|
|
112
|
+
const object = softModelLookup(playable.objectModels, playable.game.assets);
|
|
113
|
+
if (entity === undefined && object === undefined)
|
|
114
|
+
return undefined;
|
|
115
|
+
return {
|
|
116
|
+
...(entity === undefined ? {} : { entity }),
|
|
117
|
+
...(object === undefined ? {} : { object }),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
85
120
|
/**
|
|
86
121
|
* Builds a `(key) => ModelConfig | null` override from a `seam`'s id/config map plus its catalog —
|
|
87
122
|
* `undefined` when either half is missing so the caller can fall back to its own default renderer.
|
|
@@ -5,6 +5,7 @@ import * as THREE from "three";
|
|
|
5
5
|
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
6
6
|
import { MeshoptDecoder } from "three/examples/jsm/libs/meshopt_decoder.module.js";
|
|
7
7
|
import { chunkScatterInstances } from "@jgengine/core/world/scatterRegion";
|
|
8
|
+
import { beginFallbackSeam, reportFallbackSeam } from "@jgengine/core/devtools/fallbackSeams";
|
|
8
9
|
import { buildScatterProxy } from "./scatterProxies.js";
|
|
9
10
|
import { buildScatterModelSources, disposeScatterModelSources } from "./scatterModels.js";
|
|
10
11
|
/** Chunk edge (m): dense fields split into this-sized buckets, each frustum-culled independently. */
|
|
@@ -90,6 +91,9 @@ function ScatterModelSpecies({ model, batches }) {
|
|
|
90
91
|
export function InstancedScatter({ instances, chunkSize = DEFAULT_CHUNK_SIZE, maxInstances = DEFAULT_MAX_INSTANCES, resolveItem, }) {
|
|
91
92
|
const batches = useMemo(() => batchInstances(instances.length > maxInstances ? instances.slice(0, maxInstances) : instances, chunkSize), [instances, chunkSize, maxInstances]);
|
|
92
93
|
const { proxyBatches, modelSpecies } = useMemo(() => {
|
|
94
|
+
// Dev diagnostic (no-op unless armed): re-zero the scatter seam before re-tallying which species
|
|
95
|
+
// fall to a stylized proxy (no resolveItem mapping / a null result). Reported once per species.
|
|
96
|
+
beginFallbackSeam("scatter");
|
|
93
97
|
const proxy = [];
|
|
94
98
|
const bySpecies = new Map();
|
|
95
99
|
const knownProxy = new Set();
|
|
@@ -106,6 +110,7 @@ export function InstancedScatter({ instances, chunkSize = DEFAULT_CHUNK_SIZE, ma
|
|
|
106
110
|
const resolved = resolveItem?.(batch.item) ?? null;
|
|
107
111
|
if (resolved === null) {
|
|
108
112
|
knownProxy.add(batch.item);
|
|
113
|
+
reportFallbackSeam("scatter", "omittedMapping");
|
|
109
114
|
proxy.push(batch);
|
|
110
115
|
continue;
|
|
111
116
|
}
|
|
@@ -6,6 +6,9 @@ const OAK = "#4a7a37";
|
|
|
6
6
|
const BUSH = "#4d7d3a";
|
|
7
7
|
const ROCK = "#82858c";
|
|
8
8
|
const GRASS = "#5f9a3c";
|
|
9
|
+
const PALM_BARK = "#8a7355";
|
|
10
|
+
const PALM_FROND = "#4c8b3d";
|
|
11
|
+
const CYPRESS = "#31502f";
|
|
9
12
|
/** Concatenates part geometries into one vertex-colored buffer (position + normal + color). */
|
|
10
13
|
function mergeParts(parts) {
|
|
11
14
|
const geos = parts.map((part) => (part.geometry.index === null ? part.geometry : part.geometry.toNonIndexed()));
|
|
@@ -80,6 +83,27 @@ const BUILDERS = {
|
|
|
80
83
|
{ geometry: cone(0.08, 0.55, 0).translate(0.12, 0, 0.05), color: GRASS },
|
|
81
84
|
{ geometry: cone(0.08, 0.6, 0).translate(-0.1, 0, -0.06), color: GRASS },
|
|
82
85
|
]),
|
|
86
|
+
palm: () => {
|
|
87
|
+
// Tall bare trunk with a radial crown of drooping fronds — each frond a flattened cone laid
|
|
88
|
+
// near-horizontal, tips sagging below the crown.
|
|
89
|
+
const parts = [{ geometry: trunk(2.6, 0.09), color: PALM_BARK }];
|
|
90
|
+
for (let i = 0; i < 6; i += 1) {
|
|
91
|
+
const yaw = (i / 6) * Math.PI * 2;
|
|
92
|
+
const frond = new THREE.ConeGeometry(0.16, 1.35, 4);
|
|
93
|
+
frond.scale(1, 1, 0.35);
|
|
94
|
+
frond.rotateX(-Math.PI / 2 - 0.5);
|
|
95
|
+
frond.rotateY(yaw);
|
|
96
|
+
frond.translate(Math.sin(yaw) * 0.32, 2.62, Math.cos(yaw) * 0.32);
|
|
97
|
+
parts.push({ geometry: frond, color: PALM_FROND });
|
|
98
|
+
}
|
|
99
|
+
parts.push({ geometry: sphere(0.14, 2.56), color: PALM_BARK });
|
|
100
|
+
return mergeParts(parts);
|
|
101
|
+
},
|
|
102
|
+
cypress: () => mergeParts([
|
|
103
|
+
{ geometry: trunk(0.5, 0.07), color: BARK },
|
|
104
|
+
{ geometry: cone(0.34, 2.5, 0.35, 6), color: CYPRESS },
|
|
105
|
+
{ geometry: cone(0.2, 0.7, 2.75, 5), color: CYPRESS },
|
|
106
|
+
]),
|
|
83
107
|
};
|
|
84
108
|
function defaultProxy() {
|
|
85
109
|
return mergeParts([{ geometry: cone(0.35, 1.2, 0), color: GRASS }]);
|
|
@@ -68,6 +68,8 @@ export interface AuthoredSceneProps {
|
|
|
68
68
|
placeObjects?: boolean | {
|
|
69
69
|
verticalOffset?: number;
|
|
70
70
|
};
|
|
71
|
+
/** Terrain surface color sampler forwarded to studio renderers (see `SceneKindRenderContext.groundColorAt`). */
|
|
72
|
+
groundColorAt?: (x: number, z: number) => string;
|
|
71
73
|
}
|
|
72
74
|
/**
|
|
73
75
|
* Renders an editor document's scene content — draped paths plus GPU-instanced foliage — from one
|
|
@@ -79,4 +81,4 @@ export interface AuthoredSceneProps {
|
|
|
79
81
|
* place markers with your own entity spawns. Pass `scatterModels`+`assets` to resolve palette items to
|
|
80
82
|
* real catalog GLBs; unmapped items keep the stylized proxy.
|
|
81
83
|
*/
|
|
82
|
-
export declare function AuthoredScene({ document, field, pathKinds, scatterModels, assets, live, placeObjects, }: AuthoredSceneProps): import("react").JSX.Element;
|
|
84
|
+
export declare function AuthoredScene({ document, field, pathKinds, scatterModels, assets, live, placeObjects, groundColorAt, }: AuthoredSceneProps): import("react").JSX.Element;
|
|
@@ -163,11 +163,16 @@ export function AuthoredObjects({ document, field, verticalOffset = 0, onExistin
|
|
|
163
163
|
* place markers with your own entity spawns. Pass `scatterModels`+`assets` to resolve palette items to
|
|
164
164
|
* real catalog GLBs; unmapped items keep the stylized proxy.
|
|
165
165
|
*/
|
|
166
|
-
export function AuthoredScene({ document, field, pathKinds, scatterModels, assets, live = true, placeObjects, }) {
|
|
166
|
+
export function AuthoredScene({ document, field, pathKinds, scatterModels, assets, live = true, placeObjects, groundColorAt, }) {
|
|
167
167
|
const liveDocument = useLiveEditorDocument(document, live);
|
|
168
168
|
const instances = useMemo(() => resolveScatter(liveDocument, field), [liveDocument, field]);
|
|
169
169
|
const resolveItem = useMemo(() => createModelMapResolver(scatterModels, assets, "scatterModels"), [scatterModels, assets]);
|
|
170
170
|
const shouldPlaceObjects = placeObjects === true || (typeof placeObjects === "object" && placeObjects !== null);
|
|
171
171
|
const objectVerticalOffset = typeof placeObjects === "object" && placeObjects !== null ? (placeObjects.verticalOffset ?? 0) : 0;
|
|
172
|
-
return (_jsxs(_Fragment, { children: [_jsx(AuthoredPaths, { document: liveDocument, field: field, ...(pathKinds === undefined ? {} : { kinds: pathKinds }) }), _jsx(InstancedScatter, { instances: instances, ...(resolveItem === undefined ? {} : { resolveItem }) }), _jsx(AuthoredStudios, { document: liveDocument, context: {
|
|
172
|
+
return (_jsxs(_Fragment, { children: [_jsx(AuthoredPaths, { document: liveDocument, field: field, ...(pathKinds === undefined ? {} : { kinds: pathKinds }) }), _jsx(InstancedScatter, { instances: instances, ...(resolveItem === undefined ? {} : { resolveItem }) }), _jsx(AuthoredStudios, { document: liveDocument, context: {
|
|
173
|
+
document: liveDocument,
|
|
174
|
+
field,
|
|
175
|
+
...(assets === undefined ? {} : { assets }),
|
|
176
|
+
...(groundColorAt === undefined ? {} : { groundColorAt }),
|
|
177
|
+
} }), _jsx(AuthoredGenerators, { document: liveDocument, field: field }), shouldPlaceObjects ? (_jsx(AuthoredObjects, { document: liveDocument, field: field, verticalOffset: objectVerticalOffset })) : null] }));
|
|
173
178
|
}
|