topazcube 0.1.13 → 0.1.14

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
@@ -365,13 +365,13 @@ var TopazCubeServer = class {
365
365
  _wss = null;
366
366
  _exited = false;
367
367
  log(...args) {
368
- this.log(this.name + ":", ...args);
368
+ console.log(this.name + ":", ...args);
369
369
  }
370
370
  warn(...args) {
371
- this.warn(this.name + ":", ...args);
371
+ console.warn(this.name + ":", ...args);
372
372
  }
373
373
  error(...args) {
374
- this.error(this.name + ":", ...args);
374
+ console.error(this.name + ":", ...args);
375
375
  }
376
376
  constructor({
377
377
  name = "TopazCubeServer",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/utils.ts","../src/compress-node.ts"],"sourcesContent":["import * as https from 'node:https'\nimport * as fs from 'node:fs'\nimport {\n reactive,\n deepGet,\n clonewo_,\n opmsg,\n msgop,\n encode_uint32,\n encode_fp412,\n encode_fp168,\n encode_fp1616,\n limitPrecision,\n encode,\n decode\n} from './utils'\nimport { compress, decompress } from './compress-node'\nimport fastjsonpatch from 'fast-json-patch'\nimport { WebSocketServer, WebSocket } from 'ws'\nimport { MongoClient, Db } from 'mongodb'\nimport { doesNotThrow } from 'assert'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\nglMatrix.setMatrixArrayType(Array)\n//import * as wrtc from '@roamhq/wrtc' // Server-side WebRTC implementation\n\n// entities/ID/\nconst fastPatchProperties: Record<string, boolean> = {\n 'type': true, // string 'enemy'\n 'status': true, // string 'idle'\n 'level': true, // number 2\n 'race': true, // string 'goblin'\n 'class': true, // string 'warrior'\n 'model': true, // string 'models/models.glb|goblin'\n 'animation': true, // string 'idle2'\n 'sound': true, // string 'sound/goblin.snd|snarl'\n 'effect': true, // 'selected'\n 'position': true, // [0, 0, 0] Vector (Number)\n 'rotation': true, // [0, 0, 0, 1] Quaternion (Number)\n 'scale': true, // [1, 1, 1] Vector (Number)\n}\n\nconst dictionaryProperties: Record<string, boolean> = {\n 'type': true,\n 'status': true,\n 'level': true,\n 'race': true,\n 'class': true,\n 'model': true,\n 'animation': true,\n 'sound': true,\n 'effect': true,\n}\n\nconst { applyOperation } = fastjsonpatch\nconst LITTLE_ENDIAN = (() => {\n const buffer = new ArrayBuffer(2)\n new DataView(buffer).setInt16(0, 256, true)\n return new Int16Array(buffer)[0] === 256\n})()\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\n\ntype ClientType = any\n\ninterface StatsType {\n tUpdate: number[]\n tPatch: number[]\n send: number\n sendRTC: number\n _sendRTCUpdate: number\n [key: string]: any\n}\n\nexport default class TopazCubeServer {\n name = 'TopazCubeServer'\n cycle = 100\n patchCycleDivider = 1\n port = 8799\n useHttps = false\n key = './cert/key.pem'\n cert = './cert/cert.pem'\n MongoUrl = 'mongodb://localhost:27017'\n mongoClient: MongoClient | null = null\n DB: Db | null = null\n database = 'topazcube'\n collection = 'documents'\n allowSave = true\n allowSync = true\n allowWebRTC = false\n allowFastPatch = false\n allowCompression = false\n simulateLatency = 0\n\n _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _loopiv: any = null\n _statsiv: any = null\n _stillUpdating = false\n stats: StatsType = {\n tUpdate: [],\n tPatch: [],\n send: 0,\n sendRTC: 0,\n _sendRTCUpdate: 0\n }\n\n _wss: WebSocketServer | null = null\n _exited = false\n\n log(...args: any[]) {\n this.log(this.name + ':', ...args);\n }\n\n warn(...args: any[]) {\n this.warn(this.name + ':', ...args);\n }\n\n error(...args: any[]) {\n this.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n port = 8799,\n useHttps = false,\n key = './cert/key.pem',\n cert = './cert/cert.pem',\n MongoUrl = 'mongodb://localhost:27017',\n database = 'topazcube',\n collection = 'documents',\n allowSave = true,\n allowSync = true,\n allowWebRTC = false,\n allowFastPatch = false,\n allowCompression = false,\n simulateLatency = 0,\n }: {\n name?: string\n cycle?: number\n port?: number\n useHttps?: boolean\n key?: string\n cert?: string\n MongoUrl?: string\n database?: string\n collection?: string\n allowSave?: boolean\n allowSync?: boolean\n allowWebRTC?: boolean\n allowFastPatch?: boolean\n allowCompression?: boolean\n simulateLatency?: number\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.port = port\n this.useHttps = useHttps\n this.key = key\n this.cert = cert\n this.MongoUrl = MongoUrl\n this.database = database\n this.collection = collection\n this.allowSave = allowSave\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.allowFastPatch = allowFastPatch\n this.allowCompression = allowCompression\n this.simulateLatency = simulateLatency\n\n this._initDB()\n\n if (useHttps) {\n let httpsServer: https.Server | null = https.createServer({\n key: fs.readFileSync(this.key),\n cert: fs.readFileSync(this.cert),\n }, (req, res) => {\n res.writeHead(200)\n res.end('<b>Hello World!</b>')\n }).listen(this.port)\n this._wss = new WebSocketServer({ server: httpsServer })\n httpsServer = null\n this.log(this.name + ' running on HTTPS port ' + this.port)\n } else {\n this._wss = new WebSocketServer({ port: this.port })\n this.log(this.name + ' running on port ' + this.port)\n }\n this._wss.on('connection', (client: WebSocket) => {\n this._onConnected(client)\n })\n\n process.stdin.resume()\n process.on('SIGINT', () => {\n this._exitSignal('SIGINT')\n })\n process.on('SIGQUIT', () => {\n this._exitSignal('SIGQUIT')\n })\n process.on('SIGTERM', () => {\n this._exitSignal('SIGTERM')\n })\n process.on('SIGUSR2', () => {\n this._exitSignal('SIGUSR2')\n })\n\n // Setup keypress handling for console input\n process.stdin.resume()\n process.stdin.setEncoding('utf8')\n\n process.stdin.on('data', (key: any) => {\n key = (''+key).trim()\n\n // ctrl-c ( end of text )\n if (key == '\\u0003') {\n this._exitSignal('SIGINT')\n return\n }\n\n // Process other keypresses\n this.log(`Key pressed: ${key}`)\n\n // Example: 's' to save all documents\n if (key == 's') {\n this.log('Saving all documents...')\n this._saveAllDocuments()\n }\n\n // Example: 'i' to print server info\n if (key == 'i') {\n this.log(\n `Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`\n )\n }\n })\n this._startLoop()\n }\n\n /*= DOCUMENTS ==============================================================*/\n\n // to be redefined. Called before a new document is created. Returns true if\n // the client has the right to create an empty document\n canCreate(client: ClientType, name: string): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is created\n // (returns an empty document)\n onCreate(name: string): any {\n return {\n data: {},\n }\n }\n\n // to be redefined. Called when a client wants to sync (modify) a document.\n // Returns true if the client has the right to sync that operation.\n canSync(client: ClientType, name: string, op: any): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is hydrated\n // (created, or loaded from db)\n async onHydrate(name: string, document: any): Promise<void> {\n document.__hydrated = true\n }\n\n _makeReactive(name: string): void {\n //this.log(`Making document '${name}' reactive`, this.documents[name])\n let ep: any = false\n if (this.allowFastPatch) {\n ep = fastPatchProperties\n }\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this),\n '',\n ep\n )\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n }\n\n _createEmptyDocument(name: string): void {\n let doc = this.onCreate(name)\n if (!doc) {\n return\n }\n this.documents[name] = doc\n }\n\n async _waitLoad(name: string): Promise<void> {\n if (this.isLoading[name]) {\n while (this.isLoading[name]) {\n await new Promise((resolve) => setTimeout(resolve, 50))\n }\n }\n }\n\n async _checkDocument(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n if (!this.documents[name]) {\n this.isLoading[name] = true\n await this._loadDocument(name)\n if (!this.documents[name] && this.canCreate(client, name)) {\n this._createEmptyDocument(name)\n }\n if (this.documents[name]) {\n this._makeReactive(name)\n this.onHydrate(name, this.documents[name])\n }\n this.isLoading[name] = false\n this._documentState[name] = {\n subscibers: 0,\n lastModified: Date.now(),\n }\n }\n }\n\n _updateAllDocumentsState(): void {\n for (let name in this.documents) {\n if (name != '_server') {\n let doc = this.documents[name]\n this._documentState[name].subscibers = 0\n for (let client of this.clients) {\n if (client.subscribed && client.subscribed[name]) {\n this._documentState[name].subscibers++\n }\n }\n }\n }\n }\n\n /*= UPDATE LOOP ============================================================*/\n\n // to be redefined. called every this.cycle ms\n onUpdate(name: string, doc: any, dt: number): void {}\n\n _startLoop(): void {\n this.lastUpdate = Date.now()\n this._loop()\n this._statsiv = setInterval(() => {\n this._doStats()\n }, 1000)\n }\n\n _loop(): void {\n let now = Date.now()\n let dtms = (now - this.lastUpdate)\n let dt = dtms / 1000.0 // Convert to seconds\n this.lastUpdate = now\n\n /*\n if (this._stillUpdating) {\n return\n }\n */\n this._stillUpdating = true\n for (let name in this.documents) {\n this.onUpdate(name, this.documents[name], dt)\n }\n let t1 = Date.now()\n this._stillUpdating = false\n let updateTime = t1 - now\n this.stats.tUpdate.push(updateTime)\n\n //this.log(`update ${this.update} patch: ${this.update % this.patchCycleDivider}`, )\n\n let patchTime = 0\n if (this.update % this.patchCycleDivider == 0) {\n this._sendPatches()\n let t2 = Date.now()\n patchTime = t2 - t1\n this.stats.tPatch.push(patchTime)\n if (this.allowFastPatch) {\n this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`, )\n }\n this.stats._sendRTCUpdate = 0\n }\n\n this.update++\n let endUpdate = Date.now()\n let totalUpdate = endUpdate - now\n\n setTimeout(() => {\n this._loop()\n }, Math.max(this.cycle - totalUpdate, 10))\n }\n\n _doStats(): void {\n for (let key in this.stats) {\n let i = this.stats[key]\n if (Array.isArray(i) && i.length > 0) {\n while (i.length > 60) {\n i.shift()\n }\n this.stats['_avg_' + key] = i.reduce((a: number, b: number) => a + b, 0) / i.length\n } else if (!key.startsWith('_')) {\n this.stats['_persec_' + key] = i / 3.0\n this.stats[key] = 0\n }\n }\n //this.log('stats', this.stats)\n }\n\n /*= MESSAGES ===============================================================*/\n\n // to be redefined. Called on message (operation) from client\n onMessage(client: ClientType, message: any): void {}\n\n // to be redefined. Called when a client connects\n onConnect(client: ClientType): void {}\n\n // to be redefined. Called when a client disconnects\n onDisconnect(client: ClientType): void {}\n\n _onConnected(client: ClientType): void {\n client.ID = this.getUID()\n client.ping = 0\n client.ctdiff = 0\n client.subscribed = {}\n client.dataChannel = null\n client.peerConnection = null\n\n this.log('client connected', client.ID)\n this.clients.push(client)\n client.on('error', () => {\n this._onError(client, arguments)\n })\n client.on('message', (message:any) => {\n let dec = decode(message)\n if (this.simulateLatency) {\n setTimeout(() => {\n this._onMessage(client, dec)\n }, this.simulateLatency)\n } else {\n this._onMessage(client, dec)\n }\n })\n client.on('close', (message:any) => {\n this._onDisconnected(client)\n this.onDisconnect(client)\n })\n this.onConnect(client)\n }\n\n async _onMessage(client: ClientType, message: any): Promise<void> {\n if (\n message.c == 'sync' &&\n this.allowSync &&\n client.subscribed &&\n client.subscribed[message.n] &&\n this.documents[message.n]\n ) {\n let name = message.n\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n for (let op of message.p) {\n if (!this.canSync(client, name, op)) {\n continue\n }\n this._documentChanges[name].push(op)\n let dop = msgop(op)\n applyOperation(this.documents[name], dop)\n }\n } else if (message.c == 'ping') {\n this.send(client, {\n c: 'pong',\n t: Date.now(),\n ct: message.ct,\n ID: client.ID,\n })\n } else if (message.c == 'peng') {\n let time = Date.now()\n let ping = time - message.st\n client.ctdiff = message.ct + ping / 2 - time\n client.ping = ping\n //this.log(time, \"PENG ping, ctdiff\", message, ping, client.ctdiff, \"ms\")\n /*\n } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\n */\n } else if (message.c == 'sub') {\n await this._checkDocument(message.n, client)\n if (!this.documents[message.n]) {\n this.send(client, {\n c: 'error',\n t: Date.now(),\n message: 'Document not found',\n })\n return\n }\n if (client.subscribed) {\n client.subscribed[message.n] = true\n }\n this._sendFullState(message.n, client)\n } else if (message.c == 'unsub') {\n if (client.subscribed) {\n client.subscribed[message.n] = false\n }\n } else {\n this.onMessage(client, message)\n }\n }\n\n _onError(client: ClientType, args: IArguments): void {\n this.error('onError:', args)\n }\n\n _onDisconnected(client: ClientType): void {\n if (client.dataChannel) {\n client.dataChannel.close()\n }\n if (client.peerConnection) {\n client.peerConnection.close()\n }\n this.log('client disconnected')\n let index = this.clients.indexOf(client)\n if (index !== -1) {\n this.clients.splice(index, 1)\n }\n }\n\n async send(client: ClientType, message: any): Promise<void> {\n try {\n let t1 = Date.now()\n let data = encode(message)\n let t2 = Date.now()\n let dl = data.byteLength\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n if (data.length > 4096) {\n this.log(`Big message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n } catch (e) {\n this.error('Error sending message:', e, message)\n }\n }\n\n async broadcast(message: object, clients: ClientType[] | false = false): Promise<void> {\n if (!clients) {\n clients = this.clients\n }\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n for (let client of this.clients) {\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n }\n }\n\n async _sendFullState(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n let excluded: any = '_'\n if (this.allowFastPatch) {\n excluded = fastPatchProperties\n }\n let doc = clonewo_(this.documents[name], excluded)\n limitPrecision(doc)\n let fdata: any = false\n if (this.allowFastPatch) {\n fdata = this._encodeFastChanges(name, false)\n }\n let fullState = {\n c: 'full',\n le: LITTLE_ENDIAN,\n t: Date.now(),\n n: name,\n doc: doc,\n fdata: fdata\n }\n this.send(client, fullState)\n }\n\n _encodeFastChanges(name: string, changesOnly = true): any {\n let doc = this.documents[name]\n if (!doc) { return false }\n let origin = this.documents[name].origin\n if (!origin) {\n origin = [0, 0, 0]\n this.documents[name].origin = origin\n }\n\n let entities = doc.entities\n let ids = Object.keys(entities)\n if (!entities) { return false }\n let count: Record<string, number> = {}\n let changed: any = {}\n let hasChanges: any = {}\n let dictionary: any = {}\n let encodedChanges: any = {}\n\n for (let key in fastPatchProperties) {\n if (changesOnly) {\n count[key] = 0\n changed[key] = {}\n hasChanges[key] = false\n } else {\n count[key] = ids.length\n changed[key] = {}\n hasChanges[key] = true\n }\n dictionary[key] = {}\n }\n\n // search for changes\n\n if (changesOnly) {\n for (let id in entities) {\n let e = entities[id]\n for (let key in fastPatchProperties) {\n if (e['__changed_' + key]) {\n changed[''+key][''+id] = true\n count[''+key] = parseInt(''+count[''+key]) + 1\n hasChanges[''+key] = true\n e['__changed_' + key] = false\n }\n }\n }\n } else {\n for (let id in entities) {\n for (let key in fastPatchProperties) {\n changed[''+key][''+id] = true\n }\n }\n }\n\n // create dictionaries\n\n let dictUID = 1\n for (let key in hasChanges) {\n if (hasChanges[key] && dictionaryProperties[key]) {\n for (let id in changed[key]) {\n let e = entities[id]\n let value = e[key]\n if (!dictionary[key][value]) {\n dictionary[key][value] = dictUID++\n }\n }\n }\n }\n\n this.log(\"--------------------------------------------------\")\n //this.log(\"changed\", changed)\n //this.log(\"count\", count)\n\n // create encoded changes\n //\n for (let key in hasChanges) {\n if (hasChanges[key]) {\n let size = parseInt(''+count[''+key])\n let encoded: any = {}\n if (dictionaryProperties[key]) {\n encoded.dict = dictionary[key]\n\n let pdata = new Uint8Array(size * 8)\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n let value = e[key]\n let did = parseInt(dictionary[key][value])\n encode_uint32(did, pdata, offset)\n offset += 4\n }\n encoded.pdata = pdata\n } else {\n\n let pdata: Uint8Array\n if (key == 'position') {\n pdata = new Uint8Array(size * 13)\n } else if (key == 'rotation') {\n pdata = new Uint8Array(size * 16)\n } else if (key == 'scale') {\n pdata = new Uint8Array(size * 16)\n } else {\n pdata = new Uint8Array(0)\n }\n\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n if (key == 'position') {\n encode_fp168(e.position[0] - origin[0], pdata, offset)\n offset += 3\n encode_fp168(e.position[1] - origin[1], pdata, offset)\n offset += 3\n encode_fp168(e.position[2] - origin[2], pdata, offset)\n offset += 3\n } else if (key == 'rotation') {\n encode_fp412(e.rotation[0], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[1], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[2], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[3], pdata, offset)\n offset += 2\n } else if (key == 'scale') {\n encode_fp1616(e.scale[0], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[1], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[2], pdata, offset)\n offset += 4\n }\n }\n encoded.pdata = pdata\n }\n encodedChanges[key] = encoded\n }\n }\n\n return encodedChanges\n }\n\n _sendPatches(): void {\n let now = Date.now()\n\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n this._documentChanges[name] = []\n let sus = this.clients.filter((client) => client.subscribed && client.subscribed[name])\n if (sus.length > 0) {\n if (dc && dc.length > 0) {\n let record = {\n c: 'patch',\n t: now, // server time\n u: this.update,\n n: name,\n doc: dc,\n }\n this.broadcast(record, sus)\n }\n }\n\n if (this.allowFastPatch) {\n if (sus.length > 0) {\n let t1 = Date.now()\n let changes = this._encodeFastChanges(name)\n let t2 = Date.now()\n let record = {\n c: 'fpatch',\n t: now, // server time\n u: this.update,\n n: name,\n fdata: changes\n }\n //this.broadcastRTC(record, sus)\n let t3 = Date.now()\n this.log(`_sendPatches: ${name} encode_changes: ${t2-t1}ms broadcast:${t3-t2}ms`)\n }\n }\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: any, value: any): void {\n this._documentChanges[name]?.push(opmsg(op, target, path, value))\n }\n\n propertyChange(name: string, id: string | number, property: string): void {\n let doc = this.documents[name]\n if (!doc) { return }\n let entities = doc.entities\n if (!entities) { return }\n let e = entities[id]\n if (!e) { return }\n e['__changed_'+property] = true\n //this.log('propertyChange', e)\n }\n\n\n /*= WEBRTC ===================================================================*/\n\n /*\n async _processOffer(client: ClientType, data: any): Promise<void> {\n //this.log(\"RTC: Offer received\", data);\n const peerConnection = new wrtc.RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n iceCandidatePoolSize: 10,\n })\n\n client.peerConnection = peerConnection\n\n peerConnection.onicecandidate = (event: any) => {\n if (event.candidate) {\n //this.log(\"RTC: ICE candidate generated\", event.candidate.candidate.substring(0, 50) + \"...\");\n this.send(client, {\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: event.candidate, // .toJSON()\n })\n } else {\n //this.log(\"RTC: ICE candidate gathering complete\");\n }\n }\n\n peerConnection.onconnectionstatechange = () => {\n //this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);\n if (peerConnection.connectionState === 'connected') {\n client.webRTCConnected = true\n this.log(`RTC: Connection established with client ${client.ID}`)\n } else if (\n peerConnection.connectionState === 'failed' ||\n peerConnection.connectionState === 'disconnected' ||\n peerConnection.connectionState === 'closed'\n ) {\n client.webRTCConnected = false\n this.log(`RTC: Connection failed or closed with client ${client.ID}`)\n }\n }\n\n peerConnection.onicegatheringstatechange = () => {\n //this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);\n }\n\n peerConnection.oniceconnectionstatechange = () => {\n //this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);\n if (\n peerConnection.iceConnectionState === 'connected' ||\n peerConnection.iceConnectionState === 'completed'\n ) {\n //this.log(`RTC: ICE connection established with client ${client.ID}`);\n }\n }\n\n try {\n await peerConnection.setRemoteDescription(\n new wrtc.RTCSessionDescription(data)\n )\n //this.log(\"RTC: Remote description set successfully\");\n\n client.dataChannel = peerConnection.createDataChannel('serverchannel', {\n ordered: true,\n maxRetransmits: 1,\n })\n\n client.dataChannel.onopen = () => {\n //this.log(`RTC: Data channel opened for client ${client.ID}`);\n // Try sending a test message\n try {\n const testData = { c: 'test', message: 'Hello WebRTC' }\n this.sendRTC(client, testData)\n } catch (e) {\n this.error(\n `RTC: Error sending test message to client ${client.ID}`,\n e\n )\n }\n }\n\n client.dataChannel.onclose = () => {\n this.log(`RTC: Data channel closed for client ${client.ID}`)\n }\n\n client.dataChannel.onerror = (error: Event) => {\n this.error(`RTC: Data channel error for client ${client.ID}:`, error)\n }\n\n client.dataChannel.onmessage = (event: MessageEvent) => {\n try {\n const data = decode(event.data)\n this.log(\n `RTC: Data channel message from client ${client.ID}:`,\n data\n )\n //this.onMessage(client, data);\n } catch (error) {\n this.error(\n `RTC: Error decoding message from client ${client.ID}:`,\n error\n )\n }\n }\n\n // Create and send answer\n const answer = await peerConnection.createAnswer()\n await peerConnection.setLocalDescription(answer)\n\n //this.log(`RTC: Sending answer to client ${client.ID}`);\n this.send(client, {\n c: 'rtc-answer',\n type: answer.type,\n sdp: answer.sdp,\n })\n } catch (error) {\n this.error(\n `RTC: Error processing offer from client ${client.ID}:`,\n error\n )\n }\n }\n\n async _processICECandidate(client: ClientType, data: any): Promise<void> {\n //this.log(`RTC: Processing ICE candidate from client ${client.ID}`);\n try {\n if (client.peerConnection && data.candidate) {\n await client.peerConnection.addIceCandidate(\n data.candidate\n //new wrtc.RTCIceCandidate(data.candidate)\n )\n //this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);\n } else {\n //this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`);\n }\n } catch (error) {\n this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)\n }\n }\n\n _clientRTCOpen(client: ClientType): boolean {\n return client.dataChannel !== null && client.dataChannel !== undefined && client.dataChannel.readyState === 'open'\n }\n\n async sendRTC(client: ClientType, message: any): Promise<void> {\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n\n let packages = this._splitRTCMessage(data)\n\n if (this.simulateLatency) {\n setTimeout(() => {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }\n }\n\n async broadcastRTC(message: any, clients: ClientType[] = []): Promise<void> {\n if (clients.length == 0) {\n clients = this.clients\n }\n let t1 = Date.now()\n let data = encode(message)\n let dl = data.byteLength\n let t2 = Date.now()\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n\n\n if (data.length > 16384) {\n this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n\n let packages = this._splitRTCMessage(data)\n\n for (let client of this.clients) {\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }\n }\n }\n\n _splitRTCMessage(data: Uint8Array): Uint8Array[] {\n let packages: Uint8Array[]\n if (data.byteLength > 65535) {\n const now = Date.now()\n this.warn(`RTC: Message too large: ${data.byteLength} bytes`)\n // Split the message into smaller packages\n packages = [];\n let offset = 0;\n let mid = this.update +'-'+ now\n let seq = 0\n\n // Create subsequent packages if needed\n while (offset < data.byteLength) {\n const remaining = data.byteLength - offset;\n const chunkSize = Math.min(remaining, MAX_PACKAGE_SIZE);\n const chunk = new Uint8Array(data.buffer, offset, chunkSize);\n let cmessage = {\n c: 'chunk',\n t: now,\n mid: mid,\n seq: seq,\n ofs: offset,\n chs: chunkSize,\n ts: data.byteLength,\n data: chunk,\n last: remaining <= MAX_PACKAGE_SIZE,\n }\n packages.push(encode(cmessage))\n offset += chunkSize;\n seq++;\n }\n\n this.log(`RTC: Large message split into ${packages.length} packages`);\n } else {\n packages = [data]\n this.log(`RTC: Message - ${data.byteLength} bytes`)\n }\n return packages\n }\n */\n\n /*= DATABASE =================================================================*/\n // properties (of the documents) that starts with __ are not saved to the database.\n // __properties are restored on hydration. (for example __physicsBody or __bigObject)\n\n getUID(): number {\n this.documents['_server'].nextUID++\n return this.documents['_server'].nextUID\n }\n\n async _initDB(): Promise<void> {\n await this._connectDB()\n await this._loadDocument('_server')\n if (!this.documents['_server']) {\n this._initServerDocument()\n }\n }\n\n async _connectDB(): Promise<void> {\n this.mongoClient = new MongoClient(this.MongoUrl)\n try {\n await this.mongoClient.connect()\n this.log('Connected to MongoDB')\n const db = this.mongoClient.db(this.database)\n this.DB = db\n } catch (error) {\n this.error('Error connecting to MongoDB:', error)\n this.mongoClient = null\n }\n }\n\n async _loadDocument(name: string): Promise<void> {\n this.log(`Loading document '${name}' from MongoDB`)\n if (this.DB) {\n try {\n const doc = await this.DB.collection(this.collection).findOne({\n name: name,\n })\n if (doc) {\n delete (doc as any)._id\n this.documents[name] = doc\n }\n } catch (error) {\n this.error('Error loading document from MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not loaded.')\n }\n }\n\n async _saveDocument(name: string): Promise<void> {\n if (this.DB) {\n try {\n const doc = this.documents[name]\n let newdoc = clonewo_(doc, '__')\n this.log(`Saving document '${name}' to MongoDB`)\n await this.DB.collection(this.collection).updateOne(\n { name: name },\n { $set: newdoc },\n { upsert: true }\n )\n this.log('Document saved to MongoDB')\n } catch (error) {\n this.error('Error saving document to MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not saved.')\n }\n }\n\n async _saveAllDocuments(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this.documents) {\n await this._saveDocument(name)\n }\n }\n\n _initServerDocument(): void {\n this.documents['_server'] = {\n nextUID: 100,\n }\n }\n\n /*= EXIT ===================================================================*/\n\n _exitSignal(signal: string): void {\n if (!this._exited) {\n this.log('\\nEXIT: Caught interrupt signal ' + signal)\n this._exited = true\n clearInterval(this._loopiv)\n this.onBeforeExit()\n this.broadcast({ server: 'Going down' })\n this._saveAllDocuments()\n this._wss!.close()\n setTimeout(() => process.exit(0), 1000)\n }\n }\n\n // To be redefined. Called BEFORE program exit, and saving all documents\n onBeforeExit(): void {}\n}\n","import { Packr } from 'msgpackr';\nimport { FLOAT32_OPTIONS } from 'msgpackr';\nconst { ALWAYS } = FLOAT32_OPTIONS;\n\nlet packr = new Packr({\n useFloat32: ALWAYS\n});\n\nexport function encode(obj: any): Uint8Array {\n return packr.pack(obj)\n}\n\nexport function decode(data: Uint8Array): any {\n return packr.unpack(data)\n}\n\ntype ReactiveCallback = (name: string, operation: string, target: any, path: string, value: any) => void;\n\nexport function reactive(name: string, object: any, callback: ReactiveCallback, path: string = '', excludedProperties: Record<string, boolean> | false = false): any {\n if (object === null || typeof object !== 'object') {\n //console.log('--- Type not object', typeof object)\n return object\n }\n\n function isReactive(p: string): boolean {\n let r = true\n if (p.startsWith('_')) {\n r = false\n }\n if (excludedProperties) {\n if (excludedProperties[p]) {\n r = false\n }\n }\n if (path == '/entities') {\n r = false\n }\n return r\n }\n\n for (const property in object) {\n if (isReactive(property)) {\n //console.log(`path '${path}', prop '${property}' is reactive`)\n object[property] = reactive(\n name,\n object[property],\n callback,\n path + '/' + property,\n excludedProperties\n )\n } else {\n //console.log(`--- path '${path}', property '${property}' is NOT reactive`)\n }\n }\n //console.log(`path '${path}' is reactive`)\n return new Proxy(object, {\n get(target: any, property: string | symbol, receiver: any): any { // ...arguments\n return Reflect.get(target, property, receiver)\n },\n set(target: any, property: string | symbol, value: any): boolean {\n let newvalue: any\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n newvalue = reactive(name, value, callback, pn, excludedProperties)\n callback(name, 'replace', target, pn, newvalue)\n } else {\n newvalue = value\n }\n return Reflect.set(target, property, newvalue)\n },\n deleteProperty(target: any, property: string | symbol): boolean {\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n callback(name, 'remove', target, pn, null)\n }\n delete target[property]\n return true\n },\n })\n\n}\n\nexport function deepGet(obj: any, path: string): any {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n for (let i = 0; i < len; i++) {\n if (obj[paths[i]!] == undefined) {\n return undefined\n } else {\n obj = obj[paths[i]!]\n }\n }\n return obj\n}\n\nexport function deepSet(obj: any, path: string, value: any): void {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n let i: number\n for (i = 0; i < len - 1; i++) {\n obj = obj[paths[i]!]\n }\n obj[paths[i]!] = value\n}\n\n// recursive clone oject, without properties that starts with _ (or __)\n\nexport function clonewo_(obj: any, excludeStart: string | Record<string, boolean> = '_'): any {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n\n function isExcluded(key: string): boolean {\n let e = false\n if (typeof (excludeStart) == 'string' && key.startsWith(excludeStart)) {\n e = true\n } else if (typeof(excludeStart) == 'object') {\n if (excludeStart[key] || key.startsWith('_')) {\n e = true\n }\n }\n return e\n }\n\n if (obj instanceof Map) {\n const mapClone = new Map()\n for (let [key, value] of obj) {\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"]}
1
+ {"version":3,"sources":["../src/server.ts","../src/utils.ts","../src/compress-node.ts"],"sourcesContent":["import * as https from 'node:https'\nimport * as fs from 'node:fs'\nimport {\n reactive,\n deepGet,\n clonewo_,\n opmsg,\n msgop,\n encode_uint32,\n encode_fp412,\n encode_fp168,\n encode_fp1616,\n limitPrecision,\n encode,\n decode\n} from './utils'\nimport { compress, decompress } from './compress-node'\nimport fastjsonpatch from 'fast-json-patch'\nimport { WebSocketServer, WebSocket } from 'ws'\nimport { MongoClient, Db } from 'mongodb'\nimport { doesNotThrow } from 'assert'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\nglMatrix.setMatrixArrayType(Array)\n//import * as wrtc from '@roamhq/wrtc' // Server-side WebRTC implementation\n\n// entities/ID/\nconst fastPatchProperties: Record<string, boolean> = {\n 'type': true, // string 'enemy'\n 'status': true, // string 'idle'\n 'level': true, // number 2\n 'race': true, // string 'goblin'\n 'class': true, // string 'warrior'\n 'model': true, // string 'models/models.glb|goblin'\n 'animation': true, // string 'idle2'\n 'sound': true, // string 'sound/goblin.snd|snarl'\n 'effect': true, // 'selected'\n 'position': true, // [0, 0, 0] Vector (Number)\n 'rotation': true, // [0, 0, 0, 1] Quaternion (Number)\n 'scale': true, // [1, 1, 1] Vector (Number)\n}\n\nconst dictionaryProperties: Record<string, boolean> = {\n 'type': true,\n 'status': true,\n 'level': true,\n 'race': true,\n 'class': true,\n 'model': true,\n 'animation': true,\n 'sound': true,\n 'effect': true,\n}\n\nconst { applyOperation } = fastjsonpatch\nconst LITTLE_ENDIAN = (() => {\n const buffer = new ArrayBuffer(2)\n new DataView(buffer).setInt16(0, 256, true)\n return new Int16Array(buffer)[0] === 256\n})()\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\n\ntype ClientType = any\n\ninterface StatsType {\n tUpdate: number[]\n tPatch: number[]\n send: number\n sendRTC: number\n _sendRTCUpdate: number\n [key: string]: any\n}\n\nexport default class TopazCubeServer {\n name = 'TopazCubeServer'\n cycle = 100\n patchCycleDivider = 1\n port = 8799\n useHttps = false\n key = './cert/key.pem'\n cert = './cert/cert.pem'\n MongoUrl = 'mongodb://localhost:27017'\n mongoClient: MongoClient | null = null\n DB: Db | null = null\n database = 'topazcube'\n collection = 'documents'\n allowSave = true\n allowSync = true\n allowWebRTC = false\n allowFastPatch = false\n allowCompression = false\n simulateLatency = 0\n\n _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _loopiv: any = null\n _statsiv: any = null\n _stillUpdating = false\n stats: StatsType = {\n tUpdate: [],\n tPatch: [],\n send: 0,\n sendRTC: 0,\n _sendRTCUpdate: 0\n }\n\n _wss: WebSocketServer | null = null\n _exited = false\n\n log(...args: any[]) {\n console.log(this.name + ':', ...args);\n }\n\n warn(...args: any[]) {\n console.warn(this.name + ':', ...args);\n }\n\n error(...args: any[]) {\n console.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n port = 8799,\n useHttps = false,\n key = './cert/key.pem',\n cert = './cert/cert.pem',\n MongoUrl = 'mongodb://localhost:27017',\n database = 'topazcube',\n collection = 'documents',\n allowSave = true,\n allowSync = true,\n allowWebRTC = false,\n allowFastPatch = false,\n allowCompression = false,\n simulateLatency = 0,\n }: {\n name?: string\n cycle?: number\n port?: number\n useHttps?: boolean\n key?: string\n cert?: string\n MongoUrl?: string\n database?: string\n collection?: string\n allowSave?: boolean\n allowSync?: boolean\n allowWebRTC?: boolean\n allowFastPatch?: boolean\n allowCompression?: boolean\n simulateLatency?: number\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.port = port\n this.useHttps = useHttps\n this.key = key\n this.cert = cert\n this.MongoUrl = MongoUrl\n this.database = database\n this.collection = collection\n this.allowSave = allowSave\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.allowFastPatch = allowFastPatch\n this.allowCompression = allowCompression\n this.simulateLatency = simulateLatency\n\n this._initDB()\n\n if (useHttps) {\n let httpsServer: https.Server | null = https.createServer({\n key: fs.readFileSync(this.key),\n cert: fs.readFileSync(this.cert),\n }, (req, res) => {\n res.writeHead(200)\n res.end('<b>Hello World!</b>')\n }).listen(this.port)\n this._wss = new WebSocketServer({ server: httpsServer })\n httpsServer = null\n this.log(this.name + ' running on HTTPS port ' + this.port)\n } else {\n this._wss = new WebSocketServer({ port: this.port })\n this.log(this.name + ' running on port ' + this.port)\n }\n this._wss.on('connection', (client: WebSocket) => {\n this._onConnected(client)\n })\n\n process.stdin.resume()\n process.on('SIGINT', () => {\n this._exitSignal('SIGINT')\n })\n process.on('SIGQUIT', () => {\n this._exitSignal('SIGQUIT')\n })\n process.on('SIGTERM', () => {\n this._exitSignal('SIGTERM')\n })\n process.on('SIGUSR2', () => {\n this._exitSignal('SIGUSR2')\n })\n\n // Setup keypress handling for console input\n process.stdin.resume()\n process.stdin.setEncoding('utf8')\n\n process.stdin.on('data', (key: any) => {\n key = (''+key).trim()\n\n // ctrl-c ( end of text )\n if (key == '\\u0003') {\n this._exitSignal('SIGINT')\n return\n }\n\n // Process other keypresses\n this.log(`Key pressed: ${key}`)\n\n // Example: 's' to save all documents\n if (key == 's') {\n this.log('Saving all documents...')\n this._saveAllDocuments()\n }\n\n // Example: 'i' to print server info\n if (key == 'i') {\n this.log(\n `Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`\n )\n }\n })\n this._startLoop()\n }\n\n /*= DOCUMENTS ==============================================================*/\n\n // to be redefined. Called before a new document is created. Returns true if\n // the client has the right to create an empty document\n canCreate(client: ClientType, name: string): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is created\n // (returns an empty document)\n onCreate(name: string): any {\n return {\n data: {},\n }\n }\n\n // to be redefined. Called when a client wants to sync (modify) a document.\n // Returns true if the client has the right to sync that operation.\n canSync(client: ClientType, name: string, op: any): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is hydrated\n // (created, or loaded from db)\n async onHydrate(name: string, document: any): Promise<void> {\n document.__hydrated = true\n }\n\n _makeReactive(name: string): void {\n //this.log(`Making document '${name}' reactive`, this.documents[name])\n let ep: any = false\n if (this.allowFastPatch) {\n ep = fastPatchProperties\n }\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this),\n '',\n ep\n )\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n }\n\n _createEmptyDocument(name: string): void {\n let doc = this.onCreate(name)\n if (!doc) {\n return\n }\n this.documents[name] = doc\n }\n\n async _waitLoad(name: string): Promise<void> {\n if (this.isLoading[name]) {\n while (this.isLoading[name]) {\n await new Promise((resolve) => setTimeout(resolve, 50))\n }\n }\n }\n\n async _checkDocument(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n if (!this.documents[name]) {\n this.isLoading[name] = true\n await this._loadDocument(name)\n if (!this.documents[name] && this.canCreate(client, name)) {\n this._createEmptyDocument(name)\n }\n if (this.documents[name]) {\n this._makeReactive(name)\n this.onHydrate(name, this.documents[name])\n }\n this.isLoading[name] = false\n this._documentState[name] = {\n subscibers: 0,\n lastModified: Date.now(),\n }\n }\n }\n\n _updateAllDocumentsState(): void {\n for (let name in this.documents) {\n if (name != '_server') {\n let doc = this.documents[name]\n this._documentState[name].subscibers = 0\n for (let client of this.clients) {\n if (client.subscribed && client.subscribed[name]) {\n this._documentState[name].subscibers++\n }\n }\n }\n }\n }\n\n /*= UPDATE LOOP ============================================================*/\n\n // to be redefined. called every this.cycle ms\n onUpdate(name: string, doc: any, dt: number): void {}\n\n _startLoop(): void {\n this.lastUpdate = Date.now()\n this._loop()\n this._statsiv = setInterval(() => {\n this._doStats()\n }, 1000)\n }\n\n _loop(): void {\n let now = Date.now()\n let dtms = (now - this.lastUpdate)\n let dt = dtms / 1000.0 // Convert to seconds\n this.lastUpdate = now\n\n /*\n if (this._stillUpdating) {\n return\n }\n */\n this._stillUpdating = true\n for (let name in this.documents) {\n this.onUpdate(name, this.documents[name], dt)\n }\n let t1 = Date.now()\n this._stillUpdating = false\n let updateTime = t1 - now\n this.stats.tUpdate.push(updateTime)\n\n //this.log(`update ${this.update} patch: ${this.update % this.patchCycleDivider}`, )\n\n let patchTime = 0\n if (this.update % this.patchCycleDivider == 0) {\n this._sendPatches()\n let t2 = Date.now()\n patchTime = t2 - t1\n this.stats.tPatch.push(patchTime)\n if (this.allowFastPatch) {\n this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`, )\n }\n this.stats._sendRTCUpdate = 0\n }\n\n this.update++\n let endUpdate = Date.now()\n let totalUpdate = endUpdate - now\n\n setTimeout(() => {\n this._loop()\n }, Math.max(this.cycle - totalUpdate, 10))\n }\n\n _doStats(): void {\n for (let key in this.stats) {\n let i = this.stats[key]\n if (Array.isArray(i) && i.length > 0) {\n while (i.length > 60) {\n i.shift()\n }\n this.stats['_avg_' + key] = i.reduce((a: number, b: number) => a + b, 0) / i.length\n } else if (!key.startsWith('_')) {\n this.stats['_persec_' + key] = i / 3.0\n this.stats[key] = 0\n }\n }\n //this.log('stats', this.stats)\n }\n\n /*= MESSAGES ===============================================================*/\n\n // to be redefined. Called on message (operation) from client\n onMessage(client: ClientType, message: any): void {}\n\n // to be redefined. Called when a client connects\n onConnect(client: ClientType): void {}\n\n // to be redefined. Called when a client disconnects\n onDisconnect(client: ClientType): void {}\n\n _onConnected(client: ClientType): void {\n client.ID = this.getUID()\n client.ping = 0\n client.ctdiff = 0\n client.subscribed = {}\n client.dataChannel = null\n client.peerConnection = null\n\n this.log('client connected', client.ID)\n this.clients.push(client)\n client.on('error', () => {\n this._onError(client, arguments)\n })\n client.on('message', (message:any) => {\n let dec = decode(message)\n if (this.simulateLatency) {\n setTimeout(() => {\n this._onMessage(client, dec)\n }, this.simulateLatency)\n } else {\n this._onMessage(client, dec)\n }\n })\n client.on('close', (message:any) => {\n this._onDisconnected(client)\n this.onDisconnect(client)\n })\n this.onConnect(client)\n }\n\n async _onMessage(client: ClientType, message: any): Promise<void> {\n if (\n message.c == 'sync' &&\n this.allowSync &&\n client.subscribed &&\n client.subscribed[message.n] &&\n this.documents[message.n]\n ) {\n let name = message.n\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n for (let op of message.p) {\n if (!this.canSync(client, name, op)) {\n continue\n }\n this._documentChanges[name].push(op)\n let dop = msgop(op)\n applyOperation(this.documents[name], dop)\n }\n } else if (message.c == 'ping') {\n this.send(client, {\n c: 'pong',\n t: Date.now(),\n ct: message.ct,\n ID: client.ID,\n })\n } else if (message.c == 'peng') {\n let time = Date.now()\n let ping = time - message.st\n client.ctdiff = message.ct + ping / 2 - time\n client.ping = ping\n //this.log(time, \"PENG ping, ctdiff\", message, ping, client.ctdiff, \"ms\")\n /*\n } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\n */\n } else if (message.c == 'sub') {\n await this._checkDocument(message.n, client)\n if (!this.documents[message.n]) {\n this.send(client, {\n c: 'error',\n t: Date.now(),\n message: 'Document not found',\n })\n return\n }\n if (client.subscribed) {\n client.subscribed[message.n] = true\n }\n this._sendFullState(message.n, client)\n } else if (message.c == 'unsub') {\n if (client.subscribed) {\n client.subscribed[message.n] = false\n }\n } else {\n this.onMessage(client, message)\n }\n }\n\n _onError(client: ClientType, args: IArguments): void {\n this.error('onError:', args)\n }\n\n _onDisconnected(client: ClientType): void {\n if (client.dataChannel) {\n client.dataChannel.close()\n }\n if (client.peerConnection) {\n client.peerConnection.close()\n }\n this.log('client disconnected')\n let index = this.clients.indexOf(client)\n if (index !== -1) {\n this.clients.splice(index, 1)\n }\n }\n\n async send(client: ClientType, message: any): Promise<void> {\n try {\n let t1 = Date.now()\n let data = encode(message)\n let t2 = Date.now()\n let dl = data.byteLength\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n if (data.length > 4096) {\n this.log(`Big message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n } catch (e) {\n this.error('Error sending message:', e, message)\n }\n }\n\n async broadcast(message: object, clients: ClientType[] | false = false): Promise<void> {\n if (!clients) {\n clients = this.clients\n }\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n for (let client of this.clients) {\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n }\n }\n\n async _sendFullState(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n let excluded: any = '_'\n if (this.allowFastPatch) {\n excluded = fastPatchProperties\n }\n let doc = clonewo_(this.documents[name], excluded)\n limitPrecision(doc)\n let fdata: any = false\n if (this.allowFastPatch) {\n fdata = this._encodeFastChanges(name, false)\n }\n let fullState = {\n c: 'full',\n le: LITTLE_ENDIAN,\n t: Date.now(),\n n: name,\n doc: doc,\n fdata: fdata\n }\n this.send(client, fullState)\n }\n\n _encodeFastChanges(name: string, changesOnly = true): any {\n let doc = this.documents[name]\n if (!doc) { return false }\n let origin = this.documents[name].origin\n if (!origin) {\n origin = [0, 0, 0]\n this.documents[name].origin = origin\n }\n\n let entities = doc.entities\n let ids = Object.keys(entities)\n if (!entities) { return false }\n let count: Record<string, number> = {}\n let changed: any = {}\n let hasChanges: any = {}\n let dictionary: any = {}\n let encodedChanges: any = {}\n\n for (let key in fastPatchProperties) {\n if (changesOnly) {\n count[key] = 0\n changed[key] = {}\n hasChanges[key] = false\n } else {\n count[key] = ids.length\n changed[key] = {}\n hasChanges[key] = true\n }\n dictionary[key] = {}\n }\n\n // search for changes\n\n if (changesOnly) {\n for (let id in entities) {\n let e = entities[id]\n for (let key in fastPatchProperties) {\n if (e['__changed_' + key]) {\n changed[''+key][''+id] = true\n count[''+key] = parseInt(''+count[''+key]) + 1\n hasChanges[''+key] = true\n e['__changed_' + key] = false\n }\n }\n }\n } else {\n for (let id in entities) {\n for (let key in fastPatchProperties) {\n changed[''+key][''+id] = true\n }\n }\n }\n\n // create dictionaries\n\n let dictUID = 1\n for (let key in hasChanges) {\n if (hasChanges[key] && dictionaryProperties[key]) {\n for (let id in changed[key]) {\n let e = entities[id]\n let value = e[key]\n if (!dictionary[key][value]) {\n dictionary[key][value] = dictUID++\n }\n }\n }\n }\n\n this.log(\"--------------------------------------------------\")\n //this.log(\"changed\", changed)\n //this.log(\"count\", count)\n\n // create encoded changes\n //\n for (let key in hasChanges) {\n if (hasChanges[key]) {\n let size = parseInt(''+count[''+key])\n let encoded: any = {}\n if (dictionaryProperties[key]) {\n encoded.dict = dictionary[key]\n\n let pdata = new Uint8Array(size * 8)\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n let value = e[key]\n let did = parseInt(dictionary[key][value])\n encode_uint32(did, pdata, offset)\n offset += 4\n }\n encoded.pdata = pdata\n } else {\n\n let pdata: Uint8Array\n if (key == 'position') {\n pdata = new Uint8Array(size * 13)\n } else if (key == 'rotation') {\n pdata = new Uint8Array(size * 16)\n } else if (key == 'scale') {\n pdata = new Uint8Array(size * 16)\n } else {\n pdata = new Uint8Array(0)\n }\n\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n if (key == 'position') {\n encode_fp168(e.position[0] - origin[0], pdata, offset)\n offset += 3\n encode_fp168(e.position[1] - origin[1], pdata, offset)\n offset += 3\n encode_fp168(e.position[2] - origin[2], pdata, offset)\n offset += 3\n } else if (key == 'rotation') {\n encode_fp412(e.rotation[0], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[1], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[2], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[3], pdata, offset)\n offset += 2\n } else if (key == 'scale') {\n encode_fp1616(e.scale[0], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[1], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[2], pdata, offset)\n offset += 4\n }\n }\n encoded.pdata = pdata\n }\n encodedChanges[key] = encoded\n }\n }\n\n return encodedChanges\n }\n\n _sendPatches(): void {\n let now = Date.now()\n\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n this._documentChanges[name] = []\n let sus = this.clients.filter((client) => client.subscribed && client.subscribed[name])\n if (sus.length > 0) {\n if (dc && dc.length > 0) {\n let record = {\n c: 'patch',\n t: now, // server time\n u: this.update,\n n: name,\n doc: dc,\n }\n this.broadcast(record, sus)\n }\n }\n\n if (this.allowFastPatch) {\n if (sus.length > 0) {\n let t1 = Date.now()\n let changes = this._encodeFastChanges(name)\n let t2 = Date.now()\n let record = {\n c: 'fpatch',\n t: now, // server time\n u: this.update,\n n: name,\n fdata: changes\n }\n //this.broadcastRTC(record, sus)\n let t3 = Date.now()\n this.log(`_sendPatches: ${name} encode_changes: ${t2-t1}ms broadcast:${t3-t2}ms`)\n }\n }\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: any, value: any): void {\n this._documentChanges[name]?.push(opmsg(op, target, path, value))\n }\n\n propertyChange(name: string, id: string | number, property: string): void {\n let doc = this.documents[name]\n if (!doc) { return }\n let entities = doc.entities\n if (!entities) { return }\n let e = entities[id]\n if (!e) { return }\n e['__changed_'+property] = true\n //this.log('propertyChange', e)\n }\n\n\n /*= WEBRTC ===================================================================*/\n\n /*\n async _processOffer(client: ClientType, data: any): Promise<void> {\n //this.log(\"RTC: Offer received\", data);\n const peerConnection = new wrtc.RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n iceCandidatePoolSize: 10,\n })\n\n client.peerConnection = peerConnection\n\n peerConnection.onicecandidate = (event: any) => {\n if (event.candidate) {\n //this.log(\"RTC: ICE candidate generated\", event.candidate.candidate.substring(0, 50) + \"...\");\n this.send(client, {\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: event.candidate, // .toJSON()\n })\n } else {\n //this.log(\"RTC: ICE candidate gathering complete\");\n }\n }\n\n peerConnection.onconnectionstatechange = () => {\n //this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);\n if (peerConnection.connectionState === 'connected') {\n client.webRTCConnected = true\n this.log(`RTC: Connection established with client ${client.ID}`)\n } else if (\n peerConnection.connectionState === 'failed' ||\n peerConnection.connectionState === 'disconnected' ||\n peerConnection.connectionState === 'closed'\n ) {\n client.webRTCConnected = false\n this.log(`RTC: Connection failed or closed with client ${client.ID}`)\n }\n }\n\n peerConnection.onicegatheringstatechange = () => {\n //this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);\n }\n\n peerConnection.oniceconnectionstatechange = () => {\n //this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);\n if (\n peerConnection.iceConnectionState === 'connected' ||\n peerConnection.iceConnectionState === 'completed'\n ) {\n //this.log(`RTC: ICE connection established with client ${client.ID}`);\n }\n }\n\n try {\n await peerConnection.setRemoteDescription(\n new wrtc.RTCSessionDescription(data)\n )\n //this.log(\"RTC: Remote description set successfully\");\n\n client.dataChannel = peerConnection.createDataChannel('serverchannel', {\n ordered: true,\n maxRetransmits: 1,\n })\n\n client.dataChannel.onopen = () => {\n //this.log(`RTC: Data channel opened for client ${client.ID}`);\n // Try sending a test message\n try {\n const testData = { c: 'test', message: 'Hello WebRTC' }\n this.sendRTC(client, testData)\n } catch (e) {\n this.error(\n `RTC: Error sending test message to client ${client.ID}`,\n e\n )\n }\n }\n\n client.dataChannel.onclose = () => {\n this.log(`RTC: Data channel closed for client ${client.ID}`)\n }\n\n client.dataChannel.onerror = (error: Event) => {\n this.error(`RTC: Data channel error for client ${client.ID}:`, error)\n }\n\n client.dataChannel.onmessage = (event: MessageEvent) => {\n try {\n const data = decode(event.data)\n this.log(\n `RTC: Data channel message from client ${client.ID}:`,\n data\n )\n //this.onMessage(client, data);\n } catch (error) {\n this.error(\n `RTC: Error decoding message from client ${client.ID}:`,\n error\n )\n }\n }\n\n // Create and send answer\n const answer = await peerConnection.createAnswer()\n await peerConnection.setLocalDescription(answer)\n\n //this.log(`RTC: Sending answer to client ${client.ID}`);\n this.send(client, {\n c: 'rtc-answer',\n type: answer.type,\n sdp: answer.sdp,\n })\n } catch (error) {\n this.error(\n `RTC: Error processing offer from client ${client.ID}:`,\n error\n )\n }\n }\n\n async _processICECandidate(client: ClientType, data: any): Promise<void> {\n //this.log(`RTC: Processing ICE candidate from client ${client.ID}`);\n try {\n if (client.peerConnection && data.candidate) {\n await client.peerConnection.addIceCandidate(\n data.candidate\n //new wrtc.RTCIceCandidate(data.candidate)\n )\n //this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);\n } else {\n //this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`);\n }\n } catch (error) {\n this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)\n }\n }\n\n _clientRTCOpen(client: ClientType): boolean {\n return client.dataChannel !== null && client.dataChannel !== undefined && client.dataChannel.readyState === 'open'\n }\n\n async sendRTC(client: ClientType, message: any): Promise<void> {\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n\n let packages = this._splitRTCMessage(data)\n\n if (this.simulateLatency) {\n setTimeout(() => {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }\n }\n\n async broadcastRTC(message: any, clients: ClientType[] = []): Promise<void> {\n if (clients.length == 0) {\n clients = this.clients\n }\n let t1 = Date.now()\n let data = encode(message)\n let dl = data.byteLength\n let t2 = Date.now()\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n\n\n if (data.length > 16384) {\n this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n\n let packages = this._splitRTCMessage(data)\n\n for (let client of this.clients) {\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }\n }\n }\n\n _splitRTCMessage(data: Uint8Array): Uint8Array[] {\n let packages: Uint8Array[]\n if (data.byteLength > 65535) {\n const now = Date.now()\n this.warn(`RTC: Message too large: ${data.byteLength} bytes`)\n // Split the message into smaller packages\n packages = [];\n let offset = 0;\n let mid = this.update +'-'+ now\n let seq = 0\n\n // Create subsequent packages if needed\n while (offset < data.byteLength) {\n const remaining = data.byteLength - offset;\n const chunkSize = Math.min(remaining, MAX_PACKAGE_SIZE);\n const chunk = new Uint8Array(data.buffer, offset, chunkSize);\n let cmessage = {\n c: 'chunk',\n t: now,\n mid: mid,\n seq: seq,\n ofs: offset,\n chs: chunkSize,\n ts: data.byteLength,\n data: chunk,\n last: remaining <= MAX_PACKAGE_SIZE,\n }\n packages.push(encode(cmessage))\n offset += chunkSize;\n seq++;\n }\n\n this.log(`RTC: Large message split into ${packages.length} packages`);\n } else {\n packages = [data]\n this.log(`RTC: Message - ${data.byteLength} bytes`)\n }\n return packages\n }\n */\n\n /*= DATABASE =================================================================*/\n // properties (of the documents) that starts with __ are not saved to the database.\n // __properties are restored on hydration. (for example __physicsBody or __bigObject)\n\n getUID(): number {\n this.documents['_server'].nextUID++\n return this.documents['_server'].nextUID\n }\n\n async _initDB(): Promise<void> {\n await this._connectDB()\n await this._loadDocument('_server')\n if (!this.documents['_server']) {\n this._initServerDocument()\n }\n }\n\n async _connectDB(): Promise<void> {\n this.mongoClient = new MongoClient(this.MongoUrl)\n try {\n await this.mongoClient.connect()\n this.log('Connected to MongoDB')\n const db = this.mongoClient.db(this.database)\n this.DB = db\n } catch (error) {\n this.error('Error connecting to MongoDB:', error)\n this.mongoClient = null\n }\n }\n\n async _loadDocument(name: string): Promise<void> {\n this.log(`Loading document '${name}' from MongoDB`)\n if (this.DB) {\n try {\n const doc = await this.DB.collection(this.collection).findOne({\n name: name,\n })\n if (doc) {\n delete (doc as any)._id\n this.documents[name] = doc\n }\n } catch (error) {\n this.error('Error loading document from MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not loaded.')\n }\n }\n\n async _saveDocument(name: string): Promise<void> {\n if (this.DB) {\n try {\n const doc = this.documents[name]\n let newdoc = clonewo_(doc, '__')\n this.log(`Saving document '${name}' to MongoDB`)\n await this.DB.collection(this.collection).updateOne(\n { name: name },\n { $set: newdoc },\n { upsert: true }\n )\n this.log('Document saved to MongoDB')\n } catch (error) {\n this.error('Error saving document to MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not saved.')\n }\n }\n\n async _saveAllDocuments(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this.documents) {\n await this._saveDocument(name)\n }\n }\n\n _initServerDocument(): void {\n this.documents['_server'] = {\n nextUID: 100,\n }\n }\n\n /*= EXIT ===================================================================*/\n\n _exitSignal(signal: string): void {\n if (!this._exited) {\n this.log('\\nEXIT: Caught interrupt signal ' + signal)\n this._exited = true\n clearInterval(this._loopiv)\n this.onBeforeExit()\n this.broadcast({ server: 'Going down' })\n this._saveAllDocuments()\n this._wss!.close()\n setTimeout(() => process.exit(0), 1000)\n }\n }\n\n // To be redefined. Called BEFORE program exit, and saving all documents\n onBeforeExit(): void {}\n}\n","import { Packr } from 'msgpackr';\nimport { FLOAT32_OPTIONS } from 'msgpackr';\nconst { ALWAYS } = FLOAT32_OPTIONS;\n\nlet packr = new Packr({\n useFloat32: ALWAYS\n});\n\nexport function encode(obj: any): Uint8Array {\n return packr.pack(obj)\n}\n\nexport function decode(data: Uint8Array): any {\n return packr.unpack(data)\n}\n\ntype ReactiveCallback = (name: string, operation: string, target: any, path: string, value: any) => void;\n\nexport function reactive(name: string, object: any, callback: ReactiveCallback, path: string = '', excludedProperties: Record<string, boolean> | false = false): any {\n if (object === null || typeof object !== 'object') {\n //console.log('--- Type not object', typeof object)\n return object\n }\n\n function isReactive(p: string): boolean {\n let r = true\n if (p.startsWith('_')) {\n r = false\n }\n if (excludedProperties) {\n if (excludedProperties[p]) {\n r = false\n }\n }\n if (path == '/entities') {\n r = false\n }\n return r\n }\n\n for (const property in object) {\n if (isReactive(property)) {\n //console.log(`path '${path}', prop '${property}' is reactive`)\n object[property] = reactive(\n name,\n object[property],\n callback,\n path + '/' + property,\n excludedProperties\n )\n } else {\n //console.log(`--- path '${path}', property '${property}' is NOT reactive`)\n }\n }\n //console.log(`path '${path}' is reactive`)\n return new Proxy(object, {\n get(target: any, property: string | symbol, receiver: any): any { // ...arguments\n return Reflect.get(target, property, receiver)\n },\n set(target: any, property: string | symbol, value: any): boolean {\n let newvalue: any\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n newvalue = reactive(name, value, callback, pn, excludedProperties)\n callback(name, 'replace', target, pn, newvalue)\n } else {\n newvalue = value\n }\n return Reflect.set(target, property, newvalue)\n },\n deleteProperty(target: any, property: string | symbol): boolean {\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n callback(name, 'remove', target, pn, null)\n }\n delete target[property]\n return true\n },\n })\n\n}\n\nexport function deepGet(obj: any, path: string): any {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n for (let i = 0; i < len; i++) {\n if (obj[paths[i]!] == undefined) {\n return undefined\n } else {\n obj = obj[paths[i]!]\n }\n }\n return obj\n}\n\nexport function deepSet(obj: any, path: string, value: any): void {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n let i: number\n for (i = 0; i < len - 1; i++) {\n obj = obj[paths[i]!]\n }\n obj[paths[i]!] = value\n}\n\n// recursive clone oject, without properties that starts with _ (or __)\n\nexport function clonewo_(obj: any, excludeStart: string | Record<string, boolean> = '_'): any {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n\n function isExcluded(key: string): boolean {\n let e = false\n if (typeof (excludeStart) == 'string' && key.startsWith(excludeStart)) {\n e = true\n } else if (typeof(excludeStart) == 'object') {\n if (excludeStart[key] || key.startsWith('_')) {\n e = true\n }\n }\n return e\n }\n\n if (obj instanceof Map) {\n const mapClone = new Map()\n for (let [key, value] of obj) {\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"]}
package/dist/server.js CHANGED
@@ -331,13 +331,13 @@ var TopazCubeServer = class {
331
331
  _wss = null;
332
332
  _exited = false;
333
333
  log(...args) {
334
- this.log(this.name + ":", ...args);
334
+ console.log(this.name + ":", ...args);
335
335
  }
336
336
  warn(...args) {
337
- this.warn(this.name + ":", ...args);
337
+ console.warn(this.name + ":", ...args);
338
338
  }
339
339
  error(...args) {
340
- this.error(this.name + ":", ...args);
340
+ console.error(this.name + ":", ...args);
341
341
  }
342
342
  constructor({
343
343
  name = "TopazCubeServer",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/utils.ts","../src/compress-node.ts"],"sourcesContent":["import * as https from 'node:https'\nimport * as fs from 'node:fs'\nimport {\n reactive,\n deepGet,\n clonewo_,\n opmsg,\n msgop,\n encode_uint32,\n encode_fp412,\n encode_fp168,\n encode_fp1616,\n limitPrecision,\n encode,\n decode\n} from './utils'\nimport { compress, decompress } from './compress-node'\nimport fastjsonpatch from 'fast-json-patch'\nimport { WebSocketServer, WebSocket } from 'ws'\nimport { MongoClient, Db } from 'mongodb'\nimport { doesNotThrow } from 'assert'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\nglMatrix.setMatrixArrayType(Array)\n//import * as wrtc from '@roamhq/wrtc' // Server-side WebRTC implementation\n\n// entities/ID/\nconst fastPatchProperties: Record<string, boolean> = {\n 'type': true, // string 'enemy'\n 'status': true, // string 'idle'\n 'level': true, // number 2\n 'race': true, // string 'goblin'\n 'class': true, // string 'warrior'\n 'model': true, // string 'models/models.glb|goblin'\n 'animation': true, // string 'idle2'\n 'sound': true, // string 'sound/goblin.snd|snarl'\n 'effect': true, // 'selected'\n 'position': true, // [0, 0, 0] Vector (Number)\n 'rotation': true, // [0, 0, 0, 1] Quaternion (Number)\n 'scale': true, // [1, 1, 1] Vector (Number)\n}\n\nconst dictionaryProperties: Record<string, boolean> = {\n 'type': true,\n 'status': true,\n 'level': true,\n 'race': true,\n 'class': true,\n 'model': true,\n 'animation': true,\n 'sound': true,\n 'effect': true,\n}\n\nconst { applyOperation } = fastjsonpatch\nconst LITTLE_ENDIAN = (() => {\n const buffer = new ArrayBuffer(2)\n new DataView(buffer).setInt16(0, 256, true)\n return new Int16Array(buffer)[0] === 256\n})()\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\n\ntype ClientType = any\n\ninterface StatsType {\n tUpdate: number[]\n tPatch: number[]\n send: number\n sendRTC: number\n _sendRTCUpdate: number\n [key: string]: any\n}\n\nexport default class TopazCubeServer {\n name = 'TopazCubeServer'\n cycle = 100\n patchCycleDivider = 1\n port = 8799\n useHttps = false\n key = './cert/key.pem'\n cert = './cert/cert.pem'\n MongoUrl = 'mongodb://localhost:27017'\n mongoClient: MongoClient | null = null\n DB: Db | null = null\n database = 'topazcube'\n collection = 'documents'\n allowSave = true\n allowSync = true\n allowWebRTC = false\n allowFastPatch = false\n allowCompression = false\n simulateLatency = 0\n\n _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _loopiv: any = null\n _statsiv: any = null\n _stillUpdating = false\n stats: StatsType = {\n tUpdate: [],\n tPatch: [],\n send: 0,\n sendRTC: 0,\n _sendRTCUpdate: 0\n }\n\n _wss: WebSocketServer | null = null\n _exited = false\n\n log(...args: any[]) {\n this.log(this.name + ':', ...args);\n }\n\n warn(...args: any[]) {\n this.warn(this.name + ':', ...args);\n }\n\n error(...args: any[]) {\n this.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n port = 8799,\n useHttps = false,\n key = './cert/key.pem',\n cert = './cert/cert.pem',\n MongoUrl = 'mongodb://localhost:27017',\n database = 'topazcube',\n collection = 'documents',\n allowSave = true,\n allowSync = true,\n allowWebRTC = false,\n allowFastPatch = false,\n allowCompression = false,\n simulateLatency = 0,\n }: {\n name?: string\n cycle?: number\n port?: number\n useHttps?: boolean\n key?: string\n cert?: string\n MongoUrl?: string\n database?: string\n collection?: string\n allowSave?: boolean\n allowSync?: boolean\n allowWebRTC?: boolean\n allowFastPatch?: boolean\n allowCompression?: boolean\n simulateLatency?: number\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.port = port\n this.useHttps = useHttps\n this.key = key\n this.cert = cert\n this.MongoUrl = MongoUrl\n this.database = database\n this.collection = collection\n this.allowSave = allowSave\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.allowFastPatch = allowFastPatch\n this.allowCompression = allowCompression\n this.simulateLatency = simulateLatency\n\n this._initDB()\n\n if (useHttps) {\n let httpsServer: https.Server | null = https.createServer({\n key: fs.readFileSync(this.key),\n cert: fs.readFileSync(this.cert),\n }, (req, res) => {\n res.writeHead(200)\n res.end('<b>Hello World!</b>')\n }).listen(this.port)\n this._wss = new WebSocketServer({ server: httpsServer })\n httpsServer = null\n this.log(this.name + ' running on HTTPS port ' + this.port)\n } else {\n this._wss = new WebSocketServer({ port: this.port })\n this.log(this.name + ' running on port ' + this.port)\n }\n this._wss.on('connection', (client: WebSocket) => {\n this._onConnected(client)\n })\n\n process.stdin.resume()\n process.on('SIGINT', () => {\n this._exitSignal('SIGINT')\n })\n process.on('SIGQUIT', () => {\n this._exitSignal('SIGQUIT')\n })\n process.on('SIGTERM', () => {\n this._exitSignal('SIGTERM')\n })\n process.on('SIGUSR2', () => {\n this._exitSignal('SIGUSR2')\n })\n\n // Setup keypress handling for console input\n process.stdin.resume()\n process.stdin.setEncoding('utf8')\n\n process.stdin.on('data', (key: any) => {\n key = (''+key).trim()\n\n // ctrl-c ( end of text )\n if (key == '\\u0003') {\n this._exitSignal('SIGINT')\n return\n }\n\n // Process other keypresses\n this.log(`Key pressed: ${key}`)\n\n // Example: 's' to save all documents\n if (key == 's') {\n this.log('Saving all documents...')\n this._saveAllDocuments()\n }\n\n // Example: 'i' to print server info\n if (key == 'i') {\n this.log(\n `Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`\n )\n }\n })\n this._startLoop()\n }\n\n /*= DOCUMENTS ==============================================================*/\n\n // to be redefined. Called before a new document is created. Returns true if\n // the client has the right to create an empty document\n canCreate(client: ClientType, name: string): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is created\n // (returns an empty document)\n onCreate(name: string): any {\n return {\n data: {},\n }\n }\n\n // to be redefined. Called when a client wants to sync (modify) a document.\n // Returns true if the client has the right to sync that operation.\n canSync(client: ClientType, name: string, op: any): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is hydrated\n // (created, or loaded from db)\n async onHydrate(name: string, document: any): Promise<void> {\n document.__hydrated = true\n }\n\n _makeReactive(name: string): void {\n //this.log(`Making document '${name}' reactive`, this.documents[name])\n let ep: any = false\n if (this.allowFastPatch) {\n ep = fastPatchProperties\n }\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this),\n '',\n ep\n )\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n }\n\n _createEmptyDocument(name: string): void {\n let doc = this.onCreate(name)\n if (!doc) {\n return\n }\n this.documents[name] = doc\n }\n\n async _waitLoad(name: string): Promise<void> {\n if (this.isLoading[name]) {\n while (this.isLoading[name]) {\n await new Promise((resolve) => setTimeout(resolve, 50))\n }\n }\n }\n\n async _checkDocument(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n if (!this.documents[name]) {\n this.isLoading[name] = true\n await this._loadDocument(name)\n if (!this.documents[name] && this.canCreate(client, name)) {\n this._createEmptyDocument(name)\n }\n if (this.documents[name]) {\n this._makeReactive(name)\n this.onHydrate(name, this.documents[name])\n }\n this.isLoading[name] = false\n this._documentState[name] = {\n subscibers: 0,\n lastModified: Date.now(),\n }\n }\n }\n\n _updateAllDocumentsState(): void {\n for (let name in this.documents) {\n if (name != '_server') {\n let doc = this.documents[name]\n this._documentState[name].subscibers = 0\n for (let client of this.clients) {\n if (client.subscribed && client.subscribed[name]) {\n this._documentState[name].subscibers++\n }\n }\n }\n }\n }\n\n /*= UPDATE LOOP ============================================================*/\n\n // to be redefined. called every this.cycle ms\n onUpdate(name: string, doc: any, dt: number): void {}\n\n _startLoop(): void {\n this.lastUpdate = Date.now()\n this._loop()\n this._statsiv = setInterval(() => {\n this._doStats()\n }, 1000)\n }\n\n _loop(): void {\n let now = Date.now()\n let dtms = (now - this.lastUpdate)\n let dt = dtms / 1000.0 // Convert to seconds\n this.lastUpdate = now\n\n /*\n if (this._stillUpdating) {\n return\n }\n */\n this._stillUpdating = true\n for (let name in this.documents) {\n this.onUpdate(name, this.documents[name], dt)\n }\n let t1 = Date.now()\n this._stillUpdating = false\n let updateTime = t1 - now\n this.stats.tUpdate.push(updateTime)\n\n //this.log(`update ${this.update} patch: ${this.update % this.patchCycleDivider}`, )\n\n let patchTime = 0\n if (this.update % this.patchCycleDivider == 0) {\n this._sendPatches()\n let t2 = Date.now()\n patchTime = t2 - t1\n this.stats.tPatch.push(patchTime)\n if (this.allowFastPatch) {\n this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`, )\n }\n this.stats._sendRTCUpdate = 0\n }\n\n this.update++\n let endUpdate = Date.now()\n let totalUpdate = endUpdate - now\n\n setTimeout(() => {\n this._loop()\n }, Math.max(this.cycle - totalUpdate, 10))\n }\n\n _doStats(): void {\n for (let key in this.stats) {\n let i = this.stats[key]\n if (Array.isArray(i) && i.length > 0) {\n while (i.length > 60) {\n i.shift()\n }\n this.stats['_avg_' + key] = i.reduce((a: number, b: number) => a + b, 0) / i.length\n } else if (!key.startsWith('_')) {\n this.stats['_persec_' + key] = i / 3.0\n this.stats[key] = 0\n }\n }\n //this.log('stats', this.stats)\n }\n\n /*= MESSAGES ===============================================================*/\n\n // to be redefined. Called on message (operation) from client\n onMessage(client: ClientType, message: any): void {}\n\n // to be redefined. Called when a client connects\n onConnect(client: ClientType): void {}\n\n // to be redefined. Called when a client disconnects\n onDisconnect(client: ClientType): void {}\n\n _onConnected(client: ClientType): void {\n client.ID = this.getUID()\n client.ping = 0\n client.ctdiff = 0\n client.subscribed = {}\n client.dataChannel = null\n client.peerConnection = null\n\n this.log('client connected', client.ID)\n this.clients.push(client)\n client.on('error', () => {\n this._onError(client, arguments)\n })\n client.on('message', (message:any) => {\n let dec = decode(message)\n if (this.simulateLatency) {\n setTimeout(() => {\n this._onMessage(client, dec)\n }, this.simulateLatency)\n } else {\n this._onMessage(client, dec)\n }\n })\n client.on('close', (message:any) => {\n this._onDisconnected(client)\n this.onDisconnect(client)\n })\n this.onConnect(client)\n }\n\n async _onMessage(client: ClientType, message: any): Promise<void> {\n if (\n message.c == 'sync' &&\n this.allowSync &&\n client.subscribed &&\n client.subscribed[message.n] &&\n this.documents[message.n]\n ) {\n let name = message.n\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n for (let op of message.p) {\n if (!this.canSync(client, name, op)) {\n continue\n }\n this._documentChanges[name].push(op)\n let dop = msgop(op)\n applyOperation(this.documents[name], dop)\n }\n } else if (message.c == 'ping') {\n this.send(client, {\n c: 'pong',\n t: Date.now(),\n ct: message.ct,\n ID: client.ID,\n })\n } else if (message.c == 'peng') {\n let time = Date.now()\n let ping = time - message.st\n client.ctdiff = message.ct + ping / 2 - time\n client.ping = ping\n //this.log(time, \"PENG ping, ctdiff\", message, ping, client.ctdiff, \"ms\")\n /*\n } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\n */\n } else if (message.c == 'sub') {\n await this._checkDocument(message.n, client)\n if (!this.documents[message.n]) {\n this.send(client, {\n c: 'error',\n t: Date.now(),\n message: 'Document not found',\n })\n return\n }\n if (client.subscribed) {\n client.subscribed[message.n] = true\n }\n this._sendFullState(message.n, client)\n } else if (message.c == 'unsub') {\n if (client.subscribed) {\n client.subscribed[message.n] = false\n }\n } else {\n this.onMessage(client, message)\n }\n }\n\n _onError(client: ClientType, args: IArguments): void {\n this.error('onError:', args)\n }\n\n _onDisconnected(client: ClientType): void {\n if (client.dataChannel) {\n client.dataChannel.close()\n }\n if (client.peerConnection) {\n client.peerConnection.close()\n }\n this.log('client disconnected')\n let index = this.clients.indexOf(client)\n if (index !== -1) {\n this.clients.splice(index, 1)\n }\n }\n\n async send(client: ClientType, message: any): Promise<void> {\n try {\n let t1 = Date.now()\n let data = encode(message)\n let t2 = Date.now()\n let dl = data.byteLength\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n if (data.length > 4096) {\n this.log(`Big message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n } catch (e) {\n this.error('Error sending message:', e, message)\n }\n }\n\n async broadcast(message: object, clients: ClientType[] | false = false): Promise<void> {\n if (!clients) {\n clients = this.clients\n }\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n for (let client of this.clients) {\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n }\n }\n\n async _sendFullState(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n let excluded: any = '_'\n if (this.allowFastPatch) {\n excluded = fastPatchProperties\n }\n let doc = clonewo_(this.documents[name], excluded)\n limitPrecision(doc)\n let fdata: any = false\n if (this.allowFastPatch) {\n fdata = this._encodeFastChanges(name, false)\n }\n let fullState = {\n c: 'full',\n le: LITTLE_ENDIAN,\n t: Date.now(),\n n: name,\n doc: doc,\n fdata: fdata\n }\n this.send(client, fullState)\n }\n\n _encodeFastChanges(name: string, changesOnly = true): any {\n let doc = this.documents[name]\n if (!doc) { return false }\n let origin = this.documents[name].origin\n if (!origin) {\n origin = [0, 0, 0]\n this.documents[name].origin = origin\n }\n\n let entities = doc.entities\n let ids = Object.keys(entities)\n if (!entities) { return false }\n let count: Record<string, number> = {}\n let changed: any = {}\n let hasChanges: any = {}\n let dictionary: any = {}\n let encodedChanges: any = {}\n\n for (let key in fastPatchProperties) {\n if (changesOnly) {\n count[key] = 0\n changed[key] = {}\n hasChanges[key] = false\n } else {\n count[key] = ids.length\n changed[key] = {}\n hasChanges[key] = true\n }\n dictionary[key] = {}\n }\n\n // search for changes\n\n if (changesOnly) {\n for (let id in entities) {\n let e = entities[id]\n for (let key in fastPatchProperties) {\n if (e['__changed_' + key]) {\n changed[''+key][''+id] = true\n count[''+key] = parseInt(''+count[''+key]) + 1\n hasChanges[''+key] = true\n e['__changed_' + key] = false\n }\n }\n }\n } else {\n for (let id in entities) {\n for (let key in fastPatchProperties) {\n changed[''+key][''+id] = true\n }\n }\n }\n\n // create dictionaries\n\n let dictUID = 1\n for (let key in hasChanges) {\n if (hasChanges[key] && dictionaryProperties[key]) {\n for (let id in changed[key]) {\n let e = entities[id]\n let value = e[key]\n if (!dictionary[key][value]) {\n dictionary[key][value] = dictUID++\n }\n }\n }\n }\n\n this.log(\"--------------------------------------------------\")\n //this.log(\"changed\", changed)\n //this.log(\"count\", count)\n\n // create encoded changes\n //\n for (let key in hasChanges) {\n if (hasChanges[key]) {\n let size = parseInt(''+count[''+key])\n let encoded: any = {}\n if (dictionaryProperties[key]) {\n encoded.dict = dictionary[key]\n\n let pdata = new Uint8Array(size * 8)\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n let value = e[key]\n let did = parseInt(dictionary[key][value])\n encode_uint32(did, pdata, offset)\n offset += 4\n }\n encoded.pdata = pdata\n } else {\n\n let pdata: Uint8Array\n if (key == 'position') {\n pdata = new Uint8Array(size * 13)\n } else if (key == 'rotation') {\n pdata = new Uint8Array(size * 16)\n } else if (key == 'scale') {\n pdata = new Uint8Array(size * 16)\n } else {\n pdata = new Uint8Array(0)\n }\n\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n if (key == 'position') {\n encode_fp168(e.position[0] - origin[0], pdata, offset)\n offset += 3\n encode_fp168(e.position[1] - origin[1], pdata, offset)\n offset += 3\n encode_fp168(e.position[2] - origin[2], pdata, offset)\n offset += 3\n } else if (key == 'rotation') {\n encode_fp412(e.rotation[0], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[1], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[2], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[3], pdata, offset)\n offset += 2\n } else if (key == 'scale') {\n encode_fp1616(e.scale[0], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[1], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[2], pdata, offset)\n offset += 4\n }\n }\n encoded.pdata = pdata\n }\n encodedChanges[key] = encoded\n }\n }\n\n return encodedChanges\n }\n\n _sendPatches(): void {\n let now = Date.now()\n\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n this._documentChanges[name] = []\n let sus = this.clients.filter((client) => client.subscribed && client.subscribed[name])\n if (sus.length > 0) {\n if (dc && dc.length > 0) {\n let record = {\n c: 'patch',\n t: now, // server time\n u: this.update,\n n: name,\n doc: dc,\n }\n this.broadcast(record, sus)\n }\n }\n\n if (this.allowFastPatch) {\n if (sus.length > 0) {\n let t1 = Date.now()\n let changes = this._encodeFastChanges(name)\n let t2 = Date.now()\n let record = {\n c: 'fpatch',\n t: now, // server time\n u: this.update,\n n: name,\n fdata: changes\n }\n //this.broadcastRTC(record, sus)\n let t3 = Date.now()\n this.log(`_sendPatches: ${name} encode_changes: ${t2-t1}ms broadcast:${t3-t2}ms`)\n }\n }\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: any, value: any): void {\n this._documentChanges[name]?.push(opmsg(op, target, path, value))\n }\n\n propertyChange(name: string, id: string | number, property: string): void {\n let doc = this.documents[name]\n if (!doc) { return }\n let entities = doc.entities\n if (!entities) { return }\n let e = entities[id]\n if (!e) { return }\n e['__changed_'+property] = true\n //this.log('propertyChange', e)\n }\n\n\n /*= WEBRTC ===================================================================*/\n\n /*\n async _processOffer(client: ClientType, data: any): Promise<void> {\n //this.log(\"RTC: Offer received\", data);\n const peerConnection = new wrtc.RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n iceCandidatePoolSize: 10,\n })\n\n client.peerConnection = peerConnection\n\n peerConnection.onicecandidate = (event: any) => {\n if (event.candidate) {\n //this.log(\"RTC: ICE candidate generated\", event.candidate.candidate.substring(0, 50) + \"...\");\n this.send(client, {\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: event.candidate, // .toJSON()\n })\n } else {\n //this.log(\"RTC: ICE candidate gathering complete\");\n }\n }\n\n peerConnection.onconnectionstatechange = () => {\n //this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);\n if (peerConnection.connectionState === 'connected') {\n client.webRTCConnected = true\n this.log(`RTC: Connection established with client ${client.ID}`)\n } else if (\n peerConnection.connectionState === 'failed' ||\n peerConnection.connectionState === 'disconnected' ||\n peerConnection.connectionState === 'closed'\n ) {\n client.webRTCConnected = false\n this.log(`RTC: Connection failed or closed with client ${client.ID}`)\n }\n }\n\n peerConnection.onicegatheringstatechange = () => {\n //this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);\n }\n\n peerConnection.oniceconnectionstatechange = () => {\n //this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);\n if (\n peerConnection.iceConnectionState === 'connected' ||\n peerConnection.iceConnectionState === 'completed'\n ) {\n //this.log(`RTC: ICE connection established with client ${client.ID}`);\n }\n }\n\n try {\n await peerConnection.setRemoteDescription(\n new wrtc.RTCSessionDescription(data)\n )\n //this.log(\"RTC: Remote description set successfully\");\n\n client.dataChannel = peerConnection.createDataChannel('serverchannel', {\n ordered: true,\n maxRetransmits: 1,\n })\n\n client.dataChannel.onopen = () => {\n //this.log(`RTC: Data channel opened for client ${client.ID}`);\n // Try sending a test message\n try {\n const testData = { c: 'test', message: 'Hello WebRTC' }\n this.sendRTC(client, testData)\n } catch (e) {\n this.error(\n `RTC: Error sending test message to client ${client.ID}`,\n e\n )\n }\n }\n\n client.dataChannel.onclose = () => {\n this.log(`RTC: Data channel closed for client ${client.ID}`)\n }\n\n client.dataChannel.onerror = (error: Event) => {\n this.error(`RTC: Data channel error for client ${client.ID}:`, error)\n }\n\n client.dataChannel.onmessage = (event: MessageEvent) => {\n try {\n const data = decode(event.data)\n this.log(\n `RTC: Data channel message from client ${client.ID}:`,\n data\n )\n //this.onMessage(client, data);\n } catch (error) {\n this.error(\n `RTC: Error decoding message from client ${client.ID}:`,\n error\n )\n }\n }\n\n // Create and send answer\n const answer = await peerConnection.createAnswer()\n await peerConnection.setLocalDescription(answer)\n\n //this.log(`RTC: Sending answer to client ${client.ID}`);\n this.send(client, {\n c: 'rtc-answer',\n type: answer.type,\n sdp: answer.sdp,\n })\n } catch (error) {\n this.error(\n `RTC: Error processing offer from client ${client.ID}:`,\n error\n )\n }\n }\n\n async _processICECandidate(client: ClientType, data: any): Promise<void> {\n //this.log(`RTC: Processing ICE candidate from client ${client.ID}`);\n try {\n if (client.peerConnection && data.candidate) {\n await client.peerConnection.addIceCandidate(\n data.candidate\n //new wrtc.RTCIceCandidate(data.candidate)\n )\n //this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);\n } else {\n //this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`);\n }\n } catch (error) {\n this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)\n }\n }\n\n _clientRTCOpen(client: ClientType): boolean {\n return client.dataChannel !== null && client.dataChannel !== undefined && client.dataChannel.readyState === 'open'\n }\n\n async sendRTC(client: ClientType, message: any): Promise<void> {\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n\n let packages = this._splitRTCMessage(data)\n\n if (this.simulateLatency) {\n setTimeout(() => {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }\n }\n\n async broadcastRTC(message: any, clients: ClientType[] = []): Promise<void> {\n if (clients.length == 0) {\n clients = this.clients\n }\n let t1 = Date.now()\n let data = encode(message)\n let dl = data.byteLength\n let t2 = Date.now()\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n\n\n if (data.length > 16384) {\n this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n\n let packages = this._splitRTCMessage(data)\n\n for (let client of this.clients) {\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }\n }\n }\n\n _splitRTCMessage(data: Uint8Array): Uint8Array[] {\n let packages: Uint8Array[]\n if (data.byteLength > 65535) {\n const now = Date.now()\n this.warn(`RTC: Message too large: ${data.byteLength} bytes`)\n // Split the message into smaller packages\n packages = [];\n let offset = 0;\n let mid = this.update +'-'+ now\n let seq = 0\n\n // Create subsequent packages if needed\n while (offset < data.byteLength) {\n const remaining = data.byteLength - offset;\n const chunkSize = Math.min(remaining, MAX_PACKAGE_SIZE);\n const chunk = new Uint8Array(data.buffer, offset, chunkSize);\n let cmessage = {\n c: 'chunk',\n t: now,\n mid: mid,\n seq: seq,\n ofs: offset,\n chs: chunkSize,\n ts: data.byteLength,\n data: chunk,\n last: remaining <= MAX_PACKAGE_SIZE,\n }\n packages.push(encode(cmessage))\n offset += chunkSize;\n seq++;\n }\n\n this.log(`RTC: Large message split into ${packages.length} packages`);\n } else {\n packages = [data]\n this.log(`RTC: Message - ${data.byteLength} bytes`)\n }\n return packages\n }\n */\n\n /*= DATABASE =================================================================*/\n // properties (of the documents) that starts with __ are not saved to the database.\n // __properties are restored on hydration. (for example __physicsBody or __bigObject)\n\n getUID(): number {\n this.documents['_server'].nextUID++\n return this.documents['_server'].nextUID\n }\n\n async _initDB(): Promise<void> {\n await this._connectDB()\n await this._loadDocument('_server')\n if (!this.documents['_server']) {\n this._initServerDocument()\n }\n }\n\n async _connectDB(): Promise<void> {\n this.mongoClient = new MongoClient(this.MongoUrl)\n try {\n await this.mongoClient.connect()\n this.log('Connected to MongoDB')\n const db = this.mongoClient.db(this.database)\n this.DB = db\n } catch (error) {\n this.error('Error connecting to MongoDB:', error)\n this.mongoClient = null\n }\n }\n\n async _loadDocument(name: string): Promise<void> {\n this.log(`Loading document '${name}' from MongoDB`)\n if (this.DB) {\n try {\n const doc = await this.DB.collection(this.collection).findOne({\n name: name,\n })\n if (doc) {\n delete (doc as any)._id\n this.documents[name] = doc\n }\n } catch (error) {\n this.error('Error loading document from MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not loaded.')\n }\n }\n\n async _saveDocument(name: string): Promise<void> {\n if (this.DB) {\n try {\n const doc = this.documents[name]\n let newdoc = clonewo_(doc, '__')\n this.log(`Saving document '${name}' to MongoDB`)\n await this.DB.collection(this.collection).updateOne(\n { name: name },\n { $set: newdoc },\n { upsert: true }\n )\n this.log('Document saved to MongoDB')\n } catch (error) {\n this.error('Error saving document to MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not saved.')\n }\n }\n\n async _saveAllDocuments(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this.documents) {\n await this._saveDocument(name)\n }\n }\n\n _initServerDocument(): void {\n this.documents['_server'] = {\n nextUID: 100,\n }\n }\n\n /*= EXIT ===================================================================*/\n\n _exitSignal(signal: string): void {\n if (!this._exited) {\n this.log('\\nEXIT: Caught interrupt signal ' + signal)\n this._exited = true\n clearInterval(this._loopiv)\n this.onBeforeExit()\n this.broadcast({ server: 'Going down' })\n this._saveAllDocuments()\n this._wss!.close()\n setTimeout(() => process.exit(0), 1000)\n }\n }\n\n // To be redefined. Called BEFORE program exit, and saving all documents\n onBeforeExit(): void {}\n}\n","import { Packr } from 'msgpackr';\nimport { FLOAT32_OPTIONS } from 'msgpackr';\nconst { ALWAYS } = FLOAT32_OPTIONS;\n\nlet packr = new Packr({\n useFloat32: ALWAYS\n});\n\nexport function encode(obj: any): Uint8Array {\n return packr.pack(obj)\n}\n\nexport function decode(data: Uint8Array): any {\n return packr.unpack(data)\n}\n\ntype ReactiveCallback = (name: string, operation: string, target: any, path: string, value: any) => void;\n\nexport function reactive(name: string, object: any, callback: ReactiveCallback, path: string = '', excludedProperties: Record<string, boolean> | false = false): any {\n if (object === null || typeof object !== 'object') {\n //console.log('--- Type not object', typeof object)\n return object\n }\n\n function isReactive(p: string): boolean {\n let r = true\n if (p.startsWith('_')) {\n r = false\n }\n if (excludedProperties) {\n if (excludedProperties[p]) {\n r = false\n }\n }\n if (path == '/entities') {\n r = false\n }\n return r\n }\n\n for (const property in object) {\n if (isReactive(property)) {\n //console.log(`path '${path}', prop '${property}' is reactive`)\n object[property] = reactive(\n name,\n object[property],\n callback,\n path + '/' + property,\n excludedProperties\n )\n } else {\n //console.log(`--- path '${path}', property '${property}' is NOT reactive`)\n }\n }\n //console.log(`path '${path}' is reactive`)\n return new Proxy(object, {\n get(target: any, property: string | symbol, receiver: any): any { // ...arguments\n return Reflect.get(target, property, receiver)\n },\n set(target: any, property: string | symbol, value: any): boolean {\n let newvalue: any\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n newvalue = reactive(name, value, callback, pn, excludedProperties)\n callback(name, 'replace', target, pn, newvalue)\n } else {\n newvalue = value\n }\n return Reflect.set(target, property, newvalue)\n },\n deleteProperty(target: any, property: string | symbol): boolean {\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n callback(name, 'remove', target, pn, null)\n }\n delete target[property]\n return true\n },\n })\n\n}\n\nexport function deepGet(obj: any, path: string): any {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n for (let i = 0; i < len; i++) {\n if (obj[paths[i]!] == undefined) {\n return undefined\n } else {\n obj = obj[paths[i]!]\n }\n }\n return obj\n}\n\nexport function deepSet(obj: any, path: string, value: any): void {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n let i: number\n for (i = 0; i < len - 1; i++) {\n obj = obj[paths[i]!]\n }\n obj[paths[i]!] = value\n}\n\n// recursive clone oject, without properties that starts with _ (or __)\n\nexport function clonewo_(obj: any, excludeStart: string | Record<string, boolean> = '_'): any {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n\n function isExcluded(key: string): boolean {\n let e = false\n if (typeof (excludeStart) == 'string' && key.startsWith(excludeStart)) {\n e = true\n } else if (typeof(excludeStart) == 'object') {\n if (excludeStart[key] || key.startsWith('_')) {\n e = true\n }\n }\n return e\n }\n\n if (obj instanceof Map) {\n const mapClone = new Map()\n for (let [key, value] of obj) {\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"]}
1
+ {"version":3,"sources":["../src/server.ts","../src/utils.ts","../src/compress-node.ts"],"sourcesContent":["import * as https from 'node:https'\nimport * as fs from 'node:fs'\nimport {\n reactive,\n deepGet,\n clonewo_,\n opmsg,\n msgop,\n encode_uint32,\n encode_fp412,\n encode_fp168,\n encode_fp1616,\n limitPrecision,\n encode,\n decode\n} from './utils'\nimport { compress, decompress } from './compress-node'\nimport fastjsonpatch from 'fast-json-patch'\nimport { WebSocketServer, WebSocket } from 'ws'\nimport { MongoClient, Db } from 'mongodb'\nimport { doesNotThrow } from 'assert'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\nglMatrix.setMatrixArrayType(Array)\n//import * as wrtc from '@roamhq/wrtc' // Server-side WebRTC implementation\n\n// entities/ID/\nconst fastPatchProperties: Record<string, boolean> = {\n 'type': true, // string 'enemy'\n 'status': true, // string 'idle'\n 'level': true, // number 2\n 'race': true, // string 'goblin'\n 'class': true, // string 'warrior'\n 'model': true, // string 'models/models.glb|goblin'\n 'animation': true, // string 'idle2'\n 'sound': true, // string 'sound/goblin.snd|snarl'\n 'effect': true, // 'selected'\n 'position': true, // [0, 0, 0] Vector (Number)\n 'rotation': true, // [0, 0, 0, 1] Quaternion (Number)\n 'scale': true, // [1, 1, 1] Vector (Number)\n}\n\nconst dictionaryProperties: Record<string, boolean> = {\n 'type': true,\n 'status': true,\n 'level': true,\n 'race': true,\n 'class': true,\n 'model': true,\n 'animation': true,\n 'sound': true,\n 'effect': true,\n}\n\nconst { applyOperation } = fastjsonpatch\nconst LITTLE_ENDIAN = (() => {\n const buffer = new ArrayBuffer(2)\n new DataView(buffer).setInt16(0, 256, true)\n return new Int16Array(buffer)[0] === 256\n})()\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\n\ntype ClientType = any\n\ninterface StatsType {\n tUpdate: number[]\n tPatch: number[]\n send: number\n sendRTC: number\n _sendRTCUpdate: number\n [key: string]: any\n}\n\nexport default class TopazCubeServer {\n name = 'TopazCubeServer'\n cycle = 100\n patchCycleDivider = 1\n port = 8799\n useHttps = false\n key = './cert/key.pem'\n cert = './cert/cert.pem'\n MongoUrl = 'mongodb://localhost:27017'\n mongoClient: MongoClient | null = null\n DB: Db | null = null\n database = 'topazcube'\n collection = 'documents'\n allowSave = true\n allowSync = true\n allowWebRTC = false\n allowFastPatch = false\n allowCompression = false\n simulateLatency = 0\n\n _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _loopiv: any = null\n _statsiv: any = null\n _stillUpdating = false\n stats: StatsType = {\n tUpdate: [],\n tPatch: [],\n send: 0,\n sendRTC: 0,\n _sendRTCUpdate: 0\n }\n\n _wss: WebSocketServer | null = null\n _exited = false\n\n log(...args: any[]) {\n console.log(this.name + ':', ...args);\n }\n\n warn(...args: any[]) {\n console.warn(this.name + ':', ...args);\n }\n\n error(...args: any[]) {\n console.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n port = 8799,\n useHttps = false,\n key = './cert/key.pem',\n cert = './cert/cert.pem',\n MongoUrl = 'mongodb://localhost:27017',\n database = 'topazcube',\n collection = 'documents',\n allowSave = true,\n allowSync = true,\n allowWebRTC = false,\n allowFastPatch = false,\n allowCompression = false,\n simulateLatency = 0,\n }: {\n name?: string\n cycle?: number\n port?: number\n useHttps?: boolean\n key?: string\n cert?: string\n MongoUrl?: string\n database?: string\n collection?: string\n allowSave?: boolean\n allowSync?: boolean\n allowWebRTC?: boolean\n allowFastPatch?: boolean\n allowCompression?: boolean\n simulateLatency?: number\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.port = port\n this.useHttps = useHttps\n this.key = key\n this.cert = cert\n this.MongoUrl = MongoUrl\n this.database = database\n this.collection = collection\n this.allowSave = allowSave\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.allowFastPatch = allowFastPatch\n this.allowCompression = allowCompression\n this.simulateLatency = simulateLatency\n\n this._initDB()\n\n if (useHttps) {\n let httpsServer: https.Server | null = https.createServer({\n key: fs.readFileSync(this.key),\n cert: fs.readFileSync(this.cert),\n }, (req, res) => {\n res.writeHead(200)\n res.end('<b>Hello World!</b>')\n }).listen(this.port)\n this._wss = new WebSocketServer({ server: httpsServer })\n httpsServer = null\n this.log(this.name + ' running on HTTPS port ' + this.port)\n } else {\n this._wss = new WebSocketServer({ port: this.port })\n this.log(this.name + ' running on port ' + this.port)\n }\n this._wss.on('connection', (client: WebSocket) => {\n this._onConnected(client)\n })\n\n process.stdin.resume()\n process.on('SIGINT', () => {\n this._exitSignal('SIGINT')\n })\n process.on('SIGQUIT', () => {\n this._exitSignal('SIGQUIT')\n })\n process.on('SIGTERM', () => {\n this._exitSignal('SIGTERM')\n })\n process.on('SIGUSR2', () => {\n this._exitSignal('SIGUSR2')\n })\n\n // Setup keypress handling for console input\n process.stdin.resume()\n process.stdin.setEncoding('utf8')\n\n process.stdin.on('data', (key: any) => {\n key = (''+key).trim()\n\n // ctrl-c ( end of text )\n if (key == '\\u0003') {\n this._exitSignal('SIGINT')\n return\n }\n\n // Process other keypresses\n this.log(`Key pressed: ${key}`)\n\n // Example: 's' to save all documents\n if (key == 's') {\n this.log('Saving all documents...')\n this._saveAllDocuments()\n }\n\n // Example: 'i' to print server info\n if (key == 'i') {\n this.log(\n `Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`\n )\n }\n })\n this._startLoop()\n }\n\n /*= DOCUMENTS ==============================================================*/\n\n // to be redefined. Called before a new document is created. Returns true if\n // the client has the right to create an empty document\n canCreate(client: ClientType, name: string): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is created\n // (returns an empty document)\n onCreate(name: string): any {\n return {\n data: {},\n }\n }\n\n // to be redefined. Called when a client wants to sync (modify) a document.\n // Returns true if the client has the right to sync that operation.\n canSync(client: ClientType, name: string, op: any): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is hydrated\n // (created, or loaded from db)\n async onHydrate(name: string, document: any): Promise<void> {\n document.__hydrated = true\n }\n\n _makeReactive(name: string): void {\n //this.log(`Making document '${name}' reactive`, this.documents[name])\n let ep: any = false\n if (this.allowFastPatch) {\n ep = fastPatchProperties\n }\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this),\n '',\n ep\n )\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n }\n\n _createEmptyDocument(name: string): void {\n let doc = this.onCreate(name)\n if (!doc) {\n return\n }\n this.documents[name] = doc\n }\n\n async _waitLoad(name: string): Promise<void> {\n if (this.isLoading[name]) {\n while (this.isLoading[name]) {\n await new Promise((resolve) => setTimeout(resolve, 50))\n }\n }\n }\n\n async _checkDocument(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n if (!this.documents[name]) {\n this.isLoading[name] = true\n await this._loadDocument(name)\n if (!this.documents[name] && this.canCreate(client, name)) {\n this._createEmptyDocument(name)\n }\n if (this.documents[name]) {\n this._makeReactive(name)\n this.onHydrate(name, this.documents[name])\n }\n this.isLoading[name] = false\n this._documentState[name] = {\n subscibers: 0,\n lastModified: Date.now(),\n }\n }\n }\n\n _updateAllDocumentsState(): void {\n for (let name in this.documents) {\n if (name != '_server') {\n let doc = this.documents[name]\n this._documentState[name].subscibers = 0\n for (let client of this.clients) {\n if (client.subscribed && client.subscribed[name]) {\n this._documentState[name].subscibers++\n }\n }\n }\n }\n }\n\n /*= UPDATE LOOP ============================================================*/\n\n // to be redefined. called every this.cycle ms\n onUpdate(name: string, doc: any, dt: number): void {}\n\n _startLoop(): void {\n this.lastUpdate = Date.now()\n this._loop()\n this._statsiv = setInterval(() => {\n this._doStats()\n }, 1000)\n }\n\n _loop(): void {\n let now = Date.now()\n let dtms = (now - this.lastUpdate)\n let dt = dtms / 1000.0 // Convert to seconds\n this.lastUpdate = now\n\n /*\n if (this._stillUpdating) {\n return\n }\n */\n this._stillUpdating = true\n for (let name in this.documents) {\n this.onUpdate(name, this.documents[name], dt)\n }\n let t1 = Date.now()\n this._stillUpdating = false\n let updateTime = t1 - now\n this.stats.tUpdate.push(updateTime)\n\n //this.log(`update ${this.update} patch: ${this.update % this.patchCycleDivider}`, )\n\n let patchTime = 0\n if (this.update % this.patchCycleDivider == 0) {\n this._sendPatches()\n let t2 = Date.now()\n patchTime = t2 - t1\n this.stats.tPatch.push(patchTime)\n if (this.allowFastPatch) {\n this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`, )\n }\n this.stats._sendRTCUpdate = 0\n }\n\n this.update++\n let endUpdate = Date.now()\n let totalUpdate = endUpdate - now\n\n setTimeout(() => {\n this._loop()\n }, Math.max(this.cycle - totalUpdate, 10))\n }\n\n _doStats(): void {\n for (let key in this.stats) {\n let i = this.stats[key]\n if (Array.isArray(i) && i.length > 0) {\n while (i.length > 60) {\n i.shift()\n }\n this.stats['_avg_' + key] = i.reduce((a: number, b: number) => a + b, 0) / i.length\n } else if (!key.startsWith('_')) {\n this.stats['_persec_' + key] = i / 3.0\n this.stats[key] = 0\n }\n }\n //this.log('stats', this.stats)\n }\n\n /*= MESSAGES ===============================================================*/\n\n // to be redefined. Called on message (operation) from client\n onMessage(client: ClientType, message: any): void {}\n\n // to be redefined. Called when a client connects\n onConnect(client: ClientType): void {}\n\n // to be redefined. Called when a client disconnects\n onDisconnect(client: ClientType): void {}\n\n _onConnected(client: ClientType): void {\n client.ID = this.getUID()\n client.ping = 0\n client.ctdiff = 0\n client.subscribed = {}\n client.dataChannel = null\n client.peerConnection = null\n\n this.log('client connected', client.ID)\n this.clients.push(client)\n client.on('error', () => {\n this._onError(client, arguments)\n })\n client.on('message', (message:any) => {\n let dec = decode(message)\n if (this.simulateLatency) {\n setTimeout(() => {\n this._onMessage(client, dec)\n }, this.simulateLatency)\n } else {\n this._onMessage(client, dec)\n }\n })\n client.on('close', (message:any) => {\n this._onDisconnected(client)\n this.onDisconnect(client)\n })\n this.onConnect(client)\n }\n\n async _onMessage(client: ClientType, message: any): Promise<void> {\n if (\n message.c == 'sync' &&\n this.allowSync &&\n client.subscribed &&\n client.subscribed[message.n] &&\n this.documents[message.n]\n ) {\n let name = message.n\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n }\n for (let op of message.p) {\n if (!this.canSync(client, name, op)) {\n continue\n }\n this._documentChanges[name].push(op)\n let dop = msgop(op)\n applyOperation(this.documents[name], dop)\n }\n } else if (message.c == 'ping') {\n this.send(client, {\n c: 'pong',\n t: Date.now(),\n ct: message.ct,\n ID: client.ID,\n })\n } else if (message.c == 'peng') {\n let time = Date.now()\n let ping = time - message.st\n client.ctdiff = message.ct + ping / 2 - time\n client.ping = ping\n //this.log(time, \"PENG ping, ctdiff\", message, ping, client.ctdiff, \"ms\")\n /*\n } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\n */\n } else if (message.c == 'sub') {\n await this._checkDocument(message.n, client)\n if (!this.documents[message.n]) {\n this.send(client, {\n c: 'error',\n t: Date.now(),\n message: 'Document not found',\n })\n return\n }\n if (client.subscribed) {\n client.subscribed[message.n] = true\n }\n this._sendFullState(message.n, client)\n } else if (message.c == 'unsub') {\n if (client.subscribed) {\n client.subscribed[message.n] = false\n }\n } else {\n this.onMessage(client, message)\n }\n }\n\n _onError(client: ClientType, args: IArguments): void {\n this.error('onError:', args)\n }\n\n _onDisconnected(client: ClientType): void {\n if (client.dataChannel) {\n client.dataChannel.close()\n }\n if (client.peerConnection) {\n client.peerConnection.close()\n }\n this.log('client disconnected')\n let index = this.clients.indexOf(client)\n if (index !== -1) {\n this.clients.splice(index, 1)\n }\n }\n\n async send(client: ClientType, message: any): Promise<void> {\n try {\n let t1 = Date.now()\n let data = encode(message)\n let t2 = Date.now()\n let dl = data.byteLength\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n if (data.length > 4096) {\n this.log(`Big message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n } catch (e) {\n this.error('Error sending message:', e, message)\n }\n }\n\n async broadcast(message: object, clients: ClientType[] | false = false): Promise<void> {\n if (!clients) {\n clients = this.clients\n }\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n for (let client of this.clients) {\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n }\n }\n\n async _sendFullState(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n let excluded: any = '_'\n if (this.allowFastPatch) {\n excluded = fastPatchProperties\n }\n let doc = clonewo_(this.documents[name], excluded)\n limitPrecision(doc)\n let fdata: any = false\n if (this.allowFastPatch) {\n fdata = this._encodeFastChanges(name, false)\n }\n let fullState = {\n c: 'full',\n le: LITTLE_ENDIAN,\n t: Date.now(),\n n: name,\n doc: doc,\n fdata: fdata\n }\n this.send(client, fullState)\n }\n\n _encodeFastChanges(name: string, changesOnly = true): any {\n let doc = this.documents[name]\n if (!doc) { return false }\n let origin = this.documents[name].origin\n if (!origin) {\n origin = [0, 0, 0]\n this.documents[name].origin = origin\n }\n\n let entities = doc.entities\n let ids = Object.keys(entities)\n if (!entities) { return false }\n let count: Record<string, number> = {}\n let changed: any = {}\n let hasChanges: any = {}\n let dictionary: any = {}\n let encodedChanges: any = {}\n\n for (let key in fastPatchProperties) {\n if (changesOnly) {\n count[key] = 0\n changed[key] = {}\n hasChanges[key] = false\n } else {\n count[key] = ids.length\n changed[key] = {}\n hasChanges[key] = true\n }\n dictionary[key] = {}\n }\n\n // search for changes\n\n if (changesOnly) {\n for (let id in entities) {\n let e = entities[id]\n for (let key in fastPatchProperties) {\n if (e['__changed_' + key]) {\n changed[''+key][''+id] = true\n count[''+key] = parseInt(''+count[''+key]) + 1\n hasChanges[''+key] = true\n e['__changed_' + key] = false\n }\n }\n }\n } else {\n for (let id in entities) {\n for (let key in fastPatchProperties) {\n changed[''+key][''+id] = true\n }\n }\n }\n\n // create dictionaries\n\n let dictUID = 1\n for (let key in hasChanges) {\n if (hasChanges[key] && dictionaryProperties[key]) {\n for (let id in changed[key]) {\n let e = entities[id]\n let value = e[key]\n if (!dictionary[key][value]) {\n dictionary[key][value] = dictUID++\n }\n }\n }\n }\n\n this.log(\"--------------------------------------------------\")\n //this.log(\"changed\", changed)\n //this.log(\"count\", count)\n\n // create encoded changes\n //\n for (let key in hasChanges) {\n if (hasChanges[key]) {\n let size = parseInt(''+count[''+key])\n let encoded: any = {}\n if (dictionaryProperties[key]) {\n encoded.dict = dictionary[key]\n\n let pdata = new Uint8Array(size * 8)\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n let value = e[key]\n let did = parseInt(dictionary[key][value])\n encode_uint32(did, pdata, offset)\n offset += 4\n }\n encoded.pdata = pdata\n } else {\n\n let pdata: Uint8Array\n if (key == 'position') {\n pdata = new Uint8Array(size * 13)\n } else if (key == 'rotation') {\n pdata = new Uint8Array(size * 16)\n } else if (key == 'scale') {\n pdata = new Uint8Array(size * 16)\n } else {\n pdata = new Uint8Array(0)\n }\n\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n if (key == 'position') {\n encode_fp168(e.position[0] - origin[0], pdata, offset)\n offset += 3\n encode_fp168(e.position[1] - origin[1], pdata, offset)\n offset += 3\n encode_fp168(e.position[2] - origin[2], pdata, offset)\n offset += 3\n } else if (key == 'rotation') {\n encode_fp412(e.rotation[0], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[1], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[2], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[3], pdata, offset)\n offset += 2\n } else if (key == 'scale') {\n encode_fp1616(e.scale[0], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[1], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[2], pdata, offset)\n offset += 4\n }\n }\n encoded.pdata = pdata\n }\n encodedChanges[key] = encoded\n }\n }\n\n return encodedChanges\n }\n\n _sendPatches(): void {\n let now = Date.now()\n\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n this._documentChanges[name] = []\n let sus = this.clients.filter((client) => client.subscribed && client.subscribed[name])\n if (sus.length > 0) {\n if (dc && dc.length > 0) {\n let record = {\n c: 'patch',\n t: now, // server time\n u: this.update,\n n: name,\n doc: dc,\n }\n this.broadcast(record, sus)\n }\n }\n\n if (this.allowFastPatch) {\n if (sus.length > 0) {\n let t1 = Date.now()\n let changes = this._encodeFastChanges(name)\n let t2 = Date.now()\n let record = {\n c: 'fpatch',\n t: now, // server time\n u: this.update,\n n: name,\n fdata: changes\n }\n //this.broadcastRTC(record, sus)\n let t3 = Date.now()\n this.log(`_sendPatches: ${name} encode_changes: ${t2-t1}ms broadcast:${t3-t2}ms`)\n }\n }\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: any, value: any): void {\n this._documentChanges[name]?.push(opmsg(op, target, path, value))\n }\n\n propertyChange(name: string, id: string | number, property: string): void {\n let doc = this.documents[name]\n if (!doc) { return }\n let entities = doc.entities\n if (!entities) { return }\n let e = entities[id]\n if (!e) { return }\n e['__changed_'+property] = true\n //this.log('propertyChange', e)\n }\n\n\n /*= WEBRTC ===================================================================*/\n\n /*\n async _processOffer(client: ClientType, data: any): Promise<void> {\n //this.log(\"RTC: Offer received\", data);\n const peerConnection = new wrtc.RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n iceCandidatePoolSize: 10,\n })\n\n client.peerConnection = peerConnection\n\n peerConnection.onicecandidate = (event: any) => {\n if (event.candidate) {\n //this.log(\"RTC: ICE candidate generated\", event.candidate.candidate.substring(0, 50) + \"...\");\n this.send(client, {\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: event.candidate, // .toJSON()\n })\n } else {\n //this.log(\"RTC: ICE candidate gathering complete\");\n }\n }\n\n peerConnection.onconnectionstatechange = () => {\n //this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);\n if (peerConnection.connectionState === 'connected') {\n client.webRTCConnected = true\n this.log(`RTC: Connection established with client ${client.ID}`)\n } else if (\n peerConnection.connectionState === 'failed' ||\n peerConnection.connectionState === 'disconnected' ||\n peerConnection.connectionState === 'closed'\n ) {\n client.webRTCConnected = false\n this.log(`RTC: Connection failed or closed with client ${client.ID}`)\n }\n }\n\n peerConnection.onicegatheringstatechange = () => {\n //this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);\n }\n\n peerConnection.oniceconnectionstatechange = () => {\n //this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);\n if (\n peerConnection.iceConnectionState === 'connected' ||\n peerConnection.iceConnectionState === 'completed'\n ) {\n //this.log(`RTC: ICE connection established with client ${client.ID}`);\n }\n }\n\n try {\n await peerConnection.setRemoteDescription(\n new wrtc.RTCSessionDescription(data)\n )\n //this.log(\"RTC: Remote description set successfully\");\n\n client.dataChannel = peerConnection.createDataChannel('serverchannel', {\n ordered: true,\n maxRetransmits: 1,\n })\n\n client.dataChannel.onopen = () => {\n //this.log(`RTC: Data channel opened for client ${client.ID}`);\n // Try sending a test message\n try {\n const testData = { c: 'test', message: 'Hello WebRTC' }\n this.sendRTC(client, testData)\n } catch (e) {\n this.error(\n `RTC: Error sending test message to client ${client.ID}`,\n e\n )\n }\n }\n\n client.dataChannel.onclose = () => {\n this.log(`RTC: Data channel closed for client ${client.ID}`)\n }\n\n client.dataChannel.onerror = (error: Event) => {\n this.error(`RTC: Data channel error for client ${client.ID}:`, error)\n }\n\n client.dataChannel.onmessage = (event: MessageEvent) => {\n try {\n const data = decode(event.data)\n this.log(\n `RTC: Data channel message from client ${client.ID}:`,\n data\n )\n //this.onMessage(client, data);\n } catch (error) {\n this.error(\n `RTC: Error decoding message from client ${client.ID}:`,\n error\n )\n }\n }\n\n // Create and send answer\n const answer = await peerConnection.createAnswer()\n await peerConnection.setLocalDescription(answer)\n\n //this.log(`RTC: Sending answer to client ${client.ID}`);\n this.send(client, {\n c: 'rtc-answer',\n type: answer.type,\n sdp: answer.sdp,\n })\n } catch (error) {\n this.error(\n `RTC: Error processing offer from client ${client.ID}:`,\n error\n )\n }\n }\n\n async _processICECandidate(client: ClientType, data: any): Promise<void> {\n //this.log(`RTC: Processing ICE candidate from client ${client.ID}`);\n try {\n if (client.peerConnection && data.candidate) {\n await client.peerConnection.addIceCandidate(\n data.candidate\n //new wrtc.RTCIceCandidate(data.candidate)\n )\n //this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);\n } else {\n //this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`);\n }\n } catch (error) {\n this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)\n }\n }\n\n _clientRTCOpen(client: ClientType): boolean {\n return client.dataChannel !== null && client.dataChannel !== undefined && client.dataChannel.readyState === 'open'\n }\n\n async sendRTC(client: ClientType, message: any): Promise<void> {\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n\n let packages = this._splitRTCMessage(data)\n\n if (this.simulateLatency) {\n setTimeout(() => {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }\n }\n\n async broadcastRTC(message: any, clients: ClientType[] = []): Promise<void> {\n if (clients.length == 0) {\n clients = this.clients\n }\n let t1 = Date.now()\n let data = encode(message)\n let dl = data.byteLength\n let t2 = Date.now()\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n\n\n if (data.length > 16384) {\n this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n\n let packages = this._splitRTCMessage(data)\n\n for (let client of this.clients) {\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }\n }\n }\n\n _splitRTCMessage(data: Uint8Array): Uint8Array[] {\n let packages: Uint8Array[]\n if (data.byteLength > 65535) {\n const now = Date.now()\n this.warn(`RTC: Message too large: ${data.byteLength} bytes`)\n // Split the message into smaller packages\n packages = [];\n let offset = 0;\n let mid = this.update +'-'+ now\n let seq = 0\n\n // Create subsequent packages if needed\n while (offset < data.byteLength) {\n const remaining = data.byteLength - offset;\n const chunkSize = Math.min(remaining, MAX_PACKAGE_SIZE);\n const chunk = new Uint8Array(data.buffer, offset, chunkSize);\n let cmessage = {\n c: 'chunk',\n t: now,\n mid: mid,\n seq: seq,\n ofs: offset,\n chs: chunkSize,\n ts: data.byteLength,\n data: chunk,\n last: remaining <= MAX_PACKAGE_SIZE,\n }\n packages.push(encode(cmessage))\n offset += chunkSize;\n seq++;\n }\n\n this.log(`RTC: Large message split into ${packages.length} packages`);\n } else {\n packages = [data]\n this.log(`RTC: Message - ${data.byteLength} bytes`)\n }\n return packages\n }\n */\n\n /*= DATABASE =================================================================*/\n // properties (of the documents) that starts with __ are not saved to the database.\n // __properties are restored on hydration. (for example __physicsBody or __bigObject)\n\n getUID(): number {\n this.documents['_server'].nextUID++\n return this.documents['_server'].nextUID\n }\n\n async _initDB(): Promise<void> {\n await this._connectDB()\n await this._loadDocument('_server')\n if (!this.documents['_server']) {\n this._initServerDocument()\n }\n }\n\n async _connectDB(): Promise<void> {\n this.mongoClient = new MongoClient(this.MongoUrl)\n try {\n await this.mongoClient.connect()\n this.log('Connected to MongoDB')\n const db = this.mongoClient.db(this.database)\n this.DB = db\n } catch (error) {\n this.error('Error connecting to MongoDB:', error)\n this.mongoClient = null\n }\n }\n\n async _loadDocument(name: string): Promise<void> {\n this.log(`Loading document '${name}' from MongoDB`)\n if (this.DB) {\n try {\n const doc = await this.DB.collection(this.collection).findOne({\n name: name,\n })\n if (doc) {\n delete (doc as any)._id\n this.documents[name] = doc\n }\n } catch (error) {\n this.error('Error loading document from MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not loaded.')\n }\n }\n\n async _saveDocument(name: string): Promise<void> {\n if (this.DB) {\n try {\n const doc = this.documents[name]\n let newdoc = clonewo_(doc, '__')\n this.log(`Saving document '${name}' to MongoDB`)\n await this.DB.collection(this.collection).updateOne(\n { name: name },\n { $set: newdoc },\n { upsert: true }\n )\n this.log('Document saved to MongoDB')\n } catch (error) {\n this.error('Error saving document to MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not saved.')\n }\n }\n\n async _saveAllDocuments(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this.documents) {\n await this._saveDocument(name)\n }\n }\n\n _initServerDocument(): void {\n this.documents['_server'] = {\n nextUID: 100,\n }\n }\n\n /*= EXIT ===================================================================*/\n\n _exitSignal(signal: string): void {\n if (!this._exited) {\n this.log('\\nEXIT: Caught interrupt signal ' + signal)\n this._exited = true\n clearInterval(this._loopiv)\n this.onBeforeExit()\n this.broadcast({ server: 'Going down' })\n this._saveAllDocuments()\n this._wss!.close()\n setTimeout(() => process.exit(0), 1000)\n }\n }\n\n // To be redefined. Called BEFORE program exit, and saving all documents\n onBeforeExit(): void {}\n}\n","import { Packr } from 'msgpackr';\nimport { FLOAT32_OPTIONS } from 'msgpackr';\nconst { ALWAYS } = FLOAT32_OPTIONS;\n\nlet packr = new Packr({\n useFloat32: ALWAYS\n});\n\nexport function encode(obj: any): Uint8Array {\n return packr.pack(obj)\n}\n\nexport function decode(data: Uint8Array): any {\n return packr.unpack(data)\n}\n\ntype ReactiveCallback = (name: string, operation: string, target: any, path: string, value: any) => void;\n\nexport function reactive(name: string, object: any, callback: ReactiveCallback, path: string = '', excludedProperties: Record<string, boolean> | false = false): any {\n if (object === null || typeof object !== 'object') {\n //console.log('--- Type not object', typeof object)\n return object\n }\n\n function isReactive(p: string): boolean {\n let r = true\n if (p.startsWith('_')) {\n r = false\n }\n if (excludedProperties) {\n if (excludedProperties[p]) {\n r = false\n }\n }\n if (path == '/entities') {\n r = false\n }\n return r\n }\n\n for (const property in object) {\n if (isReactive(property)) {\n //console.log(`path '${path}', prop '${property}' is reactive`)\n object[property] = reactive(\n name,\n object[property],\n callback,\n path + '/' + property,\n excludedProperties\n )\n } else {\n //console.log(`--- path '${path}', property '${property}' is NOT reactive`)\n }\n }\n //console.log(`path '${path}' is reactive`)\n return new Proxy(object, {\n get(target: any, property: string | symbol, receiver: any): any { // ...arguments\n return Reflect.get(target, property, receiver)\n },\n set(target: any, property: string | symbol, value: any): boolean {\n let newvalue: any\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n newvalue = reactive(name, value, callback, pn, excludedProperties)\n callback(name, 'replace', target, pn, newvalue)\n } else {\n newvalue = value\n }\n return Reflect.set(target, property, newvalue)\n },\n deleteProperty(target: any, property: string | symbol): boolean {\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n callback(name, 'remove', target, pn, null)\n }\n delete target[property]\n return true\n },\n })\n\n}\n\nexport function deepGet(obj: any, path: string): any {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n for (let i = 0; i < len; i++) {\n if (obj[paths[i]!] == undefined) {\n return undefined\n } else {\n obj = obj[paths[i]!]\n }\n }\n return obj\n}\n\nexport function deepSet(obj: any, path: string, value: any): void {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n let i: number\n for (i = 0; i < len - 1; i++) {\n obj = obj[paths[i]!]\n }\n obj[paths[i]!] = value\n}\n\n// recursive clone oject, without properties that starts with _ (or __)\n\nexport function clonewo_(obj: any, excludeStart: string | Record<string, boolean> = '_'): any {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n\n function isExcluded(key: string): boolean {\n let e = false\n if (typeof (excludeStart) == 'string' && key.startsWith(excludeStart)) {\n e = true\n } else if (typeof(excludeStart) == 'object') {\n if (excludeStart[key] || key.startsWith('_')) {\n e = true\n }\n }\n return e\n }\n\n if (obj instanceof Map) {\n const mapClone = new Map()\n for (let [key, value] of obj) {\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "topazcube",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
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
@@ -116,15 +116,15 @@ export default class TopazCubeServer {
116
116
  _exited = false
117
117
 
118
118
  log(...args: any[]) {
119
- this.log(this.name + ':', ...args);
119
+ console.log(this.name + ':', ...args);
120
120
  }
121
121
 
122
122
  warn(...args: any[]) {
123
- this.warn(this.name + ':', ...args);
123
+ console.warn(this.name + ':', ...args);
124
124
  }
125
125
 
126
126
  error(...args: any[]) {
127
- this.error(this.name + ':', ...args);
127
+ console.error(this.name + ':', ...args);
128
128
  }
129
129
 
130
130
  constructor({