@crowdedkingdoms/crowdyjs 18.20.0 → 18.21.0-dev.1
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/README.md +22 -15
- package/dist/default-origin.d.ts +6 -6
- package/dist/default-origin.d.ts.map +1 -1
- package/dist/default-origin.js +6 -6
- package/dist/domains/udp.d.ts +16 -5
- package/dist/domains/udp.d.ts.map +1 -1
- package/dist/domains/udp.js +52 -12
- package/dist/generated/graphql-schema.d.ts +7 -7
- package/dist/generated/graphql-schema.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,19 +12,23 @@ gameplay, minted per app through `client.portal`.
|
|
|
12
12
|
|
|
13
13
|
Start here:
|
|
14
14
|
|
|
15
|
-
- [SDK guide](https://docs.crowdedkingdoms.com/crowdyjs/readme) — the canonical
|
|
15
|
+
- [SDK guide](https://docs.dev.crowdedkingdoms.com/crowdyjs/readme) — the canonical
|
|
16
16
|
walkthrough of everything in this README.
|
|
17
|
-
- [Build a game](https://docs.crowdedkingdoms.com/build-a-game/intro) — a
|
|
17
|
+
- [Build a game](https://docs.dev.crowdedkingdoms.com/build-a-game/intro) — a
|
|
18
18
|
hands-on tutorial from sign-in to a playable voxel game.
|
|
19
|
-
- [Platform overview](https://docs.crowdedkingdoms.com/overview/client-workflow)
|
|
19
|
+
- [Platform overview](https://docs.dev.crowdedkingdoms.com/overview/client-workflow)
|
|
20
20
|
— how a client session flows through the platform.
|
|
21
21
|
|
|
22
22
|
## Install
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
npm install @crowdedkingdoms/crowdyjs
|
|
25
|
+
npm install @crowdedkingdoms/crowdyjs@dev
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
This README is the `dev` branch's: it documents the release on the `dev` dist-tag
|
|
29
|
+
(`npm view @crowdedkingdoms/crowdyjs dist-tags`), and its links go to the dev docs site. A
|
|
30
|
+
plain `npm install` resolves `latest`, the production release, which has no `client.exec`.
|
|
31
|
+
|
|
28
32
|
**Server compatibility.** A release selects fields the Game API it was built against has,
|
|
29
33
|
so it needs that Game API or newer; promote the Game API before the SDK on each tier.
|
|
30
34
|
|
|
@@ -196,8 +200,8 @@ Notes:
|
|
|
196
200
|
- Use `client.auth.setToken(token)` to seed a token externally (e.g. when
|
|
197
201
|
restoring auth from a non-default storage).
|
|
198
202
|
|
|
199
|
-
Deeper reading: [Portals & app-scoped tokens](https://docs.crowdedkingdoms.com/management-api/portals-and-app-tokens)
|
|
200
|
-
and [Sign in](https://docs.crowdedkingdoms.com/management-api/authentication).
|
|
203
|
+
Deeper reading: [Portals & app-scoped tokens](https://docs.dev.crowdedkingdoms.com/management-api/portals-and-app-tokens)
|
|
204
|
+
and [Sign in](https://docs.dev.crowdedkingdoms.com/management-api/authentication).
|
|
201
205
|
|
|
202
206
|
### Org-managed players
|
|
203
207
|
|
|
@@ -394,7 +398,7 @@ query AppForRouting($appId: BigInt!) {
|
|
|
394
398
|
`CrowdyClient` with `httpUrl: gameApiUrl` (and the matching `wsUrl`) holding
|
|
395
399
|
that app's app-scoped token, then drive gameplay through that client. Apps
|
|
396
400
|
with no `gameApiUrl` keep working against the default `httpUrl` you
|
|
397
|
-
configured. See [Loading an app's Game API](https://docs.crowdedkingdoms.com/crowdyjs/shared-environment-routing).
|
|
401
|
+
configured. See [Loading an app's Game API](https://docs.dev.crowdedkingdoms.com/crowdyjs/shared-environment-routing).
|
|
398
402
|
|
|
399
403
|
## Realtime notifications
|
|
400
404
|
|
|
@@ -557,7 +561,10 @@ first awaited send of each session (the first connect, a reconnect, or a move to
|
|
|
557
561
|
another instance) is retried once with a fresh `sequenceNumber` if it is refused
|
|
558
562
|
`UNAUTHORIZED` or, for the actor and voxel updates the server echoes, if it times
|
|
559
563
|
out (`UDP_SEQUENCE_TIMEOUT`), which is how a realtime server older than v0.42.0
|
|
560
|
-
answers a session's first message.
|
|
564
|
+
answers a session's first message. An actor or voxel update still waiting when
|
|
565
|
+
the client reconnects or moves to another instance is resent as soon as the new
|
|
566
|
+
session is up, rather than at its timeout, since its echo went to the session it
|
|
567
|
+
left; that is its one retry. A send whose `sequenceNumber` you chose is
|
|
561
568
|
not retried, and an audio, text or event send's timeout (its normal success) is
|
|
562
569
|
never retried. `sendChannelMessage` broadcasts an opaque payload on a
|
|
563
570
|
channel. `sendRangedChannelMessage` publishes on a channel too, but only members
|
|
@@ -827,7 +834,7 @@ reach your bundle. Reads are synchronous snapshots and writes happen on
|
|
|
827
834
|
WebSocket events (not `requestAnimationFrame`), so render loops read freely
|
|
828
835
|
and a backgrounded tab keeps ingesting updates; pass `workerTicker()` to also
|
|
829
836
|
keep timer-driven sends at full rate while hidden. See the
|
|
830
|
-
[World Stores guide](https://docs.crowdedkingdoms.com/crowdyjs/stores).
|
|
837
|
+
[World Stores guide](https://docs.dev.crowdedkingdoms.com/crowdyjs/stores).
|
|
831
838
|
|
|
832
839
|
## Game Kit
|
|
833
840
|
|
|
@@ -905,7 +912,7 @@ The protocol is held to ck-exec's golden record of the starters
|
|
|
905
912
|
(`test/unit/fixtures/kit-protocol.json`): every module call and topic in it is replayed in
|
|
906
913
|
`test/unit/game-kit.test.mjs`. The blueprints, `kit.deploy`, the engines and the model-backed
|
|
907
914
|
helpers went with the game model in 18.0.0; the hub modules replace them. See the
|
|
908
|
-
[Game Kit docs](https://docs.crowdedkingdoms.com/game-kit/intro) and
|
|
915
|
+
[Game Kit docs](https://docs.dev.crowdedkingdoms.com/game-kit/intro) and
|
|
909
916
|
[MIGRATION.md](MIGRATION.md).
|
|
910
917
|
|
|
911
918
|
## ck-exec
|
|
@@ -969,7 +976,7 @@ Integers above 2^53 decode as `number` and lose precision unless you pass
|
|
|
969
976
|
`{ decode: { useBigInt64: true } }`. A call's whole numbers outside 32 bits (a timestamp in
|
|
970
977
|
milliseconds, a player id) go out as 64-bit integers (18.11.0; before, as floats, which a
|
|
971
978
|
hub's integer fields refuse). The wire format is in the
|
|
972
|
-
[ck-exec docs](https://docs.crowdedkingdoms.com/exec/intro).
|
|
979
|
+
[ck-exec docs](https://docs.dev.crowdedkingdoms.com/exec/intro).
|
|
973
980
|
|
|
974
981
|
### A mod's CLIENT half
|
|
975
982
|
|
|
@@ -1040,7 +1047,7 @@ counts what was dropped); `invoke` sends at most 256 KiB each way and is refused
|
|
|
1040
1047
|
module is not running. `NOT_FOUND` holds a CLIENT half back 15 s and `RATE_LIMITED` 60 s. The
|
|
1041
1048
|
grid's owner is asked about their own CLIENT halves like anyone; answer yes in `confirm` when
|
|
1042
1049
|
`prompt.authorId` is the player. See
|
|
1043
|
-
[CLIENT halves](https://docs.crowdedkingdoms.com/exec/client-halves).
|
|
1050
|
+
[CLIENT halves](https://docs.dev.crowdedkingdoms.com/exec/client-halves).
|
|
1044
1051
|
|
|
1045
1052
|
## Hosting a game on Crowdy Games
|
|
1046
1053
|
|
|
@@ -1159,8 +1166,8 @@ CLIENT project needs ck-api `v2.25.1` or later. A CLIENT crate still on the lega
|
|
|
1159
1166
|
`mountCrowdyStudio` and the controller take `mods: client.exec`. Crowdy Studio runs nothing
|
|
1160
1167
|
on legacy player compute since 18.0.0.
|
|
1161
1168
|
|
|
1162
|
-
See [CLIENT halves](https://docs.crowdedkingdoms.com/exec/client-halves), [mods](https://docs.crowdedkingdoms.com/exec/mods)
|
|
1163
|
-
and [Embed Crowdy Studio in your game](https://docs.crowdedkingdoms.com/crowdyjs/crowdy-studio-embed).
|
|
1169
|
+
See [CLIENT halves](https://docs.dev.crowdedkingdoms.com/exec/client-halves), [mods](https://docs.dev.crowdedkingdoms.com/exec/mods)
|
|
1170
|
+
and [Embed Crowdy Studio in your game](https://docs.dev.crowdedkingdoms.com/crowdyjs/crowdy-studio-embed).
|
|
1164
1171
|
|
|
1165
1172
|
### The Studio agent (DeepSeek Harness in the browser)
|
|
1166
1173
|
|
|
@@ -1351,7 +1358,7 @@ no other repositories and no network access required:
|
|
|
1351
1358
|
`src/generated/graphql-schema.ts`, the generated schema types.
|
|
1352
1359
|
|
|
1353
1360
|
Schema refresh is explicit, from the published
|
|
1354
|
-
[SDL](https://docs.crowdedkingdoms.com/schema/game-api.graphql):
|
|
1361
|
+
[SDL](https://docs.dev.crowdedkingdoms.com/schema/game-api.graphql):
|
|
1355
1362
|
|
|
1356
1363
|
```bash
|
|
1357
1364
|
npm run schema:sync:prod
|
package/dist/default-origin.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GENERATED — do not edit. The operator tooling's
|
|
3
|
-
* `sync-client-origins.mjs --write --tier
|
|
3
|
+
* `sync-client-origins.mjs --write --tier dev` writes this file, and
|
|
4
4
|
* `check-sdk-default-origin.mjs` refuses it when it names the wrong tier or a
|
|
5
5
|
* host that declaration does not carry. Regenerate; never hand-edit.
|
|
6
6
|
*
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
* than no default at all. Every fallback this SDK ever removed named a host that
|
|
11
11
|
* was already dead. A generated file plus a gate is what makes this one different.
|
|
12
12
|
*
|
|
13
|
-
* Source: the operator's per-tier public CK API origin declaration, tier '
|
|
13
|
+
* Source: the operator's per-tier public CK API origin declaration, tier 'dev'
|
|
14
14
|
*/
|
|
15
15
|
/** The tier this build of the SDK is published for. */
|
|
16
|
-
export declare const CROWDY_DEFAULT_TIER = "
|
|
16
|
+
export declare const CROWDY_DEFAULT_TIER = "dev";
|
|
17
17
|
/** The public CK API origin for that tier. */
|
|
18
|
-
export declare const CROWDY_DEFAULT_HTTP_ORIGIN = "https://ck.
|
|
18
|
+
export declare const CROWDY_DEFAULT_HTTP_ORIGIN = "https://ck.dev.crowdedkingdoms.com";
|
|
19
19
|
/** The same host over WebSocket. A scheme is composed; a hostname is looked up. */
|
|
20
|
-
export declare const CROWDY_DEFAULT_WS_ORIGIN = "wss://ck.
|
|
20
|
+
export declare const CROWDY_DEFAULT_WS_ORIGIN = "wss://ck.dev.crowdedkingdoms.com";
|
|
21
21
|
/** The bare hostname, for callers that need to compare rather than dial. */
|
|
22
|
-
export declare const CROWDY_DEFAULT_HOST = "ck.
|
|
22
|
+
export declare const CROWDY_DEFAULT_HOST = "ck.dev.crowdedkingdoms.com";
|
|
23
23
|
//# sourceMappingURL=default-origin.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-origin.d.ts","sourceRoot":"","sources":["../src/default-origin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,uDAAuD;AACvD,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"default-origin.d.ts","sourceRoot":"","sources":["../src/default-origin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,uDAAuD;AACvD,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC,8CAA8C;AAC9C,eAAO,MAAM,0BAA0B,uCAAuC,CAAC;AAE/E,mFAAmF;AACnF,eAAO,MAAM,wBAAwB,qCAAqC,CAAC;AAE3E,4EAA4E;AAC5E,eAAO,MAAM,mBAAmB,+BAA+B,CAAC"}
|
package/dist/default-origin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GENERATED — do not edit. The operator tooling's
|
|
3
|
-
* `sync-client-origins.mjs --write --tier
|
|
3
|
+
* `sync-client-origins.mjs --write --tier dev` writes this file, and
|
|
4
4
|
* `check-sdk-default-origin.mjs` refuses it when it names the wrong tier or a
|
|
5
5
|
* host that declaration does not carry. Regenerate; never hand-edit.
|
|
6
6
|
*
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
* than no default at all. Every fallback this SDK ever removed named a host that
|
|
11
11
|
* was already dead. A generated file plus a gate is what makes this one different.
|
|
12
12
|
*
|
|
13
|
-
* Source: the operator's per-tier public CK API origin declaration, tier '
|
|
13
|
+
* Source: the operator's per-tier public CK API origin declaration, tier 'dev'
|
|
14
14
|
*/
|
|
15
15
|
/** The tier this build of the SDK is published for. */
|
|
16
|
-
export const CROWDY_DEFAULT_TIER = '
|
|
16
|
+
export const CROWDY_DEFAULT_TIER = 'dev';
|
|
17
17
|
/** The public CK API origin for that tier. */
|
|
18
|
-
export const CROWDY_DEFAULT_HTTP_ORIGIN = 'https://ck.
|
|
18
|
+
export const CROWDY_DEFAULT_HTTP_ORIGIN = 'https://ck.dev.crowdedkingdoms.com';
|
|
19
19
|
/** The same host over WebSocket. A scheme is composed; a hostname is looked up. */
|
|
20
|
-
export const CROWDY_DEFAULT_WS_ORIGIN = 'wss://ck.
|
|
20
|
+
export const CROWDY_DEFAULT_WS_ORIGIN = 'wss://ck.dev.crowdedkingdoms.com';
|
|
21
21
|
/** The bare hostname, for callers that need to compare rather than dial. */
|
|
22
|
-
export const CROWDY_DEFAULT_HOST = 'ck.
|
|
22
|
+
export const CROWDY_DEFAULT_HOST = 'ck.dev.crowdedkingdoms.com';
|
package/dist/domains/udp.d.ts
CHANGED
|
@@ -38,8 +38,10 @@ import { type VideoCodec } from '../media/video-frames.js';
|
|
|
38
38
|
* loaded (realtime server v0.42.0 and later); an older server dropped or
|
|
39
39
|
* refused them. Against one, the SDK retries the first awaited send of each
|
|
40
40
|
* session once (see {@link sendActorUpdateAndWait}), but a plain `send*` may
|
|
41
|
-
* still be lost.
|
|
42
|
-
*
|
|
41
|
+
* still be lost. An awaited actor or voxel update still waiting when the client
|
|
42
|
+
* reconnects or moves to another instance is resent as soon as the new session
|
|
43
|
+
* is up. To receive any `...AndWait` echo or notification you must have an
|
|
44
|
+
* active {@link subscribe}.
|
|
43
45
|
*/
|
|
44
46
|
export declare class UdpAPI {
|
|
45
47
|
private gql;
|
|
@@ -176,6 +178,10 @@ export declare class UdpAPI {
|
|
|
176
178
|
* the resolved notification then carries the retry's sequence number. A
|
|
177
179
|
* send whose `sequenceNumber` you chose is not retried, and neither is the
|
|
178
180
|
* timeout of an audio, text or event send, which is how those succeed.
|
|
181
|
+
* - An actor or voxel update still waiting when the client reconnects or moves
|
|
182
|
+
* to another instance is resent, with a fresh sequence number, as soon as
|
|
183
|
+
* the new session is up, rather than at its timeout: its echo went to the
|
|
184
|
+
* session the client left. That is the send's one retry.
|
|
179
185
|
*
|
|
180
186
|
* @param options - `timeoutMs`: how long to wait for the echo once the send
|
|
181
187
|
* is accepted, in milliseconds; defaults to the client's realtime
|
|
@@ -622,9 +628,14 @@ export declare class UdpAPI {
|
|
|
622
628
|
* its echo times out: a game server from before the one that holds a
|
|
623
629
|
* session's first messages refuses or drops them while the session's
|
|
624
630
|
* permissions load. A send the server does not echo (audio, text, a client
|
|
625
|
-
* event) succeeds by timing out, so its timeout is never retried.
|
|
626
|
-
*
|
|
627
|
-
*
|
|
631
|
+
* event) succeeds by timing out, so its timeout is never retried.
|
|
632
|
+
*
|
|
633
|
+
* A send the server echoes that is still waiting when a new session is
|
|
634
|
+
* established is resent then, once, rather than at its timeout: its echo went
|
|
635
|
+
* to the session the client left. That retry is the send's one retry.
|
|
636
|
+
*
|
|
637
|
+
* Only when the SDK chose the sequence number, because a retry needs one of
|
|
638
|
+
* its own and a caller who chose theirs is correlating by it.
|
|
628
639
|
*/
|
|
629
640
|
private sendAndWait;
|
|
630
641
|
private sendOnceAndWait;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"udp.d.ts","sourceRoot":"","sources":["../../src/domains/udp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EACV,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAEL,KAAK,uBAAuB,EAG5B,KAAK,6BAA6B,EAElC,KAAK,gCAAgC,EAErC,KAAK,gCAAgC,EAErC,KAAK,gCAAgC,EAErC,KAAK,gCAAgC,EAErC,KAAK,+BAA+B,EAEpC,KAAK,gCAAgC,EAErC,KAAK,uCAAuC,EAE5C,KAAK,mCAAmC,EAExC,KAAK,iCAAiC,EAEtC,KAAK,yCAAyC,EAC/C,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAkB1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAG1E
|
|
1
|
+
{"version":3,"file":"udp.d.ts","sourceRoot":"","sources":["../../src/domains/udp.ts"],"names":[],"mappings":"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"}
|
package/dist/domains/udp.js
CHANGED
|
@@ -38,8 +38,10 @@ import { encodeBase64 } from '../utils.js';
|
|
|
38
38
|
* loaded (realtime server v0.42.0 and later); an older server dropped or
|
|
39
39
|
* refused them. Against one, the SDK retries the first awaited send of each
|
|
40
40
|
* session once (see {@link sendActorUpdateAndWait}), but a plain `send*` may
|
|
41
|
-
* still be lost.
|
|
42
|
-
*
|
|
41
|
+
* still be lost. An awaited actor or voxel update still waiting when the client
|
|
42
|
+
* reconnects or moves to another instance is resent as soon as the new session
|
|
43
|
+
* is up. To receive any `...AndWait` echo or notification you must have an
|
|
44
|
+
* active {@link subscribe}.
|
|
43
45
|
*/
|
|
44
46
|
export class UdpAPI {
|
|
45
47
|
constructor(gql, subs, metrics,
|
|
@@ -278,6 +280,10 @@ export class UdpAPI {
|
|
|
278
280
|
* the resolved notification then carries the retry's sequence number. A
|
|
279
281
|
* send whose `sequenceNumber` you chose is not retried, and neither is the
|
|
280
282
|
* timeout of an audio, text or event send, which is how those succeed.
|
|
283
|
+
* - An actor or voxel update still waiting when the client reconnects or moves
|
|
284
|
+
* to another instance is resent, with a fresh sequence number, as soon as
|
|
285
|
+
* the new session is up, rather than at its timeout: its echo went to the
|
|
286
|
+
* session the client left. That is the send's one retry.
|
|
281
287
|
*
|
|
282
288
|
* @param options - `timeoutMs`: how long to wait for the echo once the send
|
|
283
289
|
* is accepted, in milliseconds; defaults to the client's realtime
|
|
@@ -828,31 +834,45 @@ export class UdpAPI {
|
|
|
828
834
|
* its echo times out: a game server from before the one that holds a
|
|
829
835
|
* session's first messages refuses or drops them while the session's
|
|
830
836
|
* permissions load. A send the server does not echo (audio, text, a client
|
|
831
|
-
* event) succeeds by timing out, so its timeout is never retried.
|
|
832
|
-
*
|
|
833
|
-
*
|
|
837
|
+
* event) succeeds by timing out, so its timeout is never retried.
|
|
838
|
+
*
|
|
839
|
+
* A send the server echoes that is still waiting when a new session is
|
|
840
|
+
* established is resent then, once, rather than at its timeout: its echo went
|
|
841
|
+
* to the session the client left. That retry is the send's one retry.
|
|
842
|
+
*
|
|
843
|
+
* Only when the SDK chose the sequence number, because a retry needs one of
|
|
844
|
+
* its own and a caller who chose theirs is correlating by it.
|
|
834
845
|
*/
|
|
835
846
|
async sendAndWait(input, timeoutMs, echoed, send) {
|
|
836
847
|
const epoch = this.subs.sessionEpoch();
|
|
837
|
-
const
|
|
848
|
+
const ownSequence = input.sequenceNumber == null;
|
|
849
|
+
const retryable = epoch !== this.confirmedEpoch && ownSequence;
|
|
850
|
+
// The session the answered attempt went to.
|
|
851
|
+
let sentEpoch = epoch;
|
|
852
|
+
const again = () => {
|
|
853
|
+
sentEpoch = this.subs.sessionEpoch();
|
|
854
|
+
return this.sendOnceAndWait(this.withSequence({ ...input, sequenceNumber: undefined }), timeoutMs, send, false);
|
|
855
|
+
};
|
|
838
856
|
try {
|
|
839
|
-
const echo = await this.sendOnceAndWait(this.withSequence(input), timeoutMs, send).catch((error) => {
|
|
857
|
+
const echo = await this.sendOnceAndWait(this.withSequence(input), timeoutMs, send, echoed && ownSequence).catch((error) => {
|
|
858
|
+
if (error instanceof SessionChanged)
|
|
859
|
+
return again();
|
|
840
860
|
if (!retryable || !isFirstSendFailure(error, echoed))
|
|
841
861
|
throw error;
|
|
842
|
-
return
|
|
862
|
+
return again();
|
|
843
863
|
});
|
|
844
|
-
this.confirmedEpoch =
|
|
864
|
+
this.confirmedEpoch = sentEpoch;
|
|
845
865
|
return echo;
|
|
846
866
|
}
|
|
847
867
|
catch (error) {
|
|
848
868
|
// A send the server does not echo succeeds by timing out, and that
|
|
849
869
|
// answers for the session as well as an echo would.
|
|
850
870
|
if (!echoed && isTimeout(error))
|
|
851
|
-
this.confirmedEpoch =
|
|
871
|
+
this.confirmedEpoch = sentEpoch;
|
|
852
872
|
throw error;
|
|
853
873
|
}
|
|
854
874
|
}
|
|
855
|
-
async sendOnceAndWait(request, timeoutMs, send) {
|
|
875
|
+
async sendOnceAndWait(request, timeoutMs, send, endOnNewSession) {
|
|
856
876
|
const wait = this.subs.expectSequence(request.sequenceNumber, timeoutMs);
|
|
857
877
|
try {
|
|
858
878
|
await send(request);
|
|
@@ -865,7 +885,24 @@ export class UdpAPI {
|
|
|
865
885
|
// send for up to bundleWindowMs, so put it on the wire before waiting.
|
|
866
886
|
this.subs.flushSends();
|
|
867
887
|
wait.start();
|
|
868
|
-
|
|
888
|
+
if (!endOnNewSession)
|
|
889
|
+
return wait.promise;
|
|
890
|
+
// A session established while this waits (a reconnect, or the new instance
|
|
891
|
+
// after a move) will not carry the echo, which went to the session the
|
|
892
|
+
// client left: end the wait then rather than at its timeout. onStatus
|
|
893
|
+
// reports the current status at once; only a later `connected` counts.
|
|
894
|
+
const epoch = this.subs.sessionEpoch();
|
|
895
|
+
let stop = () => undefined;
|
|
896
|
+
const changed = new Promise((_, reject) => {
|
|
897
|
+
stop = this.subs.onStatus((status) => {
|
|
898
|
+
if (status !== 'connected' || this.subs.sessionEpoch() === epoch)
|
|
899
|
+
return;
|
|
900
|
+
wait.cancel();
|
|
901
|
+
reject(new SessionChanged());
|
|
902
|
+
});
|
|
903
|
+
});
|
|
904
|
+
changed.catch(() => undefined);
|
|
905
|
+
return Promise.race([wait.promise, changed]).finally(() => stop());
|
|
869
906
|
}
|
|
870
907
|
withSequence(input) {
|
|
871
908
|
return {
|
|
@@ -874,6 +911,9 @@ export class UdpAPI {
|
|
|
874
911
|
};
|
|
875
912
|
}
|
|
876
913
|
}
|
|
914
|
+
/** A new realtime session was established while an echoed send waited. */
|
|
915
|
+
class SessionChanged extends Error {
|
|
916
|
+
}
|
|
877
917
|
/** How a session's first message failed on a game server that did not hold it. */
|
|
878
918
|
function isFirstSendFailure(error, echoed) {
|
|
879
919
|
return (error instanceof CrowdyRealtimeError &&
|
|
@@ -4609,7 +4609,7 @@ export type ManagedPlayer = {
|
|
|
4609
4609
|
export type ManagedPlayerSpecInput = {
|
|
4610
4610
|
/** The id your organization knows the player by. */
|
|
4611
4611
|
externalId: Scalars['String']['input'];
|
|
4612
|
-
/** Display name (at most 64 characters). */
|
|
4612
|
+
/** Display name (at most 64 characters, none of them control, line-break or bidirectional-formatting characters). */
|
|
4613
4613
|
gamertag?: InputMaybe<Scalars['String']['input']>;
|
|
4614
4614
|
};
|
|
4615
4615
|
/** One page of an org’s managed players, by user id. */
|
|
@@ -4638,7 +4638,7 @@ export type MintManagedPlayerTokenInput = {
|
|
|
4638
4638
|
appId: Scalars['BigInt']['input'];
|
|
4639
4639
|
/** The id your organization knows the player by (1-256 characters, no control characters). Use your own stable account id, not an email address. The first sign-in creates the player. */
|
|
4640
4640
|
externalId: Scalars['String']['input'];
|
|
4641
|
-
/** Display name (at most 64 characters). Set when the player is created; later sign-ins leave it (rename with updateManagedPlayer). */
|
|
4641
|
+
/** Display name (at most 64 characters, none of them control, line-break or bidirectional-formatting characters). Set when the player is created; later sign-ins leave it (rename with updateManagedPlayer). */
|
|
4642
4642
|
gamertag?: InputMaybe<Scalars['String']['input']>;
|
|
4643
4643
|
/** How long this sign-in lasts, in seconds (default and maximum: the org's settings). The app token refreshes (refreshAppToken) until then; after it, sign the player in again. */
|
|
4644
4644
|
sessionTtlSeconds?: InputMaybe<Scalars['Int']['input']>;
|
|
@@ -8003,7 +8003,7 @@ export type RegisterUserInput = {
|
|
|
8003
8003
|
attestAgeOfMajority?: InputMaybe<Scalars['Boolean']['input']>;
|
|
8004
8004
|
/** Email for the new account; the confirmation email is sent here. */
|
|
8005
8005
|
email: Scalars['String']['input'];
|
|
8006
|
-
/** Optional initial public gamertag (
|
|
8006
|
+
/** Optional initial public gamertag (3 to 64 characters, none of them control, line-break or bidirectional-formatting characters). Can be set later via updateGamertag. */
|
|
8007
8007
|
gamertag?: InputMaybe<Scalars['String']['input']>;
|
|
8008
8008
|
/** Password for the new account (min 8 characters). */
|
|
8009
8009
|
password: Scalars['String']['input'];
|
|
@@ -9088,9 +9088,9 @@ export type UpdateChunkStateInput = {
|
|
|
9088
9088
|
coordinates: ChunkCoordinatesInput;
|
|
9089
9089
|
};
|
|
9090
9090
|
export type UpdateGamertagInput = {
|
|
9091
|
-
/** Discriminator paired with `gamertag` (max 128 characters) to form a unique handle. */
|
|
9091
|
+
/** Discriminator paired with `gamertag` (max 128 characters, the same characters refused as in `gamertag`) to form a unique handle. */
|
|
9092
9092
|
disambiguation: Scalars['String']['input'];
|
|
9093
|
-
/** New gamertag (max 64 characters). Must be unique in combination with `disambiguation`. */
|
|
9093
|
+
/** New gamertag (max 64 characters, none of them control, line-break or bidirectional-formatting characters). Must be unique in combination with `disambiguation`. */
|
|
9094
9094
|
gamertag: Scalars['String']['input'];
|
|
9095
9095
|
};
|
|
9096
9096
|
/** Update a custom group role. Omitted fields are left unchanged. */
|
|
@@ -9107,10 +9107,10 @@ export type UpdateGroupRoleInput = {
|
|
|
9107
9107
|
export type UpdateManagedPlayerInput = {
|
|
9108
9108
|
/** True disables the player (no sign-in; every session ends now, Buddy and ck-exec included). False enables a player the org disabled. */
|
|
9109
9109
|
disabled?: InputMaybe<Scalars['Boolean']['input']>;
|
|
9110
|
-
/** New disambiguation (at most 128 characters). */
|
|
9110
|
+
/** New disambiguation (at most 128 characters, the same characters refused as in the display name). */
|
|
9111
9111
|
disambiguation?: InputMaybe<Scalars['String']['input']>;
|
|
9112
9112
|
externalId: Scalars['String']['input'];
|
|
9113
|
-
/** New display name. */
|
|
9113
|
+
/** New display name (at most 64 characters, none of them control, line-break or bidirectional-formatting characters). */
|
|
9114
9114
|
gamertag?: InputMaybe<Scalars['String']['input']>;
|
|
9115
9115
|
orgId: Scalars['BigInt']['input'];
|
|
9116
9116
|
};
|