├── LICENSE ├── server ├── .gitignore ├── .dockerignore ├── index.html ├── package.json ├── fly.toml ├── Dockerfile ├── main.js └── package-lock.json ├── assets ├── models │ ├── rocks.fbx │ ├── scene.bin │ ├── scene.glb │ ├── terr4.glb │ ├── paintbg.png │ ├── terrain.glb │ ├── explosion.png │ ├── heightmap.png │ ├── explosionold.png │ ├── rocktexture.jpg │ ├── terrain-draco-1.glb │ ├── terrain-draco-2.glb │ ├── GrassRockyAlbedo.jpg │ ├── textures │ │ ├── DL2X2_1_baseColor.png │ │ ├── Trank_bark_baseColor.jpeg │ │ ├── DL2X2_1_metallicRoughness.png │ │ └── Trank_bark_metallicRoughness.png │ └── tree.gltf ├── skybox │ ├── Up_Tex.webp │ ├── Back_Tex.webp │ ├── Down_Tex.webp │ ├── Front_Tex.webp │ ├── Left_Tex.webp │ └── Right_Tex.webp ├── sounds │ ├── bamboo.mp3 │ ├── asiastana.ogg │ ├── slownomotion.ogg │ ├── rocket-explode.ogg │ └── rocket-flying.ogg ├── images │ └── crosshair.png └── draco │ ├── draco_decoder.wasm │ ├── draco_decoder_gltf.wasm │ └── draco_wasm_wrapper_gltf.js ├── .prettierrc.json ├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── .vsls.json ├── bundler ├── webpack.prod.js ├── webpack.dev.js └── webpack.common.js ├── src ├── shader │ ├── Explosion.frag │ └── Explosion.vert ├── main.js ├── index.html ├── style.css └── core │ └── Game.js ├── package.json └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | ADD LICENSE -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /server/.dockerignore: -------------------------------------------------------------------------------- 1 | fly.toml 2 | Dockerfile 3 | .dockerignore 4 | node_modules 5 | .git 6 | -------------------------------------------------------------------------------- /assets/models/rocks.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/rocks.fbx -------------------------------------------------------------------------------- /assets/models/scene.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/scene.bin -------------------------------------------------------------------------------- /assets/models/scene.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/scene.glb -------------------------------------------------------------------------------- /assets/models/terr4.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/terr4.glb -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "tabWidth": 4, 4 | "printWidth": 80 5 | } 6 | -------------------------------------------------------------------------------- /assets/models/paintbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/paintbg.png -------------------------------------------------------------------------------- /assets/models/terrain.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/terrain.glb -------------------------------------------------------------------------------- /assets/skybox/Up_Tex.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/skybox/Up_Tex.webp -------------------------------------------------------------------------------- /assets/sounds/bamboo.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/sounds/bamboo.mp3 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /dist 3 | .vercel 4 | 5 | /src/entities 6 | /src/temp 7 | /assets/sounds/wip/ 8 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["slevesque.shader", "esbenp.prettier-vscode"] 3 | } 4 | -------------------------------------------------------------------------------- /assets/images/crosshair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/images/crosshair.png -------------------------------------------------------------------------------- /assets/models/explosion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/explosion.png -------------------------------------------------------------------------------- /assets/models/heightmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/heightmap.png -------------------------------------------------------------------------------- /assets/skybox/Back_Tex.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/skybox/Back_Tex.webp -------------------------------------------------------------------------------- /assets/skybox/Down_Tex.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/skybox/Down_Tex.webp -------------------------------------------------------------------------------- /assets/skybox/Front_Tex.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/skybox/Front_Tex.webp -------------------------------------------------------------------------------- /assets/skybox/Left_Tex.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/skybox/Left_Tex.webp -------------------------------------------------------------------------------- /assets/skybox/Right_Tex.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/skybox/Right_Tex.webp -------------------------------------------------------------------------------- /assets/sounds/asiastana.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/sounds/asiastana.ogg -------------------------------------------------------------------------------- /assets/models/explosionold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/explosionold.png -------------------------------------------------------------------------------- /assets/models/rocktexture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/rocktexture.jpg -------------------------------------------------------------------------------- /assets/sounds/slownomotion.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/sounds/slownomotion.ogg -------------------------------------------------------------------------------- /assets/draco/draco_decoder.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/draco/draco_decoder.wasm -------------------------------------------------------------------------------- /assets/models/terrain-draco-1.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/terrain-draco-1.glb -------------------------------------------------------------------------------- /assets/models/terrain-draco-2.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/terrain-draco-2.glb -------------------------------------------------------------------------------- /assets/sounds/rocket-explode.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/sounds/rocket-explode.ogg -------------------------------------------------------------------------------- /assets/sounds/rocket-flying.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/sounds/rocket-flying.ogg -------------------------------------------------------------------------------- /assets/models/GrassRockyAlbedo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/GrassRockyAlbedo.jpg -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "esbenp.prettier-vscode", 3 | "editor.formatOnSave": true 4 | } 5 | -------------------------------------------------------------------------------- /assets/draco/draco_decoder_gltf.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/draco/draco_decoder_gltf.wasm -------------------------------------------------------------------------------- /assets/models/textures/DL2X2_1_baseColor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/textures/DL2X2_1_baseColor.png -------------------------------------------------------------------------------- /assets/models/textures/Trank_bark_baseColor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/textures/Trank_bark_baseColor.jpeg -------------------------------------------------------------------------------- /assets/models/textures/DL2X2_1_metallicRoughness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/textures/DL2X2_1_metallicRoughness.png -------------------------------------------------------------------------------- /.vsls.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/vsls", 3 | "gitignore": "none", 4 | "excludeFiles": ["!.env"], 5 | "hideFiles": [] 6 | } 7 | -------------------------------------------------------------------------------- /assets/models/textures/Trank_bark_metallicRoughness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixgren/three-arena/HEAD/assets/models/textures/Trank_bark_metallicRoughness.png -------------------------------------------------------------------------------- /server/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Socket 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /bundler/webpack.prod.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge'); 2 | const commonConfiguration = require('./webpack.common.js'); 3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin'); 4 | 5 | module.exports = merge(commonConfiguration, { 6 | mode: 'production', 7 | plugins: [new CleanWebpackPlugin()], 8 | }); 9 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "main.js", 6 | "scripts": { 7 | "start": "node main.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "express": "^4.17.1", 15 | "socket.io": "^4.1.1" 16 | }, 17 | "engines": { 18 | "node": "15.14.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/shader/Explosion.frag: -------------------------------------------------------------------------------- 1 | export default ` 2 | varying vec2 vUv; 3 | varying float noise; 4 | uniform sampler2D tExplosion; 5 | 6 | float random( vec3 scale, float seed ){ 7 | return fract( sin( dot( gl_FragCoord.xyz + seed, scale ) ) * 43758.5453 + seed ) ; 8 | } 9 | 10 | void main() { 11 | 12 | float r = .01 * random( vec3( 12.9898, 78.233, 151.7182 ), 0.0 ); 13 | vec2 tPos = vec2( 0, 1.3 * noise + r ); 14 | vec4 color = texture2D( tExplosion, tPos ); 15 | gl_FragColor = vec4( color.rgb, 1.0 ); 16 | 17 | } 18 | `; 19 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Game from './core/Game'; 2 | 3 | const startGameButton = document.querySelector('.start-button-wrapper'); 4 | const respawnGameButton = document.querySelector('.respawn-button-wrapper'); 5 | 6 | Game.load(); 7 | 8 | startGameButton.addEventListener('click', () => { 9 | Game.startGame(); 10 | startGameButton.style.display = 'none'; 11 | }); 12 | 13 | respawnGameButton.addEventListener('click', () => { 14 | Game.triggerRespawn(); 15 | Game.activatePointerLock(); 16 | respawnGameButton.style.display = 'none'; 17 | }); 18 | -------------------------------------------------------------------------------- /server/fly.toml: -------------------------------------------------------------------------------- 1 | # fly.toml file generated for three-arena on 2023-01-29T16:30:46+01:00 2 | 3 | app = "three-arena" 4 | kill_signal = "SIGINT" 5 | kill_timeout = 5 6 | processes = [] 7 | 8 | [env] 9 | PORT = "8080" 10 | 11 | [experimental] 12 | auto_rollback = true 13 | 14 | [[services]] 15 | http_checks = [] 16 | internal_port = 8080 17 | processes = ["app"] 18 | protocol = "tcp" 19 | script_checks = [] 20 | [services.concurrency] 21 | hard_limit = 25 22 | soft_limit = 20 23 | type = "connections" 24 | 25 | [[services.ports]] 26 | force_https = true 27 | handlers = ["http"] 28 | port = 80 29 | 30 | [[services.ports]] 31 | handlers = ["tls", "http"] 32 | port = 443 33 | 34 | [[services.tcp_checks]] 35 | grace_period = "1s" 36 | interval = "15s" 37 | restart_limit = 0 38 | timeout = "2s" 39 | -------------------------------------------------------------------------------- /server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:bullseye as builder 2 | 3 | ARG NODE_VERSION=16.19.0 4 | 5 | RUN apt-get update; apt install -y curl python-is-python3 pkg-config build-essential 6 | RUN curl https://get.volta.sh | bash 7 | ENV VOLTA_HOME /root/.volta 8 | ENV PATH /root/.volta/bin:$PATH 9 | RUN volta install node@${NODE_VERSION} 10 | 11 | ####################################################################### 12 | 13 | RUN mkdir /app 14 | WORKDIR /app 15 | 16 | # NPM will not install any package listed in "devDependencies" when NODE_ENV is set to "production", 17 | # to install all modules: "npm install --production=false". 18 | # Ref: https://docs.npmjs.com/cli/v9/commands/npm-install#description 19 | 20 | ENV NODE_ENV production 21 | 22 | COPY . . 23 | 24 | RUN npm install 25 | FROM debian:bullseye 26 | 27 | LABEL fly_launch_runtime="nodejs" 28 | 29 | COPY --from=builder /root/.volta /root/.volta 30 | COPY --from=builder /app /app 31 | 32 | WORKDIR /app 33 | ENV NODE_ENV production 34 | ENV PATH /root/.volta/bin:$PATH 35 | 36 | CMD [ "npm", "run", "start" ] 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "level-up", 3 | "version": "1.0.0", 4 | "description": "", 5 | "private": true, 6 | "scripts": { 7 | "build": "webpack --config ./bundler/webpack.prod.js", 8 | "dev": "webpack serve --config ./bundler/webpack.dev.js", 9 | "start": "npm run dev", 10 | "server": "npm start --prefix server" 11 | }, 12 | "devDependencies": { 13 | "@babel/core": "^7.13.16", 14 | "@babel/preset-env": "^7.13.15", 15 | "babel-loader": "^8.2.2", 16 | "clean-webpack-plugin": "*", 17 | "copy-webpack-plugin": "^8.1.1", 18 | "css-loader": "^5.2.4", 19 | "file-loader": "^6.2.0", 20 | "html-loader": "^2.1.2", 21 | "html-webpack-plugin": "^5.3.1", 22 | "mini-css-extract-plugin": "^1.5.1", 23 | "portfinder-sync": "^0.0.2", 24 | "prettier": "^2.2.1", 25 | "raw-loader": "^4.0.2", 26 | "style-loader": "^2.0.0", 27 | "webpack": "^5.36.1", 28 | "webpack-cli": "^4.6.0", 29 | "webpack-dev-server": "^3.11.2", 30 | "webpack-merge": "^5.7.3" 31 | }, 32 | "dependencies": { 33 | "dat.gui": "^0.7.7", 34 | "socket.io-client": "^4.1.1", 35 | "three": "^0.128.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /bundler/webpack.dev.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge'); 2 | const commonConfiguration = require('./webpack.common.js'); 3 | const ip = require('internal-ip'); 4 | const portFinderSync = require('portfinder-sync'); 5 | 6 | const infoColor = (_message) => { 7 | return `\u001b[1m\u001b[34m${_message}\u001b[39m\u001b[22m`; 8 | }; 9 | 10 | module.exports = merge(commonConfiguration, { 11 | mode: 'development', 12 | devServer: { 13 | host: '0.0.0.0', 14 | port: portFinderSync.getPort(5000), 15 | contentBase: './dist', 16 | watchContentBase: true, 17 | open: true, 18 | https: false, 19 | useLocalIp: true, 20 | disableHostCheck: true, 21 | overlay: true, 22 | noInfo: true, 23 | after: function (app, server, compiler) { 24 | const port = server.options.port; 25 | const https = server.options.https ? 's' : ''; 26 | const localIp = ip.v4.sync(); 27 | const domain1 = `http${https}://localhost:${port}`; 28 | const domain2 = `http${https}://${localIp}:${port}`; 29 | 30 | console.log( 31 | `Project running at:\n - ${infoColor( 32 | domain1 33 | )}\n - ${infoColor(domain2)}` 34 | ); 35 | }, 36 | }, 37 | }); 38 | -------------------------------------------------------------------------------- /bundler/webpack.common.js: -------------------------------------------------------------------------------- 1 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 2 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | const MiniCSSExtractPlugin = require('mini-css-extract-plugin'); 4 | const path = require('path'); 5 | 6 | module.exports = { 7 | entry: path.resolve(__dirname, '../src/main.js'), 8 | output: { 9 | filename: 'bundle.[contenthash].js', 10 | path: path.resolve(__dirname, '../dist'), 11 | }, 12 | devtool: 'source-map', 13 | plugins: [ 14 | new CopyWebpackPlugin({ 15 | patterns: [{ from: path.resolve(__dirname, '../assets') }], 16 | }), 17 | new HtmlWebpackPlugin({ 18 | template: path.resolve(__dirname, '../src/index.html'), 19 | minify: true, 20 | }), 21 | new MiniCSSExtractPlugin(), 22 | ], 23 | module: { 24 | rules: [ 25 | // HTML 26 | { 27 | test: /\.(html)$/, 28 | use: ['html-loader'], 29 | }, 30 | 31 | // JS 32 | { 33 | test: /\.js$/, 34 | exclude: /node_modules/, 35 | use: ['babel-loader'], 36 | }, 37 | 38 | // CSS 39 | { 40 | test: /\.css$/, 41 | use: [MiniCSSExtractPlugin.loader, 'css-loader'], 42 | }, 43 | 44 | // Images 45 | { 46 | test: /\.(jpg|png|gif|svg)$/, 47 | use: [ 48 | { 49 | loader: 'file-loader', 50 | options: { 51 | outputPath: 'assets/images/', 52 | }, 53 | }, 54 | ], 55 | }, 56 | 57 | // Fonts 58 | { 59 | test: /\.(ttf|eot|woff|woff2)$/, 60 | use: [ 61 | { 62 | loader: 'file-loader', 63 | options: { 64 | outputPath: 'assets/fonts/', 65 | }, 66 | }, 67 | ], 68 | }, 69 | ], 70 | }, 71 | }; 72 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Three.js arena 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |

Velocity:

19 |

Initial

20 |

Position:

21 |

Initial

22 |
23 | 24 | 25 |
26 | Toggle 27 |
28 | 29 | 30 |
31 |
32 |

You died

33 | 34 |
35 | 36 | 37 |
38 |
39 | 40 |
41 | 42 | 43 | 48 | 49 | 50 | 51 |
52 |
53 | 59 |
60 |
61 | 62 | 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | ## Three Arena 4 | Join now on *[three-arena.vercel.app](https://three-arena.vercel.app/)* 5 | 6 | An arena shooter created in three.js. Shoot your friends in this socket.io multiplayer game. You can open chat by pressing t. 7 | 8 | It features a vanilla built movement system, collisions (with the help of octrees), chat & shooting. Backend is an express socket.io server which gathers and sends out all player data (movement, directions, chat, rocket fire events) to the clients. The clients then react by generating and updating the players & events, the client is completely trusted. Best part is that it's all in one file... but would be very easy to break out & expand upon if you have some time. 9 | 10 | If you've found this repo valuable, do give it a star. 11 | 12 | This game was created using the following technologies: 13 | 14 | - [three.js](https://threejs.org/) 15 | - [Socket.IO](https://socket.io/) 16 | - [webpack](https://webpack.js.org/) 17 | 18 | ## Installation 19 | 20 | **Prerequisites** 21 | 22 | - [UNIX based OS (Mac, Linux or WSL2 for Windows)](https://docs.microsoft.com/en-us/windows/wsl/install-win10) 23 | - node 24 | - npm 25 | 26 | ### Setting up project 27 | 28 | ``` 29 | git clone https://github.com/felixgren/three-arena.git 30 | cd three-arena 31 | npm install 32 | cd server 33 | npm install 34 | ``` 35 | 36 | ### Run project 37 | 38 | ```js 39 | // Start client 40 | npm run dev 41 | 42 | // Start server 43 | npm run server 44 | ``` 45 | 46 | > In case of errors, verify that socket.io client in `game.js` is targeted at matching localhost port inside `/server/main.js`. 47 | 48 | # Changelog 49 | 50 | - [#1 - Initial setup](https://github.com/felixgren/level-up/pull/1) 51 | - [#2 - Shadows ](https://github.com/felixgren/level-up/pull/2) 52 | - [#3 - Basic skybox & model, FPS counter](https://github.com/felixgren/level-up/pull/3) 53 | - [#4 - Drawcalls to debug GUI](https://github.com/felixgren/level-up/pull/4/) 54 | - [#5 - Movement and collisions.](https://github.com/felixgren/level-up/pull/5/) 55 | - [#6 - Rockets.](https://github.com/felixgren/level-up/pull/6/) 56 | - [#7 - World terrain, heightmap, model, skybox](https://github.com/felixgren/level-up/pull/7/) 57 | - [#8 - Refactored entire project](https://github.com/felixgren/level-up/pull/8/) 58 | - [#9 - Code Review](https://github.com/felixgren/three-arena/pull/9) 59 | - [#10 - Core Features 1 (Multiplayer, Chat, Explosions, etc)](https://github.com/felixgren/three-arena/pull/10/) 60 | - [#11 - Environment 2 (New Map)](https://github.com/felixgren/three-arena/pull/11/) 61 | - [#12 - Core Features 2 (Respawn, UI, Chat types)](https://github.com/felixgren/three-arena/pull/12/) 62 | - [#13 - Core Features 3 (General improvements)](https://github.com/felixgren/three-arena/pull/13/) 63 | - [#14 - Update node server host](https://github.com/felixgren/three-arena/pull/14/) 64 | -------------------------------------------------------------------------------- /server/main.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const http = require('http').Server(app); 4 | 5 | const io = require('socket.io')(http, { 6 | cors: { 7 | origin: '*', 8 | methods: ['GET', 'POST'], 9 | }, 10 | }); 11 | 12 | app.use(express.static('../dist/')); 13 | 14 | app.get('/', function (req, res) { 15 | res.sendFile(__dirname + '../../dist/index.html'); 16 | }); 17 | 18 | let players = {}; 19 | 20 | (() => { 21 | setup(); 22 | 23 | // Update player position, roughly matches 120 refresh 24 | setInterval(function () { 25 | io.sockets.emit('playerPositions', players); 26 | }, 8); 27 | })(); 28 | 29 | function setup() { 30 | io.on('connection', function (socket) { 31 | // Client connect... 32 | console.log(`User ${socket.id} connected`); 33 | 34 | // Add to server players object 35 | players[socket.id] = { 36 | position: [0, 0, 0], 37 | direction: [0, 0, 0], 38 | }; 39 | 40 | // We give all clients notice of new player and their ID.. 41 | socket.broadcast.emit( 42 | 'player connect', 43 | socket.id, 44 | io.engine.clientsCount 45 | ); 46 | 47 | // We give client their ID, playerCount and playerIDs 48 | socket.emit( 49 | 'initPlayer', 50 | { id: socket.id }, 51 | io.engine.clientsCount, 52 | Object.keys(players) 53 | ); 54 | 55 | // We give clients notice of disconnection and the their ID 56 | socket.on('disconnect', function () { 57 | console.log(`User ${socket.id} disconnected`); 58 | socket.broadcast.emit( 59 | 'player disconnect', 60 | socket.id, 61 | io.engine.clientsCount 62 | ); 63 | // Delete from players object 64 | delete players[socket.id]; 65 | }); 66 | 67 | // On chat message emit it to everyone 68 | socket.on('chat message', function (username, message) { 69 | io.emit('chat message', username, message); 70 | }); 71 | 72 | socket.on('kill message', function (shooter, killed) { 73 | io.emit('kill message', shooter, killed); 74 | }); 75 | 76 | // Data every client uploads 77 | socket.on('updateClientPos', (position, direction) => { 78 | if (players[socket.id]) { 79 | players[socket.id].position = position; 80 | players[socket.id].direction = direction; 81 | } 82 | }); 83 | 84 | socket.on('triggerRemoteRocket', () => { 85 | socket.broadcast.emit( 86 | 'shootSyncRocket', 87 | players[socket.id], 88 | socket.id 89 | ); 90 | }); 91 | }); 92 | 93 | let port = process.env.PORT; 94 | if (port == null || port == '') { 95 | port = 3000; 96 | } 97 | 98 | http.listen(port, function () { 99 | console.log(`Listening on port ${port}`); 100 | }); 101 | } 102 | -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | font-family: 'Montserrat', sans-serif; 5 | } 6 | 7 | html, 8 | body { 9 | height: 100vh; 10 | background: black; 11 | } 12 | 13 | .webgl { 14 | position: fixed; 15 | top: 0; 16 | left: 0; 17 | outline: none; 18 | } 19 | 20 | .custom-stats { 21 | bottom: 0; 22 | right: 0; 23 | color: rgb(255, 102, 0); 24 | background-color: rgba(53, 53, 53, 0.5); 25 | position: absolute; 26 | padding: 5px; 27 | /* font-family: Arial, Helvetica, sans-serif; */ 28 | font-weight: 400; 29 | z-index: 100; 30 | } 31 | 32 | .custom-stats h4 { 33 | font-weight: 500; 34 | } 35 | 36 | .pause-button { 37 | bottom: 0; 38 | right: 10vh; 39 | position: absolute; 40 | z-index: 100; 41 | display: inline-block; 42 | padding: 0.35em 1.2em; 43 | border: 0.1em solid #ffffff; 44 | margin: 0 0.3em 0.3em 0; 45 | border-radius: 0.12em; 46 | box-sizing: border-box; 47 | text-decoration: none; 48 | font-family: 'Arial', sans-serif; 49 | font-weight: 300; 50 | color: #ffffff; 51 | text-align: center; 52 | transition: all 0.2s; 53 | /* display: none; */ 54 | } 55 | 56 | .pause-button:hover { 57 | color: #000000; 58 | background-color: #ffffff; 59 | } 60 | 61 | .respawn-button-wrapper { 62 | position: absolute; 63 | display: none; 64 | z-index: 10; 65 | width: 100vw; 66 | height: 100vh; 67 | background-color: black; 68 | } 69 | 70 | .respawn-text { 71 | position: absolute; 72 | top: 200px; 73 | left: calc(50% - 75px); 74 | color: white; 75 | font-size: 30px; 76 | /* font-weight: 500; */ 77 | letter-spacing: 0.15em; 78 | transition: 150ms; 79 | } 80 | 81 | .button { 82 | position: absolute; 83 | top: 250px; 84 | left: calc(50% - 150px); 85 | font-size: 40px; 86 | cursor: pointer; 87 | background-color: #1b1b1b; 88 | color: white; 89 | font-weight: 300; 90 | letter-spacing: 0.15em; 91 | transition: 150ms; 92 | border: 3px solid black; 93 | border-radius: 8px; 94 | margin: 8px 6px; 95 | transform: translate(8px, 8px); 96 | width: 300px; 97 | height: 60px; 98 | } 99 | 100 | .button:hover { 101 | transform: translate(0px, 0px) !important; 102 | } 103 | 104 | .button-background { 105 | position: absolute; 106 | top: 250px; 107 | left: calc(50% - 150px); 108 | background-color: #ee0000; 109 | border: 3px solid black; 110 | border-radius: 8px; 111 | margin: 8px 6px; 112 | width: 300px; 113 | height: 60px; 114 | box-sizing: border-box; 115 | } 116 | 117 | #chatSection { 118 | left: 4%; 119 | bottom: 4%; 120 | z-index: 10; 121 | position: absolute; 122 | border-radius: 3px; 123 | } 124 | 125 | .chatList { 126 | list-style-type: none; 127 | font-size: 16px; 128 | text-align: left; 129 | font-family: 'Roboto Mono', monospace; 130 | } 131 | 132 | .chatContainer { 133 | background-color: #4e4e4eaf; 134 | font-size: 28px; 135 | color: #ffffff; 136 | text-align: center; 137 | line-height: 20px; 138 | } 139 | 140 | .chatContainer > div { 141 | padding: 4px; 142 | } 143 | 144 | .chatContainer > div > span { 145 | display: inline-block; 146 | } 147 | 148 | .chatContainer > div > ul > li:not(:first-child) { 149 | border-top: 1px solid #6b6b6b60; 150 | } 151 | 152 | .chatContainer > div > ul > li { 153 | padding: 4px; 154 | } 155 | 156 | .hidden { 157 | display: none; 158 | } 159 | 160 | #inputForm { 161 | z-index: 10; 162 | display: none; 163 | position: absolute; 164 | bottom: 2%; 165 | left: 4%; 166 | z-index: 50; 167 | padding: 2px; 168 | } 169 | 170 | #inputForm input { 171 | line-height: 20px; 172 | color: white; 173 | border: none; 174 | background-color: transparent; 175 | outline: none; 176 | } 177 | -------------------------------------------------------------------------------- /src/shader/Explosion.vert: -------------------------------------------------------------------------------- 1 | export default ` 2 | // 3 | // GLSL textureless classic 3D noise "cnoise", 4 | // with an RSL-style periodic variant "pnoise". 5 | // Author: Stefan Gustavson (stefan.gustavson@liu.se) 6 | // Version: 2011-10-11 7 | // 8 | // Many thanks to Ian McEwan of Ashima Arts for the 9 | // ideas for permutation and gradient selection. 10 | // 11 | // Copyright (c) 2011 Stefan Gustavson. All rights reserved. 12 | // Distributed under the MIT license. See LICENSE file. 13 | // https://github.com/ashima/webgl-noise 14 | // 15 | 16 | vec3 mod289(vec3 x) 17 | { 18 | return x - floor(x * (1.0 / 289.0)) * 289.0; 19 | } 20 | 21 | vec4 mod289(vec4 x) 22 | { 23 | return x - floor(x * (1.0 / 289.0)) * 289.0; 24 | } 25 | 26 | vec4 permute(vec4 x) 27 | { 28 | return mod289(((x*34.0)+1.0)*x); 29 | } 30 | 31 | vec4 taylorInvSqrt(vec4 r) 32 | { 33 | return 1.79284291400159 - 0.85373472095314 * r; 34 | } 35 | 36 | vec3 fade(vec3 t) { 37 | return t*t*t*(t*(t*6.0-15.0)+10.0); 38 | } 39 | 40 | // Classic Perlin noise 41 | float cnoise(vec3 P) 42 | { 43 | vec3 Pi0 = floor(P); // Integer part for indexing 44 | vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1 45 | Pi0 = mod289(Pi0); 46 | Pi1 = mod289(Pi1); 47 | vec3 Pf0 = fract(P); // Fractional part for interpolation 48 | vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0 49 | vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); 50 | vec4 iy = vec4(Pi0.yy, Pi1.yy); 51 | vec4 iz0 = Pi0.zzzz; 52 | vec4 iz1 = Pi1.zzzz; 53 | 54 | vec4 ixy = permute(permute(ix) + iy); 55 | vec4 ixy0 = permute(ixy + iz0); 56 | vec4 ixy1 = permute(ixy + iz1); 57 | 58 | vec4 gx0 = ixy0 * (1.0 / 7.0); 59 | vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5; 60 | gx0 = fract(gx0); 61 | vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0); 62 | vec4 sz0 = step(gz0, vec4(0.0)); 63 | gx0 -= sz0 * (step(0.0, gx0) - 0.5); 64 | gy0 -= sz0 * (step(0.0, gy0) - 0.5); 65 | 66 | vec4 gx1 = ixy1 * (1.0 / 7.0); 67 | vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5; 68 | gx1 = fract(gx1); 69 | vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1); 70 | vec4 sz1 = step(gz1, vec4(0.0)); 71 | gx1 -= sz1 * (step(0.0, gx1) - 0.5); 72 | gy1 -= sz1 * (step(0.0, gy1) - 0.5); 73 | 74 | vec3 g000 = vec3(gx0.x,gy0.x,gz0.x); 75 | vec3 g100 = vec3(gx0.y,gy0.y,gz0.y); 76 | vec3 g010 = vec3(gx0.z,gy0.z,gz0.z); 77 | vec3 g110 = vec3(gx0.w,gy0.w,gz0.w); 78 | vec3 g001 = vec3(gx1.x,gy1.x,gz1.x); 79 | vec3 g101 = vec3(gx1.y,gy1.y,gz1.y); 80 | vec3 g011 = vec3(gx1.z,gy1.z,gz1.z); 81 | vec3 g111 = vec3(gx1.w,gy1.w,gz1.w); 82 | 83 | vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); 84 | g000 *= norm0.x; 85 | g010 *= norm0.y; 86 | g100 *= norm0.z; 87 | g110 *= norm0.w; 88 | vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); 89 | g001 *= norm1.x; 90 | g011 *= norm1.y; 91 | g101 *= norm1.z; 92 | g111 *= norm1.w; 93 | 94 | float n000 = dot(g000, Pf0); 95 | float n100 = dot(g100, vec3(Pf1.x, Pf0.yz)); 96 | float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)); 97 | float n110 = dot(g110, vec3(Pf1.xy, Pf0.z)); 98 | float n001 = dot(g001, vec3(Pf0.xy, Pf1.z)); 99 | float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)); 100 | float n011 = dot(g011, vec3(Pf0.x, Pf1.yz)); 101 | float n111 = dot(g111, Pf1); 102 | 103 | vec3 fade_xyz = fade(Pf0); 104 | vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); 105 | vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y); 106 | float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); 107 | return 2.2 * n_xyz; 108 | } 109 | 110 | // Classic Perlin noise, periodic variant 111 | float pnoise(vec3 P, vec3 rep) 112 | { 113 | vec3 Pi0 = mod(floor(P), rep); // Integer part, modulo period 114 | vec3 Pi1 = mod(Pi0 + vec3(1.0), rep); // Integer part + 1, mod period 115 | Pi0 = mod289(Pi0); 116 | Pi1 = mod289(Pi1); 117 | vec3 Pf0 = fract(P); // Fractional part for interpolation 118 | vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0 119 | vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); 120 | vec4 iy = vec4(Pi0.yy, Pi1.yy); 121 | vec4 iz0 = Pi0.zzzz; 122 | vec4 iz1 = Pi1.zzzz; 123 | 124 | vec4 ixy = permute(permute(ix) + iy); 125 | vec4 ixy0 = permute(ixy + iz0); 126 | vec4 ixy1 = permute(ixy + iz1); 127 | 128 | vec4 gx0 = ixy0 * (1.0 / 7.0); 129 | vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5; 130 | gx0 = fract(gx0); 131 | vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0); 132 | vec4 sz0 = step(gz0, vec4(0.0)); 133 | gx0 -= sz0 * (step(0.0, gx0) - 0.5); 134 | gy0 -= sz0 * (step(0.0, gy0) - 0.5); 135 | 136 | vec4 gx1 = ixy1 * (1.0 / 7.0); 137 | vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5; 138 | gx1 = fract(gx1); 139 | vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1); 140 | vec4 sz1 = step(gz1, vec4(0.0)); 141 | gx1 -= sz1 * (step(0.0, gx1) - 0.5); 142 | gy1 -= sz1 * (step(0.0, gy1) - 0.5); 143 | 144 | vec3 g000 = vec3(gx0.x,gy0.x,gz0.x); 145 | vec3 g100 = vec3(gx0.y,gy0.y,gz0.y); 146 | vec3 g010 = vec3(gx0.z,gy0.z,gz0.z); 147 | vec3 g110 = vec3(gx0.w,gy0.w,gz0.w); 148 | vec3 g001 = vec3(gx1.x,gy1.x,gz1.x); 149 | vec3 g101 = vec3(gx1.y,gy1.y,gz1.y); 150 | vec3 g011 = vec3(gx1.z,gy1.z,gz1.z); 151 | vec3 g111 = vec3(gx1.w,gy1.w,gz1.w); 152 | 153 | vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); 154 | g000 *= norm0.x; 155 | g010 *= norm0.y; 156 | g100 *= norm0.z; 157 | g110 *= norm0.w; 158 | vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); 159 | g001 *= norm1.x; 160 | g011 *= norm1.y; 161 | g101 *= norm1.z; 162 | g111 *= norm1.w; 163 | 164 | float n000 = dot(g000, Pf0); 165 | float n100 = dot(g100, vec3(Pf1.x, Pf0.yz)); 166 | float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)); 167 | float n110 = dot(g110, vec3(Pf1.xy, Pf0.z)); 168 | float n001 = dot(g001, vec3(Pf0.xy, Pf1.z)); 169 | float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)); 170 | float n011 = dot(g011, vec3(Pf0.x, Pf1.yz)); 171 | float n111 = dot(g111, Pf1); 172 | 173 | vec3 fade_xyz = fade(Pf0); 174 | vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); 175 | vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y); 176 | float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); 177 | return 2.2 * n_xyz; 178 | } 179 | 180 | // 181 | // Created largely with the help of ClickToRelease! 182 | // https://www.clicktorelease.com/blog/vertex-displacement-noise-3d-webgl-glsl-three-js/ 183 | 184 | varying vec2 vUv; 185 | varying float noise; 186 | uniform float time; 187 | 188 | float turbulence( vec3 p ) { 189 | float w = 100.0; 190 | float t = -.5; 191 | for (float f = 1.0 ; f <= 10.0 ; f++ ){ 192 | float power = pow( 2.0, f ); 193 | t += abs( pnoise( vec3( power * p ), vec3( 10.0, 10.0, 10.0 ) ) / power ); 194 | } 195 | return t; 196 | } 197 | 198 | void main() { 199 | 200 | vUv = uv; 201 | 202 | noise = 10.0 * -.10 * turbulence( .5 * normal + time ); 203 | float b = 5.0 * pnoise( 0.05 * position + vec3( 2.0 * time ), vec3( 100.0 ) ); 204 | float displacement = - 10. * noise + b; 205 | 206 | vec3 newPosition = position + normal * displacement; 207 | gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 ); 208 | 209 | } 210 | `; 211 | -------------------------------------------------------------------------------- /assets/models/tree.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "accessors": [ 3 | { 4 | "bufferView": 2, 5 | "componentType": 5126, 6 | "count": 12020, 7 | "max": [ 8 | 0.80282998085021973, 9 | 1.3153300285339355, 10 | 2.0525000095367432 11 | ], 12 | "min": [ 13 | -1.3118699789047241, 14 | -1.439210057258606, 15 | 0.18327000737190247 16 | ], 17 | "type": "VEC3" 18 | }, 19 | { 20 | "bufferView": 2, 21 | "byteOffset": 144240, 22 | "componentType": 5126, 23 | "count": 12020, 24 | "max": [ 25 | 0.99983775615692139, 26 | 0.99993628263473511, 27 | 0.99950402975082397 28 | ], 29 | "min": [ 30 | -0.99997878074645996, 31 | -0.99986916780471802, 32 | -0.99989950656890869 33 | ], 34 | "type": "VEC3" 35 | }, 36 | { 37 | "bufferView": 1, 38 | "componentType": 5126, 39 | "count": 12020, 40 | "max": [ 41 | 1.0006699562072754, 42 | 1.0001300573348999 43 | ], 44 | "min": [ 45 | -0.0019499999471008778, 46 | 0 47 | ], 48 | "type": "VEC2" 49 | }, 50 | { 51 | "bufferView": 0, 52 | "componentType": 5125, 53 | "count": 18030, 54 | "max": [ 55 | 12019 56 | ], 57 | "min": [ 58 | 0 59 | ], 60 | "type": "SCALAR" 61 | }, 62 | { 63 | "bufferView": 2, 64 | "byteOffset": 288480, 65 | "componentType": 5126, 66 | "count": 18717, 67 | "max": [ 68 | 0.6457899808883667, 69 | 1.1660900115966797, 70 | 1.9106500148773193 71 | ], 72 | "min": [ 73 | -1.131909966468811, 74 | -1.2874499559402466, 75 | 0 76 | ], 77 | "type": "VEC3" 78 | }, 79 | { 80 | "bufferView": 2, 81 | "byteOffset": 513084, 82 | "componentType": 5126, 83 | "count": 18717, 84 | "max": [ 85 | 1, 86 | 0.99992716312408447, 87 | 0.99930250644683838 88 | ], 89 | "min": [ 90 | -0.99997878074645996, 91 | -0.99992716312408447, 92 | -0.99930250644683838 93 | ], 94 | "type": "VEC3" 95 | }, 96 | { 97 | "bufferView": 1, 98 | "byteOffset": 96160, 99 | "componentType": 5126, 100 | "count": 18717, 101 | "max": [ 102 | 2, 103 | 112.55133056640625 104 | ], 105 | "min": [ 106 | 0, 107 | 0 108 | ], 109 | "type": "VEC2" 110 | }, 111 | { 112 | "bufferView": 0, 113 | "byteOffset": 72120, 114 | "componentType": 5125, 115 | "count": 96276, 116 | "max": [ 117 | 18716 118 | ], 119 | "min": [ 120 | 0 121 | ], 122 | "type": "SCALAR" 123 | } 124 | ], 125 | "asset": { 126 | "extras": { 127 | "author": "RosticOstafi (https://sketchfab.com/RosticOstafi)", 128 | "license": "CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)", 129 | "source": "https://sketchfab.com/3d-models/tree-sakura-4a201fe7f1a548fa9a0b32388be75499", 130 | "title": "Tree Sakura" 131 | }, 132 | "generator": "Sketchfab-8.20.0", 133 | "version": "2.0" 134 | }, 135 | "bufferViews": [ 136 | { 137 | "buffer": 0, 138 | "byteLength": 457224, 139 | "byteOffset": 0, 140 | "name": "floatBufferViews", 141 | "target": 34963 142 | }, 143 | { 144 | "buffer": 0, 145 | "byteLength": 245896, 146 | "byteOffset": 457224, 147 | "byteStride": 8, 148 | "name": "floatBufferViews", 149 | "target": 34962 150 | }, 151 | { 152 | "buffer": 0, 153 | "byteLength": 737688, 154 | "byteOffset": 703120, 155 | "byteStride": 12, 156 | "name": "floatBufferViews", 157 | "target": 34962 158 | } 159 | ], 160 | "buffers": [ 161 | { 162 | "byteLength": 1440808, 163 | "uri": "scene.bin" 164 | } 165 | ], 166 | "images": [ 167 | { 168 | "uri": "textures/DL2X2_1_baseColor.png" 169 | }, 170 | { 171 | "uri": "textures/DL2X2_1_metallicRoughness.png" 172 | }, 173 | { 174 | "uri": "textures/Trank_bark_baseColor.jpeg" 175 | }, 176 | { 177 | "uri": "textures/Trank_bark_metallicRoughness.png" 178 | } 179 | ], 180 | "materials": [ 181 | { 182 | "alphaMode": "BLEND", 183 | "doubleSided": true, 184 | "name": "DL2X2_1", 185 | "pbrMetallicRoughness": { 186 | "baseColorFactor": [ 187 | 1, 188 | 1, 189 | 1, 190 | 1 191 | ], 192 | "baseColorTexture": { 193 | "index": 0, 194 | "texCoord": 0 195 | }, 196 | "metallicFactor": 1, 197 | "metallicRoughnessTexture": { 198 | "index": 1, 199 | "texCoord": 0 200 | }, 201 | "roughnessFactor": 0.59999999999999998 202 | } 203 | }, 204 | { 205 | "doubleSided": true, 206 | "name": "Trank_bark", 207 | "pbrMetallicRoughness": { 208 | "baseColorFactor": [ 209 | 0.32488567073170732, 210 | 0.32488567073170732, 211 | 0.32488567073170732, 212 | 1 213 | ], 214 | "baseColorTexture": { 215 | "index": 2, 216 | "texCoord": 0 217 | }, 218 | "metallicFactor": 1, 219 | "metallicRoughnessTexture": { 220 | "index": 3, 221 | "texCoord": 0 222 | }, 223 | "roughnessFactor": 1 224 | } 225 | } 226 | ], 227 | "meshes": [ 228 | { 229 | "primitives": [ 230 | { 231 | "attributes": { 232 | "NORMAL": 1, 233 | "POSITION": 0, 234 | "TEXCOORD_0": 2 235 | }, 236 | "indices": 3, 237 | "material": 0, 238 | "mode": 4 239 | } 240 | ] 241 | }, 242 | { 243 | "primitives": [ 244 | { 245 | "attributes": { 246 | "NORMAL": 5, 247 | "POSITION": 4, 248 | "TEXCOORD_0": 6 249 | }, 250 | "indices": 7, 251 | "material": 1, 252 | "mode": 4 253 | } 254 | ] 255 | } 256 | ], 257 | "nodes": [ 258 | { 259 | "children": [ 260 | 1 261 | ], 262 | "name": "RootNode (gltf orientation matrix)", 263 | "rotation": [ 264 | -0.70710678118654746, 265 | -0, 266 | -0, 267 | 0.70710678118654757 268 | ] 269 | }, 270 | { 271 | "children": [ 272 | 2 273 | ], 274 | "name": "RootNode (model correction matrix)" 275 | }, 276 | { 277 | "children": [ 278 | 3, 279 | 4 280 | ], 281 | "name": "Tree.obj.cleaner.materialmerger.gles" 282 | }, 283 | { 284 | "mesh": 0, 285 | "name": "" 286 | }, 287 | { 288 | "mesh": 1, 289 | "name": "" 290 | } 291 | ], 292 | "samplers": [ 293 | { 294 | "magFilter": 9729, 295 | "minFilter": 9987, 296 | "wrapS": 10497, 297 | "wrapT": 10497 298 | } 299 | ], 300 | "scene": 0, 301 | "scenes": [ 302 | { 303 | "name": "OSG_Scene", 304 | "nodes": [ 305 | 0 306 | ] 307 | } 308 | ], 309 | "textures": [ 310 | { 311 | "sampler": 0, 312 | "source": 0 313 | }, 314 | { 315 | "sampler": 0, 316 | "source": 1 317 | }, 318 | { 319 | "sampler": 0, 320 | "source": 2 321 | }, 322 | { 323 | "sampler": 0, 324 | "source": 3 325 | } 326 | ] 327 | } 328 | 329 | -------------------------------------------------------------------------------- /src/core/Game.js: -------------------------------------------------------------------------------- 1 | import '../style.css'; 2 | import * as THREE from 'three'; 3 | import * as dat from 'dat.gui'; 4 | import io from 'socket.io-client'; 5 | import Stats from 'three/examples/jsm/libs/stats.module'; 6 | import { Capsule } from 'three/examples/jsm/math/Capsule'; 7 | import { Octree } from 'three/examples/jsm/math/Octree'; 8 | import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; 9 | import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; 10 | import { Sprite, SpriteMaterial, OrthographicCamera, Scene } from 'three'; 11 | import explosionFragment from '../shader/Explosion.frag'; 12 | import explosionVertex from '../shader/Explosion.vert'; 13 | 14 | class Game { 15 | constructor() { 16 | this.camera = null; 17 | this.scene = null; 18 | this.renderer = null; 19 | 20 | this.gui = null; 21 | this.clock = null; 22 | 23 | this.worldOctree = new Octree(); 24 | this.world = new THREE.Group(); 25 | 26 | this.lastTime = null; 27 | this.stats = null; 28 | this.drawCallPanel = null; 29 | 30 | this.player = null; 31 | this.players = null; 32 | this.playerCapsule = null; 33 | this.isPlayerGrounded = false; 34 | this.playerSpeed = 50; 35 | this.playerVelocity = null; 36 | this.teleportVec = new THREE.Vector3(0, 0, 0); // Better performance to reuse same vector 37 | 38 | this.Key = {}; 39 | this.controls = null; 40 | this.maxJumps = 2; 41 | this.upVector = null; 42 | this.gravity = 70; 43 | 44 | this.toggle = false; 45 | this.collisionsEnabled = true; 46 | this.playerFocused = false; 47 | this.inputDisabled = false; 48 | 49 | this.rockets = []; 50 | this.rocketForce = 90; 51 | this.maxRockets = 100; 52 | this.rocketIdx = 0; 53 | this.deltaRocket = 0; 54 | this.frontRocketLight = null; 55 | this.backRocketLight = null; 56 | 57 | this.textureLoader = new THREE.TextureLoader(); 58 | this.textureMap = new Map(); 59 | 60 | this.elaspedTime = 0; 61 | this.chatMessages = new Array(); 62 | 63 | this.loadingManager = new THREE.LoadingManager(); 64 | this.audioLoader = new THREE.AudioLoader(this.loadingManager); 65 | this.listener = new THREE.AudioListener(); 66 | this.audioMap = new Map(); 67 | 68 | this.shaderLoader = new THREE.TextureLoader(); 69 | this.explosionMaterial = null; 70 | this.explosionTime = Date.now(); 71 | 72 | this.animRequest; 73 | this.requestAnimId = null; 74 | this.startAnimation = startAnimation.bind(this); 75 | this.stopAnimation = stopAnimation.bind(this); 76 | 77 | this.ui = { 78 | body: document.querySelector('body'), 79 | respawnButton: document.querySelector('.respawn-button-wrapper'), 80 | pauseButton: document.querySelector('.pause-button-wrapper'), 81 | velocityStats: document.querySelector('.velocity-stats'), 82 | positionStats: document.querySelector('.position-stats'), 83 | chatSection: document.getElementById('chatSection'), 84 | chatList: document.querySelector('.chatList'), 85 | crosshair: null, 86 | }; 87 | } 88 | 89 | // Loading scene function before game is started 90 | load() { 91 | console.log('PRELOADING...'); 92 | 93 | this.initAudio().then(() => { 94 | this.initScene(); 95 | this.initSkybox(); 96 | this.initMap(); 97 | this.initPlayer(); 98 | this.initCrosshair(); 99 | this.initExplosion(); 100 | this.initStats(); 101 | this.initDevWIP(); 102 | this.initSocket(); 103 | }); 104 | } 105 | 106 | // Init function when game starts 107 | startGame() { 108 | console.log('START GAME'); 109 | 110 | this.activatePointerLock(); 111 | this.activateMovement(); 112 | this.activateRocketShooting(); 113 | this.activateGamePause(); 114 | this.startAnimation(); // Starts tick function 115 | this.addChatMessage('Admin', 'Welcome to three arena.'); 116 | } 117 | 118 | // Main update game function 119 | tick() { 120 | const delta = this.clock.getDelta(); 121 | this.elaspedTime += delta; 122 | 123 | this.updatePlayerControl(delta); 124 | this.updateCheckOnGround(delta); 125 | this.updatePlayerMovement(delta); 126 | this.updateRockets(delta); 127 | this.updateChatList(); 128 | this.updateStats(); 129 | this.updateCloneCube(); 130 | 131 | this.stats.update(); 132 | this.renderer.render(this.scene, this.camera); 133 | this.renderer.autoClear = false; 134 | this.renderer.render(this.hudScene, this.hudCamera); 135 | } 136 | 137 | createCloneCube() { 138 | const geometry = new THREE.BoxGeometry(); 139 | const material = new THREE.MeshBasicMaterial({ color: 0x00ffff }); 140 | this.cube = new THREE.Mesh(geometry, material); 141 | this.scene.add(this.cube); 142 | } 143 | 144 | createMannequin() { 145 | const headGeo = new THREE.BoxGeometry(1, 1, 1); 146 | const bodyGeo = new THREE.BoxGeometry(0.7, 1, 0.7); 147 | const gunGeo = new THREE.BoxGeometry(1.5, 0.2, 0.2); 148 | 149 | const playerMat = new THREE.MeshNormalMaterial(); 150 | const gunMat = new THREE.MeshPhongMaterial(); 151 | gunMat.color = new THREE.Color(0x000000); 152 | 153 | const playerHead = new THREE.Mesh(headGeo, playerMat); 154 | const playerBody = new THREE.Mesh(bodyGeo, playerMat); 155 | const playerGun = new THREE.Mesh(gunGeo, gunMat); 156 | 157 | playerBody.position.set(0, -1, 0); 158 | playerGun.position.set(0.3, -1, 0.5); 159 | 160 | const playerModel = new THREE.Group(); 161 | playerModel.add(playerHead); 162 | playerModel.add(playerBody); 163 | playerModel.add(playerGun); 164 | 165 | this.scene.add(playerModel); 166 | playerModel.position.set(5, 0, 0); 167 | } 168 | 169 | updateCloneCube() { 170 | const position = this.playerCapsule.end; 171 | this.cube.position.set(position.x + 2, position.y + 2, position.z + 2); 172 | } 173 | 174 | // ------------------------------------------------ 175 | // Main init functions during loading screen 176 | 177 | initAudio() { 178 | console.log('init audio'); 179 | const loadingManager = this.loadingManager; 180 | const audioLoader = this.audioLoader; 181 | const audioMap = this.audioMap; 182 | const listener = this.listener; 183 | 184 | const rocketExplode = new THREE.PositionalAudio(listener); 185 | const rocketFly = new THREE.PositionalAudio(listener); 186 | const ambientSong = new THREE.Audio(listener); 187 | 188 | audioLoader.load('sounds/rocket-explode.ogg', (buffer) => 189 | rocketExplode.setBuffer(buffer) 190 | ); 191 | 192 | audioLoader.load('sounds/rocket-flying.ogg', (buffer) => 193 | rocketFly.setBuffer(buffer) 194 | ); 195 | 196 | audioLoader.load('sounds/slownomotion.ogg', (buffer) => { 197 | ambientSong.setBuffer(buffer); 198 | ambientSong.setLoop(true); 199 | ambientSong.setVolume(0.02); 200 | // ambientSong.play(); 201 | }); 202 | 203 | audioMap.set('rocketFly', rocketFly); 204 | audioMap.set('rocketExplode', rocketExplode); 205 | audioMap.set('ambientSong', ambientSong); 206 | 207 | loadingManager.onProgress = (url, itemsLoaded, itemsTotal) => { 208 | console.log( 209 | 'Loading file: ' + 210 | url + 211 | '.\nLoaded ' + 212 | itemsLoaded + 213 | ' of ' + 214 | itemsTotal + 215 | ' files.' 216 | ); 217 | }; 218 | 219 | loadingManager.onError = function (url) { 220 | console.log('There was an error loading ' + url); 221 | }; 222 | 223 | return new Promise((resolve) => { 224 | loadingManager.onLoad = () => { 225 | resolve(); 226 | console.log('All loading completed!'); 227 | }; 228 | }); 229 | } 230 | 231 | initScene() { 232 | this.gui = new dat.GUI(); 233 | this.clock = new THREE.Clock(); 234 | this.scene = new THREE.Scene(); 235 | 236 | this.camera = new THREE.PerspectiveCamera( 237 | 75, 238 | window.innerWidth / window.innerHeight, 239 | 0.1, 240 | 2000 241 | ); 242 | this.camera.add(this.listener); 243 | 244 | this.renderer = new THREE.WebGLRenderer({ 245 | powerPreference: 'high-performance', 246 | antialias: false, 247 | }); 248 | this.renderer.setSize(window.innerWidth, window.innerHeight); 249 | this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1)); 250 | this.renderer.shadowMap.enabled = true; 251 | this.renderer.shadowMap.type = THREE.PCFSoftShadowMap; 252 | this.ui.body.appendChild(this.renderer.domElement); 253 | 254 | window.addEventListener('resize', () => { 255 | this.camera.aspect = window.innerWidth / window.innerHeight; 256 | this.camera.updateProjectionMatrix(); 257 | this.renderer.setSize(window.innerWidth, window.innerHeight); 258 | this.hudSetSize(window.innerWidth, window.innerHeight); 259 | this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1)); 260 | }); 261 | 262 | // Maybe other init functions here such as field, playermodel, map, objects, rockets etc in here 263 | console.log('init scene'); 264 | } 265 | 266 | initSkybox() { 267 | this.scene.background = new THREE.CubeTextureLoader().load([ 268 | 'skybox/Right_Tex.webp', 269 | 'skybox/Left_Tex.webp', 270 | 'skybox/Up_Tex.webp', 271 | 'skybox/Down_Tex.webp', 272 | 'skybox/Front_Tex.webp', 273 | 'skybox/Back_Tex.webp', 274 | ]); 275 | 276 | console.log('init skybox'); 277 | } 278 | 279 | initMap() { 280 | const ambientLight = new THREE.AmbientLight(0xddbf96, 0.6); // Soft white light 281 | const dirLight = new THREE.DirectionalLight(0xfcd6a4, 1); 282 | 283 | dirLight.position.set(-25, 250, 120); 284 | dirLight.castShadow = true; 285 | dirLight.shadow.camera.near = 1; 286 | dirLight.shadow.camera.far = 2000; 287 | dirLight.shadow.camera.right = 250; 288 | dirLight.shadow.camera.left = -250; 289 | dirLight.shadow.camera.top = 250; 290 | dirLight.shadow.camera.bottom = -250; 291 | dirLight.shadow.mapSize.width = 4064; 292 | dirLight.shadow.mapSize.height = 4064; 293 | dirLight.shadow.radius = 0.6; 294 | 295 | this.scene.add(ambientLight); 296 | this.scene.add(dirLight); 297 | 298 | const gltfLoader = new GLTFLoader().setPath('models/'); 299 | const dracoLoader = new DRACOLoader(); 300 | dracoLoader.setDecoderPath('draco/'); 301 | gltfLoader.setDRACOLoader(dracoLoader); 302 | gltfLoader.load('scene.glb', (gltf) => { 303 | gltf.scene.traverse((model) => { 304 | model.receiveShadow = true; 305 | model.castShadow = true; 306 | }); 307 | gltf.scene.receiveShadow = true; 308 | gltf.scene.castShadow = true; 309 | this.world.add(gltf.scene); 310 | this.worldOctree.fromGraphNode(gltf.scene); 311 | }); 312 | gltfLoader.load('tree.gltf', (gltf) => { 313 | gltf.scene.traverse((model) => { 314 | model.castShadow = true; 315 | }); 316 | gltf.scene.scale.set(35, 35, 35); 317 | gltf.scene.position.set(-3, -10, -3); 318 | this.world.add(gltf.scene); 319 | }); 320 | 321 | // TEST Objects 322 | const geometry = new THREE.IcosahedronGeometry(1); 323 | const bgGeometry = new THREE.PlaneBufferGeometry(1500, 1500, 128, 128); 324 | 325 | const textureRock = new THREE.TextureLoader().load( 326 | 'models/rocktexture.jpg' 327 | ); 328 | textureRock.wrapS = THREE.RepeatWrapping; 329 | textureRock.wrapT = THREE.RepeatWrapping; 330 | textureRock.repeat.set(1, 1); 331 | 332 | const displacementMap = new THREE.TextureLoader().load( 333 | 'models/paintbg.png' 334 | ); 335 | displacementMap.wrapS = THREE.RepeatWrapping; 336 | displacementMap.wrapT = THREE.RepeatWrapping; 337 | displacementMap.repeat.set(1, 1); 338 | const textMat = new THREE.MeshPhongMaterial({ 339 | color: '#030303', 340 | map: textureRock, 341 | shininess: 0, 342 | displacementMap: displacementMap, 343 | displacementScale: 500, 344 | displacementBias: -0.428408, 345 | }); 346 | 347 | const bgMaterial = new THREE.MeshBasicMaterial(); 348 | bgMaterial.color = new THREE.Color(0xff111111); 349 | const material = new THREE.MeshPhongMaterial(); 350 | material.color = new THREE.Color(0xff109000); 351 | 352 | const sphere = new THREE.Mesh(geometry, material); 353 | const bgfull = new THREE.Mesh(bgGeometry, textMat); 354 | 355 | bgfull.position.set(0, -210, 0); 356 | bgfull.rotation.x = -89.5; 357 | bgfull.rotation.z = 89.5; 358 | 359 | sphere.castShadow = true; 360 | sphere.position.set(0, 75, 0); 361 | sphere.scale.set(2, 2, 2); 362 | 363 | this.scene.add(bgfull); 364 | this.world.add(sphere); 365 | this.scene.add(this.world); 366 | this.worldOctree.fromGraphNode(this.world); 367 | 368 | console.log('init map'); 369 | } 370 | 371 | initPlayer() { 372 | this.playerVelocity = new THREE.Vector3(); 373 | this.playerDirection = new THREE.Vector3(); 374 | this.upVector = new THREE.Vector3(0, 1, 0); 375 | 376 | // https://wickedengine.net/2020/04/26/capsule-collision-detection/ 377 | this.playerCapsule = new Capsule( 378 | new THREE.Vector3(), 379 | new THREE.Vector3(0, 2, 0), 380 | 0.5 381 | ); 382 | 383 | this.triggerRespawn(); 384 | this.playerCapsule.translate(this.teleportVec.set(0, 100, 0)); 385 | 386 | console.log('init player'); 387 | } 388 | 389 | initCrosshair() { 390 | const textureLoader = this.textureLoader; 391 | 392 | let texture = textureLoader.load('images/crosshair.png'); 393 | texture.matrixAutoUpdate = false; 394 | this.textureMap.set('crosshair', texture); 395 | 396 | const crosshairTexture = this.textureMap.get('crosshair'); 397 | const crosshairMat = new SpriteMaterial({ 398 | map: crosshairTexture, 399 | opacity: 1, 400 | }); 401 | 402 | const crosshair = new Sprite(crosshairMat); 403 | crosshair.matrixAutoUpdate = false; 404 | crosshair.visible = true; 405 | crosshair.position.set(0, 0, 2); 406 | crosshair.scale.set(70, 70, 1); 407 | crosshair.updateMatrix(); 408 | 409 | this.ui.crosshair = crosshair; 410 | 411 | this.hudCamera = new OrthographicCamera( 412 | -window.innerWidth / 2, 413 | window.innerWidth / 2, 414 | window.innerHeight / 2, 415 | -window.innerHeight / 2, 416 | 1, 417 | 10 418 | ); 419 | this.hudCamera.position.z = 10; 420 | this.hudScene = new Scene(); 421 | this.hudScene.add(crosshair); 422 | 423 | console.log('init crosshair'); 424 | return this; 425 | } 426 | 427 | initExplosion() { 428 | this.shaderLoader.load( 429 | 'models/explosion.png', 430 | (texture) => { 431 | this.explosionMaterial = new THREE.ShaderMaterial({ 432 | uniforms: { 433 | tExplosion: { 434 | type: 't', 435 | value: texture, 436 | }, 437 | time: { 438 | type: 'f', 439 | value: 0.0, 440 | }, 441 | }, 442 | vertexShader: explosionVertex, 443 | fragmentShader: explosionFragment, 444 | }); 445 | 446 | this.rocketExplosion = new THREE.Mesh( 447 | new THREE.IcosahedronGeometry(10, 10), 448 | this.explosionMaterial 449 | ); 450 | this.scene.add(this.rocketExplosion); 451 | this.rocketExplosion.position.set(0, 10, -50); 452 | console.log('init explosions'); 453 | 454 | this.initRockets(); 455 | }, 456 | undefined, 457 | function (err) { 458 | console.error( 459 | 'An error happened whilst loading initExplosions' 460 | ); 461 | } 462 | ); 463 | } 464 | 465 | initRockets() { 466 | const rocketGeometry = new THREE.CylinderGeometry(0.05, 0.15, 2, 12); 467 | const rocketMaterial = new THREE.MeshPhongMaterial(); 468 | rocketMaterial.color = new THREE.Color(0x000000); 469 | 470 | this.frontRocketLight = new THREE.PointLight(0xffaa00, 0.1); 471 | this.backRocketLight = new THREE.PointLight(0xff0000, 0.1); 472 | 473 | this.scene.add(this.frontRocketLight, this.backRocketLight); 474 | 475 | this.frontRocketLight.castShadow = true; 476 | this.backRocketLight.castShadow = true; 477 | 478 | for (let i = 0; i < this.maxRockets; i++) { 479 | const coolRocket = new THREE.Mesh(rocketGeometry, rocketMaterial); 480 | const coolExplosion = this.rocketExplosion.clone(); 481 | coolRocket.castShadow = true; 482 | coolRocket.receiveShadow = true; 483 | coolRocket.userData.isExploded = false; 484 | 485 | const audioFly = this.createAudioInstance( 486 | this.audioMap.get('rocketFly') 487 | ); 488 | const audioExplode = this.createAudioInstance( 489 | this.audioMap.get('rocketExplode') 490 | ); 491 | coolRocket.add(audioFly); 492 | coolRocket.add(audioExplode); 493 | 494 | coolExplosion.position.set(0, 0, 0); 495 | coolExplosion.visible = false; 496 | coolExplosion.name = 'explosion'; 497 | this.scene.add(coolRocket); 498 | coolRocket.add(coolExplosion); 499 | 500 | this.rockets.push({ 501 | mesh: coolRocket, 502 | collider: new THREE.Sphere(new THREE.Vector3(0, -50, 0), 0.5), 503 | velocity: new THREE.Vector3(), 504 | timer: new THREE.Clock(), 505 | }); 506 | } 507 | console.log('init rockets'); 508 | } 509 | 510 | initStats() { 511 | this.stats = new Stats(); 512 | this.drawCallPanel = this.stats.addPanel( 513 | new Stats.Panel('drawcalls', '#ff8', '#221') 514 | ); 515 | this.stats.showPanel(0, 1, 3); 516 | this.ui.body.appendChild(this.stats.domElement); 517 | this.ui.body.appendChild(this.stats.domElement); 518 | 519 | this.lastTime = performance.now(); 520 | } 521 | 522 | initDevWIP() { 523 | this.createCloneCube(); 524 | this.createMannequin(); 525 | } 526 | 527 | initSocket() { 528 | console.log('init socket'); 529 | this.socket = io('https://three-arena.fly.dev/'); 530 | 531 | this.player = {}; 532 | this.players = {}; 533 | 534 | this.socket.on('connect', () => { 535 | this.socket.on('initPlayer', (data, playerCount, playerIDs) => { 536 | this.player.id = data.id; 537 | console.log( 538 | `I am ${this.socket.id}, the ${playerCount}${ 539 | playerCount <= 1 540 | ? 'st' 541 | : playerCount == 2 542 | ? 'nd' 543 | : playerCount == 3 544 | ? 'rd' 545 | : 'th' 546 | } player` 547 | ); 548 | 549 | // Check all that isn't local player 550 | for (let i = 0; i < playerCount; i++) { 551 | if (playerIDs[i] !== this.player.id) { 552 | console.log( 553 | `${playerIDs[i]} needs to be added to the world...` 554 | ); 555 | this.initRemotePlayer(playerIDs[i]); 556 | } 557 | } 558 | }); 559 | }); 560 | 561 | this.socket.on('playerPositions', (players) => { 562 | this.updateRemotePlayers(players); 563 | }); 564 | 565 | this.socket.on('player connect', (playerId, playerCount) => { 566 | console.log(`${playerId} joined the session!`); 567 | console.log(`There are now ${playerCount} players`); 568 | if (playerId !== this.player.id) { 569 | console.log(`${playerId} needs to be added to the world...`); 570 | this.initRemotePlayer(playerId); 571 | } 572 | this.addStatusMessage(playerId, 'join'); 573 | }); 574 | 575 | this.socket.on('player disconnect', (playerId, playerCount) => { 576 | this.deleteRemotePlayer(playerId); 577 | console.log(`${playerId} has left us...`); 578 | console.log(`There are now ${playerCount} players`); 579 | this.addStatusMessage(playerId, 'leave'); 580 | }); 581 | 582 | this.socket.on('connect', () => { 583 | this.socket.on('chat message', (username, message) => { 584 | this.addChatMessage(username, message); 585 | }); 586 | }); 587 | 588 | this.socket.on('shootSyncRocket', (playerData, playerID) => { 589 | this.shootRemoteRocket(playerData, playerID); 590 | }); 591 | 592 | this.socket.on('kill message', (shooter, killed) => { 593 | if (shooter) { 594 | this.addKillMessage(shooter, killed); 595 | } else { 596 | this.addKillMessage(killed); 597 | } 598 | }); 599 | } 600 | 601 | initRemotePlayer(playerID) { 602 | const geometry = new THREE.BoxGeometry(1, 1, 1); 603 | const material = new THREE.MeshNormalMaterial(); 604 | material.color = new THREE.Color(0x000000); 605 | 606 | const remotePlayer = new THREE.Mesh(geometry, material); 607 | remotePlayer.position.set(0, 0, 0); 608 | 609 | this.scene.add(remotePlayer); 610 | 611 | this.players[playerID] = {}; 612 | this.players[playerID].mesh = remotePlayer; 613 | this.players[playerID].positionSync = new THREE.Vector3(); 614 | this.players[playerID].lookDirection = new THREE.Vector3(); 615 | 616 | console.log(`${playerID} added to the scene!`); 617 | console.log(this.players); 618 | } 619 | 620 | deleteRemotePlayer(playerID) { 621 | this.scene.remove(this.players[playerID].mesh); 622 | delete this.players[playerID]; 623 | console.log(this.players); 624 | } 625 | 626 | updateRemotePlayers(remotePlayers) { 627 | for (let id in remotePlayers) { 628 | if (id != this.player.id) { 629 | // Should not forget to reuse vectors 630 | this.players[id].positionSync = new THREE.Vector3().fromArray( 631 | remotePlayers[id].position 632 | ); 633 | this.players[id].lookDirection = new THREE.Vector3().fromArray( 634 | remotePlayers[id].direction 635 | ); 636 | 637 | // Set player position 638 | this.players[id].mesh.position.set( 639 | this.players[id].positionSync.x, 640 | this.players[id].positionSync.y, 641 | this.players[id].positionSync.z 642 | ); 643 | 644 | // Set head rotation 645 | this.players[id].mesh.rotation.y = 646 | this.players[id].lookDirection.x; 647 | this.players[id].mesh.rotation.x = 648 | this.players[id].lookDirection.y; 649 | } 650 | } 651 | } 652 | 653 | uploadMovementData() { 654 | this.socket.emit( 655 | 'updateClientPos', 656 | [ 657 | this.playerCapsule.end.x, 658 | this.playerCapsule.end.y, 659 | this.playerCapsule.end.z, 660 | ], 661 | this.lookVector().toArray() 662 | ); 663 | } 664 | 665 | // ------------------------------------------------ 666 | // Activate functions when game starts 667 | 668 | activatePointerLock() { 669 | this.ui.body.requestPointerLock(); 670 | 671 | document.querySelector('canvas').addEventListener('mousedown', () => { 672 | !this.inputDisabled && this.ui.body.requestPointerLock(); 673 | }); 674 | 675 | this.camera.rotation.order = 'YXZ'; 676 | 677 | document.addEventListener('mousemove', (event) => { 678 | if (document.pointerLockElement === this.ui.body) { 679 | // add check looking for 360 rotation 680 | this.camera.rotation.x -= event.movementY / 700; 681 | this.camera.rotation.y -= event.movementX / 700; 682 | } 683 | }); 684 | 685 | document.addEventListener('pointerlockchange', () => { 686 | this.playerFocused = document.pointerLockElement === this.ui.body; 687 | console.log(`Player Focus is ${this.playerFocused}`); 688 | }); 689 | 690 | document.addEventListener( 691 | 'click', 692 | (event) => { 693 | if (this.inputDisabled) { 694 | event.stopPropagation(); 695 | event.preventDefault(); 696 | } 697 | }, 698 | true 699 | ); 700 | 701 | console.log('Activate pointerlock'); 702 | } 703 | 704 | activateGamePause() { 705 | this.ui.pauseButton.addEventListener('click', () => { 706 | this.toggle = !this.toggle; 707 | this.toggle ? this.stopAnimation() : this.startAnimation(); 708 | }); 709 | } 710 | 711 | activateMovement() { 712 | document.addEventListener('keydown', (event) => { 713 | !this.inputDisabled && (this.Key[event.key] = true); 714 | if (event.key == 'Enter') { 715 | event.preventDefault(); 716 | } 717 | }); 718 | document.addEventListener('keyup', (event) => { 719 | this.Key[event.key] = false; 720 | }); 721 | 722 | console.log('Activate movement controls'); 723 | } 724 | 725 | activateRocketShooting() { 726 | let canShoot = true; 727 | 728 | document.addEventListener('click', () => { 729 | if (canShoot) { 730 | // Currently bug causes rocket to misalign after reaching maxRocket count, AKA when rocketIdx is reset. 731 | const rocket = this.rockets[this.rocketIdx]; 732 | 733 | // Align rocket to look direction 734 | rocket.mesh.lookAt(this.lookVector().negate()); 735 | 736 | rocket.mesh.add(this.frontRocketLight, this.backRocketLight); 737 | this.frontRocketLight.position.set(0, -1.1, 0); 738 | this.backRocketLight.position.set(0, -1.2, 0); 739 | this.frontRocketLight.power = 120; 740 | this.backRocketLight.power = 100; 741 | this.frontRocketLight.distance = 10; 742 | this.backRocketLight.distance = 10; // use for animation 743 | 744 | // Copy player head pos to projectile center 745 | rocket.collider.center.copy(this.playerCapsule.end); 746 | 747 | // Apply force in look direction 748 | rocket.velocity 749 | .copy(this.lookVector()) 750 | .multiplyScalar(this.rocketForce); 751 | 752 | // Reset explode state 753 | rocket.mesh.userData.isExploded = false; 754 | 755 | // Set rocket visible 756 | rocket.mesh.visible = true; 757 | 758 | // Emit to other players 759 | this.socket.emit('triggerRemoteRocket'); 760 | 761 | this.rocketIdx = (this.rocketIdx + 1) % this.rockets.length; 762 | 763 | canShoot = false; 764 | console.log('Rocket fired'); 765 | 766 | setTimeout(() => { 767 | canShoot = true; 768 | }, 500); 769 | } 770 | }); 771 | } 772 | 773 | shootRemoteRocket(playerData, playerID) { 774 | const rocket = this.rockets[this.rocketIdx]; 775 | const playerPosition = new THREE.Vector3().fromArray( 776 | playerData.position 777 | ); 778 | const playerDirection = new THREE.Vector3().fromArray( 779 | playerData.direction 780 | ); 781 | 782 | // Model direction 783 | rocket.mesh.lookAt(playerDirection.negate()); 784 | 785 | rocket.mesh.add(this.frontRocketLight, this.backRocketLight); 786 | this.frontRocketLight.position.set(0, -1.1, 0); 787 | this.backRocketLight.position.set(0, -1.2, 0); 788 | this.frontRocketLight.power = 120; 789 | this.backRocketLight.power = 100; 790 | this.frontRocketLight.distance = 10; 791 | this.backRocketLight.distance = 10; // Could be used for explosion animation 792 | 793 | // Spawn Position 794 | rocket.collider.center.copy(playerPosition); 795 | 796 | // Spawn shoot direction 797 | rocket.velocity 798 | .copy(playerDirection.negate()) 799 | .multiplyScalar(this.rocketForce); 800 | 801 | // Reset explode state 802 | rocket.mesh.userData.isExploded = false; 803 | 804 | // Set rocket owner 805 | rocket.mesh.userData.shooter = playerID; 806 | 807 | // Set visible 808 | rocket.mesh.visible = true; 809 | 810 | this.rocketIdx = (this.rocketIdx + 1) % this.rockets.length; 811 | 812 | console.log('Remote rocket fired'); 813 | } 814 | 815 | // ------------------------------------------------ 816 | // Functions to update game in animation function (tick) 817 | 818 | updatePlayerControl(delta) { 819 | if (this.Key['w']) { 820 | this.playerVelocity.add( 821 | this.lookVector().multiplyScalar(this.playerSpeed * delta) 822 | ); 823 | } 824 | if (this.Key['a']) { 825 | this.playerVelocity.add( 826 | this.playerDirection.crossVectors( 827 | this.upVector, 828 | this.lookVector().multiplyScalar(this.playerSpeed * delta) 829 | ) 830 | ); 831 | } 832 | if (this.Key['s']) { 833 | this.playerVelocity.add( 834 | this.lookVector() 835 | .negate() 836 | .multiplyScalar(this.playerSpeed * delta) 837 | ); 838 | } 839 | if (this.Key['d']) { 840 | this.playerVelocity.add( 841 | this.playerDirection.crossVectors( 842 | this.upVector, 843 | this.lookVector() 844 | .negate() 845 | .multiplyScalar(this.playerSpeed * delta) 846 | ) 847 | ); 848 | } 849 | if (this.isPlayerGrounded) { 850 | if (this.Key[' ']) { 851 | this.playerVelocity.y = 50; 852 | } 853 | } 854 | if (this.Key['Control']) { 855 | this.playerVelocity.y -= this.playerSpeed * delta; 856 | } 857 | if (this.Key['e']) { 858 | this.playerVelocity.set(0, 0, 0); 859 | } 860 | if (this.Key['t']) { 861 | openForm(); 862 | } 863 | if (this.Key['Enter']) { 864 | closeForm(); 865 | let inputText = document.getElementById('inputText'); 866 | if (inputText.value !== '') { 867 | this.socket.emit( 868 | 'chat message', 869 | this.socket.id, 870 | inputText.value 871 | ); 872 | inputText.value = ''; 873 | } 874 | } 875 | } 876 | 877 | updateCheckOnGround(delta) { 878 | if (this.isPlayerGrounded) { 879 | this.playerVelocity.addScaledVector( 880 | this.playerVelocity, 881 | -5 * delta 882 | ); 883 | } else if (this.playerFocused) { 884 | this.playerVelocity.y -= this.gravity * delta; 885 | } 886 | } 887 | 888 | updatePlayerMovement(delta) { 889 | // if (this.collisionsEnabled) { 890 | this.playerCollision(); 891 | // } 892 | 893 | if (this.playerFocused) { 894 | const deltaPosition = this.playerVelocity 895 | .clone() 896 | .multiplyScalar(delta); 897 | this.playerCapsule.translate(deltaPosition); 898 | this.camera.position.copy(this.playerCapsule.end); 899 | 900 | this.uploadMovementData(); 901 | } 902 | 903 | if ( 904 | this.camera.position.y < -10 && 905 | Math.abs(this.camera.position.x) <= 125 && 906 | Math.abs(this.camera.position.z) <= 125 907 | ) { 908 | console.log('Player glitched through floor, correction applied'); 909 | this.teleportToGround(); 910 | this.playerVelocity.setY(0); 911 | // this.collisionsEnabled = true; 912 | } 913 | 914 | if (this.camera.position.y < -200) { 915 | console.log('Player fell off the map, up they go'); 916 | let pushForce = 200; 917 | this.camera.position.y < -500 && (pushForce = 500); 918 | this.playerVelocity.set(0, 0, 0); 919 | this.playerVelocity.y = pushForce; 920 | // this.collisionsEnabled = false; 921 | 922 | if (this.camera.position.y < -1000) { 923 | console.log('Player way off, teleported back up'); 924 | this.teleportToGround(50); 925 | this.playerVelocity.set(0, 0, 0); 926 | } 927 | 928 | setTimeout(() => { 929 | this.camera.position.y > -200 && 930 | console.log('World collisions re-enabled'); 931 | // this.collisionsEnabled = true; 932 | }, 2500); 933 | } 934 | } 935 | 936 | updateRockets(delta) { 937 | if (this.explosionMaterial) { 938 | this.explosionMaterial.uniforms['time'].value = 939 | 0.00025 * (Date.now() - this.explosionTime); 940 | } 941 | 942 | this.rockets.forEach((rocket) => { 943 | rocket.collider.center.addScaledVector(rocket.velocity, delta); 944 | 945 | // Check collision 946 | const result = this.worldOctree.sphereIntersect(rocket.collider); 947 | 948 | let airRocketIdx; 949 | if (this.rocketIdx > 0) { 950 | airRocketIdx = this.rocketIdx - 1; 951 | } else { 952 | airRocketIdx = this.rocketIdx; 953 | } 954 | 955 | const flySound = this.rockets[airRocketIdx].mesh.children[0]; 956 | const explodeSound = this.rockets[airRocketIdx].mesh.children[1]; 957 | 958 | if (this.rocketIdx !== this.deltaRocket) { 959 | this.deltaRocket = this.rocketIdx; 960 | 961 | flySound.offset = 1; 962 | flySound.play(); 963 | } 964 | 965 | // On rocket impact 966 | if (result) { 967 | rocket.velocity.set(0, 0, 0); 968 | const explodeMesh = rocket.mesh.getObjectByName('explosion'); 969 | 970 | if (!rocket.mesh.userData.isExploded) { 971 | rocket.mesh.userData.isExploded = true; 972 | console.log('Rocket hit'); 973 | 974 | const playerDistance = 975 | this.playerCapsule.end.distanceToSquared( 976 | rocket.collider.center 977 | ); 978 | 979 | // On Player hit 980 | if (playerDistance < 170) { 981 | this.socket.emit( 982 | 'kill message', 983 | rocket.mesh.userData.shooter, 984 | this.player.id 985 | ); 986 | 987 | this.triggerDeath(); 988 | } 989 | 990 | explodeSound.offset = 0.05; 991 | explodeSound.play(); 992 | flySound.stop(); 993 | 994 | explodeMesh.visible = true; 995 | rocket.timer.start(); 996 | } 997 | 998 | if (rocket.timer.getElapsedTime() >= 0.2) { 999 | { 1000 | // Plays once 1001 | rocket.timer.stop(); 1002 | explodeMesh.scale.set(0, 0, 0); 1003 | explodeMesh.position.set(0, 0, 0); 1004 | rocket.mesh.visible = false; 1005 | 1006 | // For looping animation, both do same thing, start() would seem most efficient 1007 | // this.explodeClock = new THREE.Clock(); 1008 | // rocket.timer.start() 1009 | } 1010 | } else { 1011 | let size = 0 + rocket.timer.getElapsedTime() * 8; 1012 | explodeMesh.scale.set(size, size, size); 1013 | } 1014 | } else { 1015 | // Whilst in air 1016 | rocket.velocity.y -= (this.gravity / 15) * delta; 1017 | } 1018 | 1019 | // Accelerate with time 1020 | const acceleration = Math.exp(3 * delta) - 1; 1021 | rocket.velocity.addScaledVector(rocket.velocity, acceleration); 1022 | 1023 | rocket.mesh.position.copy(rocket.collider.center); 1024 | }); 1025 | } 1026 | 1027 | updateChatList() { 1028 | const chatMessages = this.chatMessages; 1029 | 1030 | for (let i = chatMessages.length - 1; i >= 0; i--) { 1031 | const message = chatMessages[i]; 1032 | 1033 | if (this.elaspedTime >= message.endTime) { 1034 | chatMessages.splice(i, 1); 1035 | 1036 | const chatList = this.ui.chatList; 1037 | chatList.removeChild(message.ui); 1038 | } 1039 | } 1040 | 1041 | if (chatMessages.length === 0) { 1042 | this.ui.chatSection.classList.add('hidden'); 1043 | } 1044 | 1045 | return this; 1046 | } 1047 | 1048 | updateStats() { 1049 | this.ui.velocityStats.innerHTML = ` 1050 | X: ${this.roundStat(this.playerVelocity.x)}
1051 | Y: ${this.roundStat(this.playerVelocity.y)}
1052 | Z: ${this.roundStat(this.playerVelocity.z)}`; 1053 | 1054 | this.ui.positionStats.innerHTML = ` 1055 | X: ${this.roundStat(this.camera.position.x)}
1056 | Y: ${this.roundStat(this.camera.position.y)}
1057 | Z: ${this.roundStat(this.camera.position.z)}`; 1058 | 1059 | if (performance.now() - this.lastTime < 1000 / 1) return; 1060 | this.lastTime = performance.now(); 1061 | this.drawCallPanel.update(this.renderer.info.render.calls); 1062 | } 1063 | 1064 | // ------------------------------------------------ 1065 | // General functions 1066 | 1067 | triggerDeath() { 1068 | console.log('You died'); 1069 | document.exitPointerLock(); 1070 | this.respawnWaitingRoom(); 1071 | this.inputDisabled = true; 1072 | this.ui.respawnButton.style.pointerEvents = 'none'; 1073 | this.ui.respawnButton.style.userSelect = 'none'; 1074 | this.ui.respawnButton.style.display = 'block'; 1075 | this.ui.respawnButton.lastChild.style.fontSize = '30px'; 1076 | this.ui.respawnButton.lastChild.style.transform = 'translate(0px, 0px)'; 1077 | this.ui.respawnButton.lastChild.textContent = `Respawn in 5`; 1078 | 1079 | let countdown = 5; 1080 | const timer = setInterval(() => { 1081 | countdown--; 1082 | countdown <= 0 && clearInterval(timer); 1083 | this.ui.respawnButton.lastChild.textContent = `Respawn in ${countdown}`; 1084 | }, 1000); 1085 | 1086 | setTimeout(() => { 1087 | console.log('You can now respawn'); 1088 | this.inputDisabled = false; 1089 | this.ui.respawnButton.style.userSelect = 'unset'; 1090 | this.ui.respawnButton.style.pointerEvents = 'unset'; 1091 | this.ui.respawnButton.lastChild.textContent = `RESPAWN`; 1092 | this.ui.respawnButton.lastChild.style.fontSize = '40px'; 1093 | this.ui.respawnButton.lastChild.style.transform = 1094 | 'translate(8px, 8px)'; 1095 | }, 5000); 1096 | } 1097 | 1098 | triggerRespawn() { 1099 | console.log('Respawn triggered'); 1100 | const distFromX = -this.playerCapsule.end.x; 1101 | const distToGround = Math.abs(this.playerCapsule.end.y); 1102 | const distFromZ = -this.playerCapsule.end.z; 1103 | this.playerCapsule.translate( 1104 | this.teleportVec.set( 1105 | distFromX + this.getRandomBetween(10, 120), 1106 | distToGround + 50, 1107 | distFromZ + this.getRandomBetween(10, 120) 1108 | ) 1109 | ); 1110 | this.playerVelocity.set(0, 0, 0); 1111 | this.gravity = 70; 1112 | } 1113 | 1114 | addChatMessage(username, message) { 1115 | const usernameSpan = document.createElement('span'); 1116 | usernameSpan.style.color = '#0fff00'; 1117 | usernameSpan.textContent = username; 1118 | 1119 | const middleSpan = document.createElement('span'); 1120 | middleSpan.textContent = ': '; 1121 | 1122 | const messageSpan = document.createElement('span'); 1123 | messageSpan.style.color = '#ffffff'; 1124 | messageSpan.textContent = message; 1125 | 1126 | const content = document.createElement('li'); 1127 | content.appendChild(usernameSpan); 1128 | content.appendChild(middleSpan); 1129 | content.appendChild(messageSpan); 1130 | 1131 | this.createMessage(content); 1132 | } 1133 | 1134 | addKillMessage(shooter, killed) { 1135 | const shooterSpan = document.createElement('span'); 1136 | shooterSpan.textContent = `${shooter}`; 1137 | shooterSpan.style.color = '#00ff00'; 1138 | 1139 | const middleSpan = document.createElement('span'); 1140 | middleSpan.textContent = ' ︻┳═一 '; 1141 | 1142 | const killedSpan = document.createElement('span'); 1143 | killedSpan.textContent = killed; 1144 | killedSpan.style.color = '#ff0000'; 1145 | 1146 | const content = document.createElement('li'); 1147 | content.style.color = '#ffff00'; 1148 | content.style.fontWeight = '500'; 1149 | content.appendChild(shooterSpan); 1150 | content.appendChild(middleSpan); 1151 | content.appendChild(killedSpan); 1152 | 1153 | this.createMessage(content); 1154 | } 1155 | 1156 | addStatusMessage(username, status) { 1157 | const usernameSpan = document.createElement('span'); 1158 | usernameSpan.textContent = username; 1159 | 1160 | const statusSpan = document.createElement('span'); 1161 | statusSpan.textContent = status; 1162 | 1163 | const content = document.createElement('li'); 1164 | switch (status) { 1165 | case 'join': 1166 | content.style.color = '#00ff00'; 1167 | statusSpan.textContent = ' has joined the game'; 1168 | break; 1169 | case 'leave': 1170 | content.style.color = '#ff0000'; 1171 | statusSpan.textContent = ' has left the game '; 1172 | break; 1173 | default: 1174 | statusSpan.textContent = ' unknown status event '; 1175 | break; 1176 | } 1177 | content.appendChild(usernameSpan); 1178 | content.appendChild(statusSpan); 1179 | 1180 | this.createMessage(content); 1181 | } 1182 | 1183 | createMessage(content) { 1184 | this.ui.chatSection.classList.remove('hidden'); 1185 | 1186 | const chatMessage = { 1187 | endTime: this.elaspedTime + 10, 1188 | ui: content, 1189 | }; 1190 | 1191 | this.chatMessages.push(chatMessage); 1192 | const chatList = this.ui.chatList; 1193 | chatList.appendChild(content); 1194 | 1195 | return this; 1196 | } 1197 | 1198 | roundStat(data) { 1199 | return Math.round(data * 100) / 100; 1200 | } 1201 | 1202 | lookVector() { 1203 | this.camera.getWorldDirection(this.playerDirection); 1204 | this.playerDirection.normalize(); 1205 | return this.playerDirection; 1206 | } 1207 | 1208 | playerCollision() { 1209 | const collide = this.worldOctree.capsuleIntersect(this.playerCapsule); 1210 | this.isPlayerGrounded = false; 1211 | if (collide) { 1212 | this.isPlayerGrounded = collide.normal.y > 0; 1213 | 1214 | this.playerCapsule.translate( 1215 | collide.normal.multiplyScalar(collide.depth) 1216 | ); 1217 | } 1218 | } 1219 | 1220 | createAudioInstance(source) { 1221 | const audio = new source.constructor(source.listener); 1222 | audio.buffer = source.buffer; 1223 | 1224 | return audio; 1225 | } 1226 | 1227 | hudSetSize(width, height) { 1228 | this.hudCamera.left = -width / 2; 1229 | this.hudCamera.right = width / 2; 1230 | this.hudCamera.top = height / 2; 1231 | this.hudCamera.bottom = -height / 2; 1232 | this.hudCamera.updateProjectionMatrix(); 1233 | 1234 | return this; 1235 | } 1236 | 1237 | getRandomBetween(min, max) { 1238 | return Math.random() * (max - min) + min; 1239 | } 1240 | 1241 | teleportToGround(extraDistance = 0) { 1242 | const distToGround = Math.abs(this.playerCapsule.end.y); 1243 | this.playerCapsule.translate( 1244 | this.teleportVec.set(0, distToGround + extraDistance, 0) 1245 | ); 1246 | } 1247 | 1248 | toggleInputs() { 1249 | this.inputDisabled = !this.inputDisabled; 1250 | this.inputDisabled ? console.log('enabled') : console.log('disabled'); 1251 | } 1252 | 1253 | respawnWaitingRoom() { 1254 | this.gravity = 0; 1255 | const distFromX = -this.playerCapsule.end.x; 1256 | const distToGround = Math.abs(this.playerCapsule.end.y); 1257 | const distFromZ = -this.playerCapsule.end.z; 1258 | this.playerCapsule.translate( 1259 | this.teleportVec.set( 1260 | distFromX + 0, 1261 | distToGround - 50, 1262 | distFromZ + 0 1263 | ) 1264 | ); 1265 | this.playerVelocity.set(0, 0, 0); 1266 | } 1267 | 1268 | // ------------------------------------------------ 1269 | // In development functions 1270 | 1271 | createCloneCube() { 1272 | const geometry = new THREE.BoxGeometry(); 1273 | const material = new THREE.MeshBasicMaterial({ color: 0x00ffff }); 1274 | this.cube = new THREE.Mesh(geometry, material); 1275 | this.scene.add(this.cube); 1276 | } 1277 | 1278 | updateCloneCube() { 1279 | const position = this.playerCapsule.end; 1280 | this.cube.position.set(position.x + 2, position.y + 2, position.z + 2); 1281 | } 1282 | 1283 | createMannequin() { 1284 | const headGeo = new THREE.BoxGeometry(1, 1, 1); 1285 | const bodyGeo = new THREE.BoxGeometry(0.7, 1, 0.7); 1286 | const gunGeo = new THREE.BoxGeometry(1.5, 0.2, 0.2); 1287 | 1288 | const playerMat = new THREE.MeshNormalMaterial(); 1289 | const gunMat = new THREE.MeshPhongMaterial(); 1290 | gunMat.color = new THREE.Color(0x000000); 1291 | 1292 | const playerHead = new THREE.Mesh(headGeo, playerMat); 1293 | const playerBody = new THREE.Mesh(bodyGeo, playerMat); 1294 | const playerGun = new THREE.Mesh(gunGeo, gunMat); 1295 | 1296 | playerBody.position.set(0, -1, 0); 1297 | playerGun.position.set(0.3, -1, 0.5); 1298 | 1299 | const playerModel = new THREE.Group(); 1300 | playerModel.add(playerHead); 1301 | playerModel.add(playerBody); 1302 | playerModel.add(playerGun); 1303 | 1304 | this.scene.add(playerModel); 1305 | playerModel.position.set(5, 0, 0); 1306 | } 1307 | 1308 | checkPlayerData() { 1309 | const playerVelocity = this.playerVelocity.clone(); 1310 | const position = this.playerCapsule.end; 1311 | const look = this.lookVector(); 1312 | console.log('Velocity is'); 1313 | console.log(playerVelocity); 1314 | console.log('Position is'); 1315 | console.log(position); 1316 | console.log('Look direction is'); 1317 | console.log(look); 1318 | } 1319 | } 1320 | 1321 | function startAnimation() { 1322 | this.requestAnimId = requestAnimationFrame(this.startAnimation); 1323 | this.tick(); 1324 | } 1325 | 1326 | function stopAnimation() { 1327 | cancelAnimationFrame(this.requestAnimId); 1328 | } 1329 | 1330 | function openForm() { 1331 | document.getElementById('inputForm').style.display = 'block'; 1332 | document.getElementById('inputText').focus(); 1333 | } 1334 | 1335 | function closeForm() { 1336 | document.getElementById('inputForm').style.display = 'none'; 1337 | } 1338 | 1339 | export default new Game(); 1340 | -------------------------------------------------------------------------------- /server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "server", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "express": "^4.17.1", 13 | "socket.io": "^4.1.1" 14 | }, 15 | "engines": { 16 | "node": "15.14.0" 17 | } 18 | }, 19 | "node_modules/@types/component-emitter": { 20 | "version": "1.2.10", 21 | "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz", 22 | "integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==" 23 | }, 24 | "node_modules/@types/cookie": { 25 | "version": "0.4.0", 26 | "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.0.tgz", 27 | "integrity": "sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg==" 28 | }, 29 | "node_modules/@types/cors": { 30 | "version": "2.8.10", 31 | "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.10.tgz", 32 | "integrity": "sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ==" 33 | }, 34 | "node_modules/@types/node": { 35 | "version": "15.12.2", 36 | "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz", 37 | "integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==" 38 | }, 39 | "node_modules/accepts": { 40 | "version": "1.3.7", 41 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 42 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 43 | "dependencies": { 44 | "mime-types": "~2.1.24", 45 | "negotiator": "0.6.2" 46 | }, 47 | "engines": { 48 | "node": ">= 0.6" 49 | } 50 | }, 51 | "node_modules/array-flatten": { 52 | "version": "1.1.1", 53 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 54 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 55 | }, 56 | "node_modules/base64-arraybuffer": { 57 | "version": "0.1.4", 58 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", 59 | "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=", 60 | "engines": { 61 | "node": ">= 0.6.0" 62 | } 63 | }, 64 | "node_modules/base64id": { 65 | "version": "2.0.0", 66 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", 67 | "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", 68 | "engines": { 69 | "node": "^4.5.0 || >= 5.9" 70 | } 71 | }, 72 | "node_modules/body-parser": { 73 | "version": "1.19.0", 74 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 75 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 76 | "dependencies": { 77 | "bytes": "3.1.0", 78 | "content-type": "~1.0.4", 79 | "debug": "2.6.9", 80 | "depd": "~1.1.2", 81 | "http-errors": "1.7.2", 82 | "iconv-lite": "0.4.24", 83 | "on-finished": "~2.3.0", 84 | "qs": "6.7.0", 85 | "raw-body": "2.4.0", 86 | "type-is": "~1.6.17" 87 | }, 88 | "engines": { 89 | "node": ">= 0.8" 90 | } 91 | }, 92 | "node_modules/bytes": { 93 | "version": "3.1.0", 94 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 95 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", 96 | "engines": { 97 | "node": ">= 0.8" 98 | } 99 | }, 100 | "node_modules/component-emitter": { 101 | "version": "1.3.0", 102 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", 103 | "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" 104 | }, 105 | "node_modules/content-disposition": { 106 | "version": "0.5.3", 107 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 108 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 109 | "dependencies": { 110 | "safe-buffer": "5.1.2" 111 | }, 112 | "engines": { 113 | "node": ">= 0.6" 114 | } 115 | }, 116 | "node_modules/content-type": { 117 | "version": "1.0.4", 118 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 119 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 120 | "engines": { 121 | "node": ">= 0.6" 122 | } 123 | }, 124 | "node_modules/cookie": { 125 | "version": "0.4.0", 126 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 127 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", 128 | "engines": { 129 | "node": ">= 0.6" 130 | } 131 | }, 132 | "node_modules/cookie-signature": { 133 | "version": "1.0.6", 134 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 135 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 136 | }, 137 | "node_modules/cors": { 138 | "version": "2.8.5", 139 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 140 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 141 | "dependencies": { 142 | "object-assign": "^4", 143 | "vary": "^1" 144 | }, 145 | "engines": { 146 | "node": ">= 0.10" 147 | } 148 | }, 149 | "node_modules/debug": { 150 | "version": "2.6.9", 151 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 152 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 153 | "dependencies": { 154 | "ms": "2.0.0" 155 | } 156 | }, 157 | "node_modules/depd": { 158 | "version": "1.1.2", 159 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 160 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", 161 | "engines": { 162 | "node": ">= 0.6" 163 | } 164 | }, 165 | "node_modules/destroy": { 166 | "version": "1.0.4", 167 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 168 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 169 | }, 170 | "node_modules/ee-first": { 171 | "version": "1.1.1", 172 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 173 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 174 | }, 175 | "node_modules/encodeurl": { 176 | "version": "1.0.2", 177 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 178 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", 179 | "engines": { 180 | "node": ">= 0.8" 181 | } 182 | }, 183 | "node_modules/engine.io": { 184 | "version": "5.1.1", 185 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-5.1.1.tgz", 186 | "integrity": "sha512-aMWot7H5aC8L4/T8qMYbLdvKlZOdJTH54FxfdFunTGvhMx1BHkJOntWArsVfgAZVwAO9LC2sryPWRcEeUzCe5w==", 187 | "dependencies": { 188 | "accepts": "~1.3.4", 189 | "base64id": "2.0.0", 190 | "cookie": "~0.4.1", 191 | "cors": "~2.8.5", 192 | "debug": "~4.3.1", 193 | "engine.io-parser": "~4.0.0", 194 | "ws": "~7.4.2" 195 | }, 196 | "engines": { 197 | "node": ">=10.0.0" 198 | } 199 | }, 200 | "node_modules/engine.io-parser": { 201 | "version": "4.0.2", 202 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.2.tgz", 203 | "integrity": "sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==", 204 | "dependencies": { 205 | "base64-arraybuffer": "0.1.4" 206 | }, 207 | "engines": { 208 | "node": ">=8.0.0" 209 | } 210 | }, 211 | "node_modules/engine.io/node_modules/cookie": { 212 | "version": "0.4.1", 213 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", 214 | "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", 215 | "engines": { 216 | "node": ">= 0.6" 217 | } 218 | }, 219 | "node_modules/engine.io/node_modules/debug": { 220 | "version": "4.3.1", 221 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 222 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 223 | "dependencies": { 224 | "ms": "2.1.2" 225 | }, 226 | "engines": { 227 | "node": ">=6.0" 228 | }, 229 | "peerDependenciesMeta": { 230 | "supports-color": { 231 | "optional": true 232 | } 233 | } 234 | }, 235 | "node_modules/engine.io/node_modules/ms": { 236 | "version": "2.1.2", 237 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 238 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 239 | }, 240 | "node_modules/escape-html": { 241 | "version": "1.0.3", 242 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 243 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 244 | }, 245 | "node_modules/etag": { 246 | "version": "1.8.1", 247 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 248 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", 249 | "engines": { 250 | "node": ">= 0.6" 251 | } 252 | }, 253 | "node_modules/express": { 254 | "version": "4.17.1", 255 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 256 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 257 | "dependencies": { 258 | "accepts": "~1.3.7", 259 | "array-flatten": "1.1.1", 260 | "body-parser": "1.19.0", 261 | "content-disposition": "0.5.3", 262 | "content-type": "~1.0.4", 263 | "cookie": "0.4.0", 264 | "cookie-signature": "1.0.6", 265 | "debug": "2.6.9", 266 | "depd": "~1.1.2", 267 | "encodeurl": "~1.0.2", 268 | "escape-html": "~1.0.3", 269 | "etag": "~1.8.1", 270 | "finalhandler": "~1.1.2", 271 | "fresh": "0.5.2", 272 | "merge-descriptors": "1.0.1", 273 | "methods": "~1.1.2", 274 | "on-finished": "~2.3.0", 275 | "parseurl": "~1.3.3", 276 | "path-to-regexp": "0.1.7", 277 | "proxy-addr": "~2.0.5", 278 | "qs": "6.7.0", 279 | "range-parser": "~1.2.1", 280 | "safe-buffer": "5.1.2", 281 | "send": "0.17.1", 282 | "serve-static": "1.14.1", 283 | "setprototypeof": "1.1.1", 284 | "statuses": "~1.5.0", 285 | "type-is": "~1.6.18", 286 | "utils-merge": "1.0.1", 287 | "vary": "~1.1.2" 288 | }, 289 | "engines": { 290 | "node": ">= 0.10.0" 291 | } 292 | }, 293 | "node_modules/finalhandler": { 294 | "version": "1.1.2", 295 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 296 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 297 | "dependencies": { 298 | "debug": "2.6.9", 299 | "encodeurl": "~1.0.2", 300 | "escape-html": "~1.0.3", 301 | "on-finished": "~2.3.0", 302 | "parseurl": "~1.3.3", 303 | "statuses": "~1.5.0", 304 | "unpipe": "~1.0.0" 305 | }, 306 | "engines": { 307 | "node": ">= 0.8" 308 | } 309 | }, 310 | "node_modules/forwarded": { 311 | "version": "0.2.0", 312 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 313 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 314 | "engines": { 315 | "node": ">= 0.6" 316 | } 317 | }, 318 | "node_modules/fresh": { 319 | "version": "0.5.2", 320 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 321 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", 322 | "engines": { 323 | "node": ">= 0.6" 324 | } 325 | }, 326 | "node_modules/http-errors": { 327 | "version": "1.7.2", 328 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 329 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 330 | "dependencies": { 331 | "depd": "~1.1.2", 332 | "inherits": "2.0.3", 333 | "setprototypeof": "1.1.1", 334 | "statuses": ">= 1.5.0 < 2", 335 | "toidentifier": "1.0.0" 336 | }, 337 | "engines": { 338 | "node": ">= 0.6" 339 | } 340 | }, 341 | "node_modules/iconv-lite": { 342 | "version": "0.4.24", 343 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 344 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 345 | "dependencies": { 346 | "safer-buffer": ">= 2.1.2 < 3" 347 | }, 348 | "engines": { 349 | "node": ">=0.10.0" 350 | } 351 | }, 352 | "node_modules/inherits": { 353 | "version": "2.0.3", 354 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 355 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 356 | }, 357 | "node_modules/ipaddr.js": { 358 | "version": "1.9.1", 359 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 360 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 361 | "engines": { 362 | "node": ">= 0.10" 363 | } 364 | }, 365 | "node_modules/media-typer": { 366 | "version": "0.3.0", 367 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 368 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", 369 | "engines": { 370 | "node": ">= 0.6" 371 | } 372 | }, 373 | "node_modules/merge-descriptors": { 374 | "version": "1.0.1", 375 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 376 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 377 | }, 378 | "node_modules/methods": { 379 | "version": "1.1.2", 380 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 381 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", 382 | "engines": { 383 | "node": ">= 0.6" 384 | } 385 | }, 386 | "node_modules/mime": { 387 | "version": "1.6.0", 388 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 389 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 390 | "bin": { 391 | "mime": "cli.js" 392 | }, 393 | "engines": { 394 | "node": ">=4" 395 | } 396 | }, 397 | "node_modules/mime-db": { 398 | "version": "1.48.0", 399 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", 400 | "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", 401 | "engines": { 402 | "node": ">= 0.6" 403 | } 404 | }, 405 | "node_modules/mime-types": { 406 | "version": "2.1.31", 407 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", 408 | "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", 409 | "dependencies": { 410 | "mime-db": "1.48.0" 411 | }, 412 | "engines": { 413 | "node": ">= 0.6" 414 | } 415 | }, 416 | "node_modules/ms": { 417 | "version": "2.0.0", 418 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 419 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 420 | }, 421 | "node_modules/negotiator": { 422 | "version": "0.6.2", 423 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 424 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", 425 | "engines": { 426 | "node": ">= 0.6" 427 | } 428 | }, 429 | "node_modules/object-assign": { 430 | "version": "4.1.1", 431 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 432 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 433 | "engines": { 434 | "node": ">=0.10.0" 435 | } 436 | }, 437 | "node_modules/on-finished": { 438 | "version": "2.3.0", 439 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 440 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 441 | "dependencies": { 442 | "ee-first": "1.1.1" 443 | }, 444 | "engines": { 445 | "node": ">= 0.8" 446 | } 447 | }, 448 | "node_modules/parseurl": { 449 | "version": "1.3.3", 450 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 451 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 452 | "engines": { 453 | "node": ">= 0.8" 454 | } 455 | }, 456 | "node_modules/path-to-regexp": { 457 | "version": "0.1.7", 458 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 459 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 460 | }, 461 | "node_modules/proxy-addr": { 462 | "version": "2.0.7", 463 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 464 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 465 | "dependencies": { 466 | "forwarded": "0.2.0", 467 | "ipaddr.js": "1.9.1" 468 | }, 469 | "engines": { 470 | "node": ">= 0.10" 471 | } 472 | }, 473 | "node_modules/qs": { 474 | "version": "6.7.0", 475 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 476 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", 477 | "engines": { 478 | "node": ">=0.6" 479 | } 480 | }, 481 | "node_modules/range-parser": { 482 | "version": "1.2.1", 483 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 484 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 485 | "engines": { 486 | "node": ">= 0.6" 487 | } 488 | }, 489 | "node_modules/raw-body": { 490 | "version": "2.4.0", 491 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 492 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 493 | "dependencies": { 494 | "bytes": "3.1.0", 495 | "http-errors": "1.7.2", 496 | "iconv-lite": "0.4.24", 497 | "unpipe": "1.0.0" 498 | }, 499 | "engines": { 500 | "node": ">= 0.8" 501 | } 502 | }, 503 | "node_modules/safe-buffer": { 504 | "version": "5.1.2", 505 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 506 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 507 | }, 508 | "node_modules/safer-buffer": { 509 | "version": "2.1.2", 510 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 511 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 512 | }, 513 | "node_modules/send": { 514 | "version": "0.17.1", 515 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 516 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 517 | "dependencies": { 518 | "debug": "2.6.9", 519 | "depd": "~1.1.2", 520 | "destroy": "~1.0.4", 521 | "encodeurl": "~1.0.2", 522 | "escape-html": "~1.0.3", 523 | "etag": "~1.8.1", 524 | "fresh": "0.5.2", 525 | "http-errors": "~1.7.2", 526 | "mime": "1.6.0", 527 | "ms": "2.1.1", 528 | "on-finished": "~2.3.0", 529 | "range-parser": "~1.2.1", 530 | "statuses": "~1.5.0" 531 | }, 532 | "engines": { 533 | "node": ">= 0.8.0" 534 | } 535 | }, 536 | "node_modules/send/node_modules/ms": { 537 | "version": "2.1.1", 538 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 539 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 540 | }, 541 | "node_modules/serve-static": { 542 | "version": "1.14.1", 543 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 544 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 545 | "dependencies": { 546 | "encodeurl": "~1.0.2", 547 | "escape-html": "~1.0.3", 548 | "parseurl": "~1.3.3", 549 | "send": "0.17.1" 550 | }, 551 | "engines": { 552 | "node": ">= 0.8.0" 553 | } 554 | }, 555 | "node_modules/setprototypeof": { 556 | "version": "1.1.1", 557 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 558 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 559 | }, 560 | "node_modules/socket.io": { 561 | "version": "4.1.2", 562 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.1.2.tgz", 563 | "integrity": "sha512-xK0SD1C7hFrh9+bYoYCdVt+ncixkSLKtNLCax5aEy1o3r5PaO5yQhVb97exIe67cE7lAK+EpyMytXWTWmyZY8w==", 564 | "dependencies": { 565 | "@types/cookie": "^0.4.0", 566 | "@types/cors": "^2.8.8", 567 | "@types/node": ">=10.0.0", 568 | "accepts": "~1.3.4", 569 | "base64id": "~2.0.0", 570 | "debug": "~4.3.1", 571 | "engine.io": "~5.1.0", 572 | "socket.io-adapter": "~2.3.0", 573 | "socket.io-parser": "~4.0.3" 574 | }, 575 | "engines": { 576 | "node": ">=10.0.0" 577 | } 578 | }, 579 | "node_modules/socket.io-adapter": { 580 | "version": "2.3.1", 581 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.1.tgz", 582 | "integrity": "sha512-8cVkRxI8Nt2wadkY6u60Y4rpW3ejA1rxgcK2JuyIhmF+RMNpTy1QRtkHIDUOf3B4HlQwakMsWbKftMv/71VMmw==" 583 | }, 584 | "node_modules/socket.io-parser": { 585 | "version": "4.0.4", 586 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", 587 | "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", 588 | "dependencies": { 589 | "@types/component-emitter": "^1.2.10", 590 | "component-emitter": "~1.3.0", 591 | "debug": "~4.3.1" 592 | }, 593 | "engines": { 594 | "node": ">=10.0.0" 595 | } 596 | }, 597 | "node_modules/socket.io-parser/node_modules/debug": { 598 | "version": "4.3.1", 599 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 600 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 601 | "dependencies": { 602 | "ms": "2.1.2" 603 | }, 604 | "engines": { 605 | "node": ">=6.0" 606 | }, 607 | "peerDependenciesMeta": { 608 | "supports-color": { 609 | "optional": true 610 | } 611 | } 612 | }, 613 | "node_modules/socket.io-parser/node_modules/ms": { 614 | "version": "2.1.2", 615 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 616 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 617 | }, 618 | "node_modules/socket.io/node_modules/debug": { 619 | "version": "4.3.1", 620 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 621 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 622 | "dependencies": { 623 | "ms": "2.1.2" 624 | }, 625 | "engines": { 626 | "node": ">=6.0" 627 | }, 628 | "peerDependenciesMeta": { 629 | "supports-color": { 630 | "optional": true 631 | } 632 | } 633 | }, 634 | "node_modules/socket.io/node_modules/ms": { 635 | "version": "2.1.2", 636 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 637 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 638 | }, 639 | "node_modules/statuses": { 640 | "version": "1.5.0", 641 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 642 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", 643 | "engines": { 644 | "node": ">= 0.6" 645 | } 646 | }, 647 | "node_modules/toidentifier": { 648 | "version": "1.0.0", 649 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 650 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", 651 | "engines": { 652 | "node": ">=0.6" 653 | } 654 | }, 655 | "node_modules/type-is": { 656 | "version": "1.6.18", 657 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 658 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 659 | "dependencies": { 660 | "media-typer": "0.3.0", 661 | "mime-types": "~2.1.24" 662 | }, 663 | "engines": { 664 | "node": ">= 0.6" 665 | } 666 | }, 667 | "node_modules/unpipe": { 668 | "version": "1.0.0", 669 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 670 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", 671 | "engines": { 672 | "node": ">= 0.8" 673 | } 674 | }, 675 | "node_modules/utils-merge": { 676 | "version": "1.0.1", 677 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 678 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", 679 | "engines": { 680 | "node": ">= 0.4.0" 681 | } 682 | }, 683 | "node_modules/vary": { 684 | "version": "1.1.2", 685 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 686 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", 687 | "engines": { 688 | "node": ">= 0.8" 689 | } 690 | }, 691 | "node_modules/ws": { 692 | "version": "7.4.6", 693 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", 694 | "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", 695 | "engines": { 696 | "node": ">=8.3.0" 697 | }, 698 | "peerDependencies": { 699 | "bufferutil": "^4.0.1", 700 | "utf-8-validate": "^5.0.2" 701 | }, 702 | "peerDependenciesMeta": { 703 | "bufferutil": { 704 | "optional": true 705 | }, 706 | "utf-8-validate": { 707 | "optional": true 708 | } 709 | } 710 | } 711 | }, 712 | "dependencies": { 713 | "@types/component-emitter": { 714 | "version": "1.2.10", 715 | "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz", 716 | "integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==" 717 | }, 718 | "@types/cookie": { 719 | "version": "0.4.0", 720 | "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.0.tgz", 721 | "integrity": "sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg==" 722 | }, 723 | "@types/cors": { 724 | "version": "2.8.10", 725 | "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.10.tgz", 726 | "integrity": "sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ==" 727 | }, 728 | "@types/node": { 729 | "version": "15.12.2", 730 | "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz", 731 | "integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==" 732 | }, 733 | "accepts": { 734 | "version": "1.3.7", 735 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 736 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 737 | "requires": { 738 | "mime-types": "~2.1.24", 739 | "negotiator": "0.6.2" 740 | } 741 | }, 742 | "array-flatten": { 743 | "version": "1.1.1", 744 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 745 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 746 | }, 747 | "base64-arraybuffer": { 748 | "version": "0.1.4", 749 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", 750 | "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=" 751 | }, 752 | "base64id": { 753 | "version": "2.0.0", 754 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", 755 | "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" 756 | }, 757 | "body-parser": { 758 | "version": "1.19.0", 759 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 760 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 761 | "requires": { 762 | "bytes": "3.1.0", 763 | "content-type": "~1.0.4", 764 | "debug": "2.6.9", 765 | "depd": "~1.1.2", 766 | "http-errors": "1.7.2", 767 | "iconv-lite": "0.4.24", 768 | "on-finished": "~2.3.0", 769 | "qs": "6.7.0", 770 | "raw-body": "2.4.0", 771 | "type-is": "~1.6.17" 772 | } 773 | }, 774 | "bytes": { 775 | "version": "3.1.0", 776 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 777 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 778 | }, 779 | "component-emitter": { 780 | "version": "1.3.0", 781 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", 782 | "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" 783 | }, 784 | "content-disposition": { 785 | "version": "0.5.3", 786 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 787 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 788 | "requires": { 789 | "safe-buffer": "5.1.2" 790 | } 791 | }, 792 | "content-type": { 793 | "version": "1.0.4", 794 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 795 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 796 | }, 797 | "cookie": { 798 | "version": "0.4.0", 799 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 800 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 801 | }, 802 | "cookie-signature": { 803 | "version": "1.0.6", 804 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 805 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 806 | }, 807 | "cors": { 808 | "version": "2.8.5", 809 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 810 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 811 | "requires": { 812 | "object-assign": "^4", 813 | "vary": "^1" 814 | } 815 | }, 816 | "debug": { 817 | "version": "2.6.9", 818 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 819 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 820 | "requires": { 821 | "ms": "2.0.0" 822 | } 823 | }, 824 | "depd": { 825 | "version": "1.1.2", 826 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 827 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 828 | }, 829 | "destroy": { 830 | "version": "1.0.4", 831 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 832 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 833 | }, 834 | "ee-first": { 835 | "version": "1.1.1", 836 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 837 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 838 | }, 839 | "encodeurl": { 840 | "version": "1.0.2", 841 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 842 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 843 | }, 844 | "engine.io": { 845 | "version": "5.1.1", 846 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-5.1.1.tgz", 847 | "integrity": "sha512-aMWot7H5aC8L4/T8qMYbLdvKlZOdJTH54FxfdFunTGvhMx1BHkJOntWArsVfgAZVwAO9LC2sryPWRcEeUzCe5w==", 848 | "requires": { 849 | "accepts": "~1.3.4", 850 | "base64id": "2.0.0", 851 | "cookie": "~0.4.1", 852 | "cors": "~2.8.5", 853 | "debug": "~4.3.1", 854 | "engine.io-parser": "~4.0.0", 855 | "ws": "~7.4.2" 856 | }, 857 | "dependencies": { 858 | "cookie": { 859 | "version": "0.4.1", 860 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", 861 | "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" 862 | }, 863 | "debug": { 864 | "version": "4.3.1", 865 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 866 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 867 | "requires": { 868 | "ms": "2.1.2" 869 | } 870 | }, 871 | "ms": { 872 | "version": "2.1.2", 873 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 874 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 875 | } 876 | } 877 | }, 878 | "engine.io-parser": { 879 | "version": "4.0.2", 880 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.2.tgz", 881 | "integrity": "sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==", 882 | "requires": { 883 | "base64-arraybuffer": "0.1.4" 884 | } 885 | }, 886 | "escape-html": { 887 | "version": "1.0.3", 888 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 889 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 890 | }, 891 | "etag": { 892 | "version": "1.8.1", 893 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 894 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 895 | }, 896 | "express": { 897 | "version": "4.17.1", 898 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 899 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 900 | "requires": { 901 | "accepts": "~1.3.7", 902 | "array-flatten": "1.1.1", 903 | "body-parser": "1.19.0", 904 | "content-disposition": "0.5.3", 905 | "content-type": "~1.0.4", 906 | "cookie": "0.4.0", 907 | "cookie-signature": "1.0.6", 908 | "debug": "2.6.9", 909 | "depd": "~1.1.2", 910 | "encodeurl": "~1.0.2", 911 | "escape-html": "~1.0.3", 912 | "etag": "~1.8.1", 913 | "finalhandler": "~1.1.2", 914 | "fresh": "0.5.2", 915 | "merge-descriptors": "1.0.1", 916 | "methods": "~1.1.2", 917 | "on-finished": "~2.3.0", 918 | "parseurl": "~1.3.3", 919 | "path-to-regexp": "0.1.7", 920 | "proxy-addr": "~2.0.5", 921 | "qs": "6.7.0", 922 | "range-parser": "~1.2.1", 923 | "safe-buffer": "5.1.2", 924 | "send": "0.17.1", 925 | "serve-static": "1.14.1", 926 | "setprototypeof": "1.1.1", 927 | "statuses": "~1.5.0", 928 | "type-is": "~1.6.18", 929 | "utils-merge": "1.0.1", 930 | "vary": "~1.1.2" 931 | } 932 | }, 933 | "finalhandler": { 934 | "version": "1.1.2", 935 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 936 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 937 | "requires": { 938 | "debug": "2.6.9", 939 | "encodeurl": "~1.0.2", 940 | "escape-html": "~1.0.3", 941 | "on-finished": "~2.3.0", 942 | "parseurl": "~1.3.3", 943 | "statuses": "~1.5.0", 944 | "unpipe": "~1.0.0" 945 | } 946 | }, 947 | "forwarded": { 948 | "version": "0.2.0", 949 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 950 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 951 | }, 952 | "fresh": { 953 | "version": "0.5.2", 954 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 955 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 956 | }, 957 | "http-errors": { 958 | "version": "1.7.2", 959 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 960 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 961 | "requires": { 962 | "depd": "~1.1.2", 963 | "inherits": "2.0.3", 964 | "setprototypeof": "1.1.1", 965 | "statuses": ">= 1.5.0 < 2", 966 | "toidentifier": "1.0.0" 967 | } 968 | }, 969 | "iconv-lite": { 970 | "version": "0.4.24", 971 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 972 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 973 | "requires": { 974 | "safer-buffer": ">= 2.1.2 < 3" 975 | } 976 | }, 977 | "inherits": { 978 | "version": "2.0.3", 979 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 980 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 981 | }, 982 | "ipaddr.js": { 983 | "version": "1.9.1", 984 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 985 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 986 | }, 987 | "media-typer": { 988 | "version": "0.3.0", 989 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 990 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 991 | }, 992 | "merge-descriptors": { 993 | "version": "1.0.1", 994 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 995 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 996 | }, 997 | "methods": { 998 | "version": "1.1.2", 999 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1000 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 1001 | }, 1002 | "mime": { 1003 | "version": "1.6.0", 1004 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1005 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 1006 | }, 1007 | "mime-db": { 1008 | "version": "1.48.0", 1009 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", 1010 | "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==" 1011 | }, 1012 | "mime-types": { 1013 | "version": "2.1.31", 1014 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", 1015 | "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", 1016 | "requires": { 1017 | "mime-db": "1.48.0" 1018 | } 1019 | }, 1020 | "ms": { 1021 | "version": "2.0.0", 1022 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1023 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1024 | }, 1025 | "negotiator": { 1026 | "version": "0.6.2", 1027 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 1028 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 1029 | }, 1030 | "object-assign": { 1031 | "version": "4.1.1", 1032 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1033 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 1034 | }, 1035 | "on-finished": { 1036 | "version": "2.3.0", 1037 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 1038 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 1039 | "requires": { 1040 | "ee-first": "1.1.1" 1041 | } 1042 | }, 1043 | "parseurl": { 1044 | "version": "1.3.3", 1045 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1046 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 1047 | }, 1048 | "path-to-regexp": { 1049 | "version": "0.1.7", 1050 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1051 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 1052 | }, 1053 | "proxy-addr": { 1054 | "version": "2.0.7", 1055 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1056 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1057 | "requires": { 1058 | "forwarded": "0.2.0", 1059 | "ipaddr.js": "1.9.1" 1060 | } 1061 | }, 1062 | "qs": { 1063 | "version": "6.7.0", 1064 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 1065 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 1066 | }, 1067 | "range-parser": { 1068 | "version": "1.2.1", 1069 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1070 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1071 | }, 1072 | "raw-body": { 1073 | "version": "2.4.0", 1074 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 1075 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 1076 | "requires": { 1077 | "bytes": "3.1.0", 1078 | "http-errors": "1.7.2", 1079 | "iconv-lite": "0.4.24", 1080 | "unpipe": "1.0.0" 1081 | } 1082 | }, 1083 | "safe-buffer": { 1084 | "version": "5.1.2", 1085 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1086 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1087 | }, 1088 | "safer-buffer": { 1089 | "version": "2.1.2", 1090 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1091 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1092 | }, 1093 | "send": { 1094 | "version": "0.17.1", 1095 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 1096 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 1097 | "requires": { 1098 | "debug": "2.6.9", 1099 | "depd": "~1.1.2", 1100 | "destroy": "~1.0.4", 1101 | "encodeurl": "~1.0.2", 1102 | "escape-html": "~1.0.3", 1103 | "etag": "~1.8.1", 1104 | "fresh": "0.5.2", 1105 | "http-errors": "~1.7.2", 1106 | "mime": "1.6.0", 1107 | "ms": "2.1.1", 1108 | "on-finished": "~2.3.0", 1109 | "range-parser": "~1.2.1", 1110 | "statuses": "~1.5.0" 1111 | }, 1112 | "dependencies": { 1113 | "ms": { 1114 | "version": "2.1.1", 1115 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 1116 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 1117 | } 1118 | } 1119 | }, 1120 | "serve-static": { 1121 | "version": "1.14.1", 1122 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 1123 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 1124 | "requires": { 1125 | "encodeurl": "~1.0.2", 1126 | "escape-html": "~1.0.3", 1127 | "parseurl": "~1.3.3", 1128 | "send": "0.17.1" 1129 | } 1130 | }, 1131 | "setprototypeof": { 1132 | "version": "1.1.1", 1133 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 1134 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 1135 | }, 1136 | "socket.io": { 1137 | "version": "4.1.2", 1138 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.1.2.tgz", 1139 | "integrity": "sha512-xK0SD1C7hFrh9+bYoYCdVt+ncixkSLKtNLCax5aEy1o3r5PaO5yQhVb97exIe67cE7lAK+EpyMytXWTWmyZY8w==", 1140 | "requires": { 1141 | "@types/cookie": "^0.4.0", 1142 | "@types/cors": "^2.8.8", 1143 | "@types/node": ">=10.0.0", 1144 | "accepts": "~1.3.4", 1145 | "base64id": "~2.0.0", 1146 | "debug": "~4.3.1", 1147 | "engine.io": "~5.1.0", 1148 | "socket.io-adapter": "~2.3.0", 1149 | "socket.io-parser": "~4.0.3" 1150 | }, 1151 | "dependencies": { 1152 | "debug": { 1153 | "version": "4.3.1", 1154 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 1155 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 1156 | "requires": { 1157 | "ms": "2.1.2" 1158 | } 1159 | }, 1160 | "ms": { 1161 | "version": "2.1.2", 1162 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1163 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1164 | } 1165 | } 1166 | }, 1167 | "socket.io-adapter": { 1168 | "version": "2.3.1", 1169 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.1.tgz", 1170 | "integrity": "sha512-8cVkRxI8Nt2wadkY6u60Y4rpW3ejA1rxgcK2JuyIhmF+RMNpTy1QRtkHIDUOf3B4HlQwakMsWbKftMv/71VMmw==" 1171 | }, 1172 | "socket.io-parser": { 1173 | "version": "4.0.4", 1174 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", 1175 | "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", 1176 | "requires": { 1177 | "@types/component-emitter": "^1.2.10", 1178 | "component-emitter": "~1.3.0", 1179 | "debug": "~4.3.1" 1180 | }, 1181 | "dependencies": { 1182 | "debug": { 1183 | "version": "4.3.1", 1184 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 1185 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 1186 | "requires": { 1187 | "ms": "2.1.2" 1188 | } 1189 | }, 1190 | "ms": { 1191 | "version": "2.1.2", 1192 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1193 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1194 | } 1195 | } 1196 | }, 1197 | "statuses": { 1198 | "version": "1.5.0", 1199 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1200 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 1201 | }, 1202 | "toidentifier": { 1203 | "version": "1.0.0", 1204 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 1205 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 1206 | }, 1207 | "type-is": { 1208 | "version": "1.6.18", 1209 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1210 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1211 | "requires": { 1212 | "media-typer": "0.3.0", 1213 | "mime-types": "~2.1.24" 1214 | } 1215 | }, 1216 | "unpipe": { 1217 | "version": "1.0.0", 1218 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1219 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 1220 | }, 1221 | "utils-merge": { 1222 | "version": "1.0.1", 1223 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1224 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 1225 | }, 1226 | "vary": { 1227 | "version": "1.1.2", 1228 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1229 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 1230 | }, 1231 | "ws": { 1232 | "version": "7.4.6", 1233 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", 1234 | "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", 1235 | "requires": {} 1236 | } 1237 | } 1238 | } 1239 | -------------------------------------------------------------------------------- /assets/draco/draco_wasm_wrapper_gltf.js: -------------------------------------------------------------------------------- 1 | var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.arrayIteratorImpl=function(l){var n=0;return function(){return nm?Math.max(C+m,0):Math.min(m,C);q=0>q?Math.max(C+q,0):Math.min(q,C);h=0>h?Math.max(C+h,0):Math.min(h,C);if(mq;)--h in this?this[--m]=this[h]:delete this[--m];return this}},"es6","es3"); 19 | $jscomp.typedArrayCopyWithin=function(l){return l?l:Array.prototype.copyWithin};$jscomp.polyfill("Int8Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Uint8Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Uint8ClampedArray.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Int16Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5"); 20 | $jscomp.polyfill("Uint16Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Int32Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Uint32Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Float32Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Float64Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5"); 21 | var DracoDecoderModule=function(){var l="undefined"!==typeof document&&document.currentScript?document.currentScript.src:void 0;"undefined"!==typeof __filename&&(l=l||__filename);return function(n){function m(e){return a.locateFile?a.locateFile(e,V):V+e}function q(e,b){e||p("Assertion failed: "+b)}function h(e,b){if(e){var c=oa;var d=e+b;for(b=e;c[b]&&!(b>=d);)++b;if(16g?d+=String.fromCharCode(g):(g-=65536,d+=String.fromCharCode(55296|g>>10,56320|g&1023))}}else d+=String.fromCharCode(g)}c=d}}else c="";return c}function C(e,b){0>2]=b};this.get_type=function(){return W[this.ptr+ 25 | D.TYPE_OFFSET>>2]};this.set_destructor=function(b){W[this.ptr+D.DESTRUCTOR_OFFSET>>2]=b};this.get_destructor=function(){return W[this.ptr+D.DESTRUCTOR_OFFSET>>2]};this.set_refcount=function(b){W[this.ptr+D.REFCOUNT_OFFSET>>2]=b};this.set_caught=function(b){Z[this.ptr+D.CAUGHT_OFFSET>>0]=b?1:0};this.get_caught=function(){return 0!=Z[this.ptr+D.CAUGHT_OFFSET>>0]};this.set_rethrown=function(b){Z[this.ptr+D.RETHROWN_OFFSET>>0]=b?1:0};this.get_rethrown=function(){return 0!=Z[this.ptr+D.RETHROWN_OFFSET>> 26 | 0]};this.init=function(b,c){this.set_type(b);this.set_destructor(c);this.set_refcount(0);this.set_caught(!1);this.set_rethrown(!1)};this.add_ref=function(){W[this.ptr+D.REFCOUNT_OFFSET>>2]+=1};this.release_ref=function(){var b=W[this.ptr+D.REFCOUNT_OFFSET>>2];W[this.ptr+D.REFCOUNT_OFFSET>>2]=b-1;return 1===b}}function Q(){return 0=d&&(d=65536+((d&1023)<<10)|e.charCodeAt(++c)&1023);127>=d?++b:b=2047>=d?b+2:65535>=d?b+3:b+4}b=Array(b+1);c=0;d=b.length;if(0=v){var ia=e.charCodeAt(++g);v=65536+((v&1023)<<10)|ia&1023}if(127>=v){if(c>=d)break;b[c++]=v}else{if(2047>=v){if(c+1>=d)break;b[c++]=192|v>>6}else{if(65535>=v){if(c+2>=d)break;b[c++]= 29 | 224|v>>12}else{if(c+3>=d)break;b[c++]=240|v>>18;b[c++]=128|v>>12&63}b[c++]=128|v>>6&63}b[c++]=128|v&63}}b[c]=0}e=r.alloc(b,Z);r.copy(b,Z,e);return e}return e}function va(e){if("object"===typeof e){var b=r.alloc(e,Z);r.copy(e,Z,b);return b}return e}function aa(){throw"cannot construct a VoidPtr, no constructor in IDL";}function S(){this.ptr=Ja();z(S)[this.ptr]=this}function P(){this.ptr=Ka();z(P)[this.ptr]=this}function Y(){this.ptr=La();z(Y)[this.ptr]=this}function w(){this.ptr=Ma();z(w)[this.ptr]= 30 | this}function B(){this.ptr=Na();z(B)[this.ptr]=this}function F(){this.ptr=Oa();z(F)[this.ptr]=this}function G(){this.ptr=Pa();z(G)[this.ptr]=this}function E(){this.ptr=Qa();z(E)[this.ptr]=this}function T(){this.ptr=Ra();z(T)[this.ptr]=this}function A(){throw"cannot construct a Status, no constructor in IDL";}function H(){this.ptr=Sa();z(H)[this.ptr]=this}function I(){this.ptr=Ta();z(I)[this.ptr]=this}function J(){this.ptr=Ua();z(J)[this.ptr]=this}function K(){this.ptr=Va();z(K)[this.ptr]=this}function L(){this.ptr= 31 | Wa();z(L)[this.ptr]=this}function M(){this.ptr=Xa();z(M)[this.ptr]=this}function N(){this.ptr=Ya();z(N)[this.ptr]=this}function x(){this.ptr=Za();z(x)[this.ptr]=this}function k(){this.ptr=$a();z(k)[this.ptr]=this}n=n||{};var a="undefined"!==typeof n?n:{},Ga,ta;a.ready=new Promise(function(e,b){Ga=e;ta=b});var ab=!1,bb=!1;a.onRuntimeInitialized=function(){ab=!0;if(bb&&"function"===typeof a.onModuleLoaded)a.onModuleLoaded(a)};a.onModuleParsed=function(){bb=!0;if(ab&&"function"===typeof a.onModuleLoaded)a.onModuleLoaded(a)}; 32 | a.isVersionSupported=function(e){if("string"!==typeof e)return!1;e=e.split(".");return 2>e.length||3=e[1]?!0:0!=e[0]||10>>=0;var b=oa.length;if(2147483648=c;c*=2){var d=b*(1+.2/c); 38 | d=Math.min(d,e+100663296);d=Math.min(2147483648,C(Math.max(16777216,e,d),65536));a:{try{ma.grow(d-pa.byteLength+65535>>>16);f(ma.buffer);var g=1;break a}catch(v){}g=void 0}if(g)return!0}return!1},memory:ma};(function(){function e(g,v){a.asm=g.exports;ua=a.asm.__indirect_function_table;ha--;a.monitorRunDependencies&&a.monitorRunDependencies(ha);0==ha&&(null!==Aa&&(clearInterval(Aa),Aa=null),na&&(g=na,na=null,g()))}function b(g){e(g.instance)}function c(g){return O().then(function(v){return WebAssembly.instantiate(v, 39 | d)}).then(g,function(v){ja("failed to asynchronously prepare wasm: "+v);p(v)})}var d={env:gb,wasi_snapshot_preview1:gb};ha++;a.monitorRunDependencies&&a.monitorRunDependencies(ha);if(a.instantiateWasm)try{return a.instantiateWasm(d,e)}catch(g){return ja("Module.instantiateWasm callback failed with error: "+g),!1}(function(){return ka||"function"!==typeof WebAssembly.instantiateStreaming||t(X,"data:application/octet-stream;base64,")||t(X,"file://")||"function"!==typeof fetch?c(b):fetch(X,{credentials:"same-origin"}).then(function(g){return WebAssembly.instantiateStreaming(g, 40 | d).then(b,function(v){ja("wasm streaming compile failed: "+v);ja("falling back to ArrayBuffer instantiation");return c(b)})})})().catch(ta);return{}})();var eb=a.___wasm_call_ctors=function(){return(eb=a.___wasm_call_ctors=a.asm.__wasm_call_ctors).apply(null,arguments)};a.___em_js__array_bounds_check_error=function(){return(a.___em_js__array_bounds_check_error=a.asm.__em_js__array_bounds_check_error).apply(null,arguments)};var hb=a._emscripten_bind_VoidPtr___destroy___0=function(){return(hb=a._emscripten_bind_VoidPtr___destroy___0= 41 | a.asm.emscripten_bind_VoidPtr___destroy___0).apply(null,arguments)},Ja=a._emscripten_bind_DecoderBuffer_DecoderBuffer_0=function(){return(Ja=a._emscripten_bind_DecoderBuffer_DecoderBuffer_0=a.asm.emscripten_bind_DecoderBuffer_DecoderBuffer_0).apply(null,arguments)},ib=a._emscripten_bind_DecoderBuffer_Init_2=function(){return(ib=a._emscripten_bind_DecoderBuffer_Init_2=a.asm.emscripten_bind_DecoderBuffer_Init_2).apply(null,arguments)},jb=a._emscripten_bind_DecoderBuffer___destroy___0=function(){return(jb= 42 | a._emscripten_bind_DecoderBuffer___destroy___0=a.asm.emscripten_bind_DecoderBuffer___destroy___0).apply(null,arguments)},Ka=a._emscripten_bind_AttributeTransformData_AttributeTransformData_0=function(){return(Ka=a._emscripten_bind_AttributeTransformData_AttributeTransformData_0=a.asm.emscripten_bind_AttributeTransformData_AttributeTransformData_0).apply(null,arguments)},kb=a._emscripten_bind_AttributeTransformData_transform_type_0=function(){return(kb=a._emscripten_bind_AttributeTransformData_transform_type_0= 43 | a.asm.emscripten_bind_AttributeTransformData_transform_type_0).apply(null,arguments)},lb=a._emscripten_bind_AttributeTransformData___destroy___0=function(){return(lb=a._emscripten_bind_AttributeTransformData___destroy___0=a.asm.emscripten_bind_AttributeTransformData___destroy___0).apply(null,arguments)},La=a._emscripten_bind_GeometryAttribute_GeometryAttribute_0=function(){return(La=a._emscripten_bind_GeometryAttribute_GeometryAttribute_0=a.asm.emscripten_bind_GeometryAttribute_GeometryAttribute_0).apply(null, 44 | arguments)},mb=a._emscripten_bind_GeometryAttribute___destroy___0=function(){return(mb=a._emscripten_bind_GeometryAttribute___destroy___0=a.asm.emscripten_bind_GeometryAttribute___destroy___0).apply(null,arguments)},Ma=a._emscripten_bind_PointAttribute_PointAttribute_0=function(){return(Ma=a._emscripten_bind_PointAttribute_PointAttribute_0=a.asm.emscripten_bind_PointAttribute_PointAttribute_0).apply(null,arguments)},nb=a._emscripten_bind_PointAttribute_size_0=function(){return(nb=a._emscripten_bind_PointAttribute_size_0= 45 | a.asm.emscripten_bind_PointAttribute_size_0).apply(null,arguments)},ob=a._emscripten_bind_PointAttribute_GetAttributeTransformData_0=function(){return(ob=a._emscripten_bind_PointAttribute_GetAttributeTransformData_0=a.asm.emscripten_bind_PointAttribute_GetAttributeTransformData_0).apply(null,arguments)},pb=a._emscripten_bind_PointAttribute_attribute_type_0=function(){return(pb=a._emscripten_bind_PointAttribute_attribute_type_0=a.asm.emscripten_bind_PointAttribute_attribute_type_0).apply(null,arguments)}, 46 | qb=a._emscripten_bind_PointAttribute_data_type_0=function(){return(qb=a._emscripten_bind_PointAttribute_data_type_0=a.asm.emscripten_bind_PointAttribute_data_type_0).apply(null,arguments)},rb=a._emscripten_bind_PointAttribute_num_components_0=function(){return(rb=a._emscripten_bind_PointAttribute_num_components_0=a.asm.emscripten_bind_PointAttribute_num_components_0).apply(null,arguments)},sb=a._emscripten_bind_PointAttribute_normalized_0=function(){return(sb=a._emscripten_bind_PointAttribute_normalized_0= 47 | a.asm.emscripten_bind_PointAttribute_normalized_0).apply(null,arguments)},tb=a._emscripten_bind_PointAttribute_byte_stride_0=function(){return(tb=a._emscripten_bind_PointAttribute_byte_stride_0=a.asm.emscripten_bind_PointAttribute_byte_stride_0).apply(null,arguments)},ub=a._emscripten_bind_PointAttribute_byte_offset_0=function(){return(ub=a._emscripten_bind_PointAttribute_byte_offset_0=a.asm.emscripten_bind_PointAttribute_byte_offset_0).apply(null,arguments)},vb=a._emscripten_bind_PointAttribute_unique_id_0= 48 | function(){return(vb=a._emscripten_bind_PointAttribute_unique_id_0=a.asm.emscripten_bind_PointAttribute_unique_id_0).apply(null,arguments)},wb=a._emscripten_bind_PointAttribute___destroy___0=function(){return(wb=a._emscripten_bind_PointAttribute___destroy___0=a.asm.emscripten_bind_PointAttribute___destroy___0).apply(null,arguments)},Na=a._emscripten_bind_AttributeQuantizationTransform_AttributeQuantizationTransform_0=function(){return(Na=a._emscripten_bind_AttributeQuantizationTransform_AttributeQuantizationTransform_0= 49 | a.asm.emscripten_bind_AttributeQuantizationTransform_AttributeQuantizationTransform_0).apply(null,arguments)},xb=a._emscripten_bind_AttributeQuantizationTransform_InitFromAttribute_1=function(){return(xb=a._emscripten_bind_AttributeQuantizationTransform_InitFromAttribute_1=a.asm.emscripten_bind_AttributeQuantizationTransform_InitFromAttribute_1).apply(null,arguments)},yb=a._emscripten_bind_AttributeQuantizationTransform_quantization_bits_0=function(){return(yb=a._emscripten_bind_AttributeQuantizationTransform_quantization_bits_0= 50 | a.asm.emscripten_bind_AttributeQuantizationTransform_quantization_bits_0).apply(null,arguments)},zb=a._emscripten_bind_AttributeQuantizationTransform_min_value_1=function(){return(zb=a._emscripten_bind_AttributeQuantizationTransform_min_value_1=a.asm.emscripten_bind_AttributeQuantizationTransform_min_value_1).apply(null,arguments)},Ab=a._emscripten_bind_AttributeQuantizationTransform_range_0=function(){return(Ab=a._emscripten_bind_AttributeQuantizationTransform_range_0=a.asm.emscripten_bind_AttributeQuantizationTransform_range_0).apply(null, 51 | arguments)},Bb=a._emscripten_bind_AttributeQuantizationTransform___destroy___0=function(){return(Bb=a._emscripten_bind_AttributeQuantizationTransform___destroy___0=a.asm.emscripten_bind_AttributeQuantizationTransform___destroy___0).apply(null,arguments)},Oa=a._emscripten_bind_AttributeOctahedronTransform_AttributeOctahedronTransform_0=function(){return(Oa=a._emscripten_bind_AttributeOctahedronTransform_AttributeOctahedronTransform_0=a.asm.emscripten_bind_AttributeOctahedronTransform_AttributeOctahedronTransform_0).apply(null, 52 | arguments)},Cb=a._emscripten_bind_AttributeOctahedronTransform_InitFromAttribute_1=function(){return(Cb=a._emscripten_bind_AttributeOctahedronTransform_InitFromAttribute_1=a.asm.emscripten_bind_AttributeOctahedronTransform_InitFromAttribute_1).apply(null,arguments)},Db=a._emscripten_bind_AttributeOctahedronTransform_quantization_bits_0=function(){return(Db=a._emscripten_bind_AttributeOctahedronTransform_quantization_bits_0=a.asm.emscripten_bind_AttributeOctahedronTransform_quantization_bits_0).apply(null, 53 | arguments)},Eb=a._emscripten_bind_AttributeOctahedronTransform___destroy___0=function(){return(Eb=a._emscripten_bind_AttributeOctahedronTransform___destroy___0=a.asm.emscripten_bind_AttributeOctahedronTransform___destroy___0).apply(null,arguments)},Pa=a._emscripten_bind_PointCloud_PointCloud_0=function(){return(Pa=a._emscripten_bind_PointCloud_PointCloud_0=a.asm.emscripten_bind_PointCloud_PointCloud_0).apply(null,arguments)},Fb=a._emscripten_bind_PointCloud_num_attributes_0=function(){return(Fb=a._emscripten_bind_PointCloud_num_attributes_0= 54 | a.asm.emscripten_bind_PointCloud_num_attributes_0).apply(null,arguments)},Gb=a._emscripten_bind_PointCloud_num_points_0=function(){return(Gb=a._emscripten_bind_PointCloud_num_points_0=a.asm.emscripten_bind_PointCloud_num_points_0).apply(null,arguments)},Hb=a._emscripten_bind_PointCloud___destroy___0=function(){return(Hb=a._emscripten_bind_PointCloud___destroy___0=a.asm.emscripten_bind_PointCloud___destroy___0).apply(null,arguments)},Qa=a._emscripten_bind_Mesh_Mesh_0=function(){return(Qa=a._emscripten_bind_Mesh_Mesh_0= 55 | a.asm.emscripten_bind_Mesh_Mesh_0).apply(null,arguments)},Ib=a._emscripten_bind_Mesh_num_faces_0=function(){return(Ib=a._emscripten_bind_Mesh_num_faces_0=a.asm.emscripten_bind_Mesh_num_faces_0).apply(null,arguments)},Jb=a._emscripten_bind_Mesh_num_attributes_0=function(){return(Jb=a._emscripten_bind_Mesh_num_attributes_0=a.asm.emscripten_bind_Mesh_num_attributes_0).apply(null,arguments)},Kb=a._emscripten_bind_Mesh_num_points_0=function(){return(Kb=a._emscripten_bind_Mesh_num_points_0=a.asm.emscripten_bind_Mesh_num_points_0).apply(null, 56 | arguments)},Lb=a._emscripten_bind_Mesh___destroy___0=function(){return(Lb=a._emscripten_bind_Mesh___destroy___0=a.asm.emscripten_bind_Mesh___destroy___0).apply(null,arguments)},Ra=a._emscripten_bind_Metadata_Metadata_0=function(){return(Ra=a._emscripten_bind_Metadata_Metadata_0=a.asm.emscripten_bind_Metadata_Metadata_0).apply(null,arguments)},Mb=a._emscripten_bind_Metadata___destroy___0=function(){return(Mb=a._emscripten_bind_Metadata___destroy___0=a.asm.emscripten_bind_Metadata___destroy___0).apply(null, 57 | arguments)},Nb=a._emscripten_bind_Status_code_0=function(){return(Nb=a._emscripten_bind_Status_code_0=a.asm.emscripten_bind_Status_code_0).apply(null,arguments)},Ob=a._emscripten_bind_Status_ok_0=function(){return(Ob=a._emscripten_bind_Status_ok_0=a.asm.emscripten_bind_Status_ok_0).apply(null,arguments)},Pb=a._emscripten_bind_Status_error_msg_0=function(){return(Pb=a._emscripten_bind_Status_error_msg_0=a.asm.emscripten_bind_Status_error_msg_0).apply(null,arguments)},Qb=a._emscripten_bind_Status___destroy___0= 58 | function(){return(Qb=a._emscripten_bind_Status___destroy___0=a.asm.emscripten_bind_Status___destroy___0).apply(null,arguments)},Sa=a._emscripten_bind_DracoFloat32Array_DracoFloat32Array_0=function(){return(Sa=a._emscripten_bind_DracoFloat32Array_DracoFloat32Array_0=a.asm.emscripten_bind_DracoFloat32Array_DracoFloat32Array_0).apply(null,arguments)},Rb=a._emscripten_bind_DracoFloat32Array_GetValue_1=function(){return(Rb=a._emscripten_bind_DracoFloat32Array_GetValue_1=a.asm.emscripten_bind_DracoFloat32Array_GetValue_1).apply(null, 59 | arguments)},Sb=a._emscripten_bind_DracoFloat32Array_size_0=function(){return(Sb=a._emscripten_bind_DracoFloat32Array_size_0=a.asm.emscripten_bind_DracoFloat32Array_size_0).apply(null,arguments)},Tb=a._emscripten_bind_DracoFloat32Array___destroy___0=function(){return(Tb=a._emscripten_bind_DracoFloat32Array___destroy___0=a.asm.emscripten_bind_DracoFloat32Array___destroy___0).apply(null,arguments)},Ta=a._emscripten_bind_DracoInt8Array_DracoInt8Array_0=function(){return(Ta=a._emscripten_bind_DracoInt8Array_DracoInt8Array_0= 60 | a.asm.emscripten_bind_DracoInt8Array_DracoInt8Array_0).apply(null,arguments)},Ub=a._emscripten_bind_DracoInt8Array_GetValue_1=function(){return(Ub=a._emscripten_bind_DracoInt8Array_GetValue_1=a.asm.emscripten_bind_DracoInt8Array_GetValue_1).apply(null,arguments)},Vb=a._emscripten_bind_DracoInt8Array_size_0=function(){return(Vb=a._emscripten_bind_DracoInt8Array_size_0=a.asm.emscripten_bind_DracoInt8Array_size_0).apply(null,arguments)},Wb=a._emscripten_bind_DracoInt8Array___destroy___0=function(){return(Wb= 61 | a._emscripten_bind_DracoInt8Array___destroy___0=a.asm.emscripten_bind_DracoInt8Array___destroy___0).apply(null,arguments)},Ua=a._emscripten_bind_DracoUInt8Array_DracoUInt8Array_0=function(){return(Ua=a._emscripten_bind_DracoUInt8Array_DracoUInt8Array_0=a.asm.emscripten_bind_DracoUInt8Array_DracoUInt8Array_0).apply(null,arguments)},Xb=a._emscripten_bind_DracoUInt8Array_GetValue_1=function(){return(Xb=a._emscripten_bind_DracoUInt8Array_GetValue_1=a.asm.emscripten_bind_DracoUInt8Array_GetValue_1).apply(null, 62 | arguments)},Yb=a._emscripten_bind_DracoUInt8Array_size_0=function(){return(Yb=a._emscripten_bind_DracoUInt8Array_size_0=a.asm.emscripten_bind_DracoUInt8Array_size_0).apply(null,arguments)},Zb=a._emscripten_bind_DracoUInt8Array___destroy___0=function(){return(Zb=a._emscripten_bind_DracoUInt8Array___destroy___0=a.asm.emscripten_bind_DracoUInt8Array___destroy___0).apply(null,arguments)},Va=a._emscripten_bind_DracoInt16Array_DracoInt16Array_0=function(){return(Va=a._emscripten_bind_DracoInt16Array_DracoInt16Array_0= 63 | a.asm.emscripten_bind_DracoInt16Array_DracoInt16Array_0).apply(null,arguments)},$b=a._emscripten_bind_DracoInt16Array_GetValue_1=function(){return($b=a._emscripten_bind_DracoInt16Array_GetValue_1=a.asm.emscripten_bind_DracoInt16Array_GetValue_1).apply(null,arguments)},ac=a._emscripten_bind_DracoInt16Array_size_0=function(){return(ac=a._emscripten_bind_DracoInt16Array_size_0=a.asm.emscripten_bind_DracoInt16Array_size_0).apply(null,arguments)},bc=a._emscripten_bind_DracoInt16Array___destroy___0=function(){return(bc= 64 | a._emscripten_bind_DracoInt16Array___destroy___0=a.asm.emscripten_bind_DracoInt16Array___destroy___0).apply(null,arguments)},Wa=a._emscripten_bind_DracoUInt16Array_DracoUInt16Array_0=function(){return(Wa=a._emscripten_bind_DracoUInt16Array_DracoUInt16Array_0=a.asm.emscripten_bind_DracoUInt16Array_DracoUInt16Array_0).apply(null,arguments)},cc=a._emscripten_bind_DracoUInt16Array_GetValue_1=function(){return(cc=a._emscripten_bind_DracoUInt16Array_GetValue_1=a.asm.emscripten_bind_DracoUInt16Array_GetValue_1).apply(null, 65 | arguments)},dc=a._emscripten_bind_DracoUInt16Array_size_0=function(){return(dc=a._emscripten_bind_DracoUInt16Array_size_0=a.asm.emscripten_bind_DracoUInt16Array_size_0).apply(null,arguments)},ec=a._emscripten_bind_DracoUInt16Array___destroy___0=function(){return(ec=a._emscripten_bind_DracoUInt16Array___destroy___0=a.asm.emscripten_bind_DracoUInt16Array___destroy___0).apply(null,arguments)},Xa=a._emscripten_bind_DracoInt32Array_DracoInt32Array_0=function(){return(Xa=a._emscripten_bind_DracoInt32Array_DracoInt32Array_0= 66 | a.asm.emscripten_bind_DracoInt32Array_DracoInt32Array_0).apply(null,arguments)},fc=a._emscripten_bind_DracoInt32Array_GetValue_1=function(){return(fc=a._emscripten_bind_DracoInt32Array_GetValue_1=a.asm.emscripten_bind_DracoInt32Array_GetValue_1).apply(null,arguments)},gc=a._emscripten_bind_DracoInt32Array_size_0=function(){return(gc=a._emscripten_bind_DracoInt32Array_size_0=a.asm.emscripten_bind_DracoInt32Array_size_0).apply(null,arguments)},hc=a._emscripten_bind_DracoInt32Array___destroy___0=function(){return(hc= 67 | a._emscripten_bind_DracoInt32Array___destroy___0=a.asm.emscripten_bind_DracoInt32Array___destroy___0).apply(null,arguments)},Ya=a._emscripten_bind_DracoUInt32Array_DracoUInt32Array_0=function(){return(Ya=a._emscripten_bind_DracoUInt32Array_DracoUInt32Array_0=a.asm.emscripten_bind_DracoUInt32Array_DracoUInt32Array_0).apply(null,arguments)},ic=a._emscripten_bind_DracoUInt32Array_GetValue_1=function(){return(ic=a._emscripten_bind_DracoUInt32Array_GetValue_1=a.asm.emscripten_bind_DracoUInt32Array_GetValue_1).apply(null, 68 | arguments)},jc=a._emscripten_bind_DracoUInt32Array_size_0=function(){return(jc=a._emscripten_bind_DracoUInt32Array_size_0=a.asm.emscripten_bind_DracoUInt32Array_size_0).apply(null,arguments)},kc=a._emscripten_bind_DracoUInt32Array___destroy___0=function(){return(kc=a._emscripten_bind_DracoUInt32Array___destroy___0=a.asm.emscripten_bind_DracoUInt32Array___destroy___0).apply(null,arguments)},Za=a._emscripten_bind_MetadataQuerier_MetadataQuerier_0=function(){return(Za=a._emscripten_bind_MetadataQuerier_MetadataQuerier_0= 69 | a.asm.emscripten_bind_MetadataQuerier_MetadataQuerier_0).apply(null,arguments)},lc=a._emscripten_bind_MetadataQuerier_HasEntry_2=function(){return(lc=a._emscripten_bind_MetadataQuerier_HasEntry_2=a.asm.emscripten_bind_MetadataQuerier_HasEntry_2).apply(null,arguments)},mc=a._emscripten_bind_MetadataQuerier_GetIntEntry_2=function(){return(mc=a._emscripten_bind_MetadataQuerier_GetIntEntry_2=a.asm.emscripten_bind_MetadataQuerier_GetIntEntry_2).apply(null,arguments)},nc=a._emscripten_bind_MetadataQuerier_GetIntEntryArray_3= 70 | function(){return(nc=a._emscripten_bind_MetadataQuerier_GetIntEntryArray_3=a.asm.emscripten_bind_MetadataQuerier_GetIntEntryArray_3).apply(null,arguments)},oc=a._emscripten_bind_MetadataQuerier_GetDoubleEntry_2=function(){return(oc=a._emscripten_bind_MetadataQuerier_GetDoubleEntry_2=a.asm.emscripten_bind_MetadataQuerier_GetDoubleEntry_2).apply(null,arguments)},pc=a._emscripten_bind_MetadataQuerier_GetStringEntry_2=function(){return(pc=a._emscripten_bind_MetadataQuerier_GetStringEntry_2=a.asm.emscripten_bind_MetadataQuerier_GetStringEntry_2).apply(null, 71 | arguments)},qc=a._emscripten_bind_MetadataQuerier_NumEntries_1=function(){return(qc=a._emscripten_bind_MetadataQuerier_NumEntries_1=a.asm.emscripten_bind_MetadataQuerier_NumEntries_1).apply(null,arguments)},rc=a._emscripten_bind_MetadataQuerier_GetEntryName_2=function(){return(rc=a._emscripten_bind_MetadataQuerier_GetEntryName_2=a.asm.emscripten_bind_MetadataQuerier_GetEntryName_2).apply(null,arguments)},sc=a._emscripten_bind_MetadataQuerier___destroy___0=function(){return(sc=a._emscripten_bind_MetadataQuerier___destroy___0= 72 | a.asm.emscripten_bind_MetadataQuerier___destroy___0).apply(null,arguments)},$a=a._emscripten_bind_Decoder_Decoder_0=function(){return($a=a._emscripten_bind_Decoder_Decoder_0=a.asm.emscripten_bind_Decoder_Decoder_0).apply(null,arguments)},tc=a._emscripten_bind_Decoder_DecodeArrayToPointCloud_3=function(){return(tc=a._emscripten_bind_Decoder_DecodeArrayToPointCloud_3=a.asm.emscripten_bind_Decoder_DecodeArrayToPointCloud_3).apply(null,arguments)},uc=a._emscripten_bind_Decoder_DecodeArrayToMesh_3=function(){return(uc= 73 | a._emscripten_bind_Decoder_DecodeArrayToMesh_3=a.asm.emscripten_bind_Decoder_DecodeArrayToMesh_3).apply(null,arguments)},vc=a._emscripten_bind_Decoder_GetAttributeId_2=function(){return(vc=a._emscripten_bind_Decoder_GetAttributeId_2=a.asm.emscripten_bind_Decoder_GetAttributeId_2).apply(null,arguments)},wc=a._emscripten_bind_Decoder_GetAttributeIdByName_2=function(){return(wc=a._emscripten_bind_Decoder_GetAttributeIdByName_2=a.asm.emscripten_bind_Decoder_GetAttributeIdByName_2).apply(null,arguments)}, 74 | xc=a._emscripten_bind_Decoder_GetAttributeIdByMetadataEntry_3=function(){return(xc=a._emscripten_bind_Decoder_GetAttributeIdByMetadataEntry_3=a.asm.emscripten_bind_Decoder_GetAttributeIdByMetadataEntry_3).apply(null,arguments)},yc=a._emscripten_bind_Decoder_GetAttribute_2=function(){return(yc=a._emscripten_bind_Decoder_GetAttribute_2=a.asm.emscripten_bind_Decoder_GetAttribute_2).apply(null,arguments)},zc=a._emscripten_bind_Decoder_GetAttributeByUniqueId_2=function(){return(zc=a._emscripten_bind_Decoder_GetAttributeByUniqueId_2= 75 | a.asm.emscripten_bind_Decoder_GetAttributeByUniqueId_2).apply(null,arguments)},Ac=a._emscripten_bind_Decoder_GetMetadata_1=function(){return(Ac=a._emscripten_bind_Decoder_GetMetadata_1=a.asm.emscripten_bind_Decoder_GetMetadata_1).apply(null,arguments)},Bc=a._emscripten_bind_Decoder_GetAttributeMetadata_2=function(){return(Bc=a._emscripten_bind_Decoder_GetAttributeMetadata_2=a.asm.emscripten_bind_Decoder_GetAttributeMetadata_2).apply(null,arguments)},Cc=a._emscripten_bind_Decoder_GetFaceFromMesh_3= 76 | function(){return(Cc=a._emscripten_bind_Decoder_GetFaceFromMesh_3=a.asm.emscripten_bind_Decoder_GetFaceFromMesh_3).apply(null,arguments)},Dc=a._emscripten_bind_Decoder_GetTriangleStripsFromMesh_2=function(){return(Dc=a._emscripten_bind_Decoder_GetTriangleStripsFromMesh_2=a.asm.emscripten_bind_Decoder_GetTriangleStripsFromMesh_2).apply(null,arguments)},Ec=a._emscripten_bind_Decoder_GetTrianglesUInt16Array_3=function(){return(Ec=a._emscripten_bind_Decoder_GetTrianglesUInt16Array_3=a.asm.emscripten_bind_Decoder_GetTrianglesUInt16Array_3).apply(null, 77 | arguments)},Fc=a._emscripten_bind_Decoder_GetTrianglesUInt32Array_3=function(){return(Fc=a._emscripten_bind_Decoder_GetTrianglesUInt32Array_3=a.asm.emscripten_bind_Decoder_GetTrianglesUInt32Array_3).apply(null,arguments)},Gc=a._emscripten_bind_Decoder_GetAttributeFloat_3=function(){return(Gc=a._emscripten_bind_Decoder_GetAttributeFloat_3=a.asm.emscripten_bind_Decoder_GetAttributeFloat_3).apply(null,arguments)},Hc=a._emscripten_bind_Decoder_GetAttributeFloatForAllPoints_3=function(){return(Hc=a._emscripten_bind_Decoder_GetAttributeFloatForAllPoints_3= 78 | a.asm.emscripten_bind_Decoder_GetAttributeFloatForAllPoints_3).apply(null,arguments)},Ic=a._emscripten_bind_Decoder_GetAttributeIntForAllPoints_3=function(){return(Ic=a._emscripten_bind_Decoder_GetAttributeIntForAllPoints_3=a.asm.emscripten_bind_Decoder_GetAttributeIntForAllPoints_3).apply(null,arguments)},Jc=a._emscripten_bind_Decoder_GetAttributeInt8ForAllPoints_3=function(){return(Jc=a._emscripten_bind_Decoder_GetAttributeInt8ForAllPoints_3=a.asm.emscripten_bind_Decoder_GetAttributeInt8ForAllPoints_3).apply(null, 79 | arguments)},Kc=a._emscripten_bind_Decoder_GetAttributeUInt8ForAllPoints_3=function(){return(Kc=a._emscripten_bind_Decoder_GetAttributeUInt8ForAllPoints_3=a.asm.emscripten_bind_Decoder_GetAttributeUInt8ForAllPoints_3).apply(null,arguments)},Lc=a._emscripten_bind_Decoder_GetAttributeInt16ForAllPoints_3=function(){return(Lc=a._emscripten_bind_Decoder_GetAttributeInt16ForAllPoints_3=a.asm.emscripten_bind_Decoder_GetAttributeInt16ForAllPoints_3).apply(null,arguments)},Mc=a._emscripten_bind_Decoder_GetAttributeUInt16ForAllPoints_3= 80 | function(){return(Mc=a._emscripten_bind_Decoder_GetAttributeUInt16ForAllPoints_3=a.asm.emscripten_bind_Decoder_GetAttributeUInt16ForAllPoints_3).apply(null,arguments)},Nc=a._emscripten_bind_Decoder_GetAttributeInt32ForAllPoints_3=function(){return(Nc=a._emscripten_bind_Decoder_GetAttributeInt32ForAllPoints_3=a.asm.emscripten_bind_Decoder_GetAttributeInt32ForAllPoints_3).apply(null,arguments)},Oc=a._emscripten_bind_Decoder_GetAttributeUInt32ForAllPoints_3=function(){return(Oc=a._emscripten_bind_Decoder_GetAttributeUInt32ForAllPoints_3= 81 | a.asm.emscripten_bind_Decoder_GetAttributeUInt32ForAllPoints_3).apply(null,arguments)},Pc=a._emscripten_bind_Decoder_GetAttributeDataArrayForAllPoints_5=function(){return(Pc=a._emscripten_bind_Decoder_GetAttributeDataArrayForAllPoints_5=a.asm.emscripten_bind_Decoder_GetAttributeDataArrayForAllPoints_5).apply(null,arguments)},Qc=a._emscripten_bind_Decoder_SkipAttributeTransform_1=function(){return(Qc=a._emscripten_bind_Decoder_SkipAttributeTransform_1=a.asm.emscripten_bind_Decoder_SkipAttributeTransform_1).apply(null, 82 | arguments)},Rc=a._emscripten_bind_Decoder_GetEncodedGeometryType_Deprecated_1=function(){return(Rc=a._emscripten_bind_Decoder_GetEncodedGeometryType_Deprecated_1=a.asm.emscripten_bind_Decoder_GetEncodedGeometryType_Deprecated_1).apply(null,arguments)},Sc=a._emscripten_bind_Decoder_DecodeBufferToPointCloud_2=function(){return(Sc=a._emscripten_bind_Decoder_DecodeBufferToPointCloud_2=a.asm.emscripten_bind_Decoder_DecodeBufferToPointCloud_2).apply(null,arguments)},Tc=a._emscripten_bind_Decoder_DecodeBufferToMesh_2= 83 | function(){return(Tc=a._emscripten_bind_Decoder_DecodeBufferToMesh_2=a.asm.emscripten_bind_Decoder_DecodeBufferToMesh_2).apply(null,arguments)},Uc=a._emscripten_bind_Decoder___destroy___0=function(){return(Uc=a._emscripten_bind_Decoder___destroy___0=a.asm.emscripten_bind_Decoder___destroy___0).apply(null,arguments)},Vc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_INVALID_TRANSFORM=function(){return(Vc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_INVALID_TRANSFORM=a.asm.emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_INVALID_TRANSFORM).apply(null, 84 | arguments)},Wc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_NO_TRANSFORM=function(){return(Wc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_NO_TRANSFORM=a.asm.emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_NO_TRANSFORM).apply(null,arguments)},Xc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_QUANTIZATION_TRANSFORM=function(){return(Xc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_QUANTIZATION_TRANSFORM=a.asm.emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_QUANTIZATION_TRANSFORM).apply(null, 85 | arguments)},Yc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_OCTAHEDRON_TRANSFORM=function(){return(Yc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_OCTAHEDRON_TRANSFORM=a.asm.emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_OCTAHEDRON_TRANSFORM).apply(null,arguments)},Zc=a._emscripten_enum_draco_GeometryAttribute_Type_INVALID=function(){return(Zc=a._emscripten_enum_draco_GeometryAttribute_Type_INVALID=a.asm.emscripten_enum_draco_GeometryAttribute_Type_INVALID).apply(null, 86 | arguments)},$c=a._emscripten_enum_draco_GeometryAttribute_Type_POSITION=function(){return($c=a._emscripten_enum_draco_GeometryAttribute_Type_POSITION=a.asm.emscripten_enum_draco_GeometryAttribute_Type_POSITION).apply(null,arguments)},ad=a._emscripten_enum_draco_GeometryAttribute_Type_NORMAL=function(){return(ad=a._emscripten_enum_draco_GeometryAttribute_Type_NORMAL=a.asm.emscripten_enum_draco_GeometryAttribute_Type_NORMAL).apply(null,arguments)},bd=a._emscripten_enum_draco_GeometryAttribute_Type_COLOR= 87 | function(){return(bd=a._emscripten_enum_draco_GeometryAttribute_Type_COLOR=a.asm.emscripten_enum_draco_GeometryAttribute_Type_COLOR).apply(null,arguments)},cd=a._emscripten_enum_draco_GeometryAttribute_Type_TEX_COORD=function(){return(cd=a._emscripten_enum_draco_GeometryAttribute_Type_TEX_COORD=a.asm.emscripten_enum_draco_GeometryAttribute_Type_TEX_COORD).apply(null,arguments)},dd=a._emscripten_enum_draco_GeometryAttribute_Type_GENERIC=function(){return(dd=a._emscripten_enum_draco_GeometryAttribute_Type_GENERIC= 88 | a.asm.emscripten_enum_draco_GeometryAttribute_Type_GENERIC).apply(null,arguments)},ed=a._emscripten_enum_draco_EncodedGeometryType_INVALID_GEOMETRY_TYPE=function(){return(ed=a._emscripten_enum_draco_EncodedGeometryType_INVALID_GEOMETRY_TYPE=a.asm.emscripten_enum_draco_EncodedGeometryType_INVALID_GEOMETRY_TYPE).apply(null,arguments)},fd=a._emscripten_enum_draco_EncodedGeometryType_POINT_CLOUD=function(){return(fd=a._emscripten_enum_draco_EncodedGeometryType_POINT_CLOUD=a.asm.emscripten_enum_draco_EncodedGeometryType_POINT_CLOUD).apply(null, 89 | arguments)},gd=a._emscripten_enum_draco_EncodedGeometryType_TRIANGULAR_MESH=function(){return(gd=a._emscripten_enum_draco_EncodedGeometryType_TRIANGULAR_MESH=a.asm.emscripten_enum_draco_EncodedGeometryType_TRIANGULAR_MESH).apply(null,arguments)},hd=a._emscripten_enum_draco_DataType_DT_INVALID=function(){return(hd=a._emscripten_enum_draco_DataType_DT_INVALID=a.asm.emscripten_enum_draco_DataType_DT_INVALID).apply(null,arguments)},id=a._emscripten_enum_draco_DataType_DT_INT8=function(){return(id=a._emscripten_enum_draco_DataType_DT_INT8= 90 | a.asm.emscripten_enum_draco_DataType_DT_INT8).apply(null,arguments)},jd=a._emscripten_enum_draco_DataType_DT_UINT8=function(){return(jd=a._emscripten_enum_draco_DataType_DT_UINT8=a.asm.emscripten_enum_draco_DataType_DT_UINT8).apply(null,arguments)},kd=a._emscripten_enum_draco_DataType_DT_INT16=function(){return(kd=a._emscripten_enum_draco_DataType_DT_INT16=a.asm.emscripten_enum_draco_DataType_DT_INT16).apply(null,arguments)},ld=a._emscripten_enum_draco_DataType_DT_UINT16=function(){return(ld=a._emscripten_enum_draco_DataType_DT_UINT16= 91 | a.asm.emscripten_enum_draco_DataType_DT_UINT16).apply(null,arguments)},md=a._emscripten_enum_draco_DataType_DT_INT32=function(){return(md=a._emscripten_enum_draco_DataType_DT_INT32=a.asm.emscripten_enum_draco_DataType_DT_INT32).apply(null,arguments)},nd=a._emscripten_enum_draco_DataType_DT_UINT32=function(){return(nd=a._emscripten_enum_draco_DataType_DT_UINT32=a.asm.emscripten_enum_draco_DataType_DT_UINT32).apply(null,arguments)},od=a._emscripten_enum_draco_DataType_DT_INT64=function(){return(od= 92 | a._emscripten_enum_draco_DataType_DT_INT64=a.asm.emscripten_enum_draco_DataType_DT_INT64).apply(null,arguments)},pd=a._emscripten_enum_draco_DataType_DT_UINT64=function(){return(pd=a._emscripten_enum_draco_DataType_DT_UINT64=a.asm.emscripten_enum_draco_DataType_DT_UINT64).apply(null,arguments)},qd=a._emscripten_enum_draco_DataType_DT_FLOAT32=function(){return(qd=a._emscripten_enum_draco_DataType_DT_FLOAT32=a.asm.emscripten_enum_draco_DataType_DT_FLOAT32).apply(null,arguments)},rd=a._emscripten_enum_draco_DataType_DT_FLOAT64= 93 | function(){return(rd=a._emscripten_enum_draco_DataType_DT_FLOAT64=a.asm.emscripten_enum_draco_DataType_DT_FLOAT64).apply(null,arguments)},sd=a._emscripten_enum_draco_DataType_DT_BOOL=function(){return(sd=a._emscripten_enum_draco_DataType_DT_BOOL=a.asm.emscripten_enum_draco_DataType_DT_BOOL).apply(null,arguments)},td=a._emscripten_enum_draco_DataType_DT_TYPES_COUNT=function(){return(td=a._emscripten_enum_draco_DataType_DT_TYPES_COUNT=a.asm.emscripten_enum_draco_DataType_DT_TYPES_COUNT).apply(null, 94 | arguments)},ud=a._emscripten_enum_draco_StatusCode_OK=function(){return(ud=a._emscripten_enum_draco_StatusCode_OK=a.asm.emscripten_enum_draco_StatusCode_OK).apply(null,arguments)},vd=a._emscripten_enum_draco_StatusCode_DRACO_ERROR=function(){return(vd=a._emscripten_enum_draco_StatusCode_DRACO_ERROR=a.asm.emscripten_enum_draco_StatusCode_DRACO_ERROR).apply(null,arguments)},wd=a._emscripten_enum_draco_StatusCode_IO_ERROR=function(){return(wd=a._emscripten_enum_draco_StatusCode_IO_ERROR=a.asm.emscripten_enum_draco_StatusCode_IO_ERROR).apply(null, 95 | arguments)},xd=a._emscripten_enum_draco_StatusCode_INVALID_PARAMETER=function(){return(xd=a._emscripten_enum_draco_StatusCode_INVALID_PARAMETER=a.asm.emscripten_enum_draco_StatusCode_INVALID_PARAMETER).apply(null,arguments)},yd=a._emscripten_enum_draco_StatusCode_UNSUPPORTED_VERSION=function(){return(yd=a._emscripten_enum_draco_StatusCode_UNSUPPORTED_VERSION=a.asm.emscripten_enum_draco_StatusCode_UNSUPPORTED_VERSION).apply(null,arguments)},zd=a._emscripten_enum_draco_StatusCode_UNKNOWN_VERSION=function(){return(zd= 96 | a._emscripten_enum_draco_StatusCode_UNKNOWN_VERSION=a.asm.emscripten_enum_draco_StatusCode_UNKNOWN_VERSION).apply(null,arguments)};a.___errno_location=function(){return(a.___errno_location=a.asm.__errno_location).apply(null,arguments)};a.stackSave=function(){return(a.stackSave=a.asm.stackSave).apply(null,arguments)};a.stackRestore=function(){return(a.stackRestore=a.asm.stackRestore).apply(null,arguments)};a.stackAlloc=function(){return(a.stackAlloc=a.asm.stackAlloc).apply(null,arguments)};a._setThrew= 97 | function(){return(a._setThrew=a.asm.setThrew).apply(null,arguments)};a._free=function(){return(a._free=a.asm.free).apply(null,arguments)};var fb=a._malloc=function(){return(fb=a._malloc=a.asm.malloc).apply(null,arguments)},sa;na=function b(){sa||ea();sa||(na=b)};a.run=ea;if(a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);0=r.size?(q(0>>=0;switch(c.BYTES_PER_ELEMENT){case 2:d>>>=1;break;case 4:d>>>=2;break;case 8:d>>>=3}for(var g=0;gb.byteLength)return a.INVALID_GEOMETRY_TYPE;switch(b[7]){case 0:return a.POINT_CLOUD;case 1:return a.TRIANGULAR_MESH;default:return a.INVALID_GEOMETRY_TYPE}};return n.ready}}();"object"===typeof exports&&"object"===typeof module?module.exports=DracoDecoderModule:"function"===typeof define&&define.amd?define([],function(){return DracoDecoderModule}):"object"===typeof exports&&(exports.DracoDecoderModule=DracoDecoderModule); 131 | --------------------------------------------------------------------------------