twinwire 0.0.0-stage → 1.0.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.
Files changed (95) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/LICENSE +21 -0
  3. package/README.md +128 -2
  4. package/dist/browser/twinwire.js +2075 -0
  5. package/dist/browser/twinwire.js.map +7 -0
  6. package/dist/browser/twinwire.min.js +1 -0
  7. package/dist/browser/twinwire.mjs +2052 -0
  8. package/dist/browser/twinwire.mjs.map +7 -0
  9. package/dist/browser.d.ts +5 -0
  10. package/dist/browser.js +6 -0
  11. package/dist/browser.js.map +1 -0
  12. package/dist/client/client.d.ts +128 -0
  13. package/dist/client/client.js +470 -0
  14. package/dist/client/client.js.map +1 -0
  15. package/dist/client/index.d.ts +3 -0
  16. package/dist/client/index.js +4 -0
  17. package/dist/client/index.js.map +1 -0
  18. package/dist/client/lobby.d.ts +40 -0
  19. package/dist/client/lobby.js +122 -0
  20. package/dist/client/lobby.js.map +1 -0
  21. package/dist/client/rtc.d.ts +17 -0
  22. package/dist/client/rtc.js +102 -0
  23. package/dist/client/rtc.js.map +1 -0
  24. package/dist/core/budget.d.ts +27 -0
  25. package/dist/core/budget.js +39 -0
  26. package/dist/core/budget.js.map +1 -0
  27. package/dist/core/endpoint.d.ts +144 -0
  28. package/dist/core/endpoint.js +501 -0
  29. package/dist/core/endpoint.js.map +1 -0
  30. package/dist/core/lobby.d.ts +59 -0
  31. package/dist/core/lobby.js +53 -0
  32. package/dist/core/lobby.js.map +1 -0
  33. package/dist/core/protocol.d.ts +52 -0
  34. package/dist/core/protocol.js +100 -0
  35. package/dist/core/protocol.js.map +1 -0
  36. package/dist/core/reliable.d.ts +52 -0
  37. package/dist/core/reliable.js +116 -0
  38. package/dist/core/reliable.js.map +1 -0
  39. package/dist/core/rtc.d.ts +28 -0
  40. package/dist/core/rtc.js +21 -0
  41. package/dist/core/rtc.js.map +1 -0
  42. package/dist/index.d.ts +6 -0
  43. package/dist/index.js +7 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/netcode/clock.d.ts +15 -0
  46. package/dist/netcode/clock.js +37 -0
  47. package/dist/netcode/clock.js.map +1 -0
  48. package/dist/netcode/codec.d.ts +10 -0
  49. package/dist/netcode/codec.js +95 -0
  50. package/dist/netcode/codec.js.map +1 -0
  51. package/dist/netcode/index.d.ts +9 -0
  52. package/dist/netcode/index.js +10 -0
  53. package/dist/netcode/index.js.map +1 -0
  54. package/dist/netcode/inputs.d.ts +7 -0
  55. package/dist/netcode/inputs.js +43 -0
  56. package/dist/netcode/inputs.js.map +1 -0
  57. package/dist/netcode/interpolation.d.ts +44 -0
  58. package/dist/netcode/interpolation.js +101 -0
  59. package/dist/netcode/interpolation.js.map +1 -0
  60. package/dist/netcode/prediction.d.ts +40 -0
  61. package/dist/netcode/prediction.js +97 -0
  62. package/dist/netcode/prediction.js.map +1 -0
  63. package/dist/netcode/replication.d.ts +36 -0
  64. package/dist/netcode/replication.js +90 -0
  65. package/dist/netcode/replication.js.map +1 -0
  66. package/dist/netcode/snapshots.d.ts +29 -0
  67. package/dist/netcode/snapshots.js +78 -0
  68. package/dist/netcode/snapshots.js.map +1 -0
  69. package/dist/netcode/spatial.d.ts +16 -0
  70. package/dist/netcode/spatial.js +63 -0
  71. package/dist/netcode/spatial.js.map +1 -0
  72. package/dist/netcode/timing.d.ts +37 -0
  73. package/dist/netcode/timing.js +41 -0
  74. package/dist/netcode/timing.js.map +1 -0
  75. package/dist/server/index.d.ts +4 -0
  76. package/dist/server/index.js +5 -0
  77. package/dist/server/index.js.map +1 -0
  78. package/dist/server/lobby.d.ts +134 -0
  79. package/dist/server/lobby.js +462 -0
  80. package/dist/server/lobby.js.map +1 -0
  81. package/dist/server/rtc.d.ts +38 -0
  82. package/dist/server/rtc.js +102 -0
  83. package/dist/server/rtc.js.map +1 -0
  84. package/dist/server/server.d.ts +145 -0
  85. package/dist/server/server.js +457 -0
  86. package/dist/server/server.js.map +1 -0
  87. package/dist/server/turn.d.ts +22 -0
  88. package/dist/server/turn.js +52 -0
  89. package/dist/server/turn.js.map +1 -0
  90. package/docs/ADOPTING.md +64 -0
  91. package/docs/API.md +181 -0
  92. package/docs/ARCHITECTURE.md +101 -0
  93. package/docs/OPERATIONS.md +93 -0
  94. package/docs/RELEASE-CHECKLIST.md +25 -0
  95. package/package.json +100 -4
