@genex-ai/multiplayer 0.9.0 → 0.10.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/README.md CHANGED
@@ -13,13 +13,13 @@ import { connect } from '@genex-ai/multiplayer';
13
13
  ## Connect
14
14
 
15
15
  ```ts
16
- import { waitForPlayer, getColyseusAuth } from '@genex-ai/embed-sdk';
16
+ import { waitForPlayer, getColyseusAuth, getColyseusUrls } from '@genex-ai/embed-sdk';
17
17
 
18
18
  type State = { x: number; y: number; z: number }; // YOUR per-player state — any JSON shape
19
19
 
20
20
  await waitForPlayer(); // identity gate — resolves for guests AND accounts
21
21
  const room = await connect<State>({
22
- url: 'wss://demo-colyseus.glotech.world', // the genex multiplayer server
22
+ urls: getColyseusUrls(), // regional relays for this session — SDK joins the fastest
23
23
  room: '<game-id>', // everyone with the same id shares a room (use the project slug)
24
24
  name: 'ada', // optional display name
25
25
  auth: getColyseusAuth()!, // REQUIRED — the relay rejects tokenless joins
@@ -246,12 +246,12 @@ bounded extrapolation.
246
246
 
247
247
  ```ts
248
248
  import { connect } from '@genex-ai/multiplayer';
249
- import { waitForPlayer, getColyseusAuth } from '@genex-ai/embed-sdk';
249
+ import { waitForPlayer, getColyseusAuth, getColyseusUrls } from '@genex-ai/embed-sdk';
250
250
  type S = { x: number; z: number };
251
251
 
252
252
  await waitForPlayer(); // identity gate (guest OR signed-in) — see Connect above
253
253
  const room = await connect<S>({
254
- url: 'wss://demo-colyseus.glotech.world',
254
+ urls: getColyseusUrls(),
255
255
  room: GAME_ID,
256
256
  auth: getColyseusAuth()!, // REQUIRED — tokenless joins are rejected
257
257
  });
@@ -289,7 +289,7 @@ import { matchmake } from "@genex-ai/multiplayer";
289
289
 
290
290
  // Pass `auth` as a FUNCTION — a handle re-joins many times (re-search/requeue) and tokens rotate
291
291
  // (~10 min); a function is read fresh each join, a static object goes stale mid-session.
292
- const mm = await matchmake<State>({ url, room: slug, auth: () => getColyseusAuth() });
292
+ const mm = await matchmake<State>({ urls, room: slug, auth: () => getColyseusAuth() });
293
293
 
294
294
  // `session` is null WHILE SEARCHING — render your own "finding a match…" HUD until it goes live.
295
295
  // each frame:
@@ -344,11 +344,11 @@ For `preset: 'private'` games, skip the queue: a host mints an invite **code**,
344
344
  import { createPrivate, joinPrivate } from "@genex-ai/multiplayer";
345
345
 
346
346
  // host
347
- const lobby = await createPrivate<State>({ url, room: slug, auth: () => getColyseusAuth() });
347
+ const lobby = await createPrivate<State>({ urls, room: slug, auth: () => getColyseusAuth() });
348
348
  share(lobby.code); // e.g. show it in the UI
349
349
 
350
350
  // friend (elsewhere)
351
- const joined = await joinPrivate<State>(code, { url, room: slug, auth: () => getColyseusAuth() });
351
+ const joined = await joinPrivate<State>(code, { urls, room: slug, auth: () => getColyseusAuth() });
352
352
 
353
353
  // then identical to matchmake(): .session, .matchmaking, eliminated()/score()/finish(), cancel()
