@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
package/dist/local.js ADDED
@@ -0,0 +1,160 @@
1
+ /**
2
+ * `@net-mesh/browser/local` — a mesh in one page, for developing a game
3
+ * without an anchor.
4
+ *
5
+ * ```ts
6
+ * import { createLocalMesh } from '@net-mesh/browser/local';
7
+ *
8
+ * const mesh = createLocalMesh();
9
+ * const hostNode = mesh.node();
10
+ * const playerNode = mesh.node();
11
+ * const host = hostStore({ definition, transport: hostNode, … });
12
+ * const player = joinStore({ definition, transport: playerNode, host: hostNode.nodeIdHex(), … });
13
+ * ```
14
+ *
15
+ * A local node satisfies the same structural type `connect()`'s node
16
+ * does for the store, so `hostStore`, `joinStore` and `hostPlayer` are
17
+ * the real ones and every frame is really encoded, parsed, chunked,
18
+ * assembled and dispatched. What is NOT real is the network: delivery
19
+ * is a function call in this page, and the peer on each frame is
20
+ * assigned by this module rather than proved by a handshake.
21
+ *
22
+ * So a game that works here has working game logic and working store
23
+ * wiring. It is not evidence that two browsers can reach each other —
24
+ * that takes an anchor and `connect()`.
25
+ *
26
+ * Discovery works too: `announce(tags)` and `query(tag)` behave like
27
+ * the real node's, including the announcement expiring, so a lobby
28
+ * list or a find-the-host loop can be built offline as well.
29
+ *
30
+ * Nothing here loads the wasm node: importing this subpath costs no
31
+ * download.
32
+ */
33
+ /**
34
+ * How long an announcement stays discoverable: the leaf's default,
35
+ * 300 s (`net-mesh-leaf` `DEFAULT_TTL_SECS`). A node that announces
36
+ * once and never again drops out of `query` after it, as on the mesh.
37
+ */
38
+ export const LOCAL_ANNOUNCEMENT_TTL_MS = 300_000;
39
+ function randomId() {
40
+ const bytes = new Uint8Array(8);
41
+ crypto.getRandomValues(bytes);
42
+ let hex = '';
43
+ for (const byte of bytes)
44
+ hex += byte.toString(16).padStart(2, '0');
45
+ return hex;
46
+ }
47
+ function canonicalId(id) {
48
+ const raw = id.startsWith('0x') ? id.slice(2) : id;
49
+ if (!/^[0-9a-fA-F]{1,16}$/.test(raw)) {
50
+ throw new TypeError(`a local node id is up to 16 hex digits, got ${JSON.stringify(id)}`);
51
+ }
52
+ return raw.toLowerCase().padStart(16, '0');
53
+ }
54
+ /** Create an empty local mesh. */
55
+ export function createLocalMesh(options = {}) {
56
+ const listeners = new Map();
57
+ const ttl = options.announcementTtlMs ?? LOCAL_ANNOUNCEMENT_TTL_MS;
58
+ const now = options.now ?? (() => Date.now());
59
+ const announcements = new Map();
60
+ function deliver(to, from, payload, streamId) {
61
+ const targets = listeners.get(to);
62
+ if (targets === undefined)
63
+ throw new Error(`no local node ${to} on this mesh`);
64
+ for (const handler of [...targets]) {
65
+ // A copy per receiver, as a network would hand each its own
66
+ // bytes: a receiver that mutates its payload must not change
67
+ // what another receiver — or the sender — holds.
68
+ handler({ type: 'stream_data', streamId, peerNode: from, payload: payload.slice() });
69
+ }
70
+ }
71
+ function node(requested) {
72
+ const self = requested === undefined ? randomId() : canonicalId(requested);
73
+ if (listeners.has(self))
74
+ throw new Error(`local node ${self} is already on this mesh`);
75
+ const own = new Set();
76
+ listeners.set(self, own);
77
+ let closed = false;
78
+ return {
79
+ nodeIdHex: () => self,
80
+ openStream: options => {
81
+ if (closed)
82
+ throw new Error(`local node ${self} is closed`);
83
+ const peer = options.peer === undefined ? null : canonicalId(options.peer);
84
+ // The label stands in for the id a real node derives from it:
85
+ // both ends name the same stream without exchanging one.
86
+ const streamId = options.label;
87
+ let open = true;
88
+ const stream = {
89
+ send: payload =>
90
+ // Asynchronous on purpose: a real `send` is a promise, and a
91
+ // game that only worked with synchronous delivery would be
92
+ // hiding an ordering assumption.
93
+ Promise.resolve().then(() => {
94
+ if (!open || closed)
95
+ throw new Error('this local stream is closed');
96
+ if (peer === null)
97
+ throw new Error('a local stream needs a peer');
98
+ deliver(peer, self, payload, streamId);
99
+ }),
100
+ close: () => {
101
+ open = false;
102
+ },
103
+ };
104
+ return stream;
105
+ },
106
+ onEvent: handler => {
107
+ own.add(handler);
108
+ return () => {
109
+ own.delete(handler);
110
+ };
111
+ },
112
+ announce: capabilities => {
113
+ if (closed)
114
+ return Promise.reject(new Error(`local node ${self} is closed`));
115
+ const version = (announcements.get(self)?.version ?? 0n) + 1n;
116
+ announcements.set(self, { capabilities: Object.freeze([...capabilities]), at: now(), version });
117
+ return Promise.resolve();
118
+ },
119
+ query: capability => {
120
+ if (closed)
121
+ return Promise.reject(new Error(`local node ${self} is closed`));
122
+ const at = now();
123
+ const found = [];
124
+ for (const [id, entry] of announcements) {
125
+ if (id === self || at - entry.at >= ttl || !entry.capabilities.includes(capability))
126
+ continue;
127
+ found.push({
128
+ nodeId: BigInt(`0x${id}`).toString(10),
129
+ peerIdHex: id,
130
+ entityId: null,
131
+ capabilities: entry.capabilities,
132
+ rtcAddr: null,
133
+ noisePubkey: null,
134
+ version: entry.version.toString(),
135
+ });
136
+ }
137
+ return Promise.resolve(found);
138
+ },
139
+ close: () => {
140
+ if (closed)
141
+ return;
142
+ closed = true;
143
+ own.clear();
144
+ announcements.delete(self);
145
+ if (listeners.get(self) === own)
146
+ listeners.delete(self);
147
+ },
148
+ };
149
+ }
150
+ return {
151
+ node,
152
+ nodes: () => [...listeners.keys()],
153
+ close: () => {
154
+ for (const handlers of listeners.values())
155
+ handlers.clear();
156
+ listeners.clear();
157
+ announcements.clear();
158
+ },
159
+ };
160
+ }