@diffenderfer-games/hub 2.0.0-next.5 → 2.0.0-next.6

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 (170) hide show
  1. package/CHANGELOG.md +54 -19
  2. package/README.md +3 -6
  3. package/dist/auto.d.ts +5 -5
  4. package/dist/auto.js +2 -2
  5. package/dist/avatar-pixi.d.ts +147 -0
  6. package/dist/avatar-pixi.d.ts.map +1 -0
  7. package/dist/avatar-pixi.js +280 -0
  8. package/dist/avatar-pixi.js.map +1 -0
  9. package/dist/avatar-svg.d.ts +4 -0
  10. package/dist/avatar-svg.js +5 -0
  11. package/dist/avatar-three.d.ts +69 -0
  12. package/dist/avatar-three.d.ts.map +1 -0
  13. package/dist/avatar-three.js +49 -0
  14. package/dist/avatar-three.js.map +1 -0
  15. package/dist/avatar.d.ts +7 -0
  16. package/dist/avatar.js +487 -0
  17. package/dist/avatar.js.map +1 -0
  18. package/dist/daily.d.ts +2 -2
  19. package/dist/doctor/cli.mjs +1 -1
  20. package/dist/index.d.ts +5 -5
  21. package/dist/index.js +2 -2
  22. package/dist/input.d.ts +2 -2
  23. package/dist/shared/animator.d.ts +104 -0
  24. package/dist/shared/animator.d.ts.map +1 -0
  25. package/dist/shared/art.js +1804 -0
  26. package/dist/shared/art.js.map +1 -0
  27. package/dist/shared/atlas.d.ts +134 -0
  28. package/dist/shared/atlas.d.ts.map +1 -0
  29. package/dist/shared/avatar.d.ts +117 -0
  30. package/dist/shared/avatar.d.ts.map +1 -0
  31. package/dist/shared/bridge.js +13 -5
  32. package/dist/shared/bridge.js.map +1 -1
  33. package/dist/shared/client-version.gen.js +1 -1
  34. package/dist/shared/daily.d.ts +129 -18
  35. package/dist/shared/daily.d.ts.map +1 -1
  36. package/dist/shared/daily.js +120 -26
  37. package/dist/shared/daily.js.map +1 -1
  38. package/dist/shared/defineProperty.js +39 -0
  39. package/dist/shared/describe.d.ts +32 -0
  40. package/dist/shared/describe.d.ts.map +1 -0
  41. package/dist/shared/describe.js +101 -0
  42. package/dist/shared/describe.js.map +1 -0
  43. package/dist/shared/globals.js +1 -39
  44. package/dist/shared/globals.js.map +1 -1
  45. package/dist/shared/index.d.ts +503 -14
  46. package/dist/shared/index.d.ts.map +1 -1
  47. package/dist/shared/input.d.ts +31 -13
  48. package/dist/shared/input.d.ts.map +1 -1
  49. package/dist/shared/input.js +40 -2
  50. package/dist/shared/input.js.map +1 -1
  51. package/dist/shared/json-guards.js +48 -0
  52. package/dist/shared/json-guards.js.map +1 -0
  53. package/dist/shared/live-canvas.js +62 -0
  54. package/dist/shared/live-canvas.js.map +1 -0
  55. package/dist/shared/mp.js +1 -1
  56. package/dist/shared/overlays.js +800 -0
  57. package/dist/shared/overlays.js.map +1 -0
  58. package/dist/shared/page-stack.js +2 -1
  59. package/dist/shared/page-stack.js.map +1 -1
  60. package/dist/shared/pose-key.js +249 -0
  61. package/dist/shared/pose-key.js.map +1 -0
  62. package/dist/shared/race.js +1 -1
  63. package/dist/shared/rooms.js +1 -1
  64. package/dist/shared/scene.d.ts +90 -0
  65. package/dist/shared/scene.d.ts.map +1 -0
  66. package/dist/shared/social.d.ts +55 -4
  67. package/dist/shared/social.d.ts.map +1 -1
  68. package/dist/shared/src.js +2020 -144
  69. package/dist/shared/src.js.map +1 -1
  70. package/dist/shared/svg-markup.js +1860 -0
  71. package/dist/shared/svg-markup.js.map +1 -0
  72. package/dist/shared/svg.js +27 -0
  73. package/dist/shared/svg.js.map +1 -0
  74. package/dist/shared/types.d.ts +166 -0
  75. package/dist/shared/types.d.ts.map +1 -0
  76. package/dist/social.d.ts +2 -2
  77. package/dist/social.js +2 -2
  78. package/dist/turns.d.ts +39 -0
  79. package/dist/turns.d.ts.map +1 -0
  80. package/dist/turns.js +117 -0
  81. package/dist/turns.js.map +1 -0
  82. package/package.json +33 -3
  83. package/src/avatar/adapters/pixi-avatar.ts +73 -0
  84. package/src/avatar/adapters/pixi-crowd.ts +302 -0
  85. package/src/avatar/adapters/pixi-types.ts +84 -0
  86. package/src/avatar/adapters/three.ts +126 -0
  87. package/src/avatar/animator/animator.ts +285 -0
  88. package/src/avatar/animator/reactions.ts +44 -0
  89. package/src/avatar/animator/schedule.ts +73 -0
  90. package/src/avatar/art/beard.ts +49 -0
  91. package/src/avatar/art/glasses.ts +9 -0
  92. package/src/avatar/art/hair.ts +254 -0
  93. package/src/avatar/art/headwear.ts +75 -0
  94. package/src/avatar/art/index.ts +21 -0
  95. package/src/avatar/art/shape.ts +68 -0
  96. package/src/avatar/art-store.ts +36 -0
  97. package/src/avatar/atlas.ts +236 -0
  98. package/src/avatar/catalog-view.ts +14 -0
  99. package/src/avatar/colour.ts +109 -0
  100. package/src/avatar/describe.ts +76 -0
  101. package/src/avatar/face.ts +187 -0
  102. package/src/avatar/geom.ts +168 -0
  103. package/src/avatar/layout.ts +47 -0
  104. package/src/avatar/look-like.ts +52 -0
  105. package/src/avatar/outputs/bitmap.ts +75 -0
  106. package/src/avatar/outputs/canvas-paint.ts +177 -0
  107. package/src/avatar/outputs/canvas.ts +62 -0
  108. package/src/avatar/outputs/custom-element.ts +140 -0
  109. package/src/avatar/outputs/element.ts +58 -0
  110. package/src/avatar/outputs/live-canvas.ts +57 -0
  111. package/src/avatar/outputs/overlay-svg.ts +22 -0
  112. package/src/avatar/outputs/pose-key.ts +30 -0
  113. package/src/avatar/outputs/svg-markup.ts +113 -0
  114. package/src/avatar/outputs/svg.ts +41 -0
  115. package/src/avatar/overlays.ts +128 -0
  116. package/src/avatar/render/body.ts +116 -0
  117. package/src/avatar/render/colours.ts +81 -0
  118. package/src/avatar/render/compose.ts +258 -0
  119. package/src/avatar/render/context.ts +117 -0
  120. package/src/avatar/render/eyes.ts +78 -0
  121. package/src/avatar/render/eyewear.ts +56 -0
  122. package/src/avatar/render/frame.ts +60 -0
  123. package/src/avatar/render/head.ts +81 -0
  124. package/src/avatar/render/mouth.ts +86 -0
  125. package/src/avatar/render/props.ts +91 -0
  126. package/src/avatar/render/types.ts +84 -0
  127. package/src/avatar/scene.ts +119 -0
  128. package/src/avatar-pixi.ts +20 -0
  129. package/src/avatar-svg.ts +21 -0
  130. package/src/avatar-three.ts +18 -0
  131. package/src/avatar.ts +62 -0
  132. package/src/core/avatar/avatar-cache.ts +95 -0
  133. package/src/core/avatar/avatar-ref.ts +34 -0
  134. package/src/core/avatar/avatar-types.ts +43 -0
  135. package/src/core/avatar/hub-avatar.ts +308 -0
  136. package/src/core/connection.ts +8 -0
  137. package/src/core/errors.ts +7 -1
  138. package/src/core/hub-progress.ts +269 -238
  139. package/src/core/hub.ts +174 -6
  140. package/src/core/offline/hub-kinds/avatar-kind.ts +42 -0
  141. package/src/core/offline/hub-kinds/index.ts +9 -0
  142. package/src/core/offline/hub-kinds/saved-kind.ts +93 -0
  143. package/src/core/page-account.ts +121 -0
  144. package/src/core/rest/routes.gen.ts +31 -1
  145. package/src/core/resume/hub-resume.ts +39 -5
  146. package/src/core/resume/resume-types.ts +2 -2
  147. package/src/core/saved/daily-saves.ts +196 -0
  148. package/src/core/saved/daily-seed.ts +16 -0
  149. package/src/core/saved/hub-saved.ts +221 -0
  150. package/src/core/saved/local-saved.ts +122 -0
  151. package/src/core/saved/saved-list.ts +129 -0
  152. package/src/core/saved/saved-open.ts +104 -0
  153. package/src/core/saved/saved-order.ts +49 -0
  154. package/src/core/saved/saved-types.ts +24 -0
  155. package/src/core/turns/hub-turns.ts +140 -0
  156. package/src/core/turns/turn-game.ts +388 -0
  157. package/src/core/version/client-version.gen.ts +2 -2
  158. package/src/daily/daily-system.ts +112 -13
  159. package/src/daily/page-daily.ts +2 -2
  160. package/src/daily/types.ts +46 -9
  161. package/src/doctor/hub-version-fetch.ts +43 -43
  162. package/src/index.ts +10 -1
  163. package/src/input/input-system.ts +10 -1
  164. package/src/input/navigator.ts +11 -0
  165. package/src/input.ts +1 -0
  166. package/src/overlay/overlay.ts +25 -1
  167. package/src/realtime/runtime-api.ts +14 -3
  168. package/src/social.ts +1 -0
  169. package/src/turns-kit/check-rules.ts +182 -0
  170. package/src/turns.ts +13 -0
