@jgengine/ws 0.10.0 → 0.11.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 +13 -2
- package/LICENSE +203 -661
- package/README.md +1 -1
- package/dist/commandMiddleware.d.ts +62 -0
- package/dist/commandMiddleware.js +66 -0
- package/dist/createWsBackend.js +13 -1
- package/dist/host.d.ts +3 -0
- package/dist/host.js +168 -93
- package/dist/hostRouter.d.ts +9 -0
- package/dist/hostRouter.js +128 -38
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/pipe.js +2 -1
- package/dist/protocol.d.ts +16 -0
- package/dist/protocol.js +51 -5
- package/dist/readsHandler.js +2 -1
- package/dist/worldHost.js +2 -2
- package/package.json +4 -4
- package/skills/jgengine/SKILL.md +51 -0
- package/skills/jgengine/api.md +434 -0
- package/skills/jgengine/capabilities.md +29 -0
- package/skills/jgengine/reference-cartridge.md +72 -0
- package/skills/jgengine-multiplayer/SKILL.md +36 -0
- package/skills/jgengine-multiplayer/api.md +611 -0
- package/skills/jgengine-multiplayer/capabilities.md +9 -0
- package/skills/jgengine-multiplayer/reference.md +69 -0
- package/llms.txt +0 -1061
|
@@ -0,0 +1,611 @@
|
|
|
1
|
+
<!-- GENERATED by scripts/gen-skill-api.ts — do not edit. Regenerate: bun run gen:skill-api -->
|
|
2
|
+
|
|
3
|
+
# jgengine-multiplayer — exported API surface
|
|
4
|
+
|
|
5
|
+
## @jgengine/convex
|
|
6
|
+
|
|
7
|
+
- `ConvexBackend` (type): type ConvexBackend<TPresenceRow = unknown, TPresenceLocation = unknown, TGameId extends string = string> = LiveGameBackend<TPresenceRow, TPresenceLocation, TGameId> & { leaderboard: ConvexLeaderboardReads; } — ⚠ undocumented
|
|
8
|
+
- `ConvexBackendOptions` (type): type ConvexBackendOptions<TRawPresenceRow extends { actorExternalId: string }, TPresenceRow> = { client: ConvexReactClient; gameId: string; userId: string; api?: ConvexGameApi; poseTuning?: PoseSyncTuning; presence?: { functions: ConvexPresenceFunctions; mapRow: (row: TRawPresenceRow) => TPresenceRo… — ⚠ undocumented
|
|
9
|
+
- `ConvexChatFunctions` (interface): interface ConvexChatFunctions — ⚠ undocumented
|
|
10
|
+
- `ConvexGameApi` (type): type ConvexGameApi = { runtime: { joinServer: FunctionReference< "mutation", "public", { gameId: string; serverId?: string; mode?: string; visibility?: "public" | "private"; joinCode?: string; externalId?: string; }, { serverId: string; isNew: boolean } >; leaveServer: FunctionReference<"mutation", … — ⚠ undocumented
|
|
11
|
+
- `ConvexGameTransportConfig` (type): type ConvexGameTransportConfig = { gameId: string; userId?: string; } — ⚠ undocumented
|
|
12
|
+
- `ConvexLeaderboardReads` (type): type ConvexLeaderboardReads = ReturnType<typeof createConvexLeaderboardReads> — ⚠ undocumented
|
|
13
|
+
- `ConvexPresenceFunctions` (interface): interface ConvexPresenceFunctions — ⚠ undocumented
|
|
14
|
+
- `ConvexSaveBackendOptions` (interface): interface ConvexSaveBackendOptions — Config for {@link createConvexSaveBackend} — the Convex client, optional function refs (defaults to the `saves.*` convention), and an optional key `namespace`.
|
|
15
|
+
- `ConvexSaveFunctions` (interface): interface ConvexSaveFunctions — The three Convex functions a save backend calls — a `query` that returns the stored string (or `null`) and two `mutation`s. Point them at your app's own module, or lean on the default `saves.*` convention.
|
|
16
|
+
- `DEFAULT_CONVEX_POSE_RULES` (const): const DEFAULT_CONVEX_POSE_RULES: PoseSyncRules — ⚠ undocumented
|
|
17
|
+
- `HostedGameConfig` (interface): interface HostedGameConfig — One game the hosted path can serve, bound per `gameId`: its definition plus content lookup.
|
|
18
|
+
- `HostedWorldInvocation` (interface): interface HostedWorldInvocation<T> — Everything one stateless invocation reconstructs a hosted world from: the persisted record via `store`, plus the member roster and held inputs the snapshot doesn't carry, and the op to apply to the fresh session.
|
|
19
|
+
- `HostedWorldOutcome` (interface): interface HostedWorldOutcome<T> — What one stateless invocation produced: the op's value, the resulting revision, whether the world changed (and was saved back), and the post-op roster.
|
|
20
|
+
- `JG_HOSTED_TICK_MS` (const): const JG_HOSTED_TICK_MS: 1000 — Default minimum elapsed ms before `tickHostedWorlds` advances a world — override via the factory's `tickMs`.
|
|
21
|
+
- `JG_RUNTIME_TICK_MS` (const): const JG_RUNTIME_TICK_MS: 1000 — ⚠ undocumented
|
|
22
|
+
- `JgAuthMode` (type): type JgAuthMode = "anonymous" | "required" — ⚠ undocumented
|
|
23
|
+
- `JgCronSpec` (type): type JgCronSpec = { name: string; intervalSeconds: number; functionKey: "tickActiveServers" | "flushDirtyServers"; } — ⚠ undocumented
|
|
24
|
+
- `REVISION_CONFLICT_REASON` (const): const REVISION_CONFLICT_REASON: "Revision conflict" — ⚠ undocumented
|
|
25
|
+
- `createConvexBackend` (function): function createConvexBackend<TRawPresenceRow extends { actorExternalId: string } = { actorExternalId: string }, TPresenceRow = unknown, TPresenceLocation = unknown, TGameId extends string = string>(options: ConvexBackendOptions<TRawPresenceRow, TPresenceRow>): ConvexBackend<TPresenceRow, TPresenceLo… — ⚠ undocumented
|
|
26
|
+
- `createConvexChatSync` (function): function createConvexChatSync(client: ConvexReactClient, api: ConvexGameApi, config: ConvexGameTransportConfig, serverId: string): ChatSync — ⚠ undocumented
|
|
27
|
+
- `createConvexChatTransport` (function): function createConvexChatTransport<TRawRow = ChatMessage>(functions: ConvexChatFunctions, options?: { mapRow?: (row: TRawRow) => ChatMessage; extraArgs?: Record<string, unknown>; }): ChatTransport — Wires a game's Convex chat functions into the engine's ChatTransport contract: one live query per subscribed channel (the channel's recent history, newest last) and one send mutation. mapRow converts backend rows into ChatMessage (defaults to structural passthrough); extraArgs is spread into both calls for games that scope chat by server or world.
|
|
28
|
+
- `createConvexFeedWrites` (function): function createConvexFeedWrites(client: ConvexReactClient, api: ConvexGameApi, config: ConvexGameTransportConfig): { pushFeedEntry(args: { serverId: string; action: string; entry: unknown; }): Promise<void>; } — ⚠ undocumented
|
|
29
|
+
- `createConvexGameFeeds` (function): function createConvexGameFeeds(client: ConvexReactClient, api: ConvexGameApi, config: ConvexGameTransportConfig): GameRuntimeFeeds — ⚠ undocumented
|
|
30
|
+
- `createConvexGameTransport` (function): function createConvexGameTransport(client: ConvexReactClient, api: ConvexGameApi, config: ConvexGameTransportConfig): GameRuntimeTransport — ⚠ undocumented
|
|
31
|
+
- `createConvexLeaderboardReads` (function): function createConvexLeaderboardReads(api: ConvexGameApi, config: ConvexGameTransportConfig): { getTop(args: { stat: string; scope: LeaderboardScope; serverId?: string | undefined; limit?: number | undefined; }): { query: FunctionReference<"query", "public", { gameId: string; stat: string; scope: Le… — ⚠ undocumented
|
|
32
|
+
- `createConvexPresenceSync` (function): function createConvexPresenceSync(client: ConvexReactClient, api: ConvexGameApi, config: ConvexGameTransportConfig, tuning?: PoseSyncTuning): PresenceSync — ⚠ undocumented
|
|
33
|
+
- `createConvexPresenceTransport` (function): function createConvexPresenceTransport<TRawRow extends RawPresenceActor, TRow, TLocation, TGameId extends string = string>(functions: ConvexPresenceFunctions, mapRow: (row: TRawRow) => TRow): PresenceTransport<TRow, TLocation, TGameId> — Wires a game's Convex presence functions into the engine's PresenceTransport contract: one snapshot subscription (my location + online players), one residents subscription (dormant candidates, decoupled from pose writes), and one tick mutation for pose upload + keep-alive. Dormant rows are derived client-side by subtracting the snapshot's online actors, so pose ticks never re-execute the residents query. mapRow converts backend rows into the game's row type (e.g. branding positions into its coordinate space).
|
|
34
|
+
- `createConvexSaveBackend` (function): function createConvexSaveBackend(options: ConvexSaveBackendOptions): SaveBackend — A cloud {@link SaveBackend} backed by Convex — reads through a query and writes through mutations, so a {@link createSaveStore} configured with it saves to the server instead of `localStorage`. The only change from an offline game is swapping the backend; autosave, slots, and migration behave the same.
|
|
35
|
+
- `defaultConvexGameApi` (function): function defaultConvexGameApi(): ConvexGameApi — ⚠ undocumented
|
|
36
|
+
- `defaultConvexSaveFunctions` (function): function defaultConvexSaveFunctions(): ConvexSaveFunctions — Default `saves.read` / `saves.write` / `saves.remove` refs for apps that follow the convention — pass your own `functions` to override.
|
|
37
|
+
- `randomConvexPlayerId` (function): function randomConvexPlayerId(): string — ⚠ undocumented
|
|
38
|
+
- `resolveConvexMultiplayer` (function): function resolveConvexMultiplayer(args: { game: GameDefinition; gameId: string; url?: string; client?: ConvexReactClient; api?: ConvexGameApi; userId?: string; force?: boolean; feedActions?: string[]; poseTuning?: PoseSyncTuning; }): MultiplayerSession | null — ⚠ undocumented
|
|
39
|
+
- `watchConvexQuery` (function): function watchConvexQuery<TArgs extends DefaultFunctionArgs, TResult, TView>(client: ConvexReactClient, query: FunctionReference<"query", "public", TArgs, TResult>, args: TArgs, toView: (result: TResult) => TView, onChange: (view: TView) => void): () => void — ⚠ undocumented
|
|
40
|
+
|
|
41
|
+
## @jgengine/convex/convexChatTransport
|
|
42
|
+
|
|
43
|
+
- `ConvexChatFunctions` (interface): interface ConvexChatFunctions — ⚠ undocumented
|
|
44
|
+
- `createConvexChatTransport` (function): function createConvexChatTransport<TRawRow = ChatMessage>(functions: ConvexChatFunctions, options?: { mapRow?: (row: TRawRow) => ChatMessage; extraArgs?: Record<string, unknown>; }): ChatTransport — Wires a game's Convex chat functions into the engine's ChatTransport contract: one live query per subscribed channel (the channel's recent history, newest last) and one send mutation. mapRow converts backend rows into ChatMessage (defaults to structural passthrough); extraArgs is spread into both calls for games that scope chat by server or world.
|
|
45
|
+
|
|
46
|
+
## @jgengine/convex/convexPresenceTransport
|
|
47
|
+
|
|
48
|
+
- `ConvexPresenceFunctions` (interface): interface ConvexPresenceFunctions — ⚠ undocumented
|
|
49
|
+
- `createConvexPresenceTransport` (function): function createConvexPresenceTransport<TRawRow extends RawPresenceActor, TRow, TLocation, TGameId extends string = string>(functions: ConvexPresenceFunctions, mapRow: (row: TRawRow) => TRow): PresenceTransport<TRow, TLocation, TGameId> — Wires a game's Convex presence functions into the engine's PresenceTransport contract: one snapshot subscription (my location + online players), one residents subscription (dormant candidates, decoupled from pose writes), and one tick mutation for pose upload + keep-alive. Dormant rows are derived client-side by subtracting the snapshot's online actors, so pose ticks never re-execute the residents query. mapRow converts backend rows into the game's row type (e.g. branding positions into its coordinate space).
|
|
50
|
+
|
|
51
|
+
## @jgengine/convex/convexSaveBackend
|
|
52
|
+
|
|
53
|
+
- `ConvexSaveBackendOptions` (interface): interface ConvexSaveBackendOptions — Config for {@link createConvexSaveBackend} — the Convex client, optional function refs (defaults to the `saves.*` convention), and an optional key `namespace`.
|
|
54
|
+
- `ConvexSaveFunctions` (interface): interface ConvexSaveFunctions — The three Convex functions a save backend calls — a `query` that returns the stored string (or `null`) and two `mutation`s. Point them at your app's own module, or lean on the default `saves.*` convention.
|
|
55
|
+
- `createConvexSaveBackend` (function): function createConvexSaveBackend(options: ConvexSaveBackendOptions): SaveBackend — A cloud {@link SaveBackend} backed by Convex — reads through a query and writes through mutations, so a {@link createSaveStore} configured with it saves to the server instead of `localStorage`. The only change from an offline game is swapping the backend; autosave, slots, and migration behave the same.
|
|
56
|
+
- `defaultConvexSaveFunctions` (function): function defaultConvexSaveFunctions(): ConvexSaveFunctions — Default `saves.read` / `saves.write` / `saves.remove` refs for apps that follow the convention — pass your own `functions` to override.
|
|
57
|
+
|
|
58
|
+
## @jgengine/convex/createConvexBackend
|
|
59
|
+
|
|
60
|
+
- `ConvexBackend` (type): type ConvexBackend<TPresenceRow = unknown, TPresenceLocation = unknown, TGameId extends string = string> = LiveGameBackend<TPresenceRow, TPresenceLocation, TGameId> & { leaderboard: ConvexLeaderboardReads; } — ⚠ undocumented
|
|
61
|
+
- `ConvexBackendOptions` (type): type ConvexBackendOptions<TRawPresenceRow extends { actorExternalId: string }, TPresenceRow> = { client: ConvexReactClient; gameId: string; userId: string; api?: ConvexGameApi; poseTuning?: PoseSyncTuning; presence?: { functions: ConvexPresenceFunctions; mapRow: (row: TRawPresenceRow) => TPresenceRo… — ⚠ undocumented
|
|
62
|
+
- `ConvexLeaderboardReads` (type): type ConvexLeaderboardReads = ReturnType<typeof createConvexLeaderboardReads> — ⚠ undocumented
|
|
63
|
+
- `createConvexBackend` (function): function createConvexBackend<TRawPresenceRow extends { actorExternalId: string } = { actorExternalId: string }, TPresenceRow = unknown, TPresenceLocation = unknown, TGameId extends string = string>(options: ConvexBackendOptions<TRawPresenceRow, TPresenceRow>): ConvexBackend<TPresenceRow, TPresenceLo… — ⚠ undocumented
|
|
64
|
+
|
|
65
|
+
## @jgengine/convex/createConvexGameTransport
|
|
66
|
+
|
|
67
|
+
- `ConvexGameApi` (type): type ConvexGameApi = { runtime: { joinServer: FunctionReference< "mutation", "public", { gameId: string; serverId?: string; mode?: string; visibility?: "public" | "private"; joinCode?: string; externalId?: string; }, { serverId: string; isNew: boolean } >; leaveServer: FunctionReference<"mutation", … — ⚠ undocumented
|
|
68
|
+
- `ConvexGameTransportConfig` (type): type ConvexGameTransportConfig = { gameId: string; userId?: string; } — ⚠ undocumented
|
|
69
|
+
- `createConvexChatSync` (function): function createConvexChatSync(client: ConvexReactClient, api: ConvexGameApi, config: ConvexGameTransportConfig, serverId: string): ChatSync — ⚠ undocumented
|
|
70
|
+
- `createConvexFeedWrites` (function): function createConvexFeedWrites(client: ConvexReactClient, api: ConvexGameApi, config: ConvexGameTransportConfig): { pushFeedEntry(args: { serverId: string; action: string; entry: unknown; }): Promise<void>; } — ⚠ undocumented
|
|
71
|
+
- `createConvexGameFeeds` (function): function createConvexGameFeeds(client: ConvexReactClient, api: ConvexGameApi, config: ConvexGameTransportConfig): GameRuntimeFeeds — ⚠ undocumented
|
|
72
|
+
- `createConvexGameTransport` (function): function createConvexGameTransport(client: ConvexReactClient, api: ConvexGameApi, config: ConvexGameTransportConfig): GameRuntimeTransport — ⚠ undocumented
|
|
73
|
+
- `createConvexLeaderboardReads` (function): function createConvexLeaderboardReads(api: ConvexGameApi, config: ConvexGameTransportConfig): { getTop(args: { stat: string; scope: LeaderboardScope; serverId?: string | undefined; limit?: number | undefined; }): { query: FunctionReference<"query", "public", { gameId: string; stat: string; scope: Le… — ⚠ undocumented
|
|
74
|
+
- `createConvexPresenceSync` (function): function createConvexPresenceSync(client: ConvexReactClient, api: ConvexGameApi, config: ConvexGameTransportConfig, tuning?: PoseSyncTuning): PresenceSync — ⚠ undocumented
|
|
75
|
+
- `defaultConvexGameApi` (function): function defaultConvexGameApi(): ConvexGameApi — ⚠ undocumented
|
|
76
|
+
- `watchConvexQuery` (function): function watchConvexQuery<TArgs extends DefaultFunctionArgs, TResult, TView>(client: ConvexReactClient, query: FunctionReference<"query", "public", TArgs, TResult>, args: TArgs, toView: (result: TResult) => TView, onChange: (view: TView) => void): () => void — ⚠ undocumented
|
|
77
|
+
|
|
78
|
+
## @jgengine/convex/hostedServer
|
|
79
|
+
|
|
80
|
+
- `HostedGameConfig` (interface): interface HostedGameConfig — One game the hosted path can serve, bound per `gameId`: its definition plus content lookup.
|
|
81
|
+
- `HostedWorldInvocation` (interface): interface HostedWorldInvocation<T> — Everything one stateless invocation reconstructs a hosted world from: the persisted record via `store`, plus the member roster and held inputs the snapshot doesn't carry, and the op to apply to the fresh session.
|
|
82
|
+
- `HostedWorldOutcome` (interface): interface HostedWorldOutcome<T> — What one stateless invocation produced: the op's value, the resulting revision, whether the world changed (and was saved back), and the post-op roster.
|
|
83
|
+
- `JG_HOSTED_TICK_MS` (const): const JG_HOSTED_TICK_MS: 1000 — Default minimum elapsed ms before `tickHostedWorlds` advances a world — override via the factory's `tickMs`.
|
|
84
|
+
|
|
85
|
+
## @jgengine/convex/occ
|
|
86
|
+
|
|
87
|
+
- `REVISION_CONFLICT_REASON` (const): const REVISION_CONFLICT_REASON: "Revision conflict" — ⚠ undocumented
|
|
88
|
+
|
|
89
|
+
## @jgengine/convex/resolveConvexMultiplayer
|
|
90
|
+
|
|
91
|
+
- `randomConvexPlayerId` (function): function randomConvexPlayerId(): string — ⚠ undocumented
|
|
92
|
+
- `resolveConvexMultiplayer` (function): function resolveConvexMultiplayer(args: { game: GameDefinition; gameId: string; url?: string; client?: ConvexReactClient; api?: ConvexGameApi; userId?: string; force?: boolean; feedActions?: string[]; poseTuning?: PoseSyncTuning; }): MultiplayerSession | null — ⚠ undocumented
|
|
93
|
+
|
|
94
|
+
## @jgengine/convex/server
|
|
95
|
+
|
|
96
|
+
- `DEFAULT_CONVEX_POSE_RULES` (const): const DEFAULT_CONVEX_POSE_RULES: PoseSyncRules — ⚠ undocumented
|
|
97
|
+
- `JG_RUNTIME_TICK_MS` (const): const JG_RUNTIME_TICK_MS: 1000 — ⚠ undocumented
|
|
98
|
+
- `JgAuthMode` (type): type JgAuthMode = "anonymous" | "required" — ⚠ undocumented
|
|
99
|
+
- `JgCronSpec` (type): type JgCronSpec = { name: string; intervalSeconds: number; functionKey: "tickActiveServers" | "flushDirtyServers"; } — ⚠ undocumented
|
|
100
|
+
|
|
101
|
+
## @jgengine/core/multiplayer
|
|
102
|
+
|
|
103
|
+
- `AuthSession` (interface): interface AuthSession — ⚠ undocumented
|
|
104
|
+
- `BoardSnapshot` (interface): interface BoardSnapshot — ⚠ undocumented
|
|
105
|
+
- `ChatActions` (interface): interface ChatActions — ⚠ undocumented
|
|
106
|
+
- `ChatSendOutcome` (interface): interface ChatSendOutcome — ⚠ undocumented
|
|
107
|
+
- `ChatSync` (interface): interface ChatSync — Callback seam for backends that cannot host React hooks (e.g. the ws client): subscribe delivers the channel's recent history on every change; send resolves with the host's verdict.
|
|
108
|
+
- `ChatTransport` (interface): interface ChatTransport — Backend seam for remote text chat, mirroring PresenceTransport: the use* members are called as React hooks by consumers, so a mounted transport must never change identity — remount the subtree to switch backends. useMessages returns undefined while the subscription is loading and the channel's recent history once live.
|
|
109
|
+
- `EnsurePresenceResult` (interface): interface EnsurePresenceResult — ⚠ undocumented
|
|
110
|
+
- `FeedWriteGate` (type): type FeedWriteGate = { allowedActions: readonly string[]; } — ⚠ undocumented
|
|
111
|
+
- `MatchFilter` (interface): interface MatchFilter — ⚠ undocumented
|
|
112
|
+
- `PlayerIdentity` (interface): interface PlayerIdentity — ⚠ undocumented
|
|
113
|
+
- `PlayerPose` (interface): interface PlayerPose — ⚠ undocumented
|
|
114
|
+
- `PoseSyncRules` (interface): interface PoseSyncRules — ⚠ undocumented
|
|
115
|
+
- `PoseSyncTuning` (interface): interface PoseSyncTuning — ⚠ undocumented
|
|
116
|
+
- `PresenceActions` (interface): interface PresenceActions<TGameId extends string = string> — ⚠ undocumented
|
|
117
|
+
- `PresenceFeeds` (interface): interface PresenceFeeds<TRow, TLocation> — ⚠ undocumented
|
|
118
|
+
- `PresencePoseState` (interface): interface PresencePoseState — ⚠ undocumented
|
|
119
|
+
- `PresenceSession` (interface): interface PresenceSession<TGameId extends string = string> — ⚠ undocumented
|
|
120
|
+
- `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.
|
|
121
|
+
- `PushToTalkMode` (type): type PushToTalkMode = "hold" | "toggle" | "openMic" — ⚠ undocumented
|
|
122
|
+
- `PushToTalkStatus` (type): type PushToTalkStatus = "idle" | "keyed" | "open" — ⚠ undocumented
|
|
123
|
+
- `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.
|
|
124
|
+
- `SessionListing` (interface): interface SessionListing — ⚠ undocumented
|
|
125
|
+
- `SessionVisibility` (type): type SessionVisibility = "public" | "private" — ⚠ undocumented
|
|
126
|
+
- `Vec3` (interface): interface Vec3 — ⚠ undocumented
|
|
127
|
+
- `VoiceParticipant` (interface): interface VoiceParticipant — ⚠ undocumented
|
|
128
|
+
- `VoiceRoute` (interface): interface VoiceRoute — ⚠ undocumented
|
|
129
|
+
- `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.
|
|
130
|
+
- `browseSessions` (function): function browseSessions(listings: readonly SessionListing[], filter: MatchFilter = {}, options: BrowseOptions = {}): SessionListing[] — ⚠ undocumented
|
|
131
|
+
- `createFeedWriteGate` (function): function createFeedWriteGate(allowedActions: readonly string[] = []): FeedWriteGate — ⚠ undocumented
|
|
132
|
+
- `createLocalVoiceTransport` (function): function createLocalVoiceTransport(options?: { userId?: string }): { transport: VoiceTransport; participants(channelId: string): readonly VoiceParticipant[]; } — ⚠ undocumented
|
|
133
|
+
- `createPoseSyncGate` (function): function createPoseSyncGate(tuning: PoseSyncTuning): PoseSyncGate — ⚠ undocumented
|
|
134
|
+
- `createPushToTalk` (function): function createPushToTalk(config?: { mode?: PushToTalkMode; onChange?: (transmitting: boolean) => void; }): PushToTalk — ⚠ undocumented
|
|
135
|
+
- `findByJoinCode` (function): function findByJoinCode(listings: readonly SessionListing[], code: string): SessionListing | null — ⚠ undocumented
|
|
136
|
+
- `normalizeJoinCode` (function): function normalizeJoinCode(code: string): string — ⚠ undocumented
|
|
137
|
+
- `quickMatch` (function): function quickMatch(listings: readonly SessionListing[], filter: MatchFilter = {}): SessionListing | null — ⚠ undocumented
|
|
138
|
+
- `resolveGuestSession` (function): function resolveGuestSession(seed?: string): AuthSession — ⚠ undocumented
|
|
139
|
+
- `sessionPlayer` (function): function sessionPlayer(session: AuthSession): PlayerIdentity — ⚠ undocumented
|
|
140
|
+
- `validateFeedWrite` (function): function validateFeedWrite(gate: FeedWriteGate | undefined, action: string): { ok: true } | { ok: false; reason: string } — ⚠ undocumented
|
|
141
|
+
|
|
142
|
+
## @jgengine/core/multiplayer/chatContract
|
|
143
|
+
|
|
144
|
+
- `ChatActions` (interface): interface ChatActions — ⚠ undocumented
|
|
145
|
+
- `ChatSendArgs` (interface): interface ChatSendArgs — ⚠ undocumented
|
|
146
|
+
- `ChatSendOutcome` (interface): interface ChatSendOutcome — ⚠ undocumented
|
|
147
|
+
- `ChatSync` (interface): interface ChatSync — Callback seam for backends that cannot host React hooks (e.g. the ws client): subscribe delivers the channel's recent history on every change; send resolves with the host's verdict.
|
|
148
|
+
- `ChatTransport` (interface): interface ChatTransport — Backend seam for remote text chat, mirroring PresenceTransport: the use* members are called as React hooks by consumers, so a mounted transport must never change identity — remount the subtree to switch backends. useMessages returns undefined while the subscription is loading and the channel's recent history once live.
|
|
149
|
+
- `createLocalChatTransport` (function): function createLocalChatTransport(options?: { userId?: string; historyLimit?: number; now?: () => number; }): { transport: ChatTransport; sync: ChatSync; actions: ChatActions; } — ⚠ undocumented
|
|
150
|
+
|
|
151
|
+
## @jgengine/core/multiplayer/combatSnapshot
|
|
152
|
+
|
|
153
|
+
- `BoardSnapshot` (interface): interface BoardSnapshot — ⚠ undocumented
|
|
154
|
+
- `CombatRules` (interface): interface CombatRules — ⚠ undocumented
|
|
155
|
+
- `CombatSide` (type): type CombatSide = "a" | "b" | "draw" — ⚠ undocumented
|
|
156
|
+
- `ReplayBlow` (interface): interface ReplayBlow — ⚠ undocumented
|
|
157
|
+
- `ReplayResult` (interface): interface ReplayResult — ⚠ undocumented
|
|
158
|
+
- `SerializeBoardArgs` (interface): interface SerializeBoardArgs — ⚠ undocumented
|
|
159
|
+
- `SnapshotUnit` (interface): interface SnapshotUnit — ⚠ undocumented
|
|
160
|
+
|
|
161
|
+
## @jgengine/core/multiplayer/feedWriteGate
|
|
162
|
+
|
|
163
|
+
- `FeedWriteGate` (type): type FeedWriteGate = { allowedActions: readonly string[]; } — ⚠ undocumented
|
|
164
|
+
- `createFeedWriteGate` (function): function createFeedWriteGate(allowedActions: readonly string[] = []): FeedWriteGate — ⚠ undocumented
|
|
165
|
+
- `validateFeedWrite` (function): function validateFeedWrite(gate: FeedWriteGate | undefined, action: string): { ok: true } | { ok: false; reason: string } — ⚠ undocumented
|
|
166
|
+
|
|
167
|
+
## @jgengine/core/multiplayer/identity
|
|
168
|
+
|
|
169
|
+
- `AuthSession` (interface): interface AuthSession — ⚠ undocumented
|
|
170
|
+
- `PlayerIdentity` (interface): interface PlayerIdentity — ⚠ undocumented
|
|
171
|
+
- `resolveGuestSession` (function): function resolveGuestSession(seed?: string): AuthSession — ⚠ undocumented
|
|
172
|
+
- `sessionPlayer` (function): function sessionPlayer(session: AuthSession): PlayerIdentity — ⚠ undocumented
|
|
173
|
+
|
|
174
|
+
## @jgengine/core/multiplayer/lagCompensation
|
|
175
|
+
|
|
176
|
+
- `HitscanHit` (interface): interface HitscanHit — ⚠ undocumented
|
|
177
|
+
- `HitscanRay` (interface): interface HitscanRay — ⚠ undocumented
|
|
178
|
+
- `HitscanTarget` (interface): interface HitscanTarget — ⚠ undocumented
|
|
179
|
+
- `PositionHistoryConfig` (interface): interface PositionHistoryConfig — ⚠ undocumented
|
|
180
|
+
- `PositionSample` (interface): interface PositionSample extends Vec3 — ⚠ undocumented
|
|
181
|
+
- `Vec3` (interface): interface Vec3 — ⚠ undocumented
|
|
182
|
+
|
|
183
|
+
## @jgengine/core/multiplayer/matchmaking
|
|
184
|
+
|
|
185
|
+
- `BrowseOptions` (interface): interface BrowseOptions — ⚠ undocumented
|
|
186
|
+
- `MatchFilter` (interface): interface MatchFilter — ⚠ undocumented
|
|
187
|
+
- `SessionListing` (interface): interface SessionListing — ⚠ undocumented
|
|
188
|
+
- `SessionStatus` (type): type SessionStatus = "open" | "running" | "closed" — ⚠ undocumented
|
|
189
|
+
- `SessionVisibility` (type): type SessionVisibility = "public" | "private" — ⚠ undocumented
|
|
190
|
+
- `browseSessions` (function): function browseSessions(listings: readonly SessionListing[], filter: MatchFilter = {}, options: BrowseOptions = {}): SessionListing[] — ⚠ undocumented
|
|
191
|
+
- `findByJoinCode` (function): function findByJoinCode(listings: readonly SessionListing[], code: string): SessionListing | null — ⚠ undocumented
|
|
192
|
+
- `generateJoinCode` (function): function generateJoinCode(random: () => number, length = 6): string — ⚠ undocumented
|
|
193
|
+
- `hasSpace` (function): function hasSpace(listing: SessionListing): boolean — ⚠ undocumented
|
|
194
|
+
- `matchesFilter` (function): function matchesFilter(listing: SessionListing, filter: MatchFilter): boolean — ⚠ undocumented
|
|
195
|
+
- `normalizeJoinCode` (function): function normalizeJoinCode(code: string): string — ⚠ undocumented
|
|
196
|
+
- `quickMatch` (function): function quickMatch(listings: readonly SessionListing[], filter: MatchFilter = {}): SessionListing | null — ⚠ undocumented
|
|
197
|
+
|
|
198
|
+
## @jgengine/core/multiplayer/poseSyncGate
|
|
199
|
+
|
|
200
|
+
- `PlayerPose` (interface): interface PlayerPose — ⚠ undocumented
|
|
201
|
+
- `PoseSyncGate` (interface): interface PoseSyncGate — ⚠ undocumented
|
|
202
|
+
- `PoseSyncTuning` (interface): interface PoseSyncTuning — ⚠ undocumented
|
|
203
|
+
- `createPoseSyncGate` (function): function createPoseSyncGate(tuning: PoseSyncTuning): PoseSyncGate — ⚠ undocumented
|
|
204
|
+
|
|
205
|
+
## @jgengine/core/multiplayer/presenceContract
|
|
206
|
+
|
|
207
|
+
- `EnsurePresenceArgs` (interface): interface EnsurePresenceArgs<TGameId extends string = string> — ⚠ undocumented
|
|
208
|
+
- `EnsurePresenceResult` (interface): interface EnsurePresenceResult — ⚠ undocumented
|
|
209
|
+
- `LeavePresenceArgs` (interface): interface LeavePresenceArgs<TGameId extends string = string> — ⚠ undocumented
|
|
210
|
+
- `PresenceActions` (interface): interface PresenceActions<TGameId extends string = string> — ⚠ undocumented
|
|
211
|
+
- `PresenceFeeds` (interface): interface PresenceFeeds<TRow, TLocation> — ⚠ undocumented
|
|
212
|
+
- `PresencePose` (interface): interface PresencePose — ⚠ undocumented
|
|
213
|
+
- `PresencePosition` (interface): interface PresencePosition — ⚠ undocumented
|
|
214
|
+
- `PresenceSession` (interface): interface PresenceSession<TGameId extends string = string> — ⚠ undocumented
|
|
215
|
+
- `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.
|
|
216
|
+
- `createLocalPresenceTransport` (function): function createLocalPresenceTransport<TRow, TLocation, TGameId extends string = string>(): { transport: PresenceTransport<TRow, TLocation, TGameId>; actions: PresenceActions<TGameId>; } — ⚠ undocumented
|
|
217
|
+
|
|
218
|
+
## @jgengine/core/multiplayer/presenceModel
|
|
219
|
+
|
|
220
|
+
- `ActivePresenceResolution` (interface): interface ActivePresenceResolution<T> — ⚠ undocumented
|
|
221
|
+
- `DEFAULT_SPAWN_ORIGIN` (const): const DEFAULT_SPAWN_ORIGIN: { readonly x: 0; readonly y: 0; readonly z: 0; } — ⚠ undocumented
|
|
222
|
+
- `IncomingPose` (interface): interface IncomingPose — ⚠ undocumented
|
|
223
|
+
- `PoseSyncDecision` (interface): interface PoseSyncDecision — ⚠ undocumented
|
|
224
|
+
- `PoseSyncRules` (interface): interface PoseSyncRules — ⚠ undocumented
|
|
225
|
+
- `PresencePoseState` (interface): interface PresencePoseState — ⚠ undocumented
|
|
226
|
+
|
|
227
|
+
## @jgengine/core/multiplayer/simultaneousCommit
|
|
228
|
+
|
|
229
|
+
- `CommitPhase` (type): type CommitPhase = "collecting" | "revealed" — ⚠ undocumented
|
|
230
|
+
- `CommitRoundConfig` (interface): interface CommitRoundConfig — ⚠ undocumented
|
|
231
|
+
- `SealResult` (type): type SealResult = | { ok: true; allSealed: boolean } | { ok: false; reason: "unknown_participant" | "already_sealed" | "already_revealed" } — ⚠ undocumented
|
|
232
|
+
- `SealedCommit` (interface): interface SealedCommit<TAction> — ⚠ undocumented
|
|
233
|
+
|
|
234
|
+
## @jgengine/core/multiplayer/voiceContract
|
|
235
|
+
|
|
236
|
+
- `PushToTalk` (interface): interface PushToTalk — ⚠ undocumented
|
|
237
|
+
- `PushToTalkMode` (type): type PushToTalkMode = "hold" | "toggle" | "openMic" — ⚠ undocumented
|
|
238
|
+
- `PushToTalkStatus` (type): type PushToTalkStatus = "idle" | "keyed" | "open" — ⚠ undocumented
|
|
239
|
+
- `VoiceParticipant` (interface): interface VoiceParticipant — ⚠ undocumented
|
|
240
|
+
- `VoiceRoute` (interface): interface VoiceRoute — ⚠ undocumented
|
|
241
|
+
- `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.
|
|
242
|
+
- `createLocalVoiceTransport` (function): function createLocalVoiceTransport(options?: { userId?: string }): { transport: VoiceTransport; participants(channelId: string): readonly VoiceParticipant[]; } — ⚠ undocumented
|
|
243
|
+
- `createPushToTalk` (function): function createPushToTalk(config?: { mode?: PushToTalkMode; onChange?: (transmitting: boolean) => void; }): PushToTalk — ⚠ undocumented
|
|
244
|
+
|
|
245
|
+
## @jgengine/core/runtime/worldProjection
|
|
246
|
+
|
|
247
|
+
- `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.
|
|
248
|
+
|
|
249
|
+
## @jgengine/node
|
|
250
|
+
|
|
251
|
+
- `DEFAULT_HEARTBEAT_INTERVAL_MS` (const): const DEFAULT_HEARTBEAT_INTERVAL_MS: 30000 — Default ping/pong interval; a socket that misses one round-trip is terminated.
|
|
252
|
+
- `DEFAULT_MAX_CONNECTIONS` (const): const DEFAULT_MAX_CONNECTIONS: 10000 — Default max concurrent sockets this server accepts before rejecting new ones.
|
|
253
|
+
- `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.
|
|
254
|
+
- `GameHost` (type): type GameHost = { joinServer: (args: { userId: string; gameId: string; serverId?: string; attributes?: SessionAttributes; code?: string; }) => Promise<JoinServerResult>; browseServers: (args: { gameId: string; filter?: MatchFilter; limit?: number; }) => Promise<SessionListing[]>; joinByCode: (args: … — A transport-agnostic authoritative game server host that manages sessions, ticking, and persistence.
|
|
255
|
+
- `GameHostOptions` (type): type GameHostOptions = { runtimes?: GameRuntime[]; persistence: HostPersistence; tickMs?: number; slotsPerServer?: number; now?: () => number; createServerId?: () => string; allowedFeedActions?: readonly string[]; } — Configuration for {@link createGameHost}, including persistence, tick rate, and game runtimes.
|
|
256
|
+
- `GameSocketIoServer` (type): type GameSocketIoServer = { rewind: (args: { serverId: string; atMs: number }) => RewoundPosition[]; close: () => void; } — ⚠ undocumented
|
|
257
|
+
- `GameSocketIoServerOptions` (type): type GameSocketIoServerOptions = HostRouterOptions & { io: SocketIoLikeServer } — ⚠ undocumented
|
|
258
|
+
- `GameWsServer` (type): type GameWsServer = { wss: WebSocketServer; port: () => number; rewind: (args: { serverId: string; atMs: number }) => RewoundPosition[]; close: () => Promise<void>; } — ⚠ undocumented
|
|
259
|
+
- `GameWsServerOptions` (type): type GameWsServerOptions = HostRouterOptions & { server?: HttpServer; port?: number; path?: string; /** Per-message payload cap in bytes. Defaults to {@link DEFAULT_MAX_PAYLOAD_BYTES}. */ maxPayloadBytes?: number; /** Max concurrent sockets accepted; connections beyond this are closed immediately. D… — ⚠ undocumented
|
|
260
|
+
- `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 `GameHost` for a server, player, or feed mutation.
|
|
261
|
+
- `HostedGameDefinition` (interface): interface HostedGameDefinition — A game the world server can host — its authoritative {@link GameDefinition} and the content lookup a `GameContext` reads.
|
|
262
|
+
- `InstallShutdownHookOptions` (interface): interface InstallShutdownHookOptions — Config for {@link installShutdownHook}.
|
|
263
|
+
- `NodeHandler` (type): type NodeHandler = (req: IncomingMessage, res: ServerResponse) => void — ⚠ undocumented
|
|
264
|
+
- `RewoundPosition` (type): type RewoundPosition = { userId: string; x: number; y: number; z: number; } — A player's interpolated position sampled from history at a past timestamp.
|
|
265
|
+
- `ShutdownHook` (interface): interface ShutdownHook — A live signal listener installed by {@link installShutdownHook}; call `remove()` to uninstall it (tests, embedders opting out).
|
|
266
|
+
- `SocketIoLikeServer` (type): type SocketIoLikeServer = { on: (event: "connection", listener: (socket: SocketIoLikeServerSocket) => void) => unknown; } — ⚠ undocumented
|
|
267
|
+
- `SocketIoLikeServerSocket` (type): type SocketIoLikeServerSocket = { on: (event: string, listener: (payload: string) => void) => unknown; send: (data: string) => unknown; disconnect: (close?: boolean) => unknown; } — ⚠ undocumented
|
|
268
|
+
- `WebHandler` (type): type WebHandler = (request: Request) => Promise<Response> — ⚠ undocumented
|
|
269
|
+
- `WorldGameServer` (interface): interface WorldGameServer — A runnable ws host for GameContext worlds: {@link createWorldGameHost} + {@link createGameWsServer} + a tick loop, with a manual `tick(dt)` seam so a fake clock can drive it in tests.
|
|
270
|
+
- `WorldGameServerOptions` (interface): interface WorldGameServerOptions extends Omit<GameWsServerOptions, "host"> — Config for {@link createWorldGameServer}: how to resolve a game by id, the tick cadence, and the underlying ws-server/router options (minus `host`, which the server builds).
|
|
271
|
+
- `WorldPersistence` (interface): interface WorldPersistence — The persistence plug-point for {@link createWorldGameServer}: resolves one {@link HostedWorldStore} per hosted world, called once when the world host session is created. Structural — a SQL, file, or Convex-backed store all conform without `node` importing a concrete driver; only a `store()` factory is required. Mirrors `HostPersistence` (the reducer host's persistence seam).
|
|
272
|
+
- `WorldPersistenceKey` (interface): interface WorldPersistenceKey — Per-world key a {@link WorldPersistence} resolves a {@link HostedWorldStore} for.
|
|
273
|
+
- `attachGameSocketIoServer` (function): function attachGameSocketIoServer(options: GameSocketIoServerOptions): GameSocketIoServer — ⚠ undocumented
|
|
274
|
+
- `clearFilePersistence` (function): function clearFilePersistence(dir: string): Promise<void> — ⚠ undocumented
|
|
275
|
+
- `createGameHost` (function): function createGameHost(options: GameHostOptions): GameHost — Creates a `GameHost` that runs game servers over the given persistence and runtimes.
|
|
276
|
+
- `createGameWsServer` (function): function createGameWsServer(options: GameWsServerOptions): GameWsServer — ⚠ undocumented
|
|
277
|
+
- `createWorldGameServer` (function): function createWorldGameServer(options: WorldGameServerOptions): WorldGameServer — Build a {@link WorldGameServer} — one process hosting authoritative GameContext worlds over ws, ready for two-client play once {@link WorldGameServer.start} runs.
|
|
278
|
+
- `filePersistence` (function): function filePersistence(dir: string, now: () => number = Date.now): HostPersistence — ⚠ undocumented
|
|
279
|
+
- `installShutdownHook` (function): function installShutdownHook(shutdown: () => Promise<void> | void, options: InstallShutdownHookOptions = {}): ShutdownHook — Wires `SIGINT`/`SIGTERM` (or a custom signal list) to a clean-shutdown callback — e.g. `() => worldServer.close()` or `() => Promise.all([wsServer.close(), host.stop()])`. Bounded by `timeoutMs` so a stuck flush can't hang the process forever; idempotent — a second signal delivered mid-shutdown reuses the same in-flight run instead of flushing twice. Returns a {@link ShutdownHook} whose `remove()` uninstalls the listeners, for tests and embedders that want their own handling.
|
|
280
|
+
- `memoryPersistence` (function): function memoryPersistence(now?: () => number): HostPersistence — Creates an in-memory `HostPersistence` implementation, useful for tests and ephemeral hosts.
|
|
281
|
+
- `memoryWorldPersistence` (function): function memoryWorldPersistence(): WorldPersistence — Default {@link WorldPersistence}: an isolated in-memory {@link HostedWorldStore} per `gameId`/`serverId`, lost on process exit.
|
|
282
|
+
- `toNodeHandler` (function): function toNodeHandler(handler: WebHandler): NodeHandler — ⚠ undocumented
|
|
283
|
+
- `toWebRequest` (function): function toWebRequest(req: IncomingMessage): Promise<Request> — ⚠ undocumented
|
|
284
|
+
|
|
285
|
+
## @jgengine/node/devSavePlugin
|
|
286
|
+
|
|
287
|
+
- `EDITOR_SCENE_FILENAME` (const): const EDITOR_SCENE_FILENAME: "editor.scene.json" — Filename editor scene documents are saved under inside a game's `src/`.
|
|
288
|
+
- `SAVE_ENDPOINT_PATH` (const): const SAVE_ENDPOINT_PATH: "/__jgengine/save" — Route the dev save middleware answers on; matches `installSaveEndpoint` defaults.
|
|
289
|
+
- `devSavePlugin` (function): function devSavePlugin(resolveSrcDir: SrcDirResolver): DevSavePluginShape — Dev-only Vite middleware that gives the F2 chord family its write path: editor mode's Save (Ctrl+S / `save_scene`) writes `editor.scene.json` and debug mode's Tune "Save to source" rewrites tunable literals, both into the directory `resolveSrcDir(gameId)` returns.
|
|
290
|
+
- `handleSaveRequest` (function): function handleSaveRequest(resolveSrcDir: SrcDirResolver, body: string): SaveEndpointResponse — Applies one parsed save request against a resolved game `src/` directory.
|
|
291
|
+
- `standaloneSavePlugin` (function): function standaloneSavePlugin(rootDir: string = process.cwd()): DevSavePluginShape — `devSavePlugin` preset for a standalone game project (one game, `src/` at the project root): every gameId maps to `<rootDir>/src`. Drop into the scaffolded `vite.config.ts` plugins array.
|
|
292
|
+
|
|
293
|
+
## @jgengine/node/editorHostPlugin
|
|
294
|
+
|
|
295
|
+
- `EditorHostOptions` (interface): interface EditorHostOptions — Where the standalone editor reads and writes: the scene folder and the model folder it scans.
|
|
296
|
+
- `EditorManifest` (interface): interface EditorManifest — What the standalone editor loads on boot: the on-disk scene document (if any) and every model in the asset folder.
|
|
297
|
+
- `EditorManifestAsset` (interface): interface EditorManifestAsset — One placeable model the standalone editor lists — a stable id and a URL the dev server serves it from.
|
|
298
|
+
|
|
299
|
+
## @jgengine/node/host
|
|
300
|
+
|
|
301
|
+
- `GameHost` (type): type GameHost = { joinServer: (args: { userId: string; gameId: string; serverId?: string; attributes?: SessionAttributes; code?: string; }) => Promise<JoinServerResult>; browseServers: (args: { gameId: string; filter?: MatchFilter; limit?: number; }) => Promise<SessionListing[]>; joinByCode: (args: … — A transport-agnostic authoritative game server host that manages sessions, ticking, and persistence.
|
|
302
|
+
- `GameHostOptions` (type): type GameHostOptions = { runtimes?: GameRuntime[]; persistence: HostPersistence; tickMs?: number; slotsPerServer?: number; now?: () => number; createServerId?: () => string; allowedFeedActions?: readonly string[]; } — Configuration for {@link createGameHost}, including persistence, tick rate, and game runtimes.
|
|
303
|
+
- `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 `GameHost` for a server, player, or feed mutation.
|
|
304
|
+
- `createGameHost` (function): function createGameHost(options: GameHostOptions): GameHost — Creates a `GameHost` that runs game servers over the given persistence and runtimes.
|
|
305
|
+
- `memoryPersistence` (function): function memoryPersistence(now?: () => number): HostPersistence — Creates an in-memory `HostPersistence` implementation, useful for tests and ephemeral hosts.
|
|
306
|
+
|
|
307
|
+
## @jgengine/node/persistence
|
|
308
|
+
|
|
309
|
+
- `WorldPersistence` (interface): interface WorldPersistence — The persistence plug-point for {@link createWorldGameServer}: resolves one {@link HostedWorldStore} per hosted world, called once when the world host session is created. Structural — a SQL, file, or Convex-backed store all conform without `node` importing a concrete driver; only a `store()` factory is required. Mirrors `HostPersistence` (the reducer host's persistence seam).
|
|
310
|
+
- `WorldPersistenceKey` (interface): interface WorldPersistenceKey — Per-world key a {@link WorldPersistence} resolves a {@link HostedWorldStore} for.
|
|
311
|
+
- `clearFilePersistence` (function): function clearFilePersistence(dir: string): Promise<void> — ⚠ undocumented
|
|
312
|
+
- `filePersistence` (function): function filePersistence(dir: string, now: () => number = Date.now): HostPersistence — ⚠ undocumented
|
|
313
|
+
- `memoryPersistence` (function): function memoryPersistence(now?: () => number): HostPersistence — Creates an in-memory `HostPersistence` implementation, useful for tests and ephemeral hosts.
|
|
314
|
+
- `memoryWorldPersistence` (function): function memoryWorldPersistence(): WorldPersistence — Default {@link WorldPersistence}: an isolated in-memory {@link HostedWorldStore} per `gameId`/`serverId`, lost on process exit.
|
|
315
|
+
|
|
316
|
+
## @jgengine/node/shutdown
|
|
317
|
+
|
|
318
|
+
- `InstallShutdownHookOptions` (interface): interface InstallShutdownHookOptions — Config for {@link installShutdownHook}.
|
|
319
|
+
- `ShutdownHook` (interface): interface ShutdownHook — A live signal listener installed by {@link installShutdownHook}; call `remove()` to uninstall it (tests, embedders opting out).
|
|
320
|
+
- `installShutdownHook` (function): function installShutdownHook(shutdown: () => Promise<void> | void, options: InstallShutdownHookOptions = {}): ShutdownHook — Wires `SIGINT`/`SIGTERM` (or a custom signal list) to a clean-shutdown callback — e.g. `() => worldServer.close()` or `() => Promise.all([wsServer.close(), host.stop()])`. Bounded by `timeoutMs` so a stuck flush can't hang the process forever; idempotent — a second signal delivered mid-shutdown reuses the same in-flight run instead of flushing twice. Returns a {@link ShutdownHook} whose `remove()` uninstalls the listeners, for tests and embedders that want their own handling.
|
|
321
|
+
|
|
322
|
+
## @jgengine/node/socketIoServer
|
|
323
|
+
|
|
324
|
+
- `GameSocketIoServer` (type): type GameSocketIoServer = { rewind: (args: { serverId: string; atMs: number }) => RewoundPosition[]; close: () => void; } — ⚠ undocumented
|
|
325
|
+
- `GameSocketIoServerOptions` (type): type GameSocketIoServerOptions = HostRouterOptions & { io: SocketIoLikeServer } — ⚠ undocumented
|
|
326
|
+
- `RewoundPosition` (type): type RewoundPosition = { userId: string; x: number; y: number; z: number; } — A player's interpolated position sampled from history at a past timestamp.
|
|
327
|
+
- `SocketIoLikeServer` (type): type SocketIoLikeServer = { on: (event: "connection", listener: (socket: SocketIoLikeServerSocket) => void) => unknown; } — ⚠ undocumented
|
|
328
|
+
- `SocketIoLikeServerSocket` (type): type SocketIoLikeServerSocket = { on: (event: string, listener: (payload: string) => void) => unknown; send: (data: string) => unknown; disconnect: (close?: boolean) => unknown; } — ⚠ undocumented
|
|
329
|
+
- `attachGameSocketIoServer` (function): function attachGameSocketIoServer(options: GameSocketIoServerOptions): GameSocketIoServer — ⚠ undocumented
|
|
330
|
+
|
|
331
|
+
## @jgengine/node/testFixtures
|
|
332
|
+
|
|
333
|
+
- `createChunkTestRuntime` (function): function createChunkTestRuntime(gameId = "chunk-game"): GameRuntime — ⚠ undocumented
|
|
334
|
+
- `createTestRuntime` (function): function createTestRuntime(gameId = "test-game"): GameRuntime — ⚠ undocumented
|
|
335
|
+
|
|
336
|
+
## @jgengine/node/webHandler
|
|
337
|
+
|
|
338
|
+
- `NodeHandler` (type): type NodeHandler = (req: IncomingMessage, res: ServerResponse) => void — ⚠ undocumented
|
|
339
|
+
- `WebHandler` (type): type WebHandler = (request: Request) => Promise<Response> — ⚠ undocumented
|
|
340
|
+
- `toNodeHandler` (function): function toNodeHandler(handler: WebHandler): NodeHandler — ⚠ undocumented
|
|
341
|
+
- `toWebRequest` (function): function toWebRequest(req: IncomingMessage): Promise<Request> — ⚠ undocumented
|
|
342
|
+
|
|
343
|
+
## @jgengine/node/worldServer
|
|
344
|
+
|
|
345
|
+
- `HostedGameDefinition` (interface): interface HostedGameDefinition — A game the world server can host — its authoritative {@link GameDefinition} and the content lookup a `GameContext` reads.
|
|
346
|
+
- `WorldGameServer` (interface): interface WorldGameServer — A runnable ws host for GameContext worlds: {@link createWorldGameHost} + {@link createGameWsServer} + a tick loop, with a manual `tick(dt)` seam so a fake clock can drive it in tests.
|
|
347
|
+
- `WorldGameServerOptions` (interface): interface WorldGameServerOptions extends Omit<GameWsServerOptions, "host"> — Config for {@link createWorldGameServer}: how to resolve a game by id, the tick cadence, and the underlying ws-server/router options (minus `host`, which the server builds).
|
|
348
|
+
- `createWorldGameServer` (function): function createWorldGameServer(options: WorldGameServerOptions): WorldGameServer — Build a {@link WorldGameServer} — one process hosting authoritative GameContext worlds over ws, ready for two-client play once {@link WorldGameServer.start} runs.
|
|
349
|
+
|
|
350
|
+
## @jgengine/node/wsServer
|
|
351
|
+
|
|
352
|
+
- `DEFAULT_HEARTBEAT_INTERVAL_MS` (const): const DEFAULT_HEARTBEAT_INTERVAL_MS: 30000 — Default ping/pong interval; a socket that misses one round-trip is terminated.
|
|
353
|
+
- `DEFAULT_MAX_CONNECTIONS` (const): const DEFAULT_MAX_CONNECTIONS: 10000 — Default max concurrent sockets this server accepts before rejecting new ones.
|
|
354
|
+
- `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.
|
|
355
|
+
- `GameWsServer` (type): type GameWsServer = { wss: WebSocketServer; port: () => number; rewind: (args: { serverId: string; atMs: number }) => RewoundPosition[]; close: () => Promise<void>; } — ⚠ undocumented
|
|
356
|
+
- `GameWsServerOptions` (type): type GameWsServerOptions = HostRouterOptions & { server?: HttpServer; port?: number; path?: string; /** Per-message payload cap in bytes. Defaults to {@link DEFAULT_MAX_PAYLOAD_BYTES}. */ maxPayloadBytes?: number; /** Max concurrent sockets accepted; connections beyond this are closed immediately. D… — ⚠ undocumented
|
|
357
|
+
- `RewoundPosition` (type): type RewoundPosition = { userId: string; x: number; y: number; z: number; } — A player's interpolated position sampled from history at a past timestamp.
|
|
358
|
+
- `createGameWsServer` (function): function createGameWsServer(options: GameWsServerOptions): GameWsServer — ⚠ undocumented
|
|
359
|
+
|
|
360
|
+
## @jgengine/sql
|
|
361
|
+
|
|
362
|
+
- `SqlPool` (type): type SqlPool = SqlQueryable & { connect: () => Promise<SqlPoolClient>; } — ⚠ undocumented
|
|
363
|
+
- `SqlPoolClient` (type): type SqlPoolClient = SqlQueryable & { release: () => void; } — ⚠ undocumented
|
|
364
|
+
- `SqlQueryResult` (type): type SqlQueryResult = { rows: Record<string, unknown>[] } — ⚠ undocumented
|
|
365
|
+
- `SqlQueryable` (type): type SqlQueryable = { query: (text: string, params?: unknown[]) => Promise<SqlQueryResult>; } — ⚠ undocumented
|
|
366
|
+
- `ensureSchema` (function): function ensureSchema(pool: SqlQueryable): Promise<void> — ⚠ undocumented
|
|
367
|
+
- `sqlPersistence` (function): function sqlPersistence(pool: SqlPool, now: () => number = Date.now): HostPersistence — ⚠ undocumented
|
|
368
|
+
|
|
369
|
+
## @jgengine/sql/sqlPersistence
|
|
370
|
+
|
|
371
|
+
- `SqlPool` (type): type SqlPool = SqlQueryable & { connect: () => Promise<SqlPoolClient>; } — ⚠ undocumented
|
|
372
|
+
- `SqlPoolClient` (type): type SqlPoolClient = SqlQueryable & { release: () => void; } — ⚠ undocumented
|
|
373
|
+
- `SqlQueryResult` (type): type SqlQueryResult = { rows: Record<string, unknown>[] } — ⚠ undocumented
|
|
374
|
+
- `SqlQueryable` (type): type SqlQueryable = { query: (text: string, params?: unknown[]) => Promise<SqlQueryResult>; } — ⚠ undocumented
|
|
375
|
+
- `ensureSchema` (function): function ensureSchema(pool: SqlQueryable): Promise<void> — ⚠ undocumented
|
|
376
|
+
- `sqlPersistence` (function): function sqlPersistence(pool: SqlPool, now: () => number = Date.now): HostPersistence — ⚠ undocumented
|
|
377
|
+
|
|
378
|
+
## @jgengine/ws
|
|
379
|
+
|
|
380
|
+
- `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.
|
|
381
|
+
- `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.
|
|
382
|
+
- `CommandCatalogEntry` (type): type CommandCatalogEntry = { validate?: (input: unknown) => CommandRejection | null; } — A declared `runCommand` name's input validator, run before the command reaches the game host.
|
|
383
|
+
- `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.
|
|
384
|
+
- `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.
|
|
385
|
+
- `CommandLimits` (type): type CommandLimits = Partial<Record<HostCommandOp, CommandRateLimit>> — Per-op rate limits. An op with no entry (or an undefined `limits`) is unlimited.
|
|
386
|
+
- `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.
|
|
387
|
+
- `CommandMiddlewareOptions` (type): type CommandMiddlewareOptions = { limits?: CommandLimits; authorize?: CommandAuthorize; validate?: CommandCatalog; } — Config for {@link createCommandMiddleware}: the same `limits`/`authorize`/`validate` fields accepted by `HostRouterOptions`.
|
|
388
|
+
- `CommandRateLimit` (type): type CommandRateLimit = { count: number; perMs: number } — A sliding-window rate limit: at most `count` calls per `perMs` window.
|
|
389
|
+
- `CommandRateLimiter` (type): type CommandRateLimiter = { allow: (connection: object, op: HostCommandOp, atMs: number) => boolean; } — A composable per-connection/per-op sliding-window rate limiter.
|
|
390
|
+
- `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.
|
|
391
|
+
- `DEFAULT_POSE_RULES` (const): const DEFAULT_POSE_RULES: PoseSyncRules — ⚠ undocumented
|
|
392
|
+
- `GameHost` (type): type GameHost = { joinServer: (args: { userId: string; gameId: string; serverId?: string; attributes?: SessionAttributes; code?: string; }) => Promise<JoinServerResult>; browseServers: (args: { gameId: string; filter?: MatchFilter; limit?: number; }) => Promise<SessionListing[]>; joinByCode: (args: … — A transport-agnostic authoritative game server host that manages sessions, ticking, and persistence.
|
|
393
|
+
- `GameHostOptions` (type): type GameHostOptions = { runtimes?: GameRuntime[]; persistence: HostPersistence; tickMs?: number; slotsPerServer?: number; now?: () => number; createServerId?: () => string; allowedFeedActions?: readonly string[]; } — Configuration for {@link createGameHost}, including persistence, tick rate, and game runtimes.
|
|
394
|
+
- `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 `GameHost` for a server, player, or feed mutation.
|
|
395
|
+
- `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.
|
|
396
|
+
- `HostRouter` (type): type HostRouter = { connect: (transport: HostRouterTransport) => HostRouterConnection; rewind: (args: { serverId: string; atMs: number }) => RewoundPosition[]; close: () => void; } — ⚠ undocumented
|
|
397
|
+
- `HostRouterAuthenticate` (type): type HostRouterAuthenticate = (args: { userId: string; token?: string; }) => Promise<string | null> | string | null — ⚠ undocumented
|
|
398
|
+
- `HostRouterConnection` (type): type HostRouterConnection = { handleRaw: (raw: unknown) => void; close: () => void; } — ⚠ undocumented
|
|
399
|
+
- `HostRouterOptions` (type): type HostRouterOptions = { host: GameHost; authenticate?: HostRouterAuthenticate; allowAnonymous?: boolean; singleSession?: boolean; poseRules?: PoseSyncRules; positionHistoryMs?: number; chatRateLimit?: ChatRateLimit; chatHistoryLimit?: number; chatMaxBodyLength?: number; /** Per-op rate limits for… — ⚠ undocumented
|
|
400
|
+
- `HostRouterTransport` (type): type HostRouterTransport = { send: (data: string) => void; close: () => void; } — ⚠ undocumented
|
|
401
|
+
- `HttpReads` (type): type HttpReads = { getTop: (args: { stat: string; scope: LeaderboardScope; serverId?: string; limit?: number; }) => Promise<LeaderboardEntry[]>; getLeaderboardProfile: (userId: string) => Promise<Record<string, number>>; getPlayerProfile: (userId: string) => Promise<GameRuntimePlayerView | null>; li… — ⚠ undocumented
|
|
402
|
+
- `HttpReadsOptions` (type): type HttpReadsOptions = { baseUrl: string; gameId: string; fetchImpl?: typeof fetch; } — ⚠ undocumented
|
|
403
|
+
- `MAX_APPEARANCE_ENTRIES` (const): const MAX_APPEARANCE_ENTRIES: 32 — Max number of keys in a pose `appearance` tag map.
|
|
404
|
+
- `MAX_APPEARANCE_VALUE_LENGTH` (const): const MAX_APPEARANCE_VALUE_LENGTH: 256 — Max length of a single `appearance` tag string value, in UTF-16 code units.
|
|
405
|
+
- `MAX_COMMAND_LENGTH` (const): const MAX_COMMAND_LENGTH: 4096 — Max length of a `runCommand` command name, in UTF-16 code units.
|
|
406
|
+
- `MAX_FEED_ACTION_LENGTH` (const): const MAX_FEED_ACTION_LENGTH: 256 — Max length of a `pushFeed` action name, in UTF-16 code units.
|
|
407
|
+
- `MAX_FEED_ENTRY_BYTES` (const): const MAX_FEED_ENTRY_BYTES: 65536 — Max serialized size of a `pushFeed` entry payload, in bytes.
|
|
408
|
+
- `MAX_QUEUED_MESSAGES` (const): const MAX_QUEUED_MESSAGES: 64 — Cap on frames queued behind a connection's in-flight message; beyond this a flood gets rejected instead of piling up unbounded promises.
|
|
409
|
+
- `OP_LEDGER_LIMIT` (const): const OP_LEDGER_LIMIT: 64 — Max recently-applied `runCommand` op IDs retained per (serverId, userId), oldest evicted first.
|
|
410
|
+
- `PeerGuest` (type): type PeerGuest = { backend: WsBackend; offer: () => Promise<string>; connect: (answerCode: string) => Promise<void>; close: () => void; } — ⚠ undocumented
|
|
411
|
+
- `PeerGuestOptions` (type): type PeerGuestOptions = { userId: string; token?: string; rtc?: PeerRtcOptions; } — ⚠ undocumented
|
|
412
|
+
- `PeerHost` (type): type PeerHost = { backend: WsBackend; host: GameHost; router: HostRouter; accept: (offerCode: string) => Promise<string>; close: () => void; } — ⚠ undocumented
|
|
413
|
+
- `PeerHostOptions` (type): type PeerHostOptions = { userId: string; token?: string; host?: GameHost; runtimes?: GameRuntime[]; persistence?: HostPersistence; tickMs?: number; router?: Omit<HostRouterOptions, "host">; rtc?: PeerRtcOptions; } — ⚠ undocumented
|
|
414
|
+
- `PeerRtcOptions` (type): type PeerRtcOptions = { configuration?: RTCConfiguration; iceGatherTimeoutMs?: number; } — ⚠ undocumented
|
|
415
|
+
- `PeerSignalPayload` (type): type PeerSignalPayload = { type: "offer" | "answer"; sdp: string } — ⚠ undocumented
|
|
416
|
+
- `PeerSignaling` (type): type PeerSignaling = { publishOffer: (offerCode: string) => Promise<string>; onOffer: (answer: (offerCode: string) => Promise<string>) => () => void; close: () => void; } — ⚠ undocumented
|
|
417
|
+
- `ReadsAuthenticate` (type): type ReadsAuthenticate = ( request: Request, ) => Promise<string | null> | string | null — ⚠ undocumented
|
|
418
|
+
- `ReadsHandler` (type): type ReadsHandler = (request: Request) => Promise<Response> — ⚠ undocumented
|
|
419
|
+
- `ReadsHandlerOptions` (type): type ReadsHandlerOptions = { persistence: ReadsPersistence | (() => Promise<ReadsPersistence>); basePath?: string; listOpenServers?: (args: { gameId: string; limit?: number }) => Promise<ServerListing[]>; authenticate?: ReadsAuthenticate; allowPublicProfiles?: boolean; } — ⚠ undocumented
|
|
420
|
+
- `ReadsPersistence` (type): type ReadsPersistence = Pick< HostPersistence, "listServers" | "loadProfile" | "getLeaderboardTop" | "getLeaderboardProfile" > — ⚠ undocumented
|
|
421
|
+
- `RewoundPosition` (type): type RewoundPosition = { userId: string; x: number; y: number; z: number; } — A player's interpolated position sampled from history at a past timestamp.
|
|
422
|
+
- `SocketIoBackendOptions` (type): type SocketIoBackendOptions = Omit<WsBackendOptions, "url" | "pipe" | "webSocketFactory"> & { socket: SocketIoLikeSocket; } — ⚠ undocumented
|
|
423
|
+
- `SocketIoLikeSocket` (type): type SocketIoLikeSocket = { connected: boolean; on: (event: string, listener: (payload: string) => void) => unknown; off: (event: string, listener: (payload: string) => void) => unknown; send: (data: string) => unknown; disconnect: () => unknown; } — ⚠ undocumented
|
|
424
|
+
- `TransportPipe` (type): type TransportPipe = { send: (data: string) => void; close: () => void; } — ⚠ undocumented
|
|
425
|
+
- `TransportPipeFactory` (type): type TransportPipeFactory = (handlers: TransportPipeHandlers) => TransportPipe — ⚠ undocumented
|
|
426
|
+
- `TransportPipeHandlers` (type): type TransportPipeHandlers = { onOpen: () => void; onMessage: (data: string) => void; onClose: () => void; } — ⚠ undocumented
|
|
427
|
+
- `VoiceChannelDef` (interface): interface VoiceChannelDef — ⚠ undocumented
|
|
428
|
+
- `VoiceChannelId` (type): type VoiceChannelId = string — ⚠ undocumented
|
|
429
|
+
- `VoiceChannelRouter` (interface): interface VoiceChannelRouter — ⚠ undocumented
|
|
430
|
+
- `VoiceMemberId` (type): type VoiceMemberId = string — ⚠ undocumented
|
|
431
|
+
- `VoicePosition` (interface): interface VoicePosition — ⚠ undocumented
|
|
432
|
+
- `VoiceRoute` (interface): interface VoiceRoute — ⚠ undocumented
|
|
433
|
+
- `WS_PROTOCOL_VERSION` (const): const WS_PROTOCOL_VERSION: 1 — ⚠ undocumented
|
|
434
|
+
- `WorldGameHost` (interface): interface WorldGameHost extends GameHost — A {@link GameHost} whose worlds run on `HostedWorldSession`s; `tick` advances them and re-broadcasts on change.
|
|
435
|
+
- `WorldGameHostOptions` (interface): interface WorldGameHostOptions — Config for {@link createWorldGameHost}: how to resolve a hosted world's authoritative session per server.
|
|
436
|
+
- `WsAppearance` (type): type WsAppearance = Record<string, string | number | boolean> — Client-set cosmetic/state tags carried alongside a pose (skin, mount, emote, ...). Primitive values only.
|
|
437
|
+
- `WsBackend` (type): type WsBackend = GameBackend & { pushFeedEntry: (args: { serverId: string; action: string; entry: unknown }) => Promise<void>; browse: (args: { gameId: string; filter?: MatchFilter; limit?: number }) => Promise<SessionListing[]>; joinByCode: (args: { gameId: string; code: string }) => Promise<JoinSe… — ⚠ undocumented
|
|
438
|
+
- `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; setTimeoutFn?: typeof s… — ⚠ undocumented
|
|
439
|
+
- `WsBrowseResult` (type): type WsBrowseResult = SessionListing[] — ⚠ undocumented
|
|
440
|
+
- `WsChannel` (type): type WsChannel = "server" | "player" | "feed" | "presence" | "chat" | "voice" — ⚠ undocumented
|
|
441
|
+
- `WsChatMessage` (type): type WsChatMessage = { id: string; channelId: string; fromUserId: string; body: string; at: number; } — ⚠ undocumented
|
|
442
|
+
- `WsChatSync` (type): type WsChatSync = { subscribe: ( serverId: string, channelId: string, onChange: (messages: WsChatMessage[]) => void, ) => () => void; send: (serverId: string, channelId: string, body: string) => Promise<ChatSendOutcome>; } — ⚠ undocumented
|
|
443
|
+
- `WsClientMessage` (type): type WsClientMessage = | { v: 1; t: "hello"; id: number; userId: string; token?: string } | { v: 1; t: "join"; id: number; gameId: string; serverId?: string; attributes?: SessionAttributes; code?: string; } | { v: 1; t: "joinByCode"; id: number; gameId: string; code: string } | { v: 1; t: "browse"; … — ⚠ undocumented
|
|
444
|
+
- `WsDecodeFailure` (type): type WsDecodeFailure = { reason: string; id?: number; } — ⚠ undocumented
|
|
445
|
+
- `WsJoinByCodeResult` (type): type WsJoinByCodeResult = JoinServerResult | null — ⚠ undocumented
|
|
446
|
+
- `WsJoinResult` (type): type WsJoinResult = JoinServerResult — ⚠ undocumented
|
|
447
|
+
- `WsPose` (type): type WsPose = PlayerPose & { appearance?: WsAppearance } — ⚠ undocumented
|
|
448
|
+
- `WsPresenceRow` (type): type WsPresenceRow = PresencePoseRow & { appearance?: WsAppearance } — ⚠ undocumented
|
|
449
|
+
- `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
|
|
450
|
+
- `WsRunCommandResult` (type): type WsRunCommandResult = TransportRunCommandResult — ⚠ undocumented
|
|
451
|
+
- `WsServerMessage` (type): type WsServerMessage = | { v: 1; t: "reply"; id: number; ok: true; result?: unknown } | { v: 1; t: "reply"; id: number; ok: false; reason: string } | WsUpdateMessage — ⚠ undocumented
|
|
452
|
+
- `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
|
|
453
|
+
- `WsVoiceParticipant` (type): type WsVoiceParticipant = { userId: string; streamId?: string; } — ⚠ undocumented
|
|
454
|
+
- `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
|
|
455
|
+
- `announcePeerHost` (function): function announcePeerHost(host: PeerHost, signaling: PeerSignaling): () => void — ⚠ undocumented
|
|
456
|
+
- `broadcastChannelSignaling` (function): function broadcastChannelSignaling(room: string): PeerSignaling — ⚠ undocumented
|
|
457
|
+
- `computeVoiceGain` (function): function computeVoiceGain(def: VoiceChannelDef, distance: number | null): number — ⚠ undocumented
|
|
458
|
+
- `createCommandMiddleware` (function): function createCommandMiddleware(options: CommandMiddlewareOptions): CommandMiddleware — Builds the composed command middleware pipeline from game-intent config: `limits`, `validate`, `authorize`.
|
|
459
|
+
- `createCommandRateLimiter` (function): function createCommandRateLimiter(limits: CommandLimits): CommandRateLimiter — Creates a sliding-window rate limiter keyed by connection identity and op; ops absent from `limits` are always allowed.
|
|
460
|
+
- `createGameHost` (function): function createGameHost(options: GameHostOptions): GameHost — Creates a `GameHost` that runs game servers over the given persistence and runtimes.
|
|
461
|
+
- `createHostRouter` (function): function createHostRouter(options: HostRouterOptions): HostRouter — ⚠ undocumented
|
|
462
|
+
- `createHttpReads` (function): function createHttpReads(options: HttpReadsOptions): HttpReads — ⚠ undocumented
|
|
463
|
+
- `createPeerGuest` (function): function createPeerGuest(options: PeerGuestOptions): PeerGuest — ⚠ undocumented
|
|
464
|
+
- `createPeerHost` (function): function createPeerHost(options: PeerHostOptions): PeerHost — ⚠ undocumented
|
|
465
|
+
- `createReadsHandler` (function): function createReadsHandler(options: ReadsHandlerOptions): ReadsHandler — ⚠ undocumented
|
|
466
|
+
- `createSocketIoBackend` (function): function createSocketIoBackend(options: SocketIoBackendOptions): WsBackend — ⚠ undocumented
|
|
467
|
+
- `createVoiceChannelRouter` (function): function createVoiceChannelRouter(channels?: readonly VoiceChannelDef[]): VoiceChannelRouter — ⚠ undocumented
|
|
468
|
+
- `createWorldGameHost` (function): function createWorldGameHost(options: WorldGameHostOptions): WorldGameHost — The GameContext-loop counterpart of the reducer `createGameHost`: a structural {@link GameHost} that serves each world's full `WorldSnapshot` as `serverState`, so the existing ws router, `createWsBackend`, and the shell's `attachWorldSync` carry host-authoritative GameContext worlds with zero changes to any of them. The harness owns the tick cadence (call {@link WorldGameHost.tick} on an interval); commands and joins broadcast immediately.
|
|
469
|
+
- `createWsBackend` (function): function createWsBackend(options: WsBackendOptions): WsBackend — ⚠ undocumented
|
|
470
|
+
- `decodePeerSignal` (function): function decodePeerSignal(code: string): PeerSignalPayload | null — ⚠ undocumented
|
|
471
|
+
- `encodePeerSignal` (function): function encodePeerSignal(payload: PeerSignalPayload): string — ⚠ undocumented
|
|
472
|
+
- `joinPeerSession` (function): function joinPeerSession(guest: PeerGuest, signaling: PeerSignaling): Promise<WsBackend> — ⚠ undocumented
|
|
473
|
+
- `loopbackPipe` (function): function loopbackPipe(router: HostRouter): TransportPipeFactory — ⚠ undocumented
|
|
474
|
+
- `memoryPersistence` (function): function memoryPersistence(now: () => number = Date.now): HostPersistence — Creates an in-memory `HostPersistence` implementation, useful for tests and ephemeral hosts.
|
|
475
|
+
- `socketIoPipe` (function): function socketIoPipe(socket: SocketIoLikeSocket): TransportPipeFactory — ⚠ undocumented
|
|
476
|
+
- `validateCommandInput` (function): function validateCommandInput(catalog: CommandCatalog | undefined, command: string, input: unknown): CommandRejection | null — Validates a `runCommand` input against a declared catalog. `undefined` catalog means "no declarations" — everything passes through unchanged.
|
|
477
|
+
- `webSocketPipe` (function): function webSocketPipe(url: string, webSocketFactory: (url: string) => WebSocket = (target) => new WebSocket(target)): TransportPipeFactory — ⚠ undocumented
|
|
478
|
+
|
|
479
|
+
## @jgengine/ws/commandMiddleware
|
|
480
|
+
|
|
481
|
+
- `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.
|
|
482
|
+
- `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.
|
|
483
|
+
- `CommandCatalogEntry` (type): type CommandCatalogEntry = { validate?: (input: unknown) => CommandRejection | null; } — A declared `runCommand` name's input validator, run before the command reaches the game host.
|
|
484
|
+
- `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.
|
|
485
|
+
- `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.
|
|
486
|
+
- `CommandLimits` (type): type CommandLimits = Partial<Record<HostCommandOp, CommandRateLimit>> — Per-op rate limits. An op with no entry (or an undefined `limits`) is unlimited.
|
|
487
|
+
- `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.
|
|
488
|
+
- `CommandMiddlewareOptions` (type): type CommandMiddlewareOptions = { limits?: CommandLimits; authorize?: CommandAuthorize; validate?: CommandCatalog; } — Config for {@link createCommandMiddleware}: the same `limits`/`authorize`/`validate` fields accepted by `HostRouterOptions`.
|
|
489
|
+
- `CommandRateLimit` (type): type CommandRateLimit = { count: number; perMs: number } — A sliding-window rate limit: at most `count` calls per `perMs` window.
|
|
490
|
+
- `CommandRateLimiter` (type): type CommandRateLimiter = { allow: (connection: object, op: HostCommandOp, atMs: number) => boolean; } — A composable per-connection/per-op sliding-window rate limiter.
|
|
491
|
+
- `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.
|
|
492
|
+
- `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.
|
|
493
|
+
- `createCommandMiddleware` (function): function createCommandMiddleware(options: CommandMiddlewareOptions): CommandMiddleware — Builds the composed command middleware pipeline from game-intent config: `limits`, `validate`, `authorize`.
|
|
494
|
+
- `createCommandRateLimiter` (function): function createCommandRateLimiter(limits: CommandLimits): CommandRateLimiter — Creates a sliding-window rate limiter keyed by connection identity and op; ops absent from `limits` are always allowed.
|
|
495
|
+
- `validateCommandInput` (function): function validateCommandInput(catalog: CommandCatalog | undefined, command: string, input: unknown): CommandRejection | null — Validates a `runCommand` input against a declared catalog. `undefined` catalog means "no declarations" — everything passes through unchanged.
|
|
496
|
+
|
|
497
|
+
## @jgengine/ws/createWsBackend
|
|
498
|
+
|
|
499
|
+
- `WsBackend` (type): type WsBackend = GameBackend & { pushFeedEntry: (args: { serverId: string; action: string; entry: unknown }) => Promise<void>; browse: (args: { gameId: string; filter?: MatchFilter; limit?: number }) => Promise<SessionListing[]>; joinByCode: (args: { gameId: string; code: string }) => Promise<JoinSe… — ⚠ undocumented
|
|
500
|
+
- `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; setTimeoutFn?: typeof s… — ⚠ undocumented
|
|
501
|
+
- `WsChatSync` (type): type WsChatSync = { subscribe: ( serverId: string, channelId: string, onChange: (messages: WsChatMessage[]) => void, ) => () => void; send: (serverId: string, channelId: string, body: string) => Promise<ChatSendOutcome>; } — ⚠ undocumented
|
|
502
|
+
- `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
|
|
503
|
+
- `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
|
|
504
|
+
- `createWsBackend` (function): function createWsBackend(options: WsBackendOptions): WsBackend — ⚠ undocumented
|
|
505
|
+
|
|
506
|
+
## @jgengine/ws/host
|
|
507
|
+
|
|
508
|
+
- `GameHost` (type): type GameHost = { joinServer: (args: { userId: string; gameId: string; serverId?: string; attributes?: SessionAttributes; code?: string; }) => Promise<JoinServerResult>; browseServers: (args: { gameId: string; filter?: MatchFilter; limit?: number; }) => Promise<SessionListing[]>; joinByCode: (args: … — A transport-agnostic authoritative game server host that manages sessions, ticking, and persistence.
|
|
509
|
+
- `GameHostOptions` (type): type GameHostOptions = { runtimes?: GameRuntime[]; persistence: HostPersistence; tickMs?: number; slotsPerServer?: number; now?: () => number; createServerId?: () => string; allowedFeedActions?: readonly string[]; } — Configuration for {@link createGameHost}, including persistence, tick rate, and game runtimes.
|
|
510
|
+
- `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 `GameHost` for a server, player, or feed mutation.
|
|
511
|
+
- `OP_LEDGER_LIMIT` (const): const OP_LEDGER_LIMIT: 64 — Max recently-applied `runCommand` op IDs retained per (serverId, userId), oldest evicted first.
|
|
512
|
+
- `createGameHost` (function): function createGameHost(options: GameHostOptions): GameHost — Creates a `GameHost` that runs game servers over the given persistence and runtimes.
|
|
513
|
+
- `memoryPersistence` (function): function memoryPersistence(now: () => number = Date.now): HostPersistence — Creates an in-memory `HostPersistence` implementation, useful for tests and ephemeral hosts.
|
|
514
|
+
|
|
515
|
+
## @jgengine/ws/hostRouter
|
|
516
|
+
|
|
517
|
+
- `DEFAULT_POSE_RULES` (const): const DEFAULT_POSE_RULES: PoseSyncRules — ⚠ undocumented
|
|
518
|
+
- `HostRouter` (type): type HostRouter = { connect: (transport: HostRouterTransport) => HostRouterConnection; rewind: (args: { serverId: string; atMs: number }) => RewoundPosition[]; close: () => void; } — ⚠ undocumented
|
|
519
|
+
- `HostRouterAuthenticate` (type): type HostRouterAuthenticate = (args: { userId: string; token?: string; }) => Promise<string | null> | string | null — ⚠ undocumented
|
|
520
|
+
- `HostRouterConnection` (type): type HostRouterConnection = { handleRaw: (raw: unknown) => void; close: () => void; } — ⚠ undocumented
|
|
521
|
+
- `HostRouterOptions` (type): type HostRouterOptions = { host: GameHost; authenticate?: HostRouterAuthenticate; allowAnonymous?: boolean; singleSession?: boolean; poseRules?: PoseSyncRules; positionHistoryMs?: number; chatRateLimit?: ChatRateLimit; chatHistoryLimit?: number; chatMaxBodyLength?: number; /** Per-op rate limits for… — ⚠ undocumented
|
|
522
|
+
- `HostRouterTransport` (type): type HostRouterTransport = { send: (data: string) => void; close: () => void; } — ⚠ undocumented
|
|
523
|
+
- `MAX_QUEUED_MESSAGES` (const): const MAX_QUEUED_MESSAGES: 64 — Cap on frames queued behind a connection's in-flight message; beyond this a flood gets rejected instead of piling up unbounded promises.
|
|
524
|
+
- `RewoundPosition` (type): type RewoundPosition = { userId: string; x: number; y: number; z: number; } — A player's interpolated position sampled from history at a past timestamp.
|
|
525
|
+
- `createHostRouter` (function): function createHostRouter(options: HostRouterOptions): HostRouter — ⚠ undocumented
|
|
526
|
+
- `loopbackPipe` (function): function loopbackPipe(router: HostRouter): TransportPipeFactory — ⚠ undocumented
|
|
527
|
+
|
|
528
|
+
## @jgengine/ws/httpReads
|
|
529
|
+
|
|
530
|
+
- `HttpReads` (type): type HttpReads = { getTop: (args: { stat: string; scope: LeaderboardScope; serverId?: string; limit?: number; }) => Promise<LeaderboardEntry[]>; getLeaderboardProfile: (userId: string) => Promise<Record<string, number>>; getPlayerProfile: (userId: string) => Promise<GameRuntimePlayerView | null>; li… — ⚠ undocumented
|
|
531
|
+
- `HttpReadsOptions` (type): type HttpReadsOptions = { baseUrl: string; gameId: string; fetchImpl?: typeof fetch; } — ⚠ undocumented
|
|
532
|
+
- `createHttpReads` (function): function createHttpReads(options: HttpReadsOptions): HttpReads — ⚠ undocumented
|
|
533
|
+
|
|
534
|
+
## @jgengine/ws/peer
|
|
535
|
+
|
|
536
|
+
- `PeerGuest` (type): type PeerGuest = { backend: WsBackend; offer: () => Promise<string>; connect: (answerCode: string) => Promise<void>; close: () => void; } — ⚠ undocumented
|
|
537
|
+
- `PeerGuestOptions` (type): type PeerGuestOptions = { userId: string; token?: string; rtc?: PeerRtcOptions; } — ⚠ undocumented
|
|
538
|
+
- `PeerHost` (type): type PeerHost = { backend: WsBackend; host: GameHost; router: HostRouter; accept: (offerCode: string) => Promise<string>; close: () => void; } — ⚠ undocumented
|
|
539
|
+
- `PeerHostOptions` (type): type PeerHostOptions = { userId: string; token?: string; host?: GameHost; runtimes?: GameRuntime[]; persistence?: HostPersistence; tickMs?: number; router?: Omit<HostRouterOptions, "host">; rtc?: PeerRtcOptions; } — ⚠ undocumented
|
|
540
|
+
- `PeerRtcOptions` (type): type PeerRtcOptions = { configuration?: RTCConfiguration; iceGatherTimeoutMs?: number; } — ⚠ undocumented
|
|
541
|
+
- `PeerSignalPayload` (type): type PeerSignalPayload = { type: "offer" | "answer"; sdp: string } — ⚠ undocumented
|
|
542
|
+
- `PeerSignaling` (type): type PeerSignaling = { publishOffer: (offerCode: string) => Promise<string>; onOffer: (answer: (offerCode: string) => Promise<string>) => () => void; close: () => void; } — ⚠ undocumented
|
|
543
|
+
- `announcePeerHost` (function): function announcePeerHost(host: PeerHost, signaling: PeerSignaling): () => void — ⚠ undocumented
|
|
544
|
+
- `broadcastChannelSignaling` (function): function broadcastChannelSignaling(room: string): PeerSignaling — ⚠ undocumented
|
|
545
|
+
- `createPeerGuest` (function): function createPeerGuest(options: PeerGuestOptions): PeerGuest — ⚠ undocumented
|
|
546
|
+
- `createPeerHost` (function): function createPeerHost(options: PeerHostOptions): PeerHost — ⚠ undocumented
|
|
547
|
+
- `decodePeerSignal` (function): function decodePeerSignal(code: string): PeerSignalPayload | null — ⚠ undocumented
|
|
548
|
+
- `encodePeerSignal` (function): function encodePeerSignal(payload: PeerSignalPayload): string — ⚠ undocumented
|
|
549
|
+
- `joinPeerSession` (function): function joinPeerSession(guest: PeerGuest, signaling: PeerSignaling): Promise<WsBackend> — ⚠ undocumented
|
|
550
|
+
|
|
551
|
+
## @jgengine/ws/pipe
|
|
552
|
+
|
|
553
|
+
- `TransportPipe` (type): type TransportPipe = { send: (data: string) => void; close: () => void; } — ⚠ undocumented
|
|
554
|
+
- `TransportPipeFactory` (type): type TransportPipeFactory = (handlers: TransportPipeHandlers) => TransportPipe — ⚠ undocumented
|
|
555
|
+
- `TransportPipeHandlers` (type): type TransportPipeHandlers = { onOpen: () => void; onMessage: (data: string) => void; onClose: () => void; } — ⚠ undocumented
|
|
556
|
+
- `webSocketPipe` (function): function webSocketPipe(url: string, webSocketFactory: (url: string) => WebSocket = (target) => new WebSocket(target)): TransportPipeFactory — ⚠ undocumented
|
|
557
|
+
|
|
558
|
+
## @jgengine/ws/protocol
|
|
559
|
+
|
|
560
|
+
- `MAX_APPEARANCE_ENTRIES` (const): const MAX_APPEARANCE_ENTRIES: 32 — Max number of keys in a pose `appearance` tag map.
|
|
561
|
+
- `MAX_APPEARANCE_VALUE_LENGTH` (const): const MAX_APPEARANCE_VALUE_LENGTH: 256 — Max length of a single `appearance` tag string value, in UTF-16 code units.
|
|
562
|
+
- `MAX_COMMAND_LENGTH` (const): const MAX_COMMAND_LENGTH: 4096 — Max length of a `runCommand` command name, in UTF-16 code units.
|
|
563
|
+
- `MAX_FEED_ACTION_LENGTH` (const): const MAX_FEED_ACTION_LENGTH: 256 — Max length of a `pushFeed` action name, in UTF-16 code units.
|
|
564
|
+
- `MAX_FEED_ENTRY_BYTES` (const): const MAX_FEED_ENTRY_BYTES: 65536 — Max serialized size of a `pushFeed` entry payload, in bytes.
|
|
565
|
+
- `WS_PROTOCOL_VERSION` (const): const WS_PROTOCOL_VERSION: 1 — ⚠ undocumented
|
|
566
|
+
- `WsAppearance` (type): type WsAppearance = Record<string, string | number | boolean> — Client-set cosmetic/state tags carried alongside a pose (skin, mount, emote, ...). Primitive values only.
|
|
567
|
+
- `WsBrowseResult` (type): type WsBrowseResult = SessionListing[] — ⚠ undocumented
|
|
568
|
+
- `WsChannel` (type): type WsChannel = "server" | "player" | "feed" | "presence" | "chat" | "voice" — ⚠ undocumented
|
|
569
|
+
- `WsChatMessage` (type): type WsChatMessage = { id: string; channelId: string; fromUserId: string; body: string; at: number; } — ⚠ undocumented
|
|
570
|
+
- `WsClientMessage` (type): type WsClientMessage = | { v: 1; t: "hello"; id: number; userId: string; token?: string } | { v: 1; t: "join"; id: number; gameId: string; serverId?: string; attributes?: SessionAttributes; code?: string; } | { v: 1; t: "joinByCode"; id: number; gameId: string; code: string } | { v: 1; t: "browse"; … — ⚠ undocumented
|
|
571
|
+
- `WsDecodeFailure` (type): type WsDecodeFailure = { reason: string; id?: number; } — ⚠ undocumented
|
|
572
|
+
- `WsJoinByCodeResult` (type): type WsJoinByCodeResult = JoinServerResult | null — ⚠ undocumented
|
|
573
|
+
- `WsJoinResult` (type): type WsJoinResult = JoinServerResult — ⚠ undocumented
|
|
574
|
+
- `WsPose` (type): type WsPose = PlayerPose & { appearance?: WsAppearance } — ⚠ undocumented
|
|
575
|
+
- `WsPresenceRow` (type): type WsPresenceRow = PresencePoseRow & { appearance?: WsAppearance } — ⚠ undocumented
|
|
576
|
+
- `WsRunCommandResult` (type): type WsRunCommandResult = TransportRunCommandResult — ⚠ undocumented
|
|
577
|
+
- `WsServerMessage` (type): type WsServerMessage = | { v: 1; t: "reply"; id: number; ok: true; result?: unknown } | { v: 1; t: "reply"; id: number; ok: false; reason: string } | WsUpdateMessage — ⚠ undocumented
|
|
578
|
+
- `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
|
|
579
|
+
- `WsVoiceParticipant` (type): type WsVoiceParticipant = { userId: string; streamId?: string; } — ⚠ undocumented
|
|
580
|
+
|
|
581
|
+
## @jgengine/ws/readsHandler
|
|
582
|
+
|
|
583
|
+
- `ReadsAuthenticate` (type): type ReadsAuthenticate = ( request: Request, ) => Promise<string | null> | string | null — ⚠ undocumented
|
|
584
|
+
- `ReadsHandler` (type): type ReadsHandler = (request: Request) => Promise<Response> — ⚠ undocumented
|
|
585
|
+
- `ReadsHandlerOptions` (type): type ReadsHandlerOptions = { persistence: ReadsPersistence | (() => Promise<ReadsPersistence>); basePath?: string; listOpenServers?: (args: { gameId: string; limit?: number }) => Promise<ServerListing[]>; authenticate?: ReadsAuthenticate; allowPublicProfiles?: boolean; } — ⚠ undocumented
|
|
586
|
+
- `ReadsPersistence` (type): type ReadsPersistence = Pick< HostPersistence, "listServers" | "loadProfile" | "getLeaderboardTop" | "getLeaderboardProfile" > — ⚠ undocumented
|
|
587
|
+
- `createReadsHandler` (function): function createReadsHandler(options: ReadsHandlerOptions): ReadsHandler — ⚠ undocumented
|
|
588
|
+
|
|
589
|
+
## @jgengine/ws/socketIoPipe
|
|
590
|
+
|
|
591
|
+
- `SocketIoBackendOptions` (type): type SocketIoBackendOptions = Omit<WsBackendOptions, "url" | "pipe" | "webSocketFactory"> & { socket: SocketIoLikeSocket; } — ⚠ undocumented
|
|
592
|
+
- `SocketIoLikeSocket` (type): type SocketIoLikeSocket = { connected: boolean; on: (event: string, listener: (payload: string) => void) => unknown; off: (event: string, listener: (payload: string) => void) => unknown; send: (data: string) => unknown; disconnect: () => unknown; } — ⚠ undocumented
|
|
593
|
+
- `createSocketIoBackend` (function): function createSocketIoBackend(options: SocketIoBackendOptions): WsBackend — ⚠ undocumented
|
|
594
|
+
- `socketIoPipe` (function): function socketIoPipe(socket: SocketIoLikeSocket): TransportPipeFactory — ⚠ undocumented
|
|
595
|
+
|
|
596
|
+
## @jgengine/ws/voiceChannel
|
|
597
|
+
|
|
598
|
+
- `VoiceChannelDef` (interface): interface VoiceChannelDef — ⚠ undocumented
|
|
599
|
+
- `VoiceChannelId` (type): type VoiceChannelId = string — ⚠ undocumented
|
|
600
|
+
- `VoiceChannelRouter` (interface): interface VoiceChannelRouter — ⚠ undocumented
|
|
601
|
+
- `VoiceMemberId` (type): type VoiceMemberId = string — ⚠ undocumented
|
|
602
|
+
- `VoicePosition` (interface): interface VoicePosition — ⚠ undocumented
|
|
603
|
+
- `VoiceRoute` (interface): interface VoiceRoute — ⚠ undocumented
|
|
604
|
+
- `computeVoiceGain` (function): function computeVoiceGain(def: VoiceChannelDef, distance: number | null): number — ⚠ undocumented
|
|
605
|
+
- `createVoiceChannelRouter` (function): function createVoiceChannelRouter(channels?: readonly VoiceChannelDef[]): VoiceChannelRouter — ⚠ undocumented
|
|
606
|
+
|
|
607
|
+
## @jgengine/ws/worldHost
|
|
608
|
+
|
|
609
|
+
- `WorldGameHost` (interface): interface WorldGameHost extends GameHost — A {@link GameHost} whose worlds run on `HostedWorldSession`s; `tick` advances them and re-broadcasts on change.
|
|
610
|
+
- `WorldGameHostOptions` (interface): interface WorldGameHostOptions — Config for {@link createWorldGameHost}: how to resolve a hosted world's authoritative session per server.
|
|
611
|
+
- `createWorldGameHost` (function): function createWorldGameHost(options: WorldGameHostOptions): WorldGameHost — The GameContext-loop counterpart of the reducer `createGameHost`: a structural {@link GameHost} that serves each world's full `WorldSnapshot` as `serverState`, so the existing ws router, `createWsBackend`, and the shell's `attachWorldSync` carry host-authoritative GameContext worlds with zero changes to any of them. The harness owns the tick cadence (call {@link WorldGameHost.tick} on an interval); commands and joins broadcast immediately.
|