@myvillage/cli 2.8.1 → 2.8.2
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/package.json
CHANGED
|
@@ -141,7 +141,8 @@ function requestHostContext(timeoutMs) {
|
|
|
141
141
|
// dev server.
|
|
142
142
|
|
|
143
143
|
const DEFAULT_DEV_SERVER = 'https://myvillage-realtime-staging.myvillage-realtime.workers.dev';
|
|
144
|
-
|
|
144
|
+
// No vowels (or look-alikes), so random codes can't spell words.
|
|
145
|
+
const CODE_ALPHABET = 'BCDFGHJKMNPQRSTVWXZ23456789';
|
|
145
146
|
|
|
146
147
|
export class MultiplayerError extends Error {
|
|
147
148
|
constructor(code, message, status) {
|
|
@@ -185,7 +186,8 @@ class Multiplayer {
|
|
|
185
186
|
this._ticket = null;
|
|
186
187
|
/** The current match (see MatchView in the platform docs), or null. */
|
|
187
188
|
this.match = null;
|
|
188
|
-
|
|
189
|
+
// Digits only: random letters can spell words.
|
|
190
|
+
this.me = { displayName: ctx ? ctx.player.displayName : options.name || 'Player ' + (100 + Math.floor(Math.random() * 900)) };
|
|
189
191
|
}
|
|
190
192
|
|
|
191
193
|
// ── lobby plumbing ──
|
|
@@ -208,8 +210,14 @@ class Multiplayer {
|
|
|
208
210
|
async quickMatch({ lobby } = {}) {
|
|
209
211
|
this._requireAvailable();
|
|
210
212
|
// Finished match rooms can't be reused, so dev quick match rotates rooms
|
|
211
|
-
// every 10 minutes
|
|
212
|
-
|
|
213
|
+
// every 10 minutes, and connect() steps through numbered rooms in that
|
|
214
|
+
// window past any that are finished or full. Tabs follow the same
|
|
215
|
+
// sequence, so they still meet.
|
|
216
|
+
if (this.mode === 'dev') {
|
|
217
|
+
this._devQuickBase = 'QUICK' + Math.floor(Date.now() / 600000).toString(36).toUpperCase();
|
|
218
|
+
this._devQuickTry = 0;
|
|
219
|
+
return this._devMatch(this._devQuickBase, false, lobby);
|
|
220
|
+
}
|
|
213
221
|
return this._enter(await this._api('POST', `/api/v1/games/${this._game()}/matches/quick`, { platform: this._ctx.platform, lobby }));
|
|
214
222
|
}
|
|
215
223
|
|
|
@@ -294,10 +302,23 @@ class Multiplayer {
|
|
|
294
302
|
async connect() {
|
|
295
303
|
this._requireAvailable();
|
|
296
304
|
if (!this.match) throw new MultiplayerError('no_match', 'Host, join or quick match first.');
|
|
297
|
-
const ticket = await this._freshTicket();
|
|
298
305
|
const { ArenaClient } = await import('./myvillage-realtime.js');
|
|
299
|
-
|
|
300
|
-
|
|
306
|
+
let net;
|
|
307
|
+
for (;;) {
|
|
308
|
+
const ticket = await this._freshTicket();
|
|
309
|
+
net = new ArenaClient({ wsUrl: ticket.wsUrl, ticket: ticket.ticket });
|
|
310
|
+
try {
|
|
311
|
+
await net.connect();
|
|
312
|
+
break;
|
|
313
|
+
} catch (err) {
|
|
314
|
+
// Dev quick match: that room is finished or full — try the next one.
|
|
315
|
+
const devQuick = this.mode === 'dev' && this._devQuickBase && this.match.code.startsWith(this._devQuickBase);
|
|
316
|
+
if (!devQuick || this._devQuickTry >= 20 || !/finished|full/i.test(String(err && err.message))) throw err;
|
|
317
|
+
this._devQuickTry++;
|
|
318
|
+
this._ticket = null;
|
|
319
|
+
this._devMatch(this._devQuickBase + '-' + this._devQuickTry, false, this.match.lobby);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
301
322
|
this._ticket = null; // single use: a reconnect fetches a fresh one
|
|
302
323
|
this._net = net;
|
|
303
324
|
return net;
|