@indiegems/gem-web-sdk 8.0.0 → 8.1.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` v8.0.0. Every symbol below links to its page on the Gem Arcade developer site.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v8.1.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
 
@@ -247,6 +247,47 @@ check that a funnel you declared names events you are actually sending.
247
247
 
248
248
  Absent when your game declares none.
249
249
 
250
+ ## GameConfig.rewarded_placements
251
+
252
+ [GameConfig.rewarded_placements](https://gemarcade.com/developer/api/game#gameconfig-rewarded_placements)
253
+
254
+ ```ts
255
+ rewarded_placements?: SnapshotRewardedPlacement[]
256
+ ```
257
+
258
+ Your rewarded placements — what pressing a rewarded button grants. An
259
+ array, one row per placement, each naming itself in `placement`, with its
260
+ `grants`, the caps the platform enforces on it (`max_per_day`,
261
+ `cooldown_seconds`, `max_held`) and what happens where no ad serves
262
+ (`without_ads`).
263
+
264
+ Read it to LABEL your button — "+1 Revive" — never to decide a reward. A
265
+ grant is an `item_grant`, with a `quantity` of the item its
266
+ `item_definition_id` names, or a `currency_grant`, with an `amount` of the
267
+ currency its `currency_id` names; the word on the button is that
268
+ definition's `display_name`, from [GameConfig.item](https://gemarcade.com/developer/api/game#gameconfig-item) or
269
+ [GameConfig.currency](https://gemarcade.com/developer/api/game#gameconfig-currency):
270
+
271
+ ```js
272
+ const row = config?.rewarded_placements?.find((p) => p.placement === 'classic_revive');
273
+ const grant = row?.grants[0];
274
+ const label =
275
+ grant?.type === 'item_grant'
276
+ ? `+${grant.quantity} ${config.item(grant.item_definition_id)?.display_name ?? ''}`
277
+ : grant?.type === 'currency_grant'
278
+ ? `+${grant.amount} ${config.currency(grant.currency_id)?.display_name ?? ''}`
279
+ : undefined;
280
+ ```
281
+
282
+ Whether an ask grants anything is the platform's decision, made against
283
+ this config server-side; the grant lands on your game's inventory, and
284
+ re-reading `gem.me.inventory` is the only way to learn that it did. Whether
285
+ the button could pay right now is [AdsApi.rewardedStatus](https://gemarcade.com/developer/api/game#adsapi-rewardedstatus).
286
+
287
+ Absent when your game declares none.
288
+
289
+ **Guides.** [cross-promotion](https://gemarcade.com/developer/docs/cross-promotion)
290
+
250
291
  ## GameConfig.version
251
292
 
252
293
  [GameConfig.version](https://gemarcade.com/developer/api/game#gameconfig-version)
@@ -2934,6 +2975,11 @@ No reason is given for a `no_ad`, and one will never be added: a reason would
2934
2975
  tell your game something about the player — an age, a consent state, a
2935
2976
  subscription — that game code is deliberately not told.
2936
2977
 
2978
+ The one thing you can learn is about **your own economy**, and not from this
2979
+ answer: [AdsApi.rewardedStatus](https://gemarcade.com/developer/api/game#adsapi-rewardedstatus) reports your own declared rewarded caps
2980
+ as the platform holds them (a platform-wide per-placement maximum, where one
2981
+ is set, can lower a cap). It never reports anything about the player.
2982
+
2937
2983
  ## AdOutcome
2938
2984
 
2939
2985
  [AdOutcome](https://gemarcade.com/developer/api/game#adoutcome)
@@ -3009,6 +3055,160 @@ startNextLevel();
3009
3055
 
3010
3056
  **Guides.** [cross-promotion](https://gemarcade.com/developer/docs/cross-promotion)
3011
3057
 
3058
+ ## AdsApi.rewardedStatus
3059
+
3060
+ [AdsApi.rewardedStatus](https://gemarcade.com/developer/api/game#adsapi-rewardedstatus)
3061
+
3062
+ ```ts
3063
+ rewardedStatus(placement: string): Promise<RewardedStatus>
3064
+ ```
3065
+
3066
+ Whether a rewarded placement could pay right now, so you can decide whether
3067
+ to draw its button. **It never says whether an ad will play.**
3068
+
3069
+ The answer comes from your own `rewarded_placements` config — its daily
3070
+ cap, cooldown and `max_held` — applied to this player's use of it, as the
3071
+ platform holds them. Nothing in it describes the player. `grantable: true`
3072
+ means the platform would grant if an ad is watched or, where no ad serves,
3073
+ under the placement's `without_ads: grant`; a player can still press the
3074
+ button and get `no_ad`, for reasons your game is not told.
3075
+
3076
+ NOTHING REJECTS, like everything else on `gem.ads`. Without a play token,
3077
+ when the read fails or takes longer than ten seconds, or for a `placement`
3078
+ outside the grammar [AdRequest.placement](https://gemarcade.com/developer/api/game#adrequest-placement) documents, it resolves not
3079
+ declared and not grantable, with no `resetsAt`, and the reason goes to your
3080
+ `onError` handler.
3081
+
3082
+ It is a read of the platform, so call it when you draw the button — on a
3083
+ results or death screen — not every frame. Calls for one placement that
3084
+ overlap share one request. Draw the rest of the screen first rather than
3085
+ holding it on this answer.
3086
+
3087
+ ⚠️ It grants nothing and reserves nothing. The reward is granted by the
3088
+ platform when the player asks with `requestAd`; re-read `gem.me.inventory`
3089
+ after that ask settles, whatever it settled as.
3090
+
3091
+ | Parameter | Type | Description |
3092
+ | --- | --- | --- |
3093
+ | `placement` | `string` | A placement your `rewarded_placements` config declares. |
3094
+
3095
+ **Returns.** The placement's state. Always resolves; never rejects.
3096
+
3097
+ ```ts
3098
+ const status = await gem.ads.rewardedStatus('classic_revive');
3099
+ reviveButton.disabled = !status.grantable;
3100
+ if (status.nextEligibleAt !== undefined) {
3101
+ reviveButton.title = `Back at ${new Date(status.nextEligibleAt).toLocaleTimeString()}`;
3102
+ }
3103
+ ```
3104
+
3105
+ **Guides.** [cross-promotion](https://gemarcade.com/developer/docs/cross-promotion)
3106
+
3107
+ ## RewardedStatus
3108
+
3109
+ [RewardedStatus](https://gemarcade.com/developer/api/game#rewardedstatus)
3110
+
3111
+ ```ts
3112
+ interface RewardedStatus
3113
+ ```
3114
+
3115
+ What [AdsApi.rewardedStatus](https://gemarcade.com/developer/api/game#adsapi-rewardedstatus) answers: the state of one rewarded
3116
+ placement for this player, from your own declared caps.
3117
+
3118
+ Every figure comes from **your** `rewarded_placements` config — `max_per_day`,
3119
+ `cooldown_seconds`, `max_held` — applied to this player's use of it, as the
3120
+ platform holds them. The platform can hold a placement's daily cap below what
3121
+ you declared, never above it. Nothing here describes the player.
3122
+
3123
+ ⚠️ **It never says whether an ad will play.** Whether one does depends on
3124
+ things your game is deliberately not told. A player can see your button,
3125
+ press it, and get `no_ad`: read that `no_ad` like any other, and never guess
3126
+ a reason.
3127
+
3128
+ ## RewardedStatus.declared
3129
+
3130
+ [RewardedStatus.declared](https://gemarcade.com/developer/api/game#rewardedstatus-declared)
3131
+
3132
+ ```ts
3133
+ readonly declared: boolean
3134
+ ```
3135
+
3136
+ Whether this channel's published config declares the placement.
3137
+
3138
+ `false` for a placement your config does not name, a config that is not
3139
+ promoted to the channel being played, and every answer the platform did not
3140
+ give (see [RewardedStatus.resetsAt](https://gemarcade.com/developer/api/game#rewardedstatus-resetsat)).
3141
+
3142
+ ## RewardedStatus.grantable
3143
+
3144
+ [RewardedStatus.grantable](https://gemarcade.com/developer/api/game#rewardedstatus-grantable)
3145
+
3146
+ ```ts
3147
+ readonly grantable: boolean
3148
+ ```
3149
+
3150
+ Whether pressing your button could pay right now: the platform would grant
3151
+ the reward if an ad is watched or, where no ad serves, under the
3152
+ placement's `without_ads: grant`.
3153
+
3154
+ **Not a promise that an ad will play, and not a promise of a reward.** It
3155
+ is `false` whenever a cap is spent, a cooldown is running, the player holds
3156
+ `max_held`, rewarded is off on this channel, or the arcade running your
3157
+ game does not take ad requests at all.
3158
+
3159
+ ## RewardedStatus.remainingToday
3160
+
3161
+ [RewardedStatus.remainingToday](https://gemarcade.com/developer/api/game#rewardedstatus-remainingtoday)
3162
+
3163
+ ```ts
3164
+ readonly remainingToday?: number
3165
+ ```
3166
+
3167
+ Grants left today under the placement's daily cap, a non-negative integer.
3168
+
3169
+ ABSENT — no key, never a sentinel — when the placement has no daily cap,
3170
+ and on any answer where `declared` is `false`.
3171
+
3172
+ ## RewardedStatus.nextEligibleAt
3173
+
3174
+ [RewardedStatus.nextEligibleAt](https://gemarcade.com/developer/api/game#rewardedstatus-nexteligibleat)
3175
+
3176
+ ```ts
3177
+ readonly nextEligibleAt?: number
3178
+ ```
3179
+
3180
+ When the placement's cooldown ends, in epoch milliseconds — render it with
3181
+ `new Date(nextEligibleAt)`.
3182
+
3183
+ ABSENT when no cooldown is running.
3184
+
3185
+ ## RewardedStatus.heldLimitReached
3186
+
3187
+ [RewardedStatus.heldLimitReached](https://gemarcade.com/developer/api/game#rewardedstatus-heldlimitreached)
3188
+
3189
+ ```ts
3190
+ readonly heldLimitReached: boolean
3191
+ ```
3192
+
3193
+ Whether the player already holds the placement's `max_held` of the item it
3194
+ grants. Spend one first.
3195
+
3196
+ ## RewardedStatus.resetsAt
3197
+
3198
+ [RewardedStatus.resetsAt](https://gemarcade.com/developer/api/game#rewardedstatus-resetsat)
3199
+
3200
+ ```ts
3201
+ readonly resetsAt?: number
3202
+ ```
3203
+
3204
+ When the daily count resets — the next 00:00 UTC — in epoch milliseconds.
3205
+ Take it from here rather than computing midnight in game code.
3206
+
3207
+ ABSENT when the platform gave no answer: no play token yet, a read that
3208
+ failed or took longer than ten seconds, or a platform that does not serve
3209
+ this read. Then the rest of the status reads not declared and not
3210
+ grantable, and the reason went to your `onError` handler.
3211
+
3012
3212
  ## AnalyticsValue
3013
3213
 
3014
3214
  [AnalyticsValue](https://gemarcade.com/developer/api/game#analyticsvalue)
@@ -4863,6 +5063,29 @@ sends only while connected, and only to an arcade that draws a wallet.
4863
5063
  **Returns.** whether it entered the send path — `false` before the bridge is
4864
5064
  up, and `false` for an arcade with no wallet to move.
4865
5065
 
5066
+ ## GemFrame.showPortraitBorders
5067
+
5068
+ [GemFrame.showPortraitBorders](https://gemarcade.com/developer/api/game#gemframe-showportraitborders)
5069
+
5070
+ ```ts
5071
+ showPortraitBorders(name: string | null): boolean
5072
+ ```
5073
+
5074
+ Tell the arcade which of your store page's portrait borders to paint beside
5075
+ your game, or `null` for none.
5076
+
5077
+ Prefer `gem.showPortraitBorders`, which holds your choice until the bridge
5078
+ is up and paces a burst of changes for you. This one sends every call it
5079
+ accepts, only while connected, and only to an arcade that paints borders.
5080
+
5081
+ | Parameter | Type |
5082
+ | --- | --- |
5083
+ | `name` | `string \| null` |
5084
+
5085
+ **Returns.** whether the message left the frame — `false` for a string that is
5086
+ not a border name (with a console warning), before the bridge is up, for
5087
+ an arcade that paints no borders, and past this frame's own limit.
5088
+
4866
5089
  ## GemFrame.setWalletVisible
4867
5090
 
4868
5091
  [GemFrame.setWalletVisible](https://gemarcade.com/developer/api/game#gemframe-setwalletvisible)
@@ -5091,8 +5314,9 @@ draw your own placeholder rather than a broken image. Pass it through
5091
5314
  readonly badges: readonly PlayerBadge[]
5092
5315
  ```
