topazcube 0.1.29 → 0.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.cjs +16 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +6 -1
- package/dist/server.d.ts +6 -1
- package/dist/server.js +16 -1
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/src/server.ts +18 -1
package/dist/server.cjs
CHANGED
|
@@ -331,6 +331,8 @@ var TopazCubeServer = class {
|
|
|
331
331
|
DEBUG = false;
|
|
332
332
|
name = "TopazCubeServer";
|
|
333
333
|
cycle = 100;
|
|
334
|
+
saveCheckCycle = 1e3;
|
|
335
|
+
saveCycle = 1e4;
|
|
334
336
|
patchCycleDivider = 1;
|
|
335
337
|
port = 8799;
|
|
336
338
|
useHttps = false;
|
|
@@ -357,6 +359,7 @@ var TopazCubeServer = class {
|
|
|
357
359
|
update = 0;
|
|
358
360
|
lastUpdate = 0;
|
|
359
361
|
_saveiv = null;
|
|
362
|
+
_lastSave = {};
|
|
360
363
|
_loopiv = null;
|
|
361
364
|
_statsiv = null;
|
|
362
365
|
_stillUpdating = false;
|
|
@@ -385,6 +388,8 @@ var TopazCubeServer = class {
|
|
|
385
388
|
constructor({
|
|
386
389
|
name = "TopazCubeServer",
|
|
387
390
|
cycle = 100,
|
|
391
|
+
saveCheckCycle = 1e3,
|
|
392
|
+
saveCycle = 1e4,
|
|
388
393
|
port = 8799,
|
|
389
394
|
useHttps = false,
|
|
390
395
|
key = "./cert/key.pem",
|
|
@@ -402,6 +407,8 @@ var TopazCubeServer = class {
|
|
|
402
407
|
} = {}) {
|
|
403
408
|
this.name = name;
|
|
404
409
|
this.cycle = cycle;
|
|
410
|
+
this.saveCheckCycle = saveCheckCycle;
|
|
411
|
+
this.saveCycle = saveCycle;
|
|
405
412
|
this.port = port;
|
|
406
413
|
this.useHttps = useHttps;
|
|
407
414
|
this.key = key;
|
|
@@ -567,7 +574,7 @@ var TopazCubeServer = class {
|
|
|
567
574
|
}, 1e3);
|
|
568
575
|
this._saveiv = setInterval(() => {
|
|
569
576
|
this._saveChanges();
|
|
570
|
-
},
|
|
577
|
+
}, 1e3);
|
|
571
578
|
}
|
|
572
579
|
_loop() {
|
|
573
580
|
let now = Date.now();
|
|
@@ -1277,9 +1284,17 @@ var TopazCubeServer = class {
|
|
|
1277
1284
|
return;
|
|
1278
1285
|
}
|
|
1279
1286
|
for (let name in this._documentChanged) {
|
|
1287
|
+
if (!this._lastSave[name]) {
|
|
1288
|
+
this._lastSave[name] = Date.now() - 6e4;
|
|
1289
|
+
}
|
|
1290
|
+
let lastSave = this._lastSave[name];
|
|
1291
|
+
if (Date.now() - lastSave < 1e4) {
|
|
1292
|
+
continue;
|
|
1293
|
+
}
|
|
1280
1294
|
if (this._documentChanged[name]) {
|
|
1281
1295
|
await this._saveDocument(name);
|
|
1282
1296
|
this._documentChanged[name] = false;
|
|
1297
|
+
this._lastSave[name] = Date.now();
|
|
1283
1298
|
}
|
|
1284
1299
|
}
|
|
1285
1300
|
}
|
package/dist/server.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/utils.ts","../src/compress-node.ts"],"sourcesContent":["import * as https from 'node:https'\nimport * as fs from 'node:fs'\nimport {\n reactive,\n deepGet,\n clonewo_,\n opmsg,\n msgop,\n encode_uint32,\n encode_fp412,\n encode_fp168,\n encode_fp1616,\n limitPrecision,\n encode,\n decode\n} from './utils'\nimport { compress, decompress } from './compress-node'\nimport fastjsonpatch from 'fast-json-patch'\nimport { WebSocketServer, WebSocket } from 'ws'\nimport { MongoClient, Db } from 'mongodb'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\nimport { RTCPeerConnection, RTCDataChannel, RTCSessionDescription } from \"werift\";\n\nglMatrix.setMatrixArrayType(Array)\n\n// entities/ID/\nconst fastPatchProperties: Record<string, boolean> = {\n 'type': true, // string 'enemy'\n 'status': true, // string 'idle'\n 'level': true, // number 2\n 'race': true, // string 'goblin'\n 'class': true, // string 'warrior'\n 'model': true, // string 'models/models.glb|goblin'\n 'animation': true, // string 'idle2'\n 'sound': true, // string 'sound/goblin.snd|snarl'\n 'effect': true, // 'selected'\n 'position': true, // [0, 0, 0] Vector (Number)\n 'rotation': true, // [0, 0, 0, 1] Quaternion (Number)\n 'scale': true, // [1, 1, 1] Vector (Number)\n}\n\nconst dictionaryProperties: Record<string, boolean> = {\n 'type': true,\n 'status': true,\n 'level': true,\n 'race': true,\n 'class': true,\n 'model': true,\n 'animation': true,\n 'sound': true,\n 'effect': true,\n}\n\nconst { applyOperation } = fastjsonpatch\nconst LITTLE_ENDIAN = (() => {\n const buffer = new ArrayBuffer(2)\n new DataView(buffer).setInt16(0, 256, true)\n return new Int16Array(buffer)[0] === 256\n})()\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\n\ntype ClientType = any\n\ninterface StatsType {\n tUpdate: number[]\n tPatch: number[]\n send: number\n sendRTC: number\n _sendRTCUpdate: number\n [key: string]: any\n}\n\nexport default class TopazCubeServer {\n DEBUG = false\n name = 'TopazCubeServer'\n cycle = 100\n patchCycleDivider = 1\n port = 8799\n useHttps = false\n key = './cert/key.pem'\n cert = './cert/cert.pem'\n MongoUrl = 'mongodb://localhost:27017'\n mongoClient: MongoClient | null = null\n DB: Db | null = null\n database = 'topazcube'\n collection = 'documents'\n allowSave = true\n allowSync = true\n allowWebRTC = false\n allowFastPatch = false\n allowCompression = false\n simulateLatency = 0\n _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentChanged: Record<string, boolean> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _saveiv: any = null\n _loopiv: any = null\n _statsiv: any = null\n _stillUpdating = false\n stats: StatsType = {\n tUpdate: [],\n tPatch: [],\n send: 0,\n sendRTC: 0,\n _sendRTCUpdate: 0\n }\n\n _wss: WebSocketServer | null = null\n _exited = false\n\n log(...args: any[]) {\n if (this.DEBUG) {\n console.log(this.name + ':', ...args);\n }\n }\n\n warn(...args: any[]) {\n if (this.DEBUG) {\n console.warn(this.name + ':', ...args);\n }\n }\n\n error(...args: any[]) {\n console.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n port = 8799,\n useHttps = false,\n key = './cert/key.pem',\n cert = './cert/cert.pem',\n MongoUrl = 'mongodb://localhost:27017',\n database = 'topazcube',\n collection = 'documents',\n allowSave = true,\n allowSync = true,\n allowWebRTC = false,\n allowFastPatch = false,\n allowCompression = false,\n simulateLatency = 0,\n DEBUG = false\n }: {\n name?: string\n cycle?: number\n port?: number\n useHttps?: boolean\n key?: string\n cert?: string\n MongoUrl?: string\n database?: string\n collection?: string\n allowSave?: boolean\n allowSync?: boolean\n allowWebRTC?: boolean\n allowFastPatch?: boolean\n allowCompression?: boolean\n simulateLatency?: number\n DEBUG?: boolean\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.port = port\n this.useHttps = useHttps\n this.key = key\n this.cert = cert\n this.MongoUrl = MongoUrl\n this.database = database\n this.collection = collection\n this.allowSave = allowSave\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.allowFastPatch = allowFastPatch\n this.allowCompression = allowCompression\n this.simulateLatency = simulateLatency\n this.DEBUG = DEBUG\n\n this._initDB()\n\n if (useHttps) {\n let httpsServer: https.Server | null = https.createServer({\n key: fs.readFileSync(this.key),\n cert: fs.readFileSync(this.cert),\n }, (req, res) => {\n res.writeHead(200)\n res.end('<b>Hello World!</b>')\n }).listen(this.port)\n this._wss = new WebSocketServer({ server: httpsServer })\n httpsServer = null\n this.log(this.name + ' running on HTTPS port ' + this.port)\n } else {\n this._wss = new WebSocketServer({ port: this.port })\n this.log(this.name + ' running on port ' + this.port)\n }\n this._wss.on('connection', (client: WebSocket) => {\n this._onConnected(client)\n })\n\n process.stdin.resume()\n process.on('SIGINT', () => {\n this._exitSignal('SIGINT')\n })\n process.on('SIGQUIT', () => {\n this._exitSignal('SIGQUIT')\n })\n process.on('SIGTERM', () => {\n this._exitSignal('SIGTERM')\n })\n process.on('SIGUSR2', () => {\n this._exitSignal('SIGUSR2')\n })\n\n // Setup keypress handling for console input\n process.stdin.resume()\n process.stdin.setEncoding('utf8')\n\n process.stdin.on('data', (key: any) => {\n key = (''+key).trim()\n\n // ctrl-c ( end of text )\n if (key == '\\u0003') {\n this._exitSignal('SIGINT')\n return\n }\n\n // Process other keypresses\n this.log(`Key pressed: ${key}`)\n\n // Example: 's' to save all documents\n if (key == 's') {\n this.log('Saving all documents...')\n this._saveAllDocuments()\n }\n\n // Example: 'i' to print server info\n if (key == 'i') {\n this.log(\n `Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`\n )\n }\n })\n this._startLoop()\n }\n\n /*= DOCUMENTS ==============================================================*/\n\n // to be redefined. Called before a new document is created. Returns true if\n // the client has the right to create an empty document\n canCreate(client: ClientType, name: string): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is created\n // (returns an empty document)\n onCreate(name: string): any {\n return {\n data: {},\n }\n }\n\n // to be redefined. Called when a client wants to sync (modify) a document.\n // Returns true if the client has the right to sync that operation.\n canSync(client: ClientType, name: string, op: any): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is hydrated\n // (created, or loaded from db)\n async onHydrate(name: string, document: any): Promise<void> {\n document.__hydrated = true\n }\n\n _makeReactive(name: string): void {\n //this.log(`Making document '${name}' reactive`, this.documents[name])\n let ep: any = false\n if (this.allowFastPatch) {\n ep = fastPatchProperties\n }\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this),\n '',\n ep\n )\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n this._documentChanged[name] = false\n }\n }\n\n _createEmptyDocument(name: string): void {\n let doc = this.onCreate(name)\n if (!doc) {\n return\n }\n this.documents[name] = doc\n }\n\n async _waitLoad(name: string): Promise<void> {\n if (this.isLoading[name]) {\n while (this.isLoading[name]) {\n await new Promise((resolve) => setTimeout(resolve, 50))\n }\n }\n }\n\n async _checkDocument(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n if (!this.documents[name]) {\n this.isLoading[name] = true\n await this._loadDocument(name)\n if (!this.documents[name] && this.canCreate(client, name)) {\n this._createEmptyDocument(name)\n }\n if (this.documents[name]) {\n this._makeReactive(name)\n this.onHydrate(name, this.documents[name])\n }\n this.isLoading[name] = false\n this._documentState[name] = {\n subscibers: 0,\n lastModified: Date.now(),\n }\n }\n }\n\n _updateAllDocumentsState(): void {\n for (let name in this.documents) {\n if (name != '_server') {\n let doc = this.documents[name]\n this._documentState[name].subscibers = 0\n for (let client of this.clients) {\n if (client.subscribed && client.subscribed[name]) {\n this._documentState[name].subscibers++\n }\n }\n }\n }\n }\n\n /*= UPDATE LOOP ============================================================*/\n\n // to be redefined. called every this.cycle ms\n onUpdate(name: string, doc: any, dt: number): void {}\n\n _startLoop(): void {\n this.lastUpdate = Date.now()\n this._loop()\n this._statsiv = setInterval(() => {\n this._doStats()\n }, 1000)\n this._saveiv = setInterval(() => {\n this._saveChanges()\n }, 60000)\n }\n\n _loop(): void {\n let now = Date.now()\n let dtms = (now - this.lastUpdate)\n let dt = dtms / 1000.0 // Convert to seconds\n this.lastUpdate = now\n\n /*\n if (this._stillUpdating) {\n return\n }\n */\n this._stillUpdating = true\n for (let name in this.documents) {\n this.onUpdate(name, this.documents[name], dt)\n }\n let t1 = Date.now()\n this._stillUpdating = false\n let updateTime = t1 - now\n this.stats.tUpdate.push(updateTime)\n\n //this.log(`update ${this.update} patch: ${this.update % this.patchCycleDivider}`, )\n\n let patchTime = 0\n if (this.update % this.patchCycleDivider == 0) {\n this._sendPatches()\n let t2 = Date.now()\n patchTime = t2 - t1\n this.stats.tPatch.push(patchTime)\n if (this.allowFastPatch) {\n this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`, )\n }\n this.stats._sendRTCUpdate = 0\n }\n\n this.update++\n let endUpdate = Date.now()\n let totalUpdate = endUpdate - now\n\n setTimeout(() => {\n this._loop()\n }, Math.max(this.cycle - totalUpdate, 10))\n }\n\n _doStats(): void {\n for (let key in this.stats) {\n let i = this.stats[key]\n if (Array.isArray(i) && i.length > 0) {\n while (i.length > 60) {\n i.shift()\n }\n this.stats['_avg_' + key] = i.reduce((a: number, b: number) => a + b, 0) / i.length\n } else if (!key.startsWith('_')) {\n this.stats['_persec_' + key] = i / 3.0\n this.stats[key] = 0\n }\n }\n //this.log('stats', this.stats)\n }\n\n /*= MESSAGES ===============================================================*/\n\n // to be redefined. Called on message (operation) from client\n onMessage(client: ClientType, message: any): void {}\n\n // to be redefined. Called when a client connects\n onConnect(client: ClientType): void {}\n\n // to be redefined. Called when a client disconnects\n onDisconnect(client: ClientType): void {}\n\n _onConnected(client: ClientType): void {\n client.ID = this.getUID()\n client.ping = 0\n client.ctdiff = 0\n client.subscribed = {}\n client.dataChannel = null\n client.peerConnection = null\n\n this.log('client connected', client.ID)\n this.clients.push(client)\n client.on('error', (...args: any[]) => {\n this._onError(client, args)\n })\n client.on('message', (message:any) => {\n let dec = decode(message)\n if (this.simulateLatency) {\n setTimeout(() => {\n this._onMessage(client, dec)\n }, this.simulateLatency)\n } else {\n this._onMessage(client, dec)\n }\n })\n client.on('close', (message:any) => {\n this._onDisconnected(client)\n this.onDisconnect(client)\n })\n this.onConnect(client)\n }\n\n async _onMessage(client: ClientType, message: any): Promise<void> {\n if (\n message.c == 'sync' &&\n this.allowSync &&\n client.subscribed &&\n client.subscribed[message.n] &&\n this.documents[message.n]\n ) {\n let name = message.n\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n this._documentChanged[name] = false\n }\n for (let op of message.p) {\n if (!this.canSync(client, name, op)) {\n continue\n }\n this._documentChanges[name].push(op)\n this._documentChanged[name] = true\n let dop = msgop(op)\n applyOperation(this.documents[name], dop)\n }\n } else if (message.c == 'ping') {\n this.send(client, {\n c: 'pong',\n t: Date.now(),\n ct: message.ct,\n ID: client.ID,\n })\n } else if (message.c == 'peng') {\n let time = Date.now()\n let ping = time - message.st\n client.ctdiff = message.ct + ping / 2 - time\n client.ping = ping\n //this.log(time, \"PENG ping, ctdiff\", message, ping, client.ctdiff, \"ms\")\n } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\n } else if (message.c == 'sub') {\n await this._checkDocument(message.n, client)\n if (!this.documents[message.n]) {\n this.send(client, {\n c: 'error',\n t: Date.now(),\n message: 'Document not found',\n })\n return\n }\n if (client.subscribed) {\n client.subscribed[message.n] = true\n }\n this._sendFullState(message.n, client)\n } else if (message.c == 'unsub') {\n if (client.subscribed) {\n client.subscribed[message.n] = false\n }\n } else {\n this.onMessage(client, message)\n }\n }\n\n _onError(client: ClientType, args: any[]): void {\n this.error('onError:', args)\n }\n\n _onDisconnected(client: ClientType): void {\n if (client.dataChannel) {\n client.dataChannel.close()\n }\n if (client.peerConnection) {\n client.peerConnection.close()\n }\n this.log('client disconnected')\n let index = this.clients.indexOf(client)\n if (index !== -1) {\n this.clients.splice(index, 1)\n }\n }\n\n async send(client: ClientType, message: any): Promise<void> {\n try {\n let t1 = Date.now()\n let data = encode(message)\n let t2 = Date.now()\n let dl = data.byteLength\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n if (data.length > 4096) {\n this.log(`Big message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n } catch (e) {\n this.error('Error sending message:', e, message)\n }\n }\n\n async broadcast(message: object, clients: ClientType[] | false = false): Promise<void> {\n if (!clients) {\n clients = this.clients\n }\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n for (let client of this.clients) {\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n }\n }\n\n async _sendFullState(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n let excluded: any = '_'\n if (this.allowFastPatch) {\n excluded = fastPatchProperties\n }\n let doc = clonewo_(this.documents[name], excluded)\n limitPrecision(doc)\n let fdata: any = false\n if (this.allowFastPatch) {\n fdata = this._encodeFastChanges(name, false)\n }\n let fullState = {\n c: 'full',\n le: LITTLE_ENDIAN,\n t: Date.now(),\n n: name,\n doc: doc,\n fdata: fdata\n }\n this.send(client, fullState)\n }\n\n _encodeFastChanges(name: string, changesOnly = true): any {\n let doc = this.documents[name]\n if (!doc) { return false }\n let origin = this.documents[name].origin\n if (!origin) {\n origin = [0, 0, 0]\n this.documents[name].origin = origin\n }\n\n let entities = doc.entities\n let ids = Object.keys(entities)\n if (!entities) { return false }\n let count: Record<string, number> = {}\n let changed: any = {}\n let hasChanges: any = {}\n let dictionary: any = {}\n let encodedChanges: any = {}\n\n for (let key in fastPatchProperties) {\n if (changesOnly) {\n count[key] = 0\n changed[key] = {}\n hasChanges[key] = false\n } else {\n count[key] = ids.length\n changed[key] = {}\n hasChanges[key] = true\n }\n dictionary[key] = {}\n }\n\n // search for changes\n\n if (changesOnly) {\n for (let id in entities) {\n let e = entities[id]\n for (let key in fastPatchProperties) {\n if (e['__changed_' + key]) {\n changed[''+key][''+id] = true\n count[''+key] = parseInt(''+count[''+key]) + 1\n hasChanges[''+key] = true\n e['__changed_' + key] = false\n }\n }\n }\n } else {\n for (let id in entities) {\n for (let key in fastPatchProperties) {\n changed[''+key][''+id] = true\n }\n }\n }\n\n // create dictionaries\n\n let dictUID = 1\n for (let key in hasChanges) {\n if (hasChanges[key] && dictionaryProperties[key]) {\n for (let id in changed[key]) {\n let e = entities[id]\n let value = e[key]\n if (!dictionary[key][value]) {\n dictionary[key][value] = dictUID++\n }\n }\n }\n }\n\n this.log(\"--------------------------------------------------\")\n //this.log(\"changed\", changed)\n //this.log(\"count\", count)\n\n // create encoded changes\n //\n for (let key in hasChanges) {\n if (hasChanges[key]) {\n let size = parseInt(''+count[''+key])\n let encoded: any = {}\n if (dictionaryProperties[key]) {\n encoded.dict = dictionary[key]\n\n let pdata = new Uint8Array(size * 8)\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n let value = e[key]\n let did = parseInt(dictionary[key][value])\n encode_uint32(did, pdata, offset)\n offset += 4\n }\n encoded.pdata = pdata\n } else {\n\n let pdata: Uint8Array\n if (key == 'position') {\n pdata = new Uint8Array(size * 13)\n } else if (key == 'rotation') {\n pdata = new Uint8Array(size * 16)\n } else if (key == 'scale') {\n pdata = new Uint8Array(size * 16)\n } else {\n pdata = new Uint8Array(0)\n }\n\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n if (key == 'position') {\n encode_fp168(e.position[0] - origin[0], pdata, offset)\n offset += 3\n encode_fp168(e.position[1] - origin[1], pdata, offset)\n offset += 3\n encode_fp168(e.position[2] - origin[2], pdata, offset)\n offset += 3\n } else if (key == 'rotation') {\n encode_fp412(e.rotation[0], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[1], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[2], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[3], pdata, offset)\n offset += 2\n } else if (key == 'scale') {\n encode_fp1616(e.scale[0], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[1], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[2], pdata, offset)\n offset += 4\n }\n }\n encoded.pdata = pdata\n }\n encodedChanges[key] = encoded\n }\n }\n\n return encodedChanges\n }\n\n _sendPatches(): void {\n let now = Date.now()\n\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n this._documentChanges[name] = []\n let sus = this.clients.filter((client) => client.subscribed && client.subscribed[name])\n if (sus.length > 0) {\n if (dc && dc.length > 0) {\n let record = {\n c: 'patch',\n t: now, // server time\n u: this.update,\n n: name,\n doc: dc,\n }\n this.broadcast(record, sus)\n }\n }\n\n if (this.allowFastPatch) {\n if (sus.length > 0) {\n let t1 = Date.now()\n let changes = this._encodeFastChanges(name)\n let t2 = Date.now()\n let record = {\n c: 'fpatch',\n t: now, // server time\n u: this.update,\n n: name,\n fdata: changes\n }\n this.broadcastRTC(record, sus)\n let t3 = Date.now()\n this.log(`_sendPatches: ${name} encode_changes: ${t2-t1}ms broadcast:${t3-t2}ms`)\n }\n }\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: any, value: any): void {\n this._documentChanges[name]?.push(opmsg(op, target, path, value))\n this._documentChanged[name] = true\n }\n\n propertyChange(name: string, id: string | number, property: string): void {\n let doc = this.documents[name]\n if (!doc) { return }\n let entities = doc.entities\n if (!entities) { return }\n let e = entities[id]\n if (!e) { return }\n e['__changed_'+property] = true\n //this.log('propertyChange', e)\n }\n\n\n /*= WEBRTC ===================================================================*/\n\n\n async _processOffer(client: ClientType, data: any): Promise<void> {\n if (!this.allowWebRTC) {\n this.warn('WebRTC is disabled')\n return\n }\n\n this.log(\"RTC: Processing offer from client\", client.ID, data);\n\n const peerConnection = new RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n //iceCandidatePoolSize: 10,\n })\n\n client.peerConnection = peerConnection\n\n peerConnection.onicecandidate = (event: any) => {\n if (event.candidate) {\n this.log(\"RTC: ICE candidate generated\", event.candidate.candidate.substring(0, 50) + \"...\");\n this.send(client, {\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: event.candidate, // .toJSON()\n })\n } else {\n this.log(\"RTC: ICE candidate gathering complete\");\n }\n }\n\n peerConnection.onconnectionstatechange = () => {\n this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);\n if (peerConnection.connectionState === 'connected') {\n client.webRTCConnected = true\n this.log(`RTC: Connection established with client ${client.ID}`)\n } else if (\n peerConnection.connectionState === 'failed' ||\n peerConnection.connectionState === 'disconnected' ||\n peerConnection.connectionState === 'closed'\n ) {\n client.webRTCConnected = false\n this.log(`RTC: Connection failed or closed with client ${client.ID}`)\n }\n }\n\n peerConnection.onicegatheringstatechange = () => {\n this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);\n }\n\n peerConnection.oniceconnectionstatechange = () => {\n this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);\n if (\n peerConnection.iceConnectionState === 'connected' ||\n peerConnection.iceConnectionState === 'completed'\n ) {\n this.log(`RTC: ICE connection established with client ${client.ID}`);\n }\n }\n\n try {\n this.log(\"RTC: Remote description set from data\", data);\n await peerConnection.setRemoteDescription(\n //data\n new RTCSessionDescription(data.sdp, data.type)\n )\n this.log(\"RTC: Remote description set successfully\");\n\n client.dataChannel = peerConnection.createDataChannel('serverchannel', {\n ordered: true,\n maxRetransmits: 1,\n })\n\n client.dataChannel.onopen = () => {\n this.log(`RTC: Data channel opened for client ${client.ID}`);\n // Try sending a test message\n try {\n const testData = { c: 'test', message: 'Hello WebRTC' }\n this.sendRTC(client, testData)\n } catch (e) {\n this.error(\n `RTC: Error sending test message to client ${client.ID}`,\n e\n )\n }\n }\n\n client.dataChannel.onclose = () => {\n this.log(`RTC: Data channel closed for client ${client.ID}`)\n }\n\n client.dataChannel.onerror = (error: Event) => {\n this.error(`RTC: Data channel error for client ${client.ID}:`, error)\n }\n\n client.dataChannel.onmessage = (event: MessageEvent) => {\n try {\n const data = decode(event.data)\n this.log(\n `RTC: Data channel message from client ${client.ID}:`,\n data\n )\n //this.onMessage(client, data);\n } catch (error) {\n this.error(\n `RTC: Error decoding message from client ${client.ID}:`,\n error\n )\n }\n }\n\n // Create and send answer\n const answer = await peerConnection.createAnswer()\n await peerConnection.setLocalDescription(answer)\n\n this.log(`RTC: Sending answer to client ${client.ID}`);\n this.send(client, {\n c: 'rtc-answer',\n type: answer.type,\n sdp: answer.sdp,\n })\n } catch (error) {\n this.error(\n `RTC: Error processing offer from client ${client.ID}:`,\n error\n )\n }\n }\n\n async _processICECandidate(client: ClientType, data: any): Promise<void> {\n this.log(`RTC: Processing ICE candidate from client ${client.ID}`);\n try {\n if (data.candidate && typeof(data.candidate) == 'object') {\n data.candidate = data.candidate.candidate\n }\n if (client.peerConnection && data.candidate) {\n await client.peerConnection.addIceCandidate(\n data.candidate\n //new wrtc.RTCIceCandidate(data.candidate)\n )\n this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);\n } else {\n this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`, client.peerConnection, data);\n }\n } catch (error) {\n this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)\n }\n }\n\n _clientRTCOpen(client: ClientType): boolean {\n return client.dataChannel !== null && client.dataChannel !== undefined && client.dataChannel.readyState === 'open'\n }\n\n async sendRTC(client: ClientType, message: any): Promise<void> {\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n\n let packages = this._splitRTCMessage(data)\n\n if (this.simulateLatency) {\n setTimeout(() => {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }\n }\n\n async broadcastRTC(message: any, clients: ClientType[] = []): Promise<void> {\n if (clients.length == 0) {\n clients = this.clients\n }\n let t1 = Date.now()\n let data = encode(message)\n let dl = data.byteLength\n let t2 = Date.now()\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n\n\n if (data.length > 16384) {\n this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n\n let packages = this._splitRTCMessage(data)\n\n for (let client of this.clients) {\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }\n }\n }\n\n _splitRTCMessage(data: Uint8Array): Uint8Array[] {\n let packages: Uint8Array[]\n if (data.byteLength > 65535) {\n const now = Date.now()\n this.warn(`RTC: Message too large: ${data.byteLength} bytes`)\n // Split the message into smaller packages\n packages = [];\n let offset = 0;\n let mid = this.update +'-'+ now\n let seq = 0\n\n // Create subsequent packages if needed\n while (offset < data.byteLength) {\n const remaining = data.byteLength - offset;\n const chunkSize = Math.min(remaining, MAX_PACKAGE_SIZE);\n const chunk = new Uint8Array(data.buffer, offset, chunkSize);\n let cmessage = {\n c: 'chunk',\n t: now,\n mid: mid,\n seq: seq,\n ofs: offset,\n chs: chunkSize,\n ts: data.byteLength,\n data: chunk,\n last: remaining <= MAX_PACKAGE_SIZE,\n }\n packages.push(encode(cmessage))\n offset += chunkSize;\n seq++;\n }\n\n this.log(`RTC: Large message split into ${packages.length} packages`);\n } else {\n packages = [data]\n this.log(`RTC: Message - ${data.byteLength} bytes`)\n }\n return packages\n }\n\n\n /*= DATABASE =================================================================*/\n // properties (of the documents) that starts with __ are not saved to the database.\n // __properties are restored on hydration. (for example __physicsBody or __bigObject)\n\n getUID(): number {\n this.documents['_server'].nextUID++\n return this.documents['_server'].nextUID\n }\n\n async _initDB(): Promise<void> {\n await this._connectDB()\n await this._loadDocument('_server')\n if (!this.documents['_server']) {\n this._initServerDocument()\n }\n }\n\n async _connectDB(): Promise<void> {\n this.mongoClient = new MongoClient(this.MongoUrl)\n try {\n await this.mongoClient.connect()\n this.log('Connected to MongoDB')\n const db = this.mongoClient.db(this.database)\n this.DB = db\n } catch (error) {\n this.error('Error connecting to MongoDB:', error)\n this.mongoClient = null\n }\n }\n\n async _loadDocument(name: string): Promise<void> {\n this.log(`Loading document '${name}' from MongoDB`)\n if (this.DB) {\n try {\n const doc = await this.DB.collection(this.collection).findOne({\n name: name,\n })\n if (doc) {\n delete (doc as any)._id\n this.documents[name] = doc\n }\n } catch (error) {\n this.error('Error loading document from MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not loaded.')\n }\n }\n\n async _saveDocument(name: string): Promise<void> {\n if (this.DB) {\n try {\n const doc = this.documents[name]\n let newdoc = clonewo_(doc, '__')\n this.log(`Saving document '${name}' to MongoDB`)\n await this.DB.collection(this.collection).updateOne(\n { name: name },\n { $set: newdoc },\n { upsert: true }\n )\n this.log('Document saved to MongoDB')\n } catch (error) {\n this.error('Error saving document to MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not saved.')\n }\n }\n\n async _saveAllDocuments(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this.documents) {\n await this._saveDocument(name)\n }\n }\n\n async _saveChanges(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this._documentChanged) {\n if (this._documentChanged[name]) {\n await this._saveDocument(name)\n this._documentChanged[name] = false\n }\n }\n }\n\n _initServerDocument(): void {\n this.documents['_server'] = {\n nextUID: 100,\n }\n }\n\n /*= EXIT ===================================================================*/\n\n _exitSignal(signal: string): void {\n if (!this._exited) {\n this.log('\\nEXIT: Caught interrupt signal ' + signal)\n this._exited = true\n clearInterval(this._loopiv)\n clearInterval(this._statsiv)\n clearInterval(this._saveiv)\n this.onBeforeExit()\n this.broadcast({ server: 'Going down' })\n this._saveAllDocuments()\n this._wss!.close()\n setTimeout(() => process.exit(0), 1000)\n }\n }\n\n // To be redefined. Called BEFORE program exit, and saving all documents\n onBeforeExit(): void {}\n}\n","import { Packr } from 'msgpackr';\nimport { FLOAT32_OPTIONS } from 'msgpackr';\nconst { ALWAYS } = FLOAT32_OPTIONS;\n\nlet packr = new Packr({\n useFloat32: ALWAYS\n});\n\nexport function encode(obj: any): Uint8Array {\n return packr.pack(obj)\n}\n\nexport function decode(data: Uint8Array): any {\n return packr.unpack(data)\n}\n\ntype ReactiveCallback = (name: string, operation: string, target: any, path: string, value: any) => void;\n\nexport function reactive(name: string, object: any, callback: ReactiveCallback, path: string = '', excludedProperties: Record<string, boolean> | false = false): any {\n if (object === null || typeof object !== 'object') {\n //console.log('--- Type not object', typeof object)\n return object\n }\n\n function isReactive(p: string): boolean {\n let r = true\n if (p.startsWith('_')) {\n r = false\n }\n if (excludedProperties) {\n if (excludedProperties[p]) {\n r = false\n }\n }\n if (path == '/entities') {\n r = false\n }\n return r\n }\n\n for (const property in object) {\n if (isReactive(property)) {\n //console.log(`path '${path}', prop '${property}' is reactive`)\n object[property] = reactive(\n name,\n object[property],\n callback,\n path + '/' + property,\n excludedProperties\n )\n } else {\n //console.log(`--- path '${path}', property '${property}' is NOT reactive`)\n }\n }\n //console.log(`path '${path}' is reactive`)\n return new Proxy(object, {\n get(target: any, property: string | symbol, receiver: any): any { // ...arguments\n return Reflect.get(target, property, receiver)\n },\n set(target: any, property: string | symbol, value: any): boolean {\n let newvalue: any\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n newvalue = reactive(name, value, callback, pn, excludedProperties)\n callback(name, 'replace', target, pn, newvalue)\n } else {\n newvalue = value\n }\n return Reflect.set(target, property, newvalue)\n },\n deleteProperty(target: any, property: string | symbol): boolean {\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n callback(name, 'remove', target, pn, null)\n }\n delete target[property]\n return true\n },\n })\n\n}\n\nexport function deepGet(obj: any, path: string): any {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n for (let i = 0; i < len; i++) {\n if (obj[paths[i]!] == undefined) {\n return undefined\n } else {\n obj = obj[paths[i]!]\n }\n }\n return obj\n}\n\nexport function deepSet(obj: any, path: string, value: any): void {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n let i: number\n for (i = 0; i < len - 1; i++) {\n obj = obj[paths[i]!]\n }\n obj[paths[i]!] = value\n}\n\n// recursive clone oject, without properties that starts with _ (or __)\n\nexport function clonewo_(obj: any, excludeStart: string | Record<string, boolean> = '_'): any {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n\n function isExcluded(key: string): boolean {\n let e = false\n if (typeof (excludeStart) == 'string' && key.startsWith(excludeStart)) {\n e = true\n } else if (typeof(excludeStart) == 'object') {\n if (excludeStart[key] || key.startsWith('_')) {\n e = true\n }\n }\n return e\n }\n\n if (obj instanceof Map) {\n const mapClone = new Map()\n Array.from(obj.entries()).forEach(([key, value]) => {\n mapClone.set(clonewo_(key, excludeStart), clonewo_(value, excludeStart))\n })\n return mapClone\n }\n\n let clone: any\n if (Array.isArray(obj)) {\n clone = []\n for (let i = 0; i < obj.length; i++) {\n clone[i] = clonewo_(obj[i], excludeStart)\n }\n } else {\n clone = {} as Record<string, any>\n for (let key in obj) {\n if (obj.hasOwnProperty(key) && !isExcluded(key)) {\n if (typeof obj[key] === 'object') {\n clone[key] = clonewo_(obj[key], excludeStart)\n } else {\n clone[key] = obj[key]\n }\n }\n }\n }\n\n return clone\n}\n\nexport function limitPrecision(obj: any): any {\n if (Array.isArray(obj)) {\n return obj.map(limitPrecision)\n } else if (obj !== null && typeof obj === 'object') {\n const result: Record<string, any> = {}\n for (const key in obj) {\n result[key] = limitPrecision(obj[key])\n }\n return result\n } else if (typeof obj === 'number') {\n if (Number.isInteger(obj)) {\n return obj\n } else {\n // Limit to max 3 decimal digits, not fixed\n return parseFloat(obj.toFixed(3))\n }\n } else {\n return obj\n }\n}\n\nexport function msgop(op: any): any {\n let nop: any = {}\n if (!op.o) {\n nop.op = 'replace'\n } else {\n nop.op = ({\n a: 'add',\n r: 'remove',\n d: 'delete',\n t: 'test',\n } as Record<string, string>)[op.o]\n }\n nop.path = op.p\n nop.value = op.v\n return nop\n}\n\nexport function opmsg(op: string, target: any, path: string, value: any): any {\n let c: any = { p: path, v: value }\n if (op != 'replace') {\n c.o = ({\n add: 'a',\n remove: 'r',\n delete: 'd',\n test: 't',\n } as Record<string, string>)[op]\n }\n return c\n}\n\n// a function that converts an int to a hexa string\n// (8 characters long)\nexport function int2hex(int: number): string {\n return int.toString(16)\n}\n\n// a function that converts a hexa string to an int\nexport function hex2int(str: string): bigint {\n if (str.length % 2) {\n str = '0' + str\n }\n return BigInt('0x' + str)\n}\n\n// - Fixed point encoding/decoding functions\n\n// 32-bit unsigned integer encoding\nexport function encode_uint32(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(4)\n }\n let p = offset + 3\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n// 32-bit unsigned integer decoding\nexport function decode_uint32(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (\n ((byteArray[p++]! & 0x7f) << 24) |\n (byteArray[p++]! << 16) |\n (byteArray[p++]! << 8) |\n byteArray[p]!\n )\n}\n\n// 24-bit unsigned integer encoding\nexport function encode_uint24(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(3)\n }\n let p = offset + 2\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n\n// 24-bit unsigned integer decoding\nexport function decode_uint24(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (\n (byteArray[p++]! << 16) |\n (byteArray[p++]! << 8) |\n byteArray[p]!\n )\n}\n\n// 16-bit unsigned integer encoding\nexport function encode_uint16(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(2)\n }\n let p = offset + 1\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n\n// 16-bit unsigned integer decoding\nexport function decode_uint16(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (byteArray[p++]! << 8) | byteArray[p]!\n}\n\n// 24.8 bit ====================================================================\n\n// 24.8-bit fixed point encoding\nexport function encode_fp248(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint32(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 24.8-bit fixed point decoding\nexport function decode_fp248(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint32(byteArray, offset)\n return fp / divider\n}\n\n// 16.8 bit ====================================================================\n\n// 16.8-bit fixed point encoding (3 bytes)\nexport function encode_fp168(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint24(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 16.8-bit fixed point decoding (3 bytes)\nexport function decode_fp168(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint24(byteArray, offset)\n return fp / divider\n}\n\n// 16.16 bit ===================================================================\n\n// 16.16-bit fixed point encoding\nexport function encode_fp1616(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 65536)\n encode_uint32(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 16.16-bit fixed point decoding\nexport function decode_fp1616(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -65536 : 65536\n byteArray[offset]! &= 0x7f\n const fp = decode_uint32(byteArray, offset)\n return fp / divider\n}\n\n// 8.8 bit =====================================================================\n\n// 8.8-bit fixed point encoding\nexport function encode_fp88(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint16(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 8.8-bit fixed point decoding\nexport function decode_fp88(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint16(byteArray, offset)\n return fp / divider\n}\n\n// 4.12 bit ====================================================================\n\n// 4.12-bit fixed point encoding\nexport function encode_fp412(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 4096)\n encode_uint16(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 4.12-bit fixed point decoding\nexport function decode_fp412(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -4096 : 4096\n byteArray[offset]! &= 0x7f\n const fp = decode_uint16(byteArray, offset)\n return fp / divider\n}\n\n// 1.7 bit =====================================================================\n\n// 1.7-bit fixed point encoding\nexport function encode_fp17(float: number, byteArray: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 128)\n byteArray[offset] = fp\n if (float < 0) {\n byteArray[offset] |= 0x80\n }\n}\n\n// 1.7-bit fixed point decoding\nexport function decode_fp17(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -128.0 : 128.0\n byteArray[offset]! &= 0x7f\n return byteArray[offset]! / divider\n}\n","import { promisify } from 'util'\nimport { gzip, gunzip, constants } from 'zlib'\n\nconst MIN_COMPRESSED_BUFFER_SIZE = 256\nconst MAX_COMPRESSED_BUFFER_SIZE = 999999\n\nconst lib_compress = promisify(gzip)\nconst lib_decompress = promisify(gunzip)\n\nexport async function compress(buffer:Uint8Array<ArrayBufferLike>) {\n if (buffer.byteLength <= MIN_COMPRESSED_BUFFER_SIZE || buffer.byteLength >= MAX_COMPRESSED_BUFFER_SIZE) return buffer\n try {\n let t1 = Date.now()\n let cbytes = await lib_compress(buffer, {\n level: constants.Z_BEST_SPEED\n })\n let t2 = Date.now()\n let cbuffer = Buffer.from(cbytes)\n let t3 = Date.now()\n\n //console.log(`Node compression ${buffer.byteLength} -> ${cbuffer.byteLength}, time: ${t2 - t1}ms`)\n\n return cbuffer\n } catch (error) {\n console.error('Error compressing buffer:', error)\n return buffer\n }\n}\n\nexport async function decompress(buffer:Uint8Array<ArrayBufferLike>) {\n try {\n let cbytes = await lib_decompress(buffer)\n let cbuffer = Buffer.from(cbytes)\n return cbuffer\n } catch (error) {\n console.error('Error decompressing buffer:', error)\n return buffer\n }\n}\n"],"mappings":"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","names":["import_msgpackr","fastjsonpatch","key","data"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/utils.ts","../src/compress-node.ts"],"sourcesContent":["import * as https from 'node:https'\nimport * as fs from 'node:fs'\nimport {\n reactive,\n deepGet,\n clonewo_,\n opmsg,\n msgop,\n encode_uint32,\n encode_fp412,\n encode_fp168,\n encode_fp1616,\n limitPrecision,\n encode,\n decode\n} from './utils'\nimport { compress, decompress } from './compress-node'\nimport fastjsonpatch from 'fast-json-patch'\nimport { WebSocketServer, WebSocket } from 'ws'\nimport { MongoClient, Db } from 'mongodb'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\nimport { RTCPeerConnection, RTCDataChannel, RTCSessionDescription } from \"werift\";\n\nglMatrix.setMatrixArrayType(Array)\n\n// entities/ID/\nconst fastPatchProperties: Record<string, boolean> = {\n 'type': true, // string 'enemy'\n 'status': true, // string 'idle'\n 'level': true, // number 2\n 'race': true, // string 'goblin'\n 'class': true, // string 'warrior'\n 'model': true, // string 'models/models.glb|goblin'\n 'animation': true, // string 'idle2'\n 'sound': true, // string 'sound/goblin.snd|snarl'\n 'effect': true, // 'selected'\n 'position': true, // [0, 0, 0] Vector (Number)\n 'rotation': true, // [0, 0, 0, 1] Quaternion (Number)\n 'scale': true, // [1, 1, 1] Vector (Number)\n}\n\nconst dictionaryProperties: Record<string, boolean> = {\n 'type': true,\n 'status': true,\n 'level': true,\n 'race': true,\n 'class': true,\n 'model': true,\n 'animation': true,\n 'sound': true,\n 'effect': true,\n}\n\nconst { applyOperation } = fastjsonpatch\nconst LITTLE_ENDIAN = (() => {\n const buffer = new ArrayBuffer(2)\n new DataView(buffer).setInt16(0, 256, true)\n return new Int16Array(buffer)[0] === 256\n})()\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\n\ntype ClientType = any\n\ninterface StatsType {\n tUpdate: number[]\n tPatch: number[]\n send: number\n sendRTC: number\n _sendRTCUpdate: number\n [key: string]: any\n}\n\nexport default class TopazCubeServer {\n DEBUG = false\n name = 'TopazCubeServer'\n cycle = 100\n saveCheckCycle = 1000\n saveCycle = 10000\n patchCycleDivider = 1\n port = 8799\n useHttps = false\n key = './cert/key.pem'\n cert = './cert/cert.pem'\n MongoUrl = 'mongodb://localhost:27017'\n mongoClient: MongoClient | null = null\n DB: Db | null = null\n database = 'topazcube'\n collection = 'documents'\n allowSave = true\n allowSync = true\n allowWebRTC = false\n allowFastPatch = false\n allowCompression = false\n simulateLatency = 0\n _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentChanged: Record<string, boolean> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _saveiv: any = null\n _lastSave: Record<string, number> = {}\n _loopiv: any = null\n _statsiv: any = null\n _stillUpdating = false\n stats: StatsType = {\n tUpdate: [],\n tPatch: [],\n send: 0,\n sendRTC: 0,\n _sendRTCUpdate: 0\n }\n\n _wss: WebSocketServer | null = null\n _exited = false\n\n log(...args: any[]) {\n if (this.DEBUG) {\n console.log(this.name + ':', ...args);\n }\n }\n\n warn(...args: any[]) {\n if (this.DEBUG) {\n console.warn(this.name + ':', ...args);\n }\n }\n\n error(...args: any[]) {\n console.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n saveCheckCycle = 1000,\n saveCycle = 10000,\n port = 8799,\n useHttps = false,\n key = './cert/key.pem',\n cert = './cert/cert.pem',\n MongoUrl = 'mongodb://localhost:27017',\n database = 'topazcube',\n collection = 'documents',\n allowSave = true,\n allowSync = true,\n allowWebRTC = false,\n allowFastPatch = false,\n allowCompression = false,\n simulateLatency = 0,\n DEBUG = false\n }: {\n name?: string\n cycle?: number\n saveCheckCycle?: number\n saveCycle?: number\n port?: number\n useHttps?: boolean\n key?: string\n cert?: string\n MongoUrl?: string\n database?: string\n collection?: string\n allowSave?: boolean\n allowSync?: boolean\n allowWebRTC?: boolean\n allowFastPatch?: boolean\n allowCompression?: boolean\n simulateLatency?: number\n DEBUG?: boolean\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.saveCheckCycle = saveCheckCycle\n this.saveCycle = saveCycle\n this.port = port\n this.useHttps = useHttps\n this.key = key\n this.cert = cert\n this.MongoUrl = MongoUrl\n this.database = database\n this.collection = collection\n this.allowSave = allowSave\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.allowFastPatch = allowFastPatch\n this.allowCompression = allowCompression\n this.simulateLatency = simulateLatency\n this.DEBUG = DEBUG\n\n this._initDB()\n\n if (useHttps) {\n let httpsServer: https.Server | null = https.createServer({\n key: fs.readFileSync(this.key),\n cert: fs.readFileSync(this.cert),\n }, (req, res) => {\n res.writeHead(200)\n res.end('<b>Hello World!</b>')\n }).listen(this.port)\n this._wss = new WebSocketServer({ server: httpsServer })\n httpsServer = null\n this.log(this.name + ' running on HTTPS port ' + this.port)\n } else {\n this._wss = new WebSocketServer({ port: this.port })\n this.log(this.name + ' running on port ' + this.port)\n }\n this._wss.on('connection', (client: WebSocket) => {\n this._onConnected(client)\n })\n\n process.stdin.resume()\n process.on('SIGINT', () => {\n this._exitSignal('SIGINT')\n })\n process.on('SIGQUIT', () => {\n this._exitSignal('SIGQUIT')\n })\n process.on('SIGTERM', () => {\n this._exitSignal('SIGTERM')\n })\n process.on('SIGUSR2', () => {\n this._exitSignal('SIGUSR2')\n })\n\n // Setup keypress handling for console input\n process.stdin.resume()\n process.stdin.setEncoding('utf8')\n\n process.stdin.on('data', (key: any) => {\n key = (''+key).trim()\n\n // ctrl-c ( end of text )\n if (key == '\\u0003') {\n this._exitSignal('SIGINT')\n return\n }\n\n // Process other keypresses\n this.log(`Key pressed: ${key}`)\n\n // Example: 's' to save all documents\n if (key == 's') {\n this.log('Saving all documents...')\n this._saveAllDocuments()\n }\n\n // Example: 'i' to print server info\n if (key == 'i') {\n this.log(\n `Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`\n )\n }\n })\n this._startLoop()\n }\n\n /*= DOCUMENTS ==============================================================*/\n\n // to be redefined. Called before a new document is created. Returns true if\n // the client has the right to create an empty document\n canCreate(client: ClientType, name: string): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is created\n // (returns an empty document)\n onCreate(name: string): any {\n return {\n data: {},\n }\n }\n\n // to be redefined. Called when a client wants to sync (modify) a document.\n // Returns true if the client has the right to sync that operation.\n canSync(client: ClientType, name: string, op: any): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is hydrated\n // (created, or loaded from db)\n async onHydrate(name: string, document: any): Promise<void> {\n document.__hydrated = true\n }\n\n _makeReactive(name: string): void {\n //this.log(`Making document '${name}' reactive`, this.documents[name])\n let ep: any = false\n if (this.allowFastPatch) {\n ep = fastPatchProperties\n }\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this),\n '',\n ep\n )\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n this._documentChanged[name] = false\n }\n }\n\n _createEmptyDocument(name: string): void {\n let doc = this.onCreate(name)\n if (!doc) {\n return\n }\n this.documents[name] = doc\n }\n\n async _waitLoad(name: string): Promise<void> {\n if (this.isLoading[name]) {\n while (this.isLoading[name]) {\n await new Promise((resolve) => setTimeout(resolve, 50))\n }\n }\n }\n\n async _checkDocument(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n if (!this.documents[name]) {\n this.isLoading[name] = true\n await this._loadDocument(name)\n if (!this.documents[name] && this.canCreate(client, name)) {\n this._createEmptyDocument(name)\n }\n if (this.documents[name]) {\n this._makeReactive(name)\n this.onHydrate(name, this.documents[name])\n }\n this.isLoading[name] = false\n this._documentState[name] = {\n subscibers: 0,\n lastModified: Date.now(),\n }\n }\n }\n\n _updateAllDocumentsState(): void {\n for (let name in this.documents) {\n if (name != '_server') {\n let doc = this.documents[name]\n this._documentState[name].subscibers = 0\n for (let client of this.clients) {\n if (client.subscribed && client.subscribed[name]) {\n this._documentState[name].subscibers++\n }\n }\n }\n }\n }\n\n /*= UPDATE LOOP ============================================================*/\n\n // to be redefined. called every this.cycle ms\n onUpdate(name: string, doc: any, dt: number): void {}\n\n _startLoop(): void {\n this.lastUpdate = Date.now()\n this._loop()\n this._statsiv = setInterval(() => {\n this._doStats()\n }, 1000)\n this._saveiv = setInterval(() => {\n this._saveChanges()\n }, 1000)\n }\n\n _loop(): void {\n let now = Date.now()\n let dtms = (now - this.lastUpdate)\n let dt = dtms / 1000.0 // Convert to seconds\n this.lastUpdate = now\n\n /*\n if (this._stillUpdating) {\n return\n }\n */\n this._stillUpdating = true\n for (let name in this.documents) {\n this.onUpdate(name, this.documents[name], dt)\n }\n let t1 = Date.now()\n this._stillUpdating = false\n let updateTime = t1 - now\n this.stats.tUpdate.push(updateTime)\n\n //this.log(`update ${this.update} patch: ${this.update % this.patchCycleDivider}`, )\n\n let patchTime = 0\n if (this.update % this.patchCycleDivider == 0) {\n this._sendPatches()\n let t2 = Date.now()\n patchTime = t2 - t1\n this.stats.tPatch.push(patchTime)\n if (this.allowFastPatch) {\n this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`, )\n }\n this.stats._sendRTCUpdate = 0\n }\n\n this.update++\n let endUpdate = Date.now()\n let totalUpdate = endUpdate - now\n\n setTimeout(() => {\n this._loop()\n }, Math.max(this.cycle - totalUpdate, 10))\n }\n\n _doStats(): void {\n for (let key in this.stats) {\n let i = this.stats[key]\n if (Array.isArray(i) && i.length > 0) {\n while (i.length > 60) {\n i.shift()\n }\n this.stats['_avg_' + key] = i.reduce((a: number, b: number) => a + b, 0) / i.length\n } else if (!key.startsWith('_')) {\n this.stats['_persec_' + key] = i / 3.0\n this.stats[key] = 0\n }\n }\n //this.log('stats', this.stats)\n }\n\n /*= MESSAGES ===============================================================*/\n\n // to be redefined. Called on message (operation) from client\n onMessage(client: ClientType, message: any): void {}\n\n // to be redefined. Called when a client connects\n onConnect(client: ClientType): void {}\n\n // to be redefined. Called when a client disconnects\n onDisconnect(client: ClientType): void {}\n\n _onConnected(client: ClientType): void {\n client.ID = this.getUID()\n client.ping = 0\n client.ctdiff = 0\n client.subscribed = {}\n client.dataChannel = null\n client.peerConnection = null\n\n this.log('client connected', client.ID)\n this.clients.push(client)\n client.on('error', (...args: any[]) => {\n this._onError(client, args)\n })\n client.on('message', (message:any) => {\n let dec = decode(message)\n if (this.simulateLatency) {\n setTimeout(() => {\n this._onMessage(client, dec)\n }, this.simulateLatency)\n } else {\n this._onMessage(client, dec)\n }\n })\n client.on('close', (message:any) => {\n this._onDisconnected(client)\n this.onDisconnect(client)\n })\n this.onConnect(client)\n }\n\n async _onMessage(client: ClientType, message: any): Promise<void> {\n if (\n message.c == 'sync' &&\n this.allowSync &&\n client.subscribed &&\n client.subscribed[message.n] &&\n this.documents[message.n]\n ) {\n let name = message.n\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n this._documentChanged[name] = false\n }\n for (let op of message.p) {\n if (!this.canSync(client, name, op)) {\n continue\n }\n this._documentChanges[name].push(op)\n this._documentChanged[name] = true\n let dop = msgop(op)\n applyOperation(this.documents[name], dop)\n }\n } else if (message.c == 'ping') {\n this.send(client, {\n c: 'pong',\n t: Date.now(),\n ct: message.ct,\n ID: client.ID,\n })\n } else if (message.c == 'peng') {\n let time = Date.now()\n let ping = time - message.st\n client.ctdiff = message.ct + ping / 2 - time\n client.ping = ping\n //this.log(time, \"PENG ping, ctdiff\", message, ping, client.ctdiff, \"ms\")\n } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\n } else if (message.c == 'sub') {\n await this._checkDocument(message.n, client)\n if (!this.documents[message.n]) {\n this.send(client, {\n c: 'error',\n t: Date.now(),\n message: 'Document not found',\n })\n return\n }\n if (client.subscribed) {\n client.subscribed[message.n] = true\n }\n this._sendFullState(message.n, client)\n } else if (message.c == 'unsub') {\n if (client.subscribed) {\n client.subscribed[message.n] = false\n }\n } else {\n this.onMessage(client, message)\n }\n }\n\n _onError(client: ClientType, args: any[]): void {\n this.error('onError:', args)\n }\n\n _onDisconnected(client: ClientType): void {\n if (client.dataChannel) {\n client.dataChannel.close()\n }\n if (client.peerConnection) {\n client.peerConnection.close()\n }\n this.log('client disconnected')\n let index = this.clients.indexOf(client)\n if (index !== -1) {\n this.clients.splice(index, 1)\n }\n }\n\n async send(client: ClientType, message: any): Promise<void> {\n try {\n let t1 = Date.now()\n let data = encode(message)\n let t2 = Date.now()\n let dl = data.byteLength\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n if (data.length > 4096) {\n this.log(`Big message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n } catch (e) {\n this.error('Error sending message:', e, message)\n }\n }\n\n async broadcast(message: object, clients: ClientType[] | false = false): Promise<void> {\n if (!clients) {\n clients = this.clients\n }\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n for (let client of this.clients) {\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n }\n }\n\n async _sendFullState(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n let excluded: any = '_'\n if (this.allowFastPatch) {\n excluded = fastPatchProperties\n }\n let doc = clonewo_(this.documents[name], excluded)\n limitPrecision(doc)\n let fdata: any = false\n if (this.allowFastPatch) {\n fdata = this._encodeFastChanges(name, false)\n }\n let fullState = {\n c: 'full',\n le: LITTLE_ENDIAN,\n t: Date.now(),\n n: name,\n doc: doc,\n fdata: fdata\n }\n this.send(client, fullState)\n }\n\n _encodeFastChanges(name: string, changesOnly = true): any {\n let doc = this.documents[name]\n if (!doc) { return false }\n let origin = this.documents[name].origin\n if (!origin) {\n origin = [0, 0, 0]\n this.documents[name].origin = origin\n }\n\n let entities = doc.entities\n let ids = Object.keys(entities)\n if (!entities) { return false }\n let count: Record<string, number> = {}\n let changed: any = {}\n let hasChanges: any = {}\n let dictionary: any = {}\n let encodedChanges: any = {}\n\n for (let key in fastPatchProperties) {\n if (changesOnly) {\n count[key] = 0\n changed[key] = {}\n hasChanges[key] = false\n } else {\n count[key] = ids.length\n changed[key] = {}\n hasChanges[key] = true\n }\n dictionary[key] = {}\n }\n\n // search for changes\n\n if (changesOnly) {\n for (let id in entities) {\n let e = entities[id]\n for (let key in fastPatchProperties) {\n if (e['__changed_' + key]) {\n changed[''+key][''+id] = true\n count[''+key] = parseInt(''+count[''+key]) + 1\n hasChanges[''+key] = true\n e['__changed_' + key] = false\n }\n }\n }\n } else {\n for (let id in entities) {\n for (let key in fastPatchProperties) {\n changed[''+key][''+id] = true\n }\n }\n }\n\n // create dictionaries\n\n let dictUID = 1\n for (let key in hasChanges) {\n if (hasChanges[key] && dictionaryProperties[key]) {\n for (let id in changed[key]) {\n let e = entities[id]\n let value = e[key]\n if (!dictionary[key][value]) {\n dictionary[key][value] = dictUID++\n }\n }\n }\n }\n\n this.log(\"--------------------------------------------------\")\n //this.log(\"changed\", changed)\n //this.log(\"count\", count)\n\n // create encoded changes\n //\n for (let key in hasChanges) {\n if (hasChanges[key]) {\n let size = parseInt(''+count[''+key])\n let encoded: any = {}\n if (dictionaryProperties[key]) {\n encoded.dict = dictionary[key]\n\n let pdata = new Uint8Array(size * 8)\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n let value = e[key]\n let did = parseInt(dictionary[key][value])\n encode_uint32(did, pdata, offset)\n offset += 4\n }\n encoded.pdata = pdata\n } else {\n\n let pdata: Uint8Array\n if (key == 'position') {\n pdata = new Uint8Array(size * 13)\n } else if (key == 'rotation') {\n pdata = new Uint8Array(size * 16)\n } else if (key == 'scale') {\n pdata = new Uint8Array(size * 16)\n } else {\n pdata = new Uint8Array(0)\n }\n\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n if (key == 'position') {\n encode_fp168(e.position[0] - origin[0], pdata, offset)\n offset += 3\n encode_fp168(e.position[1] - origin[1], pdata, offset)\n offset += 3\n encode_fp168(e.position[2] - origin[2], pdata, offset)\n offset += 3\n } else if (key == 'rotation') {\n encode_fp412(e.rotation[0], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[1], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[2], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[3], pdata, offset)\n offset += 2\n } else if (key == 'scale') {\n encode_fp1616(e.scale[0], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[1], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[2], pdata, offset)\n offset += 4\n }\n }\n encoded.pdata = pdata\n }\n encodedChanges[key] = encoded\n }\n }\n\n return encodedChanges\n }\n\n _sendPatches(): void {\n let now = Date.now()\n\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n this._documentChanges[name] = []\n let sus = this.clients.filter((client) => client.subscribed && client.subscribed[name])\n if (sus.length > 0) {\n if (dc && dc.length > 0) {\n let record = {\n c: 'patch',\n t: now, // server time\n u: this.update,\n n: name,\n doc: dc,\n }\n this.broadcast(record, sus)\n }\n }\n\n if (this.allowFastPatch) {\n if (sus.length > 0) {\n let t1 = Date.now()\n let changes = this._encodeFastChanges(name)\n let t2 = Date.now()\n let record = {\n c: 'fpatch',\n t: now, // server time\n u: this.update,\n n: name,\n fdata: changes\n }\n this.broadcastRTC(record, sus)\n let t3 = Date.now()\n this.log(`_sendPatches: ${name} encode_changes: ${t2-t1}ms broadcast:${t3-t2}ms`)\n }\n }\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: any, value: any): void {\n this._documentChanges[name]?.push(opmsg(op, target, path, value))\n this._documentChanged[name] = true\n }\n\n propertyChange(name: string, id: string | number, property: string): void {\n let doc = this.documents[name]\n if (!doc) { return }\n let entities = doc.entities\n if (!entities) { return }\n let e = entities[id]\n if (!e) { return }\n e['__changed_'+property] = true\n //this.log('propertyChange', e)\n }\n\n\n /*= WEBRTC ===================================================================*/\n\n\n async _processOffer(client: ClientType, data: any): Promise<void> {\n if (!this.allowWebRTC) {\n this.warn('WebRTC is disabled')\n return\n }\n\n this.log(\"RTC: Processing offer from client\", client.ID, data);\n\n const peerConnection = new RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n //iceCandidatePoolSize: 10,\n })\n\n client.peerConnection = peerConnection\n\n peerConnection.onicecandidate = (event: any) => {\n if (event.candidate) {\n this.log(\"RTC: ICE candidate generated\", event.candidate.candidate.substring(0, 50) + \"...\");\n this.send(client, {\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: event.candidate, // .toJSON()\n })\n } else {\n this.log(\"RTC: ICE candidate gathering complete\");\n }\n }\n\n peerConnection.onconnectionstatechange = () => {\n this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);\n if (peerConnection.connectionState === 'connected') {\n client.webRTCConnected = true\n this.log(`RTC: Connection established with client ${client.ID}`)\n } else if (\n peerConnection.connectionState === 'failed' ||\n peerConnection.connectionState === 'disconnected' ||\n peerConnection.connectionState === 'closed'\n ) {\n client.webRTCConnected = false\n this.log(`RTC: Connection failed or closed with client ${client.ID}`)\n }\n }\n\n peerConnection.onicegatheringstatechange = () => {\n this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);\n }\n\n peerConnection.oniceconnectionstatechange = () => {\n this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);\n if (\n peerConnection.iceConnectionState === 'connected' ||\n peerConnection.iceConnectionState === 'completed'\n ) {\n this.log(`RTC: ICE connection established with client ${client.ID}`);\n }\n }\n\n try {\n this.log(\"RTC: Remote description set from data\", data);\n await peerConnection.setRemoteDescription(\n //data\n new RTCSessionDescription(data.sdp, data.type)\n )\n this.log(\"RTC: Remote description set successfully\");\n\n client.dataChannel = peerConnection.createDataChannel('serverchannel', {\n ordered: true,\n maxRetransmits: 1,\n })\n\n client.dataChannel.onopen = () => {\n this.log(`RTC: Data channel opened for client ${client.ID}`);\n // Try sending a test message\n try {\n const testData = { c: 'test', message: 'Hello WebRTC' }\n this.sendRTC(client, testData)\n } catch (e) {\n this.error(\n `RTC: Error sending test message to client ${client.ID}`,\n e\n )\n }\n }\n\n client.dataChannel.onclose = () => {\n this.log(`RTC: Data channel closed for client ${client.ID}`)\n }\n\n client.dataChannel.onerror = (error: Event) => {\n this.error(`RTC: Data channel error for client ${client.ID}:`, error)\n }\n\n client.dataChannel.onmessage = (event: MessageEvent) => {\n try {\n const data = decode(event.data)\n this.log(\n `RTC: Data channel message from client ${client.ID}:`,\n data\n )\n //this.onMessage(client, data);\n } catch (error) {\n this.error(\n `RTC: Error decoding message from client ${client.ID}:`,\n error\n )\n }\n }\n\n // Create and send answer\n const answer = await peerConnection.createAnswer()\n await peerConnection.setLocalDescription(answer)\n\n this.log(`RTC: Sending answer to client ${client.ID}`);\n this.send(client, {\n c: 'rtc-answer',\n type: answer.type,\n sdp: answer.sdp,\n })\n } catch (error) {\n this.error(\n `RTC: Error processing offer from client ${client.ID}:`,\n error\n )\n }\n }\n\n async _processICECandidate(client: ClientType, data: any): Promise<void> {\n this.log(`RTC: Processing ICE candidate from client ${client.ID}`);\n try {\n if (data.candidate && typeof(data.candidate) == 'object') {\n data.candidate = data.candidate.candidate\n }\n if (client.peerConnection && data.candidate) {\n await client.peerConnection.addIceCandidate(\n data.candidate\n //new wrtc.RTCIceCandidate(data.candidate)\n )\n this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);\n } else {\n this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`, client.peerConnection, data);\n }\n } catch (error) {\n this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)\n }\n }\n\n _clientRTCOpen(client: ClientType): boolean {\n return client.dataChannel !== null && client.dataChannel !== undefined && client.dataChannel.readyState === 'open'\n }\n\n async sendRTC(client: ClientType, message: any): Promise<void> {\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n\n let packages = this._splitRTCMessage(data)\n\n if (this.simulateLatency) {\n setTimeout(() => {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }\n }\n\n async broadcastRTC(message: any, clients: ClientType[] = []): Promise<void> {\n if (clients.length == 0) {\n clients = this.clients\n }\n let t1 = Date.now()\n let data = encode(message)\n let dl = data.byteLength\n let t2 = Date.now()\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n\n\n if (data.length > 16384) {\n this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n\n let packages = this._splitRTCMessage(data)\n\n for (let client of this.clients) {\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }\n }\n }\n\n _splitRTCMessage(data: Uint8Array): Uint8Array[] {\n let packages: Uint8Array[]\n if (data.byteLength > 65535) {\n const now = Date.now()\n this.warn(`RTC: Message too large: ${data.byteLength} bytes`)\n // Split the message into smaller packages\n packages = [];\n let offset = 0;\n let mid = this.update +'-'+ now\n let seq = 0\n\n // Create subsequent packages if needed\n while (offset < data.byteLength) {\n const remaining = data.byteLength - offset;\n const chunkSize = Math.min(remaining, MAX_PACKAGE_SIZE);\n const chunk = new Uint8Array(data.buffer, offset, chunkSize);\n let cmessage = {\n c: 'chunk',\n t: now,\n mid: mid,\n seq: seq,\n ofs: offset,\n chs: chunkSize,\n ts: data.byteLength,\n data: chunk,\n last: remaining <= MAX_PACKAGE_SIZE,\n }\n packages.push(encode(cmessage))\n offset += chunkSize;\n seq++;\n }\n\n this.log(`RTC: Large message split into ${packages.length} packages`);\n } else {\n packages = [data]\n this.log(`RTC: Message - ${data.byteLength} bytes`)\n }\n return packages\n }\n\n\n /*= DATABASE =================================================================*/\n // properties (of the documents) that starts with __ are not saved to the database.\n // __properties are restored on hydration. (for example __physicsBody or __bigObject)\n\n getUID(): number {\n this.documents['_server'].nextUID++\n return this.documents['_server'].nextUID\n }\n\n async _initDB(): Promise<void> {\n await this._connectDB()\n await this._loadDocument('_server')\n if (!this.documents['_server']) {\n this._initServerDocument()\n }\n }\n\n async _connectDB(): Promise<void> {\n this.mongoClient = new MongoClient(this.MongoUrl)\n try {\n await this.mongoClient.connect()\n this.log('Connected to MongoDB')\n const db = this.mongoClient.db(this.database)\n this.DB = db\n } catch (error) {\n this.error('Error connecting to MongoDB:', error)\n this.mongoClient = null\n }\n }\n\n async _loadDocument(name: string): Promise<void> {\n this.log(`Loading document '${name}' from MongoDB`)\n if (this.DB) {\n try {\n const doc = await this.DB.collection(this.collection).findOne({\n name: name,\n })\n if (doc) {\n delete (doc as any)._id\n this.documents[name] = doc\n }\n } catch (error) {\n this.error('Error loading document from MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not loaded.')\n }\n }\n\n async _saveDocument(name: string): Promise<void> {\n if (this.DB) {\n try {\n const doc = this.documents[name]\n let newdoc = clonewo_(doc, '__')\n this.log(`Saving document '${name}' to MongoDB`)\n await this.DB.collection(this.collection).updateOne(\n { name: name },\n { $set: newdoc },\n { upsert: true }\n )\n this.log('Document saved to MongoDB')\n } catch (error) {\n this.error('Error saving document to MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not saved.')\n }\n }\n\n async _saveAllDocuments(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this.documents) {\n await this._saveDocument(name)\n }\n }\n\n async _saveChanges(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this._documentChanged) {\n if (!this._lastSave[name]) {\n this._lastSave[name] = Date.now() - 60000\n }\n let lastSave = this._lastSave[name]\n if (Date.now() - lastSave < 10000) {\n continue\n }\n if (this._documentChanged[name]) {\n await this._saveDocument(name)\n this._documentChanged[name] = false\n this._lastSave[name] = Date.now()\n }\n }\n }\n\n _initServerDocument(): void {\n this.documents['_server'] = {\n nextUID: 100,\n }\n }\n\n /*= EXIT ===================================================================*/\n\n _exitSignal(signal: string): void {\n if (!this._exited) {\n this.log('\\nEXIT: Caught interrupt signal ' + signal)\n this._exited = true\n clearInterval(this._loopiv)\n clearInterval(this._statsiv)\n clearInterval(this._saveiv)\n this.onBeforeExit()\n this.broadcast({ server: 'Going down' })\n this._saveAllDocuments()\n this._wss!.close()\n setTimeout(() => process.exit(0), 1000)\n }\n }\n\n // To be redefined. Called BEFORE program exit, and saving all documents\n onBeforeExit(): void {}\n}\n","import { Packr } from 'msgpackr';\nimport { FLOAT32_OPTIONS } from 'msgpackr';\nconst { ALWAYS } = FLOAT32_OPTIONS;\n\nlet packr = new Packr({\n useFloat32: ALWAYS\n});\n\nexport function encode(obj: any): Uint8Array {\n return packr.pack(obj)\n}\n\nexport function decode(data: Uint8Array): any {\n return packr.unpack(data)\n}\n\ntype ReactiveCallback = (name: string, operation: string, target: any, path: string, value: any) => void;\n\nexport function reactive(name: string, object: any, callback: ReactiveCallback, path: string = '', excludedProperties: Record<string, boolean> | false = false): any {\n if (object === null || typeof object !== 'object') {\n //console.log('--- Type not object', typeof object)\n return object\n }\n\n function isReactive(p: string): boolean {\n let r = true\n if (p.startsWith('_')) {\n r = false\n }\n if (excludedProperties) {\n if (excludedProperties[p]) {\n r = false\n }\n }\n if (path == '/entities') {\n r = false\n }\n return r\n }\n\n for (const property in object) {\n if (isReactive(property)) {\n //console.log(`path '${path}', prop '${property}' is reactive`)\n object[property] = reactive(\n name,\n object[property],\n callback,\n path + '/' + property,\n excludedProperties\n )\n } else {\n //console.log(`--- path '${path}', property '${property}' is NOT reactive`)\n }\n }\n //console.log(`path '${path}' is reactive`)\n return new Proxy(object, {\n get(target: any, property: string | symbol, receiver: any): any { // ...arguments\n return Reflect.get(target, property, receiver)\n },\n set(target: any, property: string | symbol, value: any): boolean {\n let newvalue: any\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n newvalue = reactive(name, value, callback, pn, excludedProperties)\n callback(name, 'replace', target, pn, newvalue)\n } else {\n newvalue = value\n }\n return Reflect.set(target, property, newvalue)\n },\n deleteProperty(target: any, property: string | symbol): boolean {\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n callback(name, 'remove', target, pn, null)\n }\n delete target[property]\n return true\n },\n })\n\n}\n\nexport function deepGet(obj: any, path: string): any {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n for (let i = 0; i < len; i++) {\n if (obj[paths[i]!] == undefined) {\n return undefined\n } else {\n obj = obj[paths[i]!]\n }\n }\n return obj\n}\n\nexport function deepSet(obj: any, path: string, value: any): void {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n let i: number\n for (i = 0; i < len - 1; i++) {\n obj = obj[paths[i]!]\n }\n obj[paths[i]!] = value\n}\n\n// recursive clone oject, without properties that starts with _ (or __)\n\nexport function clonewo_(obj: any, excludeStart: string | Record<string, boolean> = '_'): any {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n\n function isExcluded(key: string): boolean {\n let e = false\n if (typeof (excludeStart) == 'string' && key.startsWith(excludeStart)) {\n e = true\n } else if (typeof(excludeStart) == 'object') {\n if (excludeStart[key] || key.startsWith('_')) {\n e = true\n }\n }\n return e\n }\n\n if (obj instanceof Map) {\n const mapClone = new Map()\n Array.from(obj.entries()).forEach(([key, value]) => {\n mapClone.set(clonewo_(key, excludeStart), clonewo_(value, excludeStart))\n })\n return mapClone\n }\n\n let clone: any\n if (Array.isArray(obj)) {\n clone = []\n for (let i = 0; i < obj.length; i++) {\n clone[i] = clonewo_(obj[i], excludeStart)\n }\n } else {\n clone = {} as Record<string, any>\n for (let key in obj) {\n if (obj.hasOwnProperty(key) && !isExcluded(key)) {\n if (typeof obj[key] === 'object') {\n clone[key] = clonewo_(obj[key], excludeStart)\n } else {\n clone[key] = obj[key]\n }\n }\n }\n }\n\n return clone\n}\n\nexport function limitPrecision(obj: any): any {\n if (Array.isArray(obj)) {\n return obj.map(limitPrecision)\n } else if (obj !== null && typeof obj === 'object') {\n const result: Record<string, any> = {}\n for (const key in obj) {\n result[key] = limitPrecision(obj[key])\n }\n return result\n } else if (typeof obj === 'number') {\n if (Number.isInteger(obj)) {\n return obj\n } else {\n // Limit to max 3 decimal digits, not fixed\n return parseFloat(obj.toFixed(3))\n }\n } else {\n return obj\n }\n}\n\nexport function msgop(op: any): any {\n let nop: any = {}\n if (!op.o) {\n nop.op = 'replace'\n } else {\n nop.op = ({\n a: 'add',\n r: 'remove',\n d: 'delete',\n t: 'test',\n } as Record<string, string>)[op.o]\n }\n nop.path = op.p\n nop.value = op.v\n return nop\n}\n\nexport function opmsg(op: string, target: any, path: string, value: any): any {\n let c: any = { p: path, v: value }\n if (op != 'replace') {\n c.o = ({\n add: 'a',\n remove: 'r',\n delete: 'd',\n test: 't',\n } as Record<string, string>)[op]\n }\n return c\n}\n\n// a function that converts an int to a hexa string\n// (8 characters long)\nexport function int2hex(int: number): string {\n return int.toString(16)\n}\n\n// a function that converts a hexa string to an int\nexport function hex2int(str: string): bigint {\n if (str.length % 2) {\n str = '0' + str\n }\n return BigInt('0x' + str)\n}\n\n// - Fixed point encoding/decoding functions\n\n// 32-bit unsigned integer encoding\nexport function encode_uint32(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(4)\n }\n let p = offset + 3\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n// 32-bit unsigned integer decoding\nexport function decode_uint32(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (\n ((byteArray[p++]! & 0x7f) << 24) |\n (byteArray[p++]! << 16) |\n (byteArray[p++]! << 8) |\n byteArray[p]!\n )\n}\n\n// 24-bit unsigned integer encoding\nexport function encode_uint24(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(3)\n }\n let p = offset + 2\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n\n// 24-bit unsigned integer decoding\nexport function decode_uint24(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (\n (byteArray[p++]! << 16) |\n (byteArray[p++]! << 8) |\n byteArray[p]!\n )\n}\n\n// 16-bit unsigned integer encoding\nexport function encode_uint16(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(2)\n }\n let p = offset + 1\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n\n// 16-bit unsigned integer decoding\nexport function decode_uint16(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (byteArray[p++]! << 8) | byteArray[p]!\n}\n\n// 24.8 bit ====================================================================\n\n// 24.8-bit fixed point encoding\nexport function encode_fp248(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint32(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 24.8-bit fixed point decoding\nexport function decode_fp248(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint32(byteArray, offset)\n return fp / divider\n}\n\n// 16.8 bit ====================================================================\n\n// 16.8-bit fixed point encoding (3 bytes)\nexport function encode_fp168(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint24(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 16.8-bit fixed point decoding (3 bytes)\nexport function decode_fp168(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint24(byteArray, offset)\n return fp / divider\n}\n\n// 16.16 bit ===================================================================\n\n// 16.16-bit fixed point encoding\nexport function encode_fp1616(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 65536)\n encode_uint32(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 16.16-bit fixed point decoding\nexport function decode_fp1616(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -65536 : 65536\n byteArray[offset]! &= 0x7f\n const fp = decode_uint32(byteArray, offset)\n return fp / divider\n}\n\n// 8.8 bit =====================================================================\n\n// 8.8-bit fixed point encoding\nexport function encode_fp88(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint16(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 8.8-bit fixed point decoding\nexport function decode_fp88(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint16(byteArray, offset)\n return fp / divider\n}\n\n// 4.12 bit ====================================================================\n\n// 4.12-bit fixed point encoding\nexport function encode_fp412(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 4096)\n encode_uint16(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 4.12-bit fixed point decoding\nexport function decode_fp412(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -4096 : 4096\n byteArray[offset]! &= 0x7f\n const fp = decode_uint16(byteArray, offset)\n return fp / divider\n}\n\n// 1.7 bit =====================================================================\n\n// 1.7-bit fixed point encoding\nexport function encode_fp17(float: number, byteArray: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 128)\n byteArray[offset] = fp\n if (float < 0) {\n byteArray[offset] |= 0x80\n }\n}\n\n// 1.7-bit fixed point decoding\nexport function decode_fp17(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -128.0 : 128.0\n byteArray[offset]! &= 0x7f\n return byteArray[offset]! / divider\n}\n","import { promisify } from 'util'\nimport { gzip, gunzip, constants } from 'zlib'\n\nconst MIN_COMPRESSED_BUFFER_SIZE = 256\nconst MAX_COMPRESSED_BUFFER_SIZE = 999999\n\nconst lib_compress = promisify(gzip)\nconst lib_decompress = promisify(gunzip)\n\nexport async function compress(buffer:Uint8Array<ArrayBufferLike>) {\n if (buffer.byteLength <= MIN_COMPRESSED_BUFFER_SIZE || buffer.byteLength >= MAX_COMPRESSED_BUFFER_SIZE) return buffer\n try {\n let t1 = Date.now()\n let cbytes = await lib_compress(buffer, {\n level: constants.Z_BEST_SPEED\n })\n let t2 = Date.now()\n let cbuffer = Buffer.from(cbytes)\n let t3 = Date.now()\n\n //console.log(`Node compression ${buffer.byteLength} -> ${cbuffer.byteLength}, time: ${t2 - t1}ms`)\n\n return cbuffer\n } catch (error) {\n console.error('Error compressing buffer:', error)\n return buffer\n }\n}\n\nexport async function decompress(buffer:Uint8Array<ArrayBufferLike>) {\n try {\n let cbytes = await lib_decompress(buffer)\n let cbuffer = Buffer.from(cbytes)\n return cbuffer\n } catch (error) {\n console.error('Error decompressing buffer:', error)\n return buffer\n }\n}\n"],"mappings":"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","names":["import_msgpackr","fastjsonpatch","key","data"]}
|
package/dist/server.d.cts
CHANGED
|
@@ -14,6 +14,8 @@ declare class TopazCubeServer {
|
|
|
14
14
|
DEBUG: boolean;
|
|
15
15
|
name: string;
|
|
16
16
|
cycle: number;
|
|
17
|
+
saveCheckCycle: number;
|
|
18
|
+
saveCycle: number;
|
|
17
19
|
patchCycleDivider: number;
|
|
18
20
|
port: number;
|
|
19
21
|
useHttps: boolean;
|
|
@@ -40,6 +42,7 @@ declare class TopazCubeServer {
|
|
|
40
42
|
update: number;
|
|
41
43
|
lastUpdate: number;
|
|
42
44
|
_saveiv: any;
|
|
45
|
+
_lastSave: Record<string, number>;
|
|
43
46
|
_loopiv: any;
|
|
44
47
|
_statsiv: any;
|
|
45
48
|
_stillUpdating: boolean;
|
|
@@ -49,9 +52,11 @@ declare class TopazCubeServer {
|
|
|
49
52
|
log(...args: any[]): void;
|
|
50
53
|
warn(...args: any[]): void;
|
|
51
54
|
error(...args: any[]): void;
|
|
52
|
-
constructor({ name, cycle, port, useHttps, key, cert, MongoUrl, database, collection, allowSave, allowSync, allowWebRTC, allowFastPatch, allowCompression, simulateLatency, DEBUG }?: {
|
|
55
|
+
constructor({ name, cycle, saveCheckCycle, saveCycle, port, useHttps, key, cert, MongoUrl, database, collection, allowSave, allowSync, allowWebRTC, allowFastPatch, allowCompression, simulateLatency, DEBUG }?: {
|
|
53
56
|
name?: string;
|
|
54
57
|
cycle?: number;
|
|
58
|
+
saveCheckCycle?: number;
|
|
59
|
+
saveCycle?: number;
|
|
55
60
|
port?: number;
|
|
56
61
|
useHttps?: boolean;
|
|
57
62
|
key?: string;
|
package/dist/server.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ declare class TopazCubeServer {
|
|
|
14
14
|
DEBUG: boolean;
|
|
15
15
|
name: string;
|
|
16
16
|
cycle: number;
|
|
17
|
+
saveCheckCycle: number;
|
|
18
|
+
saveCycle: number;
|
|
17
19
|
patchCycleDivider: number;
|
|
18
20
|
port: number;
|
|
19
21
|
useHttps: boolean;
|
|
@@ -40,6 +42,7 @@ declare class TopazCubeServer {
|
|
|
40
42
|
update: number;
|
|
41
43
|
lastUpdate: number;
|
|
42
44
|
_saveiv: any;
|
|
45
|
+
_lastSave: Record<string, number>;
|
|
43
46
|
_loopiv: any;
|
|
44
47
|
_statsiv: any;
|
|
45
48
|
_stillUpdating: boolean;
|
|
@@ -49,9 +52,11 @@ declare class TopazCubeServer {
|
|
|
49
52
|
log(...args: any[]): void;
|
|
50
53
|
warn(...args: any[]): void;
|
|
51
54
|
error(...args: any[]): void;
|
|
52
|
-
constructor({ name, cycle, port, useHttps, key, cert, MongoUrl, database, collection, allowSave, allowSync, allowWebRTC, allowFastPatch, allowCompression, simulateLatency, DEBUG }?: {
|
|
55
|
+
constructor({ name, cycle, saveCheckCycle, saveCycle, port, useHttps, key, cert, MongoUrl, database, collection, allowSave, allowSync, allowWebRTC, allowFastPatch, allowCompression, simulateLatency, DEBUG }?: {
|
|
53
56
|
name?: string;
|
|
54
57
|
cycle?: number;
|
|
58
|
+
saveCheckCycle?: number;
|
|
59
|
+
saveCycle?: number;
|
|
55
60
|
port?: number;
|
|
56
61
|
useHttps?: boolean;
|
|
57
62
|
key?: string;
|
package/dist/server.js
CHANGED
|
@@ -297,6 +297,8 @@ var TopazCubeServer = class {
|
|
|
297
297
|
DEBUG = false;
|
|
298
298
|
name = "TopazCubeServer";
|
|
299
299
|
cycle = 100;
|
|
300
|
+
saveCheckCycle = 1e3;
|
|
301
|
+
saveCycle = 1e4;
|
|
300
302
|
patchCycleDivider = 1;
|
|
301
303
|
port = 8799;
|
|
302
304
|
useHttps = false;
|
|
@@ -323,6 +325,7 @@ var TopazCubeServer = class {
|
|
|
323
325
|
update = 0;
|
|
324
326
|
lastUpdate = 0;
|
|
325
327
|
_saveiv = null;
|
|
328
|
+
_lastSave = {};
|
|
326
329
|
_loopiv = null;
|
|
327
330
|
_statsiv = null;
|
|
328
331
|
_stillUpdating = false;
|
|
@@ -351,6 +354,8 @@ var TopazCubeServer = class {
|
|
|
351
354
|
constructor({
|
|
352
355
|
name = "TopazCubeServer",
|
|
353
356
|
cycle = 100,
|
|
357
|
+
saveCheckCycle = 1e3,
|
|
358
|
+
saveCycle = 1e4,
|
|
354
359
|
port = 8799,
|
|
355
360
|
useHttps = false,
|
|
356
361
|
key = "./cert/key.pem",
|
|
@@ -368,6 +373,8 @@ var TopazCubeServer = class {
|
|
|
368
373
|
} = {}) {
|
|
369
374
|
this.name = name;
|
|
370
375
|
this.cycle = cycle;
|
|
376
|
+
this.saveCheckCycle = saveCheckCycle;
|
|
377
|
+
this.saveCycle = saveCycle;
|
|
371
378
|
this.port = port;
|
|
372
379
|
this.useHttps = useHttps;
|
|
373
380
|
this.key = key;
|
|
@@ -533,7 +540,7 @@ var TopazCubeServer = class {
|
|
|
533
540
|
}, 1e3);
|
|
534
541
|
this._saveiv = setInterval(() => {
|
|
535
542
|
this._saveChanges();
|
|
536
|
-
},
|
|
543
|
+
}, 1e3);
|
|
537
544
|
}
|
|
538
545
|
_loop() {
|
|
539
546
|
let now = Date.now();
|
|
@@ -1243,9 +1250,17 @@ var TopazCubeServer = class {
|
|
|
1243
1250
|
return;
|
|
1244
1251
|
}
|
|
1245
1252
|
for (let name in this._documentChanged) {
|
|
1253
|
+
if (!this._lastSave[name]) {
|
|
1254
|
+
this._lastSave[name] = Date.now() - 6e4;
|
|
1255
|
+
}
|
|
1256
|
+
let lastSave = this._lastSave[name];
|
|
1257
|
+
if (Date.now() - lastSave < 1e4) {
|
|
1258
|
+
continue;
|
|
1259
|
+
}
|
|
1246
1260
|
if (this._documentChanged[name]) {
|
|
1247
1261
|
await this._saveDocument(name);
|
|
1248
1262
|
this._documentChanged[name] = false;
|
|
1263
|
+
this._lastSave[name] = Date.now();
|
|
1249
1264
|
}
|
|
1250
1265
|
}
|
|
1251
1266
|
}
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/utils.ts","../src/compress-node.ts"],"sourcesContent":["import * as https from 'node:https'\nimport * as fs from 'node:fs'\nimport {\n reactive,\n deepGet,\n clonewo_,\n opmsg,\n msgop,\n encode_uint32,\n encode_fp412,\n encode_fp168,\n encode_fp1616,\n limitPrecision,\n encode,\n decode\n} from './utils'\nimport { compress, decompress } from './compress-node'\nimport fastjsonpatch from 'fast-json-patch'\nimport { WebSocketServer, WebSocket } from 'ws'\nimport { MongoClient, Db } from 'mongodb'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\nimport { RTCPeerConnection, RTCDataChannel, RTCSessionDescription } from \"werift\";\n\nglMatrix.setMatrixArrayType(Array)\n\n// entities/ID/\nconst fastPatchProperties: Record<string, boolean> = {\n 'type': true, // string 'enemy'\n 'status': true, // string 'idle'\n 'level': true, // number 2\n 'race': true, // string 'goblin'\n 'class': true, // string 'warrior'\n 'model': true, // string 'models/models.glb|goblin'\n 'animation': true, // string 'idle2'\n 'sound': true, // string 'sound/goblin.snd|snarl'\n 'effect': true, // 'selected'\n 'position': true, // [0, 0, 0] Vector (Number)\n 'rotation': true, // [0, 0, 0, 1] Quaternion (Number)\n 'scale': true, // [1, 1, 1] Vector (Number)\n}\n\nconst dictionaryProperties: Record<string, boolean> = {\n 'type': true,\n 'status': true,\n 'level': true,\n 'race': true,\n 'class': true,\n 'model': true,\n 'animation': true,\n 'sound': true,\n 'effect': true,\n}\n\nconst { applyOperation } = fastjsonpatch\nconst LITTLE_ENDIAN = (() => {\n const buffer = new ArrayBuffer(2)\n new DataView(buffer).setInt16(0, 256, true)\n return new Int16Array(buffer)[0] === 256\n})()\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\n\ntype ClientType = any\n\ninterface StatsType {\n tUpdate: number[]\n tPatch: number[]\n send: number\n sendRTC: number\n _sendRTCUpdate: number\n [key: string]: any\n}\n\nexport default class TopazCubeServer {\n DEBUG = false\n name = 'TopazCubeServer'\n cycle = 100\n patchCycleDivider = 1\n port = 8799\n useHttps = false\n key = './cert/key.pem'\n cert = './cert/cert.pem'\n MongoUrl = 'mongodb://localhost:27017'\n mongoClient: MongoClient | null = null\n DB: Db | null = null\n database = 'topazcube'\n collection = 'documents'\n allowSave = true\n allowSync = true\n allowWebRTC = false\n allowFastPatch = false\n allowCompression = false\n simulateLatency = 0\n _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentChanged: Record<string, boolean> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _saveiv: any = null\n _loopiv: any = null\n _statsiv: any = null\n _stillUpdating = false\n stats: StatsType = {\n tUpdate: [],\n tPatch: [],\n send: 0,\n sendRTC: 0,\n _sendRTCUpdate: 0\n }\n\n _wss: WebSocketServer | null = null\n _exited = false\n\n log(...args: any[]) {\n if (this.DEBUG) {\n console.log(this.name + ':', ...args);\n }\n }\n\n warn(...args: any[]) {\n if (this.DEBUG) {\n console.warn(this.name + ':', ...args);\n }\n }\n\n error(...args: any[]) {\n console.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n port = 8799,\n useHttps = false,\n key = './cert/key.pem',\n cert = './cert/cert.pem',\n MongoUrl = 'mongodb://localhost:27017',\n database = 'topazcube',\n collection = 'documents',\n allowSave = true,\n allowSync = true,\n allowWebRTC = false,\n allowFastPatch = false,\n allowCompression = false,\n simulateLatency = 0,\n DEBUG = false\n }: {\n name?: string\n cycle?: number\n port?: number\n useHttps?: boolean\n key?: string\n cert?: string\n MongoUrl?: string\n database?: string\n collection?: string\n allowSave?: boolean\n allowSync?: boolean\n allowWebRTC?: boolean\n allowFastPatch?: boolean\n allowCompression?: boolean\n simulateLatency?: number\n DEBUG?: boolean\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.port = port\n this.useHttps = useHttps\n this.key = key\n this.cert = cert\n this.MongoUrl = MongoUrl\n this.database = database\n this.collection = collection\n this.allowSave = allowSave\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.allowFastPatch = allowFastPatch\n this.allowCompression = allowCompression\n this.simulateLatency = simulateLatency\n this.DEBUG = DEBUG\n\n this._initDB()\n\n if (useHttps) {\n let httpsServer: https.Server | null = https.createServer({\n key: fs.readFileSync(this.key),\n cert: fs.readFileSync(this.cert),\n }, (req, res) => {\n res.writeHead(200)\n res.end('<b>Hello World!</b>')\n }).listen(this.port)\n this._wss = new WebSocketServer({ server: httpsServer })\n httpsServer = null\n this.log(this.name + ' running on HTTPS port ' + this.port)\n } else {\n this._wss = new WebSocketServer({ port: this.port })\n this.log(this.name + ' running on port ' + this.port)\n }\n this._wss.on('connection', (client: WebSocket) => {\n this._onConnected(client)\n })\n\n process.stdin.resume()\n process.on('SIGINT', () => {\n this._exitSignal('SIGINT')\n })\n process.on('SIGQUIT', () => {\n this._exitSignal('SIGQUIT')\n })\n process.on('SIGTERM', () => {\n this._exitSignal('SIGTERM')\n })\n process.on('SIGUSR2', () => {\n this._exitSignal('SIGUSR2')\n })\n\n // Setup keypress handling for console input\n process.stdin.resume()\n process.stdin.setEncoding('utf8')\n\n process.stdin.on('data', (key: any) => {\n key = (''+key).trim()\n\n // ctrl-c ( end of text )\n if (key == '\\u0003') {\n this._exitSignal('SIGINT')\n return\n }\n\n // Process other keypresses\n this.log(`Key pressed: ${key}`)\n\n // Example: 's' to save all documents\n if (key == 's') {\n this.log('Saving all documents...')\n this._saveAllDocuments()\n }\n\n // Example: 'i' to print server info\n if (key == 'i') {\n this.log(\n `Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`\n )\n }\n })\n this._startLoop()\n }\n\n /*= DOCUMENTS ==============================================================*/\n\n // to be redefined. Called before a new document is created. Returns true if\n // the client has the right to create an empty document\n canCreate(client: ClientType, name: string): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is created\n // (returns an empty document)\n onCreate(name: string): any {\n return {\n data: {},\n }\n }\n\n // to be redefined. Called when a client wants to sync (modify) a document.\n // Returns true if the client has the right to sync that operation.\n canSync(client: ClientType, name: string, op: any): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is hydrated\n // (created, or loaded from db)\n async onHydrate(name: string, document: any): Promise<void> {\n document.__hydrated = true\n }\n\n _makeReactive(name: string): void {\n //this.log(`Making document '${name}' reactive`, this.documents[name])\n let ep: any = false\n if (this.allowFastPatch) {\n ep = fastPatchProperties\n }\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this),\n '',\n ep\n )\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n this._documentChanged[name] = false\n }\n }\n\n _createEmptyDocument(name: string): void {\n let doc = this.onCreate(name)\n if (!doc) {\n return\n }\n this.documents[name] = doc\n }\n\n async _waitLoad(name: string): Promise<void> {\n if (this.isLoading[name]) {\n while (this.isLoading[name]) {\n await new Promise((resolve) => setTimeout(resolve, 50))\n }\n }\n }\n\n async _checkDocument(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n if (!this.documents[name]) {\n this.isLoading[name] = true\n await this._loadDocument(name)\n if (!this.documents[name] && this.canCreate(client, name)) {\n this._createEmptyDocument(name)\n }\n if (this.documents[name]) {\n this._makeReactive(name)\n this.onHydrate(name, this.documents[name])\n }\n this.isLoading[name] = false\n this._documentState[name] = {\n subscibers: 0,\n lastModified: Date.now(),\n }\n }\n }\n\n _updateAllDocumentsState(): void {\n for (let name in this.documents) {\n if (name != '_server') {\n let doc = this.documents[name]\n this._documentState[name].subscibers = 0\n for (let client of this.clients) {\n if (client.subscribed && client.subscribed[name]) {\n this._documentState[name].subscibers++\n }\n }\n }\n }\n }\n\n /*= UPDATE LOOP ============================================================*/\n\n // to be redefined. called every this.cycle ms\n onUpdate(name: string, doc: any, dt: number): void {}\n\n _startLoop(): void {\n this.lastUpdate = Date.now()\n this._loop()\n this._statsiv = setInterval(() => {\n this._doStats()\n }, 1000)\n this._saveiv = setInterval(() => {\n this._saveChanges()\n }, 60000)\n }\n\n _loop(): void {\n let now = Date.now()\n let dtms = (now - this.lastUpdate)\n let dt = dtms / 1000.0 // Convert to seconds\n this.lastUpdate = now\n\n /*\n if (this._stillUpdating) {\n return\n }\n */\n this._stillUpdating = true\n for (let name in this.documents) {\n this.onUpdate(name, this.documents[name], dt)\n }\n let t1 = Date.now()\n this._stillUpdating = false\n let updateTime = t1 - now\n this.stats.tUpdate.push(updateTime)\n\n //this.log(`update ${this.update} patch: ${this.update % this.patchCycleDivider}`, )\n\n let patchTime = 0\n if (this.update % this.patchCycleDivider == 0) {\n this._sendPatches()\n let t2 = Date.now()\n patchTime = t2 - t1\n this.stats.tPatch.push(patchTime)\n if (this.allowFastPatch) {\n this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`, )\n }\n this.stats._sendRTCUpdate = 0\n }\n\n this.update++\n let endUpdate = Date.now()\n let totalUpdate = endUpdate - now\n\n setTimeout(() => {\n this._loop()\n }, Math.max(this.cycle - totalUpdate, 10))\n }\n\n _doStats(): void {\n for (let key in this.stats) {\n let i = this.stats[key]\n if (Array.isArray(i) && i.length > 0) {\n while (i.length > 60) {\n i.shift()\n }\n this.stats['_avg_' + key] = i.reduce((a: number, b: number) => a + b, 0) / i.length\n } else if (!key.startsWith('_')) {\n this.stats['_persec_' + key] = i / 3.0\n this.stats[key] = 0\n }\n }\n //this.log('stats', this.stats)\n }\n\n /*= MESSAGES ===============================================================*/\n\n // to be redefined. Called on message (operation) from client\n onMessage(client: ClientType, message: any): void {}\n\n // to be redefined. Called when a client connects\n onConnect(client: ClientType): void {}\n\n // to be redefined. Called when a client disconnects\n onDisconnect(client: ClientType): void {}\n\n _onConnected(client: ClientType): void {\n client.ID = this.getUID()\n client.ping = 0\n client.ctdiff = 0\n client.subscribed = {}\n client.dataChannel = null\n client.peerConnection = null\n\n this.log('client connected', client.ID)\n this.clients.push(client)\n client.on('error', (...args: any[]) => {\n this._onError(client, args)\n })\n client.on('message', (message:any) => {\n let dec = decode(message)\n if (this.simulateLatency) {\n setTimeout(() => {\n this._onMessage(client, dec)\n }, this.simulateLatency)\n } else {\n this._onMessage(client, dec)\n }\n })\n client.on('close', (message:any) => {\n this._onDisconnected(client)\n this.onDisconnect(client)\n })\n this.onConnect(client)\n }\n\n async _onMessage(client: ClientType, message: any): Promise<void> {\n if (\n message.c == 'sync' &&\n this.allowSync &&\n client.subscribed &&\n client.subscribed[message.n] &&\n this.documents[message.n]\n ) {\n let name = message.n\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n this._documentChanged[name] = false\n }\n for (let op of message.p) {\n if (!this.canSync(client, name, op)) {\n continue\n }\n this._documentChanges[name].push(op)\n this._documentChanged[name] = true\n let dop = msgop(op)\n applyOperation(this.documents[name], dop)\n }\n } else if (message.c == 'ping') {\n this.send(client, {\n c: 'pong',\n t: Date.now(),\n ct: message.ct,\n ID: client.ID,\n })\n } else if (message.c == 'peng') {\n let time = Date.now()\n let ping = time - message.st\n client.ctdiff = message.ct + ping / 2 - time\n client.ping = ping\n //this.log(time, \"PENG ping, ctdiff\", message, ping, client.ctdiff, \"ms\")\n } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\n } else if (message.c == 'sub') {\n await this._checkDocument(message.n, client)\n if (!this.documents[message.n]) {\n this.send(client, {\n c: 'error',\n t: Date.now(),\n message: 'Document not found',\n })\n return\n }\n if (client.subscribed) {\n client.subscribed[message.n] = true\n }\n this._sendFullState(message.n, client)\n } else if (message.c == 'unsub') {\n if (client.subscribed) {\n client.subscribed[message.n] = false\n }\n } else {\n this.onMessage(client, message)\n }\n }\n\n _onError(client: ClientType, args: any[]): void {\n this.error('onError:', args)\n }\n\n _onDisconnected(client: ClientType): void {\n if (client.dataChannel) {\n client.dataChannel.close()\n }\n if (client.peerConnection) {\n client.peerConnection.close()\n }\n this.log('client disconnected')\n let index = this.clients.indexOf(client)\n if (index !== -1) {\n this.clients.splice(index, 1)\n }\n }\n\n async send(client: ClientType, message: any): Promise<void> {\n try {\n let t1 = Date.now()\n let data = encode(message)\n let t2 = Date.now()\n let dl = data.byteLength\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n if (data.length > 4096) {\n this.log(`Big message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n } catch (e) {\n this.error('Error sending message:', e, message)\n }\n }\n\n async broadcast(message: object, clients: ClientType[] | false = false): Promise<void> {\n if (!clients) {\n clients = this.clients\n }\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n for (let client of this.clients) {\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n }\n }\n\n async _sendFullState(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n let excluded: any = '_'\n if (this.allowFastPatch) {\n excluded = fastPatchProperties\n }\n let doc = clonewo_(this.documents[name], excluded)\n limitPrecision(doc)\n let fdata: any = false\n if (this.allowFastPatch) {\n fdata = this._encodeFastChanges(name, false)\n }\n let fullState = {\n c: 'full',\n le: LITTLE_ENDIAN,\n t: Date.now(),\n n: name,\n doc: doc,\n fdata: fdata\n }\n this.send(client, fullState)\n }\n\n _encodeFastChanges(name: string, changesOnly = true): any {\n let doc = this.documents[name]\n if (!doc) { return false }\n let origin = this.documents[name].origin\n if (!origin) {\n origin = [0, 0, 0]\n this.documents[name].origin = origin\n }\n\n let entities = doc.entities\n let ids = Object.keys(entities)\n if (!entities) { return false }\n let count: Record<string, number> = {}\n let changed: any = {}\n let hasChanges: any = {}\n let dictionary: any = {}\n let encodedChanges: any = {}\n\n for (let key in fastPatchProperties) {\n if (changesOnly) {\n count[key] = 0\n changed[key] = {}\n hasChanges[key] = false\n } else {\n count[key] = ids.length\n changed[key] = {}\n hasChanges[key] = true\n }\n dictionary[key] = {}\n }\n\n // search for changes\n\n if (changesOnly) {\n for (let id in entities) {\n let e = entities[id]\n for (let key in fastPatchProperties) {\n if (e['__changed_' + key]) {\n changed[''+key][''+id] = true\n count[''+key] = parseInt(''+count[''+key]) + 1\n hasChanges[''+key] = true\n e['__changed_' + key] = false\n }\n }\n }\n } else {\n for (let id in entities) {\n for (let key in fastPatchProperties) {\n changed[''+key][''+id] = true\n }\n }\n }\n\n // create dictionaries\n\n let dictUID = 1\n for (let key in hasChanges) {\n if (hasChanges[key] && dictionaryProperties[key]) {\n for (let id in changed[key]) {\n let e = entities[id]\n let value = e[key]\n if (!dictionary[key][value]) {\n dictionary[key][value] = dictUID++\n }\n }\n }\n }\n\n this.log(\"--------------------------------------------------\")\n //this.log(\"changed\", changed)\n //this.log(\"count\", count)\n\n // create encoded changes\n //\n for (let key in hasChanges) {\n if (hasChanges[key]) {\n let size = parseInt(''+count[''+key])\n let encoded: any = {}\n if (dictionaryProperties[key]) {\n encoded.dict = dictionary[key]\n\n let pdata = new Uint8Array(size * 8)\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n let value = e[key]\n let did = parseInt(dictionary[key][value])\n encode_uint32(did, pdata, offset)\n offset += 4\n }\n encoded.pdata = pdata\n } else {\n\n let pdata: Uint8Array\n if (key == 'position') {\n pdata = new Uint8Array(size * 13)\n } else if (key == 'rotation') {\n pdata = new Uint8Array(size * 16)\n } else if (key == 'scale') {\n pdata = new Uint8Array(size * 16)\n } else {\n pdata = new Uint8Array(0)\n }\n\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n if (key == 'position') {\n encode_fp168(e.position[0] - origin[0], pdata, offset)\n offset += 3\n encode_fp168(e.position[1] - origin[1], pdata, offset)\n offset += 3\n encode_fp168(e.position[2] - origin[2], pdata, offset)\n offset += 3\n } else if (key == 'rotation') {\n encode_fp412(e.rotation[0], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[1], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[2], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[3], pdata, offset)\n offset += 2\n } else if (key == 'scale') {\n encode_fp1616(e.scale[0], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[1], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[2], pdata, offset)\n offset += 4\n }\n }\n encoded.pdata = pdata\n }\n encodedChanges[key] = encoded\n }\n }\n\n return encodedChanges\n }\n\n _sendPatches(): void {\n let now = Date.now()\n\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n this._documentChanges[name] = []\n let sus = this.clients.filter((client) => client.subscribed && client.subscribed[name])\n if (sus.length > 0) {\n if (dc && dc.length > 0) {\n let record = {\n c: 'patch',\n t: now, // server time\n u: this.update,\n n: name,\n doc: dc,\n }\n this.broadcast(record, sus)\n }\n }\n\n if (this.allowFastPatch) {\n if (sus.length > 0) {\n let t1 = Date.now()\n let changes = this._encodeFastChanges(name)\n let t2 = Date.now()\n let record = {\n c: 'fpatch',\n t: now, // server time\n u: this.update,\n n: name,\n fdata: changes\n }\n this.broadcastRTC(record, sus)\n let t3 = Date.now()\n this.log(`_sendPatches: ${name} encode_changes: ${t2-t1}ms broadcast:${t3-t2}ms`)\n }\n }\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: any, value: any): void {\n this._documentChanges[name]?.push(opmsg(op, target, path, value))\n this._documentChanged[name] = true\n }\n\n propertyChange(name: string, id: string | number, property: string): void {\n let doc = this.documents[name]\n if (!doc) { return }\n let entities = doc.entities\n if (!entities) { return }\n let e = entities[id]\n if (!e) { return }\n e['__changed_'+property] = true\n //this.log('propertyChange', e)\n }\n\n\n /*= WEBRTC ===================================================================*/\n\n\n async _processOffer(client: ClientType, data: any): Promise<void> {\n if (!this.allowWebRTC) {\n this.warn('WebRTC is disabled')\n return\n }\n\n this.log(\"RTC: Processing offer from client\", client.ID, data);\n\n const peerConnection = new RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n //iceCandidatePoolSize: 10,\n })\n\n client.peerConnection = peerConnection\n\n peerConnection.onicecandidate = (event: any) => {\n if (event.candidate) {\n this.log(\"RTC: ICE candidate generated\", event.candidate.candidate.substring(0, 50) + \"...\");\n this.send(client, {\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: event.candidate, // .toJSON()\n })\n } else {\n this.log(\"RTC: ICE candidate gathering complete\");\n }\n }\n\n peerConnection.onconnectionstatechange = () => {\n this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);\n if (peerConnection.connectionState === 'connected') {\n client.webRTCConnected = true\n this.log(`RTC: Connection established with client ${client.ID}`)\n } else if (\n peerConnection.connectionState === 'failed' ||\n peerConnection.connectionState === 'disconnected' ||\n peerConnection.connectionState === 'closed'\n ) {\n client.webRTCConnected = false\n this.log(`RTC: Connection failed or closed with client ${client.ID}`)\n }\n }\n\n peerConnection.onicegatheringstatechange = () => {\n this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);\n }\n\n peerConnection.oniceconnectionstatechange = () => {\n this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);\n if (\n peerConnection.iceConnectionState === 'connected' ||\n peerConnection.iceConnectionState === 'completed'\n ) {\n this.log(`RTC: ICE connection established with client ${client.ID}`);\n }\n }\n\n try {\n this.log(\"RTC: Remote description set from data\", data);\n await peerConnection.setRemoteDescription(\n //data\n new RTCSessionDescription(data.sdp, data.type)\n )\n this.log(\"RTC: Remote description set successfully\");\n\n client.dataChannel = peerConnection.createDataChannel('serverchannel', {\n ordered: true,\n maxRetransmits: 1,\n })\n\n client.dataChannel.onopen = () => {\n this.log(`RTC: Data channel opened for client ${client.ID}`);\n // Try sending a test message\n try {\n const testData = { c: 'test', message: 'Hello WebRTC' }\n this.sendRTC(client, testData)\n } catch (e) {\n this.error(\n `RTC: Error sending test message to client ${client.ID}`,\n e\n )\n }\n }\n\n client.dataChannel.onclose = () => {\n this.log(`RTC: Data channel closed for client ${client.ID}`)\n }\n\n client.dataChannel.onerror = (error: Event) => {\n this.error(`RTC: Data channel error for client ${client.ID}:`, error)\n }\n\n client.dataChannel.onmessage = (event: MessageEvent) => {\n try {\n const data = decode(event.data)\n this.log(\n `RTC: Data channel message from client ${client.ID}:`,\n data\n )\n //this.onMessage(client, data);\n } catch (error) {\n this.error(\n `RTC: Error decoding message from client ${client.ID}:`,\n error\n )\n }\n }\n\n // Create and send answer\n const answer = await peerConnection.createAnswer()\n await peerConnection.setLocalDescription(answer)\n\n this.log(`RTC: Sending answer to client ${client.ID}`);\n this.send(client, {\n c: 'rtc-answer',\n type: answer.type,\n sdp: answer.sdp,\n })\n } catch (error) {\n this.error(\n `RTC: Error processing offer from client ${client.ID}:`,\n error\n )\n }\n }\n\n async _processICECandidate(client: ClientType, data: any): Promise<void> {\n this.log(`RTC: Processing ICE candidate from client ${client.ID}`);\n try {\n if (data.candidate && typeof(data.candidate) == 'object') {\n data.candidate = data.candidate.candidate\n }\n if (client.peerConnection && data.candidate) {\n await client.peerConnection.addIceCandidate(\n data.candidate\n //new wrtc.RTCIceCandidate(data.candidate)\n )\n this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);\n } else {\n this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`, client.peerConnection, data);\n }\n } catch (error) {\n this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)\n }\n }\n\n _clientRTCOpen(client: ClientType): boolean {\n return client.dataChannel !== null && client.dataChannel !== undefined && client.dataChannel.readyState === 'open'\n }\n\n async sendRTC(client: ClientType, message: any): Promise<void> {\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n\n let packages = this._splitRTCMessage(data)\n\n if (this.simulateLatency) {\n setTimeout(() => {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }\n }\n\n async broadcastRTC(message: any, clients: ClientType[] = []): Promise<void> {\n if (clients.length == 0) {\n clients = this.clients\n }\n let t1 = Date.now()\n let data = encode(message)\n let dl = data.byteLength\n let t2 = Date.now()\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n\n\n if (data.length > 16384) {\n this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n\n let packages = this._splitRTCMessage(data)\n\n for (let client of this.clients) {\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }\n }\n }\n\n _splitRTCMessage(data: Uint8Array): Uint8Array[] {\n let packages: Uint8Array[]\n if (data.byteLength > 65535) {\n const now = Date.now()\n this.warn(`RTC: Message too large: ${data.byteLength} bytes`)\n // Split the message into smaller packages\n packages = [];\n let offset = 0;\n let mid = this.update +'-'+ now\n let seq = 0\n\n // Create subsequent packages if needed\n while (offset < data.byteLength) {\n const remaining = data.byteLength - offset;\n const chunkSize = Math.min(remaining, MAX_PACKAGE_SIZE);\n const chunk = new Uint8Array(data.buffer, offset, chunkSize);\n let cmessage = {\n c: 'chunk',\n t: now,\n mid: mid,\n seq: seq,\n ofs: offset,\n chs: chunkSize,\n ts: data.byteLength,\n data: chunk,\n last: remaining <= MAX_PACKAGE_SIZE,\n }\n packages.push(encode(cmessage))\n offset += chunkSize;\n seq++;\n }\n\n this.log(`RTC: Large message split into ${packages.length} packages`);\n } else {\n packages = [data]\n this.log(`RTC: Message - ${data.byteLength} bytes`)\n }\n return packages\n }\n\n\n /*= DATABASE =================================================================*/\n // properties (of the documents) that starts with __ are not saved to the database.\n // __properties are restored on hydration. (for example __physicsBody or __bigObject)\n\n getUID(): number {\n this.documents['_server'].nextUID++\n return this.documents['_server'].nextUID\n }\n\n async _initDB(): Promise<void> {\n await this._connectDB()\n await this._loadDocument('_server')\n if (!this.documents['_server']) {\n this._initServerDocument()\n }\n }\n\n async _connectDB(): Promise<void> {\n this.mongoClient = new MongoClient(this.MongoUrl)\n try {\n await this.mongoClient.connect()\n this.log('Connected to MongoDB')\n const db = this.mongoClient.db(this.database)\n this.DB = db\n } catch (error) {\n this.error('Error connecting to MongoDB:', error)\n this.mongoClient = null\n }\n }\n\n async _loadDocument(name: string): Promise<void> {\n this.log(`Loading document '${name}' from MongoDB`)\n if (this.DB) {\n try {\n const doc = await this.DB.collection(this.collection).findOne({\n name: name,\n })\n if (doc) {\n delete (doc as any)._id\n this.documents[name] = doc\n }\n } catch (error) {\n this.error('Error loading document from MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not loaded.')\n }\n }\n\n async _saveDocument(name: string): Promise<void> {\n if (this.DB) {\n try {\n const doc = this.documents[name]\n let newdoc = clonewo_(doc, '__')\n this.log(`Saving document '${name}' to MongoDB`)\n await this.DB.collection(this.collection).updateOne(\n { name: name },\n { $set: newdoc },\n { upsert: true }\n )\n this.log('Document saved to MongoDB')\n } catch (error) {\n this.error('Error saving document to MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not saved.')\n }\n }\n\n async _saveAllDocuments(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this.documents) {\n await this._saveDocument(name)\n }\n }\n\n async _saveChanges(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this._documentChanged) {\n if (this._documentChanged[name]) {\n await this._saveDocument(name)\n this._documentChanged[name] = false\n }\n }\n }\n\n _initServerDocument(): void {\n this.documents['_server'] = {\n nextUID: 100,\n }\n }\n\n /*= EXIT ===================================================================*/\n\n _exitSignal(signal: string): void {\n if (!this._exited) {\n this.log('\\nEXIT: Caught interrupt signal ' + signal)\n this._exited = true\n clearInterval(this._loopiv)\n clearInterval(this._statsiv)\n clearInterval(this._saveiv)\n this.onBeforeExit()\n this.broadcast({ server: 'Going down' })\n this._saveAllDocuments()\n this._wss!.close()\n setTimeout(() => process.exit(0), 1000)\n }\n }\n\n // To be redefined. Called BEFORE program exit, and saving all documents\n onBeforeExit(): void {}\n}\n","import { Packr } from 'msgpackr';\nimport { FLOAT32_OPTIONS } from 'msgpackr';\nconst { ALWAYS } = FLOAT32_OPTIONS;\n\nlet packr = new Packr({\n useFloat32: ALWAYS\n});\n\nexport function encode(obj: any): Uint8Array {\n return packr.pack(obj)\n}\n\nexport function decode(data: Uint8Array): any {\n return packr.unpack(data)\n}\n\ntype ReactiveCallback = (name: string, operation: string, target: any, path: string, value: any) => void;\n\nexport function reactive(name: string, object: any, callback: ReactiveCallback, path: string = '', excludedProperties: Record<string, boolean> | false = false): any {\n if (object === null || typeof object !== 'object') {\n //console.log('--- Type not object', typeof object)\n return object\n }\n\n function isReactive(p: string): boolean {\n let r = true\n if (p.startsWith('_')) {\n r = false\n }\n if (excludedProperties) {\n if (excludedProperties[p]) {\n r = false\n }\n }\n if (path == '/entities') {\n r = false\n }\n return r\n }\n\n for (const property in object) {\n if (isReactive(property)) {\n //console.log(`path '${path}', prop '${property}' is reactive`)\n object[property] = reactive(\n name,\n object[property],\n callback,\n path + '/' + property,\n excludedProperties\n )\n } else {\n //console.log(`--- path '${path}', property '${property}' is NOT reactive`)\n }\n }\n //console.log(`path '${path}' is reactive`)\n return new Proxy(object, {\n get(target: any, property: string | symbol, receiver: any): any { // ...arguments\n return Reflect.get(target, property, receiver)\n },\n set(target: any, property: string | symbol, value: any): boolean {\n let newvalue: any\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n newvalue = reactive(name, value, callback, pn, excludedProperties)\n callback(name, 'replace', target, pn, newvalue)\n } else {\n newvalue = value\n }\n return Reflect.set(target, property, newvalue)\n },\n deleteProperty(target: any, property: string | symbol): boolean {\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n callback(name, 'remove', target, pn, null)\n }\n delete target[property]\n return true\n },\n })\n\n}\n\nexport function deepGet(obj: any, path: string): any {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n for (let i = 0; i < len; i++) {\n if (obj[paths[i]!] == undefined) {\n return undefined\n } else {\n obj = obj[paths[i]!]\n }\n }\n return obj\n}\n\nexport function deepSet(obj: any, path: string, value: any): void {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n let i: number\n for (i = 0; i < len - 1; i++) {\n obj = obj[paths[i]!]\n }\n obj[paths[i]!] = value\n}\n\n// recursive clone oject, without properties that starts with _ (or __)\n\nexport function clonewo_(obj: any, excludeStart: string | Record<string, boolean> = '_'): any {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n\n function isExcluded(key: string): boolean {\n let e = false\n if (typeof (excludeStart) == 'string' && key.startsWith(excludeStart)) {\n e = true\n } else if (typeof(excludeStart) == 'object') {\n if (excludeStart[key] || key.startsWith('_')) {\n e = true\n }\n }\n return e\n }\n\n if (obj instanceof Map) {\n const mapClone = new Map()\n Array.from(obj.entries()).forEach(([key, value]) => {\n mapClone.set(clonewo_(key, excludeStart), clonewo_(value, excludeStart))\n })\n return mapClone\n }\n\n let clone: any\n if (Array.isArray(obj)) {\n clone = []\n for (let i = 0; i < obj.length; i++) {\n clone[i] = clonewo_(obj[i], excludeStart)\n }\n } else {\n clone = {} as Record<string, any>\n for (let key in obj) {\n if (obj.hasOwnProperty(key) && !isExcluded(key)) {\n if (typeof obj[key] === 'object') {\n clone[key] = clonewo_(obj[key], excludeStart)\n } else {\n clone[key] = obj[key]\n }\n }\n }\n }\n\n return clone\n}\n\nexport function limitPrecision(obj: any): any {\n if (Array.isArray(obj)) {\n return obj.map(limitPrecision)\n } else if (obj !== null && typeof obj === 'object') {\n const result: Record<string, any> = {}\n for (const key in obj) {\n result[key] = limitPrecision(obj[key])\n }\n return result\n } else if (typeof obj === 'number') {\n if (Number.isInteger(obj)) {\n return obj\n } else {\n // Limit to max 3 decimal digits, not fixed\n return parseFloat(obj.toFixed(3))\n }\n } else {\n return obj\n }\n}\n\nexport function msgop(op: any): any {\n let nop: any = {}\n if (!op.o) {\n nop.op = 'replace'\n } else {\n nop.op = ({\n a: 'add',\n r: 'remove',\n d: 'delete',\n t: 'test',\n } as Record<string, string>)[op.o]\n }\n nop.path = op.p\n nop.value = op.v\n return nop\n}\n\nexport function opmsg(op: string, target: any, path: string, value: any): any {\n let c: any = { p: path, v: value }\n if (op != 'replace') {\n c.o = ({\n add: 'a',\n remove: 'r',\n delete: 'd',\n test: 't',\n } as Record<string, string>)[op]\n }\n return c\n}\n\n// a function that converts an int to a hexa string\n// (8 characters long)\nexport function int2hex(int: number): string {\n return int.toString(16)\n}\n\n// a function that converts a hexa string to an int\nexport function hex2int(str: string): bigint {\n if (str.length % 2) {\n str = '0' + str\n }\n return BigInt('0x' + str)\n}\n\n// - Fixed point encoding/decoding functions\n\n// 32-bit unsigned integer encoding\nexport function encode_uint32(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(4)\n }\n let p = offset + 3\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n// 32-bit unsigned integer decoding\nexport function decode_uint32(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (\n ((byteArray[p++]! & 0x7f) << 24) |\n (byteArray[p++]! << 16) |\n (byteArray[p++]! << 8) |\n byteArray[p]!\n )\n}\n\n// 24-bit unsigned integer encoding\nexport function encode_uint24(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(3)\n }\n let p = offset + 2\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n\n// 24-bit unsigned integer decoding\nexport function decode_uint24(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (\n (byteArray[p++]! << 16) |\n (byteArray[p++]! << 8) |\n byteArray[p]!\n )\n}\n\n// 16-bit unsigned integer encoding\nexport function encode_uint16(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(2)\n }\n let p = offset + 1\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n\n// 16-bit unsigned integer decoding\nexport function decode_uint16(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (byteArray[p++]! << 8) | byteArray[p]!\n}\n\n// 24.8 bit ====================================================================\n\n// 24.8-bit fixed point encoding\nexport function encode_fp248(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint32(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 24.8-bit fixed point decoding\nexport function decode_fp248(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint32(byteArray, offset)\n return fp / divider\n}\n\n// 16.8 bit ====================================================================\n\n// 16.8-bit fixed point encoding (3 bytes)\nexport function encode_fp168(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint24(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 16.8-bit fixed point decoding (3 bytes)\nexport function decode_fp168(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint24(byteArray, offset)\n return fp / divider\n}\n\n// 16.16 bit ===================================================================\n\n// 16.16-bit fixed point encoding\nexport function encode_fp1616(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 65536)\n encode_uint32(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 16.16-bit fixed point decoding\nexport function decode_fp1616(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -65536 : 65536\n byteArray[offset]! &= 0x7f\n const fp = decode_uint32(byteArray, offset)\n return fp / divider\n}\n\n// 8.8 bit =====================================================================\n\n// 8.8-bit fixed point encoding\nexport function encode_fp88(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint16(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 8.8-bit fixed point decoding\nexport function decode_fp88(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint16(byteArray, offset)\n return fp / divider\n}\n\n// 4.12 bit ====================================================================\n\n// 4.12-bit fixed point encoding\nexport function encode_fp412(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 4096)\n encode_uint16(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 4.12-bit fixed point decoding\nexport function decode_fp412(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -4096 : 4096\n byteArray[offset]! &= 0x7f\n const fp = decode_uint16(byteArray, offset)\n return fp / divider\n}\n\n// 1.7 bit =====================================================================\n\n// 1.7-bit fixed point encoding\nexport function encode_fp17(float: number, byteArray: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 128)\n byteArray[offset] = fp\n if (float < 0) {\n byteArray[offset] |= 0x80\n }\n}\n\n// 1.7-bit fixed point decoding\nexport function decode_fp17(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -128.0 : 128.0\n byteArray[offset]! &= 0x7f\n return byteArray[offset]! / divider\n}\n","import { promisify } from 'util'\nimport { gzip, gunzip, constants } from 'zlib'\n\nconst MIN_COMPRESSED_BUFFER_SIZE = 256\nconst MAX_COMPRESSED_BUFFER_SIZE = 999999\n\nconst lib_compress = promisify(gzip)\nconst lib_decompress = promisify(gunzip)\n\nexport async function compress(buffer:Uint8Array<ArrayBufferLike>) {\n if (buffer.byteLength <= MIN_COMPRESSED_BUFFER_SIZE || buffer.byteLength >= MAX_COMPRESSED_BUFFER_SIZE) return buffer\n try {\n let t1 = Date.now()\n let cbytes = await lib_compress(buffer, {\n level: constants.Z_BEST_SPEED\n })\n let t2 = Date.now()\n let cbuffer = Buffer.from(cbytes)\n let t3 = Date.now()\n\n //console.log(`Node compression ${buffer.byteLength} -> ${cbuffer.byteLength}, time: ${t2 - t1}ms`)\n\n return cbuffer\n } catch (error) {\n console.error('Error compressing buffer:', error)\n return buffer\n }\n}\n\nexport async function decompress(buffer:Uint8Array<ArrayBufferLike>) {\n try {\n let cbytes = await lib_decompress(buffer)\n let cbuffer = Buffer.from(cbytes)\n return cbuffer\n } catch (error) {\n console.error('Error decompressing buffer:', error)\n return buffer\n }\n}\n"],"mappings":"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","names":["key","data"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/utils.ts","../src/compress-node.ts"],"sourcesContent":["import * as https from 'node:https'\nimport * as fs from 'node:fs'\nimport {\n reactive,\n deepGet,\n clonewo_,\n opmsg,\n msgop,\n encode_uint32,\n encode_fp412,\n encode_fp168,\n encode_fp1616,\n limitPrecision,\n encode,\n decode\n} from './utils'\nimport { compress, decompress } from './compress-node'\nimport fastjsonpatch from 'fast-json-patch'\nimport { WebSocketServer, WebSocket } from 'ws'\nimport { MongoClient, Db } from 'mongodb'\nimport { glMatrix, vec3, quat } from 'gl-matrix'\nimport { RTCPeerConnection, RTCDataChannel, RTCSessionDescription } from \"werift\";\n\nglMatrix.setMatrixArrayType(Array)\n\n// entities/ID/\nconst fastPatchProperties: Record<string, boolean> = {\n 'type': true, // string 'enemy'\n 'status': true, // string 'idle'\n 'level': true, // number 2\n 'race': true, // string 'goblin'\n 'class': true, // string 'warrior'\n 'model': true, // string 'models/models.glb|goblin'\n 'animation': true, // string 'idle2'\n 'sound': true, // string 'sound/goblin.snd|snarl'\n 'effect': true, // 'selected'\n 'position': true, // [0, 0, 0] Vector (Number)\n 'rotation': true, // [0, 0, 0, 1] Quaternion (Number)\n 'scale': true, // [1, 1, 1] Vector (Number)\n}\n\nconst dictionaryProperties: Record<string, boolean> = {\n 'type': true,\n 'status': true,\n 'level': true,\n 'race': true,\n 'class': true,\n 'model': true,\n 'animation': true,\n 'sound': true,\n 'effect': true,\n}\n\nconst { applyOperation } = fastjsonpatch\nconst LITTLE_ENDIAN = (() => {\n const buffer = new ArrayBuffer(2)\n new DataView(buffer).setInt16(0, 256, true)\n return new Int16Array(buffer)[0] === 256\n})()\n\nconst MAX_PACKAGE_SIZE = 65400; // Slightly below the 65535 limit to allow for overhead\n\n\ntype ClientType = any\n\ninterface StatsType {\n tUpdate: number[]\n tPatch: number[]\n send: number\n sendRTC: number\n _sendRTCUpdate: number\n [key: string]: any\n}\n\nexport default class TopazCubeServer {\n DEBUG = false\n name = 'TopazCubeServer'\n cycle = 100\n saveCheckCycle = 1000\n saveCycle = 10000\n patchCycleDivider = 1\n port = 8799\n useHttps = false\n key = './cert/key.pem'\n cert = './cert/cert.pem'\n MongoUrl = 'mongodb://localhost:27017'\n mongoClient: MongoClient | null = null\n DB: Db | null = null\n database = 'topazcube'\n collection = 'documents'\n allowSave = true\n allowSync = true\n allowWebRTC = false\n allowFastPatch = false\n allowCompression = false\n simulateLatency = 0\n _lastUID = 100\n clients: ClientType[] = []\n documents: Record<string, any> = {}\n isLoading: Record<string, boolean> = {}\n _documentChanges: Record<string, any[]> = {}\n _documentChanged: Record<string, boolean> = {}\n _documentState: Record<string, any> = {}\n\n update = 0\n lastUpdate = 0\n _saveiv: any = null\n _lastSave: Record<string, number> = {}\n _loopiv: any = null\n _statsiv: any = null\n _stillUpdating = false\n stats: StatsType = {\n tUpdate: [],\n tPatch: [],\n send: 0,\n sendRTC: 0,\n _sendRTCUpdate: 0\n }\n\n _wss: WebSocketServer | null = null\n _exited = false\n\n log(...args: any[]) {\n if (this.DEBUG) {\n console.log(this.name + ':', ...args);\n }\n }\n\n warn(...args: any[]) {\n if (this.DEBUG) {\n console.warn(this.name + ':', ...args);\n }\n }\n\n error(...args: any[]) {\n console.error(this.name + ':', ...args);\n }\n\n constructor({\n name = 'TopazCubeServer',\n cycle = 100,\n saveCheckCycle = 1000,\n saveCycle = 10000,\n port = 8799,\n useHttps = false,\n key = './cert/key.pem',\n cert = './cert/cert.pem',\n MongoUrl = 'mongodb://localhost:27017',\n database = 'topazcube',\n collection = 'documents',\n allowSave = true,\n allowSync = true,\n allowWebRTC = false,\n allowFastPatch = false,\n allowCompression = false,\n simulateLatency = 0,\n DEBUG = false\n }: {\n name?: string\n cycle?: number\n saveCheckCycle?: number\n saveCycle?: number\n port?: number\n useHttps?: boolean\n key?: string\n cert?: string\n MongoUrl?: string\n database?: string\n collection?: string\n allowSave?: boolean\n allowSync?: boolean\n allowWebRTC?: boolean\n allowFastPatch?: boolean\n allowCompression?: boolean\n simulateLatency?: number\n DEBUG?: boolean\n } = {}) {\n this.name = name\n this.cycle = cycle\n this.saveCheckCycle = saveCheckCycle\n this.saveCycle = saveCycle\n this.port = port\n this.useHttps = useHttps\n this.key = key\n this.cert = cert\n this.MongoUrl = MongoUrl\n this.database = database\n this.collection = collection\n this.allowSave = allowSave\n this.allowSync = allowSync\n this.allowWebRTC = allowWebRTC\n this.allowFastPatch = allowFastPatch\n this.allowCompression = allowCompression\n this.simulateLatency = simulateLatency\n this.DEBUG = DEBUG\n\n this._initDB()\n\n if (useHttps) {\n let httpsServer: https.Server | null = https.createServer({\n key: fs.readFileSync(this.key),\n cert: fs.readFileSync(this.cert),\n }, (req, res) => {\n res.writeHead(200)\n res.end('<b>Hello World!</b>')\n }).listen(this.port)\n this._wss = new WebSocketServer({ server: httpsServer })\n httpsServer = null\n this.log(this.name + ' running on HTTPS port ' + this.port)\n } else {\n this._wss = new WebSocketServer({ port: this.port })\n this.log(this.name + ' running on port ' + this.port)\n }\n this._wss.on('connection', (client: WebSocket) => {\n this._onConnected(client)\n })\n\n process.stdin.resume()\n process.on('SIGINT', () => {\n this._exitSignal('SIGINT')\n })\n process.on('SIGQUIT', () => {\n this._exitSignal('SIGQUIT')\n })\n process.on('SIGTERM', () => {\n this._exitSignal('SIGTERM')\n })\n process.on('SIGUSR2', () => {\n this._exitSignal('SIGUSR2')\n })\n\n // Setup keypress handling for console input\n process.stdin.resume()\n process.stdin.setEncoding('utf8')\n\n process.stdin.on('data', (key: any) => {\n key = (''+key).trim()\n\n // ctrl-c ( end of text )\n if (key == '\\u0003') {\n this._exitSignal('SIGINT')\n return\n }\n\n // Process other keypresses\n this.log(`Key pressed: ${key}`)\n\n // Example: 's' to save all documents\n if (key == 's') {\n this.log('Saving all documents...')\n this._saveAllDocuments()\n }\n\n // Example: 'i' to print server info\n if (key == 'i') {\n this.log(\n `Server: ${this.name}, Clients: ${this.clients.length}, Documents: ${Object.keys(this.documents).length}`\n )\n }\n })\n this._startLoop()\n }\n\n /*= DOCUMENTS ==============================================================*/\n\n // to be redefined. Called before a new document is created. Returns true if\n // the client has the right to create an empty document\n canCreate(client: ClientType, name: string): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is created\n // (returns an empty document)\n onCreate(name: string): any {\n return {\n data: {},\n }\n }\n\n // to be redefined. Called when a client wants to sync (modify) a document.\n // Returns true if the client has the right to sync that operation.\n canSync(client: ClientType, name: string, op: any): boolean {\n return true\n }\n\n // to be redefined. Called when a new document is hydrated\n // (created, or loaded from db)\n async onHydrate(name: string, document: any): Promise<void> {\n document.__hydrated = true\n }\n\n _makeReactive(name: string): void {\n //this.log(`Making document '${name}' reactive`, this.documents[name])\n let ep: any = false\n if (this.allowFastPatch) {\n ep = fastPatchProperties\n }\n this.documents[name] = reactive(\n name,\n this.documents[name],\n this._onDocumentChange.bind(this),\n '',\n ep\n )\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n this._documentChanged[name] = false\n }\n }\n\n _createEmptyDocument(name: string): void {\n let doc = this.onCreate(name)\n if (!doc) {\n return\n }\n this.documents[name] = doc\n }\n\n async _waitLoad(name: string): Promise<void> {\n if (this.isLoading[name]) {\n while (this.isLoading[name]) {\n await new Promise((resolve) => setTimeout(resolve, 50))\n }\n }\n }\n\n async _checkDocument(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n if (!this.documents[name]) {\n this.isLoading[name] = true\n await this._loadDocument(name)\n if (!this.documents[name] && this.canCreate(client, name)) {\n this._createEmptyDocument(name)\n }\n if (this.documents[name]) {\n this._makeReactive(name)\n this.onHydrate(name, this.documents[name])\n }\n this.isLoading[name] = false\n this._documentState[name] = {\n subscibers: 0,\n lastModified: Date.now(),\n }\n }\n }\n\n _updateAllDocumentsState(): void {\n for (let name in this.documents) {\n if (name != '_server') {\n let doc = this.documents[name]\n this._documentState[name].subscibers = 0\n for (let client of this.clients) {\n if (client.subscribed && client.subscribed[name]) {\n this._documentState[name].subscibers++\n }\n }\n }\n }\n }\n\n /*= UPDATE LOOP ============================================================*/\n\n // to be redefined. called every this.cycle ms\n onUpdate(name: string, doc: any, dt: number): void {}\n\n _startLoop(): void {\n this.lastUpdate = Date.now()\n this._loop()\n this._statsiv = setInterval(() => {\n this._doStats()\n }, 1000)\n this._saveiv = setInterval(() => {\n this._saveChanges()\n }, 1000)\n }\n\n _loop(): void {\n let now = Date.now()\n let dtms = (now - this.lastUpdate)\n let dt = dtms / 1000.0 // Convert to seconds\n this.lastUpdate = now\n\n /*\n if (this._stillUpdating) {\n return\n }\n */\n this._stillUpdating = true\n for (let name in this.documents) {\n this.onUpdate(name, this.documents[name], dt)\n }\n let t1 = Date.now()\n this._stillUpdating = false\n let updateTime = t1 - now\n this.stats.tUpdate.push(updateTime)\n\n //this.log(`update ${this.update} patch: ${this.update % this.patchCycleDivider}`, )\n\n let patchTime = 0\n if (this.update % this.patchCycleDivider == 0) {\n this._sendPatches()\n let t2 = Date.now()\n patchTime = t2 - t1\n this.stats.tPatch.push(patchTime)\n if (this.allowFastPatch) {\n this.log(`update ${this.update} dt:${dtms}ms RTC:${this.stats._sendRTCUpdate}bytes, tUpdate: ${updateTime}ms, tPatch: ${patchTime}ms`, )\n }\n this.stats._sendRTCUpdate = 0\n }\n\n this.update++\n let endUpdate = Date.now()\n let totalUpdate = endUpdate - now\n\n setTimeout(() => {\n this._loop()\n }, Math.max(this.cycle - totalUpdate, 10))\n }\n\n _doStats(): void {\n for (let key in this.stats) {\n let i = this.stats[key]\n if (Array.isArray(i) && i.length > 0) {\n while (i.length > 60) {\n i.shift()\n }\n this.stats['_avg_' + key] = i.reduce((a: number, b: number) => a + b, 0) / i.length\n } else if (!key.startsWith('_')) {\n this.stats['_persec_' + key] = i / 3.0\n this.stats[key] = 0\n }\n }\n //this.log('stats', this.stats)\n }\n\n /*= MESSAGES ===============================================================*/\n\n // to be redefined. Called on message (operation) from client\n onMessage(client: ClientType, message: any): void {}\n\n // to be redefined. Called when a client connects\n onConnect(client: ClientType): void {}\n\n // to be redefined. Called when a client disconnects\n onDisconnect(client: ClientType): void {}\n\n _onConnected(client: ClientType): void {\n client.ID = this.getUID()\n client.ping = 0\n client.ctdiff = 0\n client.subscribed = {}\n client.dataChannel = null\n client.peerConnection = null\n\n this.log('client connected', client.ID)\n this.clients.push(client)\n client.on('error', (...args: any[]) => {\n this._onError(client, args)\n })\n client.on('message', (message:any) => {\n let dec = decode(message)\n if (this.simulateLatency) {\n setTimeout(() => {\n this._onMessage(client, dec)\n }, this.simulateLatency)\n } else {\n this._onMessage(client, dec)\n }\n })\n client.on('close', (message:any) => {\n this._onDisconnected(client)\n this.onDisconnect(client)\n })\n this.onConnect(client)\n }\n\n async _onMessage(client: ClientType, message: any): Promise<void> {\n if (\n message.c == 'sync' &&\n this.allowSync &&\n client.subscribed &&\n client.subscribed[message.n] &&\n this.documents[message.n]\n ) {\n let name = message.n\n if (!this._documentChanges[name]) {\n this._documentChanges[name] = []\n this._documentChanged[name] = false\n }\n for (let op of message.p) {\n if (!this.canSync(client, name, op)) {\n continue\n }\n this._documentChanges[name].push(op)\n this._documentChanged[name] = true\n let dop = msgop(op)\n applyOperation(this.documents[name], dop)\n }\n } else if (message.c == 'ping') {\n this.send(client, {\n c: 'pong',\n t: Date.now(),\n ct: message.ct,\n ID: client.ID,\n })\n } else if (message.c == 'peng') {\n let time = Date.now()\n let ping = time - message.st\n client.ctdiff = message.ct + ping / 2 - time\n client.ping = ping\n //this.log(time, \"PENG ping, ctdiff\", message, ping, client.ctdiff, \"ms\")\n } else if (message.c == 'rtc-offer') {\n this._processOffer(client, message)\n } else if (message.c == 'rtc-candidate') {\n this._processICECandidate(client, message)\n } else if (message.c == 'sub') {\n await this._checkDocument(message.n, client)\n if (!this.documents[message.n]) {\n this.send(client, {\n c: 'error',\n t: Date.now(),\n message: 'Document not found',\n })\n return\n }\n if (client.subscribed) {\n client.subscribed[message.n] = true\n }\n this._sendFullState(message.n, client)\n } else if (message.c == 'unsub') {\n if (client.subscribed) {\n client.subscribed[message.n] = false\n }\n } else {\n this.onMessage(client, message)\n }\n }\n\n _onError(client: ClientType, args: any[]): void {\n this.error('onError:', args)\n }\n\n _onDisconnected(client: ClientType): void {\n if (client.dataChannel) {\n client.dataChannel.close()\n }\n if (client.peerConnection) {\n client.peerConnection.close()\n }\n this.log('client disconnected')\n let index = this.clients.indexOf(client)\n if (index !== -1) {\n this.clients.splice(index, 1)\n }\n }\n\n async send(client: ClientType, message: any): Promise<void> {\n try {\n let t1 = Date.now()\n let data = encode(message)\n let t2 = Date.now()\n let dl = data.byteLength\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n if (data.length > 4096) {\n this.log(`Big message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n } catch (e) {\n this.error('Error sending message:', e, message)\n }\n }\n\n async broadcast(message: object, clients: ClientType[] | false = false): Promise<void> {\n if (!clients) {\n clients = this.clients\n }\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n for (let client of this.clients) {\n this.stats.send += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n client.send(data)\n }, this.simulateLatency)\n } else {\n client.send(data)\n }\n }\n }\n\n async _sendFullState(name: string, client: ClientType): Promise<void> {\n await this._waitLoad(name)\n let excluded: any = '_'\n if (this.allowFastPatch) {\n excluded = fastPatchProperties\n }\n let doc = clonewo_(this.documents[name], excluded)\n limitPrecision(doc)\n let fdata: any = false\n if (this.allowFastPatch) {\n fdata = this._encodeFastChanges(name, false)\n }\n let fullState = {\n c: 'full',\n le: LITTLE_ENDIAN,\n t: Date.now(),\n n: name,\n doc: doc,\n fdata: fdata\n }\n this.send(client, fullState)\n }\n\n _encodeFastChanges(name: string, changesOnly = true): any {\n let doc = this.documents[name]\n if (!doc) { return false }\n let origin = this.documents[name].origin\n if (!origin) {\n origin = [0, 0, 0]\n this.documents[name].origin = origin\n }\n\n let entities = doc.entities\n let ids = Object.keys(entities)\n if (!entities) { return false }\n let count: Record<string, number> = {}\n let changed: any = {}\n let hasChanges: any = {}\n let dictionary: any = {}\n let encodedChanges: any = {}\n\n for (let key in fastPatchProperties) {\n if (changesOnly) {\n count[key] = 0\n changed[key] = {}\n hasChanges[key] = false\n } else {\n count[key] = ids.length\n changed[key] = {}\n hasChanges[key] = true\n }\n dictionary[key] = {}\n }\n\n // search for changes\n\n if (changesOnly) {\n for (let id in entities) {\n let e = entities[id]\n for (let key in fastPatchProperties) {\n if (e['__changed_' + key]) {\n changed[''+key][''+id] = true\n count[''+key] = parseInt(''+count[''+key]) + 1\n hasChanges[''+key] = true\n e['__changed_' + key] = false\n }\n }\n }\n } else {\n for (let id in entities) {\n for (let key in fastPatchProperties) {\n changed[''+key][''+id] = true\n }\n }\n }\n\n // create dictionaries\n\n let dictUID = 1\n for (let key in hasChanges) {\n if (hasChanges[key] && dictionaryProperties[key]) {\n for (let id in changed[key]) {\n let e = entities[id]\n let value = e[key]\n if (!dictionary[key][value]) {\n dictionary[key][value] = dictUID++\n }\n }\n }\n }\n\n this.log(\"--------------------------------------------------\")\n //this.log(\"changed\", changed)\n //this.log(\"count\", count)\n\n // create encoded changes\n //\n for (let key in hasChanges) {\n if (hasChanges[key]) {\n let size = parseInt(''+count[''+key])\n let encoded: any = {}\n if (dictionaryProperties[key]) {\n encoded.dict = dictionary[key]\n\n let pdata = new Uint8Array(size * 8)\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n let value = e[key]\n let did = parseInt(dictionary[key][value])\n encode_uint32(did, pdata, offset)\n offset += 4\n }\n encoded.pdata = pdata\n } else {\n\n let pdata: Uint8Array\n if (key == 'position') {\n pdata = new Uint8Array(size * 13)\n } else if (key == 'rotation') {\n pdata = new Uint8Array(size * 16)\n } else if (key == 'scale') {\n pdata = new Uint8Array(size * 16)\n } else {\n pdata = new Uint8Array(0)\n }\n\n let offset = 0\n for (let id in changed[key]) {\n let e = entities[id]\n let nid = parseInt(id)\n encode_uint32(nid, pdata, offset)\n offset += 4\n if (key == 'position') {\n encode_fp168(e.position[0] - origin[0], pdata, offset)\n offset += 3\n encode_fp168(e.position[1] - origin[1], pdata, offset)\n offset += 3\n encode_fp168(e.position[2] - origin[2], pdata, offset)\n offset += 3\n } else if (key == 'rotation') {\n encode_fp412(e.rotation[0], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[1], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[2], pdata, offset)\n offset += 2\n encode_fp412(e.rotation[3], pdata, offset)\n offset += 2\n } else if (key == 'scale') {\n encode_fp1616(e.scale[0], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[1], pdata, offset)\n offset += 4\n encode_fp1616(e.scale[2], pdata, offset)\n offset += 4\n }\n }\n encoded.pdata = pdata\n }\n encodedChanges[key] = encoded\n }\n }\n\n return encodedChanges\n }\n\n _sendPatches(): void {\n let now = Date.now()\n\n for (let name in this._documentChanges) {\n let dc = this._documentChanges[name]\n this._documentChanges[name] = []\n let sus = this.clients.filter((client) => client.subscribed && client.subscribed[name])\n if (sus.length > 0) {\n if (dc && dc.length > 0) {\n let record = {\n c: 'patch',\n t: now, // server time\n u: this.update,\n n: name,\n doc: dc,\n }\n this.broadcast(record, sus)\n }\n }\n\n if (this.allowFastPatch) {\n if (sus.length > 0) {\n let t1 = Date.now()\n let changes = this._encodeFastChanges(name)\n let t2 = Date.now()\n let record = {\n c: 'fpatch',\n t: now, // server time\n u: this.update,\n n: name,\n fdata: changes\n }\n this.broadcastRTC(record, sus)\n let t3 = Date.now()\n this.log(`_sendPatches: ${name} encode_changes: ${t2-t1}ms broadcast:${t3-t2}ms`)\n }\n }\n }\n }\n\n _onDocumentChange(name: string, op: any, target: any, path: any, value: any): void {\n this._documentChanges[name]?.push(opmsg(op, target, path, value))\n this._documentChanged[name] = true\n }\n\n propertyChange(name: string, id: string | number, property: string): void {\n let doc = this.documents[name]\n if (!doc) { return }\n let entities = doc.entities\n if (!entities) { return }\n let e = entities[id]\n if (!e) { return }\n e['__changed_'+property] = true\n //this.log('propertyChange', e)\n }\n\n\n /*= WEBRTC ===================================================================*/\n\n\n async _processOffer(client: ClientType, data: any): Promise<void> {\n if (!this.allowWebRTC) {\n this.warn('WebRTC is disabled')\n return\n }\n\n this.log(\"RTC: Processing offer from client\", client.ID, data);\n\n const peerConnection = new RTCPeerConnection({\n iceServers: [\n { urls: 'stun:stun.l.google.com:19302' },\n { urls: 'stun:stun.cloudflare.com:3478' },\n { urls: 'stun:freestun.net:3478' },\n ],\n //iceCandidatePoolSize: 10,\n })\n\n client.peerConnection = peerConnection\n\n peerConnection.onicecandidate = (event: any) => {\n if (event.candidate) {\n this.log(\"RTC: ICE candidate generated\", event.candidate.candidate.substring(0, 50) + \"...\");\n this.send(client, {\n c: 'rtc-candidate',\n type: 'ice-candidate',\n candidate: event.candidate, // .toJSON()\n })\n } else {\n this.log(\"RTC: ICE candidate gathering complete\");\n }\n }\n\n peerConnection.onconnectionstatechange = () => {\n this.log(`RTC: Connection state changed: ${peerConnection.connectionState}`);\n if (peerConnection.connectionState === 'connected') {\n client.webRTCConnected = true\n this.log(`RTC: Connection established with client ${client.ID}`)\n } else if (\n peerConnection.connectionState === 'failed' ||\n peerConnection.connectionState === 'disconnected' ||\n peerConnection.connectionState === 'closed'\n ) {\n client.webRTCConnected = false\n this.log(`RTC: Connection failed or closed with client ${client.ID}`)\n }\n }\n\n peerConnection.onicegatheringstatechange = () => {\n this.log(`RTC: ICE gathering state: ${peerConnection.iceGatheringState}`);\n }\n\n peerConnection.oniceconnectionstatechange = () => {\n this.log(`RTC: ICE connection state: ${peerConnection.iceConnectionState}`);\n if (\n peerConnection.iceConnectionState === 'connected' ||\n peerConnection.iceConnectionState === 'completed'\n ) {\n this.log(`RTC: ICE connection established with client ${client.ID}`);\n }\n }\n\n try {\n this.log(\"RTC: Remote description set from data\", data);\n await peerConnection.setRemoteDescription(\n //data\n new RTCSessionDescription(data.sdp, data.type)\n )\n this.log(\"RTC: Remote description set successfully\");\n\n client.dataChannel = peerConnection.createDataChannel('serverchannel', {\n ordered: true,\n maxRetransmits: 1,\n })\n\n client.dataChannel.onopen = () => {\n this.log(`RTC: Data channel opened for client ${client.ID}`);\n // Try sending a test message\n try {\n const testData = { c: 'test', message: 'Hello WebRTC' }\n this.sendRTC(client, testData)\n } catch (e) {\n this.error(\n `RTC: Error sending test message to client ${client.ID}`,\n e\n )\n }\n }\n\n client.dataChannel.onclose = () => {\n this.log(`RTC: Data channel closed for client ${client.ID}`)\n }\n\n client.dataChannel.onerror = (error: Event) => {\n this.error(`RTC: Data channel error for client ${client.ID}:`, error)\n }\n\n client.dataChannel.onmessage = (event: MessageEvent) => {\n try {\n const data = decode(event.data)\n this.log(\n `RTC: Data channel message from client ${client.ID}:`,\n data\n )\n //this.onMessage(client, data);\n } catch (error) {\n this.error(\n `RTC: Error decoding message from client ${client.ID}:`,\n error\n )\n }\n }\n\n // Create and send answer\n const answer = await peerConnection.createAnswer()\n await peerConnection.setLocalDescription(answer)\n\n this.log(`RTC: Sending answer to client ${client.ID}`);\n this.send(client, {\n c: 'rtc-answer',\n type: answer.type,\n sdp: answer.sdp,\n })\n } catch (error) {\n this.error(\n `RTC: Error processing offer from client ${client.ID}:`,\n error\n )\n }\n }\n\n async _processICECandidate(client: ClientType, data: any): Promise<void> {\n this.log(`RTC: Processing ICE candidate from client ${client.ID}`);\n try {\n if (data.candidate && typeof(data.candidate) == 'object') {\n data.candidate = data.candidate.candidate\n }\n if (client.peerConnection && data.candidate) {\n await client.peerConnection.addIceCandidate(\n data.candidate\n //new wrtc.RTCIceCandidate(data.candidate)\n )\n this.log(`RTC: ICE candidate added successfully for client ${client.ID}`);\n } else {\n this.warn(`RTC: Cannot add ICE candidate for client ${client.ID} - peerConnection not ready or candidate missing`, client.peerConnection, data);\n }\n } catch (error) {\n this.error(`RTC: Error adding ICE candidate for client ${client.ID}`)\n }\n }\n\n _clientRTCOpen(client: ClientType): boolean {\n return client.dataChannel !== null && client.dataChannel !== undefined && client.dataChannel.readyState === 'open'\n }\n\n async sendRTC(client: ClientType, message: any): Promise<void> {\n let data = encode(message)\n if (this.allowCompression) {\n data = await compress(data)\n }\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n\n let packages = this._splitRTCMessage(data)\n\n if (this.simulateLatency) {\n setTimeout(() => {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (this._clientRTCOpen(client)) {\n packages.forEach((p) => {\n client.dataChannel!.send(p)\n })\n }\n }\n }\n\n async broadcastRTC(message: any, clients: ClientType[] = []): Promise<void> {\n if (clients.length == 0) {\n clients = this.clients\n }\n let t1 = Date.now()\n let data = encode(message)\n let dl = data.byteLength\n let t2 = Date.now()\n if (this.allowCompression) {\n data = await compress(data)\n }\n let t3 = Date.now()\n\n\n if (data.length > 16384) {\n this.log(`BroadcastRTC message ${dl} -> ${data.length} (${(100.0 * data.length / dl).toFixed()}%) encoding:${t2 - t1}ms compression:${t3 - t1}ms`)\n }\n\n let packages = this._splitRTCMessage(data)\n\n for (let client of this.clients) {\n this.stats.sendRTC += data.byteLength\n this.stats._sendRTCUpdate += data.byteLength\n if (this.simulateLatency) {\n setTimeout(() => {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }, this.simulateLatency)\n } else {\n if (client.dataChannel && client.dataChannel.readyState === 'open') {\n packages.forEach((p) => {\n client?.dataChannel?.send(p)\n })\n }\n }\n }\n }\n\n _splitRTCMessage(data: Uint8Array): Uint8Array[] {\n let packages: Uint8Array[]\n if (data.byteLength > 65535) {\n const now = Date.now()\n this.warn(`RTC: Message too large: ${data.byteLength} bytes`)\n // Split the message into smaller packages\n packages = [];\n let offset = 0;\n let mid = this.update +'-'+ now\n let seq = 0\n\n // Create subsequent packages if needed\n while (offset < data.byteLength) {\n const remaining = data.byteLength - offset;\n const chunkSize = Math.min(remaining, MAX_PACKAGE_SIZE);\n const chunk = new Uint8Array(data.buffer, offset, chunkSize);\n let cmessage = {\n c: 'chunk',\n t: now,\n mid: mid,\n seq: seq,\n ofs: offset,\n chs: chunkSize,\n ts: data.byteLength,\n data: chunk,\n last: remaining <= MAX_PACKAGE_SIZE,\n }\n packages.push(encode(cmessage))\n offset += chunkSize;\n seq++;\n }\n\n this.log(`RTC: Large message split into ${packages.length} packages`);\n } else {\n packages = [data]\n this.log(`RTC: Message - ${data.byteLength} bytes`)\n }\n return packages\n }\n\n\n /*= DATABASE =================================================================*/\n // properties (of the documents) that starts with __ are not saved to the database.\n // __properties are restored on hydration. (for example __physicsBody or __bigObject)\n\n getUID(): number {\n this.documents['_server'].nextUID++\n return this.documents['_server'].nextUID\n }\n\n async _initDB(): Promise<void> {\n await this._connectDB()\n await this._loadDocument('_server')\n if (!this.documents['_server']) {\n this._initServerDocument()\n }\n }\n\n async _connectDB(): Promise<void> {\n this.mongoClient = new MongoClient(this.MongoUrl)\n try {\n await this.mongoClient.connect()\n this.log('Connected to MongoDB')\n const db = this.mongoClient.db(this.database)\n this.DB = db\n } catch (error) {\n this.error('Error connecting to MongoDB:', error)\n this.mongoClient = null\n }\n }\n\n async _loadDocument(name: string): Promise<void> {\n this.log(`Loading document '${name}' from MongoDB`)\n if (this.DB) {\n try {\n const doc = await this.DB.collection(this.collection).findOne({\n name: name,\n })\n if (doc) {\n delete (doc as any)._id\n this.documents[name] = doc\n }\n } catch (error) {\n this.error('Error loading document from MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not loaded.')\n }\n }\n\n async _saveDocument(name: string): Promise<void> {\n if (this.DB) {\n try {\n const doc = this.documents[name]\n let newdoc = clonewo_(doc, '__')\n this.log(`Saving document '${name}' to MongoDB`)\n await this.DB.collection(this.collection).updateOne(\n { name: name },\n { $set: newdoc },\n { upsert: true }\n )\n this.log('Document saved to MongoDB')\n } catch (error) {\n this.error('Error saving document to MongoDB:', error)\n }\n } else {\n this.warn('MongoDB client not initialized. Document not saved.')\n }\n }\n\n async _saveAllDocuments(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this.documents) {\n await this._saveDocument(name)\n }\n }\n\n async _saveChanges(): Promise<void> {\n if (!this.allowSave) {\n return\n }\n for (let name in this._documentChanged) {\n if (!this._lastSave[name]) {\n this._lastSave[name] = Date.now() - 60000\n }\n let lastSave = this._lastSave[name]\n if (Date.now() - lastSave < 10000) {\n continue\n }\n if (this._documentChanged[name]) {\n await this._saveDocument(name)\n this._documentChanged[name] = false\n this._lastSave[name] = Date.now()\n }\n }\n }\n\n _initServerDocument(): void {\n this.documents['_server'] = {\n nextUID: 100,\n }\n }\n\n /*= EXIT ===================================================================*/\n\n _exitSignal(signal: string): void {\n if (!this._exited) {\n this.log('\\nEXIT: Caught interrupt signal ' + signal)\n this._exited = true\n clearInterval(this._loopiv)\n clearInterval(this._statsiv)\n clearInterval(this._saveiv)\n this.onBeforeExit()\n this.broadcast({ server: 'Going down' })\n this._saveAllDocuments()\n this._wss!.close()\n setTimeout(() => process.exit(0), 1000)\n }\n }\n\n // To be redefined. Called BEFORE program exit, and saving all documents\n onBeforeExit(): void {}\n}\n","import { Packr } from 'msgpackr';\nimport { FLOAT32_OPTIONS } from 'msgpackr';\nconst { ALWAYS } = FLOAT32_OPTIONS;\n\nlet packr = new Packr({\n useFloat32: ALWAYS\n});\n\nexport function encode(obj: any): Uint8Array {\n return packr.pack(obj)\n}\n\nexport function decode(data: Uint8Array): any {\n return packr.unpack(data)\n}\n\ntype ReactiveCallback = (name: string, operation: string, target: any, path: string, value: any) => void;\n\nexport function reactive(name: string, object: any, callback: ReactiveCallback, path: string = '', excludedProperties: Record<string, boolean> | false = false): any {\n if (object === null || typeof object !== 'object') {\n //console.log('--- Type not object', typeof object)\n return object\n }\n\n function isReactive(p: string): boolean {\n let r = true\n if (p.startsWith('_')) {\n r = false\n }\n if (excludedProperties) {\n if (excludedProperties[p]) {\n r = false\n }\n }\n if (path == '/entities') {\n r = false\n }\n return r\n }\n\n for (const property in object) {\n if (isReactive(property)) {\n //console.log(`path '${path}', prop '${property}' is reactive`)\n object[property] = reactive(\n name,\n object[property],\n callback,\n path + '/' + property,\n excludedProperties\n )\n } else {\n //console.log(`--- path '${path}', property '${property}' is NOT reactive`)\n }\n }\n //console.log(`path '${path}' is reactive`)\n return new Proxy(object, {\n get(target: any, property: string | symbol, receiver: any): any { // ...arguments\n return Reflect.get(target, property, receiver)\n },\n set(target: any, property: string | symbol, value: any): boolean {\n let newvalue: any\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n newvalue = reactive(name, value, callback, pn, excludedProperties)\n callback(name, 'replace', target, pn, newvalue)\n } else {\n newvalue = value\n }\n return Reflect.set(target, property, newvalue)\n },\n deleteProperty(target: any, property: string | symbol): boolean {\n let pn = path + '/' + String(property)\n if (isReactive(String(property))) {\n callback(name, 'remove', target, pn, null)\n }\n delete target[property]\n return true\n },\n })\n\n}\n\nexport function deepGet(obj: any, path: string): any {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n for (let i = 0; i < len; i++) {\n if (obj[paths[i]!] == undefined) {\n return undefined\n } else {\n obj = obj[paths[i]!]\n }\n }\n return obj\n}\n\nexport function deepSet(obj: any, path: string, value: any): void {\n //path = path.replace(/^\\/+/, '')\n let paths = ('' + path).split('/').filter((p) => p)\n let len = paths.length\n let i: number\n for (i = 0; i < len - 1; i++) {\n obj = obj[paths[i]!]\n }\n obj[paths[i]!] = value\n}\n\n// recursive clone oject, without properties that starts with _ (or __)\n\nexport function clonewo_(obj: any, excludeStart: string | Record<string, boolean> = '_'): any {\n if (obj === null || typeof obj !== 'object') {\n return obj\n }\n\n function isExcluded(key: string): boolean {\n let e = false\n if (typeof (excludeStart) == 'string' && key.startsWith(excludeStart)) {\n e = true\n } else if (typeof(excludeStart) == 'object') {\n if (excludeStart[key] || key.startsWith('_')) {\n e = true\n }\n }\n return e\n }\n\n if (obj instanceof Map) {\n const mapClone = new Map()\n Array.from(obj.entries()).forEach(([key, value]) => {\n mapClone.set(clonewo_(key, excludeStart), clonewo_(value, excludeStart))\n })\n return mapClone\n }\n\n let clone: any\n if (Array.isArray(obj)) {\n clone = []\n for (let i = 0; i < obj.length; i++) {\n clone[i] = clonewo_(obj[i], excludeStart)\n }\n } else {\n clone = {} as Record<string, any>\n for (let key in obj) {\n if (obj.hasOwnProperty(key) && !isExcluded(key)) {\n if (typeof obj[key] === 'object') {\n clone[key] = clonewo_(obj[key], excludeStart)\n } else {\n clone[key] = obj[key]\n }\n }\n }\n }\n\n return clone\n}\n\nexport function limitPrecision(obj: any): any {\n if (Array.isArray(obj)) {\n return obj.map(limitPrecision)\n } else if (obj !== null && typeof obj === 'object') {\n const result: Record<string, any> = {}\n for (const key in obj) {\n result[key] = limitPrecision(obj[key])\n }\n return result\n } else if (typeof obj === 'number') {\n if (Number.isInteger(obj)) {\n return obj\n } else {\n // Limit to max 3 decimal digits, not fixed\n return parseFloat(obj.toFixed(3))\n }\n } else {\n return obj\n }\n}\n\nexport function msgop(op: any): any {\n let nop: any = {}\n if (!op.o) {\n nop.op = 'replace'\n } else {\n nop.op = ({\n a: 'add',\n r: 'remove',\n d: 'delete',\n t: 'test',\n } as Record<string, string>)[op.o]\n }\n nop.path = op.p\n nop.value = op.v\n return nop\n}\n\nexport function opmsg(op: string, target: any, path: string, value: any): any {\n let c: any = { p: path, v: value }\n if (op != 'replace') {\n c.o = ({\n add: 'a',\n remove: 'r',\n delete: 'd',\n test: 't',\n } as Record<string, string>)[op]\n }\n return c\n}\n\n// a function that converts an int to a hexa string\n// (8 characters long)\nexport function int2hex(int: number): string {\n return int.toString(16)\n}\n\n// a function that converts a hexa string to an int\nexport function hex2int(str: string): bigint {\n if (str.length % 2) {\n str = '0' + str\n }\n return BigInt('0x' + str)\n}\n\n// - Fixed point encoding/decoding functions\n\n// 32-bit unsigned integer encoding\nexport function encode_uint32(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(4)\n }\n let p = offset + 3\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n// 32-bit unsigned integer decoding\nexport function decode_uint32(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (\n ((byteArray[p++]! & 0x7f) << 24) |\n (byteArray[p++]! << 16) |\n (byteArray[p++]! << 8) |\n byteArray[p]!\n )\n}\n\n// 24-bit unsigned integer encoding\nexport function encode_uint24(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(3)\n }\n let p = offset + 2\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n\n// 24-bit unsigned integer decoding\nexport function decode_uint24(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (\n (byteArray[p++]! << 16) |\n (byteArray[p++]! << 8) |\n byteArray[p]!\n )\n}\n\n// 16-bit unsigned integer encoding\nexport function encode_uint16(uint: number, byteArray?: Uint8Array, offset: number = 0): Uint8Array {\n if (!byteArray) {\n byteArray = new Uint8Array(2)\n }\n let p = offset + 1\n byteArray[p--] = uint & 0xff\n uint >>= 8\n byteArray[p] = uint\n return byteArray\n}\n\n// 16-bit unsigned integer decoding\nexport function decode_uint16(byteArray: Uint8Array, offset: number = 0): number {\n let p = offset\n return (byteArray[p++]! << 8) | byteArray[p]!\n}\n\n// 24.8 bit ====================================================================\n\n// 24.8-bit fixed point encoding\nexport function encode_fp248(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint32(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 24.8-bit fixed point decoding\nexport function decode_fp248(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint32(byteArray, offset)\n return fp / divider\n}\n\n// 16.8 bit ====================================================================\n\n// 16.8-bit fixed point encoding (3 bytes)\nexport function encode_fp168(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint24(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 16.8-bit fixed point decoding (3 bytes)\nexport function decode_fp168(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint24(byteArray, offset)\n return fp / divider\n}\n\n// 16.16 bit ===================================================================\n\n// 16.16-bit fixed point encoding\nexport function encode_fp1616(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 65536)\n encode_uint32(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 16.16-bit fixed point decoding\nexport function decode_fp1616(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -65536 : 65536\n byteArray[offset]! &= 0x7f\n const fp = decode_uint32(byteArray, offset)\n return fp / divider\n}\n\n// 8.8 bit =====================================================================\n\n// 8.8-bit fixed point encoding\nexport function encode_fp88(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 256)\n encode_uint16(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 8.8-bit fixed point decoding\nexport function decode_fp88(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -256 : 256\n byteArray[offset]! &= 0x7f\n const fp = decode_uint16(byteArray, offset)\n return fp / divider\n}\n\n// 4.12 bit ====================================================================\n\n// 4.12-bit fixed point encoding\nexport function encode_fp412(float: number, byteArray?: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 4096)\n encode_uint16(fp, byteArray, offset)\n if (float < 0 && byteArray) {\n byteArray[offset]! |= 0x80\n }\n}\n\n// 4.12-bit fixed point decoding\nexport function decode_fp412(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -4096 : 4096\n byteArray[offset]! &= 0x7f\n const fp = decode_uint16(byteArray, offset)\n return fp / divider\n}\n\n// 1.7 bit =====================================================================\n\n// 1.7-bit fixed point encoding\nexport function encode_fp17(float: number, byteArray: Uint8Array, offset: number = 0): void {\n const fp = Math.round(Math.abs(float) * 128)\n byteArray[offset] = fp\n if (float < 0) {\n byteArray[offset] |= 0x80\n }\n}\n\n// 1.7-bit fixed point decoding\nexport function decode_fp17(byteArray: Uint8Array, offset: number = 0): number {\n const divider = (byteArray[offset]! & 0x80) === 0x80 ? -128.0 : 128.0\n byteArray[offset]! &= 0x7f\n return byteArray[offset]! / divider\n}\n","import { promisify } from 'util'\nimport { gzip, gunzip, constants } from 'zlib'\n\nconst MIN_COMPRESSED_BUFFER_SIZE = 256\nconst MAX_COMPRESSED_BUFFER_SIZE = 999999\n\nconst lib_compress = promisify(gzip)\nconst lib_decompress = promisify(gunzip)\n\nexport async function compress(buffer:Uint8Array<ArrayBufferLike>) {\n if (buffer.byteLength <= MIN_COMPRESSED_BUFFER_SIZE || buffer.byteLength >= MAX_COMPRESSED_BUFFER_SIZE) return buffer\n try {\n let t1 = Date.now()\n let cbytes = await lib_compress(buffer, {\n level: constants.Z_BEST_SPEED\n })\n let t2 = Date.now()\n let cbuffer = Buffer.from(cbytes)\n let t3 = Date.now()\n\n //console.log(`Node compression ${buffer.byteLength} -> ${cbuffer.byteLength}, time: ${t2 - t1}ms`)\n\n return cbuffer\n } catch (error) {\n console.error('Error compressing buffer:', error)\n return buffer\n }\n}\n\nexport async function decompress(buffer:Uint8Array<ArrayBufferLike>) {\n try {\n let cbytes = await lib_decompress(buffer)\n let cbuffer = Buffer.from(cbytes)\n return cbuffer\n } catch (error) {\n console.error('Error decompressing buffer:', error)\n return buffer\n }\n}\n"],"mappings":"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","names":["key","data"]}
|
package/package.json
CHANGED
package/src/server.ts
CHANGED
|
@@ -76,6 +76,8 @@ export default class TopazCubeServer {
|
|
|
76
76
|
DEBUG = false
|
|
77
77
|
name = 'TopazCubeServer'
|
|
78
78
|
cycle = 100
|
|
79
|
+
saveCheckCycle = 1000
|
|
80
|
+
saveCycle = 10000
|
|
79
81
|
patchCycleDivider = 1
|
|
80
82
|
port = 8799
|
|
81
83
|
useHttps = false
|
|
@@ -103,6 +105,7 @@ export default class TopazCubeServer {
|
|
|
103
105
|
update = 0
|
|
104
106
|
lastUpdate = 0
|
|
105
107
|
_saveiv: any = null
|
|
108
|
+
_lastSave: Record<string, number> = {}
|
|
106
109
|
_loopiv: any = null
|
|
107
110
|
_statsiv: any = null
|
|
108
111
|
_stillUpdating = false
|
|
@@ -136,6 +139,8 @@ export default class TopazCubeServer {
|
|
|
136
139
|
constructor({
|
|
137
140
|
name = 'TopazCubeServer',
|
|
138
141
|
cycle = 100,
|
|
142
|
+
saveCheckCycle = 1000,
|
|
143
|
+
saveCycle = 10000,
|
|
139
144
|
port = 8799,
|
|
140
145
|
useHttps = false,
|
|
141
146
|
key = './cert/key.pem',
|
|
@@ -153,6 +158,8 @@ export default class TopazCubeServer {
|
|
|
153
158
|
}: {
|
|
154
159
|
name?: string
|
|
155
160
|
cycle?: number
|
|
161
|
+
saveCheckCycle?: number
|
|
162
|
+
saveCycle?: number
|
|
156
163
|
port?: number
|
|
157
164
|
useHttps?: boolean
|
|
158
165
|
key?: string
|
|
@@ -170,6 +177,8 @@ export default class TopazCubeServer {
|
|
|
170
177
|
} = {}) {
|
|
171
178
|
this.name = name
|
|
172
179
|
this.cycle = cycle
|
|
180
|
+
this.saveCheckCycle = saveCheckCycle
|
|
181
|
+
this.saveCycle = saveCycle
|
|
173
182
|
this.port = port
|
|
174
183
|
this.useHttps = useHttps
|
|
175
184
|
this.key = key
|
|
@@ -362,7 +371,7 @@ export default class TopazCubeServer {
|
|
|
362
371
|
}, 1000)
|
|
363
372
|
this._saveiv = setInterval(() => {
|
|
364
373
|
this._saveChanges()
|
|
365
|
-
},
|
|
374
|
+
}, 1000)
|
|
366
375
|
}
|
|
367
376
|
|
|
368
377
|
_loop(): void {
|
|
@@ -1167,9 +1176,17 @@ export default class TopazCubeServer {
|
|
|
1167
1176
|
return
|
|
1168
1177
|
}
|
|
1169
1178
|
for (let name in this._documentChanged) {
|
|
1179
|
+
if (!this._lastSave[name]) {
|
|
1180
|
+
this._lastSave[name] = Date.now() - 60000
|
|
1181
|
+
}
|
|
1182
|
+
let lastSave = this._lastSave[name]
|
|
1183
|
+
if (Date.now() - lastSave < 10000) {
|
|
1184
|
+
continue
|
|
1185
|
+
}
|
|
1170
1186
|
if (this._documentChanged[name]) {
|
|
1171
1187
|
await this._saveDocument(name)
|
|
1172
1188
|
this._documentChanged[name] = false
|
|
1189
|
+
this._lastSave[name] = Date.now()
|
|
1173
1190
|
}
|
|
1174
1191
|
}
|
|
1175
1192
|
}
|