onelobby 0.1.0 → 0.2.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 +2 -2
- package/dist/direct/index.d.ts +3 -1
- package/dist/direct/index.js +1 -1
- package/dist/direct/index.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/lobby.d.ts +33 -0
- package/dist/lobby.js +62 -0
- package/dist/lobby.js.map +1 -1
- package/dist/onelobby.bundle.mjs +5 -5
- package/dist/onelobby.bundle.mjs.map +4 -4
- package/dist/onelobby.d.ts +12 -3
- package/dist/onelobby.global.js +186 -19
- package/dist/onelobby.global.js.map +4 -4
- package/dist/onelobby.global.min.js +5 -5
- package/dist/onelobby.global.min.js.map +4 -4
- package/dist/onelobby.js +7 -4
- package/dist/onelobby.js.map +1 -1
- package/dist/socket.d.ts +63 -0
- package/dist/socket.js +142 -0
- package/dist/socket.js.map +1 -0
- package/package.json +1 -1
package/dist/onelobby.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { type Clock } from "./clock.js";
|
|
2
2
|
import { Emitter } from "./emitter.js";
|
|
3
|
-
import { Lobby } from "./lobby.js";
|
|
3
|
+
import { Lobby, type RateLimit } from "./lobby.js";
|
|
4
4
|
import { type LobbySummary } from "./signaling.js";
|
|
5
5
|
import { type LinkFactory, type SocketFactory } from "./transport.js";
|
|
6
6
|
import type { VoiceCodec, FrameSource, AudioSink } from "./voice-types.js";
|
|
7
7
|
export declare const LIB_NAME = "onelobby";
|
|
8
|
-
export declare const LIB_VERSION = "0.
|
|
8
|
+
export declare const LIB_VERSION = "0.2.0";
|
|
9
9
|
/** Where `rememberSeat` keeps the resume token: the subset of the Web Storage API it uses. */
|
|
10
10
|
export interface SeatStorage {
|
|
11
11
|
getItem(key: string): string | null;
|
|
@@ -44,6 +44,13 @@ export interface OneLobbyOptions {
|
|
|
44
44
|
* Default 15000; 0 waits forever.
|
|
45
45
|
*/
|
|
46
46
|
readyTimeoutMs?: number;
|
|
47
|
+
/**
|
|
48
|
+
* Treat a peer as gone after this many ms of silence. Joiners ping the host every 2 s and the host answers, so the
|
|
49
|
+
* host drops a silent joiner (`peerLeft`, "timeout") and a joiner handles a silent host as lost (a direct lobby
|
|
50
|
+
* ends with "host_left"). Default 0 (off): a silently dead peer then surfaces when its link or signaling socket
|
|
51
|
+
* times out, within about 30 s. Values under 6000 are raised to 6000.
|
|
52
|
+
*/
|
|
53
|
+
peerTimeoutMs?: number;
|
|
47
54
|
/**
|
|
48
55
|
* Keep this tab's seat across a page reload (sessionStorage): `join(code)` and `resume()` take the seat back
|
|
49
56
|
* instead of joining as a new player. Cleared when the session ends. Default true where sessionStorage exists.
|
|
@@ -76,6 +83,8 @@ export interface HostOptions {
|
|
|
76
83
|
visibility?: "public" | "unlisted" | "private";
|
|
77
84
|
lateJoin?: boolean;
|
|
78
85
|
meta?: Record<string, string>;
|
|
86
|
+
/** Per-joiner cap on incoming raw messages, e.g. `{ messages: 60, perMs: 1000 }`; the excess is dropped before `message` fires or is relayed. */
|
|
87
|
+
rateLimit?: RateLimit;
|
|
79
88
|
}
|
|
80
89
|
export interface ListOptions {
|
|
81
90
|
meta?: Record<string, string>;
|
|
@@ -102,7 +111,7 @@ export type OneLobbyEvents = {
|
|
|
102
111
|
export declare const DEFAULT_READY_TIMEOUT_MS = 15000;
|
|
103
112
|
/** Entry point (DESIGN s.11.2). */
|
|
104
113
|
export declare class OneLobby extends Emitter<OneLobbyEvents> {
|
|
105
|
-
readonly options: Required<Pick<OneLobbyOptions, "gameId" | "netVersion" | "lobbyServer" | "mode" | "tickRate" | "hashEveryTicks" | "displayName" | "relayOnly" | "readyTimeoutMs">>;
|
|
114
|
+
readonly options: Required<Pick<OneLobbyOptions, "gameId" | "netVersion" | "lobbyServer" | "mode" | "tickRate" | "hashEveryTicks" | "displayName" | "relayOnly" | "readyTimeoutMs" | "peerTimeoutMs">>;
|
|
106
115
|
private socketFactory;
|
|
107
116
|
private linkFactory;
|
|
108
117
|
private clock;
|
package/dist/onelobby.global.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! onelobby 0.
|
|
1
|
+
/*! onelobby 0.2.0 | MIT license */
|
|
2
2
|
"use strict";
|
|
3
3
|
var OneLobby = (() => {
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -33,10 +33,12 @@ var OneLobby = (() => {
|
|
|
33
33
|
Lobby: () => Lobby,
|
|
34
34
|
LobbyController: () => LobbyController,
|
|
35
35
|
Lockstep: () => Lockstep,
|
|
36
|
+
MIN_PEER_TIMEOUT_MS: () => MIN_PEER_TIMEOUT_MS,
|
|
36
37
|
OneLobby: () => OneLobby,
|
|
37
38
|
OneLobbyError: () => OneLobbyError,
|
|
38
39
|
SharedState: () => SharedState,
|
|
39
40
|
Voice: () => Voice,
|
|
41
|
+
closeCodeFor: () => closeCodeFor,
|
|
40
42
|
codeFromUrl: () => codeFromUrl,
|
|
41
43
|
decodeJoinCode: () => decodeJoinCode,
|
|
42
44
|
defineLobbyElement: () => defineLobbyElement,
|
|
@@ -1622,7 +1624,118 @@ var OneLobby = (() => {
|
|
|
1622
1624
|
static END = FLAG_END_OF_BURST;
|
|
1623
1625
|
};
|
|
1624
1626
|
|
|
1627
|
+
// src/socket.ts
|
|
1628
|
+
function closeCodeFor(reason) {
|
|
1629
|
+
if (reason === "left") return 1e3;
|
|
1630
|
+
if (reason === "host_left" || reason === "closed") return 1001;
|
|
1631
|
+
if (reason === "kicked") return 4e3;
|
|
1632
|
+
return 1006;
|
|
1633
|
+
}
|
|
1634
|
+
var enc2 = new TextEncoder();
|
|
1635
|
+
var dec2 = new TextDecoder();
|
|
1636
|
+
var PeerSocket = class {
|
|
1637
|
+
constructor(peerId, out, binary, onLocalClose) {
|
|
1638
|
+
this.peerId = peerId;
|
|
1639
|
+
this.out = out;
|
|
1640
|
+
this.binary = binary;
|
|
1641
|
+
this.onLocalClose = onLocalClose;
|
|
1642
|
+
}
|
|
1643
|
+
peerId;
|
|
1644
|
+
out;
|
|
1645
|
+
binary;
|
|
1646
|
+
onLocalClose;
|
|
1647
|
+
readyState = 0;
|
|
1648
|
+
bufferedAmount = 0;
|
|
1649
|
+
onopen = null;
|
|
1650
|
+
onmessage = null;
|
|
1651
|
+
onclose = null;
|
|
1652
|
+
onerror = null;
|
|
1653
|
+
/** Unsubscribes from the lobby; set by the factory. */
|
|
1654
|
+
detach = () => {
|
|
1655
|
+
};
|
|
1656
|
+
send(data) {
|
|
1657
|
+
if (this.readyState !== 1) return;
|
|
1658
|
+
this.out(typeof data === "string" ? enc2.encode(data) : data);
|
|
1659
|
+
}
|
|
1660
|
+
close(code = 1e3, reason = "left") {
|
|
1661
|
+
if (this.readyState === 3) return;
|
|
1662
|
+
this.closed(code, reason);
|
|
1663
|
+
this.onLocalClose();
|
|
1664
|
+
}
|
|
1665
|
+
/** @internal OPEN now; `onopen` now, or one microtask later so a handler assigned right after creation still runs. */
|
|
1666
|
+
open(later = false) {
|
|
1667
|
+
if (this.readyState !== 0) return;
|
|
1668
|
+
this.readyState = 1;
|
|
1669
|
+
if (!later) this.onopen?.({ type: "open" });
|
|
1670
|
+
else queueMicrotask(() => this.readyState === 1 && this.onopen?.({ type: "open" }));
|
|
1671
|
+
}
|
|
1672
|
+
/** @internal */
|
|
1673
|
+
deliver(bytes) {
|
|
1674
|
+
if (this.readyState === 1) this.onmessage?.({ type: "message", data: this.binary ? bytes : dec2.decode(bytes) });
|
|
1675
|
+
}
|
|
1676
|
+
/** @internal */
|
|
1677
|
+
closed(code, reason) {
|
|
1678
|
+
if (this.readyState === 3) return;
|
|
1679
|
+
this.readyState = 3;
|
|
1680
|
+
this.detach();
|
|
1681
|
+
this.onclose?.({ type: "close", code, reason, wasClean: code === 1e3 || code === 1001 });
|
|
1682
|
+
}
|
|
1683
|
+
};
|
|
1684
|
+
function joinerSocket(lobby, o = {}) {
|
|
1685
|
+
if (lobby.isHost) throw new Error("asWebSocket() is for joiners; the host uses lobby.onConnection()");
|
|
1686
|
+
const channel = o.channel ?? "reliable";
|
|
1687
|
+
const s = new PeerSocket(lobby.hostPeerId, (b) => lobby.send(lobby.hostPeerId, b, { channel }), !!o.binary, () => void lobby.leave());
|
|
1688
|
+
const offs = [
|
|
1689
|
+
lobby.on("message", (from, bytes) => {
|
|
1690
|
+
if (from === lobby.hostPeerId) s.deliver(bytes);
|
|
1691
|
+
}),
|
|
1692
|
+
lobby.on("sessionEnded", (reason) => s.closed(closeCodeFor(reason), reason)),
|
|
1693
|
+
// The socket's far end is the host it opened to; after a migration that server is gone (direct lobbies end instead).
|
|
1694
|
+
lobby.on("hostChanged", () => s.closed(1001, "host_changed"))
|
|
1695
|
+
];
|
|
1696
|
+
s.detach = () => offs.forEach((f) => f());
|
|
1697
|
+
if (lobby.connectedPeers.includes(lobby.hostPeerId)) s.open(true);
|
|
1698
|
+
else lobby.ready.then(() => s.open(true), () => {
|
|
1699
|
+
});
|
|
1700
|
+
return s;
|
|
1701
|
+
}
|
|
1702
|
+
function hostConnections(lobby, handler, o = {}) {
|
|
1703
|
+
if (!lobby.isHost) throw new Error("onConnection() is for the host; a joiner uses lobby.asWebSocket()");
|
|
1704
|
+
const channel = o.channel ?? "reliable";
|
|
1705
|
+
const conns = /* @__PURE__ */ new Map();
|
|
1706
|
+
let stopped = false;
|
|
1707
|
+
const ensure = (peerId) => {
|
|
1708
|
+
if (peerId === lobby.localPeerId) return void 0;
|
|
1709
|
+
let c = conns.get(peerId);
|
|
1710
|
+
if (c || stopped) return c;
|
|
1711
|
+
c = new PeerSocket(peerId, (b) => lobby.send(peerId, b, { channel }), !!o.binary, () => {
|
|
1712
|
+
});
|
|
1713
|
+
const conn = c;
|
|
1714
|
+
conn.detach = () => {
|
|
1715
|
+
if (conns.get(peerId) === conn) conns.delete(peerId);
|
|
1716
|
+
};
|
|
1717
|
+
conns.set(peerId, conn);
|
|
1718
|
+
conn.open();
|
|
1719
|
+
handler(conn);
|
|
1720
|
+
return conn;
|
|
1721
|
+
};
|
|
1722
|
+
const offs = [
|
|
1723
|
+
lobby.on("peerReady", (p) => void ensure(p.peerId)),
|
|
1724
|
+
lobby.on("message", (from, bytes) => ensure(from)?.deliver(bytes)),
|
|
1725
|
+
lobby.on("peerLeft", (p, reason) => conns.get(p.peerId)?.closed(reason === "left" ? 1001 : closeCodeFor(reason), reason)),
|
|
1726
|
+
lobby.on("sessionEnded", (reason) => {
|
|
1727
|
+
for (const c of [...conns.values()]) c.closed(reason === "left" ? 1001 : closeCodeFor(reason), reason);
|
|
1728
|
+
offs.forEach((f) => f());
|
|
1729
|
+
})
|
|
1730
|
+
];
|
|
1731
|
+
for (const id of lobby.connectedPeers) ensure(id);
|
|
1732
|
+
return () => {
|
|
1733
|
+
stopped = true;
|
|
1734
|
+
};
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1625
1737
|
// src/lobby.ts
|
|
1738
|
+
var MIN_PEER_TIMEOUT_MS = 6e3;
|
|
1626
1739
|
function seatName(p) {
|
|
1627
1740
|
const n = typeof p.name === "string" ? p.name.trim() : "";
|
|
1628
1741
|
if (n && n !== "Player") return p;
|
|
@@ -1682,6 +1795,10 @@ var OneLobby = (() => {
|
|
|
1682
1795
|
isReady = false;
|
|
1683
1796
|
cancelReadyTimer = null;
|
|
1684
1797
|
relayRetry = false;
|
|
1798
|
+
/** clock.now() of the last frame from each peer (peerTimeoutMs). */
|
|
1799
|
+
lastHeard = /* @__PURE__ */ new Map();
|
|
1800
|
+
/** Host: per-peer fixed window for rateLimit. */
|
|
1801
|
+
rate = /* @__PURE__ */ new Map();
|
|
1685
1802
|
/**
|
|
1686
1803
|
* Resolves when this peer can exchange data: immediately for the host, once the link to the host is open for a
|
|
1687
1804
|
* joiner. Rejects with OneLobbyError("ice_failed") when the joiner cannot reach the host in `readyTimeoutMs`
|
|
@@ -1765,6 +1882,21 @@ var OneLobby = (() => {
|
|
|
1765
1882
|
peer(peerId) {
|
|
1766
1883
|
return this.roster.get(peerId);
|
|
1767
1884
|
}
|
|
1885
|
+
/** Peers whose link is open and handshake done (host: the ready joiners; joiner: the host once ready). */
|
|
1886
|
+
get connectedPeers() {
|
|
1887
|
+
return this.connectedPeerIds();
|
|
1888
|
+
}
|
|
1889
|
+
/**
|
|
1890
|
+
* Joiner: the link to the host as a WebSocket-shaped object (text by default), so WebSocket client code runs
|
|
1891
|
+
* unchanged. It opens when `ready` resolves and closes when the session ends (`host_left` gives code 1001).
|
|
1892
|
+
*/
|
|
1893
|
+
asWebSocket(opts) {
|
|
1894
|
+
return joinerSocket(this, opts);
|
|
1895
|
+
}
|
|
1896
|
+
/** Host: `handler(conn)` once per joiner (a WebSocket-shaped connection), the server-side mirror of asWebSocket(). */
|
|
1897
|
+
onConnection(handler, opts) {
|
|
1898
|
+
return hostConnections(this, handler, opts);
|
|
1899
|
+
}
|
|
1768
1900
|
set snapshotChunkSize(n) {
|
|
1769
1901
|
this.lockstep.chunkSize = n;
|
|
1770
1902
|
}
|
|
@@ -1972,6 +2104,7 @@ var OneLobby = (() => {
|
|
|
1972
2104
|
return;
|
|
1973
2105
|
}
|
|
1974
2106
|
if (!d) return;
|
|
2107
|
+
if (!reassembled) this.lastHeard.set(from, this.cfg.clock.now());
|
|
1975
2108
|
const { msg, route } = d;
|
|
1976
2109
|
switch (msg.type) {
|
|
1977
2110
|
case "hi":
|
|
@@ -2056,6 +2189,7 @@ var OneLobby = (() => {
|
|
|
2056
2189
|
this.emit("message", route, bytes, channel);
|
|
2057
2190
|
return;
|
|
2058
2191
|
}
|
|
2192
|
+
if (!this.allowRaw(from)) return;
|
|
2059
2193
|
if (route === 0 || route === this.localPeerId) {
|
|
2060
2194
|
this.emit("message", from, bytes, channel);
|
|
2061
2195
|
}
|
|
@@ -2065,6 +2199,14 @@ var OneLobby = (() => {
|
|
|
2065
2199
|
this.sendTo(route, { type: "raw", bytes }, from, channel);
|
|
2066
2200
|
}
|
|
2067
2201
|
}
|
|
2202
|
+
allowRaw(from) {
|
|
2203
|
+
const lim = this.cfg.rateLimit;
|
|
2204
|
+
if (!lim || !(lim.messages > 0) || !(lim.perMs > 0)) return true;
|
|
2205
|
+
const now = this.cfg.clock.now();
|
|
2206
|
+
let w = this.rate.get(from);
|
|
2207
|
+
if (!w || now - w.start >= lim.perMs) this.rate.set(from, w = { start: now, n: 0 });
|
|
2208
|
+
return ++w.n <= lim.messages;
|
|
2209
|
+
}
|
|
2068
2210
|
// ---- migration -------------------------------------------------------------------------------------------------
|
|
2069
2211
|
setHost(hostId) {
|
|
2070
2212
|
if (hostId === this.hostPeerId) return;
|
|
@@ -2101,6 +2243,7 @@ var OneLobby = (() => {
|
|
|
2101
2243
|
this.markReady();
|
|
2102
2244
|
this.connected.clear();
|
|
2103
2245
|
this.hiSentTo.clear();
|
|
2246
|
+
this.lastHeard.clear();
|
|
2104
2247
|
this.lockstep.becomeHost();
|
|
2105
2248
|
this.emit("hostChanged", this.localPeerId);
|
|
2106
2249
|
if (this.serverUp) this.signaling.send({ t: "host_changed", hostId: this.localPeerId, epoch: this.epoch });
|
|
@@ -2224,6 +2367,8 @@ var OneLobby = (() => {
|
|
|
2224
2367
|
}
|
|
2225
2368
|
this.connected.delete(peerId);
|
|
2226
2369
|
this.outbox.delete(peerId);
|
|
2370
|
+
this.lastHeard.delete(peerId);
|
|
2371
|
+
this.rate.delete(peerId);
|
|
2227
2372
|
this.lockstep.onPeerLeft(peerId);
|
|
2228
2373
|
this.chat.onPeerLeft(peerId);
|
|
2229
2374
|
this.voice.onPeerLeft(peerId);
|
|
@@ -2255,6 +2400,9 @@ var OneLobby = (() => {
|
|
|
2255
2400
|
}
|
|
2256
2401
|
// ---- housekeeping ----------------------------------------------------------------------------------------------
|
|
2257
2402
|
watchdog() {
|
|
2403
|
+
if (this.ended) return;
|
|
2404
|
+
const timeout = this.cfg.peerTimeoutMs ?? 0;
|
|
2405
|
+
if (timeout > 0) this.dropSilent(Math.max(timeout, MIN_PEER_TIMEOUT_MS));
|
|
2258
2406
|
if (this.ended || this.isHost) return;
|
|
2259
2407
|
if (this.mode === "lockstep" && this.lockstep.hostSilent()) {
|
|
2260
2408
|
this.lockstep.touch();
|
|
@@ -2262,6 +2410,22 @@ var OneLobby = (() => {
|
|
|
2262
2410
|
this.handleHostLost("timeout");
|
|
2263
2411
|
}
|
|
2264
2412
|
}
|
|
2413
|
+
/** peerTimeoutMs: the host drops joiners it has not heard from; a joiner handles a silent host as lost. */
|
|
2414
|
+
dropSilent(timeout) {
|
|
2415
|
+
const now = this.cfg.clock.now();
|
|
2416
|
+
if (this.isHost) {
|
|
2417
|
+
for (const id of [...this.connected]) {
|
|
2418
|
+
const last = this.lastHeard.get(id);
|
|
2419
|
+
if (last !== void 0 && now - last > timeout) this.removePeer(id, "timeout");
|
|
2420
|
+
}
|
|
2421
|
+
} else if (this.isReady) {
|
|
2422
|
+
const last = this.lastHeard.get(this.hostPeerId);
|
|
2423
|
+
if (last !== void 0 && now - last > timeout) {
|
|
2424
|
+
this.lastHeard.delete(this.hostPeerId);
|
|
2425
|
+
this.handleHostLost("timeout");
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2265
2429
|
pingHost() {
|
|
2266
2430
|
if (this.ended || this.isHost) return;
|
|
2267
2431
|
this.sendTo(this.hostPeerId, { type: "ping", n: ++this.pingN, t: this.cfg.clock.now() >>> 0 }, 0, "fast");
|
|
@@ -2306,7 +2470,7 @@ var OneLobby = (() => {
|
|
|
2306
2470
|
var webCodecsOpus = {
|
|
2307
2471
|
createEncoder(opts, onFrame) {
|
|
2308
2472
|
let ts = 0;
|
|
2309
|
-
const
|
|
2473
|
+
const enc4 = new AudioEncoder({
|
|
2310
2474
|
output: (chunk) => {
|
|
2311
2475
|
const out = new Uint8Array(chunk.byteLength);
|
|
2312
2476
|
chunk.copyTo(out);
|
|
@@ -2314,7 +2478,7 @@ var OneLobby = (() => {
|
|
|
2314
2478
|
},
|
|
2315
2479
|
error: (e) => console.error("onelobby: AudioEncoder", e)
|
|
2316
2480
|
});
|
|
2317
|
-
|
|
2481
|
+
enc4.configure({
|
|
2318
2482
|
codec: "opus",
|
|
2319
2483
|
sampleRate: SAMPLE_RATE,
|
|
2320
2484
|
numberOfChannels: 1,
|
|
@@ -2332,17 +2496,17 @@ var OneLobby = (() => {
|
|
|
2332
2496
|
data: pcm
|
|
2333
2497
|
});
|
|
2334
2498
|
ts += 2e4;
|
|
2335
|
-
|
|
2499
|
+
enc4.encode(data);
|
|
2336
2500
|
data.close();
|
|
2337
2501
|
},
|
|
2338
2502
|
close() {
|
|
2339
|
-
if (
|
|
2503
|
+
if (enc4.state !== "closed") enc4.close();
|
|
2340
2504
|
}
|
|
2341
2505
|
};
|
|
2342
2506
|
},
|
|
2343
2507
|
createDecoder(onPcm) {
|
|
2344
2508
|
let ts = 0;
|
|
2345
|
-
const
|
|
2509
|
+
const dec4 = new AudioDecoder({
|
|
2346
2510
|
output: (audio) => {
|
|
2347
2511
|
const pcm = new Float32Array(audio.numberOfFrames);
|
|
2348
2512
|
audio.copyTo(pcm, { planeIndex: 0, format: "f32-planar" });
|
|
@@ -2351,18 +2515,18 @@ var OneLobby = (() => {
|
|
|
2351
2515
|
},
|
|
2352
2516
|
error: (e) => console.error("onelobby: AudioDecoder", e)
|
|
2353
2517
|
});
|
|
2354
|
-
|
|
2518
|
+
dec4.configure({ codec: "opus", sampleRate: SAMPLE_RATE, numberOfChannels: 1 });
|
|
2355
2519
|
return {
|
|
2356
2520
|
decode(opus) {
|
|
2357
2521
|
if (opus === null) {
|
|
2358
2522
|
onPcm(new Float32Array(FRAME_SAMPLES));
|
|
2359
2523
|
return;
|
|
2360
2524
|
}
|
|
2361
|
-
|
|
2525
|
+
dec4.decode(new EncodedAudioChunk({ type: "key", timestamp: ts, data: opus }));
|
|
2362
2526
|
ts += 2e4;
|
|
2363
2527
|
},
|
|
2364
2528
|
close() {
|
|
2365
|
-
if (
|
|
2529
|
+
if (dec4.state !== "closed") dec4.close();
|
|
2366
2530
|
}
|
|
2367
2531
|
};
|
|
2368
2532
|
}
|
|
@@ -2672,7 +2836,7 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
2672
2836
|
|
|
2673
2837
|
// src/onelobby.ts
|
|
2674
2838
|
var LIB_NAME = "onelobby";
|
|
2675
|
-
var LIB_VERSION = "0.
|
|
2839
|
+
var LIB_VERSION = "0.2.0";
|
|
2676
2840
|
var DEFAULT_READY_TIMEOUT_MS = 15e3;
|
|
2677
2841
|
function hasMic() {
|
|
2678
2842
|
return typeof navigator !== "undefined" && !!navigator.mediaDevices?.getUserMedia && typeof AudioWorkletNode !== "undefined";
|
|
@@ -2712,7 +2876,8 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
2712
2876
|
hashEveryTicks: o.hashEveryTicks ?? tickRate,
|
|
2713
2877
|
displayName: (o.displayName ?? "").trim(),
|
|
2714
2878
|
relayOnly: o.relayOnly ?? false,
|
|
2715
|
-
readyTimeoutMs: o.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS
|
|
2879
|
+
readyTimeoutMs: o.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS,
|
|
2880
|
+
peerTimeoutMs: o.peerTimeoutMs ?? 0
|
|
2716
2881
|
};
|
|
2717
2882
|
const a = o.advanced ?? {};
|
|
2718
2883
|
const pick = (k) => a[k] !== void 0 ? a[k] : o[k];
|
|
@@ -2821,7 +2986,7 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
2821
2986
|
throw e;
|
|
2822
2987
|
}
|
|
2823
2988
|
}
|
|
2824
|
-
makeLobby(sig, welcome, state, direct) {
|
|
2989
|
+
makeLobby(sig, welcome, state, direct, rateLimit) {
|
|
2825
2990
|
const lobby = new Lobby({
|
|
2826
2991
|
signaling: sig,
|
|
2827
2992
|
state,
|
|
@@ -2834,7 +2999,9 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
2834
2999
|
relayOnly: state.relayOnly ?? this.options.relayOnly,
|
|
2835
3000
|
displayName: this.options.displayName,
|
|
2836
3001
|
voice: { codec: this.voiceCodec, createSource: this.createMic, createSink: this.createSink },
|
|
2837
|
-
readyTimeoutMs: this.options.readyTimeoutMs
|
|
3002
|
+
readyTimeoutMs: this.options.readyTimeoutMs,
|
|
3003
|
+
peerTimeoutMs: this.options.peerTimeoutMs,
|
|
3004
|
+
rateLimit
|
|
2838
3005
|
});
|
|
2839
3006
|
lobby.errorSink = (e) => this.emit("error", e);
|
|
2840
3007
|
if (this.storage && !direct) {
|
|
@@ -2865,7 +3032,7 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
2865
3032
|
},
|
|
2866
3033
|
"lobby"
|
|
2867
3034
|
);
|
|
2868
|
-
return this.makeLobby(sig, welcome, state);
|
|
3035
|
+
return this.makeLobby(sig, welcome, state, void 0, h.rateLimit);
|
|
2869
3036
|
} catch (e) {
|
|
2870
3037
|
sig.close();
|
|
2871
3038
|
throw e;
|
|
@@ -2936,7 +3103,7 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
2936
3103
|
},
|
|
2937
3104
|
"lobby"
|
|
2938
3105
|
);
|
|
2939
|
-
return this.makeLobby(sig, welcome, state, { links: hooks.wrapLinks(this.linkFactory) });
|
|
3106
|
+
return this.makeLobby(sig, welcome, state, { links: hooks.wrapLinks(this.linkFactory) }, h.rateLimit);
|
|
2940
3107
|
} catch (e) {
|
|
2941
3108
|
sig.close();
|
|
2942
3109
|
throw e;
|
|
@@ -3069,9 +3236,9 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
3069
3236
|
var KeepaliveError = OneLobbyError;
|
|
3070
3237
|
|
|
3071
3238
|
// src/ui/controller.ts
|
|
3072
|
-
var
|
|
3073
|
-
var
|
|
3074
|
-
var toBytes = (w) =>
|
|
3239
|
+
var enc3 = new TextEncoder();
|
|
3240
|
+
var dec3 = new TextDecoder();
|
|
3241
|
+
var toBytes = (w) => enc3.encode(JSON.stringify(w));
|
|
3075
3242
|
var SharedState = class {
|
|
3076
3243
|
constructor(c) {
|
|
3077
3244
|
this.c = c;
|
|
@@ -3312,7 +3479,7 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
3312
3479
|
onRaw(from, bytes) {
|
|
3313
3480
|
let w;
|
|
3314
3481
|
try {
|
|
3315
|
-
w = JSON.parse(
|
|
3482
|
+
w = JSON.parse(dec3.decode(bytes));
|
|
3316
3483
|
} catch {
|
|
3317
3484
|
return;
|
|
3318
3485
|
}
|