@indiegems/gem-web-sdk 14.0.0 → 14.0.2

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 (44) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +2 -2
  3. package/brand/ticket-hero-128.png +0 -0
  4. package/brand/ticket-hero-256.png +0 -0
  5. package/brand/ticket-hero-384.png +0 -0
  6. package/brand/ticket-hero-512.png +0 -0
  7. package/brand/ticket-hero-768.png +0 -0
  8. package/brand/ticket-icon-20-1.5x.png +0 -0
  9. package/brand/ticket-icon-20-1x.png +0 -0
  10. package/brand/ticket-icon-20-2x.png +0 -0
  11. package/brand/ticket-icon-20-3x.png +0 -0
  12. package/brand/ticket-icon-32-1.5x.png +0 -0
  13. package/brand/ticket-icon-32-1x.png +0 -0
  14. package/brand/ticket-icon-32-2x.png +0 -0
  15. package/brand/ticket-icon-32-3x.png +0 -0
  16. package/dist/gem-web-sdk.esm.js +1 -1
  17. package/dist/gem-web-sdk.function.js +1 -1
  18. package/dist/gem-web-sdk.game.js +2 -2
  19. package/dist/gem-web-sdk.min.js +2 -2
  20. package/dist/gem-web-sdk.sdk.js +2 -2
  21. package/dist/gem-web-sdk.server.js +1 -1
  22. package/docs/achievements.md +2 -2
  23. package/docs/api/api-reference-function.md +3 -3
  24. package/docs/api/api-reference-game.md +65 -32
  25. package/docs/api/api-reference-server.md +1 -1
  26. package/docs/api/reference.json +21 -21
  27. package/docs/arcade-avatars.md +3 -3
  28. package/docs/arcade-economy.md +37 -36
  29. package/docs/brand-art.md +31 -30
  30. package/docs/changelog.md +12 -0
  31. package/docs/daily-challenges.md +1 -1
  32. package/docs/game-economy-tutorial.md +14 -14
  33. package/docs/getting-started.md +3 -3
  34. package/docs/inventory-and-catalogs.md +29 -29
  35. package/docs/manifest.json +32 -32
  36. package/docs/platform-rules.md +2 -2
  37. package/docs/rewarded-ads.md +1 -1
  38. package/docs/saving-player-progress.md +1 -1
  39. package/docs/server-bundles.md +2 -2
  40. package/docs/serverless-functions.md +2 -2
  41. package/docs/trading-and-gifting.md +1 -1
  42. package/docs/what-a-game-must-do.md +57 -36
  43. package/package.json +1 -1
  44. package/schema/bridge.v1.json +7 -7
@@ -507,7 +507,7 @@ unlock_celebration: arcade
507
507
  always get the Arcade's card, whatever you declare.
508
508
  - **Only the store page on `release` is read**, and it takes effect when that page is
509
509
  promoted. It is display-only, and it needs no `schema_version` change.
510
- - **Gems or Tickets paid in the same moment** still go through `gem.cueReward`, with
510
+ - **Gems or Coins paid in the same moment** still go through `gem.cueReward`, with
511
511
  no flight of your own.
512
512
 
513
513
  How your game learns an unlock happened, and the field's full rules, are in
@@ -618,7 +618,7 @@ there is no route by which the frame could request one. `createGem` forwards all
618
618
  player would mind losing there, and never hold it back for a terminate warning that may not come.
619
619
 
620
620
  **Re-read on resume.** Your game is told that it was paused and resumed, never why, and never
621
- what the player did in the meantime. Their Gems and Tickets can change while you are paused, so
621
+ what the player did in the meantime. Their Gems and Coins can change while you are paused, so
622
622
  if your game keeps anything worked out from a balance, such as a Buy button it greyed out or a
623
623
  "not enough Gems" line, read `gem.platform.currencies.get()` again on every `onPause(false)`
624
624
  rather than trusting what it read before the pause
@@ -731,10 +731,10 @@ game, a framed or full-window game on a desktop, a tablet or a TV in native full
731
731
 
732
732
  - **The Gem button**, the Gem Arcade's gem, always there (a 44px square touch target), in
