@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.
Files changed (110) hide show
  1. package/CHANGELOG.md +517 -0
  2. package/LICENSE-APACHE +190 -0
  3. package/LICENSE-MIT +21 -0
  4. package/README.md +666 -0
  5. package/dist/async-queue.d.ts +26 -0
  6. package/dist/async-queue.js +62 -0
  7. package/dist/credential.d.ts +70 -0
  8. package/dist/credential.js +95 -0
  9. package/dist/errors.d.ts +400 -0
  10. package/dist/errors.js +726 -0
  11. package/dist/events.d.ts +232 -0
  12. package/dist/events.js +298 -0
  13. package/dist/identity.d.ts +40 -0
  14. package/dist/identity.js +78 -0
  15. package/dist/index.bundle.js +2 -0
  16. package/dist/index.d.ts +38 -0
  17. package/dist/index.js +46 -0
  18. package/dist/leader/events.d.ts +111 -0
  19. package/dist/leader/events.js +116 -0
  20. package/dist/leader/index.d.ts +14 -0
  21. package/dist/leader/index.js +11 -0
  22. package/dist/leader/session.d.ts +539 -0
  23. package/dist/leader/session.js +770 -0
  24. package/dist/leader/wasm.d.ts +123 -0
  25. package/dist/leader/wasm.js +39 -0
  26. package/dist/lobby.d.ts +183 -0
  27. package/dist/lobby.js +504 -0
  28. package/dist/local.d.ts +80 -0
  29. package/dist/local.js +160 -0
  30. package/dist/net_leaf.d.ts +1494 -0
  31. package/dist/net_leaf.js +3753 -0
  32. package/dist/net_leaf_bg.wasm +0 -0
  33. package/dist/net_leaf_bg.wasm.d.ts +137 -0
  34. package/dist/netcode/client.d.ts +102 -0
  35. package/dist/netcode/client.js +296 -0
  36. package/dist/netcode/clock.d.ts +45 -0
  37. package/dist/netcode/clock.js +54 -0
  38. package/dist/netcode/host.d.ts +118 -0
  39. package/dist/netcode/host.js +276 -0
  40. package/dist/netcode/index.d.ts +19 -0
  41. package/dist/netcode/index.js +14 -0
  42. package/dist/netcode/interpolate.d.ts +50 -0
  43. package/dist/netcode/interpolate.js +100 -0
  44. package/dist/netcode/wire.d.ts +125 -0
  45. package/dist/netcode/wire.js +117 -0
  46. package/dist/node.d.ts +908 -0
  47. package/dist/node.js +1085 -0
  48. package/dist/org.d.ts +412 -0
  49. package/dist/org.js +567 -0
  50. package/dist/peer-driver.d.ts +117 -0
  51. package/dist/peer-driver.js +224 -0
  52. package/dist/store/assembly.d.ts +176 -0
  53. package/dist/store/assembly.js +325 -0
  54. package/dist/store/chunker.d.ts +83 -0
  55. package/dist/store/chunker.js +190 -0
  56. package/dist/store/core.d.ts +136 -0
  57. package/dist/store/core.js +477 -0
  58. package/dist/store/definition.d.ts +23 -0
  59. package/dist/store/definition.js +83 -0
  60. package/dist/store/errors.d.ts +77 -0
  61. package/dist/store/errors.js +94 -0
  62. package/dist/store/host.d.ts +247 -0
  63. package/dist/store/host.js +675 -0
  64. package/dist/store/index.d.ts +50 -0
  65. package/dist/store/index.js +40 -0
  66. package/dist/store/interest.d.ts +40 -0
  67. package/dist/store/interest.js +77 -0
  68. package/dist/store/inventory.d.ts +81 -0
  69. package/dist/store/inventory.js +140 -0
  70. package/dist/store/join.d.ts +118 -0
  71. package/dist/store/join.js +724 -0
  72. package/dist/store/json.d.ts +50 -0
  73. package/dist/store/json.js +283 -0
  74. package/dist/store/ledger.d.ts +187 -0
  75. package/dist/store/ledger.js +292 -0
  76. package/dist/store/owner.d.ts +616 -0
  77. package/dist/store/owner.js +1711 -0
  78. package/dist/store/patch.d.ts +70 -0
  79. package/dist/store/patch.js +166 -0
  80. package/dist/store/player.d.ts +65 -0
  81. package/dist/store/player.js +261 -0
  82. package/dist/store/replica.d.ts +187 -0
  83. package/dist/store/replica.js +740 -0
  84. package/dist/store/state.d.ts +42 -0
  85. package/dist/store/state.js +165 -0
  86. package/dist/store/types.d.ts +200 -0
  87. package/dist/store/types.js +25 -0
  88. package/dist/store/visibility.d.ts +118 -0
  89. package/dist/store/visibility.js +282 -0
  90. package/dist/store/wire.d.ts +309 -0
  91. package/dist/store/wire.js +834 -0
  92. package/dist/stream.d.ts +174 -0
  93. package/dist/stream.js +238 -0
  94. package/dist/three/index.d.ts +109 -0
  95. package/dist/three/index.js +130 -0
  96. package/dist/udp-probe.d.ts +159 -0
  97. package/dist/udp-probe.js +245 -0
  98. package/dist/wasm.d.ts +642 -0
  99. package/dist/wasm.js +98 -0
  100. package/dist/world/border.d.ts +84 -0
  101. package/dist/world/border.js +99 -0
  102. package/dist/world/handoff.d.ts +187 -0
  103. package/dist/world/handoff.js +222 -0
  104. package/dist/world/index.d.ts +13 -0
  105. package/dist/world/index.js +9 -0
  106. package/dist/world/link.d.ts +179 -0
  107. package/dist/world/link.js +476 -0
  108. package/dist/world/regions.d.ts +154 -0
  109. package/dist/world/regions.js +314 -0
  110. package/package.json +72 -0
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Netcode frames and the transport they ride.
3
+ *
4
+ * Every frame is small JSON tagged with the netcode instance's label
5
+ * (`n`), so several netcode instances — and the store — can share one
6
+ * node: a frame for another label is not this instance's. All frames ride
7
+ * a fire-and-forget **lossy** stream (`openStream({ lossy: true })`): the
8
+ * protocol is built for loss (inputs are sent redundantly, snapshots
9
+ * supersede each other, pings are repeated).
10
+ */
11
+ /** The structural transport netcode uses: `BrowserNode`, the local mesh,
12
+ * `meshStoreTransport` on a native host. */
13
+ export interface NetcodeTransport {
14
+ nodeIdHex(): string | null;
15
+ openStream(options: {
16
+ reliability: 'reliable' | 'fireAndForget';
17
+ peer?: string;
18
+ label?: string;
19
+ lossy?: boolean;
20
+ }): NetcodeStream | Promise<NetcodeStream>;
21
+ onEvent(handler: (event: {
22
+ readonly type: string;
23
+ readonly streamId?: string;
24
+ readonly peerNode?: string | null;
25
+ readonly payload?: Uint8Array;
26
+ }) => void): () => void;
27
+ connectPeer?(peerHex: string): Promise<unknown>;
28
+ }
29
+ /** A stream the netcode sends on. */
30
+ export interface NetcodeStream {
31
+ send(payload: Uint8Array): unknown;
32
+ close(): unknown;
33
+ }
34
+ /** One player input as it travels: `seq` counts from 1 per player. */
35
+ export interface WireInput<I> {
36
+ readonly seq: number;
37
+ /** The host time the player was RENDERING when it issued this input —
38
+ * what lag compensation rewinds to. */
39
+ readonly seen: number;
40
+ readonly data: I;
41
+ }
42
+ export type Frame<E, I> =
43
+ /** Player → host: join (repeated until the first snapshot). */
44
+ {
45
+ readonly n: string;
46
+ readonly k: 'h';
47
+ }
48
+ /** Player → host: the newest inputs, the unacknowledged ones repeated. */
49
+ | {
50
+ readonly n: string;
51
+ readonly k: 'i';
52
+ readonly i: readonly WireInput<I>[];
53
+ }
54
+ /** Player → host: clock ping. */
55
+ | {
56
+ readonly n: string;
57
+ readonly k: 'p';
58
+ readonly t0: number;
59
+ }
60
+ /**
61
+ * Player → host: the interest keys it wants, version `v` (repeated until a
62
+ * snapshot echoes `v` back as `iv`; the host keeps the highest version).
63
+ */
64
+ | {
65
+ readonly n: string;
66
+ readonly k: 'w';
67
+ readonly v: number;
68
+ readonly w: readonly string[];
69
+ }
70
+ /** Host → player: clock pong. */
71
+ | {
72
+ readonly n: string;
73
+ readonly k: 'q';
74
+ readonly t0: number;
75
+ readonly t1: number;
76
+ readonly t2: number;
77
+ }
78
+ /**
79
+ * Host → player: a snapshot, and the last input seq applied for them.
80
+ *
81
+ * A snapshot too large for one frame is sent as `of` chunks, chunk `c`
82
+ * carrying the entities {@link chunkOf} assigns to it — each chunk
83
+ * usable on its own, so a lost one costs part of a snapshot, not all.
84
+ */
85
+ | {
86
+ readonly n: string;
87
+ readonly k: 's';
88
+ readonly tick: number;
89
+ readonly t: number;
90
+ readonly ack: number;
91
+ readonly e: Readonly<Record<string, E>>;
92
+ readonly c?: number;
93
+ readonly of?: number;
94
+ /** The interest version this snapshot was filtered by, if any. */
95
+ readonly iv?: number;
96
+ };
97
+ /** Interest keys a player may name, and the longest key, in UTF-16 units. */
98
+ export declare const MAX_NETCODE_INTEREST_KEYS = 256;
99
+ export declare const MAX_NETCODE_INTEREST_KEY_LENGTH = 64;
100
+ /** Chunks a snapshot may be split into, at most. */
101
+ export declare const MAX_SNAPSHOT_CHUNKS = 256;
102
+ /**
103
+ * The chunk (of `of`) entity `id` travels in: FNV-1a of the id. Stable, so
104
+ * a player missing a chunk knows which entities it would have carried.
105
+ */
106
+ export declare function chunkOf(id: string, of: number): number;
107
+ export declare function encodeFrame<E, I>(frame: Frame<E, I>): Uint8Array;
108
+ /** A frame for `label`, or `null` for anything else (another label, not a
109
+ * netcode frame, malformed). */
110
+ export declare function decodeFrame<E, I>(payload: Uint8Array | undefined, label: string): Frame<E, I> | null;
111
+ /**
112
+ * A node id the CALLER supplied (`host`, from `nodeIdHex()`): hex only, 16
113
+ * lowercase digits out, or `null`.
114
+ */
115
+ export declare function peerHex(peer: string | null | undefined): string | null;
116
+ /**
117
+ * The authenticated sender of a transport event, 16 lowercase hex. The
118
+ * browser node reports it as a DECIMAL u64, `meshStoreTransport` as hex —
119
+ * read exactly the way the store reads it (`peerHexOf`), so netcode and the
120
+ * store never disagree about who a peer is.
121
+ */
122
+ export declare function eventPeer(peer: string | null | undefined): string | null;
123
+ /** The time source: `performance.now()` unless a test injects one. */
124
+ export type Now = () => number;
125
+ export declare const defaultNow: Now;
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Netcode frames and the transport they ride.
3
+ *
4
+ * Every frame is small JSON tagged with the netcode instance's label
5
+ * (`n`), so several netcode instances — and the store — can share one
6
+ * node: a frame for another label is not this instance's. All frames ride
7
+ * a fire-and-forget **lossy** stream (`openStream({ lossy: true })`): the
8
+ * protocol is built for loss (inputs are sent redundantly, snapshots
9
+ * supersede each other, pings are repeated).
10
+ */
11
+ /** Interest keys a player may name, and the longest key, in UTF-16 units. */
12
+ export const MAX_NETCODE_INTEREST_KEYS = 256;
13
+ export const MAX_NETCODE_INTEREST_KEY_LENGTH = 64;
14
+ /** Chunks a snapshot may be split into, at most. */
15
+ export const MAX_SNAPSHOT_CHUNKS = 256;
16
+ /**
17
+ * The chunk (of `of`) entity `id` travels in: FNV-1a of the id. Stable, so
18
+ * a player missing a chunk knows which entities it would have carried.
19
+ */
20
+ export function chunkOf(id, of) {
21
+ let hash = 0x811c9dc5;
22
+ for (let i = 0; i < id.length; i += 1) {
23
+ hash ^= id.charCodeAt(i);
24
+ hash = Math.imul(hash, 0x01000193);
25
+ }
26
+ return (hash >>> 0) % of;
27
+ }
28
+ const encoder = new TextEncoder();
29
+ const decoder = new TextDecoder('utf-8', { fatal: true });
30
+ export function encodeFrame(frame) {
31
+ return encoder.encode(JSON.stringify(frame));
32
+ }
33
+ /** A frame for `label`, or `null` for anything else (another label, not a
34
+ * netcode frame, malformed). */
35
+ export function decodeFrame(payload, label) {
36
+ if (payload === undefined)
37
+ return null;
38
+ let value;
39
+ try {
40
+ value = JSON.parse(decoder.decode(payload));
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ if (typeof value !== 'object' || value === null)
46
+ return null;
47
+ const frame = value;
48
+ if (frame.n !== label || typeof frame.k !== 'string')
49
+ return null;
50
+ switch (frame.k) {
51
+ case 'h':
52
+ return frame;
53
+ case 'i':
54
+ return Array.isArray(frame.i) ? frame : null;
55
+ case 'p':
56
+ return typeof frame.t0 === 'number' ? frame : null;
57
+ case 'w': {
58
+ const w = frame;
59
+ return Number.isSafeInteger(w.v) &&
60
+ w.v >= 1 &&
61
+ Array.isArray(w.w) &&
62
+ w.w.length <= MAX_NETCODE_INTEREST_KEYS &&
63
+ w.w.every(key => typeof key === 'string' && key.length <= MAX_NETCODE_INTEREST_KEY_LENGTH)
64
+ ? frame
65
+ : null;
66
+ }
67
+ case 'q': {
68
+ const q = frame;
69
+ return typeof q.t0 === 'number' && typeof q.t1 === 'number' && typeof q.t2 === 'number'
70
+ ? frame
71
+ : null;
72
+ }
73
+ case 's': {
74
+ const s = frame;
75
+ if ((s.iv !== undefined && !Number.isSafeInteger(s.iv)) ||
76
+ typeof s.tick !== 'number' ||
77
+ typeof s.t !== 'number' ||
78
+ typeof s.ack !== 'number' ||
79
+ typeof s.e !== 'object' ||
80
+ s.e === null) {
81
+ return null;
82
+ }
83
+ if (s.c === undefined && s.of === undefined)
84
+ return frame;
85
+ const chunked = Number.isInteger(s.c) &&
86
+ Number.isInteger(s.of) &&
87
+ s.of >= 1 &&
88
+ s.of <= MAX_SNAPSHOT_CHUNKS &&
89
+ s.c >= 0 &&
90
+ s.c < s.of;
91
+ return chunked ? frame : null;
92
+ }
93
+ default:
94
+ return null;
95
+ }
96
+ }
97
+ import { peerHexOf } from '../store/host.js';
98
+ /**
99
+ * A node id the CALLER supplied (`host`, from `nodeIdHex()`): hex only, 16
100
+ * lowercase digits out, or `null`.
101
+ */
102
+ export function peerHex(peer) {
103
+ if (typeof peer !== 'string')
104
+ return null;
105
+ const raw = peer.startsWith('0x') ? peer.slice(2) : peer;
106
+ return /^[0-9a-fA-F]{1,16}$/.test(raw) ? raw.toLowerCase().padStart(16, '0') : null;
107
+ }
108
+ /**
109
+ * The authenticated sender of a transport event, 16 lowercase hex. The
110
+ * browser node reports it as a DECIMAL u64, `meshStoreTransport` as hex —
111
+ * read exactly the way the store reads it (`peerHexOf`), so netcode and the
112
+ * store never disagree about who a peer is.
113
+ */
114
+ export function eventPeer(peer) {
115
+ return typeof peer === 'string' && peer.length > 0 ? peerHexOf(peer) : null;
116
+ }
117
+ export const defaultNow = () => globalThis.performance?.now() ?? Date.now();