@indiegems/gem-web-sdk 13.0.0 → 13.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` v13.0.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v13.1.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
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
 
@@ -3925,6 +3925,100 @@ for the avatars already worn when you subscribe: read
3925
3925
 
3926
3926
  **Returns.** a function that stops the calls. Calling it twice is harmless.
3927
3927
 
3928
+ <a id="avatarrignode"></a>
3929
+
3930
+ ## AvatarRigNode
3931
+
3932
+ ```ts
3933
+ interface AvatarRigNode
3934
+ ```
3935
+
3936
+ One node of a rig family's tree: its exact, case-sensitive name, and the
3937
+ name of the node it is a DIRECT child of. `parent` is `null` for the rig's
3938
+ root, which is a root node of the scene.
3939
+
3940
+ <a id="avatarrignode-node"></a>
3941
+
3942
+ ## AvatarRigNode.node
3943
+
3944
+ ```ts
3945
+ readonly node: string
3946
+ ```
3947
+
3948
+ The node's name, exact and case-sensitive.
3949
+
3950
+ <a id="avatarrignode-parent"></a>
3951
+
3952
+ ## AvatarRigNode.parent
3953
+
3954
+ ```ts
3955
+ readonly parent: string | null
3956
+ ```
3957
+
3958
+ The node it is a direct child of; `null` for the rig's root.
3959
+
3960
+ <a id="avatarrigs"></a>
3961
+
3962
+ ## AvatarRigs
3963
+
3964
+ ```ts
3965
+ interface AvatarRigs
3966
+ ```
3967
+
3968
+ The rig families this SDK knows, by name.
3969
+
3970
+ <a id="avatarrigs-small_human"></a>
3971
+
3972
+ ## AvatarRigs.small_human
3973
+
3974
+ ```ts
3975
+ readonly small_human: readonly AvatarRigNode[]
3976
+ ```
3977
+
3978
+ The toy rig: rigid limbs on a body, eight nodes.
3979
+
3980
+ <a id="avatarrigs-adult_human"></a>
3981
+
3982
+ ## AvatarRigs.adult_human
3983
+
3984
+ ```ts
3985
+ readonly adult_human: readonly AvatarRigNode[]
3986
+ ```
3987
+
3988
+ The adult humanoid with fingers: 56 nodes, world-aligned at rest.
3989
+
3990
+ <a id="avatar_rigs"></a>
3991
+
3992
+ ## AVATAR_RIGS
3993
+
3994
+ ```ts
3995
+ AVATAR_RIGS: AvatarRigs
3996
+ ```
3997
+
3998
+ Every node each rig family requires, with the node it is a direct child of,
3999
+ parents before children. Frozen: read it, never change it.
4000
+
4001
+ The platform refuses an upload whose model is missing one of these, has one
4002
+ under another parent, or has one twice (`rig_mismatch`). Extra nodes are
4003
+ allowed anywhere. `adult_human` also requires every one of its nodes to be
4004
+ world-aligned at rest; that rule is not in this list, see the guide.
4005
+
4006
+ ```js
4007
+ import { AVATAR_RIGS } from '@indiegems/gem-web-sdk/sdk';
4008
+
4009
+ // Every joint of the worn avatar, by name.
4010
+ const joints = new Map(
4011
+ AVATAR_RIGS.adult_human.map(({ node }) => [node, gltf.scene.getObjectByName(node)]),
4012
+ );
4013
+
4014
+ // A test that one of your own models is on the rig.
4015
+ for (const { node, parent } of AVATAR_RIGS.adult_human) {
4016
+ const found = gltf.scene.getObjectByName(node);
4017
+ if (!found) throw new Error(`missing ${node}`);
4018
+ if (parent !== null && found.parent?.name !== parent) throw new Error(`${node} is not under ${parent}`);
4019
+ }
4020
+ ```
4021
+
3928
4022
  <a id="gemapierror"></a>
3929
4023
 
3930
4024
  ## GemApiError
@@ -5347,7 +5441,7 @@ interface RewardCue
5347
5441
  ```
5348
5442
 
5349
5443
  A platform-currency reward on its way to the arcade — in the Gem Arcade, a
5350
- flight into the Gem button at the top-left of your frame — what
5444
+ flight into the Gem button, in whichever corner of your frame it sits — what
5351
5445
  `gem.cueReward` takes.
5352
5446
 
5353
5447
  <a id="rewardcue-currencyslug"></a>
@@ -5408,6 +5502,18 @@ y: number
5408
5502
 
