@crowdedkingdomstudios/crowdyjs 1.0.3 → 1.0.5
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 +259 -100
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# CrowdyJS SDK
|
|
2
2
|
|
|
3
|
-
Client SDK for Crowded Kingdoms GraphQL API with UDP proxy support.
|
|
3
|
+
Client SDK for the Crowded Kingdoms GraphQL API with UDP proxy support.
|
|
4
|
+
Handles authentication, real-time subscriptions, and all game-server
|
|
5
|
+
communication through a single `CrowdyClient` instance.
|
|
4
6
|
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
@@ -8,74 +10,120 @@ Client SDK for Crowded Kingdoms GraphQL API with UDP proxy support.
|
|
|
8
10
|
npm install @crowdedkingdomstudios/crowdyjs
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
### Node.js
|
|
14
|
+
|
|
15
|
+
The SDK uses the browser-native `WebSocket` API. In Node.js you need a
|
|
16
|
+
polyfill such as the `ws` package:
|
|
17
|
+
|
|
12
18
|
```bash
|
|
13
|
-
npm
|
|
19
|
+
npm install ws
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
import WebSocket from 'ws';
|
|
24
|
+
globalThis.WebSocket = WebSocket;
|
|
14
25
|
```
|
|
15
26
|
|
|
16
|
-
|
|
27
|
+
Place this **before** importing `CrowdyClient`.
|
|
28
|
+
|
|
29
|
+
### Browser
|
|
17
30
|
|
|
18
|
-
|
|
31
|
+
No extra setup needed -- the SDK uses the built-in `WebSocket`.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
19
34
|
|
|
20
35
|
```javascript
|
|
21
36
|
import { CrowdyClient } from '@crowdedkingdomstudios/crowdyjs';
|
|
22
37
|
|
|
23
38
|
const client = new CrowdyClient({
|
|
24
|
-
graphqlEndpoint: '
|
|
25
|
-
wsEndpoint: '
|
|
39
|
+
graphqlEndpoint: 'https://your-server.com/graphql',
|
|
40
|
+
wsEndpoint: 'wss://your-server.com/graphql',
|
|
26
41
|
});
|
|
27
42
|
```
|
|
28
43
|
|
|
29
|
-
|
|
44
|
+
If omitted, both endpoints default to `localhost:3000/graphql`.
|
|
45
|
+
|
|
46
|
+
## Connection Lifecycle
|
|
47
|
+
|
|
48
|
+
The SDK follows a four-step lifecycle that matches the server protocol:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
1. Login --> obtain a game token
|
|
52
|
+
2. Subscribe --> auto-opens UDP proxy session
|
|
53
|
+
3. Register --> tell the game server your chunk position
|
|
54
|
+
4. Send updates --> replicated to other clients in range
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 1. Login
|
|
30
58
|
|
|
31
59
|
```javascript
|
|
32
|
-
const
|
|
33
|
-
|
|
60
|
+
const auth = await client.login('user@example.com', 'password');
|
|
61
|
+
// auth.token -- 64-char hex game token (set automatically)
|
|
62
|
+
// auth.user.email -- logged-in user
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Or register a new account:
|
|
34
66
|
|
|
35
|
-
|
|
36
|
-
const
|
|
67
|
+
```javascript
|
|
68
|
+
const auth = await client.register('user@example.com', 'password', 'MyGamertag');
|
|
37
69
|
```
|
|
38
70
|
|
|
39
|
-
### Subscribe to Notifications
|
|
71
|
+
### 2. Subscribe to Notifications
|
|
40
72
|
|
|
41
|
-
|
|
42
|
-
|
|
73
|
+
Register one or more notification handlers. The first handler automatically
|
|
74
|
+
opens a WebSocket subscription and a UDP proxy session to the game server --
|
|
75
|
+
no explicit `connectUdpProxy()` call is needed.
|
|
43
76
|
|
|
44
77
|
```javascript
|
|
45
|
-
const
|
|
46
|
-
console.log('Actor
|
|
47
|
-
console.log('
|
|
48
|
-
console.log('
|
|
49
|
-
console.log('
|
|
78
|
+
const unsub = client.onActorUpdate((notification) => {
|
|
79
|
+
console.log('Actor:', notification.uuid);
|
|
80
|
+
console.log('State:', notification.state);
|
|
81
|
+
console.log('Chunk:', notification.chunkX, notification.chunkY, notification.chunkZ);
|
|
82
|
+
console.log('Time:', notification.epochMillis);
|
|
50
83
|
});
|
|
84
|
+
```
|
|
51
85
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
86
|
+
Handlers are unsubscribed by calling the returned function:
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
unsub(); // stop receiving ActorUpdateNotification
|
|
55
90
|
```
|
|
56
91
|
|
|
57
|
-
|
|
92
|
+
When all handlers are removed the WebSocket is closed automatically.
|
|
93
|
+
|
|
94
|
+
### 3. Register in a Chunk
|
|
58
95
|
|
|
59
|
-
Before other clients can
|
|
60
|
-
|
|
61
|
-
|
|
96
|
+
Before other clients can see you, send an initial actor update so the game
|
|
97
|
+
server knows which chunk you occupy. Use a minimal base64 payload (the
|
|
98
|
+
server requires a non-empty `state`):
|
|
62
99
|
|
|
63
100
|
```javascript
|
|
64
|
-
const MY_UUID = 'aaaaaaaabbbbccccddddeeeeeeeeeeee'; // 32 bytes UTF-8
|
|
101
|
+
const MY_UUID = 'aaaaaaaabbbbccccddddeeeeeeeeeeee'; // exactly 32 bytes UTF-8
|
|
65
102
|
|
|
66
103
|
await client.sendActorUpdate({
|
|
67
104
|
mapId: 0,
|
|
68
105
|
chunk: { x: 0, y: 0, z: 0 },
|
|
69
106
|
distance: 8,
|
|
70
107
|
uuid: MY_UUID,
|
|
71
|
-
state: 'AA==',
|
|
108
|
+
state: 'AA==', // minimal base64 payload for registration
|
|
72
109
|
sequenceNumber: 1,
|
|
73
110
|
});
|
|
74
111
|
```
|
|
75
112
|
|
|
76
|
-
|
|
113
|
+
Every client in the same chunk must do this. After registration, the game
|
|
114
|
+
server fans out subsequent updates to all registered clients in range.
|
|
115
|
+
|
|
116
|
+
### 4. Send Actor Updates
|
|
77
117
|
|
|
78
118
|
```javascript
|
|
119
|
+
// Build your binary state and base64-encode it
|
|
120
|
+
const stateBuffer = new ArrayBuffer(96);
|
|
121
|
+
const view = new DataView(stateBuffer);
|
|
122
|
+
view.setFloat32(0, posX, true);
|
|
123
|
+
view.setFloat32(4, posY, true);
|
|
124
|
+
view.setFloat32(8, posZ, true);
|
|
125
|
+
// ... fill remaining fields
|
|
126
|
+
|
|
79
127
|
const base64State = btoa(String.fromCharCode(...new Uint8Array(stateBuffer)));
|
|
80
128
|
|
|
81
129
|
await client.sendActorUpdate({
|
|
@@ -89,35 +137,120 @@ await client.sendActorUpdate({
|
|
|
89
137
|
});
|
|
90
138
|
```
|
|
91
139
|
|
|
92
|
-
###
|
|
93
|
-
|
|
94
|
-
The SDK provides type-specific handlers so you don't need to switch on `__typename`.
|
|
95
|
-
All spatial notifications include the uniform header fields: `mapId`, `chunkX`,
|
|
96
|
-
`chunkY`, `chunkZ`, `distance`, `decayRate`, `uuid`, `sequenceNumber`, `epochMillis`.
|
|
140
|
+
### 5. Disconnect
|
|
97
141
|
|
|
98
142
|
```javascript
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
143
|
+
await client.disconnectUdpProxy(); // release the UDP session
|
|
144
|
+
client.close(); // close WebSocket + clear state
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Unsubscribing from notifications stops delivery but does **not** release
|
|
148
|
+
the UDP session. Call `disconnectUdpProxy()` explicitly, or the server
|
|
149
|
+
will release it after 30 seconds of inactivity.
|
|
150
|
+
|
|
151
|
+
## Subscription Handlers
|
|
152
|
+
|
|
153
|
+
All spatial notification types share a uniform header:
|
|
154
|
+
|
|
155
|
+
| Field | Type | Description |
|
|
156
|
+
|-------|------|-------------|
|
|
157
|
+
| `mapId` | `string` | Map / chunk-W coordinate |
|
|
158
|
+
| `chunkX` | `string` | Chunk X coordinate |
|
|
159
|
+
| `chunkY` | `string` | Chunk Y coordinate |
|
|
160
|
+
| `chunkZ` | `string` | Chunk Z coordinate |
|
|
161
|
+
| `distance` | `number` | Replication distance (0-8) |
|
|
162
|
+
| `decayRate` | `number` | Delivery decay (0-5) |
|
|
163
|
+
| `uuid` | `string` | 32-byte sender UUID |
|
|
164
|
+
| `sequenceNumber` | `number` | uint8 (0-255), wraps |
|
|
165
|
+
| `epochMillis` | `string` | Server UTC timestamp in ms |
|
|
166
|
+
|
|
167
|
+
Each handler receives a fully-typed notification object:
|
|
108
168
|
|
|
109
|
-
|
|
110
|
-
|
|
169
|
+
```javascript
|
|
170
|
+
client.onActorUpdate((n) => { /* n: ActorUpdateNotification -- adds: state */ });
|
|
171
|
+
client.onActorUpdateResponse((n) => { /* n: ActorUpdateResponse */ });
|
|
172
|
+
client.onVoxelUpdate((n) => { /* n: VoxelUpdateNotification -- adds: voxelX/Y/Z, voxelType, voxelState */ });
|
|
173
|
+
client.onVoxelUpdateResponse((n) => { /* n: VoxelUpdateResponse */ });
|
|
174
|
+
client.onClientAudio((n) => { /* n: ClientAudioNotification -- adds: audioData */ });
|
|
175
|
+
client.onClientText((n) => { /* n: ClientTextNotification -- adds: text */ });
|
|
176
|
+
client.onClientEvent((n) => { /* n: ClientEventNotification -- adds: eventType, state */ });
|
|
177
|
+
client.onServerEvent((n) => { /* n: ServerEventNotification -- adds: eventType, state */ });
|
|
178
|
+
client.onGenericError((e) => { /* e: GenericErrorResponse -- sequenceNumber, errorCode only */ });
|
|
111
179
|
```
|
|
112
180
|
|
|
113
|
-
|
|
181
|
+
`GenericErrorResponse` is the only type without the spatial header; it has
|
|
182
|
+
just `sequenceNumber` and `errorCode`.
|
|
183
|
+
|
|
184
|
+
## Input Parameters
|
|
185
|
+
|
|
186
|
+
### Common fields
|
|
187
|
+
|
|
188
|
+
All mutation inputs share these fields:
|
|
189
|
+
|
|
190
|
+
| Field | Type | Required | Default | Description |
|
|
191
|
+
|-------|------|----------|---------|-------------|
|
|
192
|
+
| `mapId` | `number` | yes | -- | Map / chunk-W coordinate |
|
|
193
|
+
| `chunk` | `{ x, y, z }` | yes | -- | Chunk coordinates (numbers) |
|
|
194
|
+
| `uuid` | `string` | yes | -- | Your 32-byte UUID |
|
|
195
|
+
| `distance` | `number` | no | `8` | Replication range (0-8 chunks, Chebyshev) |
|
|
196
|
+
| `decayRate` | `number` | no | `0` | Delivery decay (see table below) |
|
|
197
|
+
| `sequenceNumber` | `number` | no | `0` | uint8 (0-255) for correlation |
|
|
198
|
+
|
|
199
|
+
### `decayRate` values
|
|
200
|
+
|
|
201
|
+
| Value | Name | Behavior |
|
|
202
|
+
|-------|------|----------|
|
|
203
|
+
| 0 | None | All clients within `distance` receive every message |
|
|
204
|
+
| 1 | Exponential | Each ring receives half the messages of the previous ring |
|
|
205
|
+
| 2 | Linear 50% | Furthest ring receives 50% of messages |
|
|
206
|
+
| 3 | Linear 25% | Furthest ring receives 25% of messages |
|
|
207
|
+
| 4 | Linear 10% | Furthest ring receives 10% of messages |
|
|
208
|
+
| 5 | Linear 5% | Furthest ring receives 5% of messages |
|
|
209
|
+
|
|
210
|
+
### `sendActorUpdate`
|
|
211
|
+
|
|
212
|
+
| Field | Type | Description |
|
|
213
|
+
|-------|------|-------------|
|
|
214
|
+
| `state` | `string` | Base64-encoded binary state (must be non-empty) |
|
|
215
|
+
|
|
216
|
+
### `sendVoxelUpdate`
|
|
217
|
+
|
|
218
|
+
| Field | Type | Description |
|
|
219
|
+
|-------|------|-------------|
|
|
220
|
+
| `voxel` | `{ x, y, z }` | Voxel position within the chunk |
|
|
221
|
+
| `voxelType` | `number` | Voxel type ID |
|
|
222
|
+
| `voxelState` | `string` | Base64-encoded voxel state |
|
|
223
|
+
|
|
224
|
+
### `sendAudioPacket`
|
|
225
|
+
|
|
226
|
+
| Field | Type | Description |
|
|
227
|
+
|-------|------|-------------|
|
|
228
|
+
| `audioData` | `string` | Base64-encoded compressed audio |
|
|
229
|
+
|
|
230
|
+
### `sendTextPacket`
|
|
231
|
+
|
|
232
|
+
| Field | Type | Description |
|
|
233
|
+
|-------|------|-------------|
|
|
234
|
+
| `text` | `string` | Chat message text |
|
|
235
|
+
|
|
236
|
+
### `sendClientEvent`
|
|
237
|
+
|
|
238
|
+
| Field | Type | Description |
|
|
239
|
+
|-------|------|-------------|
|
|
240
|
+
| `eventType` | `number` | Custom event type ID |
|
|
241
|
+
| `state` | `string` | Base64-encoded event state |
|
|
242
|
+
|
|
243
|
+
## Complete Example
|
|
114
244
|
|
|
115
245
|
```javascript
|
|
246
|
+
import WebSocket from 'ws';
|
|
247
|
+
globalThis.WebSocket = WebSocket;
|
|
248
|
+
|
|
116
249
|
import { CrowdyClient } from '@crowdedkingdomstudios/crowdyjs';
|
|
117
250
|
|
|
118
251
|
const client = new CrowdyClient({
|
|
119
|
-
graphqlEndpoint: '
|
|
120
|
-
wsEndpoint: '
|
|
252
|
+
graphqlEndpoint: 'https://your-server.com/graphql',
|
|
253
|
+
wsEndpoint: 'wss://your-server.com/graphql',
|
|
121
254
|
});
|
|
122
255
|
|
|
123
256
|
const MY_UUID = 'aaaaaaaabbbbccccddddeeeeeeeeeeee';
|
|
@@ -126,8 +259,13 @@ const MY_UUID = 'aaaaaaaabbbbccccddddeeeeeeeeeeee';
|
|
|
126
259
|
await client.login('user@example.com', 'password');
|
|
127
260
|
|
|
128
261
|
// 2. Subscribe (auto-opens UDP proxy session)
|
|
129
|
-
const
|
|
130
|
-
console.log(
|
|
262
|
+
const unsubActors = client.onActorUpdate((n) => {
|
|
263
|
+
console.log(`Actor ${n.uuid} at chunk (${n.chunkX},${n.chunkY},${n.chunkZ})`);
|
|
264
|
+
console.log(` state=${n.state} seq=${n.sequenceNumber} t=${n.epochMillis}`);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
const unsubErrors = client.onGenericError((e) => {
|
|
268
|
+
console.error(`Error: ${e.errorCode} (seq ${e.sequenceNumber})`);
|
|
131
269
|
});
|
|
132
270
|
|
|
133
271
|
// 3. Register in chunk
|
|
@@ -140,78 +278,99 @@ await client.sendActorUpdate({
|
|
|
140
278
|
sequenceNumber: 1,
|
|
141
279
|
});
|
|
142
280
|
|
|
143
|
-
// 4. Send updates
|
|
281
|
+
// 4. Send updates in a loop
|
|
144
282
|
let seq = 2;
|
|
145
|
-
setInterval(async () => {
|
|
283
|
+
const interval = setInterval(async () => {
|
|
284
|
+
const buf = new Uint8Array(96);
|
|
285
|
+
crypto.getRandomValues(buf);
|
|
286
|
+
const state = btoa(String.fromCharCode(...buf));
|
|
287
|
+
|
|
146
288
|
await client.sendActorUpdate({
|
|
147
289
|
mapId: 0,
|
|
148
290
|
chunk: { x: 0, y: 0, z: 0 },
|
|
149
291
|
distance: 8,
|
|
150
292
|
uuid: MY_UUID,
|
|
151
|
-
state
|
|
293
|
+
state,
|
|
152
294
|
sequenceNumber: seq++ % 256,
|
|
153
295
|
});
|
|
154
296
|
}, 100);
|
|
155
297
|
|
|
156
|
-
// Cleanup
|
|
157
|
-
|
|
298
|
+
// 5. Cleanup
|
|
299
|
+
clearInterval(interval);
|
|
300
|
+
unsubActors();
|
|
301
|
+
unsubErrors();
|
|
158
302
|
await client.disconnectUdpProxy();
|
|
159
303
|
client.close();
|
|
160
304
|
```
|
|
161
305
|
|
|
162
306
|
## API Reference
|
|
163
307
|
|
|
164
|
-
###
|
|
165
|
-
|
|
166
|
-
Main client class for interacting with the API.
|
|
167
|
-
|
|
168
|
-
#### Constructor
|
|
308
|
+
### Constructor
|
|
169
309
|
|
|
170
310
|
```typescript
|
|
171
311
|
new CrowdyClient(config?: CrowdyClientConfig)
|
|
172
312
|
```
|
|
173
313
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
314
|
+
| Option | Type | Default | Description |
|
|
315
|
+
|--------|------|---------|-------------|
|
|
316
|
+
| `graphqlEndpoint` | `string` | `http://localhost:3000/graphql` | HTTP endpoint for mutations/queries |
|
|
317
|
+
| `wsEndpoint` | `string` | `ws://localhost:3000/graphql` | WebSocket endpoint for subscriptions |
|
|
318
|
+
| `timeout` | `number` | `60000` | HTTP request timeout in ms |
|
|
178
319
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
**Authentication:**
|
|
182
|
-
- `login(email: string, password: string): Promise<AuthResponse>`
|
|
183
|
-
- `register(email: string, password: string, gamertag?: string): Promise<AuthResponse>`
|
|
184
|
-
- `getAuthToken(): string | null`
|
|
185
|
-
|
|
186
|
-
**UDP Proxy:**
|
|
187
|
-
- `connectUdpProxy(): Promise<UdpProxyConnectionStatus>` -- optional; subscriptions and mutations auto-open the session
|
|
188
|
-
- `disconnectUdpProxy(): Promise<boolean>`
|
|
189
|
-
- `getConnectionStatus(): Promise<UdpProxyConnectionStatus>`
|
|
190
|
-
|
|
191
|
-
**Sending Updates:**
|
|
192
|
-
- `sendActorUpdate(input: ActorUpdateRequestInput): Promise<boolean>`
|
|
193
|
-
- `sendVoxelUpdate(input: VoxelUpdateRequestInput): Promise<boolean>`
|
|
194
|
-
- `sendAudioPacket(input: ClientAudioPacketInput): Promise<boolean>`
|
|
195
|
-
- `sendTextPacket(input: ClientTextPacketInput): Promise<boolean>`
|
|
196
|
-
- `sendClientEvent(input: ClientEventNotificationInput): Promise<boolean>`
|
|
197
|
-
|
|
198
|
-
**Subscriptions:**
|
|
199
|
-
- `onActorUpdate(handler): UnsubscribeFn`
|
|
200
|
-
- `onActorUpdateResponse(handler): UnsubscribeFn`
|
|
201
|
-
- `onVoxelUpdate(handler): UnsubscribeFn`
|
|
202
|
-
- `onVoxelUpdateResponse(handler): UnsubscribeFn`
|
|
203
|
-
- `onClientAudio(handler): UnsubscribeFn`
|
|
204
|
-
- `onClientText(handler): UnsubscribeFn`
|
|
205
|
-
- `onClientEvent(handler): UnsubscribeFn`
|
|
206
|
-
- `onServerEvent(handler): UnsubscribeFn`
|
|
207
|
-
- `onGenericError(handler): UnsubscribeFn`
|
|
208
|
-
|
|
209
|
-
**Cleanup:**
|
|
210
|
-
- `close(): void` - Closes all subscriptions and cleans up
|
|
211
|
-
|
|
212
|
-
## TypeScript Support
|
|
320
|
+
### Authentication
|
|
213
321
|
|
|
214
|
-
|
|
322
|
+
| Method | Returns | Description |
|
|
323
|
+
|--------|---------|-------------|
|
|
324
|
+
| `login(email, password)` | `Promise<AuthResponse>` | Login and store the game token |
|
|
325
|
+
| `register(email, password, gamertag?)` | `Promise<AuthResponse>` | Register and store the game token |
|
|
326
|
+
| `getAuthToken()` | `string \| null` | Get the current game token |
|
|
327
|
+
|
|
328
|
+
### UDP Proxy
|
|
329
|
+
|
|
330
|
+
| Method | Returns | Description |
|
|
331
|
+
|--------|---------|-------------|
|
|
332
|
+
| `connectUdpProxy()` | `Promise<UdpProxyConnectionStatus>` | Explicitly open a UDP session (optional) |
|
|
333
|
+
| `disconnectUdpProxy()` | `Promise<boolean>` | Release the UDP session |
|
|
334
|
+
| `getConnectionStatus()` | `Promise<UdpProxyConnectionStatus>` | Check if a UDP session is active |
|
|
335
|
+
|
|
336
|
+
### Mutations
|
|
337
|
+
|
|
338
|
+
| Method | Returns | Description |
|
|
339
|
+
|--------|---------|-------------|
|
|
340
|
+
| `sendActorUpdate(input)` | `Promise<boolean>` | Send an actor state update |
|
|
341
|
+
| `sendVoxelUpdate(input)` | `Promise<boolean>` | Modify a voxel in a chunk |
|
|
342
|
+
| `sendAudioPacket(input)` | `Promise<boolean>` | Send voice audio data |
|
|
343
|
+
| `sendTextPacket(input)` | `Promise<boolean>` | Send chat text |
|
|
344
|
+
| `sendClientEvent(input)` | `Promise<boolean>` | Send a custom event |
|
|
345
|
+
|
|
346
|
+
### Subscriptions
|
|
347
|
+
|
|
348
|
+
| Method | Handler receives | Description |
|
|
349
|
+
|--------|-----------------|-------------|
|
|
350
|
+
| `onActorUpdate(handler)` | `ActorUpdateNotification` | Another client's actor state |
|
|
351
|
+
| `onActorUpdateResponse(handler)` | `ActorUpdateResponse` | Server ack for your actor update |
|
|
352
|
+
| `onVoxelUpdate(handler)` | `VoxelUpdateNotification` | A voxel was modified |
|
|
353
|
+
| `onVoxelUpdateResponse(handler)` | `VoxelUpdateResponse` | Server ack for your voxel update |
|
|
354
|
+
| `onClientAudio(handler)` | `ClientAudioNotification` | Voice audio from another client |
|
|
355
|
+
| `onClientText(handler)` | `ClientTextNotification` | Chat text from another client |
|
|
356
|
+
| `onClientEvent(handler)` | `ClientEventNotification` | Custom event from another client |
|
|
357
|
+
| `onServerEvent(handler)` | `ServerEventNotification` | Event from the game server |
|
|
358
|
+
| `onGenericError(handler)` | `GenericErrorResponse` | Error from the server |
|
|
359
|
+
|
|
360
|
+
All subscription methods return an `UnsubscribeFn` -- call it to remove
|
|
361
|
+
the handler.
|
|
362
|
+
|
|
363
|
+
### Cleanup
|
|
364
|
+
|
|
365
|
+
| Method | Description |
|
|
366
|
+
|--------|-------------|
|
|
367
|
+
| `close()` | Close the WebSocket, remove all handlers, clear auth state |
|
|
368
|
+
|
|
369
|
+
## TypeScript
|
|
370
|
+
|
|
371
|
+
The SDK is written in TypeScript and ships type declarations. All
|
|
372
|
+
notification interfaces, input types, and handler signatures are fully
|
|
373
|
+
typed for IDE autocomplete and compile-time safety.
|
|
215
374
|
|
|
216
375
|
## License
|
|
217
376
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CrowdyJS SDK - Client SDK for Crowded Kingdoms GraphQL API
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
declare const VERSION: string;
|
|
5
|
+
export { VERSION };
|
|
5
6
|
export { CrowdyClient } from './crowdy-client.js';
|
|
6
7
|
export type { CrowdyClientConfig, BigInt, ChunkCoordinates, ChunkCoordinatesInput, VoxelCoordinates, VoxelCoordinatesInput, UdpErrorCode, User, AuthResponse, UdpProxyConnectionStatus, ActorUpdateRequestInput, VoxelUpdateRequestInput, ClientAudioPacketInput, ClientTextPacketInput, ClientEventNotificationInput, ActorUpdateNotification, ActorUpdateResponse, VoxelUpdateNotification, VoxelUpdateResponse, ClientAudioNotification, ClientTextNotification, ClientEventNotification, ServerEventNotification, GenericErrorResponse, UdpNotification, ActorUpdateHandler, ActorUpdateResponseHandler, VoxelUpdateHandler, VoxelUpdateResponseHandler, ClientAudioHandler, ClientTextHandler, ClientEventHandler, ServerEventHandler, GenericErrorHandler, UnsubscribeFn, } from './types.js';
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,QAAA,MAAiB,OAAO,QAAsD,CAAC;AAE/E,OAAO,EAAE,OAAO,EAAE,CAAC;AAGnB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAEV,kBAAkB,EAElB,MAAM,EACN,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,IAAI,EACJ,YAAY,EACZ,wBAAwB,EAExB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,4BAA4B,EAE5B,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,eAAe,EAEf,kBAAkB,EAClB,0BAA0B,EAC1B,kBAAkB,EAClB,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,GACd,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CrowdyJS SDK - Client SDK for Crowded Kingdoms GraphQL API
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
const { version: VERSION } = require('../package.json');
|
|
7
|
+
export { VERSION };
|
|
5
8
|
console.log(`CrowdyJS v${VERSION}`);
|
|
6
9
|
export { CrowdyClient } from './crowdy-client.js';
|