@genex-ai/multiplayer 0.17.8 → 0.17.10

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.
@@ -9,10 +9,10 @@ import {
9
9
  } from "./chunk-4R7C2TLH.js";
10
10
  import {
11
11
  connectAuthority
12
- } from "./chunk-QZOCUQJT.js";
13
- import "./chunk-FPWP22Y7.js";
12
+ } from "./chunk-SQC6WTMF.js";
13
+ import "./chunk-42R7NREA.js";
14
14
  import "./chunk-YWQ3ALYY.js";
15
- import "./chunk-NFMGIKFZ.js";
15
+ import "./chunk-HHETHPGL.js";
16
16
  import "./chunk-OD6NRSX2.js";
17
17
  import {
18
18
  firstpersonWorld
@@ -22,7 +22,7 @@ import {
22
22
  CloseCode,
23
23
  ServerMessage,
24
24
  isReservedEventType
25
- } from "./chunk-CSQEEANB.js";
25
+ } from "./chunk-7J3YWPCA.js";
26
26
 
27
27
  // src/bridge-authority.ts
28
28
  import { getAuthorityRegions, getAuthorityUrls, getColyseusAuth } from "@genex-ai/embed-sdk";
package/dist/bridge.js CHANGED
@@ -15,14 +15,14 @@ import {
15
15
  joinPrivate,
16
16
  matchmake,
17
17
  roomOf
18
- } from "./chunk-QY3QQNDJ.js";
19
- import "./chunk-FPWP22Y7.js";
18
+ } from "./chunk-NSQQCLMA.js";
19
+ import "./chunk-42R7NREA.js";
20
20
  import {
21
21
  Limits,
22
22
  RESERVED_SHARED_PREFIX,
23
23
  ServerMessage,
24
24
  isReservedEventType
25
- } from "./chunk-CSQEEANB.js";
25
+ } from "./chunk-7J3YWPCA.js";
26
26
 
27
27
  // src/bridge.ts
28
28
  var version = 2;
@@ -2,7 +2,7 @@ import {
2
2
  ClientReconnection,
3
3
  JoinError,
4
4
  PROTOCOL_VERSION
5
- } from "./chunk-CSQEEANB.js";
5
+ } from "./chunk-7J3YWPCA.js";
6
6
 
7
7
  // src/join.ts
8
8
  import { Client as Client2 } from "@colyseus/sdk";
@@ -55,7 +55,7 @@ var AuthorityJoinOption = {
55
55
  * refused with 400. */
56
56
  SUCCESSOR_CLOSED: "successorClosed"
57
57
  };
58
- var AUTHORITY_SDK_LABEL = "ts/0.17.8";
58
+ var AUTHORITY_SDK_LABEL = "ts/0.17.10";
59
59
  var AuthorityCaps = {
60
60
  /** Decodes and draws §17.10's physics bodies. A physics room refuses a join without it (426). An
61
61
  * SDK sends it only once its drawing passes `physics-draw.json` and, for an engine SDK, its own
@@ -149,6 +149,7 @@ var JoinError = {
149
149
  /** No authority server can take the room right now, or admission could not be checked. Retry later. */
150
150
  AUTHORITY_CAPACITY: 503
151
151
  };
152
+ var FREE_QUOTA_REFUSAL = "free_quota_exhausted";
152
153
  var STAGING_ROOM_PREFIX = "preview--";
153
154
  var roomKeyFor = (slug, channel) => channel === "staging" ? `${STAGING_ROOM_PREFIX}${slug}` : slug;
154
155
  var slugOfRoomKey = (key) => key.startsWith(STAGING_ROOM_PREFIX) ? key.slice(STAGING_ROOM_PREFIX.length) : key;
