@jgengine/sql 0.18.0 → 0.19.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.
@@ -12,10 +12,30 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
12
12
 
13
13
  - `collectAuthoredTriggers` (function) · `import { collectAuthoredTriggers } from "@jgengine/shell/gameKit"`
14
14
 
15
+ ## chase-view-cycle — cycle a vehicle camera between chase, hood and cockpit views at runtime
16
+
17
+ - `nextChaseView` (function) · `import { nextChaseView } from "@jgengine/core/runtime/cameraDirector"`
18
+
19
+ ## client-side — input prediction with replay reconciliation
20
+
21
+ - `createPredictionBuffer` (function) · `import { createPredictionBuffer } from "@jgengine/core/runtime/prediction"`
22
+
15
23
  ## collider-autofit — hitboxes and physical bodies fit each kind's rendered model bounds automatically — no hand-tuned sizes
16
24
 
17
25
  - `GameContextModels` (interface) · `import { GameContextModels } from "@jgengine/core/runtime/gameContext"`
18
26
 
27
+ ## command-number — validate finite, bounded numbers and integers at command boundaries
28
+
29
+ - `readInputNumber` (function) · `import { readInputNumber } from "@jgengine/core/runtime/commandInput"`
30
+
31
+ ## command-parse — parse untrusted command input once so every command stage sees typed, bounded values
32
+
33
+ - `defineCommand` (function) · `import { defineCommand } from "@jgengine/core/runtime/commandRunner"`
34
+
35
+ ## command-quantity — validate bounded whole-item counts at command boundaries
36
+
37
+ - `readQuantity` (function) · `import { readQuantity } from "@jgengine/core/runtime/commandInput"`
38
+
19
39
  ## default-walk-codes — stock WASD + jump key codes for the shell walk controller
20
40
 
21
41
  - `DEFAULT_WALK_CODES` (const) · `import { DEFAULT_WALK_CODES } from "@jgengine/shell/gameKit"`
@@ -32,6 +52,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
32
52
 
33
53
  - `EditorCatalogDefinition` (interface) · `import { EditorCatalogDefinition } from "@jgengine/shell/gameKit"`
34
54
 
55
+ ## fire-input — bind a key or mouse button to a named action that runs the same-named command with the aim; repeatMs auto-fires while held
56
+
57
+ - `ActionCodesMap` (type) · `import { ActionCodesMap } from "@jgengine/core/authoring"`
58
+
35
59
  ## game-system — declare a composable capability with its own schedule and lifecycle
36
60
 
37
61
  - `SystemDefinition` (interface) · `import { SystemDefinition } from "@jgengine/shell/gameKit"`
@@ -84,6 +108,14 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
84
108
 
85
109
  - `StatBar` (function) · `import { StatBar } from "@jgengine/shell/gameKit"`
86
110
 
111
+ ## input-recorder — tick-indexed input log for replay, rollback, and regression tests
112
+
113
+ - `createInputRecorder` (function) · `import { createInputRecorder } from "@jgengine/core/runtime/inputRecorder"`
114
+
115
+ ## local-players — Couch co-op seats: devices hot-join into slots, each with its own user id and input snapshot.
116
+
117
+ - `createLocalPlayers` (function) · `import { createLocalPlayers } from "@jgengine/core/runtime/localPlayers"`
118
+
87
119
  ## loot-table — validate a loot table definition for use with the registry
88
120
 
89
121
  - `lootTable` (function) · `import { lootTable } from "@jgengine/core/authoring"`
@@ -116,6 +148,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
116
148
 
117
149
  - `toRuntimeObjectRow` (function) · `import { toRuntimeObjectRow } from "@jgengine/core/runtime/objectRows"`
118
150
 
151
+ ## pose-interpolation — render entity poses between fixed simulation steps without stutter
152
+
153
+ - `createPoseHistory` (function) · `import { createPoseHistory } from "@jgengine/core/runtime/poseInterpolation"`
154
+
119
155
  ## render-fallback-diagnostics — Enable/disable the dev-only placeholder-fallback probe.
120
156
 
121
157
  - `armFallbackSeams` (function) · `import { armFallbackSeams } from "@jgengine/core/devtools/fallbackSeams"`
@@ -126,6 +162,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
126
162
  - `resetTextureErrors` (function) · `import { resetTextureErrors } from "@jgengine/core/devtools/textureErrors"`
