experimenting with first three scenes
411
package-lock.json
generated
|
|
@ -8,6 +8,7 @@
|
|||
"name": "skyjo-fe",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@react-three/drei": "^9.84.1",
|
||||
"@react-three/fiber": "^8.14.1",
|
||||
"@types/three": "^0.156.0",
|
||||
"react": "^18.2.0",
|
||||
|
|
@ -911,6 +912,11 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@mediapipe/tasks-vision": {
|
||||
"version": "0.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.2.tgz",
|
||||
"integrity": "sha512-d8Q9uRK89ZRWmED2JLI9/blpJcfdbh0iEUuMo8TgkMzNfQBY1/GC0FEJWrairTwHkxIf6Oud1vFBP+aHicWqJA=="
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
|
|
@ -946,6 +952,115 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-spring/animated": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.6.1.tgz",
|
||||
"integrity": "sha512-ls/rJBrAqiAYozjLo5EPPLLOb1LM0lNVQcXODTC1SMtS6DbuBCPaKco5svFUQFMP2dso3O+qcC4k9FsKc0KxMQ==",
|
||||
"dependencies": {
|
||||
"@react-spring/shared": "~9.6.1",
|
||||
"@react-spring/types": "~9.6.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-spring/core": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.6.1.tgz",
|
||||
"integrity": "sha512-3HAAinAyCPessyQNNXe5W0OHzRfa8Yo5P748paPcmMowZ/4sMfaZ2ZB6e5x5khQI8NusOHj8nquoutd6FRY5WQ==",
|
||||
"dependencies": {
|
||||
"@react-spring/animated": "~9.6.1",
|
||||
"@react-spring/rafz": "~9.6.1",
|
||||
"@react-spring/shared": "~9.6.1",
|
||||
"@react-spring/types": "~9.6.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/react-spring/donate"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-spring/rafz": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.6.1.tgz",
|
||||
"integrity": "sha512-v6qbgNRpztJFFfSE3e2W1Uz+g8KnIBs6SmzCzcVVF61GdGfGOuBrbjIcp+nUz301awVmREKi4eMQb2Ab2gGgyQ=="
|
||||
},
|
||||
"node_modules/@react-spring/shared": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.6.1.tgz",
|
||||
"integrity": "sha512-PBFBXabxFEuF8enNLkVqMC9h5uLRBo6GQhRMQT/nRTnemVENimgRd+0ZT4yFnAQ0AxWNiJfX3qux+bW2LbG6Bw==",
|
||||
"dependencies": {
|
||||
"@react-spring/rafz": "~9.6.1",
|
||||
"@react-spring/types": "~9.6.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-spring/three": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-spring/three/-/three-9.6.1.tgz",
|
||||
"integrity": "sha512-Tyw2YhZPKJAX3t2FcqvpLRb71CyTe1GvT3V+i+xJzfALgpk10uPGdGaQQ5Xrzmok1340DAeg2pR/MCfaW7b8AA==",
|
||||
"dependencies": {
|
||||
"@react-spring/animated": "~9.6.1",
|
||||
"@react-spring/core": "~9.6.1",
|
||||
"@react-spring/shared": "~9.6.1",
|
||||
"@react-spring/types": "~9.6.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-three/fiber": ">=6.0",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"three": ">=0.126"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-spring/types": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.6.1.tgz",
|
||||
"integrity": "sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q=="
|
||||
},
|
||||
"node_modules/@react-three/drei": {
|
||||
"version": "9.84.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.84.1.tgz",
|
||||
"integrity": "sha512-0RbpRPW87OYAZcFSqnlhHitG2aXoT/52zAAxiPqoWeVXBSHogLqvTkiKPWi2iaKKBOezeGkzXsCDs3sLJ9ED/Q==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"@mediapipe/tasks-vision": "0.10.2",
|
||||
"@react-spring/three": "~9.6.1",
|
||||
"@use-gesture/react": "^10.2.24",
|
||||
"camera-controls": "^2.4.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"detect-gpu": "^5.0.28",
|
||||
"glsl-noise": "^0.0.0",
|
||||
"lodash.clamp": "^4.0.3",
|
||||
"lodash.omit": "^4.5.0",
|
||||
"lodash.pick": "^4.4.0",
|
||||
"maath": "^0.9.0",
|
||||
"meshline": "^3.1.6",
|
||||
"react-composer": "^5.0.3",
|
||||
"react-merge-refs": "^1.1.0",
|
||||
"stats-gl": "^1.0.4",
|
||||
"stats.js": "^0.17.0",
|
||||
"suspend-react": "^0.1.3",
|
||||
"three-mesh-bvh": "^0.6.0",
|
||||
"three-stdlib": "^2.25.1",
|
||||
"troika-three-text": "^0.47.2",
|
||||
"utility-types": "^3.10.0",
|
||||
"zustand": "^3.5.13"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-three/fiber": ">=8.0",
|
||||
"react": ">=18.0",
|
||||
"react-dom": ">=18.0",
|
||||
"three": ">=0.137"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@react-three/fiber": {
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.14.1.tgz",
|
||||
|
|
@ -997,6 +1112,11 @@
|
|||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||
},
|
||||
"node_modules/@types/draco3d": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.4.tgz",
|
||||
"integrity": "sha512-qmFieVcgNRvXphmSjnQnJGXbKq2ymE38L/22GlDD/IIzyA0dHQNI0za+RLSfyW6aG/lOoYWkGudFZnrs9PmqCw=="
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
|
||||
|
|
@ -1009,6 +1129,11 @@
|
|||
"integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/offscreencanvas": {
|
||||
"version": "2019.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.1.tgz",
|
||||
"integrity": "sha512-+HSrJgjBW77ALieQdMJvXhRZUIRN1597L+BKvsyeiIlHHERnqjcuOLyodK3auJ3Y3zRezNKtKAhuQWYJfEgFHQ=="
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||
|
|
@ -1262,6 +1387,22 @@
|
|||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@use-gesture/core": {
|
||||
"version": "10.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.0.tgz",
|
||||
"integrity": "sha512-rh+6MND31zfHcy9VU3dOZCqGY511lvGcfyJenN4cWZe0u1BH6brBpBddLVXhF2r4BMqWbvxfsbL7D287thJU2A=="
|
||||
},
|
||||
"node_modules/@use-gesture/react": {
|
||||
"version": "10.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@use-gesture/react/-/react-10.3.0.tgz",
|
||||
"integrity": "sha512-3zc+Ve99z4usVP6l9knYVbVnZgfqhKah7sIG+PS2w+vpig2v2OLct05vs+ZXMzwxdNCMka8B+8WlOo0z6Pn6DA==",
|
||||
"dependencies": {
|
||||
"@use-gesture/core": "10.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">= 16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitejs/plugin-react": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.4.tgz",
|
||||
|
|
@ -1378,6 +1519,14 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"node_modules/bidi-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz",
|
||||
"integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==",
|
||||
"dependencies": {
|
||||
"require-from-string": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
|
|
@ -1441,6 +1590,14 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/camera-controls": {
|
||||
"version": "2.7.2",
|
||||
"resolved": "https://registry.npmjs.org/camera-controls/-/camera-controls-2.7.2.tgz",
|
||||
"integrity": "sha512-6+gaZFK3LYbWaXC94EN0BYLlvpo9xfUqwp59vsU3nV7WXIU05q4wyP5TOgyG1tqTHReuBofb20vKfZNBNjMtzw==",
|
||||
"peerDependencies": {
|
||||
"three": ">=0.126.1"
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001533",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001533.tgz",
|
||||
|
|
@ -1502,11 +1659,27 @@
|
|||
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cross-env": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
|
||||
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"cross-env": "src/bin/cross-env.js",
|
||||
"cross-env-shell": "src/bin/cross-env-shell.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.14",
|
||||
"npm": ">=6",
|
||||
"yarn": ">=1"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
|
|
@ -1548,6 +1721,14 @@
|
|||
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/detect-gpu": {
|
||||
"version": "5.0.37",
|
||||
"resolved": "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.37.tgz",
|
||||
"integrity": "sha512-EraWs84faI4iskB4qvE39bevMIazEvd1RpoyGLOBesRLbiz6eMeJqqRPHjEFClfRByYZzi9IzU35rBXIO76oDw==",
|
||||
"dependencies": {
|
||||
"webgl-constants": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/dir-glob": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||
|
|
@ -1572,6 +1753,11 @@
|
|||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/draco3d": {
|
||||
"version": "1.5.6",
|
||||
"resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.6.tgz",
|
||||
"integrity": "sha512-+3NaRjWktb5r61ZFoDejlykPEFKT5N/LkbXsaddlw6xNSXBanUYpFc2AXXpbJDilPHazcSreU/DpQIaxfX0NfQ=="
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.515",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.515.tgz",
|
||||
|
|
@ -2122,6 +2308,11 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/glsl-noise": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/glsl-noise/-/glsl-noise-0.0.0.tgz",
|
||||
"integrity": "sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w=="
|
||||
},
|
||||
"node_modules/graphemer": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||
|
|
@ -2229,8 +2420,7 @@
|
|||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
||||
},
|
||||
"node_modules/its-fine": {
|
||||
"version": "1.1.1",
|
||||
|
|
@ -2319,6 +2509,11 @@
|
|||
"json-buffer": "3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ktx-parse": {
|
||||
"version": "0.4.5",
|
||||
"resolved": "https://registry.npmjs.org/ktx-parse/-/ktx-parse-0.4.5.tgz",
|
||||
"integrity": "sha512-MK3FOody4TXbFf8Yqv7EBbySw7aPvEcPX++Ipt6Sox+/YMFvR5xaTyhfNSk1AEmMy+RYIw81ctN4IMxCB8OAlg=="
|
||||
},
|
||||
"node_modules/levn": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
||||
|
|
@ -2347,12 +2542,27 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.clamp": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/lodash.clamp/-/lodash.clamp-4.0.3.tgz",
|
||||
"integrity": "sha512-HvzRFWjtcguTW7yd8NJBshuNaCa8aqNFtnswdT7f/cMd/1YKy5Zzoq4W/Oxvnx9l7aeY258uSdDfM793+eLsVg=="
|
||||
},
|
||||
"node_modules/lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.omit": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz",
|
||||
"integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg=="
|
||||
},
|
||||
"node_modules/lodash.pick": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
|
||||
"integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q=="
|
||||
},
|
||||
"node_modules/loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
|
|
@ -2373,6 +2583,15 @@
|
|||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/maath": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/maath/-/maath-0.9.0.tgz",
|
||||
"integrity": "sha512-aAR8hoUqPxlsU8VOxkS9y37jhUzdUxM017NpCuxFU1Gk+nMaZASZxymZrV8LRSHzRk/watlbfyNKu6XPUhCFrQ==",
|
||||
"peerDependencies": {
|
||||
"@types/three": ">=0.144.0",
|
||||
"three": ">=0.144.0"
|
||||
}
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
|
|
@ -2382,6 +2601,14 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/meshline": {
|
||||
"version": "3.1.6",
|
||||
"resolved": "https://registry.npmjs.org/meshline/-/meshline-3.1.6.tgz",
|
||||
"integrity": "sha512-8JZJOdaL5oz3PI/upG8JvP/5FfzYUOhrkJ8np/WKvXzl0/PZ2V9pqTvCIjSKv+w9ccg2xb+yyBhXAwt6ier3ug==",
|
||||
"peerDependencies": {
|
||||
"three": ">=0.137"
|
||||
}
|
||||
},
|
||||
"node_modules/meshoptimizer": {
|
||||
"version": "0.18.1",
|
||||
"resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz",
|
||||
|
|
@ -2412,6 +2639,11 @@
|
|||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/mmd-parser": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mmd-parser/-/mmd-parser-1.0.4.tgz",
|
||||
"integrity": "sha512-Qi0VCU46t2IwfGv5KF0+D/t9cizcDug7qnNoy9Ggk7aucp0tssV8IwTMkBlDbm+VqAf3cdQHTCARKSsuS2MYFg=="
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
|
|
@ -2447,6 +2679,14 @@
|
|||
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
|
|
@ -2456,6 +2696,21 @@
|
|||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/opentype.js": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/opentype.js/-/opentype.js-1.3.4.tgz",
|
||||
"integrity": "sha512-d2JE9RP/6uagpQAVtJoF0pJJA/fgai89Cc50Yp0EJHk+eLp6QQ7gBoblsnubRULNY132I0J1QKMJ+JTbMqz4sw==",
|
||||
"dependencies": {
|
||||
"string.prototype.codepointat": "^0.2.1",
|
||||
"tiny-inflate": "^1.0.3"
|
||||
},
|
||||
"bin": {
|
||||
"ot": "bin/ot"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/optionator": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
|
||||
|
|
@ -2537,7 +2792,6 @@
|
|||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
|
@ -2597,6 +2851,11 @@
|
|||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/potpack": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz",
|
||||
"integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ=="
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
|
|
@ -2606,6 +2865,16 @@
|
|||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prop-types": {
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
|
||||
|
|
@ -2646,6 +2915,17 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-composer": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/react-composer/-/react-composer-5.0.3.tgz",
|
||||
"integrity": "sha512-1uWd07EME6XZvMfapwZmc7NgCZqDemcvicRi3wMJzXsQLvZ3L7fTHVyPy1bZdnWXM4iPjYuNE+uJ41MLKeTtnA==",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
|
||||
|
|
@ -2666,6 +2946,20 @@
|
|||
"loose-envify": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"node_modules/react-merge-refs": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-merge-refs/-/react-merge-refs-1.1.0.tgz",
|
||||
"integrity": "sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/gregberge"
|
||||
}
|
||||
},
|
||||
"node_modules/react-reconciler": {
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.27.0.tgz",
|
||||
|
|
@ -2707,6 +3001,14 @@
|
|||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
|
||||
"integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
|
||||
},
|
||||
"node_modules/require-from-string": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-from": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||
|
|
@ -2825,7 +3127,6 @@
|
|||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
},
|
||||
|
|
@ -2837,7 +3138,6 @@
|
|||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
|
@ -2886,6 +3186,21 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/stats-gl": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/stats-gl/-/stats-gl-1.0.5.tgz",
|
||||
"integrity": "sha512-XimMxvwnf1Qf5KwebhcoA34kcX+fWEkIl0QjNkCbu4IpoyDMMsOajExn7FIq5w569k45+LhmsuRlGSrsvmGdNw=="
|
||||
},
|
||||
"node_modules/stats.js": {
|
||||
"version": "0.17.0",
|
||||
"resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz",
|
||||
"integrity": "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw=="
|
||||
},
|
||||
"node_modules/string.prototype.codepointat": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz",
|
||||
"integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg=="
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
|
|
@ -2941,6 +3256,39 @@
|
|||
"resolved": "https://registry.npmjs.org/three/-/three-0.156.1.tgz",
|
||||
"integrity": "sha512-kP7H0FK9d/k6t/XvQ9FO6i+QrePoDcNhwl0I02+wmUJRNSLCUIDMcfObnzQvxb37/0Uc9TDT0T1HgsRRrO6SYQ=="
|
||||
},
|
||||
"node_modules/three-mesh-bvh": {
|
||||
"version": "0.6.7",
|
||||
"resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.6.7.tgz",
|
||||
"integrity": "sha512-RYdjMsH+vZvjLwA+ehI4+ZqTaTehAz4iho2yfL5PdGsIHyxpB78g0iy4Emj8079m/9KBX02TzddkvPSKSruQjg==",
|
||||
"peerDependencies": {
|
||||
"three": ">= 0.151.0"
|
||||
}
|
||||
},
|
||||
"node_modules/three-stdlib": {
|
||||
"version": "2.26.0",
|
||||
"resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.26.0.tgz",
|
||||
"integrity": "sha512-zfae1OrUx7cLnH9GGW9PyIKwu7qCfEbWUk/GIT6JmEn7JZOu153mIPQxVXaJCAD6rDxb0Sr14Ab/vOIcJ7RpsA==",
|
||||
"dependencies": {
|
||||
"@types/draco3d": "^1.4.0",
|
||||
"@types/offscreencanvas": "^2019.6.4",
|
||||
"@types/webxr": "^0.5.2",
|
||||
"draco3d": "^1.4.1",
|
||||
"fflate": "^0.6.9",
|
||||
"ktx-parse": "^0.4.5",
|
||||
"mmd-parser": "^1.0.4",
|
||||
"opentype.js": "^1.3.3",
|
||||
"potpack": "^1.0.1",
|
||||
"zstddec": "^0.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"three": ">=0.128.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tiny-inflate": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
|
||||
"integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="
|
||||
},
|
||||
"node_modules/to-fast-properties": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||
|
|
@ -2962,6 +3310,33 @@
|
|||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/troika-three-text": {
|
||||
"version": "0.47.2",
|
||||
"resolved": "https://registry.npmjs.org/troika-three-text/-/troika-three-text-0.47.2.tgz",
|
||||
"integrity": "sha512-qylT0F+U7xGs+/PEf3ujBdJMYWbn0Qci0kLqI5BJG2kW1wdg4T1XSxneypnF05DxFqJhEzuaOR9S2SjiyknMng==",
|
||||
"dependencies": {
|
||||
"bidi-js": "^1.0.2",
|
||||
"troika-three-utils": "^0.47.2",
|
||||
"troika-worker-utils": "^0.47.2",
|
||||
"webgl-sdf-generator": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"three": ">=0.125.0"
|
||||
}
|
||||
},
|
||||
"node_modules/troika-three-utils": {
|
||||
"version": "0.47.2",
|
||||
"resolved": "https://registry.npmjs.org/troika-three-utils/-/troika-three-utils-0.47.2.tgz",
|
||||
"integrity": "sha512-/28plhCxfKtH7MSxEGx8e3b/OXU5A0xlwl+Sbdp0H8FXUHKZDoksduEKmjQayXYtxAyuUiCRunYIv/8Vi7aiyg==",
|
||||
"peerDependencies": {
|
||||
"three": ">=0.125.0"
|
||||
}
|
||||
},
|
||||
"node_modules/troika-worker-utils": {
|
||||
"version": "0.47.2",
|
||||
"resolved": "https://registry.npmjs.org/troika-worker-utils/-/troika-worker-utils-0.47.2.tgz",
|
||||
"integrity": "sha512-mzss4MeyzUkYBppn4x5cdAqrhBHFEuVmMMgLMTyFV23x6GvQMyo+/R5E5Lsbrt7WSt5RfvewjcwD1DChRTA9lA=="
|
||||
},
|
||||
"node_modules/ts-api-utils": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
|
||||
|
|
@ -3050,6 +3425,14 @@
|
|||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/utility-types": {
|
||||
"version": "3.10.0",
|
||||
"resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz",
|
||||
"integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "4.4.9",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz",
|
||||
|
|
@ -3105,11 +3488,20 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/webgl-constants": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/webgl-constants/-/webgl-constants-1.1.1.tgz",
|
||||
"integrity": "sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg=="
|
||||
},
|
||||
"node_modules/webgl-sdf-generator": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz",
|
||||
"integrity": "sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA=="
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
|
|
@ -3172,6 +3564,11 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/zstddec": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.0.2.tgz",
|
||||
"integrity": "sha512-DCo0oxvcvOTGP/f5FA6tz2Z6wF+FIcEApSTu0zV5sQgn9hoT5lZ9YRAKUraxt9oP7l4e8TnNdi8IZTCX6WCkwA=="
|
||||
},
|
||||
"node_modules/zustand": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-three/drei": "^9.84.1",
|
||||
"@react-three/fiber": "^8.14.1",
|
||||
"@types/three": "^0.156.0",
|
||||
"react": "^18.2.0",
|
||||
|
|
|
|||
BIN
public/models/table.glb
Normal file
BIN
public/textures/card-0.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
public/textures/card-1.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/textures/card-10.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
public/textures/card-11.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/textures/card-12.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
public/textures/card-2.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/textures/card-3.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
public/textures/card-4.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
public/textures/card-5.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
public/textures/card-6.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
public/textures/card-7.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/textures/card-8.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
public/textures/card-9.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
public/textures/card-back.png
Normal file
|
After Width: | Height: | Size: 185 KiB |
BIN
public/textures/card-minus1.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/textures/card-minus2.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
67
src/App.tsx
|
|
@ -1,11 +1,15 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import { socket } from "./socket";
|
||||
import ThreeScene from "./components/ThreeScene";
|
||||
import { ConnectionState } from "./components/ConnectionState";
|
||||
import { ConnectionManager } from "./components/ConnectionManager";
|
||||
import { JoinSession } from "./components/JoinSession";
|
||||
import { Events } from "./components/Events";
|
||||
import { Game } from "./types/gameTypes";
|
||||
import Action from "./components/Action";
|
||||
import CardStack from "./components/CardStack";
|
||||
import DepositCards from "./components/DepositCards";
|
||||
import CardCache from "./components/CardCache";
|
||||
|
||||
export default function App() {
|
||||
const [isConnected, setIsConnected] = useState(socket.connected);
|
||||
|
|
@ -16,11 +20,7 @@ export default function App() {
|
|||
const [messageDispaly, setMessageDisplay] = useState<string>("");
|
||||
|
||||
const showStartGameButton = session !== "" && clientsInRoom >= 2;
|
||||
|
||||
const remainingInCardStack = gameData?.cardStack?.cards?.length || 0;
|
||||
const remainingInDiscardPile = gameData?.discardPile?.length || 0;
|
||||
const topCardInDiscardPile =
|
||||
gameData?.discardPile?.[remainingInDiscardPile - 1];
|
||||
const showNextGameButton = gameData?.phase === "new round";
|
||||
|
||||
const playersData = extractMyData(gameData);
|
||||
|
||||
|
|
@ -28,21 +28,15 @@ export default function App() {
|
|||
socket.emit("new-game", { sessionId: session });
|
||||
}
|
||||
|
||||
function nextGame() {
|
||||
socket.emit("next-round", { sessionId: session });
|
||||
}
|
||||
|
||||
function clickCard(cardPosition: number) {
|
||||
console.log("Clicked card", cardPosition);
|
||||
socket.emit("click-card", cardPosition);
|
||||
}
|
||||
|
||||
function drawFromCardStack() {
|
||||
console.log("Draw card");
|
||||
socket.emit("draw-from-card-stack", { sessionId: session });
|
||||
}
|
||||
|
||||
function clickDiscardPile() {
|
||||
console.log("Clicked discard pile");
|
||||
socket.emit("click-discard-pile", { sessionId: session });
|
||||
}
|
||||
|
||||
function extractMyData(gameData: Game | null) {
|
||||
if (!gameData) return undefined;
|
||||
return gameData.players.find((player) => player.socketId === socket.id);
|
||||
|
|
@ -78,8 +72,9 @@ export default function App() {
|
|||
setClientsInRoom(clients);
|
||||
}
|
||||
|
||||
function onMessageEvent(value: string) {
|
||||
setMessageEvents((previous) => [...previous, value]);
|
||||
function onMessageEvent(message: string) {
|
||||
setTempMessage(message);
|
||||
setMessageEvents((previous) => [...previous, message]);
|
||||
}
|
||||
|
||||
function onGameUpdate(gameData: Game) {
|
||||
|
|
@ -103,20 +98,23 @@ export default function App() {
|
|||
|
||||
return (
|
||||
<div className="App">
|
||||
<ThreeScene gameData={gameData} />
|
||||
<ConnectionState
|
||||
isConnected={isConnected}
|
||||
session={session}
|
||||
clientsInRoom={clientsInRoom}
|
||||
/>
|
||||
<Events events={messageEvents} />
|
||||
<ConnectionManager />
|
||||
<JoinSession session={session} setSession={setSession} />
|
||||
{showStartGameButton && <button onClick={startGame}>Start Game</button>}
|
||||
{showNextGameButton && <button onClick={nextGame}>Next Game</button>}
|
||||
{gameData &&
|
||||
gameData.players.map((playerData, index) => (
|
||||
<div key={index}>
|
||||
<p>Player ID: {playerData.id}</p>
|
||||
<p>Player Name: {playerData.name}</p>
|
||||
<p>Player Round Points: {playerData.roundPoints}</p>
|
||||
<p>Player Total Points: {playerData.totalPoints}</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
@ -155,35 +153,18 @@ export default function App() {
|
|||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
<CardStack gameData={gameData} playerData={playerData} />
|
||||
<DepositCards gameData={gameData} playerData={playerData} />
|
||||
<CardCache playersData={playersData} />
|
||||
<br />
|
||||
</div>
|
||||
))}
|
||||
<br />
|
||||
{gameData?.cardStack && remainingInCardStack > 0 && (
|
||||
<div>
|
||||
<Action data={playersData} action={drawFromCardStack}>
|
||||
Draw
|
||||
</Action>
|
||||
<span style={{ color: "grey", marginLeft: "5px" }}>
|
||||
{remainingInCardStack} in Card Set
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{gameData?.discardPile && remainingInDiscardPile > 0 && (
|
||||
<div>
|
||||
<Action data={playersData} action={clickDiscardPile}>
|
||||
{topCardInDiscardPile?.value}
|
||||
</Action>
|
||||
<span style={{ color: "grey", marginLeft: "5px" }}>
|
||||
{remainingInDiscardPile} Discard Pile
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{playersData?.cardCache && (
|
||||
<div>
|
||||
<p>Card Cache: {playersData.cardCache.value}</p>
|
||||
</div>
|
||||
)}
|
||||
<br />
|
||||
|
||||
{messageDispaly && messageDispaly !== "" && <p>{messageDispaly}</p>}
|
||||
<Events events={messageEvents} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
21
src/components/CardCache.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { FC } from "react";
|
||||
|
||||
import { Player } from "../types/gameTypes";
|
||||
|
||||
type CardCacheProps = {
|
||||
playersData: Player | undefined;
|
||||
};
|
||||
|
||||
const CardCache: FC<CardCacheProps> = ({ playersData }) => {
|
||||
if (!playersData?.cardCache) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>Card Cache: {playersData.cardCache.value}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CardCache;
|
||||
37
src/components/CardStack.tsx
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { FC } from "react";
|
||||
import { socket } from "../socket";
|
||||
|
||||
import Action from "./Action";
|
||||
import Display from "./Display";
|
||||
import { Game, Player } from "../types/gameTypes";
|
||||
|
||||
type CardStackProps = {
|
||||
gameData: Game | null;
|
||||
playerData: Player;
|
||||
};
|
||||
|
||||
const CardStack: FC<CardStackProps> = ({ gameData, playerData }) => {
|
||||
const remainingInCardStack = gameData?.cardStack?.cards?.length || 0;
|
||||
|
||||
function drawFromCardStack() {
|
||||
console.log("Draw card");
|
||||
socket.emit("draw-from-card-stack", { sessionId: gameData?.sessionId });
|
||||
}
|
||||
|
||||
if (!gameData?.cardStack || remainingInCardStack <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Display data={playerData}>
|
||||
<Action data={playerData} action={drawFromCardStack}>
|
||||
Draw
|
||||
</Action>
|
||||
<span style={{ color: "grey", marginLeft: "5px" }}>
|
||||
{remainingInCardStack} in Card Set
|
||||
</span>
|
||||
</Display>
|
||||
);
|
||||
};
|
||||
|
||||
export default CardStack;
|
||||
40
src/components/DepositCards.tsx
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import { FC } from "react";
|
||||
import { socket } from "../socket";
|
||||
|
||||
import Action from "./Action";
|
||||
import Display from "./Display";
|
||||
import { Game, Player } from "../types/gameTypes";
|
||||
|
||||
type DepositCardsProps = {
|
||||
gameData: Game | null;
|
||||
playerData: Player;
|
||||
};
|
||||
|
||||
const DepositCards: FC<DepositCardsProps> = ({ gameData, playerData }) => {
|
||||
const remainingInCardStack = gameData?.cardStack?.cards?.length || 0;
|
||||
const remainingInDiscardPile = gameData?.discardPile?.length || 0;
|
||||
const topCardInDiscardPile =
|
||||
gameData?.discardPile?.[remainingInDiscardPile - 1];
|
||||
|
||||
function clickDiscardPile() {
|
||||
console.log("Clicked discard pile");
|
||||
socket.emit("click-discard-pile", { sessionId: gameData?.sessionId });
|
||||
}
|
||||
|
||||
if (!gameData?.discardPile || remainingInCardStack <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Display data={playerData}>
|
||||
<Action data={playerData} action={clickDiscardPile}>
|
||||
{topCardInDiscardPile?.value}
|
||||
</Action>
|
||||
<span style={{ color: "grey", marginLeft: "5px" }}>
|
||||
{remainingInDiscardPile} Discard Pile
|
||||
</span>
|
||||
</Display>
|
||||
);
|
||||
};
|
||||
|
||||
export default DepositCards;
|
||||
26
src/components/Display.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { FC, ReactNode } from "react";
|
||||
import { socket } from "../socket";
|
||||
import { Player } from "../types/gameTypes";
|
||||
|
||||
type DisplayProps = {
|
||||
data: Player | undefined;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* This component will display its children only if they are the owner.
|
||||
* @param param0
|
||||
* @returns
|
||||
*/
|
||||
|
||||
const Display: FC<DisplayProps> = ({ data, children }) => {
|
||||
const userSocketId = socket.id;
|
||||
|
||||
if (!data || userSocketId !== data.socketId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <div>{children}</div>;
|
||||
};
|
||||
|
||||
export default Display;
|
||||
198
src/components/ThreeScene.tsx
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
import { useRef, useEffect, FC } from "react";
|
||||
import {
|
||||
Scene,
|
||||
PerspectiveCamera,
|
||||
WebGLRenderer,
|
||||
Vector3,
|
||||
DirectionalLight,
|
||||
DirectionalLightHelper,
|
||||
AmbientLight,
|
||||
Object3D,
|
||||
Mesh,
|
||||
GridHelper,
|
||||
AxesHelper,
|
||||
Material,
|
||||
} from "three";
|
||||
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
||||
import { useGLTF } from "@react-three/drei";
|
||||
import { createCube } from "../objects/cube";
|
||||
import { createPlayerCards, createCard } from "../objects/cards";
|
||||
import { Game, Player } from "../types/gameTypes";
|
||||
import { socket } from "../socket";
|
||||
|
||||
type ThreeSceneProps = {
|
||||
gameData: Game | null;
|
||||
};
|
||||
|
||||
const ThreeScene: FC<ThreeSceneProps> = ({ gameData }) => {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
const cardsRef = useRef<Mesh[]>([]);
|
||||
const tableModel = useGLTF("/models/table.glb");
|
||||
const heightProportion = 1.25;
|
||||
|
||||
function extractCurrentPlayer(gameData: Game | null): Player | undefined {
|
||||
if (!gameData) return undefined;
|
||||
return gameData.players.find((player) => player.socketId === socket.id);
|
||||
}
|
||||
|
||||
function disposeMesh(mesh: THREE.Mesh) {
|
||||
if (mesh.material instanceof Material) {
|
||||
mesh.material.dispose();
|
||||
} else if (Array.isArray(mesh.material)) {
|
||||
for (const material of mesh.material) {
|
||||
material.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
mesh.geometry.dispose();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const container = containerRef.current;
|
||||
const scene = new Scene();
|
||||
const camera = new PerspectiveCamera(
|
||||
75,
|
||||
window.innerWidth / (window.innerHeight / heightProportion),
|
||||
0.1,
|
||||
1000
|
||||
);
|
||||
|
||||
const renderer = new WebGLRenderer();
|
||||
|
||||
renderer.setSize(window.innerWidth, window.innerHeight / heightProportion);
|
||||
container && container.appendChild(renderer.domElement);
|
||||
|
||||
// Objects
|
||||
const cubeCenter = createCube(new Vector3(1, 1, 1), 0x00ff00);
|
||||
cubeCenter.position.set(0, 20, 0);
|
||||
|
||||
const cubeTL = createCube(new Vector3(1, 1, 1), 0x00ff00);
|
||||
cubeTL.position.set(-10, 20, -15);
|
||||
|
||||
const cubeTR = createCube(new Vector3(1, 1, 1), 0x00ff00);
|
||||
cubeTR.position.set(10, 20, -15);
|
||||
|
||||
const cubeBL = createCube(new Vector3(1, 1, 1), 0x00ff00);
|
||||
cubeBL.position.set(-10, 20, 15);
|
||||
|
||||
const cubeBR = createCube(new Vector3(1, 1, 1), 0x00ff00);
|
||||
cubeBR.position.set(10, 20, 15);
|
||||
|
||||
scene.add(cubeCenter, cubeBL, cubeBR, cubeTL, cubeTR);
|
||||
|
||||
// Cards
|
||||
/*const initialCards: Card[] = [];
|
||||
for (let i = 1; i < 13; i++) {
|
||||
initialCards.push({ id: i, name: `${i} Card`, value: i as CardValue });
|
||||
}
|
||||
|
||||
const playerCards = createPlayerCards(initialCards, new Vector3(0, 20, 0));
|
||||
|
||||
scene.add(...playerCards);*/
|
||||
|
||||
const currentPlayer = extractCurrentPlayer(gameData);
|
||||
if (currentPlayer && !cardsRef.current.length) {
|
||||
cardsRef.current = createPlayerCards(
|
||||
currentPlayer.cards,
|
||||
new Vector3(0, 20, 0)
|
||||
);
|
||||
scene.add(...cardsRef.current);
|
||||
}
|
||||
|
||||
// Camera
|
||||
camera.position.set(0, 45, 10);
|
||||
camera.lookAt(0, 0, 0);
|
||||
|
||||
// Orbit Controls
|
||||
const orbit = new OrbitControls(camera, renderer.domElement);
|
||||
orbit.update();
|
||||
|
||||
// Lights
|
||||
const directionalLight = new DirectionalLight(0xffffff, 0.8);
|
||||
directionalLight.position.set(0, 50, 20);
|
||||
scene.add(directionalLight);
|
||||
|
||||
directionalLight.castShadow = true;
|
||||
directionalLight.shadow.mapSize.width = 1024;
|
||||
directionalLight.shadow.mapSize.height = 1024;
|
||||
|
||||
const ambientLight = new AmbientLight(0xa3a3a3, 0.3);
|
||||
scene.add(ambientLight);
|
||||
|
||||
// Import models
|
||||
const table = tableModel.scene;
|
||||
scene.add(table);
|
||||
// table.rotateY(Math.PI / 2);
|
||||
table.scale.set(2, 2, 2);
|
||||
table.position.set(0, 1.8, 0);
|
||||
|
||||
table.traverse(function (node: Object3D) {
|
||||
if (node instanceof Mesh) {
|
||||
// node.castShadow = true;
|
||||
node.receiveShadow = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Helpers
|
||||
const gridHelper = new GridHelper(100, 100);
|
||||
scene.add(gridHelper);
|
||||
|
||||
const axesHelper = new AxesHelper(5);
|
||||
scene.add(axesHelper);
|
||||
|
||||
const directionalLightHelper = new DirectionalLightHelper(
|
||||
directionalLight,
|
||||
5
|
||||
);
|
||||
scene.add(directionalLightHelper);
|
||||
|
||||
// Animation
|
||||
const animate = () => {
|
||||
requestAnimationFrame(animate);
|
||||
// cube.rotation.x += 0.01;
|
||||
// cube.rotation.y += 0.01;
|
||||
const currentPlayer = extractCurrentPlayer(gameData);
|
||||
if (currentPlayer) {
|
||||
if (cardsRef.current.length === 0) {
|
||||
cardsRef.current = createPlayerCards(
|
||||
currentPlayer.cards,
|
||||
new Vector3(0, 20, 0)
|
||||
);
|
||||
scene.add(...cardsRef.current);
|
||||
} else {
|
||||
cardsRef.current.forEach((card, index) => {
|
||||
if (card.name !== currentPlayer.cards[index]?.name) {
|
||||
disposeMesh(card);
|
||||
scene.remove(card);
|
||||
cardsRef.current[index] = createCard(
|
||||
currentPlayer.cards[index],
|
||||
card.position
|
||||
);
|
||||
scene.add(cardsRef.current[index]);
|
||||
}
|
||||
});
|
||||
}
|
||||
//const cards = createPlayerCards(currentPlayer.cards);
|
||||
//scene.add(...cards);
|
||||
}
|
||||
|
||||
renderer.render(scene, camera);
|
||||
};
|
||||
|
||||
console.log("Animate");
|
||||
animate();
|
||||
|
||||
return () => {
|
||||
// Clean up on unmount
|
||||
renderer.dispose();
|
||||
// scene.dispose();
|
||||
// material.dispose();
|
||||
// geometry.dispose();
|
||||
container && container.removeChild(renderer.domElement);
|
||||
};
|
||||
}, [gameData]);
|
||||
|
||||
return <div ref={containerRef}></div>;
|
||||
};
|
||||
|
||||
export default ThreeScene;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
margin: 0;
|
||||
}
|
||||
119
src/objects/cards.ts
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
import {
|
||||
BoxGeometry,
|
||||
TextureLoader,
|
||||
MeshBasicMaterial,
|
||||
SRGBColorSpace,
|
||||
Vector3,
|
||||
Mesh,
|
||||
Object3DEventMap,
|
||||
} from "three";
|
||||
|
||||
import { Card } from "../types/gameTypes";
|
||||
|
||||
const textureLoader = new TextureLoader();
|
||||
const cardSize = 5;
|
||||
const cardGeometry = new BoxGeometry(
|
||||
cardSize * 0.4,
|
||||
cardSize * 0.001,
|
||||
cardSize * 0.6
|
||||
);
|
||||
|
||||
const getCardTexture = (value: number | string) => {
|
||||
let cardTexture;
|
||||
switch (value) {
|
||||
case -2:
|
||||
cardTexture = textureLoader.load("/textures/card-minus2.png");
|
||||
break;
|
||||
case -1:
|
||||
cardTexture = textureLoader.load("/textures/card-minus1.png");
|
||||
break;
|
||||
case 0:
|
||||
cardTexture = textureLoader.load("/textures/card-0.png");
|
||||
break;
|
||||
case 1:
|
||||
cardTexture = textureLoader.load("/textures/card-1.png");
|
||||
break;
|
||||
case 2:
|
||||
cardTexture = textureLoader.load("/textures/card-2.png");
|
||||
break;
|
||||
case 3:
|
||||
cardTexture = textureLoader.load("/textures/card-3.png");
|
||||
break;
|
||||
case 4:
|
||||
cardTexture = textureLoader.load("/textures/card-4.png");
|
||||
break;
|
||||
case 5:
|
||||
cardTexture = textureLoader.load("/textures/card-5.png");
|
||||
break;
|
||||
case 6:
|
||||
cardTexture = textureLoader.load("/textures/card-6.png");
|
||||
break;
|
||||
case 7:
|
||||
cardTexture = textureLoader.load("/textures/card-7.png");
|
||||
break;
|
||||
case 8:
|
||||
cardTexture = textureLoader.load("/textures/card-8.png");
|
||||
break;
|
||||
case 9:
|
||||
cardTexture = textureLoader.load("/textures/card-9.png");
|
||||
break;
|
||||
case 10:
|
||||
cardTexture = textureLoader.load("/textures/card-10.png");
|
||||
break;
|
||||
case 11:
|
||||
cardTexture = textureLoader.load("/textures/card-11.png");
|
||||
break;
|
||||
case 12:
|
||||
cardTexture = textureLoader.load("/textures/card-12.png");
|
||||
break;
|
||||
case "X":
|
||||
cardTexture = textureLoader.load("/textures/card-back.png");
|
||||
break;
|
||||
default:
|
||||
cardTexture = textureLoader.load("/textures/card-back.png");
|
||||
break;
|
||||
}
|
||||
cardTexture.colorSpace = SRGBColorSpace;
|
||||
return cardTexture;
|
||||
};
|
||||
|
||||
export const createCard = (cardData: Card, position: Vector3) => {
|
||||
const cardMaterial = [
|
||||
new MeshBasicMaterial(),
|
||||
new MeshBasicMaterial(),
|
||||
new MeshBasicMaterial({ map: getCardTexture("X") }), // X = backside
|
||||
new MeshBasicMaterial({ map: getCardTexture(cardData.value) }),
|
||||
new MeshBasicMaterial(),
|
||||
new MeshBasicMaterial(),
|
||||
];
|
||||
const card = new Mesh(cardGeometry, cardMaterial);
|
||||
card.name = cardData.name;
|
||||
card.position.copy(position);
|
||||
return card;
|
||||
};
|
||||
|
||||
export const createPlayerCards = (
|
||||
cards: Card[],
|
||||
positionReference: Vector3
|
||||
) => {
|
||||
const playerCards: Mesh<
|
||||
BoxGeometry,
|
||||
MeshBasicMaterial[],
|
||||
Object3DEventMap
|
||||
>[] = [];
|
||||
cards.forEach((card, index) => {
|
||||
const cardPositionX = positionReference.x + (index % 4) * 4 - 6;
|
||||
const cardPositionY = positionReference.y;
|
||||
const cardPositionZ =
|
||||
positionReference.z + (Math.ceil((index + 1) / 4) - 1) * 4 - 8;
|
||||
|
||||
const cardPosition = new Vector3(
|
||||
cardPositionX,
|
||||
cardPositionY,
|
||||
cardPositionZ
|
||||
);
|
||||
const playerCard = createCard(card, cardPosition);
|
||||
playerCards.push(playerCard);
|
||||
});
|
||||
return playerCards;
|
||||
};
|
||||
14
src/objects/cube.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import {
|
||||
Vector3,
|
||||
BoxGeometry,
|
||||
Mesh,
|
||||
MeshBasicMaterial,
|
||||
ColorRepresentation,
|
||||
} from "three";
|
||||
|
||||
export const createCube = (size: Vector3, color: ColorRepresentation) => {
|
||||
const geometry = new BoxGeometry(size.x, size.y, size.z);
|
||||
const material = new MeshBasicMaterial({ color });
|
||||
const cube = new Mesh(geometry, material);
|
||||
return cube;
|
||||
};
|
||||
0
src/objects/gameObjects.ts
Normal file
|
|
@ -6,9 +6,13 @@ export type Player = {
|
|||
knownCardPositions: boolean[];
|
||||
playersTurn: boolean;
|
||||
cardCache: Card | null;
|
||||
tookDispiledCard: boolean;
|
||||
roundPoints: number;
|
||||
totalPoints: number;
|
||||
closedRound: boolean;
|
||||
};
|
||||
|
||||
type CardValue =
|
||||
export type CardValue =
|
||||
| -2
|
||||
| -1
|
||||
| 0
|
||||
|
|
@ -25,19 +29,11 @@ type CardValue =
|
|||
| 11
|
||||
| 12
|
||||
| "X";
|
||||
type CardColor =
|
||||
| "darkblue"
|
||||
| "lightblue"
|
||||
| "green"
|
||||
| "yellow"
|
||||
| "red"
|
||||
| "black";
|
||||
|
||||
export type Card = {
|
||||
id: number;
|
||||
name: string;
|
||||
value: CardValue;
|
||||
color: CardColor;
|
||||
};
|
||||
|
||||
export type CardStack = {
|
||||
|
|
|
|||