@usions/sdk 2.20.0 → 2.20.2
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 +5 -4
- package/package.json +1 -1
- package/src/browser.js +23 -2
- package/src/modules/game-core.js +18 -0
- package/src/modules/game-methods.js +4 -1
- package/types/index.d.ts +8 -5
package/README.md
CHANGED
|
@@ -139,10 +139,11 @@ follow four rules so both screens always agree:
|
|
|
139
139
|
actions automatically. Use `onPlayerConnection` for the opponent's status;
|
|
140
140
|
don't end the match on `'reconnecting'` (a ~15s grace window applies),
|
|
141
141
|
treat `'gone'` as the opponent having left.
|
|
142
|
-
4. **
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
4. **Checkpoint with `setState`** — any participant (not just the host)
|
|
143
|
+
should checkpoint at meaningful transitions so a rejoining client restores
|
|
144
|
+
instantly (delivered as `game_state` in the join result and `onSync`; max
|
|
145
|
+
64 KB). Letting whoever made the move persist state keeps the snapshot
|
|
146
|
+
fresh even while the host is backgrounded:
|
|
146
147
|
```javascript
|
|
147
148
|
await Usion.game.setState(fullGameState)
|
|
148
149
|
```
|
package/package.json
CHANGED
package/src/browser.js
CHANGED
|
@@ -69,7 +69,7 @@ var Usion = (function () {
|
|
|
69
69
|
* Core Usion object with init, _post, _request
|
|
70
70
|
*/
|
|
71
71
|
const core = {
|
|
72
|
-
version: '2.20.
|
|
72
|
+
version: '2.20.2', // injected from package.json at build
|
|
73
73
|
config: {},
|
|
74
74
|
_initialized: false,
|
|
75
75
|
_initCallback: null,
|
|
@@ -2220,7 +2220,10 @@ var Usion = (function () {
|
|
|
2220
2220
|
* in the join ack and in game:sync — recovery becomes "load checkpoint,
|
|
2221
2221
|
* replay the tail" instead of replaying every action from zero.
|
|
2222
2222
|
*
|
|
2223
|
-
*
|
|
2223
|
+
* Any participant in the room may call this (not just the host) — the
|
|
2224
|
+
* server only requires that you're in player_ids. This keeps the snapshot
|
|
2225
|
+
* fresh even while the host is backgrounded; the host-authority pattern
|
|
2226
|
+
* (only the host calls setState) still works for games that prefer it. The
|
|
2224
2227
|
* serialized state is capped at 64 KB.
|
|
2225
2228
|
*
|
|
2226
2229
|
* @param {*} state - JSON-serializable authoritative game state
|
|
@@ -4851,6 +4854,24 @@ var Usion = (function () {
|
|
|
4851
4854
|
applyGameMethods(game, Usion);
|
|
4852
4855
|
applyGameNetcode(game, Usion);
|
|
4853
4856
|
|
|
4857
|
+
// Foreground catch-up safety net (generic across every transport).
|
|
4858
|
+
//
|
|
4859
|
+
// When a page/iframe is backgrounded its JS is suspended: timers freeze and
|
|
4860
|
+
// relayed actions can be missed (postMessage to a frozen WebView). A brief
|
|
4861
|
+
// app-switch may also never trip a socket disconnect/reconnect, so the game's
|
|
4862
|
+
// onReconnect handler never fires and it silently misses moves made while it
|
|
4863
|
+
// was away — leaving turn state behind and the table deadlocked. On every
|
|
4864
|
+
// return to visibility, if we're in a room, request a sync so the game
|
|
4865
|
+
// deterministically catches up. Per the action reliability contract, onSync
|
|
4866
|
+
// is deduped by sequence, so an unnecessary resync is a no-op.
|
|
4867
|
+
if (typeof document !== 'undefined' && typeof document.addEventListener === 'function') {
|
|
4868
|
+
document.addEventListener('visibilitychange', function() {
|
|
4869
|
+
if (document.visibilityState !== 'visible') return;
|
|
4870
|
+
if (!game.roomId) return;
|
|
4871
|
+
try { game.requestSync(); } catch (e) { /* non-fatal */ }
|
|
4872
|
+
});
|
|
4873
|
+
}
|
|
4874
|
+
|
|
4854
4875
|
return game;
|
|
4855
4876
|
}
|
|
4856
4877
|
|
package/src/modules/game-core.js
CHANGED
|
@@ -242,5 +242,23 @@ export function createGameModule(Usion) {
|
|
|
242
242
|
applyGameMethods(game, Usion);
|
|
243
243
|
applyGameNetcode(game, Usion);
|
|
244
244
|
|
|
245
|
+
// Foreground catch-up safety net (generic across every transport).
|
|
246
|
+
//
|
|
247
|
+
// When a page/iframe is backgrounded its JS is suspended: timers freeze and
|
|
248
|
+
// relayed actions can be missed (postMessage to a frozen WebView). A brief
|
|
249
|
+
// app-switch may also never trip a socket disconnect/reconnect, so the game's
|
|
250
|
+
// onReconnect handler never fires and it silently misses moves made while it
|
|
251
|
+
// was away — leaving turn state behind and the table deadlocked. On every
|
|
252
|
+
// return to visibility, if we're in a room, request a sync so the game
|
|
253
|
+
// deterministically catches up. Per the action reliability contract, onSync
|
|
254
|
+
// is deduped by sequence, so an unnecessary resync is a no-op.
|
|
255
|
+
if (typeof document !== 'undefined' && typeof document.addEventListener === 'function') {
|
|
256
|
+
document.addEventListener('visibilitychange', function() {
|
|
257
|
+
if (document.visibilityState !== 'visible') return;
|
|
258
|
+
if (!game.roomId) return;
|
|
259
|
+
try { game.requestSync(); } catch (e) { /* non-fatal */ }
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
245
263
|
return game;
|
|
246
264
|
}
|
|
@@ -248,7 +248,10 @@ export function applyGameMethods(game, Usion) {
|
|
|
248
248
|
* in the join ack and in game:sync — recovery becomes "load checkpoint,
|
|
249
249
|
* replay the tail" instead of replaying every action from zero.
|
|
250
250
|
*
|
|
251
|
-
*
|
|
251
|
+
* Any participant in the room may call this (not just the host) — the
|
|
252
|
+
* server only requires that you're in player_ids. This keeps the snapshot
|
|
253
|
+
* fresh even while the host is backgrounded; the host-authority pattern
|
|
254
|
+
* (only the host calls setState) still works for games that prefer it. The
|
|
252
255
|
* serialized state is capped at 64 KB.
|
|
253
256
|
*
|
|
254
257
|
* @param {*} state - JSON-serializable authoritative game state
|
package/types/index.d.ts
CHANGED
|
@@ -300,8 +300,9 @@ export interface GameModule {
|
|
|
300
300
|
// pause input and show a "reconnecting" indicator.
|
|
301
301
|
// - For turn-based games, pass { nextTurn } on each move and trust
|
|
302
302
|
// current_turn from join/sync instead of deriving the turn locally.
|
|
303
|
-
// -
|
|
304
|
-
//
|
|
303
|
+
// - Any participant should checkpoint via setState() at meaningful
|
|
304
|
+
// transitions so rejoining clients can restore instantly (the host
|
|
305
|
+
// need not be the one to call it).
|
|
305
306
|
join(roomId?: string): Promise<GameJoinResult>;
|
|
306
307
|
leave(): void;
|
|
307
308
|
action(actionType: string, actionData?: Record<string, any>, opts?: GameActionOptions): Promise<ActionResult>;
|
|
@@ -322,9 +323,11 @@ export interface GameModule {
|
|
|
322
323
|
invite(opts?: GameInviteOptions): Promise<GameInviteResult>;
|
|
323
324
|
|
|
324
325
|
/**
|
|
325
|
-
* Checkpoint authoritative game state on the server
|
|
326
|
-
* player_ids[0]/host)
|
|
327
|
-
*
|
|
326
|
+
* Checkpoint authoritative game state on the server. Any participant in the
|
|
327
|
+
* room may call this (not just player_ids[0]/host), so the snapshot stays
|
|
328
|
+
* fresh even while the host is backgrounded. (Re)joining clients receive the
|
|
329
|
+
* latest checkpoint as game_state in the join ack and in game:sync. Max 64 KB
|
|
330
|
+
* serialized.
|
|
328
331
|
*/
|
|
329
332
|
setState(state: Record<string, any>): Promise<{ success: boolean; error?: string; code?: UsionErrorCode }>;
|
|
330
333
|
|