topazcube 0.1.29 → 0.1.30

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
@@ -331,6 +331,8 @@ var TopazCubeServer = class {
331
331
  DEBUG = false;
332
332
  name = "TopazCubeServer";
333
333
  cycle = 100;
334
+ saveCheckCycle = 1e3;
335
+ saveCycle = 1e4;
334
336
  patchCycleDivider = 1;
335
337
  port = 8799;
336
338
  useHttps = false;
@@ -357,6 +359,7 @@ var TopazCubeServer = class {
357
359
  update = 0;
358
360
  lastUpdate = 0;
359
361
  _saveiv = null;
362
+ _lastSave = {};
360
363
  _loopiv = null;
361
364
  _statsiv = null;
362
365
  _stillUpdating = false;
@@ -385,6 +388,8 @@ var TopazCubeServer = class {
385
388
  constructor({
386
389
  name = "TopazCubeServer",
387
390
  cycle = 100,
391
+ saveCheckCycle = 1e3,
392
+ saveCycle = 1e4,
388
393
  port = 8799,
389
394
  useHttps = false,
390
395
  key = "./cert/key.pem",
@@ -402,6 +407,8 @@ var TopazCubeServer = class {
402
407
  } = {}) {
403
408
  this.name = name;
404
409
  this.cycle = cycle;
410
+ this.saveCheckCycle = saveCheckCycle;
411
+ this.saveCycle = saveCycle;
405
412
  this.port = port;
406
413
  this.useHttps = useHttps;
407
414
  this.key = key;
@@ -567,7 +574,7 @@ var TopazCubeServer = class {
567
574
  }, 1e3);
568
575
  this._saveiv = setInterval(() => {
569
576
  this._saveChanges();
570
- }, 6e4);
577
+ }, 1e3);
571
578
  }
572
579
  _loop() {
573
580
  let now = Date.now();
@@ -1277,9 +1284,17 @@ var TopazCubeServer = class {
1277
1284
  return;
1278
1285
  }
1279
1286
  for (let name in this._documentChanged) {
1287
+ if (!this._lastSave[name]) {
1288
+ this._lastSave[name] = Date.now() - 6e4;
1289
+ }
1290
+ let lastSave = this._lastSave[name];
1291
+ if (Date.now() - lastSave < 1e4) {
1292
+ continue;
1293
+ }
1280
1294
  if (this._documentChanged[name]) {
1281
1295
  await this._saveDocument(name);
1282
1296
  this._documentChanged[name] = false;
1297
+ this._lastSave[name] = Date.now();
1283
1298
  }
1284
1299
  }
1285
1300
  }
@@ -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 { glMatrix, vec3, quat } from 'gl-matrix'\nimport { RTCPeerConnection, RTCDataChannel, RTCSessionDescription } from \"werift\";\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 DEBUG = false\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 _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentChanged: Record<string, boolean> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _saveiv: any = null\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 if (this.DEBUG) {\n console.log(this.name + ':', ...args);\n }\n }\n\n warn(...args: any[]) {\n if (this.DEBUG) {\n console.warn(this.name + ':', ...args);\n }\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 DEBUG = false\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 DEBUG?: boolean\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 this.DEBUG = DEBUG\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 this._documentChanged[name] = false\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 this._saveiv = setInterval(() => {\n this._saveChanges()\n }, 60000)\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 this._documentChanged[name] = false\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 this._documentChanged[name] = true\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 } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\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 this._documentChanged[name] = true\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 if (!this.allowWebRTC) {\n this.warn('WebRTC is disabled')\n return\n }\n\n this.log(\"RTC: Processing offer from client\", client.ID, data);\n\n const peerConnection = new RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n //iceCandidatePoolSize: 10,\n })\n\n 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 this.log(\"RTC: Remote description set from data\", data);\n await peerConnection.setRemoteDescription(\n //data\n new RTCSessionDescription(data.sdp, data.type)\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 (data.candidate && typeof(data.candidate) == 'object') {\n data.candidate = data.candidate.candidate\n }\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`, client.peerConnection, data);\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 async _saveChanges(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this._documentChanged) {\n if (this._documentChanged[name]) {\n await this._saveDocument(name)\n this._documentChanged[name] = false\n }\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 clearInterval(this._statsiv)\n clearInterval(this._saveiv)\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 { RTCPeerConnection, RTCDataChannel, RTCSessionDescription } from \"werift\";\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 DEBUG = false\n name = 'TopazCubeServer'\n cycle = 100\n saveCheckCycle = 1000\n saveCycle = 10000\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 _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentChanged: Record<string, boolean> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _saveiv: any = null\n _lastSave: Record<string, number> = {}\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 if (this.DEBUG) {\n console.log(this.name + ':', ...args);\n }\n }\n\n warn(...args: any[]) {\n if (this.DEBUG) {\n console.warn(this.name + ':', ...args);\n }\n }\n\n error(...args: any[]) {\n console.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n saveCheckCycle = 1000,\n saveCycle = 10000,\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 DEBUG = false\n }: {\n name?: string\n cycle?: number\n saveCheckCycle?: number\n saveCycle?: 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 DEBUG?: boolean\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.saveCheckCycle = saveCheckCycle\n this.saveCycle = saveCycle\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 this.DEBUG = DEBUG\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 this._documentChanged[name] = false\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 this._saveiv = setInterval(() => {\n this._saveChanges()\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 this._documentChanged[name] = false\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 this._documentChanged[name] = true\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 } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\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 this._documentChanged[name] = true\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 if (!this.allowWebRTC) {\n this.warn('WebRTC is disabled')\n return\n }\n\n this.log(\"RTC: Processing offer from client\", client.ID, data);\n\n const peerConnection = new RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n //iceCandidatePoolSize: 10,\n })\n\n 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 this.log(\"RTC: Remote description set from data\", data);\n await peerConnection.setRemoteDescription(\n //data\n new RTCSessionDescription(data.sdp, data.type)\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 (data.candidate && typeof(data.candidate) == 'object') {\n data.candidate = data.candidate.candidate\n }\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`, client.peerConnection, data);\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 async _saveChanges(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this._documentChanged) {\n if (!this._lastSave[name]) {\n this._lastSave[name] = Date.now() - 60000\n }\n let lastSave = this._lastSave[name]\n if (Date.now() - lastSave < 10000) {\n continue\n }\n if (this._documentChanged[name]) {\n await this._saveDocument(name)\n this._documentChanged[name] = false\n this._lastSave[name] = Date.now()\n }\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 clearInterval(this._statsiv)\n clearInterval(this._saveiv)\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"]}
package/dist/server.d.cts CHANGED
@@ -14,6 +14,8 @@ declare class TopazCubeServer {
14
14
  DEBUG: boolean;
15
15
  name: string;
16
16
  cycle: number;
17
+ saveCheckCycle: number;
18
+ saveCycle: number;
17
19
  patchCycleDivider: number;
18
20
  port: number;
19
21
  useHttps: boolean;
@@ -40,6 +42,7 @@ declare class TopazCubeServer {
40
42
  update: number;
41
43
  lastUpdate: number;
42
44
  _saveiv: any;
45
+ _lastSave: Record<string, number>;
43
46
  _loopiv: any;
44
47
  _statsiv: any;
45
48
  _stillUpdating: boolean;
@@ -49,9 +52,11 @@ declare class TopazCubeServer {
49
52
  log(...args: any[]): void;
50
53
  warn(...args: any[]): void;
51
54
  error(...args: any[]): void;
52
- constructor({ name, cycle, port, useHttps, key, cert, MongoUrl, database, collection, allowSave, allowSync, allowWebRTC, allowFastPatch, allowCompression, simulateLatency, DEBUG }?: {
55
+ constructor({ name, cycle, saveCheckCycle, saveCycle, port, useHttps, key, cert, MongoUrl, database, collection, allowSave, allowSync, allowWebRTC, allowFastPatch, allowCompression, simulateLatency, DEBUG }?: {
53
56
  name?: string;
54
57
  cycle?: number;
58
+ saveCheckCycle?: number;
59
+ saveCycle?: number;
55
60
  port?: number;
56
61
  useHttps?: boolean;
57
62
  key?: string;
package/dist/server.d.ts CHANGED
@@ -14,6 +14,8 @@ declare class TopazCubeServer {
14
14
  DEBUG: boolean;
15
15
  name: string;
16
16
  cycle: number;
17
+ saveCheckCycle: number;
18
+ saveCycle: number;
17
19
  patchCycleDivider: number;
18
20
  port: number;
19
21
  useHttps: boolean;
@@ -40,6 +42,7 @@ declare class TopazCubeServer {
40
42
  update: number;
41
43
  lastUpdate: number;
42
44
  _saveiv: any;
45
+ _lastSave: Record<string, number>;
43
46
  _loopiv: any;
44
47
  _statsiv: any;
45
48
  _stillUpdating: boolean;
@@ -49,9 +52,11 @@ declare class TopazCubeServer {
49
52
  log(...args: any[]): void;
50
53
  warn(...args: any[]): void;
51
54
  error(...args: any[]): void;
52
- constructor({ name, cycle, port, useHttps, key, cert, MongoUrl, database, collection, allowSave, allowSync, allowWebRTC, allowFastPatch, allowCompression, simulateLatency, DEBUG }?: {
55
+ constructor({ name, cycle, saveCheckCycle, saveCycle, port, useHttps, key, cert, MongoUrl, database, collection, allowSave, allowSync, allowWebRTC, allowFastPatch, allowCompression, simulateLatency, DEBUG }?: {
53
56
  name?: string;
54
57
  cycle?: number;
58
+ saveCheckCycle?: number;
59
+ saveCycle?: number;
55
60
  port?: number;
56
61
  useHttps?: boolean;
57
62
  key?: string;
package/dist/server.js CHANGED
@@ -297,6 +297,8 @@ var TopazCubeServer = class {
297
297
  DEBUG = false;
298
298
  name = "TopazCubeServer";
299
299
  cycle = 100;
300
+ saveCheckCycle = 1e3;
301
+ saveCycle = 1e4;
300
302
  patchCycleDivider = 1;
301
303
  port = 8799;
302
304
  useHttps = false;
@@ -323,6 +325,7 @@ var TopazCubeServer = class {
323
325
  update = 0;
324
326
  lastUpdate = 0;
325
327
  _saveiv = null;
328
+ _lastSave = {};
326
329
  _loopiv = null;
327
330
  _statsiv = null;
328
331
  _stillUpdating = false;
@@ -351,6 +354,8 @@ var TopazCubeServer = class {
351
354
  constructor({
352
355
  name = "TopazCubeServer",
353
356
  cycle = 100,
357
+ saveCheckCycle = 1e3,
358
+ saveCycle = 1e4,
354
359
  port = 8799,
355
360
  useHttps = false,
356
361
  key = "./cert/key.pem",
@@ -368,6 +373,8 @@ var TopazCubeServer = class {
368
373
  } = {}) {
369
374
  this.name = name;
370
375
  this.cycle = cycle;
376
+ this.saveCheckCycle = saveCheckCycle;
377
+ this.saveCycle = saveCycle;
371
378
  this.port = port;
372
379
  this.useHttps = useHttps;
373
380
  this.key = key;
@@ -533,7 +540,7 @@ var TopazCubeServer = class {
533
540
  }, 1e3);
534
541
  this._saveiv = setInterval(() => {
535
542
  this._saveChanges();
536
- }, 6e4);
543
+ }, 1e3);
537
544
  }
538
545
  _loop() {
539
546
  let now = Date.now();
@@ -1243,9 +1250,17 @@ var TopazCubeServer = class {
1243
1250
  return;
1244
1251
  }
1245
1252
  for (let name in this._documentChanged) {
1253
+ if (!this._lastSave[name]) {
1254
+ this._lastSave[name] = Date.now() - 6e4;
1255
+ }
1256
+ let lastSave = this._lastSave[name];
1257
+ if (Date.now() - lastSave < 1e4) {
1258
+ continue;
1259
+ }
1246
1260
  if (this._documentChanged[name]) {
1247
1261
  await this._saveDocument(name);
1248
1262
  this._documentChanged[name] = false;
1263
+ this._lastSave[name] = Date.now();
1249
1264
  }
1250
1265
  }
1251
1266
  }
@@ -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 { glMatrix, vec3, quat } from 'gl-matrix'\nimport { RTCPeerConnection, RTCDataChannel, RTCSessionDescription } from \"werift\";\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 DEBUG = false\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 _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentChanged: Record<string, boolean> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _saveiv: any = null\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 if (this.DEBUG) {\n console.log(this.name + ':', ...args);\n }\n }\n\n warn(...args: any[]) {\n if (this.DEBUG) {\n console.warn(this.name + ':', ...args);\n }\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 DEBUG = false\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 DEBUG?: boolean\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 this.DEBUG = DEBUG\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 this._documentChanged[name] = false\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 this._saveiv = setInterval(() => {\n this._saveChanges()\n }, 60000)\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 this._documentChanged[name] = false\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 this._documentChanged[name] = true\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 } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\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 this._documentChanged[name] = true\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 if (!this.allowWebRTC) {\n this.warn('WebRTC is disabled')\n return\n }\n\n this.log(\"RTC: Processing offer from client\", client.ID, data);\n\n const peerConnection = new RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n //iceCandidatePoolSize: 10,\n })\n\n 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 this.log(\"RTC: Remote description set from data\", data);\n await peerConnection.setRemoteDescription(\n //data\n new RTCSessionDescription(data.sdp, data.type)\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 (data.candidate && typeof(data.candidate) == 'object') {\n data.candidate = data.candidate.candidate\n }\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`, client.peerConnection, data);\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 async _saveChanges(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this._documentChanged) {\n if (this._documentChanged[name]) {\n await this._saveDocument(name)\n this._documentChanged[name] = false\n }\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 clearInterval(this._statsiv)\n clearInterval(this._saveiv)\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;AACzC,SAAO,MAAM,KAAK,GAAG;AACzB;AAEO,SAAS,OAAO,MAAuB;AAC1C,SAAO,MAAM,OAAO,IAAI;AAC5B;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;AAChC,SAAS,gBAA4B;AACrC,SAAS,mBAAmC,6BAA6B;AAEzE,SAAS,mBAAmB,KAAK;AAGjC,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,QAAQ;AAAA,EACR,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,EAClB,WAAW;AAAA,EACX,UAAwB,CAAC;AAAA,EACzB,YAAiC,CAAC;AAAA,EAClC,YAAqC,CAAC;AAAA,EACtC,mBAA0C,CAAC;AAAA,EAC3C,mBAA4C,CAAC;AAAA,EAC7C,iBAAsC,CAAC;AAAA,EAEvC,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAe;AAAA,EACf,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;AAClB,QAAI,KAAK,OAAO;AACd,cAAQ,IAAI,KAAK,OAAO,KAAK,GAAG,IAAI;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,QAAQ,MAAa;AACnB,QAAI,KAAK,OAAO;AACd,cAAQ,KAAK,KAAK,OAAO,KAAK,GAAG,IAAI;AAAA,IACvC;AAAA,EACF;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,IAClB,QAAQ;AAAA,EACV,IAiBI,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;AACvB,SAAK,QAAQ;AAEb,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;AAC/B,WAAK,iBAAiB,IAAI,IAAI;AAAA,IAChC;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;AACP,SAAK,UAAU,YAAY,MAAM;AAC/B,WAAK,aAAa;AAAA,IACpB,GAAG,GAAK;AAAA,EACV;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;AAC/B,aAAK,iBAAiB,IAAI,IAAI;AAAA,MAChC;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,aAAK,iBAAiB,IAAI,IAAI;AAC9B,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,IAEhB,WAAW,QAAQ,KAAK,aAAa;AACnC,WAAK,cAAc,QAAQ,OAAO;AAAA,IACpC,WAAW,QAAQ,KAAK,iBAAiB;AACvC,WAAK,qBAAqB,QAAQ,OAAO;AAAA,IAC3C,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;AACA,eAAK,aAAa,QAAQ,GAAG;AAC7B,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;AAChE,SAAK,iBAAiB,IAAI,IAAI;AAAA,EAChC;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;AAChE,QAAI,CAAC,KAAK,aAAa;AACrB,WAAK,KAAK,oBAAoB;AAC9B;AAAA,IACF;AAEA,SAAK,IAAI,qCAAqC,OAAO,IAAI,IAAI;AAE7D,UAAM,iBAAiB,IAAI,kBAAkB;AAAA,MAC3C,YAAY;AAAA,QACV,EAAE,MAAM,+BAA+B;AAAA,QACvC,EAAE,MAAM,gCAAgC;AAAA,QACxC,EAAE,MAAM,yBAAyB;AAAA,MACnC;AAAA;AAAA,IAEF,CAAC;AAED,WAAO,iBAAiB;AAExB,mBAAe,iBAAiB,CAAC,UAAe;AAC9C,UAAI,MAAM,WAAW;AACnB,aAAK,IAAI,gCAAgC,MAAM,UAAU,UAAU,UAAU,GAAG,EAAE,IAAI,KAAK;AAC3F,aAAK,KAAK,QAAQ;AAAA,UAChB,GAAG;AAAA,UACH,MAAM;AAAA,UACN,WAAW,MAAM;AAAA;AAAA,QACnB,CAAC;AAAA,MACH,OAAO;AACL,aAAK,IAAI,uCAAuC;AAAA,MAClD;AAAA,IACF;AAEA,mBAAe,0BAA0B,MAAM;AAC7C,WAAK,IAAI,kCAAkC,eAAe,eAAe,EAAE;AAC3E,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;AAC/C,WAAK,IAAI,6BAA6B,eAAe,iBAAiB,EAAE;AAAA,IAC1E;AAEA,mBAAe,6BAA6B,MAAM;AAChD,WAAK,IAAI,8BAA8B,eAAe,kBAAkB,EAAE;AAC1E,UACE,eAAe,uBAAuB,eACtC,eAAe,uBAAuB,aACtC;AACA,aAAK,IAAI,+CAA+C,OAAO,EAAE,EAAE;AAAA,MACrE;AAAA,IACF;AAEA,QAAI;AACF,WAAK,IAAI,yCAAyC,IAAI;AACtD,YAAM,eAAe;AAAA;AAAA,QAEnB,IAAI,sBAAsB,KAAK,KAAK,KAAK,IAAI;AAAA,MAC/C;AACA,WAAK,IAAI,0CAA0C;AAEnD,aAAO,cAAc,eAAe,kBAAkB,iBAAiB;AAAA,QACrE,SAAS;AAAA,QACT,gBAAgB;AAAA,MAClB,CAAC;AAED,aAAO,YAAY,SAAS,MAAM;AAChC,aAAK,IAAI,uCAAuC,OAAO,EAAE,EAAE;AAE3D,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;AAE/C,WAAK,IAAI,iCAAiC,OAAO,EAAE,EAAE;AACrD,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;AACvE,SAAK,IAAI,6CAA6C,OAAO,EAAE,EAAE;AACjE,QAAI;AACF,UAAI,KAAK,aAAa,OAAO,KAAK,aAAc,UAAU;AACxD,aAAK,YAAY,KAAK,UAAU;AAAA,MAClC;AACA,UAAI,OAAO,kBAAkB,KAAK,WAAW;AAC3C,cAAM,OAAO,eAAe;AAAA,UAC1B,KAAK;AAAA;AAAA,QAEP;AACA,aAAK,IAAI,oDAAoD,OAAO,EAAE,EAAE;AAAA,MAC1E,OAAO;AACL,aAAK,KAAK,4CAA4C,OAAO,EAAE,oDAAoD,OAAO,gBAAgB,IAAI;AAAA,MAChJ;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,MAAM,eAA8B;AAClC,QAAI,CAAC,KAAK,WAAW;AACnB;AAAA,IACF;AACA,aAAS,QAAQ,KAAK,kBAAkB;AACtC,UAAI,KAAK,iBAAiB,IAAI,GAAG;AAC/B,cAAM,KAAK,cAAc,IAAI;AAC7B,aAAK,iBAAiB,IAAI,IAAI;AAAA,MAChC;AAAA,IACF;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,oBAAc,KAAK,QAAQ;AAC3B,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 { RTCPeerConnection, RTCDataChannel, RTCSessionDescription } from \"werift\";\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 DEBUG = false\n name = 'TopazCubeServer'\n cycle = 100\n saveCheckCycle = 1000\n saveCycle = 10000\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 _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentChanged: Record<string, boolean> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _saveiv: any = null\n _lastSave: Record<string, number> = {}\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 if (this.DEBUG) {\n console.log(this.name + ':', ...args);\n }\n }\n\n warn(...args: any[]) {\n if (this.DEBUG) {\n console.warn(this.name + ':', ...args);\n }\n }\n\n error(...args: any[]) {\n console.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n saveCheckCycle = 1000,\n saveCycle = 10000,\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 DEBUG = false\n }: {\n name?: string\n cycle?: number\n saveCheckCycle?: number\n saveCycle?: 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 DEBUG?: boolean\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.saveCheckCycle = saveCheckCycle\n this.saveCycle = saveCycle\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 this.DEBUG = DEBUG\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 this._documentChanged[name] = false\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 this._saveiv = setInterval(() => {\n this._saveChanges()\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 this._documentChanged[name] = false\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 this._documentChanged[name] = true\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 } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\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 this._documentChanged[name] = true\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 if (!this.allowWebRTC) {\n this.warn('WebRTC is disabled')\n return\n }\n\n this.log(\"RTC: Processing offer from client\", client.ID, data);\n\n const peerConnection = new RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n //iceCandidatePoolSize: 10,\n })\n\n 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 this.log(\"RTC: Remote description set from data\", data);\n await peerConnection.setRemoteDescription(\n //data\n new RTCSessionDescription(data.sdp, data.type)\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 (data.candidate && typeof(data.candidate) == 'object') {\n data.candidate = data.candidate.candidate\n }\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`, client.peerConnection, data);\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 async _saveChanges(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this._documentChanged) {\n if (!this._lastSave[name]) {\n this._lastSave[name] = Date.now() - 60000\n }\n let lastSave = this._lastSave[name]\n if (Date.now() - lastSave < 10000) {\n continue\n }\n if (this._documentChanged[name]) {\n await this._saveDocument(name)\n this._documentChanged[name] = false\n this._lastSave[name] = Date.now()\n }\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 clearInterval(this._statsiv)\n clearInterval(this._saveiv)\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.29",
3
+ "version": "0.1.30",
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
@@ -76,6 +76,8 @@ export default class TopazCubeServer {
76
76
  DEBUG = false
77
77
  name = 'TopazCubeServer'
78
78
  cycle = 100
79
+ saveCheckCycle = 1000
80
+ saveCycle = 10000
79
81
  patchCycleDivider = 1
80
82
  port = 8799
81
83
  useHttps = false
@@ -103,6 +105,7 @@ export default class TopazCubeServer {
103
105
  update = 0
104
106
  lastUpdate = 0
105
107
  _saveiv: any = null
108
+ _lastSave: Record<string, number> = {}
106
109
  _loopiv: any = null
107
110
  _statsiv: any = null
108
111
  _stillUpdating = false
@@ -136,6 +139,8 @@ export default class TopazCubeServer {
136
139
  constructor({
137
140
  name = 'TopazCubeServer',
138
141
  cycle = 100,
142
+ saveCheckCycle = 1000,
143
+ saveCycle = 10000,
139
144
  port = 8799,
140
145
  useHttps = false,
141
146
  key = './cert/key.pem',
@@ -153,6 +158,8 @@ export default class TopazCubeServer {
153
158
  }: {
154
159
  name?: string
155
160
  cycle?: number
161
+ saveCheckCycle?: number
162
+ saveCycle?: number
156
163
  port?: number
157
164
  useHttps?: boolean
158
165
  key?: string
@@ -170,6 +177,8 @@ export default class TopazCubeServer {
170
177
  } = {}) {
171
178
  this.name = name
172
179
  this.cycle = cycle
180
+ this.saveCheckCycle = saveCheckCycle
181
+ this.saveCycle = saveCycle
173
182
  this.port = port
174
183
  this.useHttps = useHttps
175
184
  this.key = key
@@ -362,7 +371,7 @@ export default class TopazCubeServer {
362
371
  }, 1000)
363
372
  this._saveiv = setInterval(() => {
364
373
  this._saveChanges()
365
- }, 60000)
374
+ }, 1000)
366
375
  }
367
376
 
368
377
  _loop(): void {
@@ -1167,9 +1176,17 @@ export default class TopazCubeServer {
1167
1176
  return
1168
1177
  }
1169
1178
  for (let name in this._documentChanged) {
1179
+ if (!this._lastSave[name]) {
1180
+ this._lastSave[name] = Date.now() - 60000
1181
+ }
1182
+ let lastSave = this._lastSave[name]
1183
+ if (Date.now() - lastSave < 10000) {
1184
+ continue
1185
+ }
1170
1186
  if (this._documentChanged[name]) {
1171
1187
  await this._saveDocument(name)
1172
1188
  this._documentChanged[name] = false
1189
+ this._lastSave[name] = Date.now()
1173
1190
  }
1174
1191
  }
1175
1192
  }