@crowdedkingdoms/crowdyjs 18.5.0-dev.1 → 18.7.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/MIGRATION.md +118 -0
- package/README.md +109 -4
- package/dist/binary-wire.d.ts +30 -2
- package/dist/binary-wire.d.ts.map +1 -1
- package/dist/binary-wire.js +61 -3
- package/dist/crowdy-client.d.ts +3 -0
- package/dist/crowdy-client.d.ts.map +1 -1
- package/dist/crowdy-client.js +2 -0
- package/dist/domains/appAccess.d.ts +32 -1
- package/dist/domains/appAccess.d.ts.map +1 -1
- package/dist/domains/appAccess.js +49 -1
- package/dist/domains/apps.d.ts +7 -1
- package/dist/domains/apps.d.ts.map +1 -1
- package/dist/domains/apps.js +7 -1
- package/dist/domains/channels.d.ts +8 -3
- package/dist/domains/channels.d.ts.map +1 -1
- package/dist/domains/channels.js +8 -3
- package/dist/domains/exec.d.ts +14 -0
- package/dist/domains/exec.d.ts.map +1 -1
- package/dist/domains/exec.js +13 -1
- package/dist/domains/grids.d.ts +1 -0
- package/dist/domains/grids.d.ts.map +1 -1
- package/dist/domains/grids.js +1 -0
- package/dist/domains/inputLog.d.ts +74 -0
- package/dist/domains/inputLog.d.ts.map +1 -0
- package/dist/domains/inputLog.js +74 -0
- package/dist/domains/portal.d.ts +18 -0
- package/dist/domains/portal.d.ts.map +1 -1
- package/dist/domains/portal.js +1 -1
- package/dist/domains/udp.d.ts +27 -8
- package/dist/domains/udp.d.ts.map +1 -1
- package/dist/domains/udp.js +39 -9
- package/dist/domains/users.d.ts +23 -2
- package/dist/domains/users.d.ts.map +1 -1
- package/dist/domains/users.js +34 -2
- package/dist/domains/voxels.d.ts +4 -3
- package/dist/domains/voxels.d.ts.map +1 -1
- package/dist/domains/voxels.js +4 -3
- package/dist/errors.d.ts +52 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +74 -0
- package/dist/generated/graphql-schema.d.ts +576 -49
- package/dist/generated/graphql-schema.d.ts.map +1 -1
- package/dist/generated/graphql-schema.js +30 -1
- package/dist/generated/graphql.d.ts +232 -17
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/generated/graphql.js +30 -21
- package/dist/grid-mods/grid-host-calls.d.ts +34 -0
- package/dist/grid-mods/grid-host-calls.d.ts.map +1 -1
- package/dist/grid-mods/grid-host-calls.js +28 -5
- package/dist/grid-mods/index.d.ts +1 -1
- package/dist/grid-mods/index.d.ts.map +1 -1
- package/dist/grid-mods/index.js +1 -1
- package/dist/grid-scope.d.ts +3 -0
- package/dist/grid-scope.d.ts.map +1 -1
- package/dist/grid-scope.js +6 -0
- package/dist/index.d.ts +11 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/media/voice-frames.d.ts +258 -0
- package/dist/media/voice-frames.d.ts.map +1 -0
- package/dist/media/voice-frames.js +424 -0
- package/dist/metrics.d.ts +1 -1
- package/dist/realtime.d.ts +19 -3
- package/dist/realtime.d.ts.map +1 -1
- package/dist/realtime.js +8 -0
- package/dist/stores/actors.d.ts +3 -1
- package/dist/stores/actors.d.ts.map +1 -1
- package/dist/stores/chunks.d.ts +65 -6
- package/dist/stores/chunks.d.ts.map +1 -1
- package/dist/stores/chunks.js +161 -19
- package/dist/stores/index.d.ts +2 -2
- package/dist/stores/index.d.ts.map +1 -1
- package/dist/stores/index.js +1 -1
- package/dist/stores/keys.d.ts +5 -0
- package/dist/stores/keys.d.ts.map +1 -1
- package/dist/stores/keys.js +7 -0
- package/dist/stores/session.d.ts +1 -1
- package/dist/stores/session.d.ts.map +1 -1
- package/dist/stores/session.js +2 -0
- package/dist/types.d.ts +49 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voice payloads: an optional convention for what an app carries inside an audio payload
|
|
3
|
+
* (`CLIENT_AUDIO_PACKET_2` 134, delivered as `CLIENT_AUDIO_NOTIFICATION_2` 135).
|
|
4
|
+
*
|
|
5
|
+
* The server never looks inside an audio payload, and an app with a format of its own keeps it.
|
|
6
|
+
* This is a shared one, implemented byte for byte by both SDKs (CrowdyCPP's
|
|
7
|
+
* `crowdy/media/voice_frames.hpp`; both replay `test/unit/fixtures/voice-frames.json`): a 10-byte
|
|
8
|
+
* header in front of each codec frame, integers little-endian.
|
|
9
|
+
*
|
|
10
|
+
* ```
|
|
11
|
+
* offset size field meaning
|
|
12
|
+
* 0 1 version 1. A reader refuses any other version.
|
|
13
|
+
* 1 1 codec 0 = unspecified / raw, 1 = Opus 48 kHz mono, 2 = G.711 µ-law 8 kHz.
|
|
14
|
+
* 2 2 seq uint16, +1 per packet sent, wraps.
|
|
15
|
+
* 4 4 timestamp uint32 in codec samples (48 kHz for Opus, 8 kHz for µ-law;
|
|
16
|
+
* milliseconds for codec 0 and any codec not listed), wraps.
|
|
17
|
+
* 8 1 frameMs the frame's duration in milliseconds.
|
|
18
|
+
* 9 1 flags bit 0: the first packet after silence (a talk spurt starts);
|
|
19
|
+
* bit 1: the last packet before silence. Other bits are reserved.
|
|
20
|
+
* 10 ... frame one codec frame.
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* A reader refuses a packet shorter than 10 bytes or of another version: {@link decodeVoicePacket}
|
|
24
|
+
* returns `null`, and nothing here throws on a packet from the network. {@link VoicePacketizer}
|
|
25
|
+
* numbers one sender's frames and sets the talk-spurt flags; {@link VoiceJitterBuffer} puts each
|
|
26
|
+
* sender's packets back in order, plays them out after a fixed delay and reports the frames that
|
|
27
|
+
* never came as gaps.
|
|
28
|
+
*
|
|
29
|
+
* **Opus.** No codec ships with this SDK. A browser encodes and decodes Opus with WebCodecs: an
|
|
30
|
+
* `AudioEncoder` configured `{ codec: 'opus', sampleRate: 48000, numberOfChannels: 1, bitrate:
|
|
31
|
+
* 24000, opus: { frameDuration: 20000 } }` emits one `EncodedAudioChunk` per 20 ms (copy it out
|
|
32
|
+
* with `copyTo` and packetize the bytes), and an `AudioDecoder` configured `{ codec: 'opus',
|
|
33
|
+
* sampleRate: 48000, numberOfChannels: 1 }` decodes each frame the jitter buffer plays (`new
|
|
34
|
+
* EncodedAudioChunk({ type: 'key', timestamp, data })`). Check `typeof AudioEncoder !==
|
|
35
|
+
* 'undefined'` and `AudioEncoder.isConfigSupported(config)` first, and fall back to G.711 µ-law
|
|
36
|
+
* (codec 2) where either is missing. WebCodecs conceals no loss: on a gap, repeat the last
|
|
37
|
+
* decoded frame more quietly, or play silence. Where a voice sits in the world (panning,
|
|
38
|
+
* distance attenuation) is the game's to decide.
|
|
39
|
+
*/
|
|
40
|
+
/** Bytes of voice header in front of every codec frame. */
|
|
41
|
+
export const VOICE_HEADER_BYTES = 10;
|
|
42
|
+
/** The one header version this SDK writes and accepts. */
|
|
43
|
+
export const VOICE_HEADER_VERSION = 1;
|
|
44
|
+
/** Largest codec frame one audio payload carries with the HMAC tail present (1123 − 10). */
|
|
45
|
+
export const MAX_VOICE_FRAME_BYTES = 1113;
|
|
46
|
+
/** Default {@link VoiceJitterBufferOptions.targetDelayMs}. */
|
|
47
|
+
export const VOICE_TARGET_DELAY_MS = 60;
|
|
48
|
+
/** Default {@link VoiceJitterBufferOptions.maxFrames}. */
|
|
49
|
+
export const VOICE_JITTER_MAX_FRAMES = 64;
|
|
50
|
+
/** Default {@link VoiceJitterBufferOptions.resetAfterMs}. */
|
|
51
|
+
export const VOICE_RESET_AFTER_MS = 200;
|
|
52
|
+
/** Codecs the header names. Any other value is carried through as it is. */
|
|
53
|
+
export const VoiceCodec = {
|
|
54
|
+
/** Unspecified, or raw samples in a format the app defines. The timestamp counts milliseconds. */
|
|
55
|
+
RAW: 0,
|
|
56
|
+
/** Opus, 48 kHz, one channel. */
|
|
57
|
+
OPUS: 1,
|
|
58
|
+
/** G.711 µ-law, 8 kHz, one byte per sample. */
|
|
59
|
+
MULAW: 2,
|
|
60
|
+
};
|
|
61
|
+
/** Header flag bits. */
|
|
62
|
+
export const VoiceFlag = {
|
|
63
|
+
/** The first packet after silence: a talk spurt starts. */
|
|
64
|
+
SPURT_START: 1,
|
|
65
|
+
/** The last packet before silence. */
|
|
66
|
+
SPURT_END: 2,
|
|
67
|
+
};
|
|
68
|
+
/** The sample clock a codec's timestamps count: 48000 (Opus), 8000 (µ-law), else 1000. */
|
|
69
|
+
export function voiceClockRate(codec) {
|
|
70
|
+
if (codec === VoiceCodec.OPUS)
|
|
71
|
+
return 48000;
|
|
72
|
+
if (codec === VoiceCodec.MULAW)
|
|
73
|
+
return 8000;
|
|
74
|
+
return 1000;
|
|
75
|
+
}
|
|
76
|
+
/** How far the timestamp moves for one frame of `frameMs` milliseconds. */
|
|
77
|
+
export function voiceSamplesPerFrame(codec, frameMs) {
|
|
78
|
+
return (voiceClockRate(codec) / 1000) * frameMs;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The distance from seq `b` to seq `a` on the wrapping uint16 counter, from −32768 to 32767:
|
|
82
|
+
* positive when `a` is newer.
|
|
83
|
+
*/
|
|
84
|
+
export function voiceSeqDiff(a, b) {
|
|
85
|
+
const d = (a - b) & 0xffff;
|
|
86
|
+
return d >= 0x8000 ? d - 0x10000 : d;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Write a voice header (always version 1).
|
|
90
|
+
*
|
|
91
|
+
* @throws {RangeError} when a field is outside its width: codec, frameMs and flags 0-255, seq
|
|
92
|
+
* 0-65535, timestamp 0-4294967295.
|
|
93
|
+
*/
|
|
94
|
+
export function encodeVoiceHeader(header) {
|
|
95
|
+
checkField('codec', header.codec, 0xff);
|
|
96
|
+
checkField('seq', header.seq, 0xffff);
|
|
97
|
+
checkField('timestamp', header.timestamp, 0xffffffff);
|
|
98
|
+
checkField('frameMs', header.frameMs, 0xff);
|
|
99
|
+
checkField('flags', header.flags, 0xff);
|
|
100
|
+
const out = new Uint8Array(VOICE_HEADER_BYTES);
|
|
101
|
+
const view = new DataView(out.buffer);
|
|
102
|
+
out[0] = VOICE_HEADER_VERSION;
|
|
103
|
+
out[1] = header.codec;
|
|
104
|
+
view.setUint16(2, header.seq, true);
|
|
105
|
+
view.setUint32(4, header.timestamp, true);
|
|
106
|
+
out[8] = header.frameMs;
|
|
107
|
+
out[9] = header.flags;
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* `header || frame`, ready for `udp.sendAudioPacket` (base64 it as `audioData`).
|
|
112
|
+
*
|
|
113
|
+
* @throws {RangeError} as {@link encodeVoiceHeader}, and when the frame is longer than
|
|
114
|
+
* {@link MAX_VOICE_FRAME_BYTES}.
|
|
115
|
+
*/
|
|
116
|
+
export function encodeVoicePacket(header, frame) {
|
|
117
|
+
if (frame.length > MAX_VOICE_FRAME_BYTES) {
|
|
118
|
+
throw new RangeError(`voice frame of ${frame.length} bytes exceeds ${MAX_VOICE_FRAME_BYTES} bytes`);
|
|
119
|
+
}
|
|
120
|
+
const packet = new Uint8Array(VOICE_HEADER_BYTES + frame.length);
|
|
121
|
+
packet.set(encodeVoiceHeader(header), 0);
|
|
122
|
+
packet.set(frame, VOICE_HEADER_BYTES);
|
|
123
|
+
return packet;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Parse a voice packet. Returns `null` for a packet shorter than {@link VOICE_HEADER_BYTES} or of
|
|
127
|
+
* a version other than {@link VOICE_HEADER_VERSION}. Codecs and flag bits this SDK does not know
|
|
128
|
+
* are returned as they are.
|
|
129
|
+
*/
|
|
130
|
+
export function decodeVoicePacket(packet) {
|
|
131
|
+
if (packet.length < VOICE_HEADER_BYTES)
|
|
132
|
+
return null;
|
|
133
|
+
if (packet[0] !== VOICE_HEADER_VERSION)
|
|
134
|
+
return null;
|
|
135
|
+
const view = new DataView(packet.buffer, packet.byteOffset, packet.byteLength);
|
|
136
|
+
return {
|
|
137
|
+
header: {
|
|
138
|
+
version: packet[0],
|
|
139
|
+
codec: packet[1],
|
|
140
|
+
seq: view.getUint16(2, true),
|
|
141
|
+
timestamp: view.getUint32(4, true),
|
|
142
|
+
frameMs: packet[8],
|
|
143
|
+
flags: packet[9],
|
|
144
|
+
},
|
|
145
|
+
frame: packet.subarray(VOICE_HEADER_BYTES),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Numbers one sender's frames: each packet gets the next seq (uint16, wraps) and a timestamp one
|
|
150
|
+
* frame later than the last (uint32, wraps). The first packet, and the first after a `last` one
|
|
151
|
+
* or a {@link skip}, carries {@link VoiceFlag.SPURT_START}. Keep one packetizer for as long as the
|
|
152
|
+
* sender speaks with the same codec and frame duration, muted stretches included: a fresh one
|
|
153
|
+
* starts its seq over, and a receiver that still holds the old stream drops packets that look old
|
|
154
|
+
* to it until the seq catches up or the stream is reset.
|
|
155
|
+
*/
|
|
156
|
+
export class VoicePacketizer {
|
|
157
|
+
/** @throws {RangeError} for a codec outside 0-255, a frameMs outside 1-255, or a bad seq or timestamp. */
|
|
158
|
+
constructor(options) {
|
|
159
|
+
this.spurtStart = true;
|
|
160
|
+
checkField('codec', options.codec, 0xff);
|
|
161
|
+
checkField('frameMs', options.frameMs, 0xff);
|
|
162
|
+
if (options.frameMs < 1)
|
|
163
|
+
throw new RangeError('frameMs must be 1-255, got 0');
|
|
164
|
+
checkField('seq', options.seq ?? 0, 0xffff);
|
|
165
|
+
checkField('timestamp', options.timestamp ?? 0, 0xffffffff);
|
|
166
|
+
this.codec = options.codec;
|
|
167
|
+
this.frameMs = options.frameMs;
|
|
168
|
+
this.seqValue = options.seq ?? 0;
|
|
169
|
+
this.timestampValue = options.timestamp ?? 0;
|
|
170
|
+
}
|
|
171
|
+
/** The seq the next packet will carry. */
|
|
172
|
+
get nextSeq() {
|
|
173
|
+
return this.seqValue;
|
|
174
|
+
}
|
|
175
|
+
/** The timestamp the next packet will carry. */
|
|
176
|
+
get nextTimestamp() {
|
|
177
|
+
return this.timestampValue;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The next packet: the header, then `frame`.
|
|
181
|
+
*
|
|
182
|
+
* @param options - `last`: this is the last packet before silence ({@link VoiceFlag.SPURT_END});
|
|
183
|
+
* the next one starts a talk spurt.
|
|
184
|
+
* @throws {RangeError} when the frame is longer than {@link MAX_VOICE_FRAME_BYTES}; nothing is
|
|
185
|
+
* numbered.
|
|
186
|
+
*/
|
|
187
|
+
packetize(frame, options = {}) {
|
|
188
|
+
const last = options.last === true;
|
|
189
|
+
const packet = encodeVoicePacket({
|
|
190
|
+
codec: this.codec,
|
|
191
|
+
seq: this.seqValue,
|
|
192
|
+
timestamp: this.timestampValue,
|
|
193
|
+
frameMs: this.frameMs,
|
|
194
|
+
flags: (this.spurtStart ? VoiceFlag.SPURT_START : 0) | (last ? VoiceFlag.SPURT_END : 0),
|
|
195
|
+
}, frame);
|
|
196
|
+
this.seqValue = (this.seqValue + 1) & 0xffff;
|
|
197
|
+
this.advance(1);
|
|
198
|
+
this.spurtStart = last;
|
|
199
|
+
return packet;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Silence: move the timestamp past `frames` frames that are not sent (the seq does not move),
|
|
203
|
+
* and start a talk spurt with the next packet. `skip(0)` only does the latter.
|
|
204
|
+
*
|
|
205
|
+
* @throws {RangeError} unless `frames` is a non-negative integer.
|
|
206
|
+
*/
|
|
207
|
+
skip(frames = 1) {
|
|
208
|
+
if (!Number.isInteger(frames) || frames < 0) {
|
|
209
|
+
throw new RangeError(`frames must be a non-negative integer, got ${frames}`);
|
|
210
|
+
}
|
|
211
|
+
this.advance(frames % 0x100000000);
|
|
212
|
+
this.spurtStart = true;
|
|
213
|
+
}
|
|
214
|
+
advance(frames) {
|
|
215
|
+
const step = voiceSamplesPerFrame(this.codec, this.frameMs);
|
|
216
|
+
this.timestampValue = (this.timestampValue + ((frames * step) % 0x100000000)) % 0x100000000;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Puts each sender's voice packets back in order and plays them out after a fixed delay. Feed
|
|
221
|
+
* every audio notification's decoded `audioData` to {@link push} with the sender's key (its actor
|
|
222
|
+
* uuid), call {@link pull} (or {@link poll}) at least once a frame, and {@link forget} a sender
|
|
223
|
+
* that left. Pass both the same clock (`performance.now()` in a browser; `Date.now()` when
|
|
224
|
+
* omitted). Pure and clock-injected, so both SDKs replay the same fixtures.
|
|
225
|
+
*
|
|
226
|
+
* - A sender's stream starts with the first packet it accepts, which plays `targetDelayMs` after
|
|
227
|
+
* it arrived; each later seq plays `frameMs` after the one before it.
|
|
228
|
+
* - {@link pull} returns the slots that are due, in seq order: the frame, or a gap (`frame:
|
|
229
|
+
* null`) when it is missing. After the last packet before silence ({@link VoiceFlag.SPURT_END})
|
|
230
|
+
* the stream reports nothing more. It reports slots only until `resetAfterMs` after the last
|
|
231
|
+
* packet it accepted, and is then reset.
|
|
232
|
+
* - A packet is late, and dropped, when its slot has passed or has been played. One older than the
|
|
233
|
+
* first slot of a spurt that has not started playing is fitted in front of it while its slot is
|
|
234
|
+
* still ahead.
|
|
235
|
+
* - The stream starts over, dropping what it holds, on a packet that starts a talk spurt and is
|
|
236
|
+
* newer than every packet it accepted; on a packet newer than the spurt's last packet before
|
|
237
|
+
* silence; on a change of codec or frame duration; on a packet `maxFrames` or more seqs ahead of
|
|
238
|
+
* the next one to play; and on any packet after `resetAfterMs` without one accepted. A sender
|
|
239
|
+
* that restarts its seq lower is dropped as late until then.
|
|
240
|
+
* - A sender holds at most `maxFrames` frames.
|
|
241
|
+
*
|
|
242
|
+
* The frame duration is fixed within a talk spurt, and so is the delay once the spurt starts: a
|
|
243
|
+
* sender whose clock runs fast fills the window, one that runs slow underruns, and both recover at
|
|
244
|
+
* the next spurt.
|
|
245
|
+
*/
|
|
246
|
+
export class VoiceJitterBuffer {
|
|
247
|
+
/**
|
|
248
|
+
* @throws {RangeError} for a negative `targetDelayMs`, a `maxFrames` outside 1-4096, or a
|
|
249
|
+
* `resetAfterMs` not above `targetDelayMs`.
|
|
250
|
+
*/
|
|
251
|
+
constructor(options = {}) {
|
|
252
|
+
/** Packets dropped because their slot had passed. */
|
|
253
|
+
this.late = 0;
|
|
254
|
+
/** Packets dropped because their seq was already buffered. */
|
|
255
|
+
this.duplicates = 0;
|
|
256
|
+
/** Packets refused as not voice v1 (or with a frame duration of 0). */
|
|
257
|
+
this.malformed = 0;
|
|
258
|
+
/** Buffered frames thrown away unplayed (a stream started over, went silent, or was forgotten). */
|
|
259
|
+
this.discarded = 0;
|
|
260
|
+
/** Slots reported as gaps. */
|
|
261
|
+
this.gaps = 0;
|
|
262
|
+
this.streams = new Map();
|
|
263
|
+
this.targetDelayMs = options.targetDelayMs ?? VOICE_TARGET_DELAY_MS;
|
|
264
|
+
this.maxFrames = options.maxFrames ?? VOICE_JITTER_MAX_FRAMES;
|
|
265
|
+
this.resetAfterMs = options.resetAfterMs ?? VOICE_RESET_AFTER_MS;
|
|
266
|
+
if (!Number.isInteger(this.targetDelayMs) || this.targetDelayMs < 0) {
|
|
267
|
+
throw new RangeError(`targetDelayMs must be a non-negative integer, got ${this.targetDelayMs}`);
|
|
268
|
+
}
|
|
269
|
+
if (!Number.isInteger(this.maxFrames) || this.maxFrames < 1 || this.maxFrames > 4096) {
|
|
270
|
+
throw new RangeError(`maxFrames must be 1-4096, got ${this.maxFrames}`);
|
|
271
|
+
}
|
|
272
|
+
if (!Number.isInteger(this.resetAfterMs) || this.resetAfterMs <= this.targetDelayMs) {
|
|
273
|
+
throw new RangeError(`resetAfterMs must be an integer above targetDelayMs (${this.targetDelayMs}), got ${this.resetAfterMs}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/** Add one packet from the sender `key`. Never throws on the packet's contents. */
|
|
277
|
+
push(key, packet, nowMs = Date.now()) {
|
|
278
|
+
const parsed = decodeVoicePacket(packet);
|
|
279
|
+
if (!parsed || parsed.header.frameMs === 0) {
|
|
280
|
+
this.malformed += 1;
|
|
281
|
+
return 'malformed';
|
|
282
|
+
}
|
|
283
|
+
const { header } = parsed;
|
|
284
|
+
const held = { header, frame: parsed.frame.slice() };
|
|
285
|
+
let stream = this.streams.get(key);
|
|
286
|
+
if (stream && this.startsOver(stream, header, nowMs)) {
|
|
287
|
+
this.discarded += stream.frames.size;
|
|
288
|
+
stream = undefined;
|
|
289
|
+
}
|
|
290
|
+
if (!stream) {
|
|
291
|
+
this.streams.set(key, {
|
|
292
|
+
codec: header.codec,
|
|
293
|
+
frameMs: header.frameMs,
|
|
294
|
+
nextSeq: header.seq,
|
|
295
|
+
nextAtMs: nowMs + this.targetDelayMs,
|
|
296
|
+
nextTimestamp: header.timestamp,
|
|
297
|
+
started: false,
|
|
298
|
+
highestSeq: header.seq,
|
|
299
|
+
endSeq: (header.flags & VoiceFlag.SPURT_END) !== 0 ? header.seq : null,
|
|
300
|
+
ended: false,
|
|
301
|
+
lastArrivalMs: nowMs,
|
|
302
|
+
frames: new Map([[header.seq, held]]),
|
|
303
|
+
});
|
|
304
|
+
return 'buffered';
|
|
305
|
+
}
|
|
306
|
+
const ahead = voiceSeqDiff(header.seq, stream.nextSeq);
|
|
307
|
+
const slotAtMs = stream.nextAtMs + ahead * stream.frameMs;
|
|
308
|
+
const behind = ahead < 0 &&
|
|
309
|
+
(stream.started || voiceSeqDiff(stream.highestSeq, header.seq) >= this.maxFrames);
|
|
310
|
+
if (behind || slotAtMs < nowMs) {
|
|
311
|
+
this.late += 1;
|
|
312
|
+
return 'late';
|
|
313
|
+
}
|
|
314
|
+
if (stream.frames.has(header.seq)) {
|
|
315
|
+
this.duplicates += 1;
|
|
316
|
+
return 'duplicate';
|
|
317
|
+
}
|
|
318
|
+
if (ahead < 0) {
|
|
319
|
+
stream.nextSeq = header.seq;
|
|
320
|
+
stream.nextAtMs = slotAtMs;
|
|
321
|
+
stream.nextTimestamp = header.timestamp;
|
|
322
|
+
}
|
|
323
|
+
stream.frames.set(header.seq, held);
|
|
324
|
+
stream.lastArrivalMs = nowMs;
|
|
325
|
+
if (voiceSeqDiff(header.seq, stream.highestSeq) > 0)
|
|
326
|
+
stream.highestSeq = header.seq;
|
|
327
|
+
if ((header.flags & VoiceFlag.SPURT_END) !== 0 && stream.endSeq === null) {
|
|
328
|
+
stream.endSeq = header.seq;
|
|
329
|
+
}
|
|
330
|
+
return 'buffered';
|
|
331
|
+
}
|
|
332
|
+
/** The sender's slots due by `nowMs`, in seq order. */
|
|
333
|
+
pull(key, nowMs = Date.now()) {
|
|
334
|
+
const stream = this.streams.get(key);
|
|
335
|
+
if (!stream)
|
|
336
|
+
return [];
|
|
337
|
+
const out = [];
|
|
338
|
+
const silentAtMs = stream.lastArrivalMs + this.resetAfterMs;
|
|
339
|
+
while (!stream.ended && stream.nextAtMs <= nowMs && stream.nextAtMs < silentAtMs) {
|
|
340
|
+
const seq = stream.nextSeq;
|
|
341
|
+
const held = stream.frames.get(seq);
|
|
342
|
+
if (held) {
|
|
343
|
+
stream.frames.delete(seq);
|
|
344
|
+
out.push({
|
|
345
|
+
key,
|
|
346
|
+
seq,
|
|
347
|
+
timestamp: held.header.timestamp,
|
|
348
|
+
codec: held.header.codec,
|
|
349
|
+
frameMs: held.header.frameMs,
|
|
350
|
+
flags: held.header.flags,
|
|
351
|
+
gap: false,
|
|
352
|
+
frame: held.frame,
|
|
353
|
+
});
|
|
354
|
+
stream.nextTimestamp = held.header.timestamp;
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
this.gaps += 1;
|
|
358
|
+
out.push({
|
|
359
|
+
key,
|
|
360
|
+
seq,
|
|
361
|
+
timestamp: stream.nextTimestamp,
|
|
362
|
+
codec: stream.codec,
|
|
363
|
+
frameMs: stream.frameMs,
|
|
364
|
+
flags: 0,
|
|
365
|
+
gap: true,
|
|
366
|
+
frame: null,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
stream.started = true;
|
|
370
|
+
if (stream.endSeq === seq)
|
|
371
|
+
stream.ended = true;
|
|
372
|
+
stream.nextSeq = (seq + 1) & 0xffff;
|
|
373
|
+
stream.nextAtMs += stream.frameMs;
|
|
374
|
+
stream.nextTimestamp =
|
|
375
|
+
(stream.nextTimestamp + voiceSamplesPerFrame(stream.codec, stream.frameMs)) % 0x100000000;
|
|
376
|
+
}
|
|
377
|
+
if (nowMs >= silentAtMs) {
|
|
378
|
+
this.discarded += stream.frames.size;
|
|
379
|
+
this.streams.delete(key);
|
|
380
|
+
}
|
|
381
|
+
return out;
|
|
382
|
+
}
|
|
383
|
+
/** Every sender's due slots ({@link pull} for each); senders in no particular order. */
|
|
384
|
+
poll(nowMs = Date.now()) {
|
|
385
|
+
const out = [];
|
|
386
|
+
for (const key of [...this.streams.keys()])
|
|
387
|
+
out.push(...this.pull(key, nowMs));
|
|
388
|
+
return out;
|
|
389
|
+
}
|
|
390
|
+
/** Drop a sender's stream (it left). */
|
|
391
|
+
forget(key) {
|
|
392
|
+
const stream = this.streams.get(key);
|
|
393
|
+
if (!stream)
|
|
394
|
+
return;
|
|
395
|
+
this.discarded += stream.frames.size;
|
|
396
|
+
this.streams.delete(key);
|
|
397
|
+
}
|
|
398
|
+
/** Senders with a stream. */
|
|
399
|
+
get senderCount() {
|
|
400
|
+
return this.streams.size;
|
|
401
|
+
}
|
|
402
|
+
/** Frames the sender has buffered. */
|
|
403
|
+
bufferedCount(key) {
|
|
404
|
+
return this.streams.get(key)?.frames.size ?? 0;
|
|
405
|
+
}
|
|
406
|
+
startsOver(stream, header, nowMs) {
|
|
407
|
+
if (nowMs - stream.lastArrivalMs >= this.resetAfterMs)
|
|
408
|
+
return true;
|
|
409
|
+
if (header.codec !== stream.codec || header.frameMs !== stream.frameMs)
|
|
410
|
+
return true;
|
|
411
|
+
if ((header.flags & VoiceFlag.SPURT_START) !== 0 &&
|
|
412
|
+
voiceSeqDiff(header.seq, stream.highestSeq) > 0) {
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
if (stream.endSeq !== null && voiceSeqDiff(header.seq, stream.endSeq) > 0)
|
|
416
|
+
return true;
|
|
417
|
+
return voiceSeqDiff(header.seq, stream.nextSeq) >= this.maxFrames;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
function checkField(name, value, max) {
|
|
421
|
+
if (!Number.isInteger(value) || value < 0 || value > max) {
|
|
422
|
+
throw new RangeError(`${name} must be an integer 0-${max}, got ${value}`);
|
|
423
|
+
}
|
|
424
|
+
}
|
package/dist/metrics.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export interface RealtimeMetricsSnapshot {
|
|
|
35
35
|
* method's message name (`actorUpdate`, `voxelUpdate`, `audio`, `text`,
|
|
36
36
|
* `clientEvent`, `singleActorMessage`, `channelMessage`); received kinds use
|
|
37
37
|
* the notification handler names (`actorUpdate`, `voxelUpdate`, `audio`,
|
|
38
|
-
* `text`, `clientEvent`, `serverEvent`, `singleActorMessage`,
|
|
38
|
+
* `text`, `clientEvent`, `serverEvent`, `genericSpatial`, `singleActorMessage`,
|
|
39
39
|
* `channelMessage`, `genericError`, `connectionEvent`, ...).
|
|
40
40
|
*/
|
|
41
41
|
perKind: Record<string, RealtimeMetricsKind>;
|
package/dist/realtime.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { RealtimeMetrics } from './metrics.js';
|
|
|
7
7
|
import { type UdpNotificationsSubscription } from './generated/graphql.js';
|
|
8
8
|
import { type BinaryRelaySendStats } from './binary-relay.js';
|
|
9
9
|
import type { RelaySignContext } from './binary-wire.js';
|
|
10
|
+
import type { ChannelAudioNotification, GenericSpatialNotification } from './types.js';
|
|
10
11
|
/**
|
|
11
12
|
* Lifecycle state of the realtime WebSocket connection, as reported by
|
|
12
13
|
* {@link RealtimeClient.status} and {@link RealtimeClient.onStatus}.
|
|
@@ -27,10 +28,11 @@ export type RealtimeStatus = 'idle' | 'connecting' | 'connected' | 'reconnecting
|
|
|
27
28
|
* Any single message delivered on the `udpNotifications` subscription — the
|
|
28
29
|
* union of every spatial echo/fan-out notification plus `GenericErrorResponse`
|
|
29
30
|
* and `RealtimeConnectionEvent`. This is the codegen-derived (canonical)
|
|
30
|
-
* shape, narrowed to the non-null payload
|
|
31
|
-
*
|
|
31
|
+
* shape, narrowed to the non-null payload, plus
|
|
32
|
+
* {@link GenericSpatialNotification}, which only the binary relay delivers;
|
|
33
|
+
* discriminate the members by their `__typename`.
|
|
32
34
|
*/
|
|
33
|
-
export type UdpNotification = NonNullable<UdpNotificationsSubscription['udpNotifications']
|
|
35
|
+
export type UdpNotification = NonNullable<UdpNotificationsSubscription['udpNotifications']> | GenericSpatialNotification;
|
|
34
36
|
/**
|
|
35
37
|
* The members of {@link UdpNotification} that carry a `sequenceNumber` and can
|
|
36
38
|
* therefore be correlated back to the send that produced them — the spatial
|
|
@@ -134,6 +136,13 @@ export interface UdpNotificationHandlers {
|
|
|
134
136
|
serverEvent?: (notification: Extract<UdpNotification, {
|
|
135
137
|
__typename?: 'ServerEventNotification';
|
|
136
138
|
}>) => void;
|
|
139
|
+
/**
|
|
140
|
+
* An app-defined spatial message (opcode 140, `GENERIC_SPATIAL_1`) from a nearby client or a
|
|
141
|
+
* hub; `payload` is base64 and opaque to the server. **Binary relay only**
|
|
142
|
+
* (`realtime: { binaryTransport: true }`): the GraphQL `udpNotifications` union has no member
|
|
143
|
+
* for it, so on the GraphQL transport this never fires.
|
|
144
|
+
*/
|
|
145
|
+
genericSpatial?: (notification: GenericSpatialNotification) => void;
|
|
137
146
|
/**
|
|
138
147
|
* A direct actor-to-actor message addressed specifically to you; `payload`
|
|
139
148
|
* is base64. There is no sender echo, so this only ever arrives on the
|
|
@@ -149,6 +158,13 @@ export interface UdpNotificationHandlers {
|
|
|
149
158
|
channelMessage?: (notification: Extract<UdpNotification, {
|
|
150
159
|
__typename?: 'ChannelMessageNotification';
|
|
151
160
|
}>) => void;
|
|
161
|
+
/**
|
|
162
|
+
* Channel audio (opcode 36) from another member of a channel you belong to;
|
|
163
|
+
* `audioData` is base64 and opaque to the server (one `VoicePacketizer` packet
|
|
164
|
+
* with the SDK voice helpers). The sender gets no echo. Arrives on the binary
|
|
165
|
+
* relay and on the GraphQL transport alike.
|
|
166
|
+
*/
|
|
167
|
+
channelAudio?: (notification: ChannelAudioNotification) => void;
|
|
152
168
|
/**
|
|
153
169
|
* An asynchronous error for a previously sent datagram. Correlate it to the
|
|
154
170
|
* originating send via `sequenceNumber` and read `errorCode`
|
package/dist/realtime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAE3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"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"}
|
package/dist/realtime.js
CHANGED
|
@@ -804,12 +804,18 @@ export class RealtimeClient {
|
|
|
804
804
|
case 'ServerEventNotification':
|
|
805
805
|
handlers.serverEvent?.(notification);
|
|
806
806
|
break;
|
|
807
|
+
case 'GenericSpatialNotification':
|
|
808
|
+
handlers.genericSpatial?.(notification);
|
|
809
|
+
break;
|
|
807
810
|
case 'SingleActorMessageNotification':
|
|
808
811
|
handlers.singleActorMessage?.(notification);
|
|
809
812
|
break;
|
|
810
813
|
case 'ChannelMessageNotification':
|
|
811
814
|
handlers.channelMessage?.(notification);
|
|
812
815
|
break;
|
|
816
|
+
case 'ChannelAudioNotification':
|
|
817
|
+
handlers.channelAudio?.(notification);
|
|
818
|
+
break;
|
|
813
819
|
case 'GenericErrorResponse':
|
|
814
820
|
handlers.genericError?.(notification);
|
|
815
821
|
break;
|
|
@@ -890,8 +896,10 @@ const NOTIFICATION_KINDS = {
|
|
|
890
896
|
ClientTextNotification: 'text',
|
|
891
897
|
ClientEventNotification: 'clientEvent',
|
|
892
898
|
ServerEventNotification: 'serverEvent',
|
|
899
|
+
GenericSpatialNotification: 'genericSpatial',
|
|
893
900
|
SingleActorMessageNotification: 'singleActorMessage',
|
|
894
901
|
ChannelMessageNotification: 'channelMessage',
|
|
902
|
+
ChannelAudioNotification: 'channelAudio',
|
|
895
903
|
GenericErrorResponse: 'genericError',
|
|
896
904
|
RealtimeConnectionEvent: 'connectionEvent',
|
|
897
905
|
};
|
package/dist/stores/actors.d.ts
CHANGED
|
@@ -88,7 +88,9 @@ export interface LocalActorConfig<T> {
|
|
|
88
88
|
sendOnChange?: boolean;
|
|
89
89
|
/**
|
|
90
90
|
* With `sendOnChange`, still force a keyframe send after this many ms of
|
|
91
|
-
* dedup silence so presence never starves. Defaults to 3000.
|
|
91
|
+
* dedup silence so presence never starves. Defaults to 3000. Idle players on
|
|
92
|
+
* different servers meet at the first full update after joining (replication
|
|
93
|
+
* v0.37.0); before it, heartbeats ahead of the first update kept them apart.
|
|
92
94
|
*/
|
|
93
95
|
keyframeEveryMs?: number;
|
|
94
96
|
/** Default replication radius in chunk units (0-8). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actors.d.ts","sourceRoot":"","sources":["../../src/stores/actors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD,+EAA+E;AAC/E,MAAM,MAAM,eAAe,GAAG,UAAU,CACtC,WAAW,CAAC,uBAAuB,CAAC,aAAa,CAAC,CAAC,CACpD,CAAC,CAAC,CAAC,CAAC;AAEL,mCAAmC;AACnC,MAAM,MAAM,gBAAgB,GAAG,UAAU,CACvC,WAAW,CAAC,uBAAuB,CAAC,cAAc,CAAC,CAAC,CACrD,CAAC,CAAC,CAAC,CAAC;AAML,oEAAoE;AACpE,MAAM,WAAW,SAAS;IACxB,IAAI,IAAI,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,IAAI,SAAS,CAQ3C;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,SAAwB,GAAG,SAAS,CAmB5E;AAMD,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAClB,MAAM,GACN,MAAM,GACN,UAAU,GACV,UAAU,GACV,QAAQ,GACR,YAAY,GACZ,SAAS,CAAC;AAEd,2DAA2D;AAC3D,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,qCAAqC;IACrC,KAAK,EAAE,CAAC,CAAC;IACT,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,qBAAqB,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,6CAA6C;IAC7C,KAAK,EAAE,CAAC,CAAC;IACT,sCAAsC;IACtC,YAAY,EAAE,eAAe,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAOD,kDAAkD;AAClD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAEtE,4CAA4C;AAC5C,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,2EAA2E;IAC3E,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACrB,wEAAwE;IACxE,YAAY,EAAE,CAAC,CAAC;IAChB,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAChC;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB
|
|
1
|
+
{"version":3,"file":"actors.d.ts","sourceRoot":"","sources":["../../src/stores/actors.ts"],"names":[],"mappings":"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"}
|