├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .grenrc.js ├── CODING_STANDARD.md ├── CONFIGURATION.md ├── LICENSE ├── PUBLISH.md ├── README.md ├── build_scripts ├── cleanDist.js └── createVersion.js ├── example ├── .eslintrc.js ├── README.md ├── interface.css ├── interface.html └── interface.js ├── jest.config.js ├── jsdoc ├── config-dev.json ├── config-sdk.json ├── dev-mainpage.md ├── hifi-jsdoc-template │ ├── LICENSE.md │ ├── README.md │ ├── package.json │ ├── publish.js │ ├── static │ │ ├── fonts │ │ │ ├── Graphik-Regular.otf │ │ │ ├── Graphik-Semibold.otf │ │ │ ├── materialdesignicons-webfont.woff │ │ │ ├── materialdesignicons-webfont.woff2 │ │ │ └── proximanova-regular.otf │ │ ├── images │ │ │ ├── fav-icon.ico │ │ │ └── vircadia-logo-1880.png │ │ ├── scripts │ │ │ ├── collapse.js │ │ │ ├── jquery-3.1.1.min.js │ │ │ ├── linenumber.js │ │ │ ├── prettify │ │ │ │ ├── Apache-License-2.0.txt │ │ │ │ ├── lang-css.js │ │ │ │ └── prettify.js │ │ │ ├── search.js │ │ │ ├── vue.min.js │ │ │ ├── vue_dev.js │ │ │ └── vuetify.js │ │ └── styles │ │ │ ├── jsdoc.css │ │ │ ├── main.css │ │ │ ├── materialdesignicons.min.css │ │ │ ├── night.css │ │ │ ├── prettify.css │ │ │ ├── responsive.css │ │ │ ├── vuetify.css │ │ │ └── vuetify.min.css │ └── tmpl │ │ ├── augments.tmpl │ │ ├── container.tmpl │ │ ├── description.tmpl │ │ ├── details.tmpl │ │ ├── example.tmpl │ │ ├── examples.tmpl │ │ ├── exceptions.tmpl │ │ ├── layout.tmpl │ │ ├── mainpage.tmpl │ │ ├── members.tmpl │ │ ├── method.tmpl │ │ ├── methodList.tmpl │ │ ├── paramList.tmpl │ │ ├── params.tmpl │ │ ├── properties.tmpl │ │ ├── returns.tmpl │ │ ├── returnsSimp.tmpl │ │ ├── signal.tmpl │ │ ├── signalList.tmpl │ │ ├── source.tmpl │ │ ├── tutorial.tmpl │ │ └── type.tmpl ├── plugins │ ├── vircadia-dev.js │ ├── vircadia-sdk.js │ └── vircadia.js └── sdk-mainpage.md ├── mocks ├── domain │ ├── audio │ │ └── AudioWorklets.mock.js │ └── networking │ │ └── AccountManager.mock.js └── worker-url.mock.js ├── package-lock.json ├── package.json ├── src ├── AudioMixer.ts ├── AvatarMixer.ts ├── Camera.ts ├── DomainServer.ts ├── EntityServer.ts ├── MessageMixer.ts ├── Vircadia.ts └── domain │ ├── AssignmentClient.ts │ ├── AvatarManager.ts │ ├── DOMAIN.md │ ├── ENTITY_SERVER.md │ ├── audio-client │ └── AudioClient.ts │ ├── audio │ ├── AudioConstants.ts │ ├── AudioInput.ts │ ├── AudioOutput.ts │ ├── AudioWorklets.ts │ └── InboundAudioStream.ts │ ├── avatar-renderer │ ├── Avatar.ts │ └── ScriptAvatar.ts │ ├── avatar │ └── MyAvatar.ts │ ├── avatars │ ├── AvatarData.ts │ ├── AvatarDataPacket.ts │ ├── AvatarHashMap.ts │ ├── AvatarTraits.ts │ └── ClientTraitsHandler.ts │ ├── entities │ ├── AmbientLightPropertyGroup.ts │ ├── BloomPropertyGroup.ts │ ├── EntityPropertyFlags.ts │ ├── EntityTypes.ts │ ├── GizmoEntityItem.ts │ ├── GridEntityItem.ts │ ├── HazePropertyGroup.ts │ ├── ImageEntityItem.ts │ ├── KeyLightPropertyGroup.ts │ ├── LightEntityItem.ts │ ├── LineEntityItem.ts │ ├── MaterialEntityItem.ts │ ├── ModelEntityItem.ts │ ├── ParticleEffectEntityItem.ts │ ├── PolyLineEntityItem.ts │ ├── PolyVoxEntityItem.ts │ ├── PulsePropertyGroup.ts │ ├── RingGizmoPropertyGroup.ts │ ├── ShapeEntityItem.ts │ ├── SkyboxPropertyGroup.ts │ ├── TextEntityItem.ts │ ├── WebEntityItem.ts │ └── ZoneEntityItem.ts │ ├── interfaces │ ├── AccountInterface.ts │ ├── AvatarListInterface.ts │ ├── MyAvatarInterface.ts │ └── UsersInterface.ts │ ├── networking │ ├── AccountManager.ts │ ├── AddressManager.ts │ ├── DataServerAccountInfo.ts │ ├── DomainHandler.ts │ ├── FingerprintUtils.ts │ ├── HMACAuth.ts │ ├── LimitedNodeList.ts │ ├── MessageData.ts │ ├── MessagesClient.ts │ ├── MetaverseAPI.ts │ ├── NETWORKING.md │ ├── NLPacket.ts │ ├── NLPacketList.ts │ ├── NetworkAccessManager.ts │ ├── NetworkPeer.ts │ ├── NetworkReply.ts │ ├── NetworkRequest.ts │ ├── NetworkingConstants.ts │ ├── Node.ts │ ├── NodeList.ts │ ├── NodePermissions.ts │ ├── NodeType.ts │ ├── OAuthAccessToken.ts │ ├── PacketReceiver.ts │ ├── PingType.ts │ ├── ReceivedMessage.ts │ ├── SockAddr.ts │ ├── SocketType.ts │ ├── packets │ │ ├── AvatarData.ts │ │ ├── AvatarIdentity.ts │ │ ├── AvatarQuery.ts │ │ ├── BulkAvatarData.ts │ │ ├── BulkAvatarTraits.ts │ │ ├── BulkAvatarTraitsAck.ts │ │ ├── DomainConnectRequest.ts │ │ ├── DomainConnectionDenied.ts │ │ ├── DomainDisconnectRequest.ts │ │ ├── DomainList.ts │ │ ├── DomainListRequest.ts │ │ ├── DomainServerAddedNode.ts │ │ ├── DomainServerConnectionToken.ts │ │ ├── DomainServerPathQuery.ts │ │ ├── DomainServerPathResponse.ts │ │ ├── DomainServerRemovedNode.ts │ │ ├── EntityData.ts │ │ ├── EntityQuery.ts │ │ ├── KillAvatar.ts │ │ ├── MessagesData.ts │ │ ├── MessagesSubscribe.ts │ │ ├── MessagesUnsubscribe.ts │ │ ├── MicrophoneAudioNoEcho.ts │ │ ├── MixedAudio.ts │ │ ├── NegotiateAudioFormat.ts │ │ ├── NodeIgnoreRequest.ts │ │ ├── NodeKickRequest.ts │ │ ├── NodeMuteRequest.ts │ │ ├── PacketScribe.ts │ │ ├── PerAvatarGainSet.ts │ │ ├── Ping.ts │ │ ├── PingReply.ts │ │ ├── RequestsDomainListData.ts │ │ ├── SelectedAudioFormat.ts │ │ ├── SetAvatarTraits.ts │ │ └── SilentAudioFrame.ts │ ├── udt │ │ ├── BasePacket.ts │ │ ├── CongestionControl.ts │ │ ├── Connection.ts │ │ ├── ControlPacket.ts │ │ ├── LossList.ts │ │ ├── Packet.ts │ │ ├── PacketHeaders.ts │ │ ├── PacketQueue.ts │ │ ├── PendingReceivedMessage.ts │ │ ├── SendQueue.ts │ │ ├── SequenceNumber.ts │ │ ├── Socket.ts │ │ └── UDT.ts │ └── webrtc │ │ ├── WebRTCDataChannel.ts │ │ ├── WebRTCSignalingChannel.ts │ │ └── WebRTCSocket.ts │ ├── octree │ ├── OctreeConstants.ts │ ├── OctreePacketProcessor.ts │ └── OctreeQuery.ts │ ├── shared │ ├── AACube.ts │ ├── AudioHelpers.ts │ ├── AvatarConstants.ts │ ├── AvatarPriorityMode.ts │ ├── BitVectorHelpers.ts │ ├── ByteCountCoded.ts │ ├── Camera.ts │ ├── Color.ts │ ├── ComponentMode.ts │ ├── ConditionVariable.ts │ ├── ContextManager.ts │ ├── DataViewExtensions.ts │ ├── GLMHelpers.ts │ ├── HighResolutionClock.ts │ ├── Mat4.ts │ ├── ModerationFlags.ts │ ├── PropertyFlags.ts │ ├── Quat.ts │ ├── Rect.ts │ ├── ShapeType.ts │ ├── SignalEmitter.ts │ ├── SpatiallyNestable.ts │ ├── Url.ts │ ├── Uuid.ts │ ├── Vec2.ts │ ├── Vec3.ts │ └── assert.ts │ └── worklets │ ├── AudioInputProcessor.ts │ └── AudioOutputProcessor.ts ├── tests ├── AudioMixer.integration.test.js ├── AudioMixer.unit.test.js ├── AvatarMixer.integration.test.js ├── AvatarMixer.unit.test.js ├── Camera.unit.test.js ├── DomainServer.integration.test.js ├── DomainServer.unit.test.js ├── EntityServer.integration.test.js ├── EntityServer.unit.test.js ├── MessageMixer.integration.test.js ├── MessageMixer.unit.test.js ├── Vircadia.integration.test.js ├── Vircadia.unit.test.js ├── domain │ ├── AssignmentClient.integration.test.js │ ├── AssignmentClient.unit.test.js │ ├── audio-client │ │ └── AudioClient.unit.test.js │ ├── audio │ │ ├── AudioConstants.unit.test.js │ │ ├── AudioInput.unit.test.js │ │ ├── AudioOutput.unit.test.js │ │ └── InboundAudioStream.unit.test.js │ ├── avatar-renderer │ │ ├── Avatar.unit.test.js │ │ └── ScriptAvatar.unit.test.js │ ├── avatar │ │ └── MyAvatar.unit.test.js │ ├── avatars │ │ ├── AvatarData.unit.test.js │ │ ├── AvatarTraits.unit.test.js │ │ └── ClientTraitsHandler.unit.test.js │ ├── entities │ │ ├── ImageEntityItem.unit.test.js │ │ ├── LightEntityItem.unit.test.js │ │ ├── MaterialEntityItem.unit.test.js │ │ ├── ModelEntityItem.unit.test.js │ │ ├── ParticleEffectEntityItem.unit.test.js │ │ ├── ShapeEntityItem.unit.test.js │ │ ├── TextEntityItem.unit.test.js │ │ ├── WebEntityItem.unit.test.js │ │ └── ZoneEntityItem.unit.test.js │ ├── interfaces │ │ ├── AccountInterface.unit.test.js │ │ ├── AvatarListInterface.unit.test.js │ │ ├── MyAvatarInterface.unit.test.js │ │ └── UsersInterface.unit.test.js │ ├── networking │ │ ├── AccountManager.integration.test.js │ │ ├── AccountManager.unit.test.js │ │ ├── AddressManager.unit.test.js │ │ ├── DataServerAccountInfo.unit.test.js │ │ ├── DomainHandler.integration.test.js │ │ ├── DomainHandler.unit.test.js │ │ ├── FingerprintUtils.unit.test.js │ │ ├── HMACAuth.unit.test.js │ │ ├── LimitedNodeList.unit.test.js │ │ ├── MessageData.unit.test.js │ │ ├── MessagesClient.unit.test.js │ │ ├── MetaverseAPI.unit.test.js │ │ ├── NLPacket.unit.test.js │ │ ├── NetworkAccessManager.integration.test.js │ │ ├── NetworkAccessManager.unit.test.js │ │ ├── NetworkPeer.unit.test.js │ │ ├── NetworkReply.unit.test.js │ │ ├── NetworkRequest.unit.test.js │ │ ├── NetworkingConstants.unit.test.js │ │ ├── Node.unit.test.js │ │ ├── NodeList.unit.test.js │ │ ├── NodePermissions.unit.test.js │ │ ├── NodeType.unit.test.js │ │ ├── OAuthAccessToken.unit.test.js │ │ ├── PacketReceiver.unit.test.js │ │ ├── PingType.unit.test.js │ │ ├── ReceivedMessage.unit.test.js │ │ ├── SockAddr.unit.test.js │ │ ├── SocketType.unit.test.js │ │ ├── packets │ │ │ ├── AvatarData.unit.test.js │ │ │ ├── AvatarIdentity.unit.test.js │ │ │ ├── AvatarQuery.unit.test.js │ │ │ ├── BulkAvatarData.unit.test.js │ │ │ ├── BulkAvatarTraits.unit.test.js │ │ │ ├── BulkAvatarTraitsAck.unit.test.js │ │ │ ├── DomainConnectRequest.unit.test.js │ │ │ ├── DomainConnectionDenied.unit.test.js │ │ │ ├── DomainDisconnectRequest.unit.test.js │ │ │ ├── DomainList.unit.test.js │ │ │ ├── DomainListRequest.unit.test.js │ │ │ ├── DomainServerAddedNode.unit.test.js │ │ │ ├── DomainServerConnectionToken.unit.test.js │ │ │ ├── DomainServerPathQuery.unit.test.js │ │ │ ├── DomainServerPathResponse.unit.test.js │ │ │ ├── DomainServerRemovedNode.unit.test.js │ │ │ ├── EntityData.unit.test.js │ │ │ ├── EntityQuery.unit.test.js │ │ │ ├── KillAvatar.unit.test.js │ │ │ ├── MessagesData.unit.test.js │ │ │ ├── MessagesSubscribe.unit.test.js │ │ │ ├── MessagesUnsubscribe.unit.test.js │ │ │ ├── MicrophoneAudioNoEcho.unit.test.js │ │ │ ├── MixedAudio.unit.test.js │ │ │ ├── NegotiateAudioFormat.unit.test.js │ │ │ ├── NodeIgnoreRequest.unit.test.js │ │ │ ├── NodeKickRequest.unit.test.js │ │ │ ├── NodeMuteRequest.unit.test.js │ │ │ ├── PacketScribe.unit.test.js │ │ │ ├── PerAvatarGainSet.unit.test.js │ │ │ ├── Ping.unit.test.js │ │ │ ├── PingReply.unit.test.js │ │ │ ├── RequestsDomainListData.unit.test.js │ │ │ ├── SelectedAudioFormat.unit.test.js │ │ │ ├── SetAvatarTraits.unit.test.js │ │ │ └── SilentAudioFrame.unit.test.js │ │ ├── udt │ │ │ ├── BasePacket.unit.test.js │ │ │ ├── ControlPacket.unit.test.js │ │ │ ├── Packet.unit.test.js │ │ │ ├── PacketHeaders.unit.test.js │ │ │ ├── Socket.integration.test.js │ │ │ ├── Socket.unit.test.js │ │ │ └── UDT.unit.test.js │ │ └── webrtc │ │ │ ├── WebRTCDataChannel.integration.test.js │ │ │ ├── WebRTCSignalingChannel.integration.test.js │ │ │ ├── WebRTCSocket.integration.test.js │ │ │ └── WebRTCSocket.unit.test.js │ ├── octree │ │ └── OctreePacketProcessor.unit.test.js │ └── shared │ │ ├── AudioHelpers.unit.test.js │ │ ├── AvatarConstants.unit.test.js │ │ ├── AvatarPriorityMode.unit.test.js │ │ ├── BitVectorHelpers.unit.test.js │ │ ├── ByteCountCoded.unit.test.js │ │ ├── Camera.unit.test.js │ │ ├── ComponentMode.unit.test.js │ │ ├── ContextManager.unit.test.js │ │ ├── DataViewExtensions.unit.test.js │ │ ├── GLMHelpers.unit.test.js │ │ ├── HighResolutionClock.unit.test.js │ │ ├── ModerationFlags.unit.test.js │ │ ├── PropertyFlags.unit.test.js │ │ ├── Quat.unit.test.js │ │ ├── ShapeType.unit.test.js │ │ ├── SignalEmitter.unit.test.js │ │ ├── SpatiallyNestable.unit.test.js │ │ ├── Url.unit.test.js │ │ ├── Uuid.unit.test.js │ │ ├── Vec3.unit.test.js │ │ └── assert.unit.test.js ├── test.config.js ├── test.config.json ├── testUtils.js └── tsconfig.json ├── tsconfig.jsdoc.json ├── tsconfig.json ├── typings └── WebAudioTyping.d.ts └── webpack.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset = utf-8 3 | indent_style = space 4 | indent_size = 4 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /build_scripts 2 | /dist 3 | /docs 4 | /jsdoc 5 | /node_modules 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .store 2 | /dist 3 | /docs 4 | /node_modules 5 | VERSION.json 6 | vircadia-web-sdk-*.tgz 7 | 8 | # Editor directories and files 9 | .idea 10 | .vs 11 | .vscode 12 | *.njsproj 13 | *.ntvs* 14 | *.sln 15 | *.suo 16 | *.sw? 17 | -------------------------------------------------------------------------------- /.grenrc.js: -------------------------------------------------------------------------------- 1 | // 2 | // .grenrc.js 3 | // 4 | // Created by Kalila L. on May 25, 2021 5 | // Copyright 2021 Vircadia contributors. 6 | // 7 | // Distributed under the Apache License, Version 2.0. 8 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 9 | // 10 | // This configuration is for generating a changelog with gren for a GitHub repository. 11 | // https://github.com/github-tools/github-release-notes 12 | // 13 | // gren changelog -G 14 | // 15 | 16 | module.exports = { 17 | "dataSource": "prs", 18 | "prefix": "", 19 | "ignoreLabels": [ 20 | "enhancement", 21 | "bugfix", 22 | "unmerged-dev", 23 | "CR approved", 24 | "QA approved", 25 | "bug", 26 | "confirmed", 27 | "do not merge", 28 | "duplicate", 29 | "good first issue", 30 | "help wanted", 31 | "high risk", 32 | "housekeeping" 33 | ], 34 | "onlyMilestones": false, 35 | "groupBy": { 36 | "Enhancements": ["enhancement"], 37 | "Bug Fixes": ["bugfix"], 38 | "Docs": ["docs"], 39 | "Housekeeping": ["housekeeping"], 40 | "In Development": ["unmerged-dev"] 41 | }, 42 | "changelogFilename": "CHANGELOG.md" 43 | } 44 | -------------------------------------------------------------------------------- /PUBLISH.md: -------------------------------------------------------------------------------- 1 | 2 | # Publishing to NPM 3 | 4 | Build for release: 5 | ``` 6 | npm run clean 7 | npm run build-prod 8 | ``` 9 | 10 | Package for release: 11 | ``` 12 | npm pack 13 | ``` 14 | 15 | This creates the SDK package, `vircadia-web-sdk-vvvv.v.v.tgz`. 16 | 17 | Publish the package to https://npmjs.com: 18 | 19 | ``` 20 | npm login 21 | npm publish --access public 22 | ``` 23 | -------------------------------------------------------------------------------- /build_scripts/cleanDist.js: -------------------------------------------------------------------------------- 1 | /* 2 | cleanDist.js 3 | 4 | Created by Kalila L. on Dec 20 2020. 5 | Copyright 2020 Vircadia contributors. 6 | 7 | Distributed under the Apache License, Version 2.0. 8 | See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 9 | */ 10 | 11 | const fs = require('fs').promises; 12 | 13 | const directory = './dist'; 14 | 15 | fs.rmdir(directory, { recursive: true }) 16 | .then(() => console.log('Dist folder cleared!')); 17 | -------------------------------------------------------------------------------- /build_scripts/createVersion.js: -------------------------------------------------------------------------------- 1 | /* 2 | createVersion.js 3 | 4 | Created by Kalila L. on Dec 20 2020. 5 | Copyright 2020 Vircadia contributors. 6 | 7 | Distributed under the Apache License, Version 2.0. 8 | See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 9 | */ 10 | 11 | const fse = require('fs-extra'); 12 | 13 | var gitVer = require('child_process').execSync('git rev-parse --short HEAD').toString().trim(); 14 | var gitVerFull = require('child_process').execSync('git rev-parse HEAD').toString().trim(); 15 | var packageVersion = process.env.npm_package_version; 16 | const filePath = './VERSION.json'; 17 | 18 | console.log('Found package version', packageVersion); 19 | console.log('Found Git commit short hash', gitVer); 20 | console.log('Found Git commit long hash', gitVerFull); 21 | 22 | function yyyymmdd() { 23 | var x = new Date(); 24 | var y = x.getFullYear().toString(); 25 | var m = (x.getMonth() + 1).toString(); 26 | var d = x.getDate().toString(); 27 | (d.length == 1) && (d = '0' + d); 28 | (m.length == 1) && (m = '0' + m); 29 | var yyyymmdd = y + m + d; 30 | return yyyymmdd; 31 | } 32 | 33 | var jsonToWrite = { 34 | "npm-package-version": packageVersion, 35 | "git-commit": gitVerFull, 36 | "version-tag": packageVersion + "-" + yyyymmdd() + "-" + gitVer 37 | } 38 | 39 | jsonToWrite = JSON.stringify(jsonToWrite); 40 | 41 | var attemptFileWrite = fse.outputFileSync(filePath, jsonToWrite); 42 | -------------------------------------------------------------------------------- /example/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | "@typescript-eslint/no-unsafe-assignment": "off", 4 | "@typescript-eslint/no-unsafe-call": "off", 5 | "@typescript-eslint/no-unsafe-member-access": "off", 6 | "@typescript-eslint/restrict-plus-operands": "off" 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Example Web App 2 | 3 | This example demonstrates using the Vircadia Web SDK. 4 | 5 | To run: 6 | - Set up and build the SDK. The SDK will be created in a `/dist` directory beside the `/example` directory. 7 | - Host the `/example` and `/dist` on a Web server. This is required so that the browser will load the SDK file without 8 | encountering a CORS error. In order for audio to work with the audio mixer, the Web server must serve HTTPS or be localhost. 9 | - Load the hosted `interface.html` in a Web browser (using HTTPS if on a remote server or HTTP if localhost). 10 | -------------------------------------------------------------------------------- /example/interface.css: -------------------------------------------------------------------------------- 1 | /* 2 | // interface.css 3 | // 4 | // Created by David Rowe on 1 Aug 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | */ 11 | 12 | h2 { 13 | margin: 24px 0 0 0; 14 | } 15 | 16 | div { 17 | margin: 16px 0; 18 | } 19 | 20 | div.row { 21 | display: table-row; 22 | height: 30px; 23 | } 24 | 25 | div.row span { 26 | display: table-cell; 27 | vertical-align: top; 28 | width: 120px; 29 | } 30 | 31 | div.row span input { 32 | width: 80px; 33 | position: relative; 34 | left: 24px; 35 | } 36 | 37 | input { 38 | width: 160px; 39 | } 40 | 41 | input.checkbox { 42 | width: 12px; 43 | } 44 | 45 | input.narrow { 46 | width: 60px; 47 | } 48 | 49 | input.medium { 50 | width: 260px; 51 | } 52 | 53 | input.wide { 54 | width: 520px; 55 | } 56 | 57 | input.align-right { 58 | text-align: right; 59 | } 60 | 61 | input:read-only { 62 | border: dotted 1px #d0d0d0; 63 | } 64 | 65 | button { 66 | width: 88px; 67 | } 68 | 69 | table { 70 | margin-left: 120px; 71 | } 72 | 73 | th { 74 | border-bottom: 1px solid #808080; 75 | font-weight: normal; 76 | } 77 | 78 | td.number { 79 | text-align: right; 80 | } 81 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: "ts-jest/presets/js-with-ts-esm", 3 | testEnvironment: "node", 4 | testPathIgnorePatterns: ["dist/tests"], 5 | maxWorkers: 1, // Counter-intuitively, this speeds up running multiple tests. 6 | 7 | moduleNameMapper: { 8 | "axios": "axios/dist/node/axios.cjs", 9 | "worker-url": "/mocks/worker-url.mock.js" 10 | } 11 | 12 | }; 13 | -------------------------------------------------------------------------------- /jsdoc/config-dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "opts": { 3 | "template": "hifi-jsdoc-template" 4 | }, 5 | "docdash": { 6 | "meta": { 7 | "title": "", 8 | "description": "", 9 | "keyword": "" 10 | }, 11 | "search": [ true ], 12 | "collapse": [ true ], 13 | "typedefs": [ false ] 14 | }, 15 | "templates": { 16 | "default": { 17 | "outputSourceFiles": false 18 | } 19 | }, 20 | "plugins": [ 21 | "plugins/vircadia", 22 | "plugins/vircadia-dev" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /jsdoc/config-sdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "opts": { 3 | "template": "hifi-jsdoc-template" 4 | }, 5 | "docdash": { 6 | "meta": { 7 | "title": "", 8 | "description": "", 9 | "keyword": "" 10 | }, 11 | "search": [ true ], 12 | "collapse": [ true ], 13 | "typedefs": [ false ] 14 | }, 15 | "templates": { 16 | "default": { 17 | "outputSourceFiles": false 18 | } 19 | }, 20 | "plugins": [ 21 | "plugins/vircadia", 22 | "plugins/vircadia-sdk" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /jsdoc/dev-mainpage.md: -------------------------------------------------------------------------------- 1 |

Developer Documention

