topazcube 0.1.21 → 0.1.23

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/dist/client.js CHANGED
@@ -150,7 +150,7 @@ async function decompress(buffer) {
150
150
  // src/client.ts
151
151
  import { vec3, quat } from "gl-matrix";
152
152
  var TopazCubeClient = class {
153
- debug = false;
153
+ DEBUG = false;
154
154
  CYCLE = 200;
155
155
  // update/patch rate in ms
156
156
  url = "";
@@ -181,6 +181,9 @@ var TopazCubeClient = class {
181
181
  ID = 0;
182
182
  socket = null;
183
183
  _peerConnection = null;
184
+ _candidates = [];
185
+ _remoteCandidates = [];
186
+ _offerSent = false;
184
187
  _dataChannel = null;
185
188
  // our data channel
186
189
  _serverDataChannel = null;
@@ -204,15 +207,30 @@ var TopazCubeClient = class {
204
207
  // auto reconnect on disconnect
205
208
  allowSync = true,
206
209
  // allow sync on connect
207
- allowWebRTC = false
210
+ allowWebRTC = false,
211
+ DEBUG = false
208
212
  }) {
209
213
  this.url = url;
210
214
  this.autoReconnect = autoReconnect;
211
215
  this.allowSync = allowSync;
212
216
  this.allowWebRTC = allowWebRTC;
213
217
  this.socket = null;
218
+ this.DEBUG = DEBUG;
214
219
  this._startLoop();
215
- console.log("Client initialized");
220
+ this.log("Client initialized");
221
+ }
222
+ log(...args) {
223
+ if (this.DEBUG) {
224
+ console.log(...args);
225
+ }
226
+ }
227
+ warn(...args) {
228
+ if (this.DEBUG) {
229
+ console.warn(...args);
230
+ }
231
+ }
232
+ error(...args) {
233
+ console.error(...args);
216
234
  }
217
235
  /*= UPDATE ===================================================================*/
218
236
  _startLoop() {
@@ -283,20 +301,32 @@ var TopazCubeClient = class {
283
301
  let t2 = e._lpostime2;
284
302
  const interval = t2 - t1;
285
303
  const elapsed = now - t1;
286
- const alpha = Math.max(0, elapsed / interval);
287
- vec3.lerp(this._dpos, e._lpos1, e._lpos2, alpha);
288
- vec3.lerp(e.position, e.position, this._dpos, 0.07);
289
- e._changed_position = now;
304
+ e.pelapsed = elapsed;
305
+ if (elapsed > 1e3) {
306
+ vec3.copy(e.position, e._lpos2);
307
+ e._changed_position = now;
308
+ } else {
309
+ const alpha = Math.max(0, elapsed / interval);
310
+ vec3.lerp(this._dpos, e._lpos1, e._lpos2, alpha);
311
+ vec3.lerp(e.position, e.position, this._dpos, 0.07);
312
+ e._changed_position = now;
313
+ }
290
314
  }
291
315
  if (e._lrottime1 && e._lrottime2) {
292
316
  let t1 = e._lrottime1;
293
317
  let t2 = e._lrottime2;
294
318
  const interval = t2 - t1;
295
319
  const elapsed = now - t1;
296
- const alpha = Math.max(0, elapsed / interval);
297
- quat.slerp(this._drot, e._lrot1, e._lrot2, alpha);
298
- quat.slerp(e.rotation, e.rotation, this._drot, 0.07);
299
- e._changed_rotation = now;
320
+ e.relapsed = elapsed;
321
+ if (elapsed > 1e3) {
322
+ quat.copy(e.rotation, e._lrot2);
323
+ e._changed_rotation = now;
324
+ } else {
325
+ const alpha = Math.max(0, elapsed / interval);
326
+ quat.slerp(this._drot, e._lrot1, e._lrot2, alpha);
327
+ quat.slerp(e.rotation, e.rotation, this._drot, 0.07);
328
+ e._changed_rotation = now;
329
+ }
300
330
  }
301
331
  }
302
332
  }
@@ -317,7 +347,7 @@ var TopazCubeClient = class {
317
347
  }
318
348
  this.isConnecting = true;
319
349
  this._clear();
320
- console.log("connecting...");
350
+ this.log("connecting...");
321
351
  this.socket = new WebSocket(this.url);
322
352
  this.socket.onmessage = async (event) => {
323
353
  let buffer = await event.data.arrayBuffer();
@@ -424,7 +454,7 @@ var TopazCubeClient = class {
424
454
  this.socket.send(enc);
425
455
  }
426
456
  } catch (e) {
427
- console.error("send failed", e);
457
+ this.error("send failed", e);
428
458
  }
429
459
  }
430
460
  get document() {
@@ -462,7 +492,7 @@ var TopazCubeClient = class {
462
492
  try {
463
493
  applyOperation(this.documents[name], dop);
464
494
  } catch (e) {
465
- console.error("applyOperation failed for", name, "with op", dop, e);
495
+ this.error("applyOperation failed for", name, "with op", dop, e);
466
496
  }
467
497
  }
468
498
  this.isPatched = false;
@@ -493,10 +523,10 @@ var TopazCubeClient = class {
493
523
  let nmessage = decode(cdecu);
494
524
  this._onMessage(nmessage);
495
525
  } catch (error) {
496
- console.error("Error decoding chunks:", error);
526
+ this.error("Error decoding chunks:", error);
497
527
  }
498
528
  } else {
499
- console.warn("missing chunks", cfound, "of", message.seq + 1);
529
+ this.warn("missing chunks", cfound, "of", message.seq + 1);
500
530
  }
501
531
  }