5409
5503
  From the top edge of your viewport.
5410
5504
 
5505
+ <a id="gemcorner"></a>
5506
+
5507
+ ## GemCorner
5508
+
5509
+ ```ts
5510
+ type GemCorner = "top-left" | "top-right" | "bottom-left" | "bottom-right"
5511
+ ```
5512
+
5513
+ A corner of your frame, for `gem.setGemCorner`: where you would like the
5514
+ arcade's Gem button to sit. `'top-left'` is where it sits unless you ask.
5515
+ Physical corners: `'top-left'` is the top-left in every language.
5516
+
5411
5517
  <a id="framestate"></a>
5412
5518
 
5413
5519
  ## FrameState
@@ -5737,6 +5843,30 @@ connected, and only to an arcade that draws a menu.
5737
5843
  **Returns.** whether the message left the frame — `false` before the bridge is
5738
5844
  up, for an arcade with no menu, and past this frame's own limit.
5739
5845
 
5846
+ <a id="gemframe-setgemcorner"></a>
5847
+
5848
+ ## GemFrame.setGemCorner
5849
+
5850
+ ```ts
5851
+ setGemCorner(corner: GemCorner): boolean
5852
+ ```
5853
+
5854
+ Ask the arcade to put its own control over your game — the Gem button —
5855
+ in this corner of your frame: the whole answer each time, the latest one
5856
+ winning.
5857
+
5858
+ Prefer `gem.setGemCorner`, which holds the corner across a reconnect.
5859
+ This one sends only while connected, and only to an arcade that can move
5860
+ its control.
5861
+
5862
+ | Parameter | Type |
5863
+ | --- | --- |
5864
+ | `corner` | `GemCorner` |
5865
+
5866
+ **Returns.** whether the message left the frame — `false` before the bridge is
5867
+ up, for an arcade that cannot move its control, for a value that is not
5868
+ one of the four corners, and past this frame's own limit.
5869
+
5740
5870
  <a id="gemframe-requestshare"></a>
5741
5871
 
5742
5872
  ## GemFrame.requestShare
@@ -8303,7 +8433,7 @@ readonly reserved: readonly GemReservedArea[]
8303
8433
  ```
8304
8434
 
8305
8435
  Rectangles of your frame the arcade's own controls cover — in the Gem
8306
- Arcade, its Gem button in the top-left corner, and the frame-rate readout
8436
+ Arcade, its Gem button in whichever corner it sits, and the frame-rate readout
8307
8437
  beside it while the player shows it; an embedder that draws wallets over
8308
8438
  your game adds theirs (see `setWalletVisible`). Keep essential UI and touch
8309
8439
  targets out of them. Empty when the arcade covers nothing.
@@ -9430,7 +9560,7 @@ cueReward(cue: RewardCue): boolean
9430
9560
 
9431
9561
  Tell the arcade a platform-currency reward is on its way, so it **shows it
9432
9562
  landing**: in the Gem Arcade the currency flies from `origin` into the Gem
9433
- button at the top-left of your frame, which pops as each mark lands, and
9563
+ button, wherever on your frame it sits, which pops as each mark lands, and
9434
9564
  the player's total moves once the platform confirms the grant. The Gem
9435
9565
  Arcade draws no wallet over your game: the player sees their Gems and
9436
9566
  Tickets in the Gem menu. A payout you do not cue still flies, from the
@@ -9532,8 +9662,9 @@ gem.setMenu({
9532
9662
  ```
9533
9663
 
9534
9664
  **Your settings are not in it: draw your own settings button, always** —
9535
- top-right, clear of `gem.viewport.reserved`. The Arcade's menu never opens
9536
- your settings screen.
9665
+ top-right, with your Back button just to its left, clear of
9666
+ `gem.viewport.reserved`. The Arcade's menu never opens your settings
9667
+ screen.
9537
9668
 
9538
9669
  **It is screen state, not a toggle.** Each call is the whole answer and
9539
9670
  replaces the last, so call it again when the entries change — a new
@@ -9553,6 +9684,46 @@ should not assume the game was paused by you.
9553
9684
  up (the menu is held and sent when it connects) and under an embedder
9554
9685
  that draws no menu.
9555
9686
 
