@usions/sdk 2.2.0 → 2.10.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 CHANGED
@@ -121,6 +121,91 @@ Usion.game.disconnect()
121
121
  Usion.game.isConnected() // boolean
122
122
  ```
123
123
 
124
+ ### Netcode (low-latency realtime toolkit)
125
+
126
+ Zero-dependency, transport-agnostic helpers for smooth, lossless multiplayer.
127
+ They work across all connection modes (platform / direct / proxy) and both
128
+ platforms. Adopt incrementally. Full guide: [`docs/realtime-netcode.md`](../../docs/realtime-netcode.md).
129
+
130
+ ```javascript
131
+ // 1. Snapshot interpolation — smooth rendering, absorbs jitter & packet loss
132
+ const interp = Usion.game.createInterpolation({ serverFps: 20 });
133
+ Usion.game.onRealtime((m) => { if (m.action_type === 'state') interp.add(m.action_data); });
134
+ function render() {
135
+ const players = interp.calc('x y angle(deg)'); // entities at "now - bufferMs"
136
+ if (players) draw(players);
137
+ requestAnimationFrame(render);
138
+ }
139
+
140
+ // 2. Sequence-guarded, delta-compressed snapshot sender (cuts bandwidth + flood)
141
+ const snap = Usion.game.createSnapshotSender({ hz: 20, channel: 'state', precision: 2 });
142
+ loop(() => snap.send(world));
143
+ // receiver (drops stale/out-of-order frames; never patches the wrong base):
144
+ const rx = Usion.game.createSnapshotReceiver();
145
+ let world = {};
146
+ Usion.game.onRealtime((m) => { if (m.action_type === 'state') world = rx.receive(m.action_data); });
147
+
148
+ // 3. Client-side prediction + reconciliation + smooth error blending
149
+ const p = Usion.game.createPredictor({ apply: (s, i) => move(s, i), initialState, smooth: { keys: 'x y' } });
150
+ const { seq } = p.predict(input); // apply locally, send seq
151
+ Usion.game.onStateUpdate((s) => p.reconcile(s.game_state.me, s.game_state.ackSeq));
152
+ function render() { draw(p.view()); requestAnimationFrame(render); } // blended, no snaps
153
+
154
+ // 4. WebRTC peer-to-peer (UDP) — escapes TCP head-of-line blocking
155
+ const mesh = Usion.game.createMesh({
156
+ role: amHost ? 'host' : 'guest',
157
+ iceServers: Usion.netcode.MeshConnection.iceServers({ turn: 'turn:host:3478', turnUsername: 'u', turnCredential: 'p' }),
158
+ });
159
+ mesh.onMessage = (d) => applyRemote(d);
160
+ await mesh.start();
161
+ mesh.send({ x, y }); // unreliable + unordered + sequenced (drops stale)
162
+ mesh.sendReliable({ event }); // ordered, must-arrive
163
+
164
+ // 4b. N-player mesh
165
+ const net = Usion.game.createMeshNetwork();
166
+ await net.setRoster(allPlayerIds);
167
+ net.onMessage = (peerId, d) => applyRemote(peerId, d);
168
+ net.broadcast({ x, y });
169
+
170
+ // 4c. WebTransport (HTTP/3) — lowest-latency client-server (no TCP HOL blocking)
171
+ const wt = Usion.game.createWebTransport({ url: 'https://game.example.com:4433/wt' });
172
+ wt.onMessage = (m, ch) => { if (ch === 'datagram') applyState(m); };
173
+ await wt.connect();
174
+ wt.send(stateBytes); // UDP-like datagram (unreliable, sequenced)
175
+ wt.sendReliable({ event }); // reliable stream
176
+ // (server: use the open-source @fails-components/webtransport Node HTTP/3 server)
177
+
178
+ // 4d. Declarative replication — mutate a plain object, it auto-syncs (host)
179
+ const world = Usion.game.replicate({ players: [] }, { channel: 'world', hz: 20, precision: 2 });
180
+ world.state.players.push({ id: myId, x: 0, y: 0 }); // just mutate it
181
+ // client:
182
+ const remote = Usion.game.replica({ channel: 'world', interpolate: { keys: 'x y', group: 'players' } });
183
+ function render() { draw(remote.view()); requestAnimationFrame(render); }
184
+
185
+ // 4e. Test under a bad network locally (latency / jitter / loss)
186
+ Usion.game.simulateNetwork({ latencyMs: 120, jitterMs: 30, lossPct: 5 });
187
+ Usion.game.simulateNetwork(null); // off
188
+
189
+ // 4f. Deterministic lockstep (inputs-only sim + free replays) — MOBA/RTS
190
+ const ls = Usion.game.createLockstep({ playerId: myId, players, step: (frame, inputs) => sim(frame, inputs) });
191
+ gameLoop(() => { ls.submit(localInput); ls.tick(); });
192
+ // replay later: Usion.netcode.Lockstep.replay(ls.getReplay(), sim);
193
+
194
+ // 4g. Server-side lag compensation (server rewind) — fair hits across pings
195
+ const lag = Usion.game.createLagCompensator({ historyMs: 1000 });
196
+ serverTick(() => lag.record(allEntities)); // each tick
197
+ function onShot(shooter, ray) { const past = lag.rewindForClient(shooter.rtt, shooter.interpMs); resolveHit(ray, past); }
198
+
199
+ // 5. Telemetry, delta + binary helpers
200
+ await Usion.game.ping(); Usion.game.getRtt(); // ms
201
+ const d = Usion.game.diff(prev, next); const next2 = Usion.game.patch(prev, d);
202
+ const bytes = Usion.game.encode(state); const back = Usion.game.decode(bytes);
203
+ ```
204
+
205
+ Also available directly: `Usion.netcode.{ SnapshotInterpolation, Predictor,
206
+ Coalescer, PingMeter, MeshConnection, MeshNetwork, diff, patch, quantize,
207
+ encode, decode }`.
208
+
124
209
  ### Utility
125
210
 
126
211
  ```javascript
