@indiegems/gem-web-sdk 10.1.1 → 10.3.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.
@@ -2,7 +2,7 @@
2
2
  "schema_version": 2,
3
3
  "source": {
4
4
  "repo": "IndieGems/gem-web-sdk",
5
- "version": "10.1.1"
5
+ "version": "10.3.0"
6
6
  },
7
7
  "entries": [
8
8
  {
@@ -65,6 +65,10 @@
65
65
  "key": "vibration",
66
66
  "title": "Vibrating the device"
67
67
  },
68
+ {
69
+ "key": "controls",
70
+ "title": "Camera and look controls"
71
+ },
68
72
  {
69
73
  "key": "config",
70
74
  "title": "Your published config"
@@ -5385,6 +5389,572 @@
5385
5389
  "defaultValue": null,
5386
5390
  "guides": []
5387
5391
  },
5392
+ {
5393
+ "id": "GemLookSpeed",
5394
+ "name": "GemLookSpeed",
5395
+ "anchor": "gemlookspeed",
5396
+ "group": "controls",
5397
+ "signature": "interface GemLookSpeed",
5398
+ "documented": true,
5399
+ "summary": "A look speed per axis, in radians: per CSS px for a pointer, per second at\nfull tilt for a stick.",
5400
+ "deprecated": null,
5401
+ "params": [],
5402
+ "returns": null,
5403
+ "throws": null,
5404
+ "example": null,
5405
+ "defaultValue": null,
5406
+ "guides": []
5407
+ },
5408
+ {
5409
+ "id": "GemLookSpeed.yaw",
5410
+ "name": "yaw",
5411
+ "anchor": "gemlookspeed-yaw",
5412
+ "group": "controls",
5413
+ "signature": "readonly yaw: number",
5414
+ "documented": true,
5415
+ "summary": "Across: radians of yaw.",
5416
+ "deprecated": null,
5417
+ "params": [],
5418
+ "returns": null,
5419
+ "throws": null,
5420
+ "example": null,
5421
+ "defaultValue": null,
5422
+ "guides": []
5423
+ },
5424
+ {
5425
+ "id": "GemLookSpeed.pitch",
5426
+ "name": "pitch",
5427
+ "anchor": "gemlookspeed-pitch",
5428
+ "group": "controls",
5429
+ "signature": "readonly pitch: number",
5430
+ "documented": true,
5431
+ "summary": "Up/down: radians of pitch.",
5432
+ "deprecated": null,
5433
+ "params": [],
5434
+ "returns": null,
5435
+ "throws": null,
5436
+ "example": null,
5437
+ "defaultValue": null,
5438
+ "guides": []
5439
+ },
5440
+ {
5441
+ "id": "GemLookBase",
5442
+ "name": "GemLookBase",
5443
+ "anchor": "gemlookbase",
5444
+ "group": "controls",
5445
+ "signature": "interface GemLookBase",
5446
+ "documented": true,
5447
+ "summary": "The shape of `gem.controls.LOOK_BASE`: Roblox's base look speeds and the\nstick and touch shaping constants `gem.controls.look()` applies.",
5448
+ "deprecated": null,
5449
+ "params": [],
5450
+ "returns": null,
5451
+ "throws": null,
5452
+ "example": null,
5453
+ "defaultValue": null,
5454
+ "guides": []
5455
+ },
5456
+ {
5457
+ "id": "GemLookBase.touch",
5458
+ "name": "touch",
5459
+ "anchor": "gemlookbase-touch",
5460
+ "group": "controls",
5461
+ "signature": "readonly touch: GemLookSpeed",
5462
+ "documented": true,
5463
+ "summary": "Radians per CSS px, for touch and pen: 1° across, 0.66° up/down.",
5464
+ "deprecated": null,
5465
+ "params": [],
5466
+ "returns": null,
5467
+ "throws": null,
5468
+ "example": null,
5469
+ "defaultValue": null,
5470
+ "guides": []
5471
+ },
5472
+ {
5473
+ "id": "GemLookBase.mouse",
5474
+ "name": "mouse",
5475
+ "anchor": "gemlookbase-mouse",
5476
+ "group": "controls",
5477
+ "signature": "readonly mouse: GemLookSpeed",
5478
+ "documented": true,
5479
+ "summary": "Radians per CSS px, for a mouse: 0.5° across, 0.385° up/down.",
5480
+ "deprecated": null,
5481
+ "params": [],
5482
+ "returns": null,
5483
+ "throws": null,
5484
+ "example": null,
5485
+ "defaultValue": null,
5486
+ "guides": []
5487
+ },
5488
+ {
5489
+ "id": "GemLookBase.stick",
5490
+ "name": "stick",
5491
+ "anchor": "gemlookbase-stick",
5492
+ "group": "controls",
5493
+ "signature": "readonly stick: GemLookSpeed",
5494
+ "documented": true,
5495
+ "summary": "Radians per second at full tilt, for a gamepad stick: 240° across, 184.8° up/down.",
5496
+ "deprecated": null,
5497
+ "params": [],
5498
+ "returns": null,
5499
+ "throws": null,
5500
+ "example": null,
5501
+ "defaultValue": null,
5502
+ "guides": []
5503
+ },
5504
+ {
5505
+ "id": "GemLookBase.stickDeadzone",
5506
+ "name": "stickDeadzone",
5507
+ "anchor": "gemlookbase-stickdeadzone",
5508
+ "group": "controls",
5509
+ "signature": "readonly stickDeadzone: number",
5510
+ "documented": true,
5511
+ "summary": "A stick axis below this magnitude turns nothing: 0.1.",
5512
+ "deprecated": null,
5513
+ "params": [],
5514
+ "returns": null,
5515
+ "throws": null,
5516
+ "example": null,
5517
+ "defaultValue": null,
5518
+ "guides": []
5519
+ },
5520
+ {
5521
+ "id": "GemLookBase.stickCurve",
5522
+ "name": "stickCurve",
5523
+ "anchor": "gemlookbase-stickcurve",
5524
+ "group": "controls",
5525
+ "signature": "readonly stickCurve: number",
5526
+ "documented": true,
5527
+ "summary": "The stick curve's curvature `k` in `(e^(k·d) − 1) / (e^k − 1)`: 2.",
5528
+ "deprecated": null,
5529
+ "params": [],
5530
+ "returns": null,
5531
+ "throws": null,
5532
+ "example": null,
5533
+ "defaultValue": null,
5534
+ "guides": []
5535
+ },
5536
+ {
5537
+ "id": "GemLookBase.touchPitchMin",
5538
+ "name": "touchPitchMin",
5539
+ "anchor": "gemlookbase-touchpitchmin",
5540
+ "group": "controls",
5541
+ "signature": "readonly touchPitchMin: number",
5542
+ "documented": true,
5543
+ "summary": "The least fraction of the pitch speed a touch drag keeps straight up or down: 0.25.",
5544
+ "deprecated": null,
5545
+ "params": [],
5546
+ "returns": null,
5547
+ "throws": null,
5548
+ "example": null,
5549
+ "defaultValue": null,
5550
+ "guides": []
5551
+ },
5552
+ {
5553
+ "id": "GemLookOptions",
5554
+ "name": "GemLookOptions",
5555
+ "anchor": "gemlookoptions",
5556
+ "group": "controls",
5557
+ "signature": "interface GemLookOptions",
5558
+ "documented": true,
5559
+ "summary": "The game's own overrides for `gem.controls.look()` — what the player chose in\nYOUR settings screen. Each one wins over the Arcade's value; leave one out to\nfollow the Arcade.",
5560
+ "deprecated": null,
5561
+ "params": [],
5562
+ "returns": null,
5563
+ "throws": null,
5564
+ "example": null,
5565
+ "defaultValue": null,
5566
+ "guides": []
5567
+ },
5568
+ {
5569
+ "id": "GemLookOptions.sensitivity",
5570
+ "name": "sensitivity",
5571
+ "anchor": "gemlookoptions-sensitivity",
5572
+ "group": "controls",
5573
+ "signature": "readonly sensitivity?: number",
5574
+ "documented": true,
5575
+ "summary": "The player's own look speed for touch, mouse and pen, as a multiplier\n(`1` = the base speed). Wins over `gem.prefs.recommended.lookSensitivity`.",
5576
+ "deprecated": null,
5577
+ "params": [],
5578
+ "returns": null,
5579
+ "throws": null,
5580
+ "example": null,
5581
+ "defaultValue": null,
5582
+ "guides": []
5583
+ },
5584
+ {
5585
+ "id": "GemLookOptions.gamepadSensitivity",
5586
+ "name": "gamepadSensitivity",
5587
+ "anchor": "gemlookoptions-gamepadsensitivity",
5588
+ "group": "controls",
5589
+ "signature": "readonly gamepadSensitivity?: number",
5590
+ "documented": true,
5591
+ "summary": "The player's own look speed for a gamepad stick, as a multiplier. Wins\nover `gem.prefs.recommended.gamepadLookSensitivity`.",
5592
+ "deprecated": null,
5593
+ "params": [],
5594
+ "returns": null,
5595
+ "throws": null,
5596
+ "example": null,
5597
+ "defaultValue": null,
5598
+ "guides": []
5599
+ },
5600
+ {
5601
+ "id": "GemLookOptions.invertY",
5602
+ "name": "invertY",
5603
+ "anchor": "gemlookoptions-inverty",
5604
+ "group": "controls",
5605
+ "signature": "readonly invertY?: boolean",
5606
+ "documented": true,
5607
+ "summary": "The player's own inverted up/down look. Wins over\n`gem.prefs.recommended.invertLookY`.",
5608
+ "deprecated": null,
5609
+ "params": [],
5610
+ "returns": null,
5611
+ "throws": null,
5612
+ "example": null,
5613
+ "defaultValue": null,
5614
+ "guides": []
5615
+ },
5616
+ {
5617
+ "id": "GemLookDelta",
5618
+ "name": "GemLookDelta",
5619
+ "anchor": "gemlookdelta",
5620
+ "group": "controls",
5621
+ "signature": "interface GemLookDelta",
5622
+ "documented": true,
5623
+ "summary": "A turn to apply to your camera, in radians to ADD: `yaw` positive turns\nright (clockwise seen from above), `pitch` positive looks up.",
5624
+ "deprecated": null,
5625
+ "params": [],
5626
+ "returns": null,
5627
+ "throws": null,
5628
+ "example": null,
5629
+ "defaultValue": null,
5630
+ "guides": []
5631
+ },
5632
+ {
5633
+ "id": "GemLookDelta.yaw",
5634
+ "name": "yaw",
5635
+ "anchor": "gemlookdelta-yaw",
5636
+ "group": "controls",
5637
+ "signature": "readonly yaw: number",
5638
+ "documented": true,
5639
+ "summary": "Radians to add to the camera's yaw; positive turns right.",
5640
+ "deprecated": null,
5641
+ "params": [],
5642
+ "returns": null,
5643
+ "throws": null,
5644
+ "example": null,
5645
+ "defaultValue": null,
5646
+ "guides": []
5647
+ },
5648
+ {
5649
+ "id": "GemLookDelta.pitch",
5650
+ "name": "pitch",
5651
+ "anchor": "gemlookdelta-pitch",
5652
+ "group": "controls",
5653
+ "signature": "readonly pitch: number",
5654
+ "documented": true,
5655
+ "summary": "Radians to add to the camera's pitch; positive looks up.",
5656
+ "deprecated": null,
5657
+ "params": [],
5658
+ "returns": null,
5659
+ "throws": null,
5660
+ "example": null,
5661
+ "defaultValue": null,
5662
+ "guides": []
5663
+ },
5664
+ {
5665
+ "id": "GemLook",
5666
+ "name": "GemLook",
5667
+ "anchor": "gemlook",
5668
+ "group": "controls",
5669
+ "signature": "interface GemLook",
5670
+ "documented": true,
5671
+ "summary": "The look helper `gem.controls.look()` returns. Pure math: it listens to\nnothing and moves no camera — feed it the deltas your input code already\nhas and add what it returns to your camera's yaw and pitch, then clamp the\npitch as you always do.",
5672
+ "deprecated": null,
5673
+ "params": [],
5674
+ "returns": null,
5675
+ "throws": null,
5676
+ "example": null,
5677
+ "defaultValue": null,
5678
+ "guides": []
5679
+ },
5680
+ {
5681
+ "id": "GemLook.fromPointer",
5682
+ "name": "fromPointer",
5683
+ "anchor": "gemlook-frompointer",
5684
+ "group": "controls",
5685
+ "signature": "fromPointer(dx: number, dy: number, pointerType: string, pitch?: number): GemLookDelta",
5686
+ "documented": true,
5687
+ "summary": "A pointer move — a touch drag, a mouse move (under pointer lock,\n`movementX` / `movementY`) or a pen — turned into a look turn.",
5688
+ "deprecated": null,
5689
+ "params": [
5690
+ {
5691
+ "name": "dx",
5692
+ "type": "number",
5693
+ "optional": false,
5694
+ "summary": "The move across, in CSS px, right positive."
5695
+ },
5696
+ {
5697
+ "name": "dy",
5698
+ "type": "number",
5699
+ "optional": false,
5700
+ "summary": "The move down the screen, in CSS px, DOWN positive (as\n `PointerEvent` reports it). Dragging up looks up."
5701
+ },
5702
+ {
5703
+ "name": "pointerType",
5704
+ "type": "string",
5705
+ "optional": false,
5706
+ "summary": "The event's `pointerType`: `'touch'` and `'pen'` take\n the touch speeds, anything else the mouse speeds."
5707
+ },
5708
+ {
5709
+ "name": "pitch",
5710
+ "type": "number",
5711
+ "optional": true,
5712
+ "summary": "The camera's current pitch in radians (0 = the horizon,\n positive = looking up), for the touch slowdown near straight up or\n down. Leave it out to skip the slowdown."
5713
+ }
5714
+ ],
5715
+ "returns": null,
5716
+ "throws": null,
5717
+ "example": null,
5718
+ "defaultValue": null,
5719
+ "guides": []
5720
+ },
5721
+ {
5722
+ "id": "GemLook.fromStick",
5723
+ "name": "fromStick",
5724
+ "anchor": "gemlook-fromstick",
5725
+ "group": "controls",
5726
+ "signature": "fromStick(x: number, y: number, dt: number): GemLookDelta",
5727
+ "documented": true,
5728
+ "summary": "A right stick turned into a look turn over one frame.",
5729
+ "deprecated": null,
5730
+ "params": [
5731
+ {
5732
+ "name": "x",
5733
+ "type": "number",
5734
+ "optional": false,
5735
+ "summary": "The stick's horizontal axis as the Gamepad API reports it,\n −1..1, right positive."
5736
+ },
5737
+ {
5738
+ "name": "y",
5739
+ "type": "number",
5740
+ "optional": false,
5741
+ "summary": "The stick's vertical axis as the Gamepad API reports it, −1..1,\n DOWN positive. Pushing up looks up."
5742
+ },
5743
+ {
5744
+ "name": "dt",
5745
+ "type": "number",
5746
+ "optional": false,
5747
+ "summary": "The frame's duration in seconds."
5748
+ }
5749
+ ],
5750
+ "returns": null,
5751
+ "throws": null,
5752
+ "example": null,
5753
+ "defaultValue": null,
5754
+ "guides": []
5755
+ },
5756
+ {
5757
+ "id": "GemLook.set",
5758
+ "name": "set",
5759
+ "anchor": "gemlook-set",
5760
+ "group": "controls",
5761
+ "signature": "set(options: GemLookOptions): void",
5762
+ "documented": true,
5763
+ "summary": "Change your game's overrides — call it when the player changes a setting\nin your settings screen. Each key you pass replaces that override; a key\npassed as `undefined` removes it, so that input follows the Arcade again;\na key you leave out is unchanged.",
5764
+ "deprecated": null,
5765
+ "params": [
5766
+ {
5767
+ "name": "options",
5768
+ "type": "GemLookOptions",
5769
+ "optional": false,
5770
+ "summary": null
5771
+ }
5772
+ ],
5773
+ "returns": null,
5774
+ "throws": "TypeError when a sensitivity is not a finite number above 0, or\n `invertY` is not a boolean.",
5775
+ "example": null,
5776
+ "defaultValue": null,
5777
+ "guides": []
5778
+ },
5779
+ {
5780
+ "id": "ControlsApi",
5781
+ "name": "ControlsApi",
5782
+ "anchor": "controlsapi",
5783
+ "group": "controls",
5784
+ "signature": "interface ControlsApi",
5785
+ "documented": true,
5786
+ "summary": "`gem.controls` — the player's camera and controls settings: tell the Arcade\nwhich ones your game leaves to the player, and turn look input into a camera\nturn at the player's sensitivity.",
5787
+ "deprecated": null,
5788
+ "params": [],
5789
+ "returns": null,
5790
+ "throws": null,
5791
+ "example": null,
5792
+ "defaultValue": null,
5793
+ "guides": [
5794
+ {
5795
+ "slug": "what-a-game-must-do",
5796
+ "anchor": null
5797
+ }
5798
+ ]
5799
+ },
5800
+ {
5801
+ "id": "ControlsApi.declare",
5802
+ "name": "declare",
5803
+ "anchor": "controlsapi-declare",
5804
+ "group": "controls",
5805
+ "signature": "declare(uses: GemControlsDeclaration): boolean",
5806
+ "documented": true,
5807
+ "summary": "Tell the Arcade which of the player's camera and controls settings your\ngame uses, and for each one who decides it: `'player'` — you apply the\nArcade's value from `gem.prefs.recommended` (or the player's own choice\nin your settings, which wins) — or `'game'` — you decide it yourself, and\nthe Arcade's Settings shows that row as \"Set by this game\". Leave out a\nsetting your game does not use.\n\n```js\ngem.controls.declare({\n lookSensitivity: 'player',\n gamepadLookSensitivity: 'player',\n invertLookY: 'player',\n touchMovement: 'game', // this game always uses a fixed stick\n});\n```\n\n**It is screen state, not a toggle.** Each call is the whole answer and\nreplaces the last. The SDK holds it and sends it again after every\nreconnect, so call it once at boot, and again only when the answer\nchanges. Any other key or value is dropped.",
5808
+ "deprecated": null,
5809
+ "params": [
5810
+ {
5811
+ "name": "uses",
5812
+ "type": "GemControlsDeclaration",
5813
+ "optional": false,
5814
+ "summary": null
5815
+ }
5816
+ ],
5817
+ "returns": "`true` when the Arcade was told now; `false` before the bridge is\n up (the declaration is held and sent when it connects), outside the\n Arcade, and under an embedder that does not show these settings. Never\n throws.",
5818
+ "throws": null,
5819
+ "example": null,
5820
+ "defaultValue": null,
5821
+ "guides": []
5822
+ },
5823
+ {
5824
+ "id": "ControlsApi.look",
5825
+ "name": "look",
5826
+ "anchor": "controlsapi-look",
5827
+ "group": "controls",
5828
+ "signature": "look(options?: GemLookOptions): GemLook",
5829
+ "documented": true,
5830
+ "summary": "Make a look helper: Roblox's camera-input math at the player's look\nsensitivity and invert. Make one and keep it.\n\n```js\nconst look = gem.controls.look();\n// A mouse under pointer lock; for touch, pass the change in clientX/clientY.\ncanvas.addEventListener('pointermove', (e) => {\n if (document.pointerLockElement !== canvas) return;\n const t = look.fromPointer(e.movementX, e.movementY, e.pointerType, camera.pitch);\n camera.yaw += t.yaw;\n camera.pitch = clamp(camera.pitch + t.pitch, -1.4, 1.4);\n});\n```\n\nThe sensitivity and invert are read **live** on every call: the Arcade's\n`gem.prefs.recommended` values, unless `options` (or a later\n[GemLook.set](api-reference-game.md#gemlook-set)) gives your game's own, which win.",
5831
+ "deprecated": null,
5832
+ "params": [
5833
+ {
5834
+ "name": "options",
5835
+ "type": "GemLookOptions",
5836
+ "optional": true,
5837
+ "summary": null
5838
+ }
5839
+ ],
5840
+ "returns": null,
5841
+ "throws": "TypeError when an option is malformed, as [GemLook.set](api-reference-game.md#gemlook-set).",
5842
+ "example": null,
5843
+ "defaultValue": null,
5844
+ "guides": []
5845
+ },
5846
+ {
5847
+ "id": "ControlsApi.LOOK_BASE",
5848
+ "name": "LOOK_BASE",
5849
+ "anchor": "controlsapi-look_base",
5850
+ "group": "controls",
5851
+ "signature": "readonly LOOK_BASE: GemLookBase",
5852
+ "documented": true,
5853
+ "summary": "The base speeds `look` applies at 1×, in radians. Frozen.",
5854
+ "deprecated": null,
5855
+ "params": [],
5856
+ "returns": null,
5857
+ "throws": null,
5858
+ "example": null,
5859
+ "defaultValue": null,
5860
+ "guides": []
5861
+ },
5862
+ {
5863
+ "id": "GemControlChoice",
5864
+ "name": "GemControlChoice",
5865
+ "anchor": "gemcontrolchoice",
5866
+ "group": "controls",
5867
+ "signature": "type GemControlChoice = \"player\" | \"game\"",
5868
+ "documented": true,
5869
+ "summary": "Who decides one camera or controls setting: `'player'` — your game applies\nthe Arcade's value, or the player's own in-game choice, which wins — or\n`'game'` — your game decides it itself, and the Arcade's Settings shows the\nrow as \"Set by this game\".",
5870
+ "deprecated": null,
5871
+ "params": [],
5872
+ "returns": null,
5873
+ "throws": null,
5874
+ "example": null,
5875
+ "defaultValue": null,
5876
+ "guides": []
5877
+ },
5878
+ {
5879
+ "id": "GemControlsDeclaration",
5880
+ "name": "GemControlsDeclaration",
5881
+ "anchor": "gemcontrolsdeclaration",
5882
+ "group": "controls",
5883
+ "signature": "interface GemControlsDeclaration",
5884
+ "documented": true,
5885
+ "summary": "What `gem.controls.declare` takes: for each of the player's camera and\ncontrols settings your game uses, who decides it. Leave a setting out when\nyour game does not use it at all — the Arcade then says \"This game doesn't\nuse this\" beside that row.",
5886
+ "deprecated": null,
5887
+ "params": [],
5888
+ "returns": null,
5889
+ "throws": null,
5890
+ "example": null,
5891
+ "defaultValue": null,
5892
+ "guides": []
5893
+ },
5894
+ {
5895
+ "id": "GemControlsDeclaration.lookSensitivity",
5896
+ "name": "lookSensitivity",
5897
+ "anchor": "gemcontrolsdeclaration-looksensitivity",
5898
+ "group": "controls",
5899
+ "signature": "readonly lookSensitivity?: GemControlChoice",
5900
+ "documented": true,
5901
+ "summary": "Look speed for touch, mouse and pen — `gem.prefs.recommended.lookSensitivity`.",
5902
+ "deprecated": null,
5903
+ "params": [],
5904
+ "returns": null,
5905
+ "throws": null,
5906
+ "example": null,
5907
+ "defaultValue": null,
5908
+ "guides": []
5909
+ },
5910
+ {
5911
+ "id": "GemControlsDeclaration.gamepadLookSensitivity",
5912
+ "name": "gamepadLookSensitivity",
5913
+ "anchor": "gemcontrolsdeclaration-gamepadlooksensitivity",
5914
+ "group": "controls",
5915
+ "signature": "readonly gamepadLookSensitivity?: GemControlChoice",
5916
+ "documented": true,
5917
+ "summary": "Look speed for a gamepad stick — `gem.prefs.recommended.gamepadLookSensitivity`.",
5918
+ "deprecated": null,
5919
+ "params": [],
5920
+ "returns": null,
5921
+ "throws": null,
5922
+ "example": null,
5923
+ "defaultValue": null,
5924
+ "guides": []
5925
+ },
5926
+ {
5927
+ "id": "GemControlsDeclaration.invertLookY",
5928
+ "name": "invertLookY",
5929
+ "anchor": "gemcontrolsdeclaration-invertlooky",
5930
+ "group": "controls",
5931
+ "signature": "readonly invertLookY?: GemControlChoice",
5932
+ "documented": true,
5933
+ "summary": "Inverted up/down look — `gem.prefs.recommended.invertLookY`.",
5934
+ "deprecated": null,
5935
+ "params": [],
5936
+ "returns": null,
5937
+ "throws": null,
5938
+ "example": null,
5939
+ "defaultValue": null,
5940
+ "guides": []
5941
+ },
5942
+ {
5943
+ "id": "GemControlsDeclaration.touchMovement",
5944
+ "name": "touchMovement",
5945
+ "anchor": "gemcontrolsdeclaration-touchmovement",
5946
+ "group": "controls",
5947
+ "signature": "readonly touchMovement?: GemControlChoice",
5948
+ "documented": true,
5949
+ "summary": "The touch movement thumbstick, floating or fixed — `gem.prefs.recommended.touchMovement`.",
5950
+ "deprecated": null,
5951
+ "params": [],
5952
+ "returns": null,
5953
+ "throws": null,
5954
+ "example": null,
5955
+ "defaultValue": null,
5956
+ "guides": []
5957
+ },
5388
5958
  {
5389
5959
  "id": "DEVICE_SETTINGS_MAX_BYTES",
5390
5960
  "name": "DEVICE_SETTINGS_MAX_BYTES",
@@ -5982,6 +6552,29 @@
5982
6552
  "defaultValue": null,
5983
6553
  "guides": []
5984
6554
  },
6555
+ {
6556
+ "id": "GemFrame.declareControls",
6557
+ "name": "declareControls",
6558
+ "anchor": "gemframe-declarecontrols",
6559
+ "group": "frame",
6560
+ "signature": "declareControls(uses: GemControlsDeclaration): boolean",
6561
+ "documented": true,
6562
+ "summary": "Tell the arcade which of the player's camera and controls settings your\ngame leaves to the player and which it decides itself — the whole answer\neach time, the latest one winning.\n\nPrefer `gem.controls.declare`, which holds the declaration across a\nreconnect. This one sends only while connected, and only to an arcade\nthat shows these settings.",
6563
+ "deprecated": null,
6564
+ "params": [
6565
+ {
6566
+ "name": "uses",
6567
+ "type": "GemControlsDeclaration",
6568
+ "optional": false,
6569
+ "summary": null
6570
+ }
6571
+ ],
6572
+ "returns": "whether the message left the frame — `false` before the bridge is\n up, for an arcade that does not show these settings, and past this\n frame's own limit.",
6573
+ "throws": null,
6574
+ "example": null,
6575
+ "defaultValue": null,
6576
+ "guides": []
6577
+ },
5985
6578
  {
5986
6579
  "id": "GemFrame.setMenu",
5987
6580
  "name": "setMenu",
@@ -6034,6 +6627,22 @@
6034
6627
  "defaultValue": null,
6035
6628
  "guides": []
6036
6629
  },
6630
+ {
6631
+ "id": "GemFrame.requestAvatarPicker",
6632
+ "name": "requestAvatarPicker",
6633
+ "anchor": "gemframe-requestavatarpicker",
6634
+ "group": "frame",
6635
+ "signature": "requestAvatarPicker(): boolean",
6636
+ "documented": true,
6637
+ "summary": "Ask the arcade to open its own avatar picker over your game. Nothing comes\nback: a changed portrait arrives as a new `gem.player`, through `onPlayer`.\n\nPrefer `gem.openAvatarPicker`, which documents what a game does with the\nchange.",
6638
+ "deprecated": null,
6639
+ "params": [],
6640
+ "returns": "whether the message left the frame — `false` before the bridge is\n up, for an arcade that has no avatar picker here, and past this frame's\n own limit of six a minute.",
6641
+ "throws": null,
6642
+ "example": null,
6643
+ "defaultValue": null,
6644
+ "guides": []
6645
+ },
6037
6646
  {
6038
6647
  "id": "GemFrame.requestVibrate",
6039
6648
  "name": "requestVibrate",
@@ -6190,7 +6799,7 @@
6190
6799
  "group": "friends",
6191
6800
  "signature": "readonly avatarIconId?: string",
6192
6801
  "documented": true,
6193
- "summary": "The id of the player's portrait item, when they have one.",
6802
+ "summary": "The id of the player's portrait item, when they have one — what a game\nthat draws Arcade avatars keys its own model on. On `gem.player` it\nchanges when the player wears another portrait, and `onPlayer` runs again;\nsee `gem.openAvatarPicker`.",
6194
6803
  "deprecated": null,
6195
6804
  "params": [],
6196
6805
  "returns": null,
@@ -7960,7 +8569,7 @@
7960
8569
  "group": "player",
7961
8570
  "signature": "readonly avatarIconId?: string",
7962
8571
  "documented": true,
7963
- "summary": "The id of the player's portrait item, when they have one.",
8572
+ "summary": "The id of the player's portrait item, when they have one — what a game\nthat draws Arcade avatars keys its own model on. On `gem.player` it\nchanges when the player wears another portrait, and `onPlayer` runs again;\nsee `gem.openAvatarPicker`.",
7964
8573
  "deprecated": null,
7965
8574
  "params": [],
7966
8575
  "returns": null,
@@ -8093,7 +8702,7 @@
8093
8702
  "group": "player",
8094
8703
  "signature": "readonly recommended: GemRecommendedSettings | null",
8095
8704
  "documented": true,
8096
- "summary": "The player's Arcade-wide defaults for this device — a volume, battery\nsaver, a keyboard layout, the gamepad's confirm button and vibration — or\n`null` when the Arcade did not send them.\n\n**Recommendations only; the player's own choice in your game wins.** Start\na setting from here while the player has made no choice of their own for\nit, and never overwrite one they made because this changed:\n\n```js\nconst saved = gem.deviceSettings.current ?? {};\nconst volume = saved.volume ?? gem.prefs?.recommended?.volume ?? 100;\n```\n\nUnlike `muted` and `reducedMotion`, nothing here is applied for you, and\nnothing obliges you to use it. See the guide's \"Game settings\" section.",
8705
+ "summary": "The player's Arcade-wide defaults for this device — a volume, battery\nsaver, a keyboard layout, the gamepad's confirm button, vibration, and the\ncamera and controls settings (look sensitivity, gamepad look sensitivity,\ninvert look, touch movement) — or `null` when the Arcade did not send them.\n\n**Recommendations only; the player's own choice in your game wins.** Start\na setting from here while the player has made no choice of their own for\nit, and never overwrite one they made because this changed:\n\n```js\nconst saved = gem.deviceSettings.current ?? {};\nconst volume = saved.volume ?? gem.prefs?.recommended?.volume ?? 100;\n```\n\nUnlike `muted` and `reducedMotion`, nothing here is applied for you, and\nnothing obliges you to use it. See the guide's \"Game settings\" section.",
8097
8706
  "deprecated": null,
8098
8707
  "params": [],
8099
8708
  "returns": null,
@@ -8203,6 +8812,70 @@
8203
8812
  "defaultValue": null,
8204
8813
  "guides": []
8205
8814
  },
8815
+ {
8816
+ "id": "GemRecommendedSettings.lookSensitivity",
8817
+ "name": "lookSensitivity",
8818
+ "anchor": "gemrecommendedsettings-looksensitivity",
8819
+ "group": "player",
8820
+ "signature": "readonly lookSensitivity: number",
8821
+ "documented": true,
8822
+ "summary": "The player's look speed for touch, mouse and pen, as a percentage of the\nbase speeds: `100` is 1×, from `20` (0.2×) to `400` (4×). `100` when the\nArcade did not say. `gem.controls.look()` applies it for you.",
8823
+ "deprecated": null,
8824
+ "params": [],
8825
+ "returns": null,
8826
+ "throws": null,
8827
+ "example": null,
8828
+ "defaultValue": null,
8829
+ "guides": []
8830
+ },
8831
+ {
8832
+ "id": "GemRecommendedSettings.gamepadLookSensitivity",
8833
+ "name": "gamepadLookSensitivity",
8834
+ "anchor": "gemrecommendedsettings-gamepadlooksensitivity",
8835
+ "group": "player",
8836
+ "signature": "readonly gamepadLookSensitivity: number",
8837
+ "documented": true,
8838
+ "summary": "The player's look speed for a gamepad stick, as a percentage: `100` is 1×,\nfrom `20` to `400`. `100` when the Arcade did not say.\n`gem.controls.look()` applies it for you.",
8839
+ "deprecated": null,
8840
+ "params": [],
8841
+ "returns": null,
8842
+ "throws": null,
8843
+ "example": null,
8844
+ "defaultValue": null,
8845
+ "guides": []
8846
+ },
8847
+ {
8848
+ "id": "GemRecommendedSettings.invertLookY",
8849
+ "name": "invertLookY",
8850
+ "anchor": "gemrecommendedsettings-invertlooky",
8851
+ "group": "player",
8852
+ "signature": "readonly invertLookY: boolean",
8853
+ "documented": true,
8854
+ "summary": "Whether the player wants up/down look inverted: pushing up or dragging up\nlooks down. Flips pitch only, never yaw. `false` when the Arcade did not\nsay. `gem.controls.look()` applies it for you.",
8855
+ "deprecated": null,
8856
+ "params": [],
8857
+ "returns": null,
8858
+ "throws": null,
8859
+ "example": null,
8860
+ "defaultValue": null,
8861
+ "guides": []
8862
+ },
8863
+ {
8864
+ "id": "GemRecommendedSettings.touchMovement",
8865
+ "name": "touchMovement",
8866
+ "anchor": "gemrecommendedsettings-touchmovement",
8867
+ "group": "player",
8868
+ "signature": "readonly touchMovement: \"floating\" | \"fixed\"",
8869
+ "documented": true,
8870
+ "summary": "On a touch screen, the movement thumbstick the player wants: `'floating'`\nappears where the thumb lands, `'fixed'` stays in one place. `'floating'`\nwhen the Arcade did not say. Your game draws the stick.",
8871
+ "deprecated": null,
8872
+ "params": [],
8873
+ "returns": null,
8874
+ "throws": null,
8875
+ "example": null,
8876
+ "defaultValue": null,
8877
+ "guides": []
8878
+ },
8206
8879
  {
8207
8880
  "id": "GemCohort",
8208
8881
  "name": "GemCohort",
@@ -9030,6 +9703,38 @@
9030
9703
  }
9031
9704
  ]