733
733
  the **top-left corner** unless your game [asks for another](#moving-the-gem-gemsetgemcorner). It
734
- opens [the Arcade's menu](#the-arcades-menu): Return to the Arcade, the player's Gems, Tickets and
734
+ opens [the Arcade's menu](#the-arcades-menu): Return to the Arcade, the player's Gems, Coins and
735
735
  achievement score, mute, the player's Arcade-wide settings and the rest. Not your settings: those
736
736
  are [your own button](#game-settings).
737
- - **Nothing else.** The player's wallets (Gems, Tickets, their achievement score) are **not** drawn
737
+ - **Nothing else.** The player's wallets (Gems, Coins, their achievement score) are **not** drawn
738
738
  over your game: the player opens the Gem menu to see them, and every platform-currency payout
739
739
  flies into the Gem button ([the Arcade's wallet](#the-arcades-wallet-in-the-gem-menu-never-drawn-by-you)).
740
740
  When the player switches the frame-rate readout on, it sits beside the gem and is reserved the
@@ -1019,10 +1019,11 @@ This is the whole model, and every other page that mentions settings links here:
1019
1019
  them again on `onPrefs`. The Arcade never asks your game anything about them.
1020
1020
  - **Every game draws its own settings button, top-right ([the top of the
1021
1021
  screen](#the-top-of-the-screen)), and its own settings screen.** The Arcade's menu never opens it.
1022
- - **A game may also mirror up to eight of its own settings into the Arcade's menu**, with
1023
- `gem.settings.declare` — a second way to reach a few of them, never the only one, and never a
1024
- setting the Arcade already has ([mirror a few settings into the Arcade's
1025
- menu](#mirror-a-few-settings-into-the-arcades-menu-gemsettings)).
1022
+ - **A game should also declare its settings — all of them, up to eight — to the Arcade's menu**,
1023
+ with `gem.settings.declare`: the Arcade's Settings screen lists every one, and the first music
1024
+ and colour-help toggles fill the Music and Color slots of its fixed quick row. It is a second way
1025
+ to reach them, never the only one, and never a second mute or vibration switch ([mirror your
1026
+ settings into the Arcade's menu](#mirror-your-settings-into-the-arcades-menu-gemsettings)).
1026
1027
  - **A setting starts from `recommended` until the player changes it in your game, and then the
1027
1028
  player's choice in your game wins.** Save only what the player chose, never a recommended value.
1028
1029
  - **Where a choice is kept.** Device configuration — volume, graphics quality, look sensitivity, a
@@ -1138,13 +1139,22 @@ owns — starts from `recommended` the same way and is kept in `gem.me.settings`
1138
1139
  ([sound](#sound-your-own-mute-control-and-the-arcades)), and `reducedMotion` is the player's
1139
1140
  accessibility setting, which your game honours.
1140
1141
 
1141
- ### Mirror a few settings into the Arcade's menu: `gem.settings`
1142
+ ### Mirror your settings into the Arcade's menu: `gem.settings`
1142
1143
 
1143
- Optional. The Arcade's Gem menu can show a few of your game's own settings beside the player's
1144
- Arcade-wide ones: in its Settings screen, in a group named for your game above the player's
1145
- defaults for all games, and — for up to two toggles — in the menu's quick row, next to the
1146
- Arcade's own Sound and Vibration buttons. A player who opens the menu mid-game can turn your music
1147
- off without hunting for your settings screen.
1144
+ Optional, and worth doing. The Arcade's Gem menu shows your game's own settings beside the
1145
+ player's Arcade-wide ones, in two places:
1146
+
1147
+ - **Its Settings screen lists every setting you declare**, up to eight, in a group named for your
1148
+ game above the player's defaults for all games. So declare **all** of your game's settings that
1149
+ fit the three kinds below, not a chosen few: a player who opens the menu mid-game finds every one
1150
+ of them without hunting for your settings screen.
1151
+ - **Its quick row is fixed: Music, Sound, Color and Vibration, in that order**, with the Arcade's
1152
+ own labels; Vibration is there on phones and tablets only. Sound (your game's mute) and Vibration
1153
+ (the player's Arcade setting) are the Arcade's. Your game fills the other two: **Music** with the
1154
+ first `toggle` you declare with `icon: 'music'`, and **Color** with the first `toggle` you
1155
+ declare with `icon: 'eye'` — a colour-help, colour-blind or high-contrast switch. A slot your
1156
+ game does not fill stays in its place, greyed and inert. Nothing else of yours reaches the quick
1157
+ row.
1148
1158
 
1149
1159
  **It is a mirror, never a replacement: keep your own settings button and screen**, with every
1150
1160
  setting you declare on it too. An embedder that draws no game settings shows none of this, and the
@@ -1153,11 +1163,12 @@ that dropped its button because the Arcade's menu had its settings would have se
1153
1163
  reach.
1154
1164
 
1155
1165
  ```js
1156
- // Built from the same state your own settings screen shows.
1166
+ // Built from the same state your own settings screen shows: every setting on it.
1157
1167
  const declared = () => [
1158
- { id: 'music', label: t('Music'), kind: 'toggle', value: music.on, quick: true, icon: 'music' },
1159
- { id: 'sfx', label: t('Sound effects'), kind: 'toggle', value: sfx.on, quick: true, icon: 'sfx' },
1160
- { id: 'colors', label: t('Color help'), kind: 'toggle', value: colorHelp, icon: 'eye' },
1168
+ { id: 'music', label: t('Music'), kind: 'toggle', value: music.on, icon: 'music' }, // the quick row's Music
1169
+ { id: 'sfx', label: t('Sound effects'), kind: 'toggle', value: sfx.on, icon: 'sfx' },
1170
+ { id: 'colors', label: t('Color help'), kind: 'toggle', value: colorHelp, icon: 'eye' }, // its Color
1171
+ { id: 'musicVolume', label: t('Music volume'), kind: 'slider', value: musicVolume, min: 0, max: 100, step: 5 },
1161
1172
  { id: 'speed', label: t('Game speed'), kind: 'slider', value: speed, min: 0.5, max: 2, step: 0.25 },
1162
1173
  {
1163
1174
  id: 'difficulty',
@@ -1179,6 +1190,7 @@ gem.settings.onChange(({ id, value }) => {
1179
1190
  if (id === 'music') setMusic(value === true);
1180
1191
  if (id === 'sfx') setSfx(value === true);
1181
1192
  if (id === 'colors') setColorHelp(value === true);
1193
+ if (id === 'musicVolume') setMusicVolume(value);
1182
1194
  if (id === 'speed') setSpeed(value);
1183
1195
  if (id === 'difficulty') setDifficulty(value);
1184
1196
  keepChoice(id, value); // where your own screen keeps the same choice
@@ -1197,17 +1209,26 @@ musicToggle.onchange = () => {
1197
1209
  `choice` has two to four `options` and its `value` is one of their ids. `id` is your own name
1198
1210
  for the setting, 1 to 40 of `A-Z a-z 0-9 _ -`, unique. An entry that breaks a rule is left out
1199
1211
  with a warning on the console, and nothing throws.
1200
- - **Mark at most two toggles `quick`** — the ones a player reaches for mid-game: Music, Sound
1201
- effects, Color help. A third that asks is shown only in the list. `icon` is optional: `music`,
1202
- `sfx`, `voice`, `eye`, `text`, `hint`, `speed`, `bright`, `controls` or `star`.
1212
+ - **`icon` is what puts a toggle in the quick row.** Give `icon: 'music'` to your music on/off
1213
+ toggle and `icon: 'eye'` to your colour-help toggle, and to no other setting: only the first
1214
+ toggle with each fills its slot, and a later one is shown only in the Settings list. Elsewhere
1215
+ `icon` is optional and only picks the glyph: `music`, `sfx`, `voice`, `eye`, `text`, `hint`,
1216
+ `speed`, `bright`, `controls` or `star`.
1217
+ - **`quick` is ignored by the Gem Arcade.** The quick row is the fixed one above, so marking a
1218
+ toggle `quick` changes nothing there. The field stays in the type and on the wire for other
1219
+ embedders, which may still honour it on the first two toggles that ask; leaving it out is fine.
1203
1220
  - **Labels are already in the player's language** (`gem.prefs.locale`): the Arcade does not
1204
- translate them, and cuts them at 40 characters. Declare again when the language changes.
1205
- - **Never declare a setting the Arcade already has.** Master volume and mute, vibration, graphics
1206
- quality and the controls defaults (look sensitivity, invert, touch stick, keyboard layout,
1207
- confirm button) are in the Arcade's own settings and reach you as `gem.prefs` and
1208
- `gem.prefs.recommended`. A "Vibration", "Volume" or "Mute" of yours beside them is a second
1209
- switch for the same thing, and the player cannot tell which one wins. Your own music and
1210
- sound-effect levels are yours to declare.
1221
+ translate them, and cuts them at 40 characters. Declare again when the language changes. The
1222
+ quick row shows the Arcade's own labels; yours are what its Settings list shows.
1223
+ - **Never declare a second mute or vibration switch.** The quick row already has the Arcade's Sound
1224
+ (your game's mute) and Vibration (the player's Arcade setting); a "Mute", "Sound off" or
1225
+ "Vibration" of yours beside them is a second switch for the same thing, and the player cannot
1226
+ tell which one wins. **Your own levels are yours to declare**: a game volume, music volume or
1227
+ sound-effects volume is your game's level, which starts from the Arcade's `recommended` volume
1228
+ like any [game setting](#game-settings) and is set over it — and so are Music and Sound effects
1229
+ on/off toggles. Graphics quality and the controls defaults (look sensitivity, invert, touch stick,
1230
+ keyboard layout, confirm button) stay the Arcade's: they reach you as `gem.prefs.recommended`,
1231
+ and you do not declare them.
1211
1232
  - **It is screen state, not a toggle.** Each call is the whole list and replaces the last;
1212
1233
  `gem.settings.declare([])` takes them all back out. **Declare again whenever your own screen
1213
1234
  changes a value**, so the menu never shows a stale one. Before the Arcade connects the list is
@@ -1366,7 +1387,7 @@ What it does, so you know what to expect:
1366
1387
 
1367
1388
  The Arcade keeps one button over every game, on every device: the Gem, top-left unless your game
1368
1389
  [asks for another corner](#moving-the-gem-gemsetgemcorner). Its menu is
1369
- how a player leaves (**Return to the Arcade**), sees their Gems, Tickets and achievement score, mutes,
1390
+ how a player leaves (**Return to the Arcade**), sees their Gems, Coins and achievement score, mutes,
1370
1391
  goes fullscreen, reports a problem and changes their Arcade-wide settings — the ones that reach you as [`gem.prefs.recommended`](#game-settings). You can add up to
1371
1392
  four entries of your own:
1372
1393
 
@@ -1377,8 +1398,8 @@ gem.setMenu({
1377
1398
  ```
1378
1399
 
1379
1400
  - **Your settings screen is not in it.** It opens from [your own button](#game-settings), and the
1380
- Arcade's menu never opens it. A few of your settings can also appear in the Arcade's menu, with
1381
- [`gem.settings`](#mirror-a-few-settings-into-the-arcades-menu-gemsettings) — a mirror of your
1401
+ Arcade's menu never opens it. Your settings can also appear in the Arcade's menu, with
1402
+ [`gem.settings`](#mirror-your-settings-into-the-arcades-menu-gemsettings) — a mirror of your
1382
1403
  screen, never a replacement for it.
1383
1404
  - **`items` are up to four entries of your own**, shown in a group below the Arcade's. `id` is your
1384
1405
  name for the entry (1 to 32 characters); `label` is what the player reads, **already in their
@@ -1511,13 +1532,13 @@ and the release checklist checks that it does.
1511
1532
 
1512
1533
  ## The Arcade's wallet: in the Gem menu, never drawn by you
1513
1534
 
1514
- The player's platform balances — Gems, Tickets (`ARCADE_TICKETS`) and their achievement score —
1535
+ The player's platform balances — Gems, Coins (`ARCADE_TICKETS`) and their achievement score —
1515
1536
  belong to the Arcade. **Your game never draws one**, and never shows a pending state for one: the
1516
1537
  Arcade takes every figure from the platform and shows them itself.
1517
1538
 
1518
1539
  **The Gem Arcade draws no wallet over your game** (since 2026-10-11). Nothing of it sits in your top
1519
1540
  row, at rest or when a balance moves. The player opens the Gem menu — the Gem button, in whichever
1520
- corner it sits — to see their Gems, Tickets and achievement score, and every payout
1541
+ corner it sits — to see their Gems, Coins and achievement score, and every payout
1521
1542
  [`gem.cueReward`](inventory-and-catalogs.md#showing-the-reward-land-in-the-arcades-wallet) announces
1522
1543
  flies into the Gem button. A payout you do not cue flies too, from the middle of your frame, so cue
1523
1544
  the ones the player earns on screen and the flight starts where they are looking.
@@ -1804,7 +1825,7 @@ first:
1804
1825
  ### The signed-in player's Boost: show it, never gate on it
1805
1826
 
1806
1827
  `gem.player` also carries **`boost`** — the player's Boost, which the Arcade sells for real money.
1807
- While it lasts the player earns Gems and Tickets faster (never achievement points), and the
1828
+ While it lasts the player earns Gems and Coins faster (never achievement points), and the
1808
1829
  platform raises their earning limits to match. The platform does all of that on its own side when
1809
1830
  it pays; your game does nothing to make a boost work.
1810
1831
 
@@ -1819,8 +1840,8 @@ backend without boosts, a read that has not landed yet — it reads as **not boo
1819
1840
  player who has no boost.
1820
1841
 
1821
1842
  ```js
1822
- const tickets = gem.player?.boost.multipliers.find((m) => m.currencySlug === 'ARCADE_TICKETS');
1823
- if (tickets && tickets.multiplier > 1) rewardScreen.showBadge(`${tickets.multiplier}× Tickets`);
1843
+ const coins = gem.player?.boost.multipliers.find((m) => m.currencySlug === 'ARCADE_TICKETS');
1844
+ if (coins && coins.multiplier > 1) rewardScreen.showBadge(`${coins.multiplier}× Coins`);
1824
1845
  ```
1825
1846
 
1826
1847
  ⚠️ **It is for display, and only for display** — a "2×" badge on a reward screen. Never gate
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indiegems/gem-web-sdk",
3
- "version": "14.0.0",
3
+ "version": "14.0.2",
4
4
  "description": "postMessage bridge contract between gem-web and browser-playable games",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -774,7 +774,7 @@
774
774
  "The player's Boost, FOR DISPLAY ONLY — a platform rule, not advice. A",
775
775
  "Boost is something the Arcade sells for real money: it",
776
776
  "multiplies what the player EARNS in platform currencies (Gems and",
777
- "Tickets) and raises their earning limits. It never touches achievement",
777
+ "Coins) and raises their earning limits. It never touches achievement",
778
778
  "points.",
779
779
  "",
780
780
  "ADVISORY. It may lag: it is pushed on connect and again when the",
@@ -2737,9 +2737,9 @@
2737
2737
  "other, `gem.cueReward` returns false and the game does NOTHING. There is",
2738
2738
  "no fallback celebration: Gems display belongs to the arcade (the",
2739
2739
  "creator's ruling, 2026-09-24), so a game draws no Gems flight, counter or",
2740
- "celebration of its own. The same holds for Tickets (`ARCADE_TICKETS`):",
2740
+ "celebration of its own. The same holds for Coins (`ARCADE_TICKETS`):",
2741
2741
  "`currencySlug` decides what flies and which total moves. `origin` is the",
2742
- "centre of the game's icon for that currency — its gem, or its ticket."
2742
+ "centre of the game's icon for that currency — its gem, or its coin."
2743
2743
  ],
2744
2744
  "fields": {
2745
2745
  "currencySlug": { "kind": "string", "maxLength": 32 },
@@ -2761,7 +2761,7 @@
2761
2761
  "direction": "frameToParent",
2762
2762
  "transport": "port",
2763
2763
  "$comment": [
2764
- "Whether the arcade shows the player's platform wallets (Gems, Tickets, the",
2764
+ "Whether the arcade shows the player's platform wallets (Gems, Coins, the",
2765
2765
  "achievement score) over the game right now — and, optionally, which of them.",
2766
2766
  "",
2767
2767
  "OPT-OUT. With no message at all, the parent shows EVERY wallet: a game that",
@@ -2775,7 +2775,7 @@
2775
2775
  "",
2776
2776
  "The narrowing is in force when EITHER optional field is present, and is",
2777
2777
  "ignored while `visible` is false. It is for a screen about one currency (a",
2778
- "ticket store); leaving it out is always safe. `currencies` are platform",
2778
+ "Coins store); leaving it out is always safe. `currencies` are platform",
2779
2779
  "currency slugs (`GEMS`, `ARCADE_TICKETS`), matched exactly and",
2780
2780
  "case-sensitively against the wallets the parent draws; a slug it does not",
2781
2781
  "draw is ignored. `score` is its own field so it can never collide with a slug.",
@@ -3677,14 +3677,14 @@
3677
3677
  " `unknown_currency` or `currency_not_in_game_payable`. Resolve it EXACTLY,",
3678
3678
  " with no",
3679
3679
  " alias table of your own: the retired `TICKETS` meant GEMS, and resolving",
3680
- " it charged Gems to games that meant Tickets. An item may carry prices in",
3680
+ " it charged Gems to games that meant Coins. An item may carry prices in",
3681
3681
  " more than one payable currency, so",
3682
3682
  " the frame does choose which wallet pays; the prompt names that currency",
3683
3683
  " and its price from platform records, which keeps the choice the player's.",
3684
3684
  "",
3685
3685
  " A PAYABLE CURRENCY MAY BE ONE THE PLAYER BOUGHT. This shipped on the",
3686
3686
  " argument that a payable currency is only ever EARNED: short of Gems or",
3687
- " Tickets the answer was to go and play, and neither was sold for money.",
3687
+ " Coins the answer was to go and play, and neither was sold for money.",
3688
3688
  " That is no longer true of Gems. The arcade's own store sells them, and",
3689
3689
  " bought Gems stay payable in games (owner decision, 2026-10-06). So",
3690
3690
  " where a balance came from protects",