@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.
- package/CHANGELOG.md +12 -0
- package/README.md +2 -2
- package/brand/ticket-hero-128.png +0 -0
- package/brand/ticket-hero-256.png +0 -0
- package/brand/ticket-hero-384.png +0 -0
- package/brand/ticket-hero-512.png +0 -0
- package/brand/ticket-hero-768.png +0 -0
- package/brand/ticket-icon-20-1.5x.png +0 -0
- package/brand/ticket-icon-20-1x.png +0 -0
- package/brand/ticket-icon-20-2x.png +0 -0
- package/brand/ticket-icon-20-3x.png +0 -0
- package/brand/ticket-icon-32-1.5x.png +0 -0
- package/brand/ticket-icon-32-1x.png +0 -0
- package/brand/ticket-icon-32-2x.png +0 -0
- package/brand/ticket-icon-32-3x.png +0 -0
- package/dist/gem-web-sdk.esm.js +1 -1
- package/dist/gem-web-sdk.function.js +1 -1
- package/dist/gem-web-sdk.game.js +2 -2
- package/dist/gem-web-sdk.min.js +2 -2
- package/dist/gem-web-sdk.sdk.js +2 -2
- package/dist/gem-web-sdk.server.js +1 -1
- package/docs/achievements.md +2 -2
- package/docs/api/api-reference-function.md +3 -3
- package/docs/api/api-reference-game.md +65 -32
- package/docs/api/api-reference-server.md +1 -1
- package/docs/api/reference.json +21 -21
- package/docs/arcade-avatars.md +3 -3
- package/docs/arcade-economy.md +37 -36
- package/docs/brand-art.md +31 -30
- package/docs/changelog.md +12 -0
- package/docs/daily-challenges.md +1 -1
- package/docs/game-economy-tutorial.md +14 -14
- package/docs/getting-started.md +3 -3
- package/docs/inventory-and-catalogs.md +29 -29
- package/docs/manifest.json +32 -32
- package/docs/platform-rules.md +2 -2
- package/docs/rewarded-ads.md +1 -1
- package/docs/saving-player-progress.md +1 -1
- package/docs/server-bundles.md +2 -2
- package/docs/serverless-functions.md +2 -2
- package/docs/trading-and-gifting.md +1 -1
- package/docs/what-a-game-must-do.md +57 -36
- package/package.json +1 -1
- 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
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
1023
|
-
`gem.settings.declare
|
|
1024
|
-
|
|
1025
|
-
|
|
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
|
|
1142
|
+
### Mirror your settings into the Arcade's menu: `gem.settings`
|
|
1142
1143
|
|
|
1143
|
-
Optional. The Arcade's Gem menu
|
|
1144
|
-
Arcade-wide ones
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
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,
|
|
1159
|
-
{ id: 'sfx', label: t('Sound effects'), kind: 'toggle', value: sfx.on,
|
|
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
|
-
-
|
|
1201
|
-
|
|
1202
|
-
|
|
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
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
sound-
|
|
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,
|
|
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.
|
|
1381
|
-
[`gem.settings`](#mirror-
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
1823
|
-
if (
|
|
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
package/schema/bridge.v1.json
CHANGED
|
@@ -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
|
-
"
|
|
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
|
|
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
|
|
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,
|
|
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
|
-
"
|
|
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
|
|
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
|
-
"
|
|
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",
|