9032
9705
  },
9706
+ {
9707
+ "id": "Gem.avatarPickerAvailable",
9708
+ "name": "avatarPickerAvailable",
9709
+ "anchor": "gem-avatarpickeravailable",
9710
+ "group": "start",
9711
+ "signature": "readonly avatarPickerAvailable: boolean",
9712
+ "documented": true,
9713
+ "summary": "Whether the arcade will open its avatar picker for [Gem.openAvatarPicker](api-reference-game.md#gem-openavatarpicker)\nhere. Decide from it whether to show your own \"Change avatar\" button, and\nread it again in the click handler — it is read live.\n\n`false` outside the arcade, before the bridge is up, after the session\nends, and under an embedder that has no avatar picker.",
9714
+ "deprecated": null,
9715
+ "params": [],
9716
+ "returns": null,
9717
+ "throws": null,
9718
+ "example": null,
9719
+ "defaultValue": null,
9720
+ "guides": []
9721
+ },
9722
+ {
9723
+ "id": "Gem.openAvatarPicker",
9724
+ "name": "openAvatarPicker",
9725
+ "anchor": "gem-openavatarpicker",
9726
+ "group": "start",
9727
+ "signature": "openAvatarPicker(): boolean",
9728
+ "documented": true,
9729
+ "summary": "Open the arcade's avatar picker over your game, so the player can change\nthe Arcade avatar they wear without leaving it. For a game that draws\nArcade avatars — whole characters the player owns as Arcade items — put a\n\"Change avatar\" button in your own UI and call this from it:\n\n```js\nchangeAvatar.hidden = !gem.avatarPickerAvailable;\nchangeAvatar.onclick = () => {\n if (!gem.openAvatarPicker()) changeAvatar.hidden = true;\n};\n```\n\n**The change arrives as a new player, not as an answer.** Nothing comes\nback from this call. When the player picks a different avatar, the arcade\npauses your game while the picker is open, then sends the player again —\nyour `onPlayer` callback runs and [Gem.player](api-reference-game.md#gem-player) holds the new\n[PlayerIdentity.avatarIconId](api-reference-game.md#playeridentity-avatariconid) — and resumes it. Redraw from\n`onPlayer`, which also runs when the player changes their avatar from the\narcade's own menu without your game asking. A player who closes the picker\nunchanged produces nothing at all.\n\n**Your server learns it only when it reads the room again.** A\nserver-authoritative game reads each member's `avatar_icon_id` from the\nroom read (`GET /v1/games/{game_id}/game-rooms/{game_room_id}`, or\n`gem.room.get()` on a dedicated server); nothing tells the server the\nplayer changed. So when `onPlayer` brings a different `avatarIconId`, have\nyour client tell your server, and have the server re-read the room — never\ntrust the id the client sends.",
9730
+ "deprecated": null,
9731
+ "params": [],
9732
+ "returns": "`true` when the arcade was asked; `false` when it was not and\n never will be for this call — outside the arcade, before the bridge is\n up, under an embedder with no avatar picker, or past six asks a minute.\n It never throws and never waits.",
9733
+ "throws": null,
9734
+ "example": null,
9735
+ "defaultValue": null,
9736
+ "guides": []
9737
+ },
9033
9738
  {
9034
9739
  "id": "Gem.vibration",
9035
9740
  "name": "vibration",
@@ -9051,6 +9756,22 @@
9051
9756
  }
