@jgengine/convex 0.6.0 → 0.8.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.
@@ -1,21 +1,27 @@
1
+ import { anyApi } from "convex/server";
2
+ import { createPoseSyncGate } from "@jgengine/core/multiplayer/poseSyncGate";
3
+ export function defaultConvexGameApi() {
4
+ return anyApi;
5
+ }
1
6
  export function createConvexGameTransport(client, api, config) {
2
7
  return {
3
8
  async joinServer(args) {
4
9
  const result = await client.mutation(api.runtime.joinServer, {
5
10
  gameId: config.gameId,
6
11
  serverId: args.serverId,
12
+ externalId: config.userId,
7
13
  });
8
14
  return result;
9
15
  },
10
16
  async leaveServer(args) {
11
- await client.mutation(api.runtime.leaveServer, args);
17
+ await client.mutation(api.runtime.leaveServer, { ...args, externalId: config.userId });
12
18
  },
13
19
  async runCommand(args) {
14
- return await client.mutation(api.runtime.runCommand, args);
20
+ return await client.mutation(api.runtime.runCommand, { ...args, externalId: config.userId });
15
21
  },
16
22
  };
17
23
  }
18
- function watchConvexQuery(client, query, args, toView, onChange) {
24
+ export function watchConvexQuery(client, query, args, toView, onChange) {
19
25
  const watch = client.watchQuery(query, args);
20
26
  const emit = () => {
21
27
  const result = watch.localQueryResult();
@@ -29,7 +35,7 @@ function watchConvexQuery(client, query, args, toView, onChange) {
29
35
  export function createConvexGameFeeds(client, api, config) {
30
36
  return {
31
37
  subscribeServer(serverId, onChange) {
32
- return watchConvexQuery(client, api.runtime.getServer, { serverId }, (result) => result === null
38
+ return watchConvexQuery(client, api.runtime.getServer, { serverId, externalId: config.userId }, (result) => result === null
33
39
  ? null
34
40
  : {
35
41
  serverId: result._id,
@@ -42,7 +48,7 @@ export function createConvexGameFeeds(client, api, config) {
42
48
  },
43
49
  subscribePlayer(args, onChange) {
44
50
  void args;
45
- return watchConvexQuery(client, api.runtime.getPlayerProfile, { gameId: config.gameId }, (result) => result === null
51
+ return watchConvexQuery(client, api.runtime.getPlayerProfile, { gameId: config.gameId, externalId: config.userId }, (result) => result === null
46
52
  ? null
47
53
  : {
48
54
  userId: result.userId,
@@ -52,7 +58,52 @@ export function createConvexGameFeeds(client, api, config) {
52
58
  }, onChange);
53
59
  },
54
60
  subscribeFeed(args, onChange) {
55
- return watchConvexQuery(client, api.runtime.getFeed, args, (entries) => ({ action: args.action, entries }), onChange);
61
+ return watchConvexQuery(client, api.runtime.getFeed, { ...args, externalId: config.userId }, (entries) => ({ action: args.action, entries }), onChange);
62
+ },
63
+ };
64
+ }
65
+ const DEFAULT_CONVEX_POSE_TUNING = {
66
+ minIntervalMs: 200,
67
+ heartbeatMs: 5_000,
68
+ positionEpsilon: 0.01,
69
+ verticalEpsilon: 0.01,
70
+ rotationEpsilon: 0.01,
71
+ };
72
+ export function createConvexPresenceSync(client, api, config, tuning) {
73
+ const gate = createPoseSyncGate(tuning ?? DEFAULT_CONVEX_POSE_TUNING);
74
+ return {
75
+ subscribe(serverId, onChange) {
76
+ return watchConvexQuery(client, api.presence.list, { serverId }, (rows) => rows, onChange);
77
+ },
78
+ syncPose(serverId, pose) {
79
+ if (!gate.evaluate(pose, Date.now()))
80
+ return;
81
+ void client
82
+ .mutation(api.presence.sync, { serverId, pose, externalId: config.userId })
83
+ .catch(() => undefined);
84
+ },
85
+ };
86
+ }
87
+ export function createConvexChatSync(client, api, config, serverId) {
88
+ return {
89
+ subscribe(channelId, onChange) {
90
+ return watchConvexQuery(client, api.chat.messages, { serverId, channelId, externalId: config.userId }, (messages) => messages, onChange);
91
+ },
92
+ async send(channelId, body) {
93
+ const outcome = await client.mutation(api.chat.sendMessage, {
94
+ serverId,
95
+ channelId,
96
+ body,
97
+ externalId: config.userId,
98
+ });
99
+ return outcome ?? { ok: true };
100
+ },
101
+ };
102
+ }
103
+ export function createConvexFeedWrites(client, api, config) {
104
+ return {
105
+ async pushFeedEntry(args) {
106
+ await client.mutation(api.runtime.pushFeedEntry, { ...args, externalId: config.userId });
56
107
  },
57
108
  };
58
109
  }
@@ -0,0 +1,17 @@
1
+ import { ConvexReactClient } from "convex/react";
2
+ import type { GameDefinition } from "@jgengine/core/game/defineGame";
3
+ import type { MultiplayerSession } from "@jgengine/core/runtime/transport";
4
+ import type { PoseSyncTuning } from "@jgengine/core/multiplayer/poseSyncGate";
5
+ import type { ConvexGameApi } from "./createConvexGameTransport.js";
6
+ export declare function randomConvexPlayerId(): string;
7
+ export declare function resolveConvexMultiplayer(args: {
8
+ game: GameDefinition;
9
+ gameId: string;
10
+ url?: string;
11
+ client?: ConvexReactClient;
12
+ api?: ConvexGameApi;
13
+ userId?: string;
14
+ force?: boolean;
15
+ feedActions?: string[];
16
+ poseTuning?: PoseSyncTuning;
17
+ }): MultiplayerSession | null;
@@ -0,0 +1,26 @@
1
+ import { ConvexReactClient } from "convex/react";
2
+ import { multiplayerAdapterKind } from "@jgengine/core/runtime/adapter";
3
+ import { createConvexBackend } from "./createConvexBackend.js";
4
+ export function randomConvexPlayerId() {
5
+ return `player-${Math.random().toString(36).slice(2, 10)}`;
6
+ }
7
+ export function resolveConvexMultiplayer(args) {
8
+ if (args.force !== true && multiplayerAdapterKind(args.game.multiplayer) !== "convex")
9
+ return null;
10
+ const client = args.client ?? (args.url === undefined ? null : new ConvexReactClient(args.url));
11
+ if (client === null)
12
+ return null;
13
+ const userId = args.userId ?? randomConvexPlayerId();
14
+ return {
15
+ gameId: args.gameId,
16
+ userId,
17
+ backend: createConvexBackend({
18
+ client,
19
+ gameId: args.gameId,
20
+ userId,
21
+ api: args.api,
22
+ poseTuning: args.poseTuning,
23
+ }),
24
+ feedActions: args.feedActions ?? ["entity.died"],
25
+ };
26
+ }
@@ -0,0 +1,506 @@
1
+ import type { DataModelFromSchemaDefinition, GenericMutationCtx } from "convex/server";
2
+ import type { GenericId } from "convex/values";
3
+ import type { ChatMessage } from "@jgengine/core/game/chat";
4
+ import type { ChatSendOutcome } from "@jgengine/core/multiplayer/chatContract";
5
+ import type { GameRuntime } from "@jgengine/core/runtime/gameRuntime";
6
+ import type { LeaderboardIncrement } from "@jgengine/core/runtime/hostPersistence";
7
+ export declare function jgengineTables(): {
8
+ jgGameServers: import("convex/server").TableDefinition<import("convex/values").VObject<{
9
+ createdAt: number;
10
+ dirtyAt?: number | undefined;
11
+ gameId: string;
12
+ lastSavedAt?: number | undefined;
13
+ memberUserIds: string[];
14
+ mode?: string | undefined;
15
+ modeConfig?: any;
16
+ revision: number;
17
+ save: "none" | {
18
+ auto: string;
19
+ scope: "chunks" | "player" | "player+chunks";
20
+ };
21
+ serverState: any;
22
+ sessionPlayers: any;
23
+ slotsPerServer: number;
24
+ status: "closed" | "open" | "running";
25
+ tickAnchorMs: number;
26
+ updatedAt: number;
27
+ }, {
28
+ gameId: import("convex/values").VString<string, "required">;
29
+ status: import("convex/values").VUnion<"closed" | "open" | "running", [import("convex/values").VLiteral<"open", "required">, import("convex/values").VLiteral<"running", "required">, import("convex/values").VLiteral<"closed", "required">], "required", never>;
30
+ mode: import("convex/values").VString<string | undefined, "optional">;
31
+ modeConfig: import("convex/values").VAny<any, "optional", string>;
32
+ memberUserIds: import("convex/values").VArray<string[], import("convex/values").VString<string, "required">, "required">;
33
+ slotsPerServer: import("convex/values").VFloat64<number, "required">;
34
+ save: import("convex/values").VUnion<"none" | {
35
+ auto: string;
36
+ scope: "chunks" | "player" | "player+chunks";
37
+ }, [import("convex/values").VLiteral<"none", "required">, import("convex/values").VObject<{
38
+ auto: string;
39
+ scope: "chunks" | "player" | "player+chunks";
40
+ }, {
41
+ auto: import("convex/values").VString<string, "required">;
42
+ scope: import("convex/values").VUnion<"chunks" | "player" | "player+chunks", [import("convex/values").VLiteral<"player", "required">, import("convex/values").VLiteral<"chunks", "required">, import("convex/values").VLiteral<"player+chunks", "required">], "required", never>;
43
+ }, "required", "auto" | "scope">], "required", "auto" | "scope">;
44
+ serverState: import("convex/values").VAny<any, "required", string>;
45
+ sessionPlayers: import("convex/values").VAny<any, "required", string>;
46
+ revision: import("convex/values").VFloat64<number, "required">;
47
+ tickAnchorMs: import("convex/values").VFloat64<number, "required">;
48
+ lastSavedAt: import("convex/values").VFloat64<number | undefined, "optional">;
49
+ dirtyAt: import("convex/values").VFloat64<number | undefined, "optional">;
50
+ createdAt: import("convex/values").VFloat64<number, "required">;
51
+ updatedAt: import("convex/values").VFloat64<number, "required">;
52
+ }, "required", "createdAt" | "dirtyAt" | "gameId" | "lastSavedAt" | "memberUserIds" | "mode" | "modeConfig" | "revision" | "save" | "save.auto" | "save.scope" | "serverState" | "sessionPlayers" | "slotsPerServer" | "status" | "tickAnchorMs" | "updatedAt" | `modeConfig.${string}` | `serverState.${string}` | `sessionPlayers.${string}`>, {
53
+ by_game_and_status: ["gameId", "status", "_creationTime"];
54
+ }, {}, {}>;
55
+ jgPlayerProfiles: import("convex/server").TableDefinition<import("convex/values").VObject<{
56
+ createdAt: number;
57
+ dirtyAt?: number | undefined;
58
+ gameId: string;
59
+ playerState: any;
60
+ revision: number;
61
+ updatedAt: number;
62
+ userId: string;
63
+ }, {
64
+ userId: import("convex/values").VString<string, "required">;
65
+ gameId: import("convex/values").VString<string, "required">;
66
+ playerState: import("convex/values").VAny<any, "required", string>;
67
+ revision: import("convex/values").VFloat64<number, "required">;
68
+ dirtyAt: import("convex/values").VFloat64<number | undefined, "optional">;
69
+ createdAt: import("convex/values").VFloat64<number, "required">;
70
+ updatedAt: import("convex/values").VFloat64<number, "required">;
71
+ }, "required", "createdAt" | "dirtyAt" | "gameId" | "playerState" | "revision" | "updatedAt" | "userId" | `playerState.${string}`>, {
72
+ by_user_and_game: ["userId", "gameId", "_creationTime"];
73
+ }, {}, {}>;
74
+ jgWorldChunks: import("convex/server").TableDefinition<import("convex/values").VObject<{
75
+ chunkKey: string;
76
+ dirtyAt?: number | undefined;
77
+ serverId: GenericId<"jgGameServers">;
78
+ snapshot: any;
79
+ updatedAt: number;
80
+ }, {
81
+ serverId: import("convex/values").VId<GenericId<"jgGameServers">, "required">;
82
+ chunkKey: import("convex/values").VString<string, "required">;
83
+ snapshot: import("convex/values").VAny<any, "required", string>;
84
+ dirtyAt: import("convex/values").VFloat64<number | undefined, "optional">;
85
+ updatedAt: import("convex/values").VFloat64<number, "required">;
86
+ }, "required", "chunkKey" | "dirtyAt" | "serverId" | "snapshot" | "updatedAt" | `snapshot.${string}`>, {
87
+ by_server: ["serverId", "_creationTime"];
88
+ by_server_and_chunk: ["serverId", "chunkKey", "_creationTime"];
89
+ }, {}, {}>;
90
+ jgLeaderboardRows: import("convex/server").TableDefinition<import("convex/values").VObject<{
91
+ gameId: string;
92
+ scope: "global" | "profile" | "server";
93
+ serverId?: GenericId<"jgGameServers"> | undefined;
94
+ stat: string;
95
+ updatedAt: number;
96
+ userId: string;
97
+ value: number;
98
+ }, {
99
+ gameId: import("convex/values").VString<string, "required">;
100
+ stat: import("convex/values").VString<string, "required">;
101
+ scope: import("convex/values").VUnion<"global" | "profile" | "server", [import("convex/values").VLiteral<"global", "required">, import("convex/values").VLiteral<"server", "required">, import("convex/values").VLiteral<"profile", "required">], "required", never>;
102
+ serverId: import("convex/values").VId<GenericId<"jgGameServers"> | undefined, "optional">;
103
+ userId: import("convex/values").VString<string, "required">;
104
+ value: import("convex/values").VFloat64<number, "required">;
105
+ updatedAt: import("convex/values").VFloat64<number, "required">;
106
+ }, "required", "gameId" | "scope" | "serverId" | "stat" | "updatedAt" | "userId" | "value">, {
107
+ by_game_scope_stat_value: ["gameId", "scope", "stat", "value", "_creationTime"];
108
+ by_user_scope_stat: ["userId", "scope", "stat", "_creationTime"];
109
+ }, {}, {}>;
110
+ jgFeedBuffers: import("convex/server").TableDefinition<import("convex/values").VObject<{
111
+ action: string;
112
+ entries: any[];
113
+ serverId: GenericId<"jgGameServers">;
114
+ updatedAt: number;
115
+ }, {
116
+ serverId: import("convex/values").VId<GenericId<"jgGameServers">, "required">;
117
+ action: import("convex/values").VString<string, "required">;
118
+ entries: import("convex/values").VArray<any[], import("convex/values").VAny<any, "required", string>, "required">;
119
+ updatedAt: import("convex/values").VFloat64<number, "required">;
120
+ }, "required", "action" | "entries" | "serverId" | "updatedAt">, {
121
+ by_server_and_action: ["serverId", "action", "_creationTime"];
122
+ }, {}, {}>;
123
+ jgPoses: import("convex/server").TableDefinition<import("convex/values").VObject<{
124
+ rotationPitch: number;
125
+ rotationY: number;
126
+ serverId: string;
127
+ updatedAt: number;
128
+ userId: string;
129
+ x: number;
130
+ y: number;
131
+ z: number;
132
+ }, {
133
+ serverId: import("convex/values").VString<string, "required">;
134
+ userId: import("convex/values").VString<string, "required">;
135
+ x: import("convex/values").VFloat64<number, "required">;
136
+ y: import("convex/values").VFloat64<number, "required">;
137
+ z: import("convex/values").VFloat64<number, "required">;
138
+ rotationY: import("convex/values").VFloat64<number, "required">;
139
+ rotationPitch: import("convex/values").VFloat64<number, "required">;
140
+ updatedAt: import("convex/values").VFloat64<number, "required">;
141
+ }, "required", "rotationPitch" | "rotationY" | "serverId" | "updatedAt" | "userId" | "x" | "y" | "z">, {
142
+ by_server: ["serverId", "_creationTime"];
143
+ by_server_and_user: ["serverId", "userId", "_creationTime"];
144
+ }, {}, {}>;
145
+ jgChatMessages: import("convex/server").TableDefinition<import("convex/values").VObject<{
146
+ at: number;
147
+ body: string;
148
+ channelId: string;
149
+ serverId: string;
150
+ userId: string;
151
+ }, {
152
+ serverId: import("convex/values").VString<string, "required">;
153
+ channelId: import("convex/values").VString<string, "required">;
154
+ userId: import("convex/values").VString<string, "required">;
155
+ body: import("convex/values").VString<string, "required">;
156
+ at: import("convex/values").VFloat64<number, "required">;
157
+ }, "required", "at" | "body" | "channelId" | "serverId" | "userId">, {
158
+ by_server_channel: ["serverId", "channelId", "_creationTime"];
159
+ }, {}, {}>;
160
+ };
161
+ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
162
+ jgGameServers: import("convex/server").TableDefinition<import("convex/values").VObject<{
163
+ createdAt: number;
164
+ dirtyAt?: number | undefined;
165
+ gameId: string;
166
+ lastSavedAt?: number | undefined;
167
+ memberUserIds: string[];
168
+ mode?: string | undefined;
169
+ modeConfig?: any;
170
+ revision: number;
171
+ save: "none" | {
172
+ auto: string;
173
+ scope: "chunks" | "player" | "player+chunks";
174
+ };
175
+ serverState: any;
176
+ sessionPlayers: any;
177
+ slotsPerServer: number;
178
+ status: "closed" | "open" | "running";
179
+ tickAnchorMs: number;
180
+ updatedAt: number;
181
+ }, {
182
+ gameId: import("convex/values").VString<string, "required">;
183
+ status: import("convex/values").VUnion<"closed" | "open" | "running", [import("convex/values").VLiteral<"open", "required">, import("convex/values").VLiteral<"running", "required">, import("convex/values").VLiteral<"closed", "required">], "required", never>;
184
+ mode: import("convex/values").VString<string | undefined, "optional">;
185
+ modeConfig: import("convex/values").VAny<any, "optional", string>;
186
+ memberUserIds: import("convex/values").VArray<string[], import("convex/values").VString<string, "required">, "required">;
187
+ slotsPerServer: import("convex/values").VFloat64<number, "required">;
188
+ save: import("convex/values").VUnion<"none" | {
189
+ auto: string;
190
+ scope: "chunks" | "player" | "player+chunks";
191
+ }, [import("convex/values").VLiteral<"none", "required">, import("convex/values").VObject<{
192
+ auto: string;
193
+ scope: "chunks" | "player" | "player+chunks";
194
+ }, {
195
+ auto: import("convex/values").VString<string, "required">;
196
+ scope: import("convex/values").VUnion<"chunks" | "player" | "player+chunks", [import("convex/values").VLiteral<"player", "required">, import("convex/values").VLiteral<"chunks", "required">, import("convex/values").VLiteral<"player+chunks", "required">], "required", never>;
197
+ }, "required", "auto" | "scope">], "required", "auto" | "scope">;
198
+ serverState: import("convex/values").VAny<any, "required", string>;
199
+ sessionPlayers: import("convex/values").VAny<any, "required", string>;
200
+ revision: import("convex/values").VFloat64<number, "required">;
201
+ tickAnchorMs: import("convex/values").VFloat64<number, "required">;
202
+ lastSavedAt: import("convex/values").VFloat64<number | undefined, "optional">;
203
+ dirtyAt: import("convex/values").VFloat64<number | undefined, "optional">;
204
+ createdAt: import("convex/values").VFloat64<number, "required">;
205
+ updatedAt: import("convex/values").VFloat64<number, "required">;
206
+ }, "required", "createdAt" | "dirtyAt" | "gameId" | "lastSavedAt" | "memberUserIds" | "mode" | "modeConfig" | "revision" | "save" | "save.auto" | "save.scope" | "serverState" | "sessionPlayers" | "slotsPerServer" | "status" | "tickAnchorMs" | "updatedAt" | `modeConfig.${string}` | `serverState.${string}` | `sessionPlayers.${string}`>, {
207
+ by_game_and_status: ["gameId", "status", "_creationTime"];
208
+ }, {}, {}>;
209
+ jgPlayerProfiles: import("convex/server").TableDefinition<import("convex/values").VObject<{
210
+ createdAt: number;
211
+ dirtyAt?: number | undefined;
212
+ gameId: string;
213
+ playerState: any;
214
+ revision: number;
215
+ updatedAt: number;
216
+ userId: string;
217
+ }, {
218
+ userId: import("convex/values").VString<string, "required">;
219
+ gameId: import("convex/values").VString<string, "required">;
220
+ playerState: import("convex/values").VAny<any, "required", string>;
221
+ revision: import("convex/values").VFloat64<number, "required">;
222
+ dirtyAt: import("convex/values").VFloat64<number | undefined, "optional">;
223
+ createdAt: import("convex/values").VFloat64<number, "required">;
224
+ updatedAt: import("convex/values").VFloat64<number, "required">;
225
+ }, "required", "createdAt" | "dirtyAt" | "gameId" | "playerState" | "revision" | "updatedAt" | "userId" | `playerState.${string}`>, {
226
+ by_user_and_game: ["userId", "gameId", "_creationTime"];
227
+ }, {}, {}>;
228
+ jgWorldChunks: import("convex/server").TableDefinition<import("convex/values").VObject<{
229
+ chunkKey: string;
230
+ dirtyAt?: number | undefined;
231
+ serverId: GenericId<"jgGameServers">;
232
+ snapshot: any;
233
+ updatedAt: number;
234
+ }, {
235
+ serverId: import("convex/values").VId<GenericId<"jgGameServers">, "required">;
236
+ chunkKey: import("convex/values").VString<string, "required">;
237
+ snapshot: import("convex/values").VAny<any, "required", string>;
238
+ dirtyAt: import("convex/values").VFloat64<number | undefined, "optional">;
239
+ updatedAt: import("convex/values").VFloat64<number, "required">;
240
+ }, "required", "chunkKey" | "dirtyAt" | "serverId" | "snapshot" | "updatedAt" | `snapshot.${string}`>, {
241
+ by_server: ["serverId", "_creationTime"];
242
+ by_server_and_chunk: ["serverId", "chunkKey", "_creationTime"];
243
+ }, {}, {}>;
244
+ jgLeaderboardRows: import("convex/server").TableDefinition<import("convex/values").VObject<{
245
+ gameId: string;
246
+ scope: "global" | "profile" | "server";
247
+ serverId?: GenericId<"jgGameServers"> | undefined;
248
+ stat: string;
249
+ updatedAt: number;
250
+ userId: string;
251
+ value: number;
252
+ }, {
253
+ gameId: import("convex/values").VString<string, "required">;
254
+ stat: import("convex/values").VString<string, "required">;
255
+ scope: import("convex/values").VUnion<"global" | "profile" | "server", [import("convex/values").VLiteral<"global", "required">, import("convex/values").VLiteral<"server", "required">, import("convex/values").VLiteral<"profile", "required">], "required", never>;
256
+ serverId: import("convex/values").VId<GenericId<"jgGameServers"> | undefined, "optional">;
257
+ userId: import("convex/values").VString<string, "required">;
258
+ value: import("convex/values").VFloat64<number, "required">;
259
+ updatedAt: import("convex/values").VFloat64<number, "required">;
260
+ }, "required", "gameId" | "scope" | "serverId" | "stat" | "updatedAt" | "userId" | "value">, {
261
+ by_game_scope_stat_value: ["gameId", "scope", "stat", "value", "_creationTime"];
262
+ by_user_scope_stat: ["userId", "scope", "stat", "_creationTime"];
263
+ }, {}, {}>;
264
+ jgFeedBuffers: import("convex/server").TableDefinition<import("convex/values").VObject<{
265
+ action: string;
266
+ entries: any[];
267
+ serverId: GenericId<"jgGameServers">;
268
+ updatedAt: number;
269
+ }, {
270
+ serverId: import("convex/values").VId<GenericId<"jgGameServers">, "required">;
271
+ action: import("convex/values").VString<string, "required">;
272
+ entries: import("convex/values").VArray<any[], import("convex/values").VAny<any, "required", string>, "required">;
273
+ updatedAt: import("convex/values").VFloat64<number, "required">;
274
+ }, "required", "action" | "entries" | "serverId" | "updatedAt">, {
275
+ by_server_and_action: ["serverId", "action", "_creationTime"];
276
+ }, {}, {}>;
277
+ jgPoses: import("convex/server").TableDefinition<import("convex/values").VObject<{
278
+ rotationPitch: number;
279
+ rotationY: number;
280
+ serverId: string;
281
+ updatedAt: number;
282
+ userId: string;
283
+ x: number;
284
+ y: number;
285
+ z: number;
286
+ }, {
287
+ serverId: import("convex/values").VString<string, "required">;
288
+ userId: import("convex/values").VString<string, "required">;
289
+ x: import("convex/values").VFloat64<number, "required">;
290
+ y: import("convex/values").VFloat64<number, "required">;
291
+ z: import("convex/values").VFloat64<number, "required">;
292
+ rotationY: import("convex/values").VFloat64<number, "required">;
293
+ rotationPitch: import("convex/values").VFloat64<number, "required">;
294
+ updatedAt: import("convex/values").VFloat64<number, "required">;
295
+ }, "required", "rotationPitch" | "rotationY" | "serverId" | "updatedAt" | "userId" | "x" | "y" | "z">, {
296
+ by_server: ["serverId", "_creationTime"];
297
+ by_server_and_user: ["serverId", "userId", "_creationTime"];
298
+ }, {}, {}>;
299
+ jgChatMessages: import("convex/server").TableDefinition<import("convex/values").VObject<{
300
+ at: number;
301
+ body: string;
302
+ channelId: string;
303
+ serverId: string;
304
+ userId: string;
305
+ }, {
306
+ serverId: import("convex/values").VString<string, "required">;
307
+ channelId: import("convex/values").VString<string, "required">;
308
+ userId: import("convex/values").VString<string, "required">;
309
+ body: import("convex/values").VString<string, "required">;
310
+ at: import("convex/values").VFloat64<number, "required">;
311
+ }, "required", "at" | "body" | "channelId" | "serverId" | "userId">, {
312
+ by_server_channel: ["serverId", "channelId", "_creationTime"];
313
+ }, {}, {}>;
314
+ }, true>;
315
+ type JGDataModel = DataModelFromSchemaDefinition<typeof schemaForTypes>;
316
+ type JGMutationCtx = GenericMutationCtx<JGDataModel>;
317
+ export type JgAuthMode = "anonymous" | "required";
318
+ export declare function applyLeaderboardIncrements(ctx: JGMutationCtx, gameId: string, entries: LeaderboardIncrement[]): Promise<void>;
319
+ export declare const JG_RUNTIME_TICK_MS = 1000;
320
+ export declare function createGameServerFunctions(options?: {
321
+ runtimes?: GameRuntime[];
322
+ auth?: JgAuthMode;
323
+ }): {
324
+ joinServer: import("convex/server").RegisteredMutation<"public", {
325
+ externalId?: string | undefined;
326
+ gameId: string;
327
+ mode?: string | undefined;
328
+ modeConfig?: any;
329
+ save?: "none" | {
330
+ auto: string;
331
+ scope: "chunks" | "player" | "player+chunks";
332
+ } | undefined;
333
+ serverId?: GenericId<"jgGameServers"> | undefined;
334
+ slotsPerServer?: number | undefined;
335
+ }, Promise<{
336
+ serverId: GenericId<"jgGameServers">;
337
+ isNew: boolean;
338
+ }>>;
339
+ leaveServer: import("convex/server").RegisteredMutation<"public", {
340
+ externalId?: string | undefined;
341
+ serverId: GenericId<"jgGameServers">;
342
+ }, Promise<null>>;
343
+ runCommand: import("convex/server").RegisteredMutation<"public", {
344
+ command: string;
345
+ externalId?: string | undefined;
346
+ input: any;
347
+ serverId: GenericId<"jgGameServers">;
348
+ }, Promise<{
349
+ ok: false;
350
+ reason: string;
351
+ } | {
352
+ ok: true;
353
+ }>>;
354
+ flushSave: import("convex/server").RegisteredMutation<"public", {
355
+ externalId?: string | undefined;
356
+ serverId: GenericId<"jgGameServers">;
357
+ }, Promise<boolean>>;
358
+ getServer: import("convex/server").RegisteredQuery<"public", {
359
+ externalId?: string | undefined;
360
+ serverId: GenericId<"jgGameServers">;
361
+ }, Promise<{
362
+ _id: GenericId<"jgGameServers">;
363
+ gameId: string;
364
+ status: "closed" | "open" | "running";
365
+ mode: string | undefined;
366
+ memberUserIds: string[];
367
+ slotsPerServer: number;
368
+ save: "none" | {
369
+ auto: string;
370
+ scope: "chunks" | "player" | "player+chunks";
371
+ };
372
+ revision: number;
373
+ serverState: any;
374
+ sessionPlayers: any;
375
+ updatedAt: number;
376
+ } | null>>;
377
+ getPlayerProfile: import("convex/server").RegisteredQuery<"public", {
378
+ externalId?: string | undefined;
379
+ gameId: string;
380
+ }, Promise<{
381
+ userId: string;
382
+ gameId: string;
383
+ playerState: any;
384
+ revision: number;
385
+ updatedAt: number;
386
+ } | null>>;
387
+ getFeed: import("convex/server").RegisteredQuery<"public", {
388
+ action: string;
389
+ externalId?: string | undefined;
390
+ serverId: GenericId<"jgGameServers">;
391
+ }, Promise<any[]>>;
392
+ pushFeedEntry: import("convex/server").RegisteredMutation<"public", {
393
+ action: string;
394
+ entry: any;
395
+ externalId?: string | undefined;
396
+ serverId: GenericId<"jgGameServers">;
397
+ }, Promise<null>>;
398
+ listOpenServers: import("convex/server").RegisteredQuery<"public", {
399
+ externalId?: string | undefined;
400
+ gameId: string;
401
+ limit?: number | undefined;
402
+ }, Promise<{
403
+ _id: GenericId<"jgGameServers">;
404
+ status: "closed" | "open" | "running";
405
+ memberCount: number;
406
+ slotsPerServer: number;
407
+ mode: string | undefined;
408
+ updatedAt: number;
409
+ }[]>>;
410
+ tickActiveServers: import("convex/server").RegisteredMutation<"internal", {}, Promise<{
411
+ ticked: number;
412
+ saved: number;
413
+ }>>;
414
+ flushDirtyServers: import("convex/server").RegisteredMutation<"internal", {}, Promise<{
415
+ saved: number;
416
+ }>>;
417
+ };
418
+ export declare function createLeaderboardFunctions(options?: {
419
+ auth?: JgAuthMode;
420
+ }): {
421
+ getTop: import("convex/server").RegisteredQuery<"public", {
422
+ externalId?: string | undefined;
423
+ gameId: string;
424
+ limit?: number | undefined;
425
+ scope: "global" | "profile" | "server";
426
+ serverId?: GenericId<"jgGameServers"> | undefined;
427
+ stat: string;
428
+ }, Promise<{
429
+ userId: string;
430
+ value: number;
431
+ }[]>>;
432
+ getProfile: import("convex/server").RegisteredQuery<"public", {
433
+ externalId?: string | undefined;
434
+ gameId: string;
435
+ userId: string;
436
+ }, Promise<Record<string, number>>>;
437
+ incrementMany: import("convex/server").RegisteredMutation<"internal", {
438
+ entries: {
439
+ by: number;
440
+ scope: "global" | "profile" | "server";
441
+ serverId?: GenericId<"jgGameServers"> | undefined;
442
+ stat: string;
443
+ userId: string;
444
+ }[];
445
+ gameId: string;
446
+ }, Promise<null>>;
447
+ };
448
+ export declare function createPresenceFunctions(options?: {
449
+ auth?: JgAuthMode;
450
+ freshWindowMs?: number;
451
+ }): {
452
+ list: import("convex/server").RegisteredQuery<"public", {
453
+ externalId?: string | undefined;
454
+ serverId: string;
455
+ }, Promise<{
456
+ userId: string;
457
+ position: {
458
+ x: number;
459
+ y: number;
460
+ z: number;
461
+ };
462
+ rotationY: number;
463
+ rotationPitch: number;
464
+ lastSeenAt: number;
465
+ }[]>>;
466
+ sync: import("convex/server").RegisteredMutation<"public", {
467
+ externalId?: string | undefined;
468
+ pose: {
469
+ rotationPitch: number;
470
+ rotationY: number;
471
+ x: number;
472
+ y: number;
473
+ z: number;
474
+ };
475
+ serverId: string;
476
+ }, Promise<null>>;
477
+ leave: import("convex/server").RegisteredMutation<"public", {
478
+ externalId?: string | undefined;
479
+ serverId: string;
480
+ }, Promise<null>>;
481
+ };
482
+ export declare function createChatFunctions(options?: {
483
+ auth?: JgAuthMode;
484
+ historyLimit?: number;
485
+ maxBodyLength?: number;
486
+ minIntervalMs?: number;
487
+ }): {
488
+ messages: import("convex/server").RegisteredQuery<"public", {
489
+ channelId: string;
490
+ externalId?: string | undefined;
491
+ serverId: string;
492
+ }, Promise<ChatMessage[]>>;
493
+ sendMessage: import("convex/server").RegisteredMutation<"public", {
494
+ body: string;
495
+ channelId: string;
496
+ externalId?: string | undefined;
497
+ serverId: string;
498
+ }, Promise<ChatSendOutcome>>;
499
+ };
500
+ export type JgCronSpec = {
501
+ name: string;
502
+ intervalSeconds: number;
503
+ functionKey: "tickActiveServers" | "flushDirtyServers";
504
+ };
505
+ export declare function jgengineCronSpecs(): readonly JgCronSpec[];
506
+ export {};