@indiegems/gem-web-sdk 7.9.1 → 8.0.0

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.
@@ -1,6 +1,6 @@
1
1
  # The browser surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v7.9.1. Every symbol below links to its page on the Gem Arcade developer site.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v8.0.0. Every symbol below links to its page on the Gem Arcade developer site.
4
4
 
5
5
  `@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/game` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
6
6
 
@@ -4935,6 +4935,30 @@ arcade that handles share.
4935
4935
  up, for an arcade that does not handle share, and past this frame's own
4936
4936
  limit of six a minute.
4937
4937
 
4938
+ ## GemFrame.requestVibrate
4939
+
4940
+ [GemFrame.requestVibrate](https://gemarcade.com/developer/api/game#gemframe-requestvibrate)
4941
+
4942
+ ```ts
4943
+ requestVibrate(pattern: readonly number[]): boolean
4944
+ ```
4945
+
4946
+ Ask the arcade to play a vibration pattern where this frame has no
4947
+ `navigator.vibrate` of its own. Nothing comes back.
4948
+
4949
+ Prefer `gem.vibration.vibrate`, which calls `navigator.vibrate` itself
4950
+ where it exists, normalizes the pattern and caps its total length. This one
4951
+ checks only the message's bounds, sends only while connected, and only to
4952
+ an arcade that handles vibration.
4953
+
4954
+ | Parameter | Type |
4955
+ | --- | --- |
4956
+ | `pattern` | `readonly number[]` |
4957
+
4958
+ **Returns.** whether the message left the frame — `false` before the bridge is
4959
+ up, for an arcade that does not handle vibration, and past this frame's
4960
+ own limit of 600 a minute.
4961
+
4938
4962
  ## GemFrame.reportFrameStats
4939
4963
 
4940
4964
  [GemFrame.reportFrameStats](https://gemarcade.com/developer/api/game#gemframe-reportframestats)
@@ -5121,7 +5145,9 @@ readonly limit?: number
5121
5145
  ```
5122
5146
 
5123
5147
  Friends per page — default 50, at most 200. A player holds at most 1000
5124
- friends, so five max-size pages is the whole list.
5148
+ friends, so five max-size pages is the whole list. A larger value is
5149
+ clamped to 200; a value that is not a non-negative integer is refused with
5150
+ `invalid`.
5125
5151
 
5126
5152
  ## ListFriendsOptions.cursor
5127
5153
 
@@ -5144,6 +5170,181 @@ readonly signal?: AbortSignal
5144
5170
 
5145
5171
  Abort the read.
5146
5172
 
5173
+ ## FriendChallenge
5174
+
5175
+ [FriendChallenge](https://gemarcade.com/developer/api/game#friendchallenge)
5176
+
5177
+ ```ts
5178
+ interface FriendChallenge
5179
+ ```
5180
+
5181
+ One friend challenge this player received, in THIS game on THIS channel.
5182
+
5183
+ What the platform holds, not what the card said: there is no rendered line,
5184
+ because your game renders its own copy from [FriendChallenge.template](https://gemarcade.com/developer/api/game#friendchallenge-template)
5185
+ and [FriendChallenge.params](https://gemarcade.com/developer/api/game#friendchallenge-params). Who sent it is
5186
+ [FriendChallenge.from](https://gemarcade.com/developer/api/game#friendchallenge-from), resolved by the platform from its own records.
5187
+
5188
+ ## FriendChallenge.id
5189
+
5190
+ [FriendChallenge.id](https://gemarcade.com/developer/api/game#friendchallenge-id)
5191
+
5192
+ ```ts
5193
+ readonly id: string
5194
+ ```
5195
+
5196
+ The challenge's id — the value the Arcade puts in the `gemChallenge`
5197
+ launch key, and what [FriendsApi.markAnswered](https://gemarcade.com/developer/api/game#friendsapi-markanswered) takes. Opaque: compare
5198
+ it, store it, never parse it.
5199
+
5200
+ ## FriendChallenge.from
5201
+
5202
+ [FriendChallenge.from](https://gemarcade.com/developer/api/game#friendchallenge-from)
5203
+
5204
+ ```ts
5205
+ readonly from: Friend
5206
+ ```
5207
+
5208
+ Who sent it, with the same display identity a [Friend](https://gemarcade.com/developer/api/game#friend) row carries.
5209
+
5210
+ The ONLY name to show. Never read a name out of
5211
+ [FriendChallenge.params](https://gemarcade.com/developer/api/game#friendchallenge-params): a name in a param is one nobody checked.
5212
+
5213
+ ## FriendChallenge.template
5214
+
5215
+ [FriendChallenge.template](https://gemarcade.com/developer/api/game#friendchallenge-template)
5216
+
5217
+ ```ts
5218
+ readonly template: string
5219
+ ```
5220
+
5221
+ The `friend_challenge_templates[].key` it was sent with — which of your
5222
+ templates, so your game knows what was asked.
5223
+
5224
+ ## FriendChallenge.params
5225
+
5226
+ [FriendChallenge.params](https://gemarcade.com/developer/api/game#friendchallenge-params)
5227
+
5228
+ ```ts
5229
+ readonly params: Readonly<Record<string, string | number>>
5230
+ ```
5231
+
5232
+ The params exactly as sent: integers as numbers, date, enum and code
5233
+ params as strings. The template constrained them when the challenge was
5234
+ sent, but the config may have changed since, so check each one against
5235
+ what your game expects before it does anything — as you would a launch
5236
+ key.
5237
+
5238
+ ## FriendChallenge.createdAt
5239
+
5240
+ [FriendChallenge.createdAt](https://gemarcade.com/developer/api/game#friendchallenge-createdat)
5241
+
5242
+ ```ts
5243
+ readonly createdAt: number
5244
+ ```
5245
+
5246
+ When it was sent, in Unix seconds.
5247
+
5248
+ ## FriendChallenge.openedAt
5249
+
5250
+ [FriendChallenge.openedAt](https://gemarcade.com/developer/api/game#friendchallenge-openedat)
5251
+
5252
+ ```ts
5253
+ readonly openedAt?: number
5254
+ ```
5255
+
5256
+ When the player pressed Play on it in the Arcade, in Unix seconds. Absent
5257
+ until they have.
5258
+
5259
+ ## FriendChallenge.answeredAt
5260
+
5261
+ [FriendChallenge.answeredAt](https://gemarcade.com/developer/api/game#friendchallenge-answeredat)
5262
+
5263
+ ```ts
5264
+ readonly answeredAt?: number
5265
+ ```
5266
+
5267
+ When a game marked it answered with [FriendsApi.markAnswered](https://gemarcade.com/developer/api/game#friendsapi-markanswered), in
5268
+ Unix seconds. Absent until one has — so present on a relaunch of a
5269
+ challenge already played, which is how a replay is told from a first
5270
+ attempt.
5271
+
5272
+ ## FriendChallengesPage
5273
+
5274
+ [FriendChallengesPage](https://gemarcade.com/developer/api/game#friendchallengespage)
5275
+
5276
+ ```ts
5277
+ interface FriendChallengesPage
5278
+ ```
5279
+
5280
+ One page of the friend challenges this player holds in this game.
5281
+
5282
+ ## FriendChallengesPage.challenges
5283
+
5284
+ [FriendChallengesPage.challenges](https://gemarcade.com/developer/api/game#friendchallengespage-challenges)
5285
+
5286
+ ```ts
5287
+ readonly challenges: readonly FriendChallenge[]
5288
+ ```
5289
+
5290
+ The page's challenges, newest first, answered ones last.
5291
+
5292
+ ## FriendChallengesPage.nextCursor
5293
+
5294
+ [FriendChallengesPage.nextCursor](https://gemarcade.com/developer/api/game#friendchallengespage-nextcursor)
5295
+
5296
+ ```ts
5297
+ readonly nextCursor?: string
5298
+ ```
5299
+
5300
+ Present exactly when another page exists — pass it back as
5301
+ [ListFriendChallengesOptions.cursor](https://gemarcade.com/developer/api/game#listfriendchallengesoptions-cursor) to continue. Opaque: mint
5302
+ nothing, store nothing, compare nothing.
5303
+
5304
+ ## ListFriendChallengesOptions
5305
+
5306
+ [ListFriendChallengesOptions](https://gemarcade.com/developer/api/game#listfriendchallengesoptions)
5307
+
5308
+ ```ts
5309
+ interface ListFriendChallengesOptions
5310
+ ```
5311
+
5312
+ What [FriendsApi.inbox](https://gemarcade.com/developer/api/game#friendsapi-inbox) takes.
5313
+
5314
+ ## ListFriendChallengesOptions.limit
5315
+
5316
+ [ListFriendChallengesOptions.limit](https://gemarcade.com/developer/api/game#listfriendchallengesoptions-limit)
5317
+
5318
+ ```ts
5319
+ readonly limit?: number
5320
+ ```
5321
+
5322
+ Challenges per page — default 50, at most 200. The platform keeps at most
5323
+ 200 per player, so one max-size page is the whole inbox. A larger value is
5324
+ clamped to 200; a value that is not a non-negative integer is refused with
5325
+ `invalid`.
5326
+
5327
+ ## ListFriendChallengesOptions.cursor
5328
+
5329
+ [ListFriendChallengesOptions.cursor](https://gemarcade.com/developer/api/game#listfriendchallengesoptions-cursor)
5330
+
5331
+ ```ts
5332
+ readonly cursor?: string
5333
+ ```
5334
+
5335
+ The previous page's [FriendChallengesPage.nextCursor](https://gemarcade.com/developer/api/game#friendchallengespage-nextcursor), verbatim. A
5336
+ cursor the platform did not mint is refused with `invalid`.
5337
+
5338
+ ## ListFriendChallengesOptions.signal
5339
+
5340
+ [ListFriendChallengesOptions.signal](https://gemarcade.com/developer/api/game#listfriendchallengesoptions-signal)
5341
+
5342
+ ```ts
5343
+ readonly signal?: AbortSignal
5344
+ ```
5345
+
5346
+ Abort the read.
5347
+
5147
5348
  ## FriendChallengeRequest
5148
5349
 
5149
5350
  [FriendChallengeRequest](https://gemarcade.com/developer/api/game#friendchallengerequest)
@@ -5423,15 +5624,18 @@ channel: the version the template is missing from.
5423
5624
  class FriendsApi
5424
5625
  ```
5425
5626
 
5426
- Reading the signed-in player's accepted friends, and asking the Arcade to
5427
- send one of them a friend challenge.
5627
+ Reading the signed-in player's accepted friends, asking the Arcade to send
5628
+ one of them a friend challenge, and reading the friend challenges this
5629
+ player received in this game.
5428
5630
 
5429
5631
  Reached as `gem.friends`. Display identity only, and every accepted friend
5430
5632
  appears whether or not they have played this game — an invite-a-friend flow
5431
5633
  needs exactly the ones who have not. The graph itself — requests, accepts,
5432
5634
  blocks — is managed on the Arcade, not here. So is a friend challenge's
5433
5635
  send: [FriendsApi.challenge](https://gemarcade.com/developer/api/game#friendsapi-challenge) asks, and the Arcade confirms with the
5434
- player and sends.
5636
+ player and sends. The receiving side is [FriendsApi.launchedChallenge](https://gemarcade.com/developer/api/game#friendsapi-launchedchallenge)
5637
+ (the challenge this frame was launched with), [FriendsApi.inbox](https://gemarcade.com/developer/api/game#friendsapi-inbox) and
5638
+ [FriendsApi.markAnswered](https://gemarcade.com/developer/api/game#friendsapi-markanswered).
5435
5639
 
5436
5640
  ```js
5437
5641
  let page = await gem.friends.list();
@@ -5460,7 +5664,8 @@ have played this one.
5460
5664
  | --- | --- |
5461
5665
  | `options` | `ListFriendsOptions` |
5462
5666
 
5463
- **Throws.** `invalid` when the cursor is not one a previous page minted,
5667
+ **Throws.** `invalid` when the cursor is not one a previous page minted or
5668
+ `limit` is not a non-negative integer,
5464
5669
  `forbidden` in a context with no player — this is a player surface, and
5465
5670
  a game server has no friend list.
5466
5671
 
@@ -5520,6 +5725,123 @@ challengeButton.onclick = async () => {
5520
5725
  };
5521
5726
  ```
5522
5727
 
5728
+ ## FriendsApi.inbox
5729
+
5730
+ [FriendsApi.inbox](https://gemarcade.com/developer/api/game#friendsapi-inbox)
5731
+
5732
+ ```ts
5733
+ inbox(options?: ListFriendChallengesOptions): Promise<FriendChallengesPage>
5734
+ ```
5735
+
5736
+ Read one page of the friend challenges this player holds in THIS game on
5737
+ THIS channel — in every state. Answered challenges are INCLUDED, and sort
5738
+ after the rest; within each part, newest first.
5739
+
5740
+ Pass the result's `nextCursor` back as `cursor` until it stops arriving.
5741
+ A guest holds no challenges, so a guest's page is empty rather than a
5742
+ refusal — build the screen for the empty state, not around an error.
5743
+
5744
+ For the one challenge this frame was launched with, use
5745
+ [FriendsApi.launchedChallenge](https://gemarcade.com/developer/api/game#friendsapi-launchedchallenge) rather than searching this list.
5746
+
5747
+ | Parameter | Type |
5748
+ | --- | --- |
5749
+ | `options` | `ListFriendChallengesOptions` |
5750
+
5751
+ **Throws.** `invalid` when the cursor is not one a previous page minted or
5752
+ `limit` is not a non-negative integer,
5753
+ `forbidden` in a context with no player of this game — a game server,
5754
+ or a token that is not a game-scoped player token.
5755
+
5756
+ ```ts
5757
+ const page = await gem.friends.inbox();
5758
+ for (const c of page.challenges) {
5759
+ if (c.template !== 'beat_code_jar') continue;
5760
+ renderChallengeRow(c.from, c.params, c.answeredAt !== undefined);
5761
+ }
5762
+ ```
5763
+
5764
+ ## FriendsApi.launchedChallenge
5765
+
5766
+ [FriendsApi.launchedChallenge](https://gemarcade.com/developer/api/game#friendsapi-launchedchallenge)
5767
+
5768
+ ```ts
5769
+ launchedChallenge(options?: { signal?: AbortSignal }): Promise<FriendChallenge | null>
5770
+ ```
5771
+
5772
+ The friend challenge this frame was launched with, or `null`.
5773
+
5774
+ When a player opens a friend challenge in the Arcade, the Arcade launches
5775
+ your game with the challenge's params as launch keys plus its own
5776
+ `gemChallenge` key. This reads that key — never parse it yourself — and
5777
+ looks the challenge up, so you get the sender from the platform's records
5778
+ and the params as they were sent.
5779
+
5780
+ The key is read ONCE, when `createGem` runs, so cleaning your URL with
5781
+ `history.replaceState` afterwards changes nothing here.
5782
+
5783
+ RESOLVES `null`, never rejects, for every launch that is not this
5784
+ player's challenge in this game: no `gemChallenge` key, a value that is
5785
+ not a challenge id, a challenge that is not this player's (a link
5786
+ someone shared), one from another game or channel, and every guest
5787
+ launch. Treat `null` as an ordinary launch.
5788
+
5789
+ A RELAUNCH REPLAYS. Pressing Play again in the Arcade relaunches the
5790
+ same challenge, so the same one comes back; it carries
5791
+ [FriendChallenge.answeredAt](https://gemarcade.com/developer/api/game#friendchallenge-answeredat) once a game has called
5792
+ [FriendsApi.markAnswered](https://gemarcade.com/developer/api/game#friendsapi-markanswered), which is how a replay is told from a
5793
+ first attempt. Asks the platform on every call, so `answeredAt` is
5794
+ current.
5795
+
5796
+ | Parameter | Type |
5797
+ | --- | --- |
5798
+ | `options` | `{ signal?: AbortSignal }` |
5799
+
5800
+ **Throws.** What any platform read throws: `forbidden` in a context with no
5801
+ player of this game, `unavailable` and `rate_limited` when the platform
5802
+ cannot answer now — and `not_found` for a 404 that is NOT the platform's
5803
+ uniform challenge answer (no `inbox_item_not_found` code), which is a
5804
+ platform that does not serve this read rather than an ordinary launch.
5805
+
5806
+ ```ts
5807
+ const challenge = await gem.friends.launchedChallenge();
5808
+ if (challenge?.template === 'beat_code_jar') {
5809
+ // Check every param before it does anything: the config may have changed since.
5810
+ const jar = challenge.params.jar;
5811
+ if (typeof jar === 'string' && /^[A-Z0-9]{7}$/.test(jar)) {
5812
+ startJar(jar, { from: challenge.from, replay: challenge.answeredAt !== undefined });
5813
+ }
5814
+ }
5815
+ ```
5816
+
5817
+ ## FriendsApi.markAnswered
5818
+
5819
+ [FriendsApi.markAnswered](https://gemarcade.com/developer/api/game#friendsapi-markanswered)
5820
+
5821
+ ```ts
5822
+ markAnswered(id: string): Promise<void>
5823
+ ```
5824
+
5825
+ Mark one of this player's friend challenges answered — the player has
5826
+ played it. Call it when your game has finished the attempt the challenge
5827
+ asked for, win or lose.
5828
+
5829
+ Idempotent: a second call changes nothing, and a challenge keeps the
5830
+ first time it was answered. The sender is told nothing — there is no read
5831
+ receipt — so this is your game's own record, which
5832
+ [FriendChallenge.answeredAt](https://gemarcade.com/developer/api/game#friendchallenge-answeredat) reads back.
5833
+
5834
+ | Parameter | Type | Description |
5835
+ | --- | --- | --- |
5836
+ | `id` | `string` | A [FriendChallenge.id](https://gemarcade.com/developer/api/game#friendchallenge-id), from
5837
+ [FriendsApi.launchedChallenge](https://gemarcade.com/developer/api/game#friendsapi-launchedchallenge) or [FriendsApi.inbox](https://gemarcade.com/developer/api/game#friendsapi-inbox). |
5838
+
5839
+ **Throws.** `not_found` when no challenge of this player's in this game and
5840
+ channel has that id — one answer for unknown and someone else's;
5841
+ `invalid` when `id` cannot be a challenge id at all, before anything is
5842
+ sent; `forbidden` in a context with no player of this game;
5843
+ `rate_limited` past the platform's per-player budget.
5844
+
5523
5845
  ## FunctionInvokeOptions
5524
5846
 
5525
5847
  [FunctionInvokeOptions](https://gemarcade.com/developer/api/game#functioninvokeoptions)
@@ -7405,6 +7727,40 @@ shareButton.onclick = () => {
7405
7727
 
7406
7728
  **Guides.** [getting-started](https://gemarcade.com/developer/docs/getting-started)
7407
7729
 
7730
+ ## Gem.vibration
7731
+
7732
+ [Gem.vibration](https://gemarcade.com/developer/api/game#gem-vibration)
7733
+
7734
+ ```ts
7735
+ readonly vibration: VibrationApi
7736
+ ```
7737
+
7738
+ Vibrate the player's device — call this instead of `navigator.vibrate`,
7739
+ which does nothing on any iPhone. It takes the same pattern and returns the
7740
+ same boolean, calls `navigator.vibrate` itself where that works, and asks
7741
+ the arcade to vibrate where it does not.
7742
+
7743
+ Read [VibrationApi.available](https://gemarcade.com/developer/api/game#vibrationapi-available) live, after `awaitBridge()`, to decide
7744
+ whether to show your game's vibration toggle — on an iPhone it is `false`
7745
+ until the bridge connects — and check that toggle before every call:
7746
+
7747
+ ```js
7748
+ await gem.awaitBridge();
7749
+ vibrationRow.hidden = !gem.vibration.available;
7750
+
7751
+ function onHit() {
7752
+ if (settings.vibration) gem.vibration.vibrate(30);
7753
+ }
7754
+ ```
7755
+
7756
+ - **Never call `navigator.vibrate`**, guarded or not, and never fall back
7757
+ to it: this already does.
7758
+ - **Nothing vibrates before the player's first tap** in your game; the
7759
+ call returns `false` until then.
7760
+ - **Stop on pause** with `gem.vibration.vibrate(0)`.
7761
+
7762
+ **Guides.** [vibration](https://gemarcade.com/developer/docs/vibration)
7763
+
7408
7764
  ## Gem.analytics
7409
7765
 
7410
7766
  [Gem.analytics](https://gemarcade.com/developer/api/game#gem-analytics)
@@ -7499,12 +7855,17 @@ readonly friends: FriendsApi
7499
7855
  The signed-in player's accepted friends — display identity only,
7500
7856
  read-only, paginated — and the one ask that reaches past them:
7501
7857
  [FriendsApi.challenge](https://gemarcade.com/developer/api/game#friendsapi-challenge), which asks the Arcade to send a friend a
7502
- challenge after the player confirms it in the Arcade's own sheet.
7858
+ challenge after the player confirms it in the Arcade's own sheet. The
7859
+ receiving side reads the challenges this player holds in this game:
7860
+ [FriendsApi.launchedChallenge](https://gemarcade.com/developer/api/game#friendsapi-launchedchallenge) for the one this frame was launched
7861
+ with, [FriendsApi.inbox](https://gemarcade.com/developer/api/game#friendsapi-inbox) for all of them, and
7862
+ [FriendsApi.markAnswered](https://gemarcade.com/developer/api/game#friendsapi-markanswered) once one has been played.
7503
7863
 
7504
7864
  Every accepted friend appears whether or not they have played this game;
7505
7865
  an invite-a-friend flow needs exactly the ones who have not. The graph
7506
7866
  itself — requests, accepts, blocks, presence — stays on the Arcade: there
7507
- is nothing here to mutate and nothing that says who is online.
7867
+ is nothing here to mutate but a challenge's own answered mark, and nothing
7868
+ that says who is online.
7508
7869
 
7509
7870
  A player surface only. In a context with no player — a game server — the
7510
7871
  platform refuses the read; a server has no friend list.
@@ -11247,6 +11608,61 @@ A unit test that constructs the SDK in a simulated DOM has to give its
11247
11608
  window a parent of its own, because a simulated top-level window is exactly
11248
11609
  what this refuses.
11249
11610
 
11611
+ ## VibrationApi
11612
+
11613
+ [VibrationApi](https://gemarcade.com/developer/api/game#vibrationapi)
11614
+
11615
+ ```ts
11616
+ interface VibrationApi
11617
+ ```
11618
+
11619
+ `gem.vibration` — vibrate the player's device, on every platform that can.
11620
+ Call it instead of `navigator.vibrate`, which does nothing on any iPhone.
11621
+
11622
+ ## VibrationApi.available
11623
+
11624
+ [VibrationApi.available](https://gemarcade.com/developer/api/game#vibrationapi-available)
11625
+
11626
+ ```ts
11627
+ readonly available: boolean
11628
+ ```
11629
+
11630
+ Whether this device can vibrate for your game: decide from this whether to
11631
+ show your game's vibration toggle. Read it live, every time — after
11632
+ `awaitBridge()`, and again when your settings screen opens — never once at
11633
+ boot: on an iPhone it is `false` until the bridge connects.
11634
+
11635
+ `false` on a desktop with a mouse, in iOS Safari, in Firefox, before the
11636
+ bridge is up where vibration goes through the arcade, and after the
11637
+ session ends there.
11638
+
11639
+ ## VibrationApi.vibrate
11640
+
11641
+ [VibrationApi.vibrate](https://gemarcade.com/developer/api/game#vibrationapi-vibrate)
11642
+
11643
+ ```ts
11644
+ vibrate(pattern: number | readonly number[]): boolean
11645
+ ```
11646
+
11647
+ Vibrate: takes what `navigator.vibrate` takes and returns what it returns.
11648
+ `pattern` is a duration in milliseconds, or an array of alternating
11649
+ vibration and pause durations, starting with a vibration. `0` or `[]`
11650
+ stops a pattern that is still playing, and every call replaces it.
11651
+
11652
+ The pattern is capped at 99 entries of at most 10 000 ms each, and at
11653
+ 10 000 ms in all: a longer one is cut short, not refused.
11654
+
11655
+ Check your game's own vibration toggle before every call. Returns `false`,
11656
+ and vibrates nothing, when [VibrationApi.available](https://gemarcade.com/developer/api/game#vibrationapi-available) is false, before
11657
+ the player's first tap or key press in your game, for a pattern with a
11658
+ negative or non-finite entry, and past 600 calls a minute; each of the last
11659
+ three says so once a session through your `log`. `true` means the pattern
11660
+ was accepted, never that a motor moved.
11661
+
11662
+ | Parameter | Type |
11663
+ | --- | --- |
11664
+ | `pattern` | `number \| readonly number[]` |
11665
+
11250
11666
  ## LeaderboardPeriod.id
11251
11667
 
11252
11668
  [LeaderboardPeriod.id](https://gemarcade.com/developer/api/game#leaderboardperiod-id)
@@ -1,6 +1,6 @@
1
1
  # The server surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v7.9.1. Every symbol below links to its page on the Gem Arcade developer site.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v8.0.0. Every symbol below links to its page on the Gem Arcade developer site.
4
4
 
5
5
  `@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/server` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
6
6