9052
9757
  ]
9053
9758
  },
9759
+ {
9760
+ "id": "Gem.controls",
9761
+ "name": "controls",
9762
+ "anchor": "gem-controls",
9763
+ "group": "start",
9764
+ "signature": "readonly controls: ControlsApi",
9765
+ "documented": true,
9766
+ "summary": "The player's camera and controls settings — look sensitivity, gamepad look\nsensitivity, invert look and touch movement, which arrive in\n`gem.prefs.recommended`. Two things to do with them:\n\n```js\n// 1. Tell the Arcade which ones your game leaves to the player.\ngem.controls.declare({ lookSensitivity: 'player', invertLookY: 'player' });\n\n// 2. Turn look input into a camera turn at the player's sensitivity.\nconst look = gem.controls.look();\n// dx, dy: the pointer's move in CSS px since the last event.\nconst t = look.fromPointer(dx, dy, e.pointerType, camera.pitch);\ncamera.yaw += t.yaw;\ncamera.pitch += t.pitch;\n```\n\nSee the guide's \"Camera and look controls\" section.",
9767
+ "deprecated": null,
9768
+ "params": [],
9769
+ "returns": null,
9770
+ "throws": null,
9771
+ "example": null,
9772
+ "defaultValue": null,
9773
+ "guides": []
9774
+ },
9054
9775
  {
9055
9776
  "id": "Gem.analytics",
9056
9777
  "name": "analytics",
@@ -10625,7 +11346,7 @@
10625
11346
  "group": "player",
10626
11347
  "signature": "readonly avatarIconId?: string",
10627
11348
  "documented": true,
10628
- "summary": "The id of the player's portrait item, when they have one.",
11349
+ "summary": "The id of the player's portrait item, when they have one — what a game\nthat draws Arcade avatars keys its own model on. On `gem.player` it\nchanges when the player wears another portrait, and `onPlayer` runs again;\nsee `gem.openAvatarPicker`.",
10629
11350
  "deprecated": null,
10630
11351
  "params": [],
10631
11352
  "returns": null,
@@ -13397,7 +14118,7 @@
13397
14118
  "group": "leaderboards",
13398
14119
  "signature": "readonly avatarIconId?: string",
13399
14120
  "documented": true,
13400
- "summary": "The id of the player's portrait item, when they have one.",
14121
+ "summary": "The id of the player's portrait item, when they have one — what a game\nthat draws Arcade avatars keys its own model on. On `gem.player` it\nchanges when the player wears another portrait, and `onPlayer` runs again;\nsee `gem.openAvatarPicker`.",
13401
14122
  "deprecated": null,
13402
14123
  "params": [],
13403
14124
  "returns": null,
@@ -15160,7 +15881,7 @@
15160
15881
  "group": "profiles",
15161
15882
  "signature": "readonly avatarIconId?: string",
15162
15883
  "documented": true,
15163
- "summary": "The id of the player's portrait item, when they have one.",
15884
+ "summary": "The id of the player's portrait item, when they have one — what a game\nthat draws Arcade avatars keys its own model on. On `gem.player` it\nchanges when the player wears another portrait, and `onPlayer` runs again;\nsee `gem.openAvatarPicker`.",
15164
15885
  "deprecated": null,
15165
15886
  "params": [],
15166
15887
  "returns": null,
@@ -17976,7 +18697,7 @@
17976
18697
  "group": "rooms",
17977
18698
  "signature": "readonly avatarIconId?: string",
17978
18699
  "documented": true,
17979
- "summary": "The id of the player's portrait item, when they have one.",
18700
+ "summary": "The id of the player's portrait item, when they have one — what a game\nthat draws Arcade avatars keys its own model on. On `gem.player` it\nchanges when the player wears another portrait, and `onPlayer` runs again;\nsee `gem.openAvatarPicker`.",
17980
18701
  "deprecated": null,
17981
18702
  "params": [],
17982
18703
  "returns": null,
@@ -19058,7 +19779,7 @@
19058
19779
  "group": "showcase",
19059
19780
  "signature": "readonly avatarIconId?: string",
19060
19781
  "documented": true,
19061
- "summary": "The id of the player's portrait item, when they have one.",
19782
+ "summary": "The id of the player's portrait item, when they have one — what a game\nthat draws Arcade avatars keys its own model on. On `gem.player` it\nchanges when the player wears another portrait, and `onPlayer` runs again;\nsee `gem.openAvatarPicker`.",
19062
19783
  "deprecated": null,
19063
19784
  "params": [],
19064
19785
  "returns": null,
@@ -21744,6 +22465,54 @@
21744
22465
  "defaultValue": null,
21745
22466
  "guides": []
21746
22467
  },
