@indiegems/gem-web-sdk 12.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.
- package/CHANGELOG.md +37 -0
- package/dist/function.d.ts +9 -1
- package/dist/game.d.ts +52 -13
- package/dist/gem-web-sdk.bridge.js +1 -1
- package/dist/gem-web-sdk.esm.js +2 -2
- package/dist/gem-web-sdk.function.js +2 -2
- 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-api.js +1 -1
- package/dist/gem-web-sdk.server.js +2 -2
- package/dist/index.d.ts +47 -14
- package/dist/sdk.d.ts +62 -14
- package/dist/server-api.d.ts +9 -1
- package/dist/server.d.ts +10 -1
- package/docs/api/api-reference-function.md +170 -2
- package/docs/api/api-reference-game.md +707 -162
- package/docs/api/api-reference-server.md +1 -1
- package/docs/api/reference.json +943 -172
- package/docs/arcade-avatars.md +471 -0
- package/docs/brand-art.md +3 -3
- package/docs/changelog.md +37 -0
- package/docs/getting-started.md +3 -2
- package/docs/inventory-and-catalogs.md +1 -1
- package/docs/manifest.json +19 -14
- package/docs/saving-player-progress.md +16 -10
- package/docs/server-bundles.md +2 -2
- package/docs/what-a-game-must-do.md +146 -99
- package/package.json +4 -2
- package/rigs/adult_human.glb +0 -0
- package/schema/bridge.v1.json +247 -20
- package/schema/capabilities.public.json +12 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# The browser surface — API reference
|
|
2
2
|
|
|
3
|
-
Generated from `@indiegems/gem-web-sdk/sdk`
|
|
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
|
|
|
@@ -3669,6 +3669,356 @@ The runtime companion to [PlatformEventName](#platformeventname), for a game tha
|
|
|
3669
3669
|
show what it gets for free, or to check a funnel step it authored against
|
|
3670
3670
|
what the platform actually emits.
|
|
3671
3671
|
|
|
3672
|
+
<a id="avatar3dprice"></a>
|
|
3673
|
+
|
|
3674
|
+
## Avatar3dPrice
|
|
3675
|
+
|
|
3676
|
+
```ts
|
|
3677
|
+
interface Avatar3dPrice
|
|
3678
|
+
```
|
|
3679
|
+
|
|
3680
|
+
One price of a 3D avatar on sale, in one platform currency.
|
|
3681
|
+
|
|
3682
|
+
<a id="avatar3dprice-currencyslug"></a>
|
|
3683
|
+
|
|
3684
|
+
## Avatar3dPrice.currencySlug
|
|
3685
|
+
|
|
3686
|
+
```ts
|
|
3687
|
+
readonly currencySlug: string
|
|
3688
|
+
```
|
|
3689
|
+
|
|
3690
|
+
`GEMS` or `ARCADE_TICKETS` — what to pass as `currencySlug`.
|
|
3691
|
+
|
|
3692
|
+
<a id="avatar3dprice-price"></a>
|
|
3693
|
+
|
|
3694
|
+
## Avatar3dPrice.price
|
|
3695
|
+
|
|
3696
|
+
```ts
|
|
3697
|
+
readonly price: number
|
|
3698
|
+
```
|
|
3699
|
+
|
|
3700
|
+
The price, a whole number of that currency.
|
|
3701
|
+
|
|
3702
|
+
<a id="avatar3doffer"></a>
|
|
3703
|
+
|
|
3704
|
+
## Avatar3dOffer
|
|
3705
|
+
|
|
3706
|
+
```ts
|
|
3707
|
+
interface Avatar3dOffer
|
|
3708
|
+
```
|
|
3709
|
+
|
|
3710
|
+
One of your game's 3D avatars on sale, as the platform prices it.
|
|
3711
|
+
|
|
3712
|
+
<a id="avatar3doffer-itemid"></a>
|
|
3713
|
+
|
|
3714
|
+
## Avatar3dOffer.itemId
|
|
3715
|
+
|
|
3716
|
+
```ts
|
|
3717
|
+
readonly itemId: string
|
|
3718
|
+
```
|
|
3719
|
+
|
|
3720
|
+
The avatar's item id — what [Avatars3dApi.purchase](#avatars3dapi-purchase) takes.
|
|
3721
|
+
|
|
3722
|
+
<a id="avatar3doffer-slug"></a>
|
|
3723
|
+
|
|
3724
|
+
## Avatar3dOffer.slug
|
|
3725
|
+
|
|
3726
|
+
```ts
|
|
3727
|
+
readonly slug: string
|
|
3728
|
+
```
|
|
3729
|
+
|
|
3730
|
+
The slug you uploaded it under. A key, not display text.
|
|
3731
|
+
|
|
3732
|
+
<a id="avatar3doffer-family"></a>
|
|
3733
|
+
|
|
3734
|
+
## Avatar3dOffer.family
|
|
3735
|
+
|
|
3736
|
+
```ts
|
|
3737
|
+
readonly family: Avatar3dFamily
|
|
3738
|
+
```
|
|
3739
|
+
|
|
3740
|
+
The rig family the model is built on.
|
|
3741
|
+
|
|
3742
|
+
<a id="avatar3doffer-displayname"></a>
|
|
3743
|
+
|
|
3744
|
+
## Avatar3dOffer.displayName
|
|
3745
|
+
|
|
3746
|
+
```ts
|
|
3747
|
+
readonly displayName: string
|
|
3748
|
+
```
|
|
3749
|
+
|
|
3750
|
+
The avatar's name, as you uploaded it.
|
|
3751
|
+
|
|
3752
|
+
<a id="avatar3doffer-description"></a>
|
|
3753
|
+
|
|
3754
|
+
## Avatar3dOffer.description
|
|
3755
|
+
|
|
3756
|
+
```ts
|
|
3757
|
+
readonly description?: string
|
|
3758
|
+
```
|
|
3759
|
+
|
|
3760
|
+
The avatar's description, when it has one.
|
|
3761
|
+
|
|
3762
|
+
<a id="avatar3doffer-iconurl"></a>
|
|
3763
|
+
|
|
3764
|
+
## Avatar3dOffer.iconUrl
|
|
3765
|
+
|
|
3766
|
+
```ts
|
|
3767
|
+
readonly iconUrl: string
|
|
3768
|
+
```
|
|
3769
|
+
|
|
3770
|
+
A rendered portrait of the avatar, for a shop tile. Pass it through
|
|
3771
|
+
`platformIconUrl` before putting it in an `<img src>`.
|
|
3772
|
+
|
|
3773
|
+
<a id="avatar3doffer-modelurl"></a>
|
|
3774
|
+
|
|
3775
|
+
## Avatar3dOffer.modelUrl
|
|
3776
|
+
|
|
3777
|
+
```ts
|
|
3778
|
+
readonly modelUrl: string
|
|
3779
|
+
```
|
|
3780
|
+
|
|
3781
|
+
The avatar's model, for a preview. Pass it through `platformIconUrl`
|
|
3782
|
+
before loading it.
|
|
3783
|
+
|
|
3784
|
+
<a id="avatar3doffer-prices"></a>
|
|
3785
|
+
|
|
3786
|
+
## Avatar3dOffer.prices
|
|
3787
|
+
|
|
3788
|
+
```ts
|
|
3789
|
+
readonly prices: readonly Avatar3dPrice[]
|
|
3790
|
+
```
|
|
3791
|
+
|
|
3792
|
+
One or two prices, each in a currency a player can pay with. Show each
|
|
3793
|
+
one the player can choose; pass the chosen one's `currencySlug` to
|
|
3794
|
+
[Avatars3dApi.purchase](#avatars3dapi-purchase).
|
|
3795
|
+
|
|
3796
|
+
<a id="avatars3dapi"></a>
|
|
3797
|
+
|
|
3798
|
+
## Avatars3dApi
|
|
3799
|
+
|
|
3800
|
+
```ts
|
|
3801
|
+
interface Avatars3dApi
|
|
3802
|
+
```
|
|
3803
|
+
|
|
3804
|
+
Arcade 3D avatars — `gem.avatars3d`. What the player wears, the rig families
|
|
3805
|
+
your game accepts, the avatars you sell, and buying one.
|
|
3806
|
+
|
|
3807
|
+
```js
|
|
3808
|
+
function draw() {
|
|
3809
|
+
const worn = gem.avatars3d.worn();
|
|
3810
|
+
if (worn) loadCharacter(platformIconUrl(worn.modelUrl));
|
|
3811
|
+
else useDefaultCharacter();
|
|
3812
|
+
}
|
|
3813
|
+
draw();
|
|
3814
|
+
gem.avatars3d.onChange(draw);
|
|
3815
|
+
```
|
|
3816
|
+
|
|
3817
|
+
The guide is `docs/arcade-avatars.md`: the rig, the config, uploading and
|
|
3818
|
+
selling with gemctl, and loading the model at runtime.
|
|
3819
|
+
|
|
3820
|
+
<a id="avatars3dapi-families"></a>
|
|
3821
|
+
|
|
3822
|
+
## Avatars3dApi.families
|
|
3823
|
+
|
|
3824
|
+
```ts
|
|
3825
|
+
families(): Promise<readonly Avatar3dFamily[]>
|
|
3826
|
+
```
|
|
3827
|
+
|
|
3828
|
+
The rig families your game accepts, in the order your published config
|
|
3829
|
+
declares them (`avatars_3d.families`) — the first is your default.
|
|
3830
|
+
|
|
3831
|
+
Resolves `[]` when your game has no published config on this channel, or
|
|
3832
|
+
its config declares no families. Loads the config through
|
|
3833
|
+
`gem.gameConfig.load()` and shares that one fetch; rejects when the config
|
|
3834
|
+
cannot be loaded, as `load()` does.
|
|
3835
|
+
|
|
3836
|
+
<a id="avatars3dapi-worn"></a>
|
|
3837
|
+
|
|
3838
|
+
## Avatars3dApi.worn
|
|
3839
|
+
|
|
3840
|
+
```ts
|
|
3841
|
+
worn(family?: Avatar3dFamily): WornAvatar3d | undefined
|
|
3842
|
+
```
|
|
3843
|
+
|
|
3844
|
+
The 3D avatar the player wears — in `family` when you name one, otherwise
|
|
3845
|
+
in your game's first declared family that has one. `undefined` when none
|
|
3846
|
+
is worn there, before the player arrives, and outside the Arcade: draw
|
|
3847
|
+
your default look.
|
|
3848
|
+
|
|
3849
|
+
Read live from [Gem.player](#gem-player), so it changes when the player wears
|
|
3850
|
+
another avatar or buys one; [Avatars3dApi.onChange](#avatars3dapi-onchange) tells you when.
|
|
3851
|
+
|
|
3852
|
+
| Parameter | Type |
|
|
3853
|
+
| --- | --- |
|
|
3854
|
+
| `family` | `Avatar3dFamily` |
|
|
3855
|
+
|
|
3856
|
+
<a id="avatars3dapi-offers"></a>
|
|
3857
|
+
|
|
3858
|
+
## Avatars3dApi.offers
|
|
3859
|
+
|
|
3860
|
+
```ts
|
|
3861
|
+
offers(): Promise<readonly Avatar3dOffer[]>
|
|
3862
|
+
```
|
|
3863
|
+
|
|
3864
|
+
Your game's 3D avatars on sale on this channel, with their prices, read
|
|
3865
|
+
from the platform with your game's own token. Render your shop from this,
|
|
3866
|
+
never from prices of your own.
|
|
3867
|
+
|
|
3868
|
+
Resolves `[]` when you have nothing on sale. Rejects with a `GemApiError`
|
|
3869
|
+
when the platform cannot be read — a shop that cannot load says so.
|
|
3870
|
+
|
|
3871
|
+
<a id="avatars3dapi-purchase"></a>
|
|
3872
|
+
|
|
3873
|
+
## Avatars3dApi.purchase
|
|
3874
|
+
|
|
3875
|
+
```ts
|
|
3876
|
+
purchase(request: Avatar3dPurchaseRequest): Promise<PurchaseOutcome>
|
|
3877
|
+
```
|
|
3878
|
+
|
|
3879
|
+
Buy one of your 3D avatars for the player and put it on. The Arcade
|
|
3880
|
+
prices it again, shows its own confirmation sheet, takes the currency and
|
|
3881
|
+
wears the avatar; your game then receives the player again, with the new
|
|
3882
|
+
avatar worn, and [Avatars3dApi.onChange](#avatars3dapi-onchange) runs.
|
|
3883
|
+
|
|
3884
|
+
Call it from the player's own click or key press — the Arcade shows no
|
|
3885
|
+
sheet without one and answers `declined` / `busy`.
|
|
3886
|
+
|
|
3887
|
+
NOTHING REJECTS. Every outcome resolves, exactly as on
|
|
3888
|
+
`gem.purchases.request`:
|
|
3889
|
+
|
|
3890
|
+
- `ok` — bought and worn, and the platform confirmed the player owns it.
|
|
3891
|
+
- `declined` — definitely not bought. `reason` says why:
|
|
3892
|
+
`already_owned` (the player has it — offer to wear it with
|
|
3893
|
+
`gem.openAvatarPicker({ tab: '3d' })`), `cancelled`, `insufficient_funds`,
|
|
3894
|
+
`no_price_in_currency`, `not_purchasable` (not on sale, or not an id from
|
|
3895
|
+
[Avatars3dApi.offers](#avatars3dapi-offers)), `busy`, and the rest of
|
|
3896
|
+
`PurchaseRefusalCode`. Return to your shop silently.
|
|
3897
|
+
- `unavailable` — no reliable answer. Show one neutral message, never
|
|
3898
|
+
retry on your own, and read [Avatars3dApi.worn](#avatars3dapi-worn) again.
|
|
3899
|
+
|
|
3900
|
+
**Outside the Arcade** — opened at the top level of a page with no Arcade
|
|
3901
|
+
around it, or under an Arcade that does not sell 3D avatars yet — it
|
|
3902
|
+
resolves `unavailable` with reason `error` at once and asks nobody.
|
|
3903
|
+
|
|
3904
|
+
| Parameter | Type |
|
|
3905
|
+
| --- | --- |
|
|
3906
|
+
| `request` | `Avatar3dPurchaseRequest` |
|
|
3907
|
+
|
|
3908
|
+
<a id="avatars3dapi-onchange"></a>
|
|
3909
|
+
|
|
3910
|
+
## Avatars3dApi.onChange
|
|
3911
|
+
|
|
3912
|
+
```ts
|
|
3913
|
+
onChange(listener: (worn: readonly WornAvatar3d[]) => void): () => void
|
|
3914
|
+
```
|
|
3915
|
+
|
|
3916
|
+
Call `listener` whenever the avatars the player wears change — they wore
|
|
3917
|
+
another one in the Arcade's picker, bought one, or their avatars arrived
|
|
3918
|
+
for the first time — with every worn avatar, one per family. Not called
|
|
3919
|
+
for the avatars already worn when you subscribe: read
|
|
3920
|
+
[Avatars3dApi.worn](#avatars3dapi-worn) for those.
|
|
3921
|
+
|
|
3922
|
+
| Parameter | Type |
|
|
3923
|
+
| --- | --- |
|
|
3924
|
+
| `listener` | `(worn: readonly WornAvatar3d[]) => void` |
|
|
3925
|
+
|
|
3926
|
+
**Returns.** a function that stops the calls. Calling it twice is harmless.
|
|
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
|
+
|
|
3672
4022
|
<a id="gemapierror"></a>
|
|
3673
4023
|
|
|
3674
4024
|
## GemApiError
|
|
@@ -4851,50 +5201,11 @@ a key you leave out is unchanged.
|
|
|
4851
5201
|
interface ControlsApi
|
|
4852
5202
|
```
|
|
4853
5203
|
|
|
4854
|
-
`gem.controls` — the player's camera and controls settings:
|
|
4855
|
-
|
|
4856
|
-
turn at the player's sensitivity.
|
|
5204
|
+
`gem.controls` — the player's camera and controls settings: turn look input
|
|
5205
|
+
into a camera turn at the player's sensitivity.
|
|
4857
5206
|
|
|
4858
5207
|
**Guides.** [what-a-game-must-do](../what-a-game-must-do.md)
|
|
4859
5208
|
|
|
4860
|
-
<a id="controlsapi-declare"></a>
|
|
4861
|
-
|
|
4862
|
-
## ControlsApi.declare
|
|
4863
|
-
|
|
4864
|
-
```ts
|
|
4865
|
-
declare(uses: GemControlsDeclaration): boolean
|
|
4866
|
-
```
|
|
4867
|
-
|
|
4868
|
-
Tell the Arcade which of the player's camera and controls settings your
|
|
4869
|
-
game uses, and for each one who decides it: `'player'` — you apply the
|
|
4870
|
-
Arcade's value from `gem.prefs.recommended` (or the player's own choice
|
|
4871
|
-
in your settings, which wins) — or `'game'` — you decide it yourself, and
|
|
4872
|
-
the Arcade's Settings shows that row as "Set by this game". Leave out a
|
|
4873
|
-
setting your game does not use.
|
|
4874
|
-
|
|
4875
|
-
```js
|
|
4876
|
-
gem.controls.declare({
|
|
4877
|
-
lookSensitivity: 'player',
|
|
4878
|
-
gamepadLookSensitivity: 'player',
|
|
4879
|
-
invertLookY: 'player',
|
|
4880
|
-
touchMovement: 'game', // this game always uses a fixed stick
|
|
4881
|
-
});
|
|
4882
|
-
```
|
|
4883
|
-
|
|
4884
|
-
**It is screen state, not a toggle.** Each call is the whole answer and
|
|
4885
|
-
replaces the last. The SDK holds it and sends it again after every
|
|
4886
|
-
reconnect, so call it once at boot, and again only when the answer
|
|
4887
|
-
changes. Any other key or value is dropped.
|
|
4888
|
-
|
|
4889
|
-
| Parameter | Type |
|
|
4890
|
-
| --- | --- |
|
|
4891
|
-
| `uses` | `GemControlsDeclaration` |
|
|
4892
|
-
|
|
4893
|
-
**Returns.** `true` when the Arcade was told now; `false` before the bridge is
|
|
4894
|
-
up (the declaration is held and sent when it connects), outside the
|
|
4895
|
-
Arcade, and under an embedder that does not show these settings. Never
|
|
4896
|
-
throws.
|
|
4897
|
-
|
|
4898
5209
|
<a id="controlsapi-look"></a>
|
|
4899
5210
|
|
|
4900
5211
|
## ControlsApi.look
|
|
@@ -4937,72 +5248,6 @@ readonly LOOK_BASE: GemLookBase
|
|
|
4937
5248
|
|
|
4938
5249
|
The base speeds `look` applies at 1×, in radians. Frozen.
|
|
4939
5250
|
|
|
4940
|
-
<a id="gemcontrolchoice"></a>
|
|
4941
|
-
|
|
4942
|
-
## GemControlChoice
|
|
4943
|
-
|
|
4944
|
-
```ts
|
|
4945
|
-
type GemControlChoice = "player" | "game"
|
|
4946
|
-
```
|
|
4947
|
-
|
|
4948
|
-
Who decides one camera or controls setting: `'player'` — your game applies
|
|
4949
|
-
the Arcade's value, or the player's own in-game choice, which wins — or
|
|
4950
|
-
`'game'` — your game decides it itself, and the Arcade's Settings shows the
|
|
4951
|
-
row as "Set by this game".
|
|
4952
|
-
|
|
4953
|
-
<a id="gemcontrolsdeclaration"></a>
|
|
4954
|
-
|
|
4955
|
-
## GemControlsDeclaration
|
|
4956
|
-
|
|
4957
|
-
```ts
|
|
4958
|
-
interface GemControlsDeclaration
|
|
4959
|
-
```
|
|
4960
|
-
|
|
4961
|
-
What `gem.controls.declare` takes: for each of the player's camera and
|
|
4962
|
-
controls settings your game uses, who decides it. Leave a setting out when
|
|
4963
|
-
your game does not use it at all — the Arcade then says "This game doesn't
|
|
4964
|
-
use this" beside that row.
|
|
4965
|
-
|
|
4966
|
-
<a id="gemcontrolsdeclaration-looksensitivity"></a>
|
|
4967
|
-
|
|
4968
|
-
## GemControlsDeclaration.lookSensitivity
|
|
4969
|
-
|
|
4970
|
-
```ts
|
|
4971
|
-
readonly lookSensitivity?: GemControlChoice
|
|
4972
|
-
```
|
|
4973
|
-
|
|
4974
|
-
Look speed for touch, mouse and pen — `gem.prefs.recommended.lookSensitivity`.
|
|
4975
|
-
|
|
4976
|
-
<a id="gemcontrolsdeclaration-gamepadlooksensitivity"></a>
|
|
4977
|
-
|
|
4978
|
-
## GemControlsDeclaration.gamepadLookSensitivity
|
|
4979
|
-
|
|
4980
|
-
```ts
|
|
4981
|
-
readonly gamepadLookSensitivity?: GemControlChoice
|
|
4982
|
-
```
|
|
4983
|
-
|
|
4984
|
-
Look speed for a gamepad stick — `gem.prefs.recommended.gamepadLookSensitivity`.
|
|
4985
|
-
|
|
4986
|
-
<a id="gemcontrolsdeclaration-invertlooky"></a>
|
|
4987
|
-
|
|
4988
|
-
## GemControlsDeclaration.invertLookY
|
|
4989
|
-
|
|
4990
|
-
```ts
|
|
4991
|
-
readonly invertLookY?: GemControlChoice
|
|
4992
|
-
```
|
|
4993
|
-
|
|
4994
|
-
Inverted up/down look — `gem.prefs.recommended.invertLookY`.
|
|
4995
|
-
|
|
4996
|
-
<a id="gemcontrolsdeclaration-touchmovement"></a>
|
|
4997
|
-
|
|
4998
|
-
## GemControlsDeclaration.touchMovement
|
|
4999
|
-
|
|
5000
|
-
```ts
|
|
5001
|
-
readonly touchMovement?: GemControlChoice
|
|
5002
|
-
```
|
|
5003
|
-
|
|
5004
|
-
The touch movement thumbstick, floating or fixed — `gem.prefs.recommended.touchMovement`.
|
|
5005
|
-
|
|
5006
5251
|
<a id="device_settings_max_bytes"></a>
|
|
5007
5252
|
|
|
5008
5253
|
## DEVICE_SETTINGS_MAX_BYTES
|
|
@@ -5196,7 +5441,7 @@ interface RewardCue
|
|
|
5196
5441
|
```
|
|
5197
5442
|
|
|
5198
5443
|
A platform-currency reward on its way to the arcade — in the Gem Arcade, a
|
|
5199
|
-
flight into the Gem button
|
|
5444
|
+
flight into the Gem button, in whichever corner of your frame it sits — what
|
|
5200
5445
|
`gem.cueReward` takes.
|
|
5201
5446
|
|
|
5202
5447
|
<a id="rewardcue-currencyslug"></a>
|
|
@@ -5257,6 +5502,18 @@ y: number
|
|
|
5257
5502
|
|
|
5258
5503
|
From the top edge of your viewport.
|
|
5259
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
|
+
|
|
5260
5517
|
<a id="framestate"></a>
|
|
5261
5518
|
|
|
5262
5519
|
## FrameState
|
|
@@ -5563,53 +5820,52 @@ wallet.
|
|
|
5563
5820
|
**Returns.** whether the message left the frame — `false` before the bridge is
|
|
5564
5821
|
up, for an arcade with no wallet, and past this frame's own limit.
|
|
5565
5822
|
|
|
5566
|
-
<a id="gemframe-
|
|
5823
|
+
<a id="gemframe-setmenu"></a>
|
|
5567
5824
|
|
|
5568
|
-
## GemFrame.
|
|
5825
|
+
## GemFrame.setMenu
|
|
5569
5826
|
|
|
5570
5827
|
```ts
|
|
5571
|
-
|
|
5828
|
+
setMenu(items?: readonly { id: string; label: string }[]): boolean
|
|
5572
5829
|
```
|
|
5573
5830
|
|
|
5574
|
-
Tell the arcade
|
|
5575
|
-
|
|
5576
|
-
|
|
5831
|
+
Tell the arcade what your game adds to its menu: up to four entries of its
|
|
5832
|
+
own — the whole answer each time, the latest one winning. Your settings
|
|
5833
|
+
are not among them: a game opens its settings from its own button.
|
|
5577
5834
|
|
|
5578
|
-
Prefer `gem.
|
|
5579
|
-
|
|
5580
|
-
that
|
|
5835
|
+
Prefer `gem.setMenu`, which holds the state across a reconnect and calls
|
|
5836
|
+
your handlers when the player chooses an entry. This one sends only while
|
|
5837
|
+
connected, and only to an arcade that draws a menu.
|
|
5581
5838
|
|
|
5582
5839
|
| Parameter | Type |
|
|
5583
5840
|
| --- | --- |
|
|
5584
|
-
| `
|
|
5841
|
+
| `items` | `readonly { id: string; label: string }[]` |
|
|
5585
5842
|
|
|
5586
5843
|
**Returns.** whether the message left the frame — `false` before the bridge is
|
|
5587
|
-
up, for an arcade
|
|
5588
|
-
frame's own limit.
|
|
5844
|
+
up, for an arcade with no menu, and past this frame's own limit.
|
|
5589
5845
|
|
|
5590
|
-
<a id="gemframe-
|
|
5846
|
+
<a id="gemframe-setgemcorner"></a>
|
|
5591
5847
|
|
|
5592
|
-
## GemFrame.
|
|
5848
|
+
## GemFrame.setGemCorner
|
|
5593
5849
|
|
|
5594
5850
|
```ts
|
|
5595
|
-
|
|
5851
|
+
setGemCorner(corner: GemCorner): boolean
|
|
5596
5852
|
```
|
|
5597
5853
|
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
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.
|
|
5601
5857
|
|
|
5602
|
-
Prefer `gem.
|
|
5603
|
-
|
|
5604
|
-
|
|
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.
|
|
5605
5861
|
|
|
5606
5862
|
| Parameter | Type |
|
|
5607
5863
|
| --- | --- |
|
|
5608
|
-
| `
|
|
5609
|
-
| `items` | `readonly { id: string; label: string }[]` |
|
|
5864
|
+
| `corner` | `GemCorner` |
|
|
5610
5865
|
|
|
5611
5866
|
**Returns.** whether the message left the frame — `false` before the bridge is
|
|
5612
|
-
up, for an arcade
|
|
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.
|
|
5613
5869
|
|
|
5614
5870
|
<a id="gemframe-requestshare"></a>
|
|
5615
5871
|
|
|
@@ -5860,6 +6116,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
5860
6116
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
5861
6117
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
5862
6118
|
|
|
6119
|
+
<a id="friend-avatars3d"></a>
|
|
6120
|
+
|
|
6121
|
+
## Friend.avatars3d
|
|
6122
|
+
|
|
6123
|
+
```ts
|
|
6124
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
6125
|
+
```
|
|
6126
|
+
|
|
6127
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
6128
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
6129
|
+
default look.
|
|
6130
|
+
|
|
6131
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
6132
|
+
avatar of the game's first declared family that has one. A game that
|
|
6133
|
+
accepts a single family can read either; one that accepts several picks by
|
|
6134
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
6135
|
+
the flat fields then.
|
|
6136
|
+
|
|
5863
6137
|
<a id="friend-badges"></a>
|
|
5864
6138
|
|
|
5865
6139
|
## Friend.badges
|
|
@@ -7721,6 +7995,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
7721
7995
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
7722
7996
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
7723
7997
|
|
|
7998
|
+
<a id="gemplayer-avatars3d"></a>
|
|
7999
|
+
|
|
8000
|
+
## GemPlayer.avatars3d
|
|
8001
|
+
|
|
8002
|
+
```ts
|
|
8003
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
8004
|
+
```
|
|
8005
|
+
|
|
8006
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
8007
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
8008
|
+
default look.
|
|
8009
|
+
|
|
8010
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
8011
|
+
avatar of the game's first declared family that has one. A game that
|
|
8012
|
+
accepts a single family can read either; one that accepts several picks by
|
|
8013
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
8014
|
+
the flat fields then.
|
|
8015
|
+
|
|
7724
8016
|
<a id="gemplayer-badges"></a>
|
|
7725
8017
|
|
|
7726
8018
|
## GemPlayer.badges
|
|
@@ -8141,7 +8433,7 @@ readonly reserved: readonly GemReservedArea[]
|
|
|
8141
8433
|
```
|
|
8142
8434
|
|
|
8143
8435
|
Rectangles of your frame the arcade's own controls cover — in the Gem
|
|
8144
|
-
Arcade, its Gem button in
|
|
8436
|
+
Arcade, its Gem button in whichever corner it sits, and the frame-rate readout
|
|
8145
8437
|
beside it while the player shows it; an embedder that draws wallets over
|
|
8146
8438
|
your game adds theirs (see `setWalletVisible`). Keep essential UI and touch
|
|
8147
8439
|
targets out of them. Empty when the arcade covers nothing.
|
|
@@ -8279,20 +8571,8 @@ and your game is running again by the time this fires.
|
|
|
8279
8571
|
interface GameMenu
|
|
8280
8572
|
```
|
|
8281
8573
|
|
|
8282
|
-
What your game adds to the arcade's menu — see `gem.setMenu`.
|
|
8283
|
-
|
|
8284
|
-
<a id="gamemenu-onsettings"></a>
|
|
8285
|
-
|
|
8286
|
-
## GameMenu.onSettings
|
|
8287
|
-
|
|
8288
|
-
```ts
|
|
8289
|
-
readonly onSettings?: () => void
|
|
8290
|
-
```
|
|
8291
|
-
|
|
8292
|
-
Open your settings screen. Another embedder may show a Settings entry that
|
|
8293
|
-
calls it, but **the Gem Arcade no longer does**: draw a settings button of
|
|
8294
|
-
your own, always (top-right is the recommendation). Passing this is still
|
|
8295
|
-
accepted and harmless.
|
|
8574
|
+
What your game adds to the arcade's menu — see `gem.setMenu`. Your settings
|
|
8575
|
+
are not part of it: they open from your own settings button.
|
|
8296
8576
|
|
|
8297
8577
|
<a id="gamemenu-items"></a>
|
|
8298
8578
|
|
|
@@ -8830,6 +9110,32 @@ client sends.
|
|
|
8830
9110
|
up, under an embedder with no avatar picker, or past six asks a minute.
|
|
8831
9111
|
It never throws and never waits.
|
|
8832
9112
|
|
|
9113
|
+
<a id="gem-avatars3d"></a>
|
|
9114
|
+
|
|
9115
|
+
## Gem.avatars3d
|
|
9116
|
+
|
|
9117
|
+
```ts
|
|
9118
|
+
readonly avatars3d: Avatars3dApi
|
|
9119
|
+
```
|
|
9120
|
+
|
|
9121
|
+
Arcade 3D avatars: what the player wears, the rig families your game
|
|
9122
|
+
accepts, the avatars your game sells, and buying one — which wears it.
|
|
9123
|
+
2D portraits are a separate system and are not here.
|
|
9124
|
+
|
|
9125
|
+
```js
|
|
9126
|
+
const draw = () => {
|
|
9127
|
+
const worn = gem.avatars3d.worn();
|
|
9128
|
+
const url = worn && platformIconUrl(worn.modelUrl);
|
|
9129
|
+
if (url) loadCharacter(url);
|
|
9130
|
+
else useDefaultCharacter();
|
|
9131
|
+
};
|
|
9132
|
+
draw();
|
|
9133
|
+
gem.avatars3d.onChange(draw);
|
|
9134
|
+
```
|
|
9135
|
+
|
|
9136
|
+
See [Arcade avatars](../arcade-avatars.md) for the rig, the config, and
|
|
9137
|
+
uploading and selling avatars with gemctl.
|
|
9138
|
+
|
|
8833
9139
|
<a id="gem-vibration"></a>
|
|
8834
9140
|
|
|
8835
9141
|
## Gem.vibration
|
|
@@ -8874,13 +9180,10 @@ readonly controls: ControlsApi
|
|
|
8874
9180
|
|
|
8875
9181
|
The player's camera and controls settings — look sensitivity, gamepad look
|
|
8876
9182
|
sensitivity, invert look and touch movement, which arrive in
|
|
8877
|
-
`gem.prefs.recommended
|
|
9183
|
+
`gem.prefs.recommended` as the player's Arcade-wide defaults. Turn look
|
|
9184
|
+
input into a camera turn at the player's sensitivity:
|
|
8878
9185
|
|
|
8879
9186
|
```js
|
|
8880
|
-
// 1. Tell the Arcade which ones your game leaves to the player.
|
|
8881
|
-
gem.controls.declare({ lookSensitivity: 'player', invertLookY: 'player' });
|
|
8882
|
-
|
|
8883
|
-
// 2. Turn look input into a camera turn at the player's sensitivity.
|
|
8884
9187
|
const look = gem.controls.look();
|
|
8885
9188
|
// dx, dy: the pointer's move in CSS px since the last event.
|
|
8886
9189
|
const t = look.fromPointer(dx, dy, e.pointerType, camera.pitch);
|
|
@@ -9257,7 +9560,7 @@ cueReward(cue: RewardCue): boolean
|
|
|
9257
9560
|
|
|
9258
9561
|
Tell the arcade a platform-currency reward is on its way, so it **shows it
|
|
9259
9562
|
landing**: in the Gem Arcade the currency flies from `origin` into the Gem
|
|
9260
|
-
button
|
|
9563
|
+
button, wherever on your frame it sits, which pops as each mark lands, and
|
|
9261
9564
|
the player's total moves once the platform confirms the grant. The Gem
|
|
9262
9565
|
Arcade draws no wallet over your game: the player sees their Gems and
|
|
9263
9566
|
Tickets in the Gem menu. A payout you do not cue still flies, from the
|
|
@@ -9359,10 +9662,9 @@ gem.setMenu({
|
|
|
9359
9662
|
```
|
|
9360
9663
|
|
|
9361
9664
|
**Your settings are not in it: draw your own settings button, always** —
|
|
9362
|
-
top-right
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
none a player can reach.
|
|
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.
|
|
9366
9668
|
|
|
9367
9669
|
**It is screen state, not a toggle.** Each call is the whole answer and
|
|
9368
9670
|
replaces the last, so call it again when the entries change — a new
|
|
@@ -9376,12 +9678,52 @@ should not assume the game was paused by you.
|
|
|
9376
9678
|
|
|
9377
9679
|
| Parameter | Type | Description |
|
|
9378
9680
|
| --- | --- | --- |
|
|
9379
|
-
| `menu` | `GameMenu` | Your
|
|
9681
|
+
| `menu` | `GameMenu` | Your own entries. |
|
|
9380
9682
|
|
|
9381
9683
|
**Returns.** `true` when the arcade was told now; `false` before the bridge is
|
|
9382
9684
|
up (the menu is held and sent when it connects) and under an embedder
|
|
9383
9685
|
that draws no menu.
|
|
9384
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
|
+
|
|
9385
9727
|
<a id="gem-exit"></a>
|
|
9386
9728
|
|
|
9387
9729
|
## Gem.exit
|
|
@@ -10181,7 +10523,7 @@ The match this connection belongs to.
|
|
|
10181
10523
|
## MatchConnection.protocol
|
|
10182
10524
|
|
|
10183
10525
|
```ts
|
|
10184
|
-
readonly protocol: "
|
|
10526
|
+
readonly protocol: "p2p" | "dedicated" | "loopback"
|
|
10185
10527
|
```
|
|
10186
10528
|
|
|
10187
10529
|
What is on the other end: `dedicated` (the platform's server), `p2p` (the
|
|
@@ -10368,6 +10710,84 @@ readonly iconUrl: string
|
|
|
10368
10710
|
The badge's thumbnail. Pass it through [platformIconUrl](#platformiconurl) before
|
|
10369
10711
|
putting it in an `<img src>`.
|
|
10370
10712
|
|
|
10713
|
+
<a id="avatar3dfamily"></a>
|
|
10714
|
+
|
|
10715
|
+
## Avatar3dFamily
|
|
10716
|
+
|
|
10717
|
+
```ts
|
|
10718
|
+
type Avatar3dFamily = "small_human" | "adult_human" | string & object
|
|
10719
|
+
```
|
|
10720
|
+
|
|
10721
|
+
A rig family — the skeleton contract a 3D avatar is built on, and what a
|
|
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.
|
|
10733
|
+
|
|
10734
|
+
Open-ended (`| (string & {})`) so a family the platform adds later does not
|
|
10735
|
+
break a `switch` you compiled against this version: keep a `default` arm and
|
|
10736
|
+
skip a family you do not draw.
|
|
10737
|
+
|
|
10738
|
+
<a id="wornavatar3d"></a>
|
|
10739
|
+
|
|
10740
|
+
## WornAvatar3d
|
|
10741
|
+
|
|
10742
|
+
```ts
|
|
10743
|
+
interface WornAvatar3d
|
|
10744
|
+
```
|
|
10745
|
+
|
|
10746
|
+
One 3D avatar a player wears — at most one per [Avatar3dFamily](#avatar3dfamily).
|
|
10747
|
+
|
|
10748
|
+
<a id="wornavatar3d-family"></a>
|
|
10749
|
+
|
|
10750
|
+
## WornAvatar3d.family
|
|
10751
|
+
|
|
10752
|
+
```ts
|
|
10753
|
+
readonly family: Avatar3dFamily
|
|
10754
|
+
```
|
|
10755
|
+
|
|
10756
|
+
The rig family this avatar is built on.
|
|
10757
|
+
|
|
10758
|
+
<a id="wornavatar3d-id"></a>
|
|
10759
|
+
|
|
10760
|
+
## WornAvatar3d.id
|
|
10761
|
+
|
|
10762
|
+
```ts
|
|
10763
|
+
readonly id: string
|
|
10764
|
+
```
|
|
10765
|
+
|
|
10766
|
+
The avatar's item id — a stable key for the model, never something to
|
|
10767
|
+
show as text.
|
|
10768
|
+
|
|
10769
|
+
<a id="wornavatar3d-modelurl"></a>
|
|
10770
|
+
|
|
10771
|
+
## WornAvatar3d.modelUrl
|
|
10772
|
+
|
|
10773
|
+
```ts
|
|
10774
|
+
readonly modelUrl: string
|
|
10775
|
+
```
|
|
10776
|
+
|
|
10777
|
+
The avatar's model, a binary glTF (`.glb`) on the family's rig. Pass it
|
|
10778
|
+
through [platformIconUrl](#platformiconurl) before loading it.
|
|
10779
|
+
|
|
10780
|
+
<a id="wornavatar3d-iconurl"></a>
|
|
10781
|
+
|
|
10782
|
+
## WornAvatar3d.iconUrl
|
|
10783
|
+
|
|
10784
|
+
```ts
|
|
10785
|
+
readonly iconUrl: string
|
|
10786
|
+
```
|
|
10787
|
+
|
|
10788
|
+
A rendered portrait of the avatar, for a roster or a menu. Pass it through
|
|
10789
|
+
[platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
10790
|
+
|
|
10371
10791
|
<a id="playeridentity"></a>
|
|
10372
10792
|
|
|
10373
10793
|
## PlayerIdentity
|
|
@@ -10511,6 +10931,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
10511
10931
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
10512
10932
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
10513
10933
|
|
|
10934
|
+
<a id="playeridentity-avatars3d"></a>
|
|
10935
|
+
|
|
10936
|
+
## PlayerIdentity.avatars3d
|
|
10937
|
+
|
|
10938
|
+
```ts
|
|
10939
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
10940
|
+
```
|
|
10941
|
+
|
|
10942
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
10943
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
10944
|
+
default look.
|
|
10945
|
+
|
|
10946
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
10947
|
+
avatar of the game's first declared family that has one. A game that
|
|
10948
|
+
accepts a single family can read either; one that accepts several picks by
|
|
10949
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
10950
|
+
the flat fields then.
|
|
10951
|
+
|
|
10514
10952
|
<a id="playeridentity-badges"></a>
|
|
10515
10953
|
|
|
10516
10954
|
## PlayerIdentity.badges
|
|
@@ -10550,7 +10988,7 @@ for (const row of opponents) {
|
|
|
10550
10988
|
|
|
10551
10989
|
Reads `player_id`, `display_name`, `discriminator`, `display_tag`,
|
|
10552
10990
|
`avatar_icon_id`, `avatar_icon_url`, `avatar_3d_id`, `avatar_3d_model_url`,
|
|
10553
|
-
`avatar_3d_icon_url` and `badges`, and nothing else from the row. Anything missing, empty or of the wrong type is absent in the result.
|
|
10991
|
+
`avatar_3d_icon_url`, `avatars_3d` and `badges`, and nothing else from the row. Anything missing, empty or of the wrong type is absent in the result.
|
|
10554
10992
|
|
|
10555
10993
|
| Parameter | Type |
|
|
10556
10994
|
| --- | --- |
|
|
@@ -11810,12 +12248,44 @@ a Buy button mostly does not write one.
|
|
|
11810
12248
|
| --- | --- |
|
|
11811
12249
|
| `req` | `PurchaseRequest` |
|
|
11812
12250
|
|
|
12251
|
+
<a id="avatar3dpurchaserequest"></a>
|
|
12252
|
+
|
|
12253
|
+
## Avatar3dPurchaseRequest
|
|
12254
|
+
|
|
12255
|
+
```ts
|
|
12256
|
+
interface Avatar3dPurchaseRequest
|
|
12257
|
+
```
|
|
12258
|
+
|
|
12259
|
+
What a game asks for when it buys one of its own 3D avatars for the player
|
|
12260
|
+
with `gem.avatars3d.purchase`.
|
|
12261
|
+
|
|
12262
|
+
<a id="avatar3dpurchaserequest-itemid"></a>
|
|
12263
|
+
|
|
12264
|
+
## Avatar3dPurchaseRequest.itemId
|
|
12265
|
+
|
|
12266
|
+
```ts
|
|
12267
|
+
itemId: string
|
|
12268
|
+
```
|
|
12269
|
+
|
|
12270
|
+
The avatar's item id — `itemId` on an `Avatar3dOffer`.
|
|
12271
|
+
|
|
12272
|
+
<a id="avatar3dpurchaserequest-currencyslug"></a>
|
|
12273
|
+
|
|
12274
|
+
## Avatar3dPurchaseRequest.currencySlug
|
|
12275
|
+
|
|
12276
|
+
```ts
|
|
12277
|
+
currencySlug: string
|
|
12278
|
+
```
|
|
12279
|
+
|
|
12280
|
+
The platform currency to pay in, `GEMS` or `ARCADE_TICKETS`. The offer
|
|
12281
|
+
must carry a price in it.
|
|
12282
|
+
|
|
11813
12283
|
<a id="purchaserefusalcode"></a>
|
|
11814
12284
|
|
|
11815
12285
|
## PurchaseRefusalCode
|
|
11816
12286
|
|
|
11817
12287
|
```ts
|
|
11818
|
-
type PurchaseRefusalCode = "unknown_currency" | "currency_not_in_game_payable" | "not_purchasable" | "no_price_in_currency" | "busy" | "cancelled" | "insufficient_funds" | "price_mismatch" | "config_version_stale" | "platform_currency_unavailable" | "not_available" | "recipe_locked" | "recipe_on_cooldown" | "recipe_max_uses_exceeded" | "item_max_stack_exceeded" | "recipe_costs_unmet" | "quantity_invalid" | "error"
|
|
12288
|
+
type PurchaseRefusalCode = "unknown_currency" | "currency_not_in_game_payable" | "not_purchasable" | "no_price_in_currency" | "busy" | "cancelled" | "insufficient_funds" | "price_mismatch" | "config_version_stale" | "platform_currency_unavailable" | "not_available" | "recipe_locked" | "already_owned" | "recipe_on_cooldown" | "recipe_max_uses_exceeded" | "item_max_stack_exceeded" | "recipe_costs_unmet" | "quantity_invalid" | "error"
|
|
11819
12289
|
```
|
|
11820
12290
|
|
|
11821
12291
|
Every reason a purchase can be refused, on either purchase path.
|
|
@@ -11841,6 +12311,9 @@ Every reason a purchase can be refused, on either purchase path.
|
|
|
11841
12311
|
- `not_available` — the recipe is outside its availability window, or
|
|
11842
12312
|
inactive; nothing was charged. Hide or disable it until its window opens.
|
|
11843
12313
|
- `recipe_locked` — the recipe's prerequisites are not met.
|
|
12314
|
+
- `already_owned` — the player already owns the 3D avatar
|
|
12315
|
+
`gem.avatars3d.purchase` asked for; nothing was charged. Only that call
|
|
12316
|
+
answers it.
|
|
11844
12317
|
- `recipe_on_cooldown`, `recipe_max_uses_exceeded`, `item_max_stack_exceeded`,
|
|
11845
12318
|
`recipe_costs_unmet`, `quantity_invalid` — the recipe or item refused this
|
|
11846
12319
|
purchase, before any charge.
|
|
@@ -13127,6 +13600,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
13127
13600
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
13128
13601
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
13129
13602
|
|
|
13603
|
+
<a id="leaderboardentry-avatars3d"></a>
|
|
13604
|
+
|
|
13605
|
+
## LeaderboardEntry.avatars3d
|
|
13606
|
+
|
|
13607
|
+
```ts
|
|
13608
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
13609
|
+
```
|
|
13610
|
+
|
|
13611
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
13612
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
13613
|
+
default look.
|
|
13614
|
+
|
|
13615
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
13616
|
+
avatar of the game's first declared family that has one. A game that
|
|
13617
|
+
accepts a single family can read either; one that accepts several picks by
|
|
13618
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
13619
|
+
the flat fields then.
|
|
13620
|
+
|
|
13130
13621
|
<a id="leaderboardentry-badges"></a>
|
|
13131
13622
|
|
|
13132
13623
|
## LeaderboardEntry.badges
|
|
@@ -14620,6 +15111,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
14620
15111
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
14621
15112
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
14622
15113
|
|
|
15114
|
+
<a id="playerprofile-avatars3d"></a>
|
|
15115
|
+
|
|
15116
|
+
## PlayerProfile.avatars3d
|
|
15117
|
+
|
|
15118
|
+
```ts
|
|
15119
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
15120
|
+
```
|
|
15121
|
+
|
|
15122
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
15123
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
15124
|
+
default look.
|
|
15125
|
+
|
|
15126
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
15127
|
+
avatar of the game's first declared family that has one. A game that
|
|
15128
|
+
accepts a single family can read either; one that accepts several picks by
|
|
15129
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
15130
|
+
the flat fields then.
|
|
15131
|
+
|
|
14623
15132
|
<a id="playerprofile-badges"></a>
|
|
14624
15133
|
|
|
14625
15134
|
## PlayerProfile.badges
|
|
@@ -17206,6 +17715,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
17206
17715
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
17207
17716
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
17208
17717
|
|
|
17718
|
+
<a id="roommember-avatars3d"></a>
|
|
17719
|
+
|
|
17720
|
+
## RoomMember.avatars3d
|
|
17721
|
+
|
|
17722
|
+
```ts
|
|
17723
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
17724
|
+
```
|
|
17725
|
+
|
|
17726
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
17727
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
17728
|
+
default look.
|
|
17729
|
+
|
|
17730
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
17731
|
+
avatar of the game's first declared family that has one. A game that
|
|
17732
|
+
accepts a single family can read either; one that accepts several picks by
|
|
17733
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
17734
|
+
the flat fields then.
|
|
17735
|
+
|
|
17209
17736
|
<a id="roommember-badges"></a>
|
|
17210
17737
|
|
|
17211
17738
|
## RoomMember.badges
|
|
@@ -18036,6 +18563,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
18036
18563
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
18037
18564
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
18038
18565
|
|
|
18566
|
+
<a id="showcasefriendentry-avatars3d"></a>
|
|
18567
|
+
|
|
18568
|
+
## ShowcaseFriendEntry.avatars3d
|
|
18569
|
+
|
|
18570
|
+
```ts
|
|
18571
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
18572
|
+
```
|
|
18573
|
+
|
|
18574
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
18575
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
18576
|
+
default look.
|
|
18577
|
+
|
|
18578
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
18579
|
+
avatar of the game's first declared family that has one. A game that
|
|
18580
|
+
accepts a single family can read either; one that accepts several picks by
|
|
18581
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
18582
|
+
the flat fields then.
|
|
18583
|
+
|
|
18039
18584
|
<a id="showcasefriendentry-badges"></a>
|
|
18040
18585
|
|
|
18041
18586
|
## ShowcaseFriendEntry.badges
|