@genex-ai/multiplayer 0.17.9 → 0.17.11
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/PROTOCOL.md +3 -1
- package/README.md +1 -1
- package/dist/authority/fast-webtransport.js +2 -2
- package/dist/authority/index.d.ts +84 -2
- package/dist/authority/index.js +26 -4
- package/dist/bridge-authority.global.js +8 -8
- package/dist/bridge-authority.js +4 -4
- package/dist/bridge.js +3 -3
- package/dist/{chunk-WEMRRIHH.js → chunk-2CSX5WA6.js} +1 -1
- package/dist/{chunk-ZDGSUR6E.js → chunk-5WENVWVO.js} +4 -3
- package/dist/{chunk-TEHGMFAG.js → chunk-BB6OIWQ2.js} +1 -1
- package/dist/{chunk-MQYARUGU.js → chunk-I3DNVGGC.js} +178 -18
- package/dist/{chunk-DJ2XYETS.js → chunk-OESKZODQ.js} +2 -2
- package/dist/index.js +3 -3
- package/dist/protocol.d.ts +1 -1
- package/dist/protocol.js +1 -1
- package/package.json +1 -1
package/dist/bridge-authority.js
CHANGED
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
} from "./chunk-4R7C2TLH.js";
|
|
10
10
|
import {
|
|
11
11
|
connectAuthority
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-I3DNVGGC.js";
|
|
13
|
+
import "./chunk-BB6OIWQ2.js";
|
|
14
14
|
import "./chunk-YWQ3ALYY.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-5WENVWVO.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-
|
|
25
|
+
} from "./chunk-2CSX5WA6.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-
|
|
19
|
-
import "./chunk-
|
|
18
|
+
} from "./chunk-OESKZODQ.js";
|
|
19
|
+
import "./chunk-BB6OIWQ2.js";
|
|
20
20
|
import {
|
|
21
21
|
Limits,
|
|
22
22
|
RESERVED_SHARED_PREFIX,
|
|
23
23
|
ServerMessage,
|
|
24
24
|
isReservedEventType
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-2CSX5WA6.js";
|
|
26
26
|
|
|
27
27
|
// src/bridge.ts
|
|
28
28
|
var version = 2;
|
|
@@ -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.
|
|
58
|
+
var AUTHORITY_SDK_LABEL = "ts/0.17.11";
|
|
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
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
JoinError,
|
|
20
20
|
Limits,
|
|
21
21
|
isReservedEventType
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-2CSX5WA6.js";
|
|
23
23
|
|
|
24
24
|
// src/authority/room-key.ts
|
|
25
25
|
var AuthorityRoomLimits = {
|
|
@@ -31,6 +31,7 @@ var AuthorityRoomLimits = {
|
|
|
31
31
|
MAX_WORLDS: 16
|
|
32
32
|
};
|
|
33
33
|
var ROOM_NOT_FOUND = 522;
|
|
34
|
+
var ROOM_NOT_FOUND_AS_SENT = 500;
|
|
34
35
|
var inRange = (c, lo, hi) => c >= lo.charCodeAt(0) && c <= hi.charCodeAt(0);
|
|
35
36
|
var isLowerOrDigit = (c) => inRange(c, "a", "z") || inRange(c, "0", "9");
|
|
36
37
|
var KEY_MARKS = "._:-";
|
|
@@ -55,7 +56,7 @@ function matchKeyOf(value2) {
|
|
|
55
56
|
if (value2 === void 0 || value2 === "") return "";
|
|
56
57
|
return validMatchKey(value2) ? value2 : null;
|
|
57
58
|
}
|
|
58
|
-
var AuthorityJoinMethod = { JoinOrCreate: "joinOrCreate", Create: "create", JoinById: "joinById" };
|
|
59
|
+
var AuthorityJoinMethod = { JoinOrCreate: "joinOrCreate", Create: "create", JoinById: "joinById", Join: "join" };
|
|
59
60
|
var AuthorityTargetRefusal = { BadMatchKey: "bad_match_key", BadCode: "bad_code", Conflict: "conflict" };
|
|
60
61
|
function planAuthorityJoin(target) {
|
|
61
62
|
const key = target.matchKey ?? "";
|
|
@@ -71,7 +72,7 @@ function planAuthorityJoin(target) {
|
|
|
71
72
|
return { method: AuthorityJoinMethod.JoinOrCreate, options };
|
|
72
73
|
}
|
|
73
74
|
function nextCodeRegion(error, region, regions) {
|
|
74
|
-
const elsewhere = error === JoinError.WRONG_REGION || error === ROOM_NOT_FOUND;
|
|
75
|
+
const elsewhere = error === JoinError.WRONG_REGION || error === ROOM_NOT_FOUND || error === ROOM_NOT_FOUND_AS_SENT;
|
|
75
76
|
return elsewhere && region + 1 < regions ? region + 1 : null;
|
|
76
77
|
}
|
|
77
78
|
function selectMatchWorld(worlds, world, key) {
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
joinOptions,
|
|
6
6
|
useSdkReconnection,
|
|
7
7
|
waitForFirstState
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-BB6OIWQ2.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-
|
|
63
|
+
} from "./chunk-5WENVWVO.js";
|
|
64
64
|
import {
|
|
65
65
|
RemotePredict
|
|
66
66
|
} from "./chunk-OD6NRSX2.js";
|
|
@@ -88,10 +88,18 @@ import {
|
|
|
88
88
|
RoomType,
|
|
89
89
|
ServerMessage,
|
|
90
90
|
authorityCloseCodeOf
|
|
91
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-2CSX5WA6.js";
|
|
92
92
|
|
|
93
93
|
// src/authority/regions.ts
|
|
94
94
|
var AUTHORITY_REFUSALS_PER_REGION = 2;
|
|
95
|
+
var AUTHORITY_MAX_PING_MS = 350;
|
|
96
|
+
var AUTHORITY_REGROUP_WAITS_MS = [2e3, 4e3, 9e3, 15e3, 3e4];
|
|
97
|
+
var RegionRule = {
|
|
98
|
+
/** A room with players in any region in reach, nearest first; else a new room in the nearest region. */
|
|
99
|
+
Players: "players",
|
|
100
|
+
/** The nearest region alone, whoever is elsewhere. */
|
|
101
|
+
Nearest: "nearest"
|
|
102
|
+
};
|
|
95
103
|
var isUrl = (u) => typeof u === "string" && u.length > 0;
|
|
96
104
|
function normalizeAuthorityRegions(regions, urls) {
|
|
97
105
|
const out = [];
|
|
@@ -113,6 +121,9 @@ function regionProbePlan(urls, samples) {
|
|
|
113
121
|
}
|
|
114
122
|
var answered = (ms) => typeof ms === "number" && Number.isFinite(ms) && ms >= 0;
|
|
115
123
|
function rankAuthorityRegions(regions, best) {
|
|
124
|
+
return rankWithLatency(regions, best).map((x) => x.pick);
|
|
125
|
+
}
|
|
126
|
+
function rankWithLatency(regions, best) {
|
|
116
127
|
const heard = [];
|
|
117
128
|
const silent = [];
|
|
118
129
|
regions.forEach((r, index) => {
|
|
@@ -127,7 +138,17 @@ function rankAuthorityRegions(regions, best) {
|
|
|
127
138
|
(ms === null ? silent : heard).push({ index, ms, pick: { region: r.region, url } });
|
|
128
139
|
});
|
|
129
140
|
heard.sort((a, b) => a.ms - b.ms || a.index - b.index);
|
|
130
|
-
return [...heard, ...silent]
|
|
141
|
+
return [...heard, ...silent];
|
|
142
|
+
}
|
|
143
|
+
function planAuthoritySearch(regions, best, options = {}) {
|
|
144
|
+
const ranked = rankWithLatency(regions, best);
|
|
145
|
+
const create = ranked.map((x) => x.pick);
|
|
146
|
+
const pinned = typeof options.region === "string" ? ranked.find((x) => x.pick.region === options.region) : void 0;
|
|
147
|
+
if (pinned !== void 0) return { search: [], create: [pinned.pick] };
|
|
148
|
+
if (options.rule === RegionRule.Nearest) return { search: [], create };
|
|
149
|
+
const limit = answered(options.maxPingMs) ? options.maxPingMs : AUTHORITY_MAX_PING_MS;
|
|
150
|
+
const reach = ranked.filter((x) => x.ms !== null && x.ms <= limit).map((x) => x.pick);
|
|
151
|
+
return { search: reach.length >= 2 ? reach : [], create };
|
|
131
152
|
}
|
|
132
153
|
function capacityWalk(regionCount, delays) {
|
|
133
154
|
const attempts = [{ region: 0, waitMs: 0 }];
|
|
@@ -151,6 +172,34 @@ function refusalKind(code) {
|
|
|
151
172
|
if (typeof code !== "number" || code <= 0 || DEAD_PATH_REFUSALS.has(code)) return RefusalKind.NextRegion;
|
|
152
173
|
return CAPACITY_REFUSALS.has(code) ? RefusalKind.Capacity : RefusalKind.Final;
|
|
153
174
|
}
|
|
175
|
+
function planAuthorityRegroup(regions, best, options = {}, joined) {
|
|
176
|
+
if (options.rule === RegionRule.Nearest) return [];
|
|
177
|
+
if (typeof options.region === "string" && regions.some((r) => r.region === options.region)) return [];
|
|
178
|
+
const at2 = regions.findIndex((r) => r.region === joined);
|
|
179
|
+
if (at2 < 0) return [];
|
|
180
|
+
const limit = answered(options.maxPingMs) ? options.maxPingMs : AUTHORITY_MAX_PING_MS;
|
|
181
|
+
return rankWithLatency(regions, best).filter((x) => x.index < at2 && x.ms !== null && x.ms <= limit).map((x) => x.pick);
|
|
182
|
+
}
|
|
183
|
+
function authorityRegionOf(regions, url) {
|
|
184
|
+
return regions.find((r) => r.urls.includes(url))?.region;
|
|
185
|
+
}
|
|
186
|
+
async function measureAuthorityRegions(regions, options = {}) {
|
|
187
|
+
const best = regions.length <= 1 ? [] : await probeAuthorityRegions(regions, options);
|
|
188
|
+
return regions.map((r, i) => {
|
|
189
|
+
const heard = (best[i] ?? []).filter(answered);
|
|
190
|
+
return { region: r.region, pingMs: heard.length === 0 ? null : Math.min(...heard) };
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
var SearchRefusal = {
|
|
194
|
+
/** No room here (Colyseus's 521, no room matches the criteria), a dead path, a full or draining
|
|
195
|
+
* region: the next region is asked. */
|
|
196
|
+
Next: "next",
|
|
197
|
+
/** The server's answer about this player or game, which every region would repeat. */
|
|
198
|
+
Final: "final"
|
|
199
|
+
};
|
|
200
|
+
function searchRefusalKind(code) {
|
|
201
|
+
return refusalKind(code) === RefusalKind.Final ? SearchRefusal.Final : SearchRefusal.Next;
|
|
202
|
+
}
|
|
154
203
|
function nextAttempt(state, regionCount, delays) {
|
|
155
204
|
const refused = state.refused + 1;
|
|
156
205
|
if (refused >= AUTHORITY_REFUSALS_PER_REGION && state.region + 1 < regionCount) {
|
|
@@ -164,10 +213,13 @@ function nextAttempt(state, regionCount, delays) {
|
|
|
164
213
|
async function selectAuthorityRegions(regions, options = {}) {
|
|
165
214
|
if (regions.length === 0) return [];
|
|
166
215
|
if (regions.length === 1) return rankAuthorityRegions(regions, []);
|
|
216
|
+
return rankAuthorityRegions(regions, await probeAuthorityRegions(regions, options));
|
|
217
|
+
}
|
|
218
|
+
async function probeAuthorityRegions(regions, options) {
|
|
167
219
|
const samples = Math.max(1, options.samples ?? RELAY_SELECT_DEFAULTS.SAMPLES);
|
|
168
220
|
const plans = regions.map((r) => regionProbePlan(r.urls, samples));
|
|
169
221
|
const results = await probeLatencies(plans, options);
|
|
170
|
-
|
|
222
|
+
return regions.map(
|
|
171
223
|
(r, i) => r.urls.map((url) => {
|
|
172
224
|
let min;
|
|
173
225
|
plans[i]?.forEach((planned, n) => {
|
|
@@ -177,7 +229,10 @@ async function selectAuthorityRegions(regions, options = {}) {
|
|
|
177
229
|
return min;
|
|
178
230
|
})
|
|
179
231
|
);
|
|
180
|
-
|
|
232
|
+
}
|
|
233
|
+
async function selectAuthoritySearch(regions, search = {}, options = {}) {
|
|
234
|
+
if (regions.length <= 1) return planAuthoritySearch(regions, [], search);
|
|
235
|
+
return planAuthoritySearch(regions, await probeAuthorityRegions(regions, options), search);
|
|
181
236
|
}
|
|
182
237
|
async function probeLatencies(plans, options = {}) {
|
|
183
238
|
const probe = options.probe ?? defaultProbe;
|
|
@@ -300,6 +355,8 @@ function survivingSession(first, deps) {
|
|
|
300
355
|
const listeners = /* @__PURE__ */ new Map();
|
|
301
356
|
let current = first;
|
|
302
357
|
let left = false;
|
|
358
|
+
let rejoining = false;
|
|
359
|
+
let endWait = null;
|
|
303
360
|
let physicsHash = null;
|
|
304
361
|
let world = null;
|
|
305
362
|
const fire = (event, ...payload) => {
|
|
@@ -312,6 +369,14 @@ function survivingSession(first, deps) {
|
|
|
312
369
|
});
|
|
313
370
|
};
|
|
314
371
|
const rejoin = async (lostCode, lostReason) => {
|
|
372
|
+
rejoining = true;
|
|
373
|
+
try {
|
|
374
|
+
await replaceLostRoom(lostCode, lostReason);
|
|
375
|
+
} finally {
|
|
376
|
+
rejoining = false;
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
const replaceLostRoom = async (lostCode, lostReason) => {
|
|
315
380
|
const startedAt = now();
|
|
316
381
|
const lost = { roomId: current.code, matchKey: current.matchKey, closed: deps.closed };
|
|
317
382
|
const regions = deps.targets.length;
|
|
@@ -362,6 +427,46 @@ function survivingSession(first, deps) {
|
|
|
362
427
|
});
|
|
363
428
|
};
|
|
364
429
|
watch(first);
|
|
430
|
+
const regroupWait = (ms) => {
|
|
431
|
+
if (deps.sleep !== void 0) return deps.sleep(ms);
|
|
432
|
+
return new Promise((resolve) => {
|
|
433
|
+
const timer = setTimeout(done, ms);
|
|
434
|
+
timer.unref?.();
|
|
435
|
+
function done() {
|
|
436
|
+
clearTimeout(timer);
|
|
437
|
+
endWait = null;
|
|
438
|
+
resolve();
|
|
439
|
+
}
|
|
440
|
+
endWait = done;
|
|
441
|
+
});
|
|
442
|
+
};
|
|
443
|
+
const regroup = async (ask) => {
|
|
444
|
+
const waits = AUTHORITY_REGROUP_WAITS_MS;
|
|
445
|
+
let step = 0;
|
|
446
|
+
while (!left) {
|
|
447
|
+
await regroupWait(waits[Math.min(step, waits.length - 1)]);
|
|
448
|
+
if (left) return;
|
|
449
|
+
if (rejoining || current.players().size > 1) {
|
|
450
|
+
step = 0;
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
step += 1;
|
|
454
|
+
const next = await ask().catch(() => null);
|
|
455
|
+
if (next === null) continue;
|
|
456
|
+
if (left || rejoining || current.players().size > 1) {
|
|
457
|
+
await next.leave().catch(() => {
|
|
458
|
+
});
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
const empty = current;
|
|
462
|
+
adopt(next);
|
|
463
|
+
fire(RejoinEvent.Rejoined, { code: next.code, url: next.url, moved: true });
|
|
464
|
+
await empty.leave().catch(() => {
|
|
465
|
+
});
|
|
466
|
+
step = 0;
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
if (deps.regroup !== void 0) void regroup(deps.regroup.bind(deps));
|
|
365
470
|
const own = {
|
|
366
471
|
input,
|
|
367
472
|
frame(frameNow) {
|
|
@@ -392,6 +497,7 @@ function survivingSession(first, deps) {
|
|
|
392
497
|
},
|
|
393
498
|
async leave() {
|
|
394
499
|
left = true;
|
|
500
|
+
endWait?.();
|
|
395
501
|
await current.leave();
|
|
396
502
|
}
|
|
397
503
|
};
|
|
@@ -5288,23 +5394,47 @@ function resimBudgetMs() {
|
|
|
5288
5394
|
const agent = typeof navigator === "undefined" ? "" : String(navigator.userAgent ?? "");
|
|
5289
5395
|
return /Mobi|Android|iPhone|iPad/i.test(agent) ? PHYS_RESIM_BUDGET_MS.mobile : PHYS_RESIM_BUDGET_MS.desktop;
|
|
5290
5396
|
}
|
|
5291
|
-
async function joinTargets(opts) {
|
|
5292
|
-
if (opts.url) return [opts.url];
|
|
5397
|
+
async function joinTargets(opts, method) {
|
|
5398
|
+
if (opts.url) return { search: [], create: [opts.url], regroup: () => [] };
|
|
5293
5399
|
const regions = normalizeAuthorityRegions(opts.regions, opts.urls);
|
|
5294
5400
|
if (regions.length === 0) throw new Error("genex multiplayer: `urls` must contain at least one authority server URL");
|
|
5295
|
-
const
|
|
5296
|
-
|
|
5401
|
+
const pool = method === AuthorityJoinMethod.JoinOrCreate;
|
|
5402
|
+
const options = {
|
|
5403
|
+
rule: pool ? opts.regionRule : RegionRule.Nearest,
|
|
5404
|
+
maxPingMs: opts.maxPingMs,
|
|
5405
|
+
...method === AuthorityJoinMethod.JoinById ? {} : { region: opts.region }
|
|
5406
|
+
};
|
|
5407
|
+
const best = regions.length <= 1 ? [] : await probeAuthorityRegions(regions, opts.probe === void 0 ? {} : { probe: opts.probe });
|
|
5408
|
+
const plan = planAuthoritySearch(regions, best, options);
|
|
5409
|
+
return {
|
|
5410
|
+
search: plan.search.map((pick) => pick.url),
|
|
5411
|
+
create: plan.create.map((pick) => pick.url),
|
|
5412
|
+
regroup: (url) => planAuthorityRegroup(regions, best, options, authorityRegionOf(regions, url) ?? "").map((pick) => pick.url)
|
|
5413
|
+
};
|
|
5414
|
+
}
|
|
5415
|
+
async function joinWherePlayersAre(opts, plan, search, where) {
|
|
5416
|
+
for (const url of search) {
|
|
5417
|
+
try {
|
|
5418
|
+
return { room: await joinOnce(new Client(url), opts, { ...plan, method: AuthorityJoinMethod.Join }), url, ...where };
|
|
5419
|
+
} catch (err) {
|
|
5420
|
+
if (searchRefusalKind(errorCode(err)) === SearchRefusal.Final) explainAuthorityRefusal(err);
|
|
5421
|
+
}
|
|
5422
|
+
}
|
|
5423
|
+
return null;
|
|
5297
5424
|
}
|
|
5298
5425
|
async function joinAuthority(opts, target) {
|
|
5299
5426
|
const plan = planAuthorityJoin(target);
|
|
5300
5427
|
if ("refused" in plan) throw new TypeError(`genex multiplayer: this room cannot be asked for (${plan.refused})`);
|
|
5301
|
-
const targets = await joinTargets(opts);
|
|
5428
|
+
const { search, create: targets, regroup: regroupOf } = await joinTargets(opts, plan.method);
|
|
5429
|
+
const regroup = plan.method === AuthorityJoinMethod.JoinOrCreate ? regroupOf : () => [];
|
|
5430
|
+
const found = await joinWherePlayersAre(opts, plan, search, { targets, regroup });
|
|
5431
|
+
if (found !== null) return found;
|
|
5302
5432
|
const delays = opts.capacityRetryMs ?? CAPACITY_RETRY_MS;
|
|
5303
5433
|
let state = { region: 0, refused: 0, step: 0 };
|
|
5304
5434
|
for (; ; ) {
|
|
5305
5435
|
const url = targets[state.region];
|
|
5306
5436
|
try {
|
|
5307
|
-
return { room: await joinOnce(new Client(url), opts, plan), url, targets };
|
|
5437
|
+
return { room: await joinOnce(new Client(url), opts, plan), url, targets, regroup };
|
|
5308
5438
|
} catch (err) {
|
|
5309
5439
|
if (plan.method === AuthorityJoinMethod.JoinById) {
|
|
5310
5440
|
const region = nextCodeRegion(errorCode(err), state.region, targets.length);
|
|
@@ -5341,6 +5471,7 @@ function joinOnce(client, opts, plan) {
|
|
|
5341
5471
|
};
|
|
5342
5472
|
if (plan.method === AuthorityJoinMethod.JoinById) return client.joinById(plan.roomId, options);
|
|
5343
5473
|
if (plan.method === AuthorityJoinMethod.Create) return client.create(RoomType.AUTHORITY, options);
|
|
5474
|
+
if (plan.method === AuthorityJoinMethod.Join) return client.join(RoomType.AUTHORITY, options);
|
|
5344
5475
|
return client.joinOrCreate(RoomType.AUTHORITY, options);
|
|
5345
5476
|
}
|
|
5346
5477
|
function roomPreset(presetText) {
|
|
@@ -5409,15 +5540,33 @@ async function joinPrivateAuthority(code, opts) {
|
|
|
5409
5540
|
function comingBack(session, opts, joined, closed) {
|
|
5410
5541
|
if (opts.rejoin === false) return session;
|
|
5411
5542
|
const others = joined.targets.filter((url) => url !== joined.url);
|
|
5543
|
+
const seatAt = async (url, plan) => {
|
|
5544
|
+
const room = await joinOnce(new Client(url), opts, plan);
|
|
5545
|
+
const next = attachAuthoritySession(useSdkReconnection(room), opts, url);
|
|
5546
|
+
await waitForFirstState(room, ClientReconnection.firstStateTimeoutMs);
|
|
5547
|
+
return next;
|
|
5548
|
+
};
|
|
5549
|
+
let here = joined.url;
|
|
5550
|
+
const pool = {
|
|
5551
|
+
method: AuthorityJoinMethod.Join,
|
|
5552
|
+
options: opts.matchKey === void 0 || opts.matchKey === "" ? {} : { matchKey: opts.matchKey }
|
|
5553
|
+
};
|
|
5554
|
+
const regroup = async () => {
|
|
5555
|
+
for (const url of joined.regroup(here)) {
|
|
5556
|
+
try {
|
|
5557
|
+
const next = await seatAt(url, pool);
|
|
5558
|
+
here = url;
|
|
5559
|
+
return next;
|
|
5560
|
+
} catch {
|
|
5561
|
+
}
|
|
5562
|
+
}
|
|
5563
|
+
return null;
|
|
5564
|
+
};
|
|
5412
5565
|
return survivingSession(session, {
|
|
5413
5566
|
closed,
|
|
5414
5567
|
targets: [joined.url, ...others],
|
|
5415
|
-
join:
|
|
5416
|
-
|
|
5417
|
-
const next = attachAuthoritySession(useSdkReconnection(room), opts, url);
|
|
5418
|
-
await waitForFirstState(room, ClientReconnection.firstStateTimeoutMs);
|
|
5419
|
-
return next;
|
|
5420
|
-
}
|
|
5568
|
+
join: (url, way, lost) => seatAt(url, rejoinPlan(way, lost)),
|
|
5569
|
+
...opts.regroup === false || joined.regroup(here).length === 0 ? {} : { regroup }
|
|
5421
5570
|
});
|
|
5422
5571
|
}
|
|
5423
5572
|
function rejoinPlan(way, lost) {
|
|
@@ -6729,13 +6878,24 @@ function attachAuthoritySession(room, opts, url) {
|
|
|
6729
6878
|
|
|
6730
6879
|
export {
|
|
6731
6880
|
AUTHORITY_REFUSALS_PER_REGION,
|
|
6881
|
+
AUTHORITY_MAX_PING_MS,
|
|
6882
|
+
AUTHORITY_REGROUP_WAITS_MS,
|
|
6883
|
+
RegionRule,
|
|
6732
6884
|
normalizeAuthorityRegions,
|
|
6733
6885
|
regionProbePlan,
|
|
6734
6886
|
rankAuthorityRegions,
|
|
6887
|
+
planAuthoritySearch,
|
|
6735
6888
|
capacityWalk,
|
|
6736
6889
|
RefusalKind,
|
|
6737
6890
|
refusalKind,
|
|
6891
|
+
planAuthorityRegroup,
|
|
6892
|
+
authorityRegionOf,
|
|
6893
|
+
measureAuthorityRegions,
|
|
6894
|
+
SearchRefusal,
|
|
6895
|
+
searchRefusalKind,
|
|
6738
6896
|
selectAuthorityRegions,
|
|
6897
|
+
probeAuthorityRegions,
|
|
6898
|
+
selectAuthoritySearch,
|
|
6739
6899
|
REJOIN,
|
|
6740
6900
|
SUCCESSOR_OPEN_MS,
|
|
6741
6901
|
RejoinWay,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
waitForFirstState,
|
|
9
9
|
warnProtocolRefusal,
|
|
10
10
|
withoutReconnection
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-BB6OIWQ2.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-
|
|
26
|
+
} from "./chunk-2CSX5WA6.js";
|
|
27
27
|
|
|
28
28
|
// src/index.ts
|
|
29
29
|
import { getStateCallbacks } from "@colyseus/sdk";
|
package/dist/index.js
CHANGED
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
createPrivate,
|
|
4
4
|
joinPrivate,
|
|
5
5
|
matchmake
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-OESKZODQ.js";
|
|
7
|
+
import "./chunk-BB6OIWQ2.js";
|
|
8
|
+
import "./chunk-2CSX5WA6.js";
|
|
9
9
|
export {
|
|
10
10
|
connect,
|
|
11
11
|
createPrivate,
|
package/dist/protocol.d.ts
CHANGED
|
@@ -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.
|
|
79
|
+
declare const AUTHORITY_SDK_LABEL = "ts/0.17.11";
|
|
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
|
package/dist/protocol.js
CHANGED