@indiegems/gem-web-sdk 16.1.0 → 16.2.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 +18 -0
- package/dist/function.d.ts +27 -3
- package/dist/game.d.ts +27 -3
- 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 +3 -3
- 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 +1 -0
- package/dist/sdk.d.ts +29 -3
- package/dist/server-api.d.ts +3 -0
- package/dist/server.d.ts +3 -0
- package/docs/api/api-reference-function.md +169 -5
- package/docs/api/api-reference-game.md +169 -5
- package/docs/api/api-reference-server.md +1 -1
- package/docs/api/reference.json +145 -17
- package/docs/changelog.md +18 -0
- package/docs/getting-started.md +1 -1
- package/docs/manifest.json +8 -8
- package/docs/saving-player-progress.md +171 -5
- package/docs/server-bundles.md +2 -2
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# The function surface — API reference
|
|
2
2
|
|
|
3
|
-
Generated from `@indiegems/gem-web-sdk/function` v16.
|
|
3
|
+
Generated from `@indiegems/gem-web-sdk/function` v16.2.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/function` exports exactly the symbols on this page and nothing else.
|
|
6
6
|
|
|
@@ -3200,9 +3200,11 @@ readonly etag: string
|
|
|
3200
3200
|
|
|
3201
3201
|
This save's version, which changes whenever the save does.
|
|
3202
3202
|
|
|
3203
|
-
NOT something to pass back on a write —
|
|
3204
|
-
|
|
3205
|
-
|
|
3203
|
+
NOT something to pass back on a write — the SDK remembers the version of
|
|
3204
|
+
each slot you last loaded or wrote and sends it for you, so a write that
|
|
3205
|
+
would replace a save you never saw is refused as `save_conflict`. This is
|
|
3206
|
+
how a game holding a copy tells whether the stored save is still the one
|
|
3207
|
+
it has.
|
|
3206
3208
|
|
|
3207
3209
|
<a id="saverecord-metadata"></a>
|
|
3208
3210
|
|
|
@@ -3295,7 +3297,7 @@ has already agreed to the write. Re-read before assuming what is stored.
|
|
|
3295
3297
|
## GemSaveError.reason
|
|
3296
3298
|
|
|
3297
3299
|
```ts
|
|
3298
|
-
readonly reason: "upload_failed" | "download_failed" | "save_timeout" | "save_malformed"
|
|
3300
|
+
readonly reason: "upload_failed" | "download_failed" | "save_timeout" | "save_malformed" | "save_conflict" | "load_failed"
|
|
3299
3301
|
```
|
|
3300
3302
|
|
|
3301
3303
|
Which part failed.
|
|
@@ -3305,15 +3307,31 @@ Which part failed.
|
|
|
3305
3307
|
- `save_timeout` — a hop did not finish in the time the call allows.
|
|
3306
3308
|
- `save_malformed` — the answer, or the stored payload, was not what it
|
|
3307
3309
|
claims to be.
|
|
3310
|
+
- `save_conflict` — a write was refused because the stored save changed
|
|
3311
|
+
since this game last loaded or wrote it: another device or tab saved
|
|
3312
|
+
in between. Nothing was written.
|
|
3313
|
+
- `load_failed` — a write was refused before anything was sent, because
|
|
3314
|
+
the last load of this slot failed, so what the write would replace is
|
|
3315
|
+
unknown — it could be the player's real progress.
|
|
3308
3316
|
|
|
3309
3317
|
`save_timeout`, and a one-off `upload_failed` or `download_failed`, are
|
|
3310
3318
|
worth one retry. `save_malformed` is not: the same bytes will fail the
|
|
3311
3319
|
same way.
|
|
3312
3320
|
|
|
3321
|
+
Neither is `save_conflict` or `load_failed`: resending the same write
|
|
3322
|
+
fails the same way. Load the slot again and decide what to write from
|
|
3323
|
+
what is stored — merge, or ask the player. Pass `overwrite: true` only to
|
|
3324
|
+
replace whatever is stored on purpose.
|
|
3325
|
+
|
|
3313
3326
|
An `upload_failed` that repeats on EVERY save, for every player, is not
|
|
3314
3327
|
transient either — it is a platform-side misconfiguration, and retrying
|
|
3315
3328
|
is a loop rather than a recovery. See the saves guide.
|
|
3316
3329
|
|
|
3330
|
+
A RATE LIMIT IS NOT ONE OF THESE. Refused for the rate on any leg — the
|
|
3331
|
+
platform, the upload, the download — a save or load rejects as
|
|
3332
|
+
`GemApiError` reason `rate_limited`, with `retryAfterSeconds` when a wait
|
|
3333
|
+
was named.
|
|
3334
|
+
|
|
3317
3335
|
<a id="putsaveoptions"></a>
|
|
3318
3336
|
|
|
3319
3337
|
## PutSaveOptions
|
|
@@ -3354,6 +3372,10 @@ Cancel the write.
|
|
|
3354
3372
|
A save is several hops, so a cancelled write can land after the platform
|
|
3355
3373
|
has already agreed to it. Re-read rather than assuming nothing was stored.
|
|
3356
3374
|
|
|
3375
|
+
A write that replaced earlier ones still waiting on its slot carries them,
|
|
3376
|
+
so cancelling it before it goes out cancels them too. Cancelling a write
|
|
3377
|
+
that a later one replaced rejects only this call; the later write goes on.
|
|
3378
|
+
|
|
3357
3379
|
<a id="putsaveoptions-timeoutms"></a>
|
|
3358
3380
|
|
|
3359
3381
|
## PutSaveOptions.timeoutMs
|
|
@@ -3376,6 +3398,68 @@ to do something about it.
|
|
|
3376
3398
|
It does not make a save faster. Three round trips plus the payload is what
|
|
3377
3399
|
a save costs; this only decides when to stop waiting.
|
|
3378
3400
|
|
|
3401
|
+
It counts from the call, so a write waiting for the one before it on the
|
|
3402
|
+
same slot spends it waiting. A rate limit whose wait it will not cover
|
|
3403
|
+
rejects at once as `GemApiError` reason `rate_limited`, not as
|
|
3404
|
+
`save_timeout`.
|
|
3405
|
+
|
|
3406
|
+
It stays this call's when a later write replaces this one: running out
|
|
3407
|
+
rejects only this call, and the later write goes on. The write that is
|
|
3408
|
+
sent runs on the newest call's `timeoutMs`, and running out of that rejects
|
|
3409
|
+
every call it carries.
|
|
3410
|
+
|
|
3411
|
+
<a id="putsaveoptions-teardown"></a>
|
|
3412
|
+
|
|
3413
|
+
## PutSaveOptions.teardown
|
|
3414
|
+
|
|
3415
|
+
```ts
|
|
3416
|
+
readonly teardown?: boolean
|
|
3417
|
+
```
|
|
3418
|
+
|
|
3419
|
+
This is the last write before the page goes away: send it without waiting
|
|
3420
|
+
for the spacing between writes to one slot.
|
|
3421
|
+
|
|
3422
|
+
Writes to one slot go out a few seconds apart, and a write made sooner
|
|
3423
|
+
waits its turn. Set this on the write you make from
|
|
3424
|
+
`GemTerminationNotice` or `pagehide`, with a `timeoutMs` inside the
|
|
3425
|
+
time you have.
|
|
3426
|
+
|
|
3427
|
+
IT STILL WAITS FOR A WRITE ALREADY IN FLIGHT to the same slot, and it
|
|
3428
|
+
still honours a rate-limit hold: when the hold outlasts `timeoutMs` the
|
|
3429
|
+
write rejects at once as `rate_limited`, and nothing is sent. Not for
|
|
3430
|
+
ordinary saves — the spacing is what keeps a save loop from spending the
|
|
3431
|
+
rate limit.
|
|
3432
|
+
|
|
3433
|
+
A later write that replaces this one while it waits keeps it: the write
|
|
3434
|
+
that goes out skips the spacing when any call it carries set `teardown`.
|
|
3435
|
+
Not across a player change: a call replaced after the signed-in player
|
|
3436
|
+
changed is refused as `save_conflict`, and its `teardown` goes with it.
|
|
3437
|
+
|
|
3438
|
+
<a id="putsaveoptions-overwrite"></a>
|
|
3439
|
+
|
|
3440
|
+
## PutSaveOptions.overwrite
|
|
3441
|
+
|
|
3442
|
+
```ts
|
|
3443
|
+
readonly overwrite?: boolean
|
|
3444
|
+
```
|
|
3445
|
+
|
|
3446
|
+
Write even if it replaces a save this game has not loaded.
|
|
3447
|
+
|
|
3448
|
+
Without it, a write to a slot whose last load FAILED is refused as
|
|
3449
|
+
`load_failed`, and a write is refused as `save_conflict` when the stored
|
|
3450
|
+
save changed since you last loaded or wrote it. Both refusals protect the
|
|
3451
|
+
player's real progress from a game that started from defaults.
|
|
3452
|
+
|
|
3453
|
+
Set it only when replacing whatever is stored is what you mean — a "new
|
|
3454
|
+
game" the player confirmed, or the player choosing this device's progress
|
|
3455
|
+
after a conflict. Never set it to get past a failed load.
|
|
3456
|
+
|
|
3457
|
+
A later write that replaces this one while it waits keeps it: the write
|
|
3458
|
+
that goes out overwrites when any call it carries set `overwrite`. A call
|
|
3459
|
+
that gives up first (its `signal` or `timeoutMs`) takes it back, and so
|
|
3460
|
+
does one replaced after the signed-in player changed: it is refused as
|
|
3461
|
+
`save_conflict`, so one player's "new game" never overwrites the next's.
|
|
3462
|
+
|
|
3379
3463
|
<a id="putbytesoptions"></a>
|
|
3380
3464
|
|
|
3381
3465
|
## PutBytesOptions
|
|
@@ -3419,6 +3503,10 @@ Cancel the write.
|
|
|
3419
3503
|
A save is several hops, so a cancelled write can land after the platform
|
|
3420
3504
|
has already agreed to it. Re-read rather than assuming nothing was stored.
|
|
3421
3505
|
|
|
3506
|
+
A write that replaced earlier ones still waiting on its slot carries them,
|
|
3507
|
+
so cancelling it before it goes out cancels them too. Cancelling a write
|
|
3508
|
+
that a later one replaced rejects only this call; the later write goes on.
|
|
3509
|
+
|
|
3422
3510
|
<a id="putbytesoptions-timeoutms"></a>
|
|
3423
3511
|
|
|
3424
3512
|
## PutBytesOptions.timeoutMs
|
|
@@ -3441,6 +3529,68 @@ to do something about it.
|
|
|
3441
3529
|
It does not make a save faster. Three round trips plus the payload is what
|
|
3442
3530
|
a save costs; this only decides when to stop waiting.
|
|
3443
3531
|
|
|
3532
|
+
It counts from the call, so a write waiting for the one before it on the
|
|
3533
|
+
same slot spends it waiting. A rate limit whose wait it will not cover
|
|
3534
|
+
rejects at once as `GemApiError` reason `rate_limited`, not as
|
|
3535
|
+
`save_timeout`.
|
|
3536
|
+
|
|
3537
|
+
It stays this call's when a later write replaces this one: running out
|
|
3538
|
+
rejects only this call, and the later write goes on. The write that is
|
|
3539
|
+
sent runs on the newest call's `timeoutMs`, and running out of that rejects
|
|
3540
|
+
every call it carries.
|
|
3541
|
+
|
|
3542
|
+
<a id="putbytesoptions-teardown"></a>
|
|
3543
|
+
|
|
3544
|
+
## PutBytesOptions.teardown
|
|
3545
|
+
|
|
3546
|
+
```ts
|
|
3547
|
+
readonly teardown?: boolean
|
|
3548
|
+
```
|
|
3549
|
+
|
|
3550
|
+
This is the last write before the page goes away: send it without waiting
|
|
3551
|
+
for the spacing between writes to one slot.
|
|
3552
|
+
|
|
3553
|
+
Writes to one slot go out a few seconds apart, and a write made sooner
|
|
3554
|
+
waits its turn. Set this on the write you make from
|
|
3555
|
+
`GemTerminationNotice` or `pagehide`, with a `timeoutMs` inside the
|
|
3556
|
+
time you have.
|
|
3557
|
+
|
|
3558
|
+
IT STILL WAITS FOR A WRITE ALREADY IN FLIGHT to the same slot, and it
|
|
3559
|
+
still honours a rate-limit hold: when the hold outlasts `timeoutMs` the
|
|
3560
|
+
write rejects at once as `rate_limited`, and nothing is sent. Not for
|
|
3561
|
+
ordinary saves — the spacing is what keeps a save loop from spending the
|
|
3562
|
+
rate limit.
|
|
3563
|
+
|
|
3564
|
+
A later write that replaces this one while it waits keeps it: the write
|
|
3565
|
+
that goes out skips the spacing when any call it carries set `teardown`.
|
|
3566
|
+
Not across a player change: a call replaced after the signed-in player
|
|
3567
|
+
changed is refused as `save_conflict`, and its `teardown` goes with it.
|
|
3568
|
+
|
|
3569
|
+
<a id="putbytesoptions-overwrite"></a>
|
|
3570
|
+
|
|
3571
|
+
## PutBytesOptions.overwrite
|
|
3572
|
+
|
|
3573
|
+
```ts
|
|
3574
|
+
readonly overwrite?: boolean
|
|
3575
|
+
```
|
|
3576
|
+
|
|
3577
|
+
Write even if it replaces a save this game has not loaded.
|
|
3578
|
+
|
|
3579
|
+
Without it, a write to a slot whose last load FAILED is refused as
|
|
3580
|
+
`load_failed`, and a write is refused as `save_conflict` when the stored
|
|
3581
|
+
save changed since you last loaded or wrote it. Both refusals protect the
|
|
3582
|
+
player's real progress from a game that started from defaults.
|
|
3583
|
+
|
|
3584
|
+
Set it only when replacing whatever is stored is what you mean — a "new
|
|
3585
|
+
game" the player confirmed, or the player choosing this device's progress
|
|
3586
|
+
after a conflict. Never set it to get past a failed load.
|
|
3587
|
+
|
|
3588
|
+
A later write that replaces this one while it waits keeps it: the write
|
|
3589
|
+
that goes out overwrites when any call it carries set `overwrite`. A call
|
|
3590
|
+
that gives up first (its `signal` or `timeoutMs`) takes it back, and so
|
|
3591
|
+
does one replaced after the signed-in player changed: it is refused as
|
|
3592
|
+
`save_conflict`, so one player's "new game" never overwrites the next's.
|
|
3593
|
+
|
|
3444
3594
|
<a id="putbytesoptions-contenttype"></a>
|
|
3445
3595
|
|
|
3446
3596
|
## PutBytesOptions.contentType
|
|
@@ -3483,6 +3633,20 @@ await gem.me.saves.put('slot1', { level: 7, checkpoint: 'bridge' });
|
|
|
3483
3633
|
const state = await gem.me.saves.get('slot1');
|
|
3484
3634
|
```
|
|
3485
3635
|
|
|
3636
|
+
LOAD BEFORE YOU SAVE. Each write carries the version of the slot your last
|
|
3637
|
+
load or write found, so a write that would replace a save this game has not
|
|
3638
|
+
seen — another device's, or the player's real progress after a load that
|
|
3639
|
+
failed — is refused as `save_conflict` or `load_failed` rather than stored.
|
|
3640
|
+
After a failed load, play on without saving and load again later; pass
|
|
3641
|
+
`overwrite: true` only when the player chose to start over.
|
|
3642
|
+
|
|
3643
|
+
ONE WRITE PER SLOT AT A TIME. A write made while another to the same slot is
|
|
3644
|
+
in flight waits for it, and a later one replaces it: the newest value is the
|
|
3645
|
+
one sent, and every caller it replaced resolves with it, keeping its own
|
|
3646
|
+
`signal`, `timeoutMs`, `teardown` and `overwrite`. Writes to one slot
|
|
3647
|
+
go out a few seconds apart (`teardown: true` skips that), and after a
|
|
3648
|
+
`rate_limited` answer none goes out until the wait it named is over.
|
|
3649
|
+
|
|
3486
3650
|
WHAT IS DELIBERATELY NOT HERE: no autosave timer, no save format, no
|
|
3487
3651
|
migration. Those are your game's, and a platform that guessed at them would
|
|
3488
3652
|
guess wrong.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# The browser surface — API reference
|
|
2
2
|
|
|
3
|
-
Generated from `@indiegems/gem-web-sdk/sdk` v16.
|
|
3
|
+
Generated from `@indiegems/gem-web-sdk/sdk` v16.2.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
|
|
|
@@ -2085,9 +2085,11 @@ readonly etag: string
|
|
|
2085
2085
|
|
|
2086
2086
|
This save's version, which changes whenever the save does.
|
|
2087
2087
|
|
|
2088
|
-
NOT something to pass back on a write —
|
|
2089
|
-
|
|
2090
|
-
|
|
2088
|
+
NOT something to pass back on a write — the SDK remembers the version of
|
|
2089
|
+
each slot you last loaded or wrote and sends it for you, so a write that
|
|
2090
|
+
would replace a save you never saw is refused as `save_conflict`. This is
|
|
2091
|
+
how a game holding a copy tells whether the stored save is still the one
|
|
2092
|
+
it has.
|
|
2091
2093
|
|
|
2092
2094
|
<a id="saverecord-metadata"></a>
|
|
2093
2095
|
|
|
@@ -2180,7 +2182,7 @@ has already agreed to the write. Re-read before assuming what is stored.
|
|
|
2180
2182
|
## GemSaveError.reason
|
|
2181
2183
|
|
|
2182
2184
|
```ts
|
|
2183
|
-
readonly reason: "upload_failed" | "download_failed" | "save_timeout" | "save_malformed"
|
|
2185
|
+
readonly reason: "upload_failed" | "download_failed" | "save_timeout" | "save_malformed" | "save_conflict" | "load_failed"
|
|
2184
2186
|
```
|
|
2185
2187
|
|
|
2186
2188
|
Which part failed.
|
|
@@ -2190,15 +2192,31 @@ Which part failed.
|
|
|
2190
2192
|
- `save_timeout` — a hop did not finish in the time the call allows.
|
|
2191
2193
|
- `save_malformed` — the answer, or the stored payload, was not what it
|
|
2192
2194
|
claims to be.
|
|
2195
|
+
- `save_conflict` — a write was refused because the stored save changed
|
|
2196
|
+
since this game last loaded or wrote it: another device or tab saved
|
|
2197
|
+
in between. Nothing was written.
|
|
2198
|
+
- `load_failed` — a write was refused before anything was sent, because
|
|
2199
|
+
the last load of this slot failed, so what the write would replace is
|
|
2200
|
+
unknown — it could be the player's real progress.
|
|
2193
2201
|
|
|
2194
2202
|
`save_timeout`, and a one-off `upload_failed` or `download_failed`, are
|
|
2195
2203
|
worth one retry. `save_malformed` is not: the same bytes will fail the
|
|
2196
2204
|
same way.
|
|
2197
2205
|
|
|
2206
|
+
Neither is `save_conflict` or `load_failed`: resending the same write
|
|
2207
|
+
fails the same way. Load the slot again and decide what to write from
|
|
2208
|
+
what is stored — merge, or ask the player. Pass `overwrite: true` only to
|
|
2209
|
+
replace whatever is stored on purpose.
|
|
2210
|
+
|
|
2198
2211
|
An `upload_failed` that repeats on EVERY save, for every player, is not
|
|
2199
2212
|
transient either — it is a platform-side misconfiguration, and retrying
|
|
2200
2213
|
is a loop rather than a recovery. See the saves guide.
|
|
2201
2214
|
|
|
2215
|
+
A RATE LIMIT IS NOT ONE OF THESE. Refused for the rate on any leg — the
|
|
2216
|
+
platform, the upload, the download — a save or load rejects as
|
|
2217
|
+
`GemApiError` reason `rate_limited`, with `retryAfterSeconds` when a wait
|
|
2218
|
+
was named.
|
|
2219
|
+
|
|
2202
2220
|
<a id="putsaveoptions"></a>
|
|
2203
2221
|
|
|
2204
2222
|
## PutSaveOptions
|
|
@@ -2239,6 +2257,10 @@ Cancel the write.
|
|
|
2239
2257
|
A save is several hops, so a cancelled write can land after the platform
|
|
2240
2258
|
has already agreed to it. Re-read rather than assuming nothing was stored.
|
|
2241
2259
|
|
|
2260
|
+
A write that replaced earlier ones still waiting on its slot carries them,
|
|
2261
|
+
so cancelling it before it goes out cancels them too. Cancelling a write
|
|
2262
|
+
that a later one replaced rejects only this call; the later write goes on.
|
|
2263
|
+
|
|
2242
2264
|
<a id="putsaveoptions-timeoutms"></a>
|
|
2243
2265
|
|
|
2244
2266
|
## PutSaveOptions.timeoutMs
|
|
@@ -2261,6 +2283,68 @@ to do something about it.
|
|
|
2261
2283
|
It does not make a save faster. Three round trips plus the payload is what
|
|
2262
2284
|
a save costs; this only decides when to stop waiting.
|
|
2263
2285
|
|
|
2286
|
+
It counts from the call, so a write waiting for the one before it on the
|
|
2287
|
+
same slot spends it waiting. A rate limit whose wait it will not cover
|
|
2288
|
+
rejects at once as `GemApiError` reason `rate_limited`, not as
|
|
2289
|
+
`save_timeout`.
|
|
2290
|
+
|
|
2291
|
+
It stays this call's when a later write replaces this one: running out
|
|
2292
|
+
rejects only this call, and the later write goes on. The write that is
|
|
2293
|
+
sent runs on the newest call's `timeoutMs`, and running out of that rejects
|
|
2294
|
+
every call it carries.
|
|
2295
|
+
|
|
2296
|
+
<a id="putsaveoptions-teardown"></a>
|
|
2297
|
+
|
|
2298
|
+
## PutSaveOptions.teardown
|
|
2299
|
+
|
|
2300
|
+
```ts
|
|
2301
|
+
readonly teardown?: boolean
|
|
2302
|
+
```
|
|
2303
|
+
|
|
2304
|
+
This is the last write before the page goes away: send it without waiting
|
|
2305
|
+
for the spacing between writes to one slot.
|
|
2306
|
+
|
|
2307
|
+
Writes to one slot go out a few seconds apart, and a write made sooner
|
|
2308
|
+
waits its turn. Set this on the write you make from
|
|
2309
|
+
[GemTerminationNotice](#gemterminationnotice) or `pagehide`, with a `timeoutMs` inside the
|
|
2310
|
+
time you have.
|
|
2311
|
+
|
|
2312
|
+
IT STILL WAITS FOR A WRITE ALREADY IN FLIGHT to the same slot, and it
|
|
2313
|
+
still honours a rate-limit hold: when the hold outlasts `timeoutMs` the
|
|
2314
|
+
write rejects at once as `rate_limited`, and nothing is sent. Not for
|
|
2315
|
+
ordinary saves — the spacing is what keeps a save loop from spending the
|
|
2316
|
+
rate limit.
|
|
2317
|
+
|
|
2318
|
+
A later write that replaces this one while it waits keeps it: the write
|
|
2319
|
+
that goes out skips the spacing when any call it carries set `teardown`.
|
|
2320
|
+
Not across a player change: a call replaced after the signed-in player
|
|
2321
|
+
changed is refused as `save_conflict`, and its `teardown` goes with it.
|
|
2322
|
+
|
|
2323
|
+
<a id="putsaveoptions-overwrite"></a>
|
|
2324
|
+
|
|
2325
|
+
## PutSaveOptions.overwrite
|
|
2326
|
+
|
|
2327
|
+
```ts
|
|
2328
|
+
readonly overwrite?: boolean
|
|
2329
|
+
```
|
|
2330
|
+
|
|
2331
|
+
Write even if it replaces a save this game has not loaded.
|
|
2332
|
+
|
|
2333
|
+
Without it, a write to a slot whose last load FAILED is refused as
|
|
2334
|
+
`load_failed`, and a write is refused as `save_conflict` when the stored
|
|
2335
|
+
save changed since you last loaded or wrote it. Both refusals protect the
|
|
2336
|
+
player's real progress from a game that started from defaults.
|
|
2337
|
+
|
|
2338
|
+
Set it only when replacing whatever is stored is what you mean — a "new
|
|
2339
|
+
game" the player confirmed, or the player choosing this device's progress
|
|
2340
|
+
after a conflict. Never set it to get past a failed load.
|
|
2341
|
+
|
|
2342
|
+
A later write that replaces this one while it waits keeps it: the write
|
|
2343
|
+
that goes out overwrites when any call it carries set `overwrite`. A call
|
|
2344
|
+
that gives up first (its `signal` or `timeoutMs`) takes it back, and so
|
|
2345
|
+
does one replaced after the signed-in player changed: it is refused as
|
|
2346
|
+
`save_conflict`, so one player's "new game" never overwrites the next's.
|
|
2347
|
+
|
|
2264
2348
|
<a id="putbytesoptions"></a>
|
|
2265
2349
|
|
|
2266
2350
|
## PutBytesOptions
|
|
@@ -2304,6 +2388,10 @@ Cancel the write.
|
|
|
2304
2388
|
A save is several hops, so a cancelled write can land after the platform
|
|
2305
2389
|
has already agreed to it. Re-read rather than assuming nothing was stored.
|
|
2306
2390
|
|
|
2391
|
+
A write that replaced earlier ones still waiting on its slot carries them,
|
|
2392
|
+
so cancelling it before it goes out cancels them too. Cancelling a write
|
|
2393
|
+
that a later one replaced rejects only this call; the later write goes on.
|
|
2394
|
+
|
|
2307
2395
|
<a id="putbytesoptions-timeoutms"></a>
|
|
2308
2396
|
|
|
2309
2397
|
## PutBytesOptions.timeoutMs
|
|
@@ -2326,6 +2414,68 @@ to do something about it.
|
|
|
2326
2414
|
It does not make a save faster. Three round trips plus the payload is what
|
|
2327
2415
|
a save costs; this only decides when to stop waiting.
|
|
2328
2416
|
|
|
2417
|
+
It counts from the call, so a write waiting for the one before it on the
|
|
2418
|
+
same slot spends it waiting. A rate limit whose wait it will not cover
|
|
2419
|
+
rejects at once as `GemApiError` reason `rate_limited`, not as
|
|
2420
|
+
`save_timeout`.
|
|
2421
|
+
|
|
2422
|
+
It stays this call's when a later write replaces this one: running out
|
|
2423
|
+
rejects only this call, and the later write goes on. The write that is
|
|
2424
|
+
sent runs on the newest call's `timeoutMs`, and running out of that rejects
|
|
2425
|
+
every call it carries.
|
|
2426
|
+
|
|
2427
|
+
<a id="putbytesoptions-teardown"></a>
|
|
2428
|
+
|
|
2429
|
+
## PutBytesOptions.teardown
|
|
2430
|
+
|
|
2431
|
+
```ts
|
|
2432
|
+
readonly teardown?: boolean
|
|
2433
|
+
```
|
|
2434
|
+
|
|
2435
|
+
This is the last write before the page goes away: send it without waiting
|
|
2436
|
+
for the spacing between writes to one slot.
|
|
2437
|
+
|
|
2438
|
+
Writes to one slot go out a few seconds apart, and a write made sooner
|
|
2439
|
+
waits its turn. Set this on the write you make from
|
|
2440
|
+
[GemTerminationNotice](#gemterminationnotice) or `pagehide`, with a `timeoutMs` inside the
|
|
2441
|
+
time you have.
|
|
2442
|
+
|
|
2443
|
+
IT STILL WAITS FOR A WRITE ALREADY IN FLIGHT to the same slot, and it
|
|
2444
|
+
still honours a rate-limit hold: when the hold outlasts `timeoutMs` the
|
|
2445
|
+
write rejects at once as `rate_limited`, and nothing is sent. Not for
|
|
2446
|
+
ordinary saves — the spacing is what keeps a save loop from spending the
|
|
2447
|
+
rate limit.
|
|
2448
|
+
|
|
2449
|
+
A later write that replaces this one while it waits keeps it: the write
|
|
2450
|
+
that goes out skips the spacing when any call it carries set `teardown`.
|
|
2451
|
+
Not across a player change: a call replaced after the signed-in player
|
|
2452
|
+
changed is refused as `save_conflict`, and its `teardown` goes with it.
|
|
2453
|
+
|
|
2454
|
+
<a id="putbytesoptions-overwrite"></a>
|
|
2455
|
+
|
|
2456
|
+
## PutBytesOptions.overwrite
|
|
2457
|
+
|
|
2458
|
+
```ts
|
|
2459
|
+
readonly overwrite?: boolean
|
|
2460
|
+
```
|
|
2461
|
+
|
|
2462
|
+
Write even if it replaces a save this game has not loaded.
|
|
2463
|
+
|
|
2464
|
+
Without it, a write to a slot whose last load FAILED is refused as
|
|
2465
|
+
`load_failed`, and a write is refused as `save_conflict` when the stored
|
|
2466
|
+
save changed since you last loaded or wrote it. Both refusals protect the
|
|
2467
|
+
player's real progress from a game that started from defaults.
|
|
2468
|
+
|
|
2469
|
+
Set it only when replacing whatever is stored is what you mean — a "new
|
|
2470
|
+
game" the player confirmed, or the player choosing this device's progress
|
|
2471
|
+
after a conflict. Never set it to get past a failed load.
|
|
2472
|
+
|
|
2473
|
+
A later write that replaces this one while it waits keeps it: the write
|
|
2474
|
+
that goes out overwrites when any call it carries set `overwrite`. A call
|
|
2475
|
+
that gives up first (its `signal` or `timeoutMs`) takes it back, and so
|
|
2476
|
+
does one replaced after the signed-in player changed: it is refused as
|
|
2477
|
+
`save_conflict`, so one player's "new game" never overwrites the next's.
|
|
2478
|
+
|
|
2329
2479
|
<a id="putbytesoptions-contenttype"></a>
|
|
2330
2480
|
|
|
2331
2481
|
## PutBytesOptions.contentType
|
|
@@ -2368,6 +2518,20 @@ await gem.me.saves.put('slot1', { level: 7, checkpoint: 'bridge' });
|
|
|
2368
2518
|
const state = await gem.me.saves.get('slot1');
|
|
2369
2519
|
```
|
|
2370
2520
|
|
|
2521
|
+
LOAD BEFORE YOU SAVE. Each write carries the version of the slot your last
|
|
2522
|
+
load or write found, so a write that would replace a save this game has not
|
|
2523
|
+
seen — another device's, or the player's real progress after a load that
|
|
2524
|
+
failed — is refused as `save_conflict` or `load_failed` rather than stored.
|
|
2525
|
+
After a failed load, play on without saving and load again later; pass
|
|
2526
|
+
`overwrite: true` only when the player chose to start over.
|
|
2527
|
+
|
|
2528
|
+
ONE WRITE PER SLOT AT A TIME. A write made while another to the same slot is
|
|
2529
|
+
in flight waits for it, and a later one replaces it: the newest value is the
|
|
2530
|
+
one sent, and every caller it replaced resolves with it, keeping its own
|
|
2531
|
+
`signal`, `timeoutMs`, `teardown` and `overwrite`. Writes to one slot
|
|
2532
|
+
go out a few seconds apart (`teardown: true` skips that), and after a
|
|
2533
|
+
`rate_limited` answer none goes out until the wait it named is over.
|
|
2534
|
+
|
|
2371
2535
|
WHAT IS DELIBERATELY NOT HERE: no autosave timer, no save format, no
|
|
2372
2536
|
migration. Those are your game's, and a platform that guessed at them would
|
|
2373
2537
|
guess wrong.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# The server surface — API reference
|
|
2
2
|
|
|
3
|
-
Generated from `@indiegems/gem-web-sdk/sdk` v16.
|
|
3
|
+
Generated from `@indiegems/gem-web-sdk/sdk` v16.2.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
|
|
4
4
|
|
|
5
5
|
`@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/server` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
|
|
6
6
|
|