topazcube 0.1.16 → 0.1.17

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/server.cjs CHANGED
@@ -281,8 +281,8 @@ var import_fast_json_patch = __toESM(require("fast-json-patch"), 1);
281
281
  var import_ws = require("ws");
282
282
  var import_mongodb = require("mongodb");
283
283
  var import_gl_matrix = require("gl-matrix");
284
+ var import_wrtc = __toESM(require("@roamhq/wrtc"), 1);
284
285
  import_gl_matrix.glMatrix.setMatrixArrayType(Array);
285
- var wrtc = require("@roamhq/wrtc");
286
286
  var fastPatchProperties = {
287
287
  "type": true,
288
288
  // string 'enemy'
@@ -959,7 +959,7 @@ var TopazCubeServer = class {
959
959
  }
960
960
  /*= WEBRTC ===================================================================*/
961
961
  async _processOffer(client, data) {
962
- const peerConnection = new wrtc.RTCPeerConnection({
962
+ const peerConnection = new import_wrtc.default.RTCPeerConnection({
963
963
  iceServers: [
964
964
  { urls: "stun:stun.l.google.com:19302" },
965
965
  { urls: "stun:stun.cloudflare.com:3478" },
@@ -996,7 +996,7 @@ var TopazCubeServer = class {
996
996
  };
997
997
  try {
998
998
  await peerConnection.setRemoteDescription(
999
- new wrtc.RTCSessionDescription(data)
999
+ new import_wrtc.default.RTCSessionDescription(data)
1000
1000
  );
1001
1001
  client.dataChannel = peerConnection.createDataChannel("serverchannel", {
1002
1002
  ordered: true,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/utils.ts","../src/compress-node.ts"],"sourcesContent":["import * as https from 'node:https'\nimport * as fs from 'node:fs'\nimport {\n reactive,\n deepGet,\n clonewo_,\n opmsg,\n msgop,\n encode_uint32,\n encode_fp412,\n encode_fp168,\n encode_fp1616,\n limitPrecision,\n encode,\n decode\n} from './utils'\nimport { compress, decompress } from './compress-node'\nimport fastjsonpatch from 'fast-json-patch'\nimport { WebSocketServer, WebSocket } from 'ws'\nimport { MongoClient, Db } from 'mongodb'\nimport { doesNotThrow } from 'assert'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\nglMatrix.setMatrixArrayType(Array)\nconst wrtc = require('@roamhq/wrtc') // Server-side WebRTC implementation\n\n// entities/ID/\nconst fastPatchProperties: Record<string, boolean> = {\n 'type': true, // string 'enemy'\n 'status': true, // string 'idle'\n 'level': true, // number 2\n 'race': true, // string 'goblin'\n 'class': true, // string 'warrior'\n 'model': true, // string 'models/models.glb|goblin'\n 'animation': true, // string 'idle2'\n 'sound': true, // string 'sound/goblin.snd|snarl'\n 'effect': true, // 'selected'\n 'position': true, // [0, 0, 0] Vector (Number)\n 'rotation': true, // [0, 0, 0, 1] Quaternion (Number)\n 'scale': true, // [1, 1, 1] Vector (Number)\n}\n\nconst dictionaryProperties: Record<string, boolean> = {\n 'type': true,\n 'status': true,\n 'level': true,\n 'race': true,\n 'class': true,\n 'model': true,\n 'animation': true,\n 'sound': true,\n 'effect': true,\n}\n\nconst { applyOperation } = fastjsonpatch\nconst LITTLE_ENDIAN = (() => {\n const buffer = new ArrayBuffer(2)\n new DataView(buffer).setInt16(0, 256, true)\n return new Int16Array(buffer)[0] === 256\n})()\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\n\ntype ClientType = any\n\ninterface StatsType {\n tUpdate: number[]\n tPatch: number[]\n send: number\n sendRTC: number\n _sendRTCUpdate: number\n [key: string]: any\n}\n\nexport default class TopazCubeServer {\n name = 'TopazCubeServer'\n cycle = 100\n patchCycleDivider = 1\n port = 8799\n useHttps = false\n key = './cert/key.pem'\n cert = './cert/cert.pem'\n MongoUrl = 'mongodb://localhost:27017'\n mongoClient: MongoClient | null = null\n DB: Db | null = null\n database = 'topazcube'\n collection = 'documents'\n allowSave = true\n allowSync = true\n allowWebRTC = false\n allowFastPatch = false\n allowCompression = false\n simulateLatency = 0\n\n _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _loopiv: any = null\n _statsiv: any = null\n _stillUpdating = false\n stats: StatsType = {\n tUpdate: [],\n tPatch: [],\n send: 0,\n sendRTC: 0,\n _sendRTCUpdate: 0\n }\n\n _wss: WebSocketServer | null = null\n _exited = false\n\n log(...args: any[]) {\n console.log(this.name + ':', ...args);\n }\n\n warn(...args: any[]) {\n console.warn(this.name + ':', ...args);\n }\n\n error(...args: any[]) {\n console.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n port = 8799,\n useHttps = false,\n key = './cert/key.pem',\n cert = './cert/cert.pem',\n MongoUrl = 'mongodb://localhost:27017',\n database = 'topazcube',\n collection = 'documents',\n allowSave = true,\n allowSync = true,\n allowWebRTC = false,\n allowFastPatch = false,\n allowCompression = false,\n simulateLatency = 0,\n }: {\n name?: string\n cycle?: number\n port?: number\n useHttps?: boolean\n key?: string\n cert?: string\n MongoUrl?: string\n database?: string\n collection?: string\n allowSave?: boolean\n allowSync?: boolean\n allowWebRTC?: boolean\n allowFastPatch?: boolean\n allowCompression?: boolean\n simulateLatency?: number\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.port = port\n this.useHttps = useHttps\n this.key = key\n this.cert = cert\n this.MongoUrl = MongoUrl\n this.database = database\n this.collection = collection\n this.allowSave = allowSave\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.allowFastPatch = allowFastPatch\n this.allowCompression = allowCompression\n this.simulateLatency = simulateLatency\n\n this._initDB()\n\n if (useHttps) {\n let httpsServer: https.Server | null = https.createServer({\n key: fs.readFileSync(this.key),\n cert: fs.readFileSync(this.cert),\n }, (req, res) => {\n res.writeHead(200)\n res.end('<b>Hello World!</b>')\n }).listen(this.port)\n this._wss = new WebSocketServer({ server: httpsServer })\n httpsServer = null\n this.log(this.name + ' running on HTTPS port ' + this.port)\n } else {\n this._wss = new WebSocketServer({ port: this.port })\n this.log(this.name + ' running on port ' + this.port)\n }\n this._wss.on('connection', (client: WebSocket) => {\n this._onConnected(client)\n })\n\n process.stdin.resume()\n process.on('SIGINT', () => {\n this._exitSignal('SIGINT')\n })\n process.on('SIGQUIT', () => {\n this._exitSignal('SIGQUIT')\n })\n process.on('SIGTERM', () => {\n this._exitSignal('SIGTERM')\n })\n process.on('SIGUSR2', () => {\n this._exitSignal('SIGUSR2')\n })\n\n // Setup keypress handling for console input\n process.stdin.resume()\n process.stdin.setEncoding('utf8')\n\n process.stdin.on('data', (key: any) => {\n key = (''+key).trim()\n\n // ctrl-c ( end of text )\n if (key == '\\u0003') {\n this._exitSignal('SIGINT')\n return\n }\n\n // Process other keypresses\n this.log(`Key pressed: ${key}`)\n\n // Example: 's' to save all documents\n if (key == 's') {\n this.log('Saving all documents...')\n this._saveAllDocuments()\n }\n\n // Example: 'i' to print server info\n if (key == 'i') {\n this.log(\n `Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`\n )\n }\n })\n this._startLoop()\n }\n\n /*= DOCUMENTS ==============================================================*/\n\n // to be redefined. Called before a new document is created. Returns true if\n // the client has the right to create an empty document\n canCreate(client: ClientType, name: string): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is created\n // (returns an empty document)\n onCreate(name: string): any {\n return {\n data: {},\n }\n }\n\n // to be redefined. Called when a client wants to sync (modify) a document.\n // Returns true if the client has the right to sync that operation.\n canSync(client: ClientType, name: string, op: any): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is hydrated\n // (created, or loaded from db)\n async onHydrate(name: string, document: any): Promise<void> {\n document.__hydrated = true\n }\n\n _makeReactive(name: string): void {\n //this.log(`Making document '${name}' reactive`, this.documents[name])\n let ep: any = false\n if (this.allowFastPatch) {\n ep = fastPatchProperties\n }\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this),\n '',\n ep\n )\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n }\n\n _createEmptyDocument(name: string): void {\n let doc = this.onCreate(name)\n if (!doc) {\n return\n }\n this.documents[name] = doc\n }\n\n async _waitLoad(name: string): Promise<void> {\n if (this.isLoading[name]) {\n while (this.isLoading[name]) {\n await new Promise((resolve) => setTimeout(resolve, 50))\n }\n }\n }\n\n async _checkDocument(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n if (!this.documents[name]) {\n this.isLoading[name] = true\n await this._loadDocument(name)\n if (!this.documents[name] && this.canCreate(client, name)) {\n this._createEmptyDocument(name)\n }\n if (this.documents[name]) {\n this._makeReactive(name)\n this.onHydrate(name, this.documents[name])\n }\n this.isLoading[name] = false\n this._documentState[name] = {\n subscibers: 0,\n lastModified: Date.now(),\n }\n }\n }\n\n _updateAllDocumentsState(): void {\n for (let name in this.documents) {\n if (name != '_server') {\n let doc = this.documents[name]\n this._documentState[name].subscibers = 0\n for (let client of this.clients) {\n if (client.subscribed && client.subscribed[name]) {\n this._documentState[name].subscibers++\n }\n }\n }\n }\n }\n\n /*= UPDATE LOOP ============================================================*/\n\n // to be redefined. called every this.cycle ms\n onUpdate(name: string, doc: any, dt: number): void {}\n\n _startLoop(): void {\n this.lastUpdate = Date.now()\n this._loop()\n this._statsiv = setInterval(() => {\n this._doStats()\n }, 1000)\n }\n\n _loop(): void {\n let now = Date.now()\n let dtms = (now - this.lastUpdate)\n let dt = dtms / 1000.0 // Convert to seconds\n this.lastUpdate = now\n\n /*\n if (this._stillUpdating) {\n return\n }\n */\n this._stillUpdating = true\n for (let name in this.documents) {\n this.onUpdate(name, this.documents[name], dt)\n }\n let t1 = Date.now()\n this._stillUpdating = false\n let updateTime = t1 - now\n this.stats.tUpdate.push(updateTime)\n\n //this.log(`update ${this.update} patch: ${this.update % this.patchCycleDivider}`, )\n\n let patchTime = 0\n if (this.update % this.patchCycleDivider == 0) {\n this._sendPatches()\n let t2 = Date.now()\n patchTime = t2 - t1\n this.stats.tPatch.push(patchTime)\n if (this.allowFastPatch) {\n this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`, )\n }\n this.stats._sendRTCUpdate = 0\n }\n\n this.update++\n let endUpdate = Date.now()\n let totalUpdate = endUpdate - now\n\n setTimeout(() => {\n this._loop()\n }, Math.max(this.cycle - totalUpdate, 10))\n }\n\n _doStats(): void {\n for (let key in this.stats) {\n let i = this.stats[key]\n if (Array.isArray(i) && i.length > 0) {\n while (i.length > 60) {\n i.shift()\n }\n this.stats['_avg_' + key] = i.reduce((a: number, b: number) => a + b, 0) / i.length\n } else if (!key.startsWith('_')) {\n this.stats['_persec_' + key] = i / 3.0\n this.stats[key] = 0\n }\n }\n //this.log('stats', this.stats)\n }\n\n /*= MESSAGES ===============================================================*/\n\n // to be redefined. Called on message (operation) from client\n onMessage(client: ClientType, message: any): void {}\n\n // to be redefined. Called when a client connects\n onConnect(client: ClientType): void {}\n\n // to be redefined. Called when a client disconnects\n onDisconnect(client: ClientType): void {}\n\n _onConnected(client: ClientType): void {\n client.ID = this.getUID()\n client.ping = 0\n client.ctdiff = 0\n client.subscribed = {}\n client.dataChannel = null\n client.peerConnection = null\n\n this.log('client connected', client.ID)\n this.clients.push(client)\n client.on('error', (...args: any[]) => {\n this._onError(client, args)\n })\n client.on('message', (message:any) => {\n let dec = decode(message)\n if (this.simulateLatency) {\n setTimeout(() => {\n this._onMessage(client, dec)\n }, this.simulateLatency)\n } else {\n this._onMessage(client, dec)\n }\n })\n client.on('close', (message:any) => {\n this._onDisconnected(client)\n this.onDisconnect(client)\n })\n this.onConnect(client)\n }\n\n async _onMessage(client: ClientType, message: any): Promise<void> {\n if (\n message.c == 'sync' &&\n this.allowSync &&\n client.subscribed &&\n client.subscribed[message.n] &&\n this.documents[message.n]\n ) {\n let name = message.n\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n for (let op of message.p) {\n if (!this.canSync(client, name, op)) {\n continue\n }\n this._documentChanges[name].push(op)\n let dop = msgop(op)\n applyOperation(this.documents[name], dop)\n }\n } else if (message.c == 'ping') {\n this.send(client, {\n c: 'pong',\n t: Date.now(),\n ct: message.ct,\n ID: client.ID,\n })\n } else if (message.c == 'peng') {\n let time = Date.now()\n let ping = time - message.st\n client.ctdiff = message.ct + ping / 2 - time\n client.ping = ping\n //this.log(time, \"PENG ping, ctdiff\", message, ping, client.ctdiff, \"ms\")\n /*\n } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\n */\n } else if (message.c == 'sub') {\n await this._checkDocument(message.n, client)\n if (!this.documents[message.n]) {\n this.send(client, {\n c: 'error',\n t: Date.now(),\n message: 'Document not found',\n })\n return\n }\n if (client.subscribed) {\n client.subscribed[message.n] = true\n }\n this._sendFullState(message.n, client)\n } else if (message.c == 'unsub') {\n if (client.subscribed) {\n client.subscribed[message.n] = false\n }\n } else {\n this.onMessage(client, message)\n }\n }\n\n _onError(client: ClientType, args: any[]): void {\n this.error('onError:', args)\n }\n\n _onDisconnected(client: ClientType): void {\n if (client.dataChannel) {\n client.dataChannel.close()\n }\n if (client.peerConnection) {\n client.peerConnection.close()\n }\n this.log('client disconnected')\n let index = this.clients.indexOf(client)\n if (index !== -1) {\n this.clients.splice(index, 1)\n }\n }\n\n async send(client: ClientType, message: any): Promise<void> {\n try {\n let t1 = Date.now()\n let data = encode(message)\n let t2 = Date.now()\n let dl = data.byteLength\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n if (data.length > 4096) {\n this.log(`Big message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n } catch (e) {\n this.error('Error sending message:', e, message)\n }\n }\n\n async broadcast(message: object, clients: ClientType[] | false = false): Promise<void> {\n if (!clients) {\n clients = this.clients\n }\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n for (let client of this.clients) {\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n }\n }\n\n async _sendFullState(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n let excluded: any = '_'\n if (this.allowFastPatch) {\n excluded = fastPatchProperties\n }\n let doc = clonewo_(this.documents[name], excluded)\n limitPrecision(doc)\n let fdata: any = false\n if (this.allowFastPatch) {\n fdata = this._encodeFastChanges(name, false)\n }\n let fullState = {\n c: 'full',\n le: LITTLE_ENDIAN,\n t: Date.now(),\n n: name,\n doc: doc,\n fdata: fdata\n }\n this.send(client, fullState)\n }\n\n _encodeFastChanges(name: string, changesOnly = true): any {\n let doc = this.documents[name]\n if (!doc) { return false }\n let origin = this.documents[name].origin\n if (!origin) {\n origin = [0, 0, 0]\n this.documents[name].origin = origin\n }\n\n let entities = doc.entities\n let ids = Object.keys(entities)\n if (!entities) { return false }\n let count: Record<string, number> = {}\n let changed: any = {}\n let hasChanges: any = {}\n let dictionary: any = {}\n let encodedChanges: any = {}\n\n for (let key in fastPatchProperties) {\n if (changesOnly) {\n count[key] = 0\n changed[key] = {}\n hasChanges[key] = false\n } else {\n count[key] = ids.length\n changed[key] = {}\n hasChanges[key] = true\n }\n dictionary[key] = {}\n }\n\n // search for changes\n\n if (changesOnly) {\n for (let id in entities) {\n let e = entities[id]\n for (let key in fastPatchProperties) {\n if (e['__changed_' + key]) {\n changed[''+key][''+id] = true\n count[''+key] = parseInt(''+count[''+key]) + 1\n hasChanges[''+key] = true\n e['__changed_' + key] = false\n }\n }\n }\n } else {\n for (let id in entities) {\n for (let key in fastPatchProperties) {\n changed[''+key][''+id] = true\n }\n }\n }\n\n // create dictionaries\n\n let dictUID = 1\n for (let key in hasChanges) {\n if (hasChanges[key] && dictionaryProperties[key]) {\n for (let id in changed[key]) {\n let e = entities[id]\n let value = e[key]\n if (!dictionary[key][value]) {\n dictionary[key][value] = dictUID++\n }\n }\n }\n }\n\n this.log(\"--------------------------------------------------\")\n //this.log(\"changed\", changed)\n //this.log(\"count\", count)\n\n // create encoded changes\n //\n for (let key in hasChanges) {\n if (hasChanges[key]) {\n let size = parseInt(''+count[''+key])\n let encoded: any = {}\n if (dictionaryProperties[key]) {\n encoded.dict = dictionary[key]\n\n let pdata = new Uint8Array(size * 8)\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n let value = e[key]\n let did = parseInt(dictionary[key][value])\n encode_uint32(did, pdata, offset)\n offset += 4\n }\n encoded.pdata = pdata\n } else {\n\n let pdata: Uint8Array\n if (key == 'position') {\n pdata = new Uint8Array(size * 13)\n } else if (key == 'rotation') {\n pdata = new Uint8Array(size * 16)\n } else if (key == 'scale') {\n pdata = new Uint8Array(size * 16)\n } else {\n pdata = new Uint8Array(0)\n }\n\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n if (key == 'position') {\n encode_fp168(e.position[0] - origin[0], pdata, offset)\n offset += 3\n encode_fp168(e.position[1] - origin[1], pdata, offset)\n offset += 3\n encode_fp168(e.position[2] - origin[2], pdata, offset)\n offset += 3\n } else if (key == 'rotation') {\n encode_fp412(e.rotation[0], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[1], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[2], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[3], pdata, offset)\n offset += 2\n } else if (key == 'scale') {\n encode_fp1616(e.scale[0], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[1], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[2], pdata, offset)\n offset += 4\n }\n }\n encoded.pdata = pdata\n }\n encodedChanges[key] = encoded\n }\n }\n\n return encodedChanges\n }\n\n _sendPatches(): void {\n let now = Date.now()\n\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n this._documentChanges[name] = []\n let sus = this.clients.filter((client) => client.subscribed && client.subscribed[name])\n if (sus.length > 0) {\n if (dc && dc.length > 0) {\n let record = {\n c: 'patch',\n t: now, // server time\n u: this.update,\n n: name,\n doc: dc,\n }\n this.broadcast(record, sus)\n }\n }\n\n if (this.allowFastPatch) {\n if (sus.length > 0) {\n let t1 = Date.now()\n let changes = this._encodeFastChanges(name)\n let t2 = Date.now()\n let record = {\n c: 'fpatch',\n t: now, // server time\n u: this.update,\n n: name,\n fdata: changes\n }\n //this.broadcastRTC(record, sus)\n let t3 = Date.now()\n this.log(`_sendPatches: ${name} encode_changes: ${t2-t1}ms broadcast:${t3-t2}ms`)\n }\n }\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: any, value: any): void {\n this._documentChanges[name]?.push(opmsg(op, target, path, value))\n }\n\n propertyChange(name: string, id: string | number, property: string): void {\n let doc = this.documents[name]\n if (!doc) { return }\n let entities = doc.entities\n if (!entities) { return }\n let e = entities[id]\n if (!e) { return }\n e['__changed_'+property] = true\n //this.log('propertyChange', e)\n }\n\n\n /*= WEBRTC ===================================================================*/\n\n\n async _processOffer(client: ClientType, data: any): Promise<void> {\n //this.log(\"RTC: Offer received\", data);\n const peerConnection = new wrtc.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 client.peerConnection = peerConnection\n\n peerConnection.onicecandidate = (event: any) => {\n if (event.candidate) {\n //this.log(\"RTC: ICE candidate generated\", event.candidate.candidate.substring(0, 50) + \"...\");\n this.send(client, {\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: event.candidate, // .toJSON()\n })\n } else {\n //this.log(\"RTC: ICE candidate gathering complete\");\n }\n }\n\n peerConnection.onconnectionstatechange = () => {\n //this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);\n if (peerConnection.connectionState === 'connected') {\n client.webRTCConnected = true\n this.log(`RTC: Connection established with client ${client.ID}`)\n } else if (\n peerConnection.connectionState === 'failed' ||\n peerConnection.connectionState === 'disconnected' ||\n peerConnection.connectionState === 'closed'\n ) {\n client.webRTCConnected = false\n this.log(`RTC: Connection failed or closed with client ${client.ID}`)\n }\n }\n\n peerConnection.onicegatheringstatechange = () => {\n //this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);\n }\n\n peerConnection.oniceconnectionstatechange = () => {\n //this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);\n if (\n peerConnection.iceConnectionState === 'connected' ||\n peerConnection.iceConnectionState === 'completed'\n ) {\n //this.log(`RTC: ICE connection established with client ${client.ID}`);\n }\n }\n\n try {\n await peerConnection.setRemoteDescription(\n new wrtc.RTCSessionDescription(data)\n )\n //this.log(\"RTC: Remote description set successfully\");\n\n client.dataChannel = peerConnection.createDataChannel('serverchannel', {\n ordered: true,\n maxRetransmits: 1,\n })\n\n client.dataChannel.onopen = () => {\n //this.log(`RTC: Data channel opened for client ${client.ID}`);\n // Try sending a test message\n try {\n const testData = { c: 'test', message: 'Hello WebRTC' }\n this.sendRTC(client, testData)\n } catch (e) {\n this.error(\n `RTC: Error sending test message to client ${client.ID}`,\n e\n )\n }\n }\n\n client.dataChannel.onclose = () => {\n this.log(`RTC: Data channel closed for client ${client.ID}`)\n }\n\n client.dataChannel.onerror = (error: Event) => {\n this.error(`RTC: Data channel error for client ${client.ID}:`, error)\n }\n\n client.dataChannel.onmessage = (event: MessageEvent) => {\n try {\n const data = decode(event.data)\n this.log(\n `RTC: Data channel message from client ${client.ID}:`,\n data\n )\n //this.onMessage(client, data);\n } catch (error) {\n this.error(\n `RTC: Error decoding message from client ${client.ID}:`,\n error\n )\n }\n }\n\n // Create and send answer\n const answer = await peerConnection.createAnswer()\n await peerConnection.setLocalDescription(answer)\n\n //this.log(`RTC: Sending answer to client ${client.ID}`);\n this.send(client, {\n c: 'rtc-answer',\n type: answer.type,\n sdp: answer.sdp,\n })\n } catch (error) {\n this.error(\n `RTC: Error processing offer from client ${client.ID}:`,\n error\n )\n }\n }\n\n async _processICECandidate(client: ClientType, data: any): Promise<void> {\n //this.log(`RTC: Processing ICE candidate from client ${client.ID}`);\n try {\n if (client.peerConnection && data.candidate) {\n await client.peerConnection.addIceCandidate(\n data.candidate\n //new wrtc.RTCIceCandidate(data.candidate)\n )\n //this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);\n } else {\n //this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`);\n }\n } catch (error) {\n this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)\n }\n }\n\n _clientRTCOpen(client: ClientType): boolean {\n return client.dataChannel !== null && client.dataChannel !== undefined && client.dataChannel.readyState === 'open'\n }\n\n async sendRTC(client: ClientType, message: any): Promise<void> {\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n\n let packages = this._splitRTCMessage(data)\n\n if (this.simulateLatency) {\n setTimeout(() => {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }\n }\n\n async broadcastRTC(message: any, clients: ClientType[] = []): Promise<void> {\n if (clients.length == 0) {\n clients = this.clients\n }\n let t1 = Date.now()\n let data = encode(message)\n let dl = data.byteLength\n let t2 = Date.now()\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n\n\n if (data.length > 16384) {\n this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n\n let packages = this._splitRTCMessage(data)\n\n for (let client of this.clients) {\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }\n }\n }\n\n _splitRTCMessage(data: Uint8Array): Uint8Array[] {\n let packages: Uint8Array[]\n if (data.byteLength > 65535) {\n const now = Date.now()\n this.warn(`RTC: Message too large: ${data.byteLength} bytes`)\n // Split the message into smaller packages\n packages = [];\n let offset = 0;\n let mid = this.update +'-'+ now\n let seq = 0\n\n // Create subsequent packages if needed\n while (offset < data.byteLength) {\n const remaining = data.byteLength - offset;\n const chunkSize = Math.min(remaining, MAX_PACKAGE_SIZE);\n const chunk = new Uint8Array(data.buffer, offset, chunkSize);\n let cmessage = {\n c: 'chunk',\n t: now,\n mid: mid,\n seq: seq,\n ofs: offset,\n chs: chunkSize,\n ts: data.byteLength,\n data: chunk,\n last: remaining <= MAX_PACKAGE_SIZE,\n }\n packages.push(encode(cmessage))\n offset += chunkSize;\n seq++;\n }\n\n this.log(`RTC: Large message split into ${packages.length} packages`);\n } else {\n packages = [data]\n this.log(`RTC: Message - ${data.byteLength} bytes`)\n }\n return packages\n }\n\n\n /*= DATABASE =================================================================*/\n // properties (of the documents) that starts with __ are not saved to the database.\n // __properties are restored on hydration. (for example __physicsBody or __bigObject)\n\n getUID(): number {\n this.documents['_server'].nextUID++\n return this.documents['_server'].nextUID\n }\n\n async _initDB(): Promise<void> {\n await this._connectDB()\n await this._loadDocument('_server')\n if (!this.documents['_server']) {\n this._initServerDocument()\n }\n }\n\n async _connectDB(): Promise<void> {\n this.mongoClient = new MongoClient(this.MongoUrl)\n try {\n await this.mongoClient.connect()\n this.log('Connected to MongoDB')\n const db = this.mongoClient.db(this.database)\n this.DB = db\n } catch (error) {\n this.error('Error connecting to MongoDB:', error)\n this.mongoClient = null\n }\n }\n\n async _loadDocument(name: string): Promise<void> {\n this.log(`Loading document '${name}' from MongoDB`)\n if (this.DB) {\n try {\n const doc = await this.DB.collection(this.collection).findOne({\n name: name,\n })\n if (doc) {\n delete (doc as any)._id\n this.documents[name] = doc\n }\n } catch (error) {\n this.error('Error loading document from MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not loaded.')\n }\n }\n\n async _saveDocument(name: string): Promise<void> {\n if (this.DB) {\n try {\n const doc = this.documents[name]\n let newdoc = clonewo_(doc, '__')\n this.log(`Saving document '${name}' to MongoDB`)\n await this.DB.collection(this.collection).updateOne(\n { name: name },\n { $set: newdoc },\n { upsert: true }\n )\n this.log('Document saved to MongoDB')\n } catch (error) {\n this.error('Error saving document to MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not saved.')\n }\n }\n\n async _saveAllDocuments(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this.documents) {\n await this._saveDocument(name)\n }\n }\n\n _initServerDocument(): void {\n this.documents['_server'] = {\n nextUID: 100,\n }\n }\n\n /*= EXIT ===================================================================*/\n\n _exitSignal(signal: string): void {\n if (!this._exited) {\n this.log('\\nEXIT: Caught interrupt signal ' + signal)\n this._exited = true\n clearInterval(this._loopiv)\n this.onBeforeExit()\n this.broadcast({ server: 'Going down' })\n this._saveAllDocuments()\n this._wss!.close()\n setTimeout(() => process.exit(0), 1000)\n }\n }\n\n // To be redefined. Called BEFORE program exit, and saving all documents\n onBeforeExit(): void {}\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","import { promisify } from 'util'\nimport { gzip, gunzip, constants } from 'zlib'\n\nconst MIN_COMPRESSED_BUFFER_SIZE = 256\nconst MAX_COMPRESSED_BUFFER_SIZE = 999999\n\nconst lib_compress = promisify(gzip)\nconst lib_decompress = promisify(gunzip)\n\nexport async function compress(buffer:Uint8Array<ArrayBufferLike>) {\n if (buffer.byteLength <= MIN_COMPRESSED_BUFFER_SIZE || buffer.byteLength >= MAX_COMPRESSED_BUFFER_SIZE) return buffer\n try {\n let t1 = Date.now()\n let cbytes = await lib_compress(buffer, {\n level: constants.Z_BEST_SPEED\n })\n let t2 = Date.now()\n let cbuffer = Buffer.from(cbytes)\n let t3 = Date.now()\n\n //console.log(`Node compression ${buffer.byteLength} -> ${cbuffer.byteLength}, time: ${t2 - t1}ms`)\n\n return cbuffer\n } catch (error) {\n console.error('Error compressing buffer:', error)\n return buffer\n }\n}\n\nexport async function decompress(buffer:Uint8Array<ArrayBufferLike>) {\n try {\n let cbytes = await lib_decompress(buffer)\n let cbuffer = Buffer.from(cbytes)\n return cbuffer\n } catch (error) {\n console.error('Error decompressing buffer:', error)\n return buffer\n }\n}\n"],"mappings":"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","names":["import_msgpackr","fastjsonpatch","key","data"]}
1
+ {"version":3,"sources":["../src/server.ts","../src/utils.ts","../src/compress-node.ts"],"sourcesContent":["import * as https from 'node:https'\nimport * as fs from 'node:fs'\nimport {\n reactive,\n deepGet,\n clonewo_,\n opmsg,\n msgop,\n encode_uint32,\n encode_fp412,\n encode_fp168,\n encode_fp1616,\n limitPrecision,\n encode,\n decode\n} from './utils'\nimport { compress, decompress } from './compress-node'\nimport fastjsonpatch from 'fast-json-patch'\nimport { WebSocketServer, WebSocket } from 'ws'\nimport { MongoClient, Db } from 'mongodb'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\nimport wrtc from '@roamhq/wrtc' // Server-side WebRTC implementation\n\nglMatrix.setMatrixArrayType(Array)\n\n// entities/ID/\nconst fastPatchProperties: Record<string, boolean> = {\n 'type': true, // string 'enemy'\n 'status': true, // string 'idle'\n 'level': true, // number 2\n 'race': true, // string 'goblin'\n 'class': true, // string 'warrior'\n 'model': true, // string 'models/models.glb|goblin'\n 'animation': true, // string 'idle2'\n 'sound': true, // string 'sound/goblin.snd|snarl'\n 'effect': true, // 'selected'\n 'position': true, // [0, 0, 0] Vector (Number)\n 'rotation': true, // [0, 0, 0, 1] Quaternion (Number)\n 'scale': true, // [1, 1, 1] Vector (Number)\n}\n\nconst dictionaryProperties: Record<string, boolean> = {\n 'type': true,\n 'status': true,\n 'level': true,\n 'race': true,\n 'class': true,\n 'model': true,\n 'animation': true,\n 'sound': true,\n 'effect': true,\n}\n\nconst { applyOperation } = fastjsonpatch\nconst LITTLE_ENDIAN = (() => {\n const buffer = new ArrayBuffer(2)\n new DataView(buffer).setInt16(0, 256, true)\n return new Int16Array(buffer)[0] === 256\n})()\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\n\ntype ClientType = any\n\ninterface StatsType {\n tUpdate: number[]\n tPatch: number[]\n send: number\n sendRTC: number\n _sendRTCUpdate: number\n [key: string]: any\n}\n\nexport default class TopazCubeServer {\n name = 'TopazCubeServer'\n cycle = 100\n patchCycleDivider = 1\n port = 8799\n useHttps = false\n key = './cert/key.pem'\n cert = './cert/cert.pem'\n MongoUrl = 'mongodb://localhost:27017'\n mongoClient: MongoClient | null = null\n DB: Db | null = null\n database = 'topazcube'\n collection = 'documents'\n allowSave = true\n allowSync = true\n allowWebRTC = false\n allowFastPatch = false\n allowCompression = false\n simulateLatency = 0\n\n _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _loopiv: any = null\n _statsiv: any = null\n _stillUpdating = false\n stats: StatsType = {\n tUpdate: [],\n tPatch: [],\n send: 0,\n sendRTC: 0,\n _sendRTCUpdate: 0\n }\n\n _wss: WebSocketServer | null = null\n _exited = false\n\n log(...args: any[]) {\n console.log(this.name + ':', ...args);\n }\n\n warn(...args: any[]) {\n console.warn(this.name + ':', ...args);\n }\n\n error(...args: any[]) {\n console.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n port = 8799,\n useHttps = false,\n key = './cert/key.pem',\n cert = './cert/cert.pem',\n MongoUrl = 'mongodb://localhost:27017',\n database = 'topazcube',\n collection = 'documents',\n allowSave = true,\n allowSync = true,\n allowWebRTC = false,\n allowFastPatch = false,\n allowCompression = false,\n simulateLatency = 0,\n }: {\n name?: string\n cycle?: number\n port?: number\n useHttps?: boolean\n key?: string\n cert?: string\n MongoUrl?: string\n database?: string\n collection?: string\n allowSave?: boolean\n allowSync?: boolean\n allowWebRTC?: boolean\n allowFastPatch?: boolean\n allowCompression?: boolean\n simulateLatency?: number\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.port = port\n this.useHttps = useHttps\n this.key = key\n this.cert = cert\n this.MongoUrl = MongoUrl\n this.database = database\n this.collection = collection\n this.allowSave = allowSave\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.allowFastPatch = allowFastPatch\n this.allowCompression = allowCompression\n this.simulateLatency = simulateLatency\n\n this._initDB()\n\n if (useHttps) {\n let httpsServer: https.Server | null = https.createServer({\n key: fs.readFileSync(this.key),\n cert: fs.readFileSync(this.cert),\n }, (req, res) => {\n res.writeHead(200)\n res.end('<b>Hello World!</b>')\n }).listen(this.port)\n this._wss = new WebSocketServer({ server: httpsServer })\n httpsServer = null\n this.log(this.name + ' running on HTTPS port ' + this.port)\n } else {\n this._wss = new WebSocketServer({ port: this.port })\n this.log(this.name + ' running on port ' + this.port)\n }\n this._wss.on('connection', (client: WebSocket) => {\n this._onConnected(client)\n })\n\n process.stdin.resume()\n process.on('SIGINT', () => {\n this._exitSignal('SIGINT')\n })\n process.on('SIGQUIT', () => {\n this._exitSignal('SIGQUIT')\n })\n process.on('SIGTERM', () => {\n this._exitSignal('SIGTERM')\n })\n process.on('SIGUSR2', () => {\n this._exitSignal('SIGUSR2')\n })\n\n // Setup keypress handling for console input\n process.stdin.resume()\n process.stdin.setEncoding('utf8')\n\n process.stdin.on('data', (key: any) => {\n key = (''+key).trim()\n\n // ctrl-c ( end of text )\n if (key == '\\u0003') {\n this._exitSignal('SIGINT')\n return\n }\n\n // Process other keypresses\n this.log(`Key pressed: ${key}`)\n\n // Example: 's' to save all documents\n if (key == 's') {\n this.log('Saving all documents...')\n this._saveAllDocuments()\n }\n\n // Example: 'i' to print server info\n if (key == 'i') {\n this.log(\n `Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`\n )\n }\n })\n this._startLoop()\n }\n\n /*= DOCUMENTS ==============================================================*/\n\n // to be redefined. Called before a new document is created. Returns true if\n // the client has the right to create an empty document\n canCreate(client: ClientType, name: string): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is created\n // (returns an empty document)\n onCreate(name: string): any {\n return {\n data: {},\n }\n }\n\n // to be redefined. Called when a client wants to sync (modify) a document.\n // Returns true if the client has the right to sync that operation.\n canSync(client: ClientType, name: string, op: any): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is hydrated\n // (created, or loaded from db)\n async onHydrate(name: string, document: any): Promise<void> {\n document.__hydrated = true\n }\n\n _makeReactive(name: string): void {\n //this.log(`Making document '${name}' reactive`, this.documents[name])\n let ep: any = false\n if (this.allowFastPatch) {\n ep = fastPatchProperties\n }\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this),\n '',\n ep\n )\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n }\n\n _createEmptyDocument(name: string): void {\n let doc = this.onCreate(name)\n if (!doc) {\n return\n }\n this.documents[name] = doc\n }\n\n async _waitLoad(name: string): Promise<void> {\n if (this.isLoading[name]) {\n while (this.isLoading[name]) {\n await new Promise((resolve) => setTimeout(resolve, 50))\n }\n }\n }\n\n async _checkDocument(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n if (!this.documents[name]) {\n this.isLoading[name] = true\n await this._loadDocument(name)\n if (!this.documents[name] && this.canCreate(client, name)) {\n this._createEmptyDocument(name)\n }\n if (this.documents[name]) {\n this._makeReactive(name)\n this.onHydrate(name, this.documents[name])\n }\n this.isLoading[name] = false\n this._documentState[name] = {\n subscibers: 0,\n lastModified: Date.now(),\n }\n }\n }\n\n _updateAllDocumentsState(): void {\n for (let name in this.documents) {\n if (name != '_server') {\n let doc = this.documents[name]\n this._documentState[name].subscibers = 0\n for (let client of this.clients) {\n if (client.subscribed && client.subscribed[name]) {\n this._documentState[name].subscibers++\n }\n }\n }\n }\n }\n\n /*= UPDATE LOOP ============================================================*/\n\n // to be redefined. called every this.cycle ms\n onUpdate(name: string, doc: any, dt: number): void {}\n\n _startLoop(): void {\n this.lastUpdate = Date.now()\n this._loop()\n this._statsiv = setInterval(() => {\n this._doStats()\n }, 1000)\n }\n\n _loop(): void {\n let now = Date.now()\n let dtms = (now - this.lastUpdate)\n let dt = dtms / 1000.0 // Convert to seconds\n this.lastUpdate = now\n\n /*\n if (this._stillUpdating) {\n return\n }\n */\n this._stillUpdating = true\n for (let name in this.documents) {\n this.onUpdate(name, this.documents[name], dt)\n }\n let t1 = Date.now()\n this._stillUpdating = false\n let updateTime = t1 - now\n this.stats.tUpdate.push(updateTime)\n\n //this.log(`update ${this.update} patch: ${this.update % this.patchCycleDivider}`, )\n\n let patchTime = 0\n if (this.update % this.patchCycleDivider == 0) {\n this._sendPatches()\n let t2 = Date.now()\n patchTime = t2 - t1\n this.stats.tPatch.push(patchTime)\n if (this.allowFastPatch) {\n this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`, )\n }\n this.stats._sendRTCUpdate = 0\n }\n\n this.update++\n let endUpdate = Date.now()\n let totalUpdate = endUpdate - now\n\n setTimeout(() => {\n this._loop()\n }, Math.max(this.cycle - totalUpdate, 10))\n }\n\n _doStats(): void {\n for (let key in this.stats) {\n let i = this.stats[key]\n if (Array.isArray(i) && i.length > 0) {\n while (i.length > 60) {\n i.shift()\n }\n this.stats['_avg_' + key] = i.reduce((a: number, b: number) => a + b, 0) / i.length\n } else if (!key.startsWith('_')) {\n this.stats['_persec_' + key] = i / 3.0\n this.stats[key] = 0\n }\n }\n //this.log('stats', this.stats)\n }\n\n /*= MESSAGES ===============================================================*/\n\n // to be redefined. Called on message (operation) from client\n onMessage(client: ClientType, message: any): void {}\n\n // to be redefined. Called when a client connects\n onConnect(client: ClientType): void {}\n\n // to be redefined. Called when a client disconnects\n onDisconnect(client: ClientType): void {}\n\n _onConnected(client: ClientType): void {\n client.ID = this.getUID()\n client.ping = 0\n client.ctdiff = 0\n client.subscribed = {}\n client.dataChannel = null\n client.peerConnection = null\n\n this.log('client connected', client.ID)\n this.clients.push(client)\n client.on('error', (...args: any[]) => {\n this._onError(client, args)\n })\n client.on('message', (message:any) => {\n let dec = decode(message)\n if (this.simulateLatency) {\n setTimeout(() => {\n this._onMessage(client, dec)\n }, this.simulateLatency)\n } else {\n this._onMessage(client, dec)\n }\n })\n client.on('close', (message:any) => {\n this._onDisconnected(client)\n this.onDisconnect(client)\n })\n this.onConnect(client)\n }\n\n async _onMessage(client: ClientType, message: any): Promise<void> {\n if (\n message.c == 'sync' &&\n this.allowSync &&\n client.subscribed &&\n client.subscribed[message.n] &&\n this.documents[message.n]\n ) {\n let name = message.n\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n for (let op of message.p) {\n if (!this.canSync(client, name, op)) {\n continue\n }\n this._documentChanges[name].push(op)\n let dop = msgop(op)\n applyOperation(this.documents[name], dop)\n }\n } else if (message.c == 'ping') {\n this.send(client, {\n c: 'pong',\n t: Date.now(),\n ct: message.ct,\n ID: client.ID,\n })\n } else if (message.c == 'peng') {\n let time = Date.now()\n let ping = time - message.st\n client.ctdiff = message.ct + ping / 2 - time\n client.ping = ping\n //this.log(time, \"PENG ping, ctdiff\", message, ping, client.ctdiff, \"ms\")\n /*\n } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\n */\n } else if (message.c == 'sub') {\n await this._checkDocument(message.n, client)\n if (!this.documents[message.n]) {\n this.send(client, {\n c: 'error',\n t: Date.now(),\n message: 'Document not found',\n })\n return\n }\n if (client.subscribed) {\n client.subscribed[message.n] = true\n }\n this._sendFullState(message.n, client)\n } else if (message.c == 'unsub') {\n if (client.subscribed) {\n client.subscribed[message.n] = false\n }\n } else {\n this.onMessage(client, message)\n }\n }\n\n _onError(client: ClientType, args: any[]): void {\n this.error('onError:', args)\n }\n\n _onDisconnected(client: ClientType): void {\n if (client.dataChannel) {\n client.dataChannel.close()\n }\n if (client.peerConnection) {\n client.peerConnection.close()\n }\n this.log('client disconnected')\n let index = this.clients.indexOf(client)\n if (index !== -1) {\n this.clients.splice(index, 1)\n }\n }\n\n async send(client: ClientType, message: any): Promise<void> {\n try {\n let t1 = Date.now()\n let data = encode(message)\n let t2 = Date.now()\n let dl = data.byteLength\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n if (data.length > 4096) {\n this.log(`Big message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n } catch (e) {\n this.error('Error sending message:', e, message)\n }\n }\n\n async broadcast(message: object, clients: ClientType[] | false = false): Promise<void> {\n if (!clients) {\n clients = this.clients\n }\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n for (let client of this.clients) {\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n }\n }\n\n async _sendFullState(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n let excluded: any = '_'\n if (this.allowFastPatch) {\n excluded = fastPatchProperties\n }\n let doc = clonewo_(this.documents[name], excluded)\n limitPrecision(doc)\n let fdata: any = false\n if (this.allowFastPatch) {\n fdata = this._encodeFastChanges(name, false)\n }\n let fullState = {\n c: 'full',\n le: LITTLE_ENDIAN,\n t: Date.now(),\n n: name,\n doc: doc,\n fdata: fdata\n }\n this.send(client, fullState)\n }\n\n _encodeFastChanges(name: string, changesOnly = true): any {\n let doc = this.documents[name]\n if (!doc) { return false }\n let origin = this.documents[name].origin\n if (!origin) {\n origin = [0, 0, 0]\n this.documents[name].origin = origin\n }\n\n let entities = doc.entities\n let ids = Object.keys(entities)\n if (!entities) { return false }\n let count: Record<string, number> = {}\n let changed: any = {}\n let hasChanges: any = {}\n let dictionary: any = {}\n let encodedChanges: any = {}\n\n for (let key in fastPatchProperties) {\n if (changesOnly) {\n count[key] = 0\n changed[key] = {}\n hasChanges[key] = false\n } else {\n count[key] = ids.length\n changed[key] = {}\n hasChanges[key] = true\n }\n dictionary[key] = {}\n }\n\n // search for changes\n\n if (changesOnly) {\n for (let id in entities) {\n let e = entities[id]\n for (let key in fastPatchProperties) {\n if (e['__changed_' + key]) {\n changed[''+key][''+id] = true\n count[''+key] = parseInt(''+count[''+key]) + 1\n hasChanges[''+key] = true\n e['__changed_' + key] = false\n }\n }\n }\n } else {\n for (let id in entities) {\n for (let key in fastPatchProperties) {\n changed[''+key][''+id] = true\n }\n }\n }\n\n // create dictionaries\n\n let dictUID = 1\n for (let key in hasChanges) {\n if (hasChanges[key] && dictionaryProperties[key]) {\n for (let id in changed[key]) {\n let e = entities[id]\n let value = e[key]\n if (!dictionary[key][value]) {\n dictionary[key][value] = dictUID++\n }\n }\n }\n }\n\n this.log(\"--------------------------------------------------\")\n //this.log(\"changed\", changed)\n //this.log(\"count\", count)\n\n // create encoded changes\n //\n for (let key in hasChanges) {\n if (hasChanges[key]) {\n let size = parseInt(''+count[''+key])\n let encoded: any = {}\n if (dictionaryProperties[key]) {\n encoded.dict = dictionary[key]\n\n let pdata = new Uint8Array(size * 8)\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n let value = e[key]\n let did = parseInt(dictionary[key][value])\n encode_uint32(did, pdata, offset)\n offset += 4\n }\n encoded.pdata = pdata\n } else {\n\n let pdata: Uint8Array\n if (key == 'position') {\n pdata = new Uint8Array(size * 13)\n } else if (key == 'rotation') {\n pdata = new Uint8Array(size * 16)\n } else if (key == 'scale') {\n pdata = new Uint8Array(size * 16)\n } else {\n pdata = new Uint8Array(0)\n }\n\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n if (key == 'position') {\n encode_fp168(e.position[0] - origin[0], pdata, offset)\n offset += 3\n encode_fp168(e.position[1] - origin[1], pdata, offset)\n offset += 3\n encode_fp168(e.position[2] - origin[2], pdata, offset)\n offset += 3\n } else if (key == 'rotation') {\n encode_fp412(e.rotation[0], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[1], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[2], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[3], pdata, offset)\n offset += 2\n } else if (key == 'scale') {\n encode_fp1616(e.scale[0], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[1], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[2], pdata, offset)\n offset += 4\n }\n }\n encoded.pdata = pdata\n }\n encodedChanges[key] = encoded\n }\n }\n\n return encodedChanges\n }\n\n _sendPatches(): void {\n let now = Date.now()\n\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n this._documentChanges[name] = []\n let sus = this.clients.filter((client) => client.subscribed && client.subscribed[name])\n if (sus.length > 0) {\n if (dc && dc.length > 0) {\n let record = {\n c: 'patch',\n t: now, // server time\n u: this.update,\n n: name,\n doc: dc,\n }\n this.broadcast(record, sus)\n }\n }\n\n if (this.allowFastPatch) {\n if (sus.length > 0) {\n let t1 = Date.now()\n let changes = this._encodeFastChanges(name)\n let t2 = Date.now()\n let record = {\n c: 'fpatch',\n t: now, // server time\n u: this.update,\n n: name,\n fdata: changes\n }\n //this.broadcastRTC(record, sus)\n let t3 = Date.now()\n this.log(`_sendPatches: ${name} encode_changes: ${t2-t1}ms broadcast:${t3-t2}ms`)\n }\n }\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: any, value: any): void {\n this._documentChanges[name]?.push(opmsg(op, target, path, value))\n }\n\n propertyChange(name: string, id: string | number, property: string): void {\n let doc = this.documents[name]\n if (!doc) { return }\n let entities = doc.entities\n if (!entities) { return }\n let e = entities[id]\n if (!e) { return }\n e['__changed_'+property] = true\n //this.log('propertyChange', e)\n }\n\n\n /*= WEBRTC ===================================================================*/\n\n\n async _processOffer(client: ClientType, data: any): Promise<void> {\n //this.log(\"RTC: Offer received\", data);\n const peerConnection = new (wrtc as any).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 client.peerConnection = peerConnection\n\n peerConnection.onicecandidate = (event: any) => {\n if (event.candidate) {\n //this.log(\"RTC: ICE candidate generated\", event.candidate.candidate.substring(0, 50) + \"...\");\n this.send(client, {\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: event.candidate, // .toJSON()\n })\n } else {\n //this.log(\"RTC: ICE candidate gathering complete\");\n }\n }\n\n peerConnection.onconnectionstatechange = () => {\n //this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);\n if (peerConnection.connectionState === 'connected') {\n client.webRTCConnected = true\n this.log(`RTC: Connection established with client ${client.ID}`)\n } else if (\n peerConnection.connectionState === 'failed' ||\n peerConnection.connectionState === 'disconnected' ||\n peerConnection.connectionState === 'closed'\n ) {\n client.webRTCConnected = false\n this.log(`RTC: Connection failed or closed with client ${client.ID}`)\n }\n }\n\n peerConnection.onicegatheringstatechange = () => {\n //this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);\n }\n\n peerConnection.oniceconnectionstatechange = () => {\n //this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);\n if (\n peerConnection.iceConnectionState === 'connected' ||\n peerConnection.iceConnectionState === 'completed'\n ) {\n //this.log(`RTC: ICE connection established with client ${client.ID}`);\n }\n }\n\n try {\n await peerConnection.setRemoteDescription(\n new (wrtc as any).RTCSessionDescription(data)\n )\n //this.log(\"RTC: Remote description set successfully\");\n\n client.dataChannel = peerConnection.createDataChannel('serverchannel', {\n ordered: true,\n maxRetransmits: 1,\n })\n\n client.dataChannel.onopen = () => {\n //this.log(`RTC: Data channel opened for client ${client.ID}`);\n // Try sending a test message\n try {\n const testData = { c: 'test', message: 'Hello WebRTC' }\n this.sendRTC(client, testData)\n } catch (e) {\n this.error(\n `RTC: Error sending test message to client ${client.ID}`,\n e\n )\n }\n }\n\n client.dataChannel.onclose = () => {\n this.log(`RTC: Data channel closed for client ${client.ID}`)\n }\n\n client.dataChannel.onerror = (error: Event) => {\n this.error(`RTC: Data channel error for client ${client.ID}:`, error)\n }\n\n client.dataChannel.onmessage = (event: MessageEvent) => {\n try {\n const data = decode(event.data)\n this.log(\n `RTC: Data channel message from client ${client.ID}:`,\n data\n )\n //this.onMessage(client, data);\n } catch (error) {\n this.error(\n `RTC: Error decoding message from client ${client.ID}:`,\n error\n )\n }\n }\n\n // Create and send answer\n const answer = await peerConnection.createAnswer()\n await peerConnection.setLocalDescription(answer)\n\n //this.log(`RTC: Sending answer to client ${client.ID}`);\n this.send(client, {\n c: 'rtc-answer',\n type: answer.type,\n sdp: answer.sdp,\n })\n } catch (error) {\n this.error(\n `RTC: Error processing offer from client ${client.ID}:`,\n error\n )\n }\n }\n\n async _processICECandidate(client: ClientType, data: any): Promise<void> {\n //this.log(`RTC: Processing ICE candidate from client ${client.ID}`);\n try {\n if (client.peerConnection && data.candidate) {\n await client.peerConnection.addIceCandidate(\n data.candidate\n //new wrtc.RTCIceCandidate(data.candidate)\n )\n //this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);\n } else {\n //this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`);\n }\n } catch (error) {\n this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)\n }\n }\n\n _clientRTCOpen(client: ClientType): boolean {\n return client.dataChannel !== null && client.dataChannel !== undefined && client.dataChannel.readyState === 'open'\n }\n\n async sendRTC(client: ClientType, message: any): Promise<void> {\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n\n let packages = this._splitRTCMessage(data)\n\n if (this.simulateLatency) {\n setTimeout(() => {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }\n }\n\n async broadcastRTC(message: any, clients: ClientType[] = []): Promise<void> {\n if (clients.length == 0) {\n clients = this.clients\n }\n let t1 = Date.now()\n let data = encode(message)\n let dl = data.byteLength\n let t2 = Date.now()\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n\n\n if (data.length > 16384) {\n this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n\n let packages = this._splitRTCMessage(data)\n\n for (let client of this.clients) {\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }\n }\n }\n\n _splitRTCMessage(data: Uint8Array): Uint8Array[] {\n let packages: Uint8Array[]\n if (data.byteLength > 65535) {\n const now = Date.now()\n this.warn(`RTC: Message too large: ${data.byteLength} bytes`)\n // Split the message into smaller packages\n packages = [];\n let offset = 0;\n let mid = this.update +'-'+ now\n let seq = 0\n\n // Create subsequent packages if needed\n while (offset < data.byteLength) {\n const remaining = data.byteLength - offset;\n const chunkSize = Math.min(remaining, MAX_PACKAGE_SIZE);\n const chunk = new Uint8Array(data.buffer, offset, chunkSize);\n let cmessage = {\n c: 'chunk',\n t: now,\n mid: mid,\n seq: seq,\n ofs: offset,\n chs: chunkSize,\n ts: data.byteLength,\n data: chunk,\n last: remaining <= MAX_PACKAGE_SIZE,\n }\n packages.push(encode(cmessage))\n offset += chunkSize;\n seq++;\n }\n\n this.log(`RTC: Large message split into ${packages.length} packages`);\n } else {\n packages = [data]\n this.log(`RTC: Message - ${data.byteLength} bytes`)\n }\n return packages\n }\n\n\n /*= DATABASE =================================================================*/\n // properties (of the documents) that starts with __ are not saved to the database.\n // __properties are restored on hydration. (for example __physicsBody or __bigObject)\n\n getUID(): number {\n this.documents['_server'].nextUID++\n return this.documents['_server'].nextUID\n }\n\n async _initDB(): Promise<void> {\n await this._connectDB()\n await this._loadDocument('_server')\n if (!this.documents['_server']) {\n this._initServerDocument()\n }\n }\n\n async _connectDB(): Promise<void> {\n this.mongoClient = new MongoClient(this.MongoUrl)\n try {\n await this.mongoClient.connect()\n this.log('Connected to MongoDB')\n const db = this.mongoClient.db(this.database)\n this.DB = db\n } catch (error) {\n this.error('Error connecting to MongoDB:', error)\n this.mongoClient = null\n }\n }\n\n async _loadDocument(name: string): Promise<void> {\n this.log(`Loading document '${name}' from MongoDB`)\n if (this.DB) {\n try {\n const doc = await this.DB.collection(this.collection).findOne({\n name: name,\n })\n if (doc) {\n delete (doc as any)._id\n this.documents[name] = doc\n }\n } catch (error) {\n this.error('Error loading document from MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not loaded.')\n }\n }\n\n async _saveDocument(name: string): Promise<void> {\n if (this.DB) {\n try {\n const doc = this.documents[name]\n let newdoc = clonewo_(doc, '__')\n this.log(`Saving document '${name}' to MongoDB`)\n await this.DB.collection(this.collection).updateOne(\n { name: name },\n { $set: newdoc },\n { upsert: true }\n )\n this.log('Document saved to MongoDB')\n } catch (error) {\n this.error('Error saving document to MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not saved.')\n }\n }\n\n async _saveAllDocuments(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this.documents) {\n await this._saveDocument(name)\n }\n }\n\n _initServerDocument(): void {\n this.documents['_server'] = {\n nextUID: 100,\n }\n }\n\n /*= EXIT ===================================================================*/\n\n _exitSignal(signal: string): void {\n if (!this._exited) {\n this.log('\\nEXIT: Caught interrupt signal ' + signal)\n this._exited = true\n clearInterval(this._loopiv)\n this.onBeforeExit()\n this.broadcast({ server: 'Going down' })\n this._saveAllDocuments()\n this._wss!.close()\n setTimeout(() => process.exit(0), 1000)\n }\n }\n\n // To be redefined. Called BEFORE program exit, and saving all documents\n onBeforeExit(): void {}\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","import { promisify } from 'util'\nimport { gzip, gunzip, constants } from 'zlib'\n\nconst MIN_COMPRESSED_BUFFER_SIZE = 256\nconst MAX_COMPRESSED_BUFFER_SIZE = 999999\n\nconst lib_compress = promisify(gzip)\nconst lib_decompress = promisify(gunzip)\n\nexport async function compress(buffer:Uint8Array<ArrayBufferLike>) {\n if (buffer.byteLength <= MIN_COMPRESSED_BUFFER_SIZE || buffer.byteLength >= MAX_COMPRESSED_BUFFER_SIZE) return buffer\n try {\n let t1 = Date.now()\n let cbytes = await lib_compress(buffer, {\n level: constants.Z_BEST_SPEED\n })\n let t2 = Date.now()\n let cbuffer = Buffer.from(cbytes)\n let t3 = Date.now()\n\n //console.log(`Node compression ${buffer.byteLength} -> ${cbuffer.byteLength}, time: ${t2 - t1}ms`)\n\n return cbuffer\n } catch (error) {\n console.error('Error compressing buffer:', error)\n return buffer\n }\n}\n\nexport async function decompress(buffer:Uint8Array<ArrayBufferLike>) {\n try {\n let cbytes = await lib_decompress(buffer)\n let cbuffer = Buffer.from(cbytes)\n return cbuffer\n } catch (error) {\n console.error('Error decompressing buffer:', error)\n return buffer\n }\n}\n"],"mappings":"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","names":["import_msgpackr","fastjsonpatch","key","wrtc","data"]}
package/dist/server.js CHANGED
@@ -1,10 +1,3 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
1
  // src/server.ts
9
2
  import * as https from "https";
10
3
  import * as fs from "fs";
@@ -254,8 +247,8 @@ import fastjsonpatch from "fast-json-patch";
254
247
  import { WebSocketServer } from "ws";
255
248
  import { MongoClient } from "mongodb";
256
249
  import { glMatrix } from "gl-matrix";
250
+ import wrtc from "@roamhq/wrtc";
257
251
  glMatrix.setMatrixArrayType(Array);
258
- var wrtc = __require("@roamhq/wrtc");
259
252
  var fastPatchProperties = {
260
253
  "type": true,
261
254
  // string 'enemy'
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/utils.ts","../src/compress-node.ts"],"sourcesContent":["import * as https from 'node:https'\nimport * as fs from 'node:fs'\nimport {\n reactive,\n deepGet,\n clonewo_,\n opmsg,\n msgop,\n encode_uint32,\n encode_fp412,\n encode_fp168,\n encode_fp1616,\n limitPrecision,\n encode,\n decode\n} from './utils'\nimport { compress, decompress } from './compress-node'\nimport fastjsonpatch from 'fast-json-patch'\nimport { WebSocketServer, WebSocket } from 'ws'\nimport { MongoClient, Db } from 'mongodb'\nimport { doesNotThrow } from 'assert'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\nglMatrix.setMatrixArrayType(Array)\nconst wrtc = require('@roamhq/wrtc') // Server-side WebRTC implementation\n\n// entities/ID/\nconst fastPatchProperties: Record<string, boolean> = {\n 'type': true, // string 'enemy'\n 'status': true, // string 'idle'\n 'level': true, // number 2\n 'race': true, // string 'goblin'\n 'class': true, // string 'warrior'\n 'model': true, // string 'models/models.glb|goblin'\n 'animation': true, // string 'idle2'\n 'sound': true, // string 'sound/goblin.snd|snarl'\n 'effect': true, // 'selected'\n 'position': true, // [0, 0, 0] Vector (Number)\n 'rotation': true, // [0, 0, 0, 1] Quaternion (Number)\n 'scale': true, // [1, 1, 1] Vector (Number)\n}\n\nconst dictionaryProperties: Record<string, boolean> = {\n 'type': true,\n 'status': true,\n 'level': true,\n 'race': true,\n 'class': true,\n 'model': true,\n 'animation': true,\n 'sound': true,\n 'effect': true,\n}\n\nconst { applyOperation } = fastjsonpatch\nconst LITTLE_ENDIAN = (() => {\n const buffer = new ArrayBuffer(2)\n new DataView(buffer).setInt16(0, 256, true)\n return new Int16Array(buffer)[0] === 256\n})()\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\n\ntype ClientType = any\n\ninterface StatsType {\n tUpdate: number[]\n tPatch: number[]\n send: number\n sendRTC: number\n _sendRTCUpdate: number\n [key: string]: any\n}\n\nexport default class TopazCubeServer {\n name = 'TopazCubeServer'\n cycle = 100\n patchCycleDivider = 1\n port = 8799\n useHttps = false\n key = './cert/key.pem'\n cert = './cert/cert.pem'\n MongoUrl = 'mongodb://localhost:27017'\n mongoClient: MongoClient | null = null\n DB: Db | null = null\n database = 'topazcube'\n collection = 'documents'\n allowSave = true\n allowSync = true\n allowWebRTC = false\n allowFastPatch = false\n allowCompression = false\n simulateLatency = 0\n\n _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _loopiv: any = null\n _statsiv: any = null\n _stillUpdating = false\n stats: StatsType = {\n tUpdate: [],\n tPatch: [],\n send: 0,\n sendRTC: 0,\n _sendRTCUpdate: 0\n }\n\n _wss: WebSocketServer | null = null\n _exited = false\n\n log(...args: any[]) {\n console.log(this.name + ':', ...args);\n }\n\n warn(...args: any[]) {\n console.warn(this.name + ':', ...args);\n }\n\n error(...args: any[]) {\n console.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n port = 8799,\n useHttps = false,\n key = './cert/key.pem',\n cert = './cert/cert.pem',\n MongoUrl = 'mongodb://localhost:27017',\n database = 'topazcube',\n collection = 'documents',\n allowSave = true,\n allowSync = true,\n allowWebRTC = false,\n allowFastPatch = false,\n allowCompression = false,\n simulateLatency = 0,\n }: {\n name?: string\n cycle?: number\n port?: number\n useHttps?: boolean\n key?: string\n cert?: string\n MongoUrl?: string\n database?: string\n collection?: string\n allowSave?: boolean\n allowSync?: boolean\n allowWebRTC?: boolean\n allowFastPatch?: boolean\n allowCompression?: boolean\n simulateLatency?: number\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.port = port\n this.useHttps = useHttps\n this.key = key\n this.cert = cert\n this.MongoUrl = MongoUrl\n this.database = database\n this.collection = collection\n this.allowSave = allowSave\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.allowFastPatch = allowFastPatch\n this.allowCompression = allowCompression\n this.simulateLatency = simulateLatency\n\n this._initDB()\n\n if (useHttps) {\n let httpsServer: https.Server | null = https.createServer({\n key: fs.readFileSync(this.key),\n cert: fs.readFileSync(this.cert),\n }, (req, res) => {\n res.writeHead(200)\n res.end('<b>Hello World!</b>')\n }).listen(this.port)\n this._wss = new WebSocketServer({ server: httpsServer })\n httpsServer = null\n this.log(this.name + ' running on HTTPS port ' + this.port)\n } else {\n this._wss = new WebSocketServer({ port: this.port })\n this.log(this.name + ' running on port ' + this.port)\n }\n this._wss.on('connection', (client: WebSocket) => {\n this._onConnected(client)\n })\n\n process.stdin.resume()\n process.on('SIGINT', () => {\n this._exitSignal('SIGINT')\n })\n process.on('SIGQUIT', () => {\n this._exitSignal('SIGQUIT')\n })\n process.on('SIGTERM', () => {\n this._exitSignal('SIGTERM')\n })\n process.on('SIGUSR2', () => {\n this._exitSignal('SIGUSR2')\n })\n\n // Setup keypress handling for console input\n process.stdin.resume()\n process.stdin.setEncoding('utf8')\n\n process.stdin.on('data', (key: any) => {\n key = (''+key).trim()\n\n // ctrl-c ( end of text )\n if (key == '\\u0003') {\n this._exitSignal('SIGINT')\n return\n }\n\n // Process other keypresses\n this.log(`Key pressed: ${key}`)\n\n // Example: 's' to save all documents\n if (key == 's') {\n this.log('Saving all documents...')\n this._saveAllDocuments()\n }\n\n // Example: 'i' to print server info\n if (key == 'i') {\n this.log(\n `Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`\n )\n }\n })\n this._startLoop()\n }\n\n /*= DOCUMENTS ==============================================================*/\n\n // to be redefined. Called before a new document is created. Returns true if\n // the client has the right to create an empty document\n canCreate(client: ClientType, name: string): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is created\n // (returns an empty document)\n onCreate(name: string): any {\n return {\n data: {},\n }\n }\n\n // to be redefined. Called when a client wants to sync (modify) a document.\n // Returns true if the client has the right to sync that operation.\n canSync(client: ClientType, name: string, op: any): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is hydrated\n // (created, or loaded from db)\n async onHydrate(name: string, document: any): Promise<void> {\n document.__hydrated = true\n }\n\n _makeReactive(name: string): void {\n //this.log(`Making document '${name}' reactive`, this.documents[name])\n let ep: any = false\n if (this.allowFastPatch) {\n ep = fastPatchProperties\n }\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this),\n '',\n ep\n )\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n }\n\n _createEmptyDocument(name: string): void {\n let doc = this.onCreate(name)\n if (!doc) {\n return\n }\n this.documents[name] = doc\n }\n\n async _waitLoad(name: string): Promise<void> {\n if (this.isLoading[name]) {\n while (this.isLoading[name]) {\n await new Promise((resolve) => setTimeout(resolve, 50))\n }\n }\n }\n\n async _checkDocument(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n if (!this.documents[name]) {\n this.isLoading[name] = true\n await this._loadDocument(name)\n if (!this.documents[name] && this.canCreate(client, name)) {\n this._createEmptyDocument(name)\n }\n if (this.documents[name]) {\n this._makeReactive(name)\n this.onHydrate(name, this.documents[name])\n }\n this.isLoading[name] = false\n this._documentState[name] = {\n subscibers: 0,\n lastModified: Date.now(),\n }\n }\n }\n\n _updateAllDocumentsState(): void {\n for (let name in this.documents) {\n if (name != '_server') {\n let doc = this.documents[name]\n this._documentState[name].subscibers = 0\n for (let client of this.clients) {\n if (client.subscribed && client.subscribed[name]) {\n this._documentState[name].subscibers++\n }\n }\n }\n }\n }\n\n /*= UPDATE LOOP ============================================================*/\n\n // to be redefined. called every this.cycle ms\n onUpdate(name: string, doc: any, dt: number): void {}\n\n _startLoop(): void {\n this.lastUpdate = Date.now()\n this._loop()\n this._statsiv = setInterval(() => {\n this._doStats()\n }, 1000)\n }\n\n _loop(): void {\n let now = Date.now()\n let dtms = (now - this.lastUpdate)\n let dt = dtms / 1000.0 // Convert to seconds\n this.lastUpdate = now\n\n /*\n if (this._stillUpdating) {\n return\n }\n */\n this._stillUpdating = true\n for (let name in this.documents) {\n this.onUpdate(name, this.documents[name], dt)\n }\n let t1 = Date.now()\n this._stillUpdating = false\n let updateTime = t1 - now\n this.stats.tUpdate.push(updateTime)\n\n //this.log(`update ${this.update} patch: ${this.update % this.patchCycleDivider}`, )\n\n let patchTime = 0\n if (this.update % this.patchCycleDivider == 0) {\n this._sendPatches()\n let t2 = Date.now()\n patchTime = t2 - t1\n this.stats.tPatch.push(patchTime)\n if (this.allowFastPatch) {\n this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`, )\n }\n this.stats._sendRTCUpdate = 0\n }\n\n this.update++\n let endUpdate = Date.now()\n let totalUpdate = endUpdate - now\n\n setTimeout(() => {\n this._loop()\n }, Math.max(this.cycle - totalUpdate, 10))\n }\n\n _doStats(): void {\n for (let key in this.stats) {\n let i = this.stats[key]\n if (Array.isArray(i) && i.length > 0) {\n while (i.length > 60) {\n i.shift()\n }\n this.stats['_avg_' + key] = i.reduce((a: number, b: number) => a + b, 0) / i.length\n } else if (!key.startsWith('_')) {\n this.stats['_persec_' + key] = i / 3.0\n this.stats[key] = 0\n }\n }\n //this.log('stats', this.stats)\n }\n\n /*= MESSAGES ===============================================================*/\n\n // to be redefined. Called on message (operation) from client\n onMessage(client: ClientType, message: any): void {}\n\n // to be redefined. Called when a client connects\n onConnect(client: ClientType): void {}\n\n // to be redefined. Called when a client disconnects\n onDisconnect(client: ClientType): void {}\n\n _onConnected(client: ClientType): void {\n client.ID = this.getUID()\n client.ping = 0\n client.ctdiff = 0\n client.subscribed = {}\n client.dataChannel = null\n client.peerConnection = null\n\n this.log('client connected', client.ID)\n this.clients.push(client)\n client.on('error', (...args: any[]) => {\n this._onError(client, args)\n })\n client.on('message', (message:any) => {\n let dec = decode(message)\n if (this.simulateLatency) {\n setTimeout(() => {\n this._onMessage(client, dec)\n }, this.simulateLatency)\n } else {\n this._onMessage(client, dec)\n }\n })\n client.on('close', (message:any) => {\n this._onDisconnected(client)\n this.onDisconnect(client)\n })\n this.onConnect(client)\n }\n\n async _onMessage(client: ClientType, message: any): Promise<void> {\n if (\n message.c == 'sync' &&\n this.allowSync &&\n client.subscribed &&\n client.subscribed[message.n] &&\n this.documents[message.n]\n ) {\n let name = message.n\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n for (let op of message.p) {\n if (!this.canSync(client, name, op)) {\n continue\n }\n this._documentChanges[name].push(op)\n let dop = msgop(op)\n applyOperation(this.documents[name], dop)\n }\n } else if (message.c == 'ping') {\n this.send(client, {\n c: 'pong',\n t: Date.now(),\n ct: message.ct,\n ID: client.ID,\n })\n } else if (message.c == 'peng') {\n let time = Date.now()\n let ping = time - message.st\n client.ctdiff = message.ct + ping / 2 - time\n client.ping = ping\n //this.log(time, \"PENG ping, ctdiff\", message, ping, client.ctdiff, \"ms\")\n /*\n } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\n */\n } else if (message.c == 'sub') {\n await this._checkDocument(message.n, client)\n if (!this.documents[message.n]) {\n this.send(client, {\n c: 'error',\n t: Date.now(),\n message: 'Document not found',\n })\n return\n }\n if (client.subscribed) {\n client.subscribed[message.n] = true\n }\n this._sendFullState(message.n, client)\n } else if (message.c == 'unsub') {\n if (client.subscribed) {\n client.subscribed[message.n] = false\n }\n } else {\n this.onMessage(client, message)\n }\n }\n\n _onError(client: ClientType, args: any[]): void {\n this.error('onError:', args)\n }\n\n _onDisconnected(client: ClientType): void {\n if (client.dataChannel) {\n client.dataChannel.close()\n }\n if (client.peerConnection) {\n client.peerConnection.close()\n }\n this.log('client disconnected')\n let index = this.clients.indexOf(client)\n if (index !== -1) {\n this.clients.splice(index, 1)\n }\n }\n\n async send(client: ClientType, message: any): Promise<void> {\n try {\n let t1 = Date.now()\n let data = encode(message)\n let t2 = Date.now()\n let dl = data.byteLength\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n if (data.length > 4096) {\n this.log(`Big message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n } catch (e) {\n this.error('Error sending message:', e, message)\n }\n }\n\n async broadcast(message: object, clients: ClientType[] | false = false): Promise<void> {\n if (!clients) {\n clients = this.clients\n }\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n for (let client of this.clients) {\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n }\n }\n\n async _sendFullState(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n let excluded: any = '_'\n if (this.allowFastPatch) {\n excluded = fastPatchProperties\n }\n let doc = clonewo_(this.documents[name], excluded)\n limitPrecision(doc)\n let fdata: any = false\n if (this.allowFastPatch) {\n fdata = this._encodeFastChanges(name, false)\n }\n let fullState = {\n c: 'full',\n le: LITTLE_ENDIAN,\n t: Date.now(),\n n: name,\n doc: doc,\n fdata: fdata\n }\n this.send(client, fullState)\n }\n\n _encodeFastChanges(name: string, changesOnly = true): any {\n let doc = this.documents[name]\n if (!doc) { return false }\n let origin = this.documents[name].origin\n if (!origin) {\n origin = [0, 0, 0]\n this.documents[name].origin = origin\n }\n\n let entities = doc.entities\n let ids = Object.keys(entities)\n if (!entities) { return false }\n let count: Record<string, number> = {}\n let changed: any = {}\n let hasChanges: any = {}\n let dictionary: any = {}\n let encodedChanges: any = {}\n\n for (let key in fastPatchProperties) {\n if (changesOnly) {\n count[key] = 0\n changed[key] = {}\n hasChanges[key] = false\n } else {\n count[key] = ids.length\n changed[key] = {}\n hasChanges[key] = true\n }\n dictionary[key] = {}\n }\n\n // search for changes\n\n if (changesOnly) {\n for (let id in entities) {\n let e = entities[id]\n for (let key in fastPatchProperties) {\n if (e['__changed_' + key]) {\n changed[''+key][''+id] = true\n count[''+key] = parseInt(''+count[''+key]) + 1\n hasChanges[''+key] = true\n e['__changed_' + key] = false\n }\n }\n }\n } else {\n for (let id in entities) {\n for (let key in fastPatchProperties) {\n changed[''+key][''+id] = true\n }\n }\n }\n\n // create dictionaries\n\n let dictUID = 1\n for (let key in hasChanges) {\n if (hasChanges[key] && dictionaryProperties[key]) {\n for (let id in changed[key]) {\n let e = entities[id]\n let value = e[key]\n if (!dictionary[key][value]) {\n dictionary[key][value] = dictUID++\n }\n }\n }\n }\n\n this.log(\"--------------------------------------------------\")\n //this.log(\"changed\", changed)\n //this.log(\"count\", count)\n\n // create encoded changes\n //\n for (let key in hasChanges) {\n if (hasChanges[key]) {\n let size = parseInt(''+count[''+key])\n let encoded: any = {}\n if (dictionaryProperties[key]) {\n encoded.dict = dictionary[key]\n\n let pdata = new Uint8Array(size * 8)\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n let value = e[key]\n let did = parseInt(dictionary[key][value])\n encode_uint32(did, pdata, offset)\n offset += 4\n }\n encoded.pdata = pdata\n } else {\n\n let pdata: Uint8Array\n if (key == 'position') {\n pdata = new Uint8Array(size * 13)\n } else if (key == 'rotation') {\n pdata = new Uint8Array(size * 16)\n } else if (key == 'scale') {\n pdata = new Uint8Array(size * 16)\n } else {\n pdata = new Uint8Array(0)\n }\n\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n if (key == 'position') {\n encode_fp168(e.position[0] - origin[0], pdata, offset)\n offset += 3\n encode_fp168(e.position[1] - origin[1], pdata, offset)\n offset += 3\n encode_fp168(e.position[2] - origin[2], pdata, offset)\n offset += 3\n } else if (key == 'rotation') {\n encode_fp412(e.rotation[0], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[1], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[2], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[3], pdata, offset)\n offset += 2\n } else if (key == 'scale') {\n encode_fp1616(e.scale[0], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[1], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[2], pdata, offset)\n offset += 4\n }\n }\n encoded.pdata = pdata\n }\n encodedChanges[key] = encoded\n }\n }\n\n return encodedChanges\n }\n\n _sendPatches(): void {\n let now = Date.now()\n\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n this._documentChanges[name] = []\n let sus = this.clients.filter((client) => client.subscribed && client.subscribed[name])\n if (sus.length > 0) {\n if (dc && dc.length > 0) {\n let record = {\n c: 'patch',\n t: now, // server time\n u: this.update,\n n: name,\n doc: dc,\n }\n this.broadcast(record, sus)\n }\n }\n\n if (this.allowFastPatch) {\n if (sus.length > 0) {\n let t1 = Date.now()\n let changes = this._encodeFastChanges(name)\n let t2 = Date.now()\n let record = {\n c: 'fpatch',\n t: now, // server time\n u: this.update,\n n: name,\n fdata: changes\n }\n //this.broadcastRTC(record, sus)\n let t3 = Date.now()\n this.log(`_sendPatches: ${name} encode_changes: ${t2-t1}ms broadcast:${t3-t2}ms`)\n }\n }\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: any, value: any): void {\n this._documentChanges[name]?.push(opmsg(op, target, path, value))\n }\n\n propertyChange(name: string, id: string | number, property: string): void {\n let doc = this.documents[name]\n if (!doc) { return }\n let entities = doc.entities\n if (!entities) { return }\n let e = entities[id]\n if (!e) { return }\n e['__changed_'+property] = true\n //this.log('propertyChange', e)\n }\n\n\n /*= WEBRTC ===================================================================*/\n\n\n async _processOffer(client: ClientType, data: any): Promise<void> {\n //this.log(\"RTC: Offer received\", data);\n const peerConnection = new wrtc.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 client.peerConnection = peerConnection\n\n peerConnection.onicecandidate = (event: any) => {\n if (event.candidate) {\n //this.log(\"RTC: ICE candidate generated\", event.candidate.candidate.substring(0, 50) + \"...\");\n this.send(client, {\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: event.candidate, // .toJSON()\n })\n } else {\n //this.log(\"RTC: ICE candidate gathering complete\");\n }\n }\n\n peerConnection.onconnectionstatechange = () => {\n //this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);\n if (peerConnection.connectionState === 'connected') {\n client.webRTCConnected = true\n this.log(`RTC: Connection established with client ${client.ID}`)\n } else if (\n peerConnection.connectionState === 'failed' ||\n peerConnection.connectionState === 'disconnected' ||\n peerConnection.connectionState === 'closed'\n ) {\n client.webRTCConnected = false\n this.log(`RTC: Connection failed or closed with client ${client.ID}`)\n }\n }\n\n peerConnection.onicegatheringstatechange = () => {\n //this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);\n }\n\n peerConnection.oniceconnectionstatechange = () => {\n //this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);\n if (\n peerConnection.iceConnectionState === 'connected' ||\n peerConnection.iceConnectionState === 'completed'\n ) {\n //this.log(`RTC: ICE connection established with client ${client.ID}`);\n }\n }\n\n try {\n await peerConnection.setRemoteDescription(\n new wrtc.RTCSessionDescription(data)\n )\n //this.log(\"RTC: Remote description set successfully\");\n\n client.dataChannel = peerConnection.createDataChannel('serverchannel', {\n ordered: true,\n maxRetransmits: 1,\n })\n\n client.dataChannel.onopen = () => {\n //this.log(`RTC: Data channel opened for client ${client.ID}`);\n // Try sending a test message\n try {\n const testData = { c: 'test', message: 'Hello WebRTC' }\n this.sendRTC(client, testData)\n } catch (e) {\n this.error(\n `RTC: Error sending test message to client ${client.ID}`,\n e\n )\n }\n }\n\n client.dataChannel.onclose = () => {\n this.log(`RTC: Data channel closed for client ${client.ID}`)\n }\n\n client.dataChannel.onerror = (error: Event) => {\n this.error(`RTC: Data channel error for client ${client.ID}:`, error)\n }\n\n client.dataChannel.onmessage = (event: MessageEvent) => {\n try {\n const data = decode(event.data)\n this.log(\n `RTC: Data channel message from client ${client.ID}:`,\n data\n )\n //this.onMessage(client, data);\n } catch (error) {\n this.error(\n `RTC: Error decoding message from client ${client.ID}:`,\n error\n )\n }\n }\n\n // Create and send answer\n const answer = await peerConnection.createAnswer()\n await peerConnection.setLocalDescription(answer)\n\n //this.log(`RTC: Sending answer to client ${client.ID}`);\n this.send(client, {\n c: 'rtc-answer',\n type: answer.type,\n sdp: answer.sdp,\n })\n } catch (error) {\n this.error(\n `RTC: Error processing offer from client ${client.ID}:`,\n error\n )\n }\n }\n\n async _processICECandidate(client: ClientType, data: any): Promise<void> {\n //this.log(`RTC: Processing ICE candidate from client ${client.ID}`);\n try {\n if (client.peerConnection && data.candidate) {\n await client.peerConnection.addIceCandidate(\n data.candidate\n //new wrtc.RTCIceCandidate(data.candidate)\n )\n //this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);\n } else {\n //this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`);\n }\n } catch (error) {\n this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)\n }\n }\n\n _clientRTCOpen(client: ClientType): boolean {\n return client.dataChannel !== null && client.dataChannel !== undefined && client.dataChannel.readyState === 'open'\n }\n\n async sendRTC(client: ClientType, message: any): Promise<void> {\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n\n let packages = this._splitRTCMessage(data)\n\n if (this.simulateLatency) {\n setTimeout(() => {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }\n }\n\n async broadcastRTC(message: any, clients: ClientType[] = []): Promise<void> {\n if (clients.length == 0) {\n clients = this.clients\n }\n let t1 = Date.now()\n let data = encode(message)\n let dl = data.byteLength\n let t2 = Date.now()\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n\n\n if (data.length > 16384) {\n this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n\n let packages = this._splitRTCMessage(data)\n\n for (let client of this.clients) {\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }\n }\n }\n\n _splitRTCMessage(data: Uint8Array): Uint8Array[] {\n let packages: Uint8Array[]\n if (data.byteLength > 65535) {\n const now = Date.now()\n this.warn(`RTC: Message too large: ${data.byteLength} bytes`)\n // Split the message into smaller packages\n packages = [];\n let offset = 0;\n let mid = this.update +'-'+ now\n let seq = 0\n\n // Create subsequent packages if needed\n while (offset < data.byteLength) {\n const remaining = data.byteLength - offset;\n const chunkSize = Math.min(remaining, MAX_PACKAGE_SIZE);\n const chunk = new Uint8Array(data.buffer, offset, chunkSize);\n let cmessage = {\n c: 'chunk',\n t: now,\n mid: mid,\n seq: seq,\n ofs: offset,\n chs: chunkSize,\n ts: data.byteLength,\n data: chunk,\n last: remaining <= MAX_PACKAGE_SIZE,\n }\n packages.push(encode(cmessage))\n offset += chunkSize;\n seq++;\n }\n\n this.log(`RTC: Large message split into ${packages.length} packages`);\n } else {\n packages = [data]\n this.log(`RTC: Message - ${data.byteLength} bytes`)\n }\n return packages\n }\n\n\n /*= DATABASE =================================================================*/\n // properties (of the documents) that starts with __ are not saved to the database.\n // __properties are restored on hydration. (for example __physicsBody or __bigObject)\n\n getUID(): number {\n this.documents['_server'].nextUID++\n return this.documents['_server'].nextUID\n }\n\n async _initDB(): Promise<void> {\n await this._connectDB()\n await this._loadDocument('_server')\n if (!this.documents['_server']) {\n this._initServerDocument()\n }\n }\n\n async _connectDB(): Promise<void> {\n this.mongoClient = new MongoClient(this.MongoUrl)\n try {\n await this.mongoClient.connect()\n this.log('Connected to MongoDB')\n const db = this.mongoClient.db(this.database)\n this.DB = db\n } catch (error) {\n this.error('Error connecting to MongoDB:', error)\n this.mongoClient = null\n }\n }\n\n async _loadDocument(name: string): Promise<void> {\n this.log(`Loading document '${name}' from MongoDB`)\n if (this.DB) {\n try {\n const doc = await this.DB.collection(this.collection).findOne({\n name: name,\n })\n if (doc) {\n delete (doc as any)._id\n this.documents[name] = doc\n }\n } catch (error) {\n this.error('Error loading document from MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not loaded.')\n }\n }\n\n async _saveDocument(name: string): Promise<void> {\n if (this.DB) {\n try {\n const doc = this.documents[name]\n let newdoc = clonewo_(doc, '__')\n this.log(`Saving document '${name}' to MongoDB`)\n await this.DB.collection(this.collection).updateOne(\n { name: name },\n { $set: newdoc },\n { upsert: true }\n )\n this.log('Document saved to MongoDB')\n } catch (error) {\n this.error('Error saving document to MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not saved.')\n }\n }\n\n async _saveAllDocuments(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this.documents) {\n await this._saveDocument(name)\n }\n }\n\n _initServerDocument(): void {\n this.documents['_server'] = {\n nextUID: 100,\n }\n }\n\n /*= EXIT ===================================================================*/\n\n _exitSignal(signal: string): void {\n if (!this._exited) {\n this.log('\\nEXIT: Caught interrupt signal ' + signal)\n this._exited = true\n clearInterval(this._loopiv)\n this.onBeforeExit()\n this.broadcast({ server: 'Going down' })\n this._saveAllDocuments()\n this._wss!.close()\n setTimeout(() => process.exit(0), 1000)\n }\n }\n\n // To be redefined. Called BEFORE program exit, and saving all documents\n onBeforeExit(): void {}\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","import { promisify } from 'util'\nimport { gzip, gunzip, constants } from 'zlib'\n\nconst MIN_COMPRESSED_BUFFER_SIZE = 256\nconst MAX_COMPRESSED_BUFFER_SIZE = 999999\n\nconst lib_compress = promisify(gzip)\nconst lib_decompress = promisify(gunzip)\n\nexport async function compress(buffer:Uint8Array<ArrayBufferLike>) {\n if (buffer.byteLength <= MIN_COMPRESSED_BUFFER_SIZE || buffer.byteLength >= MAX_COMPRESSED_BUFFER_SIZE) return buffer\n try {\n let t1 = Date.now()\n let cbytes = await lib_compress(buffer, {\n level: constants.Z_BEST_SPEED\n })\n let t2 = Date.now()\n let cbuffer = Buffer.from(cbytes)\n let t3 = Date.now()\n\n //console.log(`Node compression ${buffer.byteLength} -> ${cbuffer.byteLength}, time: ${t2 - t1}ms`)\n\n return cbuffer\n } catch (error) {\n console.error('Error compressing buffer:', error)\n return buffer\n }\n}\n\nexport async function decompress(buffer:Uint8Array<ArrayBufferLike>) {\n try {\n let cbytes = await lib_decompress(buffer)\n let cbuffer = Buffer.from(cbytes)\n return cbuffer\n } catch (error) {\n console.error('Error decompressing buffer:', error)\n return buffer\n }\n}\n"],"mappings":";;;;;;;;AAAA,YAAY,WAAW;AACvB,YAAY,QAAQ;;;ACDpB,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;AA6BO,SAAS,SAAS,KAAU,eAAiD,KAAU;AAC5F,MAAI,QAAQ,QAAQ,OAAO,QAAQ,UAAU;AAC3C,WAAO;AAAA,EACT;AAEA,WAAS,WAAW,KAAsB;AACxC,QAAI,IAAI;AACR,QAAI,OAAQ,gBAAiB,YAAY,IAAI,WAAW,YAAY,GAAG;AACrE,UAAI;AAAA,IACN,WAAW,OAAO,gBAAiB,UAAU;AAC3C,UAAI,aAAa,GAAG,KAAK,IAAI,WAAW,GAAG,GAAG;AAC5C,YAAI;AAAA,MACN;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,MAAI,eAAe,KAAK;AACtB,UAAM,WAAW,oBAAI,IAAI;AACzB,UAAM,KAAK,IAAI,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAClD,eAAS,IAAI,SAAS,KAAK,YAAY,GAAG,SAAS,OAAO,YAAY,CAAC;AAAA,IACzE,CAAC;AACD,WAAO;AAAA,EACT;AAEA,MAAI;AACJ,MAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,YAAQ,CAAC;AACT,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,YAAM,CAAC,IAAI,SAAS,IAAI,CAAC,GAAG,YAAY;AAAA,IAC1C;AAAA,EACF,OAAO;AACL,YAAQ,CAAC;AACT,aAAS,OAAO,KAAK;AACnB,UAAI,IAAI,eAAe,GAAG,KAAK,CAAC,WAAW,GAAG,GAAG;AAC/C,YAAI,OAAO,IAAI,GAAG,MAAM,UAAU;AAChC,gBAAM,GAAG,IAAI,SAAS,IAAI,GAAG,GAAG,YAAY;AAAA,QAC9C,OAAO;AACL,gBAAM,GAAG,IAAI,IAAI,GAAG;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,eAAe,KAAe;AAC5C,MAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,WAAO,IAAI,IAAI,cAAc;AAAA,EAC/B,WAAW,QAAQ,QAAQ,OAAO,QAAQ,UAAU;AAClD,UAAM,SAA8B,CAAC;AACrC,eAAW,OAAO,KAAK;AACrB,aAAO,GAAG,IAAI,eAAe,IAAI,GAAG,CAAC;AAAA,IACvC;AACA,WAAO;AAAA,EACT,WAAW,OAAO,QAAQ,UAAU;AAClC,QAAI,OAAO,UAAU,GAAG,GAAG;AACzB,aAAO;AAAA,IACT,OAAO;AAEL,aAAO,WAAW,IAAI,QAAQ,CAAC,CAAC;AAAA,IAClC;AAAA,EACF,OAAO;AACL,WAAO;AAAA,EACT;AACF;AAEO,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;AAmBO,SAAS,cAAc,MAAc,WAAwB,SAAiB,GAAe;AAClG,MAAI,CAAC,WAAW;AACd,gBAAY,IAAI,WAAW,CAAC;AAAA,EAC9B;AACA,MAAI,IAAI,SAAS;AACjB,YAAU,GAAG,IAAI,OAAO;AACxB,WAAS;AACT,YAAU,GAAG,IAAI,OAAO;AACxB,WAAS;AACT,YAAU,GAAG,IAAI,OAAO;AACxB,WAAS;AACT,YAAU,CAAC,IAAI;AACf,SAAO;AACT;AAaO,SAAS,cAAc,MAAc,WAAwB,SAAiB,GAAe;AAClG,MAAI,CAAC,WAAW;AACd,gBAAY,IAAI,WAAW,CAAC;AAAA,EAC9B;AACA,MAAI,IAAI,SAAS;AACjB,YAAU,GAAG,IAAI,OAAO;AACxB,WAAS;AACT,YAAU,GAAG,IAAI,OAAO;AACxB,WAAS;AACT,YAAU,CAAC,IAAI;AACf,SAAO;AACT;AAaO,SAAS,cAAc,MAAc,WAAwB,SAAiB,GAAe;AAClG,MAAI,CAAC,WAAW;AACd,gBAAY,IAAI,WAAW,CAAC;AAAA,EAC9B;AACA,MAAI,IAAI,SAAS;AACjB,YAAU,GAAG,IAAI,OAAO;AACxB,WAAS;AACT,YAAU,CAAC,IAAI;AACf,SAAO;AACT;AA8BO,SAAS,aAAa,OAAe,WAAwB,SAAiB,GAAS;AAC5F,QAAM,KAAK,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,GAAG;AAC3C,gBAAc,IAAI,WAAW,MAAM;AACnC,MAAI,QAAQ,KAAK,WAAW;AAC1B,cAAU,MAAM,KAAM;AAAA,EACxB;AACF;AAaO,SAAS,cAAc,OAAe,WAAwB,SAAiB,GAAS;AAC7F,QAAM,KAAK,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK;AAC7C,gBAAc,IAAI,WAAW,MAAM;AACnC,MAAI,QAAQ,KAAK,WAAW;AAC1B,cAAU,MAAM,KAAM;AAAA,EACxB;AACF;AAgCO,SAAS,aAAa,OAAe,WAAwB,SAAiB,GAAS;AAC5F,QAAM,KAAK,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,IAAI;AAC5C,gBAAc,IAAI,WAAW,MAAM;AACnC,MAAI,QAAQ,KAAK,WAAW;AAC1B,cAAU,MAAM,KAAM;AAAA,EACxB;AACF;;;ACxXA,SAAS,iBAAkB;AAC3B,SAAS,MAAM,QAAQ,iBAAkB;AAEzC,IAAM,6BAA6B;AACnC,IAAM,6BAA6B;AAEnC,IAAM,eAAe,UAAU,IAAI;AACnC,IAAM,iBAAiB,UAAU,MAAM;AAEvC,eAAsB,SAAS,QAAoC;AACjE,MAAI,OAAO,cAAc,8BAA8B,OAAO,cAAc,2BAA4B,QAAO;AAC/G,MAAI;AACF,QAAI,KAAK,KAAK,IAAI;AAClB,QAAI,SAAS,MAAM,aAAa,QAAQ;AAAA,MACtC,OAAO,UAAU;AAAA,IACnB,CAAC;AACD,QAAI,KAAK,KAAK,IAAI;AAClB,QAAI,UAAU,OAAO,KAAK,MAAM;AAChC,QAAI,KAAK,KAAK,IAAI;AAIlB,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,6BAA6B,KAAK;AAChD,WAAO;AAAA,EACT;AACF;;;AFVA,OAAO,mBAAmB;AAC1B,SAAS,uBAAkC;AAC3C,SAAS,mBAAuB;AAEhC,SAAS,gBAA4B;AACrC,SAAS,mBAAmB,KAAK;AACjC,IAAM,OAAO,UAAQ,cAAc;AAGnC,IAAM,sBAA+C;AAAA,EACnD,QAAQ;AAAA;AAAA,EACR,UAAU;AAAA;AAAA,EACV,SAAS;AAAA;AAAA,EACT,QAAQ;AAAA;AAAA,EACR,SAAS;AAAA;AAAA,EACT,SAAS;AAAA;AAAA,EACT,aAAa;AAAA;AAAA,EACb,SAAS;AAAA;AAAA,EACT,UAAU;AAAA;AAAA,EACV,YAAY;AAAA;AAAA,EACZ,YAAY;AAAA;AAAA,EACZ,SAAS;AAAA;AACX;AAEA,IAAM,uBAAgD;AAAA,EACpD,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,EACT,aAAa;AAAA,EACb,SAAS;AAAA,EACT,UAAU;AACZ;AAEA,IAAM,EAAE,eAAe,IAAI;AAC3B,IAAM,iBAAiB,MAAM;AAC3B,QAAM,SAAS,IAAI,YAAY,CAAC;AAChC,MAAI,SAAS,MAAM,EAAE,SAAS,GAAG,KAAK,IAAI;AAC1C,SAAO,IAAI,WAAW,MAAM,EAAE,CAAC,MAAM;AACvC,GAAG;AAEH,IAAM,mBAAmB;AAczB,IAAqB,kBAArB,MAAqC;AAAA,EACnC,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,oBAAoB;AAAA,EACpB,OAAO;AAAA,EACP,WAAW;AAAA,EACX,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,cAAkC;AAAA,EAClC,KAAgB;AAAA,EAChB,WAAW;AAAA,EACX,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAElB,WAAW;AAAA,EACX,UAAwB,CAAC;AAAA,EACzB,YAAiC,CAAC;AAAA,EAClC,YAAqC,CAAC;AAAA,EACtC,mBAA0C,CAAC;AAAA,EAC3C,iBAAsC,CAAC;AAAA,EAEvC,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAe;AAAA,EACf,WAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,QAAmB;AAAA,IACjB,SAAS,CAAC;AAAA,IACV,QAAQ,CAAC;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,gBAAgB;AAAA,EAClB;AAAA,EAEA,OAA+B;AAAA,EAC/B,UAAU;AAAA,EAEV,OAAO,MAAa;AAChB,YAAQ,IAAI,KAAK,OAAO,KAAK,GAAG,IAAI;AAAA,EACxC;AAAA,EAEA,QAAQ,MAAa;AACjB,YAAQ,KAAK,KAAK,OAAO,KAAK,GAAG,IAAI;AAAA,EACzC;AAAA,EAEA,SAAS,MAAa;AAClB,YAAQ,MAAM,KAAK,OAAO,KAAK,GAAG,IAAI;AAAA,EAC1C;AAAA,EAEA,YAAY;AAAA,IACV,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,IACX,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,WAAW;AAAA,IACX,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACpB,IAgBI,CAAC,GAAG;AACN,SAAK,OAAO;AACZ,SAAK,QAAQ;AACb,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,SAAK,MAAM;AACX,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,YAAY;AACjB,SAAK,YAAY;AACjB,SAAK,cAAc;AACnB,SAAK,iBAAiB;AACtB,SAAK,mBAAmB;AACxB,SAAK,kBAAkB;AAEvB,SAAK,QAAQ;AAEb,QAAI,UAAU;AACZ,UAAI,cAAyC,mBAAa;AAAA,QACxD,KAAQ,gBAAa,KAAK,GAAG;AAAA,QAC7B,MAAS,gBAAa,KAAK,IAAI;AAAA,MACjC,GAAG,CAAC,KAAK,QAAQ;AACf,YAAI,UAAU,GAAG;AACjB,YAAI,IAAI,qBAAqB;AAAA,MAC/B,CAAC,EAAE,OAAO,KAAK,IAAI;AACnB,WAAK,OAAO,IAAI,gBAAgB,EAAE,QAAQ,YAAY,CAAC;AACvD,oBAAc;AACd,WAAK,IAAI,KAAK,OAAO,4BAA4B,KAAK,IAAI;AAAA,IAC5D,OAAO;AACL,WAAK,OAAO,IAAI,gBAAgB,EAAE,MAAM,KAAK,KAAK,CAAC;AACnD,WAAK,IAAI,KAAK,OAAO,sBAAsB,KAAK,IAAI;AAAA,IACtD;AACA,SAAK,KAAK,GAAG,cAAc,CAAC,WAAsB;AAChD,WAAK,aAAa,MAAM;AAAA,IAC1B,CAAC;AAED,YAAQ,MAAM,OAAO;AACrB,YAAQ,GAAG,UAAU,MAAM;AACzB,WAAK,YAAY,QAAQ;AAAA,IAC3B,CAAC;AACD,YAAQ,GAAG,WAAW,MAAM;AAC1B,WAAK,YAAY,SAAS;AAAA,IAC5B,CAAC;AACD,YAAQ,GAAG,WAAW,MAAM;AAC1B,WAAK,YAAY,SAAS;AAAA,IAC5B,CAAC;AACD,YAAQ,GAAG,WAAW,MAAM;AAC1B,WAAK,YAAY,SAAS;AAAA,IAC5B,CAAC;AAGD,YAAQ,MAAM,OAAO;AACrB,YAAQ,MAAM,YAAY,MAAM;AAEhC,YAAQ,MAAM,GAAG,QAAQ,CAACA,SAAa;AACrC,MAAAA,QAAO,KAAGA,MAAK,KAAK;AAGpB,UAAIA,QAAO,KAAU;AACnB,aAAK,YAAY,QAAQ;AACzB;AAAA,MACF;AAGA,WAAK,IAAI,gBAAgBA,IAAG,EAAE;AAG9B,UAAIA,QAAO,KAAK;AACd,aAAK,IAAI,yBAAyB;AAClC,aAAK,kBAAkB;AAAA,MACzB;AAGA,UAAIA,QAAO,KAAK;AACd,aAAK;AAAA,UACH,WAAW,KAAK,IAAI,cAAc,KAAK,QAAQ,MAAM,gBAAgB,OAAO,KAAK,KAAK,SAAS,EAAE,MAAM;AAAA,QACzG;AAAA,MACF;AAAA,IACF,CAAC;AACD,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,QAAoB,MAAuB;AACnD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAIA,SAAS,MAAmB;AAC1B,WAAO;AAAA,MACL,MAAM,CAAC;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA,EAIA,QAAQ,QAAoB,MAAc,IAAkB;AAC1D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAIA,MAAM,UAAU,MAAc,UAA8B;AAC1D,aAAS,aAAa;AAAA,EACxB;AAAA,EAEA,cAAc,MAAoB;AAEhC,QAAI,KAAU;AACd,QAAI,KAAK,gBAAgB;AACvB,WAAK;AAAA,IACP;AACA,SAAK,UAAU,IAAI,IAAI;AAAA,MACrB;AAAA,MACA,KAAK,UAAU,IAAI;AAAA,MACnB,KAAK,kBAAkB,KAAK,IAAI;AAAA,MAChC;AAAA,MACA;AAAA,IACF;AACA,QAAI,CAAC,KAAK,iBAAiB,IAAI,GAAG;AAChC,WAAK,iBAAiB,IAAI,IAAI,CAAC;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,qBAAqB,MAAoB;AACvC,QAAI,MAAM,KAAK,SAAS,IAAI;AAC5B,QAAI,CAAC,KAAK;AACR;AAAA,IACF;AACA,SAAK,UAAU,IAAI,IAAI;AAAA,EACzB;AAAA,EAEA,MAAM,UAAU,MAA6B;AAC3C,QAAI,KAAK,UAAU,IAAI,GAAG;AACxB,aAAO,KAAK,UAAU,IAAI,GAAG;AAC3B,cAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,MAAc,QAAmC;AACpE,UAAM,KAAK,UAAU,IAAI;AACzB,QAAI,CAAC,KAAK,UAAU,IAAI,GAAG;AACzB,WAAK,UAAU,IAAI,IAAI;AACvB,YAAM,KAAK,cAAc,IAAI;AAC7B,UAAI,CAAC,KAAK,UAAU,IAAI,KAAK,KAAK,UAAU,QAAQ,IAAI,GAAG;AACzD,aAAK,qBAAqB,IAAI;AAAA,MAChC;AACA,UAAI,KAAK,UAAU,IAAI,GAAG;AACxB,aAAK,cAAc,IAAI;AACvB,aAAK,UAAU,MAAM,KAAK,UAAU,IAAI,CAAC;AAAA,MAC3C;AACA,WAAK,UAAU,IAAI,IAAI;AACvB,WAAK,eAAe,IAAI,IAAI;AAAA,QAC1B,YAAY;AAAA,QACZ,cAAc,KAAK,IAAI;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,2BAAiC;AAC/B,aAAS,QAAQ,KAAK,WAAW;AAC/B,UAAI,QAAQ,WAAW;AACrB,YAAI,MAAM,KAAK,UAAU,IAAI;AAC7B,aAAK,eAAe,IAAI,EAAE,aAAa;AACvC,iBAAS,UAAU,KAAK,SAAS;AAC/B,cAAI,OAAO,cAAc,OAAO,WAAW,IAAI,GAAG;AAChD,iBAAK,eAAe,IAAI,EAAE;AAAA,UAC5B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA,EAKA,SAAS,MAAc,KAAU,IAAkB;AAAA,EAAC;AAAA,EAEpD,aAAmB;AACjB,SAAK,aAAa,KAAK,IAAI;AAC3B,SAAK,MAAM;AACX,SAAK,WAAW,YAAY,MAAM;AAChC,WAAK,SAAS;AAAA,IAChB,GAAG,GAAI;AAAA,EACT;AAAA,EAEA,QAAc;AACZ,QAAI,MAAM,KAAK,IAAI;AACnB,QAAI,OAAQ,MAAM,KAAK;AACvB,QAAI,KAAK,OAAO;AAChB,SAAK,aAAa;AAOlB,SAAK,iBAAiB;AACtB,aAAS,QAAQ,KAAK,WAAW;AAC/B,WAAK,SAAS,MAAM,KAAK,UAAU,IAAI,GAAG,EAAE;AAAA,IAC9C;AACA,QAAI,KAAK,KAAK,IAAI;AAClB,SAAK,iBAAiB;AACtB,QAAI,aAAa,KAAK;AACtB,SAAK,MAAM,QAAQ,KAAK,UAAU;AAIlC,QAAI,YAAY;AAChB,QAAI,KAAK,SAAS,KAAK,qBAAqB,GAAG;AAC7C,WAAK,aAAa;AAClB,UAAI,KAAK,KAAK,IAAI;AAClB,kBAAY,KAAK;AACjB,WAAK,MAAM,OAAO,KAAK,SAAS;AAChC,UAAI,KAAK,gBAAgB;AACvB,aAAK,IAAI,UAAU,KAAK,MAAM,OAAO,IAAI,UAAU,KAAK,MAAM,cAAc,mBAAmB,UAAU,eAAe,SAAS,IAAM;AAAA,MACzI;AACA,WAAK,MAAM,iBAAiB;AAAA,IAC9B;AAEA,SAAK;AACL,QAAI,YAAY,KAAK,IAAI;AACzB,QAAI,cAAc,YAAY;AAE9B,eAAW,MAAM;AACf,WAAK,MAAM;AAAA,IACb,GAAG,KAAK,IAAI,KAAK,QAAQ,aAAa,EAAE,CAAC;AAAA,EAC3C;AAAA,EAEA,WAAiB;AACf,aAAS,OAAO,KAAK,OAAO;AAC1B,UAAI,IAAI,KAAK,MAAM,GAAG;AACtB,UAAI,MAAM,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG;AACpC,eAAO,EAAE,SAAS,IAAI;AACpB,YAAE,MAAM;AAAA,QACV;AACA,aAAK,MAAM,UAAU,GAAG,IAAI,EAAE,OAAO,CAAC,GAAW,MAAc,IAAI,GAAG,CAAC,IAAI,EAAE;AAAA,MAC/E,WAAW,CAAC,IAAI,WAAW,GAAG,GAAG;AAC/B,aAAK,MAAM,aAAa,GAAG,IAAI,IAAI;AACnC,aAAK,MAAM,GAAG,IAAI;AAAA,MACpB;AAAA,IACF;AAAA,EAEF;AAAA;AAAA;AAAA,EAKA,UAAU,QAAoB,SAAoB;AAAA,EAAC;AAAA;AAAA,EAGnD,UAAU,QAA0B;AAAA,EAAC;AAAA;AAAA,EAGrC,aAAa,QAA0B;AAAA,EAAC;AAAA,EAExC,aAAa,QAA0B;AACrC,WAAO,KAAK,KAAK,OAAO;AACxB,WAAO,OAAO;AACd,WAAO,SAAS;AAChB,WAAO,aAAa,CAAC;AACrB,WAAO,cAAc;AACrB,WAAO,iBAAiB;AAExB,SAAK,IAAI,oBAAoB,OAAO,EAAE;AACtC,SAAK,QAAQ,KAAK,MAAM;AACxB,WAAO,GAAG,SAAS,IAAI,SAAgB;AACrC,WAAK,SAAS,QAAQ,IAAI;AAAA,IAC5B,CAAC;AACD,WAAO,GAAG,WAAW,CAAC,YAAgB;AACpC,UAAI,MAAM,OAAO,OAAO;AACxB,UAAI,KAAK,iBAAiB;AACxB,mBAAW,MAAM;AACf,eAAK,WAAW,QAAQ,GAAG;AAAA,QAC7B,GAAG,KAAK,eAAe;AAAA,MACzB,OAAO;AACL,aAAK,WAAW,QAAQ,GAAG;AAAA,MAC7B;AAAA,IACF,CAAC;AACD,WAAO,GAAG,SAAS,CAAC,YAAgB;AAClC,WAAK,gBAAgB,MAAM;AAC3B,WAAK,aAAa,MAAM;AAAA,IAC1B,CAAC;AACD,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA,EAEA,MAAM,WAAW,QAAoB,SAA6B;AAChE,QACE,QAAQ,KAAK,UACb,KAAK,aACL,OAAO,cACP,OAAO,WAAW,QAAQ,CAAC,KAC3B,KAAK,UAAU,QAAQ,CAAC,GACxB;AACA,UAAI,OAAO,QAAQ;AACnB,UAAI,CAAC,KAAK,iBAAiB,IAAI,GAAG;AAChC,aAAK,iBAAiB,IAAI,IAAI,CAAC;AAAA,MACjC;AACA,eAAS,MAAM,QAAQ,GAAG;AACxB,YAAI,CAAC,KAAK,QAAQ,QAAQ,MAAM,EAAE,GAAG;AACnC;AAAA,QACF;AACA,aAAK,iBAAiB,IAAI,EAAE,KAAK,EAAE;AACnC,YAAI,MAAM,MAAM,EAAE;AAClB,uBAAe,KAAK,UAAU,IAAI,GAAG,GAAG;AAAA,MAC1C;AAAA,IACF,WAAW,QAAQ,KAAK,QAAQ;AAC9B,WAAK,KAAK,QAAQ;AAAA,QAChB,GAAG;AAAA,QACH,GAAG,KAAK,IAAI;AAAA,QACZ,IAAI,QAAQ;AAAA,QACZ,IAAI,OAAO;AAAA,MACb,CAAC;AAAA,IACH,WAAW,QAAQ,KAAK,QAAQ;AAC9B,UAAI,OAAO,KAAK,IAAI;AACpB,UAAI,OAAO,OAAO,QAAQ;AAC1B,aAAO,SAAS,QAAQ,KAAK,OAAO,IAAI;AACxC,aAAO,OAAO;AAAA,IAQhB,WAAW,QAAQ,KAAK,OAAO;AAC7B,YAAM,KAAK,eAAe,QAAQ,GAAG,MAAM;AAC3C,UAAI,CAAC,KAAK,UAAU,QAAQ,CAAC,GAAG;AAC9B,aAAK,KAAK,QAAQ;AAAA,UAChB,GAAG;AAAA,UACH,GAAG,KAAK,IAAI;AAAA,UACZ,SAAS;AAAA,QACX,CAAC;AACD;AAAA,MACF;AACA,UAAI,OAAO,YAAY;AACrB,eAAO,WAAW,QAAQ,CAAC,IAAI;AAAA,MACjC;AACA,WAAK,eAAe,QAAQ,GAAG,MAAM;AAAA,IACvC,WAAW,QAAQ,KAAK,SAAS;AAC/B,UAAI,OAAO,YAAY;AACrB,eAAO,WAAW,QAAQ,CAAC,IAAI;AAAA,MACjC;AAAA,IACF,OAAO;AACL,WAAK,UAAU,QAAQ,OAAO;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,SAAS,QAAoB,MAAmB;AAC9C,SAAK,MAAM,YAAY,IAAI;AAAA,EAC7B;AAAA,EAEA,gBAAgB,QAA0B;AACxC,QAAI,OAAO,aAAa;AACtB,aAAO,YAAY,MAAM;AAAA,IAC3B;AACA,QAAI,OAAO,gBAAgB;AACzB,aAAO,eAAe,MAAM;AAAA,IAC9B;AACA,SAAK,IAAI,qBAAqB;AAC9B,QAAI,QAAQ,KAAK,QAAQ,QAAQ,MAAM;AACvC,QAAI,UAAU,IAAI;AAChB,WAAK,QAAQ,OAAO,OAAO,CAAC;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,QAAoB,SAA6B;AAC1D,QAAI;AACF,UAAI,KAAK,KAAK,IAAI;AAClB,UAAI,OAAO,OAAO,OAAO;AACzB,UAAI,KAAK,KAAK,IAAI;AAClB,UAAI,KAAK,KAAK;AACd,UAAI,KAAK,kBAAkB;AACzB,eAAO,MAAM,SAAS,IAAI;AAAA,MAC5B;AACA,UAAI,KAAK,KAAK,IAAI;AAClB,UAAI,KAAK,SAAS,MAAM;AACtB,aAAK,IAAI,eAAe,EAAE,OAAO,KAAK,MAAM,MAAM,MAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,eAAe,KAAK,EAAE,kBAAkB,KAAK,EAAE,IAAI;AAAA,MAC1I;AACA,WAAK,MAAM,QAAQ,KAAK;AACxB,UAAI,KAAK,iBAAiB;AACxB,mBAAW,MAAM;AACf,iBAAO,KAAK,IAAI;AAAA,QAClB,GAAG,KAAK,eAAe;AAAA,MACzB,OAAO;AACL,eAAO,KAAK,IAAI;AAAA,MAClB;AAAA,IACF,SAAS,GAAG;AACV,WAAK,MAAM,0BAA0B,GAAG,OAAO;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,SAAiB,UAAgC,OAAsB;AACrF,QAAI,CAAC,SAAS;AACZ,gBAAU,KAAK;AAAA,IACjB;AACA,QAAI,OAAO,OAAO,OAAO;AACzB,QAAI,KAAK,kBAAkB;AACzB,aAAO,MAAM,SAAS,IAAI;AAAA,IAC5B;AACA,aAAS,UAAU,KAAK,SAAS;AAC/B,WAAK,MAAM,QAAQ,KAAK;AACxB,UAAI,KAAK,iBAAiB;AACxB,mBAAW,MAAM;AACf,iBAAO,KAAK,IAAI;AAAA,QAClB,GAAG,KAAK,eAAe;AAAA,MACzB,OAAO;AACL,eAAO,KAAK,IAAI;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,MAAc,QAAmC;AACpE,UAAM,KAAK,UAAU,IAAI;AACzB,QAAI,WAAgB;AACpB,QAAI,KAAK,gBAAgB;AACvB,iBAAW;AAAA,IACb;AACA,QAAI,MAAM,SAAS,KAAK,UAAU,IAAI,GAAG,QAAQ;AACjD,mBAAe,GAAG;AAClB,QAAI,QAAa;AACjB,QAAI,KAAK,gBAAgB;AACvB,cAAQ,KAAK,mBAAmB,MAAM,KAAK;AAAA,IAC7C;AACA,QAAI,YAAY;AAAA,MACd,GAAG;AAAA,MACH,IAAI;AAAA,MACJ,GAAG,KAAK,IAAI;AAAA,MACZ,GAAG;AAAA,MACH;AAAA,MACA;AAAA,IACF;AACA,SAAK,KAAK,QAAQ,SAAS;AAAA,EAC7B;AAAA,EAEA,mBAAmB,MAAc,cAAc,MAAW;AACxD,QAAI,MAAM,KAAK,UAAU,IAAI;AAC7B,QAAI,CAAC,KAAK;AAAE,aAAO;AAAA,IAAM;AACzB,QAAI,SAAS,KAAK,UAAU,IAAI,EAAE;AAClC,QAAI,CAAC,QAAQ;AACX,eAAS,CAAC,GAAG,GAAG,CAAC;AACjB,WAAK,UAAU,IAAI,EAAE,SAAS;AAAA,IAChC;AAEA,QAAI,WAAW,IAAI;AACnB,QAAI,MAAM,OAAO,KAAK,QAAQ;AAC9B,QAAI,CAAC,UAAU;AAAE,aAAO;AAAA,IAAM;AAC9B,QAAI,QAAgC,CAAC;AACrC,QAAI,UAAe,CAAC;AACpB,QAAI,aAAkB,CAAC;AACvB,QAAI,aAAkB,CAAC;AACvB,QAAI,iBAAsB,CAAC;AAE3B,aAAS,OAAO,qBAAqB;AACnC,UAAI,aAAa;AACf,cAAM,GAAG,IAAI;AACb,gBAAQ,GAAG,IAAI,CAAC;AAChB,mBAAW,GAAG,IAAI;AAAA,MACpB,OAAO;AACL,cAAM,GAAG,IAAI,IAAI;AACjB,gBAAQ,GAAG,IAAI,CAAC;AAChB,mBAAW,GAAG,IAAI;AAAA,MACpB;AACA,iBAAW,GAAG,IAAI,CAAC;AAAA,IACrB;AAIA,QAAI,aAAa;AACf,eAAS,MAAM,UAAU;AACvB,YAAI,IAAI,SAAS,EAAE;AACnB,iBAAS,OAAO,qBAAqB;AACnC,cAAI,EAAE,eAAe,GAAG,GAAG;AACzB,oBAAQ,KAAG,GAAG,EAAE,KAAG,EAAE,IAAI;AACzB,kBAAM,KAAG,GAAG,IAAI,SAAS,KAAG,MAAM,KAAG,GAAG,CAAC,IAAI;AAC7C,uBAAW,KAAG,GAAG,IAAI;AACrB,cAAE,eAAe,GAAG,IAAI;AAAA,UAC1B;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,eAAS,MAAM,UAAU;AACvB,iBAAS,OAAO,qBAAqB;AACnC,kBAAQ,KAAG,GAAG,EAAE,KAAG,EAAE,IAAI;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAIA,QAAI,UAAU;AACd,aAAS,OAAO,YAAY;AAC1B,UAAI,WAAW,GAAG,KAAK,qBAAqB,GAAG,GAAG;AAChD,iBAAS,MAAM,QAAQ,GAAG,GAAG;AAC3B,cAAI,IAAI,SAAS,EAAE;AACnB,cAAI,QAAQ,EAAE,GAAG;AACjB,cAAI,CAAC,WAAW,GAAG,EAAE,KAAK,GAAG;AAC3B,uBAAW,GAAG,EAAE,KAAK,IAAI;AAAA,UAC3B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,SAAK,IAAI,oDAAoD;AAM7D,aAAS,OAAO,YAAY;AAC1B,UAAI,WAAW,GAAG,GAAG;AACnB,YAAI,OAAO,SAAS,KAAG,MAAM,KAAG,GAAG,CAAC;AACpC,YAAI,UAAe,CAAC;AACpB,YAAI,qBAAqB,GAAG,GAAG;AAC7B,kBAAQ,OAAO,WAAW,GAAG;AAE7B,cAAI,QAAQ,IAAI,WAAW,OAAO,CAAC;AACnC,cAAI,SAAS;AACb,mBAAS,MAAM,QAAQ,GAAG,GAAG;AAC3B,gBAAI,IAAI,SAAS,EAAE;AACnB,gBAAI,MAAM,SAAS,EAAE;AACrB,0BAAc,KAAK,OAAO,MAAM;AAChC,sBAAU;AACV,gBAAI,QAAQ,EAAE,GAAG;AACjB,gBAAI,MAAM,SAAS,WAAW,GAAG,EAAE,KAAK,CAAC;AACzC,0BAAc,KAAK,OAAO,MAAM;AAChC,sBAAU;AAAA,UACZ;AACA,kBAAQ,QAAQ;AAAA,QAClB,OAAO;AAEL,cAAI;AACJ,cAAI,OAAO,YAAY;AACrB,oBAAQ,IAAI,WAAW,OAAO,EAAE;AAAA,UAClC,WAAW,OAAO,YAAY;AAC5B,oBAAQ,IAAI,WAAW,OAAO,EAAE;AAAA,UAClC,WAAW,OAAO,SAAS;AACzB,oBAAQ,IAAI,WAAW,OAAO,EAAE;AAAA,UAClC,OAAO;AACL,oBAAQ,IAAI,WAAW,CAAC;AAAA,UAC1B;AAEA,cAAI,SAAS;AACb,mBAAS,MAAM,QAAQ,GAAG,GAAG;AAC3B,gBAAI,IAAI,SAAS,EAAE;AACnB,gBAAI,MAAM,SAAS,EAAE;AACrB,0BAAc,KAAK,OAAO,MAAM;AAChC,sBAAU;AACV,gBAAI,OAAO,YAAY;AACrB,2BAAa,EAAE,SAAS,CAAC,IAAI,OAAO,CAAC,GAAG,OAAO,MAAM;AACrD,wBAAU;AACV,2BAAa,EAAE,SAAS,CAAC,IAAI,OAAO,CAAC,GAAG,OAAO,MAAM;AACrD,wBAAU;AACV,2BAAa,EAAE,SAAS,CAAC,IAAI,OAAO,CAAC,GAAG,OAAO,MAAM;AACrD,wBAAU;AAAA,YACZ,WAAW,OAAO,YAAY;AAC5B,2BAAa,EAAE,SAAS,CAAC,GAAG,OAAO,MAAM;AACzC,wBAAU;AACV,2BAAa,EAAE,SAAS,CAAC,GAAG,OAAO,MAAM;AACzC,wBAAU;AACV,2BAAa,EAAE,SAAS,CAAC,GAAG,OAAO,MAAM;AACzC,wBAAU;AACV,2BAAa,EAAE,SAAS,CAAC,GAAG,OAAO,MAAM;AACzC,wBAAU;AAAA,YACZ,WAAW,OAAO,SAAS;AACzB,4BAAc,EAAE,MAAM,CAAC,GAAG,OAAO,MAAM;AACvC,wBAAU;AACV,4BAAc,EAAE,MAAM,CAAC,GAAG,OAAO,MAAM;AACvC,wBAAU;AACV,4BAAc,EAAE,MAAM,CAAC,GAAG,OAAO,MAAM;AACvC,wBAAU;AAAA,YACZ;AAAA,UACF;AACA,kBAAQ,QAAQ;AAAA,QAClB;AACA,uBAAe,GAAG,IAAI;AAAA,MACxB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,eAAqB;AACnB,QAAI,MAAM,KAAK,IAAI;AAEnB,aAAS,QAAQ,KAAK,kBAAkB;AACtC,UAAI,KAAK,KAAK,iBAAiB,IAAI;AACnC,WAAK,iBAAiB,IAAI,IAAI,CAAC;AAC/B,UAAI,MAAM,KAAK,QAAQ,OAAO,CAAC,WAAW,OAAO,cAAc,OAAO,WAAW,IAAI,CAAC;AACtF,UAAI,IAAI,SAAS,GAAG;AAClB,YAAI,MAAM,GAAG,SAAS,GAAG;AACvB,cAAI,SAAS;AAAA,YACX,GAAG;AAAA,YACH,GAAG;AAAA;AAAA,YACH,GAAG,KAAK;AAAA,YACR,GAAG;AAAA,YACH,KAAK;AAAA,UACP;AACA,eAAK,UAAU,QAAQ,GAAG;AAAA,QAC5B;AAAA,MACF;AAEA,UAAI,KAAK,gBAAgB;AACvB,YAAI,IAAI,SAAS,GAAG;AAClB,cAAI,KAAK,KAAK,IAAI;AAClB,cAAI,UAAU,KAAK,mBAAmB,IAAI;AAC1C,cAAI,KAAK,KAAK,IAAI;AAClB,cAAI,SAAS;AAAA,YACX,GAAG;AAAA,YACH,GAAG;AAAA;AAAA,YACH,GAAG,KAAK;AAAA,YACR,GAAG;AAAA,YACH,OAAO;AAAA,UACT;AAEA,cAAI,KAAK,KAAK,IAAI;AAClB,eAAK,IAAI,iBAAiB,IAAI,oBAAoB,KAAG,EAAE,gBAAgB,KAAG,EAAE,IAAI;AAAA,QAClF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,kBAAkB,MAAc,IAAS,QAAa,MAAW,OAAkB;AACjF,SAAK,iBAAiB,IAAI,GAAG,KAAK,MAAM,IAAI,QAAQ,MAAM,KAAK,CAAC;AAAA,EAClE;AAAA,EAEA,eAAe,MAAc,IAAqB,UAAwB;AACxE,QAAI,MAAM,KAAK,UAAU,IAAI;AAC7B,QAAI,CAAC,KAAK;AAAE;AAAA,IAAO;AACnB,QAAI,WAAW,IAAI;AACnB,QAAI,CAAC,UAAU;AAAE;AAAA,IAAO;AACxB,QAAI,IAAI,SAAS,EAAE;AACnB,QAAI,CAAC,GAAG;AAAE;AAAA,IAAO;AACjB,MAAE,eAAa,QAAQ,IAAI;AAAA,EAE7B;AAAA;AAAA,EAMA,MAAM,cAAc,QAAoB,MAA0B;AAEhE,UAAM,iBAAiB,IAAI,KAAK,kBAAkB;AAAA,MAChD,YAAY;AAAA,QACV,EAAE,MAAM,+BAA+B;AAAA,QACvC,EAAE,MAAM,gCAAgC;AAAA,QACxC,EAAE,MAAM,yBAAyB;AAAA,MACnC;AAAA,MACA,sBAAsB;AAAA,IACxB,CAAC;AAED,WAAO,iBAAiB;AAExB,mBAAe,iBAAiB,CAAC,UAAe;AAC9C,UAAI,MAAM,WAAW;AAEnB,aAAK,KAAK,QAAQ;AAAA,UAChB,GAAG;AAAA,UACH,MAAM;AAAA,UACN,WAAW,MAAM;AAAA;AAAA,QACnB,CAAC;AAAA,MACH,OAAO;AAAA,MAEP;AAAA,IACF;AAEA,mBAAe,0BAA0B,MAAM;AAE7C,UAAI,eAAe,oBAAoB,aAAa;AAClD,eAAO,kBAAkB;AACzB,aAAK,IAAI,2CAA2C,OAAO,EAAE,EAAE;AAAA,MACjE,WACE,eAAe,oBAAoB,YACnC,eAAe,oBAAoB,kBACnC,eAAe,oBAAoB,UACnC;AACA,eAAO,kBAAkB;AACzB,aAAK,IAAI,gDAAgD,OAAO,EAAE,EAAE;AAAA,MACtE;AAAA,IACF;AAEA,mBAAe,4BAA4B,MAAM;AAAA,IAEjD;AAEA,mBAAe,6BAA6B,MAAM;AAEhD,UACE,eAAe,uBAAuB,eACtC,eAAe,uBAAuB,aACtC;AAAA,MAEF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,eAAe;AAAA,QACnB,IAAI,KAAK,sBAAsB,IAAI;AAAA,MACrC;AAGA,aAAO,cAAc,eAAe,kBAAkB,iBAAiB;AAAA,QACrE,SAAS;AAAA,QACT,gBAAgB;AAAA,MAClB,CAAC;AAED,aAAO,YAAY,SAAS,MAAM;AAGhC,YAAI;AACF,gBAAM,WAAW,EAAE,GAAG,QAAQ,SAAS,eAAe;AACtD,eAAK,QAAQ,QAAQ,QAAQ;AAAA,QAC/B,SAAS,GAAG;AACV,eAAK;AAAA,YACH,6CAA6C,OAAO,EAAE;AAAA,YACtD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO,YAAY,UAAU,MAAM;AACjC,aAAK,IAAI,uCAAuC,OAAO,EAAE,EAAE;AAAA,MAC7D;AAEA,aAAO,YAAY,UAAU,CAAC,UAAiB;AAC7C,aAAK,MAAM,sCAAsC,OAAO,EAAE,KAAK,KAAK;AAAA,MACtE;AAEA,aAAO,YAAY,YAAY,CAAC,UAAwB;AACtD,YAAI;AACF,gBAAMC,QAAO,OAAO,MAAM,IAAI;AAC9B,eAAK;AAAA,YACH,yCAAyC,OAAO,EAAE;AAAA,YAClDA;AAAA,UACF;AAAA,QAEF,SAAS,OAAO;AACd,eAAK;AAAA,YACH,2CAA2C,OAAO,EAAE;AAAA,YACpD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,YAAM,SAAS,MAAM,eAAe,aAAa;AACjD,YAAM,eAAe,oBAAoB,MAAM;AAG/C,WAAK,KAAK,QAAQ;AAAA,QAChB,GAAG;AAAA,QACH,MAAM,OAAO;AAAA,QACb,KAAK,OAAO;AAAA,MACd,CAAC;AAAA,IACH,SAAS,OAAO;AACd,WAAK;AAAA,QACH,2CAA2C,OAAO,EAAE;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,qBAAqB,QAAoB,MAA0B;AAEvE,QAAI;AACF,UAAI,OAAO,kBAAkB,KAAK,WAAW;AAC3C,cAAM,OAAO,eAAe;AAAA,UAC1B,KAAK;AAAA;AAAA,QAEP;AAAA,MAEF,OAAO;AAAA,MAEP;AAAA,IACF,SAAS,OAAO;AACd,WAAK,MAAM,8CAA8C,OAAO,EAAE,EAAE;AAAA,IACtE;AAAA,EACF;AAAA,EAEA,eAAe,QAA6B;AAC1C,WAAO,OAAO,gBAAgB,QAAQ,OAAO,gBAAgB,UAAa,OAAO,YAAY,eAAe;AAAA,EAC9G;AAAA,EAEA,MAAM,QAAQ,QAAoB,SAA6B;AAC7D,QAAI,OAAO,OAAO,OAAO;AACzB,QAAI,KAAK,kBAAkB;AACzB,aAAO,MAAM,SAAS,IAAI;AAAA,IAC5B;AACA,SAAK,MAAM,WAAW,KAAK;AAC3B,SAAK,MAAM,kBAAkB,KAAK;AAElC,QAAI,WAAW,KAAK,iBAAiB,IAAI;AAEzC,QAAI,KAAK,iBAAiB;AACxB,iBAAW,MAAM;AACf,YAAI,KAAK,eAAe,MAAM,GAAG;AAC/B,mBAAS,QAAQ,CAAC,MAAM;AACtB,mBAAO,YAAa,KAAK,CAAC;AAAA,UAC5B,CAAC;AAAA,QACH;AAAA,MACF,GAAG,KAAK,eAAe;AAAA,IACzB,OAAO;AACL,UAAI,KAAK,eAAe,MAAM,GAAG;AAC/B,iBAAS,QAAQ,CAAC,MAAM;AACtB,iBAAO,YAAa,KAAK,CAAC;AAAA,QAC5B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,SAAc,UAAwB,CAAC,GAAkB;AAC1E,QAAI,QAAQ,UAAU,GAAG;AACvB,gBAAU,KAAK;AAAA,IACjB;AACA,QAAI,KAAK,KAAK,IAAI;AAClB,QAAI,OAAO,OAAO,OAAO;AACzB,QAAI,KAAK,KAAK;AACd,QAAI,KAAK,KAAK,IAAI;AAClB,QAAI,KAAK,kBAAkB;AACzB,aAAO,MAAM,SAAS,IAAI;AAAA,IAC5B;AACA,QAAI,KAAK,KAAK,IAAI;AAGlB,QAAI,KAAK,SAAS,OAAO;AACvB,WAAK,IAAI,wBAAwB,EAAE,OAAO,KAAK,MAAM,MAAM,MAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,eAAe,KAAK,EAAE,kBAAkB,KAAK,EAAE,IAAI;AAAA,IACnJ;AAEA,QAAI,WAAW,KAAK,iBAAiB,IAAI;AAEzC,aAAS,UAAU,KAAK,SAAS;AAC/B,WAAK,MAAM,WAAW,KAAK;AAC3B,WAAK,MAAM,kBAAkB,KAAK;AAClC,UAAI,KAAK,iBAAiB;AACxB,mBAAW,MAAM;AACf,cAAI,OAAO,eAAe,OAAO,YAAY,eAAe,QAAQ;AAClE,qBAAS,QAAQ,CAAC,MAAM;AACtB,sBAAQ,aAAa,KAAK,CAAC;AAAA,YAC7B,CAAC;AAAA,UACH;AAAA,QACF,GAAG,KAAK,eAAe;AAAA,MACzB,OAAO;AACL,YAAI,OAAO,eAAe,OAAO,YAAY,eAAe,QAAQ;AAClE,mBAAS,QAAQ,CAAC,MAAM;AACtB,oBAAQ,aAAa,KAAK,CAAC;AAAA,UAC7B,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,iBAAiB,MAAgC;AAC/C,QAAI;AACJ,QAAI,KAAK,aAAa,OAAO;AAC3B,YAAM,MAAM,KAAK,IAAI;AACrB,WAAK,KAAK,2BAA2B,KAAK,UAAU,QAAQ;AAE5D,iBAAW,CAAC;AACZ,UAAI,SAAS;AACb,UAAI,MAAM,KAAK,SAAQ,MAAK;AAC5B,UAAI,MAAM;AAGV,aAAO,SAAS,KAAK,YAAY;AAC/B,cAAM,YAAY,KAAK,aAAa;AACpC,cAAM,YAAY,KAAK,IAAI,WAAW,gBAAgB;AACtD,cAAM,QAAQ,IAAI,WAAW,KAAK,QAAQ,QAAQ,SAAS;AAC3D,YAAI,WAAW;AAAA,UACb,GAAG;AAAA,UACH,GAAG;AAAA,UACH;AAAA,UACA;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AAAA,UACL,IAAI,KAAK;AAAA,UACT,MAAM;AAAA,UACN,MAAM,aAAa;AAAA,QACrB;AACA,iBAAS,KAAK,OAAO,QAAQ,CAAC;AAC9B,kBAAU;AACV;AAAA,MACF;AAEA,WAAK,IAAI,iCAAiC,SAAS,MAAM,WAAW;AAAA,IACtE,OAAO;AACL,iBAAW,CAAC,IAAI;AAChB,WAAK,IAAI,kBAAkB,KAAK,UAAU,QAAQ;AAAA,IACpD;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAOA,SAAiB;AACf,SAAK,UAAU,SAAS,EAAE;AAC1B,WAAO,KAAK,UAAU,SAAS,EAAE;AAAA,EACnC;AAAA,EAEA,MAAM,UAAyB;AAC7B,UAAM,KAAK,WAAW;AACtB,UAAM,KAAK,cAAc,SAAS;AAClC,QAAI,CAAC,KAAK,UAAU,SAAS,GAAG;AAC9B,WAAK,oBAAoB;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,MAAM,aAA4B;AAChC,SAAK,cAAc,IAAI,YAAY,KAAK,QAAQ;AAChD,QAAI;AACF,YAAM,KAAK,YAAY,QAAQ;AAC/B,WAAK,IAAI,sBAAsB;AAC/B,YAAM,KAAK,KAAK,YAAY,GAAG,KAAK,QAAQ;AAC5C,WAAK,KAAK;AAAA,IACZ,SAAS,OAAO;AACd,WAAK,MAAM,gCAAgC,KAAK;AAChD,WAAK,cAAc;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,MAA6B;AAC/C,SAAK,IAAI,qBAAqB,IAAI,gBAAgB;AAClD,QAAI,KAAK,IAAI;AACX,UAAI;AACF,cAAM,MAAM,MAAM,KAAK,GAAG,WAAW,KAAK,UAAU,EAAE,QAAQ;AAAA,UAC5D;AAAA,QACF,CAAC;AACD,YAAI,KAAK;AACP,iBAAQ,IAAY;AACpB,eAAK,UAAU,IAAI,IAAI;AAAA,QACzB;AAAA,MACF,SAAS,OAAO;AACd,aAAK,MAAM,wCAAwC,KAAK;AAAA,MAC1D;AAAA,IACF,OAAO;AACL,WAAK,KAAK,sDAAsD;AAAA,IAClE;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,MAA6B;AAC/C,QAAI,KAAK,IAAI;AACX,UAAI;AACF,cAAM,MAAM,KAAK,UAAU,IAAI;AAC/B,YAAI,SAAS,SAAS,KAAK,IAAI;AAC/B,aAAK,IAAI,oBAAoB,IAAI,cAAc;AAC/C,cAAM,KAAK,GAAG,WAAW,KAAK,UAAU,EAAE;AAAA,UACxC,EAAE,KAAW;AAAA,UACb,EAAE,MAAM,OAAO;AAAA,UACf,EAAE,QAAQ,KAAK;AAAA,QACjB;AACA,aAAK,IAAI,2BAA2B;AAAA,MACtC,SAAS,OAAO;AACd,aAAK,MAAM,qCAAqC,KAAK;AAAA,MACvD;AAAA,IACF,OAAO;AACL,WAAK,KAAK,qDAAqD;AAAA,IACjE;AAAA,EACF;AAAA,EAEA,MAAM,oBAAmC;AACvC,QAAI,CAAC,KAAK,WAAW;AACnB;AAAA,IACF;AACA,aAAS,QAAQ,KAAK,WAAW;AAC/B,YAAM,KAAK,cAAc,IAAI;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,sBAA4B;AAC1B,SAAK,UAAU,SAAS,IAAI;AAAA,MAC1B,SAAS;AAAA,IACX;AAAA,EACF;AAAA;AAAA,EAIA,YAAY,QAAsB;AAChC,QAAI,CAAC,KAAK,SAAS;AACjB,WAAK,IAAI,qCAAqC,MAAM;AACpD,WAAK,UAAU;AACf,oBAAc,KAAK,OAAO;AAC1B,WAAK,aAAa;AAClB,WAAK,UAAU,EAAE,QAAQ,aAAa,CAAC;AACvC,WAAK,kBAAkB;AACvB,WAAK,KAAM,MAAM;AACjB,iBAAW,MAAM,QAAQ,KAAK,CAAC,GAAG,GAAI;AAAA,IACxC;AAAA,EACF;AAAA;AAAA,EAGA,eAAqB;AAAA,EAAC;AACxB;","names":["key","data"]}
1
+ {"version":3,"sources":["../src/server.ts","../src/utils.ts","../src/compress-node.ts"],"sourcesContent":["import * as https from 'node:https'\nimport * as fs from 'node:fs'\nimport {\n reactive,\n deepGet,\n clonewo_,\n opmsg,\n msgop,\n encode_uint32,\n encode_fp412,\n encode_fp168,\n encode_fp1616,\n limitPrecision,\n encode,\n decode\n} from './utils'\nimport { compress, decompress } from './compress-node'\nimport fastjsonpatch from 'fast-json-patch'\nimport { WebSocketServer, WebSocket } from 'ws'\nimport { MongoClient, Db } from 'mongodb'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\nimport wrtc from '@roamhq/wrtc' // Server-side WebRTC implementation\n\nglMatrix.setMatrixArrayType(Array)\n\n// entities/ID/\nconst fastPatchProperties: Record<string, boolean> = {\n 'type': true, // string 'enemy'\n 'status': true, // string 'idle'\n 'level': true, // number 2\n 'race': true, // string 'goblin'\n 'class': true, // string 'warrior'\n 'model': true, // string 'models/models.glb|goblin'\n 'animation': true, // string 'idle2'\n 'sound': true, // string 'sound/goblin.snd|snarl'\n 'effect': true, // 'selected'\n 'position': true, // [0, 0, 0] Vector (Number)\n 'rotation': true, // [0, 0, 0, 1] Quaternion (Number)\n 'scale': true, // [1, 1, 1] Vector (Number)\n}\n\nconst dictionaryProperties: Record<string, boolean> = {\n 'type': true,\n 'status': true,\n 'level': true,\n 'race': true,\n 'class': true,\n 'model': true,\n 'animation': true,\n 'sound': true,\n 'effect': true,\n}\n\nconst { applyOperation } = fastjsonpatch\nconst LITTLE_ENDIAN = (() => {\n const buffer = new ArrayBuffer(2)\n new DataView(buffer).setInt16(0, 256, true)\n return new Int16Array(buffer)[0] === 256\n})()\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\n\ntype ClientType = any\n\ninterface StatsType {\n tUpdate: number[]\n tPatch: number[]\n send: number\n sendRTC: number\n _sendRTCUpdate: number\n [key: string]: any\n}\n\nexport default class TopazCubeServer {\n name = 'TopazCubeServer'\n cycle = 100\n patchCycleDivider = 1\n port = 8799\n useHttps = false\n key = './cert/key.pem'\n cert = './cert/cert.pem'\n MongoUrl = 'mongodb://localhost:27017'\n mongoClient: MongoClient | null = null\n DB: Db | null = null\n database = 'topazcube'\n collection = 'documents'\n allowSave = true\n allowSync = true\n allowWebRTC = false\n allowFastPatch = false\n allowCompression = false\n simulateLatency = 0\n\n _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _loopiv: any = null\n _statsiv: any = null\n _stillUpdating = false\n stats: StatsType = {\n tUpdate: [],\n tPatch: [],\n send: 0,\n sendRTC: 0,\n _sendRTCUpdate: 0\n }\n\n _wss: WebSocketServer | null = null\n _exited = false\n\n log(...args: any[]) {\n console.log(this.name + ':', ...args);\n }\n\n warn(...args: any[]) {\n console.warn(this.name + ':', ...args);\n }\n\n error(...args: any[]) {\n console.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n port = 8799,\n useHttps = false,\n key = './cert/key.pem',\n cert = './cert/cert.pem',\n MongoUrl = 'mongodb://localhost:27017',\n database = 'topazcube',\n collection = 'documents',\n allowSave = true,\n allowSync = true,\n allowWebRTC = false,\n allowFastPatch = false,\n allowCompression = false,\n simulateLatency = 0,\n }: {\n name?: string\n cycle?: number\n port?: number\n useHttps?: boolean\n key?: string\n cert?: string\n MongoUrl?: string\n database?: string\n collection?: string\n allowSave?: boolean\n allowSync?: boolean\n allowWebRTC?: boolean\n allowFastPatch?: boolean\n allowCompression?: boolean\n simulateLatency?: number\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.port = port\n this.useHttps = useHttps\n this.key = key\n this.cert = cert\n this.MongoUrl = MongoUrl\n this.database = database\n this.collection = collection\n this.allowSave = allowSave\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.allowFastPatch = allowFastPatch\n this.allowCompression = allowCompression\n this.simulateLatency = simulateLatency\n\n this._initDB()\n\n if (useHttps) {\n let httpsServer: https.Server | null = https.createServer({\n key: fs.readFileSync(this.key),\n cert: fs.readFileSync(this.cert),\n }, (req, res) => {\n res.writeHead(200)\n res.end('<b>Hello World!</b>')\n }).listen(this.port)\n this._wss = new WebSocketServer({ server: httpsServer })\n httpsServer = null\n this.log(this.name + ' running on HTTPS port ' + this.port)\n } else {\n this._wss = new WebSocketServer({ port: this.port })\n this.log(this.name + ' running on port ' + this.port)\n }\n this._wss.on('connection', (client: WebSocket) => {\n this._onConnected(client)\n })\n\n process.stdin.resume()\n process.on('SIGINT', () => {\n this._exitSignal('SIGINT')\n })\n process.on('SIGQUIT', () => {\n this._exitSignal('SIGQUIT')\n })\n process.on('SIGTERM', () => {\n this._exitSignal('SIGTERM')\n })\n process.on('SIGUSR2', () => {\n this._exitSignal('SIGUSR2')\n })\n\n // Setup keypress handling for console input\n process.stdin.resume()\n process.stdin.setEncoding('utf8')\n\n process.stdin.on('data', (key: any) => {\n key = (''+key).trim()\n\n // ctrl-c ( end of text )\n if (key == '\\u0003') {\n this._exitSignal('SIGINT')\n return\n }\n\n // Process other keypresses\n this.log(`Key pressed: ${key}`)\n\n // Example: 's' to save all documents\n if (key == 's') {\n this.log('Saving all documents...')\n this._saveAllDocuments()\n }\n\n // Example: 'i' to print server info\n if (key == 'i') {\n this.log(\n `Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`\n )\n }\n })\n this._startLoop()\n }\n\n /*= DOCUMENTS ==============================================================*/\n\n // to be redefined. Called before a new document is created. Returns true if\n // the client has the right to create an empty document\n canCreate(client: ClientType, name: string): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is created\n // (returns an empty document)\n onCreate(name: string): any {\n return {\n data: {},\n }\n }\n\n // to be redefined. Called when a client wants to sync (modify) a document.\n // Returns true if the client has the right to sync that operation.\n canSync(client: ClientType, name: string, op: any): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is hydrated\n // (created, or loaded from db)\n async onHydrate(name: string, document: any): Promise<void> {\n document.__hydrated = true\n }\n\n _makeReactive(name: string): void {\n //this.log(`Making document '${name}' reactive`, this.documents[name])\n let ep: any = false\n if (this.allowFastPatch) {\n ep = fastPatchProperties\n }\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this),\n '',\n ep\n )\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n }\n\n _createEmptyDocument(name: string): void {\n let doc = this.onCreate(name)\n if (!doc) {\n return\n }\n this.documents[name] = doc\n }\n\n async _waitLoad(name: string): Promise<void> {\n if (this.isLoading[name]) {\n while (this.isLoading[name]) {\n await new Promise((resolve) => setTimeout(resolve, 50))\n }\n }\n }\n\n async _checkDocument(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n if (!this.documents[name]) {\n this.isLoading[name] = true\n await this._loadDocument(name)\n if (!this.documents[name] && this.canCreate(client, name)) {\n this._createEmptyDocument(name)\n }\n if (this.documents[name]) {\n this._makeReactive(name)\n this.onHydrate(name, this.documents[name])\n }\n this.isLoading[name] = false\n this._documentState[name] = {\n subscibers: 0,\n lastModified: Date.now(),\n }\n }\n }\n\n _updateAllDocumentsState(): void {\n for (let name in this.documents) {\n if (name != '_server') {\n let doc = this.documents[name]\n this._documentState[name].subscibers = 0\n for (let client of this.clients) {\n if (client.subscribed && client.subscribed[name]) {\n this._documentState[name].subscibers++\n }\n }\n }\n }\n }\n\n /*= UPDATE LOOP ============================================================*/\n\n // to be redefined. called every this.cycle ms\n onUpdate(name: string, doc: any, dt: number): void {}\n\n _startLoop(): void {\n this.lastUpdate = Date.now()\n this._loop()\n this._statsiv = setInterval(() => {\n this._doStats()\n }, 1000)\n }\n\n _loop(): void {\n let now = Date.now()\n let dtms = (now - this.lastUpdate)\n let dt = dtms / 1000.0 // Convert to seconds\n this.lastUpdate = now\n\n /*\n if (this._stillUpdating) {\n return\n }\n */\n this._stillUpdating = true\n for (let name in this.documents) {\n this.onUpdate(name, this.documents[name], dt)\n }\n let t1 = Date.now()\n this._stillUpdating = false\n let updateTime = t1 - now\n this.stats.tUpdate.push(updateTime)\n\n //this.log(`update ${this.update} patch: ${this.update % this.patchCycleDivider}`, )\n\n let patchTime = 0\n if (this.update % this.patchCycleDivider == 0) {\n this._sendPatches()\n let t2 = Date.now()\n patchTime = t2 - t1\n this.stats.tPatch.push(patchTime)\n if (this.allowFastPatch) {\n this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`, )\n }\n this.stats._sendRTCUpdate = 0\n }\n\n this.update++\n let endUpdate = Date.now()\n let totalUpdate = endUpdate - now\n\n setTimeout(() => {\n this._loop()\n }, Math.max(this.cycle - totalUpdate, 10))\n }\n\n _doStats(): void {\n for (let key in this.stats) {\n let i = this.stats[key]\n if (Array.isArray(i) && i.length > 0) {\n while (i.length > 60) {\n i.shift()\n }\n this.stats['_avg_' + key] = i.reduce((a: number, b: number) => a + b, 0) / i.length\n } else if (!key.startsWith('_')) {\n this.stats['_persec_' + key] = i / 3.0\n this.stats[key] = 0\n }\n }\n //this.log('stats', this.stats)\n }\n\n /*= MESSAGES ===============================================================*/\n\n // to be redefined. Called on message (operation) from client\n onMessage(client: ClientType, message: any): void {}\n\n // to be redefined. Called when a client connects\n onConnect(client: ClientType): void {}\n\n // to be redefined. Called when a client disconnects\n onDisconnect(client: ClientType): void {}\n\n _onConnected(client: ClientType): void {\n client.ID = this.getUID()\n client.ping = 0\n client.ctdiff = 0\n client.subscribed = {}\n client.dataChannel = null\n client.peerConnection = null\n\n this.log('client connected', client.ID)\n this.clients.push(client)\n client.on('error', (...args: any[]) => {\n this._onError(client, args)\n })\n client.on('message', (message:any) => {\n let dec = decode(message)\n if (this.simulateLatency) {\n setTimeout(() => {\n this._onMessage(client, dec)\n }, this.simulateLatency)\n } else {\n this._onMessage(client, dec)\n }\n })\n client.on('close', (message:any) => {\n this._onDisconnected(client)\n this.onDisconnect(client)\n })\n this.onConnect(client)\n }\n\n async _onMessage(client: ClientType, message: any): Promise<void> {\n if (\n message.c == 'sync' &&\n this.allowSync &&\n client.subscribed &&\n client.subscribed[message.n] &&\n this.documents[message.n]\n ) {\n let name = message.n\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n for (let op of message.p) {\n if (!this.canSync(client, name, op)) {\n continue\n }\n this._documentChanges[name].push(op)\n let dop = msgop(op)\n applyOperation(this.documents[name], dop)\n }\n } else if (message.c == 'ping') {\n this.send(client, {\n c: 'pong',\n t: Date.now(),\n ct: message.ct,\n ID: client.ID,\n })\n } else if (message.c == 'peng') {\n let time = Date.now()\n let ping = time - message.st\n client.ctdiff = message.ct + ping / 2 - time\n client.ping = ping\n //this.log(time, \"PENG ping, ctdiff\", message, ping, client.ctdiff, \"ms\")\n /*\n } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\n */\n } else if (message.c == 'sub') {\n await this._checkDocument(message.n, client)\n if (!this.documents[message.n]) {\n this.send(client, {\n c: 'error',\n t: Date.now(),\n message: 'Document not found',\n })\n return\n }\n if (client.subscribed) {\n client.subscribed[message.n] = true\n }\n this._sendFullState(message.n, client)\n } else if (message.c == 'unsub') {\n if (client.subscribed) {\n client.subscribed[message.n] = false\n }\n } else {\n this.onMessage(client, message)\n }\n }\n\n _onError(client: ClientType, args: any[]): void {\n this.error('onError:', args)\n }\n\n _onDisconnected(client: ClientType): void {\n if (client.dataChannel) {\n client.dataChannel.close()\n }\n if (client.peerConnection) {\n client.peerConnection.close()\n }\n this.log('client disconnected')\n let index = this.clients.indexOf(client)\n if (index !== -1) {\n this.clients.splice(index, 1)\n }\n }\n\n async send(client: ClientType, message: any): Promise<void> {\n try {\n let t1 = Date.now()\n let data = encode(message)\n let t2 = Date.now()\n let dl = data.byteLength\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n if (data.length > 4096) {\n this.log(`Big message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n } catch (e) {\n this.error('Error sending message:', e, message)\n }\n }\n\n async broadcast(message: object, clients: ClientType[] | false = false): Promise<void> {\n if (!clients) {\n clients = this.clients\n }\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n for (let client of this.clients) {\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n }\n }\n\n async _sendFullState(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n let excluded: any = '_'\n if (this.allowFastPatch) {\n excluded = fastPatchProperties\n }\n let doc = clonewo_(this.documents[name], excluded)\n limitPrecision(doc)\n let fdata: any = false\n if (this.allowFastPatch) {\n fdata = this._encodeFastChanges(name, false)\n }\n let fullState = {\n c: 'full',\n le: LITTLE_ENDIAN,\n t: Date.now(),\n n: name,\n doc: doc,\n fdata: fdata\n }\n this.send(client, fullState)\n }\n\n _encodeFastChanges(name: string, changesOnly = true): any {\n let doc = this.documents[name]\n if (!doc) { return false }\n let origin = this.documents[name].origin\n if (!origin) {\n origin = [0, 0, 0]\n this.documents[name].origin = origin\n }\n\n let entities = doc.entities\n let ids = Object.keys(entities)\n if (!entities) { return false }\n let count: Record<string, number> = {}\n let changed: any = {}\n let hasChanges: any = {}\n let dictionary: any = {}\n let encodedChanges: any = {}\n\n for (let key in fastPatchProperties) {\n if (changesOnly) {\n count[key] = 0\n changed[key] = {}\n hasChanges[key] = false\n } else {\n count[key] = ids.length\n changed[key] = {}\n hasChanges[key] = true\n }\n dictionary[key] = {}\n }\n\n // search for changes\n\n if (changesOnly) {\n for (let id in entities) {\n let e = entities[id]\n for (let key in fastPatchProperties) {\n if (e['__changed_' + key]) {\n changed[''+key][''+id] = true\n count[''+key] = parseInt(''+count[''+key]) + 1\n hasChanges[''+key] = true\n e['__changed_' + key] = false\n }\n }\n }\n } else {\n for (let id in entities) {\n for (let key in fastPatchProperties) {\n changed[''+key][''+id] = true\n }\n }\n }\n\n // create dictionaries\n\n let dictUID = 1\n for (let key in hasChanges) {\n if (hasChanges[key] && dictionaryProperties[key]) {\n for (let id in changed[key]) {\n let e = entities[id]\n let value = e[key]\n if (!dictionary[key][value]) {\n dictionary[key][value] = dictUID++\n }\n }\n }\n }\n\n this.log(\"--------------------------------------------------\")\n //this.log(\"changed\", changed)\n //this.log(\"count\", count)\n\n // create encoded changes\n //\n for (let key in hasChanges) {\n if (hasChanges[key]) {\n let size = parseInt(''+count[''+key])\n let encoded: any = {}\n if (dictionaryProperties[key]) {\n encoded.dict = dictionary[key]\n\n let pdata = new Uint8Array(size * 8)\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n let value = e[key]\n let did = parseInt(dictionary[key][value])\n encode_uint32(did, pdata, offset)\n offset += 4\n }\n encoded.pdata = pdata\n } else {\n\n let pdata: Uint8Array\n if (key == 'position') {\n pdata = new Uint8Array(size * 13)\n } else if (key == 'rotation') {\n pdata = new Uint8Array(size * 16)\n } else if (key == 'scale') {\n pdata = new Uint8Array(size * 16)\n } else {\n pdata = new Uint8Array(0)\n }\n\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n if (key == 'position') {\n encode_fp168(e.position[0] - origin[0], pdata, offset)\n offset += 3\n encode_fp168(e.position[1] - origin[1], pdata, offset)\n offset += 3\n encode_fp168(e.position[2] - origin[2], pdata, offset)\n offset += 3\n } else if (key == 'rotation') {\n encode_fp412(e.rotation[0], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[1], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[2], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[3], pdata, offset)\n offset += 2\n } else if (key == 'scale') {\n encode_fp1616(e.scale[0], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[1], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[2], pdata, offset)\n offset += 4\n }\n }\n encoded.pdata = pdata\n }\n encodedChanges[key] = encoded\n }\n }\n\n return encodedChanges\n }\n\n _sendPatches(): void {\n let now = Date.now()\n\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n this._documentChanges[name] = []\n let sus = this.clients.filter((client) => client.subscribed && client.subscribed[name])\n if (sus.length > 0) {\n if (dc && dc.length > 0) {\n let record = {\n c: 'patch',\n t: now, // server time\n u: this.update,\n n: name,\n doc: dc,\n }\n this.broadcast(record, sus)\n }\n }\n\n if (this.allowFastPatch) {\n if (sus.length > 0) {\n let t1 = Date.now()\n let changes = this._encodeFastChanges(name)\n let t2 = Date.now()\n let record = {\n c: 'fpatch',\n t: now, // server time\n u: this.update,\n n: name,\n fdata: changes\n }\n //this.broadcastRTC(record, sus)\n let t3 = Date.now()\n this.log(`_sendPatches: ${name} encode_changes: ${t2-t1}ms broadcast:${t3-t2}ms`)\n }\n }\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: any, value: any): void {\n this._documentChanges[name]?.push(opmsg(op, target, path, value))\n }\n\n propertyChange(name: string, id: string | number, property: string): void {\n let doc = this.documents[name]\n if (!doc) { return }\n let entities = doc.entities\n if (!entities) { return }\n let e = entities[id]\n if (!e) { return }\n e['__changed_'+property] = true\n //this.log('propertyChange', e)\n }\n\n\n /*= WEBRTC ===================================================================*/\n\n\n async _processOffer(client: ClientType, data: any): Promise<void> {\n //this.log(\"RTC: Offer received\", data);\n const peerConnection = new (wrtc as any).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 client.peerConnection = peerConnection\n\n peerConnection.onicecandidate = (event: any) => {\n if (event.candidate) {\n //this.log(\"RTC: ICE candidate generated\", event.candidate.candidate.substring(0, 50) + \"...\");\n this.send(client, {\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: event.candidate, // .toJSON()\n })\n } else {\n //this.log(\"RTC: ICE candidate gathering complete\");\n }\n }\n\n peerConnection.onconnectionstatechange = () => {\n //this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);\n if (peerConnection.connectionState === 'connected') {\n client.webRTCConnected = true\n this.log(`RTC: Connection established with client ${client.ID}`)\n } else if (\n peerConnection.connectionState === 'failed' ||\n peerConnection.connectionState === 'disconnected' ||\n peerConnection.connectionState === 'closed'\n ) {\n client.webRTCConnected = false\n this.log(`RTC: Connection failed or closed with client ${client.ID}`)\n }\n }\n\n peerConnection.onicegatheringstatechange = () => {\n //this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);\n }\n\n peerConnection.oniceconnectionstatechange = () => {\n //this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);\n if (\n peerConnection.iceConnectionState === 'connected' ||\n peerConnection.iceConnectionState === 'completed'\n ) {\n //this.log(`RTC: ICE connection established with client ${client.ID}`);\n }\n }\n\n try {\n await peerConnection.setRemoteDescription(\n new (wrtc as any).RTCSessionDescription(data)\n )\n //this.log(\"RTC: Remote description set successfully\");\n\n client.dataChannel = peerConnection.createDataChannel('serverchannel', {\n ordered: true,\n maxRetransmits: 1,\n })\n\n client.dataChannel.onopen = () => {\n //this.log(`RTC: Data channel opened for client ${client.ID}`);\n // Try sending a test message\n try {\n const testData = { c: 'test', message: 'Hello WebRTC' }\n this.sendRTC(client, testData)\n } catch (e) {\n this.error(\n `RTC: Error sending test message to client ${client.ID}`,\n e\n )\n }\n }\n\n client.dataChannel.onclose = () => {\n this.log(`RTC: Data channel closed for client ${client.ID}`)\n }\n\n client.dataChannel.onerror = (error: Event) => {\n this.error(`RTC: Data channel error for client ${client.ID}:`, error)\n }\n\n client.dataChannel.onmessage = (event: MessageEvent) => {\n try {\n const data = decode(event.data)\n this.log(\n `RTC: Data channel message from client ${client.ID}:`,\n data\n )\n //this.onMessage(client, data);\n } catch (error) {\n this.error(\n `RTC: Error decoding message from client ${client.ID}:`,\n error\n )\n }\n }\n\n // Create and send answer\n const answer = await peerConnection.createAnswer()\n await peerConnection.setLocalDescription(answer)\n\n //this.log(`RTC: Sending answer to client ${client.ID}`);\n this.send(client, {\n c: 'rtc-answer',\n type: answer.type,\n sdp: answer.sdp,\n })\n } catch (error) {\n this.error(\n `RTC: Error processing offer from client ${client.ID}:`,\n error\n )\n }\n }\n\n async _processICECandidate(client: ClientType, data: any): Promise<void> {\n //this.log(`RTC: Processing ICE candidate from client ${client.ID}`);\n try {\n if (client.peerConnection && data.candidate) {\n await client.peerConnection.addIceCandidate(\n data.candidate\n //new wrtc.RTCIceCandidate(data.candidate)\n )\n //this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);\n } else {\n //this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`);\n }\n } catch (error) {\n this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)\n }\n }\n\n _clientRTCOpen(client: ClientType): boolean {\n return client.dataChannel !== null && client.dataChannel !== undefined && client.dataChannel.readyState === 'open'\n }\n\n async sendRTC(client: ClientType, message: any): Promise<void> {\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n\n let packages = this._splitRTCMessage(data)\n\n if (this.simulateLatency) {\n setTimeout(() => {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }\n }\n\n async broadcastRTC(message: any, clients: ClientType[] = []): Promise<void> {\n if (clients.length == 0) {\n clients = this.clients\n }\n let t1 = Date.now()\n let data = encode(message)\n let dl = data.byteLength\n let t2 = Date.now()\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n\n\n if (data.length > 16384) {\n this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n\n let packages = this._splitRTCMessage(data)\n\n for (let client of this.clients) {\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }\n }\n }\n\n _splitRTCMessage(data: Uint8Array): Uint8Array[] {\n let packages: Uint8Array[]\n if (data.byteLength > 65535) {\n const now = Date.now()\n this.warn(`RTC: Message too large: ${data.byteLength} bytes`)\n // Split the message into smaller packages\n packages = [];\n let offset = 0;\n let mid = this.update +'-'+ now\n let seq = 0\n\n // Create subsequent packages if needed\n while (offset < data.byteLength) {\n const remaining = data.byteLength - offset;\n const chunkSize = Math.min(remaining, MAX_PACKAGE_SIZE);\n const chunk = new Uint8Array(data.buffer, offset, chunkSize);\n let cmessage = {\n c: 'chunk',\n t: now,\n mid: mid,\n seq: seq,\n ofs: offset,\n chs: chunkSize,\n ts: data.byteLength,\n data: chunk,\n last: remaining <= MAX_PACKAGE_SIZE,\n }\n packages.push(encode(cmessage))\n offset += chunkSize;\n seq++;\n }\n\n this.log(`RTC: Large message split into ${packages.length} packages`);\n } else {\n packages = [data]\n this.log(`RTC: Message - ${data.byteLength} bytes`)\n }\n return packages\n }\n\n\n /*= DATABASE =================================================================*/\n // properties (of the documents) that starts with __ are not saved to the database.\n // __properties are restored on hydration. (for example __physicsBody or __bigObject)\n\n getUID(): number {\n this.documents['_server'].nextUID++\n return this.documents['_server'].nextUID\n }\n\n async _initDB(): Promise<void> {\n await this._connectDB()\n await this._loadDocument('_server')\n if (!this.documents['_server']) {\n this._initServerDocument()\n }\n }\n\n async _connectDB(): Promise<void> {\n this.mongoClient = new MongoClient(this.MongoUrl)\n try {\n await this.mongoClient.connect()\n this.log('Connected to MongoDB')\n const db = this.mongoClient.db(this.database)\n this.DB = db\n } catch (error) {\n this.error('Error connecting to MongoDB:', error)\n this.mongoClient = null\n }\n }\n\n async _loadDocument(name: string): Promise<void> {\n this.log(`Loading document '${name}' from MongoDB`)\n if (this.DB) {\n try {\n const doc = await this.DB.collection(this.collection).findOne({\n name: name,\n })\n if (doc) {\n delete (doc as any)._id\n this.documents[name] = doc\n }\n } catch (error) {\n this.error('Error loading document from MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not loaded.')\n }\n }\n\n async _saveDocument(name: string): Promise<void> {\n if (this.DB) {\n try {\n const doc = this.documents[name]\n let newdoc = clonewo_(doc, '__')\n this.log(`Saving document '${name}' to MongoDB`)\n await this.DB.collection(this.collection).updateOne(\n { name: name },\n { $set: newdoc },\n { upsert: true }\n )\n this.log('Document saved to MongoDB')\n } catch (error) {\n this.error('Error saving document to MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not saved.')\n }\n }\n\n async _saveAllDocuments(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this.documents) {\n await this._saveDocument(name)\n }\n }\n\n _initServerDocument(): void {\n this.documents['_server'] = {\n nextUID: 100,\n }\n }\n\n /*= EXIT ===================================================================*/\n\n _exitSignal(signal: string): void {\n if (!this._exited) {\n this.log('\\nEXIT: Caught interrupt signal ' + signal)\n this._exited = true\n clearInterval(this._loopiv)\n this.onBeforeExit()\n this.broadcast({ server: 'Going down' })\n this._saveAllDocuments()\n this._wss!.close()\n setTimeout(() => process.exit(0), 1000)\n }\n }\n\n // To be redefined. Called BEFORE program exit, and saving all documents\n onBeforeExit(): void {}\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","import { promisify } from 'util'\nimport { gzip, gunzip, constants } from 'zlib'\n\nconst MIN_COMPRESSED_BUFFER_SIZE = 256\nconst MAX_COMPRESSED_BUFFER_SIZE = 999999\n\nconst lib_compress = promisify(gzip)\nconst lib_decompress = promisify(gunzip)\n\nexport async function compress(buffer:Uint8Array<ArrayBufferLike>) {\n if (buffer.byteLength <= MIN_COMPRESSED_BUFFER_SIZE || buffer.byteLength >= MAX_COMPRESSED_BUFFER_SIZE) return buffer\n try {\n let t1 = Date.now()\n let cbytes = await lib_compress(buffer, {\n level: constants.Z_BEST_SPEED\n })\n let t2 = Date.now()\n let cbuffer = Buffer.from(cbytes)\n let t3 = Date.now()\n\n //console.log(`Node compression ${buffer.byteLength} -> ${cbuffer.byteLength}, time: ${t2 - t1}ms`)\n\n return cbuffer\n } catch (error) {\n console.error('Error compressing buffer:', error)\n return buffer\n }\n}\n\nexport async function decompress(buffer:Uint8Array<ArrayBufferLike>) {\n try {\n let cbytes = await lib_decompress(buffer)\n let cbuffer = Buffer.from(cbytes)\n return cbuffer\n } catch (error) {\n console.error('Error decompressing buffer:', error)\n return buffer\n }\n}\n"],"mappings":"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","names":["key","data"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "topazcube",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "TopazCube is a real-time collaborative document editing, and multiplayer game library.",
5
5
  "author": "László Matuska @BitOfGold",
6
6
  "license": "Apache-2.0",
package/src/server.ts CHANGED
@@ -18,10 +18,10 @@ import { compress, decompress } from './compress-node'
18
18
  import fastjsonpatch from 'fast-json-patch'
19
19
  import { WebSocketServer, WebSocket } from 'ws'
20
20
  import { MongoClient, Db } from 'mongodb'
21
- import { doesNotThrow } from 'assert'
22
21
  import { glMatrix, vec3, quat } from 'gl-matrix'
22
+ import wrtc from '@roamhq/wrtc' // Server-side WebRTC implementation
23
+
23
24
  glMatrix.setMatrixArrayType(Array)
24
- const wrtc = require('@roamhq/wrtc') // Server-side WebRTC implementation
25
25
 
26
26
  // entities/ID/
27
27
  const fastPatchProperties: Record<string, boolean> = {
@@ -809,7 +809,7 @@ export default class TopazCubeServer {
809
809
 
810
810
  async _processOffer(client: ClientType, data: any): Promise<void> {
811
811
  //this.log("RTC: Offer received", data);
812
- const peerConnection = new wrtc.RTCPeerConnection({
812
+ const peerConnection = new (wrtc as any).RTCPeerConnection({
813
813
  iceServers: [
814
814
  { urls: 'stun:stun.l.google.com:19302' },
815
815
  { urls: 'stun:stun.cloudflare.com:3478' },
@@ -864,7 +864,7 @@ export default class TopazCubeServer {
864
864
 
865
865
  try {
866
866
  await peerConnection.setRemoteDescription(
867
- new wrtc.RTCSessionDescription(data)
867
+ new (wrtc as any).RTCSessionDescription(data)
868
868
  )
869
869
  //this.log("RTC: Remote description set successfully");
870
870