package/CHANGELOG.md CHANGED
@@ -1,31 +1,66 @@
1
1
  # @diffenderfer-games/hub
2
2
 
3
- ## 2.0.0-next.5
4
-
5
- ### Patch Changes
6
-
7
- - 7585522: Saves offline no longer risk the cloud copy. Offline, `getSave(slot)` rejects with a `HubError` whose `code` is `save_unknown` (new export `SAVE_UNKNOWN_CODE`; `isOffline` is `true`) when the device has never seen the hub's copy of that slot, instead of answering `save: null`; it still answers from the device's copy after a snapshot (`prefetchAll`), an online read, a landed write, or for a slot the device wrote and has queued. A `putSave` replayed from the offline queue now sends `base`, the slot's `updatedAt` on the hub as the device last saw it, and the hub refuses it with 409 `save_conflict` when another device saved since (dropped and reported in the `hub:sync` conflicts); writes sent at once while online are unchanged. The client also remembers the signed-in user from `login`, `signup`, `claim` and `ensureGuest` replies, and forgets it on `logout`. Contract: `writeSave` takes an optional `base` and may answer 409; new error code `save_conflict`. Older clients (no `base`) behave as before. See docs/hub.md "Saves offline".
8
- - Updated dependencies [7585522]
9
- - @diffenderfer-games/hub-contract@2.0.0-next.5
10
-
11
- ## 2.0.0-next.4
3
+ ## 2.0.0-next.6
12
4
 
13
5
  ### Minor Changes
14
6
 