5093
5316
 
5094
- The player's equipped badges, in display order. Always a list, and empty
5095
- until platform achievements equip any.
5317
+ The player's equipped badges, at most two, in the order the player
5318
+ arranged them. Always a list — empty when they wear none, or when their
5319
+ identity is withheld — so draw what is there and key on `itemId`.
5096
5320
 
5097
5321
  ## FriendsPage
5098
5322
 
@@ -6883,8 +7107,9 @@ draw your own placeholder rather than a broken image. Pass it through
6883
7107
  readonly badges: readonly PlayerBadge[]
6884
7108
  ```
6885
7109
 
6886
- The player's equipped badges, in display order. Always a list, and empty
6887
- until platform achievements equip any.
7110
+ The player's equipped badges, at most two, in the order the player
7111
+ arranged them. Always a list — empty when they wear none, or when their
7112
+ identity is withheld — so draw what is there and key on `itemId`.
6888
7113
 
6889
7114
  ## GemPrefs
6890
7115
 
@@ -7664,7 +7889,10 @@ resumes it when the promise settles, so you do not pause anything yourself.
7664
7889
  ⚠️ `shown` **grants nothing.** It is not a receipt and not an entitlement,
7665
7890
  and a reward must never be handed out on the strength of it.
7666
7891
 
7667
- You are told no reason for a no, and there is nothing to infer from one.
7892
+ You are told no reason for a no, and there is nothing to infer from one
7893
+ about the player. What you can read is your own economy:
7894
+ `rewardedStatus(placement)` says whether a rewarded placement could pay
7895
+ right now under your own declared caps — never whether an ad will play.
7668
7896
 
7669
7897
  **Guides.** [cross-promotion](https://gemarcade.com/developer/docs/cross-promotion)
7670
7898
 
@@ -8059,6 +8287,51 @@ arcade just said is not sent.
8059
8287
  | --- | --- |
8060
8288
  | `muted` | `boolean` |
8061
8289
 
8290
+ ## Gem.showPortraitBorders
8291
+
8292
+ [Gem.showPortraitBorders](https://gemarcade.com/developer/api/game#gem-showportraitborders)
8293
+
8294
+ ```ts
8295
+ showPortraitBorders(name: string | null): void
8296
+ ```
8297
+
8298
+ Choose which of your store page's **portrait borders** the arcade paints on
8299
+ either side of your game, or `null` for none.
8300
+
8301
+ On a desktop browser, the arcade's desktop app or a television, the arcade
8302
+ shows a portrait-only game as a centred portrait column. With borders
8303
+ declared on your store page (`media.portrait_borders`), it paints one of
8304
+ those images beside the column instead of its own bars. Call this at
8305
+ start-up and on every theme change, with the border that goes with what is
8306
+ on screen:
8307
+
8308
+ ```js
8309
+ const BORDERS = new Set(['meadow', 'alpine']); // the names your store page declares
8310
+
8311
+ function applyTheme(id) {
8312
+ document.body.dataset.theme = id;
8313
+ gem.showPortraitBorders(BORDERS.has(id) ? id : null); // null: a theme with no art
8314
+ }
8315
+ ```
8316
+
8317
+ Until your first call the arcade shows the page's first border. Whether
8318
+ your game is letterboxed at all is decided by your store page's
8319
+ `orientations`, never by this call, so call it unconditionally: before the
8320
+ connection exists your choice is held and sent when it connects, a burst of
8321
+ changes (a picker previewing on hover) reaches the arcade as its final
8322
+ value, and an arcade that paints no borders is simply not told. The arcade
8323
+ owns the change itself — when and how the image swaps — and sends no
8324
+ acknowledgement.
8325
+
8326
+ A name is 1 to 40 characters of `a-z`, `0-9`, `_` and `-`, starting with a
8327
+ letter or digit — the store page's own rule. Anything else is refused with
8328
+ a console warning and never sent; a valid name your page does not declare
8329
+ is ignored by the arcade, which keeps the image it is showing.
8330
+
8331
+ | Parameter | Type |
8332
+ | --- | --- |
8333
+ | `name` | `string \| null` |
8334
+
8062
8335
  ## Gem.cueReward
8063
8336
 
8064
8337
  [Gem.cueReward](https://gemarcade.com/developer/api/game#gem-cuereward)
@@ -9159,7 +9432,8 @@ interface PlayerBadge
9159
9432
  One badge a player has equipped — an icon the platform shows beside their
9160
9433
  name.
9161
9434
 
9162
- Always an empty list today; platform achievements fill it with at most two.
9435
+ A player wears at most two, in the order they arranged them. Each is an icon
9436
+ they own — an achievement in any game may have awarded it.
9163
9437
 
9164
9438
  ## PlayerBadge.itemId
9165
9439
 
@@ -9283,8 +9557,9 @@ draw your own placeholder rather than a broken image. Pass it through
9283
9557
  readonly badges: readonly PlayerBadge[]
9284
9558
  ```
