@jgengine/core 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/dist/ai/populationDirector.d.ts +103 -0
- package/dist/ai/populationDirector.js +190 -0
- package/dist/ai/pursuit.d.ts +56 -0
- package/dist/ai/pursuit.js +53 -0
- package/dist/authoring.d.ts +1 -1
- package/dist/authoring.js +1 -1
- package/dist/combat/effects.d.ts +11 -4
- package/dist/combat/effects.js +24 -17
- package/dist/combat/magazine.d.ts +13 -0
- package/dist/combat/magazine.js +27 -0
- package/dist/combat/vfxPresets.d.ts +176 -0
- package/dist/combat/vfxPresets.js +74 -0
- package/dist/combat/weaponFire.d.ts +114 -0
- package/dist/combat/weaponFire.js +96 -0
- package/dist/combat.d.ts +5 -2
- package/dist/combat.js +4 -1
- package/dist/devtools/controls.d.ts +38 -0
- package/dist/devtools/controls.js +181 -0
- package/dist/devtools/devtools.d.ts +5 -197
- package/dist/devtools/devtools.js +38 -774
- package/dist/devtools/discover.d.ts +32 -0
- package/dist/devtools/discover.js +240 -0
- package/dist/devtools/fallbackSeams.d.ts +50 -0
- package/dist/devtools/fallbackSeams.js +111 -0
- package/dist/devtools/frame.d.ts +15 -0
- package/dist/devtools/frame.js +247 -0
- package/dist/devtools/logs.d.ts +15 -0
- package/dist/devtools/logs.js +86 -0
- package/dist/devtools/overrides.d.ts +16 -0
- package/dist/devtools/overrides.js +66 -0
- package/dist/devtools/types.d.ts +212 -0
- package/dist/devtools/types.js +1 -0
- package/dist/devtools/urlFlags.d.ts +22 -0
- package/dist/devtools/urlFlags.js +62 -0
- package/dist/economy/auctionBook.d.ts +122 -0
- package/dist/economy/auctionBook.js +213 -0
- package/dist/economy/priceHistory.d.ts +44 -0
- package/dist/economy/priceHistory.js +89 -0
- package/dist/economy/unlockPoints.d.ts +92 -0
- package/dist/economy/unlockPoints.js +103 -0
- package/dist/editor/commandApply.d.ts +5 -0
- package/dist/editor/commandApply.js +755 -0
- package/dist/editor/commands.d.ts +48 -3
- package/dist/editor/commands.js +40 -754
- package/dist/editor/directives.d.ts +94 -0
- package/dist/editor/directives.js +206 -0
- package/dist/editor/document.d.ts +37 -2
- package/dist/editor/document.js +422 -6
- package/dist/editor/entityCatalog.d.ts +42 -0
- package/dist/editor/entityCatalog.js +101 -0
- package/dist/editor/environment.d.ts +74 -0
- package/dist/editor/environment.js +169 -0
- package/dist/editor/index.d.ts +26 -1
- package/dist/editor/index.js +8 -1
- package/dist/editor/minimap.d.ts +31 -0
- package/dist/editor/minimap.js +73 -0
- package/dist/editor/streamer.d.ts +66 -0
- package/dist/editor/streamer.js +68 -0
- package/dist/editor/types.d.ts +143 -0
- package/dist/editor/world.d.ts +136 -0
- package/dist/editor/world.js +303 -0
- package/dist/game/breeding.d.ts +161 -0
- package/dist/game/breeding.js +181 -0
- package/dist/game/cameraConfig.d.ts +451 -0
- package/dist/game/cameraConfig.js +1 -0
- package/dist/game/clipRoles.d.ts +51 -0
- package/dist/game/clipRoles.js +142 -0
- package/dist/game/defineGame.d.ts +16 -9
- package/dist/game/defineGame.js +14 -6
- package/dist/game/defineSystem.d.ts +2 -0
- package/dist/game/defineSystem.js +2 -0
- package/dist/game/events.d.ts +28 -0
- package/dist/game/partAnimation.d.ts +78 -0
- package/dist/game/partAnimation.js +147 -0
- package/dist/game/playableGame.d.ts +72 -440
- package/dist/game/playableGame.js +1 -1
- package/dist/game/progression.d.ts +35 -0
- package/dist/game/progression.js +22 -1
- package/dist/game/quest.js +1 -3
- package/dist/game/tribe.d.ts +184 -0
- package/dist/game/tribe.js +432 -0
- package/dist/gameplay.d.ts +3 -1
- package/dist/gameplay.js +3 -1
- package/dist/inventory/encumbrance.d.ts +69 -0
- package/dist/inventory/encumbrance.js +68 -0
- package/dist/inventory/inventoryModel.d.ts +24 -8
- package/dist/inventory/inventoryModel.js +47 -8
- package/dist/item/durability.js +1 -3
- package/dist/meta/changelog.d.ts +1 -1
- package/dist/meta/changelog.js +48 -1
- package/dist/movement/movementModel.d.ts +15 -1
- package/dist/movement/movementModel.js +33 -15
- package/dist/movement/playerMovement.js +102 -2
- package/dist/multiplayer/combatSnapshot.js +13 -8
- package/dist/multiplayer/presenceModel.d.ts +2 -0
- package/dist/multiplayer/presenceModel.js +8 -0
- package/dist/physics/drivableVehicle.d.ts +2 -0
- package/dist/physics/drivableVehicle.js +1 -1
- package/dist/physics/flightDynamics.d.ts +82 -0
- package/dist/physics/flightDynamics.js +165 -0
- package/dist/physics/gravityField.d.ts +25 -0
- package/dist/physics/gravityField.js +41 -0
- package/dist/physics/kinematicVehicle.d.ts +87 -0
- package/dist/physics/kinematicVehicle.js +193 -11
- package/dist/physics/physicsWorld.d.ts +26 -0
- package/dist/physics/physicsWorld.js +109 -117
- package/dist/physics/vehicleObstacles.d.ts +44 -0
- package/dist/physics/vehicleObstacles.js +115 -0
- package/dist/random/rng.d.ts +4 -1
- package/dist/random/rng.js +4 -1
- package/dist/runtime/adapter.d.ts +13 -0
- package/dist/runtime/adapter.js +13 -0
- package/dist/runtime/context/combat.d.ts +51 -0
- package/dist/runtime/context/combat.js +131 -0
- package/dist/runtime/context/combatFx.js +15 -5
- package/dist/runtime/context/deathLoot.d.ts +30 -0
- package/dist/runtime/context/deathLoot.js +39 -0
- package/dist/runtime/context/player.d.ts +48 -0
- package/dist/runtime/context/player.js +125 -0
- package/dist/runtime/context/scene.d.ts +60 -0
- package/dist/runtime/context/scene.js +329 -0
- package/dist/runtime/context/snapshotCodecs.d.ts +12 -0
- package/dist/runtime/context/snapshotCodecs.js +26 -0
- package/dist/runtime/descriptors/baseline.js +26 -3
- package/dist/runtime/descriptors/features.d.ts +5 -0
- package/dist/runtime/descriptors/features.js +20 -2
- package/dist/runtime/gameContext.d.ts +2 -428
- package/dist/runtime/gameContext.js +133 -500
- package/dist/runtime/gameContextTypes.d.ts +500 -0
- package/dist/runtime/gameContextTypes.js +1 -0
- package/dist/runtime/headlessRunner.d.ts +17 -2
- package/dist/runtime/headlessRunner.js +15 -0
- package/dist/runtime/hostPolicy.d.ts +51 -0
- package/dist/runtime/hostPolicy.js +68 -0
- package/dist/runtime/hostedGameRunner.d.ts +3 -1
- package/dist/runtime/hostedGameRunner.js +1 -0
- package/dist/runtime/hostedWorldSession.d.ts +3 -1
- package/dist/runtime/hostedWorldSession.js +1 -0
- package/dist/runtime/worldSnapshot.d.ts +13 -1
- package/dist/runtime/worldSnapshot.js +15 -3
- package/dist/scene/assetCatalog.d.ts +7 -0
- package/dist/scene/assetSpace.js +1 -3
- package/dist/scene/authoredTriggers.d.ts +50 -0
- package/dist/scene/authoredTriggers.js +114 -0
- package/dist/scene/builtinSceneKinds.js +8 -3
- package/dist/scene/colliders.d.ts +79 -0
- package/dist/scene/colliders.js +170 -0
- package/dist/scene/collisionMesh.d.ts +94 -0
- package/dist/scene/collisionMesh.js +699 -0
- package/dist/scene/companion.d.ts +147 -0
- package/dist/scene/companion.js +193 -0
- package/dist/scene/entityStats.d.ts +7 -9
- package/dist/scene/entityStats.js +19 -15
- package/dist/scene/sceneKinds.d.ts +16 -0
- package/dist/scene/sceneKinds.js +4 -0
- package/dist/scene/sceneRaycast.js +15 -0
- package/dist/stats/spawnLevelStats.d.ts +110 -0
- package/dist/stats/spawnLevelStats.js +140 -0
- package/dist/stats/statModifiers.d.ts +16 -0
- package/dist/stats/statModifiers.js +30 -1
- package/dist/stats/statPool.d.ts +70 -0
- package/dist/stats/statPool.js +62 -0
- package/dist/store/changeSignal.d.ts +3 -0
- package/dist/store/changeSignal.js +2 -0
- package/dist/store/observableKeyedStore.d.ts +2 -0
- package/dist/store/observableKeyedStore.js +1 -0
- package/dist/survival/decayMeter.js +1 -3
- package/dist/survival/regionHealth.js +1 -3
- package/dist/ui/hudLayout.d.ts +5 -0
- package/dist/ui/hudLayout.js +17 -1
- package/dist/ui/panelModel.d.ts +120 -0
- package/dist/ui/panelModel.js +168 -0
- package/dist/ui.d.ts +1 -0
- package/dist/ui.js +1 -0
- package/dist/world/authoredEntities.d.ts +29 -0
- package/dist/world/authoredEntities.js +29 -0
- package/dist/world/authoredObjects.d.ts +15 -1
- package/dist/world/authoredObjects.js +13 -1
- package/dist/world/authoredSpawn.d.ts +39 -0
- package/dist/world/authoredSpawn.js +37 -0
- package/dist/world/buildSockets.d.ts +152 -0
- package/dist/world/buildSockets.js +188 -0
- package/dist/world/buildingLots.d.ts +84 -0
- package/dist/world/buildingLots.js +119 -0
- package/dist/world/buildings.d.ts +6 -0
- package/dist/world/cityBlocks.d.ts +152 -0
- package/dist/world/cityBlocks.js +670 -0
- package/dist/world/cityContent.d.ts +77 -0
- package/dist/world/cityContent.js +261 -0
- package/dist/world/cityGenerator.d.ts +41 -0
- package/dist/world/cityGenerator.js +58 -0
- package/dist/world/cityGeometry.d.ts +114 -0
- package/dist/world/cityGeometry.js +573 -0
- package/dist/world/cityKind.d.ts +314 -0
- package/dist/world/cityKind.js +1578 -0
- package/dist/world/environmentSummary.js +57 -1
- package/dist/world/features.d.ts +53 -5
- package/dist/world/features.js +15 -3
- package/dist/world/grassKind.js +2 -2
- package/dist/world/markers.d.ts +50 -4
- package/dist/world/markers.js +49 -0
- package/dist/world/massing.js +1 -1
- package/dist/world/minimapBake.d.ts +78 -0
- package/dist/world/minimapBake.js +208 -0
- package/dist/world/minimapTrack.d.ts +17 -0
- package/dist/world/minimapTrack.js +22 -0
- package/dist/world/place.d.ts +166 -0
- package/dist/world/place.js +96 -0
- package/dist/world/placeAsset.js +3 -1
- package/dist/world/poleLineKind.d.ts +40 -0
- package/dist/world/poleLineKind.js +97 -0
- package/dist/world/polyline.js +9 -2
- package/dist/world/resourceNode.d.ts +109 -0
- package/dist/world/resourceNode.js +140 -0
- package/dist/world/roads.d.ts +19 -2
- package/dist/world/roads.js +60 -3
- package/dist/world/scatter.js +2 -20
- package/dist/world/streetGenerator.d.ts +159 -0
- package/dist/world/streetGenerator.js +684 -0
- package/dist/world/streets.d.ts +103 -1
- package/dist/world/streets.js +273 -0
- package/dist/world/terraform.js +58 -88
- package/dist/world/terrain.d.ts +65 -1
- package/dist/world/terrain.js +119 -2
- package/dist/world.d.ts +14 -5
- package/dist/world.js +12 -3
- package/package.json +1 -1
- 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 +8 -4
- package/skills/jgengine/api.md +182 -81
- package/skills/jgengine/capabilities.md +104 -2
- package/skills/jgengine/recipes/minimal-game.md +88 -0
- package/skills/jgengine-combat/SKILL.md +19 -1
- package/skills/jgengine-combat/api.md +75 -2
- package/skills/jgengine-combat/capabilities.md +61 -1
- package/skills/jgengine-combat/recipes/portable-damage-effects.md +197 -0
- package/skills/jgengine-combat/recipes/portable-runtime-state.md +154 -0
- package/skills/jgengine-combat/recipes/portable-stat-pools.md +122 -0
- package/skills/jgengine-combat/recipes/portable-weapon-plumbing.md +156 -0
- package/skills/jgengine-combat/recipes/visible-attacks.md +81 -0
- package/skills/jgengine-combat/reference.md +33 -4
- package/skills/jgengine-gameplay/SKILL.md +8 -0
- package/skills/jgengine-gameplay/api.md +182 -26
- package/skills/jgengine-gameplay/capabilities.md +96 -2
- package/skills/jgengine-gameplay/recipes/portable-xp-leveling.md +168 -0
- package/skills/jgengine-gameplay/reference-systems.md +10 -5
- package/skills/jgengine-world/SKILL.md +13 -0
- package/skills/jgengine-world/api.md +453 -21
- package/skills/jgengine-world/capabilities.md +112 -2
- package/skills/jgengine-world/recipes/commanding-entities.md +128 -0
- package/skills/jgengine-world/reference.md +43 -4
- package/skills/jgengine/reference-cartridge.md +0 -72
package/dist/scene/colliders.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { prepareCollisionMesh } from "./collisionMesh.js";
|
|
1
2
|
export const DEFAULT_ENTITY_HIT_RADIUS = 0.5;
|
|
2
3
|
export const DEFAULT_OBJECT_HALF_EXTENTS = [0.5, 0.5, 0.5];
|
|
3
4
|
/** Matches the shell's fallback actor capsule (~0.7m wide, feet at y=0 to head at ~1.8m). */
|
|
@@ -80,6 +81,175 @@ export function scaledObjectColliders(scale) {
|
|
|
80
81
|
},
|
|
81
82
|
};
|
|
82
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* The entity-local AABB the rendered model actually occupies, from measured dims + render config — the
|
|
86
|
+
* same scale/normalize/anchor math the shell uses to place the mesh, so box equals visual by
|
|
87
|
+
* construction. `null` when the model is unmeasured (`dims`/`maxY` absent) or degenerate.
|
|
88
|
+
*/
|
|
89
|
+
function fittedModelBox(model) {
|
|
90
|
+
const dims = model.dims;
|
|
91
|
+
if (dims === undefined || dims.maxY === undefined)
|
|
92
|
+
return null;
|
|
93
|
+
const { w, d } = dims.footprint;
|
|
94
|
+
const height = dims.maxY - dims.minY;
|
|
95
|
+
if (!(w > 0) || !(d > 0) || !(height > 0))
|
|
96
|
+
return null;
|
|
97
|
+
if (!Number.isFinite(w) || !Number.isFinite(d) || !Number.isFinite(height))
|
|
98
|
+
return null;
|
|
99
|
+
const normalize = model.targetHeight !== undefined && model.targetHeight > 0 ? model.targetHeight / height : 1;
|
|
100
|
+
const scale = (model.scale ?? 1) * normalize;
|
|
101
|
+
if (!(scale > 0) || !Number.isFinite(scale))
|
|
102
|
+
return null;
|
|
103
|
+
const baseY = model.y ?? 0;
|
|
104
|
+
// The renderer centers/grounds whenever it normalizes to targetHeight or anchors "center" (the
|
|
105
|
+
// default); only a raw-origin model without targetHeight keeps its authored pivot.
|
|
106
|
+
const centered = model.targetHeight !== undefined || (model.anchor ?? "center") === "center";
|
|
107
|
+
const halfExtents = [(w / 2) * scale, (height / 2) * scale, (d / 2) * scale];
|
|
108
|
+
const offset = centered
|
|
109
|
+
? [0, baseY + (height / 2) * scale, 0]
|
|
110
|
+
: [dims.center.x * scale, baseY + (dims.minY + height / 2) * scale, dims.center.z * scale];
|
|
111
|
+
// Maps the model point (center.x, minY, center.z) to the entity-local (0, baseY, 0) the box grounds
|
|
112
|
+
// on when centered; a raw-origin model keeps its authored pivot and only takes the render offset.
|
|
113
|
+
const meshTranslate = centered
|
|
114
|
+
? [-dims.center.x * scale, baseY - dims.minY * scale, -dims.center.z * scale]
|
|
115
|
+
: [0, baseY, 0];
|
|
116
|
+
return { halfExtents, offset, scale, meshTranslate };
|
|
117
|
+
}
|
|
118
|
+
/** Map a model-space point onto entity-local space with the mesh shape's uniform `scale` and per-axis
|
|
119
|
+
* `translate` (`coord * scale + translate`) — the same composition applied to `meshScale`/`meshTranslate`,
|
|
120
|
+
* so a model-space AABB corner lands exactly where the placed mesh puts it. `scale > 0` keeps min<max. */
|
|
121
|
+
function scaleTranslatePoint(point, scale, translate) {
|
|
122
|
+
return [point[0] * scale + translate[0], point[1] * scale + translate[1], point[2] * scale + translate[2]];
|
|
123
|
+
}
|
|
124
|
+
/** The fitted collider shape for a rendered model: a mesh-accurate triangle shape when the model
|
|
125
|
+
* opts in with a decodable `collisionMesh`, otherwise the conservative fitted box. `null` when the
|
|
126
|
+
* model is unmeasured or degenerate.
|
|
127
|
+
*/
|
|
128
|
+
function fittedBodyShape(model) {
|
|
129
|
+
const box = fittedModelBox(model);
|
|
130
|
+
if (box === null)
|
|
131
|
+
return null;
|
|
132
|
+
const mesh = model.collisionMesh !== undefined ? prepareCollisionMesh(model.collisionMesh) : null;
|
|
133
|
+
if (mesh !== null) {
|
|
134
|
+
const sourceBoxes = model.collisionMesh?.boxes;
|
|
135
|
+
const boxes = sourceBoxes !== undefined && sourceBoxes.length > 0
|
|
136
|
+
? sourceBoxes.map((b) => ({
|
|
137
|
+
min: scaleTranslatePoint(b.min, box.scale, box.meshTranslate),
|
|
138
|
+
max: scaleTranslatePoint(b.max, box.scale, box.meshTranslate),
|
|
139
|
+
}))
|
|
140
|
+
: undefined;
|
|
141
|
+
return {
|
|
142
|
+
kind: "mesh",
|
|
143
|
+
mesh,
|
|
144
|
+
meshScale: box.scale,
|
|
145
|
+
meshTranslate: box.meshTranslate,
|
|
146
|
+
halfExtents: box.halfExtents,
|
|
147
|
+
...(boxes !== undefined ? { boxes } : {}),
|
|
148
|
+
offset: box.offset,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return { kind: "aabb", halfExtents: box.halfExtents, offset: box.offset };
|
|
152
|
+
}
|
|
153
|
+
/** Damage hitbox fitted to the rendered model's measured bounds — the model-aware replacement for the
|
|
154
|
+
* fixed humanoid default. `null` when the model is unmeasured, keeping the caller's existing fallback.
|
|
155
|
+
* @internal
|
|
156
|
+
*/
|
|
157
|
+
export function fittedEntityColliders(model) {
|
|
158
|
+
const shape = fittedBodyShape(model);
|
|
159
|
+
if (shape === null)
|
|
160
|
+
return null;
|
|
161
|
+
return {
|
|
162
|
+
hitboxes: [
|
|
163
|
+
{
|
|
164
|
+
name: "body",
|
|
165
|
+
purpose: "damage",
|
|
166
|
+
shape,
|
|
167
|
+
damageEligible: true,
|
|
168
|
+
blocks: false,
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/** Blocking physical body fitted to the rendered model's measured bounds — the model-aware replacement
|
|
174
|
+
* for the unit-cube-times-scale guess. `null` when the model is unmeasured.
|
|
175
|
+
* @internal
|
|
176
|
+
*/
|
|
177
|
+
export function fittedObjectColliders(model) {
|
|
178
|
+
const shape = fittedBodyShape(model);
|
|
179
|
+
if (shape === null)
|
|
180
|
+
return null;
|
|
181
|
+
return {
|
|
182
|
+
body: {
|
|
183
|
+
name: "body",
|
|
184
|
+
purpose: "physical",
|
|
185
|
+
shape,
|
|
186
|
+
damageEligible: false,
|
|
187
|
+
blocks: true,
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/** Thin measured axes (decals, blades, flat panels) keep at least this half-extent so the box stays hittable. */
|
|
192
|
+
const MIN_MEASURED_HALF_EXTENT = 0.01;
|
|
193
|
+
/** Tight AABB from measured bounds — `null` when inverted, non-finite, or a degenerate point. */
|
|
194
|
+
function measuredBox(bounds) {
|
|
195
|
+
const { min, max } = bounds;
|
|
196
|
+
let volume = 0;
|
|
197
|
+
for (let axis = 0; axis < 3; axis += 1) {
|
|
198
|
+
const lo = min[axis];
|
|
199
|
+
const hi = max[axis];
|
|
200
|
+
if (!Number.isFinite(lo) || !Number.isFinite(hi) || hi < lo)
|
|
201
|
+
return null;
|
|
202
|
+
volume = Math.max(volume, hi - lo);
|
|
203
|
+
}
|
|
204
|
+
if (!(volume > 0))
|
|
205
|
+
return null;
|
|
206
|
+
return {
|
|
207
|
+
halfExtents: [
|
|
208
|
+
Math.max((max[0] - min[0]) / 2, MIN_MEASURED_HALF_EXTENT),
|
|
209
|
+
Math.max((max[1] - min[1]) / 2, MIN_MEASURED_HALF_EXTENT),
|
|
210
|
+
Math.max((max[2] - min[2]) / 2, MIN_MEASURED_HALF_EXTENT),
|
|
211
|
+
],
|
|
212
|
+
offset: [(min[0] + max[0]) / 2, (min[1] + max[1]) / 2, (min[2] + max[2]) / 2],
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
/** Damage hitbox exactly wrapping runtime-measured render bounds — what `reportBounds` stores for an
|
|
216
|
+
* entity kind. `null` when the bounds are degenerate, keeping the caller's existing fallback.
|
|
217
|
+
* @internal
|
|
218
|
+
*/
|
|
219
|
+
export function measuredEntityColliders(bounds) {
|
|
220
|
+
const box = measuredBox(bounds);
|
|
221
|
+
if (box === null)
|
|
222
|
+
return null;
|
|
223
|
+
return {
|
|
224
|
+
hitboxes: [
|
|
225
|
+
{
|
|
226
|
+
name: "body",
|
|
227
|
+
purpose: "damage",
|
|
228
|
+
shape: { kind: "aabb", halfExtents: box.halfExtents, offset: box.offset },
|
|
229
|
+
damageEligible: true,
|
|
230
|
+
blocks: false,
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
/** Blocking physical body exactly wrapping runtime-measured render bounds — what `reportBounds`
|
|
236
|
+
* stores for an object catalog id. `null` when the bounds are degenerate.
|
|
237
|
+
* @internal
|
|
238
|
+
*/
|
|
239
|
+
export function measuredObjectColliders(bounds) {
|
|
240
|
+
const box = measuredBox(bounds);
|
|
241
|
+
if (box === null)
|
|
242
|
+
return null;
|
|
243
|
+
return {
|
|
244
|
+
body: {
|
|
245
|
+
name: "body",
|
|
246
|
+
purpose: "physical",
|
|
247
|
+
shape: { kind: "aabb", halfExtents: box.halfExtents, offset: box.offset },
|
|
248
|
+
damageEligible: false,
|
|
249
|
+
blocks: true,
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
}
|
|
83
253
|
/** @internal */
|
|
84
254
|
export function resolveColliders(set) {
|
|
85
255
|
if (set === null || set === undefined)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { EntityPosition } from "./entityStore.js";
|
|
2
|
+
/**
|
|
3
|
+
* Compact, serializable triangle collision mesh measured at asset reindex — the renderer-free source
|
|
4
|
+
* of mesh-accurate hitboxes. Positions are welded onto a 16-bit grid spanning `min`..`max` (model
|
|
5
|
+
* space) and stored base64-encoded, so an opted-in catalog asset ships its collision triangles inside
|
|
6
|
+
* the generated index without the runtime ever touching the rendered scene graph.
|
|
7
|
+
*/
|
|
8
|
+
export interface CollisionMeshData {
|
|
9
|
+
/** Model-space bounds of the encoded vertices — the quantization frame. */
|
|
10
|
+
min: readonly [number, number, number];
|
|
11
|
+
max: readonly [number, number, number];
|
|
12
|
+
/** Welded vertex count; `positions` holds exactly `vertexCount * 3` u16 values. */
|
|
13
|
+
vertexCount: number;
|
|
14
|
+
/** Triangle count; `indices` holds exactly `triangleCount * 3` values. */
|
|
15
|
+
triangleCount: number;
|
|
16
|
+
/** Base64 little-endian u16 xyz triples, each axis normalized 0..65535 across `min`..`max`. */
|
|
17
|
+
positions: string;
|
|
18
|
+
/** Base64 little-endian triangle vertex indices — u16, or u32 when `vertexCount` exceeds 65536. */
|
|
19
|
+
indices: string;
|
|
20
|
+
/**
|
|
21
|
+
* Optional compact model-space solid decomposition from {@link voxelizeToBoxes} — a deterministic set
|
|
22
|
+
* of AABBs approximating the model's filled volume so movement obstruction can slide a capsule against
|
|
23
|
+
* the real pillars/lintel of a concave opening (walk THROUGH an arch) instead of one outer box. Absent
|
|
24
|
+
* for models whose voxelization is empty, keeping box-less assets byte-identical.
|
|
25
|
+
*/
|
|
26
|
+
boxes?: readonly {
|
|
27
|
+
min: readonly [number, number, number];
|
|
28
|
+
max: readonly [number, number, number];
|
|
29
|
+
}[];
|
|
30
|
+
}
|
|
31
|
+
/** Raw triangle soup for {@link encodeCollisionMesh}: model-space xyz triples plus triangle indices. */
|
|
32
|
+
export interface CollisionMeshSource {
|
|
33
|
+
positions: ArrayLike<number>;
|
|
34
|
+
indices: ArrayLike<number>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Decoded, BVH-indexed triangles ready for per-ray queries — build once per asset via
|
|
38
|
+
* {@link prepareCollisionMesh}. Treat the fields as opaque; they exist so the raycast hot path can
|
|
39
|
+
* run allocation-free over flat arrays.
|
|
40
|
+
*/
|
|
41
|
+
export interface PreparedCollisionMesh {
|
|
42
|
+
/** Dequantized model-space vertex xyz triples. */
|
|
43
|
+
readonly positions: Float32Array;
|
|
44
|
+
/** Triangle vertex indices, 3 per triangle. */
|
|
45
|
+
readonly indices: Uint32Array;
|
|
46
|
+
/** Per-node AABBs, 6 floats (minXYZ, maxXYZ) per node. */
|
|
47
|
+
readonly nodeBounds: Float32Array;
|
|
48
|
+
/** Leaf: first slot in `triOrder`. Internal: right-child node index (left child is `node + 1`). */
|
|
49
|
+
readonly nodeStart: Int32Array;
|
|
50
|
+
/** Leaf: triangle count (> 0). Internal: 0. */
|
|
51
|
+
readonly nodeCount: Int32Array;
|
|
52
|
+
/** Triangle indices grouped by leaf ranges. */
|
|
53
|
+
readonly triOrder: Uint32Array;
|
|
54
|
+
}
|
|
55
|
+
/** Nearest triangle impact from {@link raycastCollisionMesh}: world distance along the ray and the world-space geometric normal facing the ray. */
|
|
56
|
+
export interface CollisionMeshHit {
|
|
57
|
+
distance: number;
|
|
58
|
+
normal: EntityPosition;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Quantize a triangle soup onto the 16-bit grid, weld coincident vertices, and drop triangles that
|
|
62
|
+
* collapse — the reindex-time compressor producing {@link CollisionMeshData}. Returns `null` when no
|
|
63
|
+
* finite, non-degenerate triangle survives.
|
|
64
|
+
*/
|
|
65
|
+
export declare function encodeCollisionMesh(source: CollisionMeshSource): CollisionMeshData | null;
|
|
66
|
+
/**
|
|
67
|
+
* Decompose a triangle soup into a compact, deterministic set of model-space AABBs approximating its
|
|
68
|
+
* solid volume — the movement-obstruction counterpart to the raycast BVH. Rasterizes triangles onto a
|
|
69
|
+
* `cellSize` voxel grid, fills each vertical column between its lowest and highest occupied voxel (so a
|
|
70
|
+
* solid becomes solid and a concave opening — an archway — keeps its central gap empty while its pillars
|
|
71
|
+
* and lintel fill in), then greedy-merges occupied voxels into AABBs in a fixed z→y→x order. Pure and
|
|
72
|
+
* allocation-tolerant (runs once per asset at reindex). Caps the output at `maxBoxes`, folding any
|
|
73
|
+
* remainder into one enclosing AABB so obstruction stays conservative. Returns `[]` for degenerate input.
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
76
|
+
export declare function voxelizeToBoxes(source: CollisionMeshSource, cellSize?: number, maxBoxes?: number): {
|
|
77
|
+
min: [number, number, number];
|
|
78
|
+
max: [number, number, number];
|
|
79
|
+
}[];
|
|
80
|
+
/**
|
|
81
|
+
* Decode a stored collision mesh and index it with a BVH. Memoized per data object, so the shell and
|
|
82
|
+
* a headless host preparing the same catalog entry share one build. Returns `null` (also memoized)
|
|
83
|
+
* when the payload is malformed.
|
|
84
|
+
*/
|
|
85
|
+
export declare function prepareCollisionMesh(data: CollisionMeshData): PreparedCollisionMesh | null;
|
|
86
|
+
/**
|
|
87
|
+
* Nearest triangle hit for a world-space ray against a prepared mesh placed like its rendered model:
|
|
88
|
+
* model space scaled uniformly by `scale`, translated by entity-local `translate`, yaw-rotated by
|
|
89
|
+
* `rotationY`, and moved to `position` — the same composition {@link "scene/colliders".ModelBodySource}
|
|
90
|
+
* fitting applies to the AABB. Allocation-free until the returned hit. `distance` is world distance
|
|
91
|
+
* along `direction` (callers pass `direction` normalized); `normal` is the world-space geometric
|
|
92
|
+
* triangle normal facing the ray.
|
|
93
|
+
*/
|
|
94
|
+
export declare function raycastCollisionMesh(mesh: PreparedCollisionMesh, origin: EntityPosition, direction: EntityPosition, maxDistance: number, position: EntityPosition, rotationY: number, scale: number, translate: EntityPosition): CollisionMeshHit | null;
|