@@ -0,0 +1,462 @@
1
+ import { randomInt } from 'node:crypto';
2
+ import { CODE_ALPHABET, LOBBY_KEY, cleanMeta, cleanName, isLobbyMessage, metaMatches, normalizeCode, } from '../core/lobby.js';
3
+ export class Room {
4
+ lobby;
5
+ code;
6
+ mode;
7
+ visibility;
8
+ maxMembers;
9
+ phase = 'lobby';
10
+ meta;
11
+ /** Free for the application (its simulation, world). */
12
+ data = undefined;
13
+ members = new Map();
14
+ host = null;
15
+ countdownEndsAt = null;
16
+ createdAt = Date.now();
17
+ emptySince = null;
18
+ closed = false;
19
+ /** @internal */ countdown;
20
+ constructor(lobby, code, mode, visibility, maxMembers, meta) {
21
+ this.lobby = lobby;
22
+ this.code = code;
23
+ this.mode = mode;
24
+ this.visibility = visibility;
25
+ this.maxMembers = maxMembers;
26
+ this.meta = meta;
27
+ }
28
+ get connectedCount() { let n = 0; for (const m of this.members.values())
29
+ if (m.connected)
30
+ n++; return n; }
31
+ memberAt(seat) { for (const m of this.members.values())
32
+ if (m.seat === seat)
33
+ return m; return undefined; }
34
+ view(viewer) {
35
+ const members = [...this.members.values()].sort((a, b) => a.seat - b.seat).map(m => ({
36
+ seat: m.seat, name: m.name, ready: m.ready, connected: m.connected, host: m === this.host, meta: m.meta,
37
+ }));
38
+ return { code: this.code, mode: this.mode, visibility: this.visibility, phase: this.phase, maxMembers: this.maxMembers,
39
+ meta: this.meta, you: viewer?.seat ?? -1, members, countdownEndsAt: this.countdownEndsAt };
40
+ }
41
+ /** Reliable event to every member (disconnected ones get it on resume). Returns members whose outbox was full. */
42
+ broadcast(data, except) {
43
+ const rejected = [];
44
+ for (const m of this.members.values())
45
+ if (m !== except && !this.send(m, data))
46
+ rejected.push(m);
47
+ return rejected;
48
+ }
49
+ send(member, data) {
50
+ try {
51
+ member.session.sendEvent(data);
52
+ return true;
53
+ }
54
+ catch (e) {
55
+ this.lobby.report(e);
56
+ return false;
57
+ }
58
+ }
59
+ setPhase(phase) {
60
+ if (typeof phase !== 'string' || !phase || phase.length > 24)
61
+ throw new RangeError('Invalid phase');
62
+ if (phase === this.phase)
63
+ return;
64
+ this.phase = phase;
65
+ this.lobby.cancelCountdown(this);
66
+ if (phase === 'lobby')
67
+ for (const m of this.members.values())
68
+ m.ready = false;
69
+ this.lobby.changed(this);
70
+ }
71
+ setMeta(patch) { Object.assign(this.meta, patch); this.lobby.changed(this); }
72
+ setVisibility(v) { this.visibility = v; this.lobby.changed(this); }
73
+ /** Start now (skips the ready countdown). */
74
+ start() { this.lobby.startRoom(this); }
75
+ close(reason = 'closed') { this.lobby.closeRoom(this, reason); }
76
+ }
77
+ export class Lobby {
78
+ server;
79
+ rooms = new Map();
80
+ bySession = new Map();
81
+ creations = new Map();
82
+ timer;
83
+ off;
84
+ options;
85
+ /** A room was made by request; `request.init` carries the creator's setup data (validate it). */
86
+ onCreate = () => { };
87
+ onJoin = () => { };
88
+ onLeave = () => { };
89
+ onDisconnect = () => { };
90
+ /** A member's session is back on a new connection: after a drop, or a reloaded page taking it over. */
91
+ onReconnect = () => { };
92
+ onStart = () => { };
93
+ onClose = () => { };
94
+ /** Application events (anything that is not a lobby request). room/member are null outside a room. */
95
+ onEvent = () => { };
96
+ onState = () => { };
97
+ onError = () => { };
98
+ constructor(server, o = {}) {
99
+ this.server = server;
100
+ this.options = {
101
+ maxMembers: o.maxMembers ?? 4, codeLength: o.codeLength ?? 4, emptyCloseMs: o.emptyCloseMs ?? 30_000,
102
+ maxRooms: o.maxRooms ?? 500, maxRoomsPerIpPerHour: o.maxRoomsPerIpPerHour ?? 30,
103
+ joinablePhases: o.joinablePhases ?? ['lobby', 'playing'], quickPlayPhases: o.quickPlayPhases ?? ['lobby'],
104
+ evictDisconnected: o.evictDisconnected ?? true, allowHostKick: o.allowHostKick ?? true,
105
+ ready: o.ready === undefined ? { countdownMs: 3000, minMembers: 1 } : o.ready, canCreate: o.canCreate, canJoin: o.canJoin, clientMetaKeys: o.clientMetaKeys,
106
+ };
107
+ const opt = this.options;
108
+ if (!Number.isInteger(opt.maxMembers) || opt.maxMembers < 1 || opt.maxMembers > 64 ||
109
+ !Number.isInteger(opt.codeLength) || opt.codeLength < 3 || opt.codeLength > 12)
110
+ throw new RangeError('Invalid lobby options');
111
+ this.off = [
112
+ server.on('session', (s, resumed) => this.attach(s, resumed)),
113
+ server.on('disconnect', s => this.disconnected(s)),
114
+ server.on('expire', s => { const m = this.bySession.get(s.id); if (m)
115
+ this.removeMember(m, 'expired'); }),
116
+ ];
117
+ for (const s of server.sessions.values())
118
+ if (s.connected)
119
+ this.attach(s, false);
120
+ this.timer = setInterval(() => this.sweep(), 1000);
121
+ this.timer.unref?.();
122
+ }
123
+ /** @internal */ report(e) { try {
124
+ this.onError(e instanceof Error ? e : new Error(String(e)));
125
+ }
126
+ catch { /* ignore */ } }
127
+ memberOf(session) { return this.bySession.get(session.id); }
128
+ roomOf(session) { return this.bySession.get(session.id)?.room; }
129
+ dispose() { clearInterval(this.timer); for (const f of this.off)
130
+ f(); for (const r of [...this.rooms.values()])
131
+ this.closeRoom(r, 'shutdown'); }
132
+ attach(s, resumed) {
133
+ s.onEvent = data => this.event(s, data);
134
+ s.onState = state => { const m = this.bySession.get(s.id); try {
135
+ this.onState(m?.room ?? null, m ?? null, state, s);
136
+ }
137
+ catch (e) {
138
+ this.report(e);
139
+ } };
140
+ // back on a new connection: after a drop, or taking over from a socket the server hasn't seen close yet (a reloaded
141
+ // page resuming its checkpoint). Either way the client is a fresh instance, so the game re-sends what it needs.
142
+ const m = this.bySession.get(s.id);
143
+ if (m && resumed) {
144
+ m.connected = true;
145
+ m.disconnectedAt = 0;
146
+ this.safe(() => this.onReconnect(m.room, m));
147
+ this.changed(m.room);
148
+ }
149
+ }
150
+ disconnected(s) {
151
+ const m = this.bySession.get(s.id);
152
+ if (!m || !m.connected)
153
+ return;
154
+ m.connected = false;
155
+ m.disconnectedAt = Date.now();
156
+ m.ready = false;
157
+ if (m.room.host === m)
158
+ this.pickHost(m.room);
159
+ this.cancelCountdown(m.room);
160
+ this.safe(() => this.onDisconnect(m.room, m));
161
+ this.changed(m.room);
162
+ }
163
+ safe(fn) { try {
164
+ fn();
165
+ }
166
+ catch (e) {
167
+ this.report(e);
168
+ } }
169
+ event(s, data) {
170
+ if (!isLobbyMessage(data)) {
171
+ const m = this.bySession.get(s.id);
172
+ this.safe(() => this.onEvent(m?.room ?? null, m ?? null, data, s));
173
+ return;
174
+ }
175
+ const d = data, id = d.id, op = d[LOBBY_KEY];
176
+ const reply = (r) => { if (typeof id === 'number')
177
+ this.send(s, { [LOBBY_KEY]: 'res', id, ...r }); };
178
+ try {
179
+ switch (op) {
180
+ case 'create': return reply(this.create(s, d));
181
+ case 'join': return reply(this.join(s, d));
182
+ case 'quick': return reply(this.quickPlay(s, d));
183
+ case 'leave': {
184
+ const m = this.bySession.get(s.id);
185
+ if (m)
186
+ this.removeMember(m, 'left', false);
187
+ return reply({ ok: true, room: null });
188
+ }
189
+ case 'ready': return reply(this.member(s, m => { this.setReady(m, d.ready === true); }));
190
+ case 'name': return reply(this.member(s, m => { const n = cleanName(d.name); if (n)
191
+ m.name = n; this.changed(m.room); }));
192
+ case 'meta': return reply(this.member(s, m => {
193
+ const meta = this.clientMeta(d.meta);
194
+ if (!meta)
195
+ throw new Error('invalid meta');
196
+ const merged = { ...m.meta, ...meta };
197
+ if (Object.keys(merged).length > 32 || JSON.stringify(merged).length > 4096)
198
+ throw new Error('too much meta');
199
+ m.meta = merged;
200
+ this.changed(m.room);
201
+ }));
202
+ case 'kick': return reply(this.member(s, m => {
203
+ if (!this.options.allowHostKick || m.room.host !== m)
204
+ throw new Error('only the host can do that');
205
+ const target = typeof d.seat === 'number' ? m.room.memberAt(d.seat) : undefined;
206
+ if (!target || target === m)
207
+ throw new Error('no such player');
208
+ this.removeMember(target, 'kicked');
209
+ }));
210
+ default: return reply({ ok: false, error: 'unknown request' });
211
+ }
212
+ }
213
+ catch (e) {
214
+ reply({ ok: false, error: e instanceof Error ? e.message.slice(0, 120) : 'error' });
215
+ }
216
+ }
217
+ member(s, fn) {
218
+ const m = this.bySession.get(s.id);
219
+ if (!m)
220
+ return { ok: false, error: 'not in a room' };
221
+ fn(m);
222
+ return { ok: true, room: m.room.view(m) };
223
+ }
224
+ send(s, data) { try {
225
+ s.sendEvent(data);
226
+ }
227
+ catch (e) {
228
+ this.report(e);
229
+ } }
230
+ /** A client's meta, cleaned and limited to the keys clients may set (null: invalid). */
231
+ clientMeta(v) {
232
+ const meta = cleanMeta(v), keys = this.options.clientMetaKeys;
233
+ if (!meta || !keys)
234
+ return meta;
235
+ for (const k of Object.keys(meta))
236
+ if (!keys.includes(k))
237
+ delete meta[k];
238
+ return meta;
239
+ }
240
+ newCode() {
241
+ for (let tries = 0; tries < 1000; tries++) {
242
+ let c = '';
243
+ for (let i = 0; i < this.options.codeLength; i++)
244
+ c += CODE_ALPHABET[randomInt(CODE_ALPHABET.length)];
245
+ if (!this.rooms.has(c))
246
+ return c;
247
+ }
248
+ throw new Error('no free room codes');
249
+ }
250
+ rateOk(ip) {
251
+ const now = Date.now(), list = (this.creations.get(ip) ?? []).filter(t => now - t < 3600_000);
252
+ if (list.length >= this.options.maxRoomsPerIpPerHour) {
253
+ this.creations.set(ip, list);
254
+ return false;
255
+ }
256
+ list.push(now);
257
+ this.creations.set(ip, list);
258
+ return true;
259
+ }
260
+ /** Create a room on the server's own initiative (no creator). */
261
+ createRoom(o = {}) {
262
+ if (this.rooms.size >= this.options.maxRooms)
263
+ throw new Error('the server is busy: try again soon');
264
+ const max = Math.min(this.options.maxMembers, Number.isInteger(o.maxMembers) && o.maxMembers > 0 ? o.maxMembers : this.options.maxMembers);
265
+ const mode = typeof o.mode === 'string' && /^[\w.-]{1,32}$/.test(o.mode) ? o.mode : 'default';
266
+ const room = new Room(this, this.newCode(), mode, o.visibility === 'public' ? 'public' : 'private', max, o.meta ?? {});
267
+ this.rooms.set(room.code, room);
268
+ room.emptySince = Date.now();
269
+ return room;
270
+ }
271
+ create(s, req) {
272
+ const meta = cleanMeta(req.meta), memberMeta = this.clientMeta(req.memberMeta);
273
+ if (!meta || !memberMeta)
274
+ return { ok: false, error: 'invalid meta' };
275
+ const refused = this.options.canCreate?.(s, req);
276
+ if (refused)
277
+ return { ok: false, error: refused };
278
+ if (!this.rateOk(s.ip))
279
+ return { ok: false, error: 'too many rooms made from here: try again later' };
280
+ const room = this.createRoom({ ...req, meta });
281
+ this.safe(() => this.onCreate(room, s, req));
282
+ if (room.closed)
283
+ return { ok: false, error: 'room closed' };
284
+ return this.seat(room, s, req.name, memberMeta);
285
+ }
286
+ join(s, req) {
287
+ const code = normalizeCode(req.code), room = code ? this.rooms.get(code) : undefined;
288
+ if (!room || room.closed)
289
+ return { ok: false, error: `no room called ${code ?? String(req.code).slice(0, 12).toUpperCase()}` };
290
+ const already = this.bySession.get(s.id);
291
+ if (already?.room === room)
292
+ return { ok: true, room: room.view(already) };
293
+ if (!this.options.joinablePhases.includes(room.phase))
294
+ return { ok: false, error: 'that game has already started' };
295
+ const refused = this.options.canJoin?.(room, s, req);
296
+ if (refused)
297
+ return { ok: false, error: refused };
298
+ const memberMeta = this.clientMeta(req.memberMeta);
299
+ if (!memberMeta)
300
+ return { ok: false, error: 'invalid meta' };
301
+ return this.seat(room, s, req.name, memberMeta);
302
+ }
303
+ quickPlay(s, req) {
304
+ const mode = typeof req.mode === 'string' ? req.mode : 'default', match = cleanMeta(req.match), memberMeta = this.clientMeta(req.memberMeta);
305
+ if (!match || !memberMeta)
306
+ return { ok: false, error: 'invalid meta' };
307
+ const current = this.bySession.get(s.id)?.room;
308
+ let best = null, bestScore = -1;
309
+ for (const r of this.rooms.values()) {
310
+ if (r.closed || r.visibility !== 'public' || r.mode !== mode || !this.options.quickPlayPhases.includes(r.phase) || !metaMatches(r.meta, match))
311
+ continue;
312
+ if (r !== current && !this.hasSeat(r))
313
+ continue;
314
+ if (r !== current && this.options.canJoin?.(r, s, req))
315
+ continue;
316
+ const score = r.connectedCount * 1e6 + (1e6 - Math.min(1e6 - 1, (Date.now() - r.createdAt) / 1000));
317
+ if (r.connectedCount > 0 || r === current)
318
+ if (score > bestScore) {
319
+ best = r;
320
+ bestScore = score;
321
+ }
322
+ }
323
+ if (best) {
324
+ const m = this.bySession.get(s.id);
325
+ return best === current && m ? { ok: true, room: best.view(m) } : this.seat(best, s, req.name, memberMeta);
326
+ }
327
+ return this.create(s, { ...(req.create ?? {}), meta: { ...(req.create?.meta ?? {}), ...match }, mode, visibility: 'public', name: req.name, memberMeta });
328
+ }
329
+ hasSeat(r) {
330
+ return r.members.size < r.maxMembers || this.options.evictDisconnected && [...r.members.values()].some(m => !m.connected);
331
+ }
332
+ seat(room, s, name, meta) {
333
+ if (room.members.size >= room.maxMembers) {
334
+ const away = [...room.members.values()].filter(m => !m.connected).sort((a, b) => a.disconnectedAt - b.disconnectedAt)[0];
335
+ if (!this.options.evictDisconnected || !away)
336
+ return { ok: false, error: 'that room is full' };
337
+ this.removeMember(away, 'replaced');
338
+ }
339
+ const old = this.bySession.get(s.id);
340
+ if (old)
341
+ this.removeMember(old, 'switched', false);
342
+ const taken = new Set([...room.members.values()].map(m => m.seat));
343
+ let seat = 0;
344
+ while (taken.has(seat))
345
+ seat++;
346
+ const fallback = cleanName(s.hello?.name) || `PLAYER ${seat + 1}`;
347
+ const m = { session: s, room, seat, joinedAt: Date.now(), name: cleanName(name) || fallback, ready: false, connected: s.connected,
348
+ disconnectedAt: 0, meta, data: undefined };
349
+ room.members.set(s.id, m);
350
+ this.bySession.set(s.id, m);
351
+ room.emptySince = null;
352
+ if (!room.host || !room.host.connected)
353
+ this.pickHost(room);
354
+ this.cancelCountdown(room);
355
+ this.safe(() => this.onJoin(room, m));
356
+ this.changed(room, m);
357
+ return { ok: true, room: room.view(m) };
358
+ }
359
+ pickHost(room) {
360
+ const list = [...room.members.values()].sort((a, b) => a.joinedAt - b.joinedAt);
361
+ room.host = list.find(m => m.connected) ?? list[0] ?? null;
362
+ }
363
+ removeMember(m, reason, notify = true) {
364
+ const room = m.room;
365
+ if (room.members.get(m.session.id) !== m)
366
+ return;
367
+ room.members.delete(m.session.id);
368
+ this.bySession.delete(m.session.id);
369
+ if (notify)
370
+ this.send(m.session, { [LOBBY_KEY]: 'left', reason });
371
+ if (room.host === m)
372
+ this.pickHost(room);
373
+ if (!room.members.size)
374
+ room.emptySince = Date.now();
375
+ this.cancelCountdown(room);
376
+ this.safe(() => this.onLeave(room, m, reason));
377
+ if (reason === 'kicked')
378
+ this.server.endSession(m.session, 'kicked');
379
+ this.changed(room);
380
+ }
381
+ setReady(m, ready) {
382
+ if (!this.options.ready)
383
+ throw new Error('this game has no ready-up');
384
+ if (m.room.phase !== 'lobby')
385
+ throw new Error('the game is already running');
386
+ m.ready = ready;
387
+ if (!ready)
388
+ this.cancelCountdown(m.room);
389
+ this.changed(m.room);
390
+ }
391
+ /** @internal Everyone gets the new room view; a ready room starts its countdown. */
392
+ changed(room, skip) {
393
+ if (room.closed)
394
+ return;
395
+ for (const m of room.members.values())
396
+ if (m !== skip)
397
+ this.send(m.session, { [LOBBY_KEY]: 'room', room: room.view(m) });
398
+ this.checkReady(room);
399
+ }
400
+ checkReady(room) {
401
+ const r = this.options.ready;
402
+ if (!r || room.phase !== 'lobby' || room.countdownEndsAt !== null)
403
+ return;
404
+ const live = [...room.members.values()].filter(m => m.connected);
405
+ if (live.length < Math.max(1, r.minMembers ?? 1) || !live.every(m => m.ready))
406
+ return;
407
+ const ms = r.countdownMs ?? 3000;
408
+ if (ms <= 0) {
409
+ this.startRoom(room);
410
+ return;
411
+ }
412
+ room.countdownEndsAt = performance.now() + ms;
413
+ room.countdown = setTimeout(() => { room.countdown = undefined; if (room.countdownEndsAt !== null)
414
+ this.startRoom(room); }, ms);
415
+ for (const m of room.members.values())
416
+ this.send(m.session, { [LOBBY_KEY]: 'room', room: room.view(m) });
417
+ }
418
+ /** @internal */ cancelCountdown(room) {
419
+ if (room.countdownEndsAt === null)
420
+ return;
421
+ clearTimeout(room.countdown);
422
+ room.countdown = undefined;
423
+ room.countdownEndsAt = null;
424
+ for (const m of room.members.values())
425
+ this.send(m.session, { [LOBBY_KEY]: 'room', room: room.view(m) });
426
+ }
427
+ /** @internal */ startRoom(room) {
428
+ if (room.closed)
429
+ return;
430
+ clearTimeout(room.countdown);
431
+ room.countdown = undefined;
432
+ room.countdownEndsAt = null;
433
+ room.phase = 'playing';
434
+ for (const m of room.members.values())
435
+ m.ready = false;
436
+ this.safe(() => this.onStart(room));
437
+ this.changed(room);
438
+ }
439
+ /** @internal */ closeRoom(room, reason) {
440
+ if (room.closed)
441
+ return;
442
+ clearTimeout(room.countdown);
443
+ for (const m of [...room.members.values()]) {
444
+ room.members.delete(m.session.id);
445
+ this.bySession.delete(m.session.id);
446
+ this.send(m.session, { [LOBBY_KEY]: 'left', reason });
447
+ }
448
+ room.closed = true;
449
+ this.rooms.delete(room.code);
450
+ this.safe(() => this.onClose(room, reason));
451
+ }
452
+ sweep() {
453
+ const now = Date.now();
454
+ for (const r of [...this.rooms.values()])
455
+ if (!r.members.size && r.emptySince !== null && now - r.emptySince >= this.options.emptyCloseMs)
456
+ this.closeRoom(r, 'empty');
457
+ for (const [ip, list] of this.creations)
458
+ if (!list.some(t => now - t < 3600_000))
459
+ this.creations.delete(ip);
460
+ }
461
+ }
462
+ //# sourceMappingURL=lobby.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lobby.js","sourceRoot":"","sources":["../../src/server/lobby.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { RtcCallbacks, RtcPeer } from '../core/rtc.js';
2
+ /** Minimal structural surface used from node-datachannel. The native module is optional and server-only. */
3
+ interface NativeChannel {
4
+ isOpen(): boolean;
5
+ bufferedAmount(): number;
6
+ sendMessageBinary(b: Buffer): boolean;
7
+ close(): void;
8
+ onOpen(cb: () => void): void;
9
+ onClosed(cb: () => void): void;
10
+ onError(cb: (s: string) => void): void;
11
+ onMessage(cb: (m: string | Buffer) => void): void;
12
+ }
13
+ interface NativeConnection {
14
+ setRemoteDescription(sdp: string, type: string): void;
15
+ addRemoteCandidate(candidate: string, mid: string): void;
16
+ createDataChannel(label: string, o: Record<string, unknown>): NativeChannel;
17
+ onLocalDescription(cb: (sdp: string, type: string) => void): void;
18
+ onLocalCandidate(cb: (candidate: string, mid: string) => void): void;
19
+ onStateChange(cb: (state: string) => void): void;
20
+ close(): void;
21
+ }
22
+ interface NativeModule {
23
+ PeerConnection: new (name: string, options: Record<string, unknown>) => NativeConnection;
24
+ }
25
+ export type RtcFactory = (cb: RtcCallbacks) => RtcPeer;
26
+ export interface NativeRtcOptions {
27
+ port?: number;
28
+ publicIp?: string;
29
+ bindAddress?: string;
30
+ iceServers?: string[];
31
+ /** Largest datagram accepted or sent, header included (default 64 KiB + 22). Match the endpoints' maxStateBytes. */
32
+ maxMessageSize?: number;
33
+ }
34
+ /** Load before opening the server. Missing native dependencies fail explicitly, not silently. */
35
+ export declare function createNativeRtcFactory(options?: NativeRtcOptions): Promise<RtcFactory>;
36
+ /** Dependency injection is also used by adapter contract tests. */
37
+ export declare function nativeRtcFactory(native: NativeModule, options?: NativeRtcOptions): RtcFactory;
38
+ export {};
@@ -0,0 +1,102 @@
1
+ /** Load before opening the server. Missing native dependencies fail explicitly, not silently. */
2
+ export async function createNativeRtcFactory(options = {}) {
3
+ const name = 'node-datachannel';
4
+ const imported = await import(name);
5
+ const native = (imported.default ?? imported);
6
+ if (typeof native.PeerConnection !== 'function')
7
+ throw new Error('Unsupported node-datachannel module');
8
+ return nativeRtcFactory(native, options);
9
+ }
10
+ /** Dependency injection is also used by adapter contract tests. */
11
+ export function nativeRtcFactory(native, options = {}) {
12
+ const port = options.port ?? 8788;
13
+ if (!Number.isInteger(port) || port < 1 || port > 65535)
14
+ throw new RangeError('Invalid UDP port');
15
+ if (options.publicIp && (!/^(\d{1,3}\.){3}\d{1,3}$/.test(options.publicIp) || options.publicIp.split('.').some(n => Number(n) > 255)))
16
+ throw new Error('publicIp must be an IPv4 address');
17
+ const maxMessage = options.maxMessageSize ?? 64 * 1024 + 22;
18
+ if (!Number.isInteger(maxMessage) || maxMessage < 1100 || maxMessage > 256 * 1024 + 22)
19
+ throw new RangeError('Invalid maxMessageSize');
20
+ let counter = 0;
21
+ return cb => {
22
+ let alive = true, remote = false, dc;
23
+ const pending = [];
24
+ const cfg = { iceServers: options.iceServers ?? [], enableIceUdpMux: true,
25
+ portRangeBegin: port, portRangeEnd: port, maxMessageSize: maxMessage };
26
+ if (options.bindAddress)
27
+ cfg.bindAddress = options.bindAddress;
28
+ const pc = new native.PeerConnection('twinwire-' + (++counter), cfg);
29
+ const advertised = (s) => options.publicIp
30
+ ? s.replace(/(candidate:\S+ \d+ udp \d+ )(\S+)( \d+ typ host)/gi, `$1${options.publicIp}$3`) : s;
31
+ const close = () => { if (!alive)
32
+ return; alive = false; pending.length = 0; try {
33
+ dc?.close();
34
+ pc.close();
35
+ }
36
+ catch { } };
37
+ pc.onLocalDescription((sdp, type) => { if (alive && type.toLowerCase() === 'answer')
38
+ cb.signal({ kind: 'answer', sdp: advertised(sdp) }); });
39
+ pc.onLocalCandidate((candidate, mid) => { if (alive)
40
+ cb.signal({ kind: 'candidate', candidate: advertised(candidate), mid }); });
41
+ pc.onStateChange(state => { if (alive && ['failed', 'closed'].includes(state.toLowerCase())) {
42
+ close();
43
+ cb.closed();
44
+ } });
45
+ return {
46
+ close,
47
+ signal(m) {
48
+ if (!alive)
49
+ return;
50
+ try {
51
+ if (m.kind === 'offer') {
52
+ if (remote)
53
+ throw new Error('Duplicate RTC offer');
54
+ pc.setRemoteDescription(m.sdp, 'offer');
55
+ remote = true;
56
+ dc = pc.createDataChannel('twinwire', { negotiated: true, id: 0, unordered: true, maxRetransmits: 0 });
57
+ const channel = dc;
58
+ channel.onOpen(() => {
59
+ if (alive)
60
+ cb.open({
61
+ get open() { return alive && channel.isOpen(); }, get bufferedAmount() { return channel.bufferedAmount(); },
62
+ send: b => {
63
+ if (!alive || !channel.isOpen())
64
+ return false;
65
+ // libdatachannel returns false when a connected SCTP send was queued.
66
+ // A nonthrowing call is consumed here; Endpoint enforces the queue limit.
67
+ channel.sendMessageBinary(Buffer.from(b));
68
+ return true;
69
+ }, close,
70
+ });
71
+ });
72
+ channel.onMessage(m => { if (alive && typeof m !== 'string' && m.length <= maxMessage)
73
+ cb.data(new Uint8Array(m)); });
74
+ channel.onClosed(() => { if (alive) {
75
+ close();
76
+ cb.closed();
77
+ } });
78
+ channel.onError(s => { if (alive)
79
+ cb.error(new Error(s)); });
80
+ for (const c of pending)
81
+ pc.addRemoteCandidate(c.candidate, c.mid);
82
+ pending.length = 0;
83
+ }
84
+ else if (m.kind === 'candidate') {
85
+ if (remote)
86
+ pc.addRemoteCandidate(m.candidate, m.mid);
87
+ else {
88
+ if (pending.length >= 64)
89
+ throw new Error('Too many RTC candidates');
90
+ pending.push(m);
91
+ }
92
+ }
93
+ }
94
+ catch (error) {
95
+ cb.error(error instanceof Error ? error : new Error(String(error)));
96
+ close();
97
+ }
98
+ },
99
+ };
100
+ };
101
+ }
102
+ //# sourceMappingURL=rtc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rtc.js","sourceRoot":"","sources":["../../src/server/rtc.ts"],"names":[],"mappings":"AAuBA,iGAAiG;AACjG,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,UAA4B,EAAE;IACzE,MAAM,IAAI,GAAG,kBAAkB,CAAC;IAChC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAuD,CAAC;IAC1F,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAiB,CAAC;IAC9D,IAAI,OAAO,MAAM,CAAC,cAAc,KAAK,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACxG,OAAO,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC;AACD,mEAAmE;AACnE,MAAM,UAAU,gBAAgB,CAAC,MAAoB,EAAE,UAA4B,EAAE;IACnF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK;QAAE,MAAM,IAAI,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAClG,IAAI,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,yBAAyB,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAC3L,MAAM,UAAU,GAAG,OAAO,CAAC,cAAc,IAAI,EAAE,GAAG,IAAI,GAAG,EAAE,CAAC;IAC5D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,IAAI,IAAI,UAAU,GAAG,GAAG,GAAG,IAAI,GAAG,EAAE;QAAE,MAAM,IAAI,UAAU,CAAC,wBAAwB,CAAC,CAAC;IACvI,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,OAAO,EAAE,CAAC,EAAE;QACV,IAAI,KAAK,GAAG,IAAI,EAAE,MAAM,GAAG,KAAK,EAAE,EAA6B,CAAC;QAChE,MAAM,OAAO,GAAgD,EAAE,CAAC;QAChE,MAAM,GAAG,GAA4B,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,EAAE,EAAE,eAAe,EAAE,IAAI;YAChG,cAAc,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC;QACzE,IAAI,OAAO,CAAC,WAAW;YAAE,GAAG,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QAC/D,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,cAAc,CAAC,WAAW,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;QACrE,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ;YAChD,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,oDAAoD,EAAE,KAAK,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnG,MAAM,KAAK,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAAC,EAAE,EAAE,KAAK,EAAE,CAAC;YAAC,EAAE,CAAC,KAAK,EAAE,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC,CAAC,CAAC,CAAC;QACzH,EAAE,CAAC,kBAAkB,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,QAAQ;YAAE,EAAE,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7I,EAAE,CAAC,gBAAgB,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,GAAG,IAAI,KAAK;YAAE,EAAE,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjI,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,KAAK,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAAC,KAAK,EAAE,CAAC;YAAC,EAAE,CAAC,MAAM,EAAE,CAAC;QAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1H,OAAO;YACL,KAAK;YACL,MAAM,CAAC,CAAC;gBACN,IAAI,CAAC,KAAK;oBAAE,OAAO;gBACnB,IAAI,CAAC;oBACH,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;wBACvB,IAAI,MAAM;4BAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;wBACnD,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;wBAAC,MAAM,GAAG,IAAI,CAAC;wBACvD,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC;wBACvG,MAAM,OAAO,GAAG,EAAE,CAAC;wBACnB,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE;4BAAG,IAAI,KAAK;gCAAE,EAAE,CAAC,IAAI,CAAC;oCACxC,IAAI,IAAI,KAAK,OAAO,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,cAAc,KAAK,OAAO,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;oCAC3G,IAAI,EAAE,CAAC,CAAC,EAAE;wCACR,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;4CAAE,OAAO,KAAK,CAAC;wCAC9C,sEAAsE;wCACtE,0EAA0E;wCAC1E,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;wCAAC,OAAO,IAAI,CAAC;oCACzD,CAAC,EAAE,KAAK;iCACT,CAAC,CAAC;wBAAC,CAAC,CAAC,CAAC;wBACP,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,KAAK,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,UAAU;4BAAE,EAAE,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBACtH,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,IAAI,KAAK,EAAE,CAAC;4BAAC,KAAK,EAAE,CAAC;4BAAC,EAAE,CAAC,MAAM,EAAE,CAAC;wBAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBACjE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,KAAK;4BAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBAC7D,KAAK,MAAM,CAAC,IAAI,OAAO;4BAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;wBAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;oBACzF,CAAC;yBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;wBAClC,IAAI,MAAM;4BAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;6BACjD,CAAC;4BAAC,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE;gCAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;4BAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;wBAAC,CAAC;oBACjG,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAAC,EAAE,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBAAC,KAAK,EAAE,CAAC;gBAAC,CAAC;YACnG,CAAC;SACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}