@jgengine/core 0.19.0 → 0.22.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 +364 -0
- package/dist/ai/decisionGraph.d.ts +2 -0
- package/dist/ai/decisionGraph.js +6 -0
- package/dist/ai/flock.d.ts +1 -1
- package/dist/ai/flock.js +7 -4
- package/dist/anim/animGraph.d.ts +33 -2
- package/dist/anim/animGraph.js +200 -12
- package/dist/anim/locomotionGraph.d.ts +11 -3
- package/dist/anim/locomotionGraph.js +25 -15
- package/dist/audio/audioFalloff.d.ts +4 -0
- package/dist/audio/voiceAllocator.d.ts +46 -0
- package/dist/audio/voiceAllocator.js +76 -0
- package/dist/combat/abilityKit.d.ts +19 -0
- package/dist/combat/abilityKit.js +40 -4
- package/dist/combat/death.d.ts +4 -3
- package/dist/combat/death.js +3 -3
- package/dist/combat/magazine.d.ts +9 -0
- package/dist/combat/magazine.js +24 -2
- package/dist/combat/projectiles.d.ts +94 -2
- package/dist/combat/projectiles.js +282 -61
- package/dist/combat/regenShield.d.ts +14 -0
- package/dist/combat/regenShield.js +23 -7
- package/dist/crafting/recipeCatalog.d.ts +16 -0
- package/dist/crafting/recipeCatalog.js +55 -0
- package/dist/economy/auctionBook.d.ts +1 -1
- package/dist/economy/auctionBook.js +11 -1
- package/dist/economy/listingBook.d.ts +1 -1
- package/dist/economy/listingBook.js +11 -1
- package/dist/economy/resourceLedger.js +3 -3
- package/dist/economy/shopStock.js +7 -6
- package/dist/economy/techTree.js +7 -6
- package/dist/economy/unlockPoints.js +3 -6
- package/dist/editor/commandApply.js +89 -16
- package/dist/editor/commands.d.ts +38 -1
- package/dist/editor/commands.js +320 -3
- package/dist/editor/creatorStorage.d.ts +59 -0
- package/dist/editor/creatorStorage.js +164 -0
- package/dist/editor/document.d.ts +4 -0
- package/dist/editor/document.js +116 -17
- package/dist/editor/index.d.ts +3 -0
- package/dist/editor/index.js +1 -0
- package/dist/editor/liveSync.d.ts +4 -1
- package/dist/editor/liveSync.js +26 -10
- package/dist/editor/materialAuthoring.d.ts +14 -0
- package/dist/editor/materialAuthoring.js +38 -0
- package/dist/editor/modelNodeVisibility.d.ts +11 -0
- package/dist/editor/modelNodeVisibility.js +29 -0
- package/dist/editor/movementCatalog.d.ts +90 -0
- package/dist/editor/movementCatalog.js +144 -0
- package/dist/editor/simulation.d.ts +60 -0
- package/dist/editor/simulation.js +202 -0
- package/dist/editor/staticPrefab.d.ts +17 -0
- package/dist/editor/staticPrefab.js +51 -0
- package/dist/editor/terrainMaterials.d.ts +10 -0
- package/dist/editor/terrainMaterials.js +13 -0
- package/dist/editor/types.d.ts +11 -0
- package/dist/game/cameraConfig.d.ts +3 -1
- package/dist/game/clipRoles.d.ts +2 -1
- package/dist/game/clipRoles.js +7 -3
- package/dist/game/contentValidation.d.ts +69 -0
- package/dist/game/contentValidation.js +118 -0
- package/dist/game/controlGate.d.ts +8 -0
- package/dist/game/controlGate.js +43 -6
- package/dist/game/defineGame.d.ts +32 -3
- package/dist/game/dialogueGraph.d.ts +20 -0
- package/dist/game/dialogueGraph.js +107 -0
- package/dist/game/events.d.ts +5 -0
- package/dist/game/keyValueStore.d.ts +17 -4
- package/dist/game/keyValueStore.js +35 -23
- package/dist/game/lootModifiers.d.ts +17 -0
- package/dist/game/lootModifiers.js +26 -0
- package/dist/game/narrativeAuthoring.d.ts +67 -0
- package/dist/game/narrativeAuthoring.js +122 -0
- package/dist/game/playableGame.d.ts +52 -20
- package/dist/game/quest.d.ts +15 -0
- package/dist/game/quest.js +209 -63
- package/dist/game/questCatalog.d.ts +50 -0
- package/dist/game/questCatalog.js +205 -0
- package/dist/game/saveStore.d.ts +6 -5
- package/dist/game/saveStore.js +57 -57
- package/dist/game/systemRuntime.d.ts +2 -2
- package/dist/game/systemRuntime.js +84 -33
- package/dist/gameplay.d.ts +3 -0
- package/dist/gameplay.js +3 -0
- package/dist/interaction/promptRegistry.d.ts +5 -4
- package/dist/interaction/promptRegistry.js +8 -2
- package/dist/inventory/inventoryModel.js +9 -6
- package/dist/inventory/shapedGrid.d.ts +48 -9
- package/dist/inventory/shapedGrid.js +69 -10
- package/dist/item/durability.js +4 -0
- package/dist/item/itemInstanceRegistry.d.ts +32 -1
- package/dist/item/itemInstanceRegistry.js +111 -7
- package/dist/item/itemgen.d.ts +1 -1
- package/dist/item/itemgen.js +1 -1
- package/dist/item/modularItem.js +7 -1
- package/dist/material/appearanceSignals.d.ts +53 -0
- package/dist/material/appearanceSignals.js +47 -0
- package/dist/material/hairCards.d.ts +47 -0
- package/dist/material/hairCards.js +136 -0
- package/dist/material/materialAsset.d.ts +162 -0
- package/dist/material/materialAsset.js +382 -0
- package/dist/meta/changelog.d.ts +1 -1
- package/dist/meta/changelog.js +348 -1
- package/dist/movement/characterController.d.ts +5 -2
- package/dist/movement/characterController.js +50 -23
- package/dist/movement/freeFlight.d.ts +2 -2
- package/dist/movement/freeFlight.js +3 -3
- package/dist/movement/movementModel.d.ts +24 -1
- package/dist/movement/movementModel.js +74 -7
- package/dist/movement/playerMovement.d.ts +28 -1
- package/dist/movement/playerMovement.js +425 -102
- package/dist/movement/poseState.d.ts +2 -0
- package/dist/movement/poseState.js +29 -1
- package/dist/movement/solidObstacles.d.ts +3 -1
- package/dist/movement/solidObstacles.js +8 -5
- package/dist/movement/terrainGrade.d.ts +13 -0
- package/dist/movement/terrainGrade.js +33 -0
- package/dist/movement/voxelController.d.ts +2 -2
- package/dist/movement/voxelController.js +3 -3
- package/dist/nav/navGrid.d.ts +19 -1
- package/dist/nav/navGrid.js +26 -10
- package/dist/nav/solidRoute.d.ts +50 -0
- package/dist/nav/solidRoute.js +144 -0
- package/dist/physics/ballisticSweep.d.ts +10 -3
- package/dist/physics/ballisticSweep.js +53 -29
- package/dist/physics/forceVolume.d.ts +41 -0
- package/dist/physics/forceVolume.js +88 -0
- package/dist/physics/kinematicVehicle.d.ts +8 -3
- package/dist/physics/kinematicVehicle.js +2 -2
- package/dist/physics/physicsWorldBackend.js +19 -3
- package/dist/physics/spatialGrid.d.ts +1 -1
- package/dist/physics/spatialGrid.js +8 -9
- package/dist/physics/vehicleDynamics.d.ts +3 -2
- package/dist/physics/vehicleDynamics.js +2 -2
- package/dist/physics/vehicleObstacles.d.ts +3 -2
- package/dist/physics/vehicleObstacles.js +29 -5
- package/dist/runtime/cameraDirector.d.ts +39 -2
- package/dist/runtime/cameraDirector.js +162 -0
- package/dist/runtime/commandDispatch.d.ts +14 -0
- package/dist/runtime/commandDispatch.js +19 -0
- package/dist/runtime/context/combat.d.ts +11 -4
- package/dist/runtime/context/combat.js +178 -11
- package/dist/runtime/context/deathLoot.d.ts +9 -8
- package/dist/runtime/context/deathLoot.js +16 -16
- package/dist/runtime/context/scene.d.ts +2 -0
- package/dist/runtime/context/scene.js +13 -21
- package/dist/runtime/descriptors/baseline.js +34 -3
- package/dist/runtime/descriptors/features.d.ts +2 -1
- package/dist/runtime/descriptors/features.js +18 -0
- package/dist/runtime/gameContext.js +79 -13
- package/dist/runtime/gameContextTypes.d.ts +14 -0
- package/dist/runtime/headlessRunner.d.ts +3 -1
- package/dist/runtime/headlessRunner.js +11 -11
- package/dist/runtime/hostedGameRunner.d.ts +24 -1
- package/dist/runtime/hostedGameRunner.js +156 -10
- package/dist/runtime/hostedWorldSession.d.ts +17 -5
- package/dist/runtime/hostedWorldSession.js +154 -16
- package/dist/runtime/hostedWorldStore.d.ts +2 -2
- package/dist/runtime/inputRecorder.d.ts +1 -1
- package/dist/runtime/inputRecorder.js +21 -1
- package/dist/runtime/inputSnapshot.d.ts +16 -4
- package/dist/runtime/inputSnapshot.js +31 -3
- package/dist/runtime/runtimeSave.d.ts +10 -6
- package/dist/runtime/runtimeSave.js +11 -5
- package/dist/runtime/simContext.d.ts +8 -3
- package/dist/runtime/simContext.js +7 -3
- package/dist/runtime/simSnapshot.js +2 -0
- package/dist/runtime/worldReplication.d.ts +2 -0
- package/dist/runtime/worldReplication.js +1 -1
- package/dist/scene/assetCatalog.d.ts +2 -0
- package/dist/scene/behaviorRuntime.d.ts +26 -5
- package/dist/scene/behaviorRuntime.js +263 -16
- package/dist/scene/behaviors.d.ts +30 -1
- package/dist/scene/behaviors.js +29 -0
- package/dist/scene/entityStore.d.ts +14 -3
- package/dist/scene/entityStore.js +45 -9
- package/dist/scene/mount.d.ts +9 -0
- package/dist/scene/mount.js +35 -0
- package/dist/scene/possession.d.ts +2 -0
- package/dist/scene/possession.js +21 -1
- package/dist/scene/sceneRaycast.d.ts +7 -0
- package/dist/scene/sceneRaycast.js +55 -0
- package/dist/scene/spatial.d.ts +20 -1
- package/dist/scene/spatial.js +94 -2
- package/dist/scene/vehicleSeat.d.ts +36 -2
- package/dist/scene/vehicleSeat.js +89 -2
- package/dist/stats/accumulatorMeter.d.ts +10 -0
- package/dist/stats/accumulatorMeter.js +6 -0
- package/dist/stats/eventMeter.d.ts +9 -2
- package/dist/stats/eventMeter.js +5 -2
- package/dist/store/defineStore.d.ts +3 -1
- package/dist/store/defineStore.js +3 -1
- package/dist/store/observableKeyedStore.d.ts +1 -1
- package/dist/store/observableKeyedStore.js +8 -6
- package/dist/time/simClock.d.ts +6 -2
- package/dist/time/simClock.js +5 -0
- package/dist/vfx/particleDirector.d.ts +58 -6
- package/dist/vfx/particleDirector.js +113 -22
- package/dist/vfx/particles.d.ts +68 -5
- package/dist/vfx/particles.js +284 -32
- package/dist/visibility/assetStreaming.d.ts +21 -3
- package/dist/visibility/assetStreaming.js +108 -24
- package/dist/visibility/settings.d.ts +8 -2
- package/dist/visibility/settings.js +3 -0
- package/dist/visibility/visibilitySystem.js +1 -0
- package/dist/work/expedition.d.ts +110 -0
- package/dist/work/expedition.js +195 -0
- package/dist/work/staffedStation.d.ts +29 -0
- package/dist/work/staffedStation.js +27 -0
- package/dist/world/authoredAnimation.d.ts +38 -0
- package/dist/world/authoredAnimation.js +99 -0
- package/dist/world/authoredObjects.d.ts +24 -4
- package/dist/world/authoredObjects.js +43 -16
- package/dist/world/authoredSimulation.d.ts +74 -0
- package/dist/world/authoredSimulation.js +302 -0
- package/dist/world/authoredWeather.d.ts +120 -0
- package/dist/world/authoredWeather.js +314 -0
- package/dist/world/buildingKit.d.ts +8 -3
- package/dist/world/buildingKit.js +21 -8
- package/dist/world/environmentForces.d.ts +21 -0
- package/dist/world/environmentForces.js +42 -0
- package/dist/world/features.d.ts +3 -3
- package/dist/world/footprintGrid.d.ts +55 -0
- package/dist/world/footprintGrid.js +201 -0
- package/dist/world/grassKind.d.ts +10 -0
- package/dist/world/grassKind.js +22 -0
- package/dist/world/pathTerrain.d.ts +1 -1
- package/dist/world/terraform.d.ts +2 -2
- package/dist/world/terraform.js +46 -18
- package/dist/world/weather.d.ts +17 -0
- package/dist/world/weather.js +116 -20
- package/dist/world/worldSolids.d.ts +11 -0
- package/dist/world/worldSolids.js +112 -1
- package/dist/world.d.ts +5 -5
- package/dist/world.js +4 -4
- package/package.json +1 -1
- package/skills/ce-handoff/SKILL.md +1 -1
- package/skills/game-design/SKILL.md +2 -0
- package/skills/jgengine/SKILL.md +23 -2
- package/skills/jgengine/api.md +28 -17
- package/skills/jgengine/recipes/minimal-game.md +7 -2
- package/skills/jgengine-combat/SKILL.md +8 -2
- package/skills/jgengine-combat/api.md +22 -10
- package/skills/jgengine-combat/recipes/portable-runtime-state.md +60 -6
- package/skills/jgengine-combat/recipes/portable-weapon-plumbing.md +37 -3
- package/skills/jgengine-combat/reference.md +24 -2
- package/skills/jgengine-gameplay/SKILL.md +63 -0
- package/skills/jgengine-gameplay/api.md +131 -37
- package/skills/jgengine-gameplay/capabilities.md +68 -0
- package/skills/jgengine-gameplay/recipes/device-save-status.md +46 -0
- package/skills/jgengine-gameplay/recipes/expeditions.md +108 -0
- package/skills/jgengine-gameplay/recipes/narrative-authoring.md +76 -0
- package/skills/jgengine-gameplay/recipes/paged-item-storage.md +101 -0
- package/skills/jgengine-gameplay/recipes/quest-authoring.md +63 -0
- package/skills/jgengine-gameplay/recipes/shaped-inventory.md +50 -0
- package/skills/jgengine-gameplay/reference-content-validation.md +74 -0
- package/skills/jgengine-gameplay/reference-systems.md +119 -0
- package/skills/jgengine-world/SKILL.md +12 -3
- package/skills/jgengine-world/api.md +201 -58
- package/skills/jgengine-world/capabilities.md +116 -3
- package/skills/jgengine-world/recipes/character-animation.md +31 -8
- package/skills/jgengine-world/recipes/controls.md +4 -0
- package/skills/jgengine-world/recipes/npc-senses.md +12 -0
- package/skills/jgengine-world/recipes/vehicle-feel.md +3 -1
- package/skills/jgengine-world/reference.md +167 -5
- package/skills/jgengine-world/visibility.md +28 -1
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
- `CraftContext` (interface): interface CraftContext { origin?: Vec2; stations?: readonly StationInstance[]; unlocked?: (id: string) => boolean } — ⚠ undocumented
|
|
109
109
|
- `CraftRejection` (type): type CraftRejection = | { reason: "missing-inputs"; missing: readonly RecipeItem[] } | { reason: "no-station"; station: string } | { reason: "locked"; requires: readonly string[] } | { reason: "no-output-space" } — ⚠ undocumented
|
|
110
110
|
- `CraftResult` (type): type CraftResult = { status: "ok"; state: InventoryState } | ({ status: "rejected" } & CraftRejection) — ⚠ undocumented
|
|
111
|
-
- `RecipeDef` (interface): interface RecipeDef { id: string; inputs: readonly RecipeItem[]; outputs: readonly RecipeItem[]; seconds?: number; station?: string; stationRange?: number; requires?: readonly string[]; category?: string } — ⚠ undocumented
|
|
111
|
+
- `RecipeDef` (interface): interface RecipeDef { id: string; inputs: readonly RecipeItem[]; outputs: readonly RecipeItem[]; seconds?: number; station?: string; stationRange?: number; requires?: readonly string[]; category?: string } — ⚠ undocumented · used by `validateRecipeCatalog` (@jgengine/core/crafting/recipeCatalog): Validate native recipes before registration: ids, counts, timing and caller-catalog references.
|
|
112
112
|
- `RecipeGraph` (interface): interface RecipeGraph { all(): readonly RecipeDef[]; get(id: string): RecipeDef | null; producing(itemId: string): RecipeDef[]; using(itemId: string): RecipeDef[]; category(categoryId: string): RecipeDef[] } — ⚠ undocumented
|
|
113
113
|
- `RecipeItem` (interface): interface RecipeItem { itemId: string; count: number } — ⚠ undocumented
|
|
114
114
|
- `StationInstance` (interface): interface StationInstance { catalogId: string; position: Vec2 } — ⚠ undocumented
|
|
@@ -120,6 +120,11 @@
|
|
|
120
120
|
- `missingInputs` (function): function missingInputs(state: InventoryState, recipe: RecipeDef): RecipeItem[] — ⚠ undocumented
|
|
121
121
|
- `stationSatisfied` (function): function stationSatisfied(recipe: RecipeDef, context: CraftContext): boolean — ⚠ undocumented
|
|
122
122
|
|
|
123
|
+
## @jgengine/core/crafting/recipeCatalog
|
|
124
|
+
|
|
125
|
+
- `RecipeCatalogValidationOptions` (interface): interface RecipeCatalogValidationOptions — Caller catalogs for native crafting references; omission leaves that namespace unchecked.
|
|
126
|
+
- `validateRecipeCatalog` (function): function validateRecipeCatalog(recipes: readonly RecipeDef[], options: RecipeCatalogValidationOptions = {}): ContentIssue[] — Validate native recipes before registration: ids, counts, timing and caller-catalog references. Empty outputs are valid for game-owned benefits; fractional and zero counts are allowed. Negative/nonfinite counts, durations and ranges reject. Duplicate input rows reject because the crafting input check does not aggregate them; consolidate their counts into one row. No price, scarcity, story or cycle policy is imposed. O(recipes + item rows + requirements).
|
|
127
|
+
|
|
123
128
|
## @jgengine/core/data/dataSource
|
|
124
129
|
|
|
125
130
|
- `DataSource` (interface): interface DataSource<T> { getState(): DataSourceState<T>; subscribe(listener: (state: DataSourceState<T>) => void): () => void; refresh(options?: RefreshOptions): Promise<void>; startPolling(intervalMs?: number): void; stopPolling(): void; dispose(): void } — ⚠ undocumented
|
|
@@ -162,7 +167,7 @@
|
|
|
162
167
|
- `CancelAuctionResult` (type): type CancelAuctionResult = | { status: "ok"; auction: Auction } | { status: "rejected"; reason: "not-found" | "not-owner" | "has-bids" } — Result of {@link AuctionBook.cancel}: a bid-on auction can no longer be withdrawn.
|
|
163
168
|
- `HighBid` (interface): interface HighBid — The current leading bid on an {@link Auction}.
|
|
164
169
|
- `PostAuctionInput` (interface): interface PostAuctionInput — Input to {@link AuctionBook.post} — the goods, opening terms, and current game-time.
|
|
165
|
-
- `PostAuctionReason` (type): type PostAuctionReason = | "invalid-count" | "invalid-price" | "invalid-increment" | "invalid-buyout" | "auction-cap-reached" — Why {@link AuctionBook.post} refused an auction.
|
|
170
|
+
- `PostAuctionReason` (type): type PostAuctionReason = | "invalid-count" | "invalid-price" | "invalid-increment" | "invalid-buyout" | "auction-cap-reached" | "duplicate-id" — Why {@link AuctionBook.post} refused an auction.
|
|
166
171
|
- `PostAuctionResult` (type): type PostAuctionResult = | { status: "ok"; auction: Auction } | { status: "rejected"; reason: PostAuctionReason } — Result of {@link AuctionBook.post}.
|
|
167
172
|
- `createAuctionBook` (function): function createAuctionBook(config: AuctionBookConfig): AuctionBook — Timed-bid auctions in the WoW/BDO auction-house mold: post an item with a start price, minimum increment, and optional buyout; bids escrow currency, outbid players are refunded into their collection box, bids near the close extend it (anti-snipe), and settlement pays the seller minus the house cut while the item lands in the winner's collection box. Unsold auctions return the goods to the seller's box. Wallet and inventory movement is the caller's job (mirrors `economy/listingBook`) — this primitive owns the auction lifecycle and the escrowed collection-box bookkeeping behind it.
|
|
168
173
|
|
|
@@ -185,7 +190,7 @@
|
|
|
185
190
|
- `ListingBook` (interface): interface ListingBook — A player-driven marketplace of {@link Listing}s plus the per-seller collection boxes behind it. See {@link createListingBook}.
|
|
186
191
|
- `ListingBookConfig` (interface): interface ListingBookConfig — Tunables for {@link createListingBook} — per-seller listing cap, expiry window, house cut, and optional price bounds.
|
|
187
192
|
- `PostListingInput` (interface): interface PostListingInput — Input to {@link ListingBook.post} — the goods, asking price, and current game-time to stamp the listing with.
|
|
188
|
-
- `PostListingReason` (type): type PostListingReason = | "invalid-count" | "invalid-price" | "price-too-low" | "price-too-high" | "listing-cap-reached" — Why {@link ListingBook.post} refused a listing.
|
|
193
|
+
- `PostListingReason` (type): type PostListingReason = | "invalid-count" | "invalid-price" | "price-too-low" | "price-too-high" | "listing-cap-reached" | "duplicate-id" — Why {@link ListingBook.post} refused a listing.
|
|
189
194
|
- `PostListingResult` (type): type PostListingResult = | { status: "ok"; listing: Listing } | { status: "rejected"; reason: PostListingReason } — Result of {@link ListingBook.post}.
|
|
190
195
|
- `createListingBook` (function): function createListingBook(config: ListingBookConfig): ListingBook — A player-driven listing marketplace: post/cancel/buy against a shared book with a house cut on every sale, an expiry sweep that pulls unsold goods out of circulation, and a per-seller collection box holding sale proceeds and returned items until claimed. Buyer/seller wallet and inventory movement is the caller's job (mirrors `game/trade`'s split) — this primitive owns only the listing lifecycle and the escrowed collection-box bookkeeping behind it.
|
|
191
196
|
|
|
@@ -373,7 +378,7 @@
|
|
|
373
378
|
- `DEFAULT_CLIP_ROLE_TABLE` (const): const DEFAULT_CLIP_ROLE_TABLE: ClipRoleTable — Default vocabulary covering KayKit, Quaternius, and Mixamo-style clip naming.
|
|
374
379
|
- `classifyClip` (function): function classifyClip(name: string, table: ClipRoleTable = DEFAULT_CLIP_ROLE_TABLE): ClipRole | null — Classify a single GLB clip name into a {@link ClipRole}, or `null` when nothing matches (or an exclusion token like `pose` disqualifies it). Deterministic: exact token matches beat prefix matches; remaining ties resolve by fixed role priority (death > hit > attack > … > idle).
|
|
375
380
|
- `defaultAnimationForClips` (function): function defaultAnimationForClips(clips: readonly string[], table: ClipRoleTable = DEFAULT_CLIP_ROLE_TABLE): ModelAnimationConfig | undefined — Build the default `ModelConfig.animation` for a rigged asset from its catalog clip names: speed-driven idle/walk/run states plus hit/death/attack one-shots where identifiable. Returns `undefined` when no idle clip is identifiable — an ambiguous rig renders its bind pose rather than guessing. Walk falls back to idle when the pack has no walk clip.
|
|
376
|
-
- `resolveAnimationConfig` (function): function resolveAnimationConfig(animation: ModelAnimationConfig | "auto" | "none" | undefined, clips: readonly string[] | undefined, table: ClipRoleTable = DEFAULT_CLIP_ROLE_TABLE): ModelAnimationConfig | undefined — Collapse `ModelConfig.animation`'s widened union to a concrete playback config: explicit configs pass through, `"none"`/absent render the bind pose, and `"auto"` derives states and one-shots from the model's clip names via {@link defaultAnimationForClips}. The shell calls this with the loaded GLB's actual clip names, so `"auto"` works on any rigged model — catalog-resolved ids are stamped `"auto"` automatically.
|
|
381
|
+
- `resolveAnimationConfig` (function): function resolveAnimationConfig(animation: ModelAnimationConfig | "auto" | "none" | undefined, clips: readonly string[] | undefined, table: ClipRoleTable = DEFAULT_CLIP_ROLE_TABLE): ModelAnimationConfig | undefined — Collapse `ModelConfig.animation`'s widened union to a concrete playback config: explicit configs pass through, `"none"`/absent render the bind pose, and `"auto"` derives states and one-shots from the model's clip names via {@link defaultAnimationForClips}. The shell calls this with the loaded GLB's actual clip names, so `"auto"` works on any rigged model — catalog-resolved ids are stamped `"auto"` automatically. An object with `auto: true` derives the same defaults, then replaces each explicitly supplied field whole, including empty maps.
|
|
377
382
|
- `rolesFromClips` (function): function rolesFromClips(clips: readonly string[], table: ClipRoleTable = DEFAULT_CLIP_ROLE_TABLE): Partial<Record<ClipRole, string[]>> — Group a GLB's clip names by role. Each role's variants are sorted simplest-first — fewest name tokens, then lexicographic — so the canonical variant (`Idle` over `2H_Melee_Idle`, KayKit `Walking_A` over `Walking_B`) is always first: stable output for the same clip set regardless of source order.
|
|
378
383
|
|
|
379
384
|
## @jgengine/core/game/codex
|
|
@@ -391,6 +396,18 @@
|
|
|
391
396
|
- `ConnectedPlayers` (interface): interface ConnectedPlayers — The set of players connected to one hosted world. A single-player game uses `ctx.player`; a shared-world loop reads `ctx.game.players` so `onTick` can advance every connected hero, not just the one local player. The host (`HostedGameRunner`) drives `join`/`leave`/`setInput`; game code reads `list`/`ids`/`has`/`count`/`input`.
|
|
392
397
|
- `createConnectedPlayers` (function): function createConnectedPlayers(): ConnectedPlayers — Build an empty {@link ConnectedPlayers} registry — the host joins/leaves players; the game loop reads them.
|
|
393
398
|
|
|
399
|
+
## @jgengine/core/game/contentValidation
|
|
400
|
+
|
|
401
|
+
- `ContentEntry` (interface): interface ContentEntry — A definition in a game-owned namespace, located in its authored document.
|
|
402
|
+
- `ContentIssue` (interface): interface ContentIssue — A repairable authoring issue. Paths are caller document locations, usually JSON Pointers.
|
|
403
|
+
- `ContentProgressionInput` (interface): interface ContentProgressionInput — Explicit possible sources; opaque fact strings may represent items, unlocks or skill milestones.
|
|
404
|
+
- `ContentProgressionRequirement` (interface): interface ContentProgressionRequirement — A game-declared availability requirement, located at the content that needs it.
|
|
405
|
+
- `ContentProgressionResult` (interface): interface ContentProgressionResult — Potential availability and diagnostics in deterministic input/traversal order.
|
|
406
|
+
- `ContentProgressionRule` (interface): interface ContentProgressionRule — A possible source or action; all required facts must be reachable to provide its facts.
|
|
407
|
+
- `ContentReference` (interface): interface ContentReference extends ContentEntry — A located reference; namespaces can express game-owned roles such as questgiver.
|
|
408
|
+
- `validateContentProgression` (function): function validateContentProgression(input: ContentProgressionInput): ContentProgressionResult — Check declared potential progression using a dependency queue in O(facts + rules + edges). Alternatives are separate rules; every requirement within one rule is necessary. Seeded cycles are valid. An unseeded cycle is blocked only under the declared sources. Facts describe possible availability, not quantities, consumption, mutually exclusive choices, chronology, station proximity or economic balance. Encode those constraints in game-owned rules or playtests. Skill training caps must be explicitly translated into attainable milestones. This is offline authoring analysis, not a quest engine or a per-frame catalog scan.
|
|
409
|
+
- `validateContentReferences` (function): function validateContentReferences(entries: readonly ContentEntry[], references: readonly ContentReference[]): ContentIssue[] — Index definitions once and check references in input order, without mutating the catalog. Namespace strings and roles are game-owned; identical ids in different namespaces are valid. Typed input must be decoded before calling. Work is O(definitions + references + allowed ids).
|
|
410
|
+
|
|
394
411
|
## @jgengine/core/game/controlGate
|
|
395
412
|
|
|
396
413
|
- `PLAY_CONTROLS_STORE_KEY` (const): const PLAY_CONTROLS_STORE_KEY: "jg.playControls" — ⚠ undocumented
|
|
@@ -398,6 +415,7 @@
|
|
|
398
415
|
- `activeActionCodes` (function): function activeActionCodes(ctx: GameContext, base: ActionCodesMap): ActionCodesMap — Applies active contexts to a base action map for shell input tracking.
|
|
399
416
|
- `playControlsActive` (function): function playControlsActive(ctx: GameContext): boolean — ⚠ undocumented
|
|
400
417
|
- `setPlayControlsActive` (function): function setPlayControlsActive(ctx: GameContext, active: boolean): void — ⚠ undocumented
|
|
418
|
+
- `suspendPlayControls` (function): function suspendPlayControls(ctx: GameContext): () => void — Suspends this context's player controls until the returned release function is called. Independent owners compose; repeated release is safe and preserves the existing play gate. Dispose the lease when its menu closes or its owning context unmounts. Leases survive this context's binding restore and are excluded from saved binding state.
|
|
401
419
|
|
|
402
420
|
## @jgengine/core/game/cosmetics
|
|
403
421
|
|
|
@@ -421,8 +439,9 @@
|
|
|
421
439
|
- `GameDefinition` (interface): interface GameDefinition<TAssetRef extends ModelAssetRef = ModelAssetRef, TMultiplayer = unknown> — Fully-resolved game description produced by {@link defineGameDefinition} — assets, scene, and opted-in subsystems.
|
|
422
440
|
- `GameDefinitionConfig` (type): type GameDefinitionConfig<TAssetRef extends ModelAssetRef = ModelAssetRef, TMultiplayer = unknown> = Omit<GameDefinition<TAssetRef, TMultiplayer>, "scene" | "assets" | "lifecycle"> & { assets?: AssetCatalog<TAssetRef>; /** * The game's run-phase story — a {@link LifecycleConfig} or the `"always-live… — Input to {@link defineGameDefinition} — a `GameDefinition` with `scene` derived and `assets` optional.
|
|
423
441
|
- `GameFeatures` (interface): interface GameFeatures — Opt-in `ctx.game.*` subsystems. Absent = off: the game doesn't carry (or expose) it, and `ctx.game.<name>` is `undefined`. Present (`true`) builds it. The universal base — `commands`, `events`, `store`, `feed` — is always on and not listed here. This is what keeps core genre-agnostic: a puzzle game isn't handed an MMO's leaderboard/roster/turn plumbing it never asked for.
|
|
424
|
-
- `GameLifecycle` (type): type GameLifecycle<TState = unknown> = LifecycleConfig<TState> | "always-live" — How a game declares its run-phase story to {@link defineGameDefinition}. Every game states this explicitly so the shell never has to guess — a silent game used to default to `"playing"`, which painted the touch dock over title/menu/results screens (#1337,
|
|
442
|
+
- `GameLifecycle` (type): type GameLifecycle<TState = unknown> = LifecycleConfig<TState> | "always-live" — How a game declares its run-phase story to {@link defineGameDefinition}. Every game states this explicitly so the shell never has to guess — a silent game used to default to `"playing"`, which painted the touch dock over title/menu/results screens (#1337, Harbor Heat #1329).
|
|
425
443
|
- `GameLoop` (interface): interface GameLoop<TContext = unknown> — Lifecycle hooks a game implements to drive init, per-tick simulation, and player join/leave.
|
|
444
|
+
- `GameProjectileTravelOptions` (interface): interface GameProjectileTravelOptions extends Pick<ProjectileTravelDeps, "maxActive" | "maxRetained"> — Context-aware projectile policy; callbacks are not included in saved shot state.
|
|
426
445
|
- `GameServerConfig` (type): type GameServerConfig = "persistent" | { mode: string; [key: string]: unknown } — Hosting mode for a game's multiplayer server: `"persistent"`, or a custom mode with its own options.
|
|
427
446
|
- `InventoryDeclaration` (interface): interface InventoryDeclaration — Shape of one named inventory a game declares — slot count, accepted item types, HUD binding.
|
|
428
447
|
- `LifecycleConfig` (interface): interface LifecycleConfig<TState = unknown> — Declarative start/restart run lifecycle: the state transitions a game's run phase every genre repeats (title screen → live run → live run → title screen again), expressed as pure functions over one typed {@link StoreHandle} slot instead of hand-rolled `commands.define("start"/"restart")` glue that re-derives phase after every mutation. `start`/`restart` receive the store's own value type — the store's `TState`, never `ctx.game.store.get(key) as T` — and return the next value; the runtime writes it back and derives {@link GamePhase} from it via `phaseOf` in one place, so every adopting game gets identical, correct phase-sync for free.
|
|
@@ -449,6 +468,7 @@
|
|
|
449
468
|
|
|
450
469
|
- `DialogueGraph` (interface): interface DialogueGraph — A serializable branching conversation: a start node id and the nodes it can reach.
|
|
451
470
|
- `DialogueGraphChoice` (interface): interface DialogueGraphChoice — One selectable response on a conversation node — the text a player clicks and the node it advances to. `kind` is a free style tag the presenter interprets; the model never reads it (no genre baked in).
|
|
471
|
+
- `DialogueGraphIssue` (interface): interface DialogueGraphIssue — A structural authoring issue, located in the original graph's node/choice arrays.
|
|
452
472
|
- `DialogueGraphNode` (interface): interface DialogueGraphNode — One conversation node: who is speaking, the line they say, and the branches out of it. `speaker`/`speakerKind`/`portrait` are opaque display data — the model never interprets them.
|
|
453
473
|
- `DialogueGraphSnapshot` (interface): interface DialogueGraphSnapshot — Serializable run state — the current node id and the ids already visited.
|
|
454
474
|
- `DialogueGraphView` (interface): interface DialogueGraphView — The render-ready snapshot of a conversation at one node — everything a view needs to draw speaker, line, and choice buttons, with no traversal logic in the component.
|
|
@@ -456,6 +476,7 @@
|
|
|
456
476
|
- `DialogueRunOptions` (interface): interface DialogueRunOptions — Options for {@link createDialogueRun}.
|
|
457
477
|
- `createDialogueRun` (function): function createDialogueRun(graph: DialogueGraph, options: DialogueRunOptions = {}): DialogueRun — Walk a branching {@link DialogueGraph}: hold the current node, expose its render-ready view, and advance by choosing one of the current node's responses (each choice names the node it leads to; a choice with no `to` ends the conversation). Purely a serializable model — a React host renders `current()` and calls `choose(index)` — so no game re-implements node lookup, choice-to-node traversal, or "am I at the end" bookkeeping. `snapshot`/`restore` round-trip the run through a save.
|
|
458
478
|
- `selectDialogueView` (function): function selectDialogueView(graph: DialogueGraph, nodeId: string): DialogueGraphView | null — Project a {@link DialogueGraph} node id to its render-ready {@link DialogueGraphView} — the pure "current view" selector a stateless renderer reads (speaker, line, choices, done). Returns `null` when the id is not in the graph. No traversal or mutation.
|
|
479
|
+
- `validateDialogueGraph` (function): function validateDialogueGraph(graph: DialogueGraph): DialogueGraphIssue[] — Check authored dialogue references, reachability, and routes to an ending in O(nodes + choices). A node without choices, or a choice with no target, is an ending. Loops with an exit are valid. Duplicate ids and missing references are errors; unreachable nodes and closed loops are warnings because games may jump to nodes or intentionally keep conversations open. Topology uses the first node for each id, matching {@link selectDialogueView}. This does not evaluate story semantics.
|
|
459
480
|
|
|
460
481
|
## @jgengine/core/game/eventTicker
|
|
461
482
|
|
|
@@ -495,7 +516,7 @@
|
|
|
495
516
|
- `LootDrop` (interface): interface LootDrop — One granted reward: an inventory `item` id or a `currency` id, plus how many. Named because every consumer of `loot.granted` needs it — a toast renderer, a loot log, a session summary — and each one that re-declares the shape inline is a cast the compiler cannot check.
|
|
496
517
|
- `LootGrantedEvent` (interface): interface LootGrantedEvent { userId: string; drops: LootDrop[]; source?: string } — ⚠ undocumented
|
|
497
518
|
- `PossessionSwappedEvent` (interface): interface PossessionSwappedEvent { userId: string; entityId: string; previousEntityId: string } — ⚠ undocumented
|
|
498
|
-
- `ProjectileSettledEvent` (interface): interface ProjectileSettledEvent
|
|
519
|
+
- `ProjectileSettledEvent` (interface): interface ProjectileSettledEvent — Exactly-once projectile result for shot-specific game policy and presentation.
|
|
499
520
|
- `QuestAcceptedEvent` (interface): interface QuestAcceptedEvent { userId: string; questId: string } — ⚠ undocumented
|
|
500
521
|
- `QuestCompletedEvent` (interface): interface QuestCompletedEvent { userId: string; questId: string } — ⚠ undocumented
|
|
501
522
|
- `QuestUpdatedEvent` (interface): interface QuestUpdatedEvent { userId: string; questId: string; objectiveId?: string; progress?: number } — ⚠ undocumented
|
|
@@ -537,10 +558,12 @@
|
|
|
537
558
|
## @jgengine/core/game/keyValueStore
|
|
538
559
|
|
|
539
560
|
- `KeyValueStorage` (interface): interface KeyValueStorage — Structural, DOM-free storage backend: the browser `localStorage` satisfies it, as does a test stub or `null`. The one storage seam core primitives target so persistence code never needs the DOM `Storage` lib.
|
|
561
|
+
- `KeyValueStorageErrorPolicy` (interface): interface KeyValueStorageErrorPolicy — Fallback keeps session state after a failed operation; throw exposes failure and preserves the previous cell value. Observers must not throw.
|
|
562
|
+
- `KeyValueStorageFailure` (interface): interface KeyValueStorageFailure — A failed storage operation, retaining the backend's original error and affected key.
|
|
540
563
|
- `KeyValueStore` (interface): interface KeyValueStore<T> — A single persisted, mutable cell: read the current value, overwrite it, or read-modify-write with {@link KeyValueStore.update}. Unlike a record book it has no monotonic guard — the value goes wherever you set it.
|
|
541
|
-
- `KeyValueStoreConfig` (interface): interface KeyValueStoreConfig<T> — Config for {@link createKeyValueStore}: the storage `key`, the `initial` value used before anything is saved, an optional `storage` backend (defaults to `localStorage`, pass `null` for memory-only), and optional custom `serialize`/`deserialize` (default JSON).
|
|
542
|
-
- `createKeyValueStore` (function): function createKeyValueStore<T>(config: KeyValueStoreConfig<T>): KeyValueStore<T> — A
|
|
543
|
-
- `defaultKeyValueStorage` (function): function defaultKeyValueStorage(): KeyValueStorage | null — The ambient `localStorage`
|
|
564
|
+
- `KeyValueStoreConfig` (interface): interface KeyValueStoreConfig<T> extends KeyValueStorageErrorPolicy — Config for {@link createKeyValueStore}: the storage `key`, the `initial` value used before anything is saved, an optional `storage` backend (defaults to `localStorage`, pass `null` for memory-only), and optional custom `serialize`/`deserialize` (default JSON).
|
|
565
|
+
- `createKeyValueStore` (function): function createKeyValueStore<T>(config: KeyValueStoreConfig<T>): KeyValueStore<T> — A mutable local save cell through {@link KeyValueStorage}. Default fallback keeps session state on failure; `errorMode: "throw"` exposes failed reads/writes/removals through the original error. `storage: null` deliberately uses memory only.
|
|
566
|
+
- `defaultKeyValueStorage` (function): function defaultKeyValueStorage(onError?: (error: unknown) => void): KeyValueStorage | null — The ambient `localStorage` when available, otherwise `null`. An optional observer receives denied getter errors; it may rethrow to reject fallback. Never references the DOM `Storage` type, so it is safe in core.
|
|
544
567
|
|
|
545
568
|
## @jgengine/core/game/leaderboard
|
|
546
569
|
|
|
@@ -590,6 +613,11 @@
|
|
|
590
613
|
- `evaluateLootFilter` (function): function evaluateLootFilter(rules: readonly LootFilterRule[], item: LootFilterItem): LootFilterOverride — First matching rule wins (PoE/Last Epoch block semantics) — later rules never override an earlier match. Returns overrides only; fields the rule doesn't set are left for the caller's baseline (rarity style) to fill in.
|
|
591
614
|
- `lootFilter` (function): function lootFilter(rules: readonly LootFilterRule[]): readonly LootFilterRule[] — Validating factory — rule ids must be unique so authoring mistakes fail loudly.
|
|
592
615
|
|
|
616
|
+
## @jgengine/core/game/lootModifiers
|
|
617
|
+
|
|
618
|
+
- `TimeScaledRarityOptions` (interface): interface TimeScaledRarityOptions — Caller-authored weighting curve; item ids, quality tiers and balance never live in the modifier.
|
|
619
|
+
- `timeScaledRarity` (function): function timeScaledRarity<TCtx extends { elapsedMs: number }>(options: TimeScaledRarityOptions): LootModifier<TCtx> — Multiply weighted odds (or independent chances, clamped to one) by a caller-authored elapsed-time curve. Keeps source tables unchanged and uses the existing pipeline's modifier provenance. Elapsed time and multipliers must be finite and nonnegative; invalid curves reject the roll.
|
|
620
|
+
|
|
593
621
|
## @jgengine/core/game/lootPipeline
|
|
594
622
|
|
|
595
623
|
- `LootDropProvenance` (interface): interface LootDropProvenance — Why one drop is in the result: the stage/table/entry that produced it, its weights, and the modifiers that shaped it.
|
|
@@ -624,6 +652,17 @@
|
|
|
624
652
|
- `AUTO_ONE_SHOT_EVENTS` (const): const AUTO_ONE_SHOT_EVENTS: readonly ["hit", "death"] — The two one-shot events the shell fires automatically for an entity, from `combat.hitReaction` and `entity.died`.
|
|
625
653
|
- `resolveOneShotClip` (function): function resolveOneShotClip(oneShots: Record<string, string | readonly string[]> | undefined, event: string, roll: number): string | null — Resolves the clip name a one-shot `event` should play from a model's `animation.oneShots` map, or `null` if the event isn't bound. A `string[]` binding picks a variant by `roll` (a value in `[0, 1)`), so combat can vary attack swings. Pure and deterministic given `roll` — the shell supplies the randomness.
|
|
626
654
|
|
|
655
|
+
## @jgengine/core/game/narrativeAuthoring
|
|
656
|
+
|
|
657
|
+
- `NarrativeBatch` (interface): interface NarrativeBatch — A candidate batch never changes canon; accepted new facts need a separately reviewed revision.
|
|
658
|
+
- `NarrativeBatchLimits` (interface): interface NarrativeBatchLimits — Caller budgets across the entire batch, including graph branches and explicit assertions.
|
|
659
|
+
- `NarrativeCanon` (interface): interface NarrativeCanon — Caller-reviewed facts for one authoring revision; event ids are in strict chronological order.
|
|
660
|
+
- `NarrativeClaim` (type): type NarrativeClaim = { readonly nodeId: string } & ( | { readonly kind: "character"; readonly characterId: string } | { readonly kind: "fact"; readonly factId: string; readonly value: string } | { readonly kind: "before"; readonly earlier: string; readonly later: string } ) — An explicit assertion attached to a dialogue node; dialogue prose is never parsed.
|
|
661
|
+
- `NarrativeDialogue` (interface): interface NarrativeDialogue — Authored dialogue with optional structured assertions against canon.
|
|
662
|
+
- `NarrativeIssue` (interface): interface NarrativeIssue — A repair diagnostic with a JSON-pointer location in the candidate batch.
|
|
663
|
+
- `freezeNarrativeCanon` (function): function freezeNarrativeCanon(canon: NarrativeCanon): NarrativeCanon — Detach and freeze reviewed canon before passing it to an asynchronous authoring callback. Duplicate character/event ids and an empty revision throw; facts retain exact caller values.
|
|
664
|
+
- `validateNarrativeBatch` (function): function validateNarrativeBatch(canon: NarrativeCanon, batch: NarrativeBatch, limits: NarrativeBatchLimits): NarrativeIssue[] — Check a typed candidate against caller budgets, canon revision, explicit claims and graph topology. Stops at the first exceeded budget before topology work; stale revisions also stop immediately. Claims check exact fact values and the declared strict event order, never prose, speaker labels, motivations, branch consequences or story quality. O(canon + bounded nodes + choices + claims). Validate/parse external JSON before calling; this is not an untrusted JSON decoder.
|
|
665
|
+
|
|
627
666
|
## @jgengine/core/game/notifications
|
|
628
667
|
|
|
629
668
|
- `NotificationCenterOptions` (interface): interface NotificationCenterOptions — Options for {@link createNotificationCenter}.
|
|
@@ -724,10 +763,10 @@
|
|
|
724
763
|
- `ModelAnimationConfig` (interface): interface ModelAnimationConfig — Rig playback for a `ModelConfig`'s GLTF animation clips — looping idles, one-shots, and held poses.
|
|
725
764
|
- `ModelAnimationStates` (interface): interface ModelAnimationStates — Movement-state clip set for `ModelAnimationConfig.states`: the shell reads the entity's live speed each frame and crossfades between these clips, so a walking mob animates without any game-side driver.
|
|
726
765
|
- `ModelAttachment` (interface): interface ModelAttachment — Parents a prop/weapon model to a named bone or node on the host model's rig — a sword on `handslot.r`, a spellbook offhand — following the bone's animated transform each frame.
|
|
727
|
-
- `ModelConfig` (interface): interface ModelConfig { url: string; scale?: number; targetHeight?: number; y?: number; anchor?: "center" | "origin"; dims?: ModelDims; collisionMesh?: CollisionMeshData; material?: ModelMaterialOverride;
|
|
766
|
+
- `ModelConfig` (interface): interface ModelConfig { url: string; scale?: number; targetHeight?: number; y?: number; anchor?: "center" | "origin"; dims?: ModelDims; collisionMesh?: CollisionMeshData; material?: ModelMaterialOverride; materialAssets?: readonly MaterialAsset[]; materialAssign… — ⚠ undocumented · used by `PartMotionRig` (@jgengine/shell/render/PartMotion): Procedural motion rig for a rig-less part-composed character (`ModelPart.role` — see `@jgengine/core/game/partAnimation`).
|
|
728
767
|
- `ModelIkConfig` (interface): interface ModelIkConfig — Bone names and limits for {@link ModelConfig.ik}.
|
|
729
|
-
- `ModelMaterialMaps` (interface): interface ModelMaterialMaps — Real PBR map URLs (e.g. `buildMaterialCatalog(...).resolve(id)!.maps` from `@jgengine/assets`) layered onto a model's material — the seam for texturing an otherwise-flat/untextured GLB. Any
|
|
730
|
-
- `ModelMaterialOverride` (interface): interface ModelMaterialOverride — Per-entity PBR material override (#151.3) applied to every standard or physical material in the model's cloned scene graph.
|
|
768
|
+
- `ModelMaterialMaps` (interface): interface ModelMaterialMaps extends Partial<Record<MaterialTextureRole, string>> — Real PBR map URLs (e.g. `buildMaterialCatalog(...).resolve(id)!.maps` from `@jgengine/assets`) layered onto a model's material — the seam for texturing an otherwise-flat/untextured GLB. Any supported MaterialTextureRole may be omitted to keep the model's own map. Physical roles use the renderer's physical material; map URLs and response parameters remain caller-owned.
|
|
769
|
+
- `ModelMaterialOverride` (interface): interface ModelMaterialOverride extends MaterialSurfaceParameters — Per-entity PBR material override (#151.3) applied to every standard or physical material in the model's cloned scene graph.
|
|
731
770
|
- `ModelPart` (interface): interface ModelPart — Static child model stacked at a fixed local offset under its parent's transform — no bone/rig resolution, unlike `ModelAttachment`. Assembles a compound entity (e.g. a modular castle wall + tower + roof) from several single-mesh kit pieces.
|
|
732
771
|
- `ModelRimLight` (interface): interface ModelRimLight — Fresnel rim-light term added on top of a model's lighting — see {@link ModelMaterialOverride.rim}.
|
|
733
772
|
- `MovementCommitFrame` (interface): interface MovementCommitFrame — One frame's movement resolution handed to `PlayerMovementConfig.beforeCommit`.
|
|
@@ -774,18 +813,26 @@
|
|
|
774
813
|
- `QuestJournalDeps` (interface): interface QuestJournalDeps { events: GameEvents; rewards: {grantXp(userId: string, amount: number): void; grantEconomy(userId: string, currencyId: string, amount: number): void; grantItem(userId: string, inventoryId: string, itemId: string, count: number): {reason: s… — ⚠ undocumented · used by `createQuestJournal`: Track accepted quests and their per-objective progress, granting rewards on completion.
|
|
775
814
|
- `QuestObjective` (interface): interface QuestObjective { id: string; kind: "kill" | "collect" | string; target?: string; item?: string; count: number; partyShare?: {radius: number; credit: "all" | "tagger"} } — ⚠ undocumented · used by `defaultObjectiveLabel`: Default objective label: a readable "verb count noun" from a {@link QuestObjective}.
|
|
776
815
|
- `QuestObjectiveProgress` (interface): interface QuestObjectiveProgress { id: string; kind: string; count: number; progress: number; complete: boolean } — ⚠ undocumented
|
|
777
|
-
- `QuestRewards` (interface): interface QuestRewards { xp?: {amount: number}; economy?: Record<string, number>; items?: {item: string; count: number; inventory: string}[]; unlocks?: string[]; quests?: string[] } — ⚠ undocumented
|
|
816
|
+
- `QuestRewards` (interface): interface QuestRewards { xp?: {amount: number}; economy?: Record<string, number>; items?: {item: string; count: number; inventory: string}[]; unlocks?: string[]; quests?: string[] } — ⚠ undocumented · used by `applyQuestRewards`: Apply items before XP, currency, and unlocks.
|
|
778
817
|
- `QuestSnapshotEntry` (type): type QuestSnapshotEntry = { questId: string; status: QuestStatus; progress: Record<string, number>; } — ⚠ undocumented
|
|
779
818
|
- `QuestStatus` (type): type QuestStatus = "active" | "completed" — ⚠ undocumented
|
|
780
819
|
- `QuestTurnIn` (interface): interface QuestTurnIn { state: QuestSnapshotEntry[]; rewards: QuestRewards | null } — ⚠ undocumented
|
|
781
820
|
- `TrackedObjectiveView` (interface): interface TrackedObjectiveView — One objective as a tracker/HUD reads it — label + progress toward its count.
|
|
782
821
|
- `TrackedQuestView` (interface): interface TrackedQuestView — A quest as a tracker/HUD reads it — title, status, and per-objective progress.
|
|
783
|
-
- `applyQuestRewards` (function): function applyQuestRewards(rewards: QuestRewards, appliers: { grantXp?(amount: number): void; grantEconomy?(currencyId: string, amount: number): void; grantItem?(inventoryId: string, itemId: string, count: number): { reason: string } | null | void;
|
|
822
|
+
- `applyQuestRewards` (function): function applyQuestRewards(rewards: QuestRewards, appliers: { grantXp?(amount: number): void; grantEconomy?(currencyId: string, amount: number): void; grantItem?(inventoryId: string, itemId: string, count: number): { reason: string } | null | void; /** Grant every item, or reject without writes. Tak… — Apply items before XP, currency, and unlocks. Multiple items require an all-or-reject `grantItems` callback; legacy single-item appliers remain supported. Rejected callbacks must make no writes. Arbitrary callback side effects or thrown exceptions cannot be rolled back by this helper.
|
|
784
823
|
- `createQuestEvaluator` (function): function createQuestEvaluator(defs: QuestDef[] | Record<string, QuestDef>): QuestEvaluator — ⚠ undocumented
|
|
785
824
|
- `createQuestJournal` (function): function createQuestJournal(deps: QuestJournalDeps): QuestJournal — Track accepted quests and their per-objective progress, granting rewards on completion.
|
|
786
825
|
- `defaultObjectiveLabel` (function): function defaultObjectiveLabel(objective: QuestObjective): string — Default objective label: a readable "verb count noun" from a {@link QuestObjective}.
|
|
787
826
|
- `describeTrackedQuest` (function): function describeTrackedQuest(def: QuestDef, instance: QuestInstance, label: (objective: QuestObjective) => string = defaultObjectiveLabel): TrackedQuestView — Join a quest's static {@link QuestDef} with a player's live {@link QuestInstance} into a flat, renderer-free view a HUD tracker draws (title, status, labelled objective progress). Pass `label` to override the derived objective text.
|
|
788
827
|
|
|
828
|
+
## @jgengine/core/game/questCatalog
|
|
829
|
+
|
|
830
|
+
- `QuestCatalogDefinition` (type): type QuestCatalogDefinition = Omit<Readonly<QuestDef>, "requires" | "objectives" | "rewards"> & { requires?: readonly string[]; objectives: readonly Readonly<QuestObjective>[]; rewards?: Omit<Readonly<QuestRewards>, "items" | "unlocks" | "quests"> & { items?: readonly Readonly<NonNullable<QuestRewar… — Readonly authoring input; mutable QuestDef catalogs also satisfy this shape.
|
|
831
|
+
- `QuestCatalogIssue` (interface): interface QuestCatalogIssue — A located structural issue; path is a JSON Pointer into the supplied catalog.
|
|
832
|
+
- `QuestCatalogReferenceKind` (type): type QuestCatalogReferenceKind = "item" | "target" | "inventory" | "currency" — Caller-owned reference namespaces; objective kinds remain unconstrained.
|
|
833
|
+
- `QuestCatalogValidationOptions` (interface): interface QuestCatalogValidationOptions — Declarations and optional lookups for a game's own authoring rules.
|
|
834
|
+
- `validateQuestCatalog` (function): function validateQuestCatalog(catalog: readonly QuestCatalogDefinition[] | Readonly<Record<string, QuestCatalogDefinition>>, options: QuestCatalogValidationOptions = {}): QuestCatalogIssue[] — Validate catalog ids, references, quantities, and potential prerequisite progression without mutation. Requirements are completed quest ids OR unlock ids; all requirements of a quest must be met. Any eligible quest may be accepted directly. External unlocks and granted quest starts are possible entry points, not claims about their timing. Blocked progression/cycles are warnings: game systems can bypass prerequisites. Topology uses the last duplicate, matching journal registration. Traversal is iterative and linear in definitions, requirements, and their producer edges. Objective and item counts may be fractional or zero; negative/nonfinite counts are invalid. This assumes objectives can be completed and does not evaluate narrative, chronology, or balance.
|
|
835
|
+
|
|
789
836
|
## @jgengine/core/game/race
|
|
790
837
|
|
|
791
838
|
- `Checkpoint` (interface): interface Checkpoint { id: string; center: readonly [number, number, number]; half: readonly [number, number, number] } — ⚠ undocumented
|
|
@@ -867,12 +914,12 @@
|
|
|
867
914
|
- `SaveAutoConfig` (interface): interface SaveAutoConfig — Autosave cadence: debounce writes `debounceMs` after the last edit, but never wait longer than `maxWaitMs` while edits keep coming (`0` removes the ceiling). `autosave: true` uses `{ debounceMs: 1000, maxWaitMs: 15000 }`.
|
|
868
915
|
- `SaveBackend` (interface): interface SaveBackend — The one async storage seam a save store persists through. Every backend satisfies this same three-method shape — the browser's `localStorage` (offline), an in-memory map (tests/SSR), or a database/Convex/HTTP endpoint (cloud) — so a game switches offline saves for cloud saves by swapping the backend and changing nothing else. Keys are opaque namespaced strings; values are already-serialized strings, so a backend never needs to know the save shape.
|
|
869
916
|
- `SaveEnvelope` (interface): interface SaveEnvelope<T> — The versioned envelope written to the backend — `version` lets a later game build detect and {@link SaveStoreConfig.migrate | migrate} an older payload.
|
|
870
|
-
- `SaveStatus` (type): type SaveStatus = "idle" | "loading" | "saving" | "saved" | "error" — Lifecycle of the last save/load — drive a "Saving…"/"Saved" indicator or a loading gate off it. `"error"`
|
|
917
|
+
- `SaveStatus` (type): type SaveStatus = "idle" | "loading" | "saving" | "saved" | "error" — Lifecycle of the last save/load — drive a "Saving…"/"Saved" indicator or a loading gate off it. `"error"` includes rejected reads, writes, removals and slot metadata updates; metadata failure can follow a successful payload write.
|
|
871
918
|
- `SaveStore` (interface): interface SaveStore<T> — A pluggable-backend game save with autosave, named slots, and versioned migration. `value()`/`patch()` hold the live state; `load()` hydrates it from the backend; `save()` (or autosave) writes it back. Backend failures surface as `"error"` status and through `onError` — a save never throws into a tick.
|
|
872
919
|
- `SaveStoreConfig` (interface): interface SaveStoreConfig<T> — How a {@link createSaveStore} is wired — the backend it persists through, the initial value, and optional slot/versioning/autosave/serialization knobs.
|
|
873
920
|
- `SaveTimers` (interface): interface SaveTimers — The timer seam autosave schedules through — defaults to the ambient `setTimeout`/`clearTimeout`; inject fakes in tests.
|
|
874
921
|
- `createSaveStore` (function): function createSaveStore<T>(config: SaveStoreConfig<T>): SaveStore<T> — Create a {@link SaveStore}. Same call for offline and cloud — only the `backend` differs (localStorage, memory, or an async DB/Convex endpoint). Turn on `autosave` and every `set`/`patch` persists on a debounce; leave it off and call `save()` at checkpoints. Bump `version` + pass `migrate` when the save shape changes so old players keep their progress.
|
|
875
|
-
- `localSaveBackend` (function): function localSaveBackend(storage?: KeyValueStorage | null): SaveBackend — A {@link SaveBackend} over a synchronous {@link KeyValueStorage} — the browser's `localStorage` by default (offline, on-device saves), a test stub, or `null` for
|
|
922
|
+
- `localSaveBackend` (function): function localSaveBackend(storage?: KeyValueStorage | null, policy: KeyValueStorageErrorPolicy = {}): SaveBackend — A {@link SaveBackend} over a synchronous {@link KeyValueStorage} — the browser's `localStorage` by default (offline, on-device saves), a test stub, or `null` for a no-op backend. Default fallback ignores failures; `errorMode: "throw"` rejects failed operations and unavailable storage, so SaveStore status/onError can report them. Use {@link memorySaveBackend} for deliberate ephemeral persistence.
|
|
876
923
|
- `memorySaveBackend` (function): function memorySaveBackend(): SaveBackend — A memory-only {@link SaveBackend} — saves survive a reload only within the same session. For tests, SSR, or a "no persistence" mode that still exercises the same save code path.
|
|
877
924
|
- `remoteSaveBackend` (function): function remoteSaveBackend(backend: SaveBackend): SaveBackend — Adopt any async `read`/`write`/`remove` trio as a {@link SaveBackend} — the seam for cloud saves backed by a database, an HTTP endpoint, or Convex (see `@jgengine/convex/convexSaveBackend`). Reads/writes may reject; the save store surfaces the failure as `"error"` status instead of throwing.
|
|
878
925
|
|
|
@@ -1079,7 +1126,7 @@
|
|
|
1079
1126
|
- `CardPile` (interface): interface CardPile { state(): CardPileState; zones(): readonly ZoneName[]; count(zone: ZoneName): number; peek(zone: ZoneName, n?: number): readonly string[]; zoneOf(cardId: string): ZoneName | null; shuffle(zone: ZoneName | undefined, seed: string | number):… — ⚠ undocumented
|
|
1080
1127
|
- `CardPileState` (interface): interface CardPileState { readonly zones: Readonly<Record<ZoneName, readonly string[]>> } — ⚠ undocumented · used by `CardStack` (@jgengine/react): `StackedPile` bound to a headless `CardPileState` zone: reads the ordered card ids from `pile.zones[zone]` and resolves each to a `PlayingCa…
|
|
1081
1128
|
- `CatchUpPolicy` (type): type CatchUpPolicy = "each" | "sum" | "skip" — How cycles that came due between two {@link advanceLedger} calls are settled: - `"each"` — replay every missed cycle as its own transaction (bounded by the limits below); - `"sum"` — collapse the missed cycles into one transaction of the combined amount; - `"skip"` — apply only the most recent cycle and discard the rest (idle income that does not bank).
|
|
1082
|
-
- `Cell` (type): type Cell = readonly [number, number] — ⚠ undocumented
|
|
1129
|
+
- `Cell` (type): type Cell = readonly [number, number] — ⚠ undocumented · used by `canPlace` (@jgengine/core/inventory/shapedGrid): Check bounds and overlap for a discrete footprint, optionally ignoring the item being moved.
|
|
1083
1130
|
- `CellGrid` (interface): interface CellGrid<T> — A fixed-size 2D board of cells, row-major from the top-left; `null` is an empty cell. Plain data, so it serializes and restores as-is.
|
|
1084
1131
|
- `ChargeOptions` (interface): interface ChargeOptions — Options for {@link charge}/{@link chargeAll}: opt one call into overdraft debt via `overdraft`.
|
|
1085
1132
|
- `ChargeResult` (type): type ChargeResult = { status: "ok"; state: WalletState } | { status: "rejected"; reason: "insufficient-funds" } — Outcome of a {@link charge}/{@link chargeAll} attempt: `status: "ok"` carries the debited {@link WalletState}, while `status: "rejected"` leaves the wallet untouched and reports why (currently only `"insufficient-funds"`). Discriminate on `status` before reading `state`.
|
|
@@ -1142,6 +1189,12 @@
|
|
|
1142
1189
|
- `EventTickerOptions` (interface): interface EventTickerOptions — Options for {@link createEventTicker}.
|
|
1143
1190
|
- `EventTickerSnapshot` (interface): interface EventTickerSnapshot — Serializable state of the ticker, for save/restore.
|
|
1144
1191
|
- `EventTickerView` (interface): interface EventTickerView extends EventTickerEntry — A live ticker entry as handed to the renderer: the stored entry plus a `fade` value `0..1` (age / `ttlMs`) — `0` for a fresh entry, approaching `1` as it nears expiry — so the UI can drop opacity as an entry ages out. `fade` is always `0` when no `ttlMs` is configured.
|
|
1192
|
+
- `ExpeditionConfig` (interface): interface ExpeditionConfig<TCtx> — Runtime policy, supplied on each transition and never saved. Callbacks must be pure.
|
|
1193
|
+
- `ExpeditionDispatch` (interface): interface ExpeditionDispatch — Dispatch data, detached from the caller's supply record. All timestamps are epoch milliseconds.
|
|
1194
|
+
- `ExpeditionEvent` (interface): interface ExpeditionEvent — Timestamped serializable event. `at` is epoch milliseconds, compatible with `appendFeed`.
|
|
1195
|
+
- `ExpeditionHazard` (interface): interface ExpeditionHazard — One encounter's mechanical effects and optional caller-authored notices.
|
|
1196
|
+
- `ExpeditionState` (interface): interface ExpeditionState — Plain saveable expedition data. Persist this whole value, including the RNG cursor and tick frontier.
|
|
1197
|
+
- `ExpeditionSupplyRule` (interface): interface ExpeditionSupplyRule — Ordered auto-consumption rule: spends one finite supply only when its declared effect changes a vital.
|
|
1145
1198
|
- `FeedEntry` (interface): interface FeedEntry<T = unknown> { at: number; data: T } — ⚠ undocumented · used by `ToastStack` (@jgengine/react): Render `ctx.game.feed`'s entries for `action` as a newest-first toast stack — the feed-backed sibling of `@jgengine/core/game/toasts`' `crea…
|
|
1146
1199
|
- `FeedWindow` (interface): interface FeedWindow — Bounds for {@link appendFeed} / {@link pruneFeed}: newest-`limit` cap and/or `ttl` age window.
|
|
1147
1200
|
- `FiringBlock` (type): type FiringBlock = "predicate" | "no-target" | "cooldown" | "rate-limit" | "no-charges" | "stack-ignored" — Reason a firing did not produce an effect — surfaced for debug inspection, never thrown.
|
|
@@ -1155,7 +1208,7 @@
|
|
|
1155
1208
|
- `GameDefinitionConfig` (type): type GameDefinitionConfig<TAssetRef extends ModelAssetRef = ModelAssetRef, TMultiplayer = unknown> = Omit<GameDefinition<TAssetRef, TMultiplayer>, "scene" | "assets" | "lifecycle"> & { assets?: AssetCatalog<TAssetRef>; /** * The game's run-phase story — a {@link LifecycleConfig} or the `"always-live… — Input to {@link defineGameDefinition} — a `GameDefinition` with `scene` derived and `assets` optional.
|
|
1156
1209
|
- `GameEventMap` (interface): interface GameEventMap { "entity.died": EntityDiedEvent; "entity.floatText": EntityFloatTextEvent; "combat.telegraph": CombatTelegraphEvent; "combat.vfx": CombatVfxEvent; "combat.vfxInstance": CombatVfxInstanceEvent; "combat.telegraphCancelled": CombatTelegraphCa… — ⚠ undocumented · used by `createGameEvents`: A typed publish/subscribe bus for gameplay events that systems and HUDs subscribe to.
|
|
1157
1210
|
- `GameEvents` (interface): interface GameEvents<TMap extends GameEventMap = GameEventMap> { on<TName extends keyof TMap>(name: TName, handler: GameEventHandler<TMap[TName]>): () => void; subscribe<TName extends keyof TMap>(name: TName, handler: GameEventHandler<TMap[TName]>): () => void; emit<TName extends keyof TMap>(name: TNam… — ⚠ undocumented · used by `createGameEvents`: A typed publish/subscribe bus for gameplay events that systems and HUDs subscribe to.
|
|
1158
|
-
- `GameLifecycle` (type): type GameLifecycle<TState = unknown> = LifecycleConfig<TState> | "always-live" — How a game declares its run-phase story to {@link defineGameDefinition}. Every game states this explicitly so the shell never has to guess — a silent game used to default to `"playing"`, which painted the touch dock over title/menu/results screens (#1337,
|
|
1211
|
+
- `GameLifecycle` (type): type GameLifecycle<TState = unknown> = LifecycleConfig<TState> | "always-live" — How a game declares its run-phase story to {@link defineGameDefinition}. Every game states this explicitly so the shell never has to guess — a silent game used to default to `"playing"`, which painted the touch dock over title/menu/results screens (#1337, Harbor Heat #1329).
|
|
1159
1212
|
- `GameLoop` (interface): interface GameLoop<TContext = unknown> — Lifecycle hooks a game implements to drive init, per-tick simulation, and player join/leave.
|
|
1160
1213
|
- `GamePhase` (type): type GamePhase = "menu" | "playing" | "paused" | "ended" — Canonical run phase every game moves through. `menu` (title/main menu), `playing` (live), `paused` (mid-run pause), `ended` (win/lose/results). Touch controls are shown only while `playing`; menus and results never paint the touch dock over themselves.
|
|
1161
1214
|
- `GenChoiceRecord` (interface): interface GenChoiceRecord — Provenance for one resolved step: which option stuck, its effective weight, how many options were eligible after constraints, and how many eligible options backtracking rejected before this one. A skipped optional step is recorded with an empty `optionId`.
|
|
@@ -1222,9 +1275,9 @@
|
|
|
1222
1275
|
- `LootStageStatus` (type): type LootStageStatus = "rolled" | "skipped" | "empty" | "replaced" | "fell-through" — The disposition of a stage after resolution — did it roll, get gated, fall through, override, or find nothing.
|
|
1223
1276
|
- `LootStageTrace` (interface): interface LootStageTrace — Per-stage record of what happened during resolution, for debugging and replay auditing.
|
|
1224
1277
|
- `LootTableDef` (interface): interface LootTableDef — A named, validated loot table — its roll count, weighted-vs-independent mode, and candidate entries.
|
|
1225
|
-
- `ModelConfig` (interface): interface ModelConfig { url: string; scale?: number; targetHeight?: number; y?: number; anchor?: "center" | "origin"; dims?: ModelDims; collisionMesh?: CollisionMeshData; material?: ModelMaterialOverride;
|
|
1226
|
-
- `ModelMaterialMaps` (interface): interface ModelMaterialMaps — Real PBR map URLs (e.g. `buildMaterialCatalog(...).resolve(id)!.maps` from `@jgengine/assets`) layered onto a model's material — the seam for texturing an otherwise-flat/untextured GLB. Any
|
|
1227
|
-
- `ModelMaterialOverride` (interface): interface ModelMaterialOverride — Per-entity PBR material override (#151.3) applied to every standard or physical material in the model's cloned scene graph.
|
|
1278
|
+
- `ModelConfig` (interface): interface ModelConfig { url: string; scale?: number; targetHeight?: number; y?: number; anchor?: "center" | "origin"; dims?: ModelDims; collisionMesh?: CollisionMeshData; material?: ModelMaterialOverride; materialAssets?: readonly MaterialAsset[]; materialAssign… — ⚠ undocumented · used by `PartMotionRig` (@jgengine/shell/render/PartMotion): Procedural motion rig for a rig-less part-composed character (`ModelPart.role` — see `@jgengine/core/game/partAnimation`).
|
|
1279
|
+
- `ModelMaterialMaps` (interface): interface ModelMaterialMaps extends Partial<Record<MaterialTextureRole, string>> — Real PBR map URLs (e.g. `buildMaterialCatalog(...).resolve(id)!.maps` from `@jgengine/assets`) layered onto a model's material — the seam for texturing an otherwise-flat/untextured GLB. Any supported MaterialTextureRole may be omitted to keep the model's own map. Physical roles use the renderer's physical material; map URLs and response parameters remain caller-owned.
|
|
1280
|
+
- `ModelMaterialOverride` (interface): interface ModelMaterialOverride extends MaterialSurfaceParameters — Per-entity PBR material override (#151.3) applied to every standard or physical material in the model's cloned scene graph.
|
|
1228
1281
|
- `ModularItemDef` (interface): interface ModularItemDef { id: string; baseStats: Record<string, number>; slots: readonly MountSlotDef[] } — ⚠ undocumented
|
|
1229
1282
|
- `Moodle` (interface): interface Moodle — One survival moodle (status icon) — severity, source, and label for HUD chips.
|
|
1230
1283
|
- `MoodleStack` (interface): interface MoodleStack — Ordered stack of active moodles derived from meters/ailments/buffs.
|
|
@@ -1271,7 +1324,7 @@
|
|
|
1271
1324
|
- `PriceStats` (interface): interface PriceStats — Aggregated market stats for one item over the retained samples.
|
|
1272
1325
|
- `QuestDef` (interface): interface QuestDef { id: string; title: string; description?: string; giver?: string; turnIn?: string; requires?: string[]; objectives: QuestObjective[]; rewards?: QuestRewards } — ⚠ undocumented · used by `describeTrackedQuest`: Join a quest's static {@link QuestDef} with a player's live {@link QuestInstance} into a flat, renderer-free view a HUD tracker draws (title…
|
|
1273
1326
|
- `QuestInstance` (interface): interface QuestInstance { questId: string; status: QuestStatus; objectives: QuestObjectiveProgress[] } — ⚠ undocumented · used by `describeTrackedQuest`: Join a quest's static {@link QuestDef} with a player's live {@link QuestInstance} into a flat, renderer-free view a HUD tracker draws (title…
|
|
1274
|
-
- `QuestRewards` (interface): interface QuestRewards { xp?: {amount: number}; economy?: Record<string, number>; items?: {item: string; count: number; inventory: string}[]; unlocks?: string[]; quests?: string[] } — ⚠ undocumented
|
|
1327
|
+
- `QuestRewards` (interface): interface QuestRewards { xp?: {amount: number}; economy?: Record<string, number>; items?: {item: string; count: number; inventory: string}[]; unlocks?: string[]; quests?: string[] } — ⚠ undocumented · used by `applyQuestRewards` (@jgengine/core/game/quest): Apply items before XP, currency, and unlocks.
|
|
1275
1328
|
- `RaceState` (class): class RaceState — Race state machine (issue #87). Drive it each tick with `update(now, positions)` — `now` is game time (`ctx.time`), `positions` maps each racer to a world point tested against the ordered checkpoint volumes. It emits `checkpoint.hit` / `lap.completed` / `position.changed` / `race.finished`, keeps cumulative split times for PB deltas, resolves a pluggable win condition (first-past-post, round-cut, derby last-standing), and `resetToCheckpoint` hands back a respawn pose at the racer's last checkpoint. `removeRacer` drops a racer mid-race and `reset` returns the whole instance to its pre-race state for reuse.
|
|
1276
1329
|
- `RankLeaderboardOptions` (interface): interface RankLeaderboardOptions — Options for {@link rankLeaderboard}. All optional.
|
|
1277
1330
|
- `RankableRow` (interface): interface RankableRow — A single input score to rank. Accepts the raw shape produced by {@link LeaderboardRow} (a `LeaderboardRow` is assignable to this) as well as a minimal `{ userId, value }` pair with an optional display `label` the game owns.
|
|
@@ -1286,7 +1339,7 @@
|
|
|
1286
1339
|
- `RebindSessionConfig` (type): type RebindSessionConfig = RebindSessionActionsConfig | RebindSessionMapConfig — Config for {@link createRebindSession}: an explicit action list, or an {@link ActionCodesMap} + labels.
|
|
1287
1340
|
- `RebindSessionMapConfig` (interface): interface RebindSessionMapConfig extends RebindSessionCommon — Declare actions from an authored {@link ActionCodesMap}, labelled by `labels` (falling back to the id).
|
|
1288
1341
|
- `RebindSessionSnapshot` (interface): interface RebindSessionSnapshot — Serializable session state for save/restore.
|
|
1289
|
-
- `RecipeDef` (interface): interface RecipeDef { id: string; inputs: readonly RecipeItem[]; outputs: readonly RecipeItem[]; seconds?: number; station?: string; stationRange?: number; requires?: readonly string[]; category?: string } — ⚠ undocumented
|
|
1342
|
+
- `RecipeDef` (interface): interface RecipeDef { id: string; inputs: readonly RecipeItem[]; outputs: readonly RecipeItem[]; seconds?: number; station?: string; stationRange?: number; requires?: readonly string[]; category?: string } — ⚠ undocumented · used by `validateRecipeCatalog` (@jgengine/core/crafting/recipeCatalog): Validate native recipes before registration: ids, counts, timing and caller-catalog references.
|
|
1290
1343
|
- `RecipeItem` (interface): interface RecipeItem { itemId: string; count: number } — ⚠ undocumented
|
|
1291
1344
|
- `RequireRule` (interface): interface RequireRule — A rule that requires a second condition to hold whenever the first matches — e.g. "a scoped rifle requires a stock". Checked at completeness time, not during incremental placement, because the `then` side may be satisfied by a part chosen later in a generation pass.
|
|
1292
1345
|
- `ResourceCost` (type): type ResourceCost = Readonly<Record<string, number>> — Resource costs keyed by currency/resource id.
|
|
@@ -1298,7 +1351,7 @@
|
|
|
1298
1351
|
- `RingConfig` (interface): interface RingConfig { center: RingPoint; phases: readonly RingPhase[] } — ⚠ undocumented
|
|
1299
1352
|
- `RingPhase` (interface): interface RingPhase { startTime: number; shrinkDuration: number; fromRadius: number; toRadius: number; damagePerSecond: number; center?: RingPoint } — ⚠ undocumented
|
|
1300
1353
|
- `RoleSpec` (interface): interface RoleSpec { id: string; count?: number; ratio?: number } — ⚠ undocumented
|
|
1301
|
-
- `Rotation` (type): type Rotation = 0 | 1 | 2 | 3 — ⚠ undocumented
|
|
1354
|
+
- `Rotation` (type): type Rotation = 0 | 1 | 2 | 3 — ⚠ undocumented · used by `canPlace` (@jgengine/core/inventory/shapedGrid): Check bounds and overlap for a discrete footprint, optionally ignoring the item being moved.
|
|
1302
1355
|
- `RoundConfig` (interface): interface RoundConfig<TPhase extends string = RoundPhase> { phases: Record<TPhase, number>; teams: readonly string[] | readonly RoundTeam[]; phaseOrder?: readonly TPhase[]; winCondition?: (state: RoundSnapshot<TPhase>) => string | null; maxRounds?: number; winReward?: number; lossBonus?: LossBonus… — ⚠ undocumented
|
|
1303
1356
|
- `RoundSnapshot` (interface): interface RoundSnapshot<TPhase extends string = RoundPhase> { round: number; phase: TPhase; timeLeft: number; scores: Record<string, number>; lossStreaks: Record<string, number>; roles: Record<string, string | undefined>; matchOver: boolean; pendingWinner: string | null } — ⚠ undocumented
|
|
1304
1357
|
- `RtsCameraConfig` (interface): interface RtsCameraConfig extends TopDownCameraConfig — Free-pan / edge-scroll RTS rig (#24) — pan/rotate/zoom independent of any avatar.
|
|
@@ -1319,7 +1372,7 @@
|
|
|
1319
1372
|
- `SaveSlots` (interface): interface SaveSlots — A serializable, observable index of save/profile slot *metadata* that a save-select menu renders. It complements `createSaveStore` (which owns the actual save payload and named slots) by carrying the per-slot display fields the store does not: name, empty flag, last-saved time, and a free-string `meta` bag the game fills. Nothing here is genre-specific.
|
|
1320
1373
|
- `SaveSlotsConfig` (interface): interface SaveSlotsConfig — How a {@link createSaveSlots} index is wired.
|
|
1321
1374
|
- `SaveSlotsSnapshot` (interface): interface SaveSlotsSnapshot — Serializable state of a {@link SaveSlots} index, for save/restore.
|
|
1322
|
-
- `SaveStatus` (type): type SaveStatus = "idle" | "loading" | "saving" | "saved" | "error" — Lifecycle of the last save/load — drive a "Saving…"/"Saved" indicator or a loading gate off it. `"error"`
|
|
1375
|
+
- `SaveStatus` (type): type SaveStatus = "idle" | "loading" | "saving" | "saved" | "error" — Lifecycle of the last save/load — drive a "Saving…"/"Saved" indicator or a loading gate off it. `"error"` includes rejected reads, writes, removals and slot metadata updates; metadata failure can follow a successful payload write.
|
|
1323
1376
|
- `SaveStore` (interface): interface SaveStore<T> — A pluggable-backend game save with autosave, named slots, and versioned migration. `value()`/`patch()` hold the live state; `load()` hydrates it from the backend; `save()` (or autosave) writes it back. Backend failures surface as `"error"` status and through `onError` — a save never throws into a tick.
|
|
1324
1377
|
- `ScheduledDelivery` (interface): interface ScheduledDelivery { userId: string; inventoryId: string; items: readonly ItemStack[]; deliverAt: number } — ⚠ undocumented
|
|
1325
1378
|
- `ScheduledRule` (interface): interface ScheduledRule — A serializable recurring resource flow. Every field is plain JSON so the whole {@link ResourceLedger} round-trips through `structuredClone`/`JSON`. Dynamic, context-aware behaviour (providers, tax curves, affordability caps) lives in the runtime {@link ResourcePolicy} pipeline, never in this data.
|
|
@@ -1341,6 +1394,7 @@
|
|
|
1341
1394
|
- `Social` (interface): interface Social { friends: Friends; party: Party; presence: {get(userId: string): PresenceInfo}; emotes: Emotes; worldInvites: WorldInvites; snapshot(): SocialSnapshot; hydrate(data: SocialSnapshot): void } — ⚠ undocumented · used by `createSocial`: Emotes and lightweight social interactions between nearby players.
|
|
1342
1395
|
- `SocialDeps` (interface): interface SocialDeps { events: GameEvents; presence?: (userId: string) => PresenceInfo; now?: () => number; emotes?: EmotesDeps; worldInviteTtlMs?: number } — ⚠ undocumented · used by `createSocial`: Emotes and lightweight social interactions between nearby players.
|
|
1343
1396
|
- `StackPolicy` (type): type StackPolicy = "refresh" | "stack" | "independent" | "ignore" — How a repeated application of the same rule's effect on the same target combines with a live one: `refresh` re-arms the timer at one stack, `stack` adds a stack up to `maxStacks` and re-arms, `independent` keeps each application as its own instance with its own expiry, `ignore` drops the new application while one is already active.
|
|
1397
|
+
- `StaffedStation` (interface): interface StaffedStation — Serializable staffing snapshot. The caller owns assignment, unique worker ids, and stable order.
|
|
1344
1398
|
- `StatContribution` (interface): interface StatContribution — One folded contribution to a value, retained so a sheet can explain "why is this value 42?" — every step carries the source that produced it.
|
|
1345
1399
|
- `StatContributionStep` (interface): interface StatContributionStep extends StatContribution — One line of a provenance trace: a contribution plus the running total after it folds in.
|
|
1346
1400
|
- `StatDeriveContext` (interface): interface StatDeriveContext — The read-only view a derived formula gets: resolved values of its declared dependencies.
|
|
@@ -1354,6 +1408,8 @@
|
|
|
1354
1408
|
- `StatOp` (type): type StatOp = "add" | "mul" | "override" | "clampMin" | "clampMax" — How a single contribution folds into a running value.
|
|
1355
1409
|
- `StatSheet` (interface): interface StatSheet — A live per-entity instance of a {@link StatGraph}: mutable base values and modifier sources over a shared schema.
|
|
1356
1410
|
- `StatSheetState` (interface): interface StatSheetState — Plain-data, JSON-safe sheet state: input base values plus registered modifier sources.
|
|
1411
|
+
- `StationRateTuning` (interface): interface StationRateTuning — Caller-owned output tuning in production cycles per game-second.
|
|
1412
|
+
- `StationWorker` (interface): interface StationWorker — One assigned worker's caller-resolved contribution; stat names and modifiers stay caller-owned.
|
|
1357
1413
|
- `SystemDefinition` (interface): interface SystemDefinition — A reusable game capability — lifecycle, timing, events, and optional save / replication / reset / disposal. Pass instances via `defineGame({ systems })`. Prefer one system per meaningful capability (`combat`, `quests`), not per micro-tick.
|
|
1358
1414
|
- `SystemEventHandlers` (type): type SystemEventHandlers = { readonly [eventName: string]: (ctx: GameContext, event: unknown) => void; } — Event name → handler. Payload is the engine event shape for that name.
|
|
1359
1415
|
- `SystemTick` (type): type SystemTick = | { type: "fixed"; /** Steps per game-second. Default 60. */ rate?: number; stage?: string; after?: string | readonly string[]; before?: string | readonly string[]; } | { type: "frame"; stage?: string; after?: string | readonly string[]; before?: string | readonly string[]; } | { t… — How a system is scheduled. Omit `tick` (or use only `events`) for event-driven systems. Multiple systems may share the same channel; order within a channel is deterministic by stage then optional `before`/`after` constraints — never import order.
|
|
@@ -1376,6 +1432,7 @@
|
|
|
1376
1432
|
- `ThresholdDirection` (type): type ThresholdDirection = "up" | "down" — Generic threshold-crossing detection over ordered numeric boundaries.
|
|
1377
1433
|
- `TickResult` (interface): interface TickResult<TSpec, TReserve = undefined, TOutput = undefined> — Outcome of {@link tick}: advanced state plus the events produced.
|
|
1378
1434
|
- `TieMode` (type): type TieMode = "standard" | "dense" — How equal scores share ranks: - `"standard"` (competition ranking): ties share a rank and the next distinct score skips ahead — `1, 2, 2, 4`. - `"dense"`: ties share a rank and the next distinct score is the very next integer — `1, 2, 2, 3`.
|
|
1435
|
+
- `TimeScaledRarityOptions` (interface): interface TimeScaledRarityOptions — Caller-authored weighting curve; item ids, quality tiers and balance never live in the modifier.
|
|
1379
1436
|
- `TimedFeedEntry` (interface): interface TimedFeedEntry — Any feed entry carrying a game-time (or wall-clock) `at` stamp for age-based pruning.
|
|
1380
1437
|
- `Toast` (interface): interface Toast<T = string> — A transient HUD message that expires on its own — banner, pickup note, alert.
|
|
1381
1438
|
- `TopDownCameraConfig` (interface): interface TopDownCameraConfig — Fixed top-down / isometric rig (#23) — height/pitch/yaw + decoupled follow.
|
|
@@ -1478,9 +1535,9 @@
|
|
|
1478
1535
|
- `createGameFeed` (function): function createGameFeed(options?: GameFeedOptions): GameFeed — A rolling per-action feed of recent gameplay events, bindable to the event bus — the HUD ticker and killfeed history.
|
|
1479
1536
|
- `createGestureSurfaceTracker` (function): function createGestureSurfaceTracker(bindings: TouchGestureBindings, tuning: GestureSurfaceTuning = DEFAULT_GESTURE_TUNING): GestureSurfaceTracker — ⚠ undocumented
|
|
1480
1537
|
- `createIntentBoard` (function): function createIntentBoard<TKind extends string = string>(): IntentBoard<TKind> — ⚠ undocumented
|
|
1481
|
-
- `createItemInstanceRegistry` (function): function createItemInstanceRegistry<TDef>(prefix = "item"): ItemInstanceRegistry<TDef> — Builds an {@link ItemInstanceRegistry}; generated ids are `"<prefix>:<baseId>:<n>"`, unique per registry instance.
|
|
1538
|
+
- `createItemInstanceRegistry` (function): function createItemInstanceRegistry<TDef>(prefix = "item", options: ItemInstanceRegistryOptions<TDef> = {}): ItemInstanceRegistry<TDef> — Builds an {@link ItemInstanceRegistry}; generated ids are `"<prefix>:<baseId>:<n>"`, unique per registry instance.
|
|
1482
1539
|
- `createItemUse` (function): function createItemUse<TState>(resolveUse: (itemId: string) => string | null | undefined): ItemUse<TState> — Use or consume items, applying their effects and per-item cooldowns.
|
|
1483
|
-
- `createKeyValueStore` (function): function createKeyValueStore<T>(config: KeyValueStoreConfig<T>): KeyValueStore<T> — A
|
|
1540
|
+
- `createKeyValueStore` (function): function createKeyValueStore<T>(config: KeyValueStoreConfig<T>): KeyValueStore<T> — A mutable local save cell through {@link KeyValueStorage}. Default fallback keeps session state on failure; `errorMode: "throw"` exposes failed reads/writes/removals through the original error. `storage: null` deliberately uses memory only.
|
|
1484
1541
|
- `createLapTimer` (function): function createLapTimer(): LapTimer — Create a {@link LapTimer} starting at lap 0 with no splits, best, or last time recorded.
|
|
1485
1542
|
- `createLayerRegistry` (function): function createLayerRegistry(initial?: readonly ParamLayer[]): LayerRegistry — Create a {@link LayerRegistry} — the registration seam difficulty tiers, mutators, and presets install into. Duplicate ids throw at registration; unknown ids at resolve time are reported, not fatal, which is what keeps saved sessions reproducible across content/version drift.
|
|
1486
1543
|
- `createLeaderboard` (function): function createLeaderboard(sink?: { onIncrement?(row: LeaderboardRow): void }): Leaderboard — Ranked score tracking across global, server, and per-profile scopes, with top-N queries and per-profile lookups.
|
|
@@ -1538,6 +1595,7 @@
|
|
|
1538
1595
|
- `describeTrackedQuest` (function): function describeTrackedQuest(def: QuestDef, instance: QuestInstance, label: (objective: QuestObjective) => string = defaultObjectiveLabel): TrackedQuestView — Join a quest's static {@link QuestDef} with a player's live {@link QuestInstance} into a flat, renderer-free view a HUD tracker draws (title, status, labelled objective progress). Pass `label` to override the derived objective text.
|
|
1539
1596
|
- `dialogueSlot` (const): const dialogueSlot: StoreHandle<string | undefined> — Typed handle onto the open-dialogue slot — React reads it via `useOpenDialogueId`; game code uses `ctx.game.dialogue`.
|
|
1540
1597
|
- `diffParams` (function): function diffParams(before: Readonly<Record<string, number>>, after: Readonly<Record<string, number>>): readonly ParamDelta[] — Compute the per-parameter deltas between two value maps — the preview/diff of applying a change, for showing a player what a difficulty tier or mutator will do before they commit.
|
|
1598
|
+
- `dispatchExpedition` (function): function dispatchExpedition(input: ExpeditionDispatch): ExpeditionState — Dispatch plain expedition state with a persisted seeded cursor; no clock, scheduler or storage is owned.
|
|
1541
1599
|
- `drainOutput` (function): function drainOutput(state: ProductionState, itemId: string, count?: number): { state: ProductionState; taken: number } — ⚠ undocumented
|
|
1542
1600
|
- `draw` (function): function draw(state: CardPileState, n: number, options: { from: ZoneName; to: ZoneName; handLimit?: number; reshuffleFrom?: ZoneName; seed?: string | number; }): DrawResult — ⚠ undocumented
|
|
1543
1601
|
- `driftValue` (function): function driftValue(record: Record<string, number>, key: string, rate: number, rest = 0, bounds?: NumericBounds): number — Decay `key` toward a `rest` value (default `0`) by `rate` per call — the common "relationships cool off" / "heat fades" drift. Thin wrapper over {@link towardValue}.
|
|
@@ -1571,7 +1629,7 @@
|
|
|
1571
1629
|
- `leveling` (function): function leveling(config: LevelingConfig): LevelingTrack — Build a leveling track from an xp-per-level {@link Curve} and a max level. The returned {@link LevelingTrack} resolves how many levels a given xp total earns (rolling over surplus xp, capping at `maxLevel`) and, via `grantXp`, writes the new level/xp back through a {@link LevelingStatAccess} and fires `onLevelUp` for each level gained in ascending order. Reach for this instead of hand-tracking xp thresholds; pair it with `resource-pool` (mana/stamina) and `ability-bar` (cooldowns) for a hero.
|
|
1572
1630
|
- `listRuleEffects` (function): function listRuleEffects(): RuleEffectDefinition[] — Every declared rule effect, for populating inspector dropdowns and validating a content set.
|
|
1573
1631
|
- `loadBindingOverrides` (function): function loadBindingOverrides(gameId: string, storage: Pick<WebStorageLike, "getItem"> | null | undefined = defaultStorage()): BindingOverrides — ⚠ undocumented
|
|
1574
|
-
- `localSaveBackend` (function): function localSaveBackend(storage?: KeyValueStorage | null): SaveBackend — A {@link SaveBackend} over a synchronous {@link KeyValueStorage} — the browser's `localStorage` by default (offline, on-device saves), a test stub, or `null` for
|
|
1632
|
+
- `localSaveBackend` (function): function localSaveBackend(storage?: KeyValueStorage | null, policy: KeyValueStorageErrorPolicy = {}): SaveBackend — A {@link SaveBackend} over a synchronous {@link KeyValueStorage} — the browser's `localStorage` by default (offline, on-device saves), a test stub, or `null` for a no-op backend. Default fallback ignores failures; `errorMode: "throw"` rejects failed operations and unavailable storage, so SaveStore status/onError can report them. Use {@link memorySaveBackend} for deliberate ephemeral persistence.
|
|
1575
1633
|
- `lootFilter` (function): function lootFilter(rules: readonly LootFilterRule[]): readonly LootFilterRule[] — Validating factory — rule ids must be unique so authoring mistakes fail loudly.
|
|
1576
1634
|
- `lootTable` (function): function lootTable(def: LootTableDef): LootTableDef — Validates a loot table definition and returns it unchanged, for use with {@link createLootRegistry}.
|
|
1577
1635
|
- `matchesQuery` (function): function matchesQuery(identity: ItemIdentity, query: IdentityQuery): boolean — Test whether an identity satisfies a declarative {@link IdentityQuery}.
|
|
@@ -1604,6 +1662,7 @@
|
|
|
1604
1662
|
- `raceTrack` (function): function raceTrack(config: RaceTrackConfig): RaceTrack — A race track is an ordered ring of checkpoint trigger volumes plus a lap count. The final checkpoint is the lap/finish line: a racer completes a lap by passing all checkpoints in order and hitting the last one. `forks` splice alternate route segments between mainline checkpoints.
|
|
1605
1663
|
- `rankLeaderboard` (function): function rankLeaderboard(rows: readonly RankableRow[], options: RankLeaderboardOptions = {}): RankedEntry[] — Turn raw leaderboard rows into a render-ready ranked table. Pure and allocation-bounded: it sorts a copy by `value` (descending by default), assigns 1-based ranks with correct tie handling (`"standard"` → `1, 2, 2, 4`; `"dense"` → `1, 2, 2, 3`), flags rows that share a score (`isTie`), marks the local player (`isLocal`, via `highlightUserId`), and finally applies `limit`. Sorting is stable, so rows with equal scores keep their input order. Nothing here styles or branches on game meaning — pair it with {@link medalFor} and a game-owned theme to render a reskinnable scoreboard. Accepts a {@link LeaderboardRow}`[]` straight from `leaderboard.snapshot()`/`getTop()` since those satisfy {@link RankableRow}.
|
|
1606
1664
|
- `readPath` (function): function readPath(facts: PredicateFacts, path: PredicatePath): unknown — Read a dot path out of a fact bag, descending only through plain objects. Returns `undefined` when any segment is missing or non-traversable. Bounded by the path's segment count.
|
|
1665
|
+
- `recallExpedition` (function): function recallExpedition<TCtx>(config: ExpeditionConfig<TCtx>, state: ExpeditionState, nowMs: number): ExpeditionState — Settle first, then recall safely. If the catch-up budget leaves due exploring ticks, return that state without recalling; repeat at the same target until the frontier catches up. Dead state never revives.
|
|
1607
1666
|
- `redirect` (function): function redirect(endpoints: { source?: string; recipient?: string }): ResourcePolicy — Override the source and/or recipient accounts of a transaction.
|
|
1608
1667
|
- `refillMeter` (function): function refillMeter(values: DecayMeterValues, defs: readonly DecayMeterConfig[], id: string, amount: number): DecayMeterValues — Refill (or drain, if negative) one meter by `amount`, clamped to its range. Returns a new record; throws on an unknown id. The pure counterpart to {@link DecayMeterSet.refill}.
|
|
1609
1668
|
- `registerRuleEffect` (function): function registerRuleEffect(definition: RuleEffectDefinition): void — Declare a rule effect id. Idempotent per id (last registration wins); call at module load next to catalogs so authored content and inspectors share one vocabulary.
|
|
@@ -1618,6 +1677,7 @@
|
|
|
1618
1677
|
- `resolveSelection` (function): function resolveSelection(base: Readonly<Record<string, number>>, registry: LayerRegistry, ids: LayerSelection): { readonly snapshot: ParamSnapshot; readonly unknown: readonly string[] } — Reproducible session setup in one call: resolve a saved {@link LayerSelection} through a registry, fold the found layers over `base`, and return the snapshot alongside any unknown ids. The same base + registry + selection always yields the same snapshot.
|
|
1619
1678
|
- `resumeJob` (function): function resumeJob<TSpec, TReserve>(state: WorkQueueState<TSpec, TReserve>, id: JobId): WorkQueueState<TSpec, TReserve> — Resume a paused job; it re-enters the queue and competes for a slot by ordering.
|
|
1620
1679
|
- `resumeRule` (function): function resumeRule(ledger: ResourceLedger, ruleId: string): ResourceLedger — Resume a paused rule. Its `nextDueSeconds` is unchanged, so the paused span counts as missed cycles that the rule's {@link CatchUpPolicy} decides how to settle on the next advance.
|
|
1680
|
+
- `returnExpeditionNow` (function): function returnExpeditionNow<TCtx>(config: ExpeditionConfig<TCtx>, state: ExpeditionState, nowMs: number): ExpeditionState — Settle first, then complete a live return instantly. Caller owns payment/authorization; pending ticks remain unsettled when the budget is exhausted, and dead/home state is never changed.
|
|
1621
1681
|
- `ringSampleAt` (function): function ringSampleAt(config: RingConfig, time: number): RingSample — ⚠ undocumented
|
|
1622
1682
|
- `runPipeline` (function): function runPipeline<V>(base: V, modifiers: readonly Modifier<V>[], equals: (a: V, b: V) => boolean = Object.is): PipelineResult<V> — ⚠ undocumented
|
|
1623
1683
|
- `saveBindingOverride` (function): function saveBindingOverride(gameId: string, action: string, codes: ActionCodes, storage: Pick<WebStorageLike, "getItem" | "setItem" | "removeItem"> | null | undefined = defaultStorage()): BindingOverrides — ⚠ undocumented
|
|
@@ -1628,12 +1688,14 @@
|
|
|
1628
1688
|
- `setGamePhase` (function): function setGamePhase(ctx: GameContext, phase: GamePhase): void — Set the current phase. Publishes it to `ctx.game.store` (React reads it via `useGamePhase`) and gates the shell's on-screen touch controls in one call — `playing` shows them, every other phase hides them. This is the whole "main menu shouldn't show touch controls" wiring: call it once per phase transition and the dock follows.
|
|
1629
1689
|
- `setTouchControlsMode` (function): function setTouchControlsMode(ctx: GameContext, mode: string | null): void — Activate a named touch control mode, or `null` to return to the base config.
|
|
1630
1690
|
- `setValue` (function): function setValue(record: Record<string, number>, key: string, value: number, bounds?: NumericBounds): number — Set `key` to `value` (clamped to `bounds`), writing the record in place. Returns the stored value.
|
|
1691
|
+
- `settleExpedition` (function): function settleExpedition<TCtx>(config: ExpeditionConfig<TCtx>, state: ExpeditionState, nowMs: number): ExpeditionState — Replay due event ticks using the existing stepped catch-up primitive. Order is loot → hazard → ordered supplies → death → capacity recall. Unprocessed ticks retain their frontier; returning never rolls or takes damage. Auto-recall uses the triggering tick's time, including offline arrival in the same call.
|
|
1631
1692
|
- `shuffleWithRng` (function): function shuffleWithRng<T>(values: readonly T[], rng: () => number): T[] — ⚠ undocumented
|
|
1632
1693
|
- `slotAccepts` (function): function slotAccepts(slot: MountSlotDef, category: string): boolean — Attach parts into an item's mount slots and resolve the combined stats.
|
|
1633
1694
|
- `splitSegments` (function): function splitSegments(splits: readonly number[], start = 0): number[] — Per-segment durations from a cumulative split book (`splits[i]` = elapsed time at checkpoint `i`): `segments[i] = splits[i] − splits[i−1]`, the first measured from `start` (default 0). Turns the cumulative splits {@link RacerProgress} records into the individual leg times a results screen shows.
|
|
1634
1695
|
- `stackMoodles` (function): function stackMoodles(...groups: readonly (readonly Moodle[])[]): Moodle[] — Merge any number of moodle groups into one stack — meters, ailments, and buffs share this display. Same-id moodles fold together (stacks add, worst severity wins); the result is ordered worst-first so the HUD reads critical statuses at a glance.
|
|
1635
1696
|
- `startRaceCountdown` (function): function startRaceCountdown(options?: RaceCountdownOptions): RaceSessionState — Drop the lights: return a fresh `countdown` session of `seconds` (default 3). A non-positive length skips straight to `racing` for a standing start with no countdown.
|
|
1636
1697
|
- `statModifierContributions` (function): function statModifierContributions<TStat extends string>(source: string, set: StatModifierSet<TStat>): Record<string, StatContribution[]> — Bridge the shared {@link StatModifierSet} shape (add/multiply, used by talents, items, and buffs) into stat-graph contributions, so a ranked talent tree or gear roll feeds the graph as one named source instead of a parallel store.
|
|
1698
|
+
- `stationOutputRate` (function): function stationOutputRate(station: StaffedStation, tuning: StationRateTuning): number — Resolve `(base + perStat * sum(admitted worker stats)) * efficiency` without allocation. Empty staffing retains base production. Negative/nonfinite contributions are zero; a nonfinite efficiency or overflowing result stops production with rate zero. Invalid workers still occupy their ordered slots. Assign the result to a `ProductionBuildingDef.rate` for `tickProduction`.
|
|
1637
1699
|
- `stationSatisfied` (function): function stationSatisfied(recipe: RecipeDef, context: CraftContext): boolean — ⚠ undocumented
|
|
1638
1700
|
- `talentTreeView` (function): function talentTreeView<TStat extends string = string>(nodes: readonly TalentNodeDef<TStat>[], tree: TalentTree<TStat>): TalentTreeView — Project the existing talent model (`createTalentTree`) into a flat, serializable render view: every node placed by branch + prerequisite-depth tier, tagged learned/available/locked/maxed, with its inbound prerequisite edges (and whether each is met) and whether a point can be spent right now. It is a pure read over the node defs plus a live {@link TalentTree}, so a React/canvas widget can lay out nodes, draw edges, and gate clicks without re-deriving topology or re-interpreting eligibility. The model still owns allocation, requirements, and point rules — this only reshapes them for drawing, and never interprets what a node *means* (ids, branches, and ranks stay opaque game data). This is the point-spend adapter over {@link talentTreeViewFrom}; pass a custom status to that builder instead to drive the tree from a currency, level, or any other unlock rule.
|
|
1639
1701
|
- `talentTreeViewFrom` (function): function talentTreeViewFrom<TStat extends string = string>(nodes: readonly TalentNodeDef<TStat>[], status: (node: TalentNodeDef<TStat>) => TalentNodeStatus, totals?: TalentPointTotals): TalentTreeView — Build a flat, serializable render view of a node graph from a caller-supplied per-node status, decoupled from any particular progression model. For each node the game returns its `rank` and whether it is `allocatable` *right now* under whatever rule it likes — a skill-point pool, a cash threshold, a level gate, a quest flag, or nothing. The builder places every node by branch + prerequisite-depth tier, tags it learned/available/locked/maxed (`available` when rank 0 and every prerequisite is met — see below), and resolves inbound prerequisite edges (each `met` when the source node's supplied rank meets the demand). This is the general escape hatch behind {@link talentTreeView}: it lets the same widget render a buy-with-points talent tree, a money-gated upgrade tree, or a condition-unlocked ability web without the renderer changing. It never interprets what a node *means* — ids, branches, and ranks stay opaque game data.
|
|
@@ -1643,6 +1705,7 @@
|
|
|
1643
1705
|
- `tickProduction` (function): function tickProduction(def: ProductionBuildingDef, state: ProductionState, input: ProductionTickInput): ProductionState — ⚠ undocumented
|
|
1644
1706
|
- `tickRaceSession` (function): function tickRaceSession(session: RaceSessionState, dt: number): RaceSessionState — Advance the session by `dt` seconds: bleed the countdown down and flip to `racing` when it reaches zero, or accumulate `elapsed` while `racing`. `idle` and `finished` are inert. Overshoot past the countdown is dropped rather than banked into `elapsed`, so the race clock always starts from zero.
|
|
1645
1707
|
- `tierAt` (function): function tierAt<Id>(boundaries: readonly ThresholdBoundary<Id>[], value: number, options: { readonly inclusive?: boolean } = {}): ThresholdBoundary<Id> | null — The highest boundary at-or-below `value` — the band the value currently sits in. Returns `null` when `value` is below every boundary. Boundaries need not be sorted.
|
|
1708
|
+
- `timeScaledRarity` (function): function timeScaledRarity<TCtx extends { elapsedMs: number }>(options: TimeScaledRarityOptions): LootModifier<TCtx> — Multiply weighted odds (or independent chances, clamped to one) by a caller-authored elapsed-time curve. Keeps source tables unchanged and uses the existing pipeline's modifier provenance. Elapsed time and multipliers must be finite and nonnegative; invalid curves reject the roll.
|
|
1646
1709
|
- `touchButtonShape` (function): function touchButtonShape(action: string): TouchButtonShape — Default silhouette for an action; `circle` when nothing more specific fits.
|
|
1647
1710
|
- `touchCode` (function): function touchCode(action: string): string — ⚠ undocumented
|
|
1648
1711
|
- `towardValue` (function): function towardValue(record: Record<string, number>, key: string, target: number, maxDelta: number, bounds?: NumericBounds): number — Step `key` toward `target` by at most `maxDelta` without overshooting, then clamp to `bounds`. Writes in place and returns the stored value.
|
|
@@ -1687,17 +1750,25 @@
|
|
|
1687
1750
|
|
|
1688
1751
|
## @jgengine/core/inventory/shapedGrid
|
|
1689
1752
|
|
|
1690
|
-
- `Cell` (type): type Cell = readonly [number, number] — ⚠ undocumented
|
|
1691
|
-
- `Footprint` (type): type Footprint = readonly Cell[] — ⚠ undocumented · used by `
|
|
1753
|
+
- `Cell` (type): type Cell = readonly [number, number] — ⚠ undocumented · used by `canPlace`: Check bounds and overlap for a discrete footprint, optionally ignoring the item being moved.
|
|
1754
|
+
- `Footprint` (type): type Footprint = readonly Cell[] — ⚠ undocumented · used by `canPlace`: Check bounds and overlap for a discrete footprint, optionally ignoring the item being moved.
|
|
1692
1755
|
- `GridAdjacencyQuery` (interface): interface GridAdjacencyQuery { cellsOf(id: string): readonly Cell[]; neighborsOf(id: string): readonly string[]; touching(idA: string, idB: string): boolean; adjacentCells(cells: readonly Cell[]): readonly Cell[] } — ⚠ undocumented
|
|
1693
1756
|
- `Placement` (interface): interface Placement<T> { id: string; value: T; footprint: Footprint; origin: Cell; rotation: Rotation } — ⚠ undocumented
|
|
1694
|
-
- `Rotation` (type): type Rotation = 0 | 1 | 2 | 3 — ⚠ undocumented
|
|
1695
|
-
- `ShapedGrid` (interface): interface ShapedGrid<T> { readonly width: number; readonly height: number; readonly placements: readonly Placement<T>[] } — ⚠ undocumented
|
|
1696
|
-
- `ShapedItem` (interface): interface ShapedItem<T> { id: string; value: T; footprint: Footprint } — ⚠ undocumented
|
|
1757
|
+
- `Rotation` (type): type Rotation = 0 | 1 | 2 | 3 — ⚠ undocumented · used by `canPlace`: Check bounds and overlap for a discrete footprint, optionally ignoring the item being moved.
|
|
1758
|
+
- `ShapedGrid` (interface): interface ShapedGrid<T> { readonly width: number; readonly height: number; readonly placements: readonly Placement<T>[] } — ⚠ undocumented · used by `canPlace`: Check bounds and overlap for a discrete footprint, optionally ignoring the item being moved.
|
|
1759
|
+
- `ShapedItem` (interface): interface ShapedItem<T> { id: string; value: T; footprint: Footprint } — ⚠ undocumented · used by `placeShaped`: Place a caller-defined item without mutating the source board; duplicate ids reject.
|
|
1697
1760
|
- `ShapedPlaceResult` (interface): interface ShapedPlaceResult<T> { status: "ok"; grid: ShapedGrid<T> } — ⚠ undocumented
|
|
1761
|
+
- `ShapedPlacementSearchOptions` (interface): interface ShapedPlacementSearchOptions — Search policy: rotation order first, then rows and columns; the work budget counts candidate origins.
|
|
1762
|
+
- `ShapedPlacementSearchResult` (type): type ShapedPlacementSearchResult = | { status: "found"; origin: Cell; rotation: Rotation; checks: number } | { status: "no-space"; checks: number } | { status: "budget-exceeded"; checks: number } — A detached placement, a completed no-fit search, or an incomplete search that reached its budget.
|
|
1698
1763
|
- `ShapedRejected` (interface): interface ShapedRejected { status: "rejected"; reason: ShapedRejection; detail?: string } — ⚠ undocumented
|
|
1699
|
-
- `ShapedRejection` (type): type ShapedRejection = "out-of-bounds" | "overlap" | "duplicate-id" | "unknown-id" — ⚠ undocumented
|
|
1700
|
-
- `ShapedResult` (type): type ShapedResult<T> = ShapedPlaceResult<T> | ShapedRejected — ⚠ undocumented
|
|
1764
|
+
- `ShapedRejection` (type): type ShapedRejection = "out-of-bounds" | "overlap" | "duplicate-id" | "unknown-id" | "invalid-footprint" | "invalid-origin" — ⚠ undocumented · used by `canPlace`: Check bounds and overlap for a discrete footprint, optionally ignoring the item being moved.
|
|
1765
|
+
- `ShapedResult` (type): type ShapedResult<T> = ShapedPlaceResult<T> | ShapedRejected — ⚠ undocumented · used by `moveShaped`: Move or rotate one placement, ignoring its current cells during overlap checks.
|
|
1766
|
+
- `canPlace` (function): function canPlace<T>(grid: ShapedGrid<T>, footprint: Footprint, origin: Cell, rotation: Rotation, ignoreId?: string): ShapedRejection | null — Check bounds and overlap for a discrete footprint, optionally ignoring the item being moved.
|
|
1767
|
+
- `createShapedGrid` (function): function createShapedGrid<T>(width: number, height: number): ShapedGrid<T> — An immutable spatial inventory board holding caller-defined multi-cell items.
|
|
1768
|
+
- `findShapedPlacement` (function): function findShapedPlacement<T>(grid: ShapedGrid<T>, footprint: Footprint, options: ShapedPlacementSearchOptions = {}): ShapedPlacementSearchResult — Find the first legal placement without mutating the board; occupancy is indexed once per search.
|
|
1769
|
+
- `moveShaped` (function): function moveShaped<T>(grid: ShapedGrid<T>, id: string, origin: Cell, rotation?: Rotation): ShapedResult<T> — Move or rotate one placement, ignoring its current cells during overlap checks.
|
|
1770
|
+
- `placeShaped` (function): function placeShaped<T>(grid: ShapedGrid<T>, item: ShapedItem<T>, origin: Cell, rotation: Rotation = 0): ShapedResult<T> — Place a caller-defined item without mutating the source board; duplicate ids reject.
|
|
1771
|
+
- `removeShaped` (function): function removeShaped<T>(grid: ShapedGrid<T>, id: string): ShapedResult<T> — Remove one placement without mutating the source board.
|
|
1701
1772
|
|
|
1702
1773
|
## @jgengine/core/inventory/slotModel
|
|
1703
1774
|
|
|
@@ -1781,7 +1852,10 @@
|
|
|
1781
1852
|
## @jgengine/core/item/itemInstanceRegistry
|
|
1782
1853
|
|
|
1783
1854
|
- `ItemInstanceRegistry` (interface): interface ItemInstanceRegistry<TDef> — A runtime store for procedurally generated item instances — a rolled unique gun, a rolled affixed relic — keyed by a generated id distinct from any static catalog id. The counterpart a game's `content.itemById` consults for ids `lootTable`'s `generate` entries hand back, so runtime rolls never need a hand-rolled parallel registry (#536.1).
|
|
1784
|
-
- `
|
|
1855
|
+
- `ItemInstanceRegistryOptions` (interface): interface ItemInstanceRegistryOptions<TDef> — Inject storage and its saved allocator sequence when attaching an existing collection.
|
|
1856
|
+
- `ItemInstanceRegistryState` (interface): interface ItemInstanceRegistryState<TDef> — Save data for a registry; definitions must be structured-cloneable and use the caller's serialization format.
|
|
1857
|
+
- `ItemInstanceStorage` (interface): interface ItemInstanceStorage<TDef> — Caller-owned synchronous storage; `entries()` must stream without materializing the collection.
|
|
1858
|
+
- `createItemInstanceRegistry` (function): function createItemInstanceRegistry<TDef>(prefix = "item", options: ItemInstanceRegistryOptions<TDef> = {}): ItemInstanceRegistry<TDef> — Builds an {@link ItemInstanceRegistry}; generated ids are `"<prefix>:<baseId>:<n>"`, unique per registry instance.
|
|
1785
1859
|
- `proceduralLootEntry` (function): function proceduralLootEntry<TDef>(registry: ItemInstanceRegistry<TDef>, roll: (rng: () => number) => { baseId: string; def: TDef }): (rng: () => number) => string — Bridges any procedural roller into a `LootEntry.generate` callback: rolls a `{ baseId, def }` pair and registers it, returning the runtime id the loot roll hands back as the drop's `item`.
|
|
1786
1860
|
|
|
1787
1861
|
## @jgengine/core/item/itemgen
|
|
@@ -2043,7 +2117,7 @@
|
|
|
2043
2117
|
## @jgengine/core/store/defineStore
|
|
2044
2118
|
|
|
2045
2119
|
- `StoreHandle` (interface): interface StoreHandle<T> — A typed, cast-free handle onto one slot of the reactive game store (`ctx.game.store`). The single type parameter is fixed at definition; `read`/`write`/`update` never widen to `unknown`, so no call site repeats `store.get(key) as T`. Writes flow through the engine store, so they bump `ctx.version()`, serialize into a {@link WorldSnapshot}, and replay under host authority — the same guarantees a hand-rolled `store.get`/`store.set` pair gives up the moment it forks run state into a module-level singleton.
|
|
2046
|
-
- `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).
|
|
2120
|
+
- `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.
|
|
2047
2121
|
|
|
2048
2122
|
## @jgengine/core/survival/decayMeter
|
|
2049
2123
|
|
|
@@ -2161,6 +2235,19 @@
|
|
|
2161
2235
|
- `TurnState` (interface): interface TurnState { round: number; order: readonly string[]; activeIndex: number; active: string | null; phaseIndex: number; phase: string | null } — ⚠ undocumented
|
|
2162
2236
|
- `createTurnLoop` (function): function createTurnLoop<TAction = unknown>(config: TurnLoopConfig): TurnLoop<TAction> — ⚠ undocumented
|
|
2163
2237
|
|
|
2238
|
+
## @jgengine/core/work/expedition
|
|
2239
|
+
|
|
2240
|
+
- `ExpeditionConfig` (interface): interface ExpeditionConfig<TCtx> — Runtime policy, supplied on each transition and never saved. Callbacks must be pure.
|
|
2241
|
+
- `ExpeditionDispatch` (interface): interface ExpeditionDispatch — Dispatch data, detached from the caller's supply record. All timestamps are epoch milliseconds.
|
|
2242
|
+
- `ExpeditionEvent` (interface): interface ExpeditionEvent — Timestamped serializable event. `at` is epoch milliseconds, compatible with `appendFeed`.
|
|
2243
|
+
- `ExpeditionHazard` (interface): interface ExpeditionHazard — One encounter's mechanical effects and optional caller-authored notices.
|
|
2244
|
+
- `ExpeditionState` (interface): interface ExpeditionState — Plain saveable expedition data. Persist this whole value, including the RNG cursor and tick frontier.
|
|
2245
|
+
- `ExpeditionSupplyRule` (interface): interface ExpeditionSupplyRule — Ordered auto-consumption rule: spends one finite supply only when its declared effect changes a vital.
|
|
2246
|
+
- `dispatchExpedition` (function): function dispatchExpedition(input: ExpeditionDispatch): ExpeditionState — Dispatch plain expedition state with a persisted seeded cursor; no clock, scheduler or storage is owned.
|
|
2247
|
+
- `recallExpedition` (function): function recallExpedition<TCtx>(config: ExpeditionConfig<TCtx>, state: ExpeditionState, nowMs: number): ExpeditionState — Settle first, then recall safely. If the catch-up budget leaves due exploring ticks, return that state without recalling; repeat at the same target until the frontier catches up. Dead state never revives.
|
|
2248
|
+
- `returnExpeditionNow` (function): function returnExpeditionNow<TCtx>(config: ExpeditionConfig<TCtx>, state: ExpeditionState, nowMs: number): ExpeditionState — Settle first, then complete a live return instantly. Caller owns payment/authorization; pending ticks remain unsettled when the budget is exhausted, and dead/home state is never changed.
|
|
2249
|
+
- `settleExpedition` (function): function settleExpedition<TCtx>(config: ExpeditionConfig<TCtx>, state: ExpeditionState, nowMs: number): ExpeditionState — Replay due event ticks using the existing stepped catch-up primitive. Order is loot → hazard → ordered supplies → death → capacity recall. Unprocessed ticks retain their frontier; returning never rolls or takes damage. Auto-recall uses the triggering tick's time, including offline arrival in the same call.
|
|
2250
|
+
|
|
2164
2251
|
## @jgengine/core/work/jobQueue
|
|
2165
2252
|
|
|
2166
2253
|
- `CancelResult` (type): type CancelResult<TSpec, TReserve = undefined> = | { readonly ok: true; readonly state: WorkQueueState<TSpec, TReserve>; readonly job: Job<TSpec, TReserve>; readonly refund: TReserve | null; } | { readonly ok: false; readonly state: WorkQueueState<TSpec, TReserve>; readonly reason: string } — Outcome of {@link cancelJob}, carrying the removed job and its computed refund.
|
|
@@ -2189,6 +2276,13 @@
|
|
|
2189
2276
|
- `resumeJob` (function): function resumeJob<TSpec, TReserve>(state: WorkQueueState<TSpec, TReserve>, id: JobId): WorkQueueState<TSpec, TReserve> — Resume a paused job; it re-enters the queue and competes for a slot by ordering.
|
|
2190
2277
|
- `tick` (function): function tick<TSpec, TReserve, TOutput>(state: WorkQueueState<TSpec, TReserve>, config: WorkQueueConfig<TSpec, TReserve, TOutput>, dt: number): TickResult<TSpec, TReserve, TOutput> — Advance the queue by `dt` seconds. Promotes queued jobs into up to `concurrency` active slots, advances active jobs, and completes those that reach their duration — emitting `started`/`completed` events in deterministic order. A large `dt` catches up across many jobs in one call: when a job completes with leftover time, the freed slot promotes the next queued job and applies the remainder, so a reconnect or save/load gap resolves in a single bounded pass. Completed jobs are removed from the returned state.
|
|
2191
2278
|
|
|
2279
|
+
## @jgengine/core/work/staffedStation
|
|
2280
|
+
|
|
2281
|
+
- `StaffedStation` (interface): interface StaffedStation — Serializable staffing snapshot. The caller owns assignment, unique worker ids, and stable order.
|
|
2282
|
+
- `StationRateTuning` (interface): interface StationRateTuning — Caller-owned output tuning in production cycles per game-second.
|
|
2283
|
+
- `StationWorker` (interface): interface StationWorker — One assigned worker's caller-resolved contribution; stat names and modifiers stay caller-owned.
|
|
2284
|
+
- `stationOutputRate` (function): function stationOutputRate(station: StaffedStation, tuning: StationRateTuning): number — Resolve `(base + perStat * sum(admitted worker stats)) * efficiency` without allocation. Empty staffing retains base production. Negative/nonfinite contributions are zero; a nonfinite efficiency or overflowing result stops production with rate zero. Invalid workers still occupy their ordered slots. Assign the result to a `ProductionBuildingDef.rate` for `tickProduction`.
|
|
2285
|
+
|
|
2192
2286
|
## @jgengine/core/work/unitTraining
|
|
2193
2287
|
|
|
2194
2288
|
- `ResourceCost` (type): type ResourceCost = Readonly<Record<string, number>> — Resource costs keyed by currency/resource id.
|