@indiegems/gem-web-sdk 23.0.5 → 23.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/dist/conformance.d.ts +2 -1
- package/dist/game.d.ts +4 -0
- package/dist/gem-web-sdk.bridge.js +1 -1
- package/dist/gem-web-sdk.conformance.js +3 -3
- package/dist/gem-web-sdk.esm.js +3 -3
- package/dist/gem-web-sdk.function.js +1 -1
- package/dist/gem-web-sdk.game.js +3 -3
- package/dist/gem-web-sdk.min.js +3 -3
- package/dist/gem-web-sdk.sdk.js +3 -3
- package/dist/gem-web-sdk.server.js +2 -2
- package/dist/index.d.ts +3 -1
- package/dist/sdk.d.ts +4 -0
- package/docs/api/api-reference-function.md +1 -1
- package/docs/api/api-reference-game.md +73 -1
- package/docs/api/api-reference-server.md +1 -1
- package/docs/api/reference.json +49 -1
- package/docs/changelog.md +26 -0
- package/docs/getting-started.md +1 -1
- package/docs/manifest.json +10 -10
- package/docs/rewarded-ads.md +7 -2
- package/docs/server-bundles.md +2 -2
- package/docs/what-a-game-must-do.md +123 -16
- package/package.json +1 -1
- package/schema/bridge.v1.json +40 -0
- package/schema/capabilities.public.json +8 -0
package/docs/changelog.md
CHANGED
|
@@ -16,6 +16,32 @@ Its entries are grouped under up to five headings:
|
|
|
16
16
|
- **Rebuild**: a type changed. Recompile against the new version; code that compiles today keeps compiling unless the entry says otherwise.
|
|
17
17
|
- **New capability**: something a game can now do. Nothing changes unless you use it.
|
|
18
18
|
|
|
19
|
+
## 23.1.0
|
|
20
|
+
|
|
21
|
+
*Written from the API facts alone; no summary was generated for this release.*
|
|
22
|
+
|
|
23
|
+
Upgrading from 23.0.6. Impact: required.
|
|
24
|
+
|
|
25
|
+
### Must change
|
|
26
|
+
|
|
27
|
+
- PARENT_CONFORMANCE_VERSION changed its signature.
|
|
28
|
+
- GemCapability changed its signature.
|
|
29
|
+
- GemHost.sendPrefs changed its signature.
|
|
30
|
+
- GemPrefs.recommended changed its signature.
|
|
31
|
+
|
|
32
|
+
### New capability
|
|
33
|
+
|
|
34
|
+
- ParentUnderTest.setTextScale was added.
|
|
35
|
+
- Gem.textScale was added.
|
|
36
|
+
- GemOptions.onTextScale was added.
|
|
37
|
+
- GemRecommendedSettings.textScale was added.
|
|
38
|
+
|
|
39
|
+
## 23.0.6
|
|
40
|
+
|
|
41
|
+
Upgrading from 23.0.5. Impact: none.
|
|
42
|
+
|
|
43
|
+
Nothing in this release asks anything of a game.
|
|
44
|
+
|
|
19
45
|
## 23.0.5
|
|
20
46
|
|
|
21
47
|
Upgrading from 23.0.4. Impact: none.
|
package/docs/getting-started.md
CHANGED
package/docs/manifest.json
CHANGED
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
"file": "changelog.md",
|
|
51
|
-
"sha256": "
|
|
52
|
-
"updated": "2026-11-
|
|
51
|
+
"sha256": "08a45ac742126bf110a16e9373e09a4e06fd4ab8cd68d62309a512a1712c8c53",
|
|
52
|
+
"updated": "2026-11-07T14:55:28Z"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"file": "daily-challenges.md",
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
"file": "getting-started.md",
|
|
81
|
-
"sha256": "
|
|
82
|
-
"updated": "2026-11-
|
|
81
|
+
"sha256": "a711052efd2252ddda2bed1af1394f8c57692086d5e3acdd6ccf2e5b7a14b4fc",
|
|
82
|
+
"updated": "2026-11-07T14:55:28Z"
|
|
83
83
|
},
|
|
84
84
|
{
|
|
85
85
|
"file": "graphics-route.md",
|
|
@@ -123,8 +123,8 @@
|
|
|
123
123
|
},
|
|
124
124
|
{
|
|
125
125
|
"file": "rewarded-ads.md",
|
|
126
|
-
"sha256": "
|
|
127
|
-
"updated": "2026-11-
|
|
126
|
+
"sha256": "0658ec71ae9938040c2a493385cd9e360224b51309b3254438950124ae444743",
|
|
127
|
+
"updated": "2026-11-07T02:38:17Z"
|
|
128
128
|
},
|
|
129
129
|
{
|
|
130
130
|
"file": "room-shapes.md",
|
|
@@ -143,8 +143,8 @@
|
|
|
143
143
|
},
|
|
144
144
|
{
|
|
145
145
|
"file": "server-bundles.md",
|
|
146
|
-
"sha256": "
|
|
147
|
-
"updated": "2026-11-
|
|
146
|
+
"sha256": "e0249cef381f23d156443b6a0b73c3a9616055e5434acf39fbdcada04ec0e745",
|
|
147
|
+
"updated": "2026-11-07T14:55:28Z"
|
|
148
148
|
},
|
|
149
149
|
{
|
|
150
150
|
"file": "serverless-functions-js.md",
|
|
@@ -168,8 +168,8 @@
|
|
|
168
168
|
},
|
|
169
169
|
{
|
|
170
170
|
"file": "what-a-game-must-do.md",
|
|
171
|
-
"sha256": "
|
|
172
|
-
"updated": "2026-11-
|
|
171
|
+
"sha256": "f70fe9fad67c6b386bddc53f1f876bb78f6a5e11c35f565bb93e925d65a99874",
|
|
172
|
+
"updated": "2026-11-06T22:48:07Z"
|
|
173
173
|
}
|
|
174
174
|
]
|
|
175
175
|
}
|
package/docs/rewarded-ads.md
CHANGED
|
@@ -505,13 +505,18 @@ reward because of anything else you have read about a channel.
|
|
|
505
505
|
stops the placement, so it tells you what to draw, not which state you are in. It never says
|
|
506
506
|
whether an ad will play.
|
|
507
507
|
|
|
508
|
+
To see what each channel serves without a running game, run `gemctl rewarded status`: it answers
|
|
509
|
+
for browsers and for the native apps. Its answer is the same for every player, so it cannot say what
|
|
510
|
+
one player gets, and the platform can move a channel after you read it. Keep the button on
|
|
511
|
+
`grantable`.
|
|
512
|
+
|
|
508
513
|
**Test ads never serve on `release`**, and a reward granted on `dev` or `test` never reaches
|
|
509
514
|
`release`: inventory is per channel.
|
|
510
515
|
|
|
511
516
|
What each state means for a game:
|
|
512
517
|
|
|
513
|
-
- **Build
|
|
514
|
-
`without_ads: grant`, a reward that should be free
|
|
518
|
+
- **Build one shape for every state.** The code in §5 is the same code in every state. Under
|
|
519
|
+
`without_ads: grant`, a reward that should be free where no ad serves is free in state B: the same
|
|
515
520
|
benefit, under the same caps. In state C the same placement plays an ad when one is available.
|
|
516
521
|
It still pays with no ad whenever no ad can play for a press, because no ad was available or the
|
|
517
522
|
ad failed. So in state C too, a `grant` placement's caps are the only limit on it. There is
|
package/docs/server-bundles.md
CHANGED
|
@@ -80,8 +80,8 @@ To check the download yourself: the package npm serves is, byte for byte, the fi
|
|
|
80
80
|
also publishes on its download host, with the hash beside it:
|
|
81
81
|
|
|
82
82
|
```bash
|
|
83
|
-
curl -fsSL -O https://downloads.gemarcade.com/sdk/v23.0
|
|
84
|
-
curl -fsSL https://downloads.gemarcade.com/sdk/v23.0
|
|
83
|
+
curl -fsSL -O https://downloads.gemarcade.com/sdk/v23.1.0/gem-web-sdk.tgz
|
|
84
|
+
curl -fsSL https://downloads.gemarcade.com/sdk/v23.1.0/gem-web-sdk.tgz.sri
|
|
85
85
|
openssl dgst -sha384 -binary gem-web-sdk.tgz | openssl base64 -A
|
|
86
86
|
```
|
|
87
87
|
|
|
@@ -1149,20 +1149,21 @@ The player sets their defaults once, in the Arcade's Settings, separately for ea
|
|
|
1149
1149
|
and a television can say different things. They reach your game as `gem.prefs.recommended`, in the
|
|
1150
1150
|
same push as `muted` and `reducedMotion`, and again whenever the player changes one:
|
|
1151
1151
|
|
|
1152
|
-
| Field | Values | What it suggests
|
|
1153
|
-
| ------------------------ | ------------------------------- |
|
|
1154
|
-
| `volume` | `0` to `100` | Your master volume's starting level, as a percentage — divide by 100 for a gain. A level, never a mute.
|
|
1155
|
-
| `batterySaver` | `true` / `false` | Spend less power: a lower frame rate, fewer effects, a lower resolution.
|
|
1156
|
-
| `keyboardLayout` | `'wasd'` / `'arrows'` | Which keys move by default.
|
|
1157
|
-
| `gamepadConfirm` | `'south'` / `'east'` | Which face button confirms, by position: the bottom one (A on an Xbox controller) or the right one (B). The other one goes back.
|
|
1158
|
-
| `vibration` | `true` / `false` | Your vibration toggle's starting state ([if your game vibrates](#if-your-game-vibrates)).
|
|
1159
|
-
| `lookSensitivity` | `20` to `400` | Look speed for touch, mouse and pen, as a percentage of the base speeds: `100` is 1×.
|
|
1160
|
-
| `gamepadLookSensitivity` | `20` to `400` | Look speed for a gamepad stick, as a percentage: `100` is 1×.
|
|
1161
|
-
| `invertLookY` | `true` / `false` | Up/down look inverted: pushing up or dragging up looks down. Pitch only, never yaw.
|
|
1162
|
-
| `touchMovement` | `'floating'` / `'fixed'` | On a touch screen, a movement stick that appears where the thumb lands, or one fixed in place.
|
|
1163
|
-
| `graphicsQuality` | `'low'` / `'medium'` / `'high'` | The graphics quality to start at on this device.
|
|
1164
|
-
| `graphicsQualityAuto` | `true` / `false` | `true`: the Arcade picked that tier for this device, so you may adapt from it. `false`: the player picked it, so hold it.
|
|
1165
|
-
| `colorHelp` | `true` / `false` / `null` | Color help: start your colour-blind aids (patterns or symbols beside colours, a colour-blind palette) on, or off. `null`: no advice.
|
|
1152
|
+
| Field | Values | What it suggests |
|
|
1153
|
+
| ------------------------ | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1154
|
+
| `volume` | `0` to `100` | Your master volume's starting level, as a percentage — divide by 100 for a gain. A level, never a mute. |
|
|
1155
|
+
| `batterySaver` | `true` / `false` | Spend less power: a lower frame rate, fewer effects, a lower resolution. |
|
|
1156
|
+
| `keyboardLayout` | `'wasd'` / `'arrows'` | Which keys move by default. |
|
|
1157
|
+
| `gamepadConfirm` | `'south'` / `'east'` | Which face button confirms, by position: the bottom one (A on an Xbox controller) or the right one (B). The other one goes back. |
|
|
1158
|
+
| `vibration` | `true` / `false` | Your vibration toggle's starting state ([if your game vibrates](#if-your-game-vibrates)). |
|
|
1159
|
+
| `lookSensitivity` | `20` to `400` | Look speed for touch, mouse and pen, as a percentage of the base speeds: `100` is 1×. |
|
|
1160
|
+
| `gamepadLookSensitivity` | `20` to `400` | Look speed for a gamepad stick, as a percentage: `100` is 1×. |
|
|
1161
|
+
| `invertLookY` | `true` / `false` | Up/down look inverted: pushing up or dragging up looks down. Pitch only, never yaw. |
|
|
1162
|
+
| `touchMovement` | `'floating'` / `'fixed'` | On a touch screen, a movement stick that appears where the thumb lands, or one fixed in place. |
|
|
1163
|
+
| `graphicsQuality` | `'low'` / `'medium'` / `'high'` | The graphics quality to start at on this device. |
|
|
1164
|
+
| `graphicsQualityAuto` | `true` / `false` | `true`: the Arcade picked that tier for this device, so you may adapt from it. `false`: the player picked it, so hold it. |
|
|
1165
|
+
| `colorHelp` | `true` / `false` / `null` | Color help: start your colour-blind aids (patterns or symbols beside colours, a colour-blind palette) on, or off. `null`: no advice. |
|
|
1166
|
+
| `textScale` | `100` to `200` / `null` | Text size, as a percent: scale your whole interface by it. Sent only to a game that passes `onTextScale`: see [text size](#the-arcades-text-size-size-in-rem-apply-ontextscale). |
|
|
1166
1167
|
|
|
1167
1168
|
`lookSensitivity` to `touchMovement` are the camera and controls settings: see
|
|
1168
1169
|
[camera and look controls](#camera-and-look-controls) for `gem.controls.look()`, which applies the
|
|
@@ -1242,6 +1243,96 @@ owns — starts from `recommended` the same way and is kept in `gem.me.settings`
|
|
|
1242
1243
|
([sound](#sound-your-own-mute-control-and-the-arcades)), and `reducedMotion` is the player's
|
|
1243
1244
|
accessibility setting, which your game honours.
|
|
1244
1245
|
|
|
1246
|
+
### The Arcade's Text size: size in `rem`, apply `onTextScale`
|
|
1247
|
+
|
|
1248
|
+
The player picks a **Text size** in the Arcade's Settings, per device: 100, 115, 130, 150, 180 or
|
|
1249
|
+
200%, or System, which follows the phone's own font size. The Arcade never enlarges your game's
|
|
1250
|
+
text for you — inside your frame, text renders at the size you chose — so a game that wants to
|
|
1251
|
+
honour it applies it, and applies it to **the whole interface**, not to text alone. Text that grows
|
|
1252
|
+
inside boxes that do not is exactly what breaks: labels overflow, overlap and clip.
|
|
1253
|
+
|
|
1254
|
+
**Pass `onTextScale` and set your root font size from it.** Passing the handler is what asks the
|
|
1255
|
+
Arcade for the value; a game without one is never sent it, and `gem.textScale` stays `null`:
|
|
1256
|
+
|
|
1257
|
+
```js
|
|
1258
|
+
const MAX = 150; // the largest size your layout supports: at least 130, ideally 150
|
|
1259
|
+
let chosen = null; // the size the player picked in YOUR settings, or null: "Arcade's size"
|
|
1260
|
+
|
|
1261
|
+
const applyTextSize = (p) => {
|
|
1262
|
+
document.documentElement.style.fontSize = (chosen ?? Math.min(p ?? 100, MAX)) + '%';
|
|
1263
|
+
};
|
|
1264
|
+
|
|
1265
|
+
const gem = createGem({ allowedEmbedders, onTextScale: applyTextSize });
|
|
1266
|
+
```
|
|
1267
|
+
|
|
1268
|
+
It is called on the first push — with `null` when the Arcade gave no advice — and again whenever
|
|
1269
|
+
the value changes. The player's own choice in your game beats the Arcade's, the Arcade's is clamped
|
|
1270
|
+
to what your layout supports, and with neither you render at 100%. The SDK applies nothing itself.
|
|
1271
|
+
|
|
1272
|
+
**This works only if your interface is sized in `rem`:**
|
|
1273
|
+
|
|
1274
|
+
- **Every length in your DOM UI is `rem`, `em` or `%`, never `px`:** font sizes, padding, gaps,
|
|
1275
|
+
widths, heights, radii and borders. Then the root font size scales them all together.
|
|
1276
|
+
- **Leave the root alone.** The root font size is the browser's default (`100%`), set only by the
|
|
1277
|
+
handler above. A `font` or `font-size` rule on `html` or `:root` breaks every `rem`: put your base
|
|
1278
|
+
font on `body` instead.
|
|
1279
|
+
- **Media queries stay in `px`**, and so do values you measure at runtime (positions, safe-area
|
|
1280
|
+
insets). A `rem` in a media query does not follow your root anyway.
|
|
1281
|
+
- **Panels that hold text are capped to the screen:** `width: min(22rem, 100% - 2rem)`, so a panel
|
|
1282
|
+
that grows never runs off a phone.
|
|
1283
|
+
- **Boxes that hold text grow with it:** `min-height` rather than `height`, and wrapping (or a
|
|
1284
|
+
fit-text routine whose floor you check) rather than `white-space: nowrap` with
|
|
1285
|
+
`overflow: hidden` or an ellipsis on an action label.
|
|
1286
|
+
- **Lay out against measured chrome, not constants.** Code that reserves room for a HUD bar or a
|
|
1287
|
+
gear button measures it (`getBoundingClientRect`, a `ResizeObserver`) instead of hard-coding
|
|
1288
|
+
pixels.
|
|
1289
|
+
- **Canvas text counts too.** A game that draws interface text on a canvas scales it from the same
|
|
1290
|
+
value.
|
|
1291
|
+
- **`text-size-adjust` is not a fix.** It does not protect your layout from any text scaling. Keep
|
|
1292
|
+
`100%` only as cheap protection against iOS's own inflation.
|
|
1293
|
+
|
|
1294
|
+
A board or playfield sized from the viewport (a `1/390` unit, say) may keep that unit: it follows
|
|
1295
|
+
the screen, which is right for the playfield. Menus, the HUD, settings and dialogs use `rem`.
|
|
1296
|
+
|
|
1297
|
+
**Support at least 130%,** with 150% the target and 200% for a game that is mostly text. Check every
|
|
1298
|
+
screen at 100%, 130% and your maximum on a phone held upright (390×844), a phone held sideways
|
|
1299
|
+
(844×390) and a desktop (1280×800), in your longest language: nothing clipped, overlapping or off
|
|
1300
|
+
screen. A phone held sideways runs out of height first, so every screen must fit or scroll
|
|
1301
|
+
vertically at your maximum. Rendered text is at least **12 CSS px**, and at least **14 CSS px** for
|
|
1302
|
+
what the player must read to act (costs, instructions, buttons), at a 360 CSS px wide viewport.
|
|
1303
|
+
|
|
1304
|
+
**A text-size setting of your own** is kept per device, like the Arcade setting it overrides (in
|
|
1305
|
+
[device settings](#device-settings-what-this-device-remembers-about-your-game)): a size chosen on a
|
|
1306
|
+
phone should not follow the player to a television. Declare it as a `choice` with `icon: 'text'`
|
|
1307
|
+
whose **first option is the Arcade's size** — the `null` state, which a slider cannot express:
|
|
1308
|
+
|
|
1309
|
+
```js
|
|
1310
|
+
{
|
|
1311
|
+
id: 'text',
|
|
1312
|
+
label: t('Text size'),
|
|
1313
|
+
kind: 'choice',
|
|
1314
|
+
icon: 'text',
|
|
1315
|
+
value: chosen === null ? 'arcade' : String(chosen),
|
|
1316
|
+
options: [
|
|
1317
|
+
{ id: 'arcade', label: t("Arcade's size") },
|
|
1318
|
+
{ id: '100', label: '100%' },
|
|
1319
|
+
{ id: '130', label: '130%' },
|
|
1320
|
+
{ id: '150', label: '150%' },
|
|
1321
|
+
],
|
|
1322
|
+
}
|
|
1323
|
+
```
|
|
1324
|
+
|
|
1325
|
+
Your choice overrides the Arcade's **for your game only**; nothing you do changes the Arcade's
|
|
1326
|
+
setting.
|
|
1327
|
+
|
|
1328
|
+
**Two rules hold however your game uses it, because a text size hints at a player's eyesight:**
|
|
1329
|
+
|
|
1330
|
+
- **Never put a text size in analytics.** No event, dimension or measure carries `textScale`, your
|
|
1331
|
+
resolved size, or the value of a text-size change. Recording that the player opened your text
|
|
1332
|
+
settings, without the value, is fine.
|
|
1333
|
+
- **Save only the player's own choice.** Never store the Arcade's value as if the player had picked
|
|
1334
|
+
it, and a `null` choice stays `null`, so a later change to the Arcade setting still reaches them.
|
|
1335
|
+
|
|
1245
1336
|
### Mirror your settings into the Arcade's menu: `gem.settings`
|
|
1246
1337
|
|
|
1247
1338
|
Optional, and worth doing. The Arcade's Gem menu shows your game's own settings beside the
|
|
@@ -1304,8 +1395,24 @@ const declared = () => [
|
|
|
1304
1395
|
{ id: 'music', label: t('Music'), kind: 'toggle', value: music.on, icon: 'music' }, // the quick row's Music
|
|
1305
1396
|
{ id: 'sfx', label: t('Sound effects'), kind: 'toggle', value: sfx.on, icon: 'sfx' },
|
|
1306
1397
|
{ id: 'colors', label: t('Color help'), kind: 'toggle', value: colorHelp, icon: 'eye' }, // its Color
|
|
1307
|
-
{
|
|
1308
|
-
|
|
1398
|
+
{
|
|
1399
|
+
id: 'musicVolume',
|
|
1400
|
+
label: t('Music volume'),
|
|
1401
|
+
kind: 'slider',
|
|
1402
|
+
value: musicVolume,
|
|
1403
|
+
min: 0,
|
|
1404
|
+
max: 100,
|
|
1405
|
+
step: 5,
|
|
1406
|
+
},
|
|
1407
|
+
{
|
|
1408
|
+
id: 'speed',
|
|
1409
|
+
label: t('Game speed'),
|
|
1410
|
+
kind: 'slider',
|
|
1411
|
+
value: speed,
|
|
1412
|
+
min: 0.5,
|
|
1413
|
+
max: 2,
|
|
1414
|
+
step: 0.25,
|
|
1415
|
+
},
|
|
1309
1416
|
{
|
|
1310
1417
|
id: 'difficulty',
|
|
1311
1418
|
label: t('Difficulty'),
|
package/package.json
CHANGED
package/schema/bridge.v1.json
CHANGED
|
@@ -1007,6 +1007,10 @@
|
|
|
1007
1007
|
"2026-10-23): the SDK does NOT fill it. An older parent omits it and the",
|
|
1008
1008
|
"game reads `null`, \"no recommendation\", never false.",
|
|
1009
1009
|
"",
|
|
1010
|
+
"`textScale` IS OPTIONAL INSIDE IT AND NOT FILLED either (owner",
|
|
1011
|
+
"decision 2026-11-05), and a parent sends it only where the game",
|
|
1012
|
+
"advertised `textScale`; an absent one is no advice.",
|
|
1013
|
+
"",
|
|
1010
1014
|
"`muted`, `reducedMotion` and `showFrameStats` stay where they are, at",
|
|
1011
1015
|
"the top of this message, and keep their meaning: they are the Arcade's",
|
|
1012
1016
|
"own state the frame acts on, not a recommendation. The Arcade starts",
|
|
@@ -1127,6 +1131,42 @@
|
|
|
1127
1131
|
"reports `null` and the game keeps its own default. Unlike the",
|
|
1128
1132
|
"camera and controls fields there is no neutral value to invent."
|
|
1129
1133
|
]
|
|
1134
|
+
},
|
|
1135
|
+
"textScale": {
|
|
1136
|
+
"kind": "int",
|
|
1137
|
+
"min": 100,
|
|
1138
|
+
"max": 200,
|
|
1139
|
+
"optional": true,
|
|
1140
|
+
"$comment": [
|
|
1141
|
+
"The player's Arcade Text size for this device, as a percent (owner",
|
|
1142
|
+
"decision 2026-11-05): 100 is the size",
|
|
1143
|
+
"the game was designed at, 200 is twice that. A game sized in `rem`",
|
|
1144
|
+
"applies it by setting its ROOT font size, so its whole interface",
|
|
1145
|
+
"-- text, padding, boxes and icons -- scales together. The Arcade",
|
|
1146
|
+
"never applies it for a game: inside a game's frame, text renders at",
|
|
1147
|
+
"the size the game chose.",
|
|
1148
|
+
"",
|
|
1149
|
+
"A DEFAULT ONLY, like every field here: the player's own text size in",
|
|
1150
|
+
"the game wins, and a game clamps this to the largest size its layout",
|
|
1151
|
+
"supports. A game never saves it as the player's choice and never",
|
|
1152
|
+
"records it in analytics.",
|
|
1153
|
+
"",
|
|
1154
|
+
"BOUNDED 100..200 PERMANENTLY. Any integer in range is valid; a",
|
|
1155
|
+
"parent sends only the six sizes of the Arcade's own control (100,",
|
|
1156
|
+
"115, 130, 150, 180, 200 -- Android's font-scale ladder), its System",
|
|
1157
|
+
"choice resolved to one of them. Nothing below 100: games design to",
|
|
1158
|
+
"a 12 CSS px floor.",
|
|
1159
|
+
"",
|
|
1160
|
+
"SENT ONLY TO A FRAME THAT ADVERTISED `textScale`, which the SDK does",
|
|
1161
|
+
"when the game passes `onTextScale` to `createGem`. That limits which",
|
|
1162
|
+
"games receive the value; it is not a security control. A parent",
|
|
1163
|
+
"whose `recommended` would fail validation with this field in it",
|
|
1164
|
+
"sends `recommended` again without it, so a bad text size never costs",
|
|
1165
|
+
"a game its volume, Color help or graphics.",
|
|
1166
|
+
"",
|
|
1167
|
+
"ABSENT IS NO ADVICE. A parent built against an older SDK, or one",
|
|
1168
|
+
"that keeps no text size, omits it, and the SDK reports `null`."
|
|
1169
|
+
]
|
|
1130
1170
|
}
|
|
1131
1171
|
}
|
|
1132
1172
|
}
|