@hopple/sdk 0.1.0-rc.1 → 0.1.0-rc.3

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
@@ -42,23 +42,25 @@ Both are named in the project's hopple config (`hopple.config.ts`, `.js` or
42
42
  like. `npx hopple create my-game` sets up the recommended way (Vite, with the
43
43
  config in TypeScript); see [`hopple create`](https://docs.hopple.app/cli.md#hopple-create).
44
44
 
45
- The host loads the page into a frame sandboxed with only `allow-scripts` and
46
- `allow-pointer-lock`. That has some consequences you need to plan for:
47
-
48
- - **One file to publish.** `hopple publish` uploads only the page, so
49
- everything the game needs (scripts, styles, images, sounds) must be inside
50
- it, and it refuses a page that loads anything from beside itself. During
51
- development `hopple dev` also serves the other files in the page's
52
- directory, but a published game can't rely on them.
53
- - **No network.** A game can't fetch, open a socket or load anything from a
54
- URL, on any host. It may load only from its own page and from `data:` and
55
- `blob:` URLs. Anything the game could send out could carry what it knows
56
- about the player. During development `hopple dev` lets the game load the
57
- files beside its page, and nothing else.
58
- - **Inline your scripts.** Inline scripts run, classic or module, and a
59
- published game's scripts are inline anyway.
60
- - **No `localStorage`, cookies or IndexedDB.** They are unavailable on an
61
- opaque origin. Use [`sdk.save`](#save) instead.
45
+ The host loads the page into a frame sandboxed with only `allow-scripts`,
46
+ `allow-same-origin` and `allow-pointer-lock`, every version on an origin of
47
+ its own. That has some consequences you need to plan for:
48
+
49
+ - **Its output directory is published.** `hopple publish` uploads the
50
+ directory the page is in, with the page as its `index.html`, and it refuses
51
+ a page that loads a file the directory doesn't hold. Refer to files
52
+ relatively. A page beside its config is published alone.
53
+ - **No network.** A game can't fetch, open a socket or load anything from
54
+ another host. It may load its own files, and `data:` and `blob:` URLs.
55
+ Anything the game could send out could carry what it knows about the
56
+ player.
57
+ - **No `localStorage`, `sessionStorage`, IndexedDB, Cache Storage or
58
+ cookies.** Whatever a game stored would be cleared every time its page
59
+ loads, so the runtime makes each of them throw an error naming
60
+ `Hopple.save`, and `hopple check` refuses a game that uses them. Use
61
+ [`sdk.save`](#save) instead.
62
+ - **Every address relative, no `<base>`, and UTF-8 pages.** `hopple check`
63
+ refuses the rest.
62
64
  - **No `alert`, `confirm` or `prompt`.** They are blocked in the sandbox.
63
65
  - **Sound may need a tap inside the game first.** Browsers only allow audio
64
66
  after a user gesture in the frame. Sound routed through
@@ -67,15 +69,35 @@ The host loads the page into a frame sandboxed with only `allow-scripts` and
67
69
 
68
70
  ## Getting started
69
71
 
70
- The SDK becomes part of your page; nothing loads it at runtime.
72
+ The SDK is not part of your game. It is **the runtime**, which whatever runs
73
+ the game serves beside it, and your page loads as its first script:
74
+
75
+ ```html
76
+ <script src="_rt/1/hopple.js"></script>
77
+ ```
78
+
79
+ The runtime defines the global `Hopple`, holding everything this guide
80
+ describes. Because it is served rather than built into the game, a fix to the
81
+ SDK (input, on-screen controls, audio, layout, the loop, save) reaches every
82
+ game without a rebuild. `_rt/1/` is the newest release of major 1; a change
83
+ that would break games is a new major, which a game takes by changing its
84
+ tag. Keep the address relative, as above: Hopple serves a game at the root of
85
+ its own origin, and a host like itch.io under a path, with `_rt/` beside
86
+ `index.html` either way.
71
87
 
72
88
  - **With a bundler** (Vite, esbuild, webpack, Rollup, Parcel, Bun):
73
- `npm install @hopple/sdk` and import it. Types come with it, and so does
74
- every doc comment, in `node_modules/@hopple/sdk/index.d.ts`.
75
- - **Without one:** paste `node_modules/@hopple/sdk/hopple-sdk.min.js` into a
76
- classic `<script>` before your own, and use the global `Hopple`
77
- (`await Hopple.init(…)` in a module script or an async function). Its first
78
- line says which SDK version it is, for your manifest's `sdk`.
89
+ `npm install @hopple/sdk` and import it. The package is the SDK's types,
90
+ with every doc comment, in `node_modules/@hopple/sdk/index.d.ts`, and a
91
+ stub of a few lines that forwards each import to `Hopple`: your bundle
92
+ carries the stub, never the SDK. Set your bundler to write relative
93
+ addresses (Vite: `base: './'`).
94
+ - **Without one:** use the global `Hopple` directly
95
+ (`const sdk = await Hopple.init()` in a module script or an async function).
96
+
97
+ `hopple check`, `hopple publish` and the server refuse a page that doesn't
98
+ load the runtime first, or that carries a copy of the SDK. Games published
99
+ before the runtime keep the SDK they bundled, and get no runtime fixes until
100
+ they are rebuilt this way.
79
101
 
80
102
  A `hopple.config.json` can point its `"$schema"` at
81
103
  `./node_modules/@hopple/sdk/config.schema.json` for an editor to check it; a
@@ -719,12 +741,15 @@ sdk.pause.on(async (paused) => { // the host asked; return a promise to make i
719
741
  - [ ] Print button labels from `sdk.input.mapping`, and read input once per frame.
720
742
  - [ ] Route every sound through `sdk.audio.output` or `media`, or multiply it by `sdk.audio.volume(channel)`, and obey mute.
721
743
  - [ ] Keep `sdk.pause` up to date, separately from the loop.
722
- - [ ] Publish a single self-contained HTML file.
744
+ - [ ] Load the runtime as the page's first script, `<script src="_rt/1/hopple.js"></script>`, and import `@hopple/sdk` rather than bundling a copy.
745
+ - [ ] Refer to every file relatively, and publish the output directory.
723
746
 
724
747
  ## License
725
748
 
726
- MIT; see `LICENSE`. The SDK is built into every game, so a game carries its
727
- one-line notice, `/*! @hopple/sdk | Copyright (c) 2026 The Hopple authors | MIT License */`.
749
+ MIT; see `LICENSE`. A game carries the stub, which carries its one-line
750
+ notice, `/*! @hopple/sdk <version> | Copyright (c) 2026 The Hopple authors | MIT License */`.
728
751
  Bundlers keep comments that start with `/*!` unless they minify them away:
729
752
  with Vite, set `build.rolldownOptions.output.comments.legal` to `true`, as a
730
- `hopple create` project does. The license covers the code, not the Hopple name or logo.
753
+ `hopple create` project does. The runtime, which is the SDK itself, is MIT
754
+ too, and is served beside the game rather than carried in it. The license
755
+ covers the code, not the Hopple name or logo.
@@ -55,6 +55,14 @@
55
55
  "maxLength": 64,
56
56
  "errorMessage": "must be lowercase letters, digits and hyphens"
57
57
  },
58
+ "owner": {
59
+ "type": "string",
60
+ "description": "The handle of the account the game is published under: the first half of `owner/id`. Absent, it is whoever publishes it. Present, only that account and the game's collaborators may publish it.",
61
+ "markdownDescription": "The handle of the account the game is published under: the first half of\n`owner/id`. Absent, it is whoever publishes it. Present, only that account\nand the game's collaborators may publish it.",
62
+ "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
63
+ "maxLength": 64,
64
+ "errorMessage": "must be a handle: lowercase letters, digits and hyphens"
65
+ },
58
66
  "version": {
59
67
  "type": "string",
60
68
  "description": "The game's own version, `MAJOR.MINOR.PATCH`. Ours to read, never to parse for meaning.",
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/achievement.d.ts
1
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/achievement.d.ts
2
2
  /**
3
3
  * The largest value progress will carry.
4
4
  *
@@ -28,7 +28,7 @@ type AchievementResult = {
28
28
  progress?: number;
29
29
  };
30
30
  //#endregion
31
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/analytics.d.ts
31
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/analytics.d.ts
32
32
  /**
33
33
  * What a game says happened.
34
34
  *
@@ -59,7 +59,7 @@ type AnalyticsValue = string | number | boolean;
59
59
  /** @group Analytics */
60
60
  type AnalyticsProps = Record<string, AnalyticsValue>;
61
61
  //#endregion
62
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/audio.d.ts
62
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/audio.d.ts
63
63
  /**
64
64
  * How loud the game is allowed to be, which is the host's to decide and the
65
65
  * game's to obey.
@@ -164,7 +164,7 @@ declare const AUDIO_FULL: AudioState;
164
164
  */
165
165
  declare function audioVolumeOf(state: AudioState, channel?: string): number;
166
166
  //#endregion
167
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/errors.d.ts
167
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/errors.d.ts
168
168
  /**
169
169
  * How a call fails.
170
170
  *
@@ -234,7 +234,7 @@ declare class BridgeError extends Error {
234
234
  constructor(error: ProtocolError);
235
235
  }
236
236
  //#endregion
237
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/envelope.d.ts
237
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/envelope.d.ts
238
238
  /**
239
239
  * `p` is the protocol version, carried on every message rather than only at the
240
240
  * handshake, because a message that arrives without context still has to be
@@ -275,7 +275,7 @@ type Envelope = {
275
275
  data: unknown;
276
276
  };
277
277
  //#endregion
278
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/input.d.ts
278
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/input.d.ts
279
279
  /**
280
280
  * What the host says about how this game is being played.
281
281
  *
@@ -361,10 +361,12 @@ type InputLayoutAxis = 'x' | 'y';
361
361
  * How an on-screen thumbstick meets a thumb: a player's setting, the same in
362
362
  * every game they open.
363
363
  *
364
- * `floating` is drawn where the layout puts it, as a sign that there is a
364
+ * `floating` is marked where the layout puts it, as a sign that there is a
365
365
  * stick, and comes to wherever a thumb lands on its side of the screen — so a
366
366
  * player never has to find it, and the place they first touch is always the
367
- * centre. `fixed` stays where it is drawn and is moved only from there.
367
+ * centre. A thumb that goes past its rim pulls it along, so turning back is
368
+ * never further than the stick is wide. `fixed` stays where it is drawn and is
369
+ * moved only from there.
368
370
  *
369
371
  * @group Input
370
372
  */
@@ -384,7 +386,7 @@ type InputChangeCause =
384
386
  /** A player changed how the on-screen controls behave. */
385
387
  'setting';
386
388
  //#endregion
387
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/panel.d.ts
389
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/panel.d.ts
388
390
  /**
389
391
  * The pages of the panel this version of the protocol has a name for.
390
392
  *
@@ -414,7 +416,7 @@ type PageId =
414
416
  /** @group Panels */
415
417
  declare const PAGES: readonly PageId[];
416
418
  //#endregion
417
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/pause.d.ts
419
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/pause.d.ts
418
420
  /**
419
421
  * Whether the game is holding still, which the host may ask for and only the
420
422
  * game can answer.
@@ -487,7 +489,7 @@ declare const PAUSE_STATES: readonly PauseState[];
487
489
  */
488
490
  declare const PAUSE_NONE: PauseState;
489
491
  //#endregion
490
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/save.d.ts
492
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/save.d.ts
491
493
  /**
492
494
  * The one thing a game may keep.
493
495
  *
@@ -538,7 +540,7 @@ type SaveStored = {
538
540
  bytes: number;
539
541
  };
540
542
  //#endregion
541
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/score.d.ts
543
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/score.d.ts
542
544
  /**
543
545
  * What a player did, as one number.
544
546
  *
@@ -614,7 +616,7 @@ type ScoreStanding = {
614
616
  of?: number;
615
617
  };
616
618
  //#endregion
617
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/share.d.ts
619
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/share.d.ts
618
620
  /**
619
621
  * A link to this game, offered to the player by the host.
620
622
  *
@@ -713,7 +715,7 @@ type ShareMeta = {
713
715
  [key: string]: ShareMetaValue;
714
716
  };
715
717
  //#endregion
716
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/methods.d.ts
718
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/methods.d.ts
717
719
  /**
718
720
  * How far a game has got with its own preparation.
719
721
  *
@@ -893,7 +895,7 @@ type DeviceInfo = {
893
895
  tier: DeviceTier;
894
896
  };
895
897
  //#endregion
896
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/listeners.d.ts
898
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/listeners.d.ts
897
899
  /**
898
900
  * The one way anything here is listened to: `on(listener)` hands back the
899
901
  * function that stops it.
@@ -922,7 +924,7 @@ type DeviceInfo = {
922
924
  */
923
925
  type Unsubscribe = () => void;
924
926
  //#endregion
925
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/protocol/src/transport.d.ts
927
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/protocol/src/transport.d.ts
926
928
  /** @group Bridge */
927
929
  type Transport = {
928
930
  send(message: Envelope): void;
@@ -1020,7 +1022,7 @@ declare global {
1020
1022
  var __HOPPLE_SET_SHIM__: ((shim: HoppleShim) => void) | undefined;
1021
1023
  }
1022
1024
  //#endregion
1023
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/manifest/src/manifest.d.ts
1025
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/manifest/src/manifest.d.ts
1024
1026
  /**
1025
1027
  * What a game says about itself.
1026
1028
  *
@@ -1757,6 +1759,17 @@ type GameManifest = {
1757
1759
  * @errorMessage must be lowercase letters, digits and hyphens
1758
1760
  */
1759
1761
  id: string;
1762
+ /**
1763
+ * The handle of the account the game is published under: the first half of
1764
+ * `owner/id`. Absent, it is whoever publishes it. Present, only that account
1765
+ * and the game's collaborators may publish it.
1766
+ *
1767
+ * @category Useful
1768
+ * @pattern ^[a-z0-9]+(?:-[a-z0-9]+)*$
1769
+ * @maxLength 64
1770
+ * @errorMessage must be a handle: lowercase letters, digits and hyphens
1771
+ */
1772
+ owner?: string;
1760
1773
  /**
1761
1774
  * The game's own version, `MAJOR.MINOR.PATCH`. Ours to read, never to parse for meaning.
1762
1775
  *
@@ -1906,7 +1919,7 @@ type HoppleConfig = {
1906
1919
  manifest: GameManifest;
1907
1920
  };
1908
1921
  //#endregion
1909
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/achievements.d.ts
1922
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/achievements.d.ts
1910
1923
  /**
1911
1924
  * Where this player stands on one achievement.
1912
1925
  *
@@ -1981,6 +1994,9 @@ type Achievements<Id extends string = string, Measured extends string = Id> = {
1981
1994
  * Legitimate on a measured achievement too, and it finishes it: the progress
1982
1995
  * goes to the target rather than leaving something unlocked at 40 of 100.
1983
1996
  *
1997
+ * Cheap to call every frame: one already unlocked, or already sent, is not
1998
+ * sent again.
1999
+ *
1984
2000
  * An id this game's manifest never declared is reported to `onError`, as an
1985
2001
  * author's mistake and not a player's.
1986
2002
  */
@@ -1991,7 +2007,8 @@ type Achievements<Id extends string = string, Measured extends string = Id> = {
1991
2007
  * *At 40*, not *add one*. The host keeps whichever value the manifest calls
1992
2008
  * better — the larger on an ordinary count, the smaller on a best time — so
1993
2009
  * reporting the same number twice does nothing, and reporting a worse one is
1994
- * not a regression. Reaching the target unlocks it.
2010
+ * not a regression. Reaching the target unlocks it. The same value as the
2011
+ * last one sent is not sent again, so this is cheap to call every frame.
1995
2012
  *
1996
2013
  * Against an achievement declared as a flag, the host refuses it and the
1997
2014
  * refusal is reported to `onError`: there is no target to move toward, and a
@@ -2000,7 +2017,7 @@ type Achievements<Id extends string = string, Measured extends string = Id> = {
2000
2017
  progress(id: Measured, value: number): void;
2001
2018
  };
2002
2019
  //#endregion
2003
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/analytics.d.ts
2020
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/analytics.d.ts
2004
2021
  /**
2005
2022
  * @group Analytics
2006
2023
  * @category Important
@@ -2017,7 +2034,7 @@ type Analytics<Events extends object = Record<string, AnalyticsProps>> = {
2017
2034
  track<Event extends keyof Events & string>(name: Event, props?: Events[Event]): void;
2018
2035
  };
2019
2036
  //#endregion
2020
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/audio.d.ts
2037
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/audio.d.ts
2021
2038
  /**
2022
2039
  * Something about the game's sound changed: the host's order, the player's
2023
2040
  * mute, a fader. Read what you need — `volume(channel)`, `allowed` — and apply
@@ -2110,7 +2127,7 @@ type Audio<Channel extends string = string> = {
2110
2127
  media(element: HTMLMediaElement, channel?: Channel): Unsubscribe;
2111
2128
  };
2112
2129
  //#endregion
2113
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/info.d.ts
2130
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/info.d.ts
2114
2131
  /**
2115
2132
  * What the host said, frozen.
2116
2133
  *
@@ -2128,7 +2145,7 @@ type Info = Readonly<{
2128
2145
  device: Readonly<DeviceInfo>;
2129
2146
  }>;
2130
2147
  //#endregion
2131
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/layout.d.ts
2148
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/layout.d.ts
2132
2149
  /**
2133
2150
  * How much of each edge belongs to the host. CSS pixels.
2134
2151
  *
@@ -2238,7 +2255,7 @@ type InsetPolicy = {
2238
2255
  */
2239
2256
  declare function insetsFrom(obstructions: readonly Obstruction[], frame: Size, policy?: InsetPolicy): Insets;
2240
2257
  //#endregion
2241
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/names.d.ts
2258
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/names.d.ts
2242
2259
  /**
2243
2260
  * The keys of a declared map, or `string` where the map is not a literal one —
2244
2261
  * which is what a manifest typed as the wide `GameManifest` gives — and
@@ -2345,7 +2362,7 @@ type EventProps<M> = M extends {
2345
2362
  */
2346
2363
  type StickName = 'pad.left.stick' | 'pad.right.stick' | 'pad.stick' | `controls.${string}`;
2347
2364
  //#endregion
2348
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/input/state.d.ts
2365
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/input/state.d.ts
2349
2366
  /**
2350
2367
  * Where the pointer is, in the frame's own coordinates.
2351
2368
  *
@@ -2406,7 +2423,7 @@ type InputSnapshot<Action extends string = string> = {
2406
2423
  pointer: PointerState | null;
2407
2424
  };
2408
2425
  //#endregion
2409
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/input/controls.d.ts
2426
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/input/controls.d.ts
2410
2427
  /**
2411
2428
  * The name a host leaves its input shim under.
2412
2429
  *
@@ -2483,11 +2500,12 @@ type ControlModel = {
2483
2500
  /**
2484
2501
  * How a thumbstick meets a thumb, as the player set it on their host.
2485
2502
  *
2486
- * `floating`: drawn where the layout puts it, so a player can see there is a
2487
- * stick, and brought to wherever a thumb lands on its side of the screen, so
2488
- * the place they first touch is the centre. `fixed`: moved only from where
2489
- * it is drawn. A renderer that ignores this draws `fixed`, which is still a
2490
- * stick a game can be played with.
2503
+ * `floating`: marked where the layout puts it, so a player can see there is
2504
+ * a stick, brought to wherever a thumb lands on its side of the screen, so
2505
+ * the place they first touch is the centre, and pulled along by a thumb that
2506
+ * goes past its rim. `fixed`: moved only from where it is drawn. A renderer
2507
+ * that ignores this draws `fixed`, which is still a stick a game can be
2508
+ * played with.
2491
2509
  */
2492
2510
  sticks: InputSticks;
2493
2511
  };
@@ -2585,7 +2603,7 @@ declare function isInputShim(value: unknown): value is InputShim;
2585
2603
  */
2586
2604
  declare const INPUT_CONTRACT = 4;
2587
2605
  //#endregion
2588
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/input/bindings.d.ts
2606
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/input/bindings.d.ts
2589
2607
  /**
2590
2608
  * The standard mapping's buttons, by index, as the names this SDK uses.
2591
2609
  *
@@ -2637,7 +2655,7 @@ declare function servesScheme(binding: string, scheme: InputScheme): boolean;
2637
2655
  */
2638
2656
  declare function labelFor(binding: string, scheme: InputScheme): string;
2639
2657
  //#endregion
2640
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/input/index.d.ts
2658
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/input/index.d.ts
2641
2659
  /**
2642
2660
  * How far a stick moves before it counts, where no shim has an opinion.
2643
2661
  *
@@ -2773,7 +2791,7 @@ type Controls<Layout extends string = string> = {
2773
2791
  readonly available: boolean;
2774
2792
  };
2775
2793
  //#endregion
2776
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/lifecycle.d.ts
2794
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/lifecycle.d.ts
2777
2795
  /** @group Lifecycle */
2778
2796
  type LifecycleListener = (phase: Phase, previous: Phase) => void | Promise<void>;
2779
2797
  /**
@@ -2792,7 +2810,7 @@ type Lifecycle = {
2792
2810
  on(listener: LifecycleListener): Unsubscribe;
2793
2811
  };
2794
2812
  //#endregion
2795
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/loop.d.ts
2813
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/loop.d.ts
2796
2814
  /**
2797
2815
  * The host has let the game run its loop, or stopped it. Return a promise to
2798
2816
  * make the host wait.
@@ -2846,7 +2864,7 @@ type Loop = {
2846
2864
  tick(frame: FrameCallback): Unsubscribe;
2847
2865
  };
2848
2866
  //#endregion
2849
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/panel.d.ts
2867
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/panel.d.ts
2850
2868
  /**
2851
2869
  * Where the host's panel stands over the game.
2852
2870
  *
@@ -2955,7 +2973,7 @@ type Panel = {
2955
2973
  open(page: PageId): void;
2956
2974
  };
2957
2975
  //#endregion
2958
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/pause.d.ts
2976
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/pause.d.ts
2959
2977
  /**
2960
2978
  * The host has asked for a pause, or for the game to carry on.
2961
2979
  *
@@ -3016,7 +3034,7 @@ type Pause = {
3016
3034
  on(listener: PauseListener): Unsubscribe;
3017
3035
  };
3018
3036
  //#endregion
3019
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/resources.d.ts
3037
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/resources.d.ts
3020
3038
  /**
3021
3039
  * The host has let the game hold its resources again, or asked for them back.
3022
3040
  * Return a promise to make the host wait until they have gone, or come back.
@@ -3046,7 +3064,7 @@ type Resources = {
3046
3064
  on(listener: ResourcesListener): Unsubscribe;
3047
3065
  };
3048
3066
  //#endregion
3049
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/save.d.ts
3067
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/save.d.ts
3050
3068
  /**
3051
3069
  * What a game gets back from a read: its own schema number, and its state.
3052
3070
  *
@@ -3135,7 +3153,7 @@ type Save = {
3135
3153
  readonly maxBytes: number;
3136
3154
  };
3137
3155
  //#endregion
3138
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/score.d.ts
3156
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/score.d.ts
3139
3157
  /**
3140
3158
  * Where this player stands on every board, as far as anybody has said.
3141
3159
  *
@@ -3212,7 +3230,7 @@ type Score<Board extends string = string> = {
3212
3230
  }): Promise<ScoreResult>;
3213
3231
  };
3214
3232
  //#endregion
3215
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/share.d.ts
3233
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/share.d.ts
3216
3234
  /**
3217
3235
  * @group Share
3218
3236
  * @category Important
@@ -3284,7 +3302,7 @@ type Share = {
3284
3302
  }): void;
3285
3303
  };
3286
3304
  //#endregion
3287
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/init.d.ts
3305
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/init.d.ts
3288
3306
  /**
3289
3307
  * What `init` hands back: every namespace a game has, on one object.
3290
3308
  *
@@ -3589,7 +3607,7 @@ type InitOptions = {
3589
3607
  */
3590
3608
  declare function init<M extends object = GameManifest>(options?: InitOptions): Promise<GameSdk<M>>;
3591
3609
  //#endregion
3592
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/transport.d.ts
3610
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/transport.d.ts
3593
3611
  /**
3594
3612
  * How long a game with no shim and no parent waits for one to turn up.
3595
3613
  *
@@ -3619,7 +3637,7 @@ type HostTransportOptions = {
3619
3637
  */
3620
3638
  declare function hostTransport(options?: HostTransportOptions): Promise<Transport>;
3621
3639
  //#endregion
3622
- //#region ../../../../../../../tmp/hopple-sdk-types-1wJl1B/game/src/shim.d.ts
3640
+ //#region ../../../../../../../tmp/hopple-sdk-types-DAYaix/game/src/shim.d.ts
3623
3641
  /**
3624
3642
  * Whether an arbitrary value is a shim this SDK knows how to speak to.
3625
3643
  *