2 | 3 | The Vircadia Web SDK is a JavaScript SDK, written in TypeScript, for developing web-based clients for virtual 4 | worlds powered by Vircadia. Vircadia domain servers provide the worlds (a.k.a. "domains") to visit, and the Vircadia metaverse 5 | server provides global services that connect the users and domains. 6 | See the user docs to [Understand the Architecture](https://docs.vircadia.com/explore/get-started/architecture.html). 7 | 8 | This SDK provides interfaces to: 9 | - Connect to domains and their assignment clients. 10 | - Use metaverse services. 11 | 12 |
13 | 14 | The primary top-level namespaces and classes provided for an application to use are, per the _Vircadia Web SDK Reference_: 15 | - `Vircadia` 16 | - `DomainServer` 17 | - `AudioMixer` 18 | - `AvatarMixer` 19 | - `EntityServer` 20 | - `MessageMixer` 21 | - `Camera` 22 | 23 |
24 | 25 | To use the API, import the namespaces and classes that you want to use — either from the SDK package installed in your 26 | project or directly from the SDK TypeScript. 27 | 28 | - Install the SDK package in your project and import, for example: 29 | ``` 30 | npm install --save-prod 31 | 32 | import { Vircadia, DomainServer , AudioMixer, AvatarMixer, MessageMixer } from "@vircadia/web-sdk"; 33 | ``` 34 | 35 | - Import directly from the SDK TypeScript: 36 | ``` 37 | import { Vircadia, DomainServer, AudioMixer, AvatarMixer, MessageMixer } from "/Vircadia"; 38 | ``` 39 | 40 |
41 | 42 | GitHub repository: [/vircadia/vircadia-web-sdk](https://github.com/vircadia/vircadia-web-sdk) 43 | 44 | For scripting API documentation, see the [Vircadia API Reference](https://apidocs.vircadia.dev). 45 | 46 | To learn more about using Vircadia and exploring the metaverse, see the [User Documentation](https://docs.vircadia.com). 47 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/README.md: -------------------------------------------------------------------------------- 1 | # hifi-jsdoc-template 2 | The hifi-jsdoc-template is based on the [DocDash](https://github.com/clenemt/docdash) template. 3 | 4 | ## Usage 5 | Clone repository to your designated `jsdoc/node_modules` template directory. 6 | 7 | In your `config.json` file, add a template option. 8 | 9 | ```json 10 | "opts": { 11 | "template": "node_modules/hifi-jsdoc-template" 12 | } 13 | ``` 14 | 15 | ## Sample `config.json` 16 | 17 | ```json 18 | { 19 | "opts": { 20 | "template": "node_modules/hifi-jsdoc-template" 21 | }, 22 | "docdash": { 23 | "meta": { 24 | "title": "", 25 | "description": "", 26 | "keyword": "" 27 | }, 28 | "search": [true], 29 | "collapse": [true], 30 | "typedefs": [false] 31 | }, 32 | "templates": { 33 | "default": { 34 | "outputSourceFiles": false 35 | } 36 | }, 37 | "plugins": [ 38 | "plugins/hifi", 39 | "plugins/hifiJSONExport" 40 | ] 41 | } 42 | ``` 43 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_from": "docdash", 3 | "_id": "docdash@1.0.0", 4 | "_inBundle": false, 5 | "_integrity": "sha512-HhK72PT4z55og8FDqskO/tTYXxU+LovRz+9pCDHLnUoPchkxjdIJidS+96LqW3CLrRdBmnkDRrcVrDFGLIluTw==", 6 | "_location": "/docdash", 7 | "_phantomChildren": {}, 8 | "_requested": { 9 | "type": "tag", 10 | "registry": true, 11 | "raw": "docdash", 12 | "name": "docdash", 13 | "escapedName": "docdash", 14 | "rawSpec": "", 15 | "saveSpec": null, 16 | "fetchSpec": "latest" 17 | }, 18 | "_requiredBy": [ 19 | "#USER", 20 | "/" 21 | ], 22 | "_resolved": "https://registry.npmjs.org/docdash/-/docdash-1.0.0.tgz", 23 | "_shasum": "5b7df10fed3d341fc4416a8978c65ad561869d18", 24 | "_spec": "docdash", 25 | "_where": "D:\\hifi\\tools\\jsdoc", 26 | "author": { 27 | "name": "Clement Moron", 28 | "email": "clement.moron@gmail.com" 29 | }, 30 | "bugs": { 31 | "url": "https://github.com/clenemt/docdash/issues" 32 | }, 33 | "bundleDependencies": false, 34 | "deprecated": false, 35 | "description": "A clean, responsive documentation template theme for JSDoc 3 inspired by lodash and minami", 36 | "devDependencies": { 37 | "browser-sync": "latest", 38 | "jsdoc": "latest", 39 | "watch-run": "latest" 40 | }, 41 | "homepage": "https://github.com/clenemt/docdash#readme", 42 | "keywords": [ 43 | "jsdoc", 44 | "template" 45 | ], 46 | "license": "Apache-2.0", 47 | "main": "publish.js", 48 | "name": "docdash", 49 | "repository": { 50 | "type": "git", 51 | "url": "git+https://github.com/clenemt/docdash.git" 52 | }, 53 | "scripts": { 54 | "sync": "browser-sync start -s ../fixtures-doc -f ../fixtures-doc --reload-delay 1000 --no-ui --no-notify", 55 | "test": "jsdoc -c fixtures/fixtures.conf.json", 56 | "watch": "watch-run -d 1000 -p tmpl/**,static/** \"npm run test\"" 57 | }, 58 | "version": "1.0.0" 59 | } 60 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/fonts/Graphik-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vircadia/vircadia-web-sdk/be293c479fbbb5ba907c6f1a0497c446e97b59a6/jsdoc/hifi-jsdoc-template/static/fonts/Graphik-Regular.otf -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/fonts/Graphik-Semibold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vircadia/vircadia-web-sdk/be293c479fbbb5ba907c6f1a0497c446e97b59a6/jsdoc/hifi-jsdoc-template/static/fonts/Graphik-Semibold.otf -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/fonts/materialdesignicons-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vircadia/vircadia-web-sdk/be293c479fbbb5ba907c6f1a0497c446e97b59a6/jsdoc/hifi-jsdoc-template/static/fonts/materialdesignicons-webfont.woff -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/fonts/materialdesignicons-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vircadia/vircadia-web-sdk/be293c479fbbb5ba907c6f1a0497c446e97b59a6/jsdoc/hifi-jsdoc-template/static/fonts/materialdesignicons-webfont.woff2 -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/fonts/proximanova-regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vircadia/vircadia-web-sdk/be293c479fbbb5ba907c6f1a0497c446e97b59a6/jsdoc/hifi-jsdoc-template/static/fonts/proximanova-regular.otf -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/images/fav-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vircadia/vircadia-web-sdk/be293c479fbbb5ba907c6f1a0497c446e97b59a6/jsdoc/hifi-jsdoc-template/static/images/fav-icon.ico -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/images/vircadia-logo-1880.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vircadia/vircadia-web-sdk/be293c479fbbb5ba907c6f1a0497c446e97b59a6/jsdoc/hifi-jsdoc-template/static/images/vircadia-logo-1880.png -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/scripts/collapse.js: -------------------------------------------------------------------------------- 1 | function hideAllButCurrent(){ 2 | //by default all submenut items are hidden 3 | $("nav > ul > li > ul li").hide(); 4 | 5 | //only current page (if it exists) should be opened 6 | var file = window.location.pathname.split("/").pop(); 7 | $("nav > ul > li > a[href^='"+file+"']").parent().find("> ul li").show(); 8 | } 9 | $( document ).ready(function() { 10 | hideAllButCurrent(); 11 | }); -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/scripts/linenumber.js: -------------------------------------------------------------------------------- 1 | /*global document */ 2 | (function() { 3 | var source = document.getElementsByClassName('prettyprint source linenums'); 4 | var i = 0; 5 | var lineNumber = 0; 6 | var lineId; 7 | var lines; 8 | var totalLines; 9 | var anchorHash; 10 | 11 | if (source && source[0]) { 12 | anchorHash = document.location.hash.substring(1); 13 | lines = source[0].getElementsByTagName('li'); 14 | totalLines = lines.length; 15 | 16 | for (; i < totalLines; i++) { 17 | lineNumber++; 18 | lineId = 'line' + lineNumber; 19 | lines[i].id = lineId; 20 | if (lineId === anchorHash) { 21 | lines[i].className += ' selected'; 22 | } 23 | } 24 | } 25 | })(); 26 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/scripts/prettify/lang-css.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", 2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/scripts/search.js: -------------------------------------------------------------------------------- 1 | $( document ).ready(function() { 2 | jQuery.expr[':'].Contains = function(a,i,m){ 3 | return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0; 4 | }; 5 | //on search 6 | $("#nav-search").on("keyup", function(event) { 7 | var search = $(this).val(); 8 | if (!search) { 9 | //no search, show all results 10 | $("nav > ul > li").show(); 11 | 12 | if(typeof hideAllButCurrent === "function"){ 13 | //let's do what ever collapse wants to do 14 | hideAllButCurrent(); 15 | } 16 | else{ 17 | //menu by default should be opened 18 | $("nav > ul > li > ul li").show(); 19 | } 20 | } 21 | else{ 22 | //we are searching 23 | //show all parents 24 | $("nav > ul > li").show(); 25 | //hide all results 26 | $("nav > ul > li > ul li").hide(); 27 | //show results matching filter 28 | $("nav > ul > li > ul").find("a:Contains("+search+")").parent().show(); 29 | //hide parents without children 30 | $("nav > ul > li").each(function(){ 31 | if($(this).find("a:Contains("+search+")").length == 0 && $(this).children("ul").length === 0){ 32 | //has no child at all and does not contain text 33 | $(this).hide(); 34 | } 35 | else if($(this).find("a:Contains("+search+")").length == 0 && $(this).find("ul").children(':visible').length == 0){ 36 | //has no visible child and does not contain text 37 | $(this).hide(); 38 | } 39 | }); 40 | } 41 | }); 42 | }); -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/styles/main.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vircadia/vircadia-web-sdk/be293c479fbbb5ba907c6f1a0497c446e97b59a6/jsdoc/hifi-jsdoc-template/static/styles/main.css -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/styles/night.css: -------------------------------------------------------------------------------- 1 | html { 2 | background-color: #061F2F; 3 | } 4 | 5 | body h1 { 6 | color: #eaeaea; 7 | } 8 | 9 | body { 10 | color: #d3d4d4 !important; 11 | } 12 | 13 | section { 14 | background-color: #061F2F; 15 | } 16 | 17 | /* Prettify */ 18 | 19 | .typ { 20 | color: #f8c555 !important; 21 | } 22 | 23 | .pun { 24 | color: #c1f1f0 !important; 25 | } 26 | 27 | .pln { 28 | color: #c1f1f0 !important; 29 | } 30 | 31 | .kwd { 32 | color: #e8a0e8 !important; 33 | } 34 | 35 | .str { 36 | color: #f08d49 !important; 37 | } 38 | 39 | .com { 40 | color: #9d9d9d !important; 41 | } 42 | 43 | .prettyprint code { 44 | background-color: #0a121b; 45 | } 46 | 47 | tr td a code { 48 | font-weight: bold; 49 | } 50 | 51 | /* JSDoc */ 52 | 53 | thead { 54 | background: #1f3341 !important; 55 | } 56 | 57 | thead tr { 58 | color: white !important; 59 | } 60 | 61 | table tr:nth-child(2n) { 62 | background: #1f3341 !important; 63 | } 64 | 65 | .name code { 66 | color: #e8a0e8 !important; 67 | font-weight: bold; 68 | } 69 | 70 | .signature { 71 | font-weight: bold; 72 | } 73 | 74 | #main a, #main a:visited, #main a:active, #main a:hover { 75 | color: #69d3ff !important; 76 | } 77 | 78 | .important { 79 | color: #F91E1E !important; 80 | } -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/static/styles/responsive.css: -------------------------------------------------------------------------------- 1 | .nav-header { 2 | display: none; 3 | } 4 | 5 | nav { 6 | display: none !important; 7 | } 8 | 9 | section { 10 | margin-right: 0px !important; 11 | } 12 | 13 | #main { 14 | margin-left: 15px !important; 15 | margin-right: 15px !important; 16 | overflow: auto; 17 | } -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/tmpl/augments.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 |
    8 |
  • 9 |
10 | 11 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/tmpl/description.tmpl: -------------------------------------------------------------------------------- 1 | ]*>', 'i'); 5 | var descriptionIndex = description.search(descriptionRegExp); 6 | ?> 7 | 8 | 9 |

10 | 11 |

12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/tmpl/examples.tmpl: -------------------------------------------------------------------------------- 1 | 8 |

9 | 10 |
11 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/tmpl/exceptions.tmpl: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |
7 |
8 | 9 |
10 |
11 |
12 |
13 |
14 |
15 | Type 16 |
17 |
18 | 19 |
20 |
21 |
22 |
23 |
24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
32 | 33 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/tmpl/mainpage.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 |
8 |
9 |
10 | 11 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/tmpl/members.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | 31 | 32 | 33 |
10 |
11 | Type: 12 |
18 | 19 | 20 | 21 |

 

22 | 23 | 24 | 25 | 26 |
Example 1? 's':'' ?>
27 | 28 | 29 | 30 |
34 | 35 | 36 |
Fires:
37 |
    38 |
  • 39 |
40 | 41 | 42 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/tmpl/paramList.tmpl: -------------------------------------------------------------------------------- 1 | 59 | 60 | 61 | 62 | 63 | 64 | , 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/tmpl/returns.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/tmpl/returnsSimp.tmpl: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/tmpl/source.tmpl: -------------------------------------------------------------------------------- 1 | 4 |
5 |
6 |
7 |
8 |
-------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/tmpl/tutorial.tmpl: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 0) { ?> 5 |
    8 |
  • 9 |
10 | 11 | 12 |

13 |
14 | 15 |
16 | 17 |
18 | 19 |
20 | -------------------------------------------------------------------------------- /jsdoc/hifi-jsdoc-template/tmpl/type.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | | 7 | -------------------------------------------------------------------------------- /jsdoc/plugins/vircadia-dev.js: -------------------------------------------------------------------------------- 1 | exports.handlers = { 2 | 3 | // This event is triggered for each file. 4 | beforeParse: function (e) { 5 | e.source = e.source.replace(/\/\*@(dev|sdk)doc/g, "/**"); 6 | }, 7 | 8 | processingComplete: function (e) { 9 | const pathTools = require('path'); 10 | var outputFolder = pathTools.join(__dirname, '../../docs/dev'); 11 | var doclets = e.doclets.map(doclet => Object.assign({}, doclet)); 12 | const fs = require('fs'); 13 | if (!fs.existsSync(outputFolder)) { 14 | fs.mkdirSync(outputFolder); 15 | } 16 | doclets.map(doclet => {delete doclet.meta; delete doclet.comment}); 17 | fs.writeFile(pathTools.join(outputFolder, "VircadiaWebDev.JSDoc.json"), JSON.stringify(doclets, null, 4), function(err) { 18 | if (err) { 19 | return console.log(err); 20 | } 21 | 22 | console.log("The Vircadia Web SDK JSDoc JSON was saved!"); 23 | }); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /jsdoc/plugins/vircadia-sdk.js: -------------------------------------------------------------------------------- 1 | exports.handlers = { 2 | 3 | // This event is triggered for each file. 4 | beforeParse: function (e) { 5 | e.source = e.source.replace(/\/\*@sdkdoc/g, "/**"); 6 | }, 7 | 8 | processingComplete: function (e) { 9 | const pathTools = require('path'); 10 | var outputFolder = pathTools.join(__dirname, '../../docs/sdk'); 11 | var doclets = e.doclets.map(doclet => Object.assign({}, doclet)); 12 | const fs = require('fs'); 13 | if (!fs.existsSync(outputFolder)) { 14 | fs.mkdirSync(outputFolder); 15 | } 16 | doclets.map(doclet => {delete doclet.meta; delete doclet.comment}); 17 | fs.writeFile(pathTools.join(outputFolder, "VircadiaWebSDK.JSDoc.json"), JSON.stringify(doclets, null, 4), function(err) { 18 | if (err) { 19 | return console.log(err); 20 | } 21 | 22 | console.log("The Vircadia Web SDK JSDoc JSON was saved!"); 23 | }); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /jsdoc/sdk-mainpage.md: -------------------------------------------------------------------------------- 1 | The Vircadia Web SDK is a JavaScript SDK, written in TypeScript, for developing web-based clients for virtual 2 | worlds powered by Vircadia. Vircadia domain servers provide the worlds (a.k.a. "domains") to visit, and the Vircadia metaverse 3 | server provides global services that connect the users and domains. 4 | See the user docs to [Understand the Architecture](https://docs.vircadia.com/explore/get-started/architecture.html). 5 | 6 | This SDK provides interfaces to: 7 | - Connect to domains and their assignment clients. 8 | - Use metaverse services. 9 | 10 |
11 | 12 | The primary top-level namespaces and classes provided for an application to use are: 13 | - `Vircadia` 14 | - `DomainServer` 15 | - `AudioMixer` 16 | - `AvatarMixer` 17 | - `EntityServer` 18 | - `MessageMixer` 19 | - `Camera` 20 | 21 |
22 | 23 | To use the API, import the namespaces and classes that you want to use — either from the SDK package installed in your 24 | project or directly from the SDK TypeScript. 25 | 26 | - Install the SDK package in your project and import, for example: 27 | ``` 28 | npm install --save-prod 29 | 30 | import { Vircadia, DomainServer, AudioMixer, AvatarMixer, MessageMixer } from "@vircadia/web-sdk"; 31 | ``` 32 | 33 | - Import directly from the SDK TypeScript: 34 | ``` 35 | import { Vircadia, DomainServer, AudioMixer, AvatarMixer, MessageMixer } from "/Vircadia"; 36 | ``` 37 | 38 |
39 | 40 | GitHub repository: [/vircadia/vircadia-web-sdk](https://github.com/vircadia/vircadia-web-sdk) 41 | 42 | For scripting API documentation, see the [Vircadia API Reference](https://apidocs.vircadia.dev). 43 | 44 | To learn more about using Vircadia and exploring the metaverse, see the [User Documentation](https://docs.vircadia.com). 45 | -------------------------------------------------------------------------------- /mocks/domain/audio/AudioWorklets.mock.js: -------------------------------------------------------------------------------- 1 | // 2 | // AudioWorklets.mock.js 3 | // 4 | // Created by David Rowe on 13 Dec 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | 13 | /* eslint-disable @typescript-eslint/no-unused-vars */ 14 | /* eslint-disable class-methods-use-this */ 15 | 16 | const AudioWorkletsMock = new class { 17 | 18 | mock() { 19 | jest.mock("../../../src/domain/audio/AudioWorklets", () => { 20 | return { 21 | loadInputProcessor: async (relativePath, audioContext) => { 22 | // No-op; 23 | }, 24 | loadOutputProcessor: async (relativePath, audioContext) => { 25 | // No-op; 26 | } 27 | }; 28 | }); 29 | } 30 | 31 | 32 | }(); 33 | 34 | export default AudioWorkletsMock; 35 | -------------------------------------------------------------------------------- /mocks/domain/networking/AccountManager.mock.js: -------------------------------------------------------------------------------- 1 | // 2 | // AccountManager.mock.js 3 | // 4 | // Created by David Rowe on 7 Jan 2023. 5 | // Copyright 2023 Vircadia contributors. 6 | // Copyright 2023 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AccountManager from "../../../src/domain/networking/AccountManager"; 13 | 14 | 15 | const AccountManagerMock = new class { 16 | 17 | /* eslint-disable class-methods-use-this */ 18 | 19 | mock() { 20 | jest 21 | .spyOn(AccountManager.prototype, "generateNewUserKeypair") 22 | .mockImplementation(() => { 23 | /* No-op. */ 24 | }); 25 | jest 26 | .spyOn(AccountManager.prototype, "refreshAccessToken") 27 | .mockImplementation(() => { 28 | /* No-op. */ 29 | }); 30 | } 31 | 32 | }(); 33 | 34 | export default AccountManagerMock; 35 | -------------------------------------------------------------------------------- /mocks/worker-url.mock.js: -------------------------------------------------------------------------------- 1 | // 2 | // worker-url.mock.js 3 | // 4 | // Mocks the worker-url Node module such that Jest tests involving it can run without encountering errors such as: 5 | // 6 | // ({"Object.":function(module,exports,require,__dirname,__filename,jest){export function WorkerUrl(url, options) { 7 | // SyntaxError: Unexpected token 'export' 8 | // 9 | // Created by David Rowe on 13 Dec 2021. 10 | // Copyright 2021 Vircadia contributors. 11 | // Copyright 2021 DigiSomni LLC. 12 | // 13 | // Distributed under the Apache License, Version 2.0. 14 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 15 | // 16 | 17 | export { }; 18 | -------------------------------------------------------------------------------- /src/domain/DOMAIN.md: -------------------------------------------------------------------------------- 1 | # Domain Files 2 | 3 | The files in the `/domain` directory are used in the domain server and assignment client APIs implemented in the root directory 4 | files: 5 | - `AgentClient.ts` 6 | - `AudioMixer.ts` 7 | - `AssetServer.ts` 8 | - `AvatarMixer.ts` 9 | - `DomainServer.ts` 10 | - `EntityServer.ts` 11 | - `MessageMixer.ts` 12 | 13 | The files in the `/domain` directory reflect the native Interface app code, with files, classes, and variables named the same 14 | and reimplemented in JavaScript. This helps lighten the intellectual load of understanding and maintaining both codebases and 15 | enables searches to be done on both sets of code simultaneously. 16 | 17 | Simplifications can often be made in the web SDK where, for example, it's not necessary to implement domain server or assignment 18 | client code, handle UDP communications, etc. Code might not need to be implemented, class hierarchies might be able to be 19 | collapsed, etc. 20 | 21 | The mappings of the JavaScript code to the C++ code and simplifications made are explicitly documented to aid maintenance. 22 | -------------------------------------------------------------------------------- /src/domain/audio/AudioConstants.ts: -------------------------------------------------------------------------------- 1 | // 2 | // AudioConstants.ts 3 | // 4 | // Created by David Rowe on 11 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /*@devdoc 13 | * The AudioConstants namespace provides the values of audio constants used in the SDK. 14 | *

C++: AudioConstants

15 | * 16 | * @namespace AudioConstants 17 | * 18 | * @property {number} SAMPLE_RATE - 24000 - The audio sample rate, in Hz. 19 | * 20 | * @property {number} STEREO - 2 - The number of audio channels for stereo. 21 | * 22 | * @property {number} NETWORK_FRAME_SAMPLES_STEREO - 480 - The number of samples in a network packet for a stereo 23 | * channel. 24 | * @property {number} NETWORK_FRAME_SAMPLES_PER_CHANNEL - 240 - The number of samples in a network packet per 25 | * channel. 26 | * 27 | * @property {number} NETWORK_FRAME_SECS - 0.01 - The interval between audio network packets, in seconds. 28 | * @property {number} NETWORK_FRAME_MSECS - 10 - The interval between audio network packets, in milliseconds. 29 | * 30 | * @property {number} AUDIO_WORKLET_BLOCK_SIZE - 128 - The number of frames in and audio worklet audio block. 31 | */ 32 | const AudioConstants = new class { 33 | // C++ AudioConstants 34 | 35 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 36 | 37 | readonly SAMPLE_RATE = 24000; 38 | 39 | readonly STEREO = 2; 40 | 41 | readonly NETWORK_FRAME_SAMPLES_STEREO = 480; 42 | readonly NETWORK_FRAME_SAMPLES_PER_CHANNEL = 240; 43 | 44 | readonly NETWORK_FRAME_SECS = this.NETWORK_FRAME_SAMPLES_PER_CHANNEL / this.SAMPLE_RATE; 45 | readonly NETWORK_FRAME_MSECS = this.NETWORK_FRAME_SECS * 1000; 46 | 47 | readonly AUDIO_WORKLET_BLOCK_SIZE = 128; // 128 frames of samples. 48 | 49 | }(); 50 | 51 | export { AudioConstants as default }; 52 | -------------------------------------------------------------------------------- /src/domain/entities/GizmoEntityItem.ts: -------------------------------------------------------------------------------- 1 | // 2 | // GizmoEntityItem.ts 3 | // 4 | // Created by Julien Merzoug on 19 Jul 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import { CommonEntityProperties } from "../networking/packets/EntityData"; 13 | import PropertyFlags from "../shared/PropertyFlags"; 14 | import { EntityPropertyFlags } from "./EntityPropertyFlags"; 15 | import RingGizmoPropertyGroup from "./RingGizmoPropertyGroup"; 16 | 17 | 18 | // WEBRTC TODO: Replace Record with GizmoEntityItem's special properties. 19 | type GizmoEntitySubclassProperties = Record; 20 | 21 | // WEBRTC TODO: Make a union with GizmoEntitySubclassProperties. 22 | type GizmoEntityProperties = CommonEntityProperties; 23 | 24 | type GizmoEntitySubclassData = { 25 | bytesRead: number; 26 | properties: GizmoEntitySubclassProperties; 27 | }; 28 | 29 | 30 | class GizmoEntityItem { 31 | // C++ class GizmoEntityItem : public EntityItem 32 | 33 | static readEntitySubclassDataFromBuffer(data: DataView, position: number, propertyFlags: PropertyFlags): GizmoEntitySubclassData { // eslint-disable-line class-methods-use-this, max-len 34 | // C++ int GizmoEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, 35 | // ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData, 36 | // bool& somethingChanged) 37 | 38 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 39 | 40 | let dataPosition = position; 41 | 42 | if (propertyFlags.getHasProperty(EntityPropertyFlags.PROP_GIZMO_TYPE)) { 43 | // WEBRTC TODO: Read gizmoType property. 44 | dataPosition += 4; 45 | } 46 | 47 | const ringProperties = RingGizmoPropertyGroup.readEntitySubclassDataFromBuffer(data, dataPosition, propertyFlags); 48 | dataPosition += ringProperties.bytesRead; 49 | 50 | return { 51 | bytesRead: dataPosition - position, 52 | properties: {} 53 | }; 54 | 55 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 56 | } 57 | 58 | } 59 | 60 | export default GizmoEntityItem; 61 | export type { GizmoEntitySubclassData, GizmoEntityProperties }; 62 | -------------------------------------------------------------------------------- /src/domain/entities/LineEntityItem.ts: -------------------------------------------------------------------------------- 1 | // 2 | // LineEntityItem.ts 3 | // 4 | // Created by Julien Merzoug on 15 Jul 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import { CommonEntityProperties } from "../networking/packets/EntityData"; 13 | import UDT from "../networking/udt/UDT"; 14 | import PropertyFlags from "../shared/PropertyFlags"; 15 | import { EntityPropertyFlags } from "./EntityPropertyFlags"; 16 | 17 | // WEBRTC TODO: Replace Record with LineEntityItem's special properties. 18 | type LineEntitySubclassProperties = Record; 19 | 20 | // WEBRTC TODO: Make a union with LineEntitySubclassProperties. 21 | type LineEntityProperties = CommonEntityProperties; 22 | 23 | type LineEntitySubclassData = { 24 | bytesRead: number; 25 | properties: LineEntitySubclassProperties; 26 | }; 27 | 28 | 29 | class LineEntityItem { 30 | // C++ class LineEntityItem : public EntityItem 31 | 32 | static readEntitySubclassDataFromBuffer(data: DataView, position: number, propertyFlags: PropertyFlags): LineEntitySubclassData { // eslint-disable-line class-methods-use-this, max-len 33 | // C++ int LineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, 34 | // ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData, 35 | // bool& somethingChanged) 36 | 37 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 38 | 39 | let dataPosition = position; 40 | 41 | if (propertyFlags.getHasProperty(EntityPropertyFlags.PROP_COLOR)) { 42 | // WEBRTC TODO: Read color property. 43 | dataPosition += 3; 44 | } 45 | 46 | if (propertyFlags.getHasProperty(EntityPropertyFlags.PROP_LINE_POINTS)) { 47 | const length = data.getUint16(dataPosition, UDT.LITTLE_ENDIAN); 48 | dataPosition += 2; 49 | 50 | if (length > 0) { 51 | // WEBRTC TODO: Read linePoints property. 52 | dataPosition += length * 12; 53 | } 54 | } 55 | 56 | return { 57 | bytesRead: dataPosition - position, 58 | properties: {} 59 | }; 60 | 61 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 62 | } 63 | 64 | } 65 | 66 | export default LineEntityItem; 67 | export type { LineEntitySubclassData, LineEntityProperties }; 68 | -------------------------------------------------------------------------------- /src/domain/networking/NetworkingConstants.ts: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkingConstants.ts 3 | // 4 | // Created by David Rowe on 6 Jan 2023. 5 | // Copyright 2023 Vircadia contributors. 6 | // Copyright 2023 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | 13 | /*@devdoc 14 | * The NetworkingConstants namespace provides networking constants. 15 | *

C++ namespace NetworkingConstants

16 | * @class NetworkingConstants 17 | * @property {string} METAVERSE_SERVER_URL_STABLE="https://metaverse.vircadia.com/live" - The default Vircadia metaverse server 18 | * API URL. 19 | */ 20 | enum NetworkingConstants { 21 | // C++ namespace NetworkingConstants 22 | 23 | METAVERSE_SERVER_URL_STABLE = "https://metaverse.vircadia.com/live" 24 | 25 | } 26 | 27 | export default NetworkingConstants; 28 | -------------------------------------------------------------------------------- /src/domain/networking/PingType.ts: -------------------------------------------------------------------------------- 1 | // 2 | // PingType.ts 3 | // 4 | // Created by David Rowe on 6 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | 13 | /*@devdoc 14 | * A {@link PingType(1)|ping type}, Agnostic ... Symmetric is the type of a network {@link Ping} packet. PingType 15 | * values are represented as 8-bit numbers in protocol packets. 16 | * @typedef {number} PingType 17 | */ 18 | const enum PingTypeValue { 19 | // C++ typedef quint8 PingType_t; 20 | Agnostic = 0, 21 | Local = 1, 22 | Public = 2, 23 | Symmetric = 3 24 | } 25 | 26 | 27 | /*@devdoc 28 | * The PingType namespace provides the types of network {@link PacketType(1)|Ping} used in Vircadia protocol 29 | * communications. 30 | *

C++: PingType

31 | * 32 | * @namespace PingType 33 | * @variation 1 34 | * 35 | * @property {PingType} Agnostic - 0 - Ping to local, public, or symmetric socket. 36 | * @property {PingType} Local - 1 - Ping to a local socket. 37 | * @property {PingType} Public - 2 - Ping to a public socket. 38 | * @property {PingType} Symmetric - 3 - Ping to a symmetric socket. 39 | */ 40 | const PingType = new class { 41 | // C++ PingType 42 | 43 | readonly Agnostic = PingTypeValue.Agnostic; 44 | readonly Local = PingTypeValue.Local; 45 | readonly Public = PingTypeValue.Public; 46 | readonly Symmetric = PingTypeValue.Symmetric; 47 | 48 | }(); 49 | 50 | export { PingType as default, PingTypeValue }; 51 | -------------------------------------------------------------------------------- /src/domain/networking/packets/BulkAvatarTraitsAck.ts: -------------------------------------------------------------------------------- 1 | // 2 | // BulkAvatarTraitsAck.ts 3 | // 4 | // Created by David Rowe on 28 Nov 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import PacketType from "../udt/PacketHeaders"; 13 | import UDT from "../udt/UDT"; 14 | import NLPacket from "../NLPacket"; 15 | 16 | 17 | type BulkAvatarTraitsAckDetails = { 18 | traitsSequenceNumber: bigint 19 | }; 20 | 21 | 22 | const BulkAvatarTraitsAck = new class { 23 | 24 | /*@devdoc 25 | * Information needed for {@link PacketScribe|writing} a {@link PacketType(1)|BulkAvatarTraitsAck} packet. 26 | * @typedef {object} PacketScribe.BulkAvatarTraitsAckDetails 27 | * @property {bigint} traitsSequenceNumber - The sequence number of the avatar traits message being acknowledged. 28 | */ 29 | 30 | /*@devdoc 31 | * Writes a {@link PacketType(1)|BulkAvatarTraitsAck} packet, ready for sending. 32 | * @function PacketScribe.BulkAvatarTraitsAck.write 33 | * @param {PacketScribe.BulkAvatarTraitsAckDetails} info - The information needed for writing the packet. 34 | * @returns {NLPacket} The packet, ready for sending. 35 | */ 36 | write(info: BulkAvatarTraitsAckDetails): NLPacket { /* eslint-disable-line class-methods-use-this */ 37 | // C++ void AvatarHashMap::processBulkAvatarTraits(ReceivedMessage* message, Node* sendingNode) 38 | 39 | const TRAIT_SEQ_NUM_BYTES = 8; 40 | const packet = NLPacket.create(PacketType.BulkAvatarTraitsAck, TRAIT_SEQ_NUM_BYTES, true); 41 | const messageData = packet.getMessageData(); 42 | const data = messageData.data; 43 | let dataPosition = messageData.dataPosition; 44 | 45 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 46 | 47 | data.setBigUint64(dataPosition, info.traitsSequenceNumber, UDT.LITTLE_ENDIAN); 48 | dataPosition += 8; 49 | 50 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 51 | 52 | messageData.dataPosition = dataPosition; 53 | messageData.packetSize = dataPosition; 54 | 55 | return packet; 56 | } 57 | 58 | }(); 59 | 60 | export default BulkAvatarTraitsAck; 61 | export type { BulkAvatarTraitsAckDetails }; 62 | -------------------------------------------------------------------------------- /src/domain/networking/packets/DomainDisconnectRequest.ts: -------------------------------------------------------------------------------- 1 | // 2 | // DomainDisonnectRequest.ts 3 | // 4 | // Created by David Rowe on 26 Jul 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import PacketType from "../udt/PacketHeaders"; 13 | import NLPacket from "../NLPacket"; 14 | 15 | 16 | const DomainDisconnectRequest = new class { 17 | 18 | /*@devdoc 19 | * Writes a {@link PacketType(1)|DomainDisconnectRequest} packet, ready for sending. 20 | * @function PacketScribe.DomainDisconnectRequest.write 21 | * @returns {NLPacket} The packet, ready for sending. 22 | */ 23 | write(): NLPacket { /* eslint-disable-line class-methods-use-this */ 24 | // C++ DomainHandler::sendDisconnectPacket() 25 | 26 | const packet = NLPacket.create(PacketType.DomainDisconnectRequest); 27 | const messageData = packet.getMessageData(); 28 | messageData.packetSize = messageData.dataPosition; 29 | return packet; 30 | } 31 | 32 | }(); 33 | 34 | export default DomainDisconnectRequest; 35 | -------------------------------------------------------------------------------- /src/domain/networking/packets/DomainServerConnectionToken.ts: -------------------------------------------------------------------------------- 1 | // 2 | // DomainServerConnectionToken.ts 3 | // 4 | // Created by David Rowe on 13 Jan 2023. 5 | // Copyright 2023 Vircadia contributors. 6 | // Copyright 2023 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import UDT from "../udt/UDT"; 13 | import assert from "../../shared/assert"; 14 | import Uuid from "../../shared/Uuid"; 15 | 16 | import "../../shared/DataViewExtensions"; 17 | 18 | 19 | type DomainServerConnectionTokenDetails = { 20 | connectionToken: Uuid 21 | }; 22 | 23 | 24 | const DomainServerConnectionToken = new class { 25 | // C++ N/A 26 | 27 | /*@devdoc 28 | * Information returned by {@link PacketScribe|reading} a {@link PacketType(1)|DomainServerConnectionToken} packet. 29 | * @typedef {object} PacketScribe.DomainServerConnectionTokenDetails 30 | * @property {Uuid} connectionToken - The domain server connection token. 31 | */ 32 | 33 | /*@devdoc 34 | * Reads a {@link PacketType(1)|DomainServerConnectionToken} packet. 35 | * @function PacketScribe.DomainServerConnectionToken.read 36 | * @param {DataView} data - The {@link Packets|DomainServerConnectionToken} message data to read. 37 | * @returns {PacketScribe.DomainServerConnectionTokenDetails} Information on the domain server connection token. 38 | */ 39 | read(data: DataView): DomainServerConnectionTokenDetails { /* eslint-disable-line class-methods-use-this */ 40 | // C++ void NodeList::processDomainServerConnectionTokenPacket(QSharedPointer message) 41 | 42 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 43 | 44 | let dataPosition = 0; 45 | 46 | const connectionToken = new Uuid(data.getBigUint128(dataPosition, UDT.BIG_ENDIAN)); 47 | dataPosition += 16; 48 | 49 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 50 | 51 | assert(dataPosition === data.byteLength, "ERROR: Length mismatch reading DomainServerConnectionToken message!"); 52 | 53 | return { 54 | connectionToken 55 | }; 56 | } 57 | 58 | }(); 59 | 60 | export default DomainServerConnectionToken; 61 | export type { DomainServerConnectionTokenDetails }; 62 | -------------------------------------------------------------------------------- /src/domain/networking/packets/DomainServerRemovedNode.ts: -------------------------------------------------------------------------------- 1 | // 2 | // DomainServerRemovedNode.ts 3 | // 4 | // Created by David Rowe on 20 Aug 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import UDT from "../udt/UDT"; 13 | import assert from "../../shared/assert"; 14 | import Uuid from "../../shared/Uuid"; 15 | 16 | import "../../shared/DataViewExtensions"; 17 | 18 | 19 | type DomainServerRemovedNodeDetails = { 20 | nodeUUID: Uuid 21 | }; 22 | 23 | 24 | const DomainServerRemovedNode = new class { 25 | // C++ N/A 26 | 27 | /*@devdoc 28 | * Information returned by {@link PacketScribe|reading} a {@link PacketType(1)|DomainServerRemovedNode} packet. 29 | * @typedef {object} PacketScribe.DomainServerRemovedNodeDetails 30 | * @property {Uuid} nodeUUID - The UUID of the assignment client node that has been removed. 31 | */ 32 | 33 | /*@devdoc 34 | * Reads a {@link PacketType(1)|DomainServerRemovedNode} packet. 35 | * @function PacketScribe.DomainServerRemovedNode.read 36 | * @param {DataView} data - The {@link Packets|DomainServerRemovedNode} message data to read. 37 | * @returns {PacketScribe.DomainServerRemovedNodeDetails} Information on the assignment client node removed. 38 | */ 39 | read(data: DataView): DomainServerRemovedNodeDetails { /* eslint-disable-line class-methods-use-this */ 40 | // C++ void NodeList::processDomainServerRemovedNode(QSharedPointer message) 41 | 42 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 43 | 44 | let dataPosition = 0; 45 | 46 | const nodeUUID = new Uuid(data.getBigUint128(dataPosition, UDT.BIG_ENDIAN)); 47 | dataPosition += 16; 48 | 49 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 50 | 51 | assert(dataPosition === data.byteLength, "ERROR: Length mismatch reading DomainServerRemovedNode message!"); 52 | 53 | return { 54 | nodeUUID 55 | }; 56 | } 57 | 58 | }(); 59 | 60 | export default DomainServerRemovedNode; 61 | export type { DomainServerRemovedNodeDetails }; 62 | -------------------------------------------------------------------------------- /src/domain/networking/packets/KillAvatar.ts: -------------------------------------------------------------------------------- 1 | // 2 | // KillAvatar.ts 3 | // 4 | // Created by David Rowe on 3 Nov 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import UDT from "../udt/UDT"; 13 | import assert from "../../shared/assert"; 14 | import Uuid from "../../shared/Uuid"; 15 | import { KillAvatarReason } from "../../avatars/AvatarData"; 16 | import "../../shared/DataViewExtensions"; 17 | 18 | 19 | type KillAvatarDetails = { 20 | sessionUUID: Uuid, 21 | reason: KillAvatarReason 22 | }; 23 | 24 | 25 | const KillAvatar = new class { 26 | // C++ N/A 27 | 28 | /*@devdoc 29 | * Information returned by {@link PacketScribe|reading} a {@link PacketType(1)|KillAvatar} packet. 30 | * @typedef {object} PacketScribe.KillAvatarDetails 31 | * @property {Uuid} sessionUUID - The session UUID that was assigned to the avatar by the domain server. 32 | * @property {KillAvatarReason} reason - The reason the avatar was killed. 33 | */ 34 | 35 | 36 | /*@devdoc 37 | * Reads a {@link PacketType(1)|KillAvatar} packet. 38 | * @function PacketScribe.KillAvatar.read 39 | * @param {DataView} data - The {@link Packets|KillAvatar} message data to read. 40 | * @returns {PacketScribe.KillAvatarDetails} The KillAvatar details. 41 | */ 42 | read(data: DataView): KillAvatarDetails { /* eslint-disable-line class-methods-use-this */ 43 | // C++ void NodeList::processKillAvatarPacket(ReceivedMessage* message, Node* sendingNode) 44 | 45 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 46 | 47 | let dataPosition = 0; 48 | 49 | const sessionUUID = new Uuid(data.getBigUint128(dataPosition, UDT.BIG_ENDIAN)); 50 | dataPosition += 16; 51 | const reason = data.getUint8(dataPosition); 52 | dataPosition += 1; 53 | 54 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 55 | 56 | assert(dataPosition === data.byteLength, "ERROR: Length mismatch reading KillAvatar packet!"); 57 | 58 | return { 59 | sessionUUID, 60 | reason 61 | }; 62 | } 63 | 64 | }(); 65 | 66 | export default KillAvatar; 67 | export type { KillAvatarDetails }; 68 | -------------------------------------------------------------------------------- /src/domain/networking/packets/MessagesSubscribe.ts: -------------------------------------------------------------------------------- 1 | // 2 | // MessagesSubscribe.ts 3 | // 4 | // Created by David Rowe on 4 Oct 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import PacketType from "../udt/PacketHeaders"; 13 | import NLPacketList from "../NLPacketList"; 14 | 15 | 16 | type MessagesSubscribeDetails = { 17 | channel: string 18 | }; 19 | 20 | 21 | const MessagesSubscribe = new class { 22 | // C++ N/A 23 | 24 | /*@devdoc 25 | * Information needed for {@link PacketScribe|writing} a {@link PacketType(1)|MessagesSubscribe} packet list. 26 | * @typedef {object} PacketScribe.MessagesSubscribeDetails 27 | * @property {string} channel - The message channel to subscribe to. 28 | */ 29 | 30 | /*@devdoc 31 | * Writes a {@link PacketType(1)|MessagesSubscribe} packet list, ready for sending. 32 | * @function PacketScribe.MessagesSubscribe.write 33 | * @param {PacketScribe.MessagesSubscribeDetails} info - The information needed for writing the packet list. 34 | * @returns {NLPacketList} The packet list, ready for sending. 35 | */ 36 | write(info: MessagesSubscribeDetails): NLPacketList { /* eslint-disable-line class-methods-use-this */ 37 | // C++ void MessagesClient::subscribe(QString channel) 38 | 39 | const packetList = NLPacketList.create(PacketType.MessagesSubscribe, null, true, true); 40 | 41 | const textEncoder = new TextEncoder(); 42 | packetList.write(textEncoder.encode(info.channel)); 43 | 44 | return packetList; 45 | } 46 | 47 | }(); 48 | 49 | export default MessagesSubscribe; 50 | export type { MessagesSubscribeDetails }; 51 | -------------------------------------------------------------------------------- /src/domain/networking/packets/MessagesUnsubscribe.ts: -------------------------------------------------------------------------------- 1 | // 2 | // MessagesUnsubscribe.ts 3 | // 4 | // Created by David Rowe on 4 Oct 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import PacketType from "../udt/PacketHeaders"; 13 | import NLPacketList from "../NLPacketList"; 14 | 15 | 16 | type MessagesUnsubscribeDetails = { 17 | channel: string 18 | }; 19 | 20 | 21 | const MessagesUnsubscribe = new class { 22 | // C++ N/A 23 | 24 | /*@devdoc 25 | * Information needed for {@link PacketScribe|writing} a {@link PacketType(1)|MessagesUnsubscribe} packet list. 26 | * @typedef {object} PacketScribe.MessagesUnsubscribeDetails 27 | * @property {string} channel - The message channel to unsubscribe from. 28 | */ 29 | 30 | /*@devdoc 31 | * Writes a {@link PacketType(1)|MessagesUnsubscribe} packet list, ready for sending. 32 | * @function PacketScribe.MessagesUnsubscribe.write 33 | * @param {PacketScribe.MessagesUnsubscribeDetails} info - The information needed for writing the packet list. 34 | * @returns {NLPacketList} The packet list, ready for sending. 35 | */ 36 | write(info: MessagesUnsubscribeDetails): NLPacketList { /* eslint-disable-line class-methods-use-this */ 37 | // C++ void MessagesClient::unsubscribe(QString channel) 38 | 39 | const packetList = NLPacketList.create(PacketType.MessagesUnsubscribe, null, true, true); 40 | 41 | const textEncoder = new TextEncoder(); 42 | packetList.write(textEncoder.encode(info.channel)); 43 | 44 | return packetList; 45 | } 46 | 47 | }(); 48 | 49 | export default MessagesUnsubscribe; 50 | export type { MessagesUnsubscribeDetails }; 51 | -------------------------------------------------------------------------------- /src/domain/networking/packets/NodeKickRequest.ts: -------------------------------------------------------------------------------- 1 | // 2 | // NodeKickRequest.ts 3 | // 4 | // Created by David Rowe on 22 Jan 2023. 5 | // Copyright 2023 Vircadia contributors. 6 | // Copyright 2023 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | 13 | import { BanFlagsValue } from "../../shared/ModerationFlags"; 14 | import Uuid from "../../shared/Uuid"; 15 | import PacketType from "../udt/PacketHeaders"; 16 | import UDT from "../udt/UDT"; 17 | import NLPacket from "../NLPacket"; 18 | 19 | 20 | type NodeKickRequestDetails = { 21 | nodeID: Uuid, 22 | banFlags: BanFlagsValue 23 | }; 24 | 25 | 26 | const NodeKickRequest = new class { 27 | 28 | /*@devdoc 29 | * Information needed for {@link PacketScribe|writing} a {@link PacketType(1)|NodeKickRequest} packet. 30 | * @typedef {object} PacketScribe.NodeKickRequestDetails 31 | * @property {Uuid} nodeID - The avatar's session ID. 32 | * @property {ModerationFlags.BanFlagsValue} banFlags - The methods of kicking (banning). 33 | */ 34 | 35 | 36 | /*@devdoc 37 | * Writes a {@link PacketType(1)|NodeKickRequest} packet, ready for sending. 38 | * @function PacketScribe.NodeKickRequest.write 39 | * @param {PacketScribe.NodeKickRequestDetails} info - The information needed for writing the packet. 40 | * @returns {NLPacket} The packet, ready for sending. 41 | */ 42 | write(info: NodeKickRequestDetails): NLPacket { /* eslint-disable-line class-methods-use-this */ 43 | // C++ void NodeList::muteNodeBySessionID(const QUuid& nodeID) 44 | 45 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 46 | 47 | const packet = NLPacket.create(PacketType.NodeKickRequest, Uuid.NUM_BYTES_RFC4122_UUID + 4, true); 48 | const messageData = packet.getMessageData(); 49 | const data = messageData.data; 50 | let dataPosition = messageData.dataPosition; 51 | 52 | data.setBigUint128(dataPosition, info.nodeID.value(), UDT.BIG_ENDIAN); 53 | dataPosition += 16; 54 | 55 | data.setUint32(dataPosition, info.banFlags, UDT.LITTLE_ENDIAN); 56 | dataPosition += 4; 57 | 58 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 59 | 60 | messageData.dataPosition = dataPosition; 61 | messageData.packetSize = dataPosition; 62 | 63 | return packet; 64 | } 65 | 66 | }(); 67 | 68 | export default NodeKickRequest; 69 | export type { NodeKickRequestDetails }; 70 | -------------------------------------------------------------------------------- /src/domain/networking/packets/NodeMuteRequest.ts: -------------------------------------------------------------------------------- 1 | // 2 | // NodeMuteRequest.ts 3 | // 4 | // Created by David Rowe on 21 Jan 2023. 5 | // Copyright 2023 Vircadia contributors. 6 | // Copyright 2023 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | 13 | import Uuid from "../../shared/Uuid"; 14 | import PacketType from "../udt/PacketHeaders"; 15 | import UDT from "../udt/UDT"; 16 | import NLPacket from "../NLPacket"; 17 | 18 | 19 | type NodeMuteRequestDetails = { 20 | nodeID: Uuid 21 | }; 22 | 23 | 24 | const NodeMuteRequest = new class { 25 | 26 | /*@devdoc 27 | * Information needed for {@link PacketScribe|writing} a {@link PacketType(1)|NodeMuteRequest} packet. 28 | * @typedef {object} PacketScribe.NodeMuteRequestDetails 29 | * @property {Uuid} nodeID - The avatar's session ID. 30 | */ 31 | 32 | 33 | /*@devdoc 34 | * Writes a {@link PacketType(1)|NodeMuteRequest} packet, ready for sending. 35 | * @function PacketScribe.NodeMuteRequest.write 36 | * @param {PacketScribe.NodeMuteRequestDetails} info - The information needed for writing the packet. 37 | * @returns {NLPacket} The packet, ready for sending. 38 | */ 39 | write(info: NodeMuteRequestDetails): NLPacket { /* eslint-disable-line class-methods-use-this */ 40 | // C++ void NodeList::muteNodeBySessionID(const QUuid& nodeID) 41 | 42 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 43 | 44 | const packet = NLPacket.create(PacketType.NodeMuteRequest, Uuid.NUM_BYTES_RFC4122_UUID, true); 45 | const messageData = packet.getMessageData(); 46 | const data = messageData.data; 47 | let dataPosition = messageData.dataPosition; 48 | 49 | data.setBigUint128(dataPosition, info.nodeID.value(), UDT.BIG_ENDIAN); 50 | dataPosition += 16; 51 | 52 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 53 | 54 | messageData.dataPosition = dataPosition; 55 | messageData.packetSize = dataPosition; 56 | 57 | return packet; 58 | } 59 | 60 | }(); 61 | 62 | export default NodeMuteRequest; 63 | export type { NodeMuteRequestDetails }; 64 | -------------------------------------------------------------------------------- /src/domain/networking/packets/PerAvatarGainSet.ts: -------------------------------------------------------------------------------- 1 | // 2 | // PerAvatarGainSet.ts 3 | // 4 | // Created by David Rowe on 26 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | 13 | import AudioHelpers from "../../shared/AudioHelpers"; 14 | import Uuid from "../../shared/Uuid"; 15 | import PacketType from "../udt/PacketHeaders"; 16 | import UDT from "../udt/UDT"; 17 | import NLPacket from "../NLPacket"; 18 | 19 | 20 | type PerAvatarGainSetDetails = { 21 | nodeID: Uuid, 22 | gain: number 23 | }; 24 | 25 | 26 | const PerAvatarGainSet = new class { 27 | 28 | /*@devdoc 29 | * Information needed for {@link PacketScribe|writing} a {@link PacketType(1)|PerAvatarGainSet} packet. 30 | * @typedef {object} PacketScribe.PerAvatarGainSetDetails 31 | * @property {Uuid} nodeID - The avatar's session ID, or Uuid.NULL to set the master avatar gain. 32 | * @property {number} gain - The gain to set, in dB. 33 | */ 34 | 35 | 36 | /*@devdoc 37 | * Writes a {@link PacketType(1)|PerAvatarGainSet} packet, ready for sending. 38 | * @function PacketScribe.PerAvatarGainSet.write 39 | * @param {PacketScribe.PerAvatarGainSetDetails} info - The information needed for writing the packet. 40 | * @returns {NLPacket} The packet, ready for sending. 41 | */ 42 | write(info: PerAvatarGainSetDetails): NLPacket { /* eslint-disable-line class-methods-use-this */ 43 | // C++ void NodeList::setAvatarGain(const QUuid& nodeID, float gain) 44 | 45 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 46 | 47 | const packet = NLPacket.create(PacketType.PerAvatarGainSet, Uuid.NUM_BYTES_RFC4122_UUID + 4, true); 48 | const messageData = packet.getMessageData(); 49 | const data = messageData.data; 50 | let dataPosition = messageData.dataPosition; 51 | 52 | data.setBigUint128(dataPosition, info.nodeID.value(), UDT.BIG_ENDIAN); 53 | dataPosition += 16; 54 | 55 | data.setUint8(dataPosition, AudioHelpers.packFloatGainToByte(2 ** (info.gain / 6.02059991))); 56 | dataPosition += 1; 57 | 58 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 59 | 60 | messageData.dataPosition = dataPosition; 61 | messageData.packetSize = dataPosition; 62 | 63 | return packet; 64 | } 65 | 66 | }(); 67 | 68 | export default PerAvatarGainSet; 69 | export type { PerAvatarGainSetDetails }; 70 | -------------------------------------------------------------------------------- /src/domain/networking/packets/Ping.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Ping.ts 3 | // 4 | // Created by David Rowe on 6 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import UDT from "../udt/UDT"; 13 | import assert from "../../shared/assert"; 14 | 15 | 16 | type PingDetails = { 17 | pingType: number, 18 | timestamp: bigint, 19 | connectionID: bigint 20 | }; 21 | 22 | 23 | const Ping = new class { 24 | // C++ N/A 25 | 26 | /*@devdoc 27 | * Information returned by {@link PacketScribe|reading} a {@link PacketType(1)|Ping} packet. 28 | * @typedef {object} PacketScribe.PingDetails 29 | * @property {PingType} pingType - The type of ping. 30 | * @property {bigint} timestamp - The time at which the ping packet was created, in usec. 31 | * @property {bigint} connectionID - The ID of the connection that the ping was sent on. 32 | */ 33 | 34 | 35 | /*@devdoc 36 | * Reads a {@link PacketType(1)|Ping} packet. 37 | * @function PacketScribe.Ping.read 38 | * @param {DataView} data - The {@link Packets|Ping} message data to read. 39 | * @returns {PacketScribe.PingDetails} The ping details. 40 | */ 41 | read(data: DataView): PingDetails { /* eslint-disable-line class-methods-use-this */ 42 | // C++ void NodeList::processPingPacket(ReceivedMessage* message, Node* sendingNode) 43 | 44 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 45 | 46 | let dataPosition = 0; 47 | 48 | const pingType = data.getUint8(dataPosition); 49 | dataPosition += 1; 50 | const timestamp = data.getBigUint64(dataPosition, UDT.LITTLE_ENDIAN); 51 | dataPosition += 8; 52 | const connectionID = data.getBigUint64(dataPosition, UDT.LITTLE_ENDIAN); 53 | dataPosition += 8; 54 | 55 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 56 | 57 | assert(dataPosition === data.byteLength, "ERROR: Length mismatch reading Ping packet!"); 58 | 59 | return { 60 | pingType, 61 | timestamp, 62 | connectionID 63 | }; 64 | } 65 | 66 | }(); 67 | 68 | export default Ping; 69 | export type { PingDetails }; 70 | -------------------------------------------------------------------------------- /src/domain/networking/packets/PingReply.ts: -------------------------------------------------------------------------------- 1 | // 2 | // PingReply.ts 3 | // 4 | // Created by David Rowe on 7 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import PacketType from "../udt/PacketHeaders"; 13 | import UDT from "../udt/UDT"; 14 | import NLPacket from "../NLPacket"; 15 | 16 | 17 | type PingReplyDetails = { 18 | pingType: number, 19 | timestampPing: bigint, 20 | timestampReply: bigint 21 | }; 22 | 23 | 24 | const PingReply = new class { 25 | // C++ N/A 26 | 27 | /*@devdoc 28 | * Information needed for {@link PacketScribe|writing} a {@link PacketType(1)|PingReply} packet. 29 | * @typedef {object} PacketScribe.PingReplyDetails 30 | * @property {PingType} pingType - The type of ping. 31 | * @property {bigint} timestampPing - The time at which the originating ping packet was created, in usec. 32 | * @property {bigint} timestampReply - The time at which the ping reply packet was created, in usec. 33 | */ 34 | 35 | 36 | /*@devdoc 37 | * Writes a {@link PacketType(1)|PingReply} packet, ready for sending. 38 | * @function PacketScribe.PingReply.write 39 | * @param {PacketScribe.PingReplyDetails} info - The information needed for writing the packet. 40 | * @returns {NLPacket} The packet, ready for sending. 41 | */ 42 | write(info: PingReplyDetails): NLPacket { /* eslint-disable-line class-methods-use-this */ 43 | // C++ NLPacket* LimitedNodeList::constructPingReplyPacket(ReceivedMessage& message) 44 | 45 | const packet = NLPacket.create(PacketType.PingReply); 46 | const messageData = packet.getMessageData(); 47 | const data = messageData.data; 48 | let dataPosition = messageData.dataPosition; 49 | 50 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 51 | 52 | data.setUint8(dataPosition, info.pingType); 53 | dataPosition += 1; 54 | data.setBigUint64(dataPosition, info.timestampPing, UDT.BIG_ENDIAN); 55 | dataPosition += 8; 56 | data.setBigUint64(dataPosition, info.timestampReply, UDT.BIG_ENDIAN); 57 | dataPosition += 8; 58 | 59 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 60 | 61 | messageData.dataPosition = dataPosition; 62 | messageData.packetSize = dataPosition; 63 | 64 | return packet; 65 | } 66 | 67 | }(); 68 | 69 | export default PingReply; 70 | export type { PingReplyDetails }; 71 | -------------------------------------------------------------------------------- /src/domain/networking/packets/RequestsDomainListData.ts: -------------------------------------------------------------------------------- 1 | // 2 | // RequestsDomainListData.ts 3 | // 4 | // Created by David Rowe on 28 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import PacketType from "../udt/PacketHeaders"; 13 | import NLPacket from "../NLPacket"; 14 | 15 | type RequestsDomainListDataDetails = { 16 | isRequesting: boolean 17 | }; 18 | 19 | 20 | const RequestsDomainListData = new class { 21 | 22 | /*@devdoc 23 | * Information needed for {@link PacketScribe|writing} a {@link PacketType(1)|RequestsDomainListData} packet. 24 | * @typedef {object} PacketScribe.RequestsDomainListDataDetails 25 | * @property {boolean} isRequesting - true to tell the audio and avatar mixers to continue sending data from 26 | * ignored avatars or avatars that have ignored the client, false to tell them to stop sending. 27 | *

Note: The audio mixer only continues to send audio from ignored or ignoring avatars if the client is an admin in 28 | * the domain (can kick avatars).

29 | */ 30 | 31 | 32 | /*@devdoc 33 | * Writes a {@link PacketType(1)|RequestsDomainListData} packet, ready for sending. 34 | * @function PacketScribe.RequestsDomainListData.write 35 | * @param {PacketScribe.RequestsDomainListDataDetails} info - The information needed for writing the packet. 36 | * @returns {NLPacket} The packet, ready for sending. 37 | */ 38 | write(info: RequestsDomainListDataDetails): NLPacket { /* eslint-disable-line class-methods-use-this */ 39 | // C++ void NodeList::setRequestsDomainListData(bool isRequesting) 40 | 41 | const packet = NLPacket.create(PacketType.RequestsDomainListData, 1, true); 42 | const messageData = packet.getMessageData(); 43 | const data = messageData.data; 44 | let dataPosition = messageData.dataPosition; 45 | 46 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 47 | 48 | data.setUint8(dataPosition, info.isRequesting ? 1 : 0); 49 | dataPosition += 1; 50 | 51 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 52 | 53 | messageData.dataPosition = dataPosition; 54 | messageData.packetSize = dataPosition; 55 | 56 | return packet; 57 | } 58 | 59 | }(); 60 | 61 | export default RequestsDomainListData; 62 | export type { RequestsDomainListDataDetails }; 63 | -------------------------------------------------------------------------------- /src/domain/networking/packets/SelectedAudioFormat.ts: -------------------------------------------------------------------------------- 1 | // 2 | // SelectedAudioFormat.ts 3 | // 4 | // Created by David Rowe on 10 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import UDT from "../udt/UDT"; 13 | import assert from "../../shared/assert"; 14 | 15 | 16 | type SelectedAudioFormatDetails = { 17 | selectedCodecName: string 18 | }; 19 | 20 | 21 | const SelectedAudioFormat = new class { 22 | // C++ N/A 23 | 24 | /*@devdoc 25 | * Information returned by {@link PacketScribe|reading} a {@link PacketType(1)|SelectedAudioFormat} packet. 26 | * @typedef {object} PacketScribe.SelectedAudioFormatDetails 27 | * @property {string} selectedCodecName - The name of the audio codec selected for use. 28 | */ 29 | 30 | 31 | /*@devdoc 32 | * Reads a {@link PacketType(1)|SelectedAudioFormat} packet. 33 | * @function PacketScribe.SelectedAudioFormat.read 34 | * @param {DataView} data - The {@link Packets|SelectedAudioFormat} message data to read. 35 | * @returns {PacketScribe.SelectedAudioFormatDetails} The audio codec selected for use. 36 | */ 37 | read(data: DataView): SelectedAudioFormatDetails { /* eslint-disable-line class-methods-use-this */ 38 | // C++ void AudioClient::handleSelectedAudioFormat(ReceivedMessage* message) 39 | 40 | const textDecoder = new TextDecoder(); 41 | 42 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 43 | 44 | let dataPosition = 0; 45 | 46 | const selectedCodecNameSize = data.getUint32(dataPosition, UDT.LITTLE_ENDIAN); 47 | dataPosition += 4; 48 | const selectedCodecName = textDecoder.decode(new Uint8Array(data.buffer, data.byteOffset + dataPosition, 49 | selectedCodecNameSize)); 50 | dataPosition += selectedCodecNameSize; 51 | 52 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 53 | 54 | assert(dataPosition === data.byteLength, "ERROR: Length mismatch reading SelectedAudioFormat packet!"); 55 | 56 | return { 57 | selectedCodecName 58 | }; 59 | } 60 | 61 | }(); 62 | 63 | export default SelectedAudioFormat; 64 | export type { SelectedAudioFormatDetails }; 65 | -------------------------------------------------------------------------------- /src/domain/networking/udt/CongestionControl.ts: -------------------------------------------------------------------------------- 1 | // 2 | // CongestionControl.ts 3 | // 4 | // Created by David Rowe on 4 Oct 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | 13 | /*@devdoc 14 | * The CongestionControl class helps control network congestion. 15 | *

C++: CongestionControl 16 | * @class CongestionControl 17 | */ 18 | class CongestionControl { 19 | // C++ CongestionControl 20 | // In the C++, this is a base class which TCPVegaCC derives. 21 | // In the SDK, there is no congestion control at present. 22 | 23 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 24 | 25 | #_packetSendPeriod = 1n; // Packet sending period, in microseconds. 26 | #_congestionWindowSize = 16; // Congestion window size, in packets. 27 | 28 | #_estimatedTimeout = 0n; // Estimated timeout, in microseconds. 29 | 30 | // WEBRTC TODO: Address further C++ code. 31 | 32 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 33 | 34 | 35 | /*@devdoc 36 | * Initializes congestion control. 37 | */ 38 | init(): void { // eslint-disable-line class-methods-use-this 39 | // C++ void init() 40 | // No-op; 41 | } 42 | 43 | /*@devdoc 44 | * Gets the packet send period. 45 | * @returns {bigint} The packet send period, in microseconds. 46 | */ 47 | packetSendPeriod(): bigint { 48 | // C++ double _packetSendPeriod 49 | return this.#_packetSendPeriod; 50 | } 51 | 52 | /*@devdoc 53 | * Gets the congestion window size, i.e., the number of packets that should be permitted to be in-flight without ACKs. 54 | * @returns {number} The congestion window size, in packets. 55 | */ 56 | congestionWindowSize(): number { 57 | // C++ int _congestionWindowSize 58 | return this.#_congestionWindowSize; 59 | } 60 | 61 | /*@devdoc 62 | * Gets the estimated timeout. 63 | * @returns {number} The estimated timeout, in microseconds. 64 | */ 65 | estimatedTimeout(): bigint { 66 | // C++ int estimatedTimeout() 67 | return this.#_estimatedTimeout; 68 | } 69 | 70 | } 71 | 72 | export default CongestionControl; 73 | -------------------------------------------------------------------------------- /src/domain/octree/OctreeConstants.ts: -------------------------------------------------------------------------------- 1 | // 2 | // OctreeConstants.ts 3 | // 4 | // Created by Julien Merzoug on 5 May 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | 13 | /*@devdoc 14 | * The OctreeConstants namespace provides constants for working with octrees. 15 | * @namespace OctreeConstants 16 | * 17 | * @property {number} DEFAULT_MAX_OCTREE_PPS=600 - The default maximum number of octree packets per second value. 18 | * Read-only. 19 | * @property {number} TREE_SCALE=32768 - The number of meters in the 0.0 to voxel universe. 20 | * Read-only. 21 | * @property {number} DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT=400 - The maximum distance where a 1x1x1 cube is visible for 22 | * 20:20 vision. 23 | * Read-only. 24 | * @property {number} DEFAULT_OCTREE_SIZE_SCALE=13107200 - The product of TREE_SCALE and 25 | * DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT. 26 | * Read-only. 27 | */ 28 | const OctreeConstants = new class { 29 | // C++ OctreeConstants 30 | 31 | /* eslint-disable class-methods-use-this */ 32 | 33 | get DEFAULT_MAX_OCTREE_PPS(): number { 34 | // eslint-disable-next-line @typescript-eslint/no-magic-numbers 35 | return 600; 36 | } 37 | 38 | get TREE_SCALE(): number { 39 | // eslint-disable-next-line @typescript-eslint/no-magic-numbers 40 | return 32768; // ~20 miles. 41 | } 42 | 43 | 44 | get DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT(): number { 45 | // eslint-disable-next-line @typescript-eslint/no-magic-numbers 46 | return 400.0; 47 | } 48 | 49 | 50 | get DEFAULT_OCTREE_SIZE_SCALE(): number { 51 | return this.TREE_SCALE * this.DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT; 52 | } 53 | 54 | 55 | /* eslint-enable class-methods-use-this */ 56 | 57 | }(); 58 | 59 | export default OctreeConstants; 60 | -------------------------------------------------------------------------------- /src/domain/shared/AACube.ts: -------------------------------------------------------------------------------- 1 | // 2 | // AACube.ts 3 | // 4 | // Created by Julien Merzoug on 28 Jun 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import { vec3 } from "../shared/Vec3"; 13 | 14 | 15 | /*@devdoc 16 | * The AACube class provides an axis-aligned cube, defined as the minimum axes values corner of the cube plus the 17 | * dimension of its sides. 18 | *

C++: class AACube

19 | * @class AACube 20 | * @param {vec3} corner - The coordinate vector of the bottom right near corner of the cube. 21 | * @param {number} scale - The dimensions of each side of the cube. 22 | * 23 | * @property {vec3} corner - The coordinate vector of the bottom right near corner of the cube. 24 | * @property {number} scale - The dimensions of each side of the cube. 25 | * 26 | */ 27 | class AACube { 28 | // C++ class AACube 29 | 30 | #_corner: vec3; 31 | #_scale: number; 32 | 33 | constructor(corner: vec3, scale: number) { 34 | this.#_corner = corner; 35 | this.#_scale = scale; 36 | } 37 | 38 | get corner(): vec3 { 39 | return this.#_corner; 40 | } 41 | 42 | get scale(): number { 43 | return this.#_scale; 44 | } 45 | } 46 | 47 | export default AACube; 48 | -------------------------------------------------------------------------------- /src/domain/shared/AudioHelpers.ts: -------------------------------------------------------------------------------- 1 | // 2 | // AudioHelpers.ts 3 | // 4 | // Created by David Rowe on 24 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 13 | 14 | // Quantize a non-negative gain value to the nearest 0.5dB, and pack to a byte. 15 | // - Values above +30dB are clamped to +30dB 16 | // - Values below -97dB are clamped to -inf 17 | // - Value of 1.0 (+0dB) is reconstructed exactly 18 | const GAIN_CONVERSION_RATIO = 2.0 * 6.02059991; // scale log2 to 0.5dB. 19 | const GAIN_CONVERSION_OFFSET = 255.0 - 60.0; // Translate +30dB to max. 20 | 21 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 22 | 23 | 24 | /*@devdoc 25 | * The AudioHelpers namespace provides helpers for working with audio data. 26 | *

C++: AudioHelpers.h

27 | * 28 | * @namespace AudioHelpers 29 | */ 30 | class AudioHelpers { 31 | // C++ AudioHelpers.h 32 | 33 | /*@devdoc 34 | * Packs an audio gain value into a single byte. 35 | * @param {number} gain - The gain value. 36 | * @returns {number} The single byte representation of the gain value. 37 | */ 38 | static packFloatGainToByte(gain: number): number { 39 | // C++ uint8_t packFloatGainToByte(float gain) 40 | 41 | // WEBRTC TODO: Consider implementing fastLog2() and using instead of Math methods. 42 | const f = Math.log2(gain) * GAIN_CONVERSION_RATIO + GAIN_CONVERSION_OFFSET; 43 | const i = Math.round(f); // Quantize. 44 | 45 | // eslint-disable-next-line @typescript-eslint/no-magic-numbers 46 | const byte = Math.max(0, Math.min(i, 255)); // Clamp. 47 | return byte; 48 | } 49 | 50 | 51 | /*@devdoc 52 | * Unpacks an audio gain from a single byte. 53 | * @param {number} byte - The single byte representation of the gain value. 54 | * @returns {number} The gain value. 55 | */ 56 | static unpackFloatGainFromByte(byte: number): number { 57 | // C++ float unpackFloatGainFromByte(uint8_t byte) 58 | 59 | const gain = byte === 0 60 | ? 0.0 61 | : 2.0 ** ((byte - GAIN_CONVERSION_OFFSET) / GAIN_CONVERSION_RATIO); 62 | return gain; 63 | } 64 | 65 | } 66 | 67 | export default AudioHelpers; 68 | -------------------------------------------------------------------------------- /src/domain/shared/AvatarConstants.ts: -------------------------------------------------------------------------------- 1 | // 2 | // AvatarConstants.ts 3 | // 4 | // Created by David Rowe on 9 Jun 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /*@devdoc 13 | * The AvatarConstants class defines avatar constants. 14 | *

C++: AvatarConstants.h

15 | * @class AvatarConstants 16 | * 17 | * @property {number} DEFAULT_AVATAR_HEIGHT=1.755 - The default avatar height, in meters. 18 | * @property {number} DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD=0.11 - The default vertical distance between the avatar's eyes to the 19 | * top of head, in meters. 20 | * @property {number} DEFAULT_AVATAR_EYE_HEIGHT= 1.645 - The default height of the avatar's eyes. 21 | * @property {number} MAX_AVATAR_HEIGHT= 1755.0 - The absolute maximum avatar height. 22 | * @property {number} MIN_AVATAR_HEIGHT=0.008775 - The absolute minimum avatar height. 23 | * 24 | * @property {number} MAX_AVATAR_SCALE=1000.0 - The maximum avatar scale factor that may be applied to an avatar. 25 | * @property {number} MIN_AVATAR_SCALE=0.005 - The minimum avatar scale factor that may be applied to an avatar. 26 | */ 27 | class AvatarConstants { 28 | // C++ AvatarConstants.h 29 | 30 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 31 | 32 | static readonly DEFAULT_AVATAR_HEIGHT = 1.755; // meters 33 | static readonly DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD = 0.11; // meters 34 | 35 | static readonly DEFAULT_AVATAR_EYE_HEIGHT = AvatarConstants.DEFAULT_AVATAR_HEIGHT 36 | - AvatarConstants.DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD; 37 | 38 | static readonly MAX_AVATAR_HEIGHT = 1000.0 * AvatarConstants.DEFAULT_AVATAR_HEIGHT; 39 | static readonly MIN_AVATAR_HEIGHT = 0.005 * AvatarConstants.DEFAULT_AVATAR_HEIGHT; 40 | 41 | static readonly MAX_AVATAR_SCALE = 1000.0; 42 | static readonly MIN_AVATAR_SCALE = 0.005; 43 | 44 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 45 | } 46 | 47 | export default AvatarConstants; 48 | -------------------------------------------------------------------------------- /src/domain/shared/AvatarPriorityMode.ts: -------------------------------------------------------------------------------- 1 | // 2 | // AvatarPriorityMode.ts 3 | // 4 | // Created by David Rowe on 13 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /*@sdkdoc 13 | * The AvatarPriorityMode namespace enumerates how the priority of updates from avatars other clients is applied 14 | * in a {@link EntityType|Zone entity}. 15 | * @namespace AvatarPriorityMode 16 | * @property {number} INHERIT - 0 - The update priority from any enclosing zone continues into this zone. 17 | * @property {number} CROWD - 1 - The update priority in this zone is the normal priority. 18 | * @property {number} HERO - 2 - Avatars in this zone have an increased update priority. 19 | * @property {number} ITEM_COUNT - 3 - The number of modes. 20 | */ 21 | enum AvatarPriorityMode { 22 | // C++ enum AvatarPriorityMode 23 | INHERIT, 24 | CROWD, 25 | HERO, 26 | ITEM_COUNT 27 | } 28 | 29 | export default AvatarPriorityMode; 30 | -------------------------------------------------------------------------------- /src/domain/shared/Color.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Color.ts 3 | // 4 | // Created by Julien Merzoug on 11 Jul 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | 13 | // The JSDoc is in ShapeEntityItem.ts. The code in this file is entirely removed during the conversion to JavaScript, leaving 14 | // no module to which the JSDoc can be attached. 15 | type color = { 16 | red: number; 17 | green: number; 18 | blue: number; 19 | }; 20 | 21 | // The JSDoc is in MaterialEntityItem.ts. The code in this file is entirely removed during the conversion to JavaScript, 22 | // leaving no module to which the JSDoc can be attached. 23 | type rgbs = number[]; 24 | 25 | export type { color, rgbs }; 26 | -------------------------------------------------------------------------------- /src/domain/shared/ComponentMode.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ComponentMode.ts 3 | // 4 | // Created by David Rowe on 13 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /*@sdkdoc 13 | * The ComponentMode namespace enumerates how an effect is applied in a {@link EntityType|Zone entity}. 14 | * @namespace ComponentMode 15 | * @property {number} INHERIT - 0 - The effect from any enclosing zone continues into this zone. 16 | * @property {number} DISABLED - 1 - The effect — from any enclosing zone and this zone — is disabled 17 | * in this zone. 18 | * @property {number} ENABLED - 2 - The effect from this zone is enabled, overriding the effect from any enclosing 19 | * zone. 20 | * @property {number} ITEM_COUNT - 3 - The number of modes. 21 | */ 22 | enum ComponentMode { 23 | // C++ enum ComponentMode 24 | INHERIT, 25 | DISABLED, 26 | ENABLED, 27 | 28 | ITEM_COUNT 29 | } 30 | 31 | export default ComponentMode; 32 | -------------------------------------------------------------------------------- /src/domain/shared/ConditionVariable.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ConditionVariable.ts 3 | // 4 | // Created by David Rowe on 6 Oct 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /*@devdoc 13 | * The ConditionVariable class provides a synchronization object that waits for a notification that a condition 14 | * has occurred, or times out. 15 | *

C++: std::condition_variable, std::condition_variable_any

16 | * @class ConditionVariable 17 | */ 18 | class ConditionVariable { 19 | // C++ std::condition_variable, std::condition_variable_any 20 | 21 | #_timeoutTimer: ReturnType | null = null; 22 | #_promise: Promise | null = null; 23 | #_resolve: ((value: boolean) => void) | null = null; 24 | 25 | 26 | /*@devdoc 27 | * Waits for notification that a condition has occurred, with a timeout. 28 | * @param {number} timeout - The timout, in milliseconds. 29 | * @returns {Promise} Resolves to true if notification was received, false if timed out. 30 | */ 31 | async waitFor(timeout: number): Promise { 32 | this.#_promise = new Promise((resolve) => { 33 | this.#_resolve = resolve; 34 | this.#_timeoutTimer = setTimeout(() => { 35 | if (this.#_resolve) { 36 | this.#_resolve(false); 37 | } 38 | this.#_resolve = null; 39 | this.#_timeoutTimer = null; 40 | }, timeout); 41 | }); 42 | return this.#_promise; 43 | } 44 | 45 | /*@devdoc 46 | * Makes a notification that the condition being waited for has occurred. 47 | */ 48 | notifyOne(): void { 49 | // C++ std::notify_one 50 | if (this.#_timeoutTimer) { 51 | clearTimeout(this.#_timeoutTimer); 52 | this.#_timeoutTimer = null; 53 | } 54 | if (this.#_resolve) { 55 | this.#_resolve(true); 56 | this.#_resolve = null; 57 | } 58 | } 59 | 60 | } 61 | 62 | export default ConditionVariable; 63 | -------------------------------------------------------------------------------- /src/domain/shared/HighResolutionClock.ts: -------------------------------------------------------------------------------- 1 | // 2 | // HighResolutionClock.ts 3 | // 4 | // Created by David Rowe on 5 Oct 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | 13 | /*@devdoc 14 | * The HighResolutionClock namespace provides a timestamp service. 15 | *

Note: In browser environments, the resolution may be limited to milliseconds.

16 | *

C++: p_high_resolution_clock 17 | * @namespace HighResolutionClock 18 | */ 19 | const HighResolutionClock = new class { 20 | // C++ p_high_resolution_clock 21 | 22 | // WEBRTC TODO: Get a higher resolution clock than Date.now(), possibly using the Performance API though this may still be 23 | // limited to millisecond resolution. 24 | 25 | // WEBRTC TODO: Regularize the use of timestamps throughout the SDK's networking code. 26 | // Note: Perhaps milliseconds should be used internally. 27 | 28 | /*@devdoc 29 | * Gets the current timestamps in microseconds. 30 | * @function HighResolutionClock.now 31 | * @returns {bigint} The current timestamps in microseconds. 32 | */ 33 | // eslint-disable-next-line class-methods-use-this 34 | now(): bigint { 35 | // C++ QUuid now() 36 | const MS_TO_US = 1000n; 37 | return BigInt(Date.now()) * MS_TO_US; 38 | } 39 | 40 | }(); 41 | 42 | export default HighResolutionClock; 43 | -------------------------------------------------------------------------------- /src/domain/shared/Mat4.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Mat4.ts 3 | // 4 | // Created by David Rowe on 11 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | // JSDoc is implemented in Vec3.ts so that it is compiled. 13 | type mat4 = { 14 | x: number, 15 | y: number, 16 | }; 17 | 18 | export type { mat4 }; 19 | -------------------------------------------------------------------------------- /src/domain/shared/Rect.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Rect.ts 3 | // 4 | // Created by David Rowe on 1 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | 13 | // The JSDoc is in ImageEntityItem.ts. The code in this file is entirely removed during the conversion to JavaScript, leaving no 14 | // module to which the JSDoc can be attached. 15 | type rect = { 16 | x: number; 17 | y: number; 18 | width: number; 19 | height: number; 20 | }; 21 | 22 | export type { rect }; 23 | -------------------------------------------------------------------------------- /src/domain/shared/ShapeType.ts: -------------------------------------------------------------------------------- 1 | // 2 | // ShapeType.ts 3 | // 4 | // Created by David Rowe on 12 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /*@sdkdoc 13 | * The ShapeType namespace enumerates types of shapes. 14 | * @namespace ShapeType 15 | * @property {number} NONE - 0 - No shape. 16 | * @property {number} BOX - 1 - A cube. 17 | * @property {number} SPHERE - 2 - A sphere. 18 | * @property {number} CAPSULE_X - 3 - A capsule (cylinder with spherical ends) oriented along the x-axis. 19 | * @property {number} CAPSULE_Y - 4 - A capsule (cylinder with spherical ends) oriented along the y-axis. 20 | * @property {number} CAPSULE_Z - 5 - A capsule (cylinder with spherical ends) oriented along the z-axis. 21 | * @property {number} CYLINDER_X - 6 - A cylinder oriented along the x-axis. 22 | * @property {number} CYLINDER_Y - 7 - A cylinder oriented along the y-axis. 23 | * @property {number} CYLINDER_Z - 8 - A cylinder oriented along the z-axis. 24 | * @property {number} HULL - 9 - Not used. 25 | * @property {number} PLANE - 10 - A plane. 26 | * @property {number} COMPOUND - 11 - A compound convex hull specified in an OBJ file. 27 | * @property {number} SIMPLE_HULL - 12 - A convex hull automatically generated from a model. 28 | * @property {number} SIMPLE_COMPOUND - 13 - A compound convex hull automatically generated from the model, using 29 | * sub-meshes. 30 | * @property {number} STATIC_MESH - 14 - The exact shape of the model. 31 | * @property {number} ELLIPSOID - 15 - An ellipsoid. 32 | * @property {number} CIRCLE - 16 - A circle. 33 | * @property {number} MULTISPHERE - 17 - A convex hull generated from a set of spheres. 34 | */ 35 | enum ShapeType { 36 | // C++ enum ShapeType 37 | NONE, 38 | BOX, 39 | SPHERE, 40 | CAPSULE_X, 41 | CAPSULE_Y, 42 | CAPSULE_Z, 43 | CYLINDER_X, 44 | CYLINDER_Y, 45 | CYLINDER_Z, 46 | HULL, 47 | PLANE, 48 | COMPOUND, 49 | SIMPLE_HULL, 50 | SIMPLE_COMPOUND, 51 | STATIC_MESH, 52 | ELLIPSOID, 53 | CIRCLE, 54 | MULTISPHERE 55 | } 56 | 57 | export default ShapeType; 58 | -------------------------------------------------------------------------------- /src/domain/shared/Vec2.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Vec2.ts 3 | // 4 | // Created by David Rowe on 11 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | // JSDoc is implemented in Vec3.ts so that it is compiled. 13 | type vec2 = { 14 | x: number, 15 | y: number, 16 | }; 17 | 18 | export type { vec2 }; 19 | -------------------------------------------------------------------------------- /src/domain/shared/assert.ts: -------------------------------------------------------------------------------- 1 | // 2 | // assert.ts 3 | // 4 | // Created by David Rowe on 9 Jun 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /*@devdoc 13 | * Reports and throws an error if an assertion is false. Information on the error is reported to the console along 14 | * with a call stack. 15 | * @function assert 16 | * @param {boolean} assertion - The assertion value. 17 | * @param {...any} info - Information to report to the console if the assertion is false. 18 | */ 19 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 20 | function assert(assertion: boolean, ...info: any[]): asserts assertion { 21 | // console.assert(assertion, ...info); 22 | if (!assertion) { 23 | throw new Error(["Assertion failed!", ...info as [string]].join(" ")); 24 | } 25 | } 26 | 27 | export default assert; 28 | -------------------------------------------------------------------------------- /tests/AvatarMixer.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // AvatarMixer.unit.test.js 3 | // 4 | // Created by David Rowe on 24 Aug 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AccountManagerMock from "../mocks/domain/networking/AccountManager.mock.js"; 13 | AccountManagerMock.mock(); 14 | import AudioWorkletsMock from "../mocks/domain/audio/AudioWorklets.mock.js"; 15 | AudioWorkletsMock.mock(); 16 | 17 | import { webcrypto } from "crypto"; 18 | globalThis.crypto = webcrypto; 19 | 20 | import AvatarMixer from "../src/AvatarMixer"; 21 | import Camera from "../src/Camera"; 22 | import DomainServer from "../src/DomainServer"; 23 | 24 | 25 | describe("AvatarMixer - unit tests", () => { 26 | 27 | test("Can create an AvatarMixer with a DomainServer", () => { 28 | const domainServer = new DomainServer(); 29 | const camera = new Camera(domainServer.contextID); // eslint-disable-line @typescript-eslint/no-unused-vars 30 | const avatarMixer = new AvatarMixer(domainServer.contextID); 31 | expect(avatarMixer instanceof AvatarMixer).toBe(true); 32 | 33 | expect(avatarMixer.state).toBe(AvatarMixer.UNAVAILABLE); 34 | }); 35 | 36 | }); 37 | -------------------------------------------------------------------------------- /tests/EntityServer.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // EntityServer.unit.test.js 3 | // 4 | // Created by Julien Merzoug on 26 Apr 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AccountManagerMock from "../mocks/domain/networking/AccountManager.mock.js"; 13 | AccountManagerMock.mock(); 14 | 15 | import { webcrypto } from "crypto"; 16 | globalThis.crypto = webcrypto; 17 | 18 | import Camera from "../src/Camera"; 19 | import DomainServer from "../src/DomainServer"; 20 | import EntityServer from "../src/EntityServer"; 21 | 22 | 23 | describe("EntityServer - unit tests", () => { 24 | 25 | test("Can create an EntityServer with a DomainServer", () => { 26 | const domainServer = new DomainServer(); 27 | const camera = new Camera(domainServer.contextID); // eslint-disable-line @typescript-eslint/no-unused-vars 28 | const entityServer = new EntityServer(domainServer.contextID); 29 | 30 | expect(entityServer instanceof EntityServer).toBe(true); 31 | }); 32 | 33 | }); 34 | -------------------------------------------------------------------------------- /tests/Vircadia.integration.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // Vircadia.integration.test.js 3 | // 4 | // Created by David Rowe on 11 Jul 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AudioWorkletsMock from "../mocks/domain/audio/AudioWorklets.mock.js"; 13 | AudioWorkletsMock.mock(); 14 | 15 | import { webcrypto } from "crypto"; 16 | globalThis.crypto = webcrypto; 17 | 18 | import { Vircadia, DomainServer, Camera, AudioMixer, AvatarMixer, EntityServer, MessageMixer } from "../src/Vircadia"; 19 | 20 | 21 | describe("Vircadia - integration tests", () => { 22 | 23 | test("Multiple API import", () => { 24 | expect(Vircadia).toBeDefined(); 25 | expect(DomainServer).toBeDefined(); 26 | expect(Camera).toBeDefined(); 27 | expect(AudioMixer).toBeDefined(); 28 | expect(AvatarMixer).toBeDefined(); 29 | expect(EntityServer).toBeDefined(); 30 | expect(MessageMixer).toBeDefined(); 31 | }); 32 | 33 | }); 34 | -------------------------------------------------------------------------------- /tests/Vircadia.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // Vircadia.unit.test.js 3 | // 4 | // Created by David Rowe on 11 Jul 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AudioWorkletsMock from "../mocks/domain/audio/AudioWorklets.mock.js"; 13 | AudioWorkletsMock.mock(); 14 | 15 | import { webcrypto } from "crypto"; 16 | globalThis.crypto = webcrypto; 17 | 18 | import Vircadia from "../src/Vircadia"; 19 | 20 | 21 | describe("Vircadia - unit tests", () => { 22 | 23 | test("Version number", () => { 24 | expect(typeof Vircadia.version).toBe("string"); 25 | expect(Vircadia.version.length).toBeGreaterThan(0); 26 | const version = Vircadia.version; 27 | try { 28 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 29 | // @ts-ignore 30 | Vircadia.version = "0.0.0"; // Shouldn't succeed. 31 | } catch (e) { 32 | // 33 | } 34 | expect(Vircadia.version).toBe(version); 35 | }); 36 | 37 | }); 38 | -------------------------------------------------------------------------------- /tests/domain/audio-client/AudioClient.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // AudioClient.unit.test.js 3 | // 4 | // Created by David Rowe on 15 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AudioWorkletsMock from "../../../mocks/domain/audio/AudioWorklets.mock.js"; 13 | AudioWorkletsMock.mock(); 14 | 15 | import { webcrypto } from "crypto"; 16 | globalThis.crypto = webcrypto; 17 | 18 | import AudioOutput from "../../../src/domain/audio/AudioOutput"; 19 | import AudioClient from "../../../src/domain/audio-client/AudioClient"; 20 | import AccountManager from "../../../src/domain/networking/AccountManager"; 21 | import AddressManager from "../../../src/domain/networking/AddressManager"; 22 | import NodeList from "../../../src/domain/networking/NodeList"; 23 | import ContextManager from "../../../src/domain/shared/ContextManager"; 24 | 25 | 26 | describe("AudioClient - unit tests", () => { 27 | 28 | const log = jest.spyOn(console, "log").mockImplementation(() => { /* no-op */ }); 29 | 30 | test("The AudioClient can be obtained from the ContextManager", () => { 31 | const contextID = ContextManager.createContext(); 32 | ContextManager.set(contextID, AccountManager, contextID); 33 | ContextManager.set(contextID, AddressManager); 34 | ContextManager.set(contextID, NodeList, contextID); 35 | ContextManager.set(contextID, AudioOutput); 36 | ContextManager.set(contextID, AudioClient, contextID); 37 | const audioClient = ContextManager.get(contextID, AudioClient); 38 | expect(audioClient instanceof AudioClient).toBe(true); 39 | }); 40 | 41 | test("Can access the \"mutedByClient\" signal", () => { 42 | const contextID = ContextManager.createContext(); 43 | ContextManager.set(contextID, AccountManager, contextID); 44 | ContextManager.set(contextID, AddressManager); 45 | ContextManager.set(contextID, NodeList, contextID); 46 | ContextManager.set(contextID, AudioOutput); 47 | ContextManager.set(contextID, AudioClient, contextID); 48 | const audioClient = ContextManager.get(contextID, AudioClient); 49 | // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access 50 | expect(typeof audioClient.mutedByMixer.connect).toBe("function"); 51 | }); 52 | 53 | log.mockReset(); 54 | }); 55 | -------------------------------------------------------------------------------- /tests/domain/audio/AudioConstants.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // AudioConstants.unit.test.js 3 | // 4 | // Created by David Rowe on 11 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AudioConstants from "../../../src/domain/audio/AudioConstants"; 13 | 14 | 15 | describe("AudioConstants - unit tests", () => { 16 | 17 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 18 | 19 | test("AudioConstants values can be accessed", () => { 20 | expect(AudioConstants.NETWORK_FRAME_SAMPLES_STEREO).toBe(480); 21 | expect(AudioConstants.NETWORK_FRAME_SAMPLES_PER_CHANNEL).toBe(240); 22 | }); 23 | 24 | }); 25 | -------------------------------------------------------------------------------- /tests/domain/audio/AudioInput.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // AudioInput.unit.test.js 3 | // 4 | // Created by David Rowe 24 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AudioWorkletsMock from "../../../mocks/domain/audio/AudioWorklets.mock.js"; 13 | AudioWorkletsMock.mock(); 14 | 15 | 16 | import AudioInput from "../../../src/domain/audio/AudioInput"; 17 | 18 | 19 | describe("AudioInput - unit tests", () => { 20 | 21 | test("Initial conditions", () => { 22 | const audioInput = new AudioInput(); 23 | expect(audioInput.errorString()).toBe(""); 24 | expect(audioInput.hasPendingFrame()).toBe(false); 25 | expect(audioInput.isStarted()).toBe(false); 26 | expect(audioInput.isSuspended()).toBe(false); 27 | }); 28 | 29 | }); 30 | -------------------------------------------------------------------------------- /tests/domain/audio/AudioOutput.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // AudioOutput.unit.test.js 3 | // 4 | // Created by David Rowe on 26 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AudioWorkletsMock from "../../../mocks/domain/audio/AudioWorklets.mock.js"; 13 | AudioWorkletsMock.mock(); 14 | 15 | 16 | import AudioOutput from "../../../src/domain/audio/AudioOutput"; 17 | import ContextManager from "../../../src/domain/shared/ContextManager"; 18 | 19 | 20 | describe("AudioOutput - unit tests", () => { 21 | 22 | test("The AudioOutput can be obtained from the ContextManager", () => { 23 | const contextID = ContextManager.createContext(); 24 | ContextManager.set(contextID, AudioOutput); 25 | const audioOutput = ContextManager.get(contextID, AudioOutput); 26 | expect(audioOutput instanceof AudioOutput).toBe(true); 27 | }); 28 | 29 | }); 30 | -------------------------------------------------------------------------------- /tests/domain/avatars/AvatarTraits.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // AvatarTraits.unit.test.js 3 | // 4 | // Created by David Rowe on 30 Apr 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import { webcrypto } from "crypto"; 13 | globalThis.crypto = webcrypto; 14 | 15 | import AvatarTraits from "../../../src/domain/avatars/AvatarTraits"; 16 | 17 | 18 | describe("AvatarTraits - unit tests", () => { 19 | 20 | test("AvatarTraits values appear to be correct", () => { 21 | expect(AvatarTraits.NullTrait).toBe(-1); 22 | expect(AvatarTraits.SkeletonModelURL).toBe(0); 23 | expect(AvatarTraits.TotalTraitTypes).toBe(AvatarTraits.Grab + 1); 24 | expect(AvatarTraits.DEFAULT_TRAIT_VERSION).toBe(0); 25 | expect(AvatarTraits.DELETED_TRAIT_SIZE).toBe(-1); 26 | }); 27 | 28 | test("Can check whether a trait is a simple trait type", () => { 29 | expect(AvatarTraits.isSimpleTrait(AvatarTraits.NullTrait)).toEqual(false); 30 | expect(AvatarTraits.isSimpleTrait(AvatarTraits.SkeletonModelURL)).toEqual(true); 31 | expect(AvatarTraits.isSimpleTrait(AvatarTraits.SkeletonData)).toEqual(true); 32 | expect(AvatarTraits.isSimpleTrait(AvatarTraits.FirstInstancedTrait)).toEqual(false); 33 | expect(AvatarTraits.isSimpleTrait(AvatarTraits.AvatarEntity)).toEqual(false); 34 | expect(AvatarTraits.isSimpleTrait(AvatarTraits.Grab)).toEqual(false); 35 | }); 36 | 37 | }); 38 | -------------------------------------------------------------------------------- /tests/domain/avatars/ClientTraitsHandler.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // AudioMixer.unit.test.js 3 | // 4 | // Created by Julien Merzoug on 08 Apr 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import { webcrypto } from "crypto"; 13 | globalThis.crypto = webcrypto; 14 | 15 | import AvatarData from "../../../src/domain/avatars/AvatarData"; 16 | import ClientTraitsHandler from "../../../src/domain/avatars/ClientTraitsHandler"; 17 | import AccountManager from "../../../src/domain/networking/AccountManager"; 18 | import AddressManager from "../../../src/domain/networking/AddressManager"; 19 | import NodeList from "../../../src/domain/networking/NodeList"; 20 | import ContextManager from "../../../src/domain/shared/ContextManager"; 21 | 22 | 23 | describe("ClientTraitsHandler - unit tests", () => { 24 | const contextID = ContextManager.createContext(); 25 | ContextManager.set(contextID, AccountManager, contextID); 26 | ContextManager.set(contextID, AddressManager); 27 | ContextManager.set(contextID, NodeList, contextID); 28 | 29 | test("Can create a ClientTraitsHandler", () => { 30 | const avatarData = new AvatarData(contextID); 31 | const clientTraitHandler = new ClientTraitsHandler(avatarData, contextID); 32 | expect(clientTraitHandler instanceof ClientTraitsHandler).toBe(true); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /tests/domain/entities/ImageEntityItem.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // ImageEntityItem.unit.test.js 3 | // 4 | // Created by Julien Merzoug on 22 Jul 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import ImageEntityItem from "../../../src/domain/entities/ImageEntityItem"; 13 | import PropertyFlags from "../../../src/domain/shared/PropertyFlags"; 14 | 15 | 16 | describe("ImageEntityItem - unit tests", () => { 17 | 18 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 19 | 20 | test("Can read image entity data", () => { 21 | const flagsBufferHex = "fff8ffff37ffffffffffffe03fbc"; 22 | let bufferArray = new Uint8Array(flagsBufferHex.match(/[\da-f]{2}/giu).map(function (hex) { 23 | return parseInt(hex, 16); 24 | })); 25 | 26 | const encodedFlags = new DataView(bufferArray.buffer); 27 | const propertyFlags = new PropertyFlags(); 28 | propertyFlags.decode(encodedFlags, encodedFlags.byteLength); 29 | 30 | // eslint-disable-next-line max-len 31 | const bufferHex = "a11aa10000803f000000000000803f0000803f00000000000000005d0068747470733a2f2f63646e2d312e76697263616469612e636f6d2f75732d652d312f42617a6161722f4173736574732f54657874757265732f44656661756c74732f496e746572666163652f64656661756c745f696d6167652e6a706701010700000013000000160000002c000000"; 32 | bufferArray = new Uint8Array(bufferHex.match(/[\da-f]{2}/giu).map(function (hex) { 33 | return parseInt(hex, 16); 34 | })); 35 | const data = new DataView(bufferArray.buffer); 36 | 37 | const imageEntity = ImageEntityItem.readEntitySubclassDataFromBuffer(data, 0, propertyFlags); 38 | 39 | expect(imageEntity.bytesRead).toBe(140); 40 | expect(imageEntity.properties.color.red).toBe(161); 41 | expect(imageEntity.properties.color.green).toBe(26); 42 | expect(imageEntity.properties.color.blue).toBe(161); 43 | expect(imageEntity.properties.alpha).toBe(1); 44 | expect(imageEntity.properties.imageURL).toBe( 45 | "https://cdn-1.vircadia.com/us-e-1/Bazaar/Assets/Textures/Defaults/Interface/default_image.jpg" 46 | ); 47 | expect(imageEntity.properties.emissive).toBe(true); 48 | expect(imageEntity.properties.keepAspectRatio).toBe(true); 49 | expect(imageEntity.properties.subImage).toStrictEqual({ x: 7, y: 19, width: 22, height: 44 }); 50 | }); 51 | 52 | }); 53 | -------------------------------------------------------------------------------- /tests/domain/entities/LightEntityItem.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // LightEntityItem.unit.test.js 3 | // 4 | // Created by David Rowe on 2 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import LightEntityItem from "../../../src/domain/entities/LightEntityItem"; 13 | import PropertyFlags from "../../../src/domain/shared/PropertyFlags"; 14 | 15 | 16 | describe("LightEntityItem - unit tests", () => { 17 | 18 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 19 | 20 | test("Can read Light entity data", () => { 21 | const flagsBufferHex = "fff8ffff37ffffffffffffe0203e"; 22 | let bufferArray = new Uint8Array(flagsBufferHex.match(/[\da-f]{2}/giu).map(function (hex) { 23 | return parseInt(hex, 16); 24 | })); 25 | 26 | const encodedFlags = new DataView(bufferArray.buffer); 27 | const propertyFlags = new PropertyFlags(); 28 | propertyFlags.decode(encodedFlags, encodedFlags.byteLength); 29 | 30 | // eslint-disable-next-line max-len 31 | const bufferHex = "704c8c01000090406666663f000096429a99993f5a090fe88bbe4893badf17f8c757b46940000000"; 32 | bufferArray = new Uint8Array(bufferHex.match(/[\da-f]{2}/giu).map(function (hex) { 33 | return parseInt(hex, 16); 34 | })); 35 | const data = new DataView(bufferArray.buffer); 36 | 37 | const lightEntity = LightEntityItem.readEntitySubclassDataFromBuffer(data, 0, propertyFlags); 38 | 39 | expect(lightEntity.bytesRead).toBe(20); 40 | expect(lightEntity.properties.color.red).toBe(112); 41 | expect(lightEntity.properties.color.green).toBe(76); 42 | expect(lightEntity.properties.color.blue).toBe(140); 43 | expect(lightEntity.properties.intensity).toBe(4.5); 44 | expect(lightEntity.properties.falloffRadius).toBeCloseTo(1.2, 4); 45 | expect(lightEntity.properties.isSpotlight).toBe(true); 46 | expect(lightEntity.properties.exponent).toBeCloseTo(0.9, 4); 47 | expect(lightEntity.properties.cutoff).toBeCloseTo(75.0, 4); 48 | }); 49 | 50 | }); 51 | -------------------------------------------------------------------------------- /tests/domain/entities/ShapeEntityItem.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // ShapeEntityItem.unit.test.js 3 | // 4 | // Created by Julien Merzoug on 11 Jul 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import ShapeEntityItem from "../../../src/domain/entities/ShapeEntityItem"; 13 | import PropertyFlags from "../../../src/domain/shared/PropertyFlags"; 14 | 15 | 16 | describe("ShapeEntityItem - unit tests", () => { 17 | 18 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 19 | 20 | test("Can read shape entity data", () => { 21 | const flagsBufferHex = "fff8ffff37ffffffffffffe03fa0"; 22 | let bufferArray = new Uint8Array(flagsBufferHex.match(/[\da-f]{2}/giu).map(function (hex) { 23 | return parseInt(hex, 16); 24 | })); 25 | 26 | const encodedFlags = new DataView(bufferArray.buffer); 27 | const propertyFlags = new PropertyFlags(); 28 | propertyFlags.decode(encodedFlags, encodedFlags.byteLength); 29 | 30 | const bufferHex = "00b4ef0000803f000000000000803f0000803f00000000000000000800547269616e676c65"; 31 | bufferArray = new Uint8Array(bufferHex.match(/[\da-f]{2}/giu).map(function (hex) { 32 | return parseInt(hex, 16); 33 | })); 34 | const data = new DataView(bufferArray.buffer); 35 | 36 | const shapeEntity = ShapeEntityItem.readEntitySubclassDataFromBuffer(data, 0, propertyFlags); 37 | 38 | expect(shapeEntity.bytesRead).toBe(37); 39 | expect(shapeEntity.properties.color.red).toBe(0); 40 | expect(shapeEntity.properties.color.green).toBe(180); 41 | expect(shapeEntity.properties.color.blue).toBe(239); 42 | expect(shapeEntity.properties.alpha).toBe(1); 43 | expect(shapeEntity.properties.shape).toBe("Triangle"); 44 | }); 45 | 46 | }); 47 | -------------------------------------------------------------------------------- /tests/domain/interfaces/AvatarListInterface.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // AvatarListInterface.unit.test.js 3 | // 4 | // Created by David Rowe on 31 Oct 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 13 | 14 | import AccountManagerMock from "../../../mocks/domain/networking/AccountManager.mock.js"; 15 | AccountManagerMock.mock(); 16 | import AudioWorkletsMock from "../../../mocks/domain/audio/AudioWorklets.mock.js"; 17 | AudioWorkletsMock.mock(); 18 | 19 | import { webcrypto } from "crypto"; 20 | globalThis.crypto = webcrypto; 21 | 22 | import AvatarManager from "../../../src/domain/AvatarManager"; 23 | import AvatarListInterface from "../../../src/domain/interfaces/AvatarListInterface"; 24 | import ContextManager from "../../../src/domain/shared/ContextManager"; 25 | import DomainServer from "../../../src/DomainServer"; 26 | 27 | 28 | describe("AvatarListInterface - unit tests", () => { 29 | 30 | test("Can access the signals", () => { 31 | const domainServer = new DomainServer(); 32 | const contextID = domainServer.contextID; 33 | ContextManager.set(contextID, AvatarManager, contextID); 34 | const avatarListInterface = new AvatarListInterface(contextID); 35 | expect(typeof avatarListInterface.avatarAdded.connect).toBe("function"); 36 | expect(typeof avatarListInterface.avatarAdded.disconnect).toBe("function"); 37 | expect(typeof avatarListInterface.avatarRemoved.connect).toBe("function"); 38 | expect(typeof avatarListInterface.avatarRemoved.disconnect).toBe("function"); 39 | }); 40 | 41 | }); 42 | -------------------------------------------------------------------------------- /tests/domain/networking/AccountManager.integration.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // AccountManager.integration.test.js 3 | // 4 | // Created by David Rowe on 7 Jan 2023. 5 | // Copyright 2023 Vircadia contributors. 6 | // copyright 2023 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import { webcrypto } from "crypto"; 13 | globalThis.crypto = webcrypto; 14 | 15 | import AccountManager from "../../../src/domain/networking/AccountManager"; 16 | import MetaverseAPI from "../../../src/domain/networking/MetaverseAPI"; 17 | import ContextManager from "../../../src/domain/shared/ContextManager"; 18 | 19 | 20 | describe("AccountManager - integration tests", () => { 21 | 22 | /* eslint-disable @typescript-eslint/no-unsafe-call */ 23 | 24 | test("Can generate a new user key pair", (done) => { 25 | const contextID = ContextManager.createContext(); 26 | ContextManager.set(contextID, AccountManager, contextID); 27 | ContextManager.set(contextID, MetaverseAPI); 28 | const accountManager = ContextManager.get(contextID, AccountManager); 29 | expect(accountManager.hasKeyPair()).toBe(false); 30 | // Public key upload to metaverse should fail because we're not authenticated. 31 | const log = jest.spyOn(console, "log").mockImplementation(/* no-op */); 32 | const warn = jest.spyOn(console, "warn").mockImplementation((...message) => { 33 | const errorMessage = message.join(" "); 34 | expect(errorMessage.startsWith("[networking] Public key upload to metaverse failed")).toBe(true); 35 | expect(errorMessage.endsWith("Not authenticated")).toBe(true); 36 | expect(accountManager.hasKeyPair()).toBe(false); // Only true if public key has been uploaded to the metaverse. 37 | warn.mockReset(); 38 | log.mockReset(); 39 | done(); 40 | }); 41 | accountManager.generateNewUserKeypair(); 42 | }); 43 | 44 | }); 45 | -------------------------------------------------------------------------------- /tests/domain/networking/DomainHandler.integration.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // DomainHandler.integration.test.js 3 | // 4 | // Created by David Rowe on 5 Jun 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | 13 | describe("DomainHandler - integration tests", () => { 14 | 15 | // WEBRTC TODO: Add integration tests. 16 | test("No test", () => { 17 | expect(true).toBe(true); 18 | }); 19 | 20 | // DomainHandler.disconnect() is tested in DomainServer.integration.test.js. 21 | 22 | }); 23 | -------------------------------------------------------------------------------- /tests/domain/networking/FingerprintUtils.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // FingerprintUtils.unit.test.js 3 | // 4 | // Created by David Rowe on 14 Jun 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import { webcrypto } from "crypto"; 13 | globalThis.crypto = webcrypto; 14 | 15 | import FingerprintUtils from "../../../src/domain/networking/FingerprintUtils"; 16 | import Uuid from "../../../src/domain/shared/Uuid"; 17 | 18 | 19 | describe("FingerprintUtils - unit tests", () => { 20 | 21 | test("Can get the machine fingerprint value", () => { 22 | const machineFingerprint = FingerprintUtils.getMachineFingerprint(); 23 | expect(machineFingerprint instanceof Uuid).toBe(true); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /tests/domain/networking/MessageData.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // MessageData.unit.test.js 3 | // 4 | // Created by David Rowe on 11 Jun 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 13 | 14 | import MessageData from "../../../src/domain/networking/MessageData"; 15 | 16 | 17 | describe("MessageData - unit tests", () => { 18 | 19 | test("Can set and get property values", () => { 20 | const messageData = new MessageData(); 21 | messageData.packetSize = 7; 22 | messageData.isReliable = true; 23 | messageData.dataPosition = 12; 24 | expect(messageData.packetSize).toBe(7); 25 | expect(messageData.isReliable).toBe(true); 26 | }); 27 | 28 | test("Can't set invalid property values", () => { 29 | const messageData = new MessageData(); 30 | let failed = false; 31 | try { 32 | messageData.invalidProperty = true; 33 | } catch (err) { 34 | failed = true; 35 | } 36 | expect(failed).toBe(true); 37 | }); 38 | 39 | test("Can construct from another MessageData object", () => { 40 | const firstMessageData = new MessageData(); 41 | firstMessageData.dataPosition = 12; 42 | const secondMessageData = new MessageData(firstMessageData); 43 | expect(secondMessageData.dataPosition).toBe(12); 44 | firstMessageData.dataPosition = 34; 45 | expect(firstMessageData.dataPosition).toBe(34); 46 | expect(secondMessageData.dataPosition).toBe(12); 47 | }); 48 | 49 | test("Can access raw data via both the buffer and data properties", () => { 50 | const messageData = new MessageData(); 51 | expect(messageData.buffer instanceof Uint8Array).toBe(true); 52 | expect(messageData.data instanceof DataView).toBe(true); 53 | expect(messageData.data.buffer).toBe(messageData.buffer.buffer); 54 | const buffer = new Uint8Array(8); 55 | messageData.buffer = buffer; 56 | expect(messageData.buffer).toBe(buffer); 57 | expect(messageData.buffer.buffer).toBe(buffer.buffer); 58 | expect(messageData.data.buffer).toBe(buffer.buffer); 59 | }); 60 | 61 | }); 62 | -------------------------------------------------------------------------------- /tests/domain/networking/MessagesClient.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // MessagesClient.unit.test.js 3 | // 4 | // Created by David Rowe on 2 Oct 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AccountManagerMock from "../../../mocks/domain/networking/AccountManager.mock.js"; 13 | AccountManagerMock.mock(); 14 | 15 | import { webcrypto } from "crypto"; 16 | globalThis.crypto = webcrypto; 17 | 18 | import DomainServer from "../../../src/DomainServer"; 19 | import MessagesClient from "../../../src/domain/networking/MessagesClient"; 20 | 21 | 22 | describe("MessagesClient - unit tests", () => { 23 | 24 | test("Can subscribe to and unsubscribe from a channel", () => { 25 | const domainServer = new DomainServer(); 26 | const messagesClient = new MessagesClient(domainServer.contextID); 27 | 28 | const error = jest.spyOn(console, "error").mockImplementation(() => { /* no-op */ }); 29 | messagesClient.subscribe("com.vircadia.test.unit"); 30 | messagesClient.unsubscribe("com.vircadia.test.unit"); 31 | expect(error).toHaveBeenCalledTimes(0); 32 | error.mockReset(); 33 | }); 34 | 35 | }); 36 | -------------------------------------------------------------------------------- /tests/domain/networking/NetworkAccessManager.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkAccessManager.unit.test.js 3 | // 4 | // Created by David Rowe on 7 Jan 2023. 5 | // Copyright 2023 Vircadia contributors. 6 | // copyright 2023 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NetworkAccessManager from "../../../src/domain/networking/NetworkAccessManager"; 13 | 14 | 15 | describe("NetworkAccessManager - unit tests", () => { 16 | 17 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 18 | 19 | test("Can access the operation types", () => { 20 | expect(NetworkAccessManager.UnknownOperation).toBe(0); 21 | expect(NetworkAccessManager.HeadOperation).toBe(1); 22 | expect(NetworkAccessManager.GetOperation).toBe(2); 23 | expect(NetworkAccessManager.PutOperation).toBe(3); 24 | expect(NetworkAccessManager.PostOperation).toBe(4); 25 | expect(NetworkAccessManager.DeleteOperation).toBe(5); 26 | expect(NetworkAccessManager.CustomOperation).toBe(6); 27 | }); 28 | 29 | test("Can retrieve the NetworkAccessManager singleton", () => { 30 | const networkAccessManager = NetworkAccessManager.getInstance(); 31 | expect(typeof networkAccessManager.put).toBe("function"); 32 | expect(NetworkAccessManager.getInstance()).toEqual(networkAccessManager); 33 | }); 34 | 35 | }); 36 | -------------------------------------------------------------------------------- /tests/domain/networking/NetworkRequest.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkRequest.unit.test.js 3 | // 4 | // Created by David Rowe on 7 Jan 2023. 5 | // Copyright 2023 Vircadia contributors. 6 | // copyright 2023 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NetworkRequest from "../../../src/domain/networking/NetworkRequest"; 13 | import Url from "../../../src/domain/shared/Url"; 14 | 15 | 16 | describe("NetworkRequest - unit tests", () => { 17 | 18 | test("Can set and get attribute values", () => { 19 | const networkRequest = new NetworkRequest(); 20 | expect(networkRequest.attributes().size).toBe(1); 21 | expect(networkRequest.attributes().get(NetworkRequest.FollowRedirectsAttribute)).toBe(false); 22 | networkRequest.setAttribute(NetworkRequest.FollowRedirectsAttribute, true); 23 | expect(networkRequest.attributes().get(NetworkRequest.FollowRedirectsAttribute)).toBe(true); 24 | networkRequest.setAttribute(NetworkRequest.FollowRedirectsAttribute, false); 25 | expect(networkRequest.attributes().get(NetworkRequest.FollowRedirectsAttribute)).toBe(false); 26 | }); 27 | 28 | test("Can set and get raw header values", () => { 29 | const networkRequest = new NetworkRequest(); 30 | expect(networkRequest.rawHeaders().size).toBe(0); 31 | networkRequest.setRawHeader("a", "x"); 32 | expect(networkRequest.rawHeaders().size).toBe(1); 33 | expect(networkRequest.rawHeaders().get("a")).toBe("x"); 34 | networkRequest.setRawHeader("a", "xx"); 35 | expect(networkRequest.rawHeaders().size).toBe(1); 36 | expect(networkRequest.rawHeaders().get("a")).toBe("xx"); 37 | networkRequest.setRawHeader("b", "y"); 38 | expect(networkRequest.rawHeaders().size).toBe(2); 39 | expect(networkRequest.rawHeaders().get("a")).toBe("xx"); 40 | expect(networkRequest.rawHeaders().get("b")).toBe("y"); 41 | }); 42 | 43 | test("Can set and get the URL", () => { 44 | const networkRequest = new NetworkRequest(); 45 | expect(networkRequest.url().isEmpty()).toBe(true); 46 | networkRequest.setUrl(new Url("http://abc.xyz/ijk")); 47 | expect(networkRequest.url().isEmpty()).toBe(false); 48 | expect(networkRequest.url().toString()).toBe("http://abc.xyz/ijk"); 49 | }); 50 | 51 | }); 52 | -------------------------------------------------------------------------------- /tests/domain/networking/NetworkingConstants.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkingConstants.unit.test.js 3 | // 4 | // Created by David Rowe on 6 Jan 2023. 5 | // Copyright 2023 Vircadia contributors. 6 | // copyright 2023 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NetworkingConstants from "../../../src/domain/networking/NetworkingConstants"; 13 | 14 | 15 | describe("NetworkingConstants - unit tests", () => { 16 | 17 | test("Can obtain networking constants", () => { 18 | expect(NetworkingConstants.METAVERSE_SERVER_URL_STABLE).toBe("https://metaverse.vircadia.com/live"); 19 | }); 20 | 21 | }); 22 | -------------------------------------------------------------------------------- /tests/domain/networking/NodePermissions.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // NodePermissions.unit.test.js 3 | // 4 | // Created by David Rowe on 11 Aug 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NodePermissions from "../../../src/domain/networking/NodePermissions"; 13 | 14 | 15 | describe("NodePermissions - unit tests", () => { 16 | 17 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 18 | 19 | test("Can set and get permission values", () => { 20 | const nodePermissions = new NodePermissions(); 21 | expect(nodePermissions.permissions).toBe(NodePermissions.Permission.none); 22 | nodePermissions.permissions = 7; 23 | expect(nodePermissions.permissions).toBe(7); 24 | }); 25 | 26 | test("Can get permission constants", () => { 27 | expect(NodePermissions.Permission.none).toBe(0); 28 | expect(NodePermissions.Permission.canKick).toBe(64); 29 | expect(NodePermissions.Permission.canRezAvatarEntities).toBe(2048); 30 | }); 31 | 32 | test("Can set and get permissions", () => { 33 | const nodePermissions = new NodePermissions(); 34 | nodePermissions.permissions = NodePermissions.Permission.canAdjustLocks 35 | | NodePermissions.Permission.canConnectPastMaxCapacity; 36 | expect(nodePermissions.can(NodePermissions.Permission.canAdjustLocks)).toBe(true); 37 | expect(nodePermissions.can(NodePermissions.Permission.canConnectPastMaxCapacity)).toBe(true); 38 | expect(nodePermissions.can(NodePermissions.Permission.canConnectToDomain)).toBe(false); 39 | expect(nodePermissions.can(NodePermissions.Permission.canRezAvatarEntities)).toBe(false); 40 | }); 41 | 42 | }); 43 | -------------------------------------------------------------------------------- /tests/domain/networking/NodeType.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // NodeType.unit.test.js 3 | // 4 | // Created by David Rowe on 7 Jun 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NodeType from "../../../src/domain/networking/NodeType"; 13 | 14 | 15 | describe("NodeType - unit tests", () => { 16 | 17 | test("NodeType values appear to be correct", () => { 18 | expect(NodeType.DomainServer).toBe("D"); 19 | expect(NodeType.MessagesMixer).toBe("m"); 20 | expect(NodeType.Unassigned).toBe(String.fromCharCode(1)); 21 | }); 22 | 23 | test("NodeType strings appear to be correct", () => { 24 | expect(NodeType.getNodeTypeName(NodeType.DomainServer)).toBe("Domain Server"); 25 | expect(NodeType.getNodeTypeName(NodeType.MessagesMixer)).toBe("Messages Mixer"); 26 | expect(NodeType.getNodeTypeName(NodeType.Unassigned)).toBe("Unassigned"); 27 | expect(NodeType.getNodeTypeName("-")).toBe("Unknown"); 28 | }); 29 | 30 | test("Upstream node types are identified", () => { 31 | expect(NodeType.isUpstream(NodeType.AudioMixer)).toBe(false); 32 | expect(NodeType.isUpstream(NodeType.UpstreamAudioMixer)).toBe(true); 33 | expect(NodeType.isUpstream(NodeType.UpstreamAvatarMixer)).toBe(true); 34 | expect(NodeType.isUpstream(NodeType.DownstreamAudioMixer)).toBe(false); 35 | expect(NodeType.isUpstream(NodeType.Unassigned)).toBe(false); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /tests/domain/networking/PingType.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // PingType.unit.test.js 3 | // 4 | // Created by David Rowe on 6 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import PingType from "../../../src/domain/networking/PingType"; 13 | 14 | 15 | describe("PingType - unit tests", () => { 16 | 17 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 18 | 19 | test("PingType values are correct", () => { 20 | expect(PingType.Agnostic).toBe(0); 21 | expect(PingType.Local).toBe(1); 22 | expect(PingType.Public).toBe(2); 23 | expect(PingType.Symmetric).toBe(3); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /tests/domain/networking/SocketType.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // SocketType.unit.test.js 3 | // 4 | // Created by David Rowe on 1 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import SocketType from "../../../src/domain/networking/SocketType"; 13 | 14 | 15 | describe("SocketType - unit tests", () => { 16 | 17 | test("SocketType values are correct", () => { 18 | expect(SocketType.Unknown).toBe(0); 19 | expect(SocketType.UDP).toBe(1); 20 | expect(SocketType.WebRTC).toBe(2); 21 | }); 22 | 23 | test("SocketType strings are correct", () => { 24 | expect(SocketType.socketTypeToString(SocketType.Unknown - 1)).toBe("Unknown"); 25 | expect(SocketType.socketTypeToString(SocketType.Unknown)).toBe("Unknown"); 26 | expect(SocketType.socketTypeToString(SocketType.UDP)).toBe("UDP"); 27 | expect(SocketType.socketTypeToString(SocketType.WebRTC)).toBe("WebRTC"); 28 | expect(SocketType.socketTypeToString(SocketType.WebRTC + 1)).toBe("Unknown"); 29 | }); 30 | 31 | }); 32 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/AvatarQuery.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // AvatarQuery.unit.test.js 3 | // 4 | // Created by David Rowe on 10 May 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AvatarQuery from "../../../../src/domain/networking/packets/AvatarQuery"; 13 | import PacketType from "../../../../src/domain/networking/udt/PacketHeaders"; 14 | import NLPacket from "../../../../src/domain/networking/NLPacket"; 15 | 16 | import { buffer2hex } from "../../../testUtils"; 17 | 18 | 19 | describe("AvatarQuery - unit tests", () => { 20 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 21 | 22 | test("Can write an AvatarQuery packet", () => { 23 | // eslint-disable-next-line max-len 24 | const EXPECTED_PACKET = "00000000481600000000000000000000000000000000000001cdcc8c3fcdcc0c4033335340ae47e1becdcc0c3fc3f528bf1d8100c0a4704d40"; 25 | const packet = AvatarQuery.write({ 26 | conicalViews: [ 27 | { 28 | position: { x: 1.1, y: 2.2, z: 3.3 }, 29 | direction: { x: -0.44, y: 0.55, z: -0.66 }, 30 | halfAngle: 1.571, 31 | farClip: 16384, 32 | centerRadius: 3.21 33 | } 34 | ] 35 | }); 36 | 37 | expect(packet instanceof NLPacket).toBe(true); 38 | expect(packet.getType()).toBe(PacketType.AvatarQuery); 39 | const packetSize = packet.getDataSize(); 40 | expect(packetSize).toBe(packet.getMessageData().dataPosition); 41 | expect(packetSize).toBe(EXPECTED_PACKET.length / 2); 42 | expect(buffer2hex(packet.getMessageData().buffer.slice(0, packetSize))).toBe(EXPECTED_PACKET); 43 | expect(packet.getMessageData().dataPosition).toBe(packetSize); 44 | expect(packet.getMessageData().packetSize).toBe(packetSize); 45 | }); 46 | 47 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 48 | }); 49 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/BulkAvatarTraitsAck.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // BulkAvatarTraitsAck.unit.test.js 3 | // 4 | // Created by David Rowe on 28 Nov 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NLPacket from "../../../../src/domain/networking/NLPacket"; 13 | import BulkAvatarTraitsAck from "../../../../src/domain/networking/packets/BulkAvatarTraitsAck"; 14 | import PacketType from "../../../../src/domain/networking/udt/PacketHeaders"; 15 | import UDT from "../../../../src/domain/networking/udt/UDT"; 16 | 17 | import { buffer2hex } from "../../../testUtils.js"; 18 | 19 | 20 | describe("BulkAvatarTraitsAck - unit tests", () => { 21 | 22 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 23 | 24 | test("Can write a BulkAvatarTraitsAck packet", () => { 25 | // eslint-disable-next-line max-len 26 | const EXPECTED_PACKET = "0000004066300000000000000000000000000000000000000200000000000000"; 27 | 28 | const packet = BulkAvatarTraitsAck.write({ 29 | traitsSequenceNumber: 2n 30 | }); 31 | 32 | expect(packet instanceof NLPacket).toBe(true); 33 | expect(packet.getType()).toBe(PacketType.BulkAvatarTraitsAck); 34 | 35 | const packetSize = packet.getDataSize(); 36 | expect(packetSize).toBe(packet.getMessageData().dataPosition); 37 | expect(packetSize).toBeGreaterThan(0); 38 | expect(packetSize).toBeLessThan(UDT.MAX_PACKET_SIZE); 39 | 40 | expect(packet.getMessageData().dataPosition).toBe(EXPECTED_PACKET.length / 2); 41 | expect(buffer2hex(packet.getMessageData().buffer.slice(0, EXPECTED_PACKET.length / 2))).toBe(EXPECTED_PACKET); 42 | }); 43 | 44 | }); 45 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/DomainConnectionDenied.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // DomainConnectionDenied.unit.test.js 3 | // 4 | // Created by David Rowe on 3 Aug 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import { webcrypto } from "crypto"; 13 | globalThis.crypto = webcrypto; 14 | 15 | import DomainConnectionDenied from "../../../../src/domain/networking/packets/DomainConnectionDenied"; 16 | import DomainHandler from "../../../../src/domain/networking/DomainHandler"; 17 | 18 | 19 | describe("DomainConnectionDenied - unit tests", () => { 20 | 21 | test("Can read a DomainConnectionDenied packet", () => { 22 | /* eslint-disable-next-line max-len */ 23 | const MESSAGE_TEXT = "070000001013012f0050726f746f636f6c2076657273696f6e206d69736d61746368202d20446f6d61696e2076657273696f6e3a206465760000"; 24 | const MESSAGE_START = 6; 25 | 26 | const arrayBuffer = new ArrayBuffer(MESSAGE_TEXT.length / 2); 27 | const uint8Array = new Uint8Array(arrayBuffer); 28 | for (let i = 0, length = arrayBuffer.byteLength; i < length; i++) { 29 | uint8Array[i] = Number.parseInt(MESSAGE_TEXT.substr(i * 2, 2), 16); 30 | } 31 | const dataView = new DataView(arrayBuffer, MESSAGE_START); 32 | 33 | const info = DomainConnectionDenied.read(dataView); 34 | 35 | expect(info.reasonCode).toBe(DomainHandler.ConnectionRefusedReason.ProtocolMismatch); 36 | expect(info.reasonMessage).toBe("Protocol version mismatch - Domain version: dev"); 37 | expect(info.extraInfo).toBe(""); 38 | }); 39 | 40 | }); 41 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/DomainDisconnectRequest.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // DomainDisconnectRequest.unit.test.js 3 | // 4 | // Created by David Rowe on 27 Jul 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NLPacket from "../../../../src/domain/networking/NLPacket"; 13 | import DomainDisconnectRequest from "../../../../src/domain/networking/packets/DomainDisconnectRequest"; 14 | import PacketType from "../../../../src/domain/networking/udt/PacketHeaders"; 15 | import UDT from "../../../../src/domain/networking/udt/UDT"; 16 | 17 | 18 | describe("DomainDisconnectRequest - unit tests", () => { 19 | 20 | test("Can write a DomainDisonnectRequest packet", () => { 21 | const packet = DomainDisconnectRequest.write(); 22 | expect(packet instanceof NLPacket).toBe(true); 23 | expect(packet.getType()).toBe(PacketType.DomainDisconnectRequest); 24 | const packetSize = packet.getDataSize(); 25 | expect(packetSize).toBeGreaterThan(0); 26 | expect(packetSize).toBeLessThan(UDT.MAX_PACKET_SIZE); 27 | }); 28 | 29 | }); 30 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/DomainServerAddedNode.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // DomainServerAddedNode.unit.test.js 3 | // 4 | // Created by David Rowe on 19 Aug 2022. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import DomainServerAddedNode from "../../../../src/domain/networking/packets/DomainServerAddedNode"; 13 | import NodeType from "../../../../src/domain/networking/NodeType"; 14 | 15 | 16 | describe("DomainServerAddedNode - unit tests", () => { 17 | 18 | test("Can read a DomainServerAddedNode packet", () => { 19 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 20 | 21 | /* eslint-disable-next-line max-len */ 22 | const MESSAGE_TEXT = "4dfb651249d9114b589d7686ed4f6dfc0901006715af042ebd0100c0a8086ee71100000f9f0015af983e5546c17542d2b838aa04fa72e915"; 23 | const MESSAGE_START = 0; 24 | 25 | const arrayBuffer = new ArrayBuffer(MESSAGE_TEXT.length / 2); 26 | const uint8Array = new Uint8Array(arrayBuffer); 27 | for (let i = 0, length = arrayBuffer.byteLength; i < length; i++) { 28 | uint8Array[i] = Number.parseInt(MESSAGE_TEXT.substr(i * 2, 2), 16); 29 | } 30 | const dataView = new DataView(arrayBuffer, MESSAGE_START); 31 | 32 | const info = DomainServerAddedNode.read(dataView); 33 | expect(info.type).toBe(NodeType.AudioMixer); 34 | expect(info.uuid.stringify()).toBe("fb651249-d911-4b58-9d76-86ed4f6dfc09"); 35 | expect(info.publicSocket.toString()).toBe("UDP 103.21.175.4:11965"); 36 | expect(info.localSocket.toString()).toBe("UDP 192.168.8.110:59153"); 37 | expect(info.permissions.permissions).toBe(3999); 38 | expect(info.isReplicated).toBe(false); 39 | expect(info.sessionLocalID).toBe(5551); 40 | expect(info.connectionSecretUUID.stringify()).toBe("983e5546-c175-42d2-b838-aa04fa72e915"); 41 | }); 42 | 43 | }); 44 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/DomainServerConnectionToken.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // DomainServerConnectionToken.unit.test.js 3 | // 4 | // Created by David Rowe on 13 Jan 2023. 5 | // Copyright 2023 Vircadia contributors. 6 | // Copyright 2023 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import DomainServerConnectionToken from "../../../../src/domain/networking/packets/DomainServerConnectionToken"; 13 | 14 | 15 | describe("DomainServerConnectionToken - unit tests", () => { 16 | 17 | test("Can read a DomainServerConnectionToken packet", () => { 18 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 19 | 20 | const MESSAGE_TEXT = "3ca423fd0f7a4d0582979d73d007773f"; 21 | const MESSAGE_START = 0; 22 | 23 | const arrayBuffer = new ArrayBuffer(MESSAGE_TEXT.length / 2); 24 | const uint8Array = new Uint8Array(arrayBuffer); 25 | for (let i = 0, length = arrayBuffer.byteLength; i < length; i++) { 26 | uint8Array[i] = Number.parseInt(MESSAGE_TEXT.substr(i * 2, 2), 16); 27 | } 28 | const dataView = new DataView(arrayBuffer, MESSAGE_START); 29 | 30 | const info = DomainServerConnectionToken.read(dataView); 31 | expect(info.connectionToken.stringify()).toBe("3ca423fd-0f7a-4d05-8297-9d73d007773f"); 32 | }); 33 | 34 | }); 35 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/DomainServerPathQuery.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // DomainServerPathQuery.unit.test.js 3 | // 4 | // Created by David Rowe on 29 Jun 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import DomainServerPathQuery from "../../../../src/domain/networking/packets/DomainServerPathQuery"; 13 | import PacketType from "../../../../src/domain/networking/udt/PacketHeaders"; 14 | import NLPacket from "../../../../src/domain/networking/NLPacket"; 15 | 16 | import { buffer2hex } from "../../../testUtils"; 17 | 18 | 19 | describe("DomainServerPathQuery - unit tests", () => { 20 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 21 | 22 | test("Can write a DomainServerPathQuery packet", () => { 23 | const EXPECTED_PACKET = "00000040131609002f736f6d6570617468"; 24 | const packet = DomainServerPathQuery.write({ 25 | path: "/somepath" 26 | }); 27 | 28 | expect(packet instanceof NLPacket).toBe(true); 29 | expect(packet.getType()).toBe(PacketType.DomainServerPathQuery); 30 | const packetSize = packet.getDataSize(); 31 | expect(buffer2hex(packet.getMessageData().buffer.slice(0, packetSize))).toBe(EXPECTED_PACKET); 32 | expect(packetSize).toBe(EXPECTED_PACKET.length / 2); 33 | expect(packetSize).toBe(packet.getMessageData().dataPosition); 34 | expect(packetSize).toBe(packet.getMessageData().packetSize); 35 | }); 36 | 37 | test("No data is written if it won't fit in the packet", () => { 38 | let packet = DomainServerPathQuery.write({ 39 | path: "/somepath" 40 | }); 41 | expect(packet.getDataSize()).toBe(17); // 6 bytes header, 2 bytes path length, path. 42 | 43 | const longPath = new Array(2000) 44 | .fill("A") 45 | .join(""); 46 | packet = DomainServerPathQuery.write({ 47 | path: longPath 48 | }); 49 | expect(packet.getDataSize()).toBe(6); 50 | }); 51 | 52 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 53 | }); 54 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/DomainServerPathResponse.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // DomainServerPathResponse.unit.test.js 3 | // 4 | // Created by David Rowe on 3 Jul 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import DomainServerPathResponse from "../../../../src/domain/networking/packets/DomainServerPathResponse"; 13 | 14 | 15 | describe("DomainServerPathResponse - unit tests", () => { 16 | 17 | test("Can read a viewpoint with position only", () => { 18 | const MESSAGE_TEXT = "01002f09002f302e352c312c3130"; 19 | const MESSAGE_START = 0; 20 | 21 | const arrayBuffer = new ArrayBuffer(MESSAGE_TEXT.length / 2); 22 | const uint8Array = new Uint8Array(arrayBuffer); 23 | for (let i = 0, length = arrayBuffer.byteLength; i < length; i++) { 24 | uint8Array[i] = Number.parseInt(MESSAGE_TEXT.substr(i * 2, 2), 16); 25 | } 26 | const dataView = new DataView(arrayBuffer, MESSAGE_START); 27 | 28 | const info = DomainServerPathResponse.read(dataView); 29 | 30 | expect(info.pathQuery).toBe("/"); 31 | expect(info.viewpoint).toBe("/0.5,1,10"); 32 | }); 33 | 34 | test("Can read a viewpoint with position and orientation", () => { 35 | // eslint-disable-next-line max-len 36 | const MESSAGE_TEXT = "0a002f736f6d65776865726530002f392e39363039352c2d302e303339353837312c362e303538312f302c302e3436313135382c302c302e383837333138"; 37 | const MESSAGE_START = 0; 38 | 39 | const arrayBuffer = new ArrayBuffer(MESSAGE_TEXT.length / 2); 40 | const uint8Array = new Uint8Array(arrayBuffer); 41 | for (let i = 0, length = arrayBuffer.byteLength; i < length; i++) { 42 | uint8Array[i] = Number.parseInt(MESSAGE_TEXT.substr(i * 2, 2), 16); 43 | } 44 | const dataView = new DataView(arrayBuffer, MESSAGE_START); 45 | 46 | const info = DomainServerPathResponse.read(dataView); 47 | 48 | expect(info.pathQuery).toBe("/somewhere"); 49 | expect(info.viewpoint).toBe("/9.96095,-0.0395871,6.0581/0,0.461158,0,0.887318"); 50 | }); 51 | 52 | 53 | }); 54 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/DomainServerRemovedNode.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // DomainServerRemovedNode.unit.test.js 3 | // 4 | // Created by David Rowe on 20 Aug 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import DomainServerRemovedNode from "../../../../src/domain/networking/packets/DomainServerRemovedNode"; 13 | 14 | 15 | describe("DomainServerRemovedNode - unit tests", () => { 16 | 17 | test("Can read a DomainServerRemovedNode packet", () => { 18 | /* eslint-disable-next-line max-len */ 19 | const MESSAGE_TEXT = "4a619e443816bcd3d2ad043a4338bca43d664b9e57f0"; 20 | const MESSAGE_START = 6; 21 | 22 | const arrayBuffer = new ArrayBuffer(MESSAGE_TEXT.length / 2); 23 | const uint8Array = new Uint8Array(arrayBuffer); 24 | for (let i = 0, length = arrayBuffer.byteLength; i < length; i++) { 25 | uint8Array[i] = Number.parseInt(MESSAGE_TEXT.substr(i * 2, 2), 16); 26 | } 27 | const dataView = new DataView(arrayBuffer, MESSAGE_START); 28 | 29 | const info = DomainServerRemovedNode.read(dataView); 30 | 31 | expect(info.nodeUUID.stringify()).toBe("bcd3d2ad-043a-4338-bca4-3d664b9e57f0"); 32 | }); 33 | 34 | }); 35 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/EntityQuery.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // EntityQuery.unit.test.js 3 | // 4 | // Created by Julien Merzoug on 27 Apr 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import EntityQuery from "../../../../src/domain/networking/packets/EntityQuery"; 13 | import PacketType from "../../../../src/domain/networking/udt/PacketHeaders"; 14 | import UDT from "../../../../src/domain/networking/udt/UDT"; 15 | import NLPacket from "../../../../src/domain/networking/NLPacket"; 16 | import OctreeQuery from "../../../../src/domain/octree/OctreeQuery"; 17 | 18 | import { buffer2hex } from "../../../testUtils"; 19 | 20 | 21 | describe("EntityQuery - unit tests", () => { 22 | 23 | test("Can write an EntityQuery packet", () => { 24 | // eslint-disable-next-line 25 | const EXPECTED_PACKET = "000000002a170000416c015bb0a3c1c4f8b8c08ededbc0743c5e3f000000007624fe3e818000c000004040580200000000484b0000000000000000"; 26 | 27 | const conicalViews = [ 28 | { 29 | position: { x: -20.461111, y: -5.7803667, z: -6.8709172 }, 30 | direction: { x: 0.86810995, y: 0, z: 0.49637193 }, 31 | halfAngle: 0.714619, 32 | farClip: 16384, 33 | centerRadius: 3 34 | } 35 | ]; 36 | 37 | const octreeQuery = new OctreeQuery(); 38 | octreeQuery.setConicalViews(conicalViews); 39 | 40 | const data = octreeQuery.getBroadcastData(); 41 | // connectionID is randomly generated, but here we set it manually because we need a deterministic value for the purpose 42 | // of this test. 43 | data.connectionID = 27713; 44 | 45 | const packet = EntityQuery.write(data); 46 | expect(packet instanceof NLPacket).toBe(true); 47 | expect(packet.getType()).toBe(PacketType.EntityQuery); 48 | const packetSize = packet.getDataSize(); 49 | expect(packetSize).toBe(packet.getMessageData().dataPosition); 50 | expect(packetSize).toBeGreaterThan(0); 51 | expect(packetSize).toBeLessThan(UDT.MAX_PACKET_SIZE); 52 | 53 | expect(packetSize).toBe(EXPECTED_PACKET.length / 2); 54 | expect(buffer2hex(packet.getMessageData().buffer.slice(0, packetSize))).toBe(EXPECTED_PACKET); 55 | }); 56 | 57 | }); 58 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/KillAvatar.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // KillAvatar.unit.test.js 3 | // 4 | // Created by David Rowe on 3 Nov 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import KillAvatar from "../../../../src/domain/networking/packets/KillAvatar"; 13 | 14 | 15 | describe("KillAvatar - unit tests", () => { 16 | 17 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 18 | 19 | 20 | test("Can read a KillAvatar packet", () => { 21 | /* eslint-disable-next-line max-len */ 22 | 23 | const RECEIVED_MESSAGE = "000000400536000000000000000000000000000000000000ed7acf04adea40c5b32bf50a5f1eae3101"; 24 | const MESSAGE_START = 24; 25 | 26 | const arrayBuffer = new ArrayBuffer(RECEIVED_MESSAGE.length / 2); 27 | const uint8Array = new Uint8Array(arrayBuffer); 28 | for (let i = 0, length = arrayBuffer.byteLength; i < length; i++) { 29 | uint8Array[i] = Number.parseInt(RECEIVED_MESSAGE.substr(i * 2, 2), 16); 30 | } 31 | const dataView = new DataView(arrayBuffer, MESSAGE_START); 32 | 33 | const info = KillAvatar.read(dataView); 34 | 35 | expect(info.sessionUUID.stringify()).toBe("ed7acf04-adea-40c5-b32b-f50a5f1eae31"); 36 | expect(info.reason).toBe(1); 37 | }); 38 | 39 | }); 40 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/MessagesSubscribe.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // MessagesSubscribe.unit.test.js 3 | // 4 | // Created by David Rowe on 4 Oct 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NLPacketList from "../../../../src/domain/networking/NLPacketList"; 13 | import MessagesSubscribe from "../../../../src/domain/networking/packets/MessagesSubscribe"; 14 | import PacketType from "../../../../src/domain/networking/udt/PacketHeaders"; 15 | import UDT from "../../../../src/domain/networking/udt/UDT"; 16 | 17 | import { buffer2hex } from "../../../testUtils.js"; 18 | 19 | 20 | describe("MessagesSubscribe - unit tests", () => { 21 | 22 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 23 | 24 | test("Can write a MessagesSubscribe packet", () => { 25 | // eslint-disable-next-line max-len 26 | const EXPECTED_PACKET = "0000006000000000000000003a1600000000000000000000000000000000000076697263616469612e756e69742e74657374"; 27 | 28 | const packetList = MessagesSubscribe.write({ 29 | channel: "vircadia.unit.test" 30 | }); 31 | packetList.closeCurrentPacket(); 32 | 33 | expect(packetList instanceof NLPacketList).toBe(true); 34 | expect(packetList.getType()).toBe(PacketType.MessagesSubscribe); 35 | const packets = packetList.getPackets(); 36 | expect(packets).toHaveLength(1); 37 | 38 | const packet = packets[0]; 39 | const packetSize = packet.getDataSize(); 40 | expect(packetSize).toBeGreaterThan(0); 41 | expect(packetSize).toBeLessThanOrEqual(UDT.MAX_PACKET_SIZE); 42 | 43 | expect(packet.getMessageData().dataPosition).toBe(EXPECTED_PACKET.length / 2); 44 | expect(packet.getMessageData().packetSize).toBe(EXPECTED_PACKET.length / 2); 45 | expect(buffer2hex(packet.getMessageData().buffer.slice(0, EXPECTED_PACKET.length / 2))).toBe(EXPECTED_PACKET); 46 | }); 47 | 48 | }); 49 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/MessagesUnsubscribe.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // MessagesUnsubscribe.unit.test.js 3 | // 4 | // Created by David Rowe on 4 Oct 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NLPacketList from "../../../../src/domain/networking/NLPacketList"; 13 | import MessagesUnsubscribe from "../../../../src/domain/networking/packets/MessagesUnsubscribe"; 14 | import PacketType from "../../../../src/domain/networking/udt/PacketHeaders"; 15 | import UDT from "../../../../src/domain/networking/udt/UDT"; 16 | 17 | import { buffer2hex } from "../../../testUtils.js"; 18 | 19 | 20 | describe("MessagesUnsubscribe - unit tests", () => { 21 | 22 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 23 | 24 | describe("MessagesUnsubscribe - unit tests", () => { 25 | 26 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 27 | 28 | test("Can write a MessagesUnsubscribe packet", () => { 29 | // eslint-disable-next-line max-len 30 | const EXPECTED_PACKET = "0000006000000000000000003b1600000000000000000000000000000000000076697263616469612e756e69742e74657374"; 31 | 32 | const packetList = MessagesUnsubscribe.write({ 33 | channel: "vircadia.unit.test" 34 | }); 35 | packetList.closeCurrentPacket(); 36 | 37 | expect(packetList instanceof NLPacketList).toBe(true); 38 | expect(packetList.getType()).toBe(PacketType.MessagesUnsubscribe); 39 | const packets = packetList.getPackets(); 40 | expect(packets).toHaveLength(1); 41 | 42 | const packet = packets[0]; 43 | const packetSize = packet.getDataSize(); 44 | expect(packetSize).toBeGreaterThan(0); 45 | expect(packetSize).toBeLessThanOrEqual(UDT.MAX_PACKET_SIZE); 46 | 47 | expect(packet.getMessageData().dataPosition).toBe(EXPECTED_PACKET.length / 2); 48 | expect(packet.getMessageData().packetSize).toBe(EXPECTED_PACKET.length / 2); 49 | expect(buffer2hex(packet.getMessageData().buffer.slice(0, EXPECTED_PACKET.length / 2))).toBe(EXPECTED_PACKET); 50 | }); 51 | 52 | }); 53 | 54 | }); 55 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/MicrophoneAudioNoEcho.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // MicrophoneAudioNoEcho.unit.test.js 3 | // 4 | // Created by David Rowe on 26 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NLPacket from "../../../../src/domain/networking/NLPacket"; 13 | import MicrophoneAudioNoEcho from "../../../../src/domain/networking/packets/MicrophoneAudioNoEcho"; 14 | import PacketType from "../../../../src/domain/networking/udt/PacketHeaders"; 15 | import UDT from "../../../../src/domain/networking/udt/UDT"; 16 | 17 | import { buffer2hex } from "../../../testUtils.js"; 18 | 19 | 20 | describe("MicrophoneAudioNoEcho - unit tests", () => { 21 | 22 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 23 | 24 | test("Can write a MicrophoneAudioNoEcho packet", () => { 25 | // eslint-disable-next-line max-len 26 | const EXPECTED_PACKET = "0000000009180000000000000000000000000000000000001700040000006f707573009a99993f9a9959403333b340cdcc4c3e9a99993e0000003fcdcccc3d0000c84200004843000096430000003f0000003f0000004001020304"; 27 | 28 | const packet = MicrophoneAudioNoEcho.write({ 29 | sequenceNumber: 23, 30 | codecName: "opus", 31 | isStereo: false, 32 | audioPosition: { x: 1.2, y: 3.4, z: 5.6 }, 33 | audioOrientation: { x: 0.2, y: 0.3, z: 0.5, w: 0.1 }, 34 | avatarBoundingBoxCorner: { x: 100.0, y: 200.0, z: 300.0 }, 35 | avatarBoundingBoxScale: { x: 0.5, y: 0.5, z: 2.0 }, 36 | audioBuffer: new Uint8Array([1, 2, 3, 4]) 37 | }); 38 | 39 | expect(packet instanceof NLPacket).toBe(true); 40 | expect(packet.getType()).toBe(PacketType.MicrophoneAudioNoEcho); 41 | const packetSize = packet.getDataSize(); 42 | expect(packetSize).toBe(packet.getMessageData().dataPosition); 43 | expect(packetSize).toBeGreaterThan(0); 44 | expect(packetSize).toBeLessThan(UDT.MAX_PACKET_SIZE); 45 | 46 | expect(packetSize).toBe(EXPECTED_PACKET.length / 2); 47 | expect(buffer2hex(packet.getMessageData().buffer.slice(0, packetSize))).toBe(EXPECTED_PACKET); 48 | }); 49 | 50 | }); 51 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/MixedAudio.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // MixedAudio.unit.test.js 3 | // 4 | // Created by David Rowe on 14 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import MixedAudio from "../../../../src/domain/networking/packets/MixedAudio"; 13 | 14 | 15 | describe("MixedAudio - unit tests", () => { 16 | 17 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 18 | 19 | test("Can read a MixedAudio packet", () => { 20 | // eslint-disable-next-line max-len 21 | const MESSAGE_TEXT = "4c02000008184bd416e23467a9c1681d77d7529c606c16fd3202040000006f707573d478b652dce3a3c3fe0c05cc6334521330e044a29856fe649b4f1e3b422b7c85a8dbab2857656ff441f1668a18aa54d083a84e92d7d806a048e5a03ced1e9bd316ed920d9c07d02fadda6a07a6cabf6a66fb10f09736ce15c5dcd7093a2d887c9d2f3bc72c611ed66245c00a7e6cce0624a7a7465ccf8f8c076ab6ceaac71579da23d10ce16b8c8e8b087987224d934f5b717a5a3f94fa8b5134f86f32c85c52f20e6484dbed7e63cafc38d46ada337f"; 22 | const MESSAGE_START = 24; 23 | const arrayBuffer = new ArrayBuffer(MESSAGE_TEXT.length / 2); 24 | const uint8Array = new Uint8Array(arrayBuffer); 25 | for (let i = 0, length = arrayBuffer.byteLength; i < length; i++) { 26 | uint8Array[i] = Number.parseInt(MESSAGE_TEXT.substr(i * 2, 2), 16); 27 | } 28 | const dataView = new DataView(arrayBuffer, MESSAGE_START); 29 | 30 | const info = MixedAudio.read(dataView); 31 | expect(info.sequenceNumber).toBeGreaterThanOrEqual(0); 32 | expect(info.codecName).toBe("opus"); 33 | expect(info.numAudioSamples).toBe(240); 34 | expect(info.audioBuffer.byteLength).toBeGreaterThan(0); 35 | }); 36 | 37 | }); 38 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/NegotiateAudioFormat.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // DomainListRequest.unit.test.js 3 | // 4 | // Created by David Rowe on 28 Jul 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NLPacket from "../../../../src/domain/networking/NLPacket"; 13 | import NegotiateAudioFormat from "../../../../src/domain/networking/packets/NegotiateAudioFormat"; 14 | import PacketType from "../../../../src/domain/networking/udt/PacketHeaders"; 15 | import UDT from "../../../../src/domain/networking/udt/UDT"; 16 | 17 | 18 | describe("NegotiateAudioFormat - unit tests", () => { 19 | 20 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 21 | 22 | 23 | test("Can write a NegotiateAudioFormat packet", () => { 24 | const codecs = [ 25 | "opus", 26 | "pcm", 27 | "zlib" 28 | ]; 29 | 30 | const packet = NegotiateAudioFormat.write({ 31 | codecs 32 | }); 33 | 34 | expect(packet instanceof NLPacket).toBe(true); 35 | expect(packet.getType()).toBe(PacketType.NegotiateAudioFormat); 36 | 37 | const packetSize = packet.getDataSize(); 38 | expect(packetSize).toBe(packet.getMessageData().dataPosition); 39 | expect(packetSize).toBeGreaterThan(0); 40 | expect(packetSize).toBeLessThan(UDT.MAX_PACKET_SIZE); 41 | 42 | const PACKET_HEADER_SIZE = 8; 43 | const MD5_VERIFICATION_SIZE = 16; 44 | expect(packetSize).toBe(PACKET_HEADER_SIZE + MD5_VERIFICATION_SIZE 45 | + 1 // Number of codecs. 46 | + 4 * codecs.length // lengths for each codec. 47 | + codecs.join("").length); // UTF8 chars for each codec. 48 | }); 49 | 50 | }); 51 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/NodeKickRequest.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // NodeKickRequest.unit.test.js 3 | // 4 | // Created by David Rowe on 21 Jan 2023. 5 | // Copyright 2023 Vircadia contributors. 6 | // Copyright 2023 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NodeKickRequest from "../../../../src/domain/networking/packets/NodeKickRequest"; 13 | import PacketType from "../../../../src/domain/networking/udt/PacketHeaders"; 14 | import NLPacket from "../../../../src/domain/networking/NLPacket"; 15 | import Uuid from "../../../../src/domain/shared/Uuid"; 16 | 17 | import { buffer2hex } from "../../../testUtils"; 18 | 19 | 20 | describe("NodeKickRequest - unit tests", () => { 21 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 22 | 23 | test("Can write a NodeKickRequest packet", () => { 24 | const EXPECTED_PACKET = "00000040431600005dfe0ae4ac1440c8b09354d9d44a15e103000000"; 25 | const packet = NodeKickRequest.write({ 26 | nodeID: new Uuid(BigInt("0x5dfe0ae4ac1440c8b09354d9d44a15e1")), 27 | banFlags: 3 28 | }); 29 | 30 | expect(packet instanceof NLPacket).toBe(true); 31 | expect(packet.getType()).toBe(PacketType.NodeKickRequest); 32 | const packetSize = packet.getDataSize(); 33 | expect(packetSize).toBe(packet.getMessageData().dataPosition); 34 | expect(packetSize).toBe(EXPECTED_PACKET.length / 2); 35 | expect(buffer2hex(packet.getMessageData().buffer.slice(0, packetSize))).toBe(EXPECTED_PACKET); 36 | expect(packet.getMessageData().dataPosition).toBe(packetSize); 37 | expect(packet.getMessageData().packetSize).toBe(packetSize); 38 | }); 39 | 40 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 41 | }); 42 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/NodeMuteRequest.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // NodeMuteRequest.unit.test.js 3 | // 4 | // Created by David Rowe on 21 Jan 2023. 5 | // Copyright 2023 Vircadia contributors. 6 | // Copyright 2023 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NodeMuteRequest from "../../../../src/domain/networking/packets/NodeMuteRequest"; 13 | import PacketType from "../../../../src/domain/networking/udt/PacketHeaders"; 14 | import NLPacket from "../../../../src/domain/networking/NLPacket"; 15 | import Uuid from "../../../../src/domain/shared/Uuid"; 16 | 17 | import { buffer2hex } from "../../../testUtils"; 18 | 19 | 20 | describe("NodeMuteRequest - unit tests", () => { 21 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 22 | 23 | test("Can write a NodeMuteRequest packet", () => { 24 | const EXPECTED_PACKET = "0000004044160000b46514e45921436ab011ae5f987bd66e"; 25 | const packet = NodeMuteRequest.write({ 26 | nodeID: new Uuid(BigInt("0xb46514e45921436ab011ae5f987bd66e")) 27 | }); 28 | 29 | expect(packet instanceof NLPacket).toBe(true); 30 | expect(packet.getType()).toBe(PacketType.NodeMuteRequest); 31 | const packetSize = packet.getDataSize(); 32 | expect(packetSize).toBe(packet.getMessageData().dataPosition); 33 | expect(packetSize).toBe(EXPECTED_PACKET.length / 2); 34 | expect(buffer2hex(packet.getMessageData().buffer.slice(0, packetSize))).toBe(EXPECTED_PACKET); 35 | expect(packet.getMessageData().dataPosition).toBe(packetSize); 36 | expect(packet.getMessageData().packetSize).toBe(packetSize); 37 | }); 38 | 39 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 40 | }); 41 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/Ping.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // Ping.unit.test.js 3 | // 4 | // Created by David Rowe on 6 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import Ping from "../../../../src/domain/networking/packets/Ping"; 13 | 14 | 15 | describe("Ping - unit tests", () => { 16 | 17 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 18 | 19 | 20 | test("Can read a Ping packet", () => { 21 | /* eslint-disable-next-line max-len */ 22 | const MESSAGE_TEXT = "00000000031200000000000000000000000000000000000002769cc3694acb05000500000000000000"; 23 | const MESSAGE_START = 24; 24 | 25 | const arrayBuffer = new ArrayBuffer(MESSAGE_TEXT.length / 2); 26 | const uint8Array = new Uint8Array(arrayBuffer); 27 | for (let i = 0, length = arrayBuffer.byteLength; i < length; i++) { 28 | uint8Array[i] = Number.parseInt(MESSAGE_TEXT.substr(i * 2, 2), 16); 29 | } 30 | const dataView = new DataView(arrayBuffer, MESSAGE_START); 31 | 32 | const info = Ping.read(dataView); 33 | 34 | expect(info.pingType).toBe(2); 35 | expect(info.timestamp).toBe(1630895345998966n); 36 | expect(info.connectionID).toBe(5n); 37 | }); 38 | 39 | }); 40 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/PingReply.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // PingReply.unit.test.js 3 | // 4 | // Created by David Rowe on 7 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NLPacket from "../../../../src/domain/networking/NLPacket"; 13 | import PingType from "../../../../src/domain/networking/PingType"; 14 | import PingReply from "../../../../src/domain/networking/packets/PingReply"; 15 | import PacketType from "../../../../src/domain/networking/udt/PacketHeaders"; 16 | import UDT from "../../../../src/domain/networking/udt/UDT"; 17 | 18 | 19 | describe("PingReply - unit tests", () => { 20 | 21 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 22 | 23 | 24 | test("Can write a PingReply packet", () => { 25 | const packet = PingReply.write({ 26 | pingType: PingType.Public, 27 | timestampPing: (BigInt(Date.now()) - 200n) * 1000n, 28 | timestampReply: BigInt(Date.now()) * 1000n 29 | }); 30 | expect(packet instanceof NLPacket).toBe(true); 31 | expect(packet.getType()).toBe(PacketType.PingReply); 32 | const packetSize = packet.getDataSize(); 33 | expect(packetSize).toBe(packet.getMessageData().dataPosition); 34 | expect(packetSize).toBeGreaterThan(0); 35 | expect(packetSize).toBeLessThan(UDT.MAX_PACKET_SIZE); 36 | }); 37 | 38 | }); 39 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/RequestsDomainListData.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // RequestsDomainListData.unit.test.js 3 | // 4 | // Created by David Rowe on 28 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import RequestsDomainListData from "../../../../src/domain/networking/packets/RequestsDomainListData"; 13 | import PacketType from "../../../../src/domain/networking/udt/PacketHeaders"; 14 | import NLPacket from "../../../../src/domain/networking/NLPacket"; 15 | 16 | import { buffer2hex } from "../../../testUtils"; 17 | 18 | 19 | describe("RequestsDomainListData - unit tests", () => { 20 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 21 | 22 | test("Can write an RequestsDomainListData packet", () => { 23 | const EXPECTED_PACKET = "00000040491600000000000000000000000000000000000001"; 24 | const packet = RequestsDomainListData.write({ 25 | isRequesting: true 26 | }); 27 | 28 | expect(packet instanceof NLPacket).toBe(true); 29 | expect(packet.getType()).toBe(PacketType.RequestsDomainListData); 30 | const packetSize = packet.getDataSize(); 31 | expect(packetSize).toBe(packet.getMessageData().dataPosition); 32 | expect(packetSize).toBe(EXPECTED_PACKET.length / 2); 33 | expect(buffer2hex(packet.getMessageData().buffer.slice(0, packetSize))).toBe(EXPECTED_PACKET); 34 | expect(packet.getMessageData().dataPosition).toBe(packetSize); 35 | expect(packet.getMessageData().packetSize).toBe(packetSize); 36 | }); 37 | 38 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 39 | }); 40 | -------------------------------------------------------------------------------- /tests/domain/networking/packets/SelectedAudioFormat.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // SelectedAudioFormat.unit.test.js 3 | // 4 | // Created by David Rowe on 10 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import SelectedAudioFormat from "../../../../src/domain/networking/packets/SelectedAudioFormat"; 13 | 14 | 15 | describe("SelectedAudioFormat - unit tests", () => { 16 | 17 | test("Can read a SelectedAudioFormat packet", () => { 18 | const MESSAGE_HEX = "030000004116762365a1595902bd988de6429deea29c0816040000006f707573"; 19 | const MESSAGE_START = 24; 20 | 21 | const arrayBuffer = new ArrayBuffer(MESSAGE_HEX.length / 2); 22 | const uint8Array = new Uint8Array(arrayBuffer); 23 | for (let i = 0, length = arrayBuffer.byteLength; i < length; i++) { 24 | uint8Array[i] = Number.parseInt(MESSAGE_HEX.substr(i * 2, 2), 16); 25 | } 26 | const dataView = new DataView(arrayBuffer, MESSAGE_START); 27 | 28 | const info = SelectedAudioFormat.read(dataView); 29 | 30 | expect(info.selectedCodecName).toBe("opus"); 31 | }); 32 | 33 | }); 34 | -------------------------------------------------------------------------------- /tests/domain/networking/udt/ControlPacket.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // ControlPacket.unit.test.js 3 | // 4 | // Created by David Rowe on 9 Jun 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import SockAddr from "../../../../src/domain/networking/SockAddr"; 13 | import ControlPacket from "../../../../src/domain/networking/udt/ControlPacket"; 14 | import SequenceNumber from "../../../../src/domain/networking/udt/SequenceNumber"; 15 | 16 | import { buffer2hex } from "../../../testUtils.js"; 17 | 18 | 19 | describe("ControlPacket - unit tests", () => { 20 | 21 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 22 | 23 | test("Can access the ControlPacket type values", () => { 24 | expect(ControlPacket.ACK).toBe(0); 25 | expect(ControlPacket.Handshake).toBe(1); 26 | expect(ControlPacket.HandshakeACK).toBe(2); 27 | expect(ControlPacket.HandshakeRequest).toBe(3); 28 | }); 29 | 30 | test("Can write a Handshake packet", () => { 31 | const EXPECTED_PACKET = "0000018007000000"; 32 | const HANDSHAKE_PAYLOAD_BYTES = 4; 33 | const initialSequenceNumber = new SequenceNumber(7); 34 | const handshakePacket = ControlPacket.create(ControlPacket.Handshake, HANDSHAKE_PAYLOAD_BYTES); 35 | handshakePacket.writeSequenceNumber(initialSequenceNumber); 36 | 37 | expect(handshakePacket.getType()).toBe(ControlPacket.Handshake); 38 | expect(handshakePacket.getMessageData().data.byteLength).toBe(EXPECTED_PACKET.length / 2); 39 | expect(buffer2hex(handshakePacket.getMessageData().buffer)).toBe(EXPECTED_PACKET); 40 | }); 41 | 42 | test("Can read a Handshake packet", () => { 43 | const RECEIVED_PACKET = "0000018007000000"; 44 | 45 | const arrayBuffer = new ArrayBuffer(RECEIVED_PACKET.length / 2); 46 | const uint8Array = new Uint8Array(arrayBuffer); 47 | for (let i = 0, length = arrayBuffer.byteLength; i < length; i++) { 48 | uint8Array[i] = Number.parseInt(RECEIVED_PACKET.substr(i * 2, 2), 16); 49 | } 50 | const dataView = new DataView(arrayBuffer, 0); 51 | 52 | const controlPacket = ControlPacket.fromReceivedPacket(dataView, dataView.byteLength, new SockAddr()); 53 | expect(controlPacket.getType()).toBe(ControlPacket.Handshake); 54 | const sequenceNumber = controlPacket.readSequenceNumber(); 55 | expect(sequenceNumber.value).toBe(7); 56 | }); 57 | 58 | }); 59 | -------------------------------------------------------------------------------- /tests/domain/networking/udt/PacketHeaders.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // PacketHeaders.unit.test.js 3 | // 4 | // Created by David Rowe on 7 Jun 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 13 | 14 | import PacketType, { protocolVersionsSignature } from "../../../../src/domain/networking/udt/PacketHeaders"; 15 | 16 | 17 | describe("PacketType - unit tests", () => { 18 | 19 | test("PacketType values can be accessed", () => { 20 | expect(PacketType.Unknown).toBe(0); 21 | expect(PacketType.DomainConnectRequestPending).toBe(1); 22 | expect(PacketType.DomainListRequest).toBe(13); 23 | expect(PacketType.WebRTCSignaling).toBe(105); 24 | }); 25 | 26 | test("Packet version values can be accessed", () => { 27 | expect(PacketType.versionForPacketType(PacketType.DomainConnectRequest)).toBe(27); 28 | }); 29 | 30 | test("Non-verified packets values can be accessed", () => { 31 | const nonVerifiedPackets = PacketType.getNonVerifiedPackets(); 32 | expect(nonVerifiedPackets.has(PacketType.DomainSettings)).toBe(false); 33 | expect(nonVerifiedPackets.has(PacketType.NodeMuteRequest)).toBe(true); 34 | }); 35 | 36 | test("Non-sourced packets values can be accessed", () => { 37 | const nonSourcedPackets = PacketType.getNonSourcedPackets(); 38 | expect(nonSourcedPackets.has(PacketType.DomainListRequest)).toBe(false); 39 | expect(nonSourcedPackets.has(PacketType.DomainList)).toBe(true); 40 | }); 41 | 42 | test("The protocol version is a 16-byte value", () => { 43 | const protocolVersion = protocolVersionsSignature(); 44 | expect(protocolVersion instanceof Uint8Array).toBe(true); 45 | expect(protocolVersion.byteLength).toBe(16); 46 | }); 47 | 48 | }); 49 | -------------------------------------------------------------------------------- /tests/domain/networking/udt/Socket.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // Socket.unit.test.js 3 | // 4 | // Created by David Rowe on 28 Jun 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NodeType from "../../../../src/domain/networking/NodeType"; 13 | import Socket from "../../../../src/domain/networking/udt/Socket"; 14 | import Url from "../../../../src/domain/shared/Url"; 15 | 16 | import TestConfig from "../../../test.config.js"; 17 | 18 | 19 | describe("Socket - unit tests", () => { 20 | 21 | test("Check initial state", () => { 22 | expect(Socket.UNCONNECTED).toBe(0); 23 | expect(Socket.CONNECTING).toBe(1); 24 | expect(Socket.CONNECTED).toBe(2); 25 | const socket = new Socket(); 26 | expect(socket.getSocketState(new Url(TestConfig.SERVER_SIGNALING_SOCKET_URL), NodeType.DomainServer)) 27 | .toBe(Socket.UNCONNECTED); 28 | }); 29 | 30 | // The Socket class is further exercised by DomainServer.unit.test.js. 31 | 32 | }); 33 | -------------------------------------------------------------------------------- /tests/domain/networking/udt/UDT.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // UDT.unit.test.js 3 | // 4 | // Created by David Rowe on 13 Jun 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 13 | 14 | import UDT from "../../../../src/domain/networking/udt/UDT"; 15 | 16 | 17 | describe("UDT - unit tests", () => { 18 | 19 | test("UDT values can be accessed", () => { 20 | expect(UDT.MAX_PACKET_SIZE).toBe(1464); 21 | expect(UDT.LITTLE_ENDIAN).toBe(true); 22 | expect(UDT.BIG_ENDIAN).toBe(false); 23 | }); 24 | 25 | }); 26 | -------------------------------------------------------------------------------- /tests/domain/networking/webrtc/WebRTCSocket.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // WebRTCSocket.unit.test.js 3 | // 4 | // Created by David Rowe on 28 Jun 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import NodeType from "../../../../src/domain/networking/NodeType"; 13 | import WebRTCSocket from "../../../../src/domain/networking/webrtc/WebRTCSocket"; 14 | 15 | 16 | describe("WebRTCSocket - unit tests", () => { 17 | 18 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 19 | 20 | 21 | test("Check initial state", () => { 22 | expect(WebRTCSocket.UNCONNECTED).toBe(0); 23 | expect(WebRTCSocket.CONNECTED).toBe(3); 24 | const webrtcSocket = new WebRTCSocket(); 25 | expect(webrtcSocket.hasPendingDatagrams()).toBe(false); 26 | expect(webrtcSocket.state("", NodeType.DomainServer)).toBe(WebRTCSocket.UNCONNECTED); 27 | }); 28 | 29 | test("Reading a datagram when there aren't any to read fails", () => { 30 | const webrtcSocket = new WebRTCSocket(); 31 | const datagram = { buffer: undefined, sender: undefined }; 32 | expect(webrtcSocket.readDatagram(datagram)).toBe(-1); 33 | }); 34 | 35 | test("Reading a datagram when not connected fails", () => { 36 | const webrtcSocket = new WebRTCSocket(); 37 | const datagram = new ArrayBuffer(100); 38 | expect(webrtcSocket.writeDatagram(datagram, 0)).toBe(-1); 39 | }); 40 | 41 | }); 42 | -------------------------------------------------------------------------------- /tests/domain/octree/OctreePacketProcessor.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // OctreePacketProcessor.unit.test.js 3 | // 4 | // Created by Julien Merzoug on 18 May 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import { webcrypto } from "crypto"; 13 | globalThis.crypto = webcrypto; 14 | 15 | import AccountManager from "../../../src/domain/networking/AccountManager"; 16 | import AddressManager from "../../../src/domain/networking/AddressManager"; 17 | import ContextManager from "../../../src/domain/shared/ContextManager"; 18 | import NodeList from "../../../src/domain/networking/NodeList"; 19 | import OctreePacketProcessor from "../../../src/domain/octree/OctreePacketProcessor"; 20 | 21 | 22 | describe("OctreePacketProcessor - unit tests", () => { 23 | 24 | test("The OctreePacketProcessor can be obtained from the ContextManager", () => { 25 | const contextID = ContextManager.createContext(); 26 | ContextManager.set(contextID, AccountManager, contextID); 27 | ContextManager.set(contextID, AddressManager); 28 | ContextManager.set(contextID, NodeList, contextID); 29 | ContextManager.set(contextID, OctreePacketProcessor, contextID); 30 | const octreePacketProcessor = ContextManager.get(contextID, OctreePacketProcessor); 31 | expect(octreePacketProcessor instanceof OctreePacketProcessor).toBe(true); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /tests/domain/shared/AudioHelpers.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // AudioHelpers.unit.test.js 3 | // 4 | // Created by David Rowe on 24 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AudioHelpers from "../../../src/domain/shared/AudioHelpers"; 13 | 14 | 15 | describe("AudioHelpers - unit tests", () => { 16 | 17 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 18 | 19 | test("packFloatGainToByte() output is correct", () => { 20 | expect(AudioHelpers.packFloatGainToByte(0)).toBe(0); 21 | expect(AudioHelpers.packFloatGainToByte(0.604)).toBe(186); 22 | expect(AudioHelpers.packFloatGainToByte(1000)).toBe(255); 23 | }); 24 | 25 | test("unpackFloatGainFromByte - unit tests", () => { 26 | expect(AudioHelpers.unpackFloatGainFromByte(255)).toBeCloseTo(31.6229, 3); 27 | expect(AudioHelpers.unpackFloatGainFromByte(164)).toBeCloseTo(0.167881, 5); 28 | expect(AudioHelpers.unpackFloatGainFromByte(16)).toBeCloseTo(3.34964e-05, 5); 29 | expect(AudioHelpers.unpackFloatGainFromByte(0)).toBe(0); 30 | }); 31 | 32 | }); 33 | -------------------------------------------------------------------------------- /tests/domain/shared/AvatarConstants.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // AvatarConstants.unit.test.js 3 | // 4 | // Created by David Rowe on 9 Jun 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AvatarConstants from "../../../src/domain/shared/AvatarConstants"; 13 | 14 | 15 | describe("AvatarConstants - unit tests", () => { 16 | 17 | test("Can access avatar constants", () => { 18 | // Test a handful constants, just to make that constants can be accessed as intended. 19 | 20 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 21 | 22 | expect(AvatarConstants.DEFAULT_AVATAR_HEIGHT).toEqual(1.755); 23 | expect(AvatarConstants.MIN_AVATAR_SCALE).toEqual(0.005); 24 | 25 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 26 | }); 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /tests/domain/shared/AvatarPriorityMode.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // AvatarPriorityMode.unit.test.js 3 | // 4 | // Created by David Rowe on 13 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import AvatarPriorityMode from "../../../src/domain/shared/AvatarPriorityMode"; 13 | 14 | 15 | describe("AvatarPriorityMode - unit tests", () => { 16 | 17 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 18 | 19 | test("Can use AvatarPriorityMode values", () => { 20 | expect(AvatarPriorityMode.INHERIT).toBe(0); 21 | expect(AvatarPriorityMode.CROWD).toBe(1); 22 | expect(AvatarPriorityMode.HERO).toBe(2); 23 | expect(AvatarPriorityMode.ITEM_COUNT).toBe(3); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /tests/domain/shared/BitVectorHelpers.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // BitVectorHelpers.unit.test.js 3 | // 4 | // Created by David Rowe on 24 Jun 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import BitVectorHelpers from "../../../src/domain/shared/BitVectorHelpers"; 13 | import { buffer2hex } from "../../testUtils"; 14 | 15 | 16 | describe("BitVectorHelpers - unit tests", () => { 17 | 18 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 19 | 20 | test("Can calculate the number of bytes needed for a number of bits", () => { 21 | expect(BitVectorHelpers.calcBitVectorSize(0)).toBe(0); 22 | expect(BitVectorHelpers.calcBitVectorSize(1)).toBe(1); 23 | expect(BitVectorHelpers.calcBitVectorSize(7)).toBe(1); 24 | expect(BitVectorHelpers.calcBitVectorSize(8)).toBe(1); 25 | expect(BitVectorHelpers.calcBitVectorSize(9)).toBe(2); 26 | expect(BitVectorHelpers.calcBitVectorSize(31)).toBe(4); 27 | expect(BitVectorHelpers.calcBitVectorSize(32)).toBe(4); 28 | expect(BitVectorHelpers.calcBitVectorSize(33)).toBe(5); 29 | }); 30 | 31 | test("Can write a bit vector for an array and an evaluation function", () => { 32 | const buffer = new ArrayBuffer(4); 33 | const data = new DataView(buffer); 34 | const bytesWritten = BitVectorHelpers.writeBitVector(data, 1, 35 | [null, 1, {}, 1, "", null, null, 1, null, 2, 2], 36 | (value) => { 37 | return value !== null; 38 | } 39 | ); 40 | const bytes = buffer2hex(buffer); 41 | expect(bytesWritten).toBe(2); 42 | expect(bytes).toBe("009e0600"); 43 | }); 44 | 45 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 46 | 47 | }); 48 | -------------------------------------------------------------------------------- /tests/domain/shared/ByteCountCoded.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // ByteCountCoded.unit.test.js 3 | // 4 | // Created by Julien Merzoug on 01 June 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import ByteCountCoded from "../../../src/domain/shared/ByteCountCoded"; 13 | 14 | 15 | describe("ByteCountCoded - unit tests", () => { 16 | 17 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 18 | 19 | test("Can decode byte count encoded data", () => { 20 | 21 | // 1 byte encoded. 22 | let bufferHex = "10dc"; 23 | let bufferArray = new Uint8Array(bufferHex.match(/[\da-f]{2}/giu).map(function (hex) { 24 | return parseInt(hex, 16); 25 | })); 26 | let data = new DataView(bufferArray.buffer); 27 | let codec = new ByteCountCoded(); 28 | let bytesConsumed = codec.decode(data, bufferArray.length); 29 | 30 | expect(bytesConsumed).toBe(1); 31 | expect(codec.data).toBe(4); 32 | 33 | // 2 bytes encoded. 34 | bufferHex = "8bfafffe3f"; 35 | bufferArray = new Uint8Array(bufferHex.match(/[\da-f]{2}/giu).map(function (hex) { 36 | return parseInt(hex, 16); 37 | })); 38 | data = new DataView(bufferArray.buffer); 39 | codec = new ByteCountCoded(); 40 | bytesConsumed = codec.decode(data, bufferArray.length); 41 | 42 | expect(bytesConsumed).toBe(2); 43 | expect(codec.data).toBe(6132); 44 | 45 | // 3 bytes encoded. 46 | bufferHex = "d20e80ffff8fff"; 47 | bufferArray = new Uint8Array(bufferHex.match(/[\da-f]{2}/giu).map(function (hex) { 48 | return parseInt(hex, 16); 49 | })); 50 | data = new DataView(bufferArray.buffer); 51 | codec = new ByteCountCoded(); 52 | bytesConsumed = codec.decode(data, bufferArray.length); 53 | 54 | expect(bytesConsumed).toBe(3); 55 | expect(codec.data).toBe(11785); 56 | }); 57 | 58 | }); 59 | -------------------------------------------------------------------------------- /tests/domain/shared/ComponentMode.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // ComponentMode.unit.test.js 3 | // 4 | // Created by David Rowe on 13 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import ComponentMode from "../../../src/domain/shared/ComponentMode"; 13 | 14 | 15 | describe("ComponentMode - unit tests", () => { 16 | 17 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 18 | 19 | test("Can use ComponentMode values", () => { 20 | expect(ComponentMode.INHERIT).toBe(0); 21 | expect(ComponentMode.DISABLED).toBe(1); 22 | expect(ComponentMode.ENABLED).toBe(2); 23 | expect(ComponentMode.ITEM_COUNT).toBe(3); 24 | }); 25 | 26 | }); 27 | -------------------------------------------------------------------------------- /tests/domain/shared/DataViewExtensions.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // DataViewExtensions.unit.test.js 3 | // 4 | // Created by David Rowe on 16 Jun 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 13 | 14 | import "../../../src/domain/shared/DataViewExtensions"; 15 | 16 | 17 | describe("DataView - unit tests", () => { 18 | 19 | test("Can write and read a Uint128 value big-endian", () => { 20 | const arrayBuffer = new ArrayBuffer(32); 21 | const dataView = new DataView(arrayBuffer); 22 | const offset = 4; 23 | const value = 2n ** 127n + 3n; // Most-significant and 2 least-significant bits. 24 | dataView.setBigUint128(offset, value); 25 | expect(dataView.getBigUint128(offset, false)).toBe(value); 26 | }); 27 | 28 | test("Can write and read a Uint128 value little-endian", () => { 29 | const arrayBuffer = new ArrayBuffer(32); 30 | const dataView = new DataView(arrayBuffer); 31 | const offset = 4; 32 | const value = 2n ** 127n + 3n; // Most-significant and 2 least-significant bits. 33 | dataView.setBigUint128(offset, value, true); 34 | expect(dataView.getBigUint128(offset, true)).toBe(value); 35 | }); 36 | 37 | test("A too-large Uint128 value overflows to 0", () => { 38 | const arrayBuffer = new ArrayBuffer(32); 39 | const dataView = new DataView(arrayBuffer); 40 | const MAX_U128_VALUE = 2n ** 128n - 1n; 41 | const offset = 4; 42 | dataView.setBigUint128(offset, MAX_U128_VALUE + 1n); 43 | expect(dataView.getBigUint128(offset)).toBe(0n); 44 | }); 45 | 46 | }); 47 | -------------------------------------------------------------------------------- /tests/domain/shared/HighResolutionClock.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // HighResolutionClock.unit.test.js 3 | // 4 | // Created by David Rowe on 5 Oct 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import HighResolutionClock from "../../../src/domain/shared/HighResolutionClock"; 13 | 14 | 15 | describe("HighResolutionClock - unit tests", () => { 16 | 17 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 18 | 19 | test("Can get the current timestamp value", () => { 20 | const timestamp = HighResolutionClock.now(); 21 | expect(typeof timestamp).toBe("bigint"); 22 | expect(timestamp > 0n).toBe(true); 23 | }); 24 | 25 | }); 26 | -------------------------------------------------------------------------------- /tests/domain/shared/ModerationFlags.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // ModerationFlags.unit.test.js 3 | // 4 | // Created by David Rowe on 22 Jan 2023. 5 | // Copyright 2023 Vircadia contributors. 6 | // Copyright 2023 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import ModerationFlags from "../../../src/domain/shared/ModerationFlags"; 13 | 14 | 15 | describe("ModerationFlags - unit tests", () => { 16 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 17 | 18 | test("Can access the ban flag values", () => { 19 | expect(ModerationFlags.BanFlags.NO_BAN).toBe(0); 20 | expect(ModerationFlags.BanFlags.BAN_BY_USERNAME).toBe(1); 21 | expect(ModerationFlags.BanFlags.BAN_BY_FINGERPRINT).toBe(2); 22 | expect(ModerationFlags.BanFlags.BAN_BY_IP).toBe(4); 23 | }); 24 | 25 | test("Can get the default ban flags value", () => { 26 | expect(ModerationFlags.getDefaultBanFlags()).toBe(3); 27 | }); 28 | 29 | /* eslint-enable @typescript-eslint/no-magic-numbers */ 30 | }); 31 | -------------------------------------------------------------------------------- /tests/domain/shared/ShapeType.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // ShapeType.unit.test.js 3 | // 4 | // Created by David Rowe on 12 Aug 2022. 5 | // Copyright 2022 Vircadia contributors. 6 | // Copyright 2022 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import ShapeType from "../../../src/domain/shared/ShapeType"; 13 | 14 | 15 | describe("ShapeType - unit tests", () => { 16 | 17 | /* eslint-disable @typescript-eslint/no-magic-numbers */ 18 | 19 | test("Can use ShapeType values", () => { 20 | expect(ShapeType.NONE).toBe(0); 21 | expect(ShapeType.MULTISPHERE).toBe(17); 22 | }); 23 | 24 | }); 25 | -------------------------------------------------------------------------------- /tests/domain/shared/assert.unit.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // assert.unit.test.js 3 | // 4 | // Created by David Rowe on 9 Jun 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | import assert from "../../../src/domain/shared/assert"; 13 | 14 | 15 | describe("assert - unit tests", () => { 16 | 17 | // Suppress console.assert messages from being displayed. 18 | // eslint-disable-next-line @typescript-eslint/no-empty-function 19 | const consoleAssert = jest.spyOn(console, "assert").mockImplementation(() => { }); 20 | 21 | test("An assertion doesn't fire if the assertion value is true", () => { 22 | let asserted = false; 23 | try { 24 | assert(true, "Asserted when true"); 25 | } catch (e) { 26 | asserted = true; 27 | } 28 | expect(asserted).toBe(false); 29 | }); 30 | 31 | test("An assertion fires if the assertion value is false", () => { 32 | let asserted = false; 33 | try { 34 | assert(false, "Asserted when false"); 35 | } catch (e) { 36 | asserted = true; 37 | } 38 | expect(asserted).toBe(true); 39 | }); 40 | 41 | consoleAssert.mockReset(); 42 | 43 | }); 44 | -------------------------------------------------------------------------------- /tests/test.config.js: -------------------------------------------------------------------------------- 1 | import TestConfig from "./test.config.json"; 2 | 3 | const env = process && process.env || {}; 4 | 5 | for (const key of Object.keys(TestConfig)) { 6 | const envKey = "VIRCADIA_" + key; 7 | if (typeof env[envKey] !== "undefined") { 8 | TestConfig[key] = env[envKey]; 9 | } 10 | } 11 | 12 | export default TestConfig; 13 | -------------------------------------------------------------------------------- /tests/test.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "SERVER_DOMAIN_URL": "ws://localhost/", 3 | "SERVER_SIGNALING_SOCKET_URL": "ws://127.0.0.1:40102/", 4 | "SERVER_SIGNALING_SOCKET_INVALID_URL": "ws://0.0.0.0:0/" 5 | } 6 | -------------------------------------------------------------------------------- /tests/testUtils.js: -------------------------------------------------------------------------------- 1 | // 2 | // testUtils.js 3 | // 4 | // Created by David Rowe on 12 Sep 2021. 5 | // Copyright 2021 Vircadia contributors. 6 | // Copyright 2021 DigiSomni LLC. 7 | // 8 | // Distributed under the Apache License, Version 2.0. 9 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 10 | // 11 | 12 | /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ 13 | 14 | function buffer2hex(buffer) { 15 | return [...new Uint8Array(buffer)] 16 | .map((x) => { 17 | return x.toString(16).padStart(2, "0"); // eslint-disable-line @typescript-eslint/no-magic-numbers 18 | }) 19 | .join(""); 20 | } 21 | 22 | export { buffer2hex }; 23 | -------------------------------------------------------------------------------- /tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "checkJs": false 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tsconfig.jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./docs/build", 4 | "allowJs": true, 5 | "target": "ESNext", 6 | "lib": [ "ES2021", "DOM" ], 7 | "module": "ES2020", 8 | "sourceMap": false, 9 | "esModuleInterop": true, 10 | "moduleResolution": "Node", 11 | "skipLibCheck": true, 12 | "preserveConstEnums": true, 13 | "useDefineForClassFields": true, 14 | 15 | // TypeScript 4.3 16 | "allowUnreachableCode": false, 17 | "allowUnusedLabels": false, 18 | "alwaysStrict": true, 19 | "noFallthroughCasesInSwitch": true, 20 | "noImplicitAny": true, 21 | "noImplicitOverride": true, 22 | "noImplicitReturns": true, 23 | "noImplicitThis": true, 24 | "noPropertyAccessFromIndexSignature": true, 25 | "noUncheckedIndexedAccess": true, 26 | "noUnusedLocals": true, 27 | "noUnusedParameters": true, 28 | "strictBindCallApply": true, 29 | "strictFunctionTypes": true, 30 | "strictNullChecks": true, 31 | "strictPropertyInitialization": true 32 | }, 33 | "include": [ 34 | "./src/**/*", 35 | "./typings/**/*" 36 | ], 37 | "exclude": [ 38 | "./node_modules/**/*" 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "allowJs": true, 5 | "checkJs": false, // Temporarily disable while unit and integration tests are JavaScript. 6 | "target": "ESNext", // ES2020+ required for BigInt literals. ESNext required for # methods and conditional constructors. 7 | "lib": [ "ES2021", "DOM" ], // ES2021+ required for WeakRef. 8 | "sourceMap": true, 9 | "declaration": true, 10 | "moduleResolution": "Node", 11 | "resolveJsonModule": true, 12 | "skipLibCheck": true, 13 | "esModuleInterop": true, 14 | "isolatedModules": false, // The audio worklets require this to be false. 15 | "preserveConstEnums": true, 16 | "useDefineForClassFields": true, // Required for ESNext. 17 | 18 | "module": "ES2020", // Required for worker-url. 19 | 20 | // TypeScript 4.3 21 | "allowUnreachableCode": false, 22 | "allowUnusedLabels": false, 23 | "alwaysStrict": true, 24 | "noFallthroughCasesInSwitch": true, 25 | "noImplicitAny": true, 26 | "noImplicitOverride": true, 27 | "noImplicitReturns": true, 28 | "noImplicitThis": true, 29 | "noPropertyAccessFromIndexSignature": true, 30 | "noUncheckedIndexedAccess": true, 31 | "noUnusedLocals": true, 32 | "noUnusedParameters": true, 33 | "strictBindCallApply": true, 34 | "strictFunctionTypes": true, 35 | "strictNullChecks": true, 36 | "strictPropertyInitialization": true 37 | }, 38 | "include": [ 39 | "./example/**/*", 40 | "./example/**/.eslintrc.js", 41 | "./mocks/**/*", 42 | "./src/**/*", 43 | "./tests/**/*", 44 | "./typings/**/*", 45 | "./.*.js", 46 | "./*.js", 47 | "./*.json" 48 | ], 49 | "exclude": [ 50 | "./build_scripts/**/*", 51 | "./node_modules/**/*" 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /typings/WebAudioTyping.d.ts: -------------------------------------------------------------------------------- 1 | // 2 | // WebAudioTyping.d.ts 3 | // 4 | // WebAudio typings missing from default typings. 5 | // https://github.com/microsoft/TypeScript/issues/28308 6 | // 7 | // Created by David Rowe on 18 Sep 2021. 8 | // Copyright 2021 Vircadia contributors. 9 | // Copyright 2021 DigiSomni LLC. 10 | // 11 | // Distributed under the Apache License, Version 2.0. 12 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html 13 | // 14 | 15 | // WEBRTC TODO: Try using https://www.npmjs.com/package/@types/audioworklet instead. 16 | 17 | /* eslint-disable @typescript-eslint/no-redeclare */ 18 | 19 | interface AudioWorkletProcessor { 20 | readonly port: MessagePort; 21 | process(inputs: Float32Array[][], outputs: Float32Array[][], parameters: Map): void; 22 | } 23 | 24 | declare const AudioWorkletProcessor: { 25 | prototype: AudioWorkletProcessor; 26 | new(options?: AudioWorkletNodeOptions): AudioWorkletProcessor; 27 | }; 28 | 29 | declare function registerProcessor( 30 | name: string, 31 | processorCtor: (new ( 32 | options?: AudioWorkletNodeOptions 33 | ) => AudioWorkletProcessor) & { 34 | parameterDescriptors?: AudioParamDescriptor[]; 35 | } 36 | ): undefined; 37 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); // eslint-disable-line 2 | const WorkerUrlPlugin = require("worker-url/plugin"); // eslint-disable-line 3 | 4 | module.exports = { 5 | entry: { 6 | Vircadia: "./src/Vircadia.ts" 7 | }, 8 | 9 | resolve: { 10 | extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"] 11 | }, 12 | 13 | experiments: { 14 | outputModule: true 15 | }, 16 | 17 | output: { 18 | filename: "[name].js", 19 | path: path.resolve(__dirname, "dist"), 20 | library: { 21 | type: "module" 22 | }, 23 | module: true, 24 | clean: true 25 | }, 26 | 27 | // Enable sourcemaps for debugging webpack's output. 28 | devtool: "source-map", 29 | 30 | plugins: [ new WorkerUrlPlugin() ], // eslint-disable-line 31 | 32 | module: { 33 | rules: [ 34 | 35 | // '.ts' and '.tsx' files are handled by 'ts-loader'. 36 | { test: /\.tsx?$/u, loader: "ts-loader" }, 37 | 38 | // '.js' files have sourcemaps re-processed by 'source-map-loader'. 39 | { test: /\.js$/u, loader: "source-map-loader" } 40 | 41 | ] 42 | } 43 | }; 44 | --------------------------------------------------------------------------------