9285
9559
 
9286
- The player's equipped badges, in display order. Always a list, and empty
9287
- until platform achievements equip any.
9560
+ The player's equipped badges, at most two, in the order the player
9561
+ arranged them. Always a list — empty when they wear none, or when their
9562
+ identity is withheld — so draw what is there and key on `itemId`.
9288
9563
 
9289
9564
  ## mapIdentity
9290
9565
 
@@ -11831,8 +12106,9 @@ draw your own placeholder rather than a broken image. Pass it through
11831
12106
  readonly badges: readonly PlayerBadge[]
11832
12107
  ```
11833
12108
 
11834
- The player's equipped badges, in display order. Always a list, and empty
11835
- until platform achievements equip any.
12109
+ The player's equipped badges, at most two, in the order the player
12110
+ arranged them. Always a list — empty when they wear none, or when their
12111
+ identity is withheld — so draw what is there and key on `itemId`.
11836
12112
 
11837
12113
  ## LeaderboardEntry.rank
11838
12114
 
@@ -13272,8 +13548,9 @@ draw your own placeholder rather than a broken image. Pass it through
13272
13548
  readonly badges: readonly PlayerBadge[]
13273
13549
  ```
13274
13550
 
13275
- The player's equipped badges, in display order. Always a list, and empty
13276
- until platform achievements equip any.
13551
+ The player's equipped badges, at most two, in the order the player
13552
+ arranged them. Always a list — empty when they wear none, or when their
13553
+ identity is withheld — so draw what is there and key on `itemId`.
13277
13554
 