127
163
  - `textureErrorsSnapshot` (function) · `import { textureErrorsSnapshot } from "@jgengine/core/devtools/textureErrors"`
128
164
 
165
+ ## runtime — snapshot interpolation
166
+
167
+ - `createSnapshotBuffer` (function) · `import { createSnapshotBuffer } from "@jgengine/core/runtime/snapshotBuffer"`
168
+
129
169
  ## runtime-save — save/load the whole game world through a pluggable backend, autosave or save points
130
170
 
131
171
  - `createRuntimeSave` (function) · `import { createRuntimeSave } from "@jgengine/core/runtime/runtimeSave"`
@@ -142,6 +182,14 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
142
182
 
143
183
  - `seededRng` (function) · `import { seededRng } from "@jgengine/shell/gameKit"`
144
184
 
185
+ ## sim-loop — fixed-step or variable simulation stepping with tick count, catch-up cap, and interpolation alpha
186
+
187
+ - `createSimLoop` (function) · `import { createSimLoop } from "@jgengine/core/runtime/simLoop"`
188
+
189
+ ## sim-snapshot — capture and restore whole-simulation state for replay, rollback, and regression tests
190
+
191
+ - `createSimSnapshotRegistry` (function) · `import { createSimSnapshotRegistry } from "@jgengine/core/runtime/simSnapshot"`
192
+
145
193
  ## typed-keyed-store — a cast-free typed handle onto a per-owner keyed family of reactive game-store slots, replayable and host-authoritative
146
194
 
147
195
  - `defineKeyedStore` (function) · `import { defineKeyedStore } from "@jgengine/shell/gameKit"`
@@ -150,6 +198,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
150
198
 
151
199
  - `defineStore` (function) · `import { defineStore } from "@jgengine/shell/gameKit"`
152
200
 
201
+ ## warn-once — emit a dev-only warning a single time per call site
202
+
203
+ - `warnOnce` (function) · `import { warnOnce } from "@jgengine/core/devtools/warnOnce"`
204
+
153
205
  ## world-chunk-key — map world positions to persisted chunk keys at a declared cell size
154
206
 
155
207
  - `chunkKeyOf` (function) · `import { chunkKeyOf } from "@jgengine/core/runtime/worldChunks"`
@@ -165,3 +217,7 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
165
217
  ## world-environment — compose editor/preset-derived outdoor dressing — terrain, weather, water, structures — into a legacy environment feature
166
218
 
167
219
  - `environment` (function) · `import { environment } from "@jgengine/shell/gameKit"`
220
+
221
+ ## world-item-pickup — pick up dropped items: ctx.scene.worldItem nearestInRadius → pickup into the player's inventory
222
+
223
+ - `SceneWorldItemContext` (interface) · `import { SceneWorldItemContext } from "@jgengine/core/runtime/gameContext"`
@@ -45,6 +45,9 @@ spatial place. When the game *is* a place, declare only substrate + laws with `w
45
45
  `@jgengine/core/world/place` (e.g. `{ id, ground: { mode: "flat", size: { x: Infinity, z: Infinity } }, physics: { gravity: -24 } }`,
46
46
  or `mode: "board"` for 2D). Never seed, sky, or vegetation in `world` — the engine renders its
47
47
  default sky until you author one in the editor, and foliage is editor scatter over the ground.
48
+ A created 3D game instead ships hills as a terrain sculpt in `editor.scene.json` and a `world.ts`
49
+ that consumes it with `environment({ sculpt })` via `environmentContentFromDocument`; the file
50
+ holds only the ground palette. Reshape the hills in the editor, not in code.
48
51
 
49
52
 
50
53
  ```ts