354
354
  ```
package/dist/index.d.ts CHANGED
@@ -2,8 +2,9 @@ export { PlayerState, RoomState } from './schema.js';
2
2
  import '@colyseus/schema';
3
3
 
4
4
  type ConnectOptions = {
5
- /** Colyseus server url, e.g. "ws://localhost:2567". */
6
- url: string;
5
+ /** Regional relay urls (pass `getColyseusUrls()`) — the SDK pings each and connects to the
6
+ * lowest-latency one; a single entry just connects. */
7
+ urls: string[];
7
8
  /** Game id — everyone who passes the same id shares a room; different ids are
8
9
  * fully isolated. Use your project slug (or any stable per-game string). */
9
10
  room: string;
@@ -264,8 +265,8 @@ type Matchmaking<TState extends Record<string, unknown>> = {
264
265
  cancel(): void;
265
266
  };
266
267
  type MatchmakeOptions = {
267
- /** Colyseus server url. */
268
- url: string;
268
+ /** Regional relay urls (pass `getColyseusUrls()`) — pings each, connects to the lowest-latency one. */
269
+ urls: string[];
269
270
  /** Game id (your project slug/id) — isolates this game's matchmaking. */
270
271
  room: string;
271
272
  name?: string;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import { Client, getStateCallbacks } from "colyseus.js";
2
+ import { Client, getStateCallbacks } from "@colyseus/sdk";
3
3
  var RELAY_ROOM_TYPE = "play";
4
4
  var QUEUE_ROOM_TYPE = "queue";
5
5
  var MATCH_ROOM_TYPE = "match";
@@ -27,6 +27,12 @@ var OBJECT_CONTROL_VERSION = 2;
27
27
  var STATE_SNAP_MSG = "__state:snap";
28
28
  var OBJECT_SNAP_MSG = "__object:snap";
29
29
  var MP_PROTOCOL = 2;
30
+ async function relayClient(opts) {
31
+ if (opts.urls.length > 1) return Client.selectByLatency(opts.urls);
32
+ const url = opts.urls[0];
33
+ if (!url) throw new Error("genex multiplayer: `urls` must contain at least one relay URL");
34
+ return new Client(url);
35
+ }
30
36
  function parseData(s) {
31
37
  if (!s) return { state: {} };
32
38
  try {
@@ -151,7 +157,7 @@ function quantile(xs, q) {
151
157
  return s[i];
152
158
  }
153
159
  async function connect(opts) {
154
- const client = new Client(opts.url);
160
+ const client = await relayClient(opts);
155
161
  const room = await client.joinOrCreate(RELAY_ROOM_TYPE, {
156
162
  gameId: opts.room,
157
163
  name: opts.name,
@@ -947,7 +953,7 @@ function buildView(matchRoom, queueInfo) {
947
953
  };
948
954
  }
949
955
  async function matchmake(opts) {
950
- const client = new Client(opts.url);
956
+ const client = await relayClient(opts);
951
957
  const emitters = /* @__PURE__ */ new Map();
952
958
  const emit = (event, ...args) => emitters.get(event)?.forEach((cb) => cb(...args));
953
959
  const on = ((event, cb) => {
@@ -1128,14 +1134,14 @@ function wirePrivate(client, room) {
1128
1134
  };
1129
1135
  }
1130
1136
  async function createPrivate(opts) {
1131
- const client = new Client(opts.url);
1137
+ const client = await relayClient(opts);
1132
1138
  const room = await client.create(MATCH_ROOM_TYPE, matchJoinOptions(opts));
1133
1139
  const handle = wirePrivate(client, room);
1134
1140
  Object.defineProperty(handle, "code", { value: room.roomId, enumerable: true });
1135
1141
  return handle;
1136
1142
  }
1137
1143
  async function joinPrivate(code, opts) {
1138
- const client = new Client(opts.url);
1144
+ const client = await relayClient(opts);
1139
1145
  const room = await client.joinById(code, matchJoinOptions(opts));
1140
1146
  return wirePrivate(client, room);
1141
1147
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genex-ai/multiplayer",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "The multiplayer client wrapper + shared room schema for genex.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -30,8 +30,8 @@
30
30
  "access": "public"
31
31
  },
32
32
  "dependencies": {
33
- "@colyseus/schema": "^3.0.76",
34
- "colyseus.js": "^0.16.22"
33
+ "@colyseus/schema": "^4.0.27",
34
+ "@colyseus/sdk": "^0.17.43"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "three": ">=0.160.0"