Added websocket presence.
This commit is contained in:
parent
4e1436b0cc
commit
d08e86e92f
203
package-lock.json
generated
203
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "immersive",
|
||||
"version": "0.0.7",
|
||||
"version": "0.0.8-13",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "immersive",
|
||||
"version": "0.0.7",
|
||||
"version": "0.0.8-13",
|
||||
"dependencies": {
|
||||
"@babylonjs/core": "^7.9.0",
|
||||
"@babylonjs/gui": "^7.9.0",
|
||||
@ -29,6 +29,7 @@
|
||||
"hls.js": "^1.1.4",
|
||||
"js-crypto-aes": "1.0.6",
|
||||
"loglevel": "^1.9.1",
|
||||
"meaningful-string": "^1.4.0",
|
||||
"peer-lite": "2.0.2",
|
||||
"pouchdb": "^8.0.1",
|
||||
"pouchdb-find": "^8.0.1",
|
||||
@ -38,7 +39,9 @@
|
||||
"rfc4648": "^1.5.3",
|
||||
"round": "^2.0.1",
|
||||
"uint8-to-b64": "^1.0.2",
|
||||
"uuid": "^9.0.1"
|
||||
"uuid": "^9.0.1",
|
||||
"websocket": "^1.0.34",
|
||||
"websocket-ts": "^2.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/dom-to-image": "^2.6.7",
|
||||
@ -1169,6 +1172,28 @@
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
|
||||
},
|
||||
"node_modules/bufferutil": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz",
|
||||
"integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.14.2"
|
||||
}
|
||||
},
|
||||
"node_modules/bufferutil/node_modules/node-gyp-build": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz",
|
||||
"integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==",
|
||||
"bin": {
|
||||
"node-gyp-build": "bin.js",
|
||||
"node-gyp-build-optional": "optional.js",
|
||||
"node-gyp-build-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/cac": {
|
||||
"version": "6.7.14",
|
||||
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
|
||||
@ -1270,6 +1295,18 @@
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||
},
|
||||
"node_modules/d": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz",
|
||||
"integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==",
|
||||
"dependencies": {
|
||||
"es5-ext": "^0.10.64",
|
||||
"type": "^2.7.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
@ -1386,6 +1423,43 @@
|
||||
"errno": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/es5-ext": {
|
||||
"version": "0.10.64",
|
||||
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
|
||||
"integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"es6-iterator": "^2.0.3",
|
||||
"es6-symbol": "^3.1.3",
|
||||
"esniff": "^2.0.1",
|
||||
"next-tick": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/es6-iterator": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
|
||||
"integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
|
||||
"dependencies": {
|
||||
"d": "1",
|
||||
"es5-ext": "^0.10.35",
|
||||
"es6-symbol": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/es6-symbol": {
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz",
|
||||
"integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==",
|
||||
"dependencies": {
|
||||
"d": "^1.0.2",
|
||||
"ext": "^1.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
|
||||
@ -1424,6 +1498,20 @@
|
||||
"@esbuild/win32-x64": "0.20.2"
|
||||
}
|
||||
},
|
||||
"node_modules/esniff": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
|
||||
"integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
|
||||
"dependencies": {
|
||||
"d": "^1.0.1",
|
||||
"es5-ext": "^0.10.62",
|
||||
"event-emitter": "^0.3.5",
|
||||
"type": "^2.7.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/estree-walker": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
|
||||
@ -1433,6 +1521,15 @@
|
||||
"@types/estree": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/event-emitter": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
|
||||
"integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
|
||||
"dependencies": {
|
||||
"d": "1",
|
||||
"es5-ext": "~0.10.14"
|
||||
}
|
||||
},
|
||||
"node_modules/event-target-shim": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
||||
@ -1472,6 +1569,14 @@
|
||||
"url": "https://github.com/sindresorhus/execa?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/ext": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
|
||||
"integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
|
||||
"dependencies": {
|
||||
"type": "^2.7.2"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
|
||||
@ -1777,6 +1882,11 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
|
||||
},
|
||||
"node_modules/isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
@ -2041,6 +2151,11 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||
}
|
||||
},
|
||||
"node_modules/meaningful-string": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/meaningful-string/-/meaningful-string-1.4.0.tgz",
|
||||
"integrity": "sha512-i95AQGuJcVR5mslLf60GyxRIr7EazCgXoR+pFAZCdySAMJ5G3PiLq/dsyv74zKOnLieF1ipeFEp86IMUvcIO3Q=="
|
||||
},
|
||||
"node_modules/merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
@ -2141,6 +2256,11 @@
|
||||
"resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.0.0.tgz",
|
||||
"integrity": "sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg=="
|
||||
},
|
||||
"node_modules/next-tick": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
|
||||
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
@ -2959,6 +3079,11 @@
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||
},
|
||||
"node_modules/type": {
|
||||
"version": "2.7.3",
|
||||
"resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz",
|
||||
"integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ=="
|
||||
},
|
||||
"node_modules/type-detect": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
||||
@ -2968,6 +3093,14 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/typedarray-to-buffer": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
||||
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
|
||||
"dependencies": {
|
||||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.9.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||
@ -3017,6 +3150,28 @@
|
||||
"requires-port": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/utf-8-validate": {
|
||||
"version": "5.0.10",
|
||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
|
||||
"integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.14.2"
|
||||
}
|
||||
},
|
||||
"node_modules/utf-8-validate/node_modules/node-gyp-build": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz",
|
||||
"integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==",
|
||||
"bin": {
|
||||
"node-gyp-build": "bin.js",
|
||||
"node-gyp-build-optional": "optional.js",
|
||||
"node-gyp-build-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
@ -3196,6 +3351,40 @@
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"node_modules/websocket": {
|
||||
"version": "1.0.35",
|
||||
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.35.tgz",
|
||||
"integrity": "sha512-/REy6amwPZl44DDzvRCkaI1q1bIiQB0mEFQLUrhz3z2EK91cp3n72rAjUlrTP0zV22HJIUOVHQGPxhFRjxjt+Q==",
|
||||
"dependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"debug": "^2.2.0",
|
||||
"es5-ext": "^0.10.63",
|
||||
"typedarray-to-buffer": "^3.1.5",
|
||||
"utf-8-validate": "^5.0.2",
|
||||
"yaeti": "^0.0.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/websocket-ts": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/websocket-ts/-/websocket-ts-2.1.5.tgz",
|
||||
"integrity": "sha512-rCNl9w6Hsir1azFm/pbjBEFzLD/gi7Th5ZgOxMifB6STUfTSovYAzryWw0TRvSZ1+Qu1Z5Plw4z42UfTNA9idA=="
|
||||
},
|
||||
"node_modules/websocket/node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/websocket/node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
@ -3257,6 +3446,14 @@
|
||||
"node": ">=0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/yaeti": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
|
||||
"integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==",
|
||||
"engines": {
|
||||
"node": ">=0.10.32"
|
||||
}
|
||||
},
|
||||
"node_modules/yocto-queue": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
"test": "vitest",
|
||||
"build": "node versionBump.js && vite build",
|
||||
"preview": "vite preview",
|
||||
"socket": "node server/server.js",
|
||||
"serve": "node server.js",
|
||||
"serverBuild": "cd server && tsc",
|
||||
"havok": "cp ./node_modules/@babylonjs/havok/lib/esm/HavokPhysics.wasm ./node_modules/.vite/deps"
|
||||
@ -46,7 +47,10 @@
|
||||
"js-crypto-aes": "1.0.6",
|
||||
"events": "^3.3.0",
|
||||
"hash-wasm": "4.11.0",
|
||||
"uint8-to-b64": "^1.0.2"
|
||||
"uint8-to-b64": "^1.0.2",
|
||||
"meaningful-string": "^1.4.0",
|
||||
"websocket-ts": "^2.1.5",
|
||||
"websocket": "^1.0.34"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/dom-to-image": "^2.6.7",
|
||||
|
||||
114
server/server.js
Normal file
114
server/server.js
Normal file
@ -0,0 +1,114 @@
|
||||
import websocket from "websocket";
|
||||
import http from "http";
|
||||
import {sha512} from "hash-wasm";
|
||||
import log from "loglevel";
|
||||
|
||||
async function start() {
|
||||
const logger = log.getLogger("server");
|
||||
logger.setLevel("DEBUG", false);
|
||||
const WebSocketServer = websocket.server;
|
||||
//const http = require('http');
|
||||
//const sha512 = require('hash-wasm').sha512;
|
||||
const connections = new Map();
|
||||
const server = http.createServer(function (request, response) {
|
||||
logger.info((new Date()) + ' Received request for ' + request.url);
|
||||
response.writeHead(404);
|
||||
response.end();
|
||||
});
|
||||
server.listen(8080, function () {
|
||||
logger.info((new Date()) + ' Server is listening on port 8080');
|
||||
});
|
||||
|
||||
const wsServer = new WebSocketServer({
|
||||
httpServer: server,
|
||||
// You should not use autoAcceptConnections for production
|
||||
// applications, as it defeats all standard cross-origin protection
|
||||
// facilities built into the protocol and the browser. You should
|
||||
// *always* verify the connection's origin and decide whether or not
|
||||
// to accept it.
|
||||
autoAcceptConnections: false
|
||||
});
|
||||
|
||||
function originIsAllowed(origin) {
|
||||
return origin.indexOf('deepdiagram') > -1;
|
||||
}
|
||||
|
||||
wsServer.on('request', async (request) => {
|
||||
if (!originIsAllowed(request.origin)) {
|
||||
// Make sure we only accept requests from an allowed origin
|
||||
request.reject();
|
||||
logger.error((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
||||
const connection = request.accept('echo-protocol', request.origin);
|
||||
const hash = await sha512(connection.socket.remoteAddress + '-' + connection.socket.remotePort);
|
||||
connections.set(hash, {connection: connection, db: null});
|
||||
|
||||
|
||||
logger.info((new Date()) + ' Connection accepted.', connections.length);
|
||||
connections.forEach((conn, key) => {
|
||||
if (key != hash) {
|
||||
conn.connection.sendUTF('{ "type": "newconnect", "netAttr": "' + hash + '" }');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
connection.on('message', function (message) {
|
||||
logger.debug(message);
|
||||
if (message.type === 'utf8') {
|
||||
logger.debug('Received Message: ' + message.utf8Data);
|
||||
connections.forEach((conn, index) => {
|
||||
const envelope = JSON.parse(message.utf8Data);
|
||||
if (index !== hash) {
|
||||
if (envelope.db === conn.db) {
|
||||
envelope.netAddr = hash;
|
||||
conn.connection.sendUTF(JSON.stringify(envelope));
|
||||
}
|
||||
} else {
|
||||
if (!conn.db && envelope.db) {
|
||||
conn.db = envelope.db;
|
||||
logger.debug('DB set to ' + envelope.db);
|
||||
}
|
||||
}
|
||||
});
|
||||
//connection.sendUTF(message.utf8Data);
|
||||
} else if (message.type === 'binary') {
|
||||
logger.debug('Received Binary Message of ' + message.binaryData.length + ' bytes');
|
||||
connections.forEach((conn, index) => {
|
||||
if (index !== hash) {
|
||||
conn.connection.sendBytes(message.utf8Data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
connection.on('close', function (reasonCode, description) {
|
||||
connections.delete(hash);
|
||||
connections.forEach((conn, index) => {
|
||||
conn.connection.sendUTF('{ "type": "close", "netAddr": "' + hash + '" }');
|
||||
});
|
||||
});
|
||||
connection.on('error', function (reasonCode, description) {
|
||||
connections.delete(hash);
|
||||
connections.forEach((conn, index) => {
|
||||
conn.connection.sendUTF('{ "type": "error", "netAddr": "' + hash + '" }');
|
||||
});
|
||||
logger.info((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.', connections.length);
|
||||
|
||||
});
|
||||
setInterval(() => {
|
||||
const message = `{ "count": ${connections.size} }`
|
||||
logger.debug(message);
|
||||
connection.sendUTF(message);
|
||||
}, 10000);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
start();
|
||||
@ -9,6 +9,8 @@ import {DiagramMenuManager} from "./diagramMenuManager";
|
||||
import {DiagramEventObserverMask} from "./types/diagramEventObserverMask";
|
||||
import {DiagramObject} from "./diagramObject";
|
||||
import {getMe} from "../util/me";
|
||||
import {UserModelType} from "../users/userTypes";
|
||||
import {vectoxys} from "./functions/vectorConversion";
|
||||
|
||||
|
||||
export class DiagramManager {
|
||||
@ -17,10 +19,14 @@ export class DiagramManager {
|
||||
private readonly _controllers: Controllers;
|
||||
private readonly _diagramEntityActionManager: ActionManager;
|
||||
public readonly onDiagramEventObservable: Observable<DiagramEvent> = new Observable();
|
||||
public readonly onUserEventObservable: Observable<UserModelType> = new Observable();
|
||||
private readonly _diagramMenuManager: DiagramMenuManager;
|
||||
private readonly _scene: Scene;
|
||||
private readonly _diagramObjects: Map<string, DiagramObject> = new Map<string, DiagramObject>();
|
||||
private readonly _me: string;
|
||||
private _moving: number = 10;
|
||||
private _i: number = 0;
|
||||
|
||||
constructor() {
|
||||
this._me = getMe();
|
||||
this._scene = DefaultScene.Scene;
|
||||
@ -30,6 +36,45 @@ export class DiagramManager {
|
||||
this._diagramEntityActionManager = buildEntityActionManager(this._controllers);
|
||||
this.onDiagramEventObservable.add(this.onDiagramEvent, DiagramEventObserverMask.FROM_DB, true, this);
|
||||
|
||||
|
||||
this.onUserEventObservable.add((user) => {
|
||||
if (user.id != this._me) {
|
||||
this._logger.debug('user event', user);
|
||||
}
|
||||
});
|
||||
window.setInterval(() => {
|
||||
this._i++;
|
||||
const platform = this._scene.getMeshByName('platform');
|
||||
|
||||
if (!platform || !platform.physicsBody) {
|
||||
return;
|
||||
}
|
||||
if (platform.physicsBody) {
|
||||
if ((this._i % this._moving) == 0) {
|
||||
this.onUserEventObservable.notifyObservers(
|
||||
{
|
||||
id: this._me,
|
||||
name: 'me',
|
||||
type: 'user',
|
||||
base: {
|
||||
position: vectoxys(platform.absolutePosition),
|
||||
rotation: vectoxys(platform.absoluteRotationQuaternion.toEulerAngles()),
|
||||
velocity: vectoxys(platform.physicsBody.getLinearVelocity())
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
if (platform.physicsBody.getLinearVelocity().length() > 0.01) {
|
||||
this._moving = 1;
|
||||
} else {
|
||||
this._moving = 10;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}, 100);
|
||||
|
||||
document.addEventListener('uploadImage', (event: CustomEvent) => {
|
||||
const diagramEntity: DiagramEntity = {
|
||||
template: '#image-template',
|
||||
@ -88,6 +133,7 @@ export class DiagramManager {
|
||||
public addObject(diagramObject: DiagramObject) {
|
||||
this._diagramObjects.set(diagramObject.diagramEntity.id, diagramObject);
|
||||
}
|
||||
|
||||
public get config(): AppConfig {
|
||||
return this._config;
|
||||
}
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import log from "loglevel";
|
||||
import {DiagramEntity} from "../../diagram/types/diagramEntity";
|
||||
import {Observable} from "@babylonjs/core";
|
||||
import {UserModelType} from "../../users/userTypes";
|
||||
import {Encryption} from "../encryption";
|
||||
import {DiagramEventObserverMask} from "../../diagram/types/diagramEventObserverMask";
|
||||
|
||||
export async function syncDoc(info: any, onDBRemoveObservable: Observable<DiagramEntity>, onDBUpdateObservable: Observable<DiagramEntity>,
|
||||
onUserObservable: Observable<UserModelType>,
|
||||
encryption: Encryption, key: string) {
|
||||
const logger = log.getLogger('syncDoc');
|
||||
logger.debug(info);
|
||||
|
||||
@ -12,27 +12,37 @@ import {checkDb} from "./functions/checkDb";
|
||||
import {UserModelType} from "../users/userTypes";
|
||||
import {getMe} from "../util/me";
|
||||
import {Encryption} from "./encryption";
|
||||
import {Presence} from "./presence";
|
||||
|
||||
type PasswordEvent = {
|
||||
detail: string;
|
||||
|
||||
}
|
||||
export class PouchdbPersistenceManager {
|
||||
private _logger: Logger = log.getLogger('PouchdbPersistenceManager');
|
||||
onDBEntityUpdateObservable: Observable<DiagramEntity> = new Observable<DiagramEntity>();
|
||||
onDBEntityRemoveObservable: Observable<DiagramEntity> = new Observable<DiagramEntity>();
|
||||
onUserObservable: Observable<UserModelType> = new Observable<UserModelType>();
|
||||
private db: PouchDB;
|
||||
private remote: PouchDB;
|
||||
private user: string;
|
||||
private _encryption = new Encryption();
|
||||
private _encKey = null;
|
||||
private _diagramManager: DiagramManager;
|
||||
|
||||
constructor() {
|
||||
document.addEventListener('passwordset', (evt) => {
|
||||
this._encKey = evt.detail || null;
|
||||
this._encKey = ((evt as unknown) as PasswordEvent).detail || null;
|
||||
if (this._encKey && typeof (this._encKey) == 'string') {
|
||||
this.initialize();
|
||||
this.initialize().then(() => {
|
||||
this._logger.debug('Initialized');
|
||||
});
|
||||
}
|
||||
console.log(evt);
|
||||
});
|
||||
}
|
||||
|
||||
public setDiagramManager(diagramManager: DiagramManager) {
|
||||
this._diagramManager = diagramManager;
|
||||
diagramManager.onDiagramEventObservable.add((evt) => {
|
||||
this._logger.debug(evt);
|
||||
switch (evt.type) {
|
||||
@ -61,11 +71,7 @@ export class PouchdbPersistenceManager {
|
||||
}
|
||||
|
||||
});
|
||||
this.onUserObservable.add((evt) => {
|
||||
if (evt.id == getMe()) {
|
||||
this.updateUser(evt);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.onDBEntityRemoveObservable.add((entity) => {
|
||||
this._logger.debug(entity);
|
||||
@ -74,21 +80,6 @@ export class PouchdbPersistenceManager {
|
||||
});
|
||||
}
|
||||
|
||||
private async updateUser(user: UserModelType) {
|
||||
try {
|
||||
const doc = await this.db.get(user.id);
|
||||
if (doc) {
|
||||
const newDoc = {...doc, ...user};
|
||||
await this.db.put(newDoc);
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.status == 404) {
|
||||
await this.db.put({...user, _id: user.id});
|
||||
} else {
|
||||
this._logger.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
public async remove(id: string) {
|
||||
if (!id) {
|
||||
return;
|
||||
@ -252,26 +243,23 @@ export class PouchdbPersistenceManager {
|
||||
salt = dbEntity.doc.encrypted.salt;
|
||||
}
|
||||
const decrypted = await this._encryption.decryptToObject(dbEntity.doc.encrypted.encrypted, dbEntity.doc.encrypted.iv);
|
||||
if (decrypted.type == 'user') {
|
||||
this.onUserObservable.notifyObservers(decrypted);
|
||||
} else {
|
||||
if (decrypted.id != 'metadata') {
|
||||
this.onDBEntityUpdateObservable.notifyObservers(decrypted, DiagramEventObserverMask.FROM_DB);
|
||||
}
|
||||
|
||||
if (decrypted.id != 'metadata') {
|
||||
this.onDBEntityUpdateObservable.notifyObservers(decrypted, DiagramEventObserverMask.FROM_DB);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (dbEntity.type == 'user') {
|
||||
this.onUserObservable.notifyObservers(dbEntity.doc);
|
||||
} else {
|
||||
if (dbEntity.id != 'metadata') {
|
||||
this.onDBEntityUpdateObservable.notifyObservers(dbEntity.doc, DiagramEventObserverMask.FROM_DB);
|
||||
}
|
||||
|
||||
if (dbEntity.id != 'metadata') {
|
||||
this.onDBEntityUpdateObservable.notifyObservers(dbEntity.doc, DiagramEventObserverMask.FROM_DB);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clear) {
|
||||
localStorage.removeItem('clearLocal');
|
||||
if (clear) {
|
||||
localStorage.removeItem('clearLocal');
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
switch (err.message) {
|
||||
@ -335,10 +323,14 @@ export class PouchdbPersistenceManager {
|
||||
{auth: {username: remoteUserName, password: password}, skip_setup: true});
|
||||
const dbInfo = await this.remote.info();
|
||||
this._logger.debug(dbInfo);
|
||||
|
||||
const presence: Presence = new Presence(getMe(), remoteDbName);
|
||||
this._diagramManager.onUserEventObservable.add((user: UserModelType) => {
|
||||
this._logger.debug(user);
|
||||
presence.sendUser(user);
|
||||
}, -1, false, this);
|
||||
this.db.sync(this.remote, {live: true, retry: true})
|
||||
.on('change', (info) => {
|
||||
syncDoc(info, this.onDBEntityRemoveObservable, this.onDBEntityUpdateObservable, this.onUserObservable, this._encryption, this._encKey);
|
||||
syncDoc(info, this.onDBEntityRemoveObservable, this.onDBEntityUpdateObservable, this._encryption, this._encKey);
|
||||
})
|
||||
.on('active', (info) => {
|
||||
this._logger.debug('sync active', info)
|
||||
|
||||
134
src/integration/presence.ts
Normal file
134
src/integration/presence.ts
Normal file
@ -0,0 +1,134 @@
|
||||
import {RingQueue, Websocket, WebsocketBuilder} from "websocket-ts";
|
||||
import {getMe} from "../util/me";
|
||||
import {UserModelType} from "../users/userTypes";
|
||||
import log, {Logger} from "loglevel";
|
||||
import {DefaultScene} from "../defaultScene";
|
||||
import {Color3, MeshBuilder, StandardMaterial, TransformNode} from "@babylonjs/core";
|
||||
import {xyztovec} from "../diagram/functions/vectorConversion";
|
||||
|
||||
|
||||
export class Presence {
|
||||
private _logger: Logger = log.getLogger("Presence");
|
||||
private _ws: Websocket;
|
||||
private _id: string;
|
||||
|
||||
constructor(id: string = null, db: string = null) {
|
||||
this._db = db;
|
||||
if (id == null) {
|
||||
const localMe = getMe();
|
||||
if (localMe != null) {
|
||||
this._id = localMe;
|
||||
}
|
||||
} else {
|
||||
this._id = id;
|
||||
}
|
||||
if (this._id != null) {
|
||||
this.build();
|
||||
} else {
|
||||
console.error('no user id found');
|
||||
}
|
||||
}
|
||||
|
||||
private _db: string;
|
||||
|
||||
public set db(db: string) {
|
||||
|
||||
this._db = db;
|
||||
}
|
||||
|
||||
public sendUser(user: UserModelType) {
|
||||
if (this._ws) {
|
||||
try {
|
||||
this._ws.send(JSON.stringify({'type': 'user', 'id': this._id, 'db': this._db, 'user': user}));
|
||||
} catch (err) {
|
||||
this._logger.error(err);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private build() {
|
||||
try {
|
||||
this._ws = new WebsocketBuilder("wss://presence.deepdiagram.com:443/")
|
||||
.withBuffer(new RingQueue(2))
|
||||
.onOpen(() => {
|
||||
const me = {'type': 'connect', id: this._id};
|
||||
this._ws.send(JSON.stringify(me));
|
||||
})
|
||||
.onClose(() => this._logger.debug("closed"))
|
||||
.onError(() => this._logger.debug("error"))
|
||||
.onMessage((i, ev) => {
|
||||
this._logger.debug(i);
|
||||
this._logger.debug(ev.data);
|
||||
try {
|
||||
const data = JSON.parse(ev.data);
|
||||
switch (data.type) {
|
||||
case 'connect':
|
||||
break;
|
||||
case 'ping':
|
||||
if (data.db && data.id != this._id) {
|
||||
this._ws.send(JSON.stringify({'type': 'pong', 'id': this._id, 'db': this._db}));
|
||||
}
|
||||
break;
|
||||
case'close':
|
||||
const scene = DefaultScene.Scene;
|
||||
const user = scene.getTransformNodeById(data.netAddr);
|
||||
if (user) {
|
||||
user.dispose(false, true)
|
||||
}
|
||||
break;
|
||||
case 'pong':
|
||||
this._logger.debug(data);
|
||||
break;
|
||||
case 'user':
|
||||
if (data.user) {
|
||||
if (data.user.id) {
|
||||
const scene = DefaultScene.Scene;
|
||||
if (scene) {
|
||||
const user = scene.getTransformNodeById(data.netAddr);
|
||||
if (user) {
|
||||
user.position = xyztovec(data.user.base.position);
|
||||
user.rotation = xyztovec(data.user.base.rotation);
|
||||
} else {
|
||||
this._logger.warn('user not found', data.user);
|
||||
const newUser = MeshBuilder.CreateDisc(data.user.id, {radius: 0.3}, scene);
|
||||
const node = new TransformNode(data.netAddr, scene);
|
||||
const material = new StandardMaterial(data.user.id + 'mat', scene);
|
||||
material.diffuseColor = new Color3(0, 0, 1);
|
||||
material.backFaceCulling = false;
|
||||
newUser.material = material;
|
||||
newUser.parent = node;
|
||||
newUser.rotation.x = Math.PI / 2;
|
||||
newUser.position.y = 0.01;
|
||||
node.position = xyztovec(data.user.base.position);
|
||||
node.rotation = xyztovec(data.user.base.rotation);
|
||||
}
|
||||
}
|
||||
this._logger.debug('user update', data.user);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
this._logger.debug("message")
|
||||
})
|
||||
.onRetry(() => this._logger.debug("retry"))
|
||||
.onReconnect(() => this._logger.debug("reconnect"))
|
||||
.withProtocols("echo-protocol")
|
||||
.build();
|
||||
window.setInterval(() => {
|
||||
|
||||
this._ws.send(JSON.stringify({'type': 'ping', 'id': this._id, db: this._db}));
|
||||
}, 15000, this);
|
||||
//this._ws.send(this._id);
|
||||
} catch (err) {
|
||||
this._logger.error(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -10,7 +10,8 @@ export type UserModelType = {
|
||||
state?: string,
|
||||
base: {
|
||||
position: XYZType,
|
||||
rotation: XYZType
|
||||
rotation: XYZType,
|
||||
velocity?: XYZType
|
||||
}
|
||||
head?: {
|
||||
position: XYZType,
|
||||
|
||||
@ -17,7 +17,6 @@ import {Introduction} from "./tutorial/introduction";
|
||||
const webGpu = false;
|
||||
|
||||
log.setLevel('error', false);
|
||||
log.getLogger('Handle').setLevel('debug');
|
||||
const canvas = (document.querySelector('#gameCanvas') as HTMLCanvasElement);
|
||||
export class VrApp {
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user