15
- - 9f993ab: Resume saved games. New `hub.resume` (`save`, `flush`, `clear`, `load`, `get`, `requested`, `blockedBy`, `list`, `discard`): one auto-saved run per player per game that the home page's new Resume card lists, so players pick long single-player runs up again on any device. Saves are kept on the device at once, debounced (3 s), sent when the page hides, and replay offline through the new `hub.resume` outbox kind; they are ignored during races, daily challenges and hub rooms. `hub.resume.requested` is a synchronous `true` when the page was opened from the card (`?hub_resume=1`, taken out of the URL). Games opt in with `game.resumable: true` in the manifest. Contract: `resumeEndpoints` (`getResumeSlot`, `saveResumeSlot`, `clearResumeSlot`, `listMyResumeSlots`), `ResumeSlot`, `ResumeSummary`, `ResumeProgress`, `ResumeWrite`, `RESUME_MAX_STATE_BYTES` (512 KB), `RESUME_TEXT_MAX`, `RESUME_RETENTION_MS` (60 days), `RESUME_REQUEST_PARAM`; `saveResumeSlot` and `clearResumeSlot` join `OFFLINE_REPLAY_ENDPOINTS`. See docs/hub.md "Resume saved games". Daily: `hub.daily.complete()` now ends the daily run at the call (`hub.daily.active` is `null` at once, even if the hub refuses the completion); games must call `hub.daily.cancel()` when the player leaves a daily unfinished, or `hub.resume.save` stays off (it warns once).
16
-
17
- ### Patch Changes
18
-
19
- - Updated dependencies [9f993ab]
20
- - @diffenderfer-games/hub-contract@2.0.0-next.4
21
-
22
- ## 2.0.0-next.3
7
+ - 537272a: `hub.avatar`: players' avatars without the renderer. `mine()` / `mineSync()` (works offline from the device cache), `of(userId)` and `many(ids)` (batched and cached), `from(seat)` (any payload with `look`, no request), `bot(seed)` for computer players, `save(look)` (queued offline), `on('change')`, `openDesigner()` ("Make your avatar" over the game) and `load()` (the `/avatar` renderer with its art). A DOM-free `@diffenderfer-games/hub/avatar/svg` entry renders avatars as SVG on servers and in workers.
8
+ - fb0a9f5: `hub.userId()`: your user id, or `null`, synchronously. It follows the account as the hub changes it (the menu's new-guest account, sign-in, sign-out, the live connection's hello) with no `hub.me()` call.
9
+
10
+ `hub.avatar` follows the account too: when your account appears or changes, your look is fetched and `change` fires with your `userId`; before it exists, `mine()` resolves at once with a default look. Each time the live connection (re)connects, the looks this page asked about are checked again and `change` fires for any that changed while it was down. `change` for your own look fires only when it differs from the one the page last had.
11
+ - 849874f: Avatars: draw players' faces in any game. New entries: `@diffenderfer-games/hub/avatar` (`ready()`, `render.svg/element/canvas/canvasAt/bitmap/dataUrl`, `<dg-avatar>` via `defineAvatarElement()`, the `animator` with 16 expressions, gaze, blinks, talking, reactions and `feel()`, `layout()` anchors, `facingFrom`, `lookToward`, `describe`, `avatarEmoji`, overlays and `createAtlas`), `@diffenderfer-games/hub/avatar/pixi` (`pixiAvatar`, `avatarTexture`, `createCrowd`) and `@diffenderfer-games/hub/avatar/three` (`avatarCanvasTexture`, `avatarSprite`). The adapters take your PIXI or THREE namespace; no new dependencies. See "Avatars" in docs/hub.md.
12
+ - 5109a42: The avatar renderer draws the new `beard.short` (a short, neat beard with a moustache) in style C, with the same beard and moustache layers and tonal outline as the full beard, in SVG, `<dg-avatar>` and the Pixi and three.js adapters. `describe()` calls it "a short beard".
13
+ - e86bfb4: "Your turn" alerts and quiet hours. The contract adds the `your_turn` notice and preference kind, `NotifyPrefs.yourTurn`/`yourTurnOff`/`yourTurnAsked`/`quiet`, `QuietHours` and `PUT /social/notify/quiet` (`setQuietHours`), plus `POST /turns/:id/share` (`shareTurnGame`) and `autoStart` on `createTurnGame`. The client adds `TurnGame.share({ link?, public? })`, `hub.turns.create({ autoStart })`, `TURN_RESYNC_EVENT` (an open online game fetches what it missed when the live connection comes back; `turn` also fires on a `chatMode` or `link` change), and `hub.saved.onOpen(handler, { kinds })`. A second Rematch joins the first one's game.
14
+ - e0e38da: Daily challenges in progress. A started day is now a saved game: starting it again (the calendar, a `?daily=` link, Your games) picks it up where the player left it, at any age, and winning it any time later gives that day's credit. `hub.daily` adds `save({ state, progress, title?, version? })`, `resume(instanceId)`, `discard()` and `inProgress()`; `challenge.saved`/`savedVersion`/`instanceId`/`resumed` in `play(challenge)`; the `hub:daily-resumed`, `hub:daily-paused` and `hub:daily-discarded` events. `hub.daily.cancel()` now pauses the day (it stays in progress) instead of dropping it. `hub.resume.save()` during a daily saves to the day instead of being ignored (`blockedBy` no longer reports `'daily'`), so games that already use `hub.resume` get mid-daily saves for free; `hub.resume.clear()` during a daily restarts the day. Works offline (a day started offline lands as the one saved game for that day). The contract adds `StartedDailyChallenge` (start answers `instanceId`, `saved`, `savedVersion`, `resumed`), `POST /daily/instances/:id/resume`, `inProgress` days in `GET /daily` and `GET /games/:slug/daily`, and 409 `too_many_dailies` (60 per game).
15
+ - ce80c33: Saved games (foundations). New `hub.saved`: `list()` (this game's games in progress: daily challenges, the saved run, online games), `listAll()`, `opened` (the instance the page was opened for, `?hub_open=<id>&hub_kind=<kind>`), `onOpen(handler)` (switch to a game picked from the hub menu without a reload), `open(id)`, `discard(id)`, `counts()` and `on('change', cb)`. Works offline from the device's copies. The contract adds `api/saved.ts` (`GET /saved`, `GET /saved/:id`, `PUT /saved/:id/state`, `POST /saved/:id/discard`, `POST /games/:slug/saved/discard`), the `saved` socket event, `TurnSummary`, the error codes `instance_closed` and `too_many_dailies`, and the pure `compareSaved`/`countSaved`. `hub.resume` is unchanged for games; saved runs never expire any more (`RESUME_RETENTION_MS` is deprecated and unused).
16
+ - 0c5c833: Online games played over days. A game declares `game.turns` (`rules`, `players`, `bots`, `modes`, `maxApplyMs`) and ships its rules as one self-contained ES module (the `TurnRules` contract: `setup`, `view`, `toAct`, `apply`, `eventView`, `outcome`, `progress`, `autoMove`, `migrate`); the hub runs it on the server, so hands and decks never reach another player. New `hub.turns` (`create`, `join`, `open`, `list`, `openLobbies`, `link`) and `TurnGame` (`summary`, `view`, `mySeat`, `outcome`, `chat`, `chatMode`, `link`, `start`, `move`, `history`, `leave`, `nudge`, `setNotify`, `rematch`, `invite`, `letComputerPlay`, `say`, `refresh`, `close`, events `move`, `turn`, `ended`, `chat`). `@diffenderfer-games/hub/turns` exports the rules types, `defineTurnRules`, the seeded RNG and the `checkTurnRules` conformance kit for a game's own tests. `HubError.rule` carries a rules refusal's code; `hub.resume.blockedBy` can be `'turns'`. The contract adds `api/turns.ts`, the `turn` and `turn.chat` events, the turn error codes, `ErrorBody.rule`, Play online's `yourTurn`/`turns`/`openTurns`/`turnGames`, and the `turn_chat` report kind.
23
17
 
24
18
  ### Patch Changes
25
19
 
26
- - ce98e79: Focus rings only for keyboard and gamepad players. The input system tracks the last input modality on `<html data-hub-input="keys|pointer|touch">`: the navigation highlight and the catalog's `gp-focus` show only after a key or gamepad press, never after a tap or click, and touch screens show no focus ring on buttons at all (the browser's own included). The ring is new: a two-tone box-shadow (dark gap, light ring) that follows the element's own corner radius instead of an orange rectangle, tunable with `--hub-focus-color`, `--hub-focus-inner`, `--hub-focus-width` and `--hub-focus-gap`. New exports from `@diffenderfer-games/hub/input`: `FOCUS_RING_SHADOW`, `MODALITY_ATTRIBUTE`, `trackInputModality` and the `InputModality` type.
27
- - @diffenderfer-games/hub-contract@2.0.0-next.3
20
+ - 4a03d21: The avatar adapters take the engines' real types and give them back: `pixiAvatar`, `avatarTexture` and `createCrowd` (`/avatar/pixi`) accept `import * as PIXI from 'pixi.js'` or an object of the named imports, and `face.view` is pixi's own `Sprite` (it goes into a `Container` with no cast). `avatarSprite` and `avatarCanvasTexture` (`/avatar/three`) do the same for three.js, returning three's `Sprite` and `CanvasTexture`; `avatarCanvasTexture` needs only `CanvasTexture` (the new `ThreeTextureNs`). `PixiNs`, `PixiSprite`, `PixiContainer`, `PixiAvatar`, `CrowdOptions`, `ThreeNs` and `ThreeAvatarTexture` are generic over the game's classes, with defaults, so existing annotations keep compiling. No runtime change.
21
+ - bcb10f1: `hub.resume.clear()` during a daily challenge now reaches the hub (the day starts over from its seed on every device instead of the old state coming back), and `hub.resume.get()`/`load()` dropping an older-version saved run no longer restarts the daily being played.
22
+ - ac2884e: `hub.input.autoNavigateTarget()` returns the game's current `autoNavigate` target (its query and back action), so hub dialogs that borrow the gamepad give the game's menu navigation back when they close. Fixes gamepad menu navigation being lost after a social dialog (a confirm, the share sheet) closed.
23
+ - b2e9e64: Saved runs (`hub.resume`) are now saved games of their own kind and never expire; the API is unchanged. The menu's Reset game also offers to discard the game's daily challenges in progress.
24
+ - 93af853: `hub.input.setInsets` also publishes the insets as `--hub-inset-top` (and right, bottom, left) on the page, so the hub's toasts sit below a game's top bar (without it, the hub looks for a top bar in the page itself).
25
+ - 06f827c: `TurnGame` fires `turn` when a seated player changes their avatar (the seat's `look`), not only when statuses or players change.
26
+ - Updated dependencies [91ca7f9]
27
+ - Updated dependencies [46fa584]
28
+ - Updated dependencies [5109a42]
29
+ - Updated dependencies [bf6445c]
30
+ - Updated dependencies [508531a]
31
+ - Updated dependencies [e86bfb4]
32
+ - Updated dependencies [e0e38da]
33
+ - Updated dependencies [ce80c33]
34
+ - Updated dependencies [0c5c833]
35
+ - Updated dependencies [17cf0af]
36
+ - @diffenderfer-games/hub-contract@2.0.0-next.6
28
37
 
38
+ ## 2.0.0-next.5
39
+
40
+ ### Patch Changes
41
+
42
+ - 7585522: Saves offline no longer risk the cloud copy. Offline, `getSave(slot)` rejects with a `HubError` whose `code` is `save_unknown` (new export `SAVE_UNKNOWN_CODE`; `isOffline` is `true`) when the device has never seen the hub's copy of that slot, instead of answering `save: null`; it still answers from the device's copy after a snapshot (`prefetchAll`), an online read, a landed write, or for a slot the device wrote and has queued. A `putSave` replayed from the offline queue now sends `base`, the slot's `updatedAt` on the hub as the device last saw it, and the hub refuses it with 409 `save_conflict` when another device saved since (dropped and reported in the `hub:sync` conflicts); writes sent at once while online are unchanged. The client also remembers the signed-in user from `login`, `signup`, `claim` and `ensureGuest` replies, and forgets it on `logout`. Contract: `writeSave` takes an optional `base` and may answer 409; new error code `save_conflict`. Older clients (no `base`) behave as before. See docs/hub.md "Saves offline".
43
+ - Updated dependencies [7585522]
44
+ - @diffenderfer-games/hub-contract@2.0.0-next.5
45
+
46
+ ## 2.0.0-next.4
47
+
48
+ ### Minor Changes
49
+
50
+ - 9f993ab: Resume saved games. New `hub.resume` (`save`, `flush`, `clear`, `load`, `get`, `requested`, `blockedBy`, `list`, `discard`): one auto-saved run per player per game that the home page's new Resume card lists, so players pick long single-player runs up again on any device. Saves are kept on the device at once, debounced (3 s), sent when the page hides, and replay offline through the new `hub.resume` outbox kind; they are ignored during races, daily challenges and hub rooms. `hub.resume.requested` is a synchronous `true` when the page was opened from the card (`?hub_resume=1`, taken out of the URL). Games opt in with `game.resumable: true` in the manifest. Contract: `resumeEndpoints` (`getResumeSlot`, `saveResumeSlot`, `clearResumeSlot`, `listMyResumeSlots`), `ResumeSlot`, `ResumeSummary`, `ResumeProgress`, `ResumeWrite`, `RESUME_MAX_STATE_BYTES` (512 KB), `RESUME_TEXT_MAX`, `RESUME_RETENTION_MS` (60 days), `RESUME_REQUEST_PARAM`; `saveResumeSlot` and `clearResumeSlot` join `OFFLINE_REPLAY_ENDPOINTS`. See docs/hub.md "Resume saved games". Daily: `hub.daily.complete()` now ends the daily run at the call (`hub.daily.active` is `null` at once, even if the hub refuses the completion); games must call `hub.daily.cancel()` when the player leaves a daily unfinished, or `hub.resume.save` stays off (it warns once).
51
+
52
+ ### Patch Changes
53
+
54
+ - Updated dependencies [9f993ab]
55
+ - @diffenderfer-games/hub-contract@2.0.0-next.4
56
+
57
+ ## 2.0.0-next.3
58
+
59
+ ### Patch Changes
60
+
61
+ - ce98e79: Focus rings only for keyboard and gamepad players. The input system tracks the last input modality on `<html data-hub-input="keys|pointer|touch">`: the navigation highlight and the catalog's `gp-focus` show only after a key or gamepad press, never after a tap or click, and touch screens show no focus ring on buttons at all (the browser's own included). The ring is new: a two-tone box-shadow (dark gap, light ring) that follows the element's own corner radius instead of an orange rectangle, tunable with `--hub-focus-color`, `--hub-focus-inner`, `--hub-focus-width` and `--hub-focus-gap`. New exports from `@diffenderfer-games/hub/input`: `FOCUS_RING_SHADOW`, `MODALITY_ATTRIBUTE`, `trackInputModality` and the `InputModality` type.
62
+ - @diffenderfer-games/hub-contract@2.0.0-next.3
63
+
29
64
  ## 2.0.0-next.2
