@jgengine/core 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/dist/ai/populationDirector.d.ts +103 -0
- package/dist/ai/populationDirector.js +190 -0
- package/dist/ai/pursuit.d.ts +56 -0
- package/dist/ai/pursuit.js +53 -0
- package/dist/authoring.d.ts +1 -1
- package/dist/authoring.js +1 -1
- package/dist/combat/effects.d.ts +11 -4
- package/dist/combat/effects.js +24 -17
- package/dist/combat/magazine.d.ts +13 -0
- package/dist/combat/magazine.js +27 -0
- package/dist/combat/vfxPresets.d.ts +176 -0
- package/dist/combat/vfxPresets.js +74 -0
- package/dist/combat/weaponFire.d.ts +114 -0
- package/dist/combat/weaponFire.js +96 -0
- package/dist/combat.d.ts +5 -2
- package/dist/combat.js +4 -1
- package/dist/devtools/controls.d.ts +38 -0
- package/dist/devtools/controls.js +181 -0
- package/dist/devtools/devtools.d.ts +5 -197
- package/dist/devtools/devtools.js +38 -774
- package/dist/devtools/discover.d.ts +32 -0
- package/dist/devtools/discover.js +240 -0
- package/dist/devtools/fallbackSeams.d.ts +50 -0
- package/dist/devtools/fallbackSeams.js +111 -0
- package/dist/devtools/frame.d.ts +15 -0
- package/dist/devtools/frame.js +247 -0
- package/dist/devtools/logs.d.ts +15 -0
- package/dist/devtools/logs.js +86 -0
- package/dist/devtools/overrides.d.ts +16 -0
- package/dist/devtools/overrides.js +66 -0
- package/dist/devtools/types.d.ts +212 -0
- package/dist/devtools/types.js +1 -0
- package/dist/devtools/urlFlags.d.ts +22 -0
- package/dist/devtools/urlFlags.js +62 -0
- package/dist/economy/auctionBook.d.ts +122 -0
- package/dist/economy/auctionBook.js +213 -0
- package/dist/economy/priceHistory.d.ts +44 -0
- package/dist/economy/priceHistory.js +89 -0
- package/dist/economy/unlockPoints.d.ts +92 -0
- package/dist/economy/unlockPoints.js +103 -0
- package/dist/editor/commandApply.d.ts +5 -0
- package/dist/editor/commandApply.js +755 -0
- package/dist/editor/commands.d.ts +48 -3
- package/dist/editor/commands.js +40 -754
- package/dist/editor/directives.d.ts +94 -0
- package/dist/editor/directives.js +206 -0
- package/dist/editor/document.d.ts +37 -2
- package/dist/editor/document.js +422 -6
- package/dist/editor/entityCatalog.d.ts +42 -0
- package/dist/editor/entityCatalog.js +101 -0
- package/dist/editor/environment.d.ts +74 -0
- package/dist/editor/environment.js +169 -0
- package/dist/editor/index.d.ts +26 -1
- package/dist/editor/index.js +8 -1
- package/dist/editor/minimap.d.ts +31 -0
- package/dist/editor/minimap.js +73 -0
- package/dist/editor/streamer.d.ts +66 -0
- package/dist/editor/streamer.js +68 -0
- package/dist/editor/types.d.ts +143 -0
- package/dist/editor/world.d.ts +136 -0
- package/dist/editor/world.js +303 -0
- package/dist/game/breeding.d.ts +161 -0
- package/dist/game/breeding.js +181 -0
- package/dist/game/cameraConfig.d.ts +451 -0
- package/dist/game/cameraConfig.js +1 -0
- package/dist/game/clipRoles.d.ts +51 -0
- package/dist/game/clipRoles.js +142 -0
- package/dist/game/defineGame.d.ts +16 -9
- package/dist/game/defineGame.js +14 -6
- package/dist/game/defineSystem.d.ts +2 -0
- package/dist/game/defineSystem.js +2 -0
- package/dist/game/events.d.ts +28 -0
- package/dist/game/partAnimation.d.ts +78 -0
- package/dist/game/partAnimation.js +147 -0
- package/dist/game/playableGame.d.ts +72 -440
- package/dist/game/playableGame.js +1 -1
- package/dist/game/progression.d.ts +35 -0
- package/dist/game/progression.js +22 -1
- package/dist/game/quest.js +1 -3
- package/dist/game/tribe.d.ts +184 -0
- package/dist/game/tribe.js +432 -0
- package/dist/gameplay.d.ts +3 -1
- package/dist/gameplay.js +3 -1
- package/dist/inventory/encumbrance.d.ts +69 -0
- package/dist/inventory/encumbrance.js +68 -0
- package/dist/inventory/inventoryModel.d.ts +24 -8
- package/dist/inventory/inventoryModel.js +47 -8
- package/dist/item/durability.js +1 -3
- package/dist/meta/changelog.d.ts +1 -1
- package/dist/meta/changelog.js +48 -1
- package/dist/movement/movementModel.d.ts +15 -1
- package/dist/movement/movementModel.js +33 -15
- package/dist/movement/playerMovement.js +102 -2
- package/dist/multiplayer/combatSnapshot.js +13 -8
- package/dist/multiplayer/presenceModel.d.ts +2 -0
- package/dist/multiplayer/presenceModel.js +8 -0
- package/dist/physics/drivableVehicle.d.ts +2 -0
- package/dist/physics/drivableVehicle.js +1 -1
- package/dist/physics/flightDynamics.d.ts +82 -0
- package/dist/physics/flightDynamics.js +165 -0
- package/dist/physics/gravityField.d.ts +25 -0
- package/dist/physics/gravityField.js +41 -0
- package/dist/physics/kinematicVehicle.d.ts +87 -0
- package/dist/physics/kinematicVehicle.js +193 -11
- package/dist/physics/physicsWorld.d.ts +26 -0
- package/dist/physics/physicsWorld.js +109 -117
- package/dist/physics/vehicleObstacles.d.ts +44 -0
- package/dist/physics/vehicleObstacles.js +115 -0
- package/dist/random/rng.d.ts +4 -1
- package/dist/random/rng.js +4 -1
- package/dist/runtime/adapter.d.ts +13 -0
- package/dist/runtime/adapter.js +13 -0
- package/dist/runtime/context/combat.d.ts +51 -0
- package/dist/runtime/context/combat.js +131 -0
- package/dist/runtime/context/combatFx.js +15 -5
- package/dist/runtime/context/deathLoot.d.ts +30 -0
- package/dist/runtime/context/deathLoot.js +39 -0
- package/dist/runtime/context/player.d.ts +48 -0
- package/dist/runtime/context/player.js +125 -0
- package/dist/runtime/context/scene.d.ts +60 -0
- package/dist/runtime/context/scene.js +329 -0
- package/dist/runtime/context/snapshotCodecs.d.ts +12 -0
- package/dist/runtime/context/snapshotCodecs.js +26 -0
- package/dist/runtime/descriptors/baseline.js +26 -3
- package/dist/runtime/descriptors/features.d.ts +5 -0
- package/dist/runtime/descriptors/features.js +20 -2
- package/dist/runtime/gameContext.d.ts +2 -428
- package/dist/runtime/gameContext.js +133 -500
- package/dist/runtime/gameContextTypes.d.ts +500 -0
- package/dist/runtime/gameContextTypes.js +1 -0
- package/dist/runtime/headlessRunner.d.ts +17 -2
- package/dist/runtime/headlessRunner.js +15 -0
- package/dist/runtime/hostPolicy.d.ts +51 -0
- package/dist/runtime/hostPolicy.js +68 -0
- package/dist/runtime/hostedGameRunner.d.ts +3 -1
- package/dist/runtime/hostedGameRunner.js +1 -0
- package/dist/runtime/hostedWorldSession.d.ts +3 -1
- package/dist/runtime/hostedWorldSession.js +1 -0
- package/dist/runtime/worldSnapshot.d.ts +13 -1
- package/dist/runtime/worldSnapshot.js +15 -3
- package/dist/scene/assetCatalog.d.ts +7 -0
- package/dist/scene/assetSpace.js +1 -3
- package/dist/scene/authoredTriggers.d.ts +50 -0
- package/dist/scene/authoredTriggers.js +114 -0
- package/dist/scene/builtinSceneKinds.js +8 -3
- package/dist/scene/colliders.d.ts +79 -0
- package/dist/scene/colliders.js +170 -0
- package/dist/scene/collisionMesh.d.ts +94 -0
- package/dist/scene/collisionMesh.js +699 -0
- package/dist/scene/companion.d.ts +147 -0
- package/dist/scene/companion.js +193 -0
- package/dist/scene/entityStats.d.ts +7 -9
- package/dist/scene/entityStats.js +19 -15
- package/dist/scene/sceneKinds.d.ts +16 -0
- package/dist/scene/sceneKinds.js +4 -0
- package/dist/scene/sceneRaycast.js +15 -0
- package/dist/stats/spawnLevelStats.d.ts +110 -0
- package/dist/stats/spawnLevelStats.js +140 -0
- package/dist/stats/statModifiers.d.ts +16 -0
- package/dist/stats/statModifiers.js +30 -1
- package/dist/stats/statPool.d.ts +70 -0
- package/dist/stats/statPool.js +62 -0
- package/dist/store/changeSignal.d.ts +3 -0
- package/dist/store/changeSignal.js +2 -0
- package/dist/store/observableKeyedStore.d.ts +2 -0
- package/dist/store/observableKeyedStore.js +1 -0
- package/dist/survival/decayMeter.js +1 -3
- package/dist/survival/regionHealth.js +1 -3
- package/dist/ui/hudLayout.d.ts +5 -0
- package/dist/ui/hudLayout.js +17 -1
- package/dist/ui/panelModel.d.ts +120 -0
- package/dist/ui/panelModel.js +168 -0
- package/dist/ui.d.ts +1 -0
- package/dist/ui.js +1 -0
- package/dist/world/authoredEntities.d.ts +29 -0
- package/dist/world/authoredEntities.js +29 -0
- package/dist/world/authoredObjects.d.ts +15 -1
- package/dist/world/authoredObjects.js +13 -1
- package/dist/world/authoredSpawn.d.ts +39 -0
- package/dist/world/authoredSpawn.js +37 -0
- package/dist/world/buildSockets.d.ts +152 -0
- package/dist/world/buildSockets.js +188 -0
- package/dist/world/buildingLots.d.ts +84 -0
- package/dist/world/buildingLots.js +119 -0
- package/dist/world/buildings.d.ts +6 -0
- package/dist/world/cityBlocks.d.ts +152 -0
- package/dist/world/cityBlocks.js +670 -0
- package/dist/world/cityContent.d.ts +77 -0
- package/dist/world/cityContent.js +261 -0
- package/dist/world/cityGenerator.d.ts +41 -0
- package/dist/world/cityGenerator.js +58 -0
- package/dist/world/cityGeometry.d.ts +114 -0
- package/dist/world/cityGeometry.js +573 -0
- package/dist/world/cityKind.d.ts +314 -0
- package/dist/world/cityKind.js +1578 -0
- package/dist/world/environmentSummary.js +57 -1
- package/dist/world/features.d.ts +53 -5
- package/dist/world/features.js +15 -3
- package/dist/world/grassKind.js +2 -2
- package/dist/world/markers.d.ts +50 -4
- package/dist/world/markers.js +49 -0
- package/dist/world/massing.js +1 -1
- package/dist/world/minimapBake.d.ts +78 -0
- package/dist/world/minimapBake.js +208 -0
- package/dist/world/minimapTrack.d.ts +17 -0
- package/dist/world/minimapTrack.js +22 -0
- package/dist/world/place.d.ts +166 -0
- package/dist/world/place.js +96 -0
- package/dist/world/placeAsset.js +3 -1
- package/dist/world/poleLineKind.d.ts +40 -0
- package/dist/world/poleLineKind.js +97 -0
- package/dist/world/polyline.js +9 -2
- package/dist/world/resourceNode.d.ts +109 -0
- package/dist/world/resourceNode.js +140 -0
- package/dist/world/roads.d.ts +19 -2
- package/dist/world/roads.js +60 -3
- package/dist/world/scatter.js +2 -20
- package/dist/world/streetGenerator.d.ts +159 -0
- package/dist/world/streetGenerator.js +684 -0
- package/dist/world/streets.d.ts +103 -1
- package/dist/world/streets.js +273 -0
- package/dist/world/terraform.js +58 -88
- package/dist/world/terrain.d.ts +65 -1
- package/dist/world/terrain.js +119 -2
- package/dist/world.d.ts +14 -5
- package/dist/world.js +12 -3
- package/package.json +1 -1
- package/skills/game-design/SKILL.md +28 -0
- package/skills/game-design/agents/openai.yaml +4 -0
- package/skills/game-design/references/application-playbook.md +170 -0
- package/skills/game-design/references/field-guide.md +288 -0
- package/skills/jgengine/SKILL.md +8 -4
- package/skills/jgengine/api.md +182 -81
- package/skills/jgengine/capabilities.md +104 -2
- package/skills/jgengine/recipes/minimal-game.md +88 -0
- package/skills/jgengine-combat/SKILL.md +19 -1
- package/skills/jgengine-combat/api.md +75 -2
- package/skills/jgengine-combat/capabilities.md +61 -1
- package/skills/jgengine-combat/recipes/portable-damage-effects.md +197 -0
- package/skills/jgengine-combat/recipes/portable-runtime-state.md +154 -0
- package/skills/jgengine-combat/recipes/portable-stat-pools.md +122 -0
- package/skills/jgengine-combat/recipes/portable-weapon-plumbing.md +156 -0
- package/skills/jgengine-combat/recipes/visible-attacks.md +81 -0
- package/skills/jgengine-combat/reference.md +33 -4
- package/skills/jgengine-gameplay/SKILL.md +8 -0
- package/skills/jgengine-gameplay/api.md +182 -26
- package/skills/jgengine-gameplay/capabilities.md +96 -2
- package/skills/jgengine-gameplay/recipes/portable-xp-leveling.md +168 -0
- package/skills/jgengine-gameplay/reference-systems.md +10 -5
- package/skills/jgengine-world/SKILL.md +13 -0
- package/skills/jgengine-world/api.md +453 -21
- package/skills/jgengine-world/capabilities.md +112 -2
- package/skills/jgengine-world/recipes/commanding-entities.md +128 -0
- package/skills/jgengine-world/reference.md +43 -4
- package/skills/jgengine/reference-cartridge.md +0 -72
|
@@ -8,6 +8,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
8
8
|
|
|
9
9
|
- `advanceLedger` (function) · `import { advanceLedger } from "@jgengine/core/gameplay"`
|
|
10
10
|
|
|
11
|
+
## auction-book — timed bid auctions with escrowed bids, buyout, anti-snipe close extension, and collection-box settlement
|
|
12
|
+
|
|
13
|
+
- `createAuctionBook` (function) · `import { createAuctionBook } from "@jgengine/core/gameplay"`
|
|
14
|
+
|
|
11
15
|
## best-record — persist personal-best times/scores with safe storage fallback
|
|
12
16
|
|
|
13
17
|
- `createRecordBook` (function) · `import { createRecordBook } from "@jgengine/core/gameplay"`
|
|
@@ -24,6 +28,19 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
24
28
|
|
|
25
29
|
- `cancelJob` (function) · `import { cancelJob } from "@jgengine/core/gameplay"`
|
|
26
30
|
|
|
31
|
+
## carry-encumbrance — carried mass vs capacity into movement penalty tiers and a speed multiplier
|
|
32
|
+
|
|
33
|
+
- `resolveEncumbrance` (function) · `import { resolveEncumbrance } from "@jgengine/core/inventory/encumbrance"`
|
|
34
|
+
|
|
35
|
+
## carry-load — sum carried mass from item stacks via an injected mass resolver
|
|
36
|
+
|
|
37
|
+
- `totalLoad` (function) · `import { totalLoad } from "@jgengine/core/inventory/encumbrance"`
|
|
38
|
+
|
|
39
|
+
## clip-roles — map a rigged asset's pack-specific clip name to its semantic animation role
|
|
40
|
+
|
|
41
|
+
- `classifyClip` (function) · `import { classifyClip } from "@jgengine/core/game/clipRoles"`
|
|
42
|
+
- `defaultAnimationForClips` (function) · `import { defaultAnimationForClips } from "@jgengine/core/game/clipRoles"`
|
|
43
|
+
|
|
27
44
|
## compose-game-loop — fold composable systems into the game loop without a manual tick fan-out
|
|
28
45
|
|
|
29
46
|
- `composeGameLoop` (function) · `import { composeGameLoop } from "@jgengine/core/gameplay"`
|
|
@@ -36,6 +53,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
36
53
|
|
|
37
54
|
- `createCosmetics` (function) · `import { createCosmetics } from "@jgengine/core/gameplay"`
|
|
38
55
|
|
|
56
|
+
## creature-breeding — deterministic stat inheritance, mutation, and lineage genetics for taming games
|
|
57
|
+
|
|
58
|
+
- `breedOffspring` (function) · `import { breedOffspring } from "@jgengine/core/game/breeding"`
|
|
59
|
+
|
|
39
60
|
## decay-meter — survival meters that drain/refill over game time (hunger, water, oxygen, stamina)
|
|
40
61
|
|
|
41
62
|
- `createDecayMeterSet` (function) · `import { createDecayMeterSet } from "@jgengine/core/gameplay"`
|
|
@@ -51,9 +72,9 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
51
72
|
- `evaluatePredicate` (function) · `import { evaluatePredicate } from "@jgengine/core/gameplay"`
|
|
52
73
|
- `readPath` (function) · `import { readPath } from "@jgengine/core/gameplay"`
|
|
53
74
|
|
|
54
|
-
## define-
|
|
75
|
+
## define-system — composable game behavior — pure data + hooks the engine schedules; pass via `defineGame({ systems })`
|
|
55
76
|
|
|
56
|
-
- `
|
|
77
|
+
- `defineSystem` (function) · `import { defineSystem } from "@jgengine/core/gameplay"`
|
|
57
78
|
|
|
58
79
|
## detect — fire-once threshold/milestone/tier crossings when a value moves
|
|
59
80
|
|
|
@@ -67,6 +88,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
67
88
|
|
|
68
89
|
- `applyWear` (function) · `import { applyWear } from "@jgengine/core/gameplay"`
|
|
69
90
|
|
|
91
|
+
## encumbrance-move-curve — progressive move-speed multiplier from a carry-load fraction
|
|
92
|
+
|
|
93
|
+
- `encumbranceMoveMultiplier` (function) · `import { encumbranceMoveMultiplier } from "@jgengine/core/inventory/encumbrance"`
|
|
94
|
+
|
|
70
95
|
## enqueue-work — reserve inputs and add a timed job, honoring capacity and validation policy
|
|
71
96
|
|
|
72
97
|
- `enqueue` (function) · `import { enqueue } from "@jgengine/core/gameplay"`
|
|
@@ -87,6 +112,30 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
87
112
|
|
|
88
113
|
- `SystemDefinition` (interface) · `import { SystemDefinition } from "@jgengine/core/gameplay"`
|
|
89
114
|
|
|
115
|
+
## imprint-bonus — apply imprint stat and handler bonuses at an imprint fraction
|
|
116
|
+
|
|
117
|
+
- `applyImprintBonus` (function) · `import { applyImprintBonus } from "@jgengine/core/game/breeding"`
|
|
118
|
+
|
|
119
|
+
## imprint-increment — per-care-request imprint gain across a maturation schedule
|
|
120
|
+
|
|
121
|
+
- `imprintIncrementPerRequest` (function) · `import { imprintIncrementPerRequest } from "@jgengine/core/game/breeding"`
|
|
122
|
+
|
|
123
|
+
## incubation-tick — advance egg incubation health inside/outside its temperature range
|
|
124
|
+
|
|
125
|
+
- `tickIncubation` (function) · `import { tickIncubation } from "@jgengine/core/game/breeding"`
|
|
126
|
+
|
|
127
|
+
## incubation-viability — test whether an egg incubation still has health to hatch
|
|
128
|
+
|
|
129
|
+
- `incubationViable` (function) · `import { incubationViable } from "@jgengine/core/game/breeding"`
|
|
130
|
+
|
|
131
|
+
## inventory-grid — a bag of stackable items with add, remove, and move
|
|
132
|
+
|
|
133
|
+
- `createEmptyInventory` (function) · `import { createEmptyInventory } from "@jgengine/core/inventory/inventoryModel"`
|
|
134
|
+
|
|
135
|
+
## inventory-split — split a stack into a target or first-empty slot
|
|
136
|
+
|
|
137
|
+
- `splitStack` (function) · `import { splitStack } from "@jgengine/core/inventory/inventoryModel"`
|
|
138
|
+
|
|
90
139
|
## item-generation — compose constraints, weighted pools, transforms, and provenance into a deterministic generated item
|
|
91
140
|
|
|
92
141
|
- `generate` (function) · `import { generate } from "@jgengine/core/gameplay"`
|
|
@@ -126,6 +175,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
126
175
|
|
|
127
176
|
- `createLeaderboard` (function) · `import { createLeaderboard } from "@jgengine/core/gameplay"`
|
|
128
177
|
|
|
178
|
+
## leveling-track — grant XP, resolve level-ups against a curve, and write level+xp stats back through a stat adapter
|
|
179
|
+
|
|
180
|
+
- `leveling` (function) · `import { leveling } from "@jgengine/core/gameplay"`
|
|
181
|
+
|
|
129
182
|
## lifecycle — declarative start/restart run flow — the engine owns the command glue and phase sync, the game supplies pure state transitions
|
|
130
183
|
|
|
131
184
|
- `LifecycleConfig` (interface) · `import { LifecycleConfig } from "@jgengine/core/gameplay"`
|
|
@@ -160,6 +213,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
160
213
|
- `createLootRegistry` (function) · `import { createLootRegistry } from "@jgengine/core/gameplay"`
|
|
161
214
|
- `lootTable` (function) · `import { lootTable } from "@jgengine/core/gameplay"`
|
|
162
215
|
|
|
216
|
+
## maturation-stage — resolve the baby/juvenile/adolescent/adult stage from elapsed maturation
|
|
217
|
+
|
|
218
|
+
- `maturationStage` (function) · `import { maturationStage } from "@jgengine/core/game/breeding"`
|
|
219
|
+
|
|
163
220
|
## modular-item — attach parts into item mount slots to compute combined stats
|
|
164
221
|
|
|
165
222
|
- `slotAccepts` (function) · `import { slotAccepts } from "@jgengine/core/gameplay"`
|
|
@@ -190,6 +247,11 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
190
247
|
- `resolveSelection` (function) · `import { resolveSelection } from "@jgengine/core/gameplay"`
|
|
191
248
|
- `validateLayers` (function) · `import { validateLayers } from "@jgengine/core/gameplay"`
|
|
192
249
|
|
|
250
|
+
## part-motion — sample the root bob/sway/squash/flinch/death pose for a rig-less part-composed character
|
|
251
|
+
|
|
252
|
+
- `sampleBodyPose` (function) · `import { sampleBodyPose } from "@jgengine/core/game/partAnimation"`
|
|
253
|
+
- `samplePartPose` (function) · `import { samplePartPose } from "@jgengine/core/game/partAnimation"`
|
|
254
|
+
|
|
193
255
|
## pause-scheduled-rule — stop a scheduled rule from firing while retaining its cursor
|
|
194
256
|
|
|
195
257
|
- `pauseRule` (function) · `import { pauseRule } from "@jgengine/core/gameplay"`
|
|
@@ -230,10 +292,18 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
230
292
|
|
|
231
293
|
- `thresholdScale` (function) · `import { thresholdScale } from "@jgengine/core/gameplay"`
|
|
232
294
|
|
|
295
|
+
## price-history — rolling per-item sale records aggregated into market price stats
|
|
296
|
+
|
|
297
|
+
- `createPriceHistory` (function) · `import { createPriceHistory } from "@jgengine/core/gameplay"`
|
|
298
|
+
|
|
233
299
|
## production-building — a factory building converting inputs to outputs over time
|
|
234
300
|
|
|
235
301
|
- `createProductionState` (function) · `import { createProductionState } from "@jgengine/core/gameplay"`
|
|
236
302
|
|
|
303
|
+
## progression-curve — evaluate a level/rank curve (const, linear, power, geometric, steps, piecewise) at a point
|
|
304
|
+
|
|
305
|
+
- `evalCurve` (function) · `import { evalCurve } from "@jgengine/core/gameplay"`
|
|
306
|
+
|
|
237
307
|
## quest-log — track accepted quests and their per-objective progress
|
|
238
308
|
|
|
239
309
|
- `createQuestJournal` (function) · `import { createQuestJournal } from "@jgengine/core/gameplay"`
|
|
@@ -281,6 +351,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
281
351
|
|
|
282
352
|
- `createRunDraft` (function) · `import { createRunDraft } from "@jgengine/core/gameplay"`
|
|
283
353
|
|
|
354
|
+
## seeded-random — injected deterministic randomness for game logic — never `Math.random` in a simulation
|
|
355
|
+
|
|
356
|
+
- `seededRng` (function) · `import { seededRng } from "@jgengine/core/gameplay"`
|
|
357
|
+
|
|
284
358
|
## set — a bounded keyed value in a caller-owned serializable record
|
|
285
359
|
|
|
286
360
|
- `setValue` (function) · `import { setValue } from "@jgengine/core/gameplay"`
|
|
@@ -318,6 +392,14 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
318
392
|
|
|
319
393
|
- `touchButtonShape` (function) · `import { touchButtonShape } from "@jgengine/core/gameplay"`
|
|
320
394
|
|
|
395
|
+
## tribe-group — shared-ownership group (tribe/guild/clan) with ranked permissions, group vs personal assets, alliances, and a bounded event log
|
|
396
|
+
|
|
397
|
+
- `createTribe` (function) · `import { createTribe } from "@jgengine/core/game/tribe"`
|
|
398
|
+
|
|
399
|
+
## tribe-registry — registry of tribes with mutual alliances and cross-tribe relation lookup
|
|
400
|
+
|
|
401
|
+
- `createTribeRegistry` (function) · `import { createTribeRegistry } from "@jgengine/core/game/tribe"`
|
|
402
|
+
|
|
321
403
|
## triggered-rules — event-conditioned effects with declarative predicates, lifetimes, and stacking
|
|
322
404
|
|
|
323
405
|
- `createTriggeredRuleEngine` (function) · `import { createTriggeredRuleEngine } from "@jgengine/core/gameplay"`
|
|
@@ -325,10 +407,22 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
325
407
|
- `listRuleEffects` (function) · `import { listRuleEffects } from "@jgengine/core/gameplay"`
|
|
326
408
|
- `registerRuleEffect` (function) · `import { registerRuleEffect } from "@jgengine/core/gameplay"`
|
|
327
409
|
|
|
410
|
+
## typed-keyed-store — a cast-free typed handle onto a per-owner keyed family of reactive game-store slots, replayable and host-authoritative
|
|
411
|
+
|
|
412
|
+
- `defineKeyedStore` (function) · `import { defineKeyedStore } from "@jgengine/core/store/defineKeyedStore"`
|
|
413
|
+
|
|
414
|
+
## typed-store — a cast-free typed handle onto one reactive game-store slot, replayable and host-authoritative
|
|
415
|
+
|
|
416
|
+
- `defineStore` (function) · `import { defineStore } from "@jgengine/core/store/defineStore"`
|
|
417
|
+
|
|
328
418
|
## unit-training — compose a timed work queue that trains catalog units into spawn orders
|
|
329
419
|
|
|
330
420
|
- `unitTrainingConfig` (function) · `import { unitTrainingConfig } from "@jgengine/core/gameplay"`
|
|
331
421
|
|
|
422
|
+
## unlock-points — spendable point pool earned per level and spent to unlock nodes, with refund and respec
|
|
423
|
+
|
|
424
|
+
- `createUnlockPoints` (function) · `import { createUnlockPoints } from "@jgengine/core/economy/unlockPoints"`
|
|
425
|
+
|
|
332
426
|
## unlockables — gate content behind unlock conditions the player earns
|
|
333
427
|
|
|
334
428
|
- `createUnlockCatalog` (function) · `import { createUnlockCatalog } from "@jgengine/core/gameplay"`
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Add XP and leveling to an existing store
|
|
2
|
+
|
|
3
|
+
Use this recipe when an existing JavaScript/TypeScript project owns its player
|
|
4
|
+
state and save format but wants JGengine's deterministic XP curves,
|
|
5
|
+
multi-level grants, and per-level events. No `GameContext`, renderer, React,
|
|
6
|
+
entity store, or JGengine loop is required.
|
|
7
|
+
|
|
8
|
+
## Install and focused imports
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
bun add @jgengine/core
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import {
|
|
16
|
+
leveling,
|
|
17
|
+
type LevelingStatAccess,
|
|
18
|
+
} from "@jgengine/core/game/progression";
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Caller-owned save data
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
interface SavedPool {
|
|
25
|
+
current: number;
|
|
26
|
+
max: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface PlayerSave {
|
|
30
|
+
experience: SavedPool;
|
|
31
|
+
rank: SavedPool;
|
|
32
|
+
unlockedAbilities: string[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface ExistingSave {
|
|
36
|
+
players: Record<string, PlayerSave>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let save: ExistingSave = {
|
|
40
|
+
players: {
|
|
41
|
+
player_1: {
|
|
42
|
+
experience: { current: 0, max: 100 },
|
|
43
|
+
rank: { current: 1, max: 20 },
|
|
44
|
+
unlockedAbilities: [],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Minimal adapter
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
const stats: LevelingStatAccess = {
|
|
54
|
+
get(userId, statId) {
|
|
55
|
+
const player = save.players[userId];
|
|
56
|
+
if (player === undefined) return null;
|
|
57
|
+
if (statId === "experience") return player.experience;
|
|
58
|
+
if (statId === "rank") return player.rank;
|
|
59
|
+
return null;
|
|
60
|
+
},
|
|
61
|
+
set(userId, statId, patch) {
|
|
62
|
+
const player = save.players[userId];
|
|
63
|
+
if (player === undefined) return false;
|
|
64
|
+
const previous = statId === "experience"
|
|
65
|
+
? player.experience
|
|
66
|
+
: statId === "rank"
|
|
67
|
+
? player.rank
|
|
68
|
+
: null;
|
|
69
|
+
if (previous === null) return false;
|
|
70
|
+
const next = {
|
|
71
|
+
current: patch.current ?? previous.current,
|
|
72
|
+
max: patch.max ?? previous.max,
|
|
73
|
+
};
|
|
74
|
+
const nextPlayer = statId === "experience"
|
|
75
|
+
? { ...player, experience: next }
|
|
76
|
+
: { ...player, rank: next };
|
|
77
|
+
save = {
|
|
78
|
+
...save,
|
|
79
|
+
players: {
|
|
80
|
+
...save.players,
|
|
81
|
+
[userId]: nextPlayer,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
return true;
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The adapter may call a Zustand `set`, dispatch a Redux action, write an ECS
|
|
90
|
+
component, or replace plain data as above. It never mirrors the player into a
|
|
91
|
+
JGengine store.
|
|
92
|
+
|
|
93
|
+
## Configure and grant XP
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
const emitted: unknown[] = [];
|
|
97
|
+
const existingEvents = {
|
|
98
|
+
emit(name: string, payload: unknown) {
|
|
99
|
+
emitted.push({ name, payload });
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const playerLevel = leveling({
|
|
104
|
+
xpForLevel: {
|
|
105
|
+
kind: "power",
|
|
106
|
+
base: 80,
|
|
107
|
+
exponent: 1.35,
|
|
108
|
+
round: "floor",
|
|
109
|
+
},
|
|
110
|
+
maxLevel: 20,
|
|
111
|
+
xpStat: "experience",
|
|
112
|
+
levelStat: "rank",
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const levelEvents: number[] = [];
|
|
116
|
+
const levelsGained = playerLevel.grantXp(
|
|
117
|
+
stats,
|
|
118
|
+
"player_1",
|
|
119
|
+
900,
|
|
120
|
+
(level) => {
|
|
121
|
+
levelEvents.push(level);
|
|
122
|
+
existingEvents.emit("player-level-up", { playerId: "player_1", level });
|
|
123
|
+
},
|
|
124
|
+
);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`levelsGained` is the count returned to the caller. The callback fires once for
|
|
128
|
+
every reached level in ascending order, so a large reward can unlock each
|
|
129
|
+
milestone deterministically instead of collapsing them into one final event.
|
|
130
|
+
|
|
131
|
+
Use `playerLevel.resolve(level, xp)` when prediction/UI needs the same math
|
|
132
|
+
without writing through the adapter.
|
|
133
|
+
|
|
134
|
+
## Save and restore
|
|
135
|
+
|
|
136
|
+
The adapter's authoritative values already live in the existing save:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
const encoded = JSON.stringify(save);
|
|
140
|
+
save = JSON.parse(encoded) as ExistingSave;
|
|
141
|
+
|
|
142
|
+
// Recreate an adapter over the restored store, then continue normally.
|
|
143
|
+
playerLevel.grantXp(stats, "player_1", 75, (level) => {
|
|
144
|
+
existingEvents.emit("player-level-up", { playerId: "player_1", level });
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The leveling track is immutable configuration; recreate it from the same curve
|
|
149
|
+
after load. Version curve changes in the existing project's migration layer.
|
|
150
|
+
|
|
151
|
+
## Ownership
|
|
152
|
+
|
|
153
|
+
The existing project retains player identity, store updates, save schema,
|
|
154
|
+
curve/content choice, reward sources, event bus, unlock handling, UI, backend,
|
|
155
|
+
and when XP is granted. JGengine owns curve evaluation, surplus rollover,
|
|
156
|
+
level caps, ordered level events, and the two-method stat adapter contract.
|
|
157
|
+
|
|
158
|
+
## Common traps
|
|
159
|
+
|
|
160
|
+
- Initialize both configured stat ids; `grantXp` returns `0` when either is
|
|
161
|
+
missing.
|
|
162
|
+
- Treat positive and negative XP policy as game-owned input validation;
|
|
163
|
+
sanitize rewards before calling when XP loss is not allowed.
|
|
164
|
+
- The default threshold mode is `perLevel`. Use `cumulative` only when the curve
|
|
165
|
+
represents total lifetime XP required to reach each level.
|
|
166
|
+
- Keep `rank.max` aligned with `maxLevel` in the caller's schema.
|
|
167
|
+
- Apply milestone rewards from each callback invocation; do not assume a large
|
|
168
|
+
grant emits only the final reached level.
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
# Composable systems (`defineSystem`)
|
|
2
2
|
|
|
3
|
-
Single public authoring path: `defineGame({ systems, loop?, … })` from `@jgengine/shell/defineGame
|
|
3
|
+
Single public authoring path: `defineGame({ systems, loop?, … })` from `@jgengine/shell/defineGame`. Systems are meaningful capabilities — not micro-ticks.
|
|
4
|
+
|
|
5
|
+
## Portable XP and leveling
|
|
6
|
+
|
|
7
|
+
`leveling` (`@jgengine/core/game/progression`) is usable without a scheduled
|
|
8
|
+
system or game context. Its `LevelingStatAccess` reads and replaces two
|
|
9
|
+
caller-named pools in an existing store; `grantXp` writes settled XP/threshold
|
|
10
|
+
and level state, then emits every reached level in ascending order. State stays
|
|
11
|
+
in the caller's save format and round-trips as ordinary JSON. See the
|
|
12
|
+
[portable XP/leveling recipe](recipes/portable-xp-leveling.md).
|
|
4
13
|
|
|
5
14
|
## API
|
|
6
15
|
|
|
@@ -50,10 +59,6 @@ Multiple systems may share a channel. Order is stage tables + optional `before`/
|
|
|
50
59
|
|
|
51
60
|
Default stages: fixed `input → movement → combat → ai → activities → cleanup`; frame includes those plus `animation → camera → effects`.
|
|
52
61
|
|
|
53
|
-
## Cartridge path
|
|
54
|
-
|
|
55
|
-
Cartridge remains a convenience wrapper. Express the same shape as ordinary systems (`runFlow`, wave director, combat) under `defineGame({ systems })` when you outgrow the cartridge schema — one authoring model, no rewrite cliff.
|
|
56
|
-
|
|
57
62
|
## Ownership
|
|
58
63
|
|
|
59
64
|
- **Save / replicate** — system modules register via `ctx.game.registerSave` / `registerReplicate` at install.
|
|
@@ -11,8 +11,16 @@ This skill owns runtime spatial behavior: authored-scene consumption, environmen
|
|
|
11
11
|
|
|
12
12
|
Search [capabilities.md](capabilities.md) by intent before designing a primitive. Use [api.md](api.md) for exact exports and [reference.md](reference.md) for environment, camera, navigation, physics, audio, and authored-scene recipes.
|
|
13
13
|
|
|
14
|
+
For a *connected* walkthrough that wires several primitives into a running loop, read the goal-oriented recipes under [recipes/](recipes/) — organized by composition seam (what connects to what), never by genre. Start there before reading a game's source to learn how pieces fit; a hybrid game is just a different composition of the same primitives.
|
|
15
|
+
|
|
16
|
+
- [recipes/commanding-entities.md](recipes/commanding-entities.md) — select → order → tick → resolve: direct command over a group of entities (the command loop behind squad control, base-defense, herding, autobattle, or a mutating game's real-time phase).
|
|
17
|
+
|
|
14
18
|
## Canonical workflows
|
|
15
19
|
|
|
20
|
+
### Declare the place
|
|
21
|
+
|
|
22
|
+
A world is the place you play in: substrate + laws, via `world()` from `@jgengine/core/world/place` — `{ id, ground: { mode: flat|round|voxel|board, size, surface?, generator? }, physics? }`. Thin is complete: flat with `Infinity` axes for 3D, `board` for 2D, or omit `world` for pure UI/rules games. Never put seed, sky, or vegetation in a world definition — seeds derive from world id + save/run (`seedForPlace`); sky look and foliage scatter are editor-authored scene content, with the engine default sky when the document has none. `ground.surface` carries matter/feel laws (metal vs slime vs felt) that the same rule systems read — swap the surface, not the rules. See [reference.md](reference.md) for the full shape; `environment()` is the legacy consumption path for editor/preset-written scene data, never the starter.
|
|
23
|
+
|
|
16
24
|
### Authored world
|
|
17
25
|
|
|
18
26
|
1. Load the scene document through the shared authored-scene feature.
|
|
@@ -28,8 +36,13 @@ Choose input intent, controller/motor, collision/navigation, and camera as separ
|
|
|
28
36
|
|
|
29
37
|
Compose perception, selection, planning/behavior, movement, and lifecycle independently. Inject randomness and scheduling. Use spatial indexes, interest tiers, or bounded candidate sets for scale.
|
|
30
38
|
|
|
39
|
+
### Fallback-seam diagnostics
|
|
40
|
+
|
|
41
|
+
Render seams fall back to placeholders when content is unauthored: default green ground (no environment), primitive capsule/box actors (no `entityModels`/`objectModels` mapping), stylized proxy foliage (no scatter `resolveItem`). These placeholders are sometimes intended, so runtime never changes — but a dev-only, opt-in probe (`@jgengine/core/devtools/fallbackSeams`) tells "unauthored/misconfigured" apart from "intended". The shell arms it via `armFallbackSeams(devtoolsEnabled)`; each seam reports at its choice site (`reportFallbackSeam`), and counts surface through the devtools `fallbacks` probe. Disarmed (production) it is a pure, allocation-free no-op.
|
|
42
|
+
|
|
31
43
|
## Traps
|
|
32
44
|
|
|
45
|
+
- Do not put seed, sky presets, or vegetation/scatter fields in a world definition — `world()` rejects them; dressing belongs to the editor's scene document.
|
|
33
46
|
- Do not put UI layout, touch chrome, combat resolution, or asset acquisition here.
|
|
34
47
|
- Do not duplicate editor coordinates in runtime state.
|
|
35
48
|
- Public APIs accept semantic policies and caller data, not renderer mechanics or internal tuning rolls.
|