22468
+ {
22469
+ "id": "MatchBackfillState",
22470
+ "name": "MatchBackfillState",
22471
+ "anchor": "matchbackfillstate",
22472
+ "group": "match",
22473
+ "signature": "interface MatchBackfillState",
22474
+ "documented": true,
22475
+ "summary": "Whether this match is being topped up from the matchmaking queue, as the\nplatform now has it.",
22476
+ "deprecated": null,
22477
+ "params": [],
22478
+ "returns": null,
22479
+ "throws": null,
22480
+ "example": null,
22481
+ "defaultValue": null,
22482
+ "guides": []
22483
+ },
22484
+ {
22485
+ "id": "MatchPlayerReport",
22486
+ "name": "MatchPlayerReport",
22487
+ "anchor": "matchplayerreport",
22488
+ "group": "match",
22489
+ "signature": "interface MatchPlayerReport",
22490
+ "documented": true,
22491
+ "summary": "What your server says about one player of its match, for\n[GemServer.match](api-reference-server.md#gemserver-match)'s `reportPlayers`.",
22492
+ "deprecated": null,
22493
+ "params": [],
22494
+ "returns": null,
22495
+ "throws": null,
22496
+ "example": null,
22497
+ "defaultValue": null,
22498
+ "guides": []
22499
+ },
22500
+ {
22501
+ "id": "MatchPlayerReportResult",
22502
+ "name": "MatchPlayerReportResult",
22503
+ "anchor": "matchplayerreportresult",
22504
+ "group": "match",
22505
+ "signature": "interface MatchPlayerReportResult",
22506
+ "documented": true,
22507
+ "summary": "What a report did for one player, in the order you reported them.",
22508
+ "deprecated": null,
22509
+ "params": [],
22510
+ "returns": null,
22511
+ "throws": null,
22512
+ "example": null,
22513
+ "defaultValue": null,
22514
+ "guides": []
22515
+ },
21747
22516
  {
21748
22517
  "id": "GemServerOptions",
21749
22518
  "name": "GemServerOptions",
@@ -22535,6 +23304,102 @@
22535
23304
  "defaultValue": null,
22536
23305
  "guides": []
22537
23306
  },
