@jgengine/convex 0.49.0 → 0.49.1
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 +20 -0
- package/package.json +2 -2
- package/skills/jgengine/api.md +9 -9
- package/skills/jgengine-multiplayer/api.md +39 -39
package/CHANGELOG.md
CHANGED
|
@@ -26,6 +26,26 @@ At publish, rename this heading to the new version and mirror the entries into
|
|
|
26
26
|
`packages/core/src/meta/changelog.ts` (the typed `CHANGELOG` export).
|
|
27
27
|
-->
|
|
28
28
|
|
|
29
|
+
## 0.49.1
|
|
30
|
+
|
|
31
|
+
### Migrate
|
|
32
|
+
|
|
33
|
+
- **Bump lockstep SDK packages to `^0.49.1`:** `@jgengine/{core,rapier,react,ws,node,sql,convex,shell,editor,assets,navbake}`. CLI `jgengine` is `0.46.1`; `@jgengine/github` is `0.36.1`.
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- bun run check type-escapes fails a file that gains an any, a non-null !, an as cast or a @ts-ignore; the per-file count lives in scripts/type-escape-baseline.json, bun run gen lowers it, and an unavoidable escape is excused by a // type-escape: <why> comment.
|
|
38
|
+
- `ActionCodeModes` (`@jgengine/core/input/actionBindings`): The hold/toggle form of an {@link ActionCodes} entry, with an optional auto-repeat rate.
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- core, shell and ws type-check with noUncheckedIndexedAccess, exactOptionalPropertyTypes, noImplicitOverride, noPropertyAccessFromIndexSignature and noImplicitReturns. All 1460 errors are fixed with guards, real types and small helpers, not casts: a missing array slot, a missing record key or an optional field that may be undefined is now a compile error.
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- spreading a game's place physics over the base no longer erases base gravity or jump velocity with an undefined.
|
|
47
|
+
- the four ActionCodes readers (camera, gamepad, touch, rebind) share one isCodeList / allActionCodes / primaryActionCodes instead of four copies with casts.
|
|
48
|
+
|
|
29
49
|
## 0.49.0
|
|
30
50
|
|
|
31
51
|
### Migrate
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jgengine/convex",
|
|
3
|
-
"version": "0.49.
|
|
3
|
+
"version": "0.49.1",
|
|
4
4
|
"description": "Convex adapters for JGengine: game transport, presence transport, and backend wiring over @jgengine/core.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"check-types": "tsgo --noEmit -p tsconfig.json"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@jgengine/core": "^0.49.
|
|
33
|
+
"@jgengine/core": "^0.49.1"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"convex": "^1.31.2",
|
package/skills/jgengine/api.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
- `CHANGELOG` (const): const CHANGELOG: Record<string, ChangelogEntry> — Per-version engine changelog keyed by semver string (e.g. `"0.10.0"`).
|
|
8
8
|
- `ChangelogEntry` (interface): interface ChangelogEntry — One release's migrate steps plus added/changed/removed notes (typed mirror of CHANGELOG.md).
|
|
9
|
-
- `VERSION` (const): const VERSION: "0.49.
|
|
9
|
+
- `VERSION` (const): const VERSION: "0.49.1" — Installed `@jgengine/core` semver - compare against {@link CHANGELOG} keys when migrating.
|
|
10
10
|
|
|
11
11
|
## @jgengine/core/authoring
|
|
12
12
|
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
- `DevtoolsLogEntry` (interface): interface DevtoolsLogEntry — A single captured log line with timestamp, level, owning system tag, and formatted message.
|
|
185
185
|
- `DevtoolsLogLevel` (type): type DevtoolsLogLevel = "log" | "info" | "warn" | "error" — Severity level for a captured devtools log entry.
|
|
186
186
|
- `DevtoolsLogs` (interface): interface DevtoolsLogs — Bounded log ring with per-system tags, a warning/error ring, and lifetime counts.
|
|
187
|
-
- `DevtoolsOverrides` (interface): interface DevtoolsOverrides { version: number; enabled: string[]; values: Record<string, unknown>; schemas?: Record<string, {kind: DevtoolsControlKind; schemaVersion?: number}> } — ⚠ undocumented
|
|
187
|
+
- `DevtoolsOverrides` (interface): interface DevtoolsOverrides { version: number; enabled: string[]; values: Record<string, unknown>; schemas?: Record<string, {kind: DevtoolsControlKind; schemaVersion?: number | undefined}> | undefined } — ⚠ undocumented
|
|
188
188
|
- `DevtoolsSnapshot` (interface): interface DevtoolsSnapshot — Serializable point-in-time snapshot of devtools state: frame, render, latency, logs, controls, and discovered fields.
|
|
189
189
|
- `DiscoveredEntry` (interface): interface DiscoveredEntry — A control auto-discovered by scanning an object/table, with its binding metadata and current reader.
|
|
190
190
|
- `DiscoverySkip` (interface): interface DiscoverySkip { readonly path: string; readonly reason: string } — ⚠ undocumented
|
|
@@ -246,7 +246,7 @@
|
|
|
246
246
|
- `DiagnosticOverlay` (function): function DiagnosticOverlay({ diagnostics, gameName }: { diagnostics: RuntimeDiagnostic[]; gameName: string }): React.JSX.Element | null — ⚠ undocumented
|
|
247
247
|
- `ErrorReportActions` (function): function ErrorReportActions({ report, issueTitle }: { report: string; issueTitle: string }): React.JSX.Element — "Copy error" + "File issue" buttons for any error surface. `report` is the full text to copy / prefill.
|
|
248
248
|
- `GameUiErrorBoundary` (class): class GameUiErrorBoundary extends Component< { children: ReactNode; onRuntimeError: (error: unknown, phase: string, componentStack?: string) => void }, { failed: boolean } > — ⚠ undocumented
|
|
249
|
-
- `RuntimeDiagnostic` (interface): interface RuntimeDiagnostic { id: number; phase: string; message: string; stack?: string; componentStack?: string; capturedAt: string } — ⚠ undocumented
|
|
249
|
+
- `RuntimeDiagnostic` (interface): interface RuntimeDiagnostic { id: number; phase: string; message: string; stack?: string | undefined; componentStack?: string | undefined; capturedAt: string } — ⚠ undocumented
|
|
250
250
|
- `errorReportContext` (function): function errorReportContext(): string — Standalone error footer text (page, browser, engine) shared by every error surface.
|
|
251
251
|
- `logRuntimeError` (function): function logRuntimeError(error: unknown, phase: string, componentStack?: string): Omit<RuntimeDiagnostic, "id"> — ⚠ undocumented
|
|
252
252
|
|
|
@@ -381,7 +381,7 @@
|
|
|
381
381
|
- `AngleUnit` (type): type AngleUnit = "rad" | "deg" — ⚠ undocumented
|
|
382
382
|
- `CONTROL_SCHEMA_VERSION` (const): const CONTROL_SCHEMA_VERSION: 1 — ⚠ undocumented
|
|
383
383
|
- `DevtoolsControlKind` (type): type DevtoolsControlKind = | "slider" | "toggle" | "color" | "select" | "text" | "vec2" | "vec3" | "vec4" | "interval" | "angle" | "enum" — ⚠ undocumented
|
|
384
|
-
- `DevtoolsOverrides` (interface): interface DevtoolsOverrides { version: number; enabled: string[]; values: Record<string, unknown>; schemas?: Record<string, {kind: DevtoolsControlKind; schemaVersion?: number}> } — ⚠ undocumented
|
|
384
|
+
- `DevtoolsOverrides` (interface): interface DevtoolsOverrides { version: number; enabled: string[]; values: Record<string, unknown>; schemas?: Record<string, {kind: DevtoolsControlKind; schemaVersion?: number | undefined}> | undefined } — ⚠ undocumented
|
|
385
385
|
- `DiscoverySkip` (interface): interface DiscoverySkip { readonly path: string; readonly reason: string } — ⚠ undocumented
|
|
386
386
|
- `MAX_SCAN_DEPTH` (const): const MAX_SCAN_DEPTH: 5 — ⚠ undocumented
|
|
387
387
|
- `MAX_SCAN_TARGETS` (const): const MAX_SCAN_TARGETS: 512 — ⚠ undocumented
|
|
@@ -438,11 +438,11 @@
|
|
|
438
438
|
|
|
439
439
|
- `CHANGELOG` (const): const CHANGELOG: Record<string, ChangelogEntry> — Per-version engine changelog keyed by semver string (e.g. `"0.10.0"`).
|
|
440
440
|
- `ChangelogEntry` (interface): interface ChangelogEntry — One release's migrate steps plus added/changed/removed notes (typed mirror of CHANGELOG.md).
|
|
441
|
-
- `VERSION` (const): const VERSION: "0.49.
|
|
441
|
+
- `VERSION` (const): const VERSION: "0.49.1" — Installed `@jgengine/core` semver - compare against {@link CHANGELOG} keys when migrating.
|
|
442
442
|
|
|
443
443
|
## @jgengine/core/runtime/adapter
|
|
444
444
|
|
|
445
|
-
- `MultiplayerAdapterConfig` (type): type MultiplayerAdapterConfig = | { kind: "convex"; topology?: MultiplayerTopology; authority?: MultiplayerAuthority } | { kind: "ws"; topology?: MultiplayerTopology; url?: string; authority?: MultiplayerAuthority } | { kind: "socketio";
|
|
445
|
+
- `MultiplayerAdapterConfig` (type): type MultiplayerAdapterConfig = | { kind: "convex"; topology?: MultiplayerTopology | undefined; authority?: MultiplayerAuthority | undefined } | { kind: "ws"; topology?: MultiplayerTopology | undefined; url?: string | undefined; authority?: MultiplayerAuthority | undefined } | { kind: "socketio"; to… — ⚠ undocumented · used by `convex`: Convex transport.
|
|
446
446
|
- `MultiplayerAuthority` (type): type MultiplayerAuthority = "server" | "client" — Where the world simulation is authoritative.
|
|
447
447
|
- `MultiplayerTopology` (type): type MultiplayerTopology = "shared" | "lobbies" | "private" — ⚠ undocumented · used by `convex`: Convex transport.
|
|
448
448
|
- `ServersPoolConfig` (type): type ServersPoolConfig = { minPlayersToStart?: number; adapter: MultiplayerAdapterConfig; } & ( | { topology: "shared"; maxServers?: number; slotsPerServer?: number } | { topology?: "rooms"; maxServers: number; slotsPerServer: number } ) — ⚠ undocumented · used by `servers`: Resolve the shared-world pool to one unbounded world; room pools keep explicit capacities.
|
|
@@ -554,7 +554,7 @@
|
|
|
554
554
|
|
|
555
555
|
## @jgengine/core/runtime/gameRuntime
|
|
556
556
|
|
|
557
|
-
- `GameRuntime` (type): type GameRuntime = { gameId: string; topology?: "shared" | "rooms"; save: SaveConfig; /** * Whether this runtime declares `loop.onTick`. A host's tick cron reads it to skip hydrating and * persisting a server whose `tick` is a no-op by construction — the difference between a world that
|
|
557
|
+
- `GameRuntime` (type): type GameRuntime = { gameId: string; topology?: "shared" | "rooms" | undefined; save: SaveConfig; /** * Whether this runtime declares `loop.onTick`. A host's tick cron reads it to skip hydrating and * persisting a server whose `tick` is a no-op by construction — the difference between a world that *… — ⚠ undocumented · used by `initialPlayerState`: Seed a fresh player through the same onNewPlayer hook as joining, without hydrating or modifying a world.
|
|
558
558
|
- `GameRuntimeDefinition` (type): type GameRuntimeDefinition = { gameId: string; topology?: "shared" | "rooms"; save: SaveConfig; commands: Record<string, CommandDef>; loop?: ServerLoopHooks; } — ⚠ undocumented
|
|
559
559
|
- `HydrateInput` (type): type HydrateInput = { gameId: string; serverId: string; serverRow: RuntimeServerRow; playersByUserId: Record<string, RuntimePlayerRow>; chunksByKey: Record<string, RuntimeChunkRow>; revision?: number; /** Host wall clock for `onInit`, in ms. Defaults to `Date.now()`. */ nowMs?: number; } — ⚠ undocumented
|
|
560
560
|
- `RuntimeInitContext` (type): type RuntimeInitContext = { snapshot: GameRuntimeSnapshot; setSnapshot: (snapshot: GameRuntimeSnapshot) => void; /** * Host wall clock at the start of this call, in ms. The host already knows it, so anything keyed to * real time — a UTC date rollover, a `lastTickAt` anchor other code paths read, a s… — ⚠ undocumented
|
|
@@ -586,7 +586,7 @@
|
|
|
586
586
|
- `OPEN_SERVER_LISTING_LIMIT` (const): const OPEN_SERVER_LISTING_LIMIT: 20 — ⚠ undocumented
|
|
587
587
|
- `OPEN_SERVER_LISTING_MAX` (const): const OPEN_SERVER_LISTING_MAX: 100 — ⚠ undocumented
|
|
588
588
|
- `PlayerProfileRecord` (type): type PlayerProfileRecord = { userId: string; gameId: string; playerState: RuntimePlayerRow; revision: number; updatedAt: number; } — ⚠ undocumented
|
|
589
|
-
- `ServerListing` (type): type ServerListing = { serverId: string; status: GameServerStatus; memberCount: number; slotsPerServer: number; mode?: string; label?: string; visibility?: SessionVisibility; joinCode?: string; tags?: string[]; updatedAt: number; } — ⚠ undocumented
|
|
589
|
+
- `ServerListing` (type): type ServerListing = { serverId: string; status: GameServerStatus; memberCount: number; slotsPerServer: number; mode?: string | undefined; label?: string | undefined; visibility?: SessionVisibility | undefined; joinCode?: string; tags?: string[] | undefined; updatedAt: number; } — ⚠ undocumented
|
|
590
590
|
- `ServerPersistPlan` (type): type ServerPersistPlan = { server: GameServerRecord; profiles: PlayerProfileRecord[]; chunks: WorldChunkRecord[]; deletedChunks: string[]; leaderboard: LeaderboardIncrement[]; /** * Which fields of the server row the plan actually moved. A store that pays per written field — * or whose subscribers r… — ⚠ undocumented
|
|
591
591
|
- `SessionAttributes` (type): type SessionAttributes = { label?: string; mode?: string; visibility?: SessionVisibility; joinCode?: string; tags?: string[]; } — ⚠ undocumented
|
|
592
592
|
- `StoredLeaderboardRow` (type): type StoredLeaderboardRow = LeaderboardRow & { gameId: string; updatedAt: number; } — A {@link LeaderboardRow} as a host stores it: keyed by game, stamped with its last write.
|
|
@@ -705,7 +705,7 @@
|
|
|
705
705
|
- `SimContextState` (interface): interface SimContextState — Serializable `ctx.sim` state: loop position plus the interpolation pose history.
|
|
706
706
|
- `SimStage` (interface): interface SimStage — Extra work a game or engine seam (a physics backend, a netcode buffer) runs inside every simulation step.
|
|
707
707
|
- `SimStagePhase` (type): type SimStagePhase = "beforeMovement" | "afterMovement" | "afterTick" — Where a registered stage runs inside one simulation step.
|
|
708
|
-
- `createSimContext` (function): function createSimContext(options: { config?: SimulationConfig; entities: EntityStore; time?: Pick<SimClock, "advance"> }): SimContext — Build `ctx.sim` for a context; `createGameContext` calls this from `definition.simulation`.
|
|
708
|
+
- `createSimContext` (function): function createSimContext(options: { config?: SimulationConfig | undefined; entities: EntityStore; time?: Pick<SimClock, "advance"> }): SimContext — Build `ctx.sim` for a context; `createGameContext` calls this from `definition.simulation`.
|
|
709
709
|
|
|
710
710
|
## @jgengine/core/runtime/simLoop
|
|
711
711
|
|
|
@@ -185,15 +185,15 @@
|
|
|
185
185
|
- `PoseSyncTuning` (interface): interface PoseSyncTuning { minIntervalMs: number; heartbeatMs: number; positionEpsilon: number; verticalEpsilon: number; rotationEpsilon: number } — ⚠ undocumented · used by `DEFAULT_POSE_SYNC_TUNING` (@jgengine/core/multiplayer/poseSyncGate): Default ten-hertz client pose gate with a five-second heartbeat.
|
|
186
186
|
- `PresenceActions` (interface): interface PresenceActions<TGameId extends string = string> { ensurePresence(args: EnsurePresenceArgs<TGameId>): Promise<EnsurePresenceResult | null>; leavePresence(args: LeavePresenceArgs<TGameId>): Promise<{left: boolean}>; syncPose(pose: PresencePose): void } — ⚠ undocumented
|
|
187
187
|
- `PresenceFeeds` (interface): interface PresenceFeeds<TRow, TLocation> { myPresenceLocation: TLocation | null | undefined; onlinePresences: readonly TRow[] | undefined; dormantPresences: readonly TRow[] | undefined } — ⚠ undocumented
|
|
188
|
-
- `PresencePoseState` (interface): interface PresencePoseState { position: {x: number; y: number; z: number}; rotationY: number; rotationPitch?: number; lastSeenAtMs?: number; appearance?: Record<string, string> } — ⚠ undocumented
|
|
188
|
+
- `PresencePoseState` (interface): interface PresencePoseState { position: {x: number; y: number; z: number}; rotationY: number; rotationPitch?: number; lastSeenAtMs?: number; appearance?: Record<string, string> | undefined } — ⚠ undocumented
|
|
189
189
|
- `PresenceSession` (interface): interface PresenceSession<TGameId extends string = string> { homeGameId: TGameId; externalId: string; viewerChunkKey?: string } — ⚠ undocumented
|
|
190
190
|
- `PresenceTransport` (interface): interface PresenceTransport<TRow, TLocation, TGameId extends string = string> — Backend seam for multiplayer presence. Feeds are reactive data and change identity whenever any player's pose updates; actions MUST be identity-stable for the lifetime of a mounted session so join/leave lifecycle effects can depend on them without re-running per pose tick. The use* members are called as React hooks by consumers, so a mounted transport must never change identity — remount the subtree to switch backends.
|
|
191
191
|
- `PushToTalkMode` (type): type PushToTalkMode = "hold" | "toggle" | "openMic" — ⚠ undocumented
|
|
192
192
|
- `PushToTalkStatus` (type): type PushToTalkStatus = "idle" | "keyed" | "open" — ⚠ undocumented
|
|
193
193
|
- `ReplicationPolicy` (interface): interface ReplicationPolicy — Host-side interest/privacy policy — how the authoritative world projects to each viewer over the wire. Unset (the default) means every client receives the whole world, exactly as before. Enabling a field changes only what each client *sees*, never how the host simulates: the game plays identically. The core replication modules read this to attach a {@link SnapshotModule.project} without the engine growing a per-feature branch.
|
|
194
|
-
- `SessionListing` (interface): interface SessionListing { serverId: string; gameId: string; status: SessionStatus; visibility: SessionVisibility; memberCount: number; slotsPerServer: number; label?: string; mode?: string; joinCode?: string; tags?: readonly
|
|
194
|
+
- `SessionListing` (interface): interface SessionListing { serverId: string; gameId: string; status: SessionStatus; visibility: SessionVisibility; memberCount: number; slotsPerServer: number; label?: string | undefined; mode?: string | undefined; joinCode?: string | undefined; tags?: readonly str… — ⚠ undocumented · used by `useWorldBrowser` (@jgengine/react): Polls a host-supplied session fetcher (e.g.
|
|
195
195
|
- `SessionVisibility` (type): type SessionVisibility = "public" | "private" — ⚠ undocumented · used by `isAutoJoinCandidate` (@jgengine/core/runtime/hostPolicy): Auto-match candidate when no `serverId` is supplied: already a member, or a public room with free capacity.
|
|
196
|
-
- `VoiceParticipant` (interface): interface VoiceParticipant { userId: string; streamId?: string } — ⚠ undocumented
|
|
196
|
+
- `VoiceParticipant` (interface): interface VoiceParticipant { userId: string; streamId?: string | undefined } — ⚠ undocumented
|
|
197
197
|
- `VoiceRoute` (interface): interface VoiceRoute { fromUserId: string; channelId: string; gain: number } — ⚠ undocumented
|
|
198
198
|
- `VoiceTransport` (interface): interface VoiceTransport — Signaling seam for voice: who is in a channel and which media stream descriptor they published. The media plane (WebRTC, SFU, or anything else that moves audio bytes) stays behind this seam, host-supplied — the engine never touches it. subscribers delivers the channel roster on every change, starting with the current roster.
|
|
199
199
|
- `browseSessions` (function): function browseSessions(listings: readonly SessionListing[], filter: MatchFilter = {}, options: BrowseOptions = {}): SessionListing[] — ⚠ undocumented
|
|
@@ -268,9 +268,9 @@
|
|
|
268
268
|
|
|
269
269
|
## @jgengine/core/multiplayer/matchmaking
|
|
270
270
|
|
|
271
|
-
- `BrowseOptions` (interface): interface BrowseOptions { limit?: number } — ⚠ undocumented
|
|
271
|
+
- `BrowseOptions` (interface): interface BrowseOptions { limit?: number | undefined } — ⚠ undocumented
|
|
272
272
|
- `MatchFilter` (interface): interface MatchFilter { mode?: string; tags?: readonly string[]; query?: string; notFull?: boolean; status?: readonly SessionStatus[]; includePrivate?: boolean } — ⚠ undocumented · used by `useWorldBrowser` (@jgengine/react): Polls a host-supplied session fetcher (e.g.
|
|
273
|
-
- `SessionListing` (interface): interface SessionListing { serverId: string; gameId: string; status: SessionStatus; visibility: SessionVisibility; memberCount: number; slotsPerServer: number; label?: string; mode?: string; joinCode?: string; tags?: readonly
|
|
273
|
+
- `SessionListing` (interface): interface SessionListing { serverId: string; gameId: string; status: SessionStatus; visibility: SessionVisibility; memberCount: number; slotsPerServer: number; label?: string | undefined; mode?: string | undefined; joinCode?: string | undefined; tags?: readonly str… — ⚠ undocumented · used by `useWorldBrowser` (@jgengine/react): Polls a host-supplied session fetcher (e.g.
|
|
274
274
|
- `SessionStatus` (type): type SessionStatus = "open" | "running" | "closed" — ⚠ undocumented
|
|
275
275
|
- `SessionVisibility` (type): type SessionVisibility = "public" | "private" — ⚠ undocumented · used by `isAutoJoinCandidate` (@jgengine/core/runtime/hostPolicy): Auto-match candidate when no `serverId` is supplied: already a member, or a public room with free capacity.
|
|
276
276
|
- `browseSessions` (function): function browseSessions(listings: readonly SessionListing[], filter: MatchFilter = {}, options: BrowseOptions = {}): SessionListing[] — ⚠ undocumented
|
|
@@ -286,7 +286,7 @@
|
|
|
286
286
|
- `DEFAULT_FEED_ACTIONS` (const): const DEFAULT_FEED_ACTIONS: string[] — ⚠ undocumented
|
|
287
287
|
- `PeerShellFactories` (interface): interface PeerShellFactories — Alternate peer factories for hosts that provide their own WebRTC implementation or transport pipe.
|
|
288
288
|
- `ResolvePeerShellMultiplayerArgs` (interface): interface ResolvePeerShellMultiplayerArgs — Peer bootstrap options; passing a playable hosts its authoritative GameContext world.
|
|
289
|
-
- `ResolveShellMultiplayerArgs` (type): type ResolveShellMultiplayerArgs = { game: GameDefinition; gameId: string; url?: string; userId?: string; force?: boolean; feedActions?: string[]; } — ⚠ undocumented
|
|
289
|
+
- `ResolveShellMultiplayerArgs` (type): type ResolveShellMultiplayerArgs = { game: GameDefinition; gameId: string; url?: string | undefined; userId?: string; force?: boolean; feedActions?: string[]; } — ⚠ undocumented
|
|
290
290
|
- `ShellMultiplayer` (type): type ShellMultiplayer = MultiplayerSession — ⚠ undocumented · used by `resolvePeerShellMultiplayer`: Opens a peer session.
|
|
291
291
|
- `randomPlayerId` (function): function randomPlayerId(): string — ⚠ undocumented
|
|
292
292
|
- `resolvePeerShellMultiplayer` (function): function resolvePeerShellMultiplayer(args: ResolvePeerShellMultiplayerArgs): Promise<ShellMultiplayer & { close: () => Promise<void> }> — Opens a peer session. With `playable`, one host runs the game loop and guests mirror its shared world. Await `close()` to finish authoritative persistence. Same-origin rooms use BroadcastChannel signaling.
|
|
@@ -320,9 +320,9 @@
|
|
|
320
320
|
- `DEFAULT_POSE_SYNC_RULES` (const): const DEFAULT_POSE_SYNC_RULES: PoseSyncRules — Canonical client-authoritative pose-sync tuning shared by every host transport (WS, Convex).
|
|
321
321
|
- `DEFAULT_SPAWN_ORIGIN` (const): const DEFAULT_SPAWN_ORIGIN: { readonly x: 0; readonly y: 0; readonly z: 0; } — ⚠ undocumented
|
|
322
322
|
- `IncomingPose` (interface): interface IncomingPose { position: {x: number; z: number; y?: number}; rotationY?: number; rotationPitch?: number; appearance?: Record<string, string> } — ⚠ undocumented
|
|
323
|
-
- `PoseSyncDecision` (interface): interface PoseSyncDecision { position: {x: number; y: number; z: number}; rotationY: number; rotationPitch: number; appearance?: Record<string, string
|
|
323
|
+
- `PoseSyncDecision` (interface): interface PoseSyncDecision { position: {x: number; y: number; z: number}; rotationY: number; rotationPitch: number; appearance?: Record<string, string> | undefined; changed: boolean; refreshKeepAlive: boolean } — ⚠ undocumented
|
|
324
324
|
- `PoseSyncRules` (interface): interface PoseSyncRules { maxSpeed: number; minIntervalMs?: number; maxVerticalOffset: number; floorY?: number; minElapsedSec: number; maxElapsedSec: number; keepAliveRefreshMs: number } — ⚠ undocumented · used by `DEFAULT_POSE_SYNC_RULES`: Canonical client-authoritative pose-sync tuning shared by every host transport (WS, Convex).
|
|
325
|
-
- `PresencePoseState` (interface): interface PresencePoseState { position: {x: number; y: number; z: number}; rotationY: number; rotationPitch?: number; lastSeenAtMs?: number; appearance?: Record<string, string> } — ⚠ undocumented
|
|
325
|
+
- `PresencePoseState` (interface): interface PresencePoseState { position: {x: number; y: number; z: number}; rotationY: number; rotationPitch?: number; lastSeenAtMs?: number; appearance?: Record<string, string> | undefined } — ⚠ undocumented
|
|
326
326
|
|
|
327
327
|
## @jgengine/core/multiplayer/simultaneousCommit
|
|
328
328
|
|
|
@@ -350,7 +350,7 @@
|
|
|
350
350
|
- `PushToTalk` (interface): interface PushToTalk { mode(): PushToTalkMode; setMode(mode: PushToTalkMode): void; keyDown(): void; keyUp(): void; muted(): boolean; setMuted(muted: boolean): void; status(): PushToTalkStatus; transmitting(): boolean } — ⚠ undocumented
|
|
351
351
|
- `PushToTalkMode` (type): type PushToTalkMode = "hold" | "toggle" | "openMic" — ⚠ undocumented
|
|
352
352
|
- `PushToTalkStatus` (type): type PushToTalkStatus = "idle" | "keyed" | "open" — ⚠ undocumented
|
|
353
|
-
- `VoiceParticipant` (interface): interface VoiceParticipant { userId: string; streamId?: string } — ⚠ undocumented
|
|
353
|
+
- `VoiceParticipant` (interface): interface VoiceParticipant { userId: string; streamId?: string | undefined } — ⚠ undocumented
|
|
354
354
|
- `VoiceRoute` (interface): interface VoiceRoute { fromUserId: string; channelId: string; gain: number } — ⚠ undocumented
|
|
355
355
|
- `VoiceTransport` (interface): interface VoiceTransport — Signaling seam for voice: who is in a channel and which media stream descriptor they published. The media plane (WebRTC, SFU, or anything else that moves audio bytes) stays behind this seam, host-supplied — the engine never touches it. subscribers delivers the channel roster on every change, starting with the current roster.
|
|
356
356
|
- `createLocalVoiceTransport` (function): function createLocalVoiceTransport(options?: { userId?: string }): { transport: VoiceTransport; participants(channelId: string): readonly VoiceParticipant[]; } — ⚠ undocumented
|
|
@@ -365,8 +365,8 @@
|
|
|
365
365
|
- `DEFAULT_HEARTBEAT_INTERVAL_MS` (const): const DEFAULT_HEARTBEAT_INTERVAL_MS: 30000 — Default ping/pong interval; a socket that misses one round-trip is terminated.
|
|
366
366
|
- `DEFAULT_MAX_CONNECTIONS` (const): const DEFAULT_MAX_CONNECTIONS: 10000 — Default max concurrent sockets this server accepts before rejecting new ones.
|
|
367
367
|
- `DEFAULT_MAX_PAYLOAD_BYTES` (const): const DEFAULT_MAX_PAYLOAD_BYTES: 1048576 — Default per-message payload cap (bytes) — `ws` closes the socket with 1009 past this.
|
|
368
|
-
- `GameServerHost` (type): type GameServerHost = { joinServer: (args: { userId: string; gameId: string; serverId?: string; attributes?: SessionAttributes; code?: string; role?: SnapshotViewer["role"]; }) => Promise<JoinServerResult>; browseServers: (args: { gameId: string;
|
|
369
|
-
- `GameServerHostOptions` (type): type GameServerHostOptions = { runtimes?: GameRuntime[]; persistence: HostPersistence; tickMs?: number; slotsPerServer?: number; now?: () => number; createServerId?: () => string; allowedFeedActions?: readonly string[]; } — Configuration for {@link createGameServerHost}, including persistence, tick rate, and game runtimes.
|
|
368
|
+
- `GameServerHost` (type): type GameServerHost = { joinServer: (args: { userId: string; gameId: string; serverId?: string | undefined; attributes?: SessionAttributes | undefined; code?: string | undefined; role?: SnapshotViewer["role"] | undefined; }) => Promise<JoinServerResult>; browseServers: (args: { gameId: string; filte… — A transport-agnostic authoritative game server host that manages sessions, ticking, and persistence.
|
|
369
|
+
- `GameServerHostOptions` (type): type GameServerHostOptions = { runtimes?: GameRuntime[] | undefined; persistence: HostPersistence; tickMs?: number | undefined; slotsPerServer?: number; now?: () => number; createServerId?: () => string; allowedFeedActions?: readonly string[]; } — Configuration for {@link createGameServerHost}, including persistence, tick rate, and game runtimes.
|
|
370
370
|
- `GameSocketIoServer` (type): type GameSocketIoServer = { rewind: (args: { serverId: string; atMs: number }) => RewoundPosition[]; close: () => void; } — ⚠ undocumented
|
|
371
371
|
- `GameSocketIoServerOptions` (type): type GameSocketIoServerOptions = HostRouterOptions & { io: SocketIoLikeServer } — ⚠ undocumented
|
|
372
372
|
- `GameWsServer` (type): type GameWsServer = { wss: WebSocketServer; port: () => number; rewind: (args: { serverId: string; atMs: number }) => RewoundPosition[]; /** Fence new messages, drain accepted router work, and close sockets. Repeated calls share completion; host persistence remains caller-owned. */ close: () => Prom… — ⚠ undocumented
|
|
@@ -422,8 +422,8 @@
|
|
|
422
422
|
|
|
423
423
|
## @jgengine/node/host
|
|
424
424
|
|
|
425
|
-
- `GameServerHost` (type): type GameServerHost = { joinServer: (args: { userId: string; gameId: string; serverId?: string; attributes?: SessionAttributes; code?: string; role?: SnapshotViewer["role"]; }) => Promise<JoinServerResult>; browseServers: (args: { gameId: string;
|
|
426
|
-
- `GameServerHostOptions` (type): type GameServerHostOptions = { runtimes?: GameRuntime[]; persistence: HostPersistence; tickMs?: number; slotsPerServer?: number; now?: () => number; createServerId?: () => string; allowedFeedActions?: readonly string[]; } — Configuration for {@link createGameServerHost}, including persistence, tick rate, and game runtimes.
|
|
425
|
+
- `GameServerHost` (type): type GameServerHost = { joinServer: (args: { userId: string; gameId: string; serverId?: string | undefined; attributes?: SessionAttributes | undefined; code?: string | undefined; role?: SnapshotViewer["role"] | undefined; }) => Promise<JoinServerResult>; browseServers: (args: { gameId: string; filte… — A transport-agnostic authoritative game server host that manages sessions, ticking, and persistence.
|
|
426
|
+
- `GameServerHostOptions` (type): type GameServerHostOptions = { runtimes?: GameRuntime[] | undefined; persistence: HostPersistence; tickMs?: number | undefined; slotsPerServer?: number; now?: () => number; createServerId?: () => string; allowedFeedActions?: readonly string[]; } — Configuration for {@link createGameServerHost}, including persistence, tick rate, and game runtimes.
|
|
427
427
|
- `HostChangeEvent` (type): type HostChangeEvent = | { type: "server"; serverId: string } | { type: "player"; serverId: string; userId: string } | { type: "feed"; serverId: string; action: string } — A change notification emitted by a `GameServerHost` for a server, player, or feed mutation.
|
|
428
428
|
- `createGameServerHost` (function): function createGameServerHost(options: GameServerHostOptions): GameServerHost — Creates a `GameServerHost` that runs game servers over the given persistence and runtimes.
|
|
429
429
|
- `memoryPersistence` (function): function memoryPersistence(now: () => number = Date.now): HostPersistence — Creates an in-memory `HostPersistence` implementation, useful for tests and ephemeral hosts.
|
|
@@ -506,25 +506,25 @@
|
|
|
506
506
|
|
|
507
507
|
## @jgengine/ws
|
|
508
508
|
|
|
509
|
-
- `CommandAuthorize` (type): type CommandAuthorize = (args: { userId: string; op: HostCommandOp; serverId?: string; command?: string; }) => boolean | Promise<boolean> — Per-command authorization hook: return `false` to reject. Defaults to allow-all when omitted.
|
|
509
|
+
- `CommandAuthorize` (type): type CommandAuthorize = (args: { userId: string; op: HostCommandOp; serverId?: string | undefined; command?: string | undefined; }) => boolean | Promise<boolean> — Per-command authorization hook: return `false` to reject. Defaults to allow-all when omitted.
|
|
510
510
|
- `CommandCatalog` (type): type CommandCatalog = Record<string, CommandCatalogEntry> — Declared `runCommand` names and their input validators. When set, any `runCommand` name absent from this catalog is rejected as unknown.
|
|
511
511
|
- `CommandCatalogEntry` (type): type CommandCatalogEntry = { validate?: (input: unknown) => CommandRejection | null; } — A declared `runCommand` name's input validator, run before the command reaches the game host.
|
|
512
|
-
- `CommandGateArgs` (type): type CommandGateArgs = { connection: object; userId: string; op: HostCommandOp; atMs: number; serverId?: string; command?: string; input?: unknown; } — One op attempt to run through the middleware pipeline: which connection, which op, and (for `runCommand`) the command name/input.
|
|
512
|
+
- `CommandGateArgs` (type): type CommandGateArgs = { connection: object; userId: string; op: HostCommandOp; atMs: number; serverId?: string | undefined; command?: string; input?: unknown; } — One op attempt to run through the middleware pipeline: which connection, which op, and (for `runCommand`) the command name/input.
|
|
513
513
|
- `CommandGateDecision` (type): type CommandGateDecision = { allow: true } | { allow: false; reason: string } — The pipeline's verdict for one {@link CommandGateArgs}: allowed, or rejected with a client-facing reason.
|
|
514
514
|
- `CommandLimits` (type): type CommandLimits = Partial<Record<HostCommandOp, CommandRateLimit>> — Per-op rate limits. An op with no entry (or an undefined `limits`) is unlimited.
|
|
515
515
|
- `CommandMiddleware` (type): type CommandMiddleware = { check: (args: CommandGateArgs) => Promise<CommandGateDecision>; } — A composable rate-limit → validate → authorize pipeline the host router runs before dispatching pose/runCommand/join/browse/voice ops. Every stage defaults to a no-op, so an unconfigured router behaves exactly as before.
|
|
516
|
-
- `CommandMiddlewareOptions` (type): type CommandMiddlewareOptions = { limits?: CommandLimits; authorize?: CommandAuthorize; validate?: CommandCatalog; } — Config for {@link createCommandMiddleware}: the same `limits`/`authorize`/`validate` fields accepted by `HostRouterOptions`.
|
|
516
|
+
- `CommandMiddlewareOptions` (type): type CommandMiddlewareOptions = { limits?: CommandLimits; authorize?: CommandAuthorize | undefined; validate?: CommandCatalog | undefined; } — Config for {@link createCommandMiddleware}: the same `limits`/`authorize`/`validate` fields accepted by `HostRouterOptions`.
|
|
517
517
|
- `CommandRateLimit` (type): type CommandRateLimit = { count: number; perMs: number } — A sliding-window rate limit: at most `count` calls per `perMs` window.
|
|
518
518
|
- `CommandRateLimiter` (type): type CommandRateLimiter = { allow: (connection: object, op: HostCommandOp, atMs: number) => boolean; } — A composable per-connection/per-op sliding-window rate limiter.
|
|
519
519
|
- `DEFAULT_COMMAND_LIMITS` (const): const DEFAULT_COMMAND_LIMITS: CommandLimits — Recommended per-op limits a host can opt into via `limits: DEFAULT_COMMAND_LIMITS`. Rate limiting is off unless `limits` is set.
|
|
520
520
|
- `DEFAULT_GRACE_MS` (const): const DEFAULT_GRACE_MS: 15000 — Default reconnect grace period for hosted socket sessions.
|
|
521
521
|
- `DEFAULT_POSE_RULES` (const): const DEFAULT_POSE_RULES: PoseSyncRules — ⚠ undocumented
|
|
522
|
-
- `GameServerHost` (type): type GameServerHost = { joinServer: (args: { userId: string; gameId: string; serverId?: string; attributes?: SessionAttributes; code?: string; role?: SnapshotViewer["role"]; }) => Promise<JoinServerResult>; browseServers: (args: { gameId: string;
|
|
523
|
-
- `GameServerHostOptions` (type): type GameServerHostOptions = { runtimes?: GameRuntime[]; persistence: HostPersistence; tickMs?: number; slotsPerServer?: number; now?: () => number; createServerId?: () => string; allowedFeedActions?: readonly string[]; } — Configuration for {@link createGameServerHost}, including persistence, tick rate, and game runtimes.
|
|
522
|
+
- `GameServerHost` (type): type GameServerHost = { joinServer: (args: { userId: string; gameId: string; serverId?: string | undefined; attributes?: SessionAttributes | undefined; code?: string | undefined; role?: SnapshotViewer["role"] | undefined; }) => Promise<JoinServerResult>; browseServers: (args: { gameId: string; filte… — A transport-agnostic authoritative game server host that manages sessions, ticking, and persistence.
|
|
523
|
+
- `GameServerHostOptions` (type): type GameServerHostOptions = { runtimes?: GameRuntime[] | undefined; persistence: HostPersistence; tickMs?: number | undefined; slotsPerServer?: number; now?: () => number; createServerId?: () => string; allowedFeedActions?: readonly string[]; } — Configuration for {@link createGameServerHost}, including persistence, tick rate, and game runtimes.
|
|
524
524
|
- `HostChangeEvent` (type): type HostChangeEvent = | { type: "server"; serverId: string } | { type: "player"; serverId: string; userId: string } | { type: "feed"; serverId: string; action: string } — A change notification emitted by a `GameServerHost` for a server, player, or feed mutation.
|
|
525
525
|
- `HostCommandOp` (type): type HostCommandOp = "pose" | "runCommand" | "join" | "browse" | "voice" — A host-side op the command middleware pipeline can gate: pose sync, `runCommand`, join/joinByCode, browse, or voice join/leave/publish.
|
|
526
526
|
- `HostRouter` (type): type HostRouter = { connect: (transport: HostRouterTransport) => HostRouterConnection; rewind: (args: { serverId: string; atMs: number }) => RewoundPosition[]; close: () => void; /** Wait for accepted message handlers and subscription reads to settle. Close first to prevent new work. */ drain: () =>… — ⚠ undocumented
|
|
527
|
-
- `HostRouterAuthenticate` (type): type HostRouterAuthenticate = (args: { userId: string; token?: string; }) => Promise<string | null> | string | null — ⚠ undocumented
|
|
527
|
+
- `HostRouterAuthenticate` (type): type HostRouterAuthenticate = (args: { userId: string; token?: string | undefined; }) => Promise<string | null> | string | null — ⚠ undocumented
|
|
528
528
|
- `HostRouterConnection` (type): type HostRouterConnection = { handleRaw: (raw: unknown) => void; close: () => void; } — ⚠ undocumented
|
|
529
529
|
- `HostRouterOptions` (type): type HostRouterOptions = { host: GameServerHost; authenticate?: HostRouterAuthenticate; allowAnonymous?: boolean; singleSession?: boolean; poseRules?: PoseSyncRules; positionHistoryMs?: number; chatRateLimit?: ChatRateLimit; chatHistoryLimit?: number; chatMaxBodyLength?: number; /** Per-op rate limi… — ⚠ undocumented
|
|
530
530
|
- `HostRouterTransport` (type): type HostRouterTransport = { send: (data: string) => void; close: () => void; } — ⚠ undocumented
|
|
@@ -546,7 +546,7 @@
|
|
|
546
546
|
- `PeerSignaling` (type): type PeerSignaling = { publishOffer: (offerCode: string) => Promise<string>; onOffer: (answer: (offerCode: string) => Promise<string>) => () => void; close: () => void; } — ⚠ undocumented
|
|
547
547
|
- `ReadsAuthenticate` (type): type ReadsAuthenticate = ( request: Request, ) => Promise<string | null> | string | null — ⚠ undocumented
|
|
548
548
|
- `ReadsHandler` (type): type ReadsHandler = (request: Request) => Promise<Response> — ⚠ undocumented
|
|
549
|
-
- `ReadsHandlerOptions` (type): type ReadsHandlerOptions = { persistence: ReadsPersistence | (() => Promise<ReadsPersistence>); basePath?: string; listOpenServers?: (args: { gameId: string; limit?: number }) => Promise<ServerListing[]>; authenticate?: ReadsAuthenticate; allowPublicProfiles?: boolean; } — ⚠ undocumented
|
|
549
|
+
- `ReadsHandlerOptions` (type): type ReadsHandlerOptions = { persistence: ReadsPersistence | (() => Promise<ReadsPersistence>); basePath?: string; listOpenServers?: (args: { gameId: string; limit?: number | undefined }) => Promise<ServerListing[]>; authenticate?: ReadsAuthenticate; allowPublicProfiles?: boolean; } — ⚠ undocumented
|
|
550
550
|
- `ReadsPersistence` (type): type ReadsPersistence = Pick< HostPersistence, "listServers" | "loadProfile" | "getLeaderboardTop" | "getLeaderboardProfile" > — ⚠ undocumented
|
|
551
551
|
- `RewoundPosition` (type): type RewoundPosition = { userId: string; x: number; y: number; z: number; } — A player's interpolated position sampled from history at a past timestamp.
|
|
552
552
|
- `SocketIoBackendOptions` (type): type SocketIoBackendOptions = Omit<WsBackendOptions, "url" | "pipe" | "webSocketFactory"> & { socket: SocketIoLikeSocket; } — ⚠ undocumented
|
|
@@ -564,22 +564,22 @@
|
|
|
564
564
|
- `WorldGameHostOptions` (interface): interface WorldGameHostOptions — Config for {@link createWorldGameHost}: how to resolve a hosted world's authoritative session per server.
|
|
565
565
|
- `WsAppearance` (type): type WsAppearance = Record<string, string | number | boolean> — Client-set cosmetic/state tags carried alongside a pose (skin, mount, emote, ...). Primitive values only.
|
|
566
566
|
- `WsBackend` (type): type WsBackend = GameBackend & { rtt: { sampleMs: number; smoothedMs: number }; pushFeedEntry: (args: { serverId: string; action: string; entry: unknown }) => Promise<void>; browse: (args: { gameId: string; filter?: MatchFilter; limit?: number }) => Promise<SessionListing[]>; joinByCode: (args: { ga… — ⚠ undocumented
|
|
567
|
-
- `WsBackendOptions` (type): type WsBackendOptions = { url?: string; pipe?: TransportPipeFactory; userId: string; token?: string; webSocketFactory?: (url: string) => WebSocket; reconnectDelayMs?: number; maxReconnectDelayMs?: number; rpcTimeoutMs?: number; poseTuning?: PoseSyncTuning; now?: () => number;
|
|
567
|
+
- `WsBackendOptions` (type): type WsBackendOptions = { url?: string; pipe?: TransportPipeFactory; userId: string; token?: string | undefined; webSocketFactory?: (url: string) => WebSocket; reconnectDelayMs?: number; maxReconnectDelayMs?: number; rpcTimeoutMs?: number; poseTuning?: PoseSyncTuning; now?: () => number; setTimeoutF… — ⚠ undocumented
|
|
568
568
|
- `WsBrowseResult` (type): type WsBrowseResult = SessionListing[] — ⚠ undocumented
|
|
569
569
|
- `WsChannel` (type): type WsChannel = "server" | "player" | "feed" | "presence" | "chat" | "voice" — ⚠ undocumented
|
|
570
570
|
- `WsChatMessage` (type): type WsChatMessage = { id: string; channelId: string; fromUserId: string; body: string; at: number; } — ⚠ undocumented
|
|
571
571
|
- `WsChatSync` (type): type WsChatSync = { subscribe: ( serverId: string, channelId: string, onChange: (messages: WsChatMessage[]) => void, ) => () => void; send: (serverId: string, channelId: string, body: string) => Promise<ChatSendOutcome>; } — ⚠ undocumented
|
|
572
|
-
- `WsClientMessage` (type): type WsClientMessage = | { v: 1; t: "ping"; id: number; at: number } | { v: 1; t: "hello"; id: number; userId: string; token?: string } | { v: 1; t: "join"; id: number; gameId: string; serverId?: string; attributes?: SessionAttributes; code?: string
|
|
573
|
-
- `WsDecodeFailure` (type): type WsDecodeFailure = { reason: string; id?: number; } — ⚠ undocumented
|
|
572
|
+
- `WsClientMessage` (type): type WsClientMessage = | { v: 1; t: "ping"; id: number; at: number } | { v: 1; t: "hello"; id: number; userId: string; token?: string | undefined } | { v: 1; t: "join"; id: number; gameId: string; serverId?: string | undefined; attributes?: SessionAttributes | undefined; code?: string | undefined; r… — ⚠ undocumented
|
|
573
|
+
- `WsDecodeFailure` (type): type WsDecodeFailure = { reason: string; id?: number | undefined; } — ⚠ undocumented
|
|
574
574
|
- `WsJoinByCodeResult` (type): type WsJoinByCodeResult = JoinServerResult | null — ⚠ undocumented
|
|
575
575
|
- `WsJoinResult` (type): type WsJoinResult = JoinServerResult — ⚠ undocumented
|
|
576
|
-
- `WsPose` (type): type WsPose = PlayerPose & { appearance?: WsAppearance } — ⚠ undocumented
|
|
577
|
-
- `WsPresenceRow` (type): type WsPresenceRow = PresencePoseRow & { appearance?: WsAppearance } — ⚠ undocumented
|
|
576
|
+
- `WsPose` (type): type WsPose = PlayerPose & { appearance?: WsAppearance | undefined } — ⚠ undocumented
|
|
577
|
+
- `WsPresenceRow` (type): type WsPresenceRow = PresencePoseRow & { appearance?: WsAppearance | undefined } — ⚠ undocumented
|
|
578
578
|
- `WsPresenceSync` (type): type WsPresenceSync = { subscribe: (serverId: string, onChange: (rows: WsPresenceRow[]) => void) => () => void; /** `pose.appearance`, when provided, is forwarded to the host as-is and surfaces on every subscriber's presence row for that user. */ syncPose: (serverId: string, pose: WsPose) => void; } — ⚠ undocumented
|
|
579
579
|
- `WsRunCommandResult` (type): type WsRunCommandResult = TransportRunCommandResult — ⚠ undocumented
|
|
580
580
|
- `WsServerMessage` (type): type WsServerMessage = | { v: 1; t: "pong"; id: number; at: number; serverAt: number } | { v: 1; t: "reply"; id: number; ok: true; result?: unknown } | { v: 1; t: "reply"; id: number; ok: false; reason: string } | WsUpdateMessage — ⚠ undocumented
|
|
581
581
|
- `WsUpdateMessage` (type): type WsUpdateMessage = | { v: 1; t: "update"; channel: "server"; serverId: string; data: GameRuntimeServerView | null } | { v: 1; t: "update"; channel: "player"; serverId: string; data: GameRuntimePlayerView | null } | { v: 1; t: "update"; channel: "feed"; serverId: string; action: string; data: unk… — ⚠ undocumented
|
|
582
|
-
- `WsVoiceParticipant` (type): type WsVoiceParticipant = { userId: string; streamId?: string; } — ⚠ undocumented
|
|
582
|
+
- `WsVoiceParticipant` (type): type WsVoiceParticipant = { userId: string; streamId?: string | undefined; } — ⚠ undocumented
|
|
583
583
|
- `WsVoiceSync` (type): type WsVoiceSync = { subscribe: ( serverId: string, channelId: string, onChange: (participants: WsVoiceParticipant[]) => void, ) => () => void; join: (serverId: string, channelId: string, streamId?: string) => Promise<void>; leave: (serverId: string, channelId: string) => Promise<void>; publish: (se… — ⚠ undocumented
|
|
584
584
|
- `announcePeerHost` (function): function announcePeerHost(host: PeerHost, signaling: PeerSignaling): () => void — ⚠ undocumented
|
|
585
585
|
- `broadcastChannelSignaling` (function): function broadcastChannelSignaling(room: string): PeerSignaling — ⚠ undocumented
|
|
@@ -607,14 +607,14 @@
|
|
|
607
607
|
|
|
608
608
|
## @jgengine/ws/commandMiddleware
|
|
609
609
|
|
|
610
|
-
- `CommandAuthorize` (type): type CommandAuthorize = (args: { userId: string; op: HostCommandOp; serverId?: string; command?: string; }) => boolean | Promise<boolean> — Per-command authorization hook: return `false` to reject. Defaults to allow-all when omitted.
|
|
610
|
+
- `CommandAuthorize` (type): type CommandAuthorize = (args: { userId: string; op: HostCommandOp; serverId?: string | undefined; command?: string | undefined; }) => boolean | Promise<boolean> — Per-command authorization hook: return `false` to reject. Defaults to allow-all when omitted.
|
|
611
611
|
- `CommandCatalog` (type): type CommandCatalog = Record<string, CommandCatalogEntry> — Declared `runCommand` names and their input validators. When set, any `runCommand` name absent from this catalog is rejected as unknown.
|
|
612
612
|
- `CommandCatalogEntry` (type): type CommandCatalogEntry = { validate?: (input: unknown) => CommandRejection | null; } — A declared `runCommand` name's input validator, run before the command reaches the game host.
|
|
613
|
-
- `CommandGateArgs` (type): type CommandGateArgs = { connection: object; userId: string; op: HostCommandOp; atMs: number; serverId?: string; command?: string; input?: unknown; } — One op attempt to run through the middleware pipeline: which connection, which op, and (for `runCommand`) the command name/input.
|
|
613
|
+
- `CommandGateArgs` (type): type CommandGateArgs = { connection: object; userId: string; op: HostCommandOp; atMs: number; serverId?: string | undefined; command?: string; input?: unknown; } — One op attempt to run through the middleware pipeline: which connection, which op, and (for `runCommand`) the command name/input.
|
|
614
614
|
- `CommandGateDecision` (type): type CommandGateDecision = { allow: true } | { allow: false; reason: string } — The pipeline's verdict for one {@link CommandGateArgs}: allowed, or rejected with a client-facing reason.
|
|
615
615
|
- `CommandLimits` (type): type CommandLimits = Partial<Record<HostCommandOp, CommandRateLimit>> — Per-op rate limits. An op with no entry (or an undefined `limits`) is unlimited.
|
|
616
616
|
- `CommandMiddleware` (type): type CommandMiddleware = { check: (args: CommandGateArgs) => Promise<CommandGateDecision>; } — A composable rate-limit → validate → authorize pipeline the host router runs before dispatching pose/runCommand/join/browse/voice ops. Every stage defaults to a no-op, so an unconfigured router behaves exactly as before.
|
|
617
|
-
- `CommandMiddlewareOptions` (type): type CommandMiddlewareOptions = { limits?: CommandLimits; authorize?: CommandAuthorize; validate?: CommandCatalog; } — Config for {@link createCommandMiddleware}: the same `limits`/`authorize`/`validate` fields accepted by `HostRouterOptions`.
|
|
617
|
+
- `CommandMiddlewareOptions` (type): type CommandMiddlewareOptions = { limits?: CommandLimits; authorize?: CommandAuthorize | undefined; validate?: CommandCatalog | undefined; } — Config for {@link createCommandMiddleware}: the same `limits`/`authorize`/`validate` fields accepted by `HostRouterOptions`.
|
|
618
618
|
- `CommandRateLimit` (type): type CommandRateLimit = { count: number; perMs: number } — A sliding-window rate limit: at most `count` calls per `perMs` window.
|
|
619
619
|
- `CommandRateLimiter` (type): type CommandRateLimiter = { allow: (connection: object, op: HostCommandOp, atMs: number) => boolean; } — A composable per-connection/per-op sliding-window rate limiter.
|
|
620
620
|
- `DEFAULT_COMMAND_LIMITS` (const): const DEFAULT_COMMAND_LIMITS: CommandLimits — Recommended per-op limits a host can opt into via `limits: DEFAULT_COMMAND_LIMITS`. Rate limiting is off unless `limits` is set.
|
|
@@ -626,7 +626,7 @@
|
|
|
626
626
|
## @jgengine/ws/createWsBackend
|
|
627
627
|
|
|
628
628
|
- `WsBackend` (type): type WsBackend = GameBackend & { rtt: { sampleMs: number; smoothedMs: number }; pushFeedEntry: (args: { serverId: string; action: string; entry: unknown }) => Promise<void>; browse: (args: { gameId: string; filter?: MatchFilter; limit?: number }) => Promise<SessionListing[]>; joinByCode: (args: { ga… — ⚠ undocumented
|
|
629
|
-
- `WsBackendOptions` (type): type WsBackendOptions = { url?: string; pipe?: TransportPipeFactory; userId: string; token?: string; webSocketFactory?: (url: string) => WebSocket; reconnectDelayMs?: number; maxReconnectDelayMs?: number; rpcTimeoutMs?: number; poseTuning?: PoseSyncTuning; now?: () => number;
|
|
629
|
+
- `WsBackendOptions` (type): type WsBackendOptions = { url?: string; pipe?: TransportPipeFactory; userId: string; token?: string | undefined; webSocketFactory?: (url: string) => WebSocket; reconnectDelayMs?: number; maxReconnectDelayMs?: number; rpcTimeoutMs?: number; poseTuning?: PoseSyncTuning; now?: () => number; setTimeoutF… — ⚠ undocumented
|
|
630
630
|
- `WsChatSync` (type): type WsChatSync = { subscribe: ( serverId: string, channelId: string, onChange: (messages: WsChatMessage[]) => void, ) => () => void; send: (serverId: string, channelId: string, body: string) => Promise<ChatSendOutcome>; } — ⚠ undocumented
|
|
631
631
|
- `WsPresenceSync` (type): type WsPresenceSync = { subscribe: (serverId: string, onChange: (rows: WsPresenceRow[]) => void) => () => void; /** `pose.appearance`, when provided, is forwarded to the host as-is and surfaces on every subscriber's presence row for that user. */ syncPose: (serverId: string, pose: WsPose) => void; } — ⚠ undocumented
|
|
632
632
|
- `WsVoiceSync` (type): type WsVoiceSync = { subscribe: ( serverId: string, channelId: string, onChange: (participants: WsVoiceParticipant[]) => void, ) => () => void; join: (serverId: string, channelId: string, streamId?: string) => Promise<void>; leave: (serverId: string, channelId: string) => Promise<void>; publish: (se… — ⚠ undocumented
|
|
@@ -634,8 +634,8 @@
|
|
|
634
634
|
|
|
635
635
|
## @jgengine/ws/host
|
|
636
636
|
|
|
637
|
-
- `GameServerHost` (type): type GameServerHost = { joinServer: (args: { userId: string; gameId: string; serverId?: string; attributes?: SessionAttributes; code?: string; role?: SnapshotViewer["role"]; }) => Promise<JoinServerResult>; browseServers: (args: { gameId: string;
|
|
638
|
-
- `GameServerHostOptions` (type): type GameServerHostOptions = { runtimes?: GameRuntime[]; persistence: HostPersistence; tickMs?: number; slotsPerServer?: number; now?: () => number; createServerId?: () => string; allowedFeedActions?: readonly string[]; } — Configuration for {@link createGameServerHost}, including persistence, tick rate, and game runtimes.
|
|
637
|
+
- `GameServerHost` (type): type GameServerHost = { joinServer: (args: { userId: string; gameId: string; serverId?: string | undefined; attributes?: SessionAttributes | undefined; code?: string | undefined; role?: SnapshotViewer["role"] | undefined; }) => Promise<JoinServerResult>; browseServers: (args: { gameId: string; filte… — A transport-agnostic authoritative game server host that manages sessions, ticking, and persistence.
|
|
638
|
+
- `GameServerHostOptions` (type): type GameServerHostOptions = { runtimes?: GameRuntime[] | undefined; persistence: HostPersistence; tickMs?: number | undefined; slotsPerServer?: number; now?: () => number; createServerId?: () => string; allowedFeedActions?: readonly string[]; } — Configuration for {@link createGameServerHost}, including persistence, tick rate, and game runtimes.
|
|
639
639
|
- `HostChangeEvent` (type): type HostChangeEvent = | { type: "server"; serverId: string } | { type: "player"; serverId: string; userId: string } | { type: "feed"; serverId: string; action: string } — A change notification emitted by a `GameServerHost` for a server, player, or feed mutation.
|
|
640
640
|
- `OP_LEDGER_LIMIT` (const): const OP_LEDGER_LIMIT: 64 — Max recently-applied `runCommand` op IDs retained per (serverId, userId), oldest evicted first.
|
|
641
641
|
- `createGameServerHost` (function): function createGameServerHost(options: GameServerHostOptions): GameServerHost — Creates a `GameServerHost` that runs game servers over the given persistence and runtimes.
|
|
@@ -646,7 +646,7 @@
|
|
|
646
646
|
- `DEFAULT_GRACE_MS` (const): const DEFAULT_GRACE_MS: 15000 — Default reconnect grace period for hosted socket sessions.
|
|
647
647
|
- `DEFAULT_POSE_RULES` (const): const DEFAULT_POSE_RULES: PoseSyncRules — ⚠ undocumented
|
|
648
648
|
- `HostRouter` (type): type HostRouter = { connect: (transport: HostRouterTransport) => HostRouterConnection; rewind: (args: { serverId: string; atMs: number }) => RewoundPosition[]; close: () => void; /** Wait for accepted message handlers and subscription reads to settle. Close first to prevent new work. */ drain: () =>… — ⚠ undocumented
|
|
649
|
-
- `HostRouterAuthenticate` (type): type HostRouterAuthenticate = (args: { userId: string; token?: string; }) => Promise<string | null> | string | null — ⚠ undocumented
|
|
649
|
+
- `HostRouterAuthenticate` (type): type HostRouterAuthenticate = (args: { userId: string; token?: string | undefined; }) => Promise<string | null> | string | null — ⚠ undocumented
|
|
650
650
|
- `HostRouterConnection` (type): type HostRouterConnection = { handleRaw: (raw: unknown) => void; close: () => void; } — ⚠ undocumented
|
|
651
651
|
- `HostRouterOptions` (type): type HostRouterOptions = { host: GameServerHost; authenticate?: HostRouterAuthenticate; allowAnonymous?: boolean; singleSession?: boolean; poseRules?: PoseSyncRules; positionHistoryMs?: number; chatRateLimit?: ChatRateLimit; chatHistoryLimit?: number; chatMaxBodyLength?: number; /** Per-op rate limi… — ⚠ undocumented
|
|
652
652
|
- `HostRouterTransport` (type): type HostRouterTransport = { send: (data: string) => void; close: () => void; } — ⚠ undocumented
|
|
@@ -697,22 +697,22 @@
|
|
|
697
697
|
- `WsBrowseResult` (type): type WsBrowseResult = SessionListing[] — ⚠ undocumented
|
|
698
698
|
- `WsChannel` (type): type WsChannel = "server" | "player" | "feed" | "presence" | "chat" | "voice" — ⚠ undocumented
|
|
699
699
|
- `WsChatMessage` (type): type WsChatMessage = { id: string; channelId: string; fromUserId: string; body: string; at: number; } — ⚠ undocumented
|
|
700
|
-
- `WsClientMessage` (type): type WsClientMessage = | { v: 1; t: "ping"; id: number; at: number } | { v: 1; t: "hello"; id: number; userId: string; token?: string } | { v: 1; t: "join"; id: number; gameId: string; serverId?: string; attributes?: SessionAttributes; code?: string
|
|
701
|
-
- `WsDecodeFailure` (type): type WsDecodeFailure = { reason: string; id?: number; } — ⚠ undocumented
|
|
700
|
+
- `WsClientMessage` (type): type WsClientMessage = | { v: 1; t: "ping"; id: number; at: number } | { v: 1; t: "hello"; id: number; userId: string; token?: string | undefined } | { v: 1; t: "join"; id: number; gameId: string; serverId?: string | undefined; attributes?: SessionAttributes | undefined; code?: string | undefined; r… — ⚠ undocumented
|
|
701
|
+
- `WsDecodeFailure` (type): type WsDecodeFailure = { reason: string; id?: number | undefined; } — ⚠ undocumented
|
|
702
702
|
- `WsJoinByCodeResult` (type): type WsJoinByCodeResult = JoinServerResult | null — ⚠ undocumented
|
|
703
703
|
- `WsJoinResult` (type): type WsJoinResult = JoinServerResult — ⚠ undocumented
|
|
704
|
-
- `WsPose` (type): type WsPose = PlayerPose & { appearance?: WsAppearance } — ⚠ undocumented
|
|
705
|
-
- `WsPresenceRow` (type): type WsPresenceRow = PresencePoseRow & { appearance?: WsAppearance } — ⚠ undocumented
|
|
704
|
+
- `WsPose` (type): type WsPose = PlayerPose & { appearance?: WsAppearance | undefined } — ⚠ undocumented
|
|
705
|
+
- `WsPresenceRow` (type): type WsPresenceRow = PresencePoseRow & { appearance?: WsAppearance | undefined } — ⚠ undocumented
|
|
706
706
|
- `WsRunCommandResult` (type): type WsRunCommandResult = TransportRunCommandResult — ⚠ undocumented
|
|
707
707
|
- `WsServerMessage` (type): type WsServerMessage = | { v: 1; t: "pong"; id: number; at: number; serverAt: number } | { v: 1; t: "reply"; id: number; ok: true; result?: unknown } | { v: 1; t: "reply"; id: number; ok: false; reason: string } | WsUpdateMessage — ⚠ undocumented
|
|
708
708
|
- `WsUpdateMessage` (type): type WsUpdateMessage = | { v: 1; t: "update"; channel: "server"; serverId: string; data: GameRuntimeServerView | null } | { v: 1; t: "update"; channel: "player"; serverId: string; data: GameRuntimePlayerView | null } | { v: 1; t: "update"; channel: "feed"; serverId: string; action: string; data: unk… — ⚠ undocumented
|
|
709
|
-
- `WsVoiceParticipant` (type): type WsVoiceParticipant = { userId: string; streamId?: string; } — ⚠ undocumented
|
|
709
|
+
- `WsVoiceParticipant` (type): type WsVoiceParticipant = { userId: string; streamId?: string | undefined; } — ⚠ undocumented
|
|
710
710
|
|
|
711
711
|
## @jgengine/ws/readsHandler
|
|
712
712
|
|
|
713
713
|
- `ReadsAuthenticate` (type): type ReadsAuthenticate = ( request: Request, ) => Promise<string | null> | string | null — ⚠ undocumented
|
|
714
714
|
- `ReadsHandler` (type): type ReadsHandler = (request: Request) => Promise<Response> — ⚠ undocumented
|
|
715
|
-
- `ReadsHandlerOptions` (type): type ReadsHandlerOptions = { persistence: ReadsPersistence | (() => Promise<ReadsPersistence>); basePath?: string; listOpenServers?: (args: { gameId: string; limit?: number }) => Promise<ServerListing[]>; authenticate?: ReadsAuthenticate; allowPublicProfiles?: boolean; } — ⚠ undocumented
|
|
715
|
+
- `ReadsHandlerOptions` (type): type ReadsHandlerOptions = { persistence: ReadsPersistence | (() => Promise<ReadsPersistence>); basePath?: string; listOpenServers?: (args: { gameId: string; limit?: number | undefined }) => Promise<ServerListing[]>; authenticate?: ReadsAuthenticate; allowPublicProfiles?: boolean; } — ⚠ undocumented
|
|
716
716
|
- `ReadsPersistence` (type): type ReadsPersistence = Pick< HostPersistence, "listServers" | "loadProfile" | "getLeaderboardTop" | "getLeaderboardProfile" > — ⚠ undocumented
|
|
717
717
|
- `createReadsHandler` (function): function createReadsHandler(options: ReadsHandlerOptions): ReadsHandler — ⚠ undocumented
|
|
718
718
|
|