@mml-io/delta-net-server 0.26.1 → 0.27.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 +2 -2
- package/build/DeltaNetConnection.d.ts +26 -0
- package/build/DeltaNetConnection.d.ts.map +1 -0
- package/build/DeltaNetServer.d.ts +36 -23
- package/build/DeltaNetServer.d.ts.map +1 -1
- package/build/DeltaNetV01Connection.d.ts +5 -24
- package/build/DeltaNetV01Connection.d.ts.map +1 -1
- package/build/DeltaNetV02Connection.d.ts +7 -0
- package/build/DeltaNetV02Connection.d.ts.map +1 -0
- package/build/createDeltaNetServerConnectionForWebsocket.d.ts +13 -3
- package/build/createDeltaNetServerConnectionForWebsocket.d.ts.map +1 -1
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +394 -256
- package/build/index.js.map +4 -4
- package/package.json +8 -3
package/build/index.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
// src/DeltaNetServer.ts
|
|
2
2
|
import {
|
|
3
3
|
BufferWriter,
|
|
4
|
+
DeltaNetServerErrors as DeltaNetServerErrors3,
|
|
5
|
+
deltaNetSupportedSubProtocols as deltaNetSupportedSubProtocols2,
|
|
6
|
+
deltaNetProtocolSubProtocol_v0_1 as deltaNetProtocolSubProtocol_v0_14,
|
|
7
|
+
deltaNetProtocolSubProtocol_v0_2 as deltaNetProtocolSubProtocol_v0_24,
|
|
4
8
|
encodeInitialCheckout,
|
|
5
|
-
|
|
9
|
+
encodeInitialCheckoutV02,
|
|
10
|
+
encodeServerCustom,
|
|
6
11
|
encodeTick,
|
|
7
|
-
|
|
12
|
+
encodeTickV02
|
|
8
13
|
} from "@mml-io/delta-net-protocol";
|
|
9
14
|
|
|
10
15
|
// src/ComponentCollection.ts
|
|
@@ -136,17 +141,26 @@ var ComponentCollection = class _ComponentCollection {
|
|
|
136
141
|
|
|
137
142
|
// src/createDeltaNetServerConnectionForWebsocket.ts
|
|
138
143
|
import {
|
|
139
|
-
|
|
144
|
+
deltaNetSupportedSubProtocols,
|
|
145
|
+
DeltaNetServerErrors as DeltaNetServerErrors2,
|
|
146
|
+
deltaNetProtocolSubProtocol_v0_1 as deltaNetProtocolSubProtocol_v0_13,
|
|
147
|
+
deltaNetProtocolSubProtocol_v0_2 as deltaNetProtocolSubProtocol_v0_23,
|
|
148
|
+
encodeError
|
|
140
149
|
} from "@mml-io/delta-net-protocol";
|
|
141
150
|
|
|
142
151
|
// src/DeltaNetV01Connection.ts
|
|
143
152
|
import {
|
|
144
|
-
|
|
153
|
+
deltaNetProtocolSubProtocol_v0_1 as deltaNetProtocolSubProtocol_v0_12,
|
|
154
|
+
encodeServerMessage
|
|
155
|
+
} from "@mml-io/delta-net-protocol";
|
|
156
|
+
|
|
157
|
+
// src/DeltaNetConnection.ts
|
|
158
|
+
import {
|
|
145
159
|
BufferReader,
|
|
146
160
|
decodeClientMessages,
|
|
147
|
-
|
|
161
|
+
DeltaNetServerErrors
|
|
148
162
|
} from "@mml-io/delta-net-protocol";
|
|
149
|
-
var
|
|
163
|
+
var DeltaNetConnection = class {
|
|
150
164
|
constructor(webSocket, deltaNetServer) {
|
|
151
165
|
this.webSocket = webSocket;
|
|
152
166
|
this.deltaNetServer = deltaNetServer;
|
|
@@ -159,7 +173,7 @@ var DeltaNetV01Connection = class {
|
|
|
159
173
|
new Error(
|
|
160
174
|
`Message size ${buffer.length} bytes exceeds maximum allowed size of ${maxMessageSize} bytes`
|
|
161
175
|
),
|
|
162
|
-
|
|
176
|
+
DeltaNetServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
163
177
|
false
|
|
164
178
|
);
|
|
165
179
|
return;
|
|
@@ -174,14 +188,13 @@ var DeltaNetV01Connection = class {
|
|
|
174
188
|
new Error(
|
|
175
189
|
`Failed to decode client messages: ${error instanceof Error ? error.message : error}`
|
|
176
190
|
),
|
|
177
|
-
|
|
191
|
+
DeltaNetServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
178
192
|
false
|
|
179
193
|
);
|
|
180
194
|
return;
|
|
181
195
|
}
|
|
182
196
|
};
|
|
183
197
|
webSocket.addEventListener("message", this.websocketListener);
|
|
184
|
-
this.deltaNetServer = deltaNetServer;
|
|
185
198
|
}
|
|
186
199
|
websocketListener;
|
|
187
200
|
internalConnectionId;
|
|
@@ -194,19 +207,19 @@ var DeltaNetV01Connection = class {
|
|
|
194
207
|
pendingStateValidations = /* @__PURE__ */ new Map();
|
|
195
208
|
nextValidationId = 1;
|
|
196
209
|
// Track authentication state
|
|
197
|
-
|
|
198
|
-
isAuthenticating = false;
|
|
210
|
+
authState = "pending";
|
|
199
211
|
authenticationAbortController = null;
|
|
200
|
-
sendMessage(message) {
|
|
201
|
-
this.sendEncodedBytes(encodeServerMessage(message).getBuffer());
|
|
202
|
-
}
|
|
203
212
|
sendEncodedBytes(bytes) {
|
|
213
|
+
if (this.webSocket.readyState !== 1) {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
204
216
|
this.webSocket.send(bytes);
|
|
217
|
+
return true;
|
|
205
218
|
}
|
|
206
219
|
dispose() {
|
|
207
220
|
this.webSocket.removeEventListener("message", this.websocketListener);
|
|
208
|
-
for (const
|
|
209
|
-
|
|
221
|
+
for (const { abortController } of this.pendingStateValidations.values()) {
|
|
222
|
+
abortController.abort();
|
|
210
223
|
}
|
|
211
224
|
this.pendingStateValidations.clear();
|
|
212
225
|
if (this.authenticationAbortController) {
|
|
@@ -215,7 +228,7 @@ var DeltaNetV01Connection = class {
|
|
|
215
228
|
}
|
|
216
229
|
}
|
|
217
230
|
setAuthenticated() {
|
|
218
|
-
this.
|
|
231
|
+
this.authState = "authenticated";
|
|
219
232
|
}
|
|
220
233
|
disconnectWithError(error, errorType, retryable = true) {
|
|
221
234
|
try {
|
|
@@ -229,34 +242,53 @@ var DeltaNetV01Connection = class {
|
|
|
229
242
|
console.warn("Failed to send error message to client:", sendError);
|
|
230
243
|
}
|
|
231
244
|
try {
|
|
232
|
-
|
|
245
|
+
const encoder = new TextEncoder();
|
|
246
|
+
const buf = new Uint8Array(123);
|
|
247
|
+
const { written } = encoder.encodeInto(error.message, buf);
|
|
248
|
+
const reason = new TextDecoder().decode(buf.subarray(0, written));
|
|
249
|
+
this.webSocket.close(1008, reason);
|
|
233
250
|
} catch (closeError) {
|
|
234
251
|
console.warn("Failed to close websocket connection:", closeError);
|
|
235
252
|
}
|
|
253
|
+
this.deltaNetServer.removeWebSocket(this.webSocket);
|
|
236
254
|
}
|
|
237
255
|
async handleConnectUser(token, observer, components, states) {
|
|
238
256
|
var _a, _b;
|
|
239
|
-
if (this.
|
|
257
|
+
if (this.authState === "authenticated") {
|
|
240
258
|
this.disconnectWithError(
|
|
241
259
|
new Error("User is already authenticated"),
|
|
242
|
-
|
|
260
|
+
DeltaNetServerErrors.USER_ALREADY_AUTHENTICATED_ERROR_TYPE,
|
|
243
261
|
false
|
|
244
262
|
);
|
|
245
263
|
return;
|
|
246
264
|
}
|
|
247
|
-
if (this.
|
|
265
|
+
if (this.authState === "authenticating") {
|
|
248
266
|
this.disconnectWithError(
|
|
249
267
|
new Error("Authentication already in progress"),
|
|
250
|
-
|
|
268
|
+
DeltaNetServerErrors.AUTHENTICATION_IN_PROGRESS_ERROR_TYPE,
|
|
251
269
|
false
|
|
252
270
|
);
|
|
253
271
|
return;
|
|
254
272
|
}
|
|
255
|
-
this.
|
|
273
|
+
if (this.authState === "failed") {
|
|
274
|
+
this.disconnectWithError(
|
|
275
|
+
new Error("Authentication has already failed for this connection"),
|
|
276
|
+
DeltaNetServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
277
|
+
false
|
|
278
|
+
);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
this.authState = "authenticating";
|
|
256
282
|
this.authenticationAbortController = new AbortController();
|
|
257
283
|
this.isObserver = observer;
|
|
258
|
-
this.components
|
|
259
|
-
|
|
284
|
+
this.components.clear();
|
|
285
|
+
for (const [id, value] of components) {
|
|
286
|
+
this.components.set(id, value);
|
|
287
|
+
}
|
|
288
|
+
this.states.clear();
|
|
289
|
+
for (const [id, value] of states) {
|
|
290
|
+
this.states.set(id, value);
|
|
291
|
+
}
|
|
260
292
|
let result;
|
|
261
293
|
try {
|
|
262
294
|
const rawResult = this.deltaNetServer.validateJoiner(this, token, components, states);
|
|
@@ -275,21 +307,24 @@ var DeltaNetV01Connection = class {
|
|
|
275
307
|
if ((_b = this.authenticationAbortController) == null ? void 0 : _b.signal.aborted) {
|
|
276
308
|
return;
|
|
277
309
|
}
|
|
278
|
-
result = error;
|
|
310
|
+
result = error instanceof Error ? error : new Error(String(error));
|
|
279
311
|
}
|
|
280
312
|
this.authenticationAbortController = null;
|
|
281
313
|
if (result instanceof DeltaNetServerError) {
|
|
314
|
+
this.authState = "failed";
|
|
282
315
|
this.disconnectWithError(result, result.errorType, result.retryable);
|
|
283
316
|
} else if (result instanceof Error) {
|
|
317
|
+
this.authState = "failed";
|
|
284
318
|
this.disconnectWithError(
|
|
285
319
|
result,
|
|
286
|
-
|
|
320
|
+
DeltaNetServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
287
321
|
false
|
|
288
322
|
);
|
|
289
323
|
} else if (typeof result !== "object") {
|
|
324
|
+
this.authState = "failed";
|
|
290
325
|
this.disconnectWithError(
|
|
291
326
|
new Error("Invalid authentication result"),
|
|
292
|
-
|
|
327
|
+
DeltaNetServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
293
328
|
false
|
|
294
329
|
);
|
|
295
330
|
} else {
|
|
@@ -301,17 +336,17 @@ var DeltaNetV01Connection = class {
|
|
|
301
336
|
}
|
|
302
337
|
this.deltaNetServer.addAuthenticatedConnection(this);
|
|
303
338
|
} else {
|
|
339
|
+
this.authState = "failed";
|
|
304
340
|
this.disconnectWithError(
|
|
305
341
|
new Error(result.error || "Authentication failed"),
|
|
306
|
-
|
|
342
|
+
DeltaNetServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
307
343
|
false
|
|
308
344
|
);
|
|
309
345
|
}
|
|
310
346
|
}
|
|
311
|
-
this.isAuthenticating = false;
|
|
312
347
|
}
|
|
313
348
|
async handleStateUpdate(stateId, stateValue) {
|
|
314
|
-
if (
|
|
349
|
+
if (this.authState !== "authenticated") {
|
|
315
350
|
console.error("State update received before authentication completed");
|
|
316
351
|
return;
|
|
317
352
|
}
|
|
@@ -320,15 +355,16 @@ var DeltaNetV01Connection = class {
|
|
|
320
355
|
existingValidation.abortController.abort();
|
|
321
356
|
this.pendingStateValidations.delete(stateId);
|
|
322
357
|
}
|
|
358
|
+
const abortController = new AbortController();
|
|
323
359
|
const result = this.deltaNetServer.validateAndApplyStateUpdate(
|
|
324
360
|
this,
|
|
325
361
|
this.internalConnectionId,
|
|
326
362
|
stateId,
|
|
327
|
-
stateValue
|
|
363
|
+
stateValue,
|
|
364
|
+
abortController.signal
|
|
328
365
|
);
|
|
329
366
|
if (result instanceof Promise) {
|
|
330
367
|
const validationId = this.nextValidationId++;
|
|
331
|
-
const abortController = new AbortController();
|
|
332
368
|
this.pendingStateValidations.set(stateId, { validationId, abortController });
|
|
333
369
|
try {
|
|
334
370
|
const asyncResult = await result;
|
|
@@ -344,7 +380,7 @@ var DeltaNetV01Connection = class {
|
|
|
344
380
|
if (asyncResult instanceof Error) {
|
|
345
381
|
this.disconnectWithError(
|
|
346
382
|
asyncResult,
|
|
347
|
-
|
|
383
|
+
DeltaNetServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
348
384
|
false
|
|
349
385
|
);
|
|
350
386
|
return;
|
|
@@ -359,13 +395,13 @@ var DeltaNetV01Connection = class {
|
|
|
359
395
|
} else if (error instanceof Error) {
|
|
360
396
|
this.disconnectWithError(
|
|
361
397
|
error,
|
|
362
|
-
|
|
398
|
+
DeltaNetServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
363
399
|
false
|
|
364
400
|
);
|
|
365
401
|
} else {
|
|
366
402
|
this.disconnectWithError(
|
|
367
403
|
new Error("State validation failed"),
|
|
368
|
-
|
|
404
|
+
DeltaNetServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
369
405
|
false
|
|
370
406
|
);
|
|
371
407
|
}
|
|
@@ -380,7 +416,7 @@ var DeltaNetV01Connection = class {
|
|
|
380
416
|
if (result instanceof Error) {
|
|
381
417
|
this.disconnectWithError(
|
|
382
418
|
result,
|
|
383
|
-
|
|
419
|
+
DeltaNetServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
384
420
|
false
|
|
385
421
|
);
|
|
386
422
|
return;
|
|
@@ -391,25 +427,29 @@ var DeltaNetV01Connection = class {
|
|
|
391
427
|
handleClientMessage(parsed) {
|
|
392
428
|
switch (parsed.type) {
|
|
393
429
|
case "connectUser": {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
430
|
+
this.handleConnectUser(
|
|
431
|
+
parsed.token,
|
|
432
|
+
parsed.observer,
|
|
433
|
+
parsed.components,
|
|
434
|
+
parsed.states
|
|
435
|
+
).catch((error) => {
|
|
436
|
+
console.error("Unhandled error in handleConnectUser:", error);
|
|
437
|
+
});
|
|
397
438
|
return;
|
|
398
439
|
}
|
|
399
440
|
case "pong":
|
|
400
441
|
return;
|
|
401
442
|
case "setUserComponents": {
|
|
402
|
-
if (
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
});
|
|
443
|
+
if (this.authState !== "authenticated") {
|
|
444
|
+
try {
|
|
445
|
+
this.sendMessage({
|
|
446
|
+
type: "error",
|
|
447
|
+
errorType: DeltaNetServerErrors.USER_NOT_AUTHENTICATED_ERROR_TYPE,
|
|
448
|
+
message: `Event sent, but user has not been authenticated yet.`,
|
|
449
|
+
retryable: false
|
|
450
|
+
});
|
|
451
|
+
} catch {
|
|
452
|
+
}
|
|
413
453
|
console.error("Event sent, but user has not been authenticated yet.");
|
|
414
454
|
this.webSocket.close(1e3, "User has not been authenticated yet");
|
|
415
455
|
return;
|
|
@@ -422,28 +462,29 @@ var DeltaNetV01Connection = class {
|
|
|
422
462
|
if (!result.success) {
|
|
423
463
|
this.disconnectWithError(
|
|
424
464
|
new Error(result.error),
|
|
425
|
-
|
|
465
|
+
DeltaNetServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
426
466
|
true
|
|
427
467
|
);
|
|
428
468
|
return;
|
|
429
469
|
}
|
|
430
470
|
for (const [stateId, stateValue] of parsed.states) {
|
|
431
|
-
this.handleStateUpdate(stateId, stateValue)
|
|
471
|
+
this.handleStateUpdate(stateId, stateValue).catch((error) => {
|
|
472
|
+
console.error("Unhandled error in handleStateUpdate:", error);
|
|
473
|
+
});
|
|
432
474
|
}
|
|
433
475
|
return;
|
|
434
476
|
}
|
|
435
477
|
case "clientCustom": {
|
|
436
|
-
if (
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
});
|
|
478
|
+
if (this.authState !== "authenticated") {
|
|
479
|
+
try {
|
|
480
|
+
this.sendMessage({
|
|
481
|
+
type: "error",
|
|
482
|
+
errorType: DeltaNetServerErrors.USER_NOT_AUTHENTICATED_ERROR_TYPE,
|
|
483
|
+
message: `Custom message sent, but user has not been authenticated yet.`,
|
|
484
|
+
retryable: false
|
|
485
|
+
});
|
|
486
|
+
} catch {
|
|
487
|
+
}
|
|
447
488
|
console.error("Custom message sent, but user has not been authenticated yet.");
|
|
448
489
|
this.webSocket.close(1e3, "User has not been authenticated yet");
|
|
449
490
|
return;
|
|
@@ -462,29 +503,55 @@ var DeltaNetV01Connection = class {
|
|
|
462
503
|
}
|
|
463
504
|
};
|
|
464
505
|
|
|
506
|
+
// src/DeltaNetV01Connection.ts
|
|
507
|
+
var DeltaNetV01Connection = class extends DeltaNetConnection {
|
|
508
|
+
protocolVersion = deltaNetProtocolSubProtocol_v0_12;
|
|
509
|
+
sendMessage(message) {
|
|
510
|
+
return this.sendEncodedBytes(encodeServerMessage(message).getBuffer());
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
// src/DeltaNetV02Connection.ts
|
|
515
|
+
import {
|
|
516
|
+
deltaNetProtocolSubProtocol_v0_2 as deltaNetProtocolSubProtocol_v0_22,
|
|
517
|
+
encodeServerMessageV02
|
|
518
|
+
} from "@mml-io/delta-net-protocol";
|
|
519
|
+
var DeltaNetV02Connection = class extends DeltaNetConnection {
|
|
520
|
+
protocolVersion = deltaNetProtocolSubProtocol_v0_22;
|
|
521
|
+
sendMessage(message) {
|
|
522
|
+
return this.sendEncodedBytes(encodeServerMessageV02(message).getBuffer());
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
|
|
465
526
|
// src/createDeltaNetServerConnectionForWebsocket.ts
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
];
|
|
469
|
-
function IsRecognizedWebsocketSubProtocol(protocol) {
|
|
470
|
-
return SupportedWebsocketSubProtocolsPreferenceOrder.includes(protocol);
|
|
527
|
+
function isRecognizedDeltaNetSubProtocol(protocol) {
|
|
528
|
+
return deltaNetSupportedSubProtocols.includes(protocol);
|
|
471
529
|
}
|
|
472
|
-
function createDeltaNetServerConnectionForWebsocket(webSocket, deltaNetServer) {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
webSocket.send(
|
|
530
|
+
function createDeltaNetServerConnectionForWebsocket(webSocket, deltaNetServer, deltaNetSubProtocol) {
|
|
531
|
+
const protocol = deltaNetSubProtocol ?? webSocket.protocol;
|
|
532
|
+
if (!protocol || !isRecognizedDeltaNetSubProtocol(protocol)) {
|
|
533
|
+
const errorMessageString = `Unsupported websocket subprotocol: ${protocol ?? "none"}. Supported: ${deltaNetSupportedSubProtocols.join(", ")}`;
|
|
534
|
+
console.warn(errorMessageString);
|
|
535
|
+
const encoded = encodeError({
|
|
536
|
+
type: "error",
|
|
537
|
+
errorType: DeltaNetServerErrors2.UNSUPPORTED_WEBSOCKET_SUBPROTOCOL_ERROR_TYPE,
|
|
538
|
+
message: errorMessageString,
|
|
539
|
+
retryable: false
|
|
540
|
+
});
|
|
541
|
+
webSocket.send(encoded.getBuffer());
|
|
484
542
|
webSocket.close();
|
|
485
543
|
return null;
|
|
486
544
|
}
|
|
487
|
-
|
|
545
|
+
switch (protocol) {
|
|
546
|
+
case deltaNetProtocolSubProtocol_v0_23:
|
|
547
|
+
return new DeltaNetV02Connection(webSocket, deltaNetServer);
|
|
548
|
+
case deltaNetProtocolSubProtocol_v0_13:
|
|
549
|
+
return new DeltaNetV01Connection(webSocket, deltaNetServer);
|
|
550
|
+
default: {
|
|
551
|
+
const _exhaustive = protocol;
|
|
552
|
+
throw new Error(`Unhandled protocol version: ${_exhaustive}`);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
488
555
|
}
|
|
489
556
|
|
|
490
557
|
// src/StateCollection.ts
|
|
@@ -572,53 +639,62 @@ var DeltaNetServer2 = class {
|
|
|
572
639
|
};
|
|
573
640
|
connectionIdToComponentIndex = /* @__PURE__ */ new Map();
|
|
574
641
|
componentIndexToConnectionId = /* @__PURE__ */ new Map();
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
642
|
+
connectionIdToConnection = /* @__PURE__ */ new Map();
|
|
643
|
+
allConnections = /* @__PURE__ */ new Set();
|
|
644
|
+
authenticatedConnections = /* @__PURE__ */ new Set();
|
|
645
|
+
authenticatedV01Connections = /* @__PURE__ */ new Set();
|
|
646
|
+
authenticatedV02Connections = /* @__PURE__ */ new Set();
|
|
578
647
|
observerConnections = /* @__PURE__ */ new Set();
|
|
579
648
|
// Track observer connections separately
|
|
580
|
-
|
|
649
|
+
webSocketToConnection = /* @__PURE__ */ new Map();
|
|
581
650
|
components = /* @__PURE__ */ new Map();
|
|
582
651
|
states = /* @__PURE__ */ new Map();
|
|
583
652
|
documentEffectiveStartTime = Date.now();
|
|
584
|
-
pingCounter = 1;
|
|
585
653
|
disposed = false;
|
|
586
654
|
maxStateValueSize;
|
|
587
655
|
maxMessageSize;
|
|
588
656
|
static handleWebsocketSubprotocol(protocols) {
|
|
589
657
|
const protocolsSet = new Set(protocols);
|
|
590
|
-
for (const protocol of
|
|
658
|
+
for (const protocol of deltaNetSupportedSubProtocols2) {
|
|
591
659
|
if (protocolsSet.has(protocol)) {
|
|
592
660
|
return protocol;
|
|
593
661
|
}
|
|
594
662
|
}
|
|
595
663
|
return false;
|
|
596
664
|
}
|
|
597
|
-
|
|
665
|
+
/**
|
|
666
|
+
* @param webSocket The upgraded WebSocket.
|
|
667
|
+
* @param deltaNetSubProtocol Optional explicit delta-net sub-protocol
|
|
668
|
+
* version. When provided, `webSocket.protocol` is ignored for version
|
|
669
|
+
* selection. This allows a higher-level protocol to be negotiated at the
|
|
670
|
+
* WebSocket level while the delta-net version is supplied by the caller.
|
|
671
|
+
*/
|
|
672
|
+
addWebSocket(webSocket, deltaNetSubProtocol) {
|
|
598
673
|
if (this.disposed) {
|
|
599
674
|
throw new Error("This DeltaNetServer has been disposed");
|
|
600
675
|
}
|
|
601
|
-
const
|
|
602
|
-
|
|
676
|
+
const connection = createDeltaNetServerConnectionForWebsocket(
|
|
677
|
+
webSocket,
|
|
678
|
+
this,
|
|
679
|
+
deltaNetSubProtocol
|
|
680
|
+
);
|
|
681
|
+
if (connection === null) {
|
|
603
682
|
return;
|
|
604
683
|
}
|
|
605
|
-
this.
|
|
606
|
-
this.
|
|
607
|
-
deltaNetV01Connection.webSocket,
|
|
608
|
-
deltaNetV01Connection
|
|
609
|
-
);
|
|
684
|
+
this.allConnections.add(connection);
|
|
685
|
+
this.webSocketToConnection.set(connection.webSocket, connection);
|
|
610
686
|
}
|
|
611
687
|
removeWebSocket(webSocket) {
|
|
612
|
-
const
|
|
613
|
-
if (
|
|
688
|
+
const connection = this.webSocketToConnection.get(webSocket);
|
|
689
|
+
if (connection === void 0) {
|
|
614
690
|
return;
|
|
615
691
|
}
|
|
616
|
-
if (!this.
|
|
692
|
+
if (!this.allConnections.has(connection)) {
|
|
617
693
|
return;
|
|
618
694
|
}
|
|
619
|
-
|
|
695
|
+
connection.dispose();
|
|
620
696
|
if (!this.disposed && this.opts.onLeave) {
|
|
621
|
-
const internalConnectionId2 =
|
|
697
|
+
const internalConnectionId2 = connection.internalConnectionId;
|
|
622
698
|
const index = this.connectionIdToComponentIndex.get(internalConnectionId2);
|
|
623
699
|
if (index !== void 0) {
|
|
624
700
|
const components = [];
|
|
@@ -637,7 +713,7 @@ var DeltaNetServer2 = class {
|
|
|
637
713
|
}
|
|
638
714
|
try {
|
|
639
715
|
this.opts.onLeave({
|
|
640
|
-
|
|
716
|
+
connection,
|
|
641
717
|
internalConnectionId: internalConnectionId2,
|
|
642
718
|
components,
|
|
643
719
|
states
|
|
@@ -645,25 +721,66 @@ var DeltaNetServer2 = class {
|
|
|
645
721
|
} catch (error) {
|
|
646
722
|
console.warn("Error in onLeave callback:", error);
|
|
647
723
|
}
|
|
724
|
+
} else if (connection.isObserver) {
|
|
725
|
+
try {
|
|
726
|
+
this.opts.onLeave({
|
|
727
|
+
connection,
|
|
728
|
+
internalConnectionId: internalConnectionId2,
|
|
729
|
+
components: [],
|
|
730
|
+
states: []
|
|
731
|
+
});
|
|
732
|
+
} catch (error) {
|
|
733
|
+
console.warn("Error in onLeave callback for observer:", error);
|
|
734
|
+
}
|
|
648
735
|
}
|
|
649
736
|
}
|
|
650
|
-
const internalConnectionId =
|
|
651
|
-
this.
|
|
652
|
-
if (this.preTickData.newJoinerConnections.has(
|
|
653
|
-
this.preTickData.newJoinerConnections.delete(
|
|
737
|
+
const internalConnectionId = connection.internalConnectionId;
|
|
738
|
+
this.connectionIdToConnection.delete(internalConnectionId);
|
|
739
|
+
if (this.preTickData.newJoinerConnections.has(connection)) {
|
|
740
|
+
this.preTickData.newJoinerConnections.delete(connection);
|
|
654
741
|
} else {
|
|
655
742
|
const index = this.connectionIdToComponentIndex.get(internalConnectionId);
|
|
656
743
|
if (index !== void 0) {
|
|
657
744
|
this.clearInternalConnectionId(internalConnectionId);
|
|
658
745
|
}
|
|
659
746
|
}
|
|
660
|
-
this.
|
|
661
|
-
this.observerConnections.delete(
|
|
662
|
-
this.
|
|
663
|
-
this.
|
|
747
|
+
this.removeFromAuthenticatedSets(connection);
|
|
748
|
+
this.observerConnections.delete(connection);
|
|
749
|
+
this.allConnections.delete(connection);
|
|
750
|
+
this.webSocketToConnection.delete(connection.webSocket);
|
|
664
751
|
}
|
|
665
752
|
hasWebSocket(webSocket) {
|
|
666
|
-
return this.
|
|
753
|
+
return this.webSocketToConnection.has(webSocket);
|
|
754
|
+
}
|
|
755
|
+
addToAuthenticatedSets(connection) {
|
|
756
|
+
this.authenticatedConnections.add(connection);
|
|
757
|
+
switch (connection.protocolVersion) {
|
|
758
|
+
case deltaNetProtocolSubProtocol_v0_14:
|
|
759
|
+
this.authenticatedV01Connections.add(connection);
|
|
760
|
+
break;
|
|
761
|
+
case deltaNetProtocolSubProtocol_v0_24:
|
|
762
|
+
this.authenticatedV02Connections.add(connection);
|
|
763
|
+
break;
|
|
764
|
+
default: {
|
|
765
|
+
const _exhaustive = connection.protocolVersion;
|
|
766
|
+
throw new Error(`Unknown protocol version: ${_exhaustive}`);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
removeFromAuthenticatedSets(connection) {
|
|
771
|
+
this.authenticatedConnections.delete(connection);
|
|
772
|
+
switch (connection.protocolVersion) {
|
|
773
|
+
case deltaNetProtocolSubProtocol_v0_14:
|
|
774
|
+
this.authenticatedV01Connections.delete(connection);
|
|
775
|
+
break;
|
|
776
|
+
case deltaNetProtocolSubProtocol_v0_24:
|
|
777
|
+
this.authenticatedV02Connections.delete(connection);
|
|
778
|
+
break;
|
|
779
|
+
default: {
|
|
780
|
+
const _exhaustive = connection.protocolVersion;
|
|
781
|
+
throw new Error(`Unknown protocol version: ${_exhaustive}`);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
667
784
|
}
|
|
668
785
|
dangerouslyGetConnectionsToComponentIndex() {
|
|
669
786
|
return this.connectionIdToComponentIndex;
|
|
@@ -671,28 +788,6 @@ var DeltaNetServer2 = class {
|
|
|
671
788
|
dangerouslyAddNewJoinerCallback(callback) {
|
|
672
789
|
this.preTickData.newJoinerCallbacks.add(callback);
|
|
673
790
|
}
|
|
674
|
-
disconnectWithError(deltaNetV01Connection, error, errorType, retryable = true) {
|
|
675
|
-
try {
|
|
676
|
-
deltaNetV01Connection.sendMessage({
|
|
677
|
-
type: "error",
|
|
678
|
-
errorType,
|
|
679
|
-
message: error.message,
|
|
680
|
-
retryable
|
|
681
|
-
});
|
|
682
|
-
} catch (sendError) {
|
|
683
|
-
console.warn("Failed to send error message to client:", sendError);
|
|
684
|
-
}
|
|
685
|
-
try {
|
|
686
|
-
deltaNetV01Connection.webSocket.close(1008, error.message);
|
|
687
|
-
} catch (closeError) {
|
|
688
|
-
console.warn("Failed to close websocket connection:", closeError);
|
|
689
|
-
}
|
|
690
|
-
try {
|
|
691
|
-
this.removeWebSocket(deltaNetV01Connection.webSocket);
|
|
692
|
-
} catch (cleanupError) {
|
|
693
|
-
console.warn("Failed to clean up connection state:", cleanupError);
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
791
|
getComponentValue(componentId, componentIndex) {
|
|
697
792
|
const componentCollection = this.components.get(componentId);
|
|
698
793
|
if (componentCollection === void 0) {
|
|
@@ -706,7 +801,7 @@ var DeltaNetServer2 = class {
|
|
|
706
801
|
getMaxMessageSize() {
|
|
707
802
|
return this.maxMessageSize;
|
|
708
803
|
}
|
|
709
|
-
validateJoiner(
|
|
804
|
+
validateJoiner(connection, token, components, states) {
|
|
710
805
|
if (this.disposed) {
|
|
711
806
|
return { success: false, error: "This DeltaNetServer has been disposed" };
|
|
712
807
|
}
|
|
@@ -735,16 +830,18 @@ var DeltaNetServer2 = class {
|
|
|
735
830
|
}
|
|
736
831
|
if (this.opts.onJoiner) {
|
|
737
832
|
const rawResult = this.opts.onJoiner({
|
|
738
|
-
|
|
833
|
+
connection,
|
|
739
834
|
components,
|
|
740
835
|
states,
|
|
741
836
|
token,
|
|
742
|
-
internalConnectionId:
|
|
837
|
+
internalConnectionId: connection.internalConnectionId
|
|
743
838
|
});
|
|
744
839
|
if (rawResult instanceof Promise) {
|
|
745
|
-
return rawResult.then(
|
|
746
|
-
|
|
747
|
-
|
|
840
|
+
return rawResult.then(
|
|
841
|
+
(resolvedResult) => {
|
|
842
|
+
return resultToReturn(resolvedResult);
|
|
843
|
+
}
|
|
844
|
+
).catch((error) => {
|
|
748
845
|
console.warn("Error in async onJoiner callback:", error);
|
|
749
846
|
return resultToReturn(error);
|
|
750
847
|
});
|
|
@@ -754,35 +851,29 @@ var DeltaNetServer2 = class {
|
|
|
754
851
|
}
|
|
755
852
|
return { success: true };
|
|
756
853
|
}
|
|
757
|
-
addAuthenticatedConnection(
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
deltaNetV01Connection.internalConnectionId,
|
|
763
|
-
deltaNetV01Connection
|
|
764
|
-
);
|
|
765
|
-
if (deltaNetV01Connection.isObserver) {
|
|
766
|
-
this.observerConnections.add(deltaNetV01Connection);
|
|
767
|
-
this.preTickData.newJoinerConnections.add(deltaNetV01Connection);
|
|
854
|
+
addAuthenticatedConnection(connection) {
|
|
855
|
+
this.connectionIdToConnection.set(connection.internalConnectionId, connection);
|
|
856
|
+
if (connection.isObserver) {
|
|
857
|
+
this.observerConnections.add(connection);
|
|
858
|
+
this.preTickData.newJoinerConnections.add(connection);
|
|
768
859
|
} else {
|
|
769
|
-
this.preTickData.newJoinerConnections.add(
|
|
860
|
+
this.preTickData.newJoinerConnections.add(connection);
|
|
770
861
|
}
|
|
771
862
|
}
|
|
772
|
-
validateAndApplyStateUpdate(
|
|
863
|
+
validateAndApplyStateUpdate(connection, internalConnectionId, stateId, stateValue, abortSignal) {
|
|
773
864
|
if (this.disposed) {
|
|
774
865
|
return new Error("This DeltaNetServer has been disposed");
|
|
775
866
|
}
|
|
776
867
|
if (stateValue.length > this.maxStateValueSize) {
|
|
777
868
|
return new DeltaNetServerError(
|
|
778
|
-
|
|
869
|
+
DeltaNetServerErrors3.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
779
870
|
`State value for state ${stateId} has size ${stateValue.length} bytes which exceeds maximum allowed size of ${this.maxStateValueSize} bytes`,
|
|
780
871
|
false
|
|
781
872
|
);
|
|
782
873
|
}
|
|
783
|
-
if (
|
|
874
|
+
if (connection.isObserver) {
|
|
784
875
|
return new DeltaNetServerError(
|
|
785
|
-
|
|
876
|
+
DeltaNetServerErrors3.OBSERVER_CANNOT_SEND_STATE_UPDATES_ERROR_TYPE,
|
|
786
877
|
"Observers cannot send state updates",
|
|
787
878
|
false
|
|
788
879
|
);
|
|
@@ -790,28 +881,27 @@ var DeltaNetServer2 = class {
|
|
|
790
881
|
if (this.opts.onStatesUpdate) {
|
|
791
882
|
try {
|
|
792
883
|
const result = this.opts.onStatesUpdate({
|
|
793
|
-
|
|
884
|
+
connection,
|
|
794
885
|
internalConnectionId,
|
|
795
|
-
states: [[stateId, stateValue]]
|
|
886
|
+
states: [[stateId, stateValue]],
|
|
887
|
+
abortSignal
|
|
796
888
|
});
|
|
797
889
|
if (result instanceof Promise) {
|
|
798
890
|
return result.then((asyncResult) => {
|
|
799
|
-
if (!this.
|
|
891
|
+
if (!this.connectionIdToConnection.has(internalConnectionId)) {
|
|
800
892
|
return;
|
|
801
893
|
}
|
|
802
894
|
if (asyncResult instanceof DeltaNetServerError || asyncResult instanceof Error) {
|
|
803
895
|
return asyncResult;
|
|
804
896
|
}
|
|
805
897
|
if (asyncResult === true || asyncResult === void 0) {
|
|
806
|
-
this.applyStateUpdates(
|
|
807
|
-
[stateId, stateValue]
|
|
808
|
-
]);
|
|
898
|
+
this.applyStateUpdates(connection, internalConnectionId, [[stateId, stateValue]]);
|
|
809
899
|
return true;
|
|
810
900
|
}
|
|
811
901
|
if (asyncResult.success) {
|
|
812
902
|
if (asyncResult.stateOverrides) {
|
|
813
903
|
this.applyStateUpdates(
|
|
814
|
-
|
|
904
|
+
connection,
|
|
815
905
|
internalConnectionId,
|
|
816
906
|
asyncResult.stateOverrides
|
|
817
907
|
);
|
|
@@ -819,7 +909,7 @@ var DeltaNetServer2 = class {
|
|
|
819
909
|
return true;
|
|
820
910
|
} else {
|
|
821
911
|
return new DeltaNetServerError(
|
|
822
|
-
|
|
912
|
+
DeltaNetServerErrors3.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
823
913
|
"State validation failed",
|
|
824
914
|
false
|
|
825
915
|
);
|
|
@@ -839,23 +929,17 @@ var DeltaNetServer2 = class {
|
|
|
839
929
|
return result;
|
|
840
930
|
}
|
|
841
931
|
if (result === true || result === void 0) {
|
|
842
|
-
this.applyStateUpdates(
|
|
843
|
-
[stateId, stateValue]
|
|
844
|
-
]);
|
|
932
|
+
this.applyStateUpdates(connection, internalConnectionId, [[stateId, stateValue]]);
|
|
845
933
|
return true;
|
|
846
934
|
}
|
|
847
935
|
if (result.success) {
|
|
848
936
|
if (result.stateOverrides) {
|
|
849
|
-
this.applyStateUpdates(
|
|
850
|
-
deltaNetV01Connection,
|
|
851
|
-
internalConnectionId,
|
|
852
|
-
result.stateOverrides
|
|
853
|
-
);
|
|
937
|
+
this.applyStateUpdates(connection, internalConnectionId, result.stateOverrides);
|
|
854
938
|
}
|
|
855
939
|
return true;
|
|
856
940
|
} else {
|
|
857
941
|
return new DeltaNetServerError(
|
|
858
|
-
|
|
942
|
+
DeltaNetServerErrors3.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
|
|
859
943
|
"State validation failed",
|
|
860
944
|
false
|
|
861
945
|
);
|
|
@@ -872,7 +956,7 @@ var DeltaNetServer2 = class {
|
|
|
872
956
|
return new Error("State validation failed");
|
|
873
957
|
}
|
|
874
958
|
} else {
|
|
875
|
-
this.applyStateUpdates(
|
|
959
|
+
this.applyStateUpdates(connection, internalConnectionId, [[stateId, stateValue]]);
|
|
876
960
|
return true;
|
|
877
961
|
}
|
|
878
962
|
}
|
|
@@ -889,29 +973,14 @@ var DeltaNetServer2 = class {
|
|
|
889
973
|
}
|
|
890
974
|
this.preTickData.unoccupyingIndices.add(index);
|
|
891
975
|
}
|
|
892
|
-
sendPings() {
|
|
893
|
-
const ping = this.pingCounter++;
|
|
894
|
-
if (this.pingCounter > 1e3) {
|
|
895
|
-
this.pingCounter = 1;
|
|
896
|
-
}
|
|
897
|
-
const v01PingMessage = {
|
|
898
|
-
type: "ping",
|
|
899
|
-
ping
|
|
900
|
-
};
|
|
901
|
-
const writer = new BufferWriter(8);
|
|
902
|
-
encodePing(v01PingMessage, writer);
|
|
903
|
-
const v01Encoded = writer.getBuffer();
|
|
904
|
-
this.allDeltaNetV01Connections.forEach((deltaNetV01Connection) => {
|
|
905
|
-
deltaNetV01Connection.sendEncodedBytes(v01Encoded);
|
|
906
|
-
});
|
|
907
|
-
}
|
|
908
976
|
tick() {
|
|
909
977
|
if (this.disposed) {
|
|
910
|
-
return { removedIds: /* @__PURE__ */ new Set(), addedIds: /* @__PURE__ */ new Set() };
|
|
978
|
+
return { removedIds: /* @__PURE__ */ new Set(), addedIds: /* @__PURE__ */ new Set(), addedObserverIds: /* @__PURE__ */ new Set() };
|
|
911
979
|
}
|
|
912
980
|
this.preTickData.componentsUpdated = 0;
|
|
913
981
|
const removedIds = /* @__PURE__ */ new Set();
|
|
914
982
|
const addedIds = /* @__PURE__ */ new Set();
|
|
983
|
+
const addedObserverIds = /* @__PURE__ */ new Set();
|
|
915
984
|
const sortedUnoccupyingIndices = Array.from(this.preTickData.unoccupyingIndices);
|
|
916
985
|
sortedUnoccupyingIndices.sort((a, b) => a - b);
|
|
917
986
|
for (const componentCollection of this.components.values()) {
|
|
@@ -946,27 +1015,32 @@ var DeltaNetServer2 = class {
|
|
|
946
1015
|
}
|
|
947
1016
|
writeIndex++;
|
|
948
1017
|
}
|
|
1018
|
+
for (let i = writeIndex; i < this.nextIndex; i++) {
|
|
1019
|
+
this.componentIndexToConnectionId.delete(i);
|
|
1020
|
+
}
|
|
949
1021
|
this.nextIndex -= sortedUnoccupyingIndices.length;
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1022
|
+
const failedConnections = /* @__PURE__ */ new Set();
|
|
1023
|
+
for (const connection of this.preTickData.newJoinerConnections) {
|
|
1024
|
+
const internalConnectionId = connection.internalConnectionId;
|
|
1025
|
+
if (connection.isObserver) {
|
|
1026
|
+
addedObserverIds.add(internalConnectionId);
|
|
953
1027
|
} else {
|
|
954
1028
|
const index = this.nextIndex++;
|
|
955
1029
|
this.connectionIdToComponentIndex.set(internalConnectionId, index);
|
|
956
1030
|
this.componentIndexToConnectionId.set(index, internalConnectionId);
|
|
957
1031
|
addedIds.add(internalConnectionId);
|
|
958
|
-
for (const [componentId] of
|
|
1032
|
+
for (const [componentId] of connection.components) {
|
|
959
1033
|
if (!this.components.has(componentId)) {
|
|
960
1034
|
this.components.set(componentId, new ComponentCollection());
|
|
961
1035
|
}
|
|
962
1036
|
}
|
|
963
|
-
for (const [stateId] of
|
|
1037
|
+
for (const [stateId] of connection.states) {
|
|
964
1038
|
if (!this.states.has(stateId)) {
|
|
965
1039
|
this.states.set(stateId, new StateCollection());
|
|
966
1040
|
}
|
|
967
1041
|
}
|
|
968
1042
|
for (const [componentId, collection] of this.components) {
|
|
969
|
-
const value =
|
|
1043
|
+
const value = connection.components.get(componentId);
|
|
970
1044
|
if (value === void 0) {
|
|
971
1045
|
collection.setValue(index, 0n);
|
|
972
1046
|
} else {
|
|
@@ -974,11 +1048,11 @@ var DeltaNetServer2 = class {
|
|
|
974
1048
|
}
|
|
975
1049
|
}
|
|
976
1050
|
for (const [stateId, collection] of this.states) {
|
|
977
|
-
const value =
|
|
1051
|
+
const value = connection.states.get(stateId);
|
|
978
1052
|
if (this.opts.serverConnectionIdStateId !== void 0 && stateId === this.opts.serverConnectionIdStateId) {
|
|
979
|
-
const
|
|
980
|
-
|
|
981
|
-
const buffer =
|
|
1053
|
+
const writer = new BufferWriter(8);
|
|
1054
|
+
writer.writeUVarint(internalConnectionId);
|
|
1055
|
+
const buffer = writer.getBuffer();
|
|
982
1056
|
collection.setValue(index, buffer);
|
|
983
1057
|
} else {
|
|
984
1058
|
if (value === void 0) {
|
|
@@ -988,10 +1062,9 @@ var DeltaNetServer2 = class {
|
|
|
988
1062
|
}
|
|
989
1063
|
}
|
|
990
1064
|
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
});
|
|
1065
|
+
if (!connection.sendMessage({ type: "userIndex", index })) {
|
|
1066
|
+
failedConnections.add(connection);
|
|
1067
|
+
}
|
|
995
1068
|
}
|
|
996
1069
|
}
|
|
997
1070
|
for (const callback of this.preTickData.newJoinerCallbacks) {
|
|
@@ -1005,9 +1078,9 @@ var DeltaNetServer2 = class {
|
|
|
1005
1078
|
this.componentIndexToConnectionId.set(index, id);
|
|
1006
1079
|
addedIds.add(id);
|
|
1007
1080
|
if (this.opts.serverConnectionIdStateId !== void 0) {
|
|
1008
|
-
const
|
|
1009
|
-
|
|
1010
|
-
const buffer =
|
|
1081
|
+
const writer = new BufferWriter(8);
|
|
1082
|
+
writer.writeUVarint(id);
|
|
1083
|
+
const buffer = writer.getBuffer();
|
|
1011
1084
|
this.setUserState(index, this.opts.serverConnectionIdStateId, buffer);
|
|
1012
1085
|
}
|
|
1013
1086
|
if (afterAddCallback) {
|
|
@@ -1039,12 +1112,26 @@ var DeltaNetServer2 = class {
|
|
|
1039
1112
|
componentDeltaDeltas: componentDeltas,
|
|
1040
1113
|
states: stateDeltas
|
|
1041
1114
|
};
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1115
|
+
if (this.authenticatedV01Connections.size > 0) {
|
|
1116
|
+
const v01Writer = new BufferWriter(this.nextIndex * this.components.size + 128);
|
|
1117
|
+
encodeTick(tickMessage, v01Writer);
|
|
1118
|
+
const v01EncodedTick = v01Writer.getBuffer();
|
|
1119
|
+
this.authenticatedV01Connections.forEach((connection) => {
|
|
1120
|
+
if (!connection.sendEncodedBytes(v01EncodedTick)) {
|
|
1121
|
+
failedConnections.add(connection);
|
|
1122
|
+
}
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
if (this.authenticatedV02Connections.size > 0) {
|
|
1126
|
+
const v02Writer = new BufferWriter(this.nextIndex * this.components.size + 128);
|
|
1127
|
+
encodeTickV02(tickMessage, v02Writer);
|
|
1128
|
+
const v02EncodedTick = v02Writer.getBuffer();
|
|
1129
|
+
this.authenticatedV02Connections.forEach((connection) => {
|
|
1130
|
+
if (!connection.sendEncodedBytes(v02EncodedTick)) {
|
|
1131
|
+
failedConnections.add(connection);
|
|
1132
|
+
}
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1048
1135
|
if (this.preTickData.newJoinerConnections.size > 0) {
|
|
1049
1136
|
const components = [];
|
|
1050
1137
|
for (const [componentId, collection] of this.components) {
|
|
@@ -1068,40 +1155,81 @@ var DeltaNetServer2 = class {
|
|
|
1068
1155
|
indicesCount: this.nextIndex,
|
|
1069
1156
|
serverTime: this.getServerTime()
|
|
1070
1157
|
};
|
|
1071
|
-
const
|
|
1072
|
-
|
|
1073
|
-
const
|
|
1074
|
-
|
|
1075
|
-
|
|
1158
|
+
const v01NewJoiners = [];
|
|
1159
|
+
const v02NewJoiners = [];
|
|
1160
|
+
for (const connection of this.preTickData.newJoinerConnections) {
|
|
1161
|
+
switch (connection.protocolVersion) {
|
|
1162
|
+
case deltaNetProtocolSubProtocol_v0_14:
|
|
1163
|
+
v01NewJoiners.push(connection);
|
|
1164
|
+
break;
|
|
1165
|
+
case deltaNetProtocolSubProtocol_v0_24:
|
|
1166
|
+
v02NewJoiners.push(connection);
|
|
1167
|
+
break;
|
|
1168
|
+
default: {
|
|
1169
|
+
const _exhaustive = connection.protocolVersion;
|
|
1170
|
+
throw new Error(`Unknown protocol version: ${_exhaustive}`);
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
if (v01NewJoiners.length > 0) {
|
|
1175
|
+
const v01Writer = new BufferWriter(this.nextIndex * this.components.size + 128);
|
|
1176
|
+
encodeInitialCheckout(initialCheckout, v01Writer);
|
|
1177
|
+
const v01EncodedInitialCheckout = v01Writer.getBuffer();
|
|
1178
|
+
for (const connection of v01NewJoiners) {
|
|
1179
|
+
if (!connection.sendEncodedBytes(v01EncodedInitialCheckout)) {
|
|
1180
|
+
failedConnections.add(connection);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
if (v02NewJoiners.length > 0) {
|
|
1185
|
+
const v02Writer = new BufferWriter(this.nextIndex * this.components.size + 128);
|
|
1186
|
+
encodeInitialCheckoutV02(initialCheckout, v02Writer);
|
|
1187
|
+
const v02EncodedInitialCheckout = v02Writer.getBuffer();
|
|
1188
|
+
for (const connection of v02NewJoiners) {
|
|
1189
|
+
if (!connection.sendEncodedBytes(v02EncodedInitialCheckout)) {
|
|
1190
|
+
failedConnections.add(connection);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1076
1193
|
}
|
|
1077
1194
|
}
|
|
1078
|
-
for (const
|
|
1079
|
-
|
|
1080
|
-
|
|
1195
|
+
for (const connection of this.preTickData.newJoinerConnections) {
|
|
1196
|
+
if (failedConnections.has(connection)) {
|
|
1197
|
+
continue;
|
|
1198
|
+
}
|
|
1199
|
+
this.addToAuthenticatedSets(connection);
|
|
1200
|
+
connection.setAuthenticated();
|
|
1081
1201
|
}
|
|
1082
1202
|
this.preTickData.unoccupyingIndices.clear();
|
|
1083
1203
|
this.preTickData.newJoinerConnections.clear();
|
|
1084
1204
|
this.preTickData.newJoinerCallbacks.clear();
|
|
1205
|
+
for (const connection of failedConnections) {
|
|
1206
|
+
try {
|
|
1207
|
+
this.removeWebSocket(connection.webSocket);
|
|
1208
|
+
} catch (cleanupError) {
|
|
1209
|
+
console.warn("Failed to clean up connection after send failure:", cleanupError);
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1085
1212
|
return {
|
|
1086
1213
|
removedIds,
|
|
1087
|
-
addedIds
|
|
1214
|
+
addedIds,
|
|
1215
|
+
addedObserverIds
|
|
1088
1216
|
};
|
|
1089
1217
|
}
|
|
1090
1218
|
getServerTime() {
|
|
1091
1219
|
return Date.now() - this.documentEffectiveStartTime;
|
|
1092
1220
|
}
|
|
1093
|
-
setUserComponents(
|
|
1221
|
+
setUserComponents(connection, internalConnectionId, components) {
|
|
1094
1222
|
if (this.disposed) {
|
|
1095
1223
|
console.error("Cannot dispatch remote event after dispose");
|
|
1096
1224
|
return { success: false, error: "This DeltaNetServer has been disposed" };
|
|
1097
1225
|
}
|
|
1098
|
-
if (
|
|
1226
|
+
if (connection.isObserver) {
|
|
1099
1227
|
return { success: false, error: "Observers cannot send component updates" };
|
|
1100
1228
|
}
|
|
1101
1229
|
if (this.opts.onComponentsUpdate) {
|
|
1102
1230
|
try {
|
|
1103
1231
|
const result = this.opts.onComponentsUpdate({
|
|
1104
|
-
|
|
1232
|
+
connection,
|
|
1105
1233
|
internalConnectionId,
|
|
1106
1234
|
components
|
|
1107
1235
|
});
|
|
@@ -1122,7 +1250,7 @@ var DeltaNetServer2 = class {
|
|
|
1122
1250
|
return { success: false, error: "Component update failed" };
|
|
1123
1251
|
}
|
|
1124
1252
|
}
|
|
1125
|
-
this.applyComponentUpdates(
|
|
1253
|
+
this.applyComponentUpdates(connection, internalConnectionId, components);
|
|
1126
1254
|
return { success: true };
|
|
1127
1255
|
}
|
|
1128
1256
|
setComponentValue(componentId, index, value) {
|
|
@@ -1134,10 +1262,10 @@ var DeltaNetServer2 = class {
|
|
|
1134
1262
|
}
|
|
1135
1263
|
collection.setValue(index, value);
|
|
1136
1264
|
}
|
|
1137
|
-
applyComponentUpdates(
|
|
1138
|
-
if (this.preTickData.newJoinerConnections.has(
|
|
1265
|
+
applyComponentUpdates(connection, internalConnectionId, components) {
|
|
1266
|
+
if (this.preTickData.newJoinerConnections.has(connection)) {
|
|
1139
1267
|
for (const [componentId, componentValue] of components) {
|
|
1140
|
-
|
|
1268
|
+
connection.components.set(componentId, componentValue);
|
|
1141
1269
|
}
|
|
1142
1270
|
return;
|
|
1143
1271
|
}
|
|
@@ -1149,8 +1277,8 @@ var DeltaNetServer2 = class {
|
|
|
1149
1277
|
this.setComponentValue(componentId, index, componentValue);
|
|
1150
1278
|
}
|
|
1151
1279
|
}
|
|
1152
|
-
overrideUserStates(
|
|
1153
|
-
this.applyStateUpdates(
|
|
1280
|
+
overrideUserStates(connection, internalConnectionId, states) {
|
|
1281
|
+
this.applyStateUpdates(connection, internalConnectionId, states);
|
|
1154
1282
|
}
|
|
1155
1283
|
setUserState(index, stateId, stateValue) {
|
|
1156
1284
|
let collection = this.states.get(stateId);
|
|
@@ -1160,10 +1288,10 @@ var DeltaNetServer2 = class {
|
|
|
1160
1288
|
}
|
|
1161
1289
|
collection.setValue(index, stateValue);
|
|
1162
1290
|
}
|
|
1163
|
-
applyStateUpdates(
|
|
1164
|
-
if (
|
|
1291
|
+
applyStateUpdates(connection, internalConnectionId, states) {
|
|
1292
|
+
if (connection !== null && this.preTickData.newJoinerConnections.has(connection)) {
|
|
1165
1293
|
for (const [stateId, stateValue] of states) {
|
|
1166
|
-
|
|
1294
|
+
connection.states.set(stateId, stateValue);
|
|
1167
1295
|
}
|
|
1168
1296
|
return;
|
|
1169
1297
|
}
|
|
@@ -1175,14 +1303,14 @@ var DeltaNetServer2 = class {
|
|
|
1175
1303
|
this.setUserState(index, stateId, stateValue);
|
|
1176
1304
|
}
|
|
1177
1305
|
}
|
|
1178
|
-
handleCustomMessage(
|
|
1306
|
+
handleCustomMessage(connection, internalConnectionId, customType, contents) {
|
|
1179
1307
|
if (this.disposed) {
|
|
1180
1308
|
return;
|
|
1181
1309
|
}
|
|
1182
1310
|
if (this.opts.onCustomMessage) {
|
|
1183
1311
|
try {
|
|
1184
1312
|
this.opts.onCustomMessage({
|
|
1185
|
-
|
|
1313
|
+
connection,
|
|
1186
1314
|
internalConnectionId,
|
|
1187
1315
|
customType,
|
|
1188
1316
|
contents
|
|
@@ -1192,41 +1320,48 @@ var DeltaNetServer2 = class {
|
|
|
1192
1320
|
}
|
|
1193
1321
|
}
|
|
1194
1322
|
}
|
|
1323
|
+
sendCustomMessageToConnection(connectionId, customType, contents) {
|
|
1324
|
+
if (this.disposed) {
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
const connection = this.connectionIdToConnection.get(connectionId);
|
|
1328
|
+
if (!connection) {
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
const writer = new BufferWriter(contents.length + 16);
|
|
1332
|
+
encodeServerCustom({ type: "serverCustom", customType, contents }, writer);
|
|
1333
|
+
const messageBytes = writer.getBuffer();
|
|
1334
|
+
connection.sendEncodedBytes(messageBytes);
|
|
1335
|
+
}
|
|
1195
1336
|
broadcastCustomMessage(customType, contents) {
|
|
1196
1337
|
if (this.disposed) {
|
|
1197
1338
|
return;
|
|
1198
1339
|
}
|
|
1199
1340
|
const writer = new BufferWriter(contents.length + 16);
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
}
|
|
1205
|
-
const encodedMessage = encodeServerMessage2(message, writer);
|
|
1206
|
-
const messageBytes = encodedMessage.getBuffer();
|
|
1207
|
-
this.authenticatedDeltaNetV01Connections.forEach((connection) => {
|
|
1208
|
-
try {
|
|
1209
|
-
connection.sendEncodedBytes(messageBytes);
|
|
1210
|
-
} catch (error) {
|
|
1211
|
-
console.warn("Failed to send custom message to connection:", error);
|
|
1212
|
-
}
|
|
1213
|
-
});
|
|
1341
|
+
encodeServerCustom({ type: "serverCustom", customType, contents }, writer);
|
|
1342
|
+
const messageBytes = writer.getBuffer();
|
|
1343
|
+
for (const connection of this.authenticatedConnections) {
|
|
1344
|
+
connection.sendEncodedBytes(messageBytes);
|
|
1345
|
+
}
|
|
1214
1346
|
}
|
|
1215
1347
|
dispose() {
|
|
1216
1348
|
this.disposed = true;
|
|
1217
|
-
const connectionsToClose = Array.from(this.
|
|
1349
|
+
const connectionsToClose = Array.from(this.allConnections);
|
|
1218
1350
|
for (const connection of connectionsToClose) {
|
|
1219
1351
|
try {
|
|
1352
|
+
connection.dispose();
|
|
1220
1353
|
connection.webSocket.close(1001, "Server shutting down");
|
|
1221
1354
|
} catch (error) {
|
|
1222
1355
|
console.warn("Failed to close connection during disposal:", error);
|
|
1223
1356
|
}
|
|
1224
1357
|
}
|
|
1225
|
-
this.
|
|
1226
|
-
this.
|
|
1358
|
+
this.allConnections.clear();
|
|
1359
|
+
this.authenticatedConnections.clear();
|
|
1360
|
+
this.authenticatedV01Connections.clear();
|
|
1361
|
+
this.authenticatedV02Connections.clear();
|
|
1227
1362
|
this.observerConnections.clear();
|
|
1228
|
-
this.
|
|
1229
|
-
this.
|
|
1363
|
+
this.webSocketToConnection.clear();
|
|
1364
|
+
this.connectionIdToConnection.clear();
|
|
1230
1365
|
this.connectionIdToComponentIndex.clear();
|
|
1231
1366
|
this.componentIndexToConnectionId.clear();
|
|
1232
1367
|
this.components.clear();
|
|
@@ -1236,8 +1371,11 @@ var DeltaNetServer2 = class {
|
|
|
1236
1371
|
}
|
|
1237
1372
|
};
|
|
1238
1373
|
export {
|
|
1374
|
+
DeltaNetConnection,
|
|
1239
1375
|
DeltaNetServer2 as DeltaNetServer,
|
|
1240
1376
|
DeltaNetServerError,
|
|
1241
|
-
DeltaNetV01Connection
|
|
1377
|
+
DeltaNetV01Connection,
|
|
1378
|
+
DeltaNetV02Connection,
|
|
1379
|
+
createDeltaNetServerConnectionForWebsocket
|
|
1242
1380
|
};
|
|
1243
1381
|
//# sourceMappingURL=index.js.map
|