23307
+ {
23308
+ "id": "MatchPlayerReport.playerId",
23309
+ "name": "playerId",
23310
+ "anchor": "matchplayerreport-playerid",
23311
+ "group": "match",
23312
+ "signature": "readonly playerId: string",
23313
+ "documented": true,
23314
+ "summary": "The player. Take it from `join()`, `leave()` or the room, never from a client.",
23315
+ "deprecated": null,
23316
+ "params": [],
23317
+ "returns": null,
23318
+ "throws": null,
23319
+ "example": null,
23320
+ "defaultValue": null,
23321
+ "guides": []
23322
+ },
23323
+ {
23324
+ "id": "MatchPlayerReport.state",
23325
+ "name": "state",
23326
+ "anchor": "matchplayerreport-state",
23327
+ "group": "match",
23328
+ "signature": "readonly state: \"connected\" | \"no_show\" | \"left\"",
23329
+ "documented": true,
23330
+ "summary": "- `connected` — the player has connected to this server.\n- `no_show` — the player was given a seat and never connected.\n- `left` — the player was in the match and is gone FOR GOOD.\n\nThe last two remove the player from the room, which frees the seat.",
23331
+ "deprecated": null,
23332
+ "params": [],
23333
+ "returns": null,
23334
+ "throws": null,
23335
+ "example": null,
23336
+ "defaultValue": null,
23337
+ "guides": []
23338
+ },
23339
+ {
23340
+ "id": "MatchPlayerReportResult.playerId",
23341
+ "name": "playerId",
23342
+ "anchor": "matchplayerreportresult-playerid",
23343
+ "group": "match",
23344
+ "signature": "readonly playerId: string",
23345
+ "documented": true,
23346
+ "summary": "The player this result is for.",
23347
+ "deprecated": null,
23348
+ "params": [],
23349
+ "returns": null,
23350
+ "throws": null,
23351
+ "example": null,
23352
+ "defaultValue": null,
23353
+ "guides": []
23354
+ },
23355
+ {
23356
+ "id": "MatchPlayerReportResult.outcome",
23357
+ "name": "outcome",
23358
+ "anchor": "matchplayerreportresult-outcome",
23359
+ "group": "match",
23360
+ "signature": "readonly outcome: \"recorded\" | \"removed\" | \"not_a_member\" | string & object",
23361
+ "documented": true,
23362
+ "summary": "- `recorded` — `connected` was noted.\n- `removed` — the player was taken out of the room.\n- `not_a_member` — the player is not in this match's room; nothing changed.",
23363
+ "deprecated": null,
23364
+ "params": [],
23365
+ "returns": null,
23366
+ "throws": null,
23367
+ "example": null,
23368
+ "defaultValue": null,
23369
+ "guides": []
23370
+ },
23371
+ {
23372
+ "id": "MatchBackfillState.open",
23373
+ "name": "open",
23374
+ "anchor": "matchbackfillstate-open",
23375
+ "group": "match",
23376
+ "signature": "readonly open: boolean",
23377
+ "documented": true,
23378
+ "summary": "Whether the match is taking players from the queue.",
23379
+ "deprecated": null,
23380
+ "params": [],
23381
+ "returns": null,
23382
+ "throws": null,
23383
+ "example": null,
23384
+ "defaultValue": null,
23385
+ "guides": []
23386
+ },
23387
+ {
23388
+ "id": "MatchBackfillState.seats",
23389
+ "name": "seats",
23390
+ "anchor": "matchbackfillstate-seats",
23391
+ "group": "match",
23392
+ "signature": "readonly seats: number | null",
23393
+ "documented": true,
23394
+ "summary": "The most players still wanted, or `null` for every open seat.",
23395
+ "deprecated": null,
23396
+ "params": [],
23397
+ "returns": null,
23398
+ "throws": null,
23399
+ "example": null,
23400
+ "defaultValue": null,
23401
+ "guides": []
23402
+ },
22538
23403
  {
22539
23404
  "id": "GemServer.identity",
22540
23405
  "name": "identity",
@@ -22588,7 +23453,7 @@
22588
23453
  "name": "match",
22589
23454
  "anchor": "gemserver-match",
22590
23455
  "group": "api",
22591
- "signature": "readonly match: { end: null }",
23456
+ "signature": "readonly match: { end: null; setBackfill: null; reportPlayers: null }",
22592
23457
  "documented": true,
22593
23458
  "summary": "Ending the match.\n\n`end()` is HOW A SERVER-AUTHORITATIVE GAME FINISHES. It tells the platform\nthe match is over; the platform then tells the runtime, and your server\nwinds down through its ordinary shutdown. You do not stop the process\nyourself.\n\nIt always means THIS match — the id is already known, so there is nothing to\npass and no way to end someone else's.\n\nThe platform half makes the request, not your process: it holds the proof\nthat this server is the one allocated to the match, which the platform\nrequires. On a platform image too old to offer that, `end()` throws rather\nthan sending a request without the proof.",
22594
23459
  "deprecated": null,
@@ -22622,6 +23487,64 @@
22622
23487
  "defaultValue": null,
22623
23488
  "guides": []
22624
23489
  },
