@crowdedkingdomstudios/crowdyjs 5.1.0 → 5.2.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/MIGRATION.md +64 -0
- package/README.md +19 -0
- package/dist/client.d.ts +98 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +74 -5
- package/dist/crowdy-client.d.ts +31 -0
- package/dist/crowdy-client.d.ts.map +1 -1
- package/dist/crowdy-client.js +8 -0
- package/dist/domains/actors.d.ts +88 -5
- package/dist/domains/actors.d.ts.map +1 -1
- package/dist/domains/actors.js +89 -6
- package/dist/domains/apps.d.ts +95 -41
- package/dist/domains/apps.d.ts.map +1 -1
- package/dist/domains/apps.js +80 -33
- package/dist/domains/auth.d.ts +139 -19
- package/dist/domains/auth.d.ts.map +1 -1
- package/dist/domains/auth.js +137 -17
- package/dist/domains/channels.d.ts +264 -5
- package/dist/domains/channels.d.ts.map +1 -1
- package/dist/domains/channels.js +264 -5
- package/dist/domains/chunks.d.ts +116 -3
- package/dist/domains/chunks.d.ts.map +1 -1
- package/dist/domains/chunks.js +116 -3
- package/dist/domains/gameModel.d.ts +412 -6
- package/dist/domains/gameModel.d.ts.map +1 -1
- package/dist/domains/gameModel.js +412 -6
- package/dist/domains/platform.d.ts +36 -20
- package/dist/domains/platform.d.ts.map +1 -1
- package/dist/domains/platform.js +29 -18
- package/dist/domains/serverStatus.d.ts +74 -6
- package/dist/domains/serverStatus.d.ts.map +1 -1
- package/dist/domains/serverStatus.js +74 -6
- package/dist/domains/state.d.ts +50 -2
- package/dist/domains/state.d.ts.map +1 -1
- package/dist/domains/state.js +50 -2
- package/dist/domains/teams.d.ts +265 -7
- package/dist/domains/teams.d.ts.map +1 -1
- package/dist/domains/teams.js +267 -9
- package/dist/domains/teleport.d.ts +30 -2
- package/dist/domains/teleport.d.ts.map +1 -1
- package/dist/domains/teleport.js +30 -2
- package/dist/domains/udp.d.ts +341 -5
- package/dist/domains/udp.d.ts.map +1 -1
- package/dist/domains/udp.js +341 -5
- package/dist/domains/users.d.ts +42 -11
- package/dist/domains/users.d.ts.map +1 -1
- package/dist/domains/users.js +41 -10
- package/dist/domains/voxels.d.ts +107 -2
- package/dist/domains/voxels.d.ts.map +1 -1
- package/dist/domains/voxels.js +107 -2
- package/dist/errors.d.ts +116 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +100 -0
- package/dist/generated/graphql.d.ts +1787 -110
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/generated/graphql.js +75 -9
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/realtime.d.ts +226 -0
- package/dist/realtime.d.ts.map +1 -1
- package/dist/realtime.js +90 -0
- package/dist/session.d.ts +46 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +35 -0
- package/dist/types.d.ts +429 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +53 -0
- package/dist/utils.d.ts +86 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +86 -0
- package/dist/world.d.ts +192 -0
- package/dist/world.d.ts.map +1 -1
- package/dist/world.js +170 -0
- package/package.json +1 -1
package/dist/world.js
CHANGED
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
import { generateCrowdyUuid, validateChunkCoordinates, validateCrowdyUuid } from './utils.js';
|
|
2
|
+
/**
|
|
3
|
+
* Ergonomic, **app-scoped** realtime facade returned by `client.world(appId)`.
|
|
4
|
+
* Wraps {@link UdpAPI}, passing `appId` for you on every spatial send and
|
|
5
|
+
* subscription so you never repeat it — the recommended entry point for game
|
|
6
|
+
* loops; the lower-level `client.udp` remains available. Requires the same
|
|
7
|
+
* authenticated bearer game token as `client.udp`.
|
|
8
|
+
*/
|
|
2
9
|
export class WorldClient {
|
|
3
10
|
constructor(appId, udp) {
|
|
4
11
|
this.appId = appId;
|
|
5
12
|
this.udp = udp;
|
|
6
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Create an {@link ActorClient} bound to this app. The actor tracks its
|
|
16
|
+
* current chunk after {@link ActorClient.join} (so later sends don't repeat
|
|
17
|
+
* the chunk) and allocates `sequenceNumber`s for its `...AndWait` calls.
|
|
18
|
+
*
|
|
19
|
+
* @param options - {@link ActorOptions}. If `uuid` is omitted a fresh
|
|
20
|
+
* 32-character id is generated; `defaultDistance` / `defaultDecayRate`
|
|
21
|
+
* become this actor's per-call defaults for {@link ActorClient.sendState}.
|
|
22
|
+
* @returns A new {@link ActorClient}.
|
|
23
|
+
* @throws {CrowdyProtocolError} if a supplied `uuid` is not exactly 32 bytes
|
|
24
|
+
* when UTF-8 encoded.
|
|
25
|
+
*/
|
|
7
26
|
actor(options = {}) {
|
|
8
27
|
return new ActorClient(this.appId, this.udp, {
|
|
9
28
|
uuid: options.uuid ?? generateCrowdyUuid(),
|
|
@@ -11,10 +30,30 @@ export class WorldClient {
|
|
|
11
30
|
defaultDecayRate: options.defaultDecayRate,
|
|
12
31
|
});
|
|
13
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Open an app-scoped subscription, passing this world's `appId` to
|
|
35
|
+
* {@link UdpAPI.subscribe} for you. The first subscriber opens the shared
|
|
36
|
+
* WebSocket; the last to unsubscribe closes it.
|
|
37
|
+
*
|
|
38
|
+
* @param handlers - {@link UdpNotificationHandlers} (see {@link UdpAPI.subscribe}).
|
|
39
|
+
* @returns An unsubscribe function that detaches these handlers (and closes
|
|
40
|
+
* the shared WebSocket if it was the last subscription).
|
|
41
|
+
* @throws {CrowdyRealtimeError} `code === 'AUTH_REQUIRED'` if there is no
|
|
42
|
+
* session token.
|
|
43
|
+
*/
|
|
14
44
|
subscribe(handlers) {
|
|
15
45
|
return this.udp.subscribe(handlers, String(this.appId));
|
|
16
46
|
}
|
|
17
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* A single actor (player / NPC) in one app's realtime world, created via
|
|
50
|
+
* `client.world(appId).actor(...)`. Holds a stable 32-character {@link uuid}
|
|
51
|
+
* and remembers the actor's current chunk after {@link join}, so the spatial
|
|
52
|
+
* helpers ({@link sendState}, {@link sendVoxelUpdate}, {@link sendText},
|
|
53
|
+
* {@link sendEvent}) don't need the chunk repeated. Those helpers use the UDP
|
|
54
|
+
* `...AndWait` path and resolve with the correlated echo/notification, so they
|
|
55
|
+
* require an active subscription (e.g. {@link WorldClient.subscribe}).
|
|
56
|
+
*/
|
|
18
57
|
export class ActorClient {
|
|
19
58
|
constructor(appId, udp, options) {
|
|
20
59
|
this.appId = appId;
|
|
@@ -24,10 +63,55 @@ export class ActorClient {
|
|
|
24
63
|
validateCrowdyUuid(options.uuid);
|
|
25
64
|
this.uuid = options.uuid;
|
|
26
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Enter a chunk: records it as this actor's current chunk and sends an
|
|
68
|
+
* initial actor update to register presence there. Resolves with the server's
|
|
69
|
+
* applied `ActorUpdateResponse` echo.
|
|
70
|
+
*
|
|
71
|
+
* The **first** spatial message to a brand-new chunk may be dropped
|
|
72
|
+
* server-side while grid permissions load, so if this rejects with a timeout,
|
|
73
|
+
* simply call `join` again (the two-client tests register twice).
|
|
74
|
+
*
|
|
75
|
+
* @param chunk - The chunk to enter, `{ x, y, z }` with each axis a signed
|
|
76
|
+
* int64 decimal string. A chunk is a 16x16x16 voxel cube.
|
|
77
|
+
* @param state - Initial actor state blob, base64-encoded. Defaults to `'AA=='`
|
|
78
|
+
* (a single zero byte), i.e. registration-only.
|
|
79
|
+
* @returns The correlated {@link SpatialNotification} (`ActorUpdateResponse`).
|
|
80
|
+
* @throws {CrowdyProtocolError} if `chunk` is outside signed int64 range.
|
|
81
|
+
* @throws {CrowdyGraphQLError} if the underlying send is rejected.
|
|
82
|
+
* @throws {CrowdyTimeoutError} if the HTTP send leg times out.
|
|
83
|
+
* @throws {CrowdyRealtimeError} if no echo arrives within the timeout
|
|
84
|
+
* (`code === 'UDP_SEQUENCE_TIMEOUT'`) or the server returns a matching
|
|
85
|
+
* `GenericErrorResponse`.
|
|
86
|
+
*/
|
|
27
87
|
async join(chunk, state = 'AA==') {
|
|
28
88
|
this.chunk = chunk;
|
|
29
89
|
return this.sendState(state, { chunk });
|
|
30
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Send a state update for this actor to its current chunk (set by
|
|
93
|
+
* {@link join}) or to `options.chunk` if provided. Uses the UDP `...AndWait`
|
|
94
|
+
* path and resolves with the applied `ActorUpdateResponse` echo. `appId` and
|
|
95
|
+
* `uuid` are filled in for you.
|
|
96
|
+
*
|
|
97
|
+
* @param state - Actor state blob, base64-encoded (may be `''` for a
|
|
98
|
+
* registration-only update).
|
|
99
|
+
* @param options - Optional overrides:
|
|
100
|
+
* - `chunk` — `{ x, y, z }` (signed int64 decimal strings) to send to
|
|
101
|
+
* instead of the tracked chunk.
|
|
102
|
+
* - `distance` — replication radius in chunk units, 0-8; defaults to the
|
|
103
|
+
* actor's `defaultDistance`.
|
|
104
|
+
* - `decayRate` — decay algorithm 0-5; defaults to the actor's
|
|
105
|
+
* `defaultDecayRate`.
|
|
106
|
+
* @returns The correlated {@link SpatialNotification} (`ActorUpdateResponse`).
|
|
107
|
+
* @throws {Error} `'Actor must join a chunk before sending state'` if no chunk
|
|
108
|
+
* has been joined and none is supplied.
|
|
109
|
+
* @throws {CrowdyProtocolError} if the resolved chunk is outside int64 range.
|
|
110
|
+
* @throws {CrowdyGraphQLError} if the underlying send is rejected.
|
|
111
|
+
* @throws {CrowdyTimeoutError} if the HTTP send leg times out.
|
|
112
|
+
* @throws {CrowdyRealtimeError} on echo timeout
|
|
113
|
+
* (`code === 'UDP_SEQUENCE_TIMEOUT'`) or a matching `GenericErrorResponse`.
|
|
114
|
+
*/
|
|
31
115
|
async sendState(state, options = {}) {
|
|
32
116
|
const chunk = options.chunk ?? this.chunk;
|
|
33
117
|
if (!chunk) {
|
|
@@ -43,6 +127,31 @@ export class ActorClient {
|
|
|
43
127
|
decayRate: options.decayRate ?? this.options.defaultDecayRate,
|
|
44
128
|
});
|
|
45
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Send a voxel (block) update from this actor to its current chunk (or
|
|
132
|
+
* `input.chunk`). Uses the UDP `...AndWait` path and resolves with the applied
|
|
133
|
+
* `VoxelUpdateResponse` echo. `appId`, `uuid`, and `chunk` are filled in for
|
|
134
|
+
* you.
|
|
135
|
+
*
|
|
136
|
+
* @param input - Voxel fields minus `appId`/`uuid`/`chunk`:
|
|
137
|
+
* - `voxel` — `{ x, y, z }` voxel coordinates within the chunk, each an
|
|
138
|
+
* int16 (-32768 to 32767).
|
|
139
|
+
* - `voxelType` — the new voxel type id.
|
|
140
|
+
* - `voxelState` — voxel state blob, base64-encoded.
|
|
141
|
+
* - `distance` — replication radius in chunk units, 0-8; defaults to 8.
|
|
142
|
+
* - `decayRate` — decay algorithm 0-5; defaults to 0 (none).
|
|
143
|
+
* - `sequenceNumber` — optional uint8 (0-255) correlation id.
|
|
144
|
+
* - `chunk` — optional `{ x, y, z }` (signed int64 decimal strings) to
|
|
145
|
+
* override the tracked chunk.
|
|
146
|
+
* @returns The correlated {@link SpatialNotification} (`VoxelUpdateResponse`).
|
|
147
|
+
* @throws {Error} `'Actor must join a chunk before sending voxel updates'` if
|
|
148
|
+
* no chunk has been joined and none is supplied.
|
|
149
|
+
* @throws {CrowdyProtocolError} if the resolved chunk is outside int64 range.
|
|
150
|
+
* @throws {CrowdyGraphQLError} if the underlying send is rejected.
|
|
151
|
+
* @throws {CrowdyTimeoutError} if the HTTP send leg times out.
|
|
152
|
+
* @throws {CrowdyRealtimeError} on echo timeout
|
|
153
|
+
* (`code === 'UDP_SEQUENCE_TIMEOUT'`) or a matching `GenericErrorResponse`.
|
|
154
|
+
*/
|
|
46
155
|
async sendVoxelUpdate(input) {
|
|
47
156
|
const chunk = input.chunk ?? this.chunk;
|
|
48
157
|
if (!chunk) {
|
|
@@ -56,6 +165,29 @@ export class ActorClient {
|
|
|
56
165
|
uuid: this.uuid,
|
|
57
166
|
});
|
|
58
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Send a spatial text/chat packet from this actor to its current chunk (or
|
|
170
|
+
* `input.chunk`), fanned out to nearby actors as a `ClientTextNotification`.
|
|
171
|
+
*
|
|
172
|
+
* Uses the UDP `...AndWait` path, but the server does **not** echo text back
|
|
173
|
+
* to the sender, so on success there is typically no notification to resolve
|
|
174
|
+
* and this will reject with a timeout — use it to surface send errors, or
|
|
175
|
+
* prefer `client.udp.sendTextPacket(...)` for plain fire-and-forget. `appId`,
|
|
176
|
+
* `uuid`, and `chunk` are filled in for you.
|
|
177
|
+
*
|
|
178
|
+
* @param text - Message content, UTF-8 (plain text, not base64).
|
|
179
|
+
* @param input - Optional extra fields: `distance` (chunk units, 0-8, default
|
|
180
|
+
* 8), `decayRate` (0-5, default 0), `sequenceNumber` (uint8), and `chunk` to
|
|
181
|
+
* override the tracked chunk.
|
|
182
|
+
* @returns The correlated {@link SpatialNotification}, if one is delivered.
|
|
183
|
+
* @throws {Error} `'Actor must join a chunk before sending text'` if no chunk
|
|
184
|
+
* has been joined and none is supplied.
|
|
185
|
+
* @throws {CrowdyProtocolError} if the resolved chunk is outside int64 range.
|
|
186
|
+
* @throws {CrowdyGraphQLError} if the underlying send is rejected.
|
|
187
|
+
* @throws {CrowdyTimeoutError} if the HTTP send leg times out.
|
|
188
|
+
* @throws {CrowdyRealtimeError} on timeout (`code === 'UDP_SEQUENCE_TIMEOUT'`)
|
|
189
|
+
* or a matching `GenericErrorResponse`.
|
|
190
|
+
*/
|
|
59
191
|
async sendText(text, input = {}) {
|
|
60
192
|
const chunk = input.chunk ?? this.chunk;
|
|
61
193
|
if (!chunk) {
|
|
@@ -70,6 +202,31 @@ export class ActorClient {
|
|
|
70
202
|
text,
|
|
71
203
|
});
|
|
72
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* Send a custom, app-defined client event from this actor to its current
|
|
207
|
+
* chunk (or `input.chunk`); nearby actors receive a `ClientEventNotification`.
|
|
208
|
+
*
|
|
209
|
+
* Uses the UDP `...AndWait` path, but the server does **not** echo events back
|
|
210
|
+
* to the sender, so on success there is typically no notification to resolve
|
|
211
|
+
* and this will reject with a timeout — use it to surface send errors, or
|
|
212
|
+
* prefer `client.udp.sendClientEvent(...)` for plain fire-and-forget. `appId`,
|
|
213
|
+
* `uuid`, and `chunk` are filled in for you.
|
|
214
|
+
*
|
|
215
|
+
* @param eventType - App-defined event id, a uint16 (0-65535).
|
|
216
|
+
* @param state - Event state blob, base64-encoded; format defined by the event
|
|
217
|
+
* type.
|
|
218
|
+
* @param input - Optional extra fields: `distance` (chunk units, 0-8, default
|
|
219
|
+
* 8), `decayRate` (0-5, default 0), `sequenceNumber` (uint8), and `chunk` to
|
|
220
|
+
* override the tracked chunk.
|
|
221
|
+
* @returns The correlated {@link SpatialNotification}, if one is delivered.
|
|
222
|
+
* @throws {Error} `'Actor must join a chunk before sending events'` if no
|
|
223
|
+
* chunk has been joined and none is supplied.
|
|
224
|
+
* @throws {CrowdyProtocolError} if the resolved chunk is outside int64 range.
|
|
225
|
+
* @throws {CrowdyGraphQLError} if the underlying send is rejected.
|
|
226
|
+
* @throws {CrowdyTimeoutError} if the HTTP send leg times out.
|
|
227
|
+
* @throws {CrowdyRealtimeError} on timeout (`code === 'UDP_SEQUENCE_TIMEOUT'`)
|
|
228
|
+
* or a matching `GenericErrorResponse`.
|
|
229
|
+
*/
|
|
73
230
|
async sendEvent(eventType, state, input = {}) {
|
|
74
231
|
const chunk = input.chunk ?? this.chunk;
|
|
75
232
|
if (!chunk) {
|
|
@@ -90,6 +247,19 @@ export class ActorClient {
|
|
|
90
247
|
* the chunk it currently occupies (the sender must know the target's chunk).
|
|
91
248
|
* Only that one actor receives it. Fire-and-forget: there is no echo to the
|
|
92
249
|
* sender, so this resolves to the send acknowledgement, not a notification.
|
|
250
|
+
*
|
|
251
|
+
* @param targetUuid - The destination actor's id: exactly 32 ASCII characters
|
|
252
|
+
* (not RFC-4122).
|
|
253
|
+
* @param payload - Message body, base64-encoded; opaque to the server.
|
|
254
|
+
* @param targetChunk - The destination actor's current `{ x, y, z }` chunk
|
|
255
|
+
* (each axis a signed int64 decimal string).
|
|
256
|
+
* @param options - `sequenceNumber`: optional uint8 (0-255) correlation id
|
|
257
|
+
* (used only to correlate a `GenericErrorResponse`).
|
|
258
|
+
* @returns `true` when the datagram was accepted for sending — **not**
|
|
259
|
+
* confirmation of delivery.
|
|
260
|
+
* @throws {CrowdyProtocolError} if `targetUuid` is not exactly 32 bytes, or
|
|
261
|
+
* `targetChunk` is outside signed int64 range.
|
|
262
|
+
* @throws {CrowdyGraphQLError} on auth/validation failures.
|
|
93
263
|
*/
|
|
94
264
|
async sendToActor(targetUuid, payload, targetChunk, options = {}) {
|
|
95
265
|
validateCrowdyUuid(targetUuid);
|