9687
+ <a id="gem-setgemcorner"></a>
9688
+
9689
+ ## Gem.setGemCorner
9690
+
9691
+ ```ts
9692
+ setGemCorner(corner: GemCorner): boolean
9693
+ ```
9694
+
9695
+ Ask the arcade to put its Gem button — its one control over your game,
9696
+ top-left unless you ask — in another corner of your frame.
9697
+
9698
+ ```js
9699
+ // This game's own HUD needs the top-left, so the Gem goes top-right.
9700
+ gem.setGemCorner('top-right');
9701
+ ```
9702
+
9703
+ **Leave it top-left unless your own HUD needs that corner**, and then pick
9704
+ one corner for the whole game — at most one per orientation. A Gem that
9705
+ moves between screens is a way out the player has to look for. In
9706
+ landscape the bottom corners sit where a player's thumbs hold the sticks.
9707
+
9708
+ **Lay out around `gem.viewport.reserved`, never around the corner you
9709
+ asked for.** The arcade moves the Gem on its own terms: not while the
9710
+ player is using it or its menu is open, not more often than every few
9711
+ seconds, and never over a corner the player chose for themselves. The
9712
+ rectangles say where it actually is, and the `--gem-reserved-*` CSS
9713
+ properties follow them.
9714
+
9715
+ **It is screen state, not a toggle.** Each call is the whole answer and
9716
+ replaces the last. A value that is not one of the four corners is ignored,
9717
+ with a warning on the console, and changes nothing.
9718
+
9719
+ | Parameter | Type | Description |
9720
+ | --- | --- | --- |
9721
+ | `corner` | `GemCorner` | `'top-left'`, `'top-right'`, `'bottom-left'` or `'bottom-right'`. |
9722
+
9723
+ **Returns.** `true` when the arcade was told now; `false` before the bridge is
9724
+ up (the corner is held and sent when it connects), under an embedder that
9725
+ cannot move its control, and for a value that is not a corner.
9726
+
9556
9727
  <a id="gem-exit"></a>
9557
9728
 
9558
9729
  ## Gem.exit
@@ -10352,7 +10523,7 @@ The match this connection belongs to.
10352
10523
  ## MatchConnection.protocol
10353
10524
 
10354
10525
  ```ts
10355
- readonly protocol: "dedicated" | "p2p" | "loopback"
10526
+ readonly protocol: "p2p" | "dedicated" | "loopback"
10356
10527
  ```
10357
10528
 