13278
13555
  ## PlayerProfile.playerId
13279
13556
 
@@ -15306,8 +15583,9 @@ draw your own placeholder rather than a broken image. Pass it through
15306
15583
  readonly badges: readonly PlayerBadge[]
15307
15584
  ```
15308
15585
 
15309
- The player's equipped badges, in display order. Always a list, and empty
15310
- until platform achievements equip any.
15586
+ The player's equipped badges, at most two, in the order the player
15587
+ arranged them. Always a list — empty when they wear none, or when their
15588
+ identity is withheld — so draw what is there and key on `itemId`.
15311
15589
 
15312
15590
  ## RoomMember.playerId
15313
15591
 
@@ -16070,8 +16348,9 @@ draw your own placeholder rather than a broken image. Pass it through
16070
16348
  readonly badges: readonly PlayerBadge[]
16071
16349
  ```
16072
16350
 
16073
- The player's equipped badges, in display order. Always a list, and empty
16074
- until platform achievements equip any.
16351
+ The player's equipped badges, at most two, in the order the player
16352
+ arranged them. Always a list — empty when they wear none, or when their
16353
+ identity is withheld — so draw what is there and key on `itemId`.
16075
16354
 
16076
16355
  ## ShowcaseFriendEntry.playerId
16077
16356
 
@@ -1,6 +1,6 @@
1
1
  # The server surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v8.0.0. Every symbol below links to its page on the Gem Arcade developer site.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v8.1.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