@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
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { normalizeJoinCode } from "../multiplayer/matchmaking.js";
|
|
2
|
+
/**
|
|
3
|
+
* True when a server's `visibility` should surface in public listings / browse results.
|
|
4
|
+
* @capability host-listing-filter exclude private sessions from public browse results
|
|
5
|
+
*/
|
|
6
|
+
export function isListablePublicly(visibility) {
|
|
7
|
+
return (visibility ?? "public") !== "private";
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Private-server join-code gate. Existing members always pass; non-members must present a
|
|
11
|
+
* matching `joinCode` (loose-normalized via {@link normalizeJoinCode}). Callers still decide
|
|
12
|
+
* whether the server is private — this only answers the code/membership half.
|
|
13
|
+
* @capability host-join-code-gate membership-or-code gate for private hosted servers
|
|
14
|
+
*/
|
|
15
|
+
export function canJoinPrivateServer(args) {
|
|
16
|
+
if (args.isMember)
|
|
17
|
+
return true;
|
|
18
|
+
if (args.joinCode === undefined || args.suppliedCode === undefined)
|
|
19
|
+
return false;
|
|
20
|
+
return normalizeJoinCode(args.suppliedCode) === normalizeJoinCode(args.joinCode);
|
|
21
|
+
}
|
|
22
|
+
/** Whether `userId` is already on the server's member roster. */
|
|
23
|
+
export function isServerMember(memberUserIds, userId) {
|
|
24
|
+
return memberUserIds.includes(userId);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* True when the server has no free slots for a non-member. Existing members never count as
|
|
28
|
+
* "full" so rejoin/leave cycles keep working.
|
|
29
|
+
*/
|
|
30
|
+
export function isServerFull(memberUserIds, slotsPerServer, userId) {
|
|
31
|
+
return memberUserIds.length >= slotsPerServer && !memberUserIds.includes(userId);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Whether a private-visibility server blocks this join (non-member without a matching code).
|
|
35
|
+
* Public / undefined visibility never blocks.
|
|
36
|
+
*/
|
|
37
|
+
export function isPrivateJoinBlocked(args) {
|
|
38
|
+
if ((args.visibility ?? "public") !== "private")
|
|
39
|
+
return false;
|
|
40
|
+
return !canJoinPrivateServer({
|
|
41
|
+
isMember: isServerMember(args.memberUserIds, args.userId),
|
|
42
|
+
joinCode: args.joinCode,
|
|
43
|
+
suppliedCode: args.suppliedCode,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/** Roster after a successful join: unchanged when already a member, else appended. */
|
|
47
|
+
export function withJoinedMember(memberUserIds, userId) {
|
|
48
|
+
return memberUserIds.includes(userId) ? [...memberUserIds] : [...memberUserIds, userId];
|
|
49
|
+
}
|
|
50
|
+
/** Roster after a leave: `userId` removed; order of remaining members preserved. */
|
|
51
|
+
export function withoutMember(memberUserIds, userId) {
|
|
52
|
+
return memberUserIds.filter((id) => id !== userId);
|
|
53
|
+
}
|
|
54
|
+
/** Status after a leave: empty rooms reopen; non-empty rooms keep their current status. */
|
|
55
|
+
export function statusAfterLeave(remainingMemberCount, currentStatus) {
|
|
56
|
+
return remainingMemberCount === 0 ? "open" : currentStatus;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Auto-match candidate when no `serverId` is supplied: already a member, or a public room with
|
|
60
|
+
* free capacity. Private rooms are never auto-picked (join-by-code / direct id only).
|
|
61
|
+
*/
|
|
62
|
+
export function isAutoJoinCandidate(args) {
|
|
63
|
+
if (isServerMember(args.memberUserIds, args.userId))
|
|
64
|
+
return true;
|
|
65
|
+
if (args.memberUserIds.length >= args.slotsPerServer)
|
|
66
|
+
return false;
|
|
67
|
+
return isListablePublicly(args.visibility);
|
|
68
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CommandResult } from "../commands/commandRegistry.js";
|
|
2
2
|
import type { GameDefinition, LoopPlayer } from "../game/defineGame.js";
|
|
3
3
|
import type { ModelAssetRef } from "../scene/assetCatalog.js";
|
|
4
|
-
import { type GameContext, type GameContextContent } from "./gameContext.js";
|
|
4
|
+
import { type GameContext, type GameContextContent, type GameContextModels } from "./gameContext.js";
|
|
5
5
|
import { type InputFrame } from "./inputSnapshot.js";
|
|
6
6
|
import { type WorldDiff } from "./worldReplication.js";
|
|
7
7
|
import type { SnapshotViewer, WorldSnapshot } from "./worldSnapshot.js";
|
|
@@ -21,6 +21,8 @@ export interface HostedGameRunnerOptions<TAssetRef extends ModelAssetRef, TMulti
|
|
|
21
21
|
* snapshot overlays the world state it seeded. Omit for a long-lived stateful host (ws) that keeps one runner.
|
|
22
22
|
*/
|
|
23
23
|
restore?: WorldSnapshot;
|
|
24
|
+
/** Render-model lookup for collider auto-fit — pass the same lookup the shell derives from `entityModels`/`objectModels` so host and clients resolve identical hitboxes. */
|
|
25
|
+
models?: GameContextModels;
|
|
24
26
|
}
|
|
25
27
|
/**
|
|
26
28
|
* The GameContext-loop equivalent of the pure-reducer `createGameHost`: one authoritative `createGameContext`
|
|
@@ -16,6 +16,7 @@ export function createHostedGameRunner(options) {
|
|
|
16
16
|
player: host ?? { userId: "host", isNew: true },
|
|
17
17
|
...(now === undefined ? {} : { now }),
|
|
18
18
|
...(definition.replication === undefined ? {} : { replication: definition.replication }),
|
|
19
|
+
...(options.models === undefined ? {} : { models: options.models }),
|
|
19
20
|
});
|
|
20
21
|
const loop = definition.loop ?? {};
|
|
21
22
|
const replicator = createWorldReplicator(() => ctx.snapshot(), {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CommandResult } from "../commands/commandRegistry.js";
|
|
2
2
|
import type { ModelAssetRef } from "../scene/assetCatalog.js";
|
|
3
|
-
import type { GameContext, GameContextContent } from "./gameContext.js";
|
|
3
|
+
import type { GameContext, GameContextContent, GameContextModels } from "./gameContext.js";
|
|
4
4
|
import type { GameDefinition, LoopPlayer } from "../game/defineGame.js";
|
|
5
5
|
import { type HostedGameRunner, type InputFrame } from "./hostedGameRunner.js";
|
|
6
6
|
import type { WorldDiff } from "./worldReplication.js";
|
|
@@ -42,6 +42,8 @@ export interface HostedWorldSessionOptions<TAssetRef extends ModelAssetRef, TMul
|
|
|
42
42
|
store?: HostedWorldStore;
|
|
43
43
|
/** Minimum elapsed ms between auto-saves on tick, measured against `now` (defaults to `Date.now` when omitted). Default `0` — persist on every revision-changing tick. */
|
|
44
44
|
saveIntervalMs?: number;
|
|
45
|
+
/** Render-model lookup for collider auto-fit, forwarded to the runner — see {@link HostedGameRunnerOptions.models}. */
|
|
46
|
+
models?: GameContextModels;
|
|
45
47
|
}
|
|
46
48
|
/**
|
|
47
49
|
* The stateful host substrate a long-lived backend binds (ws server, browser P2P host): a live
|
|
@@ -25,6 +25,7 @@ export function createHostedWorldSession(options) {
|
|
|
25
25
|
...(host === undefined ? {} : { host }),
|
|
26
26
|
...(now === undefined ? {} : { now }),
|
|
27
27
|
...(loaded === null ? {} : { restore: loaded.snapshot }),
|
|
28
|
+
...(options.models === undefined ? {} : { models: options.models }),
|
|
28
29
|
});
|
|
29
30
|
let savedRevision = loaded?.revision ?? 0;
|
|
30
31
|
let lastSaveAt = clock();
|
|
@@ -13,11 +13,20 @@ export interface SnapshotViewer {
|
|
|
13
13
|
* - {@link project} narrows this module's snapshot to what one viewer may see (private state, area of
|
|
14
14
|
* interest). Absent → the module is world-public and every client receives it verbatim (the default).
|
|
15
15
|
* - {@link version} is a monotone counter the host reads to skip re-serializing an unchanged module.
|
|
16
|
+
* - {@link decode} validates/coerces wire `unknown` into `T` before hydrate; returning `null` skips
|
|
17
|
+
* that module (fail-soft) instead of poisoning live state with a bare cast.
|
|
16
18
|
*/
|
|
17
19
|
export interface SnapshotModule<T = unknown> {
|
|
18
20
|
readonly key: string;
|
|
19
21
|
snapshot(): T;
|
|
20
22
|
hydrate(data: T): void;
|
|
23
|
+
/**
|
|
24
|
+
* Optional wire codec: turn the raw snapshot value into a typed `T`, or `null` to skip this module.
|
|
25
|
+
* When present, {@link applyWorldSnapshot} runs it before {@link hydrate} and never calls hydrate on
|
|
26
|
+
* a failed decode — a bad host/client payload leaves the prior module state intact rather than
|
|
27
|
+
* throwing or applying garbage.
|
|
28
|
+
*/
|
|
29
|
+
decode?(raw: unknown): T | null;
|
|
21
30
|
/**
|
|
22
31
|
* Narrow this module's full snapshot to what `viewer` is allowed to see — return the same shape
|
|
23
32
|
* carrying only the visible subset (drop other players' private state, cull entities outside the
|
|
@@ -38,7 +47,10 @@ export type WorldSnapshot = Record<string, unknown>;
|
|
|
38
47
|
* @internal
|
|
39
48
|
*/
|
|
40
49
|
export declare function composeWorldSnapshot(modules: readonly SnapshotModule[], viewer?: SnapshotViewer): WorldSnapshot;
|
|
41
|
-
/**
|
|
50
|
+
/**
|
|
51
|
+
* Hydrate every registered module whose key is present in `snapshot`; keys absent from it are left
|
|
52
|
+
* untouched. When a module provides {@link SnapshotModule.decode}, a `null` decode skips that module
|
|
53
|
+
* (fail-soft) instead of calling hydrate with unvalidated wire data.
|
|
42
54
|
* @internal
|
|
43
55
|
*/
|
|
44
56
|
export declare function applyWorldSnapshot(modules: readonly SnapshotModule[], snapshot: WorldSnapshot): void;
|
|
@@ -18,13 +18,25 @@ export function composeWorldSnapshot(modules, viewer) {
|
|
|
18
18
|
}
|
|
19
19
|
return snapshot;
|
|
20
20
|
}
|
|
21
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Hydrate every registered module whose key is present in `snapshot`; keys absent from it are left
|
|
23
|
+
* untouched. When a module provides {@link SnapshotModule.decode}, a `null` decode skips that module
|
|
24
|
+
* (fail-soft) instead of calling hydrate with unvalidated wire data.
|
|
22
25
|
* @internal
|
|
23
26
|
*/
|
|
24
27
|
export function applyWorldSnapshot(modules, snapshot) {
|
|
25
28
|
for (const module of modules) {
|
|
26
|
-
if (Object.prototype.hasOwnProperty.call(snapshot, module.key))
|
|
27
|
-
|
|
29
|
+
if (!Object.prototype.hasOwnProperty.call(snapshot, module.key))
|
|
30
|
+
continue;
|
|
31
|
+
const raw = snapshot[module.key];
|
|
32
|
+
if (module.decode !== undefined) {
|
|
33
|
+
const decoded = module.decode(raw);
|
|
34
|
+
if (decoded === null)
|
|
35
|
+
continue;
|
|
36
|
+
module.hydrate(decoded);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
module.hydrate(raw);
|
|
28
40
|
}
|
|
29
41
|
}
|
|
30
42
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AssetSpace } from "./assetSpace.js";
|
|
2
|
+
import type { CollisionMeshData } from "./collisionMesh.js";
|
|
2
3
|
/** Measured horizontal footprint, footprint center, and lowest Y of a model in model space. */
|
|
3
4
|
export interface ModelDims {
|
|
4
5
|
footprint: {
|
|
@@ -10,13 +11,19 @@ export interface ModelDims {
|
|
|
10
11
|
z: number;
|
|
11
12
|
};
|
|
12
13
|
minY: number;
|
|
14
|
+
/** Highest Y in model space (pre-scale). `maxY - minY` is the measured model height; absent in indexes generated before it was measured. */
|
|
15
|
+
maxY?: number;
|
|
13
16
|
}
|
|
14
17
|
export interface ModelAssetRef {
|
|
15
18
|
url: string;
|
|
16
19
|
/** Measured at asset reindex: horizontal footprint, footprint center, and lowest Y in model space (pre-scale). Lets the shell auto-center and ground-snap corner-pivot kit models. */
|
|
17
20
|
dims?: ModelDims;
|
|
21
|
+
/** Opt-in compact triangle mesh extracted at asset reindex (see {@link "scene/collisionMesh".CollisionMeshData}) — feeds mesh-accurate hitboxes for concave models. */
|
|
22
|
+
collisionMesh?: CollisionMeshData;
|
|
18
23
|
/** Authored asset-space metadata — canonical facing (degrees), source-unit scale, footprint, anchor, bounds, and rotation policy. The upstream owner of placement corrections; see {@link "scene/assetSpace".AssetSpace}. */
|
|
19
24
|
space?: AssetSpace;
|
|
25
|
+
/** Animation clip names read from the GLB at asset reindex. Lets the shell auto-animate rigged catalog assets (semantic clip roles → default idle/walk/run + one-shots) with no game-side clip strings. */
|
|
26
|
+
clips?: readonly string[];
|
|
20
27
|
}
|
|
21
28
|
/**
|
|
22
29
|
* A catalog entry backed by a registered {@link registerAssetGenerator} instead of a GLB URL — a
|
package/dist/scene/assetSpace.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { clamp } from "../math/scalar.js";
|
|
1
2
|
/**
|
|
2
3
|
* Asset-space metadata + placement rotation policy: the catalog-owned description of how a model sits
|
|
3
4
|
* in its source space and how a placement tool may rotate it. Games author scenes against engine north
|
|
@@ -11,9 +12,6 @@
|
|
|
11
12
|
const DEG2RAD = Math.PI / 180;
|
|
12
13
|
const RAD2DEG = 180 / Math.PI;
|
|
13
14
|
const FULL_TURN = 360;
|
|
14
|
-
function clamp(value, min, max) {
|
|
15
|
-
return value < min ? min : value > max ? max : value;
|
|
16
|
-
}
|
|
17
15
|
/**
|
|
18
16
|
* Wrap `degrees` into `[0, 360)` — the canonical heading range every policy and conversion here works
|
|
19
17
|
* in. Non-finite input collapses to `0` so bad metadata never leaks a `NaN` heading downstream.
|
|
@@ -71,6 +71,23 @@ export declare function getTriggerAction(id: string): TriggerActionDefinition |
|
|
|
71
71
|
export declare function listTriggerActions(target?: TriggerSourceKind): TriggerActionDefinition[];
|
|
72
72
|
/** Clears the action registry — tests only. @internal */
|
|
73
73
|
export declare function clearTriggerActions(): void;
|
|
74
|
+
/**
|
|
75
|
+
* The engine's built-in trigger actions — the shared `announce` / `win` / `advance` vocabulary every
|
|
76
|
+
* game gets for free, so "enter this zone → win" is authored entirely in the editor with no bespoke
|
|
77
|
+
* action code. Their params land flat on the object's `meta` like any registered action; drive them
|
|
78
|
+
* at runtime with the handlers from {@link createTriggerOutcome}.
|
|
79
|
+
*
|
|
80
|
+
* @capability authored-triggers built-in announce/win/advance actions authorable on any marker or volume
|
|
81
|
+
*/
|
|
82
|
+
export declare const BUILTIN_TRIGGER_ACTIONS: readonly TriggerActionDefinition[];
|
|
83
|
+
/**
|
|
84
|
+
* Register the engine's built-in {@link BUILTIN_TRIGGER_ACTIONS} so they appear in the editor's
|
|
85
|
+
* trigger inspector. Idempotent; call at module load (a game may still register its own actions or
|
|
86
|
+
* re-register a built-in id to override it).
|
|
87
|
+
*
|
|
88
|
+
* @capability authored-triggers register the shared announce/win/advance actions
|
|
89
|
+
*/
|
|
90
|
+
export declare function registerBuiltinTriggerActions(): void;
|
|
74
91
|
/** Resolve the proximity radius for a marker trigger from meta. @internal */
|
|
75
92
|
export declare function triggerRadiusOf(meta: Record<string, unknown> | undefined, fallback?: number): number;
|
|
76
93
|
/**
|
|
@@ -156,6 +173,39 @@ export declare function createAuthoredTriggerRuntime(options: {
|
|
|
156
173
|
/** Override the collected trigger list (tests / hot-reload). Default: {@link collectAuthoredTriggers}. */
|
|
157
174
|
triggers?: readonly AuthoredTrigger[];
|
|
158
175
|
}): AuthoredTriggerRuntime;
|
|
176
|
+
/** Serializable read-model the built-in trigger actions write — the HUD/game reads it each frame. */
|
|
177
|
+
export interface TriggerOutcome {
|
|
178
|
+
/** True once a `win` action fired. */
|
|
179
|
+
won: boolean;
|
|
180
|
+
/** Latest announce/win/advance message to surface, or null before any fires. */
|
|
181
|
+
message: string | null;
|
|
182
|
+
/** Tone for the latest message: `"info" | "warn" | "good"`. */
|
|
183
|
+
tone: string;
|
|
184
|
+
/** Current objective id from the latest `advance`, or null. */
|
|
185
|
+
objective: string | null;
|
|
186
|
+
/** Bumped on every change — a cheap key for `useSyncExternalStore`. */
|
|
187
|
+
revision: number;
|
|
188
|
+
}
|
|
189
|
+
/** Outcome store: the built-in action handlers plus a subscribable snapshot of what they produced. */
|
|
190
|
+
export interface TriggerOutcomeStore {
|
|
191
|
+
/** Current outcome snapshot (stable reference until the next change). */
|
|
192
|
+
get(): TriggerOutcome;
|
|
193
|
+
/** Subscribe to outcome changes; returns an unsubscribe fn. */
|
|
194
|
+
subscribe(listener: () => void): () => void;
|
|
195
|
+
/** Handlers for `createAuthoredTriggerRuntime({ handlers })` — wires announce/win/advance. */
|
|
196
|
+
handlers: TriggerHandlers;
|
|
197
|
+
/** Reset to the initial (un-won) outcome — new run / retry. */
|
|
198
|
+
reset(): void;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Default runtime for the built-in {@link BUILTIN_TRIGGER_ACTIONS}: a small serializable outcome the
|
|
202
|
+
* HUD renders, with no engine-side UI. Pass {@link TriggerOutcomeStore.handlers} to
|
|
203
|
+
* {@link createAuthoredTriggerRuntime} and read {@link TriggerOutcomeStore.get} from the HUD via
|
|
204
|
+
* `useSyncExternalStore` — that is the whole zero-code "reach the zone to win" wiring.
|
|
205
|
+
*
|
|
206
|
+
* @capability authored-triggers headless win/announce/objective outcome for the built-in actions
|
|
207
|
+
*/
|
|
208
|
+
export declare function createTriggerOutcome(): TriggerOutcomeStore;
|
|
159
209
|
/**
|
|
160
210
|
* Build a meta patch that sets a single flat trigger (`on` + `action` + optional param fields) and
|
|
161
211
|
* clears a multi-trigger list if present. Used by the editor inspector.
|
|
@@ -41,6 +41,64 @@ export function listTriggerActions(target) {
|
|
|
41
41
|
export function clearTriggerActions() {
|
|
42
42
|
actionRegistry.clear();
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* The engine's built-in trigger actions — the shared `announce` / `win` / `advance` vocabulary every
|
|
46
|
+
* game gets for free, so "enter this zone → win" is authored entirely in the editor with no bespoke
|
|
47
|
+
* action code. Their params land flat on the object's `meta` like any registered action; drive them
|
|
48
|
+
* at runtime with the handlers from {@link createTriggerOutcome}.
|
|
49
|
+
*
|
|
50
|
+
* @capability authored-triggers built-in announce/win/advance actions authorable on any marker or volume
|
|
51
|
+
*/
|
|
52
|
+
export const BUILTIN_TRIGGER_ACTIONS = [
|
|
53
|
+
{
|
|
54
|
+
id: "announce",
|
|
55
|
+
label: "Announce",
|
|
56
|
+
schema: {
|
|
57
|
+
fields: [
|
|
58
|
+
{ type: "text", key: "message", label: "Message", default: "Entered zone" },
|
|
59
|
+
{
|
|
60
|
+
type: "select",
|
|
61
|
+
key: "tone",
|
|
62
|
+
label: "Tone",
|
|
63
|
+
options: [
|
|
64
|
+
{ value: "info", label: "Info" },
|
|
65
|
+
{ value: "warn", label: "Warn" },
|
|
66
|
+
{ value: "good", label: "Good" },
|
|
67
|
+
],
|
|
68
|
+
default: "info",
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: "win",
|
|
75
|
+
label: "Win the game",
|
|
76
|
+
schema: {
|
|
77
|
+
fields: [{ type: "text", key: "message", label: "Message", default: "You win!" }],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: "advance",
|
|
82
|
+
label: "Advance objective",
|
|
83
|
+
schema: {
|
|
84
|
+
fields: [
|
|
85
|
+
{ type: "text", key: "objective", label: "Next objective", default: "" },
|
|
86
|
+
{ type: "text", key: "message", label: "Message", default: "" },
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
/**
|
|
92
|
+
* Register the engine's built-in {@link BUILTIN_TRIGGER_ACTIONS} so they appear in the editor's
|
|
93
|
+
* trigger inspector. Idempotent; call at module load (a game may still register its own actions or
|
|
94
|
+
* re-register a built-in id to override it).
|
|
95
|
+
*
|
|
96
|
+
* @capability authored-triggers register the shared announce/win/advance actions
|
|
97
|
+
*/
|
|
98
|
+
export function registerBuiltinTriggerActions() {
|
|
99
|
+
for (const definition of BUILTIN_TRIGGER_ACTIONS)
|
|
100
|
+
registerTriggerAction(definition);
|
|
101
|
+
}
|
|
44
102
|
function isTriggerEvent(value) {
|
|
45
103
|
return typeof value === "string" && TRIGGER_EVENTS.includes(value);
|
|
46
104
|
}
|
|
@@ -311,6 +369,62 @@ export function createAuthoredTriggerRuntime(options) {
|
|
|
311
369
|
},
|
|
312
370
|
};
|
|
313
371
|
}
|
|
372
|
+
const INITIAL_OUTCOME = { won: false, message: null, tone: "info", objective: null, revision: 0 };
|
|
373
|
+
/**
|
|
374
|
+
* Default runtime for the built-in {@link BUILTIN_TRIGGER_ACTIONS}: a small serializable outcome the
|
|
375
|
+
* HUD renders, with no engine-side UI. Pass {@link TriggerOutcomeStore.handlers} to
|
|
376
|
+
* {@link createAuthoredTriggerRuntime} and read {@link TriggerOutcomeStore.get} from the HUD via
|
|
377
|
+
* `useSyncExternalStore` — that is the whole zero-code "reach the zone to win" wiring.
|
|
378
|
+
*
|
|
379
|
+
* @capability authored-triggers headless win/announce/objective outcome for the built-in actions
|
|
380
|
+
*/
|
|
381
|
+
export function createTriggerOutcome() {
|
|
382
|
+
let outcome = INITIAL_OUTCOME;
|
|
383
|
+
const listeners = new Set();
|
|
384
|
+
const commit = (next) => {
|
|
385
|
+
outcome = { ...next, revision: outcome.revision + 1 };
|
|
386
|
+
for (const listener of listeners)
|
|
387
|
+
listener();
|
|
388
|
+
};
|
|
389
|
+
const messageOf = (event, fallback) => {
|
|
390
|
+
const value = event.params.message;
|
|
391
|
+
return typeof value === "string" && value.length > 0 ? value : fallback;
|
|
392
|
+
};
|
|
393
|
+
const stringParam = (event, key) => {
|
|
394
|
+
const value = event.params[key];
|
|
395
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
396
|
+
};
|
|
397
|
+
return {
|
|
398
|
+
get: () => outcome,
|
|
399
|
+
subscribe(listener) {
|
|
400
|
+
listeners.add(listener);
|
|
401
|
+
return () => {
|
|
402
|
+
listeners.delete(listener);
|
|
403
|
+
};
|
|
404
|
+
},
|
|
405
|
+
handlers: {
|
|
406
|
+
announce: (event) => {
|
|
407
|
+
commit({ won: outcome.won, message: messageOf(event, "Entered zone"), tone: stringParam(event, "tone") ?? "info", objective: outcome.objective });
|
|
408
|
+
},
|
|
409
|
+
win: (event) => {
|
|
410
|
+
commit({ won: true, message: messageOf(event, "You win!"), tone: "good", objective: outcome.objective });
|
|
411
|
+
},
|
|
412
|
+
advance: (event) => {
|
|
413
|
+
commit({
|
|
414
|
+
won: outcome.won,
|
|
415
|
+
message: stringParam(event, "message") ?? outcome.message,
|
|
416
|
+
tone: outcome.tone,
|
|
417
|
+
objective: stringParam(event, "objective") ?? outcome.objective,
|
|
418
|
+
});
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
reset() {
|
|
422
|
+
outcome = INITIAL_OUTCOME;
|
|
423
|
+
for (const listener of listeners)
|
|
424
|
+
listener();
|
|
425
|
+
},
|
|
426
|
+
};
|
|
427
|
+
}
|
|
314
428
|
/**
|
|
315
429
|
* Build a meta patch that sets a single flat trigger (`on` + `action` + optional param fields) and
|
|
316
430
|
* clears a multi-trigger list if present. Used by the editor inspector.
|
|
@@ -2,16 +2,19 @@
|
|
|
2
2
|
* Registers the engine's built-in *environment* scene kinds against the {@link registerSceneKind}
|
|
3
3
|
* seam: `scatter` (the proof adopter — its inspector, `+ Add` entry, and parse now come from the
|
|
4
4
|
* registry), `water` (a reusable parametric water surface), `grass_field` (GPU vertex-wind grass), and
|
|
5
|
-
* `soil` (crack/moss ground-variation patch)
|
|
6
|
-
* Domain studios (
|
|
7
|
-
* code via the same public seam, needing zero
|
|
5
|
+
* `soil` (crack/moss ground-variation patch), and `pole_line` (poles + sagging cables along a path).
|
|
6
|
+
* These are genre-agnostic engine primitives, like terrain. Domain studios (bookcases, …) are NOT
|
|
7
|
+
* built in — they register themselves from example/game code via the same public seam, needing zero
|
|
8
|
+
* engine edits (see `examples/studios`). Call
|
|
8
9
|
* {@link registerBuiltinSceneKinds} once at startup (idempotent).
|
|
9
10
|
*/
|
|
10
11
|
import { SCATTER_PATH_KIND } from "../world/scatterRegion.js";
|
|
11
12
|
import { registerWaterKind } from "../world/waterKind.js";
|
|
12
13
|
import { registerGrassKind } from "../world/grassKind.js";
|
|
13
14
|
import { registerSoilKind } from "../world/soilKind.js";
|
|
15
|
+
import { registerPoleLineKind } from "../world/poleLineKind.js";
|
|
14
16
|
import { registerBuildingGenerator } from "../world/buildingGenerator.js";
|
|
17
|
+
import { registerCityKind } from "../world/cityKind.js";
|
|
15
18
|
import { registerSceneKind } from "./sceneKinds.js";
|
|
16
19
|
/** The scatter/foliage region schema — the fields the inspector exposed as hand-written `ScatterFields`. */
|
|
17
20
|
export const SCATTER_SCHEMA = {
|
|
@@ -58,5 +61,7 @@ export function registerBuiltinSceneKinds() {
|
|
|
58
61
|
registerWaterKind();
|
|
59
62
|
registerGrassKind();
|
|
60
63
|
registerSoilKind();
|
|
64
|
+
registerCityKind();
|
|
65
|
+
registerPoleLineKind();
|
|
61
66
|
registerBuildingGenerator();
|
|
62
67
|
}
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
+
import type { ModelDims } from "./assetCatalog.js";
|
|
2
|
+
import { type CollisionMeshData, type PreparedCollisionMesh } from "./collisionMesh.js";
|
|
1
3
|
import type { EntityPosition } from "./entityStore.js";
|
|
2
4
|
export type ColliderPurpose = "physical" | "damage";
|
|
5
|
+
/**
|
|
6
|
+
* Collision geometry in entity-local space. `sphere` and `aabb` are analytic; `mesh` carries a
|
|
7
|
+
* prepared triangle mesh so opted-in concave models raycast their real surface while bounds and
|
|
8
|
+
* broadphase keep reading the conservative `halfExtents`.
|
|
9
|
+
* @capability mesh-hitboxes shots pass through holes in concave models — opted-in catalog assets raycast their actual triangles instead of the fitted box.
|
|
10
|
+
* @capability mesh-movement the walking player slides against a mesh collider's compound `boxes` — a capsule walks THROUGH an opted-in archway opening and is stopped by its pillars/lintel instead of one outer box.
|
|
11
|
+
*/
|
|
3
12
|
export type ColliderShape = {
|
|
4
13
|
kind: "sphere";
|
|
5
14
|
radius: number;
|
|
@@ -8,6 +17,27 @@ export type ColliderShape = {
|
|
|
8
17
|
kind: "aabb";
|
|
9
18
|
halfExtents: EntityPosition;
|
|
10
19
|
offset?: EntityPosition;
|
|
20
|
+
} | {
|
|
21
|
+
kind: "mesh";
|
|
22
|
+
/** Prepared triangle mesh in model space — engine-derived from an opted-in catalog asset, never hand-authored. */
|
|
23
|
+
mesh: PreparedCollisionMesh;
|
|
24
|
+
/** Uniform model→entity-local scale (same composition as the fitted box). */
|
|
25
|
+
meshScale: number;
|
|
26
|
+
/** Entity-local translation applied after `meshScale`. */
|
|
27
|
+
meshTranslate: EntityPosition;
|
|
28
|
+
/** Conservative entity-local AABB of the placed mesh — bounds/broadphase read this exactly like an `aabb`. */
|
|
29
|
+
halfExtents: EntityPosition;
|
|
30
|
+
/**
|
|
31
|
+
* Optional compact entity-local solid decomposition (from the model's `collisionMesh.boxes`, scaled
|
|
32
|
+
* and translated onto the placement exactly like `mesh`). Movement obstruction slides against these
|
|
33
|
+
* sub-boxes so a capsule walks THROUGH a concave opening; raycasts still use `mesh`. Absent when the
|
|
34
|
+
* model shipped no `boxes`.
|
|
35
|
+
*/
|
|
36
|
+
boxes?: readonly {
|
|
37
|
+
min: EntityPosition;
|
|
38
|
+
max: EntityPosition;
|
|
39
|
+
}[];
|
|
40
|
+
offset?: EntityPosition;
|
|
11
41
|
};
|
|
12
42
|
export interface ColliderDef {
|
|
13
43
|
name: string;
|
|
@@ -49,6 +79,55 @@ export declare function defaultObjectColliders(halfExtents?: EntityPosition): En
|
|
|
49
79
|
* @internal
|
|
50
80
|
*/
|
|
51
81
|
export declare function scaledObjectColliders(scale: readonly [number, number, number]): EntityColliderSet;
|
|
82
|
+
/**
|
|
83
|
+
* The render-config subset collider fitting reads — structurally satisfied by a resolved `ModelConfig`,
|
|
84
|
+
* so the shell can hand its render config straight to the fitting math without a conversion step.
|
|
85
|
+
*/
|
|
86
|
+
export interface ModelBodySource {
|
|
87
|
+
/** Measured model-space bounds from the asset index; fitting requires `dims` with `maxY`. */
|
|
88
|
+
dims?: ModelDims;
|
|
89
|
+
/** Uniform render scale. Default `1`. */
|
|
90
|
+
scale?: number;
|
|
91
|
+
/** Normalize-to-height in world units — fitting composes it exactly like the renderer (`targetHeight / measured height`, multiplied by `scale`). */
|
|
92
|
+
targetHeight?: number;
|
|
93
|
+
/** Vertical render offset added to the placement Y. Default `0`. */
|
|
94
|
+
y?: number;
|
|
95
|
+
/** Placement registration. `"center"` (default) centers the footprint and grounds `minY` on the placement point; `"origin"` renders at the raw model origin. */
|
|
96
|
+
anchor?: "center" | "origin";
|
|
97
|
+
/** Opt-in triangle collision mesh extracted at asset reindex; when present, fitting emits a mesh-accurate shape (rays pass through holes in concave models) instead of the fitted box. */
|
|
98
|
+
collisionMesh?: CollisionMeshData;
|
|
99
|
+
}
|
|
100
|
+
/** Damage hitbox fitted to the rendered model's measured bounds — the model-aware replacement for the
|
|
101
|
+
* fixed humanoid default. `null` when the model is unmeasured, keeping the caller's existing fallback.
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
104
|
+
export declare function fittedEntityColliders(model: ModelBodySource): EntityColliderSet | null;
|
|
105
|
+
/** Blocking physical body fitted to the rendered model's measured bounds — the model-aware replacement
|
|
106
|
+
* for the unit-cube-times-scale guess. `null` when the model is unmeasured.
|
|
107
|
+
* @internal
|
|
108
|
+
*/
|
|
109
|
+
export declare function fittedObjectColliders(model: ModelBodySource): EntityColliderSet | null;
|
|
110
|
+
/**
|
|
111
|
+
* Entity-local AABB of what the renderer actually mounted for a kind — the runtime counterpart to
|
|
112
|
+
* index-measured `dims`. Reported through `ctx.scene.entity.reportBounds` /
|
|
113
|
+
* `ctx.scene.object.reportBounds` (the shell does this automatically for custom
|
|
114
|
+
* `renderEntity`/`renderObject` content and models without index dims) so collider resolution can
|
|
115
|
+
* wrap the real rendered shape instead of a fixed-size guess.
|
|
116
|
+
*/
|
|
117
|
+
export interface MeasuredBounds {
|
|
118
|
+
min: EntityPosition;
|
|
119
|
+
max: EntityPosition;
|
|
120
|
+
}
|
|
121
|
+
/** Damage hitbox exactly wrapping runtime-measured render bounds — what `reportBounds` stores for an
|
|
122
|
+
* entity kind. `null` when the bounds are degenerate, keeping the caller's existing fallback.
|
|
123
|
+
* @internal
|
|
124
|
+
*/
|
|
125
|
+
export declare function measuredEntityColliders(bounds: MeasuredBounds): EntityColliderSet | null;
|
|
126
|
+
/** Blocking physical body exactly wrapping runtime-measured render bounds — what `reportBounds`
|
|
127
|
+
* stores for an object catalog id. `null` when the bounds are degenerate.
|
|
128
|
+
* @internal
|
|
129
|
+
*/
|
|
130
|
+
export declare function measuredObjectColliders(bounds: MeasuredBounds): EntityColliderSet | null;
|
|
52
131
|
/** @internal */
|
|
53
132
|
export declare function resolveColliders(set: EntityColliderSet | null | undefined): ResolvedCollider[];
|
|
54
133
|
/** @internal */
|