23490
+ {
23491
+ "id": "GemServer.match.setBackfill",
23492
+ "name": "setBackfill",
23493
+ "anchor": "gemserver-match-setbackfill",
23494
+ "group": "api",
23495
+ "signature": "setBackfill(options: { open: boolean; seats?: number }, signal?: AbortSignal): Promise<MatchBackfillState>",
23496
+ "documented": true,
23497
+ "summary": "Stop, or restart, the platform topping this match up from the\nmatchmaking queue.\n\nA match the platform matchmade from a room type with backfill turned on\ntakes waiting players into its open seats from the moment it starts.\nThis is how your server takes control of that: close it once joining\nlate no longer makes sense — the last round, a boss fight — and open it\nagain if it does.\n\nClosing removes nobody, and a player already on the way in still\narrives. The setting lasts for the match.",
23498
+ "deprecated": null,
23499
+ "params": [
23500
+ {
23501
+ "name": "options",
23502
+ "type": "{ open: boolean; seats?: number }",
23503
+ "optional": false,
23504
+ "summary": "`open` — whether to take players. `seats` — with\n `open: true`, the most players still wanted; it counts down as seats\n fill. Omit it for every open seat."
23505
+ },
23506
+ {
23507
+ "name": "signal",
23508
+ "type": "AbortSignal",
23509
+ "optional": true,
23510
+ "summary": "Cancels the request."
23511
+ }
23512
+ ],
23513
+ "returns": null,
23514
+ "throws": "A `GemApiError` with code `backfill_not_enabled` when this match\n is not one the platform tops up: its room type has no backfill, or the\n room was not matchmade.",
23515
+ "example": "```js\n// Nobody new once the final round starts.\nawait gem.match.setBackfill({ open: false });\n```",
23516
+ "defaultValue": null,
23517
+ "guides": []
23518
+ },
23519
+ {
23520
+ "id": "GemServer.match.reportPlayers",
23521
+ "name": "reportPlayers",
23522
+ "anchor": "gemserver-match-reportplayers",
23523
+ "group": "api",
23524
+ "signature": "reportPlayers(reports: readonly MatchPlayerReport[], signal?: AbortSignal): Promise<MatchPlayerReportResult[]>",
23525
+ "documented": true,
23526
+ "summary": "Tell the platform which players have connected, never arrived, or left.\n\n`no_show` and `left` REMOVE THE PLAYER FROM THE ROOM, which frees the\nseat — for the queue, when the match is being topped up. Report `left`\nonly for a player who is gone for good: reconnecting does not put a\nremoved player back, they have to join again.\n\nYOU DO NOT REPORT `connected` YOURSELF in a bundle built with\n[defineServer](api-reference-server.md#defineserver): it reports each player as they join. That report is\nwhat gives a seat the platform filled from the queue a time limit — a\nplayer who is seated and never connects is removed, and the seat goes to\nthe next one waiting.",
23527
+ "deprecated": null,
23528
+ "params": [
23529
+ {
23530
+ "name": "reports",
23531
+ "type": "readonly MatchPlayerReport[]",
23532
+ "optional": false,
23533
+ "summary": "1 to 32 players."
23534
+ },
23535
+ {
23536
+ "name": "signal",
23537
+ "type": "AbortSignal",
23538
+ "optional": true,
23539
+ "summary": "Cancels the request."
23540
+ }
23541
+ ],
23542
+ "returns": "One result per report, in the same order.",
23543
+ "throws": null,
23544
+ "example": "```js\nleave(playerId) {\n // This game does not let a player back in once they quit.\n void gem.match.reportPlayers([{ playerId, state: 'left' }]);\n}\n```",
23545
+ "defaultValue": null,
23546
+ "guides": []
23547
+ },
22625
23548
  {
22626
23549
  "id": "GemServer.analytics",
22627
23550
  "name": "analytics",
@@ -23340,7 +24263,7 @@
23340
24263
  "name": "endMatch",
23341
24264
  "anchor": "gemserverhost-endmatch",
23342
24265
  "group": "host",
23343
- "signature": "endMatch(): Promise<\"ok\" | \"already_ended\" | \"refused\" | \"failed\" | string & object>",
24266
+ "signature": "endMatch(): Promise<string & object | \"ok\" | \"already_ended\" | \"refused\" | \"failed\">",
23344
24267
  "documented": true,
23345
24268
  "summary": "Ask the platform half to end this match, with the allocation's own proof.\n\nMAY BE ABSENT on older platform images. `gem.match.end()` is this call —\nthe request carries the allocation nonce, which never enters the bundle\nprocess — and refuses on an image that does not offer it. You rarely call\nthis yourself.\n\nResolves with what the platform half did: `ok`, `already_ended` (this\nmatch was already over, or you asked twice), `refused` (the allocation was\nnot ready yet) or `failed` (the platform could not be reached).",
23346
24269
  "deprecated": null,
@@ -23930,7 +24853,7 @@
23930
24853
  "name": "match",
23931
24854
  "anchor": "gemmatchserver-match",
23932
24855
  "group": "start",
23933
- "signature": "readonly match: { end: null }",
24856
+ "signature": "readonly match: { end: null; setBackfill: null; reportPlayers: null }",
23934
24857
  "documented": true,
23935
24858
  "summary": "Ending the match.\n\n`end()` is HOW A SERVER-AUTHORITATIVE GAME FINISHES. It tells the platform\nthe match is over; the platform then tells the runtime, and your server\nwinds down through its ordinary shutdown. You do not stop the process\nyourself.\n\nIt always means THIS match — the id is already known, so there is nothing to\npass and no way to end someone else's.\n\nThe platform half makes the request, not your process: it holds the proof\nthat this server is the one allocated to the match, which the platform\nrequires. On a platform image too old to offer that, `end()` throws rather\nthan sending a request without the proof.",
23936
24859
  "deprecated": null,
@@ -23964,6 +24887,64 @@
23964
24887
  "defaultValue": null,
23965
24888
  "guides": []
23966
24889
  },