@@ -494,6 +495,7 @@ export {
494
495
  SERVER_OWNED_JOIN_OPTIONS,
495
496
  AUTHORITY_SERVER_OWNED_JOIN_OPTIONS,
496
497
  JoinError,
498
+ FREE_QUOTA_REFUSAL,
497
499
  STAGING_ROOM_PREFIX,
498
500
  roomKeyFor,
499
501
  slugOfRoomKey,
@@ -19,7 +19,7 @@ import {
19
19
  JoinError,
20
20
  Limits,
21
21
  isReservedEventType
22
- } from "./chunk-CSQEEANB.js";
22
+ } from "./chunk-7J3YWPCA.js";
23
23
 
24
24
  // src/authority/room-key.ts
25
25
  var AuthorityRoomLimits = {
@@ -55,7 +55,7 @@ function matchKeyOf(value2) {
55
55
  if (value2 === void 0 || value2 === "") return "";
56
56
  return validMatchKey(value2) ? value2 : null;
57
57
  }
58
- var AuthorityJoinMethod = { JoinOrCreate: "joinOrCreate", Create: "create", JoinById: "joinById" };
58
+ var AuthorityJoinMethod = { JoinOrCreate: "joinOrCreate", Create: "create", JoinById: "joinById", Join: "join" };
59
59
  var AuthorityTargetRefusal = { BadMatchKey: "bad_match_key", BadCode: "bad_code", Conflict: "conflict" };
60
60
  function planAuthorityJoin(target) {
61
61
  const key = target.matchKey ?? "";
@@ -8,7 +8,7 @@ import {
8
8
  waitForFirstState,
9
9
  warnProtocolRefusal,
10
10
  withoutReconnection
11
- } from "./chunk-FPWP22Y7.js";
11
+ } from "./chunk-42R7NREA.js";
12
12
  import {
13
13
  ClientMessage,
14
14
  ClientReconnection,
@@ -23,7 +23,7 @@ import {
23
23
  SEND_TIME_KEY,
24
24
  ServerMessage,
25
25
  isReservedEventType
26
- } from "./chunk-CSQEEANB.js";
26
+ } from "./chunk-7J3YWPCA.js";
27
27
 
28
28
  // src/index.ts
29
29
  import { getStateCallbacks } from "@colyseus/sdk";
@@ -5,7 +5,7 @@ import {
5
5
  joinOptions,
6
6
  useSdkReconnection,
7
7
  waitForFirstState
8
- } from "./chunk-FPWP22Y7.js";
8
+ } from "./chunk-42R7NREA.js";
9
9
  import {
10
10
  udpFastOpener
11
11
  } from "./chunk-YWQ3ALYY.js";
@@ -60,7 +60,7 @@ import {
60
60
  serverTick,
61
61
  tickInstant,
62
62
  validRoomCode
63
- } from "./chunk-NFMGIKFZ.js";
63
+ } from "./chunk-HHETHPGL.js";
64
64
  import {
65
65
  RemotePredict
66
66
  } from "./chunk-OD6NRSX2.js";
@@ -83,14 +83,22 @@ import {
83
83
  AuthorityTiming,
84
84
  ClientReconnection,
85
85
  CloseCode,
86
+ FREE_QUOTA_REFUSAL,
86
87
  JoinError,
87
88
  RoomType,
88
89
  ServerMessage,
89
90
  authorityCloseCodeOf
90
- } from "./chunk-CSQEEANB.js";
91
+ } from "./chunk-7J3YWPCA.js";
91
92
 
92
93
  // src/authority/regions.ts
93
94
  var AUTHORITY_REFUSALS_PER_REGION = 2;
95
+ var AUTHORITY_MAX_PING_MS = 350;
96
+ var RegionRule = {
97
+ /** A room with players in any region in reach, nearest first; else a new room in the nearest region. */
98
+ Players: "players",
99
+ /** The nearest region alone, whoever is elsewhere. */
100
+ Nearest: "nearest"
101
+ };
94
102
  var isUrl = (u) => typeof u === "string" && u.length > 0;
