tickcli-js 0.1.3 → 0.1.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.4
4
+
5
+ Idle pages send less. A visible page with no key, pointer, touch or gamepad input for 1 min asks the hub for a quarter of the update frames (nothing is lost, changes are merged into each frame); the first input brings the full rate back. In a 4-player test room the idle reader's download fell from 4.4 to 1.2 KB/s. Hidden pages already got no frames.
6
+
3
7
  ## 0.1.3
4
8
 
5
9
  Flood limits. New sockets per client address (`connectsPerAddress`, 40 per 10 s) are checked before the server-wide accept budget, so one client can no longer spend it for everyone; IPv6 addresses count by their /64 (`addressKey`) for every per-address limit. `hardenServer(server)` in `tickcli-js/node` (used by `createGameServer` and `createRemoteServer`): request headers within 10 s, whole request 15 s, idle keep-alive 5 s, 100 headers. Remote: a deployment is looked up at most once per 15 s per id, found or not (`remote.forget(id)` drops one after an edit), fresh lookups are capped per address, and an upgrade over the address budget is refused before any lookup. `ws` 8.23.0 or later (GHSA-37g9-w4hg-h9qr, ping flood).
package/client/room.js CHANGED
@@ -216,15 +216,39 @@
216
216
  // and how fast the game draws (game.js reports frames a second). When either is bad for 2 s the page asks for half the rate (then a quarter);
217
217
  // after 15 s of good readings it asks one step back. The hub uses the slower of its reading and the page's ask and says which (rate {div}).
218
218
  // navigator.connection (Chrome, Edge, Android) only sets the starting point: saveData or 3g = half, 2g = a quarter.
219
- var Q = { rate: 1, every: 0, ask: 1, net: 1, dev: 1, lateMs: 0, fps: 0, rtt: 0 };
219
+ // Idle: a visible page with no key, pointer, touch or gamepad input for IDLE_MS = 1 min (someone who walked away; a short pause or a turn-based wait keeps the full rate) asks a quarter of
220
+ // the frames; the first input brings the full rate back. A hidden page already gets none (see the hub's vis).
221
+ var Q = { rate: 1, every: 0, ask: 1, net: 1, dev: 1, idle: 1, lateMs: 0, fps: 0, rtt: 0 };
220
222
  var late = [], lateBase = [], badSince = 0, goodSince = 0, devBad = 0, devGood = 0, askedAt = 0;
223
+ var IDLE_MS = 60000, lastInput = Date.now();
224
+ function touched() {
225
+ lastInput = Date.now();
226
+ if (Q.idle > 1) { Q.idle = 1; askRate(); }
227
+ }
228
+ function idleCheck() {
229
+ if (typeof document !== "undefined" && document.hidden) return;
230
+ try {
231
+ var gp = navigator.getGamepads && navigator.getGamepads();
232
+ for (var g = 0; gp && g < gp.length; g++) {
233
+ var pad = gp[g]; if (!pad) continue;
234
+ var i; for (i = 0; i < pad.buttons.length; i++) if (pad.buttons[i].pressed) return touched();
235
+ for (i = 0; i < pad.axes.length; i++) if (Math.abs(pad.axes[i]) > 0.3) return touched();
236
+ }
237
+ } catch (e) { /* no gamepads */ }
238
+ if (Q.idle === 1 && Date.now() - lastInput >= IDLE_MS) { Q.idle = 4; askRate(); }
239
+ }
240
+ try {
241
+ ["pointerdown", "pointermove", "keydown", "touchstart", "wheel"].forEach(function (ev) { addEventListener(ev, touched, { capture: true, passive: true }); });
242
+ addEventListener("visibilitychange", function () { if (typeof document === "undefined" || !document.hidden) touched(); });
243
+ } catch (e) { /* no window events */ }
244
+ setInterval(idleCheck, 2000);
221
245
  try {
222
246
  var nc = navigator.connection;
223
247
  if (nc) Q.net = nc.effectiveType === "slow-2g" || nc.effectiveType === "2g" ? 4 : nc.saveData || nc.effectiveType === "3g" ? 2 : 1;
224
248
  } catch (e) { /* no Network Information API */ }
225
249
  Q.ask = Q.net;
226
250
  function askRate() {
227
- var want = Math.max(Q.net, Q.dev);
251
+ var want = Math.max(Q.net, Q.dev, Q.idle);
228
252
  if (want === Q.ask) return;
229
253
  Q.ask = want; askedAt = Date.now();
230
254
  send({ t: "rate", div: want });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tickcli-js",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Live rooms for browser games: one player's browser runs the rules, a small Node hub keeps the shared state, membership and order. No game code on the server.",
5
5
  "license": "MIT",
6
6
  "repository": {