502
532
  } else if (message.c == "fpatch") {
@@ -509,11 +539,11 @@ var TopazCubeClient = class {
509
539
  if (this._lastUpdateId[name] < message.u) {
510
540
  let lp = message.u - this._lastUpdateId[name] - 1;
511
541
  if (lp > 0) {
512
- console.warn("Lost " + lp + " updates");
542
+ this.warn("Lost " + lp + " updates");
513
543
  }
514
544
  this._lastUpdateId[name] = message.u;
515
545
  } else if (this._lastUpdateId[name] > message.u) {
516
- console.warn(`Received outdated update ID for document ${name}: ${message.u} < ${this._lastUpdateId[name]}`);
546
+ this.warn(`Received outdated update ID for document ${name}: ${message.u} < ${this._lastUpdateId[name]}`);
517
547
  doPatch = false;
518
548
  }
519
549
  }
@@ -529,9 +559,11 @@ var TopazCubeClient = class {
529
559
  this.send({ c: "peng", ct: Date.now(), st: stime });
530
560
  this.stats.stdiff = stime + ping / 2 - time;
531
561
  this.stats.ping = ping;
532
- console.log("ping", ping, "ms", "stdiff", this.stats.stdiff, "ms");
562
+ this.log("ping", ping, "ms", "stdiff", this.stats.stdiff, "ms");
533
563
  } else if (message.c == "rtc-offer") {
564
+ this.log("RTC: offer received:", message);
534
565
  } else if (message.c == "rtc-answer") {
566
+ this.log("RTC: answer received:", message);
535
567
  try {
536
568
  const sessionDesc = new RTCSessionDescription({
537
569
  type: message.type,
@@ -540,30 +572,30 @@ var TopazCubeClient = class {
540
572
  if (this._peerConnection) {
541
573
  await this._peerConnection.setRemoteDescription(sessionDesc);
542
574
  }
575
+ this.log("RTC: Remote description set successfully");
576
+ for (let candidate of this._remoteCandidates) {
577
+ try {
578
+ await this._peerConnection?.addIceCandidate(candidate);
579
+ this.log("RTC: Added remote ICE candidate:", candidate);
580
+ } catch (error) {
581
+ this.error("RTC: Error adding remote ICE candidate:", error);
582
+ }
583
+ }
543
584
  } catch (error) {
544
- console.error("RTC: Error setting remote description:", error);
585
+ this.error("RTC: Error setting remote description:", error);
545
586
  }
546
587
  } else if (message.c == "rtc-candidate") {
547
- try {
548
- if (this._peerConnection && message.candidate) {
549
- await this._peerConnection.addIceCandidate(
550
- //new RTCIceCandidate(message.candidate)
551
- message.candidate
552
- );
553
- } else {
554
- console.warn(
555
- "RTC: Received candidate but peerConnection not ready or candidate missing"
556
- );
557
- }
558
- } catch (error) {
588
+ this.log("RTC: candidate received", message);
589
+ if (this._peerConnection && message.candidate) {
590
+ this._remoteCandidates.push(message.candidate);
559
591
  }
560
592
  } else {
561
593
  this.onMessage(message);
562
594
  }
563
595
  }
564
596
  _onDocumentChange(name, op, target, path, value) {
565
- if (this.debug) {
566
- console.log("Document change:", name, op, target, path, value);
597
+ if (this.DEBUG) {
598
+ this.log("Document change:", name, op, target, path, value);
567
599
  }
568
600
  if (this.isPatched || !this.allowSync) {
569
601
  return;
@@ -746,12 +778,12 @@ var TopazCubeClient = class {
746
778
  }
747
779
  }
748
780
  _onRTCConnect() {
749
- console.log("RTC: Connected");
781
+ this.log("RTC: Connected");
750
782
  this.send({ c: "test", message: "Hello RTC from client" });
751
783
  }
752
784
  _onRTCDisconnect() {
753
785
  this._webRTCConnected = false;
754
- console.log("RTC: Disconnected");
786
+ this.log("RTC: Disconnected");
755
787
  }
756
788
  async _onRTCMessage(data) {
757
789
  this.stats.recRTC += data.byteLength;
@@ -763,6 +795,9 @@ var TopazCubeClient = class {
763
795
  }
764
796
  async _initializeWebRTC() {
765
797
  this._peerConnection = null;
798
+ this._candidates = [];
799
+ this._remoteCandidates = [];
800
+ this._offerSent = false;
766
801
  try {
767
802
  this._peerConnection = new RTCPeerConnection({
768
803
  iceServers: [
@@ -774,22 +809,31 @@ var TopazCubeClient = class {
774
809
  });
775
810
  this._peerConnection.onicecandidate = (event) => {
776
811
  if (event.candidate) {
777
- this.send({
778
- c: "rtc-candidate",
779
- type: "ice-candidate",
780
- candidate: event.candidate
781
- });
812
+ this._candidates.push(event.candidate);
782
813
  } else {
814
+ this.log("RTC: ICE candidate gathering complete");
783
815
  }
784
816
  };
785
817
  this._peerConnection.onconnectionstatechange = () => {
786
818
  if (this._peerConnection && this._peerConnection.connectionState === "connected") {
787
819
  this._webRTCConnected = true;
820
+ this.log("RTC: Peer connection established!");
788
821
  } else if (this._peerConnection && (this._peerConnection.connectionState === "failed" || this._peerConnection.connectionState === "disconnected" || this._peerConnection.connectionState === "closed")) {
789
822
  this._webRTCConnected = false;
823
+ this.log("RTC: Peer connection closed or failed");
790
824
  }
791
825
  };
792
826
  this._peerConnection.onicegatheringstatechange = () => {
827
+ this.log(`RTC: ICE gathering state. _candidates:`, this._candidates.length, this._peerConnection?.iceGatheringState);
828
+ if (this._peerConnection?.iceGatheringState == "complete" && this._offerSent) {
829
+ for (let candidate of this._candidates) {
830
+ this.send({
831
+ c: "rtc-candidate",
832
+ type: "ice-candidate",
833
+ candidate
834
+ });
835
+ }
836
+ }
793
837
  };
794
838
  this._peerConnection.oniceconnectionstatechange = () => {
795
839
  if (this._peerConnection && (this._peerConnection.iceConnectionState === "connected" || this._peerConnection.iceConnectionState === "completed")) {
@@ -809,7 +853,7 @@ var TopazCubeClient = class {
809
853
  this._onRTCDisconnect();
810
854
  };
811
855
  this._dataChannel.onerror = (_error) => {
812
- console.error("RTC: Client data channel error", _error);
856
+ this.error("RTC: Client data channel error", _error);
813
857
  };
814
858
  this._peerConnection.ondatachannel = (event) => {
815
859
  const dataChannel = event.channel;
@@ -840,17 +884,18 @@ var TopazCubeClient = class {
840
884
  sdp: ld.sdp
841
885
  };
842
886
  this.send(offerPayload);
887
+ this._offerSent = true;
843
888
  }
844
889
  setTimeout(() => {
845
890
  if (!this._webRTCConnected && this._peerConnection) {
846
891
  if (this._peerConnection.iceConnectionState === "failed") {
847
- console.log("RTC: Attempting ICE restart");
892
+ this.log("RTC: Attempting ICE restart");
848
893
  this._restartIce();
849
894
  }
850
895
  }
851
896
  }, 5e3);
852
897
  } catch (error) {
853
- console.error("RTC: error:", error);
898
+ this.error("RTC: error:", error);
854
899
  }
855
900
  }
856
901
  // Add this method to restart ICE if needed
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts","../src/utils.ts","../src/compress-browser.ts"],"sourcesContent":["import { applyOperation } from 'fast-json-patch'\nimport {\n reactive,\n opmsg,\n msgop,\n decode_uint32,\n decode_fp412,\n decode_fp168,\n decode_fp1616,\n deepGet,\n encode,\n decode,\n} from './utils'\nimport { compress, decompress } from './compress-browser'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\ninterface Stats {\n send: number;\n rec: number;\n recRTC: number;\n sendBps: number;\n recBps: number;\n recRTCBps: number;\n ping: number;\n stdiff: number; // server time difference\n}\n\ninterface ConstructorParams {\n url: string; // server url\n autoReconnect?: boolean; // auto reconnect on disconnect\n allowSync?: boolean; // allow sync on connect\n allowWebRTC?: boolean;\n}\n\ninterface Message {\n c: string;\n [key: string]: any;\n}\n\ninterface Document {\n entities?: { [key: string]: any };\n origin?: vec3;\n [key: string]: any;\n}\n\ninterface Entity {\n position?: vec3;\n rotation?: quat;\n _lpos1?: vec3;\n _lpos2?: vec3;\n _lpostime1?: number | undefined;\n _lpostime2?: number | undefined;\n _lrot1?: quat;\n _lrot2?: quat;\n _lrottime1?: number | undefined;\n _lrottime2?: number | undefined;\n _lsca1?: vec3;\n _lsca2?: vec3;\n _lscatime1?: number | undefined;\n _lscatime2?: number | undefined;\n sca?: vec3;\n [key: string]: any;\n}\n// WebRTC type declarations for environments that don't have them built-in\ndeclare global {\n interface RTCPeerConnection {\n new(configuration?: RTCConfiguration): RTCPeerConnection;\n createOffer(options?: RTCOfferOptions): Promise<RTCSessionDescriptionInit>;\n createAnswer(options?: RTCAnswerOptions): Promise<RTCSessionDescriptionInit>;\n setLocalDescription(description?: RTCSessionDescriptionInit): Promise<void>;\n setRemoteDescription(description: RTCSessionDescriptionInit): Promise<void>;\n addIceCandidate(candidate?: RTCIceCandidateInit): Promise<void>;\n createDataChannel(label: string, dataChannelDict?: RTCDataChannelInit): RTCDataChannel;\n close(): void;\n readonly connectionState: RTCPeerConnectionState;\n readonly iceConnectionState: RTCIceConnectionState;\n readonly iceGatheringState: RTCIceGatheringState;\n readonly localDescription: RTCSessionDescription | null;\n readonly remoteDescription: RTCSessionDescription | null;\n onconnectionstatechange: ((this: RTCPeerConnection, ev: Event) => any) | null;\n oniceconnectionstatechange: ((this: RTCPeerConnection, ev: Event) => any) | null;\n onicegatheringstatechange: ((this: RTCPeerConnection, ev: Event) => any) | null;\n onicecandidate: ((this: RTCPeerConnection, ev: RTCPeerConnectionIceEvent) => any) | null;\n ondatachannel: ((this: RTCPeerConnection, ev: RTCDataChannelEvent) => any) | null;\n dataChannel?: RTCDataChannel;\n }\n\n interface RTCDataChannel {\n readonly label: string;\n readonly readyState: RTCDataChannelState;\n send(data: string | Blob | ArrayBuffer | ArrayBufferView): void;\n close(): void;\n onopen: ((this: RTCDataChannel, ev: Event) => any) | null;\n onclose: ((this: RTCDataChannel, ev: Event) => any) | null;\n onerror: ((this: RTCDataChannel, ev: Event) => any) | null;\n onmessage: ((this: RTCDataChannel, ev: MessageEvent) => any) | null;\n }\n\n interface RTCSessionDescription {\n readonly type: RTCSdpType;\n readonly sdp: string;\n }\n\n interface RTCIceCandidate {\n new(candidateInitDict?: RTCIceCandidateInit): RTCIceCandidate;\n }\n\n interface RTCPeerConnectionIceEvent extends Event {\n readonly candidate: RTCIceCandidate | null;\n }\n\n interface RTCDataChannelEvent extends Event {\n readonly channel: RTCDataChannel;\n }\n\n type RTCPeerConnectionState = 'closed' | 'connected' | 'connecting' | 'disconnected' | 'failed' | 'new';\n type RTCIceConnectionState = 'checking' | 'closed' | 'completed' | 'connected' | 'disconnected' | 'failed' | 'new';\n type RTCIceGatheringState = 'complete' | 'gathering' | 'new';\n type RTCDataChannelState = 'closed' | 'closing' | 'connecting' | 'open';\n type RTCSdpType = 'answer' | 'offer' | 'pranswer' | 'rollback';\n\n interface RTCConfiguration {\n iceServers?: RTCIceServer[];\n iceCandidatePoolSize?: number;\n }\n\n interface RTCIceServer {\n urls: string | string[];\n username?: string;\n credential?: string;\n }\n\n interface RTCOfferOptions {\n offerToReceiveAudio?: boolean;\n offerToReceiveVideo?: boolean;\n iceRestart?: boolean;\n }\n\n interface RTCAnswerOptions {\n // Currently no standard options for answers\n }\n\n interface RTCSessionDescriptionInit {\n type: RTCSdpType;\n sdp?: string;\n }\n\n interface RTCIceCandidateInit {\n candidate?: string;\n sdpMLineIndex?: number | null;\n sdpMid?: string | null;\n usernameFragment?: string | null;\n }\n\n interface RTCDataChannelInit {\n ordered?: boolean;\n maxPacketLifeTime?: number;\n maxRetransmits?: number;\n protocol?: string;\n negotiated?: boolean;\n id?: number;\n }\n\n const RTCPeerConnection: {\n prototype: RTCPeerConnection;\n new(configuration?: RTCConfiguration): RTCPeerConnection;\n };\n\n const RTCSessionDescription: {\n prototype: RTCSessionDescription;\n new(descriptionInitDict: RTCSessionDescriptionInit): RTCSessionDescription;\n };\n\n const RTCIceCandidate: {\n prototype: RTCIceCandidate;\n new(candidateInitDict?: RTCIceCandidateInit): RTCIceCandidate;\n };\n}\n\nexport default class TopazCubeClient {\n debug = false\n CYCLE = 200 // update/patch rate in ms\n url = ''\n documents: { [key: string]: Document } = {}\n autoReconnect = true\n allowSync = true\n allowWebRTC = false\n isConnected = false\n isConnecting = false\n isPatched = false\n stats: Stats = {\n send: 0,\n rec: 0,\n recRTC: 0,\n\n sendBps: 0,\n recBps: 0,\n recRTCBps: 0,\n\n ping: 0,\n stdiff: 0, // server time difference\n }\n lastFullState = 0\n lastPatch = 0\n _chunks: { [key: string]: any } = {}\n le = true // Server is little endian\n _documentChanges: { [key: string]: any[] } = {}\n\n ID = 0\n socket: WebSocket | null = null\n _peerConnection: RTCPeerConnection | null = null\n _dataChannel: RTCDataChannel | null = null // our data channel\n _serverDataChannel: RTCDataChannel | null = null // server data channel\n _webRTCConnected: boolean = false\n\n isInterpolated = false\n _lastInterpolate = Date.now()\n _lastUpdateId: { [key: string]: number } = {}\n _dpos: vec3 = [0, 0, 0]\n _drot: quat = [0, 0, 0, 1]\n _sca: vec3 = [1, 1, 1]\n _notifyChanges = true\n _siv: NodeJS.Timeout | null = null\n _loopiv: NodeJS.Timeout | null = null\n _updateiv: NodeJS.Timeout | null = null\n _pingiv: NodeJS.Timeout | null = null\n\n\n constructor({\n url, // server url\n autoReconnect = true, // auto reconnect on disconnect\n allowSync = true, // allow sync on connect\n allowWebRTC = false,\n }: ConstructorParams) {\n this.url = url\n this.autoReconnect = autoReconnect\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.socket = null\n this._startLoop()\n console.log('Client initialized')\n }\n\n /*= UPDATE ===================================================================*/\n\n _startLoop() {\n if (this._loopiv) {\n clearInterval(this._loopiv)\n }\n this._loopiv = setInterval(() => {\n this._loop()\n }, this.CYCLE)\n this._siv = setInterval(() => {\n this._updateStats()\n }, 1000)\n this._pingiv = setInterval(() => {\n this._ping()\n }, 10000)\n }\n _loop() {\n if (!this.isConnected) {\n return\n }\n this._sendPatches()\n }\n\n _updateStats() {\n this.stats.recBps = this.stats.rec\n this.stats.rec = 0\n this.stats.recRTCBps = this.stats.recRTC\n this.stats.recRTC = 0\n this.stats.sendBps = this.stats.send\n this.stats.send = 0\n }\n\n _clear() {\n this.stats.sendBps = 0\n this.stats.recBps = 0\n this.stats.recRTC = 0\n this.stats.recRTCBps = 0\n this.stats.send = 0\n this.stats.rec = 0\n\n this.ID = 0\n this.documents = {}\n this._documentChanges = {}\n this._lastUpdateId = {}\n this.lastFullState = 0\n this.lastPatch = 0\n this._lastInterpolate = 0\n this.isPatched = false\n this.le = true\n }\n\n /*= INTERPOLATION ============================================================*/\n\n // to be called in display rate (like 60fps) to interpolate .position, .rotation and .scale\n interpolate() {\n let now = Date.now()\n let dt = now - this._lastInterpolate\n this._lastInterpolate = now\n if (dt <= 0 || dt > 200) { return }\n this.isInterpolated = true\n for (let name in this.documents) {\n let doc = this.documents[name]\n let entities = doc?.entities\n if (!entities) { continue }\n for (let id in entities) {\n let e: Entity = entities[id]\n if (e._lpostime1 && e._lpostime2) {\n let t1 = e._lpostime1\n let t2 = e._lpostime2\n const interval = t2 - t1;\n const elapsed = now - t1;\n const alpha = Math.max(0, elapsed / interval)\n vec3.lerp(this._dpos, e._lpos1!, e._lpos2!, alpha)\n vec3.lerp(e.position!, e.position!, this._dpos, 0.07)\n e._changed_position = now\n }\n if (e._lrottime1 && e._lrottime2) {\n\n let t1 = e._lrottime1\n let t2 = e._lrottime2\n const interval = t2 - t1;\n const elapsed = now - t1;\n const alpha = Math.max(0, elapsed / interval)\n quat.slerp(this._drot, e._lrot1!, e._lrot2!, alpha)\n quat.slerp(e.rotation!, e.rotation!, this._drot, 0.07)\n e._changed_rotation = now\n }\n\n }\n }\n this.isInterpolated = false\n }\n\n /*= CONNECTION ===============================================================*/\n\n subscribe(name: string) {\n this.documents[name] = {}\n this.send({ c: 'sub', n: name })\n }\n\n unsubscribe(name: string) {\n this.send({ c: 'unsub', n: name })\n delete this.documents[name]\n }\n\n connect() {\n if (this.isConnecting) {\n return\n }\n this.isConnecting = true\n this._clear()\n console.log('connecting...')\n\n this.socket = new WebSocket(this.url)\n\n // message received\n this.socket.onmessage = async (event: MessageEvent) => {\n let buffer = await event.data.arrayBuffer()\n this.stats.rec += buffer.byteLength\n let dec = await decompress(buffer)\n let decu = new Uint8Array(dec)\n let message = decode(decu)\n this._onMessage(message)\n }\n\n // connection closed\n this.socket.onclose = (_event: any) => {\n this._clear()\n this.isConnected = false\n this.isConnecting = false\n this.lastFullState = 0\n this.socket = null\n this.onDisconnect()\n if (this.allowWebRTC) {\n this._destroyWebRTC()\n }\n if (this.autoReconnect) {\n setTimeout(\n () => {\n this._reconnect()\n },\n 500 + Math.random() * 500\n )\n }\n }\n\n this.socket.onerror = (_event: Event) => {\n this._clear()\n this.isConnected = false\n this.isConnecting = false\n this.lastFullState = 0\n this.socket = null\n this.onDisconnect()\n if (this.allowWebRTC) {\n this._destroyWebRTC()\n }\n\n if (this.autoReconnect) {\n setTimeout(\n () => {\n this._reconnect()\n },\n 500 + Math.random() * 500\n )\n }\n }\n\n this.socket.onopen = async (_event: Event) => {\n this._clear()\n this.isConnecting = false\n this.isConnected = true\n this.lastFullState = 0\n this._ping()\n this.onConnect()\n if (this.allowWebRTC) {\n await this._initializeWebRTC()\n }\n }\n }\n\n disconnect() {\n this._clear()\n this.isConnected = false\n this.isConnecting = false\n this.lastFullState = 0\n if (this.socket) {\n this.socket.close()\n }\n this.socket = null\n }\n\n destroy() {\n this._clear()\n this.autoReconnect = false\n this.disconnect()\n this.socket = null\n if (this._siv) clearInterval(this._siv)\n if (this._loopiv) clearInterval(this._loopiv)\n }\n\n onConnect() {}\n\n onDisconnect() {}\n\n _reconnect() {\n if (!this.isConnected) {\n if (!this.isConnecting) {\n this.connect()\n }\n }\n }\n\n _ping() {\n if (this.isConnected) {\n this.send({ c: 'ping', ct: Date.now() })\n }\n }\n\n /*= MESSAGES =================================================================*/\n\n onChange(_name: string, _doc: Document | undefined, patch: any | undefined) {}\n\n onMessage(_message: Message) {}\n\n send(operation: any) {\n try {\n let enc = encode(operation)\n this.stats.send += enc.byteLength\n if (this.socket) {\n this.socket.send(enc)\n }\n } catch (e) {\n console.error('send failed', e)\n }\n }\n\n get document(): Document | undefined {\n let names:string = ''+Object.keys(this.documents)\n return this.documents[''+names[0]]\n }\n\n async _onMessage(message: Message) {\n let time = Date.now()\n if (message.c == 'full') {\n //console.log('full:', message)\n let name:string = ''+message.n\n let doc = message.doc\n this.documents[name] = doc\n this._decodeFastChanges(message)\n this.isPatched = false\n if (this.allowSync) {\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this)\n )\n }\n this.isPatched = false\n this.lastFullState = message.t\n this.le = message.le\n if (this._notifyChanges) {\n this.onChange(name, this.documents[name], null)\n }\n } else if (message.c == 'patch') {\n // patch\n this.lastPatch = message.t\n let name = message.n\n if (message.doc) {\n this.isPatched = true\n for (let op of message.doc) {\n let dop = msgop(op)\n try {\n applyOperation(this.documents[name], dop)\n } catch (e) {\n console.error('applyOperation failed for', name, 'with op', dop, e)\n }\n }\n this.isPatched = false\n }\n if (this._notifyChanges) {\n this.onChange(name, this.documents[name], message.doc)\n }\n } else if (message.c == 'chunk') {\n //console.log('chunk', message)\n this._chunks[message.mid+'-'+message.seq] = message\n if (message.last) {\n let cfound = 0\n let ts = message.ts\n let cdata = new Uint8Array(ts)\n for (const cid in this._chunks) {\n let chunk = this._chunks[cid]\n if (chunk.mid == message.mid) {\n let offset = chunk.ofs\n let _csize = chunk.chs\n cdata.set(new Uint8Array(chunk.data), offset);\n cfound++\n delete this._chunks[cid]\n }\n }\n //console.log('found chunks ', cfound, 'of', message.seq + 1)\n if (cfound == message.seq + 1) {\n try {\n let cdec = await decompress(cdata)\n let cdecu = new Uint8Array(cdec)\n let nmessage = decode(cdecu)\n //console.log('decoded message', nmessage)\n this._onMessage(nmessage)\n } catch (error) {\n console.error('Error decoding chunks:', error)\n }\n } else {\n console.warn('missing chunks', cfound, 'of', message.seq + 1)\n }\n }\n } else if (message.c == 'fpatch') {\n time = Date.now()\n let name = message.n\n //console.log('fpatch', message)\n let doPatch = true\n if (!this._lastUpdateId[name]) {\n this._lastUpdateId[name] = message.u\n } else {\n if (this._lastUpdateId[name] < message.u) {\n let lp = message.u - this._lastUpdateId[name] - 1\n if (lp > 0) {\n console.warn('Lost ' + lp + ' updates')\n }\n this._lastUpdateId[name] = message.u\n } else if (this._lastUpdateId[name] > message.u) {\n // Handle the case where the server's update ID is older than the client's\n // This could be due to a network issue or a clock skew\n console.warn(`Received outdated update ID for document ${name}: ${message.u} < ${this._lastUpdateId[name]}`)\n doPatch = false\n }\n }\n if (doPatch) {\n this._decodeFastChanges(message)\n }\n } else if (message.c == 'pong') {\n this.ID = message.ID\n time = Date.now()\n let lastct = message.ct\n let ping = time - lastct\n let stime = message.t\n this.send({ c: 'peng', ct: Date.now(), st: stime })\n this.stats.stdiff = stime + ping / 2 - time\n this.stats.ping = ping\n console.log('ping', ping, 'ms', 'stdiff', this.stats.stdiff, 'ms')\n } else if (message.c == 'rtc-offer') {\n //console.log(\"RTC: offer received:\", message);\n // You might need to handle this if the server sends offers\n } else if (message.c == 'rtc-answer') {\n //console.log(\"RTC: answer received:\", message);\n try {\n const sessionDesc = new RTCSessionDescription({\n type: message.type,\n sdp: message.sdp,\n })\n if (this._peerConnection) {\n await this._peerConnection.setRemoteDescription(sessionDesc)\n }\n //console.log(\"RTC: Remote description set successfully\");\n\n // Log the current state after setting remote description\n //console.log(\"RTC: Current connection state:\", this._peerConnection.connectionState);\n //console.log(\"RTC: Current ICE connection state:\", this._peerConnection.iceConnectionState);\n } catch (error) {\n console.error('RTC: Error setting remote description:', error)\n }\n } else if (message.c == 'rtc-candidate') {\n //console.log(\"RTC: candidate received\", message);\n try {\n if (this._peerConnection && message.candidate) {\n await this._peerConnection.addIceCandidate(\n //new RTCIceCandidate(message.candidate)\n message.candidate\n )\n //console.log(\"RTC: ICE candidate added successfully\");\n } else {\n console.warn(\n 'RTC: Received candidate but peerConnection not ready or candidate missing'\n )\n }\n } catch (error) {\n //console.error(\"RTC: Error adding ICE candidate:\", error);\n }\n } else {\n this.onMessage(message)\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: string, value: any) {\n if (this.debug) {\n console.log('Document change:', name, op, target, path, value)\n }\n if (this.isPatched || !this.allowSync) {\n return\n }\n if (path.indexOf('/_') >= 0) {\n return\n }\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n this._documentChanges[name].push(opmsg(op, target, path, value))\n }\n\n _sendPatches() {\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n if (!dc || dc.length == 0) {\n continue\n }\n let record: any = {\n n: name,\n c: 'sync',\n ct: Date.now(),\n p: null\n }\n\n if (dc.length > 0) {\n record.p = dc\n }\n this.send(record)\n dc.length = 0\n if (this._notifyChanges) {\n this.onChange(name, this.documents[''+name], record.p)\n }\n }\n }\n\n _decodeFastChanges(message: Message) {\n let time = Date.now()\n let name = message.n\n let fdata = message.fdata\n if (!fdata) {\n return\n }\n let doc = this.documents[name]\n if (!doc) {\n return\n }\n let entities = doc.entities\n if (!entities) {\n return\n }\n let origin = this.documents[''+name]?.origin\n if (!origin) {\n origin = [0, 0, 0]\n }\n for (let key in fdata) {\n let changes = fdata[key]\n if (changes.dict) {\n let pdata = changes.pdata\n let dict = changes.dict\n // Reverse the dictionary for lookup (value to key)\n let rdict: { [key: string]: string } = {};\n for (let key in dict) {\n rdict[dict[key]] = key;\n }\n let offset = 0\n\n while (offset < pdata.byteLength) {\n let id = ''+decode_uint32(pdata, offset)\n offset += 4\n let did = ''+decode_uint32(pdata, offset)\n offset += 4\n let e: Entity = entities[id]\n if (!e) {\n //console.log('Entity not found:', id)\n continue\n }\n let value = rdict[did]\n e[key] = value\n //console.log('FCHANGE', key, id, did, value, rdict)\n e['_changed_'+key] = time\n }\n } else {\n let pdata = changes.pdata\n let offset = 0\n while (offset < pdata.byteLength) {\n let id = ''+decode_uint32(pdata, offset)\n let e: Entity = entities[id]\n if (!e) {\n if (key == 'position') {\n offset += 13\n } else if (key == 'rotation') {\n offset += 8\n } else if (key == 'scale') {\n offset += 16\n }\n continue\n }\n offset += 4\n\n if (key == 'position') {\n if (!e._lpos2) {\n e._lpos1 = [0, 0, 0]\n e._lpos2 = [0, 0, 0]\n } else {\n e._lpos1![0] = e._lpos2[0]\n e._lpos1![1] = e._lpos2[1]\n e._lpos1![2] = e._lpos2[2]\n e._lpostime1 = e._lpostime2\n }\n e._lpostime2 = time\n e._lpos2[0] = origin[0] + decode_fp168(pdata, offset)\n offset += 3\n e._lpos2[1] = origin[1] + decode_fp168(pdata, offset)\n offset += 3\n e._lpos2[2] = origin[2] + decode_fp168(pdata, offset)\n offset += 3\n if (!e.position) {\n e.position = [\n e._lpos2[0],\n e._lpos2[1],\n e._lpos2[2],\n ]\n }\n } else if (key == 'rotation') {\n if (!e._lrot2) {\n e._lrot1 = [0, 0, 0, 1]\n e._lrot2 = [0, 0, 0, 1]\n } else {\n e._lrot1![0] = e._lrot2[0]\n e._lrot1![1] = e._lrot2[1]\n e._lrot1![2] = e._lrot2[2]\n e._lrot1![3] = e._lrot2[3]\n e._lrottime1 = e._lrottime2\n }\n e._lrottime2 = time\n e._lrot2[0] = decode_fp412(pdata, offset)\n offset += 2\n e._lrot2[1] = decode_fp412(pdata, offset)\n offset += 2\n e._lrot2[2] = decode_fp412(pdata, offset)\n offset += 2\n e._lrot2[3] = decode_fp412(pdata, offset)\n offset += 2\n quat.normalize(e._lrot2, e._lrot2)\n if (!e.rotation) {\n e.rotation = [\n e._lrot2[0],\n e._lrot2[1],\n e._lrot2[2],\n e._lrot2[3],\n ]\n }\n } else if (key == 'scale') {\n if (!e._lsca2) {\n e._lsca1 = [0, 0, 0]\n e._lsca2 = [0, 0, 0]\n } else {\n e._lsca1![0] = e._lsca2[0]\n e._lsca1![1] = e._lsca2[1]\n e._lsca1![2] = e._lsca2[2]\n e._lscatime1 = e._lscatime2\n }\n e._lscatime2 = time\n e._lsca2[0] = decode_fp1616(pdata, offset)\n offset += 4\n e._lsca2[1] = decode_fp1616(pdata, offset)\n offset += 4\n e._lsca2[2] = decode_fp1616(pdata, offset)\n offset += 4\n if (!e.sca) {\n e.sca = [\n e._lsca2[0],\n e._lsca2[1],\n e._lsca2[2],\n ]\n }\n }\n }\n }\n }\n }\n\n /*= WEBRTC ===================================================================*/\n\n sendRTC(message: Message) {\n if (this._dataChannel && this._dataChannel.readyState === 'open') {\n this._dataChannel.send(encode(message))\n }\n }\n\n _onRTCConnect() {\n console.log('RTC: Connected')\n this.send({ c: 'test', message: 'Hello RTC from client' })\n }\n\n _onRTCDisconnect() {\n this._webRTCConnected = false\n console.log('RTC: Disconnected')\n }\n\n async _onRTCMessage(data: ArrayBuffer) {\n this.stats.recRTC += data.byteLength\n let datau = new Uint8Array(data)\n let dec = await decompress(datau)\n let decu = new Uint8Array(dec)\n let message = decode(decu)\n this._onMessage(message)\n }\n\n async _initializeWebRTC() {\n //console.log(\"RTC: _initializeWebRTC\")\n this._peerConnection = null\n try {\n // Create RTCPeerConnection with more comprehensive STUN server list\n this._peerConnection = new RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n iceCandidatePoolSize: 10,\n })\n\n //console.log(\"RTC: peerConnection created\", this._peerConnection)\n\n // Handle ICE candidates\n this._peerConnection.onicecandidate = (event: RTCPeerConnectionIceEvent) => {\n //console.log(\"RTC: onicecandidate\", event.candidate)\n if (event.candidate) {\n this.send({\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: event.candidate,\n })\n } else {\n //console.log(\"RTC: ICE candidate gathering complete\")\n }\n }\n\n // Log connection state changes\n this._peerConnection.onconnectionstatechange = () => {\n //console.log(`RTC: Connection state changed: ${this._peerConnection.connectionState}`)\n if (this._peerConnection && this._peerConnection.connectionState === 'connected') {\n this._webRTCConnected = true\n } else if (\n this._peerConnection && (\n this._peerConnection.connectionState === 'failed' ||\n this._peerConnection.connectionState === 'disconnected' ||\n this._peerConnection.connectionState === 'closed')\n ) {\n this._webRTCConnected = false\n }\n }\n\n this._peerConnection.onicegatheringstatechange = () => {\n //console.log(`RTC: ICE gathering state: ${this._peerConnection.iceGatheringState}`)\n }\n\n this._peerConnection.oniceconnectionstatechange = () => {\n //console.log(`RTC: ICE connection state: ${this._peerConnection.iceConnectionState}`)\n\n // This is critical - when ICE succeeds, the connection should be established\n if (\n this._peerConnection && (\n this._peerConnection.iceConnectionState === 'connected' ||\n this._peerConnection.iceConnectionState === 'completed')\n ) {\n //console.log(\"RTC: ICE connection established!\")\n }\n }\n\n // Create a data channel on our side as well (belt and suspenders approach)\n this._dataChannel = this._peerConnection.createDataChannel(\n 'clientchannel',\n {\n ordered: true,\n maxRetransmits: 1,\n }\n )\n\n this._dataChannel.onopen = () => {\n this._onRTCConnect()\n }\n\n this._dataChannel.onclose = () => {\n this._onRTCDisconnect()\n }\n\n this._dataChannel.onerror = (_error: Event) => {\n console.error('RTC: Client data channel error', _error)\n }\n\n // Handle data channels created by the server\n this._peerConnection.ondatachannel = (event: RTCDataChannelEvent) => {\n //console.log(\"RTC: Server data channel received\", event.channel.label);\n const dataChannel = event.channel\n this._serverDataChannel = dataChannel\n\n dataChannel.onopen = () => {\n //console.log(\"RTC: Server data channel open\");\n }\n\n dataChannel.onclose = () => {\n //console.log(\"RTC: Server data channel closed\");\n }\n\n dataChannel.onerror = (_error: Event) => {\n //console.error(\"RTC: Server data channel error\", error);\n }\n\n dataChannel.onmessage = (event: MessageEvent) => {\n this._onRTCMessage(event.data)\n }\n }\n\n // Create and send offer with specific constraints\n const offerOptions: RTCOfferOptions = {\n offerToReceiveAudio: false,\n offerToReceiveVideo: false,\n iceRestart: true,\n }\n\n const offer = await this._peerConnection.createOffer(offerOptions)\n //console.log(\"RTC: our offer:\", offer);\n await this._peerConnection.setLocalDescription(offer)\n\n // Wait a moment to ensure the local description is set\n await new Promise((resolve) => setTimeout(resolve, 100))\n\n let ld = this._peerConnection.localDescription\n //console.log(\"RTC: our localDescription\", ld);\n\n if (ld) {\n const offerPayload = {\n c: 'rtc-offer',\n type: ld.type,\n sdp: ld.sdp,\n }\n //console.log(\"RTC: our offer payload\", offerPayload);\n this.send(offerPayload)\n }\n\n // Set a timeout to check connection status\n setTimeout(() => {\n if (!this._webRTCConnected && this._peerConnection) {\n /*\n console.log(\"RTC: Connection not established after timeout, current states:\");\n console.log(\"Connection state:\", this._peerConnection.connectionState);\n console.log(\"ICE connection state:\", this._peerConnection.iceConnectionState);\n console.log(\"ICE gathering state:\", this._peerConnection.iceGatheringState);\n */\n // Attempt to restart ICE if needed\n if (this._peerConnection.iceConnectionState === 'failed') {\n console.log('RTC: Attempting ICE restart')\n this._restartIce()\n }\n }\n }, 5000)\n } catch (error) {\n console.error('RTC: error:', error)\n }\n }\n\n // Add this method to restart ICE if needed\n async _restartIce() {\n try {\n const offerOptions = {\n offerToReceiveAudio: false,\n offerToReceiveVideo: false,\n iceRestart: true,\n }\n\n const offer = await this._peerConnection?.createOffer(offerOptions)\n await this._peerConnection?.setLocalDescription(offer)\n\n const offerPayload = {\n c: 'rtc-offer',\n type: offer?.type,\n sdp: offer?.sdp,\n }\n //console.log(\"RTC: ICE restart offer payload\", offerPayload);\n this.send(offerPayload)\n } catch (error) {\n //console.error(\"RTC: Error during ICE restart:\", error);\n }\n }\n\n async _destroyWebRTC() {\n if (this._peerConnection) {\n if (this._peerConnection.dataChannel) {\n this._peerConnection.dataChannel.close()\n }\n this._peerConnection.close()\n this._peerConnection = null\n }\n if (this._dataChannel) {\n this._dataChannel.close()\n this._dataChannel = null\n }\n this._webRTCConnected = false\n }\n}\n","import { Packr } from 'msgpackr';\nimport { FLOAT32_OPTIONS } from 'msgpackr';\nconst { ALWAYS } = FLOAT32_OPTIONS;\n\nlet packr = new Packr({\n useFloat32: ALWAYS\n});\n\nexport function encode(obj: any): Uint8Array {\n return packr.pack(obj)\n}\n\nexport function decode(data: Uint8Array): any {\n return packr.unpack(data)\n}\n\ntype ReactiveCallback = (name: string, operation: string, target: any, path: string, value: any) => void;\n\nexport function reactive(name: string, object: any, callback: ReactiveCallback, path: string = '', excludedProperties: Record<string, boolean> | false = false): any {\n if (object === null || typeof object !== 'object') {\n //console.log('--- Type not object', typeof object)\n return object\n }\n\n function isReactive(p: string): boolean {\n let r = true\n if (p.startsWith('_')) {\n r = false\n }\n if (excludedProperties) {\n if (excludedProperties[p]) {\n r = false\n }\n }\n if (path == '/entities') {\n r = false\n }\n return r\n }\n\n for (const property in object) {\n if (isReactive(property)) {\n //console.log(`path '${path}', prop '${property}' is reactive`)\n object[property] = reactive(\n name,\n object[property],\n callback,\n path + '/' + property,\n excludedProperties\n )\n } else {\n //console.log(`--- path '${path}', property '${property}' is NOT reactive`)\n }\n }\n //console.log(`path '${path}' is reactive`)\n return new Proxy(object, {\n get(target: any, property: string | symbol, receiver: any): any { // ...arguments\n return Reflect.get(target, property, receiver)\n },\n set(target: any, property: string | symbol, value: any): boolean {\n let newvalue: any\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n newvalue = reactive(name, value, callback, pn, excludedProperties)\n callback(name, 'replace', target, pn, newvalue)\n } else {\n newvalue = value\n }\n return Reflect.set(target, property, newvalue)\n },\n deleteProperty(target: any, property: string | symbol): boolean {\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n callback(name, 'remove', target, pn, null)\n }\n delete target[property]\n return true\n },\n })\n\n}\n\nexport function deepGet(obj: any, path: string): any {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n for (let i = 0; i < len; i++) {\n if (obj[paths[i]!] == undefined) {\n return undefined\n } else {\n obj = obj[paths[i]!]\n }\n }\n return obj\n}\n\nexport function deepSet(obj: any, path: string, value: any): void {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n let i: number\n for (i = 0; i < len - 1; i++) {\n obj = obj[paths[i]!]\n }\n obj[paths[i]!] = value\n}\n\n// recursive clone oject, without properties that starts with _ (or __)\n\nexport function clonewo_(obj: any, excludeStart: string | Record<string, boolean> = '_'): any {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n\n function isExcluded(key: string): boolean {\n let e = false\n if (typeof (excludeStart) == 'string' && key.startsWith(excludeStart)) {\n e = true\n } else if (typeof(excludeStart) == 'object') {\n if (excludeStart[key] || key.startsWith('_')) {\n e = true\n }\n }\n return e\n }\n\n if (obj instanceof Map) {\n const mapClone = new Map()\n Array.from(obj.entries()).forEach(([key, value]) => {\n mapClone.set(clonewo_(key, excludeStart), clonewo_(value, excludeStart))\n })\n return mapClone\n }\n\n let clone: any\n if (Array.isArray(obj)) {\n clone = []\n for (let i = 0; i < obj.length; i++) {\n clone[i] = clonewo_(obj[i], excludeStart)\n }\n } else {\n clone = {} as Record<string, any>\n for (let key in obj) {\n if (obj.hasOwnProperty(key) && !isExcluded(key)) {\n if (typeof obj[key] === 'object') {\n clone[key] = clonewo_(obj[key], excludeStart)\n } else {\n clone[key] = obj[key]\n }\n }\n }\n }\n\n return clone\n}\n\nexport function limitPrecision(obj: any): any {\n if (Array.isArray(obj)) {\n return obj.map(limitPrecision)\n } else if (obj !== null && typeof obj === 'object') {\n const result: Record<string, any> = {}\n for (const key in obj) {\n result[key] = limitPrecision(obj[key])\n }\n return result\n } else if (typeof obj === 'number') {\n if (Number.isInteger(obj)) {\n return obj\n } else {\n // Limit to max 3 decimal digits, not fixed\n return parseFloat(obj.toFixed(3))\n }\n } else {\n return obj\n }\n}\n\nexport function msgop(op: any): any {\n let nop: any = {}\n if (!op.o) {\n nop.op = 'replace'\n } else {\n nop.op = ({\n a: 'add',\n r: 'remove',\n d: 'delete',\n t: 'test',\n } as Record<string, string>)[op.o]\n }\n nop.path = op.p\n nop.value = op.v\n return nop\n}\n\nexport function opmsg(op: string, target: any, path: string, value: any): any {\n let c: any = { p: path, v: value }\n if (op != 'replace') {\n c.o = ({\n add: 'a',\n remove: 'r',\n delete: 'd',\n test: 't',\n } as Record<string, string>)[op]\n }\n return c\n}\n\n// a function that converts an int to a hexa string\n// (8 characters long)\nexport function int2hex(int: number): string {\n return int.toString(16)\n}\n\n// a function that converts a hexa string to an int\nexport function hex2int(str: string): bigint {\n if (str.length % 2) {\n str = '0' + str\n }\n return BigInt('0x' + str)\n}\n\n// - Fixed point encoding/decoding functions\n\n// 32-bit unsigned integer encoding\nexport function encode_uint32(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(4)\n }\n let p = offset + 3\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n// 32-bit unsigned integer decoding\nexport function decode_uint32(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (\n ((byteArray[p++]! & 0x7f) << 24) |\n (byteArray[p++]! << 16) |\n (byteArray[p++]! << 8) |\n byteArray[p]!\n )\n}\n\n// 24-bit unsigned integer encoding\nexport function encode_uint24(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(3)\n }\n let p = offset + 2\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n\n// 24-bit unsigned integer decoding\nexport function decode_uint24(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (\n (byteArray[p++]! << 16) |\n (byteArray[p++]! << 8) |\n byteArray[p]!\n )\n}\n\n// 16-bit unsigned integer encoding\nexport function encode_uint16(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(2)\n }\n let p = offset + 1\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n\n// 16-bit unsigned integer decoding\nexport function decode_uint16(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (byteArray[p++]! << 8) | byteArray[p]!\n}\n\n// 24.8 bit ====================================================================\n\n// 24.8-bit fixed point encoding\nexport function encode_fp248(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint32(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 24.8-bit fixed point decoding\nexport function decode_fp248(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint32(byteArray, offset)\n return fp / divider\n}\n\n// 16.8 bit ====================================================================\n\n// 16.8-bit fixed point encoding (3 bytes)\nexport function encode_fp168(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint24(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 16.8-bit fixed point decoding (3 bytes)\nexport function decode_fp168(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint24(byteArray, offset)\n return fp / divider\n}\n\n// 16.16 bit ===================================================================\n\n// 16.16-bit fixed point encoding\nexport function encode_fp1616(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 65536)\n encode_uint32(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 16.16-bit fixed point decoding\nexport function decode_fp1616(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -65536 : 65536\n byteArray[offset]! &= 0x7f\n const fp = decode_uint32(byteArray, offset)\n return fp / divider\n}\n\n// 8.8 bit =====================================================================\n\n// 8.8-bit fixed point encoding\nexport function encode_fp88(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint16(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 8.8-bit fixed point decoding\nexport function decode_fp88(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint16(byteArray, offset)\n return fp / divider\n}\n\n// 4.12 bit ====================================================================\n\n// 4.12-bit fixed point encoding\nexport function encode_fp412(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 4096)\n encode_uint16(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 4.12-bit fixed point decoding\nexport function decode_fp412(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -4096 : 4096\n byteArray[offset]! &= 0x7f\n const fp = decode_uint16(byteArray, offset)\n return fp / divider\n}\n\n// 1.7 bit =====================================================================\n\n// 1.7-bit fixed point encoding\nexport function encode_fp17(float: number, byteArray: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 128)\n byteArray[offset] = fp\n if (float < 0) {\n byteArray[offset] |= 0x80\n }\n}\n\n// 1.7-bit fixed point decoding\nexport function decode_fp17(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -128.0 : 128.0\n byteArray[offset]! &= 0x7f\n return byteArray[offset]! / divider\n}\n","const browserFormat = 'gzip'\n\nconst MIN_COMPRESSED_BUFFER_SIZE = 256\n\nexport async function compress(buffer:Uint8Array<ArrayBufferLike>) {\n if (buffer.byteLength <= MIN_COMPRESSED_BUFFER_SIZE) return buffer\n if (typeof CompressionStream !== 'undefined') {\n const cs = new CompressionStream(browserFormat)\n const compressed = await new Response(\n new Blob([buffer]).stream().pipeThrough(cs)\n ).arrayBuffer()\n return compressed\n } else {\n throw new Error('CompressionStream not supported')\n }\n}\n\nexport async function decompress(buffer:Uint8Array<ArrayBufferLike>) {\n if (typeof DecompressionStream !== 'undefined') {\n try {\n const ds = new DecompressionStream(browserFormat)\n const decompressed = await new Response(\n new Blob([buffer]).stream().pipeThrough(ds)\n ).arrayBuffer()\n //console.log(` ${buffer.byteLength} -> ${decompressed.byteLength}`)\n return decompressed\n } catch (e) {\n //console.error('Decompression failed:', e)\n return buffer\n }\n } else {\n throw new Error('DecompressionStream not supported')\n }\n}\n"],"mappings":"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","names":["key","event"]}
1
+ {"version":3,"sources":["../src/client.ts","../src/utils.ts","../src/compress-browser.ts"],"sourcesContent":["import { applyOperation } from 'fast-json-patch'\nimport {\n reactive,\n opmsg,\n msgop,\n decode_uint32,\n decode_fp412,\n decode_fp168,\n decode_fp1616,\n deepGet,\n encode,\n decode,\n} from './utils'\nimport { compress, decompress } from './compress-browser'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\ninterface Stats {\n send: number;\n rec: number;\n recRTC: number;\n sendBps: number;\n recBps: number;\n recRTCBps: number;\n ping: number;\n stdiff: number; // server time difference\n}\n\ninterface ConstructorParams {\n url: string; // server url\n autoReconnect?: boolean; // auto reconnect on disconnect\n allowSync?: boolean; // allow sync on connect\n allowWebRTC?: boolean;\n DEBUG?: boolean;\n}\n\ninterface Message {\n c: string;\n [key: string]: any;\n}\n\ninterface Document {\n entities?: { [key: string]: any };\n origin?: vec3;\n [key: string]: any;\n}\n\ninterface Entity {\n position?: vec3;\n rotation?: quat;\n _lpos1?: vec3;\n _lpos2?: vec3;\n _lpostime1?: number | undefined;\n _lpostime2?: number | undefined;\n _lrot1?: quat;\n _lrot2?: quat;\n _lrottime1?: number | undefined;\n _lrottime2?: number | undefined;\n _lsca1?: vec3;\n _lsca2?: vec3;\n _lscatime1?: number | undefined;\n _lscatime2?: number | undefined;\n sca?: vec3;\n [key: string]: any;\n}\n// WebRTC type declarations for environments that don't have them built-in\ndeclare global {\n interface RTCPeerConnection {\n new(configuration?: RTCConfiguration): RTCPeerConnection;\n createOffer(options?: RTCOfferOptions): Promise<RTCSessionDescriptionInit>;\n createAnswer(options?: RTCAnswerOptions): Promise<RTCSessionDescriptionInit>;\n setLocalDescription(description?: RTCSessionDescriptionInit): Promise<void>;\n setRemoteDescription(description: RTCSessionDescriptionInit): Promise<void>;\n addIceCandidate(candidate?: RTCIceCandidateInit): Promise<void>;\n createDataChannel(label: string, dataChannelDict?: RTCDataChannelInit): RTCDataChannel;\n close(): void;\n readonly connectionState: RTCPeerConnectionState;\n readonly iceConnectionState: RTCIceConnectionState;\n readonly iceGatheringState: RTCIceGatheringState;\n readonly localDescription: RTCSessionDescription | null;\n readonly remoteDescription: RTCSessionDescription | null;\n onconnectionstatechange: ((this: RTCPeerConnection, ev: Event) => any) | null;\n oniceconnectionstatechange: ((this: RTCPeerConnection, ev: Event) => any) | null;\n onicegatheringstatechange: ((this: RTCPeerConnection, ev: Event) => any) | null;\n onicecandidate: ((this: RTCPeerConnection, ev: RTCPeerConnectionIceEvent) => any) | null;\n ondatachannel: ((this: RTCPeerConnection, ev: RTCDataChannelEvent) => any) | null;\n dataChannel?: RTCDataChannel;\n }\n\n interface RTCDataChannel {\n readonly label: string;\n readonly readyState: RTCDataChannelState;\n send(data: string | Blob | ArrayBuffer | ArrayBufferView): void;\n close(): void;\n onopen: ((this: RTCDataChannel, ev: Event) => any) | null;\n onclose: ((this: RTCDataChannel, ev: Event) => any) | null;\n onerror: ((this: RTCDataChannel, ev: Event) => any) | null;\n onmessage: ((this: RTCDataChannel, ev: MessageEvent) => any) | null;\n }\n\n interface RTCSessionDescription {\n readonly type: RTCSdpType;\n readonly sdp: string;\n }\n\n interface RTCIceCandidate {\n new(candidateInitDict?: RTCIceCandidateInit): RTCIceCandidate;\n }\n\n interface RTCPeerConnectionIceEvent extends Event {\n readonly candidate: RTCIceCandidate | null;\n }\n\n interface RTCDataChannelEvent extends Event {\n readonly channel: RTCDataChannel;\n }\n\n type RTCPeerConnectionState = 'closed' | 'connected' | 'connecting' | 'disconnected' | 'failed' | 'new';\n type RTCIceConnectionState = 'checking' | 'closed' | 'completed' | 'connected' | 'disconnected' | 'failed' | 'new';\n type RTCIceGatheringState = 'complete' | 'gathering' | 'new';\n type RTCDataChannelState = 'closed' | 'closing' | 'connecting' | 'open';\n type RTCSdpType = 'answer' | 'offer' | 'pranswer' | 'rollback';\n\n interface RTCConfiguration {\n iceServers?: RTCIceServer[];\n iceCandidatePoolSize?: number;\n }\n\n interface RTCIceServer {\n urls: string | string[];\n username?: string;\n credential?: string;\n }\n\n interface RTCOfferOptions {\n offerToReceiveAudio?: boolean;\n offerToReceiveVideo?: boolean;\n iceRestart?: boolean;\n }\n\n interface RTCAnswerOptions {\n // Currently no standard options for answers\n }\n\n interface RTCSessionDescriptionInit {\n type: RTCSdpType;\n sdp?: string;\n }\n\n interface RTCIceCandidateInit {\n candidate?: string;\n sdpMLineIndex?: number | null;\n sdpMid?: string | null;\n usernameFragment?: string | null;\n }\n\n interface RTCDataChannelInit {\n ordered?: boolean;\n maxPacketLifeTime?: number;\n maxRetransmits?: number;\n protocol?: string;\n negotiated?: boolean;\n id?: number;\n }\n\n const RTCPeerConnection: {\n prototype: RTCPeerConnection;\n new(configuration?: RTCConfiguration): RTCPeerConnection;\n };\n\n const RTCSessionDescription: {\n prototype: RTCSessionDescription;\n new(descriptionInitDict: RTCSessionDescriptionInit): RTCSessionDescription;\n };\n\n const RTCIceCandidate: {\n prototype: RTCIceCandidate;\n new(candidateInitDict?: RTCIceCandidateInit): RTCIceCandidate;\n };\n}\n\nexport default class TopazCubeClient {\n DEBUG = false\n CYCLE = 200 // update/patch rate in ms\n url = ''\n documents: { [key: string]: Document } = {}\n autoReconnect = true\n allowSync = true\n allowWebRTC = false\n isConnected = false\n isConnecting = false\n isPatched = false\n stats: Stats = {\n send: 0,\n rec: 0,\n recRTC: 0,\n\n sendBps: 0,\n recBps: 0,\n recRTCBps: 0,\n\n ping: 0,\n stdiff: 0, // server time difference\n }\n lastFullState = 0\n lastPatch = 0\n _chunks: { [key: string]: any } = {}\n le = true // Server is little endian\n _documentChanges: { [key: string]: any[] } = {}\n\n ID = 0\n socket: WebSocket | null = null\n _peerConnection: RTCPeerConnection | null = null\n _candidates: RTCIceCandidate[] = []\n _remoteCandidates: RTCIceCandidateInit[] = []\n _offerSent: boolean = false\n _dataChannel: RTCDataChannel | null = null // our data channel\n _serverDataChannel: RTCDataChannel | null = null // server data channel\n _webRTCConnected: boolean = false\n\n isInterpolated = false\n _lastInterpolate = Date.now()\n _lastUpdateId: { [key: string]: number } = {}\n _dpos: vec3 = [0, 0, 0]\n _drot: quat = [0, 0, 0, 1]\n _sca: vec3 = [1, 1, 1]\n _notifyChanges = true\n _siv: NodeJS.Timeout | null = null\n _loopiv: NodeJS.Timeout | null = null\n _updateiv: NodeJS.Timeout | null = null\n _pingiv: NodeJS.Timeout | null = null\n\n\n constructor({\n url, // server url\n autoReconnect = true, // auto reconnect on disconnect\n allowSync = true, // allow sync on connect\n allowWebRTC = false,\n DEBUG = false\n }: ConstructorParams) {\n this.url = url\n this.autoReconnect = autoReconnect\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.socket = null\n this.DEBUG = DEBUG\n this._startLoop()\n this.log('Client initialized')\n }\n\n log(...args: any[]) {\n if (this.DEBUG) {\n console.log(...args);\n }\n }\n\n warn(...args: any[]) {\n if (this.DEBUG) {\n console.warn(...args);\n }\n }\n\n error(...args: any[]) {\n console.error(...args);\n }\n\n /*= UPDATE ===================================================================*/\n\n _startLoop() {\n if (this._loopiv) {\n clearInterval(this._loopiv)\n }\n this._loopiv = setInterval(() => {\n this._loop()\n }, this.CYCLE)\n this._siv = setInterval(() => {\n this._updateStats()\n }, 1000)\n this._pingiv = setInterval(() => {\n this._ping()\n }, 10000)\n }\n _loop() {\n if (!this.isConnected) {\n return\n }\n this._sendPatches()\n }\n\n _updateStats() {\n this.stats.recBps = this.stats.rec\n this.stats.rec = 0\n this.stats.recRTCBps = this.stats.recRTC\n this.stats.recRTC = 0\n this.stats.sendBps = this.stats.send\n this.stats.send = 0\n }\n\n _clear() {\n this.stats.sendBps = 0\n this.stats.recBps = 0\n this.stats.recRTC = 0\n this.stats.recRTCBps = 0\n this.stats.send = 0\n this.stats.rec = 0\n\n this.ID = 0\n this.documents = {}\n this._documentChanges = {}\n this._lastUpdateId = {}\n this.lastFullState = 0\n this.lastPatch = 0\n this._lastInterpolate = 0\n this.isPatched = false\n this.le = true\n }\n\n /*= INTERPOLATION ============================================================*/\n\n // to be called in display rate (like 60fps) to interpolate .position, .rotation and .scale\n interpolate() {\n let now = Date.now()\n let dt = now - this._lastInterpolate\n this._lastInterpolate = now\n if (dt <= 0 || dt > 200) { return }\n this.isInterpolated = true\n for (let name in this.documents) {\n let doc = this.documents[name]\n let entities = doc?.entities\n if (!entities) { continue }\n for (let id in entities) {\n let e: Entity = entities[id]\n if (e._lpostime1 && e._lpostime2) {\n let t1 = e._lpostime1\n let t2 = e._lpostime2\n const interval = t2 - t1;\n const elapsed = now - t1;\n e.pelapsed = elapsed\n /*if (elapsed > 5000) {\n } else */if (elapsed > 1000) {\n vec3.copy(e.position!, e._lpos2!)\n e._changed_position = now\n } else {\n const alpha = Math.max(0, elapsed / interval)\n vec3.lerp(this._dpos, e._lpos1!, e._lpos2!, alpha)\n vec3.lerp(e.position!, e.position!, this._dpos, 0.07)\n e._changed_position = now\n }\n }\n if (e._lrottime1 && e._lrottime2) {\n let t1 = e._lrottime1\n let t2 = e._lrottime2\n const interval = t2 - t1;\n const elapsed = now - t1;\n e.relapsed = elapsed\n /*if (elapsed > 5000) {\n } else */if (elapsed > 1000) {\n quat.copy(e.rotation!, e._lrot2!)\n e._changed_rotation = now\n } else {\n const alpha = Math.max(0, elapsed / interval)\n quat.slerp(this._drot, e._lrot1!, e._lrot2!, alpha)\n quat.slerp(e.rotation!, e.rotation!, this._drot, 0.07)\n e._changed_rotation = now\n }\n }\n\n }\n }\n this.isInterpolated = false\n }\n\n /*= CONNECTION ===============================================================*/\n\n subscribe(name: string) {\n this.documents[name] = {}\n this.send({ c: 'sub', n: name })\n }\n\n unsubscribe(name: string) {\n this.send({ c: 'unsub', n: name })\n delete this.documents[name]\n }\n\n connect() {\n if (this.isConnecting) {\n return\n }\n this.isConnecting = true\n this._clear()\n this.log('connecting...')\n\n this.socket = new WebSocket(this.url)\n\n // message received\n this.socket.onmessage = async (event: MessageEvent) => {\n let buffer = await event.data.arrayBuffer()\n this.stats.rec += buffer.byteLength\n let dec = await decompress(buffer)\n let decu = new Uint8Array(dec)\n let message = decode(decu)\n this._onMessage(message)\n }\n\n // connection closed\n this.socket.onclose = (_event: any) => {\n this._clear()\n this.isConnected = false\n this.isConnecting = false\n this.lastFullState = 0\n this.socket = null\n this.onDisconnect()\n if (this.allowWebRTC) {\n this._destroyWebRTC()\n }\n if (this.autoReconnect) {\n setTimeout(\n () => {\n this._reconnect()\n },\n 500 + Math.random() * 500\n )\n }\n }\n\n this.socket.onerror = (_event: Event) => {\n this._clear()\n this.isConnected = false\n this.isConnecting = false\n this.lastFullState = 0\n this.socket = null\n this.onDisconnect()\n if (this.allowWebRTC) {\n this._destroyWebRTC()\n }\n\n if (this.autoReconnect) {\n setTimeout(\n () => {\n this._reconnect()\n },\n 500 + Math.random() * 500\n )\n }\n }\n\n this.socket.onopen = async (_event: Event) => {\n this._clear()\n this.isConnecting = false\n this.isConnected = true\n this.lastFullState = 0\n this._ping()\n this.onConnect()\n if (this.allowWebRTC) {\n await this._initializeWebRTC()\n }\n }\n }\n\n disconnect() {\n this._clear()\n this.isConnected = false\n this.isConnecting = false\n this.lastFullState = 0\n if (this.socket) {\n this.socket.close()\n }\n this.socket = null\n }\n\n destroy() {\n this._clear()\n this.autoReconnect = false\n this.disconnect()\n this.socket = null\n if (this._siv) clearInterval(this._siv)\n if (this._loopiv) clearInterval(this._loopiv)\n }\n\n onConnect() {}\n\n onDisconnect() {}\n\n _reconnect() {\n if (!this.isConnected) {\n if (!this.isConnecting) {\n this.connect()\n }\n }\n }\n\n _ping() {\n if (this.isConnected) {\n this.send({ c: 'ping', ct: Date.now() })\n }\n }\n\n /*= MESSAGES =================================================================*/\n\n onChange(_name: string, _doc: Document | undefined, patch: any | undefined) {}\n\n onMessage(_message: Message) {}\n\n send(operation: any) {\n try {\n let enc = encode(operation)\n this.stats.send += enc.byteLength\n if (this.socket) {\n this.socket.send(enc)\n }\n } catch (e) {\n this.error('send failed', e)\n }\n }\n\n get document(): Document | undefined {\n let names:string = ''+Object.keys(this.documents)\n return this.documents[''+names[0]]\n }\n\n async _onMessage(message: Message) {\n let time = Date.now()\n if (message.c == 'full') {\n //this.log('full:', message)\n let name:string = ''+message.n\n let doc = message.doc\n this.documents[name] = doc\n this._decodeFastChanges(message)\n this.isPatched = false\n if (this.allowSync) {\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this)\n )\n }\n this.isPatched = false\n this.lastFullState = message.t\n this.le = message.le\n if (this._notifyChanges) {\n this.onChange(name, this.documents[name], null)\n }\n } else if (message.c == 'patch') {\n // patch\n this.lastPatch = message.t\n let name = message.n\n if (message.doc) {\n this.isPatched = true\n for (let op of message.doc) {\n let dop = msgop(op)\n try {\n applyOperation(this.documents[name], dop)\n } catch (e) {\n this.error('applyOperation failed for', name, 'with op', dop, e)\n }\n }\n this.isPatched = false\n }\n if (this._notifyChanges) {\n this.onChange(name, this.documents[name], message.doc)\n }\n } else if (message.c == 'chunk') {\n //this.log('chunk', message)\n this._chunks[message.mid+'-'+message.seq] = message\n if (message.last) {\n let cfound = 0\n let ts = message.ts\n let cdata = new Uint8Array(ts)\n for (const cid in this._chunks) {\n let chunk = this._chunks[cid]\n if (chunk.mid == message.mid) {\n let offset = chunk.ofs\n let _csize = chunk.chs\n cdata.set(new Uint8Array(chunk.data), offset);\n cfound++\n delete this._chunks[cid]\n }\n }\n //this.log('found chunks ', cfound, 'of', message.seq + 1)\n if (cfound == message.seq + 1) {\n try {\n let cdec = await decompress(cdata)\n let cdecu = new Uint8Array(cdec)\n let nmessage = decode(cdecu)\n //this.log('decoded message', nmessage)\n this._onMessage(nmessage)\n } catch (error) {\n this.error('Error decoding chunks:', error)\n }\n } else {\n this.warn('missing chunks', cfound, 'of', message.seq + 1)\n }\n }\n } else if (message.c == 'fpatch') {\n time = Date.now()\n let name = message.n\n //this.log('fpatch', message)\n let doPatch = true\n if (!this._lastUpdateId[name]) {\n this._lastUpdateId[name] = message.u\n } else {\n if (this._lastUpdateId[name] < message.u) {\n let lp = message.u - this._lastUpdateId[name] - 1\n if (lp > 0) {\n this.warn('Lost ' + lp + ' updates')\n }\n this._lastUpdateId[name] = message.u\n } else if (this._lastUpdateId[name] > message.u) {\n // Handle the case where the server's update ID is older than the client's\n // This could be due to a network issue or a clock skew\n this.warn(`Received outdated update ID for document ${name}: ${message.u} < ${this._lastUpdateId[name]}`)\n doPatch = false\n }\n }\n if (doPatch) {\n this._decodeFastChanges(message)\n }\n } else if (message.c == 'pong') {\n this.ID = message.ID\n time = Date.now()\n let lastct = message.ct\n let ping = time - lastct\n let stime = message.t\n this.send({ c: 'peng', ct: Date.now(), st: stime })\n this.stats.stdiff = stime + ping / 2 - time\n this.stats.ping = ping\n this.log('ping', ping, 'ms', 'stdiff', this.stats.stdiff, 'ms')\n } else if (message.c == 'rtc-offer') {\n this.log(\"RTC: offer received:\", message);\n // You might need to handle this if the server sends offers\n } else if (message.c == 'rtc-answer') {\n this.log(\"RTC: answer received:\", message);\n try {\n const sessionDesc = new RTCSessionDescription({\n type: message.type,\n sdp: message.sdp,\n })\n if (this._peerConnection) {\n await this._peerConnection.setRemoteDescription(sessionDesc)\n }\n this.log(\"RTC: Remote description set successfully\");\n\n // Log the current state after setting remote description\n //\n //this.log(\"RTC: Current connection state:\", this._peerConnection.connectionState);\n //this.log(\"RTC: Current ICE connection state:\", this._peerConnection.iceConnectionState);\n for (let candidate of this._remoteCandidates) {\n try {\n await this._peerConnection?.addIceCandidate(candidate);\n this.log(\"RTC: Added remote ICE candidate:\", candidate);\n } catch (error) {\n this.error(\"RTC: Error adding remote ICE candidate:\", error);\n }\n }\n } catch (error) {\n this.error('RTC: Error setting remote description:', error)\n }\n } else if (message.c == 'rtc-candidate') {\n this.log(\"RTC: candidate received\", message);\n if (this._peerConnection && message.candidate) {\n this._remoteCandidates.push(message.candidate);\n }\n } else {\n this.onMessage(message)\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: string, value: any) {\n if (this.DEBUG) {\n this.log('Document change:', name, op, target, path, value)\n }\n if (this.isPatched || !this.allowSync) {\n return\n }\n if (path.indexOf('/_') >= 0) {\n return\n }\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n this._documentChanges[name].push(opmsg(op, target, path, value))\n }\n\n _sendPatches() {\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n if (!dc || dc.length == 0) {\n continue\n }\n let record: any = {\n n: name,\n c: 'sync',\n ct: Date.now(),\n p: null\n }\n\n if (dc.length > 0) {\n record.p = dc\n }\n this.send(record)\n dc.length = 0\n if (this._notifyChanges) {\n this.onChange(name, this.documents[''+name], record.p)\n }\n }\n }\n\n _decodeFastChanges(message: Message) {\n let time = Date.now()\n let name = message.n\n let fdata = message.fdata\n if (!fdata) {\n return\n }\n let doc = this.documents[name]\n if (!doc) {\n return\n }\n let entities = doc.entities\n if (!entities) {\n return\n }\n let origin = this.documents[''+name]?.origin\n if (!origin) {\n origin = [0, 0, 0]\n }\n for (let key in fdata) {\n let changes = fdata[key]\n if (changes.dict) {\n let pdata = changes.pdata\n let dict = changes.dict\n // Reverse the dictionary for lookup (value to key)\n let rdict: { [key: string]: string } = {};\n for (let key in dict) {\n rdict[dict[key]] = key;\n }\n let offset = 0\n\n while (offset < pdata.byteLength) {\n let id = ''+decode_uint32(pdata, offset)\n offset += 4\n let did = ''+decode_uint32(pdata, offset)\n offset += 4\n let e: Entity = entities[id]\n if (!e) {\n //this.log('Entity not found:', id)\n continue\n }\n let value = rdict[did]\n e[key] = value\n //this.log('FCHANGE', key, id, did, value, rdict)\n e['_changed_'+key] = time\n }\n } else {\n let pdata = changes.pdata\n let offset = 0\n while (offset < pdata.byteLength) {\n let id = ''+decode_uint32(pdata, offset)\n let e: Entity = entities[id]\n if (!e) {\n if (key == 'position') {\n offset += 13\n } else if (key == 'rotation') {\n offset += 8\n } else if (key == 'scale') {\n offset += 16\n }\n continue\n }\n offset += 4\n\n if (key == 'position') {\n if (!e._lpos2) {\n e._lpos1 = [0, 0, 0]\n e._lpos2 = [0, 0, 0]\n } else {\n e._lpos1![0] = e._lpos2[0]\n e._lpos1![1] = e._lpos2[1]\n e._lpos1![2] = e._lpos2[2]\n e._lpostime1 = e._lpostime2\n }\n e._lpostime2 = time\n e._lpos2[0] = origin[0] + decode_fp168(pdata, offset)\n offset += 3\n e._lpos2[1] = origin[1] + decode_fp168(pdata, offset)\n offset += 3\n e._lpos2[2] = origin[2] + decode_fp168(pdata, offset)\n offset += 3\n if (!e.position) {\n e.position = [\n e._lpos2[0],\n e._lpos2[1],\n e._lpos2[2],\n ]\n }\n } else if (key == 'rotation') {\n if (!e._lrot2) {\n e._lrot1 = [0, 0, 0, 1]\n e._lrot2 = [0, 0, 0, 1]\n } else {\n e._lrot1![0] = e._lrot2[0]\n e._lrot1![1] = e._lrot2[1]\n e._lrot1![2] = e._lrot2[2]\n e._lrot1![3] = e._lrot2[3]\n e._lrottime1 = e._lrottime2\n }\n e._lrottime2 = time\n e._lrot2[0] = decode_fp412(pdata, offset)\n offset += 2\n e._lrot2[1] = decode_fp412(pdata, offset)\n offset += 2\n e._lrot2[2] = decode_fp412(pdata, offset)\n offset += 2\n e._lrot2[3] = decode_fp412(pdata, offset)\n offset += 2\n quat.normalize(e._lrot2, e._lrot2)\n if (!e.rotation) {\n e.rotation = [\n e._lrot2[0],\n e._lrot2[1],\n e._lrot2[2],\n e._lrot2[3],\n ]\n }\n } else if (key == 'scale') {\n if (!e._lsca2) {\n e._lsca1 = [0, 0, 0]\n e._lsca2 = [0, 0, 0]\n } else {\n e._lsca1![0] = e._lsca2[0]\n e._lsca1![1] = e._lsca2[1]\n e._lsca1![2] = e._lsca2[2]\n e._lscatime1 = e._lscatime2\n }\n e._lscatime2 = time\n e._lsca2[0] = decode_fp1616(pdata, offset)\n offset += 4\n e._lsca2[1] = decode_fp1616(pdata, offset)\n offset += 4\n e._lsca2[2] = decode_fp1616(pdata, offset)\n offset += 4\n if (!e.sca) {\n e.sca = [\n e._lsca2[0],\n e._lsca2[1],\n e._lsca2[2],\n ]\n }\n }\n }\n }\n }\n }\n\n /*= WEBRTC ===================================================================*/\n\n sendRTC(message: Message) {\n if (this._dataChannel && this._dataChannel.readyState === 'open') {\n this._dataChannel.send(encode(message))\n }\n }\n\n _onRTCConnect() {\n this.log('RTC: Connected')\n this.send({ c: 'test', message: 'Hello RTC from client' })\n }\n\n _onRTCDisconnect() {\n this._webRTCConnected = false\n this.log('RTC: Disconnected')\n }\n\n async _onRTCMessage(data: ArrayBuffer) {\n this.stats.recRTC += data.byteLength\n let datau = new Uint8Array(data)\n let dec = await decompress(datau)\n let decu = new Uint8Array(dec)\n let message = decode(decu)\n this._onMessage(message)\n }\n\n async _initializeWebRTC() {\n //this.log(\"RTC: _initializeWebRTC\")\n this._peerConnection = null\n this._candidates = []\n this._remoteCandidates = []\n this._offerSent = false\n try {\n // Create RTCPeerConnection with more comprehensive STUN server list\n this._peerConnection = new RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n iceCandidatePoolSize: 10,\n })\n\n //this.log(\"RTC: peerConnection created\", this._peerConnection)\n\n // Handle ICE candidates\n this._peerConnection.onicecandidate = (event: RTCPeerConnectionIceEvent) => {\n //this.log(\"RTC: onicecandidate\", event.candidate)\n if (event.candidate) {\n this._candidates.push(event.candidate)\n } else {\n this.log(\"RTC: ICE candidate gathering complete\")\n }\n }\n\n // Log connection state changes\n this._peerConnection.onconnectionstatechange = () => {\n //this.log(`RTC: Connection state changed: ${this._peerConnection.connectionState}`)\n if (this._peerConnection && this._peerConnection.connectionState === 'connected') {\n this._webRTCConnected = true\n this.log('RTC: Peer connection established!')\n } else if (\n this._peerConnection && (\n this._peerConnection.connectionState === 'failed' ||\n this._peerConnection.connectionState === 'disconnected' ||\n this._peerConnection.connectionState === 'closed')\n ) {\n this._webRTCConnected = false\n this.log('RTC: Peer connection closed or failed')\n }\n }\n\n this._peerConnection.onicegatheringstatechange = () => {\n this.log(`RTC: ICE gathering state. _candidates:`, this._candidates.length, this._peerConnection?.iceGatheringState)\n if (this._peerConnection?.iceGatheringState == 'complete' && this._offerSent) {\n for (let candidate of this._candidates) {\n this.send({\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: candidate,\n })\n }\n }\n }\n\n this._peerConnection.oniceconnectionstatechange = () => {\n //this.log(`RTC: ICE connection state: ${this._peerConnection.iceConnectionState}`)\n\n // This is critical - when ICE succeeds, the connection should be established\n if (\n this._peerConnection && (\n this._peerConnection.iceConnectionState === 'connected' ||\n this._peerConnection.iceConnectionState === 'completed')\n ) {\n //this.log(\"RTC: ICE connection established!\")\n }\n }\n\n // Create a data channel on our side as well (belt and suspenders approach)\n this._dataChannel = this._peerConnection.createDataChannel(\n 'clientchannel',\n {\n ordered: true,\n maxRetransmits: 1,\n }\n )\n\n this._dataChannel.onopen = () => {\n this._onRTCConnect()\n }\n\n this._dataChannel.onclose = () => {\n this._onRTCDisconnect()\n }\n\n this._dataChannel.onerror = (_error: Event) => {\n this.error('RTC: Client data channel error', _error)\n }\n\n // Handle data channels created by the server\n this._peerConnection.ondatachannel = (event: RTCDataChannelEvent) => {\n //this.log(\"RTC: Server data channel received\", event.channel.label);\n const dataChannel = event.channel\n this._serverDataChannel = dataChannel\n\n dataChannel.onopen = () => {\n //this.log(\"RTC: Server data channel open\");\n }\n\n dataChannel.onclose = () => {\n //this.log(\"RTC: Server data channel closed\");\n }\n\n dataChannel.onerror = (_error: Event) => {\n //this.error(\"RTC: Server data channel error\", error);\n }\n\n dataChannel.onmessage = (event: MessageEvent) => {\n this._onRTCMessage(event.data)\n }\n }\n\n // Create and send offer with specific constraints\n const offerOptions: RTCOfferOptions = {\n offerToReceiveAudio: false,\n offerToReceiveVideo: false,\n iceRestart: true,\n }\n\n const offer = await this._peerConnection.createOffer(offerOptions)\n //this.log(\"RTC: our offer:\", offer);\n await this._peerConnection.setLocalDescription(offer)\n\n // Wait a moment to ensure the local description is set\n await new Promise((resolve) => setTimeout(resolve, 100))\n\n let ld = this._peerConnection.localDescription\n //this.log(\"RTC: our localDescription\", ld);\n\n if (ld) {\n const offerPayload = {\n c: 'rtc-offer',\n type: ld.type,\n sdp: ld.sdp,\n }\n //this.log(\"RTC: our offer payload\", offerPayload);\n this.send(offerPayload)\n this._offerSent = true\n }\n\n // Set a timeout to check connection status\n setTimeout(() => {\n if (!this._webRTCConnected && this._peerConnection) {\n /*\n this.log(\"RTC: Connection not established after timeout, current states:\");\n this.log(\"Connection state:\", this._peerConnection.connectionState);\n this.log(\"ICE connection state:\", this._peerConnection.iceConnectionState);\n this.log(\"ICE gathering state:\", this._peerConnection.iceGatheringState);\n */\n // Attempt to restart ICE if needed\n if (this._peerConnection.iceConnectionState === 'failed') {\n this.log('RTC: Attempting ICE restart')\n this._restartIce()\n }\n }\n }, 5000)\n } catch (error) {\n this.error('RTC: error:', error)\n }\n }\n\n // Add this method to restart ICE if needed\n async _restartIce() {\n try {\n const offerOptions = {\n offerToReceiveAudio: false,\n offerToReceiveVideo: false,\n iceRestart: true,\n }\n\n const offer = await this._peerConnection?.createOffer(offerOptions)\n await this._peerConnection?.setLocalDescription(offer)\n\n const offerPayload = {\n c: 'rtc-offer',\n type: offer?.type,\n sdp: offer?.sdp,\n }\n //this.log(\"RTC: ICE restart offer payload\", offerPayload);\n this.send(offerPayload)\n } catch (error) {\n //this.error(\"RTC: Error during ICE restart:\", error);\n }\n }\n\n async _destroyWebRTC() {\n if (this._peerConnection) {\n if (this._peerConnection.dataChannel) {\n this._peerConnection.dataChannel.close()\n }\n this._peerConnection.close()\n this._peerConnection = null\n }\n if (this._dataChannel) {\n this._dataChannel.close()\n this._dataChannel = null\n }\n this._webRTCConnected = false\n }\n}\n","import { Packr } from 'msgpackr';\nimport { FLOAT32_OPTIONS } from 'msgpackr';\nconst { ALWAYS } = FLOAT32_OPTIONS;\n\nlet packr = new Packr({\n useFloat32: ALWAYS\n});\n\nexport function encode(obj: any): Uint8Array {\n return packr.pack(obj)\n}\n\nexport function decode(data: Uint8Array): any {\n return packr.unpack(data)\n}\n\ntype ReactiveCallback = (name: string, operation: string, target: any, path: string, value: any) => void;\n\nexport function reactive(name: string, object: any, callback: ReactiveCallback, path: string = '', excludedProperties: Record<string, boolean> | false = false): any {\n if (object === null || typeof object !== 'object') {\n //console.log('--- Type not object', typeof object)\n return object\n }\n\n function isReactive(p: string): boolean {\n let r = true\n if (p.startsWith('_')) {\n r = false\n }\n if (excludedProperties) {\n if (excludedProperties[p]) {\n r = false\n }\n }\n if (path == '/entities') {\n r = false\n }\n return r\n }\n\n for (const property in object) {\n if (isReactive(property)) {\n //console.log(`path '${path}', prop '${property}' is reactive`)\n object[property] = reactive(\n name,\n object[property],\n callback,\n path + '/' + property,\n excludedProperties\n )\n } else {\n //console.log(`--- path '${path}', property '${property}' is NOT reactive`)\n }\n }\n //console.log(`path '${path}' is reactive`)\n return new Proxy(object, {\n get(target: any, property: string | symbol, receiver: any): any { // ...arguments\n return Reflect.get(target, property, receiver)\n },\n set(target: any, property: string | symbol, value: any): boolean {\n let newvalue: any\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n newvalue = reactive(name, value, callback, pn, excludedProperties)\n callback(name, 'replace', target, pn, newvalue)\n } else {\n newvalue = value\n }\n return Reflect.set(target, property, newvalue)\n },\n deleteProperty(target: any, property: string | symbol): boolean {\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n callback(name, 'remove', target, pn, null)\n }\n delete target[property]\n return true\n },\n })\n\n}\n\nexport function deepGet(obj: any, path: string): any {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n for (let i = 0; i < len; i++) {\n if (obj[paths[i]!] == undefined) {\n return undefined\n } else {\n obj = obj[paths[i]!]\n }\n }\n return obj\n}\n\nexport function deepSet(obj: any, path: string, value: any): void {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n let i: number\n for (i = 0; i < len - 1; i++) {\n obj = obj[paths[i]!]\n }\n obj[paths[i]!] = value\n}\n\n// recursive clone oject, without properties that starts with _ (or __)\n\nexport function clonewo_(obj: any, excludeStart: string | Record<string, boolean> = '_'): any {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n\n function isExcluded(key: string): boolean {\n let e = false\n if (typeof (excludeStart) == 'string' && key.startsWith(excludeStart)) {\n e = true\n } else if (typeof(excludeStart) == 'object') {\n if (excludeStart[key] || key.startsWith('_')) {\n e = true\n }\n }\n return e\n }\n\n if (obj instanceof Map) {\n const mapClone = new Map()\n Array.from(obj.entries()).forEach(([key, value]) => {\n mapClone.set(clonewo_(key, excludeStart), clonewo_(value, excludeStart))\n })\n return mapClone\n }\n\n let clone: any\n if (Array.isArray(obj)) {\n clone = []\n for (let i = 0; i < obj.length; i++) {\n clone[i] = clonewo_(obj[i], excludeStart)\n }\n } else {\n clone = {} as Record<string, any>\n for (let key in obj) {\n if (obj.hasOwnProperty(key) && !isExcluded(key)) {\n if (typeof obj[key] === 'object') {\n clone[key] = clonewo_(obj[key], excludeStart)\n } else {\n clone[key] = obj[key]\n }\n }\n }\n }\n\n return clone\n}\n\nexport function limitPrecision(obj: any): any {\n if (Array.isArray(obj)) {\n return obj.map(limitPrecision)\n } else if (obj !== null && typeof obj === 'object') {\n const result: Record<string, any> = {}\n for (const key in obj) {\n result[key] = limitPrecision(obj[key])\n }\n return result\n } else if (typeof obj === 'number') {\n if (Number.isInteger(obj)) {\n return obj\n } else {\n // Limit to max 3 decimal digits, not fixed\n return parseFloat(obj.toFixed(3))\n }\n } else {\n return obj\n }\n}\n\nexport function msgop(op: any): any {\n let nop: any = {}\n if (!op.o) {\n nop.op = 'replace'\n } else {\n nop.op = ({\n a: 'add',\n r: 'remove',\n d: 'delete',\n t: 'test',\n } as Record<string, string>)[op.o]\n }\n nop.path = op.p\n nop.value = op.v\n return nop\n}\n\nexport function opmsg(op: string, target: any, path: string, value: any): any {\n let c: any = { p: path, v: value }\n if (op != 'replace') {\n c.o = ({\n add: 'a',\n remove: 'r',\n delete: 'd',\n test: 't',\n } as Record<string, string>)[op]\n }\n return c\n}\n\n// a function that converts an int to a hexa string\n// (8 characters long)\nexport function int2hex(int: number): string {\n return int.toString(16)\n}\n\n// a function that converts a hexa string to an int\nexport function hex2int(str: string): bigint {\n if (str.length % 2) {\n str = '0' + str\n }\n return BigInt('0x' + str)\n}\n\n// - Fixed point encoding/decoding functions\n\n// 32-bit unsigned integer encoding\nexport function encode_uint32(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(4)\n }\n let p = offset + 3\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n// 32-bit unsigned integer decoding\nexport function decode_uint32(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (\n ((byteArray[p++]! & 0x7f) << 24) |\n (byteArray[p++]! << 16) |\n (byteArray[p++]! << 8) |\n byteArray[p]!\n )\n}\n\n// 24-bit unsigned integer encoding\nexport function encode_uint24(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(3)\n }\n let p = offset + 2\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n\n// 24-bit unsigned integer decoding\nexport function decode_uint24(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (\n (byteArray[p++]! << 16) |\n (byteArray[p++]! << 8) |\n byteArray[p]!\n )\n}\n\n// 16-bit unsigned integer encoding\nexport function encode_uint16(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(2)\n }\n let p = offset + 1\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n\n// 16-bit unsigned integer decoding\nexport function decode_uint16(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (byteArray[p++]! << 8) | byteArray[p]!\n}\n\n// 24.8 bit ====================================================================\n\n// 24.8-bit fixed point encoding\nexport function encode_fp248(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint32(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 24.8-bit fixed point decoding\nexport function decode_fp248(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint32(byteArray, offset)\n return fp / divider\n}\n\n// 16.8 bit ====================================================================\n\n// 16.8-bit fixed point encoding (3 bytes)\nexport function encode_fp168(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint24(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 16.8-bit fixed point decoding (3 bytes)\nexport function decode_fp168(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint24(byteArray, offset)\n return fp / divider\n}\n\n// 16.16 bit ===================================================================\n\n// 16.16-bit fixed point encoding\nexport function encode_fp1616(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 65536)\n encode_uint32(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 16.16-bit fixed point decoding\nexport function decode_fp1616(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -65536 : 65536\n byteArray[offset]! &= 0x7f\n const fp = decode_uint32(byteArray, offset)\n return fp / divider\n}\n\n// 8.8 bit =====================================================================\n\n// 8.8-bit fixed point encoding\nexport function encode_fp88(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint16(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 8.8-bit fixed point decoding\nexport function decode_fp88(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint16(byteArray, offset)\n return fp / divider\n}\n\n// 4.12 bit ====================================================================\n\n// 4.12-bit fixed point encoding\nexport function encode_fp412(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 4096)\n encode_uint16(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 4.12-bit fixed point decoding\nexport function decode_fp412(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -4096 : 4096\n byteArray[offset]! &= 0x7f\n const fp = decode_uint16(byteArray, offset)\n return fp / divider\n}\n\n// 1.7 bit =====================================================================\n\n// 1.7-bit fixed point encoding\nexport function encode_fp17(float: number, byteArray: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 128)\n byteArray[offset] = fp\n if (float < 0) {\n byteArray[offset] |= 0x80\n }\n}\n\n// 1.7-bit fixed point decoding\nexport function decode_fp17(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -128.0 : 128.0\n byteArray[offset]! &= 0x7f\n return byteArray[offset]! / divider\n}\n","const browserFormat = 'gzip'\n\nconst MIN_COMPRESSED_BUFFER_SIZE = 256\n\nexport async function compress(buffer:Uint8Array<ArrayBufferLike>) {\n if (buffer.byteLength <= MIN_COMPRESSED_BUFFER_SIZE) return buffer\n if (typeof CompressionStream !== 'undefined') {\n const cs = new CompressionStream(browserFormat)\n const compressed = await new Response(\n new Blob([buffer]).stream().pipeThrough(cs)\n ).arrayBuffer()\n return compressed\n } else {\n throw new Error('CompressionStream not supported')\n }\n}\n\nexport async function decompress(buffer:Uint8Array<ArrayBufferLike>) {\n if (typeof DecompressionStream !== 'undefined') {\n try {\n const ds = new DecompressionStream(browserFormat)\n const decompressed = await new Response(\n new Blob([buffer]).stream().pipeThrough(ds)\n ).arrayBuffer()\n //console.log(` ${buffer.byteLength} -> ${decompressed.byteLength}`)\n return decompressed\n } catch (e) {\n //console.error('Decompression failed:', e)\n return buffer\n }\n } else {\n throw new Error('DecompressionStream not supported')\n }\n}\n"],"mappings":";AAAA,SAAS,sBAAsB;;;ACA/B,SAAS,aAAa;AACtB,SAAS,uBAAuB;AAChC,IAAM,EAAE,OAAO,IAAI;AAEnB,IAAI,QAAQ,IAAI,MAAM;AAAA,EACpB,YAAY;AACd,CAAC;AAEM,SAAS,OAAO,KAAsB;AAC3C,SAAO,MAAM,KAAK,GAAG;AACvB;AAEO,SAAS,OAAO,MAAuB;AAC5C,SAAO,MAAM,OAAO,IAAI;AAC1B;AAIO,SAAS,SAAS,MAAc,QAAa,UAA4B,OAAe,IAAI,qBAAsD,OAAY;AACnK,MAAI,WAAW,QAAQ,OAAO,WAAW,UAAU;AAEjD,WAAO;AAAA,EACT;AAEA,WAAS,WAAW,GAAoB;AACtC,QAAI,IAAI;AACR,QAAI,EAAE,WAAW,GAAG,GAAG;AACrB,UAAI;AAAA,IACN;AACA,QAAI,oBAAoB;AACtB,UAAI,mBAAmB,CAAC,GAAG;AACzB,YAAI;AAAA,MACN;AAAA,IACF;AACA,QAAI,QAAQ,aAAa;AACvB,UAAI;AAAA,IACN;AACA,WAAO;AAAA,EACT;AAEA,aAAW,YAAY,QAAQ;AAC7B,QAAI,WAAW,QAAQ,GAAG;AAExB,aAAO,QAAQ,IAAI;AAAA,QACjB;AAAA,QACA,OAAO,QAAQ;AAAA,QACf;AAAA,QACA,OAAO,MAAM;AAAA,QACb;AAAA,MACF;AAAA,IACF,OAAO;AAAA,IAEP;AAAA,EACF;AAEA,SAAO,IAAI,MAAM,QAAQ;AAAA,IACvB,IAAI,QAAa,UAA2B,UAAoB;AAC9D,aAAO,QAAQ,IAAI,QAAQ,UAAU,QAAQ;AAAA,IAC/C;AAAA,IACA,IAAI,QAAa,UAA2B,OAAqB;AAC/D,UAAI;AACJ,UAAI,KAAK,OAAO,MAAM,OAAO,QAAQ;AACrC,UAAI,WAAW,OAAO,QAAQ,CAAC,GAAG;AAChC,mBAAW,SAAS,MAAM,OAAO,UAAU,IAAI,kBAAkB;AACjE,iBAAS,MAAM,WAAW,QAAQ,IAAI,QAAQ;AAAA,MAChD,OAAO;AACL,mBAAW;AAAA,MACb;AACA,aAAO,QAAQ,IAAI,QAAQ,UAAU,QAAQ;AAAA,IAC/C;AAAA,IACA,eAAe,QAAa,UAAoC;AAC9D,UAAI,KAAK,OAAO,MAAM,OAAO,QAAQ;AACrC,UAAI,WAAW,OAAO,QAAQ,CAAC,GAAG;AAChC,iBAAS,MAAM,UAAU,QAAQ,IAAI,IAAI;AAAA,MAC3C;AACA,aAAO,OAAO,QAAQ;AACtB,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAEH;AAiGO,SAAS,MAAM,IAAc;AAClC,MAAI,MAAW,CAAC;AAChB,MAAI,CAAC,GAAG,GAAG;AACT,QAAI,KAAK;AAAA,EACX,OAAO;AACL,QAAI,KAAM;AAAA,MACR,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,IACL,EAA6B,GAAG,CAAC;AAAA,EACnC;AACA,MAAI,OAAO,GAAG;AACd,MAAI,QAAQ,GAAG;AACf,SAAO;AACT;AAEO,SAAS,MAAM,IAAY,QAAa,MAAc,OAAiB;AAC5E,MAAI,IAAS,EAAE,GAAG,MAAM,GAAG,MAAM;AACjC,MAAI,MAAM,WAAW;AACnB,MAAE,IAAK;AAAA,MACL,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,EAA6B,EAAE;AAAA,EACjC;AACA,SAAO;AACT;AAkCO,SAAS,cAAc,WAAuB,SAAiB,GAAW;AAC/E,MAAI,IAAI;AACR,UACI,UAAU,GAAG,IAAK,QAAS,KAC5B,UAAU,GAAG,KAAM,KACnB,UAAU,GAAG,KAAM,IACpB,UAAU,CAAC;AAEf;AAiBO,SAAS,cAAc,WAAuB,SAAiB,GAAW;AAC/E,MAAI,IAAI;AACR,SACG,UAAU,GAAG,KAAM,KACnB,UAAU,GAAG,KAAM,IACpB,UAAU,CAAC;AAEf;AAeO,SAAS,cAAc,WAAuB,SAAiB,GAAW;AAC/E,MAAI,IAAI;AACR,SAAQ,UAAU,GAAG,KAAM,IAAK,UAAU,CAAC;AAC7C;AAiCO,SAAS,aAAa,WAAuB,SAAiB,GAAW;AAC9E,QAAM,WAAW,UAAU,MAAM,IAAK,SAAU,MAAO,OAAO;AAC9D,YAAU,MAAM,KAAM;AACtB,QAAM,KAAK,cAAc,WAAW,MAAM;AAC1C,SAAO,KAAK;AACd;AAcO,SAAS,cAAc,WAAuB,SAAiB,GAAW;AAC/E,QAAM,WAAW,UAAU,MAAM,IAAK,SAAU,MAAO,SAAS;AAChE,YAAU,MAAM,KAAM;AACtB,QAAM,KAAK,cAAc,WAAW,MAAM;AAC1C,SAAO,KAAK;AACd;AAiCO,SAAS,aAAa,WAAuB,SAAiB,GAAW;AAC9E,QAAM,WAAW,UAAU,MAAM,IAAK,SAAU,MAAO,QAAQ;AAC/D,YAAU,MAAM,KAAM;AACtB,QAAM,KAAK,cAAc,WAAW,MAAM;AAC1C,SAAO,KAAK;AACd;;;AChYA,IAAM,gBAAgB;AAiBtB,eAAsB,WAAW,QAAoC;AACnE,MAAI,OAAO,wBAAwB,aAAa;AAC9C,QAAI;AACF,YAAM,KAAK,IAAI,oBAAoB,aAAa;AAChD,YAAM,eAAe,MAAM,IAAI;AAAA,QAC7B,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE;AAAA,MAC5C,EAAE,YAAY;AAEd,aAAO;AAAA,IACT,SAAS,GAAG;AAEV,aAAO;AAAA,IACT;AAAA,EACF,OAAO;AACL,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AACF;;;AFnBA,SAAmB,MAAM,YAAY;AAwKrC,IAAqB,kBAArB,MAAqC;AAAA,EACnC,QAAQ;AAAA,EACR,QAAQ;AAAA;AAAA,EACR,MAAM;AAAA,EACN,YAAyC,CAAC;AAAA,EAC1C,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,cAAc;AAAA,EACd,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,QAAe;AAAA,IACb,MAAM;AAAA,IACN,KAAK;AAAA,IACL,QAAQ;AAAA,IAER,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,WAAW;AAAA,IAEX,MAAM;AAAA,IACN,QAAQ;AAAA;AAAA,EACV;AAAA,EACA,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,UAAkC,CAAC;AAAA,EACnC,KAAK;AAAA;AAAA,EACL,mBAA6C,CAAC;AAAA,EAE9C,KAAK;AAAA,EACL,SAA2B;AAAA,EAC3B,kBAA4C;AAAA,EAC5C,cAAiC,CAAC;AAAA,EAClC,oBAA2C,CAAC;AAAA,EAC5C,aAAsB;AAAA,EACtB,eAAsC;AAAA;AAAA,EACtC,qBAA4C;AAAA;AAAA,EAC5C,mBAA4B;AAAA,EAE5B,iBAAiB;AAAA,EACjB,mBAAmB,KAAK,IAAI;AAAA,EAC5B,gBAA2C,CAAC;AAAA,EAC5C,QAAc,CAAC,GAAG,GAAG,CAAC;AAAA,EACtB,QAAc,CAAC,GAAG,GAAG,GAAG,CAAC;AAAA,EACzB,OAAa,CAAC,GAAG,GAAG,CAAC;AAAA,EACrB,iBAAiB;AAAA,EACjB,OAA8B;AAAA,EAC9B,UAAiC;AAAA,EACjC,YAAmC;AAAA,EACnC,UAAiC;AAAA,EAGjC,YAAY;AAAA,IACV;AAAA;AAAA,IACA,gBAAgB;AAAA;AAAA,IAChB,YAAY;AAAA;AAAA,IACZ,cAAc;AAAA,IACd,QAAQ;AAAA,EACV,GAAsB;AACpB,SAAK,MAAM;AACX,SAAK,gBAAgB;AACrB,SAAK,YAAY;AACjB,SAAK,cAAc;AACnB,SAAK,SAAS;AACd,SAAK,QAAQ;AACb,SAAK,WAAW;AAChB,SAAK,IAAI,oBAAoB;AAAA,EAC/B;AAAA,EAEA,OAAO,MAAa;AAClB,QAAI,KAAK,OAAO;AACd,cAAQ,IAAI,GAAG,IAAI;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,QAAQ,MAAa;AACnB,QAAI,KAAK,OAAO;AACd,cAAQ,KAAK,GAAG,IAAI;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,SAAS,MAAa;AACpB,YAAQ,MAAM,GAAG,IAAI;AAAA,EACvB;AAAA;AAAA,EAIA,aAAa;AACX,QAAI,KAAK,SAAS;AAChB,oBAAc,KAAK,OAAO;AAAA,IAC5B;AACA,SAAK,UAAU,YAAY,MAAM;AAC/B,WAAK,MAAM;AAAA,IACb,GAAG,KAAK,KAAK;AACb,SAAK,OAAO,YAAY,MAAM;AAC5B,WAAK,aAAa;AAAA,IACpB,GAAG,GAAI;AACP,SAAK,UAAU,YAAY,MAAM;AAC/B,WAAK,MAAM;AAAA,IACb,GAAG,GAAK;AAAA,EACV;AAAA,EACA,QAAQ;AACN,QAAI,CAAC,KAAK,aAAa;AACrB;AAAA,IACF;AACA,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,eAAe;AACb,SAAK,MAAM,SAAS,KAAK,MAAM;AAC/B,SAAK,MAAM,MAAM;AACjB,SAAK,MAAM,YAAY,KAAK,MAAM;AAClC,SAAK,MAAM,SAAS;AACpB,SAAK,MAAM,UAAU,KAAK,MAAM;AAChC,SAAK,MAAM,OAAO;AAAA,EACpB;AAAA,EAEA,SAAS;AACP,SAAK,MAAM,UAAU;AACrB,SAAK,MAAM,SAAS;AACpB,SAAK,MAAM,SAAS;AACpB,SAAK,MAAM,YAAY;AACvB,SAAK,MAAM,OAAO;AAClB,SAAK,MAAM,MAAM;AAEjB,SAAK,KAAK;AACV,SAAK,YAAY,CAAC;AAClB,SAAK,mBAAmB,CAAC;AACzB,SAAK,gBAAgB,CAAC;AACtB,SAAK,gBAAgB;AACrB,SAAK,YAAY;AACjB,SAAK,mBAAmB;AACxB,SAAK,YAAY;AACjB,SAAK,KAAK;AAAA,EACZ;AAAA;AAAA;AAAA,EAKA,cAAc;AACZ,QAAI,MAAM,KAAK,IAAI;AACnB,QAAI,KAAK,MAAM,KAAK;AACpB,SAAK,mBAAmB;AACxB,QAAI,MAAM,KAAK,KAAK,KAAK;AAAE;AAAA,IAAO;AAClC,SAAK,iBAAiB;AACtB,aAAS,QAAQ,KAAK,WAAW;AAC/B,UAAI,MAAM,KAAK,UAAU,IAAI;AAC7B,UAAI,WAAW,KAAK;AACpB,UAAI,CAAC,UAAU;AAAE;AAAA,MAAS;AAC1B,eAAS,MAAM,UAAU;AACvB,YAAI,IAAY,SAAS,EAAE;AAC3B,YAAI,EAAE,cAAc,EAAE,YAAY;AAChC,cAAI,KAAK,EAAE;AACX,cAAI,KAAK,EAAE;AACX,gBAAM,WAAW,KAAK;AACtB,gBAAM,UAAU,MAAM;AACtB,YAAE,WAAW;AAEJ,cAAI,UAAU,KAAM;AAC3B,iBAAK,KAAK,EAAE,UAAW,EAAE,MAAO;AAChC,cAAE,oBAAoB;AAAA,UACxB,OAAO;AACL,kBAAM,QAAQ,KAAK,IAAI,GAAG,UAAU,QAAQ;AAC5C,iBAAK,KAAK,KAAK,OAAO,EAAE,QAAS,EAAE,QAAS,KAAK;AACjD,iBAAK,KAAK,EAAE,UAAW,EAAE,UAAW,KAAK,OAAO,IAAI;AACpD,cAAE,oBAAoB;AAAA,UACxB;AAAA,QACF;AACA,YAAI,EAAE,cAAc,EAAE,YAAY;AAChC,cAAI,KAAK,EAAE;AACX,cAAI,KAAK,EAAE;AACX,gBAAM,WAAW,KAAK;AACtB,gBAAM,UAAU,MAAM;AACtB,YAAE,WAAW;AAEJ,cAAI,UAAU,KAAM;AAC3B,iBAAK,KAAK,EAAE,UAAW,EAAE,MAAO;AAChC,cAAE,oBAAoB;AAAA,UACxB,OAAO;AACL,kBAAM,QAAQ,KAAK,IAAI,GAAG,UAAU,QAAQ;AAC5C,iBAAK,MAAM,KAAK,OAAO,EAAE,QAAS,EAAE,QAAS,KAAK;AAClD,iBAAK,MAAM,EAAE,UAAW,EAAE,UAAW,KAAK,OAAO,IAAI;AACrD,cAAE,oBAAoB;AAAA,UACxB;AAAA,QACF;AAAA,MAEF;AAAA,IACF;AACA,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA,EAIA,UAAU,MAAc;AACtB,SAAK,UAAU,IAAI,IAAI,CAAC;AACxB,SAAK,KAAK,EAAE,GAAG,OAAO,GAAG,KAAK,CAAC;AAAA,EACjC;AAAA,EAEA,YAAY,MAAc;AACxB,SAAK,KAAK,EAAE,GAAG,SAAS,GAAG,KAAK,CAAC;AACjC,WAAO,KAAK,UAAU,IAAI;AAAA,EAC5B;AAAA,EAEA,UAAU;AACR,QAAI,KAAK,cAAc;AACrB;AAAA,IACF;AACA,SAAK,eAAe;AACpB,SAAK,OAAO;AACZ,SAAK,IAAI,eAAe;AAExB,SAAK,SAAS,IAAI,UAAU,KAAK,GAAG;AAGpC,SAAK,OAAO,YAAY,OAAO,UAAwB;AACrD,UAAI,SAAS,MAAM,MAAM,KAAK,YAAY;AAC1C,WAAK,MAAM,OAAO,OAAO;AACzB,UAAI,MAAM,MAAM,WAAW,MAAM;AACjC,UAAI,OAAO,IAAI,WAAW,GAAG;AAC7B,UAAI,UAAU,OAAO,IAAI;AACzB,WAAK,WAAW,OAAO;AAAA,IACzB;AAGA,SAAK,OAAO,UAAU,CAAC,WAAgB;AACrC,WAAK,OAAO;AACZ,WAAK,cAAc;AACnB,WAAK,eAAe;AACpB,WAAK,gBAAgB;AACrB,WAAK,SAAS;AACd,WAAK,aAAa;AAClB,UAAI,KAAK,aAAa;AACpB,aAAK,eAAe;AAAA,MACtB;AACA,UAAI,KAAK,eAAe;AACtB;AAAA,UACE,MAAM;AACJ,iBAAK,WAAW;AAAA,UAClB;AAAA,UACA,MAAM,KAAK,OAAO,IAAI;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAEA,SAAK,OAAO,UAAU,CAAC,WAAkB;AACvC,WAAK,OAAO;AACZ,WAAK,cAAc;AACnB,WAAK,eAAe;AACpB,WAAK,gBAAgB;AACrB,WAAK,SAAS;AACd,WAAK,aAAa;AAClB,UAAI,KAAK,aAAa;AACpB,aAAK,eAAe;AAAA,MACtB;AAEA,UAAI,KAAK,eAAe;AACtB;AAAA,UACE,MAAM;AACJ,iBAAK,WAAW;AAAA,UAClB;AAAA,UACA,MAAM,KAAK,OAAO,IAAI;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAEA,SAAK,OAAO,SAAS,OAAO,WAAkB;AAC5C,WAAK,OAAO;AACZ,WAAK,eAAe;AACpB,WAAK,cAAc;AACnB,WAAK,gBAAgB;AACrB,WAAK,MAAM;AACX,WAAK,UAAU;AACf,UAAI,KAAK,aAAa;AACpB,cAAM,KAAK,kBAAkB;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAa;AACX,SAAK,OAAO;AACZ,SAAK,cAAc;AACnB,SAAK,eAAe;AACpB,SAAK,gBAAgB;AACrB,QAAI,KAAK,QAAQ;AACf,WAAK,OAAO,MAAM;AAAA,IACpB;AACA,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,UAAU;AACR,SAAK,OAAO;AACZ,SAAK,gBAAgB;AACrB,SAAK,WAAW;AAChB,SAAK,SAAS;AACd,QAAI,KAAK,KAAM,eAAc,KAAK,IAAI;AACtC,QAAI,KAAK,QAAS,eAAc,KAAK,OAAO;AAAA,EAC9C;AAAA,EAEA,YAAY;AAAA,EAAC;AAAA,EAEb,eAAe;AAAA,EAAC;AAAA,EAEhB,aAAa;AACX,QAAI,CAAC,KAAK,aAAa;AACrB,UAAI,CAAC,KAAK,cAAc;AACtB,aAAK,QAAQ;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA,EAEA,QAAQ;AACN,QAAI,KAAK,aAAa;AACpB,WAAK,KAAK,EAAE,GAAG,QAAQ,IAAI,KAAK,IAAI,EAAE,CAAC;AAAA,IACzC;AAAA,EACF;AAAA;AAAA,EAIA,SAAS,OAAe,MAA4B,OAAwB;AAAA,EAAC;AAAA,EAE7E,UAAU,UAAmB;AAAA,EAAC;AAAA,EAE9B,KAAK,WAAgB;AACnB,QAAI;AACF,UAAI,MAAM,OAAO,SAAS;AAC1B,WAAK,MAAM,QAAQ,IAAI;AACvB,UAAI,KAAK,QAAQ;AACf,aAAK,OAAO,KAAK,GAAG;AAAA,MACtB;AAAA,IACF,SAAS,GAAG;AACV,WAAK,MAAM,eAAe,CAAC;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,IAAI,WAAiC;AACnC,QAAI,QAAe,KAAG,OAAO,KAAK,KAAK,SAAS;AAChD,WAAO,KAAK,UAAU,KAAG,MAAM,CAAC,CAAC;AAAA,EACnC;AAAA,EAEA,MAAM,WAAW,SAAkB;AACjC,QAAI,OAAO,KAAK,IAAI;AACpB,QAAI,QAAQ,KAAK,QAAQ;AAEvB,UAAI,OAAc,KAAG,QAAQ;AAC7B,UAAI,MAAM,QAAQ;AAClB,WAAK,UAAU,IAAI,IAAI;AACvB,WAAK,mBAAmB,OAAO;AAC/B,WAAK,YAAY;AACjB,UAAI,KAAK,WAAW;AAClB,aAAK,UAAU,IAAI,IAAI;AAAA,UACrB;AAAA,UACA,KAAK,UAAU,IAAI;AAAA,UACnB,KAAK,kBAAkB,KAAK,IAAI;AAAA,QAClC;AAAA,MACF;AACA,WAAK,YAAY;AACjB,WAAK,gBAAgB,QAAQ;AAC7B,WAAK,KAAK,QAAQ;AAClB,UAAI,KAAK,gBAAgB;AACvB,aAAK,SAAS,MAAM,KAAK,UAAU,IAAI,GAAG,IAAI;AAAA,MAChD;AAAA,IACF,WAAW,QAAQ,KAAK,SAAS;AAE/B,WAAK,YAAY,QAAQ;AACzB,UAAI,OAAO,QAAQ;AACnB,UAAI,QAAQ,KAAK;AACf,aAAK,YAAY;AACjB,iBAAS,MAAM,QAAQ,KAAK;AAC1B,cAAI,MAAM,MAAM,EAAE;AAClB,cAAI;AACF,2BAAe,KAAK,UAAU,IAAI,GAAG,GAAG;AAAA,UAC1C,SAAS,GAAG;AACV,iBAAK,MAAM,6BAA6B,MAAM,WAAW,KAAK,CAAC;AAAA,UACjE;AAAA,QACF;AACA,aAAK,YAAY;AAAA,MACnB;AACA,UAAI,KAAK,gBAAgB;AACvB,aAAK,SAAS,MAAM,KAAK,UAAU,IAAI,GAAG,QAAQ,GAAG;AAAA,MACvD;AAAA,IACF,WAAW,QAAQ,KAAK,SAAS;AAE/B,WAAK,QAAQ,QAAQ,MAAI,MAAI,QAAQ,GAAG,IAAI;AAC5C,UAAI,QAAQ,MAAM;AAChB,YAAI,SAAS;AACb,YAAI,KAAK,QAAQ;AACjB,YAAI,QAAQ,IAAI,WAAW,EAAE;AAC7B,mBAAW,OAAO,KAAK,SAAS;AAC9B,cAAI,QAAQ,KAAK,QAAQ,GAAG;AAC5B,cAAI,MAAM,OAAO,QAAQ,KAAK;AAC5B,gBAAI,SAAS,MAAM;AACnB,gBAAI,SAAS,MAAM;AACnB,kBAAM,IAAI,IAAI,WAAW,MAAM,IAAI,GAAG,MAAM;AAC5C;AACA,mBAAO,KAAK,QAAQ,GAAG;AAAA,UACzB;AAAA,QACF;AAEA,YAAI,UAAU,QAAQ,MAAM,GAAG;AAC7B,cAAI;AACF,gBAAI,OAAO,MAAM,WAAW,KAAK;AACjC,gBAAI,QAAQ,IAAI,WAAW,IAAI;AAC/B,gBAAI,WAAW,OAAO,KAAK;AAE3B,iBAAK,WAAW,QAAQ;AAAA,UAC1B,SAAS,OAAO;AACd,iBAAK,MAAM,0BAA0B,KAAK;AAAA,UAC5C;AAAA,QACF,OAAO;AACL,eAAK,KAAK,kBAAkB,QAAQ,MAAM,QAAQ,MAAM,CAAC;AAAA,QAC3D;AAAA,MACF;AAAA,IACF,WAAW,QAAQ,KAAK,UAAU;AAChC,aAAO,KAAK,IAAI;AAChB,UAAI,OAAO,QAAQ;AAEnB,UAAI,UAAU;AACd,UAAI,CAAC,KAAK,cAAc,IAAI,GAAG;AAC7B,aAAK,cAAc,IAAI,IAAI,QAAQ;AAAA,MACrC,OAAO;AACL,YAAI,KAAK,cAAc,IAAI,IAAI,QAAQ,GAAG;AACxC,cAAI,KAAK,QAAQ,IAAI,KAAK,cAAc,IAAI,IAAI;AAChD,cAAI,KAAK,GAAG;AACV,iBAAK,KAAK,UAAU,KAAK,UAAU;AAAA,UACrC;AACA,eAAK,cAAc,IAAI,IAAI,QAAQ;AAAA,QACrC,WAAW,KAAK,cAAc,IAAI,IAAI,QAAQ,GAAG;AAG/C,eAAK,KAAK,4CAA4C,IAAI,KAAK,QAAQ,CAAC,MAAM,KAAK,cAAc,IAAI,CAAC,EAAE;AACxG,oBAAU;AAAA,QACZ;AAAA,MACF;AACA,UAAI,SAAS;AACX,aAAK,mBAAmB,OAAO;AAAA,MACjC;AAAA,IACF,WAAW,QAAQ,KAAK,QAAQ;AAC9B,WAAK,KAAK,QAAQ;AAClB,aAAO,KAAK,IAAI;AAChB,UAAI,SAAS,QAAQ;AACrB,UAAI,OAAO,OAAO;AAClB,UAAI,QAAQ,QAAQ;AACpB,WAAK,KAAK,EAAE,GAAG,QAAQ,IAAI,KAAK,IAAI,GAAG,IAAI,MAAM,CAAC;AAClD,WAAK,MAAM,SAAS,QAAQ,OAAO,IAAI;AACvC,WAAK,MAAM,OAAO;AAClB,WAAK,IAAI,QAAQ,MAAM,MAAM,UAAU,KAAK,MAAM,QAAQ,IAAI;AAAA,IAChE,WAAW,QAAQ,KAAK,aAAa;AACnC,WAAK,IAAI,wBAAwB,OAAO;AAAA,IAE1C,WAAW,QAAQ,KAAK,cAAc;AACpC,WAAK,IAAI,yBAAyB,OAAO;AACzC,UAAI;AACF,cAAM,cAAc,IAAI,sBAAsB;AAAA,UAC5C,MAAM,QAAQ;AAAA,UACd,KAAK,QAAQ;AAAA,QACf,CAAC;AACD,YAAI,KAAK,iBAAiB;AACxB,gBAAM,KAAK,gBAAgB,qBAAqB,WAAW;AAAA,QAC7D;AACA,aAAK,IAAI,0CAA0C;AAMnD,iBAAS,aAAa,KAAK,mBAAmB;AAC5C,cAAI;AACF,kBAAM,KAAK,iBAAiB,gBAAgB,SAAS;AACrD,iBAAK,IAAI,oCAAoC,SAAS;AAAA,UACxD,SAAS,OAAO;AACd,iBAAK,MAAM,2CAA2C,KAAK;AAAA,UAC7D;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,aAAK,MAAM,0CAA0C,KAAK;AAAA,MAC5D;AAAA,IACF,WAAW,QAAQ,KAAK,iBAAiB;AACvC,WAAK,IAAI,2BAA2B,OAAO;AACzC,UAAI,KAAK,mBAAmB,QAAQ,WAAW;AAC7C,aAAK,kBAAkB,KAAK,QAAQ,SAAS;AAAA,MAC/C;AAAA,IACJ,OAAO;AACL,WAAK,UAAU,OAAO;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,kBAAkB,MAAc,IAAS,QAAa,MAAc,OAAY;AAC9E,QAAI,KAAK,OAAO;AACd,WAAK,IAAI,oBAAoB,MAAM,IAAI,QAAQ,MAAM,KAAK;AAAA,IAC5D;AACA,QAAI,KAAK,aAAa,CAAC,KAAK,WAAW;AACrC;AAAA,IACF;AACA,QAAI,KAAK,QAAQ,IAAI,KAAK,GAAG;AAC3B;AAAA,IACF;AACA,QAAI,CAAC,KAAK,iBAAiB,IAAI,GAAG;AAChC,WAAK,iBAAiB,IAAI,IAAI,CAAC;AAAA,IACjC;AACA,SAAK,iBAAiB,IAAI,EAAE,KAAK,MAAM,IAAI,QAAQ,MAAM,KAAK,CAAC;AAAA,EACjE;AAAA,EAEA,eAAe;AACb,aAAS,QAAQ,KAAK,kBAAkB;AACtC,UAAI,KAAK,KAAK,iBAAiB,IAAI;AACnC,UAAI,CAAC,MAAM,GAAG,UAAU,GAAG;AACzB;AAAA,MACF;AACA,UAAI,SAAc;AAAA,QAChB,GAAG;AAAA,QACH,GAAG;AAAA,QACH,IAAI,KAAK,IAAI;AAAA,QACb,GAAG;AAAA,MACL;AAEA,UAAI,GAAG,SAAS,GAAG;AACjB,eAAO,IAAI;AAAA,MACb;AACA,WAAK,KAAK,MAAM;AAChB,SAAG,SAAS;AACZ,UAAI,KAAK,gBAAgB;AACvB,aAAK,SAAS,MAAM,KAAK,UAAU,KAAG,IAAI,GAAG,OAAO,CAAC;AAAA,MACvD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,mBAAmB,SAAkB;AACnC,QAAI,OAAO,KAAK,IAAI;AACpB,QAAI,OAAO,QAAQ;AACnB,QAAI,QAAQ,QAAQ;AACpB,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AACA,QAAI,MAAM,KAAK,UAAU,IAAI;AAC7B,QAAI,CAAC,KAAK;AACR;AAAA,IACF;AACA,QAAI,WAAW,IAAI;AACnB,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AACA,QAAI,SAAS,KAAK,UAAU,KAAG,IAAI,GAAG;AACtC,QAAI,CAAC,QAAQ;AACX,eAAS,CAAC,GAAG,GAAG,CAAC;AAAA,IACnB;AACA,aAAS,OAAO,OAAO;AACrB,UAAI,UAAU,MAAM,GAAG;AACvB,UAAI,QAAQ,MAAM;AAChB,YAAI,QAAQ,QAAQ;AACpB,YAAI,OAAO,QAAQ;AAEnB,YAAI,QAAmC,CAAC;AACxC,iBAASA,QAAO,MAAM;AACpB,gBAAM,KAAKA,IAAG,CAAC,IAAIA;AAAA,QACrB;AACA,YAAI,SAAS;AAEb,eAAO,SAAS,MAAM,YAAY;AAChC,cAAI,KAAK,KAAG,cAAc,OAAO,MAAM;AACvC,oBAAU;AACV,cAAI,MAAM,KAAG,cAAc,OAAO,MAAM;AACxC,oBAAU;AACV,cAAI,IAAY,SAAS,EAAE;AAC3B,cAAI,CAAC,GAAG;AAEN;AAAA,UACF;AACA,cAAI,QAAQ,MAAM,GAAG;AACrB,YAAE,GAAG,IAAI;AAET,YAAE,cAAY,GAAG,IAAI;AAAA,QACvB;AAAA,MACF,OAAO;AACL,YAAI,QAAQ,QAAQ;AACpB,YAAI,SAAS;AACb,eAAO,SAAS,MAAM,YAAY;AAChC,cAAI,KAAK,KAAG,cAAc,OAAO,MAAM;AACvC,cAAI,IAAY,SAAS,EAAE;AAC3B,cAAI,CAAC,GAAG;AACN,gBAAI,OAAO,YAAY;AACrB,wBAAU;AAAA,YACZ,WAAW,OAAO,YAAY;AAC5B,wBAAU;AAAA,YACZ,WAAW,OAAO,SAAS;AACzB,wBAAU;AAAA,YACZ;AACA;AAAA,UACF;AACA,oBAAU;AAEV,cAAI,OAAO,YAAY;AACrB,gBAAI,CAAC,EAAE,QAAQ;AACb,gBAAE,SAAS,CAAC,GAAG,GAAG,CAAC;AACnB,gBAAE,SAAS,CAAC,GAAG,GAAG,CAAC;AAAA,YACrB,OAAO;AACL,gBAAE,OAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;AACzB,gBAAE,OAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;AACzB,gBAAE,OAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;AACzB,gBAAE,aAAa,EAAE;AAAA,YACnB;AACA,cAAE,aAAa;AACf,cAAE,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,aAAa,OAAO,MAAM;AACpD,sBAAU;AACV,cAAE,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,aAAa,OAAO,MAAM;AACpD,sBAAU;AACV,cAAE,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,aAAa,OAAO,MAAM;AACpD,sBAAU;AACV,gBAAI,CAAC,EAAE,UAAU;AACf,gBAAE,WAAW;AAAA,gBACX,EAAE,OAAO,CAAC;AAAA,gBACV,EAAE,OAAO,CAAC;AAAA,gBACV,EAAE,OAAO,CAAC;AAAA,cACZ;AAAA,YACF;AAAA,UACF,WAAW,OAAO,YAAY;AAC5B,gBAAI,CAAC,EAAE,QAAQ;AACb,gBAAE,SAAS,CAAC,GAAG,GAAG,GAAG,CAAC;AACtB,gBAAE,SAAS,CAAC,GAAG,GAAG,GAAG,CAAC;AAAA,YACxB,OAAO;AACL,gBAAE,OAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;AACzB,gBAAE,OAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;AACzB,gBAAE,OAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;AACzB,gBAAE,OAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;AACzB,gBAAE,aAAa,EAAE;AAAA,YACnB;AACA,cAAE,aAAa;AACf,cAAE,OAAO,CAAC,IAAI,aAAa,OAAO,MAAM;AACxC,sBAAU;AACV,cAAE,OAAO,CAAC,IAAI,aAAa,OAAO,MAAM;AACxC,sBAAU;AACV,cAAE,OAAO,CAAC,IAAI,aAAa,OAAO,MAAM;AACxC,sBAAU;AACV,cAAE,OAAO,CAAC,IAAI,aAAa,OAAO,MAAM;AACxC,sBAAU;AACV,iBAAK,UAAU,EAAE,QAAQ,EAAE,MAAM;AACjC,gBAAI,CAAC,EAAE,UAAU;AACf,gBAAE,WAAW;AAAA,gBACX,EAAE,OAAO,CAAC;AAAA,gBACV,EAAE,OAAO,CAAC;AAAA,gBACV,EAAE,OAAO,CAAC;AAAA,gBACV,EAAE,OAAO,CAAC;AAAA,cACZ;AAAA,YACF;AAAA,UACF,WAAW,OAAO,SAAS;AACzB,gBAAI,CAAC,EAAE,QAAQ;AACb,gBAAE,SAAS,CAAC,GAAG,GAAG,CAAC;AACnB,gBAAE,SAAS,CAAC,GAAG,GAAG,CAAC;AAAA,YACrB,OAAO;AACL,gBAAE,OAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;AACzB,gBAAE,OAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;AACzB,gBAAE,OAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;AACzB,gBAAE,aAAa,EAAE;AAAA,YACnB;AACA,cAAE,aAAa;AACf,cAAE,OAAO,CAAC,IAAI,cAAc,OAAO,MAAM;AACzC,sBAAU;AACV,cAAE,OAAO,CAAC,IAAI,cAAc,OAAO,MAAM;AACzC,sBAAU;AACV,cAAE,OAAO,CAAC,IAAI,cAAc,OAAO,MAAM;AACzC,sBAAU;AACV,gBAAI,CAAC,EAAE,KAAK;AACV,gBAAE,MAAM;AAAA,gBACN,EAAE,OAAO,CAAC;AAAA,gBACV,EAAE,OAAO,CAAC;AAAA,gBACV,EAAE,OAAO,CAAC;AAAA,cACZ;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAIA,QAAQ,SAAkB;AACxB,QAAI,KAAK,gBAAgB,KAAK,aAAa,eAAe,QAAQ;AAChE,WAAK,aAAa,KAAK,OAAO,OAAO,CAAC;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,gBAAgB;AACd,SAAK,IAAI,gBAAgB;AACzB,SAAK,KAAK,EAAE,GAAG,QAAQ,SAAS,wBAAwB,CAAC;AAAA,EAC3D;AAAA,EAEA,mBAAmB;AACjB,SAAK,mBAAmB;AACxB,SAAK,IAAI,mBAAmB;AAAA,EAC9B;AAAA,EAEA,MAAM,cAAc,MAAmB;AACrC,SAAK,MAAM,UAAU,KAAK;AAC1B,QAAI,QAAQ,IAAI,WAAW,IAAI;AAC/B,QAAI,MAAM,MAAM,WAAW,KAAK;AAChC,QAAI,OAAO,IAAI,WAAW,GAAG;AAC7B,QAAI,UAAU,OAAO,IAAI;AACzB,SAAK,WAAW,OAAO;AAAA,EACzB;AAAA,EAEA,MAAM,oBAAoB;AAExB,SAAK,kBAAkB;AACvB,SAAK,cAAc,CAAC;AACpB,SAAK,oBAAoB,CAAC;AAC1B,SAAK,aAAa;AAClB,QAAI;AAEF,WAAK,kBAAkB,IAAI,kBAAkB;AAAA,QAC3C,YAAY;AAAA,UACV,EAAE,MAAM,+BAA+B;AAAA,UACvC,EAAE,MAAM,gCAAgC;AAAA,UACxC,EAAE,MAAM,yBAAyB;AAAA,QACnC;AAAA,QACA,sBAAsB;AAAA,MACxB,CAAC;AAKD,WAAK,gBAAgB,iBAAiB,CAAC,UAAqC;AAE1E,YAAI,MAAM,WAAW;AACnB,eAAK,YAAY,KAAK,MAAM,SAAS;AAAA,QACvC,OAAO;AACL,eAAK,IAAI,uCAAuC;AAAA,QAClD;AAAA,MACF;AAGA,WAAK,gBAAgB,0BAA0B,MAAM;AAEnD,YAAI,KAAK,mBAAmB,KAAK,gBAAgB,oBAAoB,aAAa;AAChF,eAAK,mBAAmB;AACxB,eAAK,IAAI,mCAAmC;AAAA,QAC9C,WACE,KAAK,oBACL,KAAK,gBAAgB,oBAAoB,YACzC,KAAK,gBAAgB,oBAAoB,kBACzC,KAAK,gBAAgB,oBAAoB,WACzC;AACA,eAAK,mBAAmB;AACxB,eAAK,IAAI,uCAAuC;AAAA,QAClD;AAAA,MACF;AAEA,WAAK,gBAAgB,4BAA4B,MAAM;AACrD,aAAK,IAAI,0CAA0C,KAAK,YAAY,QAAQ,KAAK,iBAAiB,iBAAiB;AACnH,YAAI,KAAK,iBAAiB,qBAAqB,cAAc,KAAK,YAAY;AAC5E,mBAAS,aAAa,KAAK,aAAa;AACtC,iBAAK,KAAK;AAAA,cACR,GAAG;AAAA,cACH,MAAM;AAAA,cACN;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAEA,WAAK,gBAAgB,6BAA6B,MAAM;AAItD,YACE,KAAK,oBACL,KAAK,gBAAgB,uBAAuB,eAC5C,KAAK,gBAAgB,uBAAuB,cAC5C;AAAA,QAEF;AAAA,MACF;AAGA,WAAK,eAAe,KAAK,gBAAgB;AAAA,QACvC;AAAA,QACA;AAAA,UACE,SAAS;AAAA,UACT,gBAAgB;AAAA,QAClB;AAAA,MACF;AAEA,WAAK,aAAa,SAAS,MAAM;AAC/B,aAAK,cAAc;AAAA,MACrB;AAEA,WAAK,aAAa,UAAU,MAAM;AAChC,aAAK,iBAAiB;AAAA,MACxB;AAEA,WAAK,aAAa,UAAU,CAAC,WAAkB;AAC7C,aAAK,MAAM,kCAAkC,MAAM;AAAA,MACrD;AAGA,WAAK,gBAAgB,gBAAgB,CAAC,UAA+B;AAEnE,cAAM,cAAc,MAAM;AAC1B,aAAK,qBAAqB;AAE1B,oBAAY,SAAS,MAAM;AAAA,QAE3B;AAEA,oBAAY,UAAU,MAAM;AAAA,QAE5B;AAEA,oBAAY,UAAU,CAAC,WAAkB;AAAA,QAEzC;AAEA,oBAAY,YAAY,CAACC,WAAwB;AAC/C,eAAK,cAAcA,OAAM,IAAI;AAAA,QAC/B;AAAA,MACF;AAGA,YAAM,eAAgC;AAAA,QACpC,qBAAqB;AAAA,QACrB,qBAAqB;AAAA,QACrB,YAAY;AAAA,MACd;AAEA,YAAM,QAAQ,MAAM,KAAK,gBAAgB,YAAY,YAAY;AAEjE,YAAM,KAAK,gBAAgB,oBAAoB,KAAK;AAGpD,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAG,CAAC;AAEvD,UAAI,KAAK,KAAK,gBAAgB;AAG9B,UAAI,IAAI;AACN,cAAM,eAAe;AAAA,UACnB,GAAG;AAAA,UACH,MAAM,GAAG;AAAA,UACT,KAAK,GAAG;AAAA,QACV;AAEA,aAAK,KAAK,YAAY;AACtB,aAAK,aAAa;AAAA,MACpB;AAGA,iBAAW,MAAM;AACf,YAAI,CAAC,KAAK,oBAAoB,KAAK,iBAAiB;AAQlD,cAAI,KAAK,gBAAgB,uBAAuB,UAAU;AACxD,iBAAK,IAAI,6BAA6B;AACtC,iBAAK,YAAY;AAAA,UACnB;AAAA,QACF;AAAA,MACF,GAAG,GAAI;AAAA,IACT,SAAS,OAAO;AACd,WAAK,MAAM,eAAe,KAAK;AAAA,IACjC;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,cAAc;AAClB,QAAI;AACF,YAAM,eAAe;AAAA,QACnB,qBAAqB;AAAA,QACrB,qBAAqB;AAAA,QACrB,YAAY;AAAA,MACd;AAEA,YAAM,QAAQ,MAAM,KAAK,iBAAiB,YAAY,YAAY;AAClE,YAAM,KAAK,iBAAiB,oBAAoB,KAAK;AAErD,YAAM,eAAe;AAAA,QACnB,GAAG;AAAA,QACH,MAAM,OAAO;AAAA,QACb,KAAK,OAAO;AAAA,MACd;AAEA,WAAK,KAAK,YAAY;AAAA,IACxB,SAAS,OAAO;AAAA,IAEhB;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiB;AACrB,QAAI,KAAK,iBAAiB;AACxB,UAAI,KAAK,gBAAgB,aAAa;AACpC,aAAK,gBAAgB,YAAY,MAAM;AAAA,MACzC;AACA,WAAK,gBAAgB,MAAM;AAC3B,WAAK,kBAAkB;AAAA,IACzB;AACA,QAAI,KAAK,cAAc;AACrB,WAAK,aAAa,MAAM;AACxB,WAAK,eAAe;AAAA,IACtB;AACA,SAAK,mBAAmB;AAAA,EAC1B;AACF;","names":["key","event"]}