95
103
  function normalizeAuthorityRegions(regions, urls) {
96
104
  const out = [];
@@ -112,6 +120,9 @@ function regionProbePlan(urls, samples) {
112
120
  }
113
121
  var answered = (ms) => typeof ms === "number" && Number.isFinite(ms) && ms >= 0;
114
122
  function rankAuthorityRegions(regions, best) {
123
+ return rankWithLatency(regions, best).map((x) => x.pick);
124
+ }
125
+ function rankWithLatency(regions, best) {
115
126
  const heard = [];
116
127
  const silent = [];
117
128
  regions.forEach((r, index) => {
@@ -126,7 +137,17 @@ function rankAuthorityRegions(regions, best) {
126
137
  (ms === null ? silent : heard).push({ index, ms, pick: { region: r.region, url } });
127
138
  });
128
139
  heard.sort((a, b) => a.ms - b.ms || a.index - b.index);
129
- return [...heard, ...silent].map((x) => x.pick);
140
+ return [...heard, ...silent];
141
+ }
142
+ function planAuthoritySearch(regions, best, options = {}) {
143
+ const ranked = rankWithLatency(regions, best);
144
+ const create = ranked.map((x) => x.pick);
145
+ const pinned = typeof options.region === "string" ? ranked.find((x) => x.pick.region === options.region) : void 0;
146
+ if (pinned !== void 0) return { search: [], create: [pinned.pick] };
147
+ if (options.rule === RegionRule.Nearest) return { search: [], create };
148
+ const limit = answered(options.maxPingMs) ? options.maxPingMs : AUTHORITY_MAX_PING_MS;
149
+ const reach = ranked.filter((x) => x.ms !== null && x.ms <= limit).map((x) => x.pick);
150
+ return { search: reach.length >= 2 ? reach : [], create };
130
151
  }
131
152
  function capacityWalk(regionCount, delays) {
132
153
  const attempts = [{ region: 0, waitMs: 0 }];
@@ -150,6 +171,16 @@ function refusalKind(code) {
150
171
  if (typeof code !== "number" || code <= 0 || DEAD_PATH_REFUSALS.has(code)) return RefusalKind.NextRegion;
151
172
  return CAPACITY_REFUSALS.has(code) ? RefusalKind.Capacity : RefusalKind.Final;
152
173
  }
174
+ var SearchRefusal = {
175
+ /** No room here (Colyseus's 521, no room matches the criteria), a dead path, a full or draining
176
+ * region: the next region is asked. */
177
+ Next: "next",
178
+ /** The server's answer about this player or game, which every region would repeat. */
179
+ Final: "final"
180
+ };
181
+ function searchRefusalKind(code) {
182
+ return refusalKind(code) === RefusalKind.Final ? SearchRefusal.Final : SearchRefusal.Next;
183
+ }
153
184
  function nextAttempt(state, regionCount, delays) {
154
185
  const refused = state.refused + 1;
155
186
  if (refused >= AUTHORITY_REFUSALS_PER_REGION && state.region + 1 < regionCount) {
@@ -163,10 +194,13 @@ function nextAttempt(state, regionCount, delays) {
163
194
  async function selectAuthorityRegions(regions, options = {}) {
164
195
  if (regions.length === 0) return [];
165
196
  if (regions.length === 1) return rankAuthorityRegions(regions, []);
197
+ return rankAuthorityRegions(regions, await probeBest(regions, options));
198
+ }
199
+ async function probeBest(regions, options) {
166
200
  const samples = Math.max(1, options.samples ?? RELAY_SELECT_DEFAULTS.SAMPLES);
167
201
  const plans = regions.map((r) => regionProbePlan(r.urls, samples));
168
202
  const results = await probeLatencies(plans, options);
169
- const best = regions.map(
203
+ return regions.map(
170
204
  (r, i) => r.urls.map((url) => {
171
205
  let min;
172
206
  plans[i]?.forEach((planned, n) => {
@@ -176,7 +210,10 @@ async function selectAuthorityRegions(regions, options = {}) {
176
210
  return min;
177
211
  })
178
212
  );
179
- return rankAuthorityRegions(regions, best);
213
+ }
214
+ async function selectAuthoritySearch(regions, search = {}, options = {}) {
215
+ if (regions.length <= 1) return planAuthoritySearch(regions, [], search);
216
+ return planAuthoritySearch(regions, await probeBest(regions, options), search);
180
217
  }
181
218
  async function probeLatencies(plans, options = {}) {
182
219
  const probe = options.probe ?? defaultProbe;
@@ -4654,6 +4691,32 @@ var ENTITY_MOTION_FIELDS = Object.keys(blankEntityMotion());
4654
4691
  var SEAT_MOTION_FIELDS = Object.keys(blankSeatEcho()).filter((f) => f !== "inAck");
4655
4692
  var motionFieldsOf = (kind) => kind === MotionRecordKind.Entity ? ENTITY_MOTION_FIELDS : SEAT_MOTION_FIELDS;
4656
4693
  var ROOT_TICK_FIELDS = ["tick", "keyframe"];
4694
+ var SETTLE_ACK_TRAIL = 64;
4695
+ function settleAckTrail() {
4696
+ let trail = [];
4697
+ let floor = 0;
4698
+ return {
4699
+ snapshot(tick, ack) {
4700
+ const last = trail.at(-1)?.ack ?? floor;
4701
+ if (ack <= last) return;
4702
+ trail.push({ tick, ack });
4703
+ if (trail.length > SETTLE_ACK_TRAIL) trail = trail.slice(-SETTLE_ACK_TRAIL);
4704
+ },
4705
+ through(tick) {
4706
+ let kept = 0;
4707
+ while (kept < trail.length && trail[kept].tick <= tick) {
4708
+ floor = Math.max(floor, trail[kept].ack);
4709
+ kept += 1;
4710
+ }
4711
+ if (kept > 0) trail = trail.slice(kept);
4712
+ return floor;
4713
+ },
4714
+ reset(at2) {
4715
+ trail = [];
4716
+ floor = at2;
4717
+ }
4718
+ };
4719
+ }
4657
4720
  function defaultFastLog(line) {
4658
4721
  const stderr = globalThis.process?.stderr;
4659
4722
  if (stderr?.write !== void 0) stderr.write(`${line}
@@ -4692,6 +4755,7 @@ function fastSeat(o) {
4692
4755
  let link = null;
4693
4756
  let fallback = null;
4694
4757
  let fastAck = 0;
4758
+ const settle2 = settleAckTrail();
4695
4759
  let early = [];
4696
4760
  let pendingBind = null;
4697
4761
  let offerAwaitedFrom = null;
@@ -4764,6 +4828,7 @@ function fastSeat(o) {
4764
4828
  const base = seqBase();
4765
4829
  const wsBefore = fallback.wsBefore + (handle.sentCount - fallback.at);
4766
4830
  fastAck = ack();
4831
+ settle2.reset(fastAck);
4767
4832
  link = { client: p.client, seqBase: base, wsBefore, stampAtBind: baselines?._lastStamp ?? 0 };
4768
4833
  fallback = null;
4769
4834
  retryAt = null;
@@ -4831,6 +4896,7 @@ function fastSeat(o) {
4831
4896
  if (at2 !== void 0) rtt = o.now() - at2;
4832
4897
  fastAck = acked;
4833
4898
  }
4899
+ settle2.snapshot(s.tick, fastAck);
4834
4900
  room.clock.sample(s.sent, rtt);
4835
4901
  guard?.write(s);
4836
4902
  };
@@ -4852,6 +4918,7 @@ function fastSeat(o) {
4852
4918
  askRoundTrip(client);
4853
4919
  link = { client, seqBase: seqBase(), wsBefore: handle.sentCount, stampAtBind: baselines?._lastStamp ?? 0 };
4854
4920
  fastAck = 0;
4921
+ settle2.reset(0);
4855
4922
  status.live = true;
4856
4923
  liveSince = o.now();
4857
4924
  for (const s of early) client.queue({ ...s, seq: link.seqBase + s.seq });
@@ -4890,6 +4957,10 @@ function fastSeat(o) {
4890
4957
  return {
4891
4958
  status,
4892
4959
  ack,
4960
+ settleAck() {
4961
+ if (link === null) return ack();
4962
+ return Math.min(ack(), settle2.through(guard?.webSocketTick() ?? Number(room.state.tick ?? 0)));
4963
+ },
4893
4964
  sent(seq, tick, input) {
4894
4965
  if (o.open === void 0 || fallback !== null) return;
4895
4966
  const render = renderStamp();
@@ -5065,6 +5136,9 @@ function motionGuard(room, live) {
5065
5136
  }
5066
5137
  });
5067
5138
  return {
5139
+ webSocketTick() {
5140
+ return Number(held.get(state)?.get("tick")?.ws ?? room.state.tick ?? 0);
5141
+ },
5068
5142
  write(s) {
5069
5143
  learn();
5070
5144
  const changes = [];
@@ -5233,12 +5307,16 @@ var SessionEvent = {
5233
5307
  var SESSION_EVENTS = new Set(Object.values(SessionEvent));
5234
5308
  var MESSAGE = {
5235
5309
  protocol: `[multiplayer] the authority server refused protocol ${AUTHORITY_PROTOCOL_VERSION} (code 426) \u2014 this game was built with a @genex-ai/multiplayer that the server no longer serves. Update the package and republish.`,
5236
- notEntitled: "[multiplayer] server-authoritative rooms are not available for this game (code 402): its owner is not entitled to them. This is final; the session does not retry."
5310
+ notEntitled: "[multiplayer] server-authoritative rooms are not available for this game (code 402): its owner is not entitled to them. This is final; the session does not retry.",
5311
+ freeQuota: "[multiplayer] no new server-authoritative room for this game (code 429): its owner is on Genex's free tier and has used the free included room time for this period. Rooms already running are not affected; new rooms open again next period, or with Genex Pro."
5237
5312
  };
5238
5313
  var errorCode = (err) => err && typeof err === "object" ? err.code : void 0;
5314
+ var errorMessage = (err) => err && typeof err === "object" ? err.message : void 0;
5315
+ var isFreeQuotaRefusal = (err) => errorCode(err) === JoinError.ROOM_QUOTA && errorMessage(err) === FREE_QUOTA_REFUSAL;
5239
5316
  function explainAuthorityRefusal(err) {
5240
5317
  if (isProtocolRefusal(err)) console.error(MESSAGE.protocol);
5241
5318
  else if (errorCode(err) === JoinError.NOT_ENTITLED) console.error(MESSAGE.notEntitled);
5319
+ else if (isFreeQuotaRefusal(err)) console.error(MESSAGE.freeQuota);
5242
5320
  throw err;
5243
5321
  }
5244
5322
  var predictsPhysics = (opts) => opts.physicsCore !== void 0 && opts.predictPhysics !== false;
@@ -5246,17 +5324,38 @@ function resimBudgetMs() {
5246
5324
  const agent = typeof navigator === "undefined" ? "" : String(navigator.userAgent ?? "");
5247
5325
  return /Mobi|Android|iPhone|iPad/i.test(agent) ? PHYS_RESIM_BUDGET_MS.mobile : PHYS_RESIM_BUDGET_MS.desktop;
5248
5326
  }
5249
- async function joinTargets(opts) {
5250
- if (opts.url) return [opts.url];
5327
+ async function joinTargets(opts, method) {
5328
+ if (opts.url) return { search: [], create: [opts.url] };
5251
5329
  const regions = normalizeAuthorityRegions(opts.regions, opts.urls);
5252
5330
  if (regions.length === 0) throw new Error("genex multiplayer: `urls` must contain at least one authority server URL");
5253
- const ranked = await selectAuthorityRegions(regions, opts.probe === void 0 ? {} : { probe: opts.probe });
5254
- return ranked.map((pick) => pick.url);
5331
+ const pool = method === AuthorityJoinMethod.JoinOrCreate;
5332
+ const plan = await selectAuthoritySearch(
5333
+ regions,
5334
+ {
5335
+ rule: pool ? opts.regionRule : RegionRule.Nearest,
5336
+ maxPingMs: opts.maxPingMs,
5337
+ ...method === AuthorityJoinMethod.JoinById ? {} : { region: opts.region }
5338
+ },
5339
+ opts.probe === void 0 ? {} : { probe: opts.probe }
5340
+ );
5341
+ return { search: plan.search.map((pick) => pick.url), create: plan.create.map((pick) => pick.url) };
5342
+ }
5343
+ async function joinWherePlayersAre(opts, plan, search, targets) {
5344
+ for (const url of search) {
5345
+ try {
5346
+ return { room: await joinOnce(new Client(url), opts, { ...plan, method: AuthorityJoinMethod.Join }), url, targets };
5347
+ } catch (err) {
5348
+ if (searchRefusalKind(errorCode(err)) === SearchRefusal.Final) explainAuthorityRefusal(err);
5349
+ }
5350
+ }
5351
+ return null;
5255
5352
  }
5256
5353
  async function joinAuthority(opts, target) {
5257
5354
  const plan = planAuthorityJoin(target);
5258
5355
  if ("refused" in plan) throw new TypeError(`genex multiplayer: this room cannot be asked for (${plan.refused})`);
5259
- const targets = await joinTargets(opts);
5356
+ const { search, create: targets } = await joinTargets(opts, plan.method);
5357
+ const found = await joinWherePlayersAre(opts, plan, search, targets);
5358
+ if (found !== null) return found;
5260
5359
  const delays = opts.capacityRetryMs ?? CAPACITY_RETRY_MS;
5261
5360
  let state = { region: 0, refused: 0, step: 0 };
5262
5361
  for (; ; ) {
@@ -5299,6 +5398,7 @@ function joinOnce(client, opts, plan) {
5299
5398
  };
5300
5399
  if (plan.method === AuthorityJoinMethod.JoinById) return client.joinById(plan.roomId, options);
5301
5400
  if (plan.method === AuthorityJoinMethod.Create) return client.create(RoomType.AUTHORITY, options);
5401
+ if (plan.method === AuthorityJoinMethod.Join) return client.join(RoomType.AUTHORITY, options);
5302
5402
  return client.joinOrCreate(RoomType.AUTHORITY, options);
5303
5403
  }
5304
5404
  function roomPreset(presetText) {
@@ -5965,7 +6065,7 @@ function attachAuthoritySession(room, opts, url) {
5965
6065
  const unsettled = /* @__PURE__ */ new Map();
5966
6066
  const settleShots = () => {
5967
6067
  if (unsettled.size === 0) return;
5968
- const acked = fast.ack();
6068
+ const acked = fast.settleAck();
5969
6069
  for (const [shot, drop] of unsettled) {
5970
6070
  if (shot.epoch !== handle.epoch || shot.seq > acked || entityMap().has(shot.id)) continue;
5971
6071
  unsettled.delete(shot);
@@ -6687,13 +6787,19 @@ function attachAuthoritySession(room, opts, url) {
6687
6787
 
6688
6788
  export {
6689
6789
  AUTHORITY_REFUSALS_PER_REGION,
6790
+ AUTHORITY_MAX_PING_MS,
6791
+ RegionRule,
6690
6792
  normalizeAuthorityRegions,
6691
6793
  regionProbePlan,
6692
6794
  rankAuthorityRegions,
6795
+ planAuthoritySearch,
6693
6796
  capacityWalk,
6694
6797
  RefusalKind,
6695
6798
  refusalKind,
6799
+ SearchRefusal,
6800
+ searchRefusalKind,
6696
6801
  selectAuthorityRegions,
6802
+ selectAuthoritySearch,
6697
6803
  REJOIN,
6698
6804
  SUCCESSOR_OPEN_MS,
6699
6805
  RejoinWay,
package/dist/index.js CHANGED
@@ -3,9 +3,9 @@ import {
3
3
  createPrivate,
4
4
  joinPrivate,
5
5
  matchmake
6
- } from "./chunk-QY3QQNDJ.js";
7
- import "./chunk-FPWP22Y7.js";
8
- import "./chunk-CSQEEANB.js";
6
+ } from "./chunk-NSQQCLMA.js";
7
+ import "./chunk-42R7NREA.js";
8
+ import "./chunk-7J3YWPCA.js";
9
9
  export {
10
10
  connect,
11
11
  createPrivate,
@@ -76,7 +76,7 @@ interface AuthorityDrainNotice {
76
76
  drainMs: number;
77
77
  }
78
78
  /** The SDK label this TypeScript client sends. tests hold it to package.json. */
79
- declare const AUTHORITY_SDK_LABEL = "ts/0.17.8";
79
+ declare const AUTHORITY_SDK_LABEL = "ts/0.17.10";
80
80
  /** Client capabilities (§17.10 *Joining*). */
81
81
  declare const AuthorityCaps: {
82
82
  /** Decodes and draws §17.10's physics bodies. A physics room refuses a join without it (426). An
@@ -177,6 +177,9 @@ declare const JoinError: {
177
177
  /** No authority server can take the room right now, or admission could not be checked. Retry later. */
178
178
  readonly AUTHORITY_CAPACITY: 503;
179
179
  };
180
+ /** The ROOM_QUOTA refusal's reason when the game's owner is on the free tier and has used its
181
+ * included room time for this period (the API's `AdmitRefusal.FreeQuotaExhausted`). */
182
+ declare const FREE_QUOTA_REFUSAL = "free_quota_exhausted";
180
183
  /** A preview (staging) build's rooms: the relay keys them `preview--<slug>`, apart from the live
181
184
  * game's rooms, so testers on a preview link play together and never meet real players. The
182
185
  * client always sends the plain slug as `gameId`; the relay picks the room from the token's
@@ -636,4 +639,4 @@ declare const ClockSync: {
636
639
  readonly WARMUP_ACKS: 30;
637
640
  };
638
641
 
639
- export { AUTHORITY_ENCODER_BUFFER_BYTES, AUTHORITY_MAX_FRAME_BYTES, AUTHORITY_MAX_MESSAGES_PER_SECOND, AUTHORITY_MIN_PROTOCOL_VERSION, AUTHORITY_PHYSICS_TICK_WEIGHT, AUTHORITY_PHYSICS_UNITS, AUTHORITY_PROTOCOL_VERSION, AUTHORITY_ROOM_ENDED_TEXT, AUTHORITY_SDK_LABEL, AUTHORITY_SERVER_OWNED_JOIN_OPTIONS, AUTHORITY_WINDOW, AuthorityCaps, AuthorityCloseCode, type AuthorityDrainNotice, AuthorityJoinOption, AuthorityTiming, type ChatMessage, ClientMessage, type ClientMessageType, ClientReconnection, ClockSync, CloseCode, GLOBAL_RATE, type IceConfig, type IceServer, type InputEnvelope, Interpolation, JoinError, JoinOption, Limits, MAX_MESSAGES_PER_SECOND, MESSAGE_LANE, MIN_PROTOCOL_VERSION, type MatchEnded, type ObjectControlOperation, type ObjectControlReason, type ObjectControlRequest, type ObjectControlResult, type ObjectPublish, POSE_KEYS, PROTOCOL_VERSION, type PoseKey, type PosePublish, type ProtocolWindow, RATE_LANES, RELAY_WINDOW, RESERVED_EVENT_PREFIXES, RESERVED_EVENT_TYPES, RESERVED_SHARED_PREFIX, type RateLane, RelayTiming, RoomType, SEND_TIME_KEY, SERVER_OWNED_JOIN_OPTIONS, STAGING_ROOM_PREFIX, SeatCloseReason, ServerMessage, type ServerMessageType, type SharedWrite, type VoiceSignal, type VoiceSignalEnvelope, authorityCloseCodeOf, authorityPhysicsBudgetSixtieths, authorityRoomUnits, authorityTickBudgetMs, capsOf, inProtocolWindow, isReservedEventType, roomKeyFor, slugOfRoomKey };
642
+ export { AUTHORITY_ENCODER_BUFFER_BYTES, AUTHORITY_MAX_FRAME_BYTES, AUTHORITY_MAX_MESSAGES_PER_SECOND, AUTHORITY_MIN_PROTOCOL_VERSION, AUTHORITY_PHYSICS_TICK_WEIGHT, AUTHORITY_PHYSICS_UNITS, AUTHORITY_PROTOCOL_VERSION, AUTHORITY_ROOM_ENDED_TEXT, AUTHORITY_SDK_LABEL, AUTHORITY_SERVER_OWNED_JOIN_OPTIONS, AUTHORITY_WINDOW, AuthorityCaps, AuthorityCloseCode, type AuthorityDrainNotice, AuthorityJoinOption, AuthorityTiming, type ChatMessage, ClientMessage, type ClientMessageType, ClientReconnection, ClockSync, CloseCode, FREE_QUOTA_REFUSAL, GLOBAL_RATE, type IceConfig, type IceServer, type InputEnvelope, Interpolation, JoinError, JoinOption, Limits, MAX_MESSAGES_PER_SECOND, MESSAGE_LANE, MIN_PROTOCOL_VERSION, type MatchEnded, type ObjectControlOperation, type ObjectControlReason, type ObjectControlRequest, type ObjectControlResult, type ObjectPublish, POSE_KEYS, PROTOCOL_VERSION, type PoseKey, type PosePublish, type ProtocolWindow, RATE_LANES, RELAY_WINDOW, RESERVED_EVENT_PREFIXES, RESERVED_EVENT_TYPES, RESERVED_SHARED_PREFIX, type RateLane, RelayTiming, RoomType, SEND_TIME_KEY, SERVER_OWNED_JOIN_OPTIONS, STAGING_ROOM_PREFIX, SeatCloseReason, ServerMessage, type ServerMessageType, type SharedWrite, type VoiceSignal, type VoiceSignalEnvelope, authorityCloseCodeOf, authorityPhysicsBudgetSixtieths, authorityRoomUnits, authorityTickBudgetMs, capsOf, inProtocolWindow, isReservedEventType, roomKeyFor, slugOfRoomKey };
package/dist/protocol.js CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  ClientReconnection,
19
19
  ClockSync,
20
20
  CloseCode,
21
+ FREE_QUOTA_REFUSAL,
21
22
  GLOBAL_RATE,
22
23
  Interpolation,
23
24
  JoinError,
@@ -49,7 +50,7 @@ import {
49
50
  isReservedEventType,
50
51
  roomKeyFor,
51
52
  slugOfRoomKey
52
- } from "./chunk-CSQEEANB.js";
53
+ } from "./chunk-7J3YWPCA.js";
53
54
  export {
54
55
  AUTHORITY_ENCODER_BUFFER_BYTES,
55
56
  AUTHORITY_MAX_FRAME_BYTES,
@@ -70,6 +71,7 @@ export {
70
71
  ClientReconnection,
71
72
  ClockSync,
72
73
  CloseCode,
74
+ FREE_QUOTA_REFUSAL,
73
75
  GLOBAL_RATE,
74
76
  Interpolation,
75
77
  JoinError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genex-ai/multiplayer",
3
- "version": "0.17.8",
3
+ "version": "0.17.10",
4
4
  "description": "The multiplayer client wrapper + shared room schema for genex.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",