@@ -130,6 +215,39 @@ Usion.exit() // Close the mini-app
130
215
  Usion.log(message) // Debug log
131
216
  ```
132
217
 
218
+ ### Leaderboard (opt-in per game)
219
+
220
+ Enable on the service (`leaderboard: { enabled: true, order: 'desc' }`), then:
221
+
222
+ ```javascript
223
+ await Usion.leaderboard.submit(1500, { level: 3 }); // best score is kept
224
+ const friends = await Usion.leaderboard.friends(); // people you've messaged + you
225
+ const top = await Usion.leaderboard.top({ limit: 20 });// global top
226
+ const me = await Usion.leaderboard.me(); // { score, rank, total }
227
+ // entry: { user_id, name, avatar, score, rank, is_me, metadata }
228
+ ```
229
+ `friends()` is scoped to users you've chatted with (your conversations) plus
230
+ yourself. Works in standalone *and* embedded games (rides the backend channel).
231
+
232
+ ### Matchmaking (play with online strangers)
233
+
234
+ Pair players who don't know each other into a game:
235
+
236
+ ```javascript
237
+ const match = await Usion.matchmaking.find(); // resolves when matched
238
+ // match = { roomId, players, serviceId }
239
+ await Usion.game.connect();
240
+ await Usion.game.join(match.roomId);
241
+
242
+ // while waiting you can stop:
243
+ Usion.matchmaking.cancel();
244
+ // or react to matches:
245
+ Usion.matchmaking.onMatch(({ roomId, players }) => { /* ... */ });
246
+ ```
247
+ `find({ size })` controls party size (default 2). Works standalone *and*
248
+ embedded (rides the backend channel). Pair this with `Usion.lobby` for
249
+ invite-a-friend, and `Usion.matchmaking` for quick-match with strangers.
250
+
133
251
  ## TypeScript
134
252
 
135
253
  Full type declarations included:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usions/sdk",
3
- "version": "2.2.0",
3
+ "version": "2.10.0",
4
4
  "description": "Usion Mini App SDK for iframe games and services",
5
5
  "type": "module",
6
6
  "main": "src/modules/index.js",
@@ -26,7 +26,8 @@
26
26
  "build": "rollup -c",
27
27
  "build:copy": "npm run build && cp src/browser.js ../../web/public/usion-sdk.js && cp src/browser.js ../../microservices/shared/usion-sdk.js",
28
28
  "watch": "rollup -c --watch",
29
- "test": "npm run build && vitest run"
29
+ "test": "npm run build && vitest run",
30
+ "prepublishOnly": "npm run build && vitest run"
30
31
  },
31
32
  "devDependencies": {
32
33
  "rollup": "^4.0.0",