@mml-io/delta-net-server 0.0.0-experimental-bcf0b7c-20250715

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/build/index.js ADDED
@@ -0,0 +1,1238 @@
1
+ // src/DeltaNetServer.ts
2
+ import {
3
+ BufferWriter,
4
+ encodeInitialCheckout,
5
+ encodePing,
6
+ encodeTick,
7
+ encodeServerMessage as encodeServerMessage2
8
+ } from "/Users/marcuslongmuir/mml/3d-web-experience/packages/deltanet/delta-net-protocol/build/index.js";
9
+
10
+ // src/ComponentCollection.ts
11
+ var ComponentCollection = class _ComponentCollection {
12
+ // Internal storage using bigint arrays for unlimited precision
13
+ targetValues;
14
+ pendingDeltas;
15
+ previousEmittedDeltas;
16
+ // Track the current observable value (what existing connections see)
17
+ currentObservableValues;
18
+ // Constants for int64 range
19
+ static MIN_INT64 = -9223372036854775808n;
20
+ static MAX_INT64 = 9223372036854775807n;
21
+ constructor(initialLength = 128) {
22
+ this.targetValues = new Array(initialLength).fill(BigInt(0));
23
+ this.pendingDeltas = new Array(initialLength).fill(BigInt(0));
24
+ this.previousEmittedDeltas = new Array(initialLength).fill(BigInt(0));
25
+ this.currentObservableValues = new Array(initialLength).fill(BigInt(0));
26
+ }
27
+ setLength(length) {
28
+ if (length > this.targetValues.length) {
29
+ while (this.targetValues.length < length) {
30
+ this.targetValues.push(BigInt(0));
31
+ this.pendingDeltas.push(BigInt(0));
32
+ this.previousEmittedDeltas.push(BigInt(0));
33
+ this.currentObservableValues.push(BigInt(0));
34
+ }
35
+ } else if (length < this.targetValues.length) {
36
+ this.targetValues = this.targetValues.slice(0, length);
37
+ this.pendingDeltas = this.pendingDeltas.slice(0, length);
38
+ this.previousEmittedDeltas = this.previousEmittedDeltas.slice(0, length);
39
+ this.currentObservableValues = this.currentObservableValues.slice(0, length);
40
+ }
41
+ }
42
+ setValue(index, value) {
43
+ if (index >= this.targetValues.length) {
44
+ const newLength = Math.pow(2, Math.ceil(Math.log2(index + 1)));
45
+ this.setLength(newLength);
46
+ }
47
+ const clampedValue = this.clampToInt64(value);
48
+ const currentValue = this.targetValues[index];
49
+ const totalDelta = clampedValue - currentValue;
50
+ this.pendingDeltas[index] += totalDelta;
51
+ this.targetValues[index] = clampedValue;
52
+ }
53
+ clampToInt64(value) {
54
+ if (value > _ComponentCollection.MAX_INT64) {
55
+ return _ComponentCollection.MAX_INT64;
56
+ }
57
+ if (value < _ComponentCollection.MIN_INT64) {
58
+ return _ComponentCollection.MIN_INT64;
59
+ }
60
+ return value;
61
+ }
62
+ tick() {
63
+ const length = this.targetValues.length;
64
+ const delta = new BigInt64Array(length);
65
+ const deltaDeltas = new BigInt64Array(length);
66
+ for (let i = 0; i < length; i++) {
67
+ const pendingDelta = this.pendingDeltas[i];
68
+ const emittableDelta = this.clampToInt64(pendingDelta);
69
+ delta[i] = emittableDelta;
70
+ const deltaDelta = emittableDelta - this.previousEmittedDeltas[i];
71
+ const clampedDeltaDelta = this.clampToInt64(deltaDelta);
72
+ deltaDeltas[i] = clampedDeltaDelta;
73
+ this.previousEmittedDeltas[i] = emittableDelta;
74
+ this.currentObservableValues[i] = this.clampToInt64(
75
+ this.currentObservableValues[i] + emittableDelta
76
+ );
77
+ this.pendingDeltas[i] -= emittableDelta;
78
+ }
79
+ return { delta, deltaDeltas };
80
+ }
81
+ removeIndices(sortedUnoccupyingIndices) {
82
+ if (sortedUnoccupyingIndices.length === 0) {
83
+ return;
84
+ }
85
+ let writeIndex = 0;
86
+ let skipIndex = 0;
87
+ for (let readIndex = 0; readIndex < this.targetValues.length; readIndex++) {
88
+ if (skipIndex < sortedUnoccupyingIndices.length && readIndex === sortedUnoccupyingIndices[skipIndex]) {
89
+ skipIndex++;
90
+ continue;
91
+ }
92
+ if (writeIndex !== readIndex) {
93
+ this.targetValues[writeIndex] = this.targetValues[readIndex];
94
+ this.pendingDeltas[writeIndex] = this.pendingDeltas[readIndex];
95
+ this.previousEmittedDeltas[writeIndex] = this.previousEmittedDeltas[readIndex];
96
+ this.currentObservableValues[writeIndex] = this.currentObservableValues[readIndex];
97
+ }
98
+ writeIndex++;
99
+ }
100
+ for (let i = writeIndex; i < this.targetValues.length; i++) {
101
+ this.targetValues[i] = BigInt(0);
102
+ this.pendingDeltas[i] = BigInt(0);
103
+ this.previousEmittedDeltas[i] = BigInt(0);
104
+ this.currentObservableValues[i] = BigInt(0);
105
+ }
106
+ }
107
+ // Getter for current target values (for testing)
108
+ getTargetValue(index) {
109
+ return this.targetValues[index] || BigInt(0);
110
+ }
111
+ // Getter for pending deltas (for testing)
112
+ getPendingDelta(index) {
113
+ return this.pendingDeltas[index] || BigInt(0);
114
+ }
115
+ // Getter for length (for testing)
116
+ get length() {
117
+ return this.targetValues.length;
118
+ }
119
+ // Get target values as BigInt64Array for serialization
120
+ getCurrentValuesArray() {
121
+ const result = new BigInt64Array(this.targetValues.length);
122
+ for (let i = 0; i < this.targetValues.length; i++) {
123
+ result[i] = this.currentObservableValues[i];
124
+ }
125
+ return result;
126
+ }
127
+ // Get previous emitted deltas as BigInt64Array for serialization
128
+ getPreviousEmittedDeltasArray() {
129
+ const result = new BigInt64Array(this.previousEmittedDeltas.length);
130
+ for (let i = 0; i < this.previousEmittedDeltas.length; i++) {
131
+ result[i] = this.previousEmittedDeltas[i];
132
+ }
133
+ return result;
134
+ }
135
+ };
136
+
137
+ // src/createDeltaNetServerConnectionForWebsocket.ts
138
+ import {
139
+ deltaNetProtocolSubProtocol_v0_1
140
+ } from "/Users/marcuslongmuir/mml/3d-web-experience/packages/deltanet/delta-net-protocol/build/index.js";
141
+
142
+ // src/DeltaNetV01Connection.ts
143
+ import {
144
+ DeltaNetV01ServerErrors,
145
+ BufferReader,
146
+ decodeClientMessages,
147
+ encodeServerMessage
148
+ } from "/Users/marcuslongmuir/mml/3d-web-experience/packages/deltanet/delta-net-protocol/build/index.js";
149
+ var DeltaNetV01Connection = class {
150
+ constructor(webSocket, deltaNetServer) {
151
+ this.webSocket = webSocket;
152
+ this.deltaNetServer = deltaNetServer;
153
+ this.internalConnectionId = deltaNetServer.getNextConnectionId();
154
+ this.websocketListener = (messageEvent) => {
155
+ const buffer = new Uint8Array(messageEvent.data);
156
+ const maxMessageSize = this.deltaNetServer.getMaxMessageSize();
157
+ if (buffer.length > maxMessageSize) {
158
+ this.disconnectWithError(
159
+ new Error(
160
+ `Message size ${buffer.length} bytes exceeds maximum allowed size of ${maxMessageSize} bytes`
161
+ ),
162
+ DeltaNetV01ServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
163
+ false
164
+ );
165
+ return;
166
+ }
167
+ try {
168
+ const messages = decodeClientMessages(new BufferReader(buffer));
169
+ for (const parsed of messages) {
170
+ this.handleClientMessage(parsed);
171
+ }
172
+ } catch (error) {
173
+ this.disconnectWithError(
174
+ new Error(`Failed to decode client messages: ${error instanceof Error ? error.message : error}`),
175
+ DeltaNetV01ServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
176
+ false
177
+ );
178
+ return;
179
+ }
180
+ };
181
+ webSocket.addEventListener("message", this.websocketListener);
182
+ this.deltaNetServer = deltaNetServer;
183
+ }
184
+ websocketListener;
185
+ internalConnectionId;
186
+ isObserver = false;
187
+ // Track observer mode
188
+ // Pending state for new joiners (before they're authenticated)
189
+ components = /* @__PURE__ */ new Map();
190
+ states = /* @__PURE__ */ new Map();
191
+ // Track pending async state validations per state
192
+ pendingStateValidations = /* @__PURE__ */ new Map();
193
+ nextValidationId = 1;
194
+ // Track authentication state
195
+ isAuthenticated = false;
196
+ isAuthenticating = false;
197
+ authenticationAbortController = null;
198
+ sendMessage(message) {
199
+ this.sendEncodedBytes(encodeServerMessage(message).getBuffer());
200
+ }
201
+ sendEncodedBytes(bytes) {
202
+ this.webSocket.send(bytes);
203
+ }
204
+ dispose() {
205
+ this.webSocket.removeEventListener("message", this.websocketListener);
206
+ for (const [, validation] of this.pendingStateValidations) {
207
+ validation.abortController.abort();
208
+ }
209
+ this.pendingStateValidations.clear();
210
+ if (this.authenticationAbortController) {
211
+ this.authenticationAbortController.abort();
212
+ this.authenticationAbortController = null;
213
+ }
214
+ }
215
+ setAuthenticated() {
216
+ this.isAuthenticated = true;
217
+ }
218
+ disconnectWithError(error, errorType, retryable = true) {
219
+ try {
220
+ this.sendMessage({
221
+ type: "error",
222
+ errorType,
223
+ message: error.message,
224
+ retryable
225
+ });
226
+ } catch (sendError) {
227
+ console.warn("Failed to send error message to client:", sendError);
228
+ }
229
+ try {
230
+ this.webSocket.close(1008, error.message);
231
+ } catch (closeError) {
232
+ console.warn("Failed to close websocket connection:", closeError);
233
+ }
234
+ }
235
+ async handleConnectUser(token, observer, components, states) {
236
+ var _a, _b;
237
+ if (this.isAuthenticated) {
238
+ this.disconnectWithError(
239
+ new Error("User is already authenticated"),
240
+ DeltaNetV01ServerErrors.USER_ALREADY_AUTHENTICATED_ERROR_TYPE,
241
+ false
242
+ );
243
+ return;
244
+ }
245
+ if (this.isAuthenticating) {
246
+ this.disconnectWithError(
247
+ new Error("Authentication already in progress"),
248
+ DeltaNetV01ServerErrors.AUTHENTICATION_IN_PROGRESS_ERROR_TYPE,
249
+ false
250
+ );
251
+ return;
252
+ }
253
+ this.isAuthenticating = true;
254
+ this.authenticationAbortController = new AbortController();
255
+ this.isObserver = observer;
256
+ this.components = new Map(components);
257
+ this.states = new Map(states);
258
+ let result;
259
+ try {
260
+ const rawResult = this.deltaNetServer.validateJoiner(this, token, components, states);
261
+ if (rawResult instanceof Promise) {
262
+ result = await rawResult;
263
+ if ((_a = this.authenticationAbortController) == null ? void 0 : _a.signal.aborted) {
264
+ return;
265
+ }
266
+ if (!this.deltaNetServer.hasWebSocket(this.webSocket)) {
267
+ return;
268
+ }
269
+ } else {
270
+ result = rawResult;
271
+ }
272
+ } catch (error) {
273
+ if ((_b = this.authenticationAbortController) == null ? void 0 : _b.signal.aborted) {
274
+ return;
275
+ }
276
+ result = error;
277
+ }
278
+ this.authenticationAbortController = null;
279
+ if (result instanceof DeltaNetServerError) {
280
+ this.disconnectWithError(result, result.errorType, result.retryable);
281
+ } else if (result instanceof Error) {
282
+ this.disconnectWithError(
283
+ result,
284
+ DeltaNetV01ServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
285
+ false
286
+ );
287
+ } else if (typeof result !== "object") {
288
+ this.disconnectWithError(
289
+ new Error("Invalid authentication result"),
290
+ DeltaNetV01ServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
291
+ false
292
+ );
293
+ } else {
294
+ if (result.success) {
295
+ if (result.stateOverrides) {
296
+ for (const [stateId, stateValue] of result.stateOverrides) {
297
+ this.states.set(stateId, stateValue);
298
+ }
299
+ }
300
+ this.deltaNetServer.addAuthenticatedConnection(this);
301
+ } else {
302
+ this.disconnectWithError(
303
+ new Error(result.error || "Authentication failed"),
304
+ DeltaNetV01ServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
305
+ false
306
+ );
307
+ }
308
+ }
309
+ this.isAuthenticating = false;
310
+ }
311
+ async handleStateUpdate(stateId, stateValue) {
312
+ if (!this.isAuthenticated) {
313
+ console.error("State update received before authentication completed");
314
+ return;
315
+ }
316
+ const existingValidation = this.pendingStateValidations.get(stateId);
317
+ if (existingValidation) {
318
+ existingValidation.abortController.abort();
319
+ this.pendingStateValidations.delete(stateId);
320
+ }
321
+ const result = this.deltaNetServer.validateAndApplyStateUpdate(
322
+ this,
323
+ this.internalConnectionId,
324
+ stateId,
325
+ stateValue
326
+ );
327
+ if (result instanceof Promise) {
328
+ const validationId = this.nextValidationId++;
329
+ const abortController = new AbortController();
330
+ this.pendingStateValidations.set(stateId, { validationId, abortController });
331
+ try {
332
+ const asyncResult = await result;
333
+ const currentValidation = this.pendingStateValidations.get(stateId);
334
+ if (!currentValidation || currentValidation.validationId !== validationId) {
335
+ return;
336
+ }
337
+ this.pendingStateValidations.delete(stateId);
338
+ if (asyncResult instanceof DeltaNetServerError) {
339
+ this.disconnectWithError(asyncResult, asyncResult.errorType, asyncResult.retryable);
340
+ return;
341
+ }
342
+ if (asyncResult instanceof Error) {
343
+ this.disconnectWithError(
344
+ asyncResult,
345
+ DeltaNetV01ServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
346
+ false
347
+ );
348
+ return;
349
+ }
350
+ return;
351
+ } catch (error) {
352
+ const currentValidation = this.pendingStateValidations.get(stateId);
353
+ if (currentValidation && currentValidation.validationId === validationId) {
354
+ this.pendingStateValidations.delete(stateId);
355
+ if (error instanceof DeltaNetServerError) {
356
+ this.disconnectWithError(error, error.errorType, error.retryable);
357
+ } else if (error instanceof Error) {
358
+ this.disconnectWithError(
359
+ error,
360
+ DeltaNetV01ServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
361
+ false
362
+ );
363
+ } else {
364
+ this.disconnectWithError(
365
+ new Error("State validation failed"),
366
+ DeltaNetV01ServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
367
+ false
368
+ );
369
+ }
370
+ }
371
+ return;
372
+ }
373
+ } else {
374
+ if (result instanceof DeltaNetServerError) {
375
+ this.disconnectWithError(result, result.errorType, result.retryable);
376
+ return;
377
+ }
378
+ if (result instanceof Error) {
379
+ this.disconnectWithError(
380
+ result,
381
+ DeltaNetV01ServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
382
+ false
383
+ );
384
+ return;
385
+ }
386
+ return;
387
+ }
388
+ }
389
+ handleClientMessage(parsed) {
390
+ switch (parsed.type) {
391
+ case "connectUser": {
392
+ if (this.deltaNetServer !== null) {
393
+ this.handleConnectUser(parsed.token, parsed.observer, parsed.components, parsed.states);
394
+ }
395
+ return;
396
+ }
397
+ case "pong":
398
+ return;
399
+ case "setUserComponents": {
400
+ if (!this.deltaNetServer) {
401
+ console.error("DeltaNetServer not set on connection that received event", this);
402
+ return;
403
+ }
404
+ if (!this.isAuthenticated) {
405
+ this.sendMessage({
406
+ type: "error",
407
+ errorType: "USER_NOT_AUTHENTICATED",
408
+ message: `Event sent, but user has not been authenticated yet.`,
409
+ retryable: false
410
+ });
411
+ console.error("Event sent, but user has not been authenticated yet.");
412
+ this.webSocket.close(1e3, "User has not been authenticated yet");
413
+ return;
414
+ }
415
+ const result = this.deltaNetServer.setUserComponents(
416
+ this,
417
+ this.internalConnectionId,
418
+ parsed.components
419
+ );
420
+ if (!result.success) {
421
+ this.disconnectWithError(
422
+ new Error(result.error),
423
+ DeltaNetV01ServerErrors.USER_NETWORKING_UNKNOWN_ERROR_TYPE,
424
+ true
425
+ );
426
+ return;
427
+ }
428
+ for (const [stateId, stateValue] of parsed.states) {
429
+ this.handleStateUpdate(stateId, stateValue);
430
+ }
431
+ return;
432
+ }
433
+ case "clientCustom": {
434
+ if (!this.deltaNetServer) {
435
+ console.error("DeltaNetServer not set on connection that received custom message", this);
436
+ return;
437
+ }
438
+ if (!this.isAuthenticated) {
439
+ this.sendMessage({
440
+ type: "error",
441
+ errorType: "USER_NOT_AUTHENTICATED",
442
+ message: `Custom message sent, but user has not been authenticated yet.`,
443
+ retryable: false
444
+ });
445
+ console.error("Custom message sent, but user has not been authenticated yet.");
446
+ this.webSocket.close(1e3, "User has not been authenticated yet");
447
+ return;
448
+ }
449
+ this.deltaNetServer.handleCustomMessage(
450
+ this,
451
+ this.internalConnectionId,
452
+ parsed.customType,
453
+ parsed.contents
454
+ );
455
+ return;
456
+ }
457
+ default:
458
+ console.error("Unknown message type from client", parsed);
459
+ }
460
+ }
461
+ };
462
+
463
+ // src/createDeltaNetServerConnectionForWebsocket.ts
464
+ var SupportedWebsocketSubProtocolsPreferenceOrder = [
465
+ deltaNetProtocolSubProtocol_v0_1
466
+ ];
467
+ function IsRecognizedWebsocketSubProtocol(protocol) {
468
+ return SupportedWebsocketSubProtocolsPreferenceOrder.includes(protocol);
469
+ }
470
+ function createDeltaNetServerConnectionForWebsocket(webSocket, deltaNetServer) {
471
+ if (!webSocket.protocol || !IsRecognizedWebsocketSubProtocol(webSocket.protocol)) {
472
+ const errorMessageString = `Unsupported websocket subprotocol: ${webSocket.protocol}`;
473
+ const errorMessage = [
474
+ {
475
+ type: "error",
476
+ errorType: "UNSUPPORTED_WEBSOCKET_SUBPROTOCOL",
477
+ message: errorMessageString,
478
+ retryable: false
479
+ }
480
+ ];
481
+ webSocket.send(JSON.stringify(errorMessage));
482
+ webSocket.close();
483
+ return null;
484
+ }
485
+ return new DeltaNetV01Connection(webSocket, deltaNetServer);
486
+ }
487
+
488
+ // src/StateCollection.ts
489
+ var emptyUint8Array = new Uint8Array(0);
490
+ var StateCollection = class {
491
+ values;
492
+ modifiedIndices = /* @__PURE__ */ new Set();
493
+ constructor() {
494
+ this.values = new Array();
495
+ }
496
+ setValue(index, value) {
497
+ if (value === null) {
498
+ value = emptyUint8Array;
499
+ }
500
+ this.modifiedIndices.add(index);
501
+ this.values[index] = value;
502
+ }
503
+ tick() {
504
+ const states = [];
505
+ for (const index of this.modifiedIndices) {
506
+ const value = this.values[index];
507
+ if (value === null) {
508
+ states.push([index, new Uint8Array(0)]);
509
+ } else {
510
+ states.push([index, value]);
511
+ }
512
+ }
513
+ this.modifiedIndices.clear();
514
+ return states;
515
+ }
516
+ removeIndices(sortedUnoccupyingIndices) {
517
+ if (sortedUnoccupyingIndices.length === 0) {
518
+ return;
519
+ }
520
+ let writeIndex = 0;
521
+ let skipIndex = 0;
522
+ for (let readIndex = 0; readIndex < this.values.length; readIndex++) {
523
+ if (skipIndex < sortedUnoccupyingIndices.length && readIndex === sortedUnoccupyingIndices[skipIndex]) {
524
+ this.modifiedIndices.delete(readIndex);
525
+ skipIndex++;
526
+ continue;
527
+ }
528
+ if (writeIndex !== readIndex && this.modifiedIndices.has(readIndex)) {
529
+ this.modifiedIndices.delete(readIndex);
530
+ this.modifiedIndices.add(writeIndex);
531
+ }
532
+ if (writeIndex !== readIndex) {
533
+ this.values[writeIndex] = this.values[readIndex];
534
+ }
535
+ writeIndex++;
536
+ }
537
+ for (let i = writeIndex; i < this.values.length; i++) {
538
+ this.values[i] = emptyUint8Array;
539
+ this.modifiedIndices.delete(i);
540
+ }
541
+ }
542
+ };
543
+
544
+ // src/DeltaNetServer.ts
545
+ var DeltaNetServerError = class extends Error {
546
+ constructor(errorType, message, retryable) {
547
+ super(message);
548
+ this.errorType = errorType;
549
+ this.retryable = retryable;
550
+ }
551
+ };
552
+ var DeltaNetServer2 = class {
553
+ constructor(opts = {}) {
554
+ this.opts = opts;
555
+ if (opts.serverConnectionIdStateId !== void 0) {
556
+ this.states.set(opts.serverConnectionIdStateId, new StateCollection());
557
+ }
558
+ this.maxStateValueSize = opts.maxStateValueSize ?? 1024 * 1024;
559
+ this.maxMessageSize = opts.maxMessageSize ?? 10 * 1024 * 1024;
560
+ }
561
+ currentConnectionId = 1;
562
+ nextIndex = 0;
563
+ preTickData = {
564
+ // This is state that will be flushed to clients in the next tick, but messages handled before the tick could change it
565
+ unoccupyingIndices: /* @__PURE__ */ new Set(),
566
+ newJoinerConnections: /* @__PURE__ */ new Set(),
567
+ // Allows for arbitrary processes to be run that can imitate a new joiner connection (currently used for legacy adapter)
568
+ newJoinerCallbacks: /* @__PURE__ */ new Set(),
569
+ componentsUpdated: 0
570
+ };
571
+ connectionIdToComponentIndex = /* @__PURE__ */ new Map();
572
+ componentIndexToConnectionId = /* @__PURE__ */ new Map();
573
+ connectionIdToDeltaNetServerConnection = /* @__PURE__ */ new Map();
574
+ allDeltaNetV01Connections = /* @__PURE__ */ new Set();
575
+ authenticatedDeltaNetV01Connections = /* @__PURE__ */ new Set();
576
+ observerConnections = /* @__PURE__ */ new Set();
577
+ // Track observer connections separately
578
+ webSocketToDeltaNetServerConnection = /* @__PURE__ */ new Map();
579
+ components = /* @__PURE__ */ new Map();
580
+ states = /* @__PURE__ */ new Map();
581
+ documentEffectiveStartTime = Date.now();
582
+ pingCounter = 1;
583
+ disposed = false;
584
+ maxStateValueSize;
585
+ maxMessageSize;
586
+ static handleWebsocketSubprotocol(protocols) {
587
+ const protocolsSet = new Set(protocols);
588
+ for (const protocol of SupportedWebsocketSubProtocolsPreferenceOrder) {
589
+ if (protocolsSet.has(protocol)) {
590
+ return protocol;
591
+ }
592
+ }
593
+ return false;
594
+ }
595
+ addWebSocket(webSocket) {
596
+ if (this.disposed) {
597
+ throw new Error("This DeltaNetServer has been disposed");
598
+ }
599
+ const deltaNetV01Connection = createDeltaNetServerConnectionForWebsocket(webSocket, this);
600
+ if (deltaNetV01Connection === null) {
601
+ return;
602
+ }
603
+ this.allDeltaNetV01Connections.add(deltaNetV01Connection);
604
+ this.webSocketToDeltaNetServerConnection.set(
605
+ deltaNetV01Connection.webSocket,
606
+ deltaNetV01Connection
607
+ );
608
+ }
609
+ removeWebSocket(webSocket) {
610
+ const deltaNetV01Connection = this.webSocketToDeltaNetServerConnection.get(webSocket);
611
+ if (deltaNetV01Connection === void 0) {
612
+ return;
613
+ }
614
+ if (!this.allDeltaNetV01Connections.has(deltaNetV01Connection)) {
615
+ return;
616
+ }
617
+ deltaNetV01Connection.dispose();
618
+ if (!this.disposed && this.opts.onLeave) {
619
+ const internalConnectionId2 = deltaNetV01Connection.internalConnectionId;
620
+ const index = this.connectionIdToComponentIndex.get(internalConnectionId2);
621
+ if (index !== void 0) {
622
+ const components = [];
623
+ for (const [componentId, collection] of this.components) {
624
+ const value = collection.getTargetValue(index);
625
+ if (value !== 0n) {
626
+ components.push([componentId, Number(value)]);
627
+ }
628
+ }
629
+ const states = [];
630
+ for (const [stateId, collection] of this.states) {
631
+ const value = collection.values[index];
632
+ if (value !== void 0 && value.length > 0) {
633
+ states.push([stateId, value]);
634
+ }
635
+ }
636
+ try {
637
+ this.opts.onLeave({
638
+ deltaNetV01Connection,
639
+ internalConnectionId: internalConnectionId2,
640
+ components,
641
+ states
642
+ });
643
+ } catch (error) {
644
+ console.warn("Error in onLeave callback:", error);
645
+ }
646
+ }
647
+ }
648
+ const internalConnectionId = deltaNetV01Connection.internalConnectionId;
649
+ this.connectionIdToDeltaNetServerConnection.delete(internalConnectionId);
650
+ if (this.preTickData.newJoinerConnections.has(deltaNetV01Connection)) {
651
+ this.preTickData.newJoinerConnections.delete(deltaNetV01Connection);
652
+ } else {
653
+ const index = this.connectionIdToComponentIndex.get(internalConnectionId);
654
+ if (index !== void 0) {
655
+ this.clearInternalConnectionId(internalConnectionId);
656
+ }
657
+ }
658
+ this.authenticatedDeltaNetV01Connections.delete(deltaNetV01Connection);
659
+ this.observerConnections.delete(deltaNetV01Connection);
660
+ this.allDeltaNetV01Connections.delete(deltaNetV01Connection);
661
+ this.webSocketToDeltaNetServerConnection.delete(deltaNetV01Connection.webSocket);
662
+ }
663
+ hasWebSocket(webSocket) {
664
+ return this.webSocketToDeltaNetServerConnection.has(webSocket);
665
+ }
666
+ dangerouslyGetConnectionsToComponentIndex() {
667
+ return this.connectionIdToComponentIndex;
668
+ }
669
+ dangerouslyAddNewJoinerCallback(callback) {
670
+ this.preTickData.newJoinerCallbacks.add(callback);
671
+ }
672
+ disconnectWithError(deltaNetV01Connection, error, errorType, retryable = true) {
673
+ try {
674
+ deltaNetV01Connection.sendMessage({
675
+ type: "error",
676
+ errorType,
677
+ message: error.message,
678
+ retryable
679
+ });
680
+ } catch (sendError) {
681
+ console.warn("Failed to send error message to client:", sendError);
682
+ }
683
+ try {
684
+ deltaNetV01Connection.webSocket.close(1008, error.message);
685
+ } catch (closeError) {
686
+ console.warn("Failed to close websocket connection:", closeError);
687
+ }
688
+ try {
689
+ this.removeWebSocket(deltaNetV01Connection.webSocket);
690
+ } catch (cleanupError) {
691
+ console.warn("Failed to clean up connection state:", cleanupError);
692
+ }
693
+ }
694
+ getComponentValue(componentId, componentIndex) {
695
+ return Number(this.components.get(componentId).getTargetValue(componentIndex));
696
+ }
697
+ getNextConnectionId() {
698
+ return this.currentConnectionId++;
699
+ }
700
+ getMaxMessageSize() {
701
+ return this.maxMessageSize;
702
+ }
703
+ validateJoiner(deltaNetV01Connection, token, components, states) {
704
+ if (this.disposed) {
705
+ return { success: false, error: "This DeltaNetServer has been disposed" };
706
+ }
707
+ for (const [stateId, stateValue] of states) {
708
+ if (stateValue.length > this.maxStateValueSize) {
709
+ return {
710
+ success: false,
711
+ error: `State value for state ${stateId} has size ${stateValue.length} bytes which exceeds maximum allowed size of ${this.maxStateValueSize} bytes`
712
+ };
713
+ }
714
+ }
715
+ function resultToReturn(result) {
716
+ if (result instanceof DeltaNetServerError) {
717
+ return { success: false, error: result.message };
718
+ }
719
+ if (result instanceof Error) {
720
+ return { success: false, error: result.message };
721
+ }
722
+ if (result === true || result === void 0) {
723
+ return { success: true };
724
+ }
725
+ if (typeof result === "object" && result.success === true) {
726
+ return result;
727
+ }
728
+ return { success: false, error: "Joiner validation failed" };
729
+ }
730
+ if (this.opts.onJoiner) {
731
+ const rawResult = this.opts.onJoiner({
732
+ deltaNetV01Connection,
733
+ components,
734
+ states,
735
+ token,
736
+ internalConnectionId: deltaNetV01Connection.internalConnectionId
737
+ });
738
+ if (rawResult instanceof Promise) {
739
+ return rawResult.then((resolvedResult) => {
740
+ return resultToReturn(resolvedResult);
741
+ }).catch((error) => {
742
+ console.warn("Error in async onJoiner callback:", error);
743
+ return resultToReturn(error);
744
+ });
745
+ } else {
746
+ return resultToReturn(rawResult);
747
+ }
748
+ }
749
+ return { success: true };
750
+ }
751
+ addAuthenticatedConnection(deltaNetV01Connection) {
752
+ if (deltaNetV01Connection.internalConnectionId === null) {
753
+ throw new Error("Connection ID must be set before adding to authenticated connections");
754
+ }
755
+ this.connectionIdToDeltaNetServerConnection.set(
756
+ deltaNetV01Connection.internalConnectionId,
757
+ deltaNetV01Connection
758
+ );
759
+ if (deltaNetV01Connection.isObserver) {
760
+ this.observerConnections.add(deltaNetV01Connection);
761
+ this.preTickData.newJoinerConnections.add(deltaNetV01Connection);
762
+ } else {
763
+ this.preTickData.newJoinerConnections.add(deltaNetV01Connection);
764
+ }
765
+ }
766
+ validateAndApplyStateUpdate(deltaNetV01Connection, internalConnectionId, stateId, stateValue) {
767
+ if (this.disposed) {
768
+ return new Error("This DeltaNetServer has been disposed");
769
+ }
770
+ if (stateValue.length > this.maxStateValueSize) {
771
+ return new DeltaNetServerError(
772
+ "USER_NETWORKING_UNKNOWN_ERROR",
773
+ `State value for state ${stateId} has size ${stateValue.length} bytes which exceeds maximum allowed size of ${this.maxStateValueSize} bytes`,
774
+ false
775
+ );
776
+ }
777
+ if (deltaNetV01Connection.isObserver) {
778
+ return new DeltaNetServerError(
779
+ "OBSERVER_CANNOT_SEND_STATE_UPDATES",
780
+ "Observers cannot send state updates",
781
+ false
782
+ );
783
+ }
784
+ if (this.opts.onStatesUpdate) {
785
+ try {
786
+ const result = this.opts.onStatesUpdate({
787
+ deltaNetV01Connection,
788
+ internalConnectionId,
789
+ states: [[stateId, stateValue]]
790
+ });
791
+ if (result instanceof Promise) {
792
+ return result.then((asyncResult) => {
793
+ if (!this.connectionIdToDeltaNetServerConnection.has(internalConnectionId)) {
794
+ return;
795
+ }
796
+ if (asyncResult instanceof DeltaNetServerError || asyncResult instanceof Error) {
797
+ return asyncResult;
798
+ }
799
+ if (asyncResult === true || asyncResult === void 0) {
800
+ this.applyStateUpdates(deltaNetV01Connection, internalConnectionId, [
801
+ [stateId, stateValue]
802
+ ]);
803
+ return true;
804
+ }
805
+ if (asyncResult.success) {
806
+ if (asyncResult.stateOverrides) {
807
+ this.applyStateUpdates(
808
+ deltaNetV01Connection,
809
+ internalConnectionId,
810
+ asyncResult.stateOverrides
811
+ );
812
+ }
813
+ return true;
814
+ } else {
815
+ return new DeltaNetServerError(
816
+ "USER_NETWORKING_UNKNOWN_ERROR",
817
+ "State validation failed",
818
+ false
819
+ );
820
+ }
821
+ }).catch((error) => {
822
+ console.warn("Error in async onStatesUpdate callback:", error);
823
+ if (error instanceof DeltaNetServerError) {
824
+ return error;
825
+ }
826
+ if (error instanceof Error) {
827
+ return error;
828
+ }
829
+ return new Error("State validation failed");
830
+ });
831
+ } else {
832
+ if (result instanceof DeltaNetServerError || result instanceof Error) {
833
+ return result;
834
+ }
835
+ if (result === true || result === void 0) {
836
+ this.applyStateUpdates(deltaNetV01Connection, internalConnectionId, [
837
+ [stateId, stateValue]
838
+ ]);
839
+ return true;
840
+ }
841
+ if (result.success) {
842
+ if (result.stateOverrides) {
843
+ this.applyStateUpdates(
844
+ deltaNetV01Connection,
845
+ internalConnectionId,
846
+ result.stateOverrides
847
+ );
848
+ }
849
+ return true;
850
+ } else {
851
+ return new DeltaNetServerError(
852
+ "USER_NETWORKING_UNKNOWN_ERROR",
853
+ "State validation failed",
854
+ false
855
+ );
856
+ }
857
+ }
858
+ } catch (error) {
859
+ console.warn("Error in onStatesUpdate callback:", error);
860
+ if (error instanceof DeltaNetServerError) {
861
+ return error;
862
+ }
863
+ if (error instanceof Error) {
864
+ return error;
865
+ }
866
+ return new Error("State validation failed");
867
+ }
868
+ } else {
869
+ this.applyStateUpdates(deltaNetV01Connection, internalConnectionId, [[stateId, stateValue]]);
870
+ return true;
871
+ }
872
+ }
873
+ clearInternalConnectionId(internalConnectionId) {
874
+ const index = this.connectionIdToComponentIndex.get(internalConnectionId);
875
+ if (index === void 0) {
876
+ throw new Error("Index for removing user is undefined");
877
+ }
878
+ for (const [, collection] of this.components) {
879
+ collection.setValue(index, 0n);
880
+ }
881
+ for (const [, collection] of this.states) {
882
+ collection.setValue(index, null);
883
+ }
884
+ this.preTickData.unoccupyingIndices.add(index);
885
+ }
886
+ sendPings() {
887
+ const ping = this.pingCounter++;
888
+ if (this.pingCounter > 1e3) {
889
+ this.pingCounter = 1;
890
+ }
891
+ const v01PingMessage = {
892
+ type: "ping",
893
+ ping
894
+ };
895
+ const writer = new BufferWriter(8);
896
+ encodePing(v01PingMessage, writer);
897
+ const v01Encoded = writer.getBuffer();
898
+ this.allDeltaNetV01Connections.forEach((deltaNetV01Connection) => {
899
+ deltaNetV01Connection.sendEncodedBytes(v01Encoded);
900
+ });
901
+ }
902
+ tick() {
903
+ if (this.disposed) {
904
+ return { removedIds: /* @__PURE__ */ new Set(), addedIds: /* @__PURE__ */ new Set() };
905
+ }
906
+ this.preTickData.componentsUpdated = 0;
907
+ const removedIds = /* @__PURE__ */ new Set();
908
+ const addedIds = /* @__PURE__ */ new Set();
909
+ const sortedUnoccupyingIndices = Array.from(this.preTickData.unoccupyingIndices);
910
+ sortedUnoccupyingIndices.sort((a, b) => a - b);
911
+ for (const componentCollection of this.components.values()) {
912
+ componentCollection.removeIndices(sortedUnoccupyingIndices);
913
+ }
914
+ for (const stateCollection of this.states.values()) {
915
+ stateCollection.removeIndices(sortedUnoccupyingIndices);
916
+ }
917
+ for (const index of sortedUnoccupyingIndices) {
918
+ const connectionId = this.componentIndexToConnectionId.get(index);
919
+ if (connectionId === void 0) {
920
+ throw new Error("Connection id not found for index " + index);
921
+ }
922
+ removedIds.add(connectionId);
923
+ this.connectionIdToComponentIndex.delete(connectionId);
924
+ this.componentIndexToConnectionId.delete(index);
925
+ }
926
+ let writeIndex = 0;
927
+ let skipIndex = 0;
928
+ for (let i = 0; i < this.nextIndex; i++) {
929
+ const connectionId = this.componentIndexToConnectionId.get(i);
930
+ if (skipIndex < sortedUnoccupyingIndices.length && i === sortedUnoccupyingIndices[skipIndex]) {
931
+ skipIndex++;
932
+ continue;
933
+ }
934
+ if (writeIndex !== i) {
935
+ if (connectionId === void 0) {
936
+ throw new Error("Connection id not found for index " + i);
937
+ }
938
+ this.componentIndexToConnectionId.set(writeIndex, connectionId);
939
+ this.connectionIdToComponentIndex.set(connectionId, writeIndex);
940
+ }
941
+ writeIndex++;
942
+ }
943
+ this.nextIndex -= sortedUnoccupyingIndices.length;
944
+ for (const deltaNetV01Connection of this.preTickData.newJoinerConnections) {
945
+ const internalConnectionId = deltaNetV01Connection.internalConnectionId;
946
+ if (deltaNetV01Connection.isObserver) {
947
+ } else {
948
+ const index = this.nextIndex++;
949
+ this.connectionIdToComponentIndex.set(internalConnectionId, index);
950
+ this.componentIndexToConnectionId.set(index, internalConnectionId);
951
+ addedIds.add(internalConnectionId);
952
+ for (const [componentId] of deltaNetV01Connection.components) {
953
+ if (!this.components.has(componentId)) {
954
+ this.components.set(componentId, new ComponentCollection());
955
+ }
956
+ }
957
+ for (const [stateId] of deltaNetV01Connection.states) {
958
+ if (!this.states.has(stateId)) {
959
+ this.states.set(stateId, new StateCollection());
960
+ }
961
+ }
962
+ for (const [componentId, collection] of this.components) {
963
+ const value = deltaNetV01Connection.components.get(componentId);
964
+ if (value === void 0) {
965
+ collection.setValue(index, 0n);
966
+ } else {
967
+ collection.setValue(index, BigInt(value));
968
+ }
969
+ }
970
+ for (const [stateId, collection] of this.states) {
971
+ const value = deltaNetV01Connection.states.get(stateId);
972
+ if (this.opts.serverConnectionIdStateId !== void 0 && stateId === this.opts.serverConnectionIdStateId) {
973
+ const writer2 = new BufferWriter(8);
974
+ writer2.writeUVarint(internalConnectionId);
975
+ const buffer = writer2.getBuffer();
976
+ collection.setValue(index, buffer);
977
+ } else {
978
+ if (value === void 0) {
979
+ collection.setValue(index, null);
980
+ } else {
981
+ collection.setValue(index, value);
982
+ }
983
+ }
984
+ }
985
+ deltaNetV01Connection.sendMessage({
986
+ type: "userIndex",
987
+ index
988
+ });
989
+ }
990
+ }
991
+ for (const callback of this.preTickData.newJoinerCallbacks) {
992
+ const index = this.nextIndex++;
993
+ const result = callback(index);
994
+ if (result === null) {
995
+ this.nextIndex--;
996
+ } else {
997
+ const { id, afterAddCallback } = result;
998
+ this.connectionIdToComponentIndex.set(id, index);
999
+ this.componentIndexToConnectionId.set(index, id);
1000
+ addedIds.add(id);
1001
+ if (this.opts.serverConnectionIdStateId !== void 0) {
1002
+ const writer2 = new BufferWriter(8);
1003
+ writer2.writeUVarint(id);
1004
+ const buffer = writer2.getBuffer();
1005
+ this.setUserState(index, this.opts.serverConnectionIdStateId, buffer);
1006
+ }
1007
+ if (afterAddCallback) {
1008
+ afterAddCallback();
1009
+ }
1010
+ }
1011
+ }
1012
+ const componentDeltas = [];
1013
+ for (const [componentId, collection] of this.components) {
1014
+ const { deltaDeltas } = collection.tick();
1015
+ componentDeltas.push({ componentId, deltaDeltas });
1016
+ }
1017
+ const stateDeltas = [];
1018
+ for (const [stateId, collection] of this.states) {
1019
+ const updatedStates = collection.tick();
1020
+ if (updatedStates.length === 0) {
1021
+ continue;
1022
+ }
1023
+ stateDeltas.push({
1024
+ stateId,
1025
+ updatedStates
1026
+ });
1027
+ }
1028
+ const tickMessage = {
1029
+ type: "tick",
1030
+ serverTime: this.getServerTime(),
1031
+ removedIndices: sortedUnoccupyingIndices,
1032
+ indicesCount: this.nextIndex,
1033
+ componentDeltaDeltas: componentDeltas,
1034
+ states: stateDeltas
1035
+ };
1036
+ const writer = new BufferWriter(this.nextIndex * this.components.size + 128);
1037
+ encodeTick(tickMessage, writer);
1038
+ const v01EncodedComponentsChanged = writer.getBuffer();
1039
+ this.authenticatedDeltaNetV01Connections.forEach((deltaNetV01Connection) => {
1040
+ deltaNetV01Connection.sendEncodedBytes(v01EncodedComponentsChanged);
1041
+ });
1042
+ if (this.preTickData.newJoinerConnections.size > 0) {
1043
+ const components = [];
1044
+ for (const [componentId, collection] of this.components) {
1045
+ components.push({
1046
+ componentId,
1047
+ values: collection.getCurrentValuesArray(),
1048
+ deltas: collection.getPreviousEmittedDeltasArray()
1049
+ });
1050
+ }
1051
+ const states = [];
1052
+ for (const [stateId, collection] of this.states) {
1053
+ states.push({
1054
+ stateId,
1055
+ values: collection.values
1056
+ });
1057
+ }
1058
+ const initialCheckout = {
1059
+ type: "initialCheckout",
1060
+ components,
1061
+ states,
1062
+ indicesCount: this.nextIndex,
1063
+ serverTime: this.getServerTime()
1064
+ };
1065
+ const writer2 = new BufferWriter(this.nextIndex * this.components.size + 128);
1066
+ encodeInitialCheckout(initialCheckout, writer2);
1067
+ const v01EncodedInitialCheckout = writer2.getBuffer();
1068
+ for (const deltaNetV01Connection of this.preTickData.newJoinerConnections) {
1069
+ deltaNetV01Connection.sendEncodedBytes(v01EncodedInitialCheckout);
1070
+ }
1071
+ }
1072
+ for (const deltaNetV01Connection of this.preTickData.newJoinerConnections) {
1073
+ this.authenticatedDeltaNetV01Connections.add(deltaNetV01Connection);
1074
+ deltaNetV01Connection.setAuthenticated();
1075
+ }
1076
+ this.preTickData.unoccupyingIndices.clear();
1077
+ this.preTickData.newJoinerConnections.clear();
1078
+ this.preTickData.newJoinerCallbacks.clear();
1079
+ return {
1080
+ removedIds,
1081
+ addedIds
1082
+ };
1083
+ }
1084
+ getServerTime() {
1085
+ return Date.now() - this.documentEffectiveStartTime;
1086
+ }
1087
+ setUserComponents(deltaNetV01Connection, internalConnectionId, components) {
1088
+ if (this.disposed) {
1089
+ console.error("Cannot dispatch remote event after dispose");
1090
+ return { success: false, error: "This DeltaNetServer has been disposed" };
1091
+ }
1092
+ if (deltaNetV01Connection.isObserver) {
1093
+ return { success: false, error: "Observers cannot send component updates" };
1094
+ }
1095
+ if (this.opts.onComponentsUpdate) {
1096
+ try {
1097
+ const result = this.opts.onComponentsUpdate({
1098
+ deltaNetV01Connection,
1099
+ internalConnectionId,
1100
+ components
1101
+ });
1102
+ if (result instanceof DeltaNetServerError) {
1103
+ return { success: false, error: result.message };
1104
+ }
1105
+ if (result instanceof Error) {
1106
+ return { success: false, error: result.message };
1107
+ }
1108
+ } catch (error) {
1109
+ console.warn("Error in onComponentsUpdate callback:", error);
1110
+ if (error instanceof DeltaNetServerError) {
1111
+ return { success: false, error: error.message };
1112
+ }
1113
+ if (error instanceof Error) {
1114
+ return { success: false, error: error.message };
1115
+ }
1116
+ return { success: false, error: "Component update failed" };
1117
+ }
1118
+ }
1119
+ this.applyComponentUpdates(deltaNetV01Connection, internalConnectionId, components);
1120
+ return { success: true };
1121
+ }
1122
+ setComponentValue(componentId, index, value) {
1123
+ this.preTickData.componentsUpdated++;
1124
+ let collection = this.components.get(componentId);
1125
+ if (!collection) {
1126
+ collection = new ComponentCollection();
1127
+ this.components.set(componentId, collection);
1128
+ }
1129
+ collection.setValue(index, value);
1130
+ }
1131
+ applyComponentUpdates(deltaNetV01Connection, internalConnectionId, components) {
1132
+ if (this.preTickData.newJoinerConnections.has(deltaNetV01Connection)) {
1133
+ for (const [componentId, componentValue] of components) {
1134
+ deltaNetV01Connection.components.set(componentId, componentValue);
1135
+ }
1136
+ return;
1137
+ }
1138
+ const index = this.connectionIdToComponentIndex.get(internalConnectionId);
1139
+ if (index === void 0) {
1140
+ return;
1141
+ }
1142
+ for (const [componentId, componentValue] of components) {
1143
+ this.setComponentValue(componentId, index, componentValue);
1144
+ }
1145
+ }
1146
+ overrideUserStates(deltaNetV01Connection, internalConnectionId, states) {
1147
+ this.applyStateUpdates(deltaNetV01Connection, internalConnectionId, states);
1148
+ }
1149
+ setUserState(index, stateId, stateValue) {
1150
+ let collection = this.states.get(stateId);
1151
+ if (!collection) {
1152
+ collection = new StateCollection();
1153
+ this.states.set(stateId, collection);
1154
+ }
1155
+ collection.setValue(index, stateValue);
1156
+ }
1157
+ applyStateUpdates(deltaNetV01Connection, internalConnectionId, states) {
1158
+ if (deltaNetV01Connection !== null && this.preTickData.newJoinerConnections.has(deltaNetV01Connection)) {
1159
+ for (const [stateId, stateValue] of states) {
1160
+ deltaNetV01Connection.states.set(stateId, stateValue);
1161
+ }
1162
+ return;
1163
+ }
1164
+ const index = this.connectionIdToComponentIndex.get(internalConnectionId);
1165
+ if (index === void 0) {
1166
+ return;
1167
+ }
1168
+ for (const [stateId, stateValue] of states) {
1169
+ this.setUserState(index, stateId, stateValue);
1170
+ }
1171
+ }
1172
+ handleCustomMessage(deltaNetV01Connection, internalConnectionId, customType, contents) {
1173
+ if (this.disposed) {
1174
+ return;
1175
+ }
1176
+ if (this.opts.onCustomMessage) {
1177
+ try {
1178
+ this.opts.onCustomMessage({
1179
+ deltaNetV01Connection,
1180
+ internalConnectionId,
1181
+ customType,
1182
+ contents
1183
+ });
1184
+ } catch (error) {
1185
+ console.warn("Error in onCustomMessage callback:", error);
1186
+ }
1187
+ }
1188
+ }
1189
+ broadcastCustomMessage(customType, contents) {
1190
+ console.log("Broadcasting custom message", customType, contents);
1191
+ if (this.disposed) {
1192
+ return;
1193
+ }
1194
+ const writer = new BufferWriter(contents.length + 16);
1195
+ const message = {
1196
+ type: "serverCustom",
1197
+ customType,
1198
+ contents
1199
+ };
1200
+ const encodedMessage = encodeServerMessage2(message, writer);
1201
+ const messageBytes = encodedMessage.getBuffer();
1202
+ this.authenticatedDeltaNetV01Connections.forEach((connection) => {
1203
+ try {
1204
+ connection.sendEncodedBytes(messageBytes);
1205
+ } catch (error) {
1206
+ console.warn("Failed to send custom message to connection:", error);
1207
+ }
1208
+ });
1209
+ }
1210
+ dispose() {
1211
+ this.disposed = true;
1212
+ const connectionsToClose = Array.from(this.allDeltaNetV01Connections);
1213
+ for (const connection of connectionsToClose) {
1214
+ try {
1215
+ connection.webSocket.close(1001, "Server shutting down");
1216
+ } catch (error) {
1217
+ console.warn("Failed to close connection during disposal:", error);
1218
+ }
1219
+ }
1220
+ this.allDeltaNetV01Connections.clear();
1221
+ this.authenticatedDeltaNetV01Connections.clear();
1222
+ this.observerConnections.clear();
1223
+ this.webSocketToDeltaNetServerConnection.clear();
1224
+ this.connectionIdToDeltaNetServerConnection.clear();
1225
+ this.connectionIdToComponentIndex.clear();
1226
+ this.componentIndexToConnectionId.clear();
1227
+ this.components.clear();
1228
+ this.states.clear();
1229
+ this.preTickData.newJoinerConnections.clear();
1230
+ this.preTickData.unoccupyingIndices.clear();
1231
+ }
1232
+ };
1233
+ export {
1234
+ DeltaNetServer2 as DeltaNetServer,
1235
+ DeltaNetServerError,
1236
+ DeltaNetV01Connection
1237
+ };
1238
+ //# sourceMappingURL=index.js.map