@@ -45,3 +45,28 @@ Use [capabilities.md](capabilities.md) for intent-to-import discovery, [api.md](
45
45
  - Presence/chat/voice are session channels, not game-state ownership.
46
46
  - Do not couple a primitive to WebSocket, Convex, Postgres, or one deployment topology.
47
47
  - Reward allocation, inventory mutation, and progression policy remain gameplay/combat concerns.
48
+
49
+ ## Shared-world capacity and persistence
50
+
51
+ | Topology | Membership and session state | Command reads | Presence fan-out |
52
+ | --- | --- | --- | --- |
53
+ | Rooms | **256 members maximum** in the room document | Declared actor/player and chunk scope | Neighborhood index |
54
+ | Shared | Indexed `jgServerMembers`, separate `jgServerCapacity`, per-user profile session state; no 256-member engine cap | Declared actor/player and chunk scope; player-only writes avoid the world row | Neighborhood index, 10 Hz maximum default pose writes |
55
+
56
+ Use `createGameServerFunctions({ topology: "shared", runtimes })` for one persistent world. Shared topology defaults to singleton matchmaking. Capacity is not a throughput guarantee; verify the command and subscription read sets under crowd load. Subscribe to `getServerCapacity` for shared membership/status without volatile world revision reads.
57
+
58
+ Every gameplay command declares `scope(input)`: use `{ players: "actor", chunkKeys: [] }` for player-only work and `chunkKeysAround(position, 1)` for spatial work. The omitted-command default is actor-only with no chunks; an explicit `{}` requests the whole world and needs a justified bounded workload. Hosts use `helpers.runCommand` and its `beforePersist` callback to pair game writes with membership and revision checks in one transaction. Never copy that check/apply/persist loop into a game. Declare commands with `defineCommand({ parse, scope, validate, apply })` and build `parse` from the `readInput*` readers in `@jgengine/core/runtime/commandInput` (finite, bounded numbers and points, capped strings and arrays): the runner refuses malformed input before `scope`, `validate` or `apply` run, so those stages never re-parse or trust raw values. Treat every field of a command's `input` as client-controlled: a command whose input carries facts only the host may decide (unlock state, prices, multipliers, whether a target exists) declares `access: "server"`, so the public `runCommand` and WebSocket clients are refused and only a host mutation calling `helpers.runCommand` (or `host.runCommand({ trusted: true })`) runs it. Read time from the `nowMs` argument, never from `input`.
59
+
60
+ Every presence query is neighborhood-scoped. Pass `PresenceSession.viewerChunkKey` through `createConvexPresenceTransport`. Hosts with custom authentication, bot ownership, or spawn policy use `createWorldPresenceStore` from `@jgengine/convex/worldPresence`: resolve trusted identities and access first, then call `ensure`, `sync`, `revoke`, `active`, `nearby`, and `reap`. Store rows in `jgPoses`, never a game-owned presence table. Optional snapshot callbacks persist game-owned last-position fields at the store's cadence. Bot identity may differ from its authorized owner; preserve that mapping explicitly. Resident rows implement `PresenceResidentRow.actorExternalId` and `ownerActorId` exactly.
61
+
62
+ Persist only dirty profiles/chunks. Join/leave are roster writes; they do not dirty or rewrite the world. Reset a player with `helpers.resetPlayerProfile`, which runs the same initializer used by joins, and keep the shared world intact.
63
+
64
+ ## Scheduled work
65
+
66
+ A cron never collects a whole table. Use presence-gated `forEachOnlinePlayer` with a bounded `batchSize`, an internal batch handler, and a continuation reference: each page schedules its handler and the next page as separate transactions. `OnlinePlayer.homeGameId` carries optional application identity from its pose row. Persist elapsed-time anchors with effects; use `accrueSince` to cap offline catch-up. `allServers` is only for explicitly global systems with a bounded server budget.
67
+
68
+ Pass runtimes to `jgengineCronSpecs` so no tick cron registers when no runtime declares `onTick`; set per-spec `intervalSeconds` deliberately. Retention sweeps and one-shot backfills are bounded, report `remaining`, and stop at convergence. Delete completed migration crons instead of leaving hourly table scans installed forever.
69
+
70
+ Join failures return typed `full`, `closed`, or `unauthorized` outcomes. Surface them through a retry gate; returning a rejection without visible UI is unfinished. Browser adapters leave sessions on `pagehide`. Membership is per client session: pass a fresh `sessionId` (`createTransportSessionId`) to each `joinServer` and its matching `leaveServer`, so a closed tab or a disposed mount never evicts a live one. A host mutation acting for a user who may have no live session calls `helpers.ensureJoined` before `helpers.runCommand`.
71
+
72
+ For the explicit shared-builder composition, `jgengine create "World Name" --shape shared-world-builder` generates the connected Convex shell, runtime scope declarations, claim/accrual examples, chat, indexed presence, and an online batch pipeline. The generated README owns setup; replace the demonstration economy and author buildable world content in the editor.