30
65
 
31
66
  ### Minor Changes
package/README.md CHANGED
@@ -181,16 +181,13 @@ warns when the client is deprecated or a vendored `src/hub/` copy (or
181
181
  The hub's test kit lives in the host repo (`test/helpers/`). Point your
182
182
  game's tests at a checkout of it with `DG_HOST`; the default is
183
183
  `../diffenderfer-games`. It boots a real hub on a free port for each test
184
- file:
184
+ file (the same hub and host production runs):
185
185
 
186
186
  ```sh
187
- DG_HOST=../diffenderfer-games HUB_IMPL=next npm run test:hub
187
+ DG_HOST=../diffenderfer-games npm run test:hub
188
188
  ```
189
189
 
190
- `HUB_IMPL=next` runs the TypeScript hub and host that production runs. Without
191
- it, the kit boots the old hub (`src/index.js`), which is kept only as a
192
- rollback path until it is deleted; test against `next`. The checkout needs
193
- `npm ci` at its root and in `next/`.
190
+ The checkout needs `npm ci` at its root.
194
191
 
195
192
  ## Moving from the vendored copy
196
193
 
package/dist/auto.d.ts CHANGED
@@ -1,14 +1,14 @@
1
+ import { A as SAVED_OPEN_EVENT, C as SavedKind, D as TurnSummary, E as SavedStatus, M as SavedOpened, N as savedGameUrl, O as SAVED_CHANGE_EVENT, S as SavedEntry, T as SavedProgress, _ as DailyStartResponse, a as isDailySystem, b as SavedCounts, c as DailyAll, d as DailyCompletionMeta, f as DailyDefinition, g as DailySaveInput, h as DailyHost, i as getDaily, j as SAVED_OPEN_PARAM, k as SAVED_KIND_PARAM, l as DailyChallenge, m as DailyGameStatus, n as DailyCompletions, o as DAILY_START_EVENT, p as DailyEventDetail, r as DAILY_SINGLETON_API, s as DailySystem, t as DailyCompletion, u as DailyCompleteResponse, v as DailyStatus, w as SavedListOptions, x as SavedDaily, y as GamePayload } from "./shared/daily.js";
1
2
  import { a as RaceRecordPlayer, c as RealtimeErrorShape, d as RoomSeat, f as RoomSeatChange, g as Snapshot, h as ServerEvents, i as RaceHistory, l as RoomChatLine, m as SchemaOutput, n as InviteLink, o as RaceResultPlayer, p as RoomStateChange, r as Notice, s as RaceStatusEvent, t as InviteCreated, u as RoomMessage } from "./shared/wire-types.js";
2
- import { _ as DailyStatus, a as isDailySystem, c as DailyAll, d as DailyCompletionMeta, f as DailyDefinition, g as DailyStartResponse, h as DailyHost, i as getDaily, l as DailyChallenge, m as DailyGameStatus, n as DailyCompletions, o as DAILY_START_EVENT, p as DailyEventDetail, r as DAILY_SINGLETON_API, s as DailySystem, t as DailyCompletion, u as DailyCompleteResponse } from "./shared/daily.js";
3
- import { $ as NavigableDef, A as PageInputControl, B as InputDef, C as INPUT_SINGLETON_API, D as parseInputOverrides, E as isInputSystem, F as DraggedSpot, G as InputSource, H as InputHost, I as EdgeOffsets, J as NavBlurEvent, K as MenuBridge, L as GamepadMapping, M as Anchor, N as AxisDef, O as InputSystem, P as AxisSide, Q as NavTarget, R as GroupDef, S as FOCUS_RING_SHADOW, T as getInput, U as InputOverrides, V as InputEvents, W as InputReading, X as NavElementKind, Y as NavElement, Z as NavFocusEvent, _ as boxesTouch, a as OverlayEdge, at as VirtualInputs, b as MODALITY_ATTRIBUTE, c as OverlayReason, d as LayoutOptions, et as Rect, f as layoutControls, g as LayoutItem, h as LayoutBox, i as AutoPauseOptions, it as VirtualDef, j as isPageInputControl, k as InputSystemOptions, l as UiStack, m as Insets, n as getUiStack, nt as Vector, o as OverlayEvent, ot as VirtualOverride, p as Overlay, q as MouseMapping, r as isUiStack, rt as VirtualControlType, s as OverlayListener, t as UI_STACK_VERSION, tt as TouchMapping, u as UiStackHandoff, v as controlSize, w as InputOptions, x as trackInputModality, y as InputModality, z as InputConfig } from "./shared/input.js";
3
+ import { $ as NavTarget, A as PageInputControl, B as InputConfig, C as INPUT_SINGLETON_API, D as parseInputOverrides, E as isInputSystem, F as AxisSide, G as InputReading, H as InputEvents, I as DraggedSpot, J as MouseMapping, K as InputSource, L as EdgeOffsets, M as AutoNavigateTarget, N as Anchor, O as InputSystem, P as AxisDef, Q as NavFocusEvent, R as GamepadMapping, S as FOCUS_RING_SHADOW, T as getInput, U as InputHost, V as InputDef, W as InputOverrides, X as NavElement, Y as NavBlurEvent, Z as NavElementKind, _ as boxesTouch, a as OverlayEdge, at as VirtualDef, b as MODALITY_ATTRIBUTE, c as OverlayReason, d as LayoutOptions, et as NavigableDef, f as layoutControls, g as LayoutItem, h as LayoutBox, i as AutoPauseOptions, it as VirtualControlType, j as isPageInputControl, k as InputSystemOptions, l as UiStack, m as Insets, n as getUiStack, nt as TouchMapping, o as OverlayEvent, ot as VirtualInputs, p as Overlay, q as MenuBridge, r as isUiStack, rt as Vector, s as OverlayListener, st as VirtualOverride, t as UI_STACK_VERSION, tt as Rect, u as UiStackHandoff, v as controlSize, w as InputOptions, x as trackInputModality, y as InputModality, z as GroupDef } from "./shared/input.js";
4
4
  import { a as InviteResult, i as InviteOptions, n as HubMpApi, o as JoinInfoEvent, r as InviteLinkMethods, t as BusyOptions } from "./shared/multiplayer-types.js";
5
5
  import { o as multiplayerForwarder } from "./shared/mp.js";
6
6
  import { a as RoomEvents, c as RoomSelf, d as RoomStateOptions, i as RoomCreateOptions, l as RoomSendOptions, n as HubRoomsApi, o as RoomListOptions, r as JoinOptions, s as RoomReclaimMethods, t as HubRoom, u as RoomState } from "./shared/room-types.js";
7
7
  import { a as RaceHistoryQuery, c as RaceRuntimeApi, i as RaceEvents, l as RaceStart, n as RaceCreateOptions, o as RaceHistoryViewOptions, r as RaceDefinition, s as RaceHudPlace, t as HubRaceApi } from "./shared/race-types.js";
8
8
  import { f as raceForwarder } from "./shared/race.js";
9
9
  import { n as roomsForwarder } from "./shared/rooms.js";
10
- import { $ as HubNotifyApi, A as RacerState, B as SuggestionStatus, C as RaceRecord, D as RaceStats, E as RaceState, F as ReportReason, G as REALTIME_READY_EVENT, H as isRealtimeApi, I as RoomInfo, J as RealtimeHubLink, K as REALTIME_SINGLETON_API, L as SocialConfig, M as Relation, N as ReportInput, O as Racer, P as ReportKind, Q as socialForwarder, R as SocialMe, S as RaceParams, T as RaceStatValue, U as REALTIME_FAILED_EVENT, V as findRealtimeApi, W as REALTIME_FEATURE_VERSION, X as notifyForwarder, Y as linkRealtimeToHub, Z as presenceForwarder, _ as PlayerLite, a as ErrorBody, at as SocialCounts, b as PresenceKind, c as JoinInfo, d as Message, et as HubPresenceApi, f as MessagesPage, g as PlayerCard, h as Party, i as Counts, it as PlayerRef, j as RecentPlayer, k as RacerResult, l as Launch, m as NotifyPrefs, n as ChatMode, nt as OpenInviteOptions, o as FriendEntry, ot as SocialEvents, p as NotifyChange, q as RealtimeApi, r as Conversation, rt as PlayOnlineMethods, s as Invite, t as Audience, tt as HubSocialApi, u as LaunchTicket, v as Presence, w as RaceResult, x as RaceOutcome, y as PresenceInput, z as Suggestion } from "./shared/social.js";
11
- import { $ as GameInfo, A as StatResult, B as OUTBOX_MAX_ENTRIES, C as GrantBundle, Ct as EndpointName, D as TradeNoteOptions, E as TradeListOptions, F as OfflineEventDetails, G as ProfilePatch, H as OfflineKindDefinition, I as OfflineEventName, J as QueuedScoreOptions, K as QueueOp, L as OfflineListener, M as SyncResult, N as OfflineApi, O as AuthResponse, P as OUTBOX_FULL_CODE, Q as GameAnalytics, R as OfflineOp, S as HubMenuControl, St as EndpointFields, T as TradeId, Tt as GamePayload, U as ReplayContext, V as OfflineHandler, W as CLIENT_VERSION_HEADER, X as Board, Y as BufferedEvent, Z as BoardWithTop, _ as ResumeEntry, _t as SortDir, a as HubErrorDetails, at as Inventory, b as ResumeRun, bt as SubmitScoreResult, c as UNSUPPORTED_BY_HUB, ct as LeaderboardEntry, d as hub, dt as Metrics, et as GameLeaderboards, f as ClientSupport, ft as Profile, g as ResumeBlocker, gt as SnapshotResponse, h as RESUME_MAX_STATE_BYTES, ht as SaveMeta, i as HubErrorCode, it as HubStatus, j as SyncConflict, k as ProfileUpdate, l as Hub, lt as LeaderboardResult, m as RESUME_DEBOUNCE_MS, mt as Save, n as ContentRejectedError, nt as GlobalAnalytics, o as OfflineError, ot as InventorySnapshot, p as HubResume, pt as ProfileSummary, q as QueueOpInput, r as HubError, rt as HubOptions, s as SAVE_UNKNOWN_CODE, st as Json, t as HUB_CLIENT_VERSION, tt as GameRecords, u as createHub, ut as MeResponse, v as ResumeLoadOptions, vt as Stats, w as TradeBundle, wt as EndpointReply, x as ResumeSaveInput, xt as User, y as ResumeProgress, yt as SubmitScoreOptions, z as OUTBOX_MAX_CHARS } from "./shared/index.js";
10
+ import { $ as RuntimeAvatarApi, A as RacerState, B as SuggestionStatus, C as RaceRecord, D as RaceStats, E as RaceState, F as ReportReason, G as REALTIME_READY_EVENT, H as isRealtimeApi, I as RoomInfo, J as SESSION_EVENT, K as REALTIME_SINGLETON_API, L as SocialConfig, M as Relation, N as ReportInput, O as Racer, P as ReportKind, Q as OpenDesignerOptions, R as SocialMe, S as RaceParams, T as RaceStatValue, U as REALTIME_FAILED_EVENT, V as findRealtimeApi, W as REALTIME_FEATURE_VERSION, X as AvatarRef, Y as AvatarChange, Z as DesignerResult, _ as PlayerLite, a as ErrorBody, at as HubNotifyApi, b as PresenceKind, c as JoinInfo, ct as OpenInviteOptions, d as Message, dt as SocialCounts, et as RealtimeHubLink, f as MessagesPage, ft as SocialEvents, g as PlayerCard, h as Party, i as Counts, it as socialForwarder, j as RecentPlayer, k as RacerResult, l as Launch, lt as PlayOnlineMethods, m as NotifyPrefs, n as ChatMode, nt as notifyForwarder, o as FriendEntry, ot as HubPresenceApi, p as NotifyChange, q as RealtimeApi, r as Conversation, rt as presenceForwarder, s as Invite, st as HubSocialApi, t as Audience, tt as linkRealtimeToHub, u as LaunchTicket, ut as PlayerRef, v as Presence, w as RaceResult, x as RaceOutcome, y as PresenceInput, z as Suggestion } from "./shared/social.js";
11
+ import { $ as OfflineApi, A as SavedChangeListener, At as MeResponse, B as ResumeRun, Bt as SubmitScoreResult, C as TURN_RESYNC_EVENT, Ct as HubOptions, D as TurnOutcome, Dt as Json, E as TurnMoveEvent, Et as InventorySnapshot, F as RESUME_MAX_STATE_BYTES, Ft as SaveMeta, G as TradeId, Gt as AvatarHost, H as HubMenuControl, Ht as EndpointFields, I as ResumeBlocker, It as SnapshotResponse, J as AuthResponse, Jt as CarriesLook, K as TradeListOptions, Kt as AvatarModule, L as ResumeEntry, Lt as SortDir, M as SavedOpenHandler, Mt as Profile, N as HubResume, Nt as ProfileSummary, O as HubSaved, Ot as LeaderboardEntry, P as RESUME_DEBOUNCE_MS, Pt as Save, Q as SyncResult, R as ResumeLoadOptions, Rt as Stats, S as TURN_POLL_MS, St as GlobalAnalytics, T as TurnGameEvents, Tt as Inventory, U as GrantBundle, Ut as EndpointName, V as ResumeSaveInput, Vt as User, W as TradeBundle, Wt as EndpointReply, X as StatResult, Y as ProfileUpdate, Z as SyncConflict, _ as HubTurns, _t as BoardWithTop, a as HUB_CLIENT_VERSION, at as OUTBOX_MAX_CHARS, b as TURN_CHAT_EVENT, bt as GameLeaderboards, c as HubErrorCode, ct as OfflineKindDefinition, d as SAVE_UNKNOWN_CODE, dt as ProfilePatch, et as OUTBOX_FULL_CODE, f as UNSUPPORTED_BY_HUB, ft as QueueOp, g as ClientSupport, gt as Board, h as hub, ht as BufferedEvent, i as TurnGameView, it as OfflineOp, j as SavedOpenDetail, jt as Metrics, k as SAVED_CHANGE_QUIET_MS, kt as LeaderboardResult, l as HubErrorDetails, lt as ReplayContext, m as createHub, mt as QueuedScoreOptions, n as TurnChatLine, nt as OfflineEventName, o as ContentRejectedError, ot as OUTBOX_MAX_ENTRIES, p as Hub, pt as QueueOpInput, q as TradeNoteOptions, qt as HubAvatar, r as TurnDeadline, rt as OfflineListener, s as HubError, st as OfflineHandler, t as OpenTurnGame, tt as OfflineEventDetails, u as OfflineError, ut as CLIENT_VERSION_HEADER, v as TURN_LINK_PARAM, vt as GameAnalytics, w as TurnGame, wt as HubStatus, x as TURN_EVENT, xt as GameRecords, y as TurnCreateOptions, yt as GameInfo, z as ResumeProgress, zt as SubmitScoreOptions } from "./shared/index.js";
12
12
  //#region src/auto.d.ts
13
13
  /** What `window.HubSDK` holds. */
14
14
  export interface HubSdkGlobal {
@@ -32,5 +32,5 @@ declare global {
32
32
  }
33
33
  }
34
34
  //#endregion
35
- export { type Anchor, type Audience, type AuthResponse, type AutoPauseOptions, type AxisDef, type AxisSide, type Board, type BoardWithTop, type BufferedEvent, type BusyOptions, CLIENT_VERSION_HEADER, type ChatMode, type ClientSupport, ContentRejectedError, type Conversation, type Counts, DAILY_SINGLETON_API, DAILY_START_EVENT, type DailyAll, type DailyChallenge, type DailyCompleteResponse, type DailyCompletion, type DailyCompletionMeta, type DailyCompletions, type DailyDefinition, type DailyEventDetail, type DailyGameStatus, type DailyHost, type DailyStartResponse, type DailyStatus, DailySystem, type DraggedSpot, type EdgeOffsets, type EndpointFields, type EndpointName, type EndpointReply, type ErrorBody, FOCUS_RING_SHADOW, type FriendEntry, type GameAnalytics, type GameInfo, type GameLeaderboards, type GamePayload, type GameRecords, type GamepadMapping, type GlobalAnalytics, type GrantBundle, type GroupDef, HUB_CLIENT_VERSION, Hub, HubError, type HubErrorCode, type HubErrorDetails, type HubMenuControl, type HubMpApi, type HubNotifyApi, type HubOptions, type HubPresenceApi, type HubRaceApi, HubResume, type HubRoom, type HubRoomsApi, type HubSocialApi, type HubStatus, INPUT_SINGLETON_API, type InputConfig, type InputDef, type InputEvents, type InputHost, type InputModality, type InputOptions, type InputOverrides, type InputReading, type InputSource, InputSystem, type InputSystemOptions, type Insets, type Inventory, type InventorySnapshot, type Invite, type InviteCreated, type InviteLink, type InviteLinkMethods, type InviteOptions, type InviteResult, type JoinInfo, type JoinInfoEvent, type JoinOptions, type Json, type Launch, type LaunchTicket, type LayoutBox, type LayoutItem, type LayoutOptions, type LeaderboardEntry, type LeaderboardResult, MODALITY_ATTRIBUTE, type MeResponse, type MenuBridge, type Message, type MessagesPage, type Metrics, type MouseMapping, type NavBlurEvent, type NavElement, type NavElementKind, type NavFocusEvent, type NavTarget, type NavigableDef, type Notice, type NotifyChange, type NotifyPrefs, OUTBOX_FULL_CODE, OUTBOX_MAX_CHARS, OUTBOX_MAX_ENTRIES, OfflineApi, OfflineError, type OfflineEventDetails, type OfflineEventName, type OfflineHandler, type OfflineKindDefinition, type OfflineListener, type OfflineOp, type OpenInviteOptions, Overlay, type OverlayEdge, type OverlayEvent, type OverlayListener, type OverlayReason, type PageInputControl, type Party, type PlayOnlineMethods, type PlayerCard, type PlayerLite, type PlayerRef, type Presence, type PresenceInput, type PresenceKind, type Profile, type ProfilePatch, type ProfileSummary, type ProfileUpdate, type QueueOp, type QueueOpInput, type QueuedScoreOptions, type REALTIME_FAILED_EVENT, type REALTIME_FEATURE_VERSION, type REALTIME_READY_EVENT, type REALTIME_SINGLETON_API, RESUME_DEBOUNCE_MS, RESUME_MAX_STATE_BYTES, type RaceCreateOptions, type RaceDefinition, type RaceEvents, type RaceHistory, type RaceHistoryQuery, type RaceHistoryViewOptions, type RaceHudPlace, type RaceOutcome, type RaceParams, type RaceRecord, type RaceRecordPlayer, type RaceResult, type RaceResultPlayer, type RaceRuntimeApi, type RaceStart, type RaceStatValue, type RaceState, type RaceStats, type RaceStatusEvent, type Racer, type RacerResult, type RacerState, type RealtimeApi, type RealtimeErrorShape, type RealtimeHubLink, type RecentPlayer, type Rect, type Relation, type ReplayContext, type ReportInput, type ReportKind, type ReportReason, type ResumeBlocker, type ResumeEntry, type ResumeLoadOptions, type ResumeProgress, type ResumeRun, type ResumeSaveInput, type RoomChatLine, type RoomCreateOptions, type RoomEvents, type RoomInfo, type RoomListOptions, type RoomMessage, type RoomReclaimMethods, type RoomSeat, type RoomSeatChange, type RoomSelf, type RoomSendOptions, type RoomState, type RoomStateChange, type RoomStateOptions, SAVE_UNKNOWN_CODE, type Save, type SaveMeta, type SchemaOutput, type ServerEvents, type Snapshot, type SnapshotResponse, type SocialConfig, type SocialCounts, type SocialEvents, type SocialMe, type SortDir, type StatResult, type Stats, type SubmitScoreOptions, type SubmitScoreResult, type Suggestion, type SuggestionStatus, type SyncConflict, type SyncResult, type TouchMapping, type TradeBundle, type TradeId, type TradeListOptions, type TradeNoteOptions, UI_STACK_VERSION, UNSUPPORTED_BY_HUB, type UiStack, type UiStackHandoff, type User, type Vector, type VirtualControlType, type VirtualDef, type VirtualInputs, type VirtualOverride, boxesTouch, controlSize, createHub, type findRealtimeApi, getDaily, getInput, getUiStack, hub, isDailySystem, isInputSystem, isPageInputControl, type isRealtimeApi, isUiStack, layoutControls, type linkRealtimeToHub, type multiplayerForwarder as mp, type notifyForwarder as notify, parseInputOverrides, type presenceForwarder as presence, type raceForwarder as race, type roomsForwarder as rooms, type socialForwarder as social, trackInputModality };
35
+ export { type Anchor, type Audience, type AuthResponse, type AutoNavigateTarget, type AutoPauseOptions, type AvatarChange, type AvatarHost, type AvatarModule, type AvatarRef, type AxisDef, type AxisSide, type Board, type BoardWithTop, type BufferedEvent, type BusyOptions, CLIENT_VERSION_HEADER, type CarriesLook, type ChatMode, type ClientSupport, ContentRejectedError, type Conversation, type Counts, DAILY_SINGLETON_API, DAILY_START_EVENT, type DailyAll, type DailyChallenge, type DailyCompleteResponse, type DailyCompletion, type DailyCompletionMeta, type DailyCompletions, type DailyDefinition, type DailyEventDetail, type DailyGameStatus, type DailyHost, type DailySaveInput, type DailyStartResponse, type DailyStatus, DailySystem, type DesignerResult, type DraggedSpot, type EdgeOffsets, type EndpointFields, type EndpointName, type EndpointReply, type ErrorBody, FOCUS_RING_SHADOW, type FriendEntry, type GameAnalytics, type GameInfo, type GameLeaderboards, type GamePayload, type GameRecords, type GamepadMapping, type GlobalAnalytics, type GrantBundle, type GroupDef, HUB_CLIENT_VERSION, Hub, HubAvatar, HubError, type HubErrorCode, type HubErrorDetails, type HubMenuControl, type HubMpApi, type HubNotifyApi, type HubOptions, type HubPresenceApi, type HubRaceApi, HubResume, type HubRoom, type HubRoomsApi, HubSaved, type HubSocialApi, type HubStatus, HubTurns, INPUT_SINGLETON_API, type InputConfig, type InputDef, type InputEvents, type InputHost, type InputModality, type InputOptions, type InputOverrides, type InputReading, type InputSource, InputSystem, type InputSystemOptions, type Insets, type Inventory, type InventorySnapshot, type Invite, type InviteCreated, type InviteLink, type InviteLinkMethods, type InviteOptions, type InviteResult, type JoinInfo, type JoinInfoEvent, type JoinOptions, type Json, type Launch, type LaunchTicket, type LayoutBox, type LayoutItem, type LayoutOptions, type LeaderboardEntry, type LeaderboardResult, MODALITY_ATTRIBUTE, type MeResponse, type MenuBridge, type Message, type MessagesPage, type Metrics, type MouseMapping, type NavBlurEvent, type NavElement, type NavElementKind, type NavFocusEvent, type NavTarget, type NavigableDef, type Notice, type NotifyChange, type NotifyPrefs, OUTBOX_FULL_CODE, OUTBOX_MAX_CHARS, OUTBOX_MAX_ENTRIES, OfflineApi, OfflineError, type OfflineEventDetails, type OfflineEventName, type OfflineHandler, type OfflineKindDefinition, type OfflineListener, type OfflineOp, type OpenDesignerOptions, type OpenInviteOptions, type OpenTurnGame, Overlay, type OverlayEdge, type OverlayEvent, type OverlayListener, type OverlayReason, type PageInputControl, type Party, type PlayOnlineMethods, type PlayerCard, type PlayerLite, type PlayerRef, type Presence, type PresenceInput, type PresenceKind, type Profile, type ProfilePatch, type ProfileSummary, type ProfileUpdate, type QueueOp, type QueueOpInput, type QueuedScoreOptions, type REALTIME_FAILED_EVENT, type REALTIME_FEATURE_VERSION, type REALTIME_READY_EVENT, type REALTIME_SINGLETON_API, RESUME_DEBOUNCE_MS, RESUME_MAX_STATE_BYTES, type RaceCreateOptions, type RaceDefinition, type RaceEvents, type RaceHistory, type RaceHistoryQuery, type RaceHistoryViewOptions, type RaceHudPlace, type RaceOutcome, type RaceParams, type RaceRecord, type RaceRecordPlayer, type RaceResult, type RaceResultPlayer, type RaceRuntimeApi, type RaceStart, type RaceStatValue, type RaceState, type RaceStats, type RaceStatusEvent, type Racer, type RacerResult, type RacerState, type RealtimeApi, type RealtimeErrorShape, type RealtimeHubLink, type RecentPlayer, type Rect, type Relation, type ReplayContext, type ReportInput, type ReportKind, type ReportReason, type ResumeBlocker, type ResumeEntry, type ResumeLoadOptions, type ResumeProgress, type ResumeRun, type ResumeSaveInput, type RoomChatLine, type RoomCreateOptions, type RoomEvents, type RoomInfo, type RoomListOptions, type RoomMessage, type RoomReclaimMethods, type RoomSeat, type RoomSeatChange, type RoomSelf, type RoomSendOptions, type RoomState, type RoomStateChange, type RoomStateOptions, type RuntimeAvatarApi, SAVED_CHANGE_EVENT, SAVED_CHANGE_QUIET_MS, SAVED_KIND_PARAM, SAVED_OPEN_EVENT, SAVED_OPEN_PARAM, SAVE_UNKNOWN_CODE, type SESSION_EVENT, type Save, type SaveMeta, type SavedChangeListener, type SavedCounts, type SavedDaily, type SavedEntry, type SavedKind, type SavedListOptions, type SavedOpenDetail, type SavedOpenHandler, type SavedOpened, type SavedProgress, type SavedStatus, type SchemaOutput, type ServerEvents, type Snapshot, type SnapshotResponse, type SocialConfig, type SocialCounts, type SocialEvents, type SocialMe, type SortDir, type StatResult, type Stats, type SubmitScoreOptions, type SubmitScoreResult, type Suggestion, type SuggestionStatus, type SyncConflict, type SyncResult, TURN_CHAT_EVENT, TURN_EVENT, TURN_LINK_PARAM, TURN_POLL_MS, TURN_RESYNC_EVENT, type TouchMapping, type TradeBundle, type TradeId, type TradeListOptions, type TradeNoteOptions, type TurnChatLine, type TurnCreateOptions, type TurnDeadline, TurnGame, type TurnGameEvents, type TurnGameView, type TurnMoveEvent, type TurnOutcome, type TurnSummary, UI_STACK_VERSION, UNSUPPORTED_BY_HUB, type UiStack, type UiStackHandoff, type User, type Vector, type VirtualControlType, type VirtualDef, type VirtualInputs, type VirtualOverride, boxesTouch, controlSize, createHub, type findRealtimeApi, getDaily, getInput, getUiStack, hub, isDailySystem, isInputSystem, isPageInputControl, type isRealtimeApi, isUiStack, layoutControls, type linkRealtimeToHub, type multiplayerForwarder as mp, type notifyForwarder as notify, parseInputOverrides, type presenceForwarder as presence, type raceForwarder as race, type roomsForwarder as rooms, savedGameUrl, type socialForwarder as social, trackInputModality };
36
36
  //# sourceMappingURL=auto.d.ts.map
package/dist/auto.js CHANGED
@@ -2,7 +2,7 @@ import { a as DailySystem, i as DAILY_START_EVENT, n as getDaily, r as isDailySy
2
2
  import { t as HUB_CLIENT_VERSION } from "./shared/client-version.gen.js";
3
3
  import { a as isPageInputControl, c as layoutControls, d as MODALITY_ATTRIBUTE, f as trackInputModality, i as parseInputOverrides, l as boxesTouch, n as getInput, o as InputSystem, p as FOCUS_RING_SHADOW, r as isInputSystem, s as Overlay, t as INPUT_SINGLETON_API, u as controlSize } from "./shared/input.js";
4
4
  import { n as isUiStack, r as UI_STACK_VERSION, t as getUiStack } from "./shared/page-stack.js";
5
- import { a as RESUME_DEBOUNCE_MS, c as OUTBOX_FULL_CODE, d as OfflineApi, f as ContentRejectedError, g as UNSUPPORTED_BY_HUB, h as SAVE_UNKNOWN_CODE, i as HubResume, l as OUTBOX_MAX_CHARS, m as OfflineError, n as createHub, o as RESUME_MAX_STATE_BYTES, p as HubError, r as hub, s as CLIENT_VERSION_HEADER, t as Hub, u as OUTBOX_MAX_ENTRIES } from "./shared/src.js";
5
+ import { A as UNSUPPORTED_BY_HUB, C as OUTBOX_MAX_CHARS, D as HubError, E as ContentRejectedError, O as OfflineError, S as OUTBOX_FULL_CODE, T as OfflineApi, _ as savedGameUrl, a as TURN_LINK_PARAM, b as RESUME_MAX_STATE_BYTES, c as TURN_POLL_MS, d as HubSaved, f as SAVED_CHANGE_QUIET_MS, g as SAVED_OPEN_PARAM, h as SAVED_OPEN_EVENT, i as HubTurns, j as HubAvatar, k as SAVE_UNKNOWN_CODE, l as TURN_RESYNC_EVENT, m as SAVED_KIND_PARAM, n as createHub, o as TURN_CHAT_EVENT, p as SAVED_CHANGE_EVENT, r as hub, s as TURN_EVENT, t as Hub, u as TurnGame, v as HubResume, w as OUTBOX_MAX_ENTRIES, x as CLIENT_VERSION_HEADER, y as RESUME_DEBOUNCE_MS } from "./shared/src.js";
6
6
  //#region src/auto.ts
7
7
  /**
8
8
  * `@diffenderfer-games/hub/auto`: everything the main entry exports, plus a
@@ -22,6 +22,6 @@ if (typeof window !== "undefined") window.HubSDK = {
22
22
  ContentRejectedError
23
23
  };
24
24
  //#endregion
25
- export { CLIENT_VERSION_HEADER, ContentRejectedError, DAILY_SINGLETON_API, DAILY_START_EVENT, DailySystem, FOCUS_RING_SHADOW, HUB_CLIENT_VERSION, Hub, HubError, HubResume, INPUT_SINGLETON_API, InputSystem, MODALITY_ATTRIBUTE, OUTBOX_FULL_CODE, OUTBOX_MAX_CHARS, OUTBOX_MAX_ENTRIES, OfflineApi, OfflineError, Overlay, RESUME_DEBOUNCE_MS, RESUME_MAX_STATE_BYTES, SAVE_UNKNOWN_CODE, UI_STACK_VERSION, UNSUPPORTED_BY_HUB, boxesTouch, controlSize, createHub, getDaily, getInput, getUiStack, hub, isDailySystem, isInputSystem, isPageInputControl, isUiStack, layoutControls, parseInputOverrides, trackInputModality };
25
+ export { CLIENT_VERSION_HEADER, ContentRejectedError, DAILY_SINGLETON_API, DAILY_START_EVENT, DailySystem, FOCUS_RING_SHADOW, HUB_CLIENT_VERSION, Hub, HubAvatar, HubError, HubResume, HubSaved, HubTurns, INPUT_SINGLETON_API, InputSystem, MODALITY_ATTRIBUTE, OUTBOX_FULL_CODE, OUTBOX_MAX_CHARS, OUTBOX_MAX_ENTRIES, OfflineApi, OfflineError, Overlay, RESUME_DEBOUNCE_MS, RESUME_MAX_STATE_BYTES, SAVED_CHANGE_EVENT, SAVED_CHANGE_QUIET_MS, SAVED_KIND_PARAM, SAVED_OPEN_EVENT, SAVED_OPEN_PARAM, SAVE_UNKNOWN_CODE, TURN_CHAT_EVENT, TURN_EVENT, TURN_LINK_PARAM, TURN_POLL_MS, TURN_RESYNC_EVENT, TurnGame, UI_STACK_VERSION, UNSUPPORTED_BY_HUB, boxesTouch, controlSize, createHub, getDaily, getInput, getUiStack, hub, isDailySystem, isInputSystem, isPageInputControl, isUiStack, layoutControls, parseInputOverrides, savedGameUrl, trackInputModality };
26
26
 
27
27
  //# sourceMappingURL=auto.js.map
@@ -0,0 +1,147 @@
1
+ import { c as Pose, l as RenderOptions, n as BodyPose, o as LookLike, r as Facing, u as StatusProp } from "./shared/types.js";
2
+ import { r as AvatarAtlas, s as ReactionGlyph } from "./shared/atlas.js";
3
+ import { t as Animator } from "./shared/animator.js";
4
+ //#region src/avatar/adapters/pixi-types.d.ts
5
+ /**
6
+ * The slice of PixiJS the adapters use, typed structurally so the hub has no
7
+ * dependency on pixi. Pixi 8 is the target; Pixi 7 works through the same
8
+ * calls where they exist (`Texture.from(canvas)`, `texture.update()`).
9
+ */
10
+ /** A canvas-like source Pixi can upload. */
11
+ type PixiSource = HTMLCanvasElement | OffscreenCanvas;
12
+ /** A texture's uploadable source (Pixi 8). */
13
+ interface PixiTextureSource {
14
+ update(): void;
15
+ }
16
+ /** A texture (Pixi 8: `source.update()`; Pixi 7: `update()`). */
17
+ interface PixiTexture {
18
+ readonly source?: PixiTextureSource;
19
+ update?(): void;
20
+ destroy(destroySource?: boolean): void;
21
+ }
22
+ /** A display object's shared fields. */
23
+ interface PixiDisplay {
24
+ x: number;
25
+ y: number;
26
+ visible: boolean;
27
+ alpha: number;
28
+ zIndex: number;
29
+ readonly scale: {
30
+ x: number;
31
+ y: number;
32
+ set(x: number, y?: number): void;
33
+ };
34
+ destroy(options?: {
35
+ children?: boolean;
36
+ }): void;
37
+ }
38
+ /** A sprite showing a `TTexture`. */
39
+ interface PixiSprite<TTexture extends PixiTexture = PixiTexture> extends PixiDisplay {
40
+ texture: TTexture;
41
+ readonly anchor: {
42
+ set(x: number, y?: number): void;
43
+ };
44
+ }
45
+ /** A container that takes `TChild` sprites. */
46
+ interface PixiContainer<TChild extends PixiDisplay = PixiSprite> extends PixiDisplay {
47
+ sortableChildren: boolean;
48
+ addChild(child: TChild): void;
49
+ removeChild(child: TChild): void;
50
+ }
51
+ /** A frame rectangle. */
52
+ interface PixiRectangle {
53
+ readonly x: number;
54
+ readonly y: number;
55
+ readonly width: number;
56
+ readonly height: number;
57
+ }
58
+ /**
59
+ * The PIXI namespace, as passed in by the game (`import * as PIXI from
60
+ * 'pixi.js'`, or an object of the named imports). It is generic over the
61
+ * game's own classes, inferred from what is passed, so the sprites and
62
+ * textures that come back are pixi's own types and go straight into a
63
+ * `Container` with no cast.
64
+ */
65
+ interface PixiNs<TTexture extends PixiTexture = PixiTexture, TSprite extends PixiSprite<TTexture> = PixiSprite<TTexture>, TRectangle extends PixiRectangle = PixiRectangle> {
66
+ readonly Texture: {
67
+ from(source: PixiSource): TTexture;
68
+ new (options: {
69
+ source: NonNullable<TTexture['source']>;
70
+ frame: TRectangle;
71
+ }): TTexture;
72
+ };
73
+ readonly Sprite: new (texture?: TTexture) => TSprite;
74
+ /** Not used by the adapters; accepted so an object of the named imports can include it. */
75
+ readonly Container?: new () => PixiDisplay;
76
+ readonly Rectangle: new (x: number, y: number, width: number, height: number) => TRectangle;
77
+ }
78
+ //#endregion
79
+ //#region src/avatar/adapters/pixi-avatar.d.ts
80
+ /** Options for {@link pixiAvatar}. */
81
+ interface PixiAvatarOptions extends RenderOptions {
82
+ /** Drives the face each `update(t)`; without one the avatar is still. */
83
+ readonly animator?: Animator;
84
+ /** Texture pixels per CSS pixel (default 2). */
85
+ readonly resolution?: number;
86
+ }
87
+ /** A live Pixi avatar; `view` is the game's own pixi `Sprite`. */
88
+ interface PixiAvatar<TSprite extends PixiSprite = PixiSprite> {
89
+ /** The sprite to add to the stage (anchored at its centre). */
90
+ readonly view: TSprite;
91
+ /** Renders the animator's pose at `t` (or a given pose). */
92
+ update(t: number | Pose): void;
93
+ /** Swaps the look. */
94
+ setLook(like: LookLike): void;
95
+ destroy(): void;
96
+ }
97
+ /** A live avatar sprite: `pixiAvatar(pixi, seat.look, { size: 64, animator })`. */
98
+ export declare function pixiAvatar<TTexture extends PixiTexture, TSprite extends PixiSprite<TTexture>, TRectangle extends PixiRectangle>(pixi: PixiNs<TTexture, TSprite, TRectangle>, like: LookLike, opts?: PixiAvatarOptions): PixiAvatar<TSprite>;
99
+ /** A still avatar texture (Pixi 7 games use this from a bitmap-like canvas). */
100
+ export declare function avatarTexture<TTexture extends PixiTexture, TSprite extends PixiSprite<TTexture>, TRectangle extends PixiRectangle>(pixi: PixiNs<TTexture, TSprite, TRectangle>, like: LookLike, opts?: RenderOptions): TTexture;
101
+ //#endregion
102
+ //#region src/avatar/adapters/pixi-crowd.d.ts
103
+ /** One avatar's state in the crowd (the world's own protocol fills it). */
104
+ interface CrowdMember {
105
+ readonly look: LookLike;
106
+ readonly x: number;
107
+ readonly y: number;
108
+ readonly facing?: Facing;
109
+ readonly body?: BodyPose;
110
+ readonly status?: StatusProp | null;
111
+ /** The username for the name tag (omit for no tag). */
112
+ readonly name?: string;
113
+ readonly friend?: boolean;
114
+ readonly you?: boolean;
115
+ /** "Playing Uno": the game's catalog title. */
116
+ readonly activity?: string;
117
+ /** A quick-chat emote to pop (shown for 2.5 s from when it's set). */
118
+ readonly emote?: string;
119
+ readonly reaction?: ReactionGlyph;
120
+ /** Ask for live vector rendering (granted to at most `liveMax`). */
121
+ readonly live?: boolean;
122
+ /** Hide the tag (the world fades tags by distance and hides them when crowded). */
123
+ readonly tagHidden?: boolean;
124
+ }
125
+ /** Crowd options; `container` is the game's own pixi `Container`. */
126
+ interface CrowdOptions<TSprite extends PixiSprite = PixiSprite> {
127
+ readonly atlas: AvatarAtlas;
128
+ /** The container avatars go into (it is made y-sortable). */
129
+ readonly container: PixiContainer<TSprite>;
130
+ /** Live vector avatars at most (default 6; 2 on low-end devices). */
131
+ readonly liveMax?: number;
132
+ /** Atlas baking budget per update, ms (default 4). */
133
+ readonly bakeMs?: number;
134
+ }
135
+ /** The crowd. */
136
+ interface AvatarCrowd {
137
+ set(id: string | number, member: CrowdMember): void;
138
+ remove(id: string | number): void;
139
+ /** Advances animation to `t` (ms), bakes, and lays everyone out. Call once per frame. */
140
+ update(t: number): void;
141
+ destroy(): void;
142
+ }
143
+ /** A crowd over an atlas: `createCrowd(pixi, { atlas, container })`. */
144
+ export declare function createCrowd<TTexture extends PixiTexture, TSprite extends PixiSprite<TTexture>, TRectangle extends PixiRectangle>(pixi: PixiNs<TTexture, TSprite, TRectangle>, opts: CrowdOptions<NoInfer<TSprite>>): AvatarCrowd;
145
+ //#endregion
146
+ export type { AvatarCrowd, CrowdMember, CrowdOptions, PixiAvatar, PixiAvatarOptions, PixiContainer, PixiNs, PixiSprite, PixiTexture };
147
+ //# sourceMappingURL=avatar-pixi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avatar-pixi.d.ts","names":[],"sources":["../src/avatar/adapters/pixi-types.ts","../src/avatar/adapters/pixi-avatar.ts","../src/avatar/adapters/pixi-crowd.ts"],"mappings":";;;;;;;;;;KAOY,aAAa,oBAAoB;;UAG5B;EACf;;;UAIe;WACN,SAAS;EAClB;EACA,QAAQ;;;UAIO;EACf;EACA;EACA;EACA;EACA;WACS;IAAS;IAAW;IAAW,IAAI,WAAW;;EACvD,QAAQ;IAAY;;;;UAIL,WAAW,iBAAiB,cAAc,qBAAqB;EAC9E,SAAS;WACA;IAAU,IAAI,WAAW;;;;UAInB,cAAc,eAAe,cAAc,oBAAoB;EAC9E;EACA,SAAS,OAAO;EAChB,YAAY,OAAO;;;UAIJ;WACN;WACA;WACA;WACA;;;;;;;;;UAUM,OACf,iBAAiB,cAAc,aAC/B,gBAAgB,WAAW,YAAY,WAAW,WAClD,mBAAmB,gBAAgB;WAE1B;IACP,KAAK,QAAQ,aAAa;SACrB;MAAW,QAAQ,YAAY;MAAqB,OAAO;QAAe;;WAExE,aAAa,UAAU,aAAa;;WAEpC,sBAAsB;WACtB,gBAAgB,WAAW,WAAW,eAAe,mBAAmB;;;;;UC5DlE,0BAA0B;;WAEhC,WAAW;;WAEX;;;UAIM,WAAW,gBAAgB,aAAa;;WAE9C,MAAM;;EAEf,OAAO,YAAY;;EAEnB,QAAQ,MAAM;EACd;;;wBAIc,WAAW,iBAAiB,aAAa,gBAAgB,WAAW,WAAW,mBAAmB,eAChH,MAAM,OAAO,UAAU,SAAS,aAChC,MAAM,UACN,OAAM,oBACL,WAAW;;wBA+BE,cAAc,iBAAiB,aAAa,gBAAgB,WAAW,WAAW,mBAAmB,eACnH,MAAM,OAAO,UAAU,SAAS,aAChC,MAAM,UACN,OAAM,gBACL;;;;UChDc;WACN,MAAM;WACN;WACA;WACA,SAAS;WACT,OAAO;WACP,SAAS;;WAET;WACA;WACA;;WAEA;;WAEA;WACA,WAAW;;WAEX;;WAEA;;;UAIM,aAAa,gBAAgB,aAAa;WAChD,OAAO;;WAEP,WAAW,cAAc;;WAEzB;;WAEA;;;UAIM;EACf,IAAI,qBAAqB,QAAQ;EACjC,OAAO;;EAEP,OAAO;EACP;;;wBAwBc,YAAY,iBAAiB,aAAa,gBAAgB,WAAW,WAAW,mBAAmB,eACjH,MAAM,OAAO,UAAU,SAAS,aAChC,MAAM,aAAa,QAAQ,YAC1B"}