castle-web-sdk 0.4.22 → 0.4.23

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.
@@ -64,16 +64,20 @@ class MultiplayerConnectionImpl {
64
64
  throw castleError;
65
65
  }
66
66
  }
67
+ // Unserializable data is a mistake in the deck and still throws. A missing
68
+ // socket is not: connections drop whenever a phone sleeps or changes network,
69
+ // and the session recovers on its own. A realtime deck sends every frame and
70
+ // has no useful branch to take meanwhile, so those messages are dropped.
71
+ // State arrives in whole snapshots, so the next send past recovery is current.
67
72
  send(data) {
68
73
  const text = serializeClientMessage(data);
69
- if (this.currentState !== "connected") {
74
+ if (this.currentState === "closed") {
70
75
  throw multiplayerError("MULTIPLAYER_NOT_CONNECTED", "Multiplayer.send requires a connected session.", "Multiplayer.send");
71
76
  }
72
77
  if (this.solo)
73
78
  return;
74
- if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
75
- throw multiplayerError("MULTIPLAYER_NOT_CONNECTED", "The multiplayer connection is not available.", "Multiplayer.send");
76
- }
79
+ if (!this.socket || this.socket.readyState !== WebSocket.OPEN)
80
+ return;
77
81
  this.socket.send(text);
78
82
  }
79
83
  onMessage(callback) {
@@ -177,6 +181,10 @@ class MultiplayerConnectionImpl {
177
181
  this.currentPlayerId = frame.playerId;
178
182
  this.currentSessionId = frame.sessionId;
179
183
  this.reconnectToken = frame.reconnectToken;
184
+ // Re-acquisition is limited to one per outage, not one per session. A phone
185
+ // is backgrounded many times in a play, and each of those is its own outage;
186
+ // without this the second one finds the budget spent and closes for good.
187
+ this.reAcquisitionUsed = false;
180
188
  this.transition("connected");
181
189
  this.startKeepalive();
182
190
  }
package/dist/storage.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { CastleError } from "./errors";
2
2
  import { hostRequest } from "./transport";
3
- // The child coalesces writes -- a frame can set the same key many times -- and
4
- // hands them to the host on this interval. The host, not the deck, talks to the
3
+ // Writes coalesce by key as they are made, so setting the same key repeatedly
4
+ // costs one entry; this is how often the result is handed to the host. The host, not the deck, talks to the
5
5
  // server and owns retry: it lives in the page, so it is still alive to finish a
6
6
  // write while the deck's frame is being torn down.
7
7
  const FLUSH_INTERVAL_MS = 200;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "castle-web-sdk",
3
- "version": "0.4.22",
3
+ "version": "0.4.23",
4
4
  "type": "module",
5
5
  "main": "dist/castle.js",
6
6
  "types": "dist/castle.d.ts",
@@ -14,7 +14,7 @@
14
14
  "default": "./dist/server/wrapper.js"
15
15
  }
16
16
  },
17
- "//host": "host.{js,d.ts} is the host-side executor and leaderboardPanel.{js,d.ts} is the host-side leaderboard UI \u2014 both deliberately NOT exported and NOT packaged. They are vendored into host repos via scripts/copy-host-module.mjs; decks must never receive them.",
17
+ "//host": "host.{js,d.ts} is the host-side executor and leaderboardPanel.{js,d.ts} is the host-side leaderboard UI both deliberately NOT exported and NOT packaged. They are vendored into host repos via scripts/copy-host-module.mjs; decks must never receive them.",
18
18
  "files": [
19
19
  "dist",
20
20
  "README.md",