24890
+ {
24891
+ "id": "GemMatchServer.match.setBackfill",
24892
+ "name": "setBackfill",
24893
+ "anchor": "gemmatchserver-match-setbackfill",
24894
+ "group": "start",
24895
+ "signature": "setBackfill(options: { open: boolean; seats?: number }, signal?: AbortSignal): Promise<MatchBackfillState>",
24896
+ "documented": true,
24897
+ "summary": "Stop, or restart, the platform topping this match up from the\nmatchmaking queue.\n\nA match the platform matchmade from a room type with backfill turned on\ntakes waiting players into its open seats from the moment it starts.\nThis is how your server takes control of that: close it once joining\nlate no longer makes sense — the last round, a boss fight — and open it\nagain if it does.\n\nClosing removes nobody, and a player already on the way in still\narrives. The setting lasts for the match.",
24898
+ "deprecated": null,
24899
+ "params": [
24900
+ {
24901
+ "name": "options",
24902
+ "type": "{ open: boolean; seats?: number }",
24903
+ "optional": false,
24904
+ "summary": "`open` — whether to take players. `seats` — with\n `open: true`, the most players still wanted; it counts down as seats\n fill. Omit it for every open seat."
24905
+ },
24906
+ {
24907
+ "name": "signal",
24908
+ "type": "AbortSignal",
24909
+ "optional": true,
24910
+ "summary": "Cancels the request."
24911
+ }
24912
+ ],
24913
+ "returns": null,
24914
+ "throws": "A `GemApiError` with code `backfill_not_enabled` when this match\n is not one the platform tops up: its room type has no backfill, or the\n room was not matchmade.",
24915
+ "example": "```js\n// Nobody new once the final round starts.\nawait gem.match.setBackfill({ open: false });\n```",
24916
+ "defaultValue": null,
24917
+ "guides": []
24918
+ },
24919
+ {
24920
+ "id": "GemMatchServer.match.reportPlayers",
24921
+ "name": "reportPlayers",
24922
+ "anchor": "gemmatchserver-match-reportplayers",
24923
+ "group": "start",
24924
+ "signature": "reportPlayers(reports: readonly MatchPlayerReport[], signal?: AbortSignal): Promise<MatchPlayerReportResult[]>",
24925
+ "documented": true,
24926
+ "summary": "Tell the platform which players have connected, never arrived, or left.\n\n`no_show` and `left` REMOVE THE PLAYER FROM THE ROOM, which frees the\nseat — for the queue, when the match is being topped up. Report `left`\nonly for a player who is gone for good: reconnecting does not put a\nremoved player back, they have to join again.\n\nYOU DO NOT REPORT `connected` YOURSELF in a bundle built with\n[defineServer](api-reference-server.md#defineserver): it reports each player as they join. That report is\nwhat gives a seat the platform filled from the queue a time limit — a\nplayer who is seated and never connects is removed, and the seat goes to\nthe next one waiting.",
24927
+ "deprecated": null,
24928
+ "params": [
24929
+ {
24930
+ "name": "reports",
24931
+ "type": "readonly MatchPlayerReport[]",
24932
+ "optional": false,
24933
+ "summary": "1 to 32 players."
24934
+ },
24935
+ {
24936
+ "name": "signal",
24937
+ "type": "AbortSignal",
24938
+ "optional": true,
24939
+ "summary": "Cancels the request."
24940
+ }
24941
+ ],
24942
+ "returns": "One result per report, in the same order.",
24943
+ "throws": null,
24944
+ "example": "```js\nleave(playerId) {\n // This game does not let a player back in once they quit.\n void gem.match.reportPlayers([{ playerId, state: 'left' }]);\n}\n```",
24945
+ "defaultValue": null,
24946
+ "guides": []
24947
+ },
23967
24948
  {
23968
24949
  "id": "GemMatchServer.analytics",
23969
24950
  "name": "analytics",