diff options
| author | Rohit T P <tprohit9@gmail.com> | 2024-04-23 17:56:04 +0530 |
|---|---|---|
| committer | Rohit T P <tprohit9@gmail.com> | 2024-04-23 17:56:04 +0530 |
| commit | 5f5922cec32072274cfcb851d8c100bc9b313a14 (patch) | |
| tree | 58348a113dbb2b73778bfc64a0e76c8c9c47db46 | |
| parent | 178daa5e58b06bb84895517765a6463fbae3ac37 (diff) | |
today
| -rw-r--r-- | README.md | 40 | ||||
| -rw-r--r-- | package.json | 2 | ||||
| -rw-r--r-- | pnpm-lock.yaml | 268 | ||||
| -rw-r--r-- | public/xbot.glb | bin | 2233444 -> 2233440 bytes | |||
| -rw-r--r-- | src/Models/xbot/xbot.png | bin | 249018 -> 0 bytes | |||
| -rw-r--r-- | src/app/api/route.ts | 79 | ||||
| -rw-r--r-- | src/app/components/ActionModel.tsx | 133 | ||||
| -rw-r--r-- | src/app/normal/page.tsx | 63 | ||||
| -rw-r--r-- | src/app/page.tsx | 153 | ||||
| -rw-r--r-- | src/app/sign/page.tsx | 62 |
10 files changed, 621 insertions, 179 deletions
@@ -1,36 +1,18 @@ -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). +# How to run -## Getting Started - -First, run the development server: +1. Install the dependencies +```bash +pnpm install +``` +2. Run the development server ```bash -npm run dev -# or -yarn dev -# or pnpm dev -# or -bun dev ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +3. Run docker +```bash +docker run -p 9000:9000 -d peerjs/peerjs-server +``` -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. +4. Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. diff --git a/package.json b/package.json index dd4df12..1e5ed23 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,10 @@ "dependencies": { "@types/three": "^0.163.0", "next": "14.2.2", + "peerjs": "^1.5.2", "react": "^18", "react-dom": "^18", + "socket.io": "^4.7.5", "three": "^0.163.0" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2ae464f..9531dab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,12 +11,18 @@ dependencies: next: specifier: 14.2.2 version: 14.2.2(react-dom@18.0.0)(react@18.0.0) + peerjs: + specifier: ^1.5.2 + version: 1.5.2 react: specifier: ^18 version: 18.0.0 react-dom: specifier: ^18 version: 18.0.0(react@18.0.0) + socket.io: + specifier: ^4.7.5 + version: 4.7.5 three: specifier: ^0.163.0 version: 0.163.0 @@ -55,6 +61,54 @@ packages: regenerator-runtime: 0.14.1 dev: true + /@cbor-extract/cbor-extract-darwin-arm64@2.2.0: + resolution: {integrity: sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@cbor-extract/cbor-extract-darwin-x64@2.2.0: + resolution: {integrity: sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@cbor-extract/cbor-extract-linux-arm64@2.2.0: + resolution: {integrity: sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@cbor-extract/cbor-extract-linux-arm@2.2.0: + resolution: {integrity: sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@cbor-extract/cbor-extract-linux-x64@2.2.0: + resolution: {integrity: sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@cbor-extract/cbor-extract-win32-x64@2.2.0: + resolution: {integrity: sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@eslint/eslintrc@1.4.1: resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -99,6 +153,11 @@ packages: wrap-ansi-cjs: /wrap-ansi@7.0.0 dev: true + /@msgpack/msgpack@2.8.0: + resolution: {integrity: sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ==} + engines: {node: '>= 10'} + dev: false + /@next/env@14.2.2: resolution: {integrity: sha512-sk72qRfM1Q90XZWYRoJKu/UWlTgihrASiYw/scb15u+tyzcze3bOuJ/UV6TBOQEeUaxOkRqGeuGUdiiuxc5oqw==} dev: false @@ -222,6 +281,10 @@ packages: resolution: {integrity: sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw==} dev: true + /@socket.io/component-emitter@3.1.1: + resolution: {integrity: sha512-dzJtaDAAoXx4GCOJpbB2eG/Qj8VDpdwkLsWGzGm+0L7E8/434RyMbAHmk9ubXWVAb9nXmc44jUf8GKqVDiKezg==} + dev: false + /@swc/counter@0.1.3: resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} dev: false @@ -237,13 +300,22 @@ packages: resolution: {integrity: sha512-ZpboH7pCPPeyBWKf8c7TJswtCEQObFo3bOBYalm99NzZarATALYCo5OhbCa/n4RQyJyHfhkdx+hNrdL5ByFYDw==} dev: false + /@types/cookie@0.4.1: + resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} + dev: false + + /@types/cors@2.8.17: + resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + dependencies: + '@types/node': 20.0.0 + dev: false + /@types/json5@0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true /@types/node@20.0.0: resolution: {integrity: sha512-cD2uPTDnQQCVpmRefonO98/PPijuOnnEy5oytWJFPY1N9aJCz2wJ5kSGWO+zJoed2cY2JxQh6yBuUq4vIn61hw==} - dev: true /@types/prop-types@15.7.12: resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} @@ -349,6 +421,14 @@ packages: eslint-visitor-keys: 3.4.3 dev: true + /accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + /acorn-jsx@5.3.2(acorn@8.11.3): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -537,6 +617,11 @@ packages: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true + /base64id@2.0.0: + resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} + engines: {node: ^4.5.0 || >= 5.9} + dev: false + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -584,6 +669,28 @@ packages: resolution: {integrity: sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==} dev: false + /cbor-extract@2.2.0: + resolution: {integrity: sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==} + hasBin: true + requiresBuild: true + dependencies: + node-gyp-build-optional-packages: 5.1.1 + optionalDependencies: + '@cbor-extract/cbor-extract-darwin-arm64': 2.2.0 + '@cbor-extract/cbor-extract-darwin-x64': 2.2.0 + '@cbor-extract/cbor-extract-linux-arm': 2.2.0 + '@cbor-extract/cbor-extract-linux-arm64': 2.2.0 + '@cbor-extract/cbor-extract-linux-x64': 2.2.0 + '@cbor-extract/cbor-extract-win32-x64': 2.2.0 + dev: false + optional: true + + /cbor-x@1.5.4: + resolution: {integrity: sha512-PVKILDn+Rf6MRhhcyzGXi5eizn1i0i3F8Fe6UMMxXBnWkalq9+C5+VTmlIjAYM4iF2IYF2N+zToqAfYOp+3rfw==} + optionalDependencies: + cbor-extract: 2.2.0 + dev: false + /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -611,6 +718,19 @@ packages: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true + /cookie@0.4.2: + resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} + engines: {node: '>= 0.6'} + dev: false + + /cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + dev: false + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -676,7 +796,6 @@ packages: optional: true dependencies: ms: 2.1.2 - dev: true /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -705,6 +824,12 @@ packages: engines: {node: '>=6'} dev: true + /detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + dev: false + optional: true + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -738,6 +863,31 @@ packages: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} dev: true + /engine.io-parser@5.2.2: + resolution: {integrity: sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==} + engines: {node: '>=10.0.0'} + dev: false + + /engine.io@6.5.4: + resolution: {integrity: sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==} + engines: {node: '>=10.2.0'} + dependencies: + '@types/cookie': 0.4.1 + '@types/cors': 2.8.17 + '@types/node': 20.0.0 + accepts: 1.3.8 + base64id: 2.0.0 + cookie: 0.4.2 + cors: 2.8.5 + debug: 4.3.4 + engine.io-parser: 5.2.2 + ws: 8.11.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + /enhanced-resolve@5.16.0: resolution: {integrity: sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==} engines: {node: '>=10.13.0'} @@ -1166,6 +1316,10 @@ packages: engines: {node: '>=0.10.0'} dev: true + /eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + dev: false + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -1742,6 +1896,18 @@ packages: picomatch: 2.3.1 dev: true + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: @@ -1773,7 +1939,6 @@ packages: /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1789,6 +1954,11 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true + /negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + /next@14.2.2(react-dom@18.0.0)(react@18.0.0): resolution: {integrity: sha512-oGwUaa2bCs47FbuxWMpOoXtBMPYpvTPgdZr3UAo+pu7Ns00z9otmYpoeV1HEiYL06AlRQQIA/ypK526KjJfaxg==} engines: {node: '>=18.17.0'} @@ -1831,10 +2001,17 @@ packages: - babel-plugin-macros dev: false + /node-gyp-build-optional-packages@5.1.1: + resolution: {integrity: sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==} + hasBin: true + dependencies: + detect-libc: 2.0.3 + dev: false + optional: true + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - dev: true /object-inspect@1.13.1: resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} @@ -1953,6 +2130,22 @@ packages: engines: {node: '>=8'} dev: true + /peerjs-js-binarypack@2.1.0: + resolution: {integrity: sha512-YIwCC+pTzp3Bi8jPI9UFKO0t0SLo6xALnHkiNt/iUFmUUZG0fEEmEyFKvjsDKweiFitzHRyhuh6NvyJZ4nNxMg==} + engines: {node: '>= 14.0.0'} + dev: false + + /peerjs@1.5.2: + resolution: {integrity: sha512-pPrtNwPyWJHRPxy2y+rHcdlrG8UwUBB1nl+3Yj6r7FLwcbBpcB2NvGNvLvcrxAVGGGX9fsdA5VT5zBKTZcm1DQ==} + engines: {node: '>= 14'} + dependencies: + '@msgpack/msgpack': 2.8.0 + cbor-x: 1.5.4 + eventemitter3: 4.0.7 + peerjs-js-binarypack: 2.1.0 + webrtc-adapter: 8.2.3 + dev: false + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: false @@ -2126,6 +2319,10 @@ packages: loose-envify: 1.4.0 dev: false + /sdp@3.2.0: + resolution: {integrity: sha512-d7wDPgDV3DDiqulJjKiV2865wKsJ34YI+NDREbm+FySq6WuKOikwyNQcm+doLAZ1O6ltdO0SeKle2xMpN3Brgw==} + dev: false + /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -2193,6 +2390,44 @@ packages: engines: {node: '>=8'} dev: true + /socket.io-adapter@2.5.4: + resolution: {integrity: sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==} + dependencies: + debug: 4.3.4 + ws: 8.11.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + + /socket.io-parser@4.2.4: + resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} + engines: {node: '>=10.0.0'} + dependencies: + '@socket.io/component-emitter': 3.1.1 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /socket.io@4.7.5: + resolution: {integrity: sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==} + engines: {node: '>=10.2.0'} + dependencies: + accepts: 1.3.8 + base64id: 2.0.0 + cors: 2.8.5 + debug: 4.3.4 + engine.io: 6.5.4 + socket.io-adapter: 2.5.4 + socket.io-parser: 4.2.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + /source-map-js@1.2.0: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} @@ -2442,6 +2677,18 @@ packages: resolution: {integrity: sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==} dev: true + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false + + /webrtc-adapter@8.2.3: + resolution: {integrity: sha512-gnmRz++suzmvxtp3ehQts6s2JtAGPuDPjA1F3a9ckNpG1kYdYuHWYpazoAnL9FS5/B21tKlhkorbdCXat0+4xQ==} + engines: {node: '>=6.0.0', npm: '>=3.10.0'} + dependencies: + sdp: 3.2.0 + dev: false + /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: @@ -2521,6 +2768,19 @@ packages: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: true + /ws@8.11.0: + resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true diff --git a/public/xbot.glb b/public/xbot.glb Binary files differindex a21d9b6..502ef3f 100644 --- a/public/xbot.glb +++ b/public/xbot.glb diff --git a/src/Models/xbot/xbot.png b/src/Models/xbot/xbot.png Binary files differdeleted file mode 100644 index eaf7a11..0000000 --- a/src/Models/xbot/xbot.png +++ /dev/null diff --git a/src/app/api/route.ts b/src/app/api/route.ts new file mode 100644 index 0000000..7a6d74c --- /dev/null +++ b/src/app/api/route.ts @@ -0,0 +1,79 @@ +import {NextApiRequest, NextApiResponse} from 'next'; +import { Server as ServerIO } from 'socket.io'; +import { Socket as NetSocket } from 'net'; +import { Server as HTTPServer } from 'http'; +import { Server as SocketIOServer } from 'socket.io'; + +type NextApiResponseServerIO = NextApiResponse & { + socket: NetSocket & { + server: HTTPServer & { + io: SocketIOServer; + }; + }; +}; + +const socketHandler = (req: NextApiRequest, res: NextApiResponseServerIO) => { + if (!res.socket.server.io) { + console.log('Socket is initializing'); + + const httpServer = res.socket.server; + const io = new ServerIO(httpServer, { path: "/api/socketio" }); + res.socket.server.io = io; + + io.on('connection', (socket) => { + console.log('connected'); + + socket.on('room:join', ({ room, user }) => { + console.table({ + 'room-id': room, + 'used-id': user.id, + 'user-name': user.name, + }); + + socket.join(room); + + socket.to(room).emit('user:joined', user); + + socket.on('disconnect', () => { + socket.to(room).emit('user:left', user.id); + }); + + socket.on('user:leave', (userId) => { + socket.to(room).emit('user:left', userId); + }); + + socket.on('host:mute-user', (userId) => { + socket.to(room).emit('host:muted-user', userId); + }); + + socket.on('host:remove-user-shared-screen', () => { + socket.to(room).emit('host:removed-user-shared-screen'); + }); + + socket.on('user:toggle-audio', (userId) => { + socket.to(room).emit('user:toggled-audio', userId); + }); + + socket.on('user:toggle-video', (userId) => { + socket.to(room).emit('user:toggled-video', userId); + }); + + socket.on('user:share-screen', (username) => { + socket.to(room).emit('user:shared-screen', username); + }); + + socket.on('user:stop-share-screen', () => { + socket.to(room).emit('user:stopped-screen-share', user.name); + }); + + socket.on('chat:post', (message) => { + socket.to(room).emit('chat:get', message); + }); + }); + }); + } + + res.end(); +}; + +export default socketHandler; diff --git a/src/app/components/ActionModel.tsx b/src/app/components/ActionModel.tsx new file mode 100644 index 0000000..b20bbe6 --- /dev/null +++ b/src/app/components/ActionModel.tsx @@ -0,0 +1,133 @@ +import words from "@/Animations/words"; +import alphabets from "@/Animations/alphabets"; +import {useEffect, useRef} from "react"; +import * as THREE from "three"; +// @ts-ignore +import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader"; +import {defaultPose} from "@/Animations/defaultPose"; + +interface ActionModelProps { + text: string; + pause: number; + speed: number; +} + +export default function ActionModel({text, pause, speed}: ActionModelProps) { + const {current: ref} = useRef<Record<string, any>>({}); + + useEffect(() => { + + ref.flag = false; + ref.pending = false; + + ref.animations = []; + ref.characters = []; + + ref.scene = new THREE.Scene(); + ref.scene.background = new THREE.Color(0xdddddd); + + const spotLight = new THREE.SpotLight(0xffffff, 20); + spotLight.position.set(0, 5, 2); + ref.scene.add(spotLight); + ref.renderer = new THREE.WebGLRenderer({antialias: true}); + + ref.camera = new THREE.PerspectiveCamera( + 30, + window.innerWidth * 0.57 / (window.innerHeight - 70), + 0.1, + 1000 + ) + ref.renderer.setSize(window.innerWidth * 0.57, window.innerHeight - 70); + + const canvas = document.getElementById("canvas"); + + if (!canvas) + return; + + canvas.innerHTML = ""; + canvas.appendChild(ref.renderer.domElement); + + ref.camera.position.z = 1.6; + ref.camera.position.y = 1.4; + + let loader = new GLTFLoader(); + loader.load( + "/xbot.glb", + (gltf: { scene: { traverse: (arg0: (child: any) => void) => void; }; }) => { + gltf.scene.traverse((child) => { + if (child.type === 'SkinnedMesh') { + child.frustumCulled = false; + } + }); + // Check if the avatar is already loaded + if (ref.avatar) { + ref.scene.remove(ref.avatar); + } + + ref.avatar = gltf.scene; + ref.scene.add(ref.avatar); + defaultPose(ref); + } + ); + + }, [ref]); + + useEffect(() => { + const strWords = text.toUpperCase().split(' '); + + for (let word of strWords) { + if (words[word]) { + ref.animations.push(['add-text', word + ' ']); + words[word](ref); + + } else { + word.split('').forEach((ch, index) => { + if (index === word.length - 1) + ref.animations.push(['add-text', ch + ' ']); + else + ref.animations.push(['add-text', ch]); + alphabets[ch](ref); + }); + } + } + }, [text]); + + ref.animate = () => { + if (ref.animations.length === 0) { + ref.pending = false; + return; + } + requestAnimationFrame(ref.animate); + if (ref.animations[0].length) { + if (!ref.flag) { + if (ref.animations[0][0] === 'add-text') { + ref.animations.shift(); + } else { + for (let i = 0; i < ref.animations[0].length;) { + let [boneName, action, axis, limit, sign] = ref.animations[0][i] + if (sign === "+" && ref.avatar.getObjectByName(boneName)[action][axis] < limit) { + ref.avatar.getObjectByName(boneName)[action][axis] += speed; + ref.avatar.getObjectByName(boneName)[action][axis] = Math.min(ref.avatar.getObjectByName(boneName)[action][axis], limit); + i++; + } else if (sign === "-" && ref.avatar.getObjectByName(boneName)[action][axis] > limit) { + ref.avatar.getObjectByName(boneName)[action][axis] -= speed; + ref.avatar.getObjectByName(boneName)[action][axis] = Math.max(ref.avatar.getObjectByName(boneName)[action][axis], limit); + i++; + } else { + ref.animations[0].splice(i, 1); + } + } + } + } + } else { + ref.flag = true; + setTimeout(() => { + ref.flag = false + }, pause); + ref.animations.shift(); + } + ref.renderer.render(ref.scene, ref.camera); + } + + return <div id='canvas'/> +} diff --git a/src/app/normal/page.tsx b/src/app/normal/page.tsx new file mode 100644 index 0000000..5ab1b5b --- /dev/null +++ b/src/app/normal/page.tsx @@ -0,0 +1,63 @@ +"use client"; + +import {useEffect, useRef, useState} from "react"; +import Link from "next/link"; +import {DataConnection, Peer} from "peerjs"; + +export default function Normal() { + const [connection, setConnection] = useState<DataConnection>(); + const videoRef = useRef<HTMLVideoElement>(null); + + function handleOnRecord() { + // @ts-ignore + const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; + const recognition = new SpeechRecognition(); + recognition.continuous = true; + recognition.interimResults = false; + + recognition.onresult = async function(event: { results: { transcript: any; }[][]; }) { + const transcript = event.results[event.results.length-1][0].transcript; + console.log(transcript); + if (connection) { + connection.send(transcript); + } + } + + recognition.start(); + } + + useEffect(() => { + const peer = new Peer("123", { + host: "localhost", + port: 9000, + path: "/", + }); + + peer.on("call", (call) => { + navigator.mediaDevices.getUserMedia({video: true, audio: false}) + .then((stream) => { + call.answer(stream); + call.on("stream", (remoteStream: MediaProvider | null) => { + if (videoRef.current) { + videoRef.current.srcObject = remoteStream; + } + }); + }); + + const connection = peer.connect("321"); + setConnection(connection); + }); + + return () => { + peer.destroy(); + } + }, [videoRef]); + + return ( + <div> + <video ref={videoRef} autoPlay playsInline/> + <br /> + <Link href="/">End Call</Link> + </div> + ) +} diff --git a/src/app/page.tsx b/src/app/page.tsx index b89feda..2e66375 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,157 +1,18 @@ "use client"; -import {useEffect, useRef} from "react"; - -import words from '@/Animations/words'; -import alphabets from '@/Animations/alphabets'; -import {defaultPose} from '@/Animations/defaultPose'; - -import * as THREE from "three"; -// @ts-ignore -import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader"; - - -const SPEED = 0.1; -const PAUSE = 800; +import {useState} from "react"; +import ActionModel from "@/app/components/ActionModel"; +import Link from "next/link"; function Home() { - const componentRef = useRef<Record<string, any>>({}); - const {current: ref} = componentRef; - - function handleOnRecord() { - // @ts-ignore - const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; - const recognition = new SpeechRecognition(); - - recognition.onresult = async function(event: { results: { transcript: any; }[][]; }) { - const transcript = event.results[0][0].transcript; - sign(transcript); - } - - recognition.start(); - } - - - useEffect(() => { - - ref.flag = false; - ref.pending = false; - - ref.animations = []; - ref.characters = []; - - ref.scene = new THREE.Scene(); - ref.scene.background = new THREE.Color(0xdddddd); - - const spotLight = new THREE.SpotLight(0xffffff, 2); - spotLight.position.set(0, 5, 5); - ref.scene.add(spotLight); - ref.renderer = new THREE.WebGLRenderer({antialias: true}); - - ref.camera = new THREE.PerspectiveCamera( - 30, - window.innerWidth * 0.57 / (window.innerHeight - 70), - 0.1, - 1000 - ) - ref.renderer.setSize(window.innerWidth * 0.57, window.innerHeight - 70); - - const canvas = document.getElementById("canvas"); - - if (!canvas) - return; - - canvas.innerHTML = ""; - canvas.appendChild(ref.renderer.domElement); - - ref.camera.position.z = 1.6; - ref.camera.position.y = 1.4; - - let loader = new GLTFLoader(); - loader.load( - "/xbot.glb", - (gltf: { scene: { traverse: (arg0: (child: any) => void) => void; }; }) => { - gltf.scene.traverse((child) => { - if (child.type === 'SkinnedMesh') { - child.frustumCulled = false; - } - }); - ref.avatar = gltf.scene; - ref.scene.add(ref.avatar); - defaultPose(ref); - }, - console.log - ); - - }, [ref]); - - ref.animate = () => { - if (ref.animations.length === 0) { - ref.pending = false; - return; - } - requestAnimationFrame(ref.animate); - if (ref.animations[0].length) { - if (!ref.flag) { - if (ref.animations[0][0] === 'add-text') { - ref.animations.shift(); - } else { - for (let i = 0; i < ref.animations[0].length;) { - let [boneName, action, axis, limit, sign] = ref.animations[0][i] - if (sign === "+" && ref.avatar.getObjectByName(boneName)[action][axis] < limit) { - ref.avatar.getObjectByName(boneName)[action][axis] += SPEED; - ref.avatar.getObjectByName(boneName)[action][axis] = Math.min(ref.avatar.getObjectByName(boneName)[action][axis], limit); - i++; - } else if (sign === "-" && ref.avatar.getObjectByName(boneName)[action][axis] > limit) { - ref.avatar.getObjectByName(boneName)[action][axis] -= SPEED; - ref.avatar.getObjectByName(boneName)[action][axis] = Math.max(ref.avatar.getObjectByName(boneName)[action][axis], limit); - i++; - } else { - ref.animations[0].splice(i, 1); - } - } - } - } - } else { - ref.flag = true; - setTimeout(() => { - ref.flag = false - }, PAUSE); - ref.animations.shift(); - } - ref.renderer.render(ref.scene, ref.camera); - } - - const sign = (text: string) => { - const strWords = text.toUpperCase().split(' '); - - for (let word of strWords) { - if (words[word]) { - ref.animations.push(['add-text', word + ' ']); - words[word](ref); - } else { - word.split('').forEach((ch, index) => { - if (index === word.length - 1) - ref.animations.push(['add-text', ch + ' ']); - else - ref.animations.push(['add-text', ch]); - alphabets[ch](ref); - }); - } - } - } + const [text, setText] = useState(''); return ( <div className='container-fluid'> - <div className='row'> - <button onClick={handleOnRecord} className='btn btn-primary w-100 btn-style'> - Start Listening - </button> - </div> - <div className='col-md-7'> - <div id='canvas'/> - </div> + <Link href={'/sign'}>Sign</Link> + <br/> + <Link href={'/normal'}>Normal</Link> </div> ) } diff --git a/src/app/sign/page.tsx b/src/app/sign/page.tsx new file mode 100644 index 0000000..d9c8de3 --- /dev/null +++ b/src/app/sign/page.tsx @@ -0,0 +1,62 @@ +"use client"; + +import {useRef, useState} from "react"; +import Link from "next/link"; +import {Peer} from "peerjs"; +import ActionModel from "@/app/components/ActionModel"; + +export default function Sign() { + const [text, setText] = useState(''); + const [started, setStarted] = useState(false); + + const videoRef = useRef<HTMLVideoElement>(null); + + function startCall() { + if(!window) return; + + const peer = new Peer("321", { + host: "localhost", + port: 9000, + path: "/", + }); + setStarted(true); + + navigator.mediaDevices.getUserMedia({video: true, audio: true}) + .then((stream) => { + const call = peer.call("123", stream); + call.on("stream", (remoteStream: MediaProvider | null) => { + if (videoRef.current) { + videoRef.current.srcObject = remoteStream; + } + }); + call.on("close", () => { + setStarted(false); + }); + call.on("error", console.log); + }); + + peer.on("error", console.log); + + peer.on("connection", (conn) => { + conn.on("data", (data) => { + console.log(data); + setText(data as string); + }); + }); + + return () => { + peer.destroy(); + } + } + + return ( + <div> + {!started && <button onClick={startCall}>Start Call</button>} + <video ref={videoRef} autoPlay playsInline/> + <ActionModel text={text} pause={400} speed={0.3} /> + <p>{text}</p> + <br /> + <Link href="/">End Call</Link> + </div> + ) +} |
