onelobby 0.4.1 → 0.6.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/blueprint.schema.json +244 -0
- package/dist/blueprint.d.ts +170 -0
- package/dist/blueprint.js +286 -0
- package/dist/blueprint.js.map +1 -0
- package/dist/codec.d.ts +23 -0
- package/dist/codec.js +28 -0
- package/dist/codec.js.map +1 -1
- package/dist/direct/browser-host.d.ts +46 -0
- package/dist/direct/browser-host.js +93 -0
- package/dist/direct/browser-host.js.map +1 -0
- package/dist/direct/hub-host.d.ts +34 -23
- package/dist/direct/hub-host.js +75 -59
- package/dist/direct/hub-host.js.map +1 -1
- package/dist/direct/hub-local.d.ts +22 -0
- package/dist/direct/hub-local.js +46 -0
- package/dist/direct/hub-local.js.map +1 -0
- package/dist/direct/hub.d.ts +37 -10
- package/dist/direct/hub.js +114 -23
- package/dist/direct/hub.js.map +1 -1
- package/dist/direct/index.d.ts +37 -4
- package/dist/direct/index.js +162 -21
- package/dist/direct/index.js.map +1 -1
- package/dist/direct/metrics.d.ts +12 -0
- package/dist/direct/metrics.js +45 -0
- package/dist/direct/metrics.js.map +1 -0
- package/dist/direct/portmap.d.ts +9 -2
- package/dist/direct/portmap.js +7 -2
- package/dist/direct/portmap.js.map +1 -1
- package/dist/direct/sha1.d.ts +16 -0
- package/dist/direct/sha1.js +111 -0
- package/dist/direct/sha1.js.map +1 -0
- package/dist/direct-address.d.ts +2 -2
- package/dist/direct-address.js.map +1 -1
- package/dist/friendly.d.ts +28 -0
- package/dist/friendly.js +40 -0
- package/dist/friendly.js.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/internals.d.ts +9 -0
- package/dist/internals.js +9 -0
- package/dist/internals.js.map +1 -1
- package/dist/join-code-kind.d.ts +10 -0
- package/dist/join-code-kind.js +10 -0
- package/dist/join-code-kind.js.map +1 -0
- package/dist/joincode.d.ts +10 -1
- package/dist/joincode.js +23 -3
- package/dist/joincode.js.map +1 -1
- package/dist/lobby.d.ts +65 -4
- package/dist/lobby.js +151 -12
- package/dist/lobby.js.map +1 -1
- package/dist/lockstep.d.ts +8 -0
- package/dist/lockstep.js +23 -2
- package/dist/lockstep.js.map +1 -1
- package/dist/nostr/crypto.d.ts +20 -0
- package/dist/nostr/crypto.js +78 -0
- package/dist/nostr/crypto.js.map +1 -0
- package/dist/nostr/host.d.ts +66 -0
- package/dist/nostr/host.js +196 -0
- package/dist/nostr/host.js.map +1 -0
- package/dist/nostr/limits.d.ts +31 -0
- package/dist/nostr/limits.js +36 -0
- package/dist/nostr/limits.js.map +1 -0
- package/dist/nostr/link.d.ts +70 -0
- package/dist/nostr/link.js +180 -0
- package/dist/nostr/link.js.map +1 -0
- package/dist/nostr/relays.d.ts +79 -0
- package/dist/nostr/relays.js +315 -0
- package/dist/nostr/relays.js.map +1 -0
- package/dist/nostr/room.d.ts +43 -0
- package/dist/nostr/room.js +104 -0
- package/dist/nostr/room.js.map +1 -0
- package/dist/nostr/secp256k1.d.ts +10 -0
- package/dist/nostr/secp256k1.js +171 -0
- package/dist/nostr/secp256k1.js.map +1 -0
- package/dist/nostr/socket.d.ts +48 -0
- package/dist/nostr/socket.js +141 -0
- package/dist/nostr/socket.js.map +1 -0
- package/dist/onelobby.bundle.js +146 -0
- package/dist/onelobby.bundle.js.map +7 -0
- package/dist/onelobby.bundle.mjs +11 -5
- package/dist/onelobby.bundle.mjs.map +4 -4
- package/dist/onelobby.d.ts +54 -4
- package/dist/onelobby.global.js +2932 -49
- package/dist/onelobby.global.js.map +4 -4
- package/dist/onelobby.global.min.js +11 -5
- package/dist/onelobby.global.min.js.map +4 -4
- package/dist/onelobby.js +158 -15
- package/dist/onelobby.js.map +1 -1
- package/dist/pause.d.ts +85 -0
- package/dist/pause.js +160 -0
- package/dist/pause.js.map +1 -0
- package/dist/transport.d.ts +3 -1
- package/dist/transport.js.map +1 -1
- package/dist/webrtc.d.ts +1 -0
- package/dist/webrtc.js +6 -1
- package/dist/webrtc.js.map +1 -1
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
* WebRTC/signaling classes, clocks, the gridpaint demo game) live in `onelobby/internals`.
|
|
5
5
|
*/
|
|
6
6
|
export { OneLobby, LIB_NAME, LIB_VERSION } from "./onelobby.js";
|
|
7
|
-
export type { OneLobbyOptions, HostOptions, ListOptions, OneLobbyEvents, JoinDirectOptions } from "./onelobby.js";
|
|
7
|
+
export type { OneLobbyOptions, FromConfigOverrides, HostOptions, ListOptions, OneLobbyEvents, JoinDirectOptions } from "./onelobby.js";
|
|
8
8
|
export { DEFAULT_READY_TIMEOUT_MS } from "./onelobby.js";
|
|
9
9
|
export type { AdvancedOptions, SeatStorage } from "./onelobby.js";
|
|
10
|
+
export { parseBlueprint, defineBlueprint, BlueprintError } from "./blueprint.js";
|
|
11
|
+
export type { Blueprint, BlueprintInput, BlueprintEngine } from "./blueprint.js";
|
|
10
12
|
export { Lobby } from "./lobby.js";
|
|
11
13
|
export type { LobbyEvents, LobbyConfig, Peer, Phase, RateLimit } from "./lobby.js";
|
|
12
14
|
export { MIN_PEER_TIMEOUT_MS } from "./lobby.js";
|
|
@@ -15,6 +17,8 @@ export type { LobbySocket, LobbySocketOptions } from "./socket.js";
|
|
|
15
17
|
export { Lockstep } from "./lockstep.js";
|
|
16
18
|
export type { Frame, DesyncInfo, LockstepEvents } from "./lockstep.js";
|
|
17
19
|
export { Chat, CHAT_MAX_BYTES } from "./chat.js";
|
|
20
|
+
export { Pause } from "./pause.js";
|
|
21
|
+
export type { PauseState, PauseEvents, PauseMode, PauseRefusal } from "./pause.js";
|
|
18
22
|
export type { ChatMessage, ChatEvents } from "./chat.js";
|
|
19
23
|
export { Voice } from "./voice.js";
|
|
20
24
|
export type { VoiceEvents, VoiceDeps } from "./voice.js";
|
|
@@ -29,7 +33,11 @@ export { OneLobbyError } from "./signaling.js";
|
|
|
29
33
|
export type { LobbySummary, LobbyState, PeerInfo } from "./signaling.js";
|
|
30
34
|
export type { PeerLink, LinkFactory, SocketFactory, SocketLike, IceServer, ChannelName } from "./transport.js";
|
|
31
35
|
export type { Clock } from "./clock.js";
|
|
32
|
-
export { describeError, shareUrl, codeFromUrl, ErrorCodes } from "./friendly.js";
|
|
33
|
-
export type { FriendlyError, ErrorCode } from "./friendly.js";
|
|
36
|
+
export { describeError, shareUrl, codeFromUrl, directJoinInfo, ErrorCodes } from "./friendly.js";
|
|
37
|
+
export type { FriendlyError, ErrorCode, JoinInfo } from "./friendly.js";
|
|
34
38
|
export { Keepalive, KeepaliveError } from "./deprecated.js";
|
|
35
39
|
export type { KeepaliveOptions, KeepaliveEvents } from "./deprecated.js";
|
|
40
|
+
export { checkNostrRelays, DEFAULT_NOSTR_RELAYS, DEFAULT_NOSTR_STUN } from "./nostr/relays.js";
|
|
41
|
+
export type { RelayCheck, RelayConnect } from "./nostr/relays.js";
|
|
42
|
+
export { encodeRoomCode } from "./joincode.js";
|
|
43
|
+
export type { BrowserHostOptions, VisibilityDoc } from "./direct/browser-host.js";
|
package/dist/index.js
CHANGED
|
@@ -5,21 +5,27 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export { OneLobby, LIB_NAME, LIB_VERSION } from "./onelobby.js";
|
|
7
7
|
export { DEFAULT_READY_TIMEOUT_MS } from "./onelobby.js";
|
|
8
|
+
// Blueprint v1: onelobby.json (docs/design/blueprint.md). OneLobby.fromConfig(json) builds a kit from it.
|
|
9
|
+
export { parseBlueprint, defineBlueprint, BlueprintError } from "./blueprint.js";
|
|
8
10
|
export { Lobby } from "./lobby.js";
|
|
9
11
|
export { MIN_PEER_TIMEOUT_MS } from "./lobby.js";
|
|
10
12
|
// WebSocket-shaped sockets over a lobby: lobby.asWebSocket() (joiner), lobby.onConnection(conn => ...) (host).
|
|
11
13
|
export { closeCodeFor } from "./socket.js";
|
|
12
14
|
export { Lockstep } from "./lockstep.js";
|
|
13
15
|
export { Chat, CHAT_MAX_BYTES } from "./chat.js";
|
|
16
|
+
export { Pause } from "./pause.js";
|
|
14
17
|
export { Voice } from "./voice.js";
|
|
15
18
|
export { webCodecsOpusAvailable } from "./voice-browser.js";
|
|
16
19
|
export { normalizeCode, formatCode } from "./crockford.js";
|
|
17
|
-
// Direct IP (docs/direct-ip.md): kit.joinDirect(code); the code is the host's address in disguise. Hosting is in
|
|
20
|
+
// Direct IP (docs/design/direct-ip.md): kit.joinDirect(code); the code is the host's address in disguise. Hosting is in
|
|
18
21
|
// onelobby/direct (Node). webRtcLinkFactoryFor gives Node joiners a WebRTC stack (node-datachannel/polyfill).
|
|
19
22
|
export { decodeJoinCode, looksLikeJoinCode } from "./joincode.js";
|
|
20
23
|
export { webRtcLinkFactoryFor } from "./webrtc.js";
|
|
21
24
|
export { OneLobbyError } from "./signaling.js";
|
|
22
|
-
export { describeError, shareUrl, codeFromUrl, ErrorCodes } from "./friendly.js";
|
|
25
|
+
export { describeError, shareUrl, codeFromUrl, directJoinInfo, ErrorCodes } from "./friendly.js";
|
|
23
26
|
// Pre-rename names, kept for one version so existing games keep working.
|
|
24
27
|
export { Keepalive, KeepaliveError } from "./deprecated.js";
|
|
28
|
+
// Nostr signaling for direct hosts (spec/nostr-signaling.md): relay probe for picking hosting.nostrRelays.
|
|
29
|
+
export { checkNostrRelays, DEFAULT_NOSTR_RELAYS, DEFAULT_NOSTR_STUN } from "./nostr/relays.js";
|
|
30
|
+
export { encodeRoomCode } from "./joincode.js";
|
|
25
31
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,+GAA+G;AAC/G,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAEzD,0GAA0G;AAC1G,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEjF,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,+GAA+G;AAC/G,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAInC,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC3D,wHAAwH;AACxH,8GAA8G;AAC9G,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAK/C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEjG,yEAAyE;AACzE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE5D,2GAA2G;AAC3G,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE/F,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC","sourcesContent":["/**\n * Public API of `onelobby`: create a `OneLobby`, `host()` / `join(code)` / `list()` lobbies, then use the\n * `Lobby`'s lockstep, raw messages, chat and voice. Lower-level pieces (codec, chunking, migration, jitter buffer,\n * WebRTC/signaling classes, clocks, the gridpaint demo game) live in `onelobby/internals`.\n */\nexport { OneLobby, LIB_NAME, LIB_VERSION } from \"./onelobby.js\";\nexport type { OneLobbyOptions, FromConfigOverrides, HostOptions, ListOptions, OneLobbyEvents, JoinDirectOptions } from \"./onelobby.js\";\nexport { DEFAULT_READY_TIMEOUT_MS } from \"./onelobby.js\";\nexport type { AdvancedOptions, SeatStorage } from \"./onelobby.js\";\n// Blueprint v1: onelobby.json (docs/design/blueprint.md). OneLobby.fromConfig(json) builds a kit from it.\nexport { parseBlueprint, defineBlueprint, BlueprintError } from \"./blueprint.js\";\nexport type { Blueprint, BlueprintInput, BlueprintEngine } from \"./blueprint.js\";\nexport { Lobby } from \"./lobby.js\";\nexport type { LobbyEvents, LobbyConfig, Peer, Phase, RateLimit } from \"./lobby.js\";\nexport { MIN_PEER_TIMEOUT_MS } from \"./lobby.js\";\n// WebSocket-shaped sockets over a lobby: lobby.asWebSocket() (joiner), lobby.onConnection(conn => ...) (host).\nexport { closeCodeFor } from \"./socket.js\";\nexport type { LobbySocket, LobbySocketOptions } from \"./socket.js\";\nexport { Lockstep } from \"./lockstep.js\";\nexport type { Frame, DesyncInfo, LockstepEvents } from \"./lockstep.js\";\nexport { Chat, CHAT_MAX_BYTES } from \"./chat.js\";\nexport { Pause } from \"./pause.js\";\nexport type { PauseState, PauseEvents, PauseMode, PauseRefusal } from \"./pause.js\";\nexport type { ChatMessage, ChatEvents } from \"./chat.js\";\nexport { Voice } from \"./voice.js\";\nexport type { VoiceEvents, VoiceDeps } from \"./voice.js\";\nexport type { VoiceMode } from \"./voice-core.js\";\nexport type { VoiceCodec, VoiceEncoderHandle, VoiceDecoderHandle, FrameSource, AudioSink, VoiceError } from \"./voice-types.js\";\nexport { webCodecsOpusAvailable } from \"./voice-browser.js\";\nexport { normalizeCode, formatCode } from \"./crockford.js\";\n// Direct IP (docs/design/direct-ip.md): kit.joinDirect(code); the code is the host's address in disguise. Hosting is in\n// onelobby/direct (Node). webRtcLinkFactoryFor gives Node joiners a WebRTC stack (node-datachannel/polyfill).\nexport { decodeJoinCode, looksLikeJoinCode } from \"./joincode.js\";\nexport type { DecodedJoinCode, JoinCodeError } from \"./joincode.js\";\nexport { webRtcLinkFactoryFor } from \"./webrtc.js\";\nexport { OneLobbyError } from \"./signaling.js\";\nexport type { LobbySummary, LobbyState, PeerInfo } from \"./signaling.js\";\n// Types for the seams in OneLobbyOptions (ChannelName also tags raw messages).\nexport type { PeerLink, LinkFactory, SocketFactory, SocketLike, IceServer, ChannelName } from \"./transport.js\";\nexport type { Clock } from \"./clock.js\";\nexport { describeError, shareUrl, codeFromUrl, directJoinInfo, ErrorCodes } from \"./friendly.js\";\nexport type { FriendlyError, ErrorCode, JoinInfo } from \"./friendly.js\";\n// Pre-rename names, kept for one version so existing games keep working.\nexport { Keepalive, KeepaliveError } from \"./deprecated.js\";\nexport type { KeepaliveOptions, KeepaliveEvents } from \"./deprecated.js\";\n// Nostr signaling for direct hosts (spec/nostr-signaling.md): relay probe for picking hosting.nostrRelays.\nexport { checkNostrRelays, DEFAULT_NOSTR_RELAYS, DEFAULT_NOSTR_STUN } from \"./nostr/relays.js\";\nexport type { RelayCheck, RelayConnect } from \"./nostr/relays.js\";\nexport { encodeRoomCode } from \"./joincode.js\";\n// Browser host (no Node process, no port): kit.hostNostr(options).\nexport type { BrowserHostOptions, VisibilityDoc } from \"./direct/browser-host.js\";\n"]}
|
package/dist/internals.d.ts
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
export * from "./index.js";
|
|
8
8
|
export { MAX_DESYNCS, HOST_SILENCE_MS } from "./lockstep.js";
|
|
9
9
|
export { ChatLimiter, sanitizeChat, CHAT_HISTORY_LINES } from "./chat.js";
|
|
10
|
+
export { PAUSE_MIN_REQUEST_GAP_MS } from "./pause.js";
|
|
11
|
+
export { PAUSE_FLAG_PAUSER_LEFT, PAUSE_REFUSE } from "./codec.js";
|
|
10
12
|
export { JitterBuffer, VoiceGate, VoicePacketizer, VoiceRelayPolicy, FRAME_SAMPLES, SAMPLE_RATE, MAX_SPEAKERS, } from "./voice-core.js";
|
|
11
13
|
export type { VoicePacket } from "./voice-core.js";
|
|
12
14
|
export { webCodecsOpus, WorkletMic, WebAudioSink } from "./voice-browser.js";
|
|
@@ -26,3 +28,10 @@ export { encodeJoinCode, decodeJoinCode, normalizeJoinCode, looksLikeJoinCode, J
|
|
|
26
28
|
export { parseDirectAddress, DEFAULT_DIRECT_PORT } from "./direct-address.js";
|
|
27
29
|
export type { DirectAddress } from "./direct-address.js";
|
|
28
30
|
export { webRtcLinkFactoryFor } from "./webrtc.js";
|
|
31
|
+
export { NostrSocket } from "./nostr/socket.js";
|
|
32
|
+
export { NostrRoom } from "./nostr/room.js";
|
|
33
|
+
export { ReliableLink } from "./nostr/link.js";
|
|
34
|
+
export { RelayPool, makeEvent, NOSTR_KIND } from "./nostr/relays.js";
|
|
35
|
+
export { schnorrSign, schnorrVerify, schnorrPublicKey } from "./nostr/secp256k1.js";
|
|
36
|
+
export { deriveRoomKeys } from "./nostr/crypto.js";
|
|
37
|
+
export { encodeRoomCodeFor } from "./joincode.js";
|
package/dist/internals.js
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
export * from "./index.js";
|
|
8
8
|
export { MAX_DESYNCS, HOST_SILENCE_MS } from "./lockstep.js";
|
|
9
9
|
export { ChatLimiter, sanitizeChat, CHAT_HISTORY_LINES } from "./chat.js";
|
|
10
|
+
export { PAUSE_MIN_REQUEST_GAP_MS } from "./pause.js";
|
|
11
|
+
export { PAUSE_FLAG_PAUSER_LEFT, PAUSE_REFUSE } from "./codec.js";
|
|
10
12
|
export { JitterBuffer, VoiceGate, VoicePacketizer, VoiceRelayPolicy, FRAME_SAMPLES, SAMPLE_RATE, MAX_SPEAKERS, } from "./voice-core.js";
|
|
11
13
|
export { webCodecsOpus, WorkletMic, WebAudioSink } from "./voice-browser.js";
|
|
12
14
|
export { pickNewHost, claimWins, claimWinsWrapped } from "./migration.js";
|
|
@@ -21,4 +23,11 @@ export { Gridpaint, paintCmd, colourOf, PALETTE, GRID_W, GRID_H, seedFromCode, f
|
|
|
21
23
|
export { encodeJoinCode, decodeJoinCode, normalizeJoinCode, looksLikeJoinCode, JOIN_CODE_LENGTH } from "./joincode.js";
|
|
22
24
|
export { parseDirectAddress, DEFAULT_DIRECT_PORT } from "./direct-address.js";
|
|
23
25
|
export { webRtcLinkFactoryFor } from "./webrtc.js";
|
|
26
|
+
export { NostrSocket } from "./nostr/socket.js";
|
|
27
|
+
export { NostrRoom } from "./nostr/room.js";
|
|
28
|
+
export { ReliableLink } from "./nostr/link.js";
|
|
29
|
+
export { RelayPool, makeEvent, NOSTR_KIND } from "./nostr/relays.js";
|
|
30
|
+
export { schnorrSign, schnorrVerify, schnorrPublicKey } from "./nostr/secp256k1.js";
|
|
31
|
+
export { deriveRoomKeys } from "./nostr/crypto.js";
|
|
32
|
+
export { encodeRoomCodeFor } from "./joincode.js";
|
|
24
33
|
//# sourceMappingURL=internals.js.map
|
package/dist/internals.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internals.js","sourceRoot":"","sources":["../src/internals.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EACL,YAAY,EACZ,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,YAAY,GACb,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEhG,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE/G,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACvH,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC","sourcesContent":["/**\n * Everything the package has, including the building blocks apps normally never call: wire codec, chunking, deflate,\n * host-migration rule, jitter buffer and voice packetizer, signaling and WebRTC classes, clocks, and the gridpaint demo\n * game. Exported as `onelobby/internals`. No stability promise: these can change in any release.\n * The public API is the root export (`onelobby`); it is re-exported here too.\n */\nexport * from \"./index.js\";\nexport { MAX_DESYNCS, HOST_SILENCE_MS } from \"./lockstep.js\";\nexport { ChatLimiter, sanitizeChat, CHAT_HISTORY_LINES } from \"./chat.js\";\nexport {\n JitterBuffer,\n VoiceGate,\n VoicePacketizer,\n VoiceRelayPolicy,\n FRAME_SAMPLES,\n SAMPLE_RATE,\n MAX_SPEAKERS,\n} from \"./voice-core.js\";\nexport type { VoicePacket } from \"./voice-core.js\";\nexport { webCodecsOpus, WorkletMic, WebAudioSink } from \"./voice-browser.js\";\nexport { pickNewHost, claimWins, claimWinsWrapped } from \"./migration.js\";\nexport type { Claim } from \"./migration.js\";\nexport { decodeCrockford, encodeCrockford, CROCKFORD_ALPHABET } from \"./crockford.js\";\nexport { encodeMessage, decodeMessage, CodecError, MAX_FRAME_BYTES, MsgType } from \"./codec.js\";\nexport type { Message, Decoded } from \"./codec.js\";\nexport { splitChunks, Reassembler, CHUNK_PAYLOAD } from \"./chunking.js\";\nexport { deflate, inflate, deflateAvailable } from \"./deflate.js\";\nexport { SignalingClient } from \"./signaling.js\";\nexport { WebRtcLink, webRtcLinkFactory } from \"./webrtc.js\";\nexport { systemClock } from \"./clock.js\";\nexport { Gridpaint, paintCmd, colourOf, PALETTE, GRID_W, GRID_H, seedFromCode, fnv1a64 } from \"./gridpaint.js\";\nexport type { Hub } from \"./hub.js\";\nexport { encodeJoinCode, decodeJoinCode, normalizeJoinCode, looksLikeJoinCode, JOIN_CODE_LENGTH } from \"./joincode.js\";\nexport { parseDirectAddress, DEFAULT_DIRECT_PORT } from \"./direct-address.js\";\nexport type { DirectAddress } from \"./direct-address.js\";\nexport { webRtcLinkFactoryFor } from \"./webrtc.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"internals.js","sourceRoot":"","sources":["../src/internals.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EACL,YAAY,EACZ,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,YAAY,GACb,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEhG,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE/G,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACvH,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC","sourcesContent":["/**\n * Everything the package has, including the building blocks apps normally never call: wire codec, chunking, deflate,\n * host-migration rule, jitter buffer and voice packetizer, signaling and WebRTC classes, clocks, and the gridpaint demo\n * game. Exported as `onelobby/internals`. No stability promise: these can change in any release.\n * The public API is the root export (`onelobby`); it is re-exported here too.\n */\nexport * from \"./index.js\";\nexport { MAX_DESYNCS, HOST_SILENCE_MS } from \"./lockstep.js\";\nexport { ChatLimiter, sanitizeChat, CHAT_HISTORY_LINES } from \"./chat.js\";\nexport { PAUSE_MIN_REQUEST_GAP_MS } from \"./pause.js\";\nexport { PAUSE_FLAG_PAUSER_LEFT, PAUSE_REFUSE } from \"./codec.js\";\nexport {\n JitterBuffer,\n VoiceGate,\n VoicePacketizer,\n VoiceRelayPolicy,\n FRAME_SAMPLES,\n SAMPLE_RATE,\n MAX_SPEAKERS,\n} from \"./voice-core.js\";\nexport type { VoicePacket } from \"./voice-core.js\";\nexport { webCodecsOpus, WorkletMic, WebAudioSink } from \"./voice-browser.js\";\nexport { pickNewHost, claimWins, claimWinsWrapped } from \"./migration.js\";\nexport type { Claim } from \"./migration.js\";\nexport { decodeCrockford, encodeCrockford, CROCKFORD_ALPHABET } from \"./crockford.js\";\nexport { encodeMessage, decodeMessage, CodecError, MAX_FRAME_BYTES, MsgType } from \"./codec.js\";\nexport type { Message, Decoded } from \"./codec.js\";\nexport { splitChunks, Reassembler, CHUNK_PAYLOAD } from \"./chunking.js\";\nexport { deflate, inflate, deflateAvailable } from \"./deflate.js\";\nexport { SignalingClient } from \"./signaling.js\";\nexport { WebRtcLink, webRtcLinkFactory } from \"./webrtc.js\";\nexport { systemClock } from \"./clock.js\";\nexport { Gridpaint, paintCmd, colourOf, PALETTE, GRID_W, GRID_H, seedFromCode, fnv1a64 } from \"./gridpaint.js\";\nexport type { Hub } from \"./hub.js\";\nexport { encodeJoinCode, decodeJoinCode, normalizeJoinCode, looksLikeJoinCode, JOIN_CODE_LENGTH } from \"./joincode.js\";\nexport { parseDirectAddress, DEFAULT_DIRECT_PORT } from \"./direct-address.js\";\nexport type { DirectAddress } from \"./direct-address.js\";\nexport { webRtcLinkFactoryFor } from \"./webrtc.js\";\nexport { NostrSocket } from \"./nostr/socket.js\";\nexport { NostrRoom } from \"./nostr/room.js\";\nexport { ReliableLink } from \"./nostr/link.js\";\nexport { RelayPool, makeEvent, NOSTR_KIND } from \"./nostr/relays.js\";\nexport { schnorrSign, schnorrVerify, schnorrPublicKey } from \"./nostr/secp256k1.js\";\nexport { deriveRoomKeys } from \"./nostr/crypto.js\";\nexport { encodeRoomCodeFor } from \"./joincode.js\";\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a direct host's join code is. One tuple for the whole client; C# has the `JoinCodeKind` enum and
|
|
3
|
+
* `DirectLobby.KindName`, and `spec/vectors/join-code-kinds.json` pins that both spell each kind alike.
|
|
4
|
+
*/
|
|
5
|
+
export declare const JOIN_CODE_KINDS: readonly ["nostr", "internet", "same_network", "none"];
|
|
6
|
+
export type JoinCodeKind = (typeof JOIN_CODE_KINDS)[number];
|
|
7
|
+
/** An IP code (the host's address): everything but `nostr`. */
|
|
8
|
+
export type IpCodeKind = Exclude<JoinCodeKind, "nostr">;
|
|
9
|
+
/** The kind as the startup line spells it (C# `JoinCodeKind.ToString()`): `same_network` -> `SameNetwork`. */
|
|
10
|
+
export declare function joinCodeKindName(k: JoinCodeKind): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a direct host's join code is. One tuple for the whole client; C# has the `JoinCodeKind` enum and
|
|
3
|
+
* `DirectLobby.KindName`, and `spec/vectors/join-code-kinds.json` pins that both spell each kind alike.
|
|
4
|
+
*/
|
|
5
|
+
export const JOIN_CODE_KINDS = ["nostr", "internet", "same_network", "none"];
|
|
6
|
+
/** The kind as the startup line spells it (C# `JoinCodeKind.ToString()`): `same_network` -> `SameNetwork`. */
|
|
7
|
+
export function joinCodeKindName(k) {
|
|
8
|
+
return k === "internet" ? "Internet" : k === "same_network" ? "SameNetwork" : k === "nostr" ? "Nostr" : "None";
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=join-code-kind.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"join-code-kind.js","sourceRoot":"","sources":["../src/join-code-kind.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,CAAU,CAAC;AAKtF,8GAA8G;AAC9G,MAAM,UAAU,gBAAgB,CAAC,CAAe;IAC9C,OAAO,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,cAAc,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AACjH,CAAC","sourcesContent":["/**\n * What a direct host's join code is. One tuple for the whole client; C# has the `JoinCodeKind` enum and\n * `DirectLobby.KindName`, and `spec/vectors/join-code-kinds.json` pins that both spell each kind alike.\n */\nexport const JOIN_CODE_KINDS = [\"nostr\", \"internet\", \"same_network\", \"none\"] as const;\nexport type JoinCodeKind = (typeof JOIN_CODE_KINDS)[number];\n/** An IP code (the host's address): everything but `nostr`. */\nexport type IpCodeKind = Exclude<JoinCodeKind, \"nostr\">;\n\n/** The kind as the startup line spells it (C# `JoinCodeKind.ToString()`): `same_network` -> `SameNetwork`. */\nexport function joinCodeKindName(k: JoinCodeKind): string {\n return k === \"internet\" ? \"Internet\" : k === \"same_network\" ? \"SameNetwork\" : k === \"nostr\" ? \"Nostr\" : \"None\";\n}\n"]}
|
package/dist/joincode.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `dc1` join codes (docs/direct-ip.md s.2a, spec/reference/joincode.mjs): a direct-IP host's IPv4 address and port in
|
|
2
|
+
* `dc1` join codes (docs/design/direct-ip.md s.2a, spec/reference/joincode.mjs): a direct-IP host's IPv4 address and port in
|
|
3
3
|
* 11 Crockford characters, shown `6B01-RGFE-P2B`. The code is the address in disguise, so decoding asks nobody.
|
|
4
4
|
* Bits, most significant first: version:2 (0 = IPv4) | ipv4:32 | port:16 | crc:5 (CRC-5, polynomial 0x05, over the 50
|
|
5
5
|
* bits before it). One mistyped character always fails the check.
|
|
@@ -9,11 +9,20 @@ export type JoinCodeError = "bad_code" | "unknown_version";
|
|
|
9
9
|
export type DecodedJoinCode = {
|
|
10
10
|
ip: string;
|
|
11
11
|
port: number;
|
|
12
|
+
} | {
|
|
13
|
+
room: string;
|
|
12
14
|
} | {
|
|
13
15
|
error: JoinCodeError;
|
|
14
16
|
};
|
|
15
17
|
/** Display form (`6B01-RGFE-P2B`) for an IPv4 address and port 1-65535. Throws on anything else. */
|
|
16
18
|
export declare function encodeJoinCode(ipv4: string, port: number): string;
|
|
19
|
+
/**
|
|
20
|
+
* Version 1 code (a Nostr room, spec/nostr-signaling.md s.1): version:2 = 1 | room:48 | crc:5. `roomHex` is 12 hex
|
|
21
|
+
* digits. The room is only a secret both sides derive keys from.
|
|
22
|
+
*/
|
|
23
|
+
export declare function encodeRoomCodeFor(roomHex: string): string;
|
|
24
|
+
/** A new version 1 code with a random 48-bit room from the platform's CSPRNG. */
|
|
25
|
+
export declare function encodeRoomCode(): string;
|
|
17
26
|
/** Upper case, spaces and hyphens dropped, i/l -> 1, o -> 0; null unless 11 alphabet characters. */
|
|
18
27
|
export declare function normalizeJoinCode(input: string): string | null;
|
|
19
28
|
export declare function decodeJoinCode(input: string): DecodedJoinCode;
|
package/dist/joincode.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CROCKFORD_ALPHABET } from "./crockford.js";
|
|
2
2
|
/**
|
|
3
|
-
* `dc1` join codes (docs/direct-ip.md s.2a, spec/reference/joincode.mjs): a direct-IP host's IPv4 address and port in
|
|
3
|
+
* `dc1` join codes (docs/design/direct-ip.md s.2a, spec/reference/joincode.mjs): a direct-IP host's IPv4 address and port in
|
|
4
4
|
* 11 Crockford characters, shown `6B01-RGFE-P2B`. The code is the address in disguise, so decoding asks nobody.
|
|
5
5
|
* Bits, most significant first: version:2 (0 = IPv4) | ipv4:32 | port:16 | crc:5 (CRC-5, polynomial 0x05, over the 50
|
|
6
6
|
* bits before it). One mistyped character always fails the check.
|
|
@@ -36,7 +36,9 @@ export function encodeJoinCode(ipv4, port) {
|
|
|
36
36
|
throw new Error(`not an IPv4 address: ${ipv4}`);
|
|
37
37
|
if (!Number.isInteger(port) || port < 1 || port > 65535)
|
|
38
38
|
throw new Error(`bad port ${port}`);
|
|
39
|
-
|
|
39
|
+
return encodeData((BigInt(ip) << 16n) | BigInt(port)); // version 0
|
|
40
|
+
}
|
|
41
|
+
function encodeData(data) {
|
|
40
42
|
let v = (data << 5n) | BigInt(crc5(data, 50));
|
|
41
43
|
let s = "";
|
|
42
44
|
for (let i = 0; i < JOIN_CODE_LENGTH; i++) {
|
|
@@ -45,6 +47,21 @@ export function encodeJoinCode(ipv4, port) {
|
|
|
45
47
|
}
|
|
46
48
|
return `${s.slice(0, 4)}-${s.slice(4, 8)}-${s.slice(8)}`;
|
|
47
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Version 1 code (a Nostr room, spec/nostr-signaling.md s.1): version:2 = 1 | room:48 | crc:5. `roomHex` is 12 hex
|
|
52
|
+
* digits. The room is only a secret both sides derive keys from.
|
|
53
|
+
*/
|
|
54
|
+
export function encodeRoomCodeFor(roomHex) {
|
|
55
|
+
if (!/^[0-9a-fA-F]{12}$/.test(roomHex))
|
|
56
|
+
throw new Error(`room must be 12 hex digits: ${roomHex}`);
|
|
57
|
+
return encodeData((1n << 48n) | BigInt("0x" + roomHex));
|
|
58
|
+
}
|
|
59
|
+
/** A new version 1 code with a random 48-bit room from the platform's CSPRNG. */
|
|
60
|
+
export function encodeRoomCode() {
|
|
61
|
+
const b = new Uint8Array(6);
|
|
62
|
+
globalThis.crypto.getRandomValues(b);
|
|
63
|
+
return encodeRoomCodeFor([...b].map((x) => x.toString(16).padStart(2, "0")).join(""));
|
|
64
|
+
}
|
|
48
65
|
/** Upper case, spaces and hyphens dropped, i/l -> 1, o -> 0; null unless 11 alphabet characters. */
|
|
49
66
|
export function normalizeJoinCode(input) {
|
|
50
67
|
const s = input
|
|
@@ -69,7 +86,10 @@ export function decodeJoinCode(input) {
|
|
|
69
86
|
const data = v >> 5n;
|
|
70
87
|
if (crc5(data, 50) !== Number(v & 31n))
|
|
71
88
|
return { error: "bad_code" };
|
|
72
|
-
|
|
89
|
+
const version = data >> 48n;
|
|
90
|
+
if (version === 1n)
|
|
91
|
+
return { room: (data & 0xffffffffffffn).toString(16).padStart(12, "0") };
|
|
92
|
+
if (version !== 0n)
|
|
73
93
|
return { error: "unknown_version" };
|
|
74
94
|
const port = Number(data & 0xffffn);
|
|
75
95
|
if (port === 0)
|
package/dist/joincode.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"joincode.js","sourceRoot":"","sources":["../src/joincode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAKnC,SAAS,IAAI,CAAC,KAAa,EAAE,IAAY;IACvC,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC3B,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;QACxB,IAAI,GAAG,GAAG,GAAG;YAAE,GAAG,IAAI,IAAI,CAAC;IAC7B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,SAAS,CAAC,EAAU;IAC3B,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC5B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG;YAAE,OAAO,IAAI,CAAC;QACzD,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,IAAY;IACvD,MAAM,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,EAAE,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;IACjE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IAC7F,
|
|
1
|
+
{"version":3,"file":"joincode.js","sourceRoot":"","sources":["../src/joincode.ts"],"names":[],"mappings":"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","sourcesContent":["import { CROCKFORD_ALPHABET } from \"./crockford.js\";\n\n/**\n * `dc1` join codes (docs/design/direct-ip.md s.2a, spec/reference/joincode.mjs): a direct-IP host's IPv4 address and port in\n * 11 Crockford characters, shown `6B01-RGFE-P2B`. The code is the address in disguise, so decoding asks nobody.\n * Bits, most significant first: version:2 (0 = IPv4) | ipv4:32 | port:16 | crc:5 (CRC-5, polynomial 0x05, over the 50\n * bits before it). One mistyped character always fails the check.\n */\nexport const JOIN_CODE_LENGTH = 11;\n\nexport type JoinCodeError = \"bad_code\" | \"unknown_version\";\nexport type DecodedJoinCode = { ip: string; port: number } | { room: string } | { error: JoinCodeError };\n\nfunction crc5(value: bigint, bits: number): number {\n let crc = 0;\n for (let i = bits - 1; i >= 0; i--) {\n const bit = Number((value >> BigInt(i)) & 1n);\n const top = (crc >> 4) & 1;\n crc = (crc << 1) & 0x1f;\n if (top ^ bit) crc ^= 0x05;\n }\n return crc;\n}\n\nfunction parseIPv4(ip: string): number | null {\n const parts = ip.split(\".\");\n if (parts.length !== 4) return null;\n let n = 0;\n for (const p of parts) {\n if (!/^\\d{1,3}$/.test(p) || Number(p) > 255) return null;\n n = n * 256 + Number(p);\n }\n return n;\n}\n\n/** Display form (`6B01-RGFE-P2B`) for an IPv4 address and port 1-65535. Throws on anything else. */\nexport function encodeJoinCode(ipv4: string, port: number): string {\n const ip = parseIPv4(ipv4);\n if (ip === null) throw new Error(`not an IPv4 address: ${ipv4}`);\n if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error(`bad port ${port}`);\n return encodeData((BigInt(ip) << 16n) | BigInt(port)); // version 0\n}\n\nfunction encodeData(data: bigint): string {\n let v = (data << 5n) | BigInt(crc5(data, 50));\n let s = \"\";\n for (let i = 0; i < JOIN_CODE_LENGTH; i++) {\n s = CROCKFORD_ALPHABET[Number(v & 31n)] + s;\n v >>= 5n;\n }\n return `${s.slice(0, 4)}-${s.slice(4, 8)}-${s.slice(8)}`;\n}\n\n/**\n * Version 1 code (a Nostr room, spec/nostr-signaling.md s.1): version:2 = 1 | room:48 | crc:5. `roomHex` is 12 hex\n * digits. The room is only a secret both sides derive keys from.\n */\nexport function encodeRoomCodeFor(roomHex: string): string {\n if (!/^[0-9a-fA-F]{12}$/.test(roomHex)) throw new Error(`room must be 12 hex digits: ${roomHex}`);\n return encodeData((1n << 48n) | BigInt(\"0x\" + roomHex));\n}\n\n/** A new version 1 code with a random 48-bit room from the platform's CSPRNG. */\nexport function encodeRoomCode(): string {\n const b = new Uint8Array(6);\n globalThis.crypto.getRandomValues(b);\n return encodeRoomCodeFor([...b].map((x) => x.toString(16).padStart(2, \"0\")).join(\"\"));\n}\n\n/** Upper case, spaces and hyphens dropped, i/l -> 1, o -> 0; null unless 11 alphabet characters. */\nexport function normalizeJoinCode(input: string): string | null {\n const s = input\n .replace(/[ \\-]/g, \"\")\n .replace(/[a-z]/g, (c) => c.toUpperCase())\n .replace(/[IL]/g, \"1\")\n .replace(/O/g, \"0\");\n if (s.length !== JOIN_CODE_LENGTH) return null;\n for (const c of s) if (CROCKFORD_ALPHABET.indexOf(c) < 0) return null;\n return s;\n}\n\nexport function decodeJoinCode(input: string): DecodedJoinCode {\n const s = normalizeJoinCode(input);\n if (!s) return { error: \"bad_code\" };\n let v = 0n;\n for (const c of s) v = (v << 5n) | BigInt(CROCKFORD_ALPHABET.indexOf(c));\n const data = v >> 5n;\n if (crc5(data, 50) !== Number(v & 31n)) return { error: \"bad_code\" };\n const version = data >> 48n;\n if (version === 1n) return { room: (data & 0xffffffffffffn).toString(16).padStart(12, \"0\") };\n if (version !== 0n) return { error: \"unknown_version\" };\n const port = Number(data & 0xffffn);\n if (port === 0) return { error: \"bad_code\" };\n const a = Number((data >> 16n) & 0xffffffffn);\n return { ip: [a >>> 24, (a >>> 16) & 255, (a >>> 8) & 255, a & 255].join(\".\"), port };\n}\n\n/** Shaped like a join code (no dots or colons, 11 alphabet characters): a failed decode is `bad_code`, not a host name. */\nexport function looksLikeJoinCode(input: string): boolean {\n return !/[.:]/.test(input) && normalizeJoinCode(input) !== null;\n}\n"]}
|
package/dist/lobby.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Chat } from "./chat.js";
|
|
2
|
+
import type { IpCodeKind, JoinCodeKind } from "./join-code-kind.js";
|
|
2
3
|
import type { Clock } from "./clock.js";
|
|
3
4
|
import { PROTO } from "./codec.js";
|
|
4
5
|
import { Emitter } from "./emitter.js";
|
|
5
6
|
import { Lockstep } from "./lockstep.js";
|
|
7
|
+
import { Pause } from "./pause.js";
|
|
6
8
|
import { type LobbyState, type PeerInfo, type SignalingClient } from "./signaling.js";
|
|
7
9
|
import type { ChannelName, IceServer, LinkFactory, PeerLink } from "./transport.js";
|
|
8
10
|
import { Voice, type VoiceDeps } from "./voice.js";
|
|
@@ -23,6 +25,8 @@ export interface KickOptions {
|
|
|
23
25
|
reason?: string;
|
|
24
26
|
}
|
|
25
27
|
export type Peer = PeerInfo;
|
|
28
|
+
/** What a direct host's `joinCode` is: see {@link Lobby.joinCodeKind}. */
|
|
29
|
+
export type { JoinCodeKind };
|
|
26
30
|
export type LobbyEvents = {
|
|
27
31
|
peerJoined: [Peer];
|
|
28
32
|
/** The peer's data channels are open and the handshake is done: reliable sends reach it now (earlier ones were queued and flushed). */
|
|
@@ -31,6 +35,13 @@ export type LobbyEvents = {
|
|
|
31
35
|
ready: [];
|
|
32
36
|
/** reason "left", "kicked", "disconnected" (kick with ban false), "timeout", ...; `close` when the host gave one. */
|
|
33
37
|
peerLeft: [Peer, reason: string, close?: CloseInfo];
|
|
38
|
+
/**
|
|
39
|
+
* Host only: a joiner never got its link to the host open ("a friend could not connect"). reason "timeout" when it is
|
|
40
|
+
* not ready `readyTimeoutMs` after joining (it may still connect: `peerReady` then fires as usual), else the
|
|
41
|
+
* `peerLeft` reason when it leaves before it was ready (a joiner's own `ice_failed` ends that way). Fires at most once
|
|
42
|
+
* per peer, just before that `peerLeft`; not for peers the host kicks or disconnects.
|
|
43
|
+
*/
|
|
44
|
+
peerFailed: [Peer, reason: string];
|
|
34
45
|
joinRequested: [Peer];
|
|
35
46
|
hostChanged: [hostId: number];
|
|
36
47
|
phase: [Phase];
|
|
@@ -40,6 +51,16 @@ export type LobbyEvents = {
|
|
|
40
51
|
/** The signaling server went away. The game continues on the data channels (s.9). */
|
|
41
52
|
serverLost: [];
|
|
42
53
|
metaChanged: [Record<string, string>];
|
|
54
|
+
/**
|
|
55
|
+
* Direct-IP host only: the join code changed after `hostDirect` resolved, e.g. the router answered a later port-mapping
|
|
56
|
+
* retry and the code went from "same_network" to "internet". Show the new code (and `joinUrl`).
|
|
57
|
+
*/
|
|
58
|
+
joinCodeChanged: [code: string, kind: JoinCodeKind];
|
|
59
|
+
/**
|
|
60
|
+
* Browser host only (`kit.hostNostr`): the host tab went hidden (`true`) or visible again (`false`). Browsers throttle
|
|
61
|
+
* timers in hidden tabs, so joiners may see lag or drop; ask the host to keep the tab visible.
|
|
62
|
+
*/
|
|
63
|
+
hostHiddenChanged: [hidden: boolean];
|
|
43
64
|
};
|
|
44
65
|
export interface LobbyConfig {
|
|
45
66
|
signaling: SignalingClient;
|
|
@@ -59,7 +80,7 @@ export interface LobbyConfig {
|
|
|
59
80
|
*/
|
|
60
81
|
readyTimeoutMs?: number;
|
|
61
82
|
/**
|
|
62
|
-
* Direct IP (docs/direct-ip.md): the hub lives in the host, so there is no migration. A joiner that loses the host
|
|
83
|
+
* Direct IP (docs/design/direct-ip.md): the hub lives in the host, so there is no migration. A joiner that loses the host
|
|
63
84
|
* (link, peer_left, a host_changed from the hub as it shuts down, or the signaling socket) ends with "host_left".
|
|
64
85
|
*/
|
|
65
86
|
direct?: boolean;
|
|
@@ -91,31 +112,55 @@ export declare class Lobby extends Emitter<LobbyEvents> {
|
|
|
91
112
|
readonly tickRate: number;
|
|
92
113
|
readonly lockstep: Lockstep;
|
|
93
114
|
readonly chat: Chat;
|
|
115
|
+
/** The shared co-op pause (docs/recipes/pause.md). */
|
|
116
|
+
readonly pause: Pause;
|
|
94
117
|
readonly voice: Voice;
|
|
95
118
|
localPeerId: number;
|
|
96
119
|
hostPeerId: number;
|
|
97
120
|
phase: Phase;
|
|
98
121
|
meta: Record<string, string>;
|
|
122
|
+
/** The lobby's name as the server keeps it (host()'s `name`, sanitised); "" if the server sends none. */
|
|
123
|
+
name: string;
|
|
99
124
|
resumeToken: string;
|
|
100
125
|
/** Last measured round trip to the host in ms (joiners), or 0. */
|
|
101
126
|
rtt: number;
|
|
102
127
|
/**
|
|
103
|
-
* Direct-IP host only (onelobby/direct): the code friends paste to join, e.g. "6B01-RGFE-P2B" (docs/direct-ip.md
|
|
128
|
+
* Direct-IP host only (onelobby/direct): the code friends paste to join, e.g. "6B01-RGFE-P2B" (docs/design/direct-ip.md
|
|
104
129
|
* s.2a). Show it with joinCodeKind. Empty when the machine has no IPv4 address, and on joiners.
|
|
105
130
|
*/
|
|
106
131
|
joinCode: string;
|
|
107
|
-
/**
|
|
108
|
-
|
|
132
|
+
/**
|
|
133
|
+
* "nostr": a version 1 code that works through public Nostr relays (spec/nostr-signaling.md; the default for a direct
|
|
134
|
+
* host). "internet": the router forwarded the port and the code carries its public address; "same_network": the LAN
|
|
135
|
+
* address. "none": no code.
|
|
136
|
+
*/
|
|
137
|
+
joinCodeKind: JoinCodeKind;
|
|
138
|
+
/**
|
|
139
|
+
* Direct-IP host only: the IP code (address and port, version 0), with `directCodeKind` "internet" or "same_network".
|
|
140
|
+
* Equal to `joinCode` when Nostr is off; otherwise the code to hand out for LAN play or when the router port is open.
|
|
141
|
+
*/
|
|
142
|
+
directCode: string;
|
|
143
|
+
directCodeKind: IpCodeKind;
|
|
109
144
|
/** Direct-IP host only: this machine's addresses with the port, for an "Advanced" fold-out. */
|
|
110
145
|
directAddresses: string[];
|
|
111
146
|
/** Direct-IP host only: how the router port-open went ("UPnP", "no UPnP gateway answered; ...", "off"). */
|
|
112
147
|
portMapping: string;
|
|
148
|
+
/** Direct-IP host only: the one startup line (bound port, join code, port mapping); see `formatHostLog` in onelobby/direct. */
|
|
149
|
+
directHostLog: string;
|
|
150
|
+
/** Browser host only (`kit.hostNostr`): true while the host tab is hidden (see the `hostHiddenChanged` event). */
|
|
151
|
+
hostHidden: boolean;
|
|
152
|
+
/** @internal kit.hostNostr: the tab's visibility changed. */
|
|
153
|
+
setHostHidden(hidden: boolean): void;
|
|
154
|
+
/** @internal onelobby/direct: fires `joinCodeChanged` with the current code. */
|
|
155
|
+
notifyJoinCodeChanged(): void;
|
|
113
156
|
private signaling;
|
|
114
157
|
private cfg;
|
|
115
158
|
private roster;
|
|
116
159
|
private links;
|
|
117
160
|
/** ICE from a peer that has no link yet: its candidates can overtake its offer (node-datachannel). */
|
|
118
161
|
private earlyIce;
|
|
162
|
+
/** Offers from roster members that arrived while the host link was open (see offerVerdict), by sender. */
|
|
163
|
+
private heldOffers;
|
|
119
164
|
private connected;
|
|
120
165
|
private hiSentTo;
|
|
121
166
|
private epoch;
|
|
@@ -137,6 +182,8 @@ export declare class Lobby extends Emitter<LobbyEvents> {
|
|
|
137
182
|
private lastHeard;
|
|
138
183
|
/** Host: links of kicked / disconnected peers, kept open briefly (removePeer `linger`). */
|
|
139
184
|
private readonly lingering;
|
|
185
|
+
/** Host: joiners that joined but are not ready yet, with the cancel of their readyTimeoutMs timer (peerFailed). */
|
|
186
|
+
private notReady;
|
|
140
187
|
/** Host: per-peer fixed window for rateLimit. */
|
|
141
188
|
private rate;
|
|
142
189
|
/**
|
|
@@ -203,6 +250,8 @@ export declare class Lobby extends Emitter<LobbyEvents> {
|
|
|
203
250
|
/** The direct attempt stalled: dial the host ourselves through the TURN relay (a host answers any offer). */
|
|
204
251
|
private retryRelayed;
|
|
205
252
|
private giveUpConnecting;
|
|
253
|
+
/** @internal A direct host's hub learns where each joiner's link comes from (Nostr kick bans the address too). */
|
|
254
|
+
linkAddressSink: ((peerId: number, ip: string) => void) | null;
|
|
206
255
|
private makeLink;
|
|
207
256
|
/** Host side: offer to a joiner. */
|
|
208
257
|
private offerTo;
|
|
@@ -217,10 +266,20 @@ export declare class Lobby extends Emitter<LobbyEvents> {
|
|
|
217
266
|
private setHost;
|
|
218
267
|
/** The host is gone (link closed, no frames for 3 s, or the server said so): run the s.9 rule. */
|
|
219
268
|
private handleHostLost;
|
|
269
|
+
/** Offers that came from roster members while the host link was still open: now the host is lost, answer them. */
|
|
270
|
+
private replayHeldOffers;
|
|
220
271
|
private becomeHost;
|
|
221
272
|
private onHostClaim;
|
|
222
273
|
private onSignaling;
|
|
223
274
|
private onSignal;
|
|
275
|
+
/**
|
|
276
|
+
* Whether an SDP offer from `from` may be answered. The host (or a joiner's host) always may. Direct lobbies have no
|
|
277
|
+
* migration, so nobody else. In a server lobby a roster member may dial us when we are the host (a claim race decides
|
|
278
|
+
* who wins) or when our own link to the host is gone (the migration window); while that link is open the offer is
|
|
279
|
+
* held, to be answered if the host turns out to be lost a moment later.
|
|
280
|
+
*/
|
|
281
|
+
private offerVerdict;
|
|
282
|
+
private acceptOffer;
|
|
224
283
|
/**
|
|
225
284
|
* `linger` (host kick / disconnect): stop using the peer's link at once but leave it open until that peer closes it
|
|
226
285
|
* or KICK_LINGER_MS pass. The hub tells the peer over its WebSocket; closing the data link first would make it look
|
|
@@ -235,6 +294,8 @@ export declare class Lobby extends Emitter<LobbyEvents> {
|
|
|
235
294
|
/** peerTimeoutMs: the host drops joiners it has not heard from; a joiner handles a silent host as lost. */
|
|
236
295
|
private dropSilent;
|
|
237
296
|
private pingHost;
|
|
297
|
+
/** Host: report a joiner that is not ready `readyTimeoutMs` after joining as peerFailed("timeout"), once. */
|
|
298
|
+
private watchReady;
|
|
238
299
|
private teardown;
|
|
239
300
|
/** Total in-flight links (diagnostics and tests). */
|
|
240
301
|
get linkCount(): number;
|