@indiegems/gem-web-sdk 11.1.2 → 13.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 +37 -0
- package/README.md +3 -1
- package/dist/function.d.ts +9 -1
- package/dist/game.d.ts +88 -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 +100 -16
- package/dist/sdk.d.ts +98 -14
- package/dist/server-api.d.ts +9 -1
- package/dist/server.d.ts +10 -1
- package/docs/api/api-reference-function.md +8076 -0
- package/docs/api/api-reference-game.md +719 -165
- package/docs/api/api-reference-server.md +5 -3
- package/docs/api/reference.json +10310 -225
- package/docs/arcade-avatars.md +303 -0
- package/docs/changelog.md +37 -0
- package/docs/getting-started.md +5 -2
- package/docs/manifest.json +21 -16
- package/docs/rooms-and-matches.md +64 -1
- package/docs/saving-player-progress.md +16 -10
- package/docs/server-bundles.md +2 -2
- package/docs/serverless-functions-js.md +118 -44
- package/docs/serverless-functions.md +26 -11
- package/docs/what-a-game-must-do.md +53 -46
- package/package.json +1 -1
- package/schema/bridge.v1.json +282 -18
- 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.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.
|
|
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,262 @@ 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
|
+
|
|
3672
3928
|
<a id="gemapierror"></a>
|
|
3673
3929
|
|
|
3674
3930
|
## GemApiError
|
|
@@ -3832,8 +4088,10 @@ the callback instead.
|
|
|
3832
4088
|
|
|
3833
4089
|
- `ready` — a usable token is held.
|
|
3834
4090
|
- `pending` — no token yet, or one is being fetched.
|
|
3835
|
-
- `degraded` — the last attempt failed but another may succeed
|
|
3836
|
-
|
|
4091
|
+
- `degraded` — the last attempt failed but another may succeed, and the SDK
|
|
4092
|
+
makes it on its own: once any wait the platform named has passed, or
|
|
4093
|
+
otherwise at growing intervals of up to a minute. Keep playing. `ready`
|
|
4094
|
+
follows when an attempt succeeds, with no call of yours needed to cause it.
|
|
3837
4095
|
- `lost` — terminal for this session. Signing back in is the only way
|
|
3838
4096
|
forward, and retrying will not produce one.
|
|
3839
4097
|
|
|
@@ -4849,50 +5107,11 @@ a key you leave out is unchanged.
|
|
|
4849
5107
|
interface ControlsApi
|
|
4850
5108
|
```
|
|
4851
5109
|
|
|
4852
|
-
`gem.controls` — the player's camera and controls settings:
|
|
4853
|
-
|
|
4854
|
-
turn at the player's sensitivity.
|
|
5110
|
+
`gem.controls` — the player's camera and controls settings: turn look input
|
|
5111
|
+
into a camera turn at the player's sensitivity.
|
|
4855
5112
|
|
|
4856
5113
|
**Guides.** [what-a-game-must-do](../what-a-game-must-do.md)
|
|
4857
5114
|
|
|
4858
|
-
<a id="controlsapi-declare"></a>
|
|
4859
|
-
|
|
4860
|
-
## ControlsApi.declare
|
|
4861
|
-
|
|
4862
|
-
```ts
|
|
4863
|
-
declare(uses: GemControlsDeclaration): boolean
|
|
4864
|
-
```
|
|
4865
|
-
|
|
4866
|
-
Tell the Arcade which of the player's camera and controls settings your
|
|
4867
|
-
game uses, and for each one who decides it: `'player'` — you apply the
|
|
4868
|
-
Arcade's value from `gem.prefs.recommended` (or the player's own choice
|
|
4869
|
-
in your settings, which wins) — or `'game'` — you decide it yourself, and
|
|
4870
|
-
the Arcade's Settings shows that row as "Set by this game". Leave out a
|
|
4871
|
-
setting your game does not use.
|
|
4872
|
-
|
|
4873
|
-
```js
|
|
4874
|
-
gem.controls.declare({
|
|
4875
|
-
lookSensitivity: 'player',
|
|
4876
|
-
gamepadLookSensitivity: 'player',
|
|
4877
|
-
invertLookY: 'player',
|
|
4878
|
-
touchMovement: 'game', // this game always uses a fixed stick
|
|
4879
|
-
});
|
|
4880
|
-
```
|
|
4881
|
-
|
|
4882
|
-
**It is screen state, not a toggle.** Each call is the whole answer and
|
|
4883
|
-
replaces the last. The SDK holds it and sends it again after every
|
|
4884
|
-
reconnect, so call it once at boot, and again only when the answer
|
|
4885
|
-
changes. Any other key or value is dropped.
|
|
4886
|
-
|
|
4887
|
-
| Parameter | Type |
|
|
4888
|
-
| --- | --- |
|
|
4889
|
-
| `uses` | `GemControlsDeclaration` |
|
|
4890
|
-
|
|
4891
|
-
**Returns.** `true` when the Arcade was told now; `false` before the bridge is
|
|
4892
|
-
up (the declaration is held and sent when it connects), outside the
|
|
4893
|
-
Arcade, and under an embedder that does not show these settings. Never
|
|
4894
|
-
throws.
|
|
4895
|
-
|
|
4896
5115
|
<a id="controlsapi-look"></a>
|
|
4897
5116
|
|
|
4898
5117
|
## ControlsApi.look
|
|
@@ -4935,72 +5154,6 @@ readonly LOOK_BASE: GemLookBase
|
|
|
4935
5154
|
|
|
4936
5155
|
The base speeds `look` applies at 1×, in radians. Frozen.
|
|
4937
5156
|
|
|
4938
|
-
<a id="gemcontrolchoice"></a>
|
|
4939
|
-
|
|
4940
|
-
## GemControlChoice
|
|
4941
|
-
|
|
4942
|
-
```ts
|
|
4943
|
-
type GemControlChoice = "player" | "game"
|
|
4944
|
-
```
|
|
4945
|
-
|
|
4946
|
-
Who decides one camera or controls setting: `'player'` — your game applies
|
|
4947
|
-
the Arcade's value, or the player's own in-game choice, which wins — or
|
|
4948
|
-
`'game'` — your game decides it itself, and the Arcade's Settings shows the
|
|
4949
|
-
row as "Set by this game".
|
|
4950
|
-
|
|
4951
|
-
<a id="gemcontrolsdeclaration"></a>
|
|
4952
|
-
|
|
4953
|
-
## GemControlsDeclaration
|
|
4954
|
-
|
|
4955
|
-
```ts
|
|
4956
|
-
interface GemControlsDeclaration
|
|
4957
|
-
```
|
|
4958
|
-
|
|
4959
|
-
What `gem.controls.declare` takes: for each of the player's camera and
|
|
4960
|
-
controls settings your game uses, who decides it. Leave a setting out when
|
|
4961
|
-
your game does not use it at all — the Arcade then says "This game doesn't
|
|
4962
|
-
use this" beside that row.
|
|
4963
|
-
|
|
4964
|
-
<a id="gemcontrolsdeclaration-looksensitivity"></a>
|
|
4965
|
-
|
|
4966
|
-
## GemControlsDeclaration.lookSensitivity
|
|
4967
|
-
|
|
4968
|
-
```ts
|
|
4969
|
-
readonly lookSensitivity?: GemControlChoice
|
|
4970
|
-
```
|
|
4971
|
-
|
|
4972
|
-
Look speed for touch, mouse and pen — `gem.prefs.recommended.lookSensitivity`.
|
|
4973
|
-
|
|
4974
|
-
<a id="gemcontrolsdeclaration-gamepadlooksensitivity"></a>
|
|
4975
|
-
|
|
4976
|
-
## GemControlsDeclaration.gamepadLookSensitivity
|
|
4977
|
-
|
|
4978
|
-
```ts
|
|
4979
|
-
readonly gamepadLookSensitivity?: GemControlChoice
|
|
4980
|
-
```
|
|
4981
|
-
|
|
4982
|
-
Look speed for a gamepad stick — `gem.prefs.recommended.gamepadLookSensitivity`.
|
|
4983
|
-
|
|
4984
|
-
<a id="gemcontrolsdeclaration-invertlooky"></a>
|
|
4985
|
-
|
|
4986
|
-
## GemControlsDeclaration.invertLookY
|
|
4987
|
-
|
|
4988
|
-
```ts
|
|
4989
|
-
readonly invertLookY?: GemControlChoice
|
|
4990
|
-
```
|
|
4991
|
-
|
|
4992
|
-
Inverted up/down look — `gem.prefs.recommended.invertLookY`.
|
|
4993
|
-
|
|
4994
|
-
<a id="gemcontrolsdeclaration-touchmovement"></a>
|
|
4995
|
-
|
|
4996
|
-
## GemControlsDeclaration.touchMovement
|
|
4997
|
-
|
|
4998
|
-
```ts
|
|
4999
|
-
readonly touchMovement?: GemControlChoice
|
|
5000
|
-
```
|
|
5001
|
-
|
|
5002
|
-
The touch movement thumbstick, floating or fixed — `gem.prefs.recommended.touchMovement`.
|
|
5003
|
-
|
|
5004
5157
|
<a id="device_settings_max_bytes"></a>
|
|
5005
5158
|
|
|
5006
5159
|
## DEVICE_SETTINGS_MAX_BYTES
|
|
@@ -5561,41 +5714,17 @@ wallet.
|
|
|
5561
5714
|
**Returns.** whether the message left the frame — `false` before the bridge is
|
|
5562
5715
|
up, for an arcade with no wallet, and past this frame's own limit.
|
|
5563
5716
|
|
|
5564
|
-
<a id="gemframe-declarecontrols"></a>
|
|
5565
|
-
|
|
5566
|
-
## GemFrame.declareControls
|
|
5567
|
-
|
|
5568
|
-
```ts
|
|
5569
|
-
declareControls(uses: GemControlsDeclaration): boolean
|
|
5570
|
-
```
|
|
5571
|
-
|
|
5572
|
-
Tell the arcade which of the player's camera and controls settings your
|
|
5573
|
-
game leaves to the player and which it decides itself — the whole answer
|
|
5574
|
-
each time, the latest one winning.
|
|
5575
|
-
|
|
5576
|
-
Prefer `gem.controls.declare`, which holds the declaration across a
|
|
5577
|
-
reconnect. This one sends only while connected, and only to an arcade
|
|
5578
|
-
that shows these settings.
|
|
5579
|
-
|
|
5580
|
-
| Parameter | Type |
|
|
5581
|
-
| --- | --- |
|
|
5582
|
-
| `uses` | `GemControlsDeclaration` |
|
|
5583
|
-
|
|
5584
|
-
**Returns.** whether the message left the frame — `false` before the bridge is
|
|
5585
|
-
up, for an arcade that does not show these settings, and past this
|
|
5586
|
-
frame's own limit.
|
|
5587
|
-
|
|
5588
5717
|
<a id="gemframe-setmenu"></a>
|
|
5589
5718
|
|
|
5590
5719
|
## GemFrame.setMenu
|
|
5591
5720
|
|
|
5592
5721
|
```ts
|
|
5593
|
-
setMenu(
|
|
5722
|
+
setMenu(items?: readonly { id: string; label: string }[]): boolean
|
|
5594
5723
|
```
|
|
5595
5724
|
|
|
5596
|
-
Tell the arcade what your game adds to its menu:
|
|
5597
|
-
|
|
5598
|
-
|
|
5725
|
+
Tell the arcade what your game adds to its menu: up to four entries of its
|
|
5726
|
+
own — the whole answer each time, the latest one winning. Your settings
|
|
5727
|
+
are not among them: a game opens its settings from its own button.
|
|
5599
5728
|
|
|
5600
5729
|
Prefer `gem.setMenu`, which holds the state across a reconnect and calls
|
|
5601
5730
|
your handlers when the player chooses an entry. This one sends only while
|
|
@@ -5603,7 +5732,6 @@ connected, and only to an arcade that draws a menu.
|
|
|
5603
5732
|
|
|
5604
5733
|
| Parameter | Type |
|
|
5605
5734
|
| --- | --- |
|
|
5606
|
-
| `settings` | `boolean` |
|
|
5607
5735
|
| `items` | `readonly { id: string; label: string }[]` |
|
|
5608
5736
|
|
|
5609
5737
|
**Returns.** whether the message left the frame — `false` before the bridge is
|
|
@@ -5858,6 +5986,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
5858
5986
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
5859
5987
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
5860
5988
|
|
|
5989
|
+
<a id="friend-avatars3d"></a>
|
|
5990
|
+
|
|
5991
|
+
## Friend.avatars3d
|
|
5992
|
+
|
|
5993
|
+
```ts
|
|
5994
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
5995
|
+
```
|
|
5996
|
+
|
|
5997
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
5998
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
5999
|
+
default look.
|
|
6000
|
+
|
|
6001
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
6002
|
+
avatar of the game's first declared family that has one. A game that
|
|
6003
|
+
accepts a single family can read either; one that accepts several picks by
|
|
6004
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
6005
|
+
the flat fields then.
|
|
6006
|
+
|
|
5861
6007
|
<a id="friend-badges"></a>
|
|
5862
6008
|
|
|
5863
6009
|
## Friend.badges
|
|
@@ -7719,6 +7865,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
7719
7865
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
7720
7866
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
7721
7867
|
|
|
7868
|
+
<a id="gemplayer-avatars3d"></a>
|
|
7869
|
+
|
|
7870
|
+
## GemPlayer.avatars3d
|
|
7871
|
+
|
|
7872
|
+
```ts
|
|
7873
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
7874
|
+
```
|
|
7875
|
+
|
|
7876
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
7877
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
7878
|
+
default look.
|
|
7879
|
+
|
|
7880
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
7881
|
+
avatar of the game's first declared family that has one. A game that
|
|
7882
|
+
accepts a single family can read either; one that accepts several picks by
|
|
7883
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
7884
|
+
the flat fields then.
|
|
7885
|
+
|
|
7722
7886
|
<a id="gemplayer-badges"></a>
|
|
7723
7887
|
|
|
7724
7888
|
## GemPlayer.badges
|
|
@@ -8277,20 +8441,8 @@ and your game is running again by the time this fires.
|
|
|
8277
8441
|
interface GameMenu
|
|
8278
8442
|
```
|
|
8279
8443
|
|
|
8280
|
-
What your game adds to the arcade's menu — see `gem.setMenu`.
|
|
8281
|
-
|
|
8282
|
-
<a id="gamemenu-onsettings"></a>
|
|
8283
|
-
|
|
8284
|
-
## GameMenu.onSettings
|
|
8285
|
-
|
|
8286
|
-
```ts
|
|
8287
|
-
readonly onSettings?: () => void
|
|
8288
|
-
```
|
|
8289
|
-
|
|
8290
|
-
Open your settings screen. Another embedder may show a Settings entry that
|
|
8291
|
-
calls it, but **the Gem Arcade no longer does**: draw a settings button of
|
|
8292
|
-
your own, always (top-right is the recommendation). Passing this is still
|
|
8293
|
-
accepted and harmless.
|
|
8444
|
+
What your game adds to the arcade's menu — see `gem.setMenu`. Your settings
|
|
8445
|
+
are not part of it: they open from your own settings button.
|
|
8294
8446
|
|
|
8295
8447
|
<a id="gamemenu-items"></a>
|
|
8296
8448
|
|
|
@@ -8828,6 +8980,32 @@ client sends.
|
|
|
8828
8980
|
up, under an embedder with no avatar picker, or past six asks a minute.
|
|
8829
8981
|
It never throws and never waits.
|
|
8830
8982
|
|
|
8983
|
+
<a id="gem-avatars3d"></a>
|
|
8984
|
+
|
|
8985
|
+
## Gem.avatars3d
|
|
8986
|
+
|
|
8987
|
+
```ts
|
|
8988
|
+
readonly avatars3d: Avatars3dApi
|
|
8989
|
+
```
|
|
8990
|
+
|
|
8991
|
+
Arcade 3D avatars: what the player wears, the rig families your game
|
|
8992
|
+
accepts, the avatars your game sells, and buying one — which wears it.
|
|
8993
|
+
2D portraits are a separate system and are not here.
|
|
8994
|
+
|
|
8995
|
+
```js
|
|
8996
|
+
const draw = () => {
|
|
8997
|
+
const worn = gem.avatars3d.worn();
|
|
8998
|
+
const url = worn && platformIconUrl(worn.modelUrl);
|
|
8999
|
+
if (url) loadCharacter(url);
|
|
9000
|
+
else useDefaultCharacter();
|
|
9001
|
+
};
|
|
9002
|
+
draw();
|
|
9003
|
+
gem.avatars3d.onChange(draw);
|
|
9004
|
+
```
|
|
9005
|
+
|
|
9006
|
+
See [Arcade avatars](../arcade-avatars.md) for the rig, the config, and
|
|
9007
|
+
uploading and selling avatars with gemctl.
|
|
9008
|
+
|
|
8831
9009
|
<a id="gem-vibration"></a>
|
|
8832
9010
|
|
|
8833
9011
|
## Gem.vibration
|
|
@@ -8872,13 +9050,10 @@ readonly controls: ControlsApi
|
|
|
8872
9050
|
|
|
8873
9051
|
The player's camera and controls settings — look sensitivity, gamepad look
|
|
8874
9052
|
sensitivity, invert look and touch movement, which arrive in
|
|
8875
|
-
`gem.prefs.recommended
|
|
9053
|
+
`gem.prefs.recommended` as the player's Arcade-wide defaults. Turn look
|
|
9054
|
+
input into a camera turn at the player's sensitivity:
|
|
8876
9055
|
|
|
8877
9056
|
```js
|
|
8878
|
-
// 1. Tell the Arcade which ones your game leaves to the player.
|
|
8879
|
-
gem.controls.declare({ lookSensitivity: 'player', invertLookY: 'player' });
|
|
8880
|
-
|
|
8881
|
-
// 2. Turn look input into a camera turn at the player's sensitivity.
|
|
8882
9057
|
const look = gem.controls.look();
|
|
8883
9058
|
// dx, dy: the pointer's move in CSS px since the last event.
|
|
8884
9059
|
const t = look.fromPointer(dx, dy, e.pointerType, camera.pitch);
|
|
@@ -9357,10 +9532,8 @@ gem.setMenu({
|
|
|
9357
9532
|
```
|
|
9358
9533
|
|
|
9359
9534
|
**Your settings are not in it: draw your own settings button, always** —
|
|
9360
|
-
top-right
|
|
9361
|
-
|
|
9362
|
-
shows a Settings entry, so a game whose settings open only from there has
|
|
9363
|
-
none a player can reach.
|
|
9535
|
+
top-right, clear of `gem.viewport.reserved`. The Arcade's menu never opens
|
|
9536
|
+
your settings screen.
|
|
9364
9537
|
|
|
9365
9538
|
**It is screen state, not a toggle.** Each call is the whole answer and
|
|
9366
9539
|
replaces the last, so call it again when the entries change — a new
|
|
@@ -9374,7 +9547,7 @@ should not assume the game was paused by you.
|
|
|
9374
9547
|
|
|
9375
9548
|
| Parameter | Type | Description |
|
|
9376
9549
|
| --- | --- | --- |
|
|
9377
|
-
| `menu` | `GameMenu` | Your
|
|
9550
|
+
| `menu` | `GameMenu` | Your own entries. |
|
|
9378
9551
|
|
|
9379
9552
|
**Returns.** `true` when the arcade was told now; `false` before the bridge is
|
|
9380
9553
|
up (the menu is held and sent when it connects) and under an embedder
|
|
@@ -10366,6 +10539,76 @@ readonly iconUrl: string
|
|
|
10366
10539
|
The badge's thumbnail. Pass it through [platformIconUrl](#platformiconurl) before
|
|
10367
10540
|
putting it in an `<img src>`.
|
|
10368
10541
|
|
|
10542
|
+
<a id="avatar3dfamily"></a>
|
|
10543
|
+
|
|
10544
|
+
## Avatar3dFamily
|
|
10545
|
+
|
|
10546
|
+
```ts
|
|
10547
|
+
type Avatar3dFamily = "small_human" | string & object
|
|
10548
|
+
```
|
|
10549
|
+
|
|
10550
|
+
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`.
|
|
10554
|
+
|
|
10555
|
+
Open-ended (`| (string & {})`) so a family the platform adds later does not
|
|
10556
|
+
break a `switch` you compiled against this version: keep a `default` arm and
|
|
10557
|
+
skip a family you do not draw.
|
|
10558
|
+
|
|
10559
|
+
<a id="wornavatar3d"></a>
|
|
10560
|
+
|
|
10561
|
+
## WornAvatar3d
|
|
10562
|
+
|
|
10563
|
+
```ts
|
|
10564
|
+
interface WornAvatar3d
|
|
10565
|
+
```
|
|
10566
|
+
|
|
10567
|
+
One 3D avatar a player wears — at most one per [Avatar3dFamily](#avatar3dfamily).
|
|
10568
|
+
|
|
10569
|
+
<a id="wornavatar3d-family"></a>
|
|
10570
|
+
|
|
10571
|
+
## WornAvatar3d.family
|
|
10572
|
+
|
|
10573
|
+
```ts
|
|
10574
|
+
readonly family: Avatar3dFamily
|
|
10575
|
+
```
|
|
10576
|
+
|
|
10577
|
+
The rig family this avatar is built on.
|
|
10578
|
+
|
|
10579
|
+
<a id="wornavatar3d-id"></a>
|
|
10580
|
+
|
|
10581
|
+
## WornAvatar3d.id
|
|
10582
|
+
|
|
10583
|
+
```ts
|
|
10584
|
+
readonly id: string
|
|
10585
|
+
```
|
|
10586
|
+
|
|
10587
|
+
The avatar's item id — a stable key for the model, never something to
|
|
10588
|
+
show as text.
|
|
10589
|
+
|
|
10590
|
+
<a id="wornavatar3d-modelurl"></a>
|
|
10591
|
+
|
|
10592
|
+
## WornAvatar3d.modelUrl
|
|
10593
|
+
|
|
10594
|
+
```ts
|
|
10595
|
+
readonly modelUrl: string
|
|
10596
|
+
```
|
|
10597
|
+
|
|
10598
|
+
The avatar's model, a binary glTF (`.glb`) on the family's rig. Pass it
|
|
10599
|
+
through [platformIconUrl](#platformiconurl) before loading it.
|
|
10600
|
+
|
|
10601
|
+
<a id="wornavatar3d-iconurl"></a>
|
|
10602
|
+
|
|
10603
|
+
## WornAvatar3d.iconUrl
|
|
10604
|
+
|
|
10605
|
+
```ts
|
|
10606
|
+
readonly iconUrl: string
|
|
10607
|
+
```
|
|
10608
|
+
|
|
10609
|
+
A rendered portrait of the avatar, for a roster or a menu. Pass it through
|
|
10610
|
+
[platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
10611
|
+
|
|
10369
10612
|
<a id="playeridentity"></a>
|
|
10370
10613
|
|
|
10371
10614
|
## PlayerIdentity
|
|
@@ -10509,6 +10752,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
10509
10752
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
10510
10753
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
10511
10754
|
|
|
10755
|
+
<a id="playeridentity-avatars3d"></a>
|
|
10756
|
+
|
|
10757
|
+
## PlayerIdentity.avatars3d
|
|
10758
|
+
|
|
10759
|
+
```ts
|
|
10760
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
10761
|
+
```
|
|
10762
|
+
|
|
10763
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
10764
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
10765
|
+
default look.
|
|
10766
|
+
|
|
10767
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
10768
|
+
avatar of the game's first declared family that has one. A game that
|
|
10769
|
+
accepts a single family can read either; one that accepts several picks by
|
|
10770
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
10771
|
+
the flat fields then.
|
|
10772
|
+
|
|
10512
10773
|
<a id="playeridentity-badges"></a>
|
|
10513
10774
|
|
|
10514
10775
|
## PlayerIdentity.badges
|
|
@@ -10548,7 +10809,7 @@ for (const row of opponents) {
|
|
|
10548
10809
|
|
|
10549
10810
|
Reads `player_id`, `display_name`, `discriminator`, `display_tag`,
|
|
10550
10811
|
`avatar_icon_id`, `avatar_icon_url`, `avatar_3d_id`, `avatar_3d_model_url`,
|
|
10551
|
-
`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.
|
|
10812
|
+
`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.
|
|
10552
10813
|
|
|
10553
10814
|
| Parameter | Type |
|
|
10554
10815
|
| --- | --- |
|
|
@@ -11808,12 +12069,44 @@ a Buy button mostly does not write one.
|
|
|
11808
12069
|
| --- | --- |
|
|
11809
12070
|
| `req` | `PurchaseRequest` |
|
|
11810
12071
|
|
|
12072
|
+
<a id="avatar3dpurchaserequest"></a>
|
|
12073
|
+
|
|
12074
|
+
## Avatar3dPurchaseRequest
|
|
12075
|
+
|
|
12076
|
+
```ts
|
|
12077
|
+
interface Avatar3dPurchaseRequest
|
|
12078
|
+
```
|
|
12079
|
+
|
|
12080
|
+
What a game asks for when it buys one of its own 3D avatars for the player
|
|
12081
|
+
with `gem.avatars3d.purchase`.
|
|
12082
|
+
|
|
12083
|
+
<a id="avatar3dpurchaserequest-itemid"></a>
|
|
12084
|
+
|
|
12085
|
+
## Avatar3dPurchaseRequest.itemId
|
|
12086
|
+
|
|
12087
|
+
```ts
|
|
12088
|
+
itemId: string
|
|
12089
|
+
```
|
|
12090
|
+
|
|
12091
|
+
The avatar's item id — `itemId` on an `Avatar3dOffer`.
|
|
12092
|
+
|
|
12093
|
+
<a id="avatar3dpurchaserequest-currencyslug"></a>
|
|
12094
|
+
|
|
12095
|
+
## Avatar3dPurchaseRequest.currencySlug
|
|
12096
|
+
|
|
12097
|
+
```ts
|
|
12098
|
+
currencySlug: string
|
|
12099
|
+
```
|
|
12100
|
+
|
|
12101
|
+
The platform currency to pay in, `GEMS` or `ARCADE_TICKETS`. The offer
|
|
12102
|
+
must carry a price in it.
|
|
12103
|
+
|
|
11811
12104
|
<a id="purchaserefusalcode"></a>
|
|
11812
12105
|
|
|
11813
12106
|
## PurchaseRefusalCode
|
|
11814
12107
|
|
|
11815
12108
|
```ts
|
|
11816
|
-
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"
|
|
12109
|
+
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"
|
|
11817
12110
|
```
|
|
11818
12111
|
|
|
11819
12112
|
Every reason a purchase can be refused, on either purchase path.
|
|
@@ -11839,6 +12132,9 @@ Every reason a purchase can be refused, on either purchase path.
|
|
|
11839
12132
|
- `not_available` — the recipe is outside its availability window, or
|
|
11840
12133
|
inactive; nothing was charged. Hide or disable it until its window opens.
|
|
11841
12134
|
- `recipe_locked` — the recipe's prerequisites are not met.
|
|
12135
|
+
- `already_owned` — the player already owns the 3D avatar
|
|
12136
|
+
`gem.avatars3d.purchase` asked for; nothing was charged. Only that call
|
|
12137
|
+
answers it.
|
|
11842
12138
|
- `recipe_on_cooldown`, `recipe_max_uses_exceeded`, `item_max_stack_exceeded`,
|
|
11843
12139
|
`recipe_costs_unmet`, `quantity_invalid` — the recipe or item refused this
|
|
11844
12140
|
purchase, before any charge.
|
|
@@ -13125,6 +13421,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
13125
13421
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
13126
13422
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
13127
13423
|
|
|
13424
|
+
<a id="leaderboardentry-avatars3d"></a>
|
|
13425
|
+
|
|
13426
|
+
## LeaderboardEntry.avatars3d
|
|
13427
|
+
|
|
13428
|
+
```ts
|
|
13429
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
13430
|
+
```
|
|
13431
|
+
|
|
13432
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
13433
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
13434
|
+
default look.
|
|
13435
|
+
|
|
13436
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
13437
|
+
avatar of the game's first declared family that has one. A game that
|
|
13438
|
+
accepts a single family can read either; one that accepts several picks by
|
|
13439
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
13440
|
+
the flat fields then.
|
|
13441
|
+
|
|
13128
13442
|
<a id="leaderboardentry-badges"></a>
|
|
13129
13443
|
|
|
13130
13444
|
## LeaderboardEntry.badges
|
|
@@ -14618,6 +14932,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
14618
14932
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
14619
14933
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
14620
14934
|
|
|
14935
|
+
<a id="playerprofile-avatars3d"></a>
|
|
14936
|
+
|
|
14937
|
+
## PlayerProfile.avatars3d
|
|
14938
|
+
|
|
14939
|
+
```ts
|
|
14940
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
14941
|
+
```
|
|
14942
|
+
|
|
14943
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
14944
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
14945
|
+
default look.
|
|
14946
|
+
|
|
14947
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
14948
|
+
avatar of the game's first declared family that has one. A game that
|
|
14949
|
+
accepts a single family can read either; one that accepts several picks by
|
|
14950
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
14951
|
+
the flat fields then.
|
|
14952
|
+
|
|
14621
14953
|
<a id="playerprofile-badges"></a>
|
|
14622
14954
|
|
|
14623
14955
|
## PlayerProfile.badges
|
|
@@ -15307,6 +15639,36 @@ room. A double fire — the push and the reconcile landing together, or the
|
|
|
15307
15639
|
event arriving just as the player presses your own button — costs one
|
|
15308
15640
|
redundant request and never a second seat.
|
|
15309
15641
|
|
|
15642
|
+
<a id="roomeventmap-partyqueued"></a>
|
|
15643
|
+
|
|
15644
|
+
## RoomEventMap.partyQueued
|
|
15645
|
+
|
|
15646
|
+
```ts
|
|
15647
|
+
partyQueued: [PartyTicket]
|
|
15648
|
+
```
|
|
15649
|
+
|
|
15650
|
+
This player's party is queued for a match: its leader called
|
|
15651
|
+
`queueForMatch`, and this player is on that ticket.
|
|
15652
|
+
|
|
15653
|
+
The ticket is a view — show a searching screen from it, and await its
|
|
15654
|
+
`outcome` to take the screen down. It has no `cancel()`: the ticket is
|
|
15655
|
+
the leader's.
|
|
15656
|
+
|
|
15657
|
+
```js
|
|
15658
|
+
gem.rooms.on('partyQueued', async (ticket) => {
|
|
15659
|
+
showSearching({ canCancel: false });
|
|
15660
|
+
const outcome = await ticket.outcome;
|
|
15661
|
+
if (outcome.status !== 'matched') backToMenu(outcome.status);
|
|
15662
|
+
});
|
|
15663
|
+
```
|
|
15664
|
+
|
|
15665
|
+
When the outcome is `matched` the room arrives as `seated`, as it does
|
|
15666
|
+
for any seat this player's party was given.
|
|
15667
|
+
|
|
15668
|
+
NOT RAISED FOR THE PLAYER WHO QUEUED — they hold the ticket itself — and
|
|
15669
|
+
not raised at all under an arcade page that does not relay ticket
|
|
15670
|
+
events. See [PartyTicket](#partyticket).
|
|
15671
|
+
|
|
15310
15672
|
<a id="roomeventmap-listed"></a>
|
|
15311
15673
|
|
|
15312
15674
|
## RoomEventMap.listed
|
|
@@ -16125,6 +16487,25 @@ Set from the moment [RoomManager.queueForMatch](#roommanager-queueformatch) answ
|
|
|
16125
16487
|
ticket ends — so it is `null` again by the time a matched ticket's room is
|
|
16126
16488
|
[RoomManager.currentRoom](#roommanager-currentroom).
|
|
16127
16489
|
|
|
16490
|
+
<a id="roommanager-partyticket"></a>
|
|
16491
|
+
|
|
16492
|
+
## RoomManager.partyTicket
|
|
16493
|
+
|
|
16494
|
+
```ts
|
|
16495
|
+
readonly partyTicket: PartyTicket | null
|
|
16496
|
+
```
|
|
16497
|
+
|
|
16498
|
+
The matchmaking ticket this player's PARTY is waiting on, or `null` — a
|
|
16499
|
+
ticket this game did not create, which it can show and cannot cancel.
|
|
16500
|
+
|
|
16501
|
+
Set when the arcade page reports that the party's leader queued, and
|
|
16502
|
+
`null` again once that ticket ends. Never set beside
|
|
16503
|
+
[RoomManager.currentTicket](#roommanager-currentticket): the player who queued holds that one.
|
|
16504
|
+
The `partyQueued` event is raised when this is set.
|
|
16505
|
+
|
|
16506
|
+
Always `null` under a page that does not relay ticket events. See
|
|
16507
|
+
[PartyTicket](#partyticket).
|
|
16508
|
+
|
|
16128
16509
|
<a id="roommanager-currentmatch"></a>
|
|
16129
16510
|
|
|
16130
16511
|
## RoomManager.currentMatch
|
|
@@ -16549,6 +16930,143 @@ Safe to call more than once, and after the ticket has ended.
|
|
|
16549
16930
|
|
|
16550
16931
|
**Returns.** The same promise as [MatchTicket.outcome](#matchticket-outcome).
|
|
16551
16932
|
|
|
16933
|
+
<a id="partyticketstatus"></a>
|
|
16934
|
+
|
|
16935
|
+
## PartyTicketStatus
|
|
16936
|
+
|
|
16937
|
+
```ts
|
|
16938
|
+
type PartyTicketStatus = "queued" | "matched" | "expired" | "cancelled" | "failed" | "lost"
|
|
16939
|
+
```
|
|
16940
|
+
|
|
16941
|
+
Where a party's ticket is, as far as this player's game has been told:
|
|
16942
|
+
`queued` while it waits, and anything else for good.
|
|
16943
|
+
|
|
16944
|
+
- `matched` — the party is seated and the match is starting. The room arrives
|
|
16945
|
+
as a `seated` event.
|
|
16946
|
+
- `expired` — it waited too long, or its owner's game stopped keeping it alive.
|
|
16947
|
+
- `cancelled` — the leader backed out, or the party changed.
|
|
16948
|
+
- `failed` — the platform formed a match and could not start it, repeatedly.
|
|
16949
|
+
- `lost` — nothing more was heard about it by the time it must have ended.
|
|
16950
|
+
|
|
16951
|
+
<a id="partyticketoutcome"></a>
|
|
16952
|
+
|
|
16953
|
+
## PartyTicketOutcome
|
|
16954
|
+
|
|
16955
|
+
```ts
|
|
16956
|
+
type PartyTicketOutcome = { status: "matched" } | { status: "expired"; reason: string } | { status: "cancelled"; reason: string } | { status: "failed"; reason: string } | { status: "lost" }
|
|
16957
|
+
```
|
|
16958
|
+
|
|
16959
|
+
How a party's ticket ended. Branch on `status`.
|
|
16960
|
+
|
|
16961
|
+
`matched` CARRIES NO ROOM. The room is reported the way a party's seat always
|
|
16962
|
+
is — the `seated` event — and that is where a game joins it. The SDK looks
|
|
16963
|
+
for the seat the moment it hears `matched`.
|
|
16964
|
+
|
|
16965
|
+
`reason` says why, where the platform gave one: `timed_out` or
|
|
16966
|
+
`heartbeat_lapsed` for `expired`, `requested` or `party_changed` for
|
|
16967
|
+
`cancelled`, `handoff_failed` for `failed`. Treat a value you do not
|
|
16968
|
+
recognise as the status alone.
|
|
16969
|
+
|
|
16970
|
+
`lost` is the SDK's own ending, not the platform's: the ticket's lifetime
|
|
16971
|
+
ran out and no ending was heard. Whatever happened, the party is not
|
|
16972
|
+
waiting any more.
|
|
16973
|
+
|
|
16974
|
+
<a id="partyticket"></a>
|
|
16975
|
+
|
|
16976
|
+
## PartyTicket
|
|
16977
|
+
|
|
16978
|
+
```ts
|
|
16979
|
+
interface PartyTicket
|
|
16980
|
+
```
|
|
16981
|
+
|
|
16982
|
+
The matchmaking ticket this player's party is waiting on — a ticket this
|
|
16983
|
+
game did not create. What `gem.rooms.partyTicket` holds, and what the
|
|
16984
|
+
`partyQueued` event hands you.
|
|
16985
|
+
|
|
16986
|
+
READ-ONLY, ON PURPOSE. There is no `cancel()`: a party is one ticket and it
|
|
16987
|
+
is its leader's to cancel. A player who wants out leaves the party, which
|
|
16988
|
+
ends the ticket for everyone.
|
|
16989
|
+
|
|
16990
|
+
```js
|
|
16991
|
+
gem.rooms.on('partyQueued', async (ticket) => {
|
|
16992
|
+
showSearching({ canCancel: false });
|
|
16993
|
+
const outcome = await ticket.outcome;
|
|
16994
|
+
if (outcome.status !== 'matched') backToMenu(outcome.status);
|
|
16995
|
+
// `matched`: your `seated` handler has the room.
|
|
16996
|
+
});
|
|
16997
|
+
```
|
|
16998
|
+
|
|
16999
|
+
ONLY WHERE THE ARCADE PAGE RELAYS IT. Under a page that does not, there is
|
|
17000
|
+
no party ticket and no `partyQueued`, and a member is carried into the match
|
|
17001
|
+
by `seated` with no lead-up. Build the searching screen as an extra, never
|
|
17002
|
+
as a step the match depends on.
|
|
17003
|
+
|
|
17004
|
+
**Guides.** [rooms-and-matches](../rooms-and-matches.md)
|
|
17005
|
+
|
|
17006
|
+
<a id="partyticket-id"></a>
|
|
17007
|
+
|
|
17008
|
+
## PartyTicket.id
|
|
17009
|
+
|
|
17010
|
+
```ts
|
|
17011
|
+
readonly id: string
|
|
17012
|
+
```
|
|
17013
|
+
|
|
17014
|
+
The ticket's id. For logs and bug reports; nothing you call takes it.
|
|
17015
|
+
|
|
17016
|
+
<a id="partyticket-status"></a>
|
|
17017
|
+
|
|
17018
|
+
## PartyTicket.status
|
|
17019
|
+
|
|
17020
|
+
```ts
|
|
17021
|
+
readonly status: PartyTicketStatus
|
|
17022
|
+
```
|
|
17023
|
+
|
|
17024
|
+
Where the ticket is, as far as this game has been told. Changes once, from
|
|
17025
|
+
`queued` to how it ended.
|
|
17026
|
+
|
|
17027
|
+
<a id="partyticket-partysize"></a>
|
|
17028
|
+
|
|
17029
|
+
## PartyTicket.partySize
|
|
17030
|
+
|
|
17031
|
+
```ts
|
|
17032
|
+
readonly partySize: number
|
|
17033
|
+
```
|
|
17034
|
+
|
|
17035
|
+
How many players the ticket seats: the size of the party. 0 when the page
|
|
17036
|
+
did not say.
|
|
17037
|
+
|
|
17038
|
+
<a id="partyticket-queuedat"></a>
|
|
17039
|
+
|
|
17040
|
+
## PartyTicket.queuedAt
|
|
17041
|
+
|
|
17042
|
+
```ts
|
|
17043
|
+
readonly queuedAt: number
|
|
17044
|
+
```
|
|
17045
|
+
|
|
17046
|
+
When the ticket joined the queue, in Unix seconds. 0 when the page did not
|
|
17047
|
+
say.
|
|
17048
|
+
|
|
17049
|
+
<a id="partyticket-expiresat"></a>
|
|
17050
|
+
|
|
17051
|
+
## PartyTicket.expiresAt
|
|
17052
|
+
|
|
17053
|
+
```ts
|
|
17054
|
+
readonly expiresAt: number
|
|
17055
|
+
```
|
|
17056
|
+
|
|
17057
|
+
When the ticket gives up if it is still waiting, in Unix seconds. Good for
|
|
17058
|
+
a countdown. 0 when the page did not say.
|
|
17059
|
+
|
|
17060
|
+
<a id="partyticket-outcome"></a>
|
|
17061
|
+
|
|
17062
|
+
## PartyTicket.outcome
|
|
17063
|
+
|
|
17064
|
+
```ts
|
|
17065
|
+
readonly outcome: Promise<PartyTicketOutcome>
|
|
17066
|
+
```
|
|
17067
|
+
|
|
17068
|
+
How the ticket ends. Settles exactly once and never rejects.
|
|
17069
|
+
|
|
16552
17070
|
<a id="roomstatus"></a>
|
|
16553
17071
|
|
|
16554
17072
|
## RoomStatus
|
|
@@ -17018,6 +17536,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
17018
17536
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
17019
17537
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
17020
17538
|
|
|
17539
|
+
<a id="roommember-avatars3d"></a>
|
|
17540
|
+
|
|
17541
|
+
## RoomMember.avatars3d
|
|
17542
|
+
|
|
17543
|
+
```ts
|
|
17544
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
17545
|
+
```
|
|
17546
|
+
|
|
17547
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
17548
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
17549
|
+
default look.
|
|
17550
|
+
|
|
17551
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
17552
|
+
avatar of the game's first declared family that has one. A game that
|
|
17553
|
+
accepts a single family can read either; one that accepts several picks by
|
|
17554
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
17555
|
+
the flat fields then.
|
|
17556
|
+
|
|
17021
17557
|
<a id="roommember-badges"></a>
|
|
17022
17558
|
|
|
17023
17559
|
## RoomMember.badges
|
|
@@ -17848,6 +18384,24 @@ loading the model is too much. Not the 2D portrait
|
|
|
17848
18384
|
([PlayerIdentity.avatarIconUrl](#playeridentity-avatariconurl)), which is a separate choice. Pass it
|
|
17849
18385
|
through [platformIconUrl](#platformiconurl) before putting it in an `<img src>`.
|
|
17850
18386
|
|
|
18387
|
+
<a id="showcasefriendentry-avatars3d"></a>
|
|
18388
|
+
|
|
18389
|
+
## ShowcaseFriendEntry.avatars3d
|
|
18390
|
+
|
|
18391
|
+
```ts
|
|
18392
|
+
readonly avatars3d?: readonly WornAvatar3d[]
|
|
18393
|
+
```
|
|
18394
|
+
|
|
18395
|
+
Every 3D avatar the player wears, one per rig family, in the order the game
|
|
18396
|
+
declared its families. Absent or empty means none is worn — draw your
|
|
18397
|
+
default look.
|
|
18398
|
+
|
|
18399
|
+
[PlayerIdentity.avatar3dId](#playeridentity-avatar3did) and its two URLs are one of these: the
|
|
18400
|
+
avatar of the game's first declared family that has one. A game that
|
|
18401
|
+
accepts a single family can read either; one that accepts several picks by
|
|
18402
|
+
`family` here. Absent too where the platform does not send it yet — read
|
|
18403
|
+
the flat fields then.
|
|
18404
|
+
|
|
17851
18405
|
<a id="showcasefriendentry-badges"></a>
|
|
17852
18406
|
|
|
17853
18407
|
## ShowcaseFriendEntry.badges
|