@net-mesh/browser 0.37.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/CHANGELOG.md +517 -0
- package/LICENSE-APACHE +190 -0
- package/LICENSE-MIT +21 -0
- package/README.md +666 -0
- package/dist/async-queue.d.ts +26 -0
- package/dist/async-queue.js +62 -0
- package/dist/credential.d.ts +70 -0
- package/dist/credential.js +95 -0
- package/dist/errors.d.ts +400 -0
- package/dist/errors.js +726 -0
- package/dist/events.d.ts +232 -0
- package/dist/events.js +298 -0
- package/dist/identity.d.ts +40 -0
- package/dist/identity.js +78 -0
- package/dist/index.bundle.js +2 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +46 -0
- package/dist/leader/events.d.ts +111 -0
- package/dist/leader/events.js +116 -0
- package/dist/leader/index.d.ts +14 -0
- package/dist/leader/index.js +11 -0
- package/dist/leader/session.d.ts +539 -0
- package/dist/leader/session.js +770 -0
- package/dist/leader/wasm.d.ts +123 -0
- package/dist/leader/wasm.js +39 -0
- package/dist/lobby.d.ts +183 -0
- package/dist/lobby.js +504 -0
- package/dist/local.d.ts +80 -0
- package/dist/local.js +160 -0
- package/dist/net_leaf.d.ts +1494 -0
- package/dist/net_leaf.js +3753 -0
- package/dist/net_leaf_bg.wasm +0 -0
- package/dist/net_leaf_bg.wasm.d.ts +137 -0
- package/dist/netcode/client.d.ts +102 -0
- package/dist/netcode/client.js +296 -0
- package/dist/netcode/clock.d.ts +45 -0
- package/dist/netcode/clock.js +54 -0
- package/dist/netcode/host.d.ts +118 -0
- package/dist/netcode/host.js +276 -0
- package/dist/netcode/index.d.ts +19 -0
- package/dist/netcode/index.js +14 -0
- package/dist/netcode/interpolate.d.ts +50 -0
- package/dist/netcode/interpolate.js +100 -0
- package/dist/netcode/wire.d.ts +125 -0
- package/dist/netcode/wire.js +117 -0
- package/dist/node.d.ts +908 -0
- package/dist/node.js +1085 -0
- package/dist/org.d.ts +412 -0
- package/dist/org.js +567 -0
- package/dist/peer-driver.d.ts +117 -0
- package/dist/peer-driver.js +224 -0
- package/dist/store/assembly.d.ts +176 -0
- package/dist/store/assembly.js +325 -0
- package/dist/store/chunker.d.ts +83 -0
- package/dist/store/chunker.js +190 -0
- package/dist/store/core.d.ts +136 -0
- package/dist/store/core.js +477 -0
- package/dist/store/definition.d.ts +23 -0
- package/dist/store/definition.js +83 -0
- package/dist/store/errors.d.ts +77 -0
- package/dist/store/errors.js +94 -0
- package/dist/store/host.d.ts +247 -0
- package/dist/store/host.js +675 -0
- package/dist/store/index.d.ts +50 -0
- package/dist/store/index.js +40 -0
- package/dist/store/interest.d.ts +40 -0
- package/dist/store/interest.js +77 -0
- package/dist/store/inventory.d.ts +81 -0
- package/dist/store/inventory.js +140 -0
- package/dist/store/join.d.ts +118 -0
- package/dist/store/join.js +724 -0
- package/dist/store/json.d.ts +50 -0
- package/dist/store/json.js +283 -0
- package/dist/store/ledger.d.ts +187 -0
- package/dist/store/ledger.js +292 -0
- package/dist/store/owner.d.ts +616 -0
- package/dist/store/owner.js +1711 -0
- package/dist/store/patch.d.ts +70 -0
- package/dist/store/patch.js +166 -0
- package/dist/store/player.d.ts +65 -0
- package/dist/store/player.js +261 -0
- package/dist/store/replica.d.ts +187 -0
- package/dist/store/replica.js +740 -0
- package/dist/store/state.d.ts +42 -0
- package/dist/store/state.js +165 -0
- package/dist/store/types.d.ts +200 -0
- package/dist/store/types.js +25 -0
- package/dist/store/visibility.d.ts +118 -0
- package/dist/store/visibility.js +282 -0
- package/dist/store/wire.d.ts +309 -0
- package/dist/store/wire.js +834 -0
- package/dist/stream.d.ts +174 -0
- package/dist/stream.js +238 -0
- package/dist/three/index.d.ts +109 -0
- package/dist/three/index.js +130 -0
- package/dist/udp-probe.d.ts +159 -0
- package/dist/udp-probe.js +245 -0
- package/dist/wasm.d.ts +642 -0
- package/dist/wasm.js +98 -0
- package/dist/world/border.d.ts +84 -0
- package/dist/world/border.js +99 -0
- package/dist/world/handoff.d.ts +187 -0
- package/dist/world/handoff.js +222 -0
- package/dist/world/index.d.ts +13 -0
- package/dist/world/index.js +9 -0
- package/dist/world/link.d.ts +179 -0
- package/dist/world/link.js +476 -0
- package/dist/world/regions.d.ts +154 -0
- package/dist/world/regions.js +314 -0
- package/package.json +72 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `wasm_bindgen` boundary for §8's session surface.
|
|
3
|
+
*
|
|
4
|
+
* `src/wasm.ts` describes the *direct* surface (`LeafNode`) and types
|
|
5
|
+
* `MeshSession` as `unknown` so the two cannot drift into two
|
|
6
|
+
* spellings of one contract. This file is the one place the session's
|
|
7
|
+
* shape is declared, in the snake_case `wasm-bindgen` emits from the
|
|
8
|
+
* Rust method names; every camelCase name a page sees is added by
|
|
9
|
+
* {@link MeshSession} one layer up.
|
|
10
|
+
*/
|
|
11
|
+
import type { LeafWasmConnectOptions, LeafWasmModule, LeafWasmOrgAccess, LeafWasmOrgCallOptions, LeafWasmOrgClientStreamHandler, LeafWasmOrgDuplexHandler, LeafWasmOrgServeHandle, LeafWasmOrgServeOptions, LeafWasmOrgStreamingHandler, LeafWasmOrgUnaryHandler, LeafWasmOrgUploadCallHandle, LeafWasmOrgByteStreamHandle, LeafWasmOrgDuplexCallHandle, LeafWasmProxyStream, LeafWasmStreamOptions } from '../wasm.js';
|
|
12
|
+
/**
|
|
13
|
+
* `MeshSession.open`'s argument: everything `LeafNode.connect` reads,
|
|
14
|
+
* plus what leader election needs.
|
|
15
|
+
*/
|
|
16
|
+
export interface LeafWasmSessionOptions extends LeafWasmConnectOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Capabilities to announce, and to **re-announce** whenever this tab
|
|
19
|
+
* becomes the leader. They live on the session rather than on a
|
|
20
|
+
* method call because a new leader has to re-publish them without
|
|
21
|
+
* being asked.
|
|
22
|
+
*/
|
|
23
|
+
capabilities?: readonly string[];
|
|
24
|
+
/**
|
|
25
|
+
* Channels this tab depends on. The leader keeps the union of every
|
|
26
|
+
* follower's declaration subscribed, and a new leader restores it.
|
|
27
|
+
*/
|
|
28
|
+
subscriptions?: readonly string[];
|
|
29
|
+
/** The IndexedDB database holding the identity. Defaults to `net-mesh-leaf`. */
|
|
30
|
+
dbName?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Override the Web Lock and `BroadcastChannel` name. Defaults to
|
|
33
|
+
* `net-mesh/<origin>/<identity-fingerprint>`, which is the scope
|
|
34
|
+
* one-node-per-origin means; overriding it is for tests that need
|
|
35
|
+
* two independent elections in one origin.
|
|
36
|
+
*/
|
|
37
|
+
lockScope?: string;
|
|
38
|
+
}
|
|
39
|
+
/** The session object `MeshSession.open` resolves to. */
|
|
40
|
+
export interface LeafWasmSession {
|
|
41
|
+
/** `"leader"` or `"follower"`. */
|
|
42
|
+
role(): string;
|
|
43
|
+
/** The generation in force for this tab, as an exact decimal string. */
|
|
44
|
+
generation(): string;
|
|
45
|
+
/** The node's id, 16 lowercase hex digits, once one is known. */
|
|
46
|
+
node_id_hex(): string | undefined;
|
|
47
|
+
/** The identity fingerprint the lock is named after. */
|
|
48
|
+
fingerprint(): string;
|
|
49
|
+
/** The lock and channel name. */
|
|
50
|
+
scope(): string;
|
|
51
|
+
/** The measured handoff for a promoted tab; `undefined` on the first leader. */
|
|
52
|
+
interruption_ms(): number | undefined;
|
|
53
|
+
call(service: string, payload: Uint8Array, timeout_ms?: number): Promise<Uint8Array>;
|
|
54
|
+
call_org(service: string, payload: Uint8Array, options: LeafWasmOrgCallOptions): Promise<Uint8Array>;
|
|
55
|
+
call_org_streaming(service: string, payload: Uint8Array, options: LeafWasmOrgCallOptions): Promise<LeafWasmOrgByteStreamHandle>;
|
|
56
|
+
call_org_client_stream(service: string, options: LeafWasmOrgCallOptions): Promise<LeafWasmOrgUploadCallHandle>;
|
|
57
|
+
call_org_duplex(service: string, options: LeafWasmOrgCallOptions): Promise<LeafWasmOrgDuplexCallHandle>;
|
|
58
|
+
serve_org(service: string, access: LeafWasmOrgAccess, handler: LeafWasmOrgUnaryHandler, options: LeafWasmOrgServeOptions): LeafWasmOrgServeHandle;
|
|
59
|
+
serve_org_streaming(service: string, access: LeafWasmOrgAccess, handler: LeafWasmOrgStreamingHandler, options: LeafWasmOrgServeOptions): LeafWasmOrgServeHandle;
|
|
60
|
+
serve_org_client_stream(service: string, access: LeafWasmOrgAccess, handler: LeafWasmOrgClientStreamHandler, options: LeafWasmOrgServeOptions): LeafWasmOrgServeHandle;
|
|
61
|
+
serve_org_duplex(service: string, access: LeafWasmOrgAccess, handler: LeafWasmOrgDuplexHandler, options: LeafWasmOrgServeOptions): LeafWasmOrgServeHandle;
|
|
62
|
+
subscribe(channel: string): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Release this tab's claim on a channel. The membership survives
|
|
65
|
+
* while another tab still declares it.
|
|
66
|
+
*/
|
|
67
|
+
unsubscribe(channel: string): Promise<void>;
|
|
68
|
+
publish(channel: string, payload: Uint8Array): Promise<void>;
|
|
69
|
+
announce(capabilities: string[]): Promise<void>;
|
|
70
|
+
query(capability: string): Promise<string>;
|
|
71
|
+
/** Every counter as JSON. A promise: on a follower the node is elsewhere. */
|
|
72
|
+
counters_json(): Promise<string>;
|
|
73
|
+
/** Proxied, so a follower's `enroll()` works — one node per origin. */
|
|
74
|
+
enroll(): Promise<void>;
|
|
75
|
+
/** A promise, where `LeafNode.is_enrolled` is synchronous. */
|
|
76
|
+
is_enrolled(): Promise<boolean>;
|
|
77
|
+
signal(peer_hex: string, dialog_hex: string, kind: string, payload: Uint8Array): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* The four peer-attempt primitives, proxied. `peer_candidate` and
|
|
80
|
+
* `peer_handshake` take the dialog because the leaf requires it:
|
|
81
|
+
* a proxied request is served after crossing a channel, so the
|
|
82
|
+
* attempt it named may have been replaced, and it is refused
|
|
83
|
+
* before it can drive the replacement.
|
|
84
|
+
*/
|
|
85
|
+
peer_offer(peer_hex: string): Promise<string>;
|
|
86
|
+
/**
|
|
87
|
+
* The live attempt's dialog when the pair is already direct and open on
|
|
88
|
+
* the leader, else `undefined`. An older leader refuses the op.
|
|
89
|
+
*/
|
|
90
|
+
peer_direct_dialog(peer_hex: string): Promise<string | undefined>;
|
|
91
|
+
peer_accept_offer(peer_hex: string): Promise<string>;
|
|
92
|
+
peer_candidate(peer_hex: string, dialog_hex: string): Promise<string>;
|
|
93
|
+
peer_handshake(peer_hex: string, dialog_hex: string): Promise<string>;
|
|
94
|
+
/**
|
|
95
|
+
* A promise, where `LeafNode.open_stream` is synchronous: on a
|
|
96
|
+
* follower the stream is opened by the tab that owns the
|
|
97
|
+
* DataChannel.
|
|
98
|
+
*/
|
|
99
|
+
open_stream(options: LeafWasmStreamOptions): Promise<LeafWasmProxyStream>;
|
|
100
|
+
on_event(callback: (eventJson: string) => void): void;
|
|
101
|
+
close(): void;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The generated module, with `MeshSession` refined.
|
|
105
|
+
*
|
|
106
|
+
* A bundle built before Stage 5 slice 3 does not carry it, which is
|
|
107
|
+
* why the base type leaves it optional and this narrows rather than
|
|
108
|
+
* assumes.
|
|
109
|
+
*/
|
|
110
|
+
export interface LeafWasmSessionModule extends LeafWasmModule {
|
|
111
|
+
MeshSession: {
|
|
112
|
+
open(options: LeafWasmSessionOptions): Promise<LeafWasmSession>;
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Narrow a loaded module to one that carries the session surface.
|
|
117
|
+
*
|
|
118
|
+
* A named refusal rather than a cast: a page bundling an older
|
|
119
|
+
* `net_leaf.js` would otherwise get `undefined is not a constructor`
|
|
120
|
+
* from inside the wrapper, which says nothing about what is actually
|
|
121
|
+
* wrong.
|
|
122
|
+
*/
|
|
123
|
+
export declare function asSessionModule(module: LeafWasmModule): LeafWasmSessionModule;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `wasm_bindgen` boundary for §8's session surface.
|
|
3
|
+
*
|
|
4
|
+
* `src/wasm.ts` describes the *direct* surface (`LeafNode`) and types
|
|
5
|
+
* `MeshSession` as `unknown` so the two cannot drift into two
|
|
6
|
+
* spellings of one contract. This file is the one place the session's
|
|
7
|
+
* shape is declared, in the snake_case `wasm-bindgen` emits from the
|
|
8
|
+
* Rust method names; every camelCase name a page sees is added by
|
|
9
|
+
* {@link MeshSession} one layer up.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Narrow a loaded module to one that carries the session surface.
|
|
13
|
+
*
|
|
14
|
+
* A named refusal rather than a cast: a page bundling an older
|
|
15
|
+
* `net_leaf.js` would otherwise get `undefined is not a constructor`
|
|
16
|
+
* from inside the wrapper, which says nothing about what is actually
|
|
17
|
+
* wrong.
|
|
18
|
+
*/
|
|
19
|
+
export function asSessionModule(module) {
|
|
20
|
+
const candidate = module.MeshSession;
|
|
21
|
+
// `wasm-bindgen` emits `export class MeshSession { static open(…) }`,
|
|
22
|
+
// and a class is a FUNCTION, not an object — so the shape check has
|
|
23
|
+
// to admit both. It used to test `typeof === 'object'` only, which
|
|
24
|
+
// rejected every real bundle and reported the pre-slice-3 message
|
|
25
|
+
// for a module that carried the session all along.
|
|
26
|
+
const usable = candidate !== null &&
|
|
27
|
+
(typeof candidate === 'object' || typeof candidate === 'function') &&
|
|
28
|
+
'open' in candidate &&
|
|
29
|
+
typeof candidate.open === 'function';
|
|
30
|
+
if (!usable) {
|
|
31
|
+
throw new Error('this net-mesh-leaf bundle has no MeshSession: leader election and the ' +
|
|
32
|
+
'follower proxy need a wasm build from Stage 5 slice 3 or later');
|
|
33
|
+
}
|
|
34
|
+
// Checked above: `MeshSession.open` exists and is callable. The
|
|
35
|
+
// argument and return types are the wasm-bindgen contract this file
|
|
36
|
+
// declares, and no runtime check can establish those.
|
|
37
|
+
const narrowed = module;
|
|
38
|
+
return narrowed;
|
|
39
|
+
}
|
package/dist/lobby.d.ts
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lobbies: host a game others can find, list the open ones, join by
|
|
3
|
+
* code or link.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* const lobby = await createLobby({ node, game: 'arena', name: 'Friday arena', capacity: 8,
|
|
7
|
+
* definition, initialState, actions, inputs, project });
|
|
8
|
+
* lobby.code; // 'K7QP2M' — say it out loud, or share lobby.link()
|
|
9
|
+
* const me = lobby.self; // the host's own player, same shape as a joined one
|
|
10
|
+
*
|
|
11
|
+
* const open = await listLobbies({ node, game: 'arena' });
|
|
12
|
+
* const world = await joinLobby({ node, definition, code: 'K7QP2M' });
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* A thin layer over what already exists — `hostStore`, `hostPlayer`,
|
|
16
|
+
* `joinStore`, `announce` and `query` — and no new protocol. A lobby is
|
|
17
|
+
* found through capability tags, which are free-form strings the mesh
|
|
18
|
+
* carries in a node's signed announcement:
|
|
19
|
+
*
|
|
20
|
+
* - `net-lobby:<game>` — the listing tag; public lobbies only.
|
|
21
|
+
* - `net-lobby:<game>:rec:<base64url JSON>` — the record a list shows:
|
|
22
|
+
* code, name, players, capacity, store version and the game's own
|
|
23
|
+
* `info`. Public lobbies only.
|
|
24
|
+
* - `net-lobby:<game>:seek:<host hex>` — announced by a player joining that
|
|
25
|
+
* host. A browser node accepts a relayed handshake only from a peer whose
|
|
26
|
+
* signed announcement it holds, and the anchor delivers announcements to
|
|
27
|
+
* its peers — so a joiner that announces nothing cannot reach the host
|
|
28
|
+
* (measured: `examples/anchor-acceptance`). The tag says why this player
|
|
29
|
+
* announces at all.
|
|
30
|
+
* - `net-lobby:<game>:code:<32 hex>` — the code, hashed; how a code is
|
|
31
|
+
* looked up. Both kinds announce it.
|
|
32
|
+
*
|
|
33
|
+
* **What a listing is.** Anyone on the mesh can announce any tag, so a
|
|
34
|
+
* record is a claim. The host id beside it is not: it comes from the
|
|
35
|
+
* signed announcement. Records are validated and bounded before they
|
|
36
|
+
* are shown, and joining connects to the announcing node, whose store
|
|
37
|
+
* then answers for itself.
|
|
38
|
+
*
|
|
39
|
+
* **Unlisted is not secret.** An unlisted lobby publishes no record, so
|
|
40
|
+
* it never appears in a list — but a 6-character code can be guessed
|
|
41
|
+
* against its hash, and the anchor relays every announcement. Who may
|
|
42
|
+
* join is decided by `authorize`, as for any store.
|
|
43
|
+
*
|
|
44
|
+
* **One lobby per node.** `announce` replaces a node's tags, so the
|
|
45
|
+
* lobby owns its node's announcement while it is open; pass any other
|
|
46
|
+
* tags the node should keep announcing as `tags`.
|
|
47
|
+
*/
|
|
48
|
+
import type { NodeDescriptor } from './node.js';
|
|
49
|
+
import { type HostedStoreHandle, type HostProjection, type HostStoreBaseOptions, type StoreTransport } from './store/host.js';
|
|
50
|
+
import { type JoinedStoreHandle } from './store/join.js';
|
|
51
|
+
import type { AccessRequest, ActionSpec, Cancel, InputSpec, StoreDefinition } from './store/types.js';
|
|
52
|
+
/** A node a lobby can run on: a store transport that can announce and query. */
|
|
53
|
+
export interface LobbyNode extends StoreTransport {
|
|
54
|
+
announce(capabilities: readonly string[]): Promise<void>;
|
|
55
|
+
query(capability: string): Promise<NodeDescriptor[]>;
|
|
56
|
+
}
|
|
57
|
+
/** Game-defined fields shown in a lobby list: small, flat, public. */
|
|
58
|
+
export type LobbyInfo = Readonly<Record<string, string | number | boolean>>;
|
|
59
|
+
/** Why a lobby call failed. */
|
|
60
|
+
export type LobbyErrorCode =
|
|
61
|
+
/** No lobby answered to that code before the deadline. */
|
|
62
|
+
'not-found'
|
|
63
|
+
/** More than one node claims the code; joining either could be the wrong one. */
|
|
64
|
+
| 'ambiguous'
|
|
65
|
+
/** A game name, code, record or option is not usable. */
|
|
66
|
+
| 'invalid';
|
|
67
|
+
export declare class LobbyError extends Error {
|
|
68
|
+
readonly code: LobbyErrorCode;
|
|
69
|
+
constructor(code: LobbyErrorCode, message: string);
|
|
70
|
+
}
|
|
71
|
+
/** One open lobby, as a list shows it. */
|
|
72
|
+
export interface LobbyListing {
|
|
73
|
+
readonly code: string;
|
|
74
|
+
readonly name: string;
|
|
75
|
+
/** Players in it, the host included, as the host last announced. */
|
|
76
|
+
readonly players: number;
|
|
77
|
+
readonly capacity: number;
|
|
78
|
+
/** The store it serves, `id@version`. */
|
|
79
|
+
readonly store: string;
|
|
80
|
+
readonly info: LobbyInfo;
|
|
81
|
+
/** The announcing node, 16 hex — from its signed announcement, not from the record. */
|
|
82
|
+
readonly host: string;
|
|
83
|
+
}
|
|
84
|
+
/** Bounds on what a lobby may publish (Q4 in the lobbies plan). */
|
|
85
|
+
export declare const MAX_LOBBY_NAME_CHARS = 64;
|
|
86
|
+
export declare const MAX_LOBBY_INFO_BYTES = 256;
|
|
87
|
+
export declare const MAX_LOBBY_RECORD_TAG_BYTES = 512;
|
|
88
|
+
export declare const MAX_LOBBY_CAPACITY = 256;
|
|
89
|
+
/** Characters a code is made of: no 0/O, 1/I/L, so a code survives being read aloud. */
|
|
90
|
+
export declare const LOBBY_CODE_ALPHABET = "ABCDEFGHJKMNPQRSTUVWXYZ23456789";
|
|
91
|
+
export declare const LOBBY_CODE_LENGTH = 6;
|
|
92
|
+
/** How often a lobby re-announces itself. */
|
|
93
|
+
export declare const LOBBY_ANNOUNCE_MS = 2000;
|
|
94
|
+
/** A code as typed: case, spaces and dashes forgiven. */
|
|
95
|
+
export declare function normalizeLobbyCode(code: string): string;
|
|
96
|
+
/** What `createLobby` takes: a store's host options, minus the transport, plus the lobby. */
|
|
97
|
+
export type CreateLobbyOptions<S extends object, A extends ActionSpec, I extends InputSpec> = Omit<HostStoreBaseOptions<S, A, I>, 'transport' | 'authorize' | 'maxEventBytes'> & HostProjection<S> & {
|
|
98
|
+
readonly node: LobbyNode;
|
|
99
|
+
/** Your game's name on the mesh: lobbies are listed per game. */
|
|
100
|
+
readonly game: string;
|
|
101
|
+
readonly name: string;
|
|
102
|
+
/** Most players at once, the host included. */
|
|
103
|
+
readonly capacity: number;
|
|
104
|
+
/** `'public'` (default) is listed; `'unlisted'` is joined by code or link only. */
|
|
105
|
+
readonly visibility?: 'public' | 'unlisted';
|
|
106
|
+
/** Small public fields a list shows — map, mode. At most 256 bytes of JSON. */
|
|
107
|
+
readonly info?: LobbyInfo;
|
|
108
|
+
/** The audience the host's own player reads. Default `[]`. */
|
|
109
|
+
readonly audience?: readonly string[];
|
|
110
|
+
/**
|
|
111
|
+
* Your game's policy, as `hostStore`'s. Default: allow. The lobby
|
|
112
|
+
* applies capacity and kicks BEFORE it, so it never sees a refused
|
|
113
|
+
* join.
|
|
114
|
+
*/
|
|
115
|
+
readonly authorize?: (request: AccessRequest<A, I>) => boolean;
|
|
116
|
+
readonly maxEventBytes?: number;
|
|
117
|
+
/** Other tags this node should keep announcing while the lobby is open. */
|
|
118
|
+
readonly tags?: readonly string[];
|
|
119
|
+
/** Re-announce interval. Default {@link LOBBY_ANNOUNCE_MS}. */
|
|
120
|
+
readonly announceEveryMs?: number;
|
|
121
|
+
};
|
|
122
|
+
/** An open lobby, on the node hosting it. */
|
|
123
|
+
export interface Lobby<S extends object, A extends ActionSpec, I extends InputSpec> {
|
|
124
|
+
readonly code: string;
|
|
125
|
+
readonly game: string;
|
|
126
|
+
readonly visibility: 'public' | 'unlisted';
|
|
127
|
+
/** The authoritative store. */
|
|
128
|
+
readonly host: HostedStoreHandle<S, A, I>;
|
|
129
|
+
/** The host's own player — the same handle shape `joinLobby` returns. */
|
|
130
|
+
readonly self: JoinedStoreHandle<S, A, I>;
|
|
131
|
+
/** Who is in: the host first, then each joined peer, 16 hex. */
|
|
132
|
+
players(): readonly string[];
|
|
133
|
+
/** Called with the new list whenever someone joins or leaves. */
|
|
134
|
+
subscribePlayers(listener: (players: readonly string[]) => void): Cancel;
|
|
135
|
+
/** A shareable link: `base` with `?lobby=<code>`. Default base: this page. */
|
|
136
|
+
link(base?: string): string;
|
|
137
|
+
/** Remove a player now and refuse them from here on. */
|
|
138
|
+
kick(peer: string): void;
|
|
139
|
+
/** Stop announcing, close the store and the host's player. */
|
|
140
|
+
close(): Promise<void>;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Open a lobby: host the store on `node`, give the host its own
|
|
144
|
+
* player, and announce the lobby until it closes.
|
|
145
|
+
*/
|
|
146
|
+
export declare function createLobby<S extends object, A extends ActionSpec, I extends InputSpec>(options: CreateLobbyOptions<S, A, I>): Promise<Lobby<S, A, I>>;
|
|
147
|
+
/** The open public lobbies of `game`, as their hosts last announced them. */
|
|
148
|
+
export declare function listLobbies(options: {
|
|
149
|
+
readonly node: LobbyNode;
|
|
150
|
+
readonly game: string;
|
|
151
|
+
}): Promise<LobbyListing[]>;
|
|
152
|
+
/** What `joinLobby` takes. */
|
|
153
|
+
export interface JoinLobbyOptions<S extends object, A extends ActionSpec, I extends InputSpec> {
|
|
154
|
+
readonly node: LobbyNode;
|
|
155
|
+
readonly definition: StoreDefinition<S, A, I>;
|
|
156
|
+
readonly game: string;
|
|
157
|
+
/** A code, as typed or from a link — or a listing from `listLobbies`. */
|
|
158
|
+
readonly code?: string;
|
|
159
|
+
readonly lobby?: LobbyListing;
|
|
160
|
+
/** The audience to read. Default `[]`. */
|
|
161
|
+
readonly audience?: readonly string[];
|
|
162
|
+
/** The interest set to join with (see `joinStore`). Default: every entity. */
|
|
163
|
+
readonly interest?: readonly string[];
|
|
164
|
+
/** The opaque join token. Default `'player'`. */
|
|
165
|
+
readonly key?: string;
|
|
166
|
+
readonly maxEventBytes?: number;
|
|
167
|
+
/** How long to look for the code, and to reach the host. Default 20 s. */
|
|
168
|
+
readonly timeoutMs?: number;
|
|
169
|
+
/**
|
|
170
|
+
* Tags this node keeps announcing while it plays. Joining announces a
|
|
171
|
+
* `seek` tag so the host can discover this player, and an announcement
|
|
172
|
+
* replaces the node's whole tag set — so anything else the page
|
|
173
|
+
* announces goes here. The same option as `createLobby`'s.
|
|
174
|
+
*/
|
|
175
|
+
readonly tags?: readonly string[];
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Join a lobby by code or by listing. Resolves once the host is found
|
|
179
|
+
* and the join is sent; await `ready()` on the result for the world.
|
|
180
|
+
*/
|
|
181
|
+
export declare function joinLobby<S extends object, A extends ActionSpec, I extends InputSpec>(options: JoinLobbyOptions<S, A, I>): Promise<JoinedStoreHandle<S, A, I>>;
|
|
182
|
+
/** The lobby code in a link made by `lobby.link()`, or `null`. Default: this page. */
|
|
183
|
+
export declare function lobbyCodeFromUrl(url?: string): string | null;
|