@indiegems/gem-web-sdk 21.1.1 → 23.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.
- package/CHANGELOG.md +61 -0
- package/dist/conformance.d.ts +4 -1
- package/dist/function.d.ts +10 -1
- package/dist/game.d.ts +46 -2
- package/dist/gem-web-sdk.bridge.js +2 -2
- package/dist/gem-web-sdk.conformance.js +3 -3
- 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-api.js +1 -1
- package/dist/gem-web-sdk.server.js +2 -2
- package/dist/index.d.ts +66 -6
- package/dist/sdk.d.ts +47 -2
- package/dist/server-api.d.ts +1 -0
- package/dist/server.d.ts +3 -0
- package/docs/api/api-reference-function.md +129 -9
- package/docs/api/api-reference-game.md +292 -13
- package/docs/api/api-reference-server.md +34 -1
- package/docs/api/reference.json +276 -10
- package/docs/arcade-economy.md +3 -1
- package/docs/changelog.md +61 -0
- package/docs/daily-challenges.md +3 -1
- package/docs/friends.md +120 -15
- package/docs/getting-started.md +7 -1
- package/docs/inventory-and-catalogs.md +86 -13
- package/docs/manifest.json +22 -22
- package/docs/rooms-and-matches.md +6 -3
- package/docs/server-bundles.md +2 -2
- package/docs/serverless-functions.md +38 -0
- package/docs/trading-and-gifting.md +12 -9
- package/docs/what-a-game-must-do.md +22 -1
- package/package.json +1 -1
- package/schema/bridge.v1.json +293 -1
- package/schema/capabilities.public.json +20 -0
package/schema/bridge.v1.json
CHANGED
|
@@ -1222,6 +1222,44 @@
|
|
|
1222
1222
|
"rateLimit": { "perMinute": 30 }
|
|
1223
1223
|
},
|
|
1224
1224
|
|
|
1225
|
+
{
|
|
1226
|
+
"type": "gem.inventoryChanged",
|
|
1227
|
+
"direction": "parentToFrame",
|
|
1228
|
+
"transport": "port",
|
|
1229
|
+
"$comment": [
|
|
1230
|
+
"Something in this player's inventory for THIS game and channel MAY have",
|
|
1231
|
+
"changed on the server, so the frame should re-read it with its own",
|
|
1232
|
+
"token if it shows it. Gated on `inventoryChanged`: a parent sends it",
|
|
1233
|
+
"only when `frameSupports('inventoryChanged')`.",
|
|
1234
|
+
"",
|
|
1235
|
+
"NO FIELDS, AND IT SHOULD STAY THAT WAY. The frame re-reads its own",
|
|
1236
|
+
"scope from gem-api, the authority, so the bridge never becomes a second",
|
|
1237
|
+
"source of truth for a balance or an item. This message never carries",
|
|
1238
|
+
"an item, a quantity, a balance, an order, an entity, a source or any",
|
|
1239
|
+
"game's id: it says only that a change happened, around now.",
|
|
1240
|
+
"",
|
|
1241
|
+
"WHEN A PARENT MAY SEND IT: on gem-api's `game_inventory_changed` socket",
|
|
1242
|
+
"event, only when its `game_id` is the game this session's token was",
|
|
1243
|
+
"granted for and its `channel` is that token's channel, and only after",
|
|
1244
|
+
"that token was sent. NEVER for another game's scope, another channel's,",
|
|
1245
|
+
"or the platform wallet (`platform_grant_fired` and the other wallet",
|
|
1246
|
+
"events): that send would tell this game, to the second, when another",
|
|
1247
|
+
"game or the platform paid the player -- a timing oracle for payouts",
|
|
1248
|
+
"this game is otherwise never shown. Nothing from the socket event's",
|
|
1249
|
+
"payload is copied. It should coalesce a burst -- one send now, then at",
|
|
1250
|
+
"most one trailing send every two seconds -- so a function that grants",
|
|
1251
|
+
"in a loop stays inside the limit.",
|
|
1252
|
+
"",
|
|
1253
|
+
"A HINT, NOT A RECEIPT. A game that granted through its own function",
|
|
1254
|
+
"already has the function's answer, which is the receipt; this is the",
|
|
1255
|
+
"cue to redraw from a fresh read. An embedder that never sends it is not",
|
|
1256
|
+
"defective. The SDK drops its cached reads of the game's inventory and",
|
|
1257
|
+
"makes no request because of it."
|
|
1258
|
+
],
|
|
1259
|
+
"fields": {},
|
|
1260
|
+
"rateLimit": { "perMinute": 30 }
|
|
1261
|
+
},
|
|
1262
|
+
|
|
1225
1263
|
{
|
|
1226
1264
|
"type": "gem.viewport",
|
|
1227
1265
|
"direction": "parentToFrame",
|
|
@@ -2947,10 +2985,24 @@
|
|
|
2947
2985
|
"creator's ruling, 2026-09-24), so a game draws no Gems flight, counter or",
|
|
2948
2986
|
"celebration of its own. The same holds for Coins (`ARCADE_TICKETS`):",
|
|
2949
2987
|
"`currencySlug` decides what flies and which total moves. `origin` is the",
|
|
2950
|
-
"centre of the game's icon for that currency — its gem, or its coin."
|
|
2988
|
+
"centre of the game's icon for that currency — its gem, or its coin.",
|
|
2989
|
+
"",
|
|
2990
|
+
"`cueId` ties this cue to the grant it announces, so the arcade flies that",
|
|
2991
|
+
"reward ONCE whichever of the two reaches it first. The game chooses it —",
|
|
2992
|
+
"one `crypto.randomUUID()` per award — and passes the same one to the",
|
|
2993
|
+
"`gem.functions.invoke` that pays, which carries it to gem-api as the",
|
|
2994
|
+
"`cue_id` query parameter; gem-api echoes it as `cue_id` on every",
|
|
2995
|
+
"`platform_grant_fired` that invocation's grants send. Opaque and for",
|
|
2996
|
+
"animation only: it moves no balance, never names an order, and is never",
|
|
2997
|
+
"rendered. The SDK sends only 1 to 64 letters, digits, `_` or `-`; the",
|
|
2998
|
+
"wire bounds the length alone (no `format`, so a parent need not learn",
|
|
2999
|
+
"one), and a parent that compares it rechecks the characters itself and",
|
|
3000
|
+
"drops a malformed one, keeping the cue. Absent, the arcade pairs the cue",
|
|
3001
|
+
"and the grant by currency and timing, as before."
|
|
2951
3002
|
],
|
|
2952
3003
|
"fields": {
|
|
2953
3004
|
"currencySlug": { "kind": "string", "maxLength": 32 },
|
|
3005
|
+
"cueId": { "kind": "string", "maxLength": 64, "optional": true },
|
|
2954
3006
|
"expected": { "kind": "int", "min": 1, "max": 1000000000, "optional": true },
|
|
2955
3007
|
"origin": {
|
|
2956
3008
|
"kind": "object",
|
|
@@ -2964,6 +3016,59 @@
|
|
|
2964
3016
|
"rateLimit": { "perMinute": 60 }
|
|
2965
3017
|
},
|
|
2966
3018
|
|
|
3019
|
+
{
|
|
3020
|
+
"type": "gem.rewardPresentation",
|
|
3021
|
+
"direction": "frameToParent",
|
|
3022
|
+
"transport": "port",
|
|
3023
|
+
"$comment": [
|
|
3024
|
+
"Who decides WHEN a platform-currency payout from this game is shown landing:",
|
|
3025
|
+
"the arcade (`arcade`, what a parent does with no message at all) or the game",
|
|
3026
|
+
"(`game`). It changes the presentation only. What is paid, when the server pays",
|
|
3027
|
+
"it, the receipt, every ceiling and the player's ledger are the same either way.",
|
|
3028
|
+
"",
|
|
3029
|
+
"`arcade`: a payout the game cues within a beat of it flies from the cue's",
|
|
3030
|
+
"`origin`, and one it does not flies from the middle of the frame. A cue that",
|
|
3031
|
+
"arrives after its payout was already shown adds nothing.",
|
|
3032
|
+
"",
|
|
3033
|
+
"`game`: the game's cue supplies the moment and the payout supplies the number.",
|
|
3034
|
+
"A parent adds each payout to an amount it HOLDS for that currency instead of",
|
|
3035
|
+
"showing it, and its own wallet readout over the game shows the true total",
|
|
3036
|
+
"minus what it still holds, so a spend or a payout from anywhere else still",
|
|
3037
|
+
"moves it at once. A `gem.rewardCue` releases up to its `expected` of the held",
|
|
3038
|
+
"amount, or all of it when it names none, flying from its `origin`. A cue that",
|
|
3039
|
+
"finds nothing held waits for the next payout of its currency, as in `arcade`.",
|
|
3040
|
+
"So payouts and cues meet in either order and several at once need no pairing.",
|
|
3041
|
+
"Whatever part of a payout no cue has released within five minutes of its",
|
|
3042
|
+
"arrival lands quietly, with no flight: a game can delay its payout's",
|
|
3043
|
+
"presentation, never hide it.",
|
|
3044
|
+
"",
|
|
3045
|
+
"A cue still adds nothing to a wallet: what lands is always the payout's own",
|
|
3046
|
+
"figure. The parent's other surfaces (its menu, its header, every purchase)",
|
|
3047
|
+
"read the true total the moment the payout lands, so a held readout never stops",
|
|
3048
|
+
"a player spending what they have.",
|
|
3049
|
+
"",
|
|
3050
|
+
"SCREEN STATE, NOT A TOGGLE, like `gem.gemCorner`. Each message is the whole",
|
|
3051
|
+
"answer and the latest one wins. The SDK holds it from before the bridge is up",
|
|
3052
|
+
"and re-sends it after every handshake, so a parent that reconnects presents",
|
|
3053
|
+
"the way the game had asked. A switch back to `arcade` lands what is held.",
|
|
3054
|
+
"",
|
|
3055
|
+
"A PRESENTATION REQUEST ONLY, and not an authorization control. Cosmetic:",
|
|
3056
|
+
"nothing may key a trust decision on it.",
|
|
3057
|
+
"",
|
|
3058
|
+
"Gated by `rewardPresentation`: sent only to a parent that advertised it. To",
|
|
3059
|
+
"any other, `gem.setRewardPresentation` returns false, and that parent presents",
|
|
3060
|
+
"every payout the `arcade` way."
|
|
3061
|
+
],
|
|
3062
|
+
"fields": {
|
|
3063
|
+
"mode": {
|
|
3064
|
+
"kind": "enum",
|
|
3065
|
+
"values": ["arcade", "game"],
|
|
3066
|
+
"$comment": "`game` holds each payout's presentation for the game's cue; `arcade` is the default, for a parent that has had no message."
|
|
3067
|
+
}
|
|
3068
|
+
},
|
|
3069
|
+
"rateLimit": { "perMinute": 12 }
|
|
3070
|
+
},
|
|
3071
|
+
|
|
2967
3072
|
{
|
|
2968
3073
|
"type": "gem.walletDisplay",
|
|
2969
3074
|
"direction": "frameToParent",
|
|
@@ -5215,6 +5320,193 @@
|
|
|
5215
5320
|
},
|
|
5216
5321
|
"rateLimit": { "perMinute": 30 }
|
|
5217
5322
|
},
|
|
5323
|
+
{
|
|
5324
|
+
"type": "gem.requestPlayInvite",
|
|
5325
|
+
"direction": "frameToParent",
|
|
5326
|
+
"transport": "port",
|
|
5327
|
+
"$comment": [
|
|
5328
|
+
"Ask the parent to open ITS OWN invite-to-play sheet for this game, so",
|
|
5329
|
+
"the player can invite friends to come and play it with them - the",
|
|
5330
|
+
"\"Invite friends\" button of a lobby or a hub. Gated by the",
|
|
5331
|
+
"`playInvites` capability. Answered by `gem.playInviteResult`.",
|
|
5332
|
+
"",
|
|
5333
|
+
"A PLATFORM DECISION: DESIGN.md section 10's eighth amendment,",
|
|
5334
|
+
"decided by the platform owner on 2026-11-04, amending its 'no",
|
|
5335
|
+
"invites in the frame'. The sheet is the Arcade's own Friends window,",
|
|
5336
|
+
"the one the player also opens from the Arcade's menu.",
|
|
5337
|
+
"",
|
|
5338
|
+
"WHY THIS CROSSES THE BRIDGE AT ALL. A game knows the moment an invite is",
|
|
5339
|
+
"worth offering - a lobby with an empty seat, a hub the player just",
|
|
5340
|
+
"reached - but an invite puts a notice in front of another person, which",
|
|
5341
|
+
"is an account-session act the game-scoped token is refused by",
|
|
5342
|
+
"construction, and the friends worth inviting are chosen by their",
|
|
5343
|
+
"presence, which never reaches a frame. So the game ASKS, and the parent,",
|
|
5344
|
+
"which holds the account session, renders its own sheet of the player's",
|
|
5345
|
+
"friends and sends an invite only on the player's own press in it.",
|
|
5346
|
+
"",
|
|
5347
|
+
"A CORRELATOR AND, OPTIONALLY, THE GAME'S LAUNCH PARAMS, deliberately",
|
|
5348
|
+
"nothing more. The params say what the window's link and invites open,",
|
|
5349
|
+
"as a share's do, and name nobody. No player id: a game",
|
|
5350
|
+
"that could name the friend would be choosing whom the platform notifies,",
|
|
5351
|
+
"and could learn from the answer whether that friend is reachable. No",
|
|
5352
|
+
"game id and no channel: the parent takes both from what it framed. No",
|
|
5353
|
+
"text: what the sheet and the invite say is the platform's own.",
|
|
5354
|
+
"",
|
|
5355
|
+
"WHAT THE PARENT OWES, none of which this schema can enforce:",
|
|
5356
|
+
"",
|
|
5357
|
+
" ADVERTISE IT AS A DEPLOYMENT-WIDE FACT, never by account state, and",
|
|
5358
|
+
" only once the platform has decided it. A guest, or a player with no",
|
|
5359
|
+
" friends, is the parent's to explain in its own chrome or to answer",
|
|
5360
|
+
" `shown: false`; a token that blinked with sign-in would move that",
|
|
5361
|
+
" disclosure into the handshake.",
|
|
5362
|
+
"",
|
|
5363
|
+
" CHECK ACTIVATION ON RECEIPT. Read `navigator.userActivation.isActive`",
|
|
5364
|
+
" synchronously when the message arrives, before any `await`, and answer",
|
|
5365
|
+
" an ask that arrives without it `shown: false` with nothing rendered.",
|
|
5366
|
+
" The frame chooses the moment it asks; the player's press is what makes",
|
|
5367
|
+
" a sheet over their game wanted rather than a nag.",
|
|
5368
|
+
"",
|
|
5369
|
+
" ONE SHEET AT A TIME, AND CAPPED. An ask arriving while this sheet - or",
|
|
5370
|
+
" any other sheet that holds the stage: a purchase, a sign-in prompt, a",
|
|
5371
|
+
" friend challenge - is open is answered `shown: false` with nothing",
|
|
5372
|
+
" rendered, and the open invite sheet holds the stage against those asks",
|
|
5373
|
+
" too. A short cooldown after the player closes one is the parent's",
|
|
5374
|
+
" call.",
|
|
5375
|
+
"",
|
|
5376
|
+
" RENDER ONLY FROM PLATFORM RECORDS. The friends, their presence and the",
|
|
5377
|
+
" game's name come from the parent's own reads, never from the frame.",
|
|
5378
|
+
" Each Invite press is one account-session send.",
|
|
5379
|
+
"",
|
|
5380
|
+
" PAUSE THE GAME while the sheet is open (`gem.pause`) and lift it when",
|
|
5381
|
+
" the sheet closes, returning focus to the frame.",
|
|
5382
|
+
"",
|
|
5383
|
+
" ANSWER ONCE, AS THE SHEET OPENS. `shown: true` once it has painted,",
|
|
5384
|
+
" not when it closes: how long the player browsed, and what they did in",
|
|
5385
|
+
" it, are theirs.",
|
|
5386
|
+
"",
|
|
5387
|
+
"NOT AN AUTHORIZATION CONTROL. The player's Invite press in the parent's",
|
|
5388
|
+
"chrome is the control, and the platform's account-session send is the",
|
|
5389
|
+
"enforcement: it re-checks the friendship, blocks and every budget,",
|
|
5390
|
+
"whatever reached it."
|
|
5391
|
+
],
|
|
5392
|
+
"fields": {
|
|
5393
|
+
"requestId": {
|
|
5394
|
+
"kind": "string",
|
|
5395
|
+
"maxLength": 64,
|
|
5396
|
+
"$comment": "Opaque and frame-chosen. The parent treats it as an echo-only correlator, exactly as it does for gem.requestFriendChallenge - it is not unique across tabs or reloads and must never key anything. It may also contain newlines and control characters, so it is not safe to write into a log line unescaped."
|
|
5397
|
+
},
|
|
5398
|
+
"params": {
|
|
5399
|
+
"kind": "array",
|
|
5400
|
+
"maxItems": 16,
|
|
5401
|
+
"optional": true,
|
|
5402
|
+
"$comment": [
|
|
5403
|
+
"The game's own launch parameters for what the invite and the",
|
|
5404
|
+
"window's share link open - `{ room: <join code> }` for a game whose",
|
|
5405
|
+
"rooms are joined by code. The same shape, grammar and reserved-key",
|
|
5406
|
+
"rules as `gem.requestShare.params`: the window's share link and its",
|
|
5407
|
+
"friend invites carry the same params, so a friend who accepts and a",
|
|
5408
|
+
"stranger who opens the link arrive the same way. ABSENT: the parent",
|
|
5409
|
+
"uses the params the game last declared with `gem.inviteParams`, or",
|
|
5410
|
+
"none. PRESENT, even empty: these, for this one opening.",
|
|
5411
|
+
"",
|
|
5412
|
+
"The parent applies the share rules to them and answers `shown:",
|
|
5413
|
+
"false`, rendering nothing, for anything it would refuse. They name",
|
|
5414
|
+
"what the link opens, never a person."
|
|
5415
|
+
],
|
|
5416
|
+
"items": {
|
|
5417
|
+
"kind": "object",
|
|
5418
|
+
"fields": {
|
|
5419
|
+
"key": { "kind": "string", "maxLength": 64 },
|
|
5420
|
+
"value": { "kind": "string", "maxLength": 512 }
|
|
5421
|
+
}
|
|
5422
|
+
}
|
|
5423
|
+
}
|
|
5424
|
+
},
|
|
5425
|
+
"rateLimit": {
|
|
5426
|
+
"perMinute": 6,
|
|
5427
|
+
"$comment": "Bounds a BUGGY game. NOT a security control: a hostile game posts on the port it holds rather than calling the SDK. What stops a game nagging is the parent's activation check, its one-sheet-at-a-time rule and the player's own Invite press."
|
|
5428
|
+
}
|
|
5429
|
+
},
|
|
5430
|
+
{
|
|
5431
|
+
"type": "gem.playInviteResult",
|
|
5432
|
+
"direction": "parentToFrame",
|
|
5433
|
+
"transport": "port",
|
|
5434
|
+
"$comment": [
|
|
5435
|
+
"The answer to one gem.requestPlayInvite. Gated by the `playInvites`",
|
|
5436
|
+
"capability.",
|
|
5437
|
+
"",
|
|
5438
|
+
"ONE BOOLEAN, AND NOTHING ELSE. `shown: true` - the parent opened its",
|
|
5439
|
+
"invite sheet. `shown: false` - nothing was rendered: no activation,",
|
|
5440
|
+
"another sheet held the stage, a guest, a parent with no sheet to offer.",
|
|
5441
|
+
"",
|
|
5442
|
+
"WHAT THE FRAME NEVER LEARNS, and a parent must not attach: whom the",
|
|
5443
|
+
"player invited, how many, whether any invite was sent, delivered or",
|
|
5444
|
+
"accepted, or why nothing was shown. Who the player invites is a fact",
|
|
5445
|
+
"about the people they know, and whether an invite landed is a fact about",
|
|
5446
|
+
"a stranger's settings; neither is the game's. So `shown: true` grants",
|
|
5447
|
+
"nothing and is no sign anything was sent - a game never gates a reward",
|
|
5448
|
+
"on it. A",
|
|
5449
|
+
"friend who accepts arrives the ordinary way: the Arcade opens the game",
|
|
5450
|
+
"for them, and its own quick-join seats them beside the player.",
|
|
5451
|
+
"",
|
|
5452
|
+
"PERMANENTLY A BOOLEAN. A field reporting the outcome would undo the",
|
|
5453
|
+
"amendment this pair rides on (DESIGN.md section 10, pending the",
|
|
5454
|
+
"platform's decision)."
|
|
5455
|
+
],
|
|
5456
|
+
"fields": {
|
|
5457
|
+
"requestId": {
|
|
5458
|
+
"kind": "string",
|
|
5459
|
+
"maxLength": 64,
|
|
5460
|
+
"$comment": "Echoes the gem.requestPlayInvite that asked. Echo-only."
|
|
5461
|
+
},
|
|
5462
|
+
"shown": {
|
|
5463
|
+
"kind": "boolean",
|
|
5464
|
+
"$comment": "Whether the parent opened its invite sheet. It grants nothing, and says nothing about whether anyone was invited."
|
|
5465
|
+
}
|
|
5466
|
+
},
|
|
5467
|
+
"rateLimit": { "perMinute": 12 }
|
|
5468
|
+
},
|
|
5469
|
+
{
|
|
5470
|
+
"type": "gem.inviteParams",
|
|
5471
|
+
"direction": "frameToParent",
|
|
5472
|
+
"transport": "port",
|
|
5473
|
+
"$comment": [
|
|
5474
|
+
"A standing declaration: the launch parameters the Arcade's Friends",
|
|
5475
|
+
"window should carry when the PLAYER opens it from the Arcade's own",
|
|
5476
|
+
"menu, over this game - its share link and its friend invites alike.",
|
|
5477
|
+
"Gated by the `playInvites` capability. Nothing answers it.",
|
|
5478
|
+
"",
|
|
5479
|
+
"A game sends it when it enters a room joined by code (`{ room:",
|
|
5480
|
+
"<join code> }`) and clears it - `params` absent - when it leaves. The",
|
|
5481
|
+
"latest one stands until the next, and an explicit",
|
|
5482
|
+
"`gem.requestPlayInvite` carrying `params` wins for that one opening.",
|
|
5483
|
+
"The SDK re-sends the latest on every handshake, so a fresh parent",
|
|
5484
|
+
"holds what the game last said.",
|
|
5485
|
+
"",
|
|
5486
|
+
"THE SAME PARAMS AS A SHARE, on the same rules. They name what a link",
|
|
5487
|
+
"opens and never a person: no player, no game id and no channel",
|
|
5488
|
+
"travel. The parent applies the share rules to them when it uses",
|
|
5489
|
+
"them, and leaves a link it would refuse unbuilt rather than",
|
|
5490
|
+
"carrying it. Sending one changes nothing on screen and tells the",
|
|
5491
|
+
"game nothing."
|
|
5492
|
+
],
|
|
5493
|
+
"fields": {
|
|
5494
|
+
"params": {
|
|
5495
|
+
"kind": "array",
|
|
5496
|
+
"maxItems": 16,
|
|
5497
|
+
"optional": true,
|
|
5498
|
+
"$comment": "The declared params, in order; the shape, grammar and reserved-key rules of `gem.requestShare.params`. ABSENT clears the declaration.",
|
|
5499
|
+
"items": {
|
|
5500
|
+
"kind": "object",
|
|
5501
|
+
"fields": {
|
|
5502
|
+
"key": { "kind": "string", "maxLength": 64 },
|
|
5503
|
+
"value": { "kind": "string", "maxLength": 512 }
|
|
5504
|
+
}
|
|
5505
|
+
}
|
|
5506
|
+
}
|
|
5507
|
+
},
|
|
5508
|
+
"rateLimit": { "perMinute": 30 }
|
|
5509
|
+
},
|
|
5218
5510
|
{
|
|
5219
5511
|
"type": "gem.requestAppLinks",
|
|
5220
5512
|
"direction": "frameToParent",
|
|
@@ -46,6 +46,14 @@
|
|
|
46
46
|
"gem.friendChallengeResult"
|
|
47
47
|
]
|
|
48
48
|
},
|
|
49
|
+
"playInvites": {
|
|
50
|
+
"implemented": true,
|
|
51
|
+
"gates": [
|
|
52
|
+
"gem.requestPlayInvite",
|
|
53
|
+
"gem.playInviteResult",
|
|
54
|
+
"gem.inviteParams"
|
|
55
|
+
]
|
|
56
|
+
},
|
|
49
57
|
"devtools": {
|
|
50
58
|
"implemented": true,
|
|
51
59
|
"gates": [
|
|
@@ -141,6 +149,12 @@
|
|
|
141
149
|
"gem.rewardCue"
|
|
142
150
|
]
|
|
143
151
|
},
|
|
152
|
+
"rewardPresentation": {
|
|
153
|
+
"implemented": true,
|
|
154
|
+
"gates": [
|
|
155
|
+
"gem.rewardPresentation"
|
|
156
|
+
]
|
|
157
|
+
},
|
|
144
158
|
"frameStats": {
|
|
145
159
|
"implemented": true,
|
|
146
160
|
"gates": [
|
|
@@ -207,6 +221,12 @@
|
|
|
207
221
|
"gem.earnAllowanceChanged"
|
|
208
222
|
]
|
|
209
223
|
},
|
|
224
|
+
"inventoryChanged": {
|
|
225
|
+
"implemented": true,
|
|
226
|
+
"gates": [
|
|
227
|
+
"gem.inventoryChanged"
|
|
228
|
+
]
|
|
229
|
+
},
|
|
210
230
|
"deviceSettings": {
|
|
211
231
|
"implemented": true,
|
|
212
232
|
"gates": [
|