10358
10529
  What is on the other end: `dedicated` (the platform's server), `p2p` (the
@@ -10544,13 +10715,21 @@ putting it in an `<img src>`.
10544
10715
  ## Avatar3dFamily
10545
10716
 
10546
10717
  ```ts
10547
- type Avatar3dFamily = "small_human" | string & object
10718
+ type Avatar3dFamily = "small_human" | "adult_human" | string & object
10548
10719
  ```
10549
10720
 
10550
10721
  A rig family — the skeleton contract a 3D avatar is built on, and what a
10551
- game declares it can animate. `small_human` is the first: a `root` node
10552
- with a `body` child, which holds `head`, `arm_l`, `arm_r`, `leg_l` and
10553
- `leg_r`, and a `hand_socket` under `arm_r`.
10722
+ game declares it can animate. Two today:
10723
+
10724
+ - `small_human`, the toy rig: a `root` node with a `body` child, which holds
10725
+ `head`, `arm_l`, `arm_r`, `leg_l` and `leg_r`, and a `hand_socket` under
10726
+ `arm_r`.
10727
+ - `adult_human`, a full humanoid with fingers: 56 nodes from `root` and
10728
+ `hips` down to `toes_r`, every one world-aligned at rest, so one clip plays
10729
+ on every avatar in the family.
10730
+
10731
+ `AVATAR_RIGS` (from `@indiegems/gem-web-sdk/sdk`) lists every node of
10732
+ both, with its parent.
10554
10733
 
10555
10734
  Open-ended (`| (string & {})`) so a family the platform adds later does not
10556
10735
  break a `switch` you compiled against this version: keep a `default` arm and
@@ -1,6 +1,6 @@
1
1
  # The server surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v13.0.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v13.1.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
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
 
@@ -2,7 +2,7 @@
2
2
  "schema_version": 2,
3
3
  "source": {
4
4
  "repo": "IndieGems/gem-web-sdk",
5
- "version": "13.0.0"
5
+ "version": "13.1.0"
6
6
  },
7
7
  "entries": [
8
8
  {
@@ -4797,6 +4797,118 @@
4797
4797
  "defaultValue": null,
4798
4798
  "guides": []
4799
4799
  },
4800
+ {
4801
+ "id": "AvatarRigNode",
4802
+ "name": "AvatarRigNode",
4803
+ "anchor": "avatarrignode",
4804
+ "group": "avatars3d",
4805
+ "signature": "interface AvatarRigNode",
4806
+ "documented": true,
4807
+ "summary": "One node of a rig family's tree: its exact, case-sensitive name, and the\nname of the node it is a DIRECT child of. `parent` is `null` for the rig's\nroot, which is a root node of the scene.",
4808
+ "deprecated": null,
4809
+ "params": [],
4810
+ "returns": null,
4811
+ "throws": null,
4812
+ "example": null,
4813
+ "defaultValue": null,
4814
+ "guides": []
4815
+ },
4816
+ {
4817
+ "id": "AvatarRigNode.node",
4818
+ "name": "node",
4819
+ "anchor": "avatarrignode-node",
4820
+ "group": "avatars3d",
4821
+ "signature": "readonly node: string",
4822
+ "documented": true,
4823
+ "summary": "The node's name, exact and case-sensitive.",
4824
+ "deprecated": null,
4825
+ "params": [],
4826
+ "returns": null,
4827
+ "throws": null,
4828
+ "example": null,
4829
+ "defaultValue": null,
4830
+ "guides": []
4831
+ },
4832
+ {
4833
+ "id": "AvatarRigNode.parent",
4834
+ "name": "parent",
4835
+ "anchor": "avatarrignode-parent",
4836
+ "group": "avatars3d",
4837
+ "signature": "readonly parent: string | null",
4838
+ "documented": true,
4839
+ "summary": "The node it is a direct child of; `null` for the rig's root.",
4840
+ "deprecated": null,
4841
+ "params": [],
4842
+ "returns": null,
4843
+ "throws": null,
4844
+ "example": null,
4845
+ "defaultValue": null,
4846
+ "guides": []
4847
+ },
4848
+ {
4849
+ "id": "AvatarRigs",
4850
+ "name": "AvatarRigs",
4851
+ "anchor": "avatarrigs",
4852
+ "group": "avatars3d",
4853
+ "signature": "interface AvatarRigs",
4854
+ "documented": true,
4855
+ "summary": "The rig families this SDK knows, by name.",
4856
+ "deprecated": null,
4857
+ "params": [],
4858
+ "returns": null,
4859
+ "throws": null,
4860
+ "example": null,
4861
+ "defaultValue": null,
4862
+ "guides": []
4863
+ },
4864
+ {
4865
+ "id": "AvatarRigs.small_human",
4866
+ "name": "small_human",
4867
+ "anchor": "avatarrigs-small_human",
4868
+ "group": "avatars3d",
4869
+ "signature": "readonly small_human: readonly AvatarRigNode[]",
4870
+ "documented": true,
4871
+ "summary": "The toy rig: rigid limbs on a body, eight nodes.",
4872
+ "deprecated": null,
4873
+ "params": [],
4874
+ "returns": null,
4875
+ "throws": null,
4876
+ "example": null,
4877
+ "defaultValue": null,
4878
+ "guides": []
4879
+ },
4880
+ {
4881
+ "id": "AvatarRigs.adult_human",
4882
+ "name": "adult_human",
4883
+ "anchor": "avatarrigs-adult_human",
4884
+ "group": "avatars3d",
4885
+ "signature": "readonly adult_human: readonly AvatarRigNode[]",
4886
+ "documented": true,
4887
+ "summary": "The adult humanoid with fingers: 56 nodes, world-aligned at rest.",
4888
+ "deprecated": null,
4889
+ "params": [],
4890
+ "returns": null,
4891
+ "throws": null,
4892
+ "example": null,
4893
+ "defaultValue": null,
4894
+ "guides": []
4895
+ },
4896
+ {
4897
+ "id": "AVATAR_RIGS",
4898
+ "name": "AVATAR_RIGS",
4899
+ "anchor": "avatar_rigs",
4900
+ "group": "avatars3d",
4901
+ "signature": "AVATAR_RIGS: AvatarRigs",
4902
+ "documented": true,
4903
+ "summary": "Every node each rig family requires, with the node it is a direct child of,\nparents before children. Frozen: read it, never change it.\n\nThe platform refuses an upload whose model is missing one of these, has one\nunder another parent, or has one twice (`rig_mismatch`). Extra nodes are\nallowed anywhere. `adult_human` also requires every one of its nodes to be\nworld-aligned at rest; that rule is not in this list, see the guide.\n\n```js\nimport { AVATAR_RIGS } from '@indiegems/gem-web-sdk/sdk';\n\n// Every joint of the worn avatar, by name.\nconst joints = new Map(\n AVATAR_RIGS.adult_human.map(({ node }) => [node, gltf.scene.getObjectByName(node)]),\n);\n\n// A test that one of your own models is on the rig.\nfor (const { node, parent } of AVATAR_RIGS.adult_human) {\n const found = gltf.scene.getObjectByName(node);\n if (!found) throw new Error(`missing ${node}`);\n if (parent !== null && found.parent?.name !== parent) throw new Error(`${node} is not under ${parent}`);\n}\n```",
4904
+ "deprecated": null,
4905
+ "params": [],
4906
+ "returns": null,
4907
+ "throws": null,
4908
+ "example": null,
4909
+ "defaultValue": null,
4910
+ "guides": []
4911
+ },
4800
4912
  {
4801
4913
  "id": "GemApiError",
4802
4914
  "name": "GemApiError",
@@ -6346,7 +6458,7 @@
6346
6458
  "group": "platform",
6347
6459
  "signature": "interface RewardCue",
6348
6460
  "documented": true,
6349
- "summary": "A platform-currency reward on its way to the arcade — in the Gem Arcade, a\nflight into the Gem button at the top-left of your frame — what\n`gem.cueReward` takes.",
6461
+ "summary": "A platform-currency reward on its way to the arcade — in the Gem Arcade, a\nflight into the Gem button, in whichever corner of your frame it sits — what\n`gem.cueReward` takes.",
6350
6462
  "deprecated": null,
6351
6463
  "params": [],
6352
6464
  "returns": null,
@@ -6435,6 +6547,22 @@
6435
6547
  "defaultValue": null,
6436
6548
  "guides": []
6437
6549
  },
6550
+ {
6551
+ "id": "GemCorner",
6552
+ "name": "GemCorner",
6553
+ "anchor": "gemcorner",
6554
+ "group": "frame",
6555
+ "signature": "type GemCorner = \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\"",
6556
+ "documented": true,
6557
+ "summary": "A corner of your frame, for `gem.setGemCorner`: where you would like the\narcade's Gem button to sit. `'top-left'` is where it sits unless you ask.\nPhysical corners: `'top-left'` is the top-left in every language.",
6558
+ "deprecated": null,
6559
+ "params": [],
6560
+ "returns": null,
6561
+ "throws": null,
6562
+ "example": null,
6563
+ "defaultValue": null,
6564
+ "guides": []
6565
+ },
6438
6566
  {
6439
6567
  "id": "FrameState",
6440
6568
  "name": "FrameState",
@@ -6769,6 +6897,29 @@
6769
6897
  "defaultValue": null,
6770
6898
  "guides": []
6771
6899
  },
6900
+ {
6901
+ "id": "GemFrame.setGemCorner",
6902
+ "name": "setGemCorner",
6903
+ "anchor": "gemframe-setgemcorner",
6904
+ "group": "frame",
6905
+ "signature": "setGemCorner(corner: GemCorner): boolean",
6906
+ "documented": true,
6907
+ "summary": "Ask the arcade to put its own control over your game — the Gem button —\nin this corner of your frame: the whole answer each time, the latest one\nwinning.\n\nPrefer `gem.setGemCorner`, which holds the corner across a reconnect.\nThis one sends only while connected, and only to an arcade that can move\nits control.",
6908
+ "deprecated": null,
6909
+ "params": [
6910
+ {
6911
+ "name": "corner",
6912
+ "type": "GemCorner",
6913
+ "optional": false,
6914
+ "summary": null
6915
+ }
6916
+ ],
6917
+ "returns": "whether the message left the frame — `false` before the bridge is\n up, for an arcade that cannot move its control, for a value that is not\n one of the four corners, and past this frame's own limit.",
6918
+ "throws": null,
6919
+ "example": null,
6920
+ "defaultValue": null,
6921
+ "guides": []
6922
+ },
6772
6923
  {
6773
6924
  "id": "GemFrame.requestShare",
6774
6925
  "name": "requestShare",
@@ -9401,7 +9552,7 @@
9401
9552
  "group": "player",
9402
9553
  "signature": "readonly reserved: readonly GemReservedArea[]",
9403
9554
  "documented": true,
9404
- "summary": "Rectangles of your frame the arcade's own controls cover — in the Gem\nArcade, its Gem button in the top-left corner, and the frame-rate readout\nbeside it while the player shows it; an embedder that draws wallets over\nyour game adds theirs (see `setWalletVisible`). Keep essential UI and touch\ntargets out of them. Empty when the arcade covers nothing.\n\nA stylesheet reads the per-corner custom properties the SDK stamps from\nthese instead — `--gem-reserved-tl-height` and friends.",
9555
+ "summary": "Rectangles of your frame the arcade's own controls cover — in the Gem\nArcade, its Gem button in whichever corner it sits, and the frame-rate readout\nbeside it while the player shows it; an embedder that draws wallets over\nyour game adds theirs (see `setWalletVisible`). Keep essential UI and touch\ntargets out of them. Empty when the arcade covers nothing.\n\nA stylesheet reads the per-corner custom properties the SDK stamps from\nthese instead — `--gem-reserved-tl-height` and friends.",
9405
9556
  "deprecated": null,
9406
9557
  "params": [],
9407
9558
  "returns": null,
@@ -10412,7 +10563,7 @@
10412
10563
  "group": "start",
10413
10564
  "signature": "cueReward(cue: RewardCue): boolean",
10414
10565
  "documented": true,
10415
- "summary": "Tell the arcade a platform-currency reward is on its way, so it **shows it\nlanding**: in the Gem Arcade the currency flies from `origin` into the Gem\nbutton at the top-left of your frame, which pops as each mark lands, and\nthe player's total moves once the platform confirms the grant. The Gem\nArcade draws no wallet over your game: the player sees their Gems and\nTickets in the Gem menu. A payout you do not cue still flies, from the\nmiddle of your frame, so cue the ones the player earns on screen.\n\nCall it the moment your game decides to award — when your server has moved\n(or is about to move) the progression mapped onto a platform currency —\nand pass the centre of that currency's icon (or hero) on your screen, so\nthe flight starts from the mark the player is looking at:\n\n```js\nconst { x, y, width, height } = rewardGem.getBoundingClientRect(); // the gem's own box\ngem.cueReward({\n currencySlug: 'GEMS', // or 'ARCADE_TICKETS', from the ticket\n expected: 15,\n origin: { x: x + width / 2, y: y + height / 2 },\n});\n```\n\n**This is the platform-currency animation, and the only one.** The display\nof every platform currency — Gems and Tickets alike — belongs to the\narcade: a game draws no flight or celebration of its own for one and keeps\nno counter of one. **If this returns `false`, do nothing** — there is no\nfallback celebration.\n\n**The arcade never takes your word for the amount.** What lands, and the\nplayer's new total, come from the platform itself; `expected` is drawn as\nprovisional, and a cue the platform never confirms fades on its own — a\ngrant clamped to zero, say, or one the receipt reports `suppressed`. So\nthe cue can only ever make the wallet move for a reward that really\nlanded — which it does on every channel, dev and test included.",
10566
+ "summary": "Tell the arcade a platform-currency reward is on its way, so it **shows it\nlanding**: in the Gem Arcade the currency flies from `origin` into the Gem\nbutton, wherever on your frame it sits, which pops as each mark lands, and\nthe player's total moves once the platform confirms the grant. The Gem\nArcade draws no wallet over your game: the player sees their Gems and\nTickets in the Gem menu. A payout you do not cue still flies, from the\nmiddle of your frame, so cue the ones the player earns on screen.\n\nCall it the moment your game decides to award — when your server has moved\n(or is about to move) the progression mapped onto a platform currency —\nand pass the centre of that currency's icon (or hero) on your screen, so\nthe flight starts from the mark the player is looking at:\n\n```js\nconst { x, y, width, height } = rewardGem.getBoundingClientRect(); // the gem's own box\ngem.cueReward({\n currencySlug: 'GEMS', // or 'ARCADE_TICKETS', from the ticket\n expected: 15,\n origin: { x: x + width / 2, y: y + height / 2 },\n});\n```\n\n**This is the platform-currency animation, and the only one.** The display\nof every platform currency — Gems and Tickets alike — belongs to the\narcade: a game draws no flight or celebration of its own for one and keeps\nno counter of one. **If this returns `false`, do nothing** — there is no\nfallback celebration.\n\n**The arcade never takes your word for the amount.** What lands, and the\nplayer's new total, come from the platform itself; `expected` is drawn as\nprovisional, and a cue the platform never confirms fades on its own — a\ngrant clamped to zero, say, or one the receipt reports `suppressed`. So\nthe cue can only ever make the wallet move for a reward that really\nlanded — which it does on every channel, dev and test included.",
10416
10567
  "deprecated": null,
10417
10568
  "params": [
10418
10569
  {
@@ -10464,7 +10615,7 @@
10464
10615
  "group": "start",
10465
10616
  "signature": "setMenu(menu: GameMenu): boolean",
10466
10617
  "documented": true,
10467
- "summary": "Put up to four entries of your own in the arcade's menu. The arcade keeps\none menu button over your game: it is how a player leaves, mutes, goes\nfullscreen, reports a problem and changes their Arcade-wide settings.\n\n```js\ngem.setMenu({\n items: [{ id: 'how-to-play', label: t('How to play'), onSelect: () => help.open() }],\n});\n```\n\n**Your settings are not in it: draw your own settings button, always** —\ntop-right, clear of `gem.viewport.reserved`. The Arcade's menu never opens\nyour settings screen.\n\n**It is screen state, not a toggle.** Each call is the whole answer and\nreplaces the last, so call it again when the entries change — a new\nlanguage, a screen with different options. `gem.setMenu({})` takes\neverything of yours back out. The arcade's own entries are not yours to\nchange, and Return to the Arcade is always among them.\n\n**The arcade pauses your game while its menu is open** (`onPause`), and\nresumes it before a handler of yours runs. A handler opens a screen; it\nshould not assume the game was paused by you.",
10618
+ "summary": "Put up to four entries of your own in the arcade's menu. The arcade keeps\none menu button over your game: it is how a player leaves, mutes, goes\nfullscreen, reports a problem and changes their Arcade-wide settings.\n\n```js\ngem.setMenu({\n items: [{ id: 'how-to-play', label: t('How to play'), onSelect: () => help.open() }],\n});\n```\n\n**Your settings are not in it: draw your own settings button, always** —\ntop-right, with your Back button just to its left, clear of\n`gem.viewport.reserved`. The Arcade's menu never opens your settings\nscreen.\n\n**It is screen state, not a toggle.** Each call is the whole answer and\nreplaces the last, so call it again when the entries change — a new\nlanguage, a screen with different options. `gem.setMenu({})` takes\neverything of yours back out. The arcade's own entries are not yours to\nchange, and Return to the Arcade is always among them.\n\n**The arcade pauses your game while its menu is open** (`onPause`), and\nresumes it before a handler of yours runs. A handler opens a screen; it\nshould not assume the game was paused by you.",
10468
10619
  "deprecated": null,
10469
10620
  "params": [
10470
10621
  {
@@ -10480,6 +10631,29 @@
10480
10631
  "defaultValue": null,
10481
10632
  "guides": []
10482
10633
  },
10634
+ {
10635
+ "id": "Gem.setGemCorner",
10636
+ "name": "setGemCorner",
10637
+ "anchor": "gem-setgemcorner",
10638
+ "group": "start",
10639
+ "signature": "setGemCorner(corner: GemCorner): boolean",
10640
+ "documented": true,
10641
+ "summary": "Ask the arcade to put its Gem button — its one control over your game,\ntop-left unless you ask — in another corner of your frame.\n\n```js\n// This game's own HUD needs the top-left, so the Gem goes top-right.\ngem.setGemCorner('top-right');\n```\n\n**Leave it top-left unless your own HUD needs that corner**, and then pick\none corner for the whole game — at most one per orientation. A Gem that\nmoves between screens is a way out the player has to look for. In\nlandscape the bottom corners sit where a player's thumbs hold the sticks.\n\n**Lay out around `gem.viewport.reserved`, never around the corner you\nasked for.** The arcade moves the Gem on its own terms: not while the\nplayer is using it or its menu is open, not more often than every few\nseconds, and never over a corner the player chose for themselves. The\nrectangles say where it actually is, and the `--gem-reserved-*` CSS\nproperties follow them.\n\n**It is screen state, not a toggle.** Each call is the whole answer and\nreplaces the last. A value that is not one of the four corners is ignored,\nwith a warning on the console, and changes nothing.",
10642
+ "deprecated": null,
10643
+ "params": [
10644
+ {
10645
+ "name": "corner",
10646
+ "type": "GemCorner",
10647
+ "optional": false,
10648
+ "summary": "`'top-left'`, `'top-right'`, `'bottom-left'` or `'bottom-right'`."
10649
+ }
10650
+ ],
10651
+ "returns": "`true` when the arcade was told now; `false` before the bridge is\n up (the corner is held and sent when it connects), under an embedder that\n cannot move its control, and for a value that is not a corner.",
10652
+ "throws": null,
10653
+ "example": null,
10654
+ "defaultValue": null,
10655
+ "guides": []
10656
+ },
10483
10657
  {
10484
10658
  "id": "Gem.exit",
10485
10659
  "name": "exit",
@@ -11364,7 +11538,7 @@
11364
11538
  "name": "protocol",
11365
11539
  "anchor": "matchconnection-protocol",
11366
11540
  "group": "match",
11367
- "signature": "readonly protocol: \"dedicated\" | \"p2p\" | \"loopback\"",
11541
+ "signature": "readonly protocol: \"p2p\" | \"dedicated\" | \"loopback\"",
11368
11542
  "documented": true,
11369
11543
  "summary": "What is on the other end: `dedicated` (the platform's server), `p2p` (the\nhosting player's browser), or `loopback` (this browser — you are the host,\nand this is the in-process link to your own bundle).",
11370
11544
  "deprecated": null,
@@ -11619,9 +11793,9 @@
11619
11793
  "name": "Avatar3dFamily",
11620
11794
  "anchor": "avatar3dfamily",
11621
11795
  "group": "avatars3d",
11622
- "signature": "type Avatar3dFamily = \"small_human\" | string & object",
11796
+ "signature": "type Avatar3dFamily = \"small_human\" | \"adult_human\" | string & object",
11623
11797
  "documented": true,
11624
- "summary": "A rig family — the skeleton contract a 3D avatar is built on, and what a\ngame declares it can animate. `small_human` is the first: a `root` node\nwith a `body` child, which holds `head`, `arm_l`, `arm_r`, `leg_l` and\n`leg_r`, and a `hand_socket` under `arm_r`.\n\nOpen-ended (`| (string & {})`) so a family the platform adds later does not\nbreak a `switch` you compiled against this version: keep a `default` arm and\nskip a family you do not draw.",
11798
+ "summary": "A rig family — the skeleton contract a 3D avatar is built on, and what a\ngame declares it can animate. Two today:\n\n- `small_human`, the toy rig: a `root` node with a `body` child, which holds\n `head`, `arm_l`, `arm_r`, `leg_l` and `leg_r`, and a `hand_socket` under\n `arm_r`.\n- `adult_human`, a full humanoid with fingers: 56 nodes from `root` and\n `hips` down to `toes_r`, every one world-aligned at rest, so one clip plays\n on every avatar in the family.\n\n`AVATAR_RIGS` (from `@indiegems/gem-web-sdk/sdk`) lists every node of\nboth, with its parent.\n\nOpen-ended (`| (string & {})`) so a family the platform adds later does not\nbreak a `switch` you compiled against this version: keep a `default` arm and\nskip a family you do not draw.",
11625
11799
  "deprecated": null,
11626
11800
  "params": [],
11627
11801
  "returns": null,
@@ -32069,9 +32243,9 @@
32069
32243
  "name": "Avatar3dFamily",
32070
32244
  "anchor": "avatar3dfamily",
32071
32245
  "group": "identity",
32072
- "signature": "type Avatar3dFamily = \"small_human\" | string & object",
32246
+ "signature": "type Avatar3dFamily = \"small_human\" | \"adult_human\" | string & object",
32073
32247
  "documented": true,
32074
- "summary": "A rig family — the skeleton contract a 3D avatar is built on, and what a\ngame declares it can animate. `small_human` is the first: a `root` node\nwith a `body` child, which holds `head`, `arm_l`, `arm_r`, `leg_l` and\n`leg_r`, and a `hand_socket` under `arm_r`.\n\nOpen-ended (`| (string & {})`) so a family the platform adds later does not\nbreak a `switch` you compiled against this version: keep a `default` arm and\nskip a family you do not draw.",
32248
+ "summary": "A rig family — the skeleton contract a 3D avatar is built on, and what a\ngame declares it can animate. Two today:\n\n- `small_human`, the toy rig: a `root` node with a `body` child, which holds\n `head`, `arm_l`, `arm_r`, `leg_l` and `leg_r`, and a `hand_socket` under\n `arm_r`.\n- `adult_human`, a full humanoid with fingers: 56 nodes from `root` and\n `hips` down to `toes_r`, every one world-aligned at rest, so one clip plays\n on every avatar in the family.\n\n`AVATAR_RIGS` (from `@indiegems/gem-web-sdk/sdk`) lists every node of\nboth, with its parent.\n\nOpen-ended (`| (string & {})`) so a family the platform adds later does not\nbreak a `switch` you compiled against this version: keep a `default` arm and\nskip a family you do not draw.",
32075
32249
  "deprecated": null,
32076
32250
  "params": [],
32077
32251
  "returns": null,