@indiegems/gem-web-sdk 20.1.0 → 21.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.
- package/CHANGELOG.md +40 -0
- package/README.md +1 -0
- 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/brand/ticket-icon-ingame-20-1.5x.png +0 -0
- package/brand/ticket-icon-ingame-20-1x.png +0 -0
- package/brand/ticket-icon-ingame-20-2x.png +0 -0
- package/brand/ticket-icon-ingame-20-3x.png +0 -0
- package/brand/ticket-icon-ingame-32-1.5x.png +0 -0
- package/brand/ticket-icon-ingame-32-1x.png +0 -0
- package/brand/ticket-icon-ingame-32-2x.png +0 -0
- package/brand/ticket-icon-ingame-32-3x.png +0 -0
- package/brand/ticket-pile-1-128.png +0 -0
- package/brand/ticket-pile-1-256.png +0 -0
- package/brand/ticket-pile-1-384.png +0 -0
- package/brand/ticket-pile-1-512.png +0 -0
- package/brand/ticket-pile-1-768.png +0 -0
- package/brand/ticket-pile-2-128.png +0 -0
- package/brand/ticket-pile-2-256.png +0 -0
- package/brand/ticket-pile-2-384.png +0 -0
- package/brand/ticket-pile-2-512.png +0 -0
- package/brand/ticket-pile-2-768.png +0 -0
- package/dist/conformance.d.ts +1 -1
- package/dist/dev-tools.d.ts +1 -0
- package/dist/function.d.ts +11 -3
- package/dist/game.d.ts +79 -12
- package/dist/gem-web-sdk.bridge.js +2 -2
- package/dist/gem-web-sdk.conformance.js +3 -3
- package/dist/gem-web-sdk.dev-tools.js +2 -0
- package/dist/gem-web-sdk.esm.js +3 -3
- package/dist/gem-web-sdk.function.js +3 -3
- package/dist/gem-web-sdk.game.js +3 -3
- package/dist/gem-web-sdk.min.js +3 -3
- package/dist/gem-web-sdk.sdk.js +3 -3
- package/dist/gem-web-sdk.server.js +2 -2
- package/dist/index.d.ts +103 -48
- package/dist/sdk.d.ts +79 -12
- package/docs/analytics.md +12 -0
- package/docs/api/api-reference-function.md +14 -2
- package/docs/api/api-reference-game.md +357 -21
- package/docs/api/api-reference-server.md +1 -1
- package/docs/api/reference.json +413 -16
- package/docs/arcade-economy.md +2 -2
- package/docs/brand-art.md +65 -16
- package/docs/changelog.md +40 -0
- package/docs/game-economy-tutorial.md +6 -3
- package/docs/getting-started.md +122 -30
- package/docs/graphics-route.md +188 -0
- package/docs/inventory-and-catalogs.md +69 -27
- package/docs/manifest.json +23 -18
- package/docs/server-bundles.md +3 -3
- package/docs/what-a-game-must-do.md +33 -2
- package/package.json +5 -1
- package/schema/bridge.v1.json +263 -12
- package/schema/capabilities.public.json +26 -0
|
@@ -654,18 +654,25 @@ subject. [brand-art.md](brand-art.md) has both, how to draw them, and the rest o
|
|
|
654
654
|
|
|
655
655
|
### Being paid in one
|
|
656
656
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
|
662
|
-
|
|
|
663
|
-
|
|
664
|
-
|
|
657
|
+
**Spend platform currency with `gem.purchases.request`.** Every game sells for Gems, Coins or any
|
|
658
|
+
other platform currency through the arcade's buy sheet: the platform confirms the purchase with the
|
|
659
|
+
player, offers a guest an account, and processes the order. Build your shop's Buy button on it.
|
|
660
|
+
|
|
661
|
+
| Call | Who owns confirmation | Transport | Use it for |
|
|
662
|
+
| -------------------------------- | --------------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
663
|
+
| `gem.purchases.request(...)` | the platform | postMessage bridge; platform sheet always opens | **every platform-currency purchase** — answers `ok`, `declined` or `unavailable` |
|
|
664
|
+
| `gem.me.mutations.purchase(...)` | your game | direct authenticated SDK request; no bridge or platform sheet | recipes paid in your own game currency or items (`payment: { kind: 'configured' }`) |
|
|
665
|
+
|
|
666
|
+
`gem.me.mutations.purchase` with a `platform_currency` payment is **not for spending on
|
|
667
|
+
gemarcade.com**. A web guest has no account the platform lets spend, so gem-api refuses them
|
|
668
|
+
`guest_upgrade_required`; the SDK then hands the attempt to the arcade as a safety net (see
|
|
669
|
+
[Game-owned direct purchase](#game-owned-direct-purchase)), but that is a fallback for games that
|
|
670
|
+
have not moved yet, not a flow to design for. A game that spends directly today should move its Buy
|
|
671
|
+
button to `gem.purchases.request`.
|
|
665
672
|
|
|
666
673
|
#### Platform-owned purchase sheet
|
|
667
674
|
|
|
668
|
-
|
|
675
|
+
This is how a game spends platform currency. The arcade confirms and processes the purchase:
|
|
669
676
|
|
|
670
677
|
```js
|
|
671
678
|
const config = await gem.gameConfig.load();
|
|
@@ -705,8 +712,8 @@ button's handler, never from a timer or on load: without one the answer is `decl
|
|
|
705
712
|
`busy`, and nothing is shown. After a player cancels, the arcade answers further asks from your
|
|
706
713
|
game `busy` for a short, growing interval — do not re-ask on `cancelled`.
|
|
707
714
|
|
|
708
|
-
Hide
|
|
709
|
-
|
|
715
|
+
Hide your Buy button when `gem.frame.parentSupports('purchases')` is false: that parent cannot sell
|
|
716
|
+
for platform currency.
|
|
710
717
|
|
|
711
718
|
The sheet shows the item's or recipe's picture from its `icon_url`. You never write that field: it
|
|
712
719
|
is the `icon:` file you upload with your config (`icon: icons/extra-life.png` in the YAML, uploaded
|
|
@@ -731,7 +738,12 @@ backend it answers `undefined` by design: there, your placeholder is what you se
|
|
|
731
738
|
|
|
732
739
|
#### Game-owned direct purchase
|
|
733
740
|
|
|
734
|
-
|
|
741
|
+
The direct path submits an order from your game with no platform sheet. Its job is recipes paid in
|
|
742
|
+
your own game currency or items (`payment: { kind: 'configured' }`, below). It also accepts a
|
|
743
|
+
`platform_currency` payment, but **do not spend platform currency this way on gemarcade.com**: a
|
|
744
|
+
web guest is refused (below), and every game spends Gems and Coins through
|
|
745
|
+
[the sheet](#platform-owned-purchase-sheet). The form is documented for games that have not moved
|
|
746
|
+
yet:
|
|
735
747
|
|
|
736
748
|
```js
|
|
737
749
|
const result = await gem.me.mutations.purchase({
|
|
@@ -809,6 +821,35 @@ try {
|
|
|
809
821
|
Do not retry an unsafe write after a timeout; re-read inventory or use the returned order/purchase
|
|
810
822
|
ids for support.
|
|
811
823
|
|
|
824
|
+
**A guest is refused `guest_upgrade_required`, and you draw nothing.** The platform lets only a
|
|
825
|
+
player with an account spend Gems or Coins — which is why platform currency is spent through
|
|
826
|
+
[the sheet](#platform-owned-purchase-sheet), where the arcade handles a guest itself. This is the
|
|
827
|
+
safety net for a game that still spends directly. When a guest's direct purchase is refused, the SDK
|
|
828
|
+
hands the attempt to the arcade, which offers the player an account over your game, and your call
|
|
829
|
+
rejects at once with a `GemApiError` whose `code` is `guest_upgrade_required`. Treat it exactly
|
|
830
|
+
like a decline: return to the shop silently, with no sign-up, "log in to buy" or error screen of
|
|
831
|
+
your own — the arcade's is already showing. The `default` arm of the switch above must not draw
|
|
832
|
+
anything for it either, so give it a quiet case of its own:
|
|
833
|
+
|
|
834
|
+
```js
|
|
835
|
+
case 'guest_upgrade_required':
|
|
836
|
+
return; // the arcade is offering the player an account; draw nothing
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
If the player makes an account and buys the item from the arcade's sheet, the purchase completes
|
|
840
|
+
after your call has answered — sometimes after a reload. Hear it with `gem.purchases.onSettled`:
|
|
841
|
+
|
|
842
|
+
```js
|
|
843
|
+
gem.purchases.onSettled(({ kind, targetId, quantity }) => {
|
|
844
|
+
showGrantFeedback(targetId, quantity); // then re-read; the SDK already refreshed gem.me
|
|
845
|
+
});
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
The SDK confirms the purchase with the platform before it calls you, and refreshes `gem.me`, so
|
|
849
|
+
`gem.me.inventory.onChanged` fires too. It hears nothing on an arcade that does not support it, and
|
|
850
|
+
never for a purchase an `ok` already reported. This needs SDK 21.1.0 or later; an older build shows
|
|
851
|
+
the guest your `default` arm instead of the arcade's offer.
|
|
852
|
+
|
|
812
853
|
**`targetId` is the UUID, never the slug.** `config.item(...)` accepts either because it is your
|
|
813
854
|
local lookup. The purchase catalog is keyed by ids. Recipes also require `catalogId`.
|
|
814
855
|
|
|
@@ -817,21 +858,22 @@ local lookup. The purchase catalog is keyed by ids. Recipes also require `catalo
|
|
|
817
858
|
One vocabulary covers both paths: the sheet's `res.reason` and the direct path's `err.code` are
|
|
818
859
|
the same strings.
|
|
819
860
|
|
|
820
|
-
| Code | What happened
|
|
821
|
-
| --------------------------------------------------------------------------------------------------------------------- |
|
|
822
|
-
| `unknown_currency` | the slug is not an active platform currency
|
|
823
|
-
| `currency_not_in_game_payable` | the currency exists but cannot pay for game items
|
|
824
|
-
| `not_purchasable` | the target is not in the purchase catalog on this channel, or cannot be bought
|
|
825
|
-
| `no_price_in_currency` | the target has no price in that currency
|
|
826
|
-
| `busy` | a purchase is
|
|
827
|
-
| `cancelled` | the player dismissed the sheet
|
|
828
|
-
| `insufficient_funds` | the player cannot afford it
|
|
829
|
-
| `
|
|
830
|
-
| `
|
|
831
|
-
| `
|
|
832
|
-
| `
|
|
833
|
-
| `
|
|
834
|
-
| `
|
|
861
|
+
| Code | What happened | What to do |
|
|
862
|
+
| --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
863
|
+
| `unknown_currency` | the slug is not an active platform currency | write `ARCADE_TICKETS` or `GEMS`; the direct path's message lists what is active |
|
|
864
|
+
| `currency_not_in_game_payable` | the currency exists but cannot pay for game items | price in a currency `gemctl platform config` lists under `platform_prices` |
|
|
865
|
+
| `not_purchasable` | the target is not in the purchase catalog on this channel, or cannot be bought | send the id (not the slug); promote the config version that prices it |
|
|
866
|
+
| `no_price_in_currency` | the target has no price in that currency | ask in the currency it is priced in, or add the price |
|
|
867
|
+
| `busy` | a purchase is in flight, a sheet is open, or the arcade is offering a guest an account | ask again only from a fresh player action |
|
|
868
|
+
| `cancelled` | the player dismissed the sheet | nothing — return to the shop |
|
|
869
|
+
| `insufficient_funds` | the player cannot afford it | say so in your shop's words; never draw a top-up screen |
|
|
870
|
+
| `guest_upgrade_required` | the player is a guest; only an account may spend. Nothing was charged | nothing — the arcade offers them an account; draw no sign-up screen of your own |
|
|
871
|
+
| `price_mismatch`, `config_version_stale` | the price or config changed since your catalog read; nothing was charged | re-read the catalog and re-render |
|
|
872
|
+
| `platform_currency_unavailable` | the currency is not available to this purchase right now | show the store as unavailable |
|
|
873
|
+
| `not_available` | the recipe is outside its availability window, or inactive; nothing was charged | hide or disable the row until its window opens |
|
|
874
|
+
| `recipe_locked` | the recipe's prerequisites are not met; nothing was charged | show the lock from `recipeAvailability().lockReasons` |
|
|
875
|
+
| `recipe_on_cooldown`, `recipe_max_uses_exceeded`, `item_max_stack_exceeded`, `recipe_costs_unmet`, `quantity_invalid` | the recipe or item refused this purchase before any charge | reflect it on the row; `recipeAvailability` has the detail |
|
|
876
|
+
| `error` | anything else, or no reliable answer | one neutral "store unavailable"; after `unavailable`, re-read inventory |
|
|
835
877
|
|
|
836
878
|
Reasons are for your shop's state and your logs. Branch money on `outcome` and on a re-read of
|
|
837
879
|
inventory, never on a reason, and do not retry because of one.
|
package/docs/manifest.json
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"file": "analytics.md",
|
|
16
|
-
"sha256": "
|
|
17
|
-
"updated": "2026-
|
|
16
|
+
"sha256": "5814655859e3d6b223f94b71f1b064783b0f242d409c3ec3078089cb4b7c8ec5",
|
|
17
|
+
"updated": "2026-11-04T17:17:14Z"
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
"file": "arcade-and-store.md",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"file": "arcade-economy.md",
|
|
31
|
-
"sha256": "
|
|
32
|
-
"updated": "2026-
|
|
31
|
+
"sha256": "c0f25495a536d5facdbb63cbcd89acf558e2fe79d44f3a99d35284de1937fc42",
|
|
32
|
+
"updated": "2026-11-04T17:09:56Z"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"file": "async-opponents.md",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"file": "brand-art.md",
|
|
41
|
-
"sha256": "
|
|
42
|
-
"updated": "2026-
|
|
41
|
+
"sha256": "7d4d5c7226710742efdb958e10387d5e5a3de0622a686734c885720e16a5b128",
|
|
42
|
+
"updated": "2026-11-02T21:18:05Z"
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
"file": "branding.md",
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
"file": "changelog.md",
|
|
51
|
-
"sha256": "
|
|
52
|
-
"updated": "2026-11-
|
|
51
|
+
"sha256": "31164cb6810097240ce18733c76b45b0b3e5ba9cda6738bfce7e27503cd90ad1",
|
|
52
|
+
"updated": "2026-11-04T19:04:00Z"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"file": "daily-challenges.md",
|
|
@@ -73,18 +73,23 @@
|
|
|
73
73
|
},
|
|
74
74
|
{
|
|
75
75
|
"file": "game-economy-tutorial.md",
|
|
76
|
-
"sha256": "
|
|
77
|
-
"updated": "2026-
|
|
76
|
+
"sha256": "0ab25a9d69cf5e40351624355da5ef84e1431bf8a8a420e2c4d7350e20a5b1c5",
|
|
77
|
+
"updated": "2026-11-04T16:44:33Z"
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
"file": "getting-started.md",
|
|
81
|
-
"sha256": "
|
|
82
|
-
"updated": "2026-11-
|
|
81
|
+
"sha256": "4cb0f2fec9438cd03a2a785ad6247fe60b32d95c9a9fdcbf0e2cc4390c9f767a",
|
|
82
|
+
"updated": "2026-11-04T19:04:00Z"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"file": "graphics-route.md",
|
|
86
|
+
"sha256": "c71c826502b415a89dd069f79d22b82f7a9fe49c9da7f5e7a1052763c826f41f",
|
|
87
|
+
"updated": "2026-11-04T17:45:35Z"
|
|
83
88
|
},
|
|
84
89
|
{
|
|
85
90
|
"file": "inventory-and-catalogs.md",
|
|
86
|
-
"sha256": "
|
|
87
|
-
"updated": "2026-11-
|
|
91
|
+
"sha256": "2094c555eb5a1a3d817a597ac07b2b193077f92176eb9596c2ba3ed461363bb6",
|
|
92
|
+
"updated": "2026-11-04T16:43:14Z"
|
|
88
93
|
},
|
|
89
94
|
{
|
|
90
95
|
"file": "leaderboards.md",
|
|
@@ -138,8 +143,8 @@
|
|
|
138
143
|
},
|
|
139
144
|
{
|
|
140
145
|
"file": "server-bundles.md",
|
|
141
|
-
"sha256": "
|
|
142
|
-
"updated": "2026-11-
|
|
146
|
+
"sha256": "a0df89891432d799fe7ad59534c68265937fe5096739afa5fbe230de97837af3",
|
|
147
|
+
"updated": "2026-11-04T19:04:00Z"
|
|
143
148
|
},
|
|
144
149
|
{
|
|
145
150
|
"file": "serverless-functions-js.md",
|
|
@@ -163,8 +168,8 @@
|
|
|
163
168
|
},
|
|
164
169
|
{
|
|
165
170
|
"file": "what-a-game-must-do.md",
|
|
166
|
-
"sha256": "
|
|
167
|
-
"updated": "2026-11-
|
|
171
|
+
"sha256": "523886cf799570ab3631bbc9db11e03554d2ad403a1083d94038a48acd4fb611",
|
|
172
|
+
"updated": "2026-11-04T18:23:48Z"
|
|
168
173
|
}
|
|
169
174
|
]
|
|
170
175
|
}
|
package/docs/server-bundles.md
CHANGED
|
@@ -80,8 +80,8 @@ To check the download yourself: the package npm serves is, byte for byte, the fi
|
|
|
80
80
|
also publishes on its download host, with the hash beside it:
|
|
81
81
|
|
|
82
82
|
```bash
|
|
83
|
-
curl -fsSL -O https://downloads.gemarcade.com/sdk/
|
|
84
|
-
curl -fsSL https://downloads.gemarcade.com/sdk/
|
|
83
|
+
curl -fsSL -O https://downloads.gemarcade.com/sdk/v21.1.0/gem-web-sdk.tgz
|
|
84
|
+
curl -fsSL https://downloads.gemarcade.com/sdk/v21.1.0/gem-web-sdk.tgz.sri
|
|
85
85
|
openssl dgst -sha384 -binary gem-web-sdk.tgz | openssl base64 -A
|
|
86
86
|
```
|
|
87
87
|
|
|
@@ -550,7 +550,7 @@ document**, so the call shapes provably match the contract:
|
|
|
550
550
|
| Loot | `getDropRates` |
|
|
551
551
|
| Leaderboards | `getLeaderboard` (the whole board — seed a match from current ranks), `getEntityLeaderboard` (one entity's own runs, best first, with its personal best — the read for deciding a reward from what the player actually did). Not `getFriendLeaderboard`: that view is per viewer, so a credential with no player identity is refused |
|
|
552
552
|
| Transfers | `listTransfers`, `initiateInventoryTransfer`, `getTransferDetails`, `acceptTransfer`, `cancelInventoryTransfer`, `rejectTransfer` |
|
|
553
|
-
| Platform-funded purchases | `getPurchaseCatalog` — the catalog read only. A
|
|
553
|
+
| Platform-funded purchases | `getPurchaseCatalog` — the catalog read only. A player spends platform currency only through the arcade's purchase sheet, which their **client** opens with `gem.purchases.request` ([inventory-and-catalogs.md](inventory-and-catalogs.md#16-selling-for-a-platform-currency)). A dedicated server token names no player and cannot start one; have the player's client initiate it. |
|
|
554
554
|
| Game rooms | `getGameRoomV2`, `updateGameRoomV2`, `getRoomArgs`, `putRoomArgs`, `listGameRooms`, `closeGameRoom`, `kickPlayer`, `transferHostV2` — the reads pre-bound to your own room as `gem.room.get()` / `gem.room.args()`. [Below](#what-your-server-reads-at-startup) |
|
|
555
555
|
| Game config | `getChannelAssignment` — which config version your server's own channel is running, and a short-lived signed URL for that version's JSON. Pass `gem.identity.channel`: the read is fenced to your own game and channel |
|
|
556
556
|
| Room templates | `listResolvedTemplates`, `getResolvedTemplate` |
|
|
@@ -1454,6 +1454,36 @@ function frame(dt) {
|
|
|
1454
1454
|
kind draws that one and ignores the field.
|
|
1455
1455
|
- **No camera, no call.** A game with no camera to turn never calls `look`.
|
|
1456
1456
|
|
|
1457
|
+
## WebGL or WebGPU: ask before you make your renderer
|
|
1458
|
+
|
|
1459
|
+
Every game that renders with WebGL asks the SDK which renderer to make, just before it makes its
|
|
1460
|
+
first one, and follows the answer for every canvas on the page:
|
|
1461
|
+
|
|
1462
|
+
```js
|
|
1463
|
+
const { route, listed } = await gem.graphics.preferredRoute();
|
|
1464
|
+
```
|
|
1465
|
+
|
|
1466
|
+
`route` is `webgl` almost everywhere. It is `webgpu` only on a device the platform lists as broken
|
|
1467
|
+
on WebGL (today the Pixel 10's PowerVR D-Series GPU, on every route but Vulkan, where WebGL crashes
|
|
1468
|
+
the game in Chrome and the whole Arcade app), and only where WebGPU is available. `listed` is true
|
|
1469
|
+
on such a device. So:
|
|
1470
|
+
|
|
1471
|
+
- `route` is `webgpu`: make your WebGPU renderer, and check it really started on WebGPU (with
|
|
1472
|
+
three.js, `renderer.backend.isWebGPUBackend` after `await renderer.init()`). If it did not, draw
|
|
1473
|
+
your **safe WebGL recipe**.
|
|
1474
|
+
- `route` is `webgl` and `listed` is true: draw your safe WebGL recipe. For every listed device
|
|
1475
|
+
today that is no shadow maps.
|
|
1476
|
+
- Otherwise: your normal WebGL renderer.
|
|
1477
|
+
|
|
1478
|
+
That holds for every WebGL canvas the page makes, menus included: one crash takes every context on
|
|
1479
|
+
the page with it. Supporting both means `WebGLRenderer` by default plus `WebGPURenderer` only on
|
|
1480
|
+
listed devices, never `WebGPURenderer` everywhere, and custom GLSL needs a TSL port for WebGPU.
|
|
1481
|
+
The call is bounded: it resolves within 1 second by default, normally at once after
|
|
1482
|
+
`awaitBridge()`, and never rejects. Do not detect devices yourself; the list is the platform's and
|
|
1483
|
+
reaches your live game without a new build. [`graphics-route.md`](graphics-route.md) has the
|
|
1484
|
+
three.js pattern, what both renderers cost, and how to test each answer with the `gemGraphics`
|
|
1485
|
+
launch key.
|
|
1486
|
+
|
|
1457
1487
|
## Graphics quality: the Arcade picks the start, your game adapts
|
|
1458
1488
|
|
|
1459
1489
|
Players open a lot of games they have never played. Each one should open at a quality that suits
|
|
@@ -2258,8 +2288,9 @@ with your game's card, and shares it through its own sheet, copy or Share panel.
|
|
|
2258
2288
|
only where `gem.share.available` is true.
|
|
2259
2289
|
|
|
2260
2290
|
Two things before you reach for it: **call it from the click**, synchronously, never from a timer
|
|
2261
|
-
or after an `await`; and **never gate a reward on it**, because
|
|
2262
|
-
not even whether the
|
|
2291
|
+
or after an `await`; and **never gate a reward on it**, because nothing about the player comes
|
|
2292
|
+
back, not even whether they shared. Its promise rejects only when the Arcade refused the link,
|
|
2293
|
+
naming why, so catch it and log it.
|
|
2263
2294
|
[Linking to your game](getting-started.md#linking-to-your-game) is the section.
|
|
2264
2295
|
|
|
2265
2296
|
## If your game vibrates
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@indiegems/gem-web-sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "21.1.0",
|
|
4
4
|
"description": "postMessage bridge contract between gem-web and browser-playable games",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -39,6 +39,10 @@
|
|
|
39
39
|
"types": "./dist/quality.d.ts",
|
|
40
40
|
"import": "./dist/gem-web-sdk.quality.js"
|
|
41
41
|
},
|
|
42
|
+
"./dev-tools": {
|
|
43
|
+
"types": "./dist/dev-tools.d.ts",
|
|
44
|
+
"import": "./dist/gem-web-sdk.dev-tools.js"
|
|
45
|
+
},
|
|
42
46
|
"./conformance": {
|
|
43
47
|
"types": "./dist/conformance.d.ts",
|
|
44
48
|
"import": "./dist/gem-web-sdk.conformance.js"
|