commit a105e283332abb5a7610222e7e2ce725000a3599 Author: Michael Mainguy Date: Fri Feb 14 14:54:16 2025 -0600 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..65d2f2c --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +/.env diff --git a/index.html b/index.html new file mode 100644 index 0000000..2fe9e75 --- /dev/null +++ b/index.html @@ -0,0 +1,25 @@ + + + + + + + Game + + + + +
+
Loading...
+ +
+ + + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..a86e91a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1227 @@ +{ + "name": "space-game", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "space-game", + "version": "0.0.1", + "dependencies": { + "@babylonjs/core": "7.13.1", + "@babylonjs/gui": "^7.13.1", + "@babylonjs/havok": "1.3.5", + "@babylonjs/inspector": "^7.13.1", + "@babylonjs/loaders": "^7.13.1", + "@babylonjs/materials": "^7.13.1", + "@babylonjs/procedural-textures": "^7.13.1", + "@babylonjs/serializers": "^7.13.1", + "openai": "4.52.3" + }, + "devDependencies": { + "typescript": "^5.4.5", + "vite": "^5.2.13" + } + }, + "node_modules/@babylonjs/core": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-7.13.1.tgz", + "integrity": "sha512-limlsRIhRBH9xsuUNsy9xAyi0jhfQxfvhlMzMjFK3Ugq4c7joYpoZMkQU038esOQ3aq3q8VPv1+CshE3NASEMQ==" + }, + "node_modules/@babylonjs/gui": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@babylonjs/gui/-/gui-7.13.1.tgz", + "integrity": "sha512-FW2QOqpzoJI2q/hFKOa7O7xnj6oKzHWmTGHVhqjg7jzZy//bMZ5AbxNdMpQgDa+QoENpd7r+yx1O4kc4Lw1UaQ==", + "peerDependencies": { + "@babylonjs/core": "^7.0.0" + } + }, + "node_modules/@babylonjs/gui-editor": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@babylonjs/gui-editor/-/gui-editor-7.13.1.tgz", + "integrity": "sha512-1piYccMR4FRqMXVu/OMqCgc6Z5uRpt49u6yUYyRY627aZkarBM7oh310A6sgTkfuk77c9ZNoIgtgbq5P/dB48Q==", + "peer": true, + "peerDependencies": { + "@babylonjs/core": "^7.0.0", + "@babylonjs/gui": "^7.0.0", + "@types/react": ">=16.7.3", + "@types/react-dom": ">=16.0.9" + } + }, + "node_modules/@babylonjs/havok": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@babylonjs/havok/-/havok-1.3.5.tgz", + "integrity": "sha512-1k6YoqfWySKn5kaYd1hKHYpYQqk9sx/QkTaizoGY+ConP3yDFQoB0XNCFttHauQOIdcJ8fpc8OGZJbl28XWcdA==", + "dependencies": { + "@types/emscripten": "^1.39.6" + } + }, + "node_modules/@babylonjs/inspector": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@babylonjs/inspector/-/inspector-7.13.1.tgz", + "integrity": "sha512-BM2ZQu15ESbWFQPwU/iqCx1P/KiJX9qX9dCVU/+5bbLqzemja5aDajLMnM+vb4uimAtbokkUdFqNckGnZVo7VQ==", + "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.1.0", + "@fortawesome/free-regular-svg-icons": "^6.0.0", + "@fortawesome/free-solid-svg-icons": "^6.0.0" + }, + "peerDependencies": { + "@babylonjs/core": "^7.0.0", + "@babylonjs/gui": "^7.0.0", + "@babylonjs/gui-editor": "^7.0.0", + "@babylonjs/loaders": "^7.0.0", + "@babylonjs/materials": "^7.0.0", + "@babylonjs/serializers": "^7.0.0", + "@types/react": ">=16.7.3", + "@types/react-dom": ">=16.0.9" + } + }, + "node_modules/@babylonjs/loaders": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-7.13.1.tgz", + "integrity": "sha512-17MCwYpMM4EF69wzsclIvs7Ci84lYdkcH2NSM3hD3phl8k373yNKVvBNrs68p9yZUCFbXIVEH1tl5QQxr2T37g==", + "peerDependencies": { + "@babylonjs/core": "^7.0.0", + "babylonjs-gltf2interface": "^7.0.0" + } + }, + "node_modules/@babylonjs/materials": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@babylonjs/materials/-/materials-7.13.1.tgz", + "integrity": "sha512-CkjHyhsMglr9Aqf5NNsqwCgVPdMxnu1yRD4I6CGDXAp814ghqb5/JwkoL4lgelSYinsSh4HXpFr4Jgays5W2hw==", + "peerDependencies": { + "@babylonjs/core": "^7.0.0" + } + }, + "node_modules/@babylonjs/procedural-textures": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@babylonjs/procedural-textures/-/procedural-textures-7.13.1.tgz", + "integrity": "sha512-FzPtNsEglAi/0rqSEGBsnCAMn6Ggnf0phYSTOL7iHec+Rhx+1DVwN5PvUBYAJT5Sy5PIq2mPZI1uhq1A5QySxA==", + "peerDependencies": { + "@babylonjs/core": "^7.0.0" + } + }, + "node_modules/@babylonjs/serializers": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@babylonjs/serializers/-/serializers-7.13.1.tgz", + "integrity": "sha512-ct1MTjRZaj4EEyMhDiHJkhSSKJRGValGPLNv3UOYh7EYc4XN0HbEz4wuMkwlgENFP7Hz5okWVBQB9yQWObR3Sg==", + "peerDependencies": { + "@babylonjs/core": "^7.0.0", + "babylonjs-gltf2interface": "^7.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz", + "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz", + "integrity": "sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-regular-svg-icons": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.2.tgz", + "integrity": "sha512-iabw/f5f8Uy2nTRtJ13XZTS1O5+t+anvlamJ3zJGLEVE2pKsAWhPv2lq01uQlfgCX7VaveT3EVs515cCN9jRbw==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz", + "integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/emscripten": { + "version": "1.39.13", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.13.tgz", + "integrity": "sha512-cFq+fO/isvhvmuP/+Sl4K4jtU6E23DoivtbO4r50e3odaxAiVdbfSYRDdJ4gCdxx+3aRjhphS5ZMwIH4hFy/Cw==" + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "peer": true + }, + "node_modules/@types/react": { + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "peer": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/babylonjs-gltf2interface": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-7.13.1.tgz", + "integrity": "sha512-kgMZrek1Gul22+Igy43pYdofg89odPv5uxYrjzryVvMxmzPI7NwgxickXT3tM/SGoyF0AoXlPrKLCK5zHT0/eg==", + "peer": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "peer": true + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==" + }, + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "dependencies": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + }, + "engines": { + "node": ">= 12.20" + } + }, + "node_modules/formdata-node/node_modules/web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/openai": { + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.52.3.tgz", + "integrity": "sha512-IyQLYKGYoEEkUCEm2frPzwHDJ3Ym663KtivnY6pWCzuoi6/HgSIMMxpcuTRS81GH6tiULPYGmTxIvzXdmPIWOw==", + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7", + "web-streams-polyfill": "^3.2.1" + }, + "bin": { + "openai": "bin/cli" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true + }, + "node_modules/postcss": { + "version": "8.4.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/typescript": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/vite": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.3.tgz", + "integrity": "sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.39", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..e35d4a8 --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "space-game", + "private": false, + "version": "0.0.1", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "havok": "cp ./node_modules/@babylonjs/havok/lib/esm/HavokPhysics.wasm ./node_modules/.vite/deps", + "speech": "tsc && node ./dist/server/voices.js" + }, + "dependencies": { + "@babylonjs/core": "7.13.1", + "@babylonjs/gui": "^7.13.1", + "@babylonjs/havok": "1.3.5", + "@babylonjs/inspector": "^7.13.1", + "@babylonjs/loaders": "^7.13.1", + "@babylonjs/materials": "^7.13.1", + "@babylonjs/serializers": "^7.13.1", + "@babylonjs/procedural-textures": "^7.13.1", + "openai": "4.52.3" + }, + "devDependencies": { + "typescript": "^5.4.5", + "vite": "^5.2.13" + } +} diff --git a/public/8192.webp b/public/8192.webp new file mode 100644 index 0000000..1d30ca6 Binary files /dev/null and b/public/8192.webp differ diff --git a/public/arrow.stl b/public/arrow.stl new file mode 100644 index 0000000..1e1b242 Binary files /dev/null and b/public/arrow.stl differ diff --git a/public/asteroid.glb b/public/asteroid.glb new file mode 100644 index 0000000..1c81260 Binary files /dev/null and b/public/asteroid.glb differ diff --git a/public/background.mp3 b/public/background.mp3 new file mode 100644 index 0000000..01078ca Binary files /dev/null and b/public/background.mp3 differ diff --git a/public/cockpit.glb b/public/cockpit.glb new file mode 100644 index 0000000..105591b Binary files /dev/null and b/public/cockpit.glb differ diff --git a/public/cockpit2.glb b/public/cockpit2.glb new file mode 100644 index 0000000..faa21e3 Binary files /dev/null and b/public/cockpit2.glb differ diff --git a/public/cockpit3.glb b/public/cockpit3.glb new file mode 100644 index 0000000..9083efb Binary files /dev/null and b/public/cockpit3.glb differ diff --git a/public/flare.png b/public/flare.png new file mode 100644 index 0000000..462acb9 Binary files /dev/null and b/public/flare.png differ diff --git a/public/ship1.stl b/public/ship1.stl new file mode 100644 index 0000000..c23cb96 Binary files /dev/null and b/public/ship1.stl differ diff --git a/public/shot.mp3 b/public/shot.mp3 new file mode 100644 index 0000000..ff2a012 Binary files /dev/null and b/public/shot.mp3 differ diff --git a/public/styles.css b/public/styles.css new file mode 100644 index 0000000..c2c988f --- /dev/null +++ b/public/styles.css @@ -0,0 +1,55 @@ +body { + width: 100vw; + height: 100vh; + margin: 0; + padding: 0; + background-color: #000; + aspect-ratio: auto; + font-family: Roboto, sans-serif; + font-size: large; +} +#startGame { + position: absolute; + display: block; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + padding: 48px; + border-radius: 12px; + background-color: #000; + color: #fff; + z-index: 1000; +} +#music { + position: absolute; + display: block; + top: 75%; + left: 50%; + width: 50%; + transform: translate(-50%, -50%); + padding: 48px; + border-radius: 12px; + background-color: #000; + color: #fff; + z-index: 1000; +} +#startButton { + background-color: #000; + color: #fff; + border: 2px solid #fff; + border-radius: 5px; + cursor: pointer; + font-size: xxx-large; + display: none; +} +#startButton.ready { + display: block; + background-color: red; +} +#gameCanvas { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + background: transparent; +} diff --git a/public/systems/explosion.json b/public/systems/explosion.json new file mode 100644 index 0000000..192a133 --- /dev/null +++ b/public/systems/explosion.json @@ -0,0 +1,1357 @@ +{ + "systems": + [ + { + "name": "flash", + "id": "flash", + "capacity": 40, + "emitter": + [ + 0, + 0, + 0 + ], + "particleEmitterType": + { + "type": "SphereParticleEmitter", + "radius": 0.1, + "directionRandomizer": 0.5 + }, + "textureName": "explosion/FlashParticle.png", + "invertY": true, + "animations": [], + "beginAnimationOnStart": false, + "beginAnimationFrom": 0, + "beginAnimationTo": 60, + "beginAnimationLoop": false, + "startDelay": 0, + "renderingGroupId": 2, + "isBillboardBased": true, + "billboardMode": 7, + "minAngularSpeed": 0, + "maxAngularSpeed": 0, + "minSize": 0.1, + "maxSize": 0.1, + "minScaleX": 10, + "maxScaleX": 20, + "minScaleY": 70, + "maxScaleY": 100, + "minEmitPower": 0, + "maxEmitPower": 0, + "minLifeTime": 0.2, + "maxLifeTime": 0.4, + "emitRate": 400, + "gravity": + [ + 0, + 0, + 0 + ], + "noiseStrength": + [ + 10, + 10, + 10 + ], + "color1": + [ + 1, + 1, + 1, + 1 + ], + "color2": + [ + 1, + 1, + 1, + 1 + ], + "colorDead": + [ + 1, + 1, + 1, + 0 + ], + "updateSpeed": 0.016666666666666666, + "targetStopDuration": 0.2, + "blendMode": 2, + "preWarmCycles": 0, + "preWarmStepOffset": 1, + "minInitialRotation": -0.78539816, + "maxInitialRotation": 0.78539816, + "startSpriteCellID": 0, + "endSpriteCellID": 0, + "spriteCellChangeSpeed": 1, + "spriteCellWidth": 0, + "spriteCellHeight": 0, + "spriteRandomStartCell": false, + "isAnimationSheetEnabled": false, + "colorGradients": + [ + { + "gradient": 0, + "color1": + [ + 1, + 0.896, + 0, + 1 + ] + }, + { + "gradient": 0.4, + "color1": + [ + 0.7547, + 0.1219, + 0.0391, + 1 + ] + }, + { + "gradient": 0.8, + "color1": + [ + 0.3679, + 0.0721, + 0.0295, + 0 + ] + } + ], + "textureMask": + [ + 1, + 1, + 1, + 1 + ], + "customShader": null, + "preventAutoStart": true + }, + { + "name": "shockwave", + "id": "shockwave", + "capacity": 500, + "emitter": + [ + 0, + 2, + 0 + ], + "particleEmitterType": + { + "type": "SphereParticleEmitter", + "radius": 1, + "directionRandomizer": 0.8 + }, + "textureName": "explosion/Smoke_SpriteSheet_8x8.png", + "invertY": false, + "animations": [], + "beginAnimationOnStart": false, + "beginAnimationFrom": 0, + "beginAnimationTo": 60, + "beginAnimationLoop": false, + "startDelay": 60, + "renderingGroupId": 0, + "isBillboardBased": true, + "billboardMode": 7, + "minAngularSpeed": 0, + "maxAngularSpeed": 0, + "minSize": 0.2, + "maxSize": 2, + "minScaleX": 1, + "maxScaleX": 1, + "minScaleY": 1, + "maxScaleY": 1, + "minEmitPower": 40, + "maxEmitPower": 90, + "minLifeTime": 3, + "maxLifeTime": 3, + "emitRate": 3000, + "gravity": + [ + 0, + 0, + 0 + ], + "noiseStrength": + [ + 10, + 10, + 10 + ], + "color1": + [ + 1, + 1, + 1, + 1 + ], + "color2": + [ + 1, + 1, + 1, + 1 + ], + "colorDead": + [ + 1, + 1, + 1, + 0 + ], + "updateSpeed": 0.016666666666666666, + "targetStopDuration": 0.5, + "blendMode": 4, + "preWarmCycles": 0, + "preWarmStepOffset": 1, + "minInitialRotation": -1.5707963267948966, + "maxInitialRotation": 1.5707963267948966, + "startSpriteCellID": 0, + "endSpriteCellID": 63, + "spriteCellChangeSpeed": 1, + "spriteCellWidth": 128, + "spriteCellHeight": 128, + "spriteRandomStartCell": true, + "isAnimationSheetEnabled": true, + "colorGradients": + [ + { + "gradient": 0, + "color1": + [ + 1, + 1, + 1, + 0.15 + ] + }, + { + "gradient": 0.6, + "color1": + [ + 1, + 1, + 1, + 0.15 + ] + }, + { + "gradient": 1, + "color1": + [ + 1, + 1, + 1, + 0 + ] + } + ], + "rampGradients": + [ + { + "gradient": 0, + "color": + [ + 1, + 1, + 1 + ] + }, + { + "gradient": 0.09, + "color": + [ + 0.8196078431372549, + 0.8, + 0.7450980392156863 + ] + }, + { + "gradient": 0.18, + "color": + [ + 0.8666666666666667, + 0.7843137254901961, + 0.7450980392156863 + ] + }, + { + "gradient": 0.28, + "color": + [ + 0.7843137254901961, + 0.7450980392156863, + 0.7058823529411765 + ] + }, + { + "gradient": 0.47, + "color": + [ + 0.45098039215686275, + 0.35294117647058826, + 0.3137254901960784 + ] + }, + { + "gradient": 0.88, + "color": + [ + 0.19607843137254902, + 0.19607843137254902, + 0.19607843137254902 + ] + }, + { + "gradient": 1, + "color": + [ + 0.19607843137254902, + 0.19607843137254902, + 0.19607843137254902 + ] + } + ], + "useRampGradients": true, + "colorRemapGradients": + [ + { + "gradient": 0, + "factor1": 0, + "factor2": 0.8 + }, + { + "gradient": 0.2, + "factor1": 0.1, + "factor2": 0.8 + }, + { + "gradient": 0.3, + "factor1": 0.2, + "factor2": 0.85 + }, + { + "gradient": 0.35, + "factor1": 0.4, + "factor2": 0.85 + }, + { + "gradient": 0.4, + "factor1": 0.5, + "factor2": 0.9 + }, + { + "gradient": 0.5, + "factor1": 0.95, + "factor2": 1 + }, + { + "gradient": 1, + "factor1": 0.95, + "factor2": 1 + } + ], + "sizeGradients": + [ + { + "gradient": 0, + "factor1": 2, + "factor2": 3 + }, + { + "gradient": 1, + "factor1": 5, + "factor2": 8 + } + ], + "angularSpeedGradients": + [ + { + "gradient": 0, + "factor1": 0 + }, + { + "gradient": 1, + "factor1": -0.4, + "factor2": 0.4 + } + ], + "limitVelocityGradients": + [ + { + "gradient": 0, + "factor1": 70 + }, + { + "gradient": 0.15, + "factor1": 10 + }, + { + "gradient": 0.25, + "factor1": 2 + }, + { + "gradient": 1, + "factor1": 1.5 + } + ], + "limitVelocityDamping": 0.9, + "textureMask": + [ + 1, + 1, + 1, + 1 + ], + "customShader": null, + "preventAutoStart": true + }, + { + "name": "fireball", + "id": "fireball", + "capacity": 1000, + "emitter": + [ + 0, + 0, + 0 + ], + "particleEmitterType": + { + "type": "SphereParticleEmitter", + "radius": 2, + "radiusRange": 1, + "directionRandomizer": 0 + }, + "textureName": "explosion/Smoke_SpriteSheet_8x8.png", + "invertY": false, + "animations": + [ + { + "name": "plumeAnimation", + "property": "emitter.y", + "framePerSecond": 60, + "dataType": 0, + "loopBehavior": 2, + "blendingSpeed": 0.01, + "keys": + [ + { + "frame": 0, + "values": + [ + 0 + ] + }, + { + "frame": 10, + "values": + [ + 2 + ] + }, + { + "frame": 40, + "values": + [ + 8 + ] + }, + { + "frame": 50, + "values": + [ + 9 + ] + }, + { + "frame": 55, + "values": + [ + 9.5 + ] + }, + { + "frame": 60, + "values": + [ + 10 + ] + } + ], + "ranges": [] + } + ], + "beginAnimationOnStart": true, + "beginAnimationFrom": 0, + "beginAnimationTo": 60, + "beginAnimationLoop": false, + "startDelay": 60, + "renderingGroupId": 1, + "isBillboardBased": true, + "billboardMode": 7, + "minAngularSpeed": 0, + "maxAngularSpeed": 0, + "minSize": 1, + "maxSize": 3, + "minScaleX": 1, + "maxScaleX": 1, + "minScaleY": 1, + "maxScaleY": 1, + "minEmitPower": 30, + "maxEmitPower": 60, + "minLifeTime": 6, + "maxLifeTime": 8, + "emitRate": 400, + "gravity": + [ + 0, + 0, + 0 + ], + "noiseStrength": + [ + 10, + 10, + 10 + ], + "color1": + [ + 1, + 1, + 1, + 1 + ], + "color2": + [ + 1, + 1, + 1, + 1 + ], + "colorDead": + [ + 1, + 1, + 1, + 0 + ], + "updateSpeed": 0.016666666666666666, + "targetStopDuration": 1, + "blendMode": 4, + "preWarmCycles": 0, + "preWarmStepOffset": 1, + "minInitialRotation": 0, + "maxInitialRotation": 0, + "startSpriteCellID": 0, + "endSpriteCellID": 63, + "spriteCellChangeSpeed": 1, + "spriteCellWidth": 128, + "spriteCellHeight": 128, + "spriteRandomStartCell": true, + "isAnimationSheetEnabled": true, + "colorGradients": + [ + { + "gradient": 0, + "color1": + [ + 1, + 1, + 1, + 0.8 + ] + }, + { + "gradient": 0.4, + "color1": + [ + 1, + 1, + 1, + 0.6 + ] + }, + { + "gradient": 1, + "color1": + [ + 1, + 1, + 1, + 0 + ] + } + ], + "rampGradients": + [ + { + "gradient": 0, + "color": + [ + 1, + 1, + 1 + ] + }, + { + "gradient": 0.09, + "color": + [ + 0.8196078431372549, + 0.8, + 0.058823529411764705 + ] + }, + { + "gradient": 0.18, + "color": + [ + 0.8666666666666667, + 0.47058823529411764, + 0.054901960784313725 + ] + }, + { + "gradient": 0.28, + "color": + [ + 0.7843137254901961, + 0.16862745098039217, + 0.07058823529411765 + ] + }, + { + "gradient": 0.47, + "color": + [ + 0.45098039215686275, + 0.08627450980392157, + 0.058823529411764705 + ] + }, + { + "gradient": 0.88, + "color": + [ + 0.054901960784313725, + 0.054901960784313725, + 0.054901960784313725 + ] + }, + { + "gradient": 1, + "color": + [ + 0.054901960784313725, + 0.054901960784313725, + 0.054901960784313725 + ] + } + ], + "useRampGradients": true, + "colorRemapGradients": + [ + { + "gradient": 0, + "factor1": 0, + "factor2": 0.8 + }, + { + "gradient": 0.2, + "factor1": 0.1, + "factor2": 0.8 + }, + { + "gradient": 0.3, + "factor1": 0.2, + "factor2": 0.85 + }, + { + "gradient": 0.35, + "factor1": 0.4, + "factor2": 0.85 + }, + { + "gradient": 0.4, + "factor1": 0.5, + "factor2": 0.9 + }, + { + "gradient": 0.5, + "factor1": 0.95, + "factor2": 1 + }, + { + "gradient": 1, + "factor1": 0.95, + "factor2": 1 + } + ], + "startSizeGradients": + [ + { + "gradient": 0, + "factor1": 2, + "factor2": 4 + }, + { + "gradient": 0.3, + "factor1": 0.5, + "factor2": 1 + }, + { + "gradient": 0.6, + "factor1": 1, + "factor2": 3 + }, + { + "gradient": 1, + "factor1": 1.7, + "factor2": 3.7 + } + ], + "limitVelocityGradients": + [ + { + "gradient": 0, + "factor1": 5 + }, + { + "gradient": 0.15, + "factor1": 3 + }, + { + "gradient": 0.25, + "factor1": 2 + }, + { + "gradient": 1, + "factor1": 1 + } + ], + "lifeTimeGradients": + [ + { + "gradient": 0, + "factor1": 3 + }, + { + "gradient": 1, + "factor1": 1.75 + } + ], + "limitVelocityDamping": 0.7, + "textureMask": + [ + 1, + 1, + 1, + 1 + ], + "customShader": null, + "preventAutoStart": true + }, + { + "name": "debris", + "id": "debris", + "capacity": 10, + "emitter": + [ + 0, + 0, + 0 + ], + "particleEmitterType": + { + "type": "SphereParticleEmitter", + "radius": 0.9, + "directionRandomizer": 0 + }, + "textureName": "explosion/Flare.png", + "invertY": true, + "animations": [], + "beginAnimationOnStart": false, + "beginAnimationFrom": 0, + "beginAnimationTo": 60, + "beginAnimationLoop": false, + "startDelay": 90, + "renderingGroupId": 0, + "isBillboardBased": true, + "billboardMode": 7, + "minAngularSpeed": 0, + "maxAngularSpeed": 0, + "minSize": 0.1, + "maxSize": 0.1, + "minScaleX": 1, + "maxScaleX": 1, + "minScaleY": 1, + "maxScaleY": 1, + "minEmitPower": 16, + "maxEmitPower": 30, + "minLifeTime": 2, + "maxLifeTime": 2, + "emitRate": 50, + "gravity": + [ + 0, + -20, + 0 + ], + "noiseStrength": + [ + 10, + 10, + 10 + ], + "color1": + [ + 1, + 1, + 1, + 1 + ], + "color2": + [ + 1, + 1, + 1, + 1 + ], + "colorDead": + [ + 1, + 1, + 1, + 0 + ], + "updateSpeed": 0.016666666666666666, + "targetStopDuration": 0.2, + "blendMode": 0, + "preWarmCycles": 0, + "preWarmStepOffset": 1, + "minInitialRotation": 0, + "maxInitialRotation": 0, + "startSpriteCellID": 0, + "endSpriteCellID": 0, + "spriteCellChangeSpeed": 1, + "spriteCellWidth": 0, + "spriteCellHeight": 0, + "spriteRandomStartCell": false, + "isAnimationSheetEnabled": false, + "colorGradients": + [ + { + "gradient": 0, + "color1": + [ + 1, + 1, + 1, + 0 + ] + }, + { + "gradient": 1, + "color1": + [ + 1, + 1, + 1, + 0 + ] + } + ], + "textureMask": + [ + 1, + 1, + 1, + 1 + ], + "customShader": null, + "preventAutoStart": true, + "subEmitters": + [ + [ + { + "type": 0, + "inheritDirection": true, + "inheritedVelocityAmount": 0, + "particleSystem": + { + "name": "fireSubEmitter", + "id": "fireSubEmitter", + "capacity": 200, + "emitter": + [ + 0, + 0, + 0 + ], + "particleEmitterType": + { + "type": "ConeParticleEmitter", + "radius": 0.1, + "angle": 0.7853981633974483, + "directionRandomizer": 0 + }, + "textureName": "explosion/FlameBlastSpriteSheet.png", + "invertY": false, + "animations": [], + "beginAnimationOnStart": false, + "beginAnimationFrom": 0, + "beginAnimationTo": 60, + "beginAnimationLoop": false, + "startDelay": 0, + "renderingGroupId": 1, + "isBillboardBased": true, + "billboardMode": 7, + "minAngularSpeed": 0, + "maxAngularSpeed": 0, + "minSize": 0.8, + "maxSize": 1.2, + "minScaleX": 1, + "maxScaleX": 1, + "minScaleY": 1, + "maxScaleY": 1, + "minEmitPower": 0, + "maxEmitPower": 0, + "minLifeTime": 0.5, + "maxLifeTime": 0.8, + "emitRate": 130, + "gravity": + [ + 0, + 0, + 0 + ], + "noiseStrength": + [ + 10, + 10, + 10 + ], + "color1": + [ + 1, + 1, + 1, + 1 + ], + "color2": + [ + 1, + 1, + 1, + 1 + ], + "colorDead": + [ + 1, + 1, + 1, + 0 + ], + "updateSpeed": 0.016666666666666666, + "targetStopDuration": 1.2, + "blendMode": 2, + "preWarmCycles": 0, + "preWarmStepOffset": 1, + "minInitialRotation": -1.5707963267948966, + "maxInitialRotation": 1.5707963267948966, + "startSpriteCellID": 0, + "endSpriteCellID": 15, + "spriteCellChangeSpeed": 1, + "spriteCellWidth": 256, + "spriteCellHeight": 256, + "spriteRandomStartCell": false, + "isAnimationSheetEnabled": true, + "colorGradients": + [ + { + "gradient": 0, + "color1": + [ + 0.9245, + 0.654, + 0.0915, + 1 + ] + }, + { + "gradient": 0.04, + "color1": + [ + 0.9062, + 0.6132, + 0.0942, + 1 + ] + }, + { + "gradient": 0.29, + "color1": + [ + 0.7968, + 0.3685, + 0.1105, + 1 + ] + }, + { + "gradient": 0.53, + "color1": + [ + 0.6886, + 0.1266, + 0.1266, + 1 + ] + }, + { + "gradient": 0.9, + "color1": + [ + 0.3113, + 0.0367, + 0.0367, + 1 + ] + }, + { + "gradient": 1, + "color1": + [ + 0.3113, + 0.0367, + 0.0367, + 1 + ] + } + ], + "startSizeGradients": + [ + { + "gradient": 0, + "factor1": 1 + }, + { + "gradient": 0.7, + "factor1": 1 + }, + { + "gradient": 1, + "factor1": 0.2 + } + ], + "textureMask": + [ + 1, + 1, + 1, + 1 + ], + "customShader": null, + "preventAutoStart": true + } + }, + { + "type": 0, + "inheritDirection": true, + "inheritedVelocityAmount": 0, + "particleSystem": + { + "name": "smokeSubEmitter", + "id": "smokeSubEmitter", + "capacity": 600, + "emitter": + [ + 0, + 0, + 0 + ], + "particleEmitterType": + { + "type": "ConeParticleEmitter", + "radius": 0.1, + "angle": 0.7853981633974483, + "directionRandomizer": 0 + }, + "textureName": "explosion/Smoke_SpriteSheet_8x8.png", + "invertY": false, + "animations": [], + "beginAnimationOnStart": false, + "beginAnimationFrom": 0, + "beginAnimationTo": 60, + "beginAnimationLoop": false, + "startDelay": 0, + "renderingGroupId": 0, + "isBillboardBased": true, + "billboardMode": 7, + "minAngularSpeed": 0, + "maxAngularSpeed": 0, + "minSize": 2, + "maxSize": 5, + "minScaleX": 1, + "maxScaleX": 1, + "minScaleY": 1, + "maxScaleY": 1, + "minEmitPower": 0, + "maxEmitPower": 0, + "minLifeTime": 1, + "maxLifeTime": 3, + "emitRate": 100, + "gravity": + [ + 0, + 0, + 0 + ], + "noiseStrength": + [ + 10, + 10, + 10 + ], + "color1": + [ + 1, + 1, + 1, + 1 + ], + "color2": + [ + 1, + 1, + 1, + 1 + ], + "colorDead": + [ + 1, + 1, + 1, + 0 + ], + "updateSpeed": 0.016666666666666666, + "targetStopDuration": 1.2, + "blendMode": 4, + "preWarmCycles": 0, + "preWarmStepOffset": 1, + "minInitialRotation": -1.5707963267948966, + "maxInitialRotation": 1.5707963267948966, + "startSpriteCellID": 0, + "endSpriteCellID": 63, + "spriteCellChangeSpeed": 1, + "spriteCellWidth": 128, + "spriteCellHeight": 128, + "spriteRandomStartCell": true, + "isAnimationSheetEnabled": true, + "colorGradients": + [ + { + "gradient": 0, + "color1": + [ + 1, + 1, + 1, + 0 + ] + }, + { + "gradient": 0.05, + "color1": + [ + 1, + 1, + 1, + 0 + ] + }, + { + "gradient": 0.1, + "color1": + [ + 1, + 1, + 1, + 0.2 + ] + }, + { + "gradient": 1, + "color1": + [ + 1, + 1, + 1, + 0 + ] + } + ], + "rampGradients": + [ + { + "gradient": 0, + "color": + [ + 1, + 1, + 1 + ] + }, + { + "gradient": 0.09, + "color": + [ + 0.8196078431372549, + 0.8, + 0.7450980392156863 + ] + }, + { + "gradient": 0.18, + "color": + [ + 0.8666666666666667, + 0.7843137254901961, + 0.7450980392156863 + ] + }, + { + "gradient": 0.28, + "color": + [ + 0.7843137254901961, + 0.7450980392156863, + 0.7058823529411765 + ] + }, + { + "gradient": 0.47, + "color": + [ + 0.45098039215686275, + 0.35294117647058826, + 0.3137254901960784 + ] + }, + { + "gradient": 0.88, + "color": + [ + 0.19607843137254902, + 0.19607843137254902, + 0.19607843137254902 + ] + }, + { + "gradient": 1, + "color": + [ + 0.19607843137254902, + 0.19607843137254902, + 0.19607843137254902 + ] + } + ], + "useRampGradients": true, + "colorRemapGradients": + [ + { + "gradient": 0, + "factor1": 0, + "factor2": 0.8 + }, + { + "gradient": 0.2, + "factor1": 0.1, + "factor2": 0.8 + }, + { + "gradient": 0.3, + "factor1": 0.2, + "factor2": 0.85 + }, + { + "gradient": 0.35, + "factor1": 0.4, + "factor2": 0.85 + }, + { + "gradient": 0.4, + "factor1": 0.5, + "factor2": 0.9 + }, + { + "gradient": 0.5, + "factor1": 0.95, + "factor2": 1 + }, + { + "gradient": 1, + "factor1": 0.95, + "factor2": 1 + } + ], + "sizeGradients": + [ + { + "gradient": 0, + "factor1": 1 + }, + { + "gradient": 1, + "factor1": 3 + } + ], + "startSizeGradients": + [ + { + "gradient": 0, + "factor1": 1 + }, + { + "gradient": 0.6, + "factor1": 1 + }, + { + "gradient": 1, + "factor1": 0.05 + } + ], + "lifeTimeGradients": + [ + { + "gradient": 0, + "factor1": 3 + }, + { + "gradient": 1, + "factor1": 1.75 + } + ], + "textureMask": + [ + 1, + 1, + 1, + 1 + ], + "customShader": null, + "preventAutoStart": true + } + } + ] + ] + } + ] +} \ No newline at end of file diff --git a/public/thrust.mp3 b/public/thrust.mp3 new file mode 100644 index 0000000..797dd7c Binary files /dev/null and b/public/thrust.mp3 differ diff --git a/public/thrust2.mp3 b/public/thrust2.mp3 new file mode 100644 index 0000000..b34850d Binary files /dev/null and b/public/thrust2.mp3 differ diff --git a/public/thust2.mp3 b/public/thust2.mp3 new file mode 100644 index 0000000..3dfe75f Binary files /dev/null and b/public/thust2.mp3 differ diff --git a/public/yehrat.mp3 b/public/yehrat.mp3 new file mode 100644 index 0000000..5e54c3e Binary files /dev/null and b/public/yehrat.mp3 differ diff --git a/server/voices.ts b/server/voices.ts new file mode 100644 index 0000000..8356019 --- /dev/null +++ b/server/voices.ts @@ -0,0 +1,14 @@ +import OpenAI from "openai"; +import * as fs from "fs"; + + +async function build() { + const client = new OpenAI({ apiKey: ""}) + const mp3 = await client.audio.speech.create({ + model: 'tts-1-hd', + voice: 'alloy', + input: 'test 1 2 3' + }); + const buffer = Buffer.from(await mp3.arrayBuffer()); + await fs.promises.writeFile('./output.mp3', buffer); +} diff --git a/src/createSun.ts b/src/createSun.ts new file mode 100644 index 0000000..69626fb --- /dev/null +++ b/src/createSun.ts @@ -0,0 +1,33 @@ +import { + AbstractMesh, + Color3, GlowLayer, + MeshBuilder, + PhysicsAggregate, + PhysicsMotionType, + PhysicsShapeType, + PointLight, + StandardMaterial, + Vector3 +} from "@babylonjs/core"; +import {DefaultScene} from "./defaultScene"; +import {FireProceduralTexture} from "@babylonjs/procedural-textures"; + +export function createSun() : AbstractMesh { + const light = new PointLight("light", new Vector3(0, 0, 0), DefaultScene.MainScene); + const sun = MeshBuilder.CreateSphere("sun", {diameter: 50, segments: 32}, DefaultScene.MainScene); + + const sunAggregate = new PhysicsAggregate(sun, PhysicsShapeType.SPHERE, {mass: 0}, DefaultScene.MainScene); + sunAggregate.body.setMotionType(PhysicsMotionType.STATIC); + const material = new StandardMaterial("material", DefaultScene.MainScene); + material.emissiveTexture =new FireProceduralTexture("fire", 256, DefaultScene.MainScene); + material.emissiveColor = new Color3(.5, .5, .1); + material.disableLighting = true; + sun.material = material; + const gl = new GlowLayer("glow", DefaultScene.MainScene); + //gl.addIncludedOnlyMesh(sun); + gl.intensity = 5; + + + sun.position = new Vector3(0, 0, 0); + return sun; +} \ No newline at end of file diff --git a/src/defaultScene.ts b/src/defaultScene.ts new file mode 100644 index 0000000..8136b4c --- /dev/null +++ b/src/defaultScene.ts @@ -0,0 +1,6 @@ +import {Scene, WebXRDefaultExperience} from "@babylonjs/core"; + +export class DefaultScene { + public static MainScene: Scene; + public static XR: WebXRDefaultExperience; +} \ No newline at end of file diff --git a/src/level1.ts b/src/level1.ts new file mode 100644 index 0000000..ee9374e --- /dev/null +++ b/src/level1.ts @@ -0,0 +1,172 @@ +import {DefaultScene} from "./defaultScene"; +import { + Color3, + HavokPlugin, + MeshBuilder, Observable, ParticleHelper, ParticleSystem, ParticleSystemSet, + PhysicsAggregate, + PhysicsMotionType, + PhysicsShapeType, + StandardMaterial, Texture, + Vector3 +} from "@babylonjs/core"; +import {Ship} from "./ship"; +import {ScoreEvent} from "./scoreEvent"; +import {createRock} from "./starfield"; + +export class Level1 { + private _ship: Ship; + private _explosion: ParticleSystemSet + + public onScoreObservable: Observable = new Observable(); + constructor(ship: Ship) { + this._ship = ship; + this.initialize(); + } + private scored: Set = new Set(); + private async initialize() { + const phys = DefaultScene.MainScene.getPhysicsEngine().getPhysicsPlugin() as HavokPlugin; + ParticleHelper.BaseAssetsUrl = window.location.href; + + //console.log(window.location.href); + DefaultScene.MainScene.onReadyObservable.addOnce(async () => { + this._explosion = await ParticleHelper.CreateAsync("explosion", DefaultScene.MainScene); + }); + // + /*phys.onTriggerCollisionObservable.add((eventData) => { + if (eventData.collider.transformNode.id.indexOf('star') > -1) { + return; + } + if (this.scored.has(eventData.collidedAgainst.transformNode.id)) { + return; + } else { + this.scored.add(eventData.collidedAgainst.transformNode.id); + //this.onScoreObservable.notifyObservers(1); + } + + }); + */ + phys.onCollisionObservable.add( (eventData) => { + this.onScoreObservable.notifyObservers({score: 0, message: eventData?.impulse?.toFixed(2)}); + if ((eventData.collidedAgainst.transformNode.id == 'bullet' || + eventData.collider.transformNode.id == 'bullet') && + (eventData.collidedAgainst.transformNode.id.indexOf('asteroid') > -1 || + eventData.collider.transformNode.id.indexOf('asteroid') > -1) + ){ + const point = eventData.point.clone(); + if (this._explosion) { + /*this._explosion.systems.forEach((system) => { + system.stop(); + });*/ + this._explosion.emitterNode = point; + this._explosion.start(); + } + + eventData.collider.transformNode.dispose(); + eventData.collidedAgainst.transformNode.dispose() + + eventData.collider.dispose(); + eventData.collidedAgainst.dispose(); + + + /*const myParticleSystem = new ParticleSystem("particles", 1000, DefaultScene.MainScene); + myParticleSystem.emitter = point; + myParticleSystem.emitRate = 100; + myParticleSystem.minEmitPower = 2; + myParticleSystem.maxEmitPower = 200; + const sphereEmitter = myParticleSystem.createSphereEmitter(10); + + myParticleSystem.particleTexture = new Texture("./flare.png"); + myParticleSystem.maxLifeTime = 10000; + + //const coneEmitter = myParticleSystem.createConeEmitter(0.1, Math.PI / 9); + myParticleSystem.addSizeGradient(0, 2); + myParticleSystem.addSizeGradient(1, 4); + //myParticleSystem.isLocal = true; + + myParticleSystem.start(); //S + console.log(eventData);*/ + } + + }); + this._ship.onReadyObservable.add(() => { + this._ship.position = new Vector3(0, 1, 0); + this.createStartBase(); + this.createEndBase(); + + createRock(1, new Vector3(0,0, 70), new Vector3(10,10,10)); + createRock(1, new Vector3(0,0, 100), new Vector3(10,10,10)); + createRock(1, new Vector3(0,0, 130), new Vector3(10,10,10)); + for (let i = 0; i < 100; i++) { + createRock(i , Vector3.Random(-200, 200), Vector3.Random(5,20)) + .then((rock) => { + rock.physicsBody.setAngularVelocity(Vector3.Random(-1, 1)); + }); + + } + + }); + } + private createStartBase() { + const mesh = MeshBuilder.CreateCylinder("startBase", {diameter: 10, height: 1, tessellation: 72}, DefaultScene.MainScene); + const material = new StandardMaterial("material", DefaultScene.MainScene); + material.diffuseColor = new Color3(1, 1, 0); + mesh.material = material; + const agg = new PhysicsAggregate(mesh, PhysicsShapeType.CONVEX_HULL, {mass: 0}, DefaultScene.MainScene); + agg.body.setMotionType(PhysicsMotionType.ANIMATED); + + } + private createEndBase() { + const mesh = MeshBuilder.CreateCylinder("endBase", {diameter: 10, height: 1, tessellation: 72}, DefaultScene.MainScene); + mesh.position = new Vector3(0, 5, 200); + const material = new StandardMaterial("material", DefaultScene.MainScene); + material.diffuseColor = new Color3(0, 1, 0); + mesh.material = material; + const agg = new PhysicsAggregate(mesh, PhysicsShapeType.CONVEX_HULL, {mass: 0}, DefaultScene.MainScene); + agg.body.setMotionType(PhysicsMotionType.ANIMATED); + /*agg.body.setCollisionCallbackEnabled(true); + const collider = agg.body.getCollisionObservable().add((eventData) => { + if (eventData.collidedAgainst.transformNode.id == 'ship') { + console.log(eventData); + this.onScoreObservable.notifyObservers({score: 0, + message: eventData?.impulse?.toFixed(2)}) + + } + }); */ + + } + private createTarget(i: number) { + const target = MeshBuilder.CreateTorus("target" + i, {diameter: 10, tessellation: 72}, DefaultScene.MainScene); + + const targetLOD = MeshBuilder.CreateTorus("target" + i, {diameter: 50, tessellation: 10}, DefaultScene.MainScene); + targetLOD.parent = target; + target.addLODLevel(300, targetLOD); + + const material = new StandardMaterial("material", DefaultScene.MainScene); + material.diffuseColor = new Color3(1, 0, 0); + material.alpha = .9; + target.material = material; + target.position = Vector3.Random(-1000, 1000); + target.rotation = Vector3.Random(0, Math.PI*2); + const disc = MeshBuilder.CreateDisc("disc-"+i, {radius: 2, tessellation: 72}, DefaultScene.MainScene); + const discMaterial = new StandardMaterial("material", DefaultScene.MainScene); + discMaterial.ambientColor = new Color3(.1, 1, .1); + discMaterial.alpha = .2; + target.addLODLevel(200, null); + disc.material = discMaterial; + disc.parent = target; + disc.rotation.x = -Math.PI/2; + const agg = new PhysicsAggregate(disc, PhysicsShapeType.MESH, {mass: 0}, DefaultScene.MainScene); + agg.body.setMotionType(PhysicsMotionType.STATIC); + agg.shape.isTrigger = true; + //agg.shape.filterCollideMask = 2; + //agg.body.dispose(); + + //const body = new PhysicsShapeMesh(disc, DefaultScene.MainScene); + + //agg.body.setCollisionCallbackEnabled(true); + /*agg.body.getCollisionObservable().add((eventData) => { + target.dispose(false, false); + agg.dispose(); + });*/ + } +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..5057e90 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,111 @@ +import {Engine, HavokPlugin, PhotoDome, Scene, Vector3, WebGPUEngine, WebXRDefaultExperience} from "@babylonjs/core"; +import '@babylonjs/loaders'; +import HavokPhysics from "@babylonjs/havok"; + +import {DefaultScene} from "./defaultScene"; +import {Ship} from "./ship"; +import {Level1} from "./level1"; +import {Scoreboard} from "./scoreboard"; + +const webGpu = false; +const canvas = (document.querySelector('#gameCanvas') as HTMLCanvasElement); + +export class Main { + + constructor() { + + this.initialize(); + } + + private async initialize() { + await this.setupScene(); + + const xr = await WebXRDefaultExperience.CreateAsync(DefaultScene.MainScene, { + disablePointerSelection: true, + disableTeleportation: true, + disableNearInteraction: true, + disableHandTracking: true, + disableDefaultUI: true, + }); + + //const sun = createSun(); + const ship = new Ship(); + const scoreboard = new Scoreboard(); + const level = new Level1(ship); + const photoDome = new PhotoDome("testdome", '/8192.webp', {}, DefaultScene.MainScene); + //starfield(sun); + //starfield(sun); + + + xr.baseExperience.onInitialXRPoseSetObservable.add(() => { + xr.baseExperience.camera.parent = ship.transformNode; + xr.baseExperience.camera.position = new Vector3(0, 0, 0); + + level.onScoreObservable.add((score) => { + scoreboard.onscoreObservable.notifyObservers(score); + }); + + }); + xr.input.onControllerAddedObservable.add((controller) => { + ship.addController(controller); + }); + DefaultScene.XR = xr; + + } + + private async setupScene() { + + let engine: WebGPUEngine | Engine = null; + if (webGpu) { + engine = new WebGPUEngine(canvas); + await (engine as WebGPUEngine).initAsync(); + } else { + engine = new Engine(canvas, true); + } + engine.setHardwareScalingLevel(1 / window.devicePixelRatio); + //Engine.audioEngine.useCustomUnlockedButton = true; + window.onresize = () => { + engine.resize(); + } + DefaultScene.MainScene = new Scene(engine); + + + await this.setupPhysics(); + + this.setupInspector(); + + engine.runRenderLoop(() => { + DefaultScene.MainScene.render(); + }); + } + + private async setupPhysics() { + const havok = await HavokPhysics(); + + const havokPlugin = new HavokPlugin(true, havok); + DefaultScene.MainScene.enablePhysics(new Vector3(0, 0, 0), havokPlugin); + + DefaultScene.MainScene.collisionsEnabled = true; + + + } + + private setupInspector() { + window.addEventListener("keydown", (ev) => { + if (ev.key == 'i') { + import ("@babylonjs/inspector").then((inspector) => { + inspector.Inspector.Show(DefaultScene.MainScene, { + overlay: true, + showExplorer: true + }); + }); + } + }); + } +} + +const main = new Main(); + + + + diff --git a/src/mirror.ts b/src/mirror.ts new file mode 100644 index 0000000..b343ec6 --- /dev/null +++ b/src/mirror.ts @@ -0,0 +1,22 @@ +import {FreeCamera, MeshBuilder, RenderTargetTexture, StandardMaterial, TransformNode, Vector3} from "@babylonjs/core"; +import {DefaultScene} from "./defaultScene"; + +export class Mirror { + constructor(ship: TransformNode) { + const renderTargetTexture = new RenderTargetTexture('mirror', 512, DefaultScene.MainScene); + const camera = new FreeCamera("mirrorCamera", new Vector3(0, 0, -5), DefaultScene.MainScene); + camera.parent = ship; + //camera.rotation.y = Math.PI; + renderTargetTexture.activeCamera = camera; + renderTargetTexture.renderList.push(DefaultScene.MainScene.getMeshByName("shipMesh")); + const mirror = MeshBuilder.CreatePlane("mirrorMesh" , {width: 1, height: 1}, DefaultScene.MainScene); + mirror.parent = ship; + const mirrorMaterial = new StandardMaterial("mirrorMaterial", DefaultScene.MainScene); + + mirrorMaterial.backFaceCulling = false; + mirrorMaterial.diffuseTexture = renderTargetTexture; + mirror.material = mirrorMaterial; + mirror.position = new Vector3(0, 1, 5); + mirror.rotation.y = Math.PI; + } +} \ No newline at end of file diff --git a/src/radar.ts b/src/radar.ts new file mode 100644 index 0000000..86714d0 --- /dev/null +++ b/src/radar.ts @@ -0,0 +1,81 @@ +import {DefaultScene} from "./defaultScene"; +import { + AbstractMesh, + Color3, + HavokPlugin, InstancedMesh, Mesh, + MeshBuilder, Ray, SceneLoader, + StandardMaterial, + TransformNode, + Vector3 +} from "@babylonjs/core"; + +const DETECTED: Color3 = Color3.Blue(); +const WARN: Color3 = Color3.Yellow(); +const DANGER: Color3 = Color3.Red(); +const DETECTED_DISTANCE = 100; +const WARN_DISTANCE = 50; +const DANGER_DISTANCE = 30; +export class Radar { + private _shipTransform: TransformNode; + private _radarTransform: TransformNode; + private _arrowMesh: AbstractMesh; + constructor(ship: TransformNode) { + this._shipTransform = ship; + this._radarTransform = new TransformNode('radar', DefaultScene.MainScene); + this._radarTransform.parent = ship; + const sphere = MeshBuilder.CreateSphere('radarSphere', {diameter: 1}, DefaultScene.MainScene); + sphere.parent = this._radarTransform; + const material = new StandardMaterial('radarMaterial', DefaultScene.MainScene); + material.diffuseColor = Color3.Yellow(); + material.alpha = .5; + sphere.material = material; + // dmaterial.alpha = .1; + this._radarTransform.position.z = 4; + //this._radarTransform.scaling = new Vector3(.01, .01 ,.01); + this.initialize(); + + } + + private async initialize() { + const scene = DefaultScene.MainScene; + const arrow = await SceneLoader.ImportMeshAsync(null, './', 'arrow.stl', scene); + //arrow.meshes[0].parent = this._radarTransform; + arrow.meshes[0].scaling = new Vector3(.05,.05,.05); + this._arrowMesh = arrow.meshes[0]; + const material = new StandardMaterial('arrowMaterial', scene); + material.emissiveColor = Color3.White(); + this._arrowMesh.material = material; + window.setInterval(() => { + const point = scene.getMeshById('endBase'); + point.computeWorldMatrix(true) + this._arrowMesh.position = this._radarTransform.absolutePosition; + this._arrowMesh.lookAt(point.absolutePosition); + }, 100); + + // arrow[0].parent = this._radarTransform; + /*window.setInterval(() => { + scene.meshes.forEach((mesh) => { + if (mesh.physicsBody) { + if (!this._radarMeshes.has(mesh.id)) { + const radarmesh = new InstancedMesh('radar-' + mesh.id, mesh as Mesh); + radarmesh.metadata = {source: mesh}; + radarmesh.parent = this._radarTransform; + this._radarMeshes.set(mesh.id, radarmesh); + } + this.update(); + } + }); + }, 2000); + + */ + } + + private async update() { + /*this._radarMeshes.forEach((radarMesh, id) => { + const mesh = radarMesh.metadata.source as AbstractMesh; + radarMesh.position = mesh.absolutePosition.subtract(this._shipTransform.absolutePosition).scaleInPlace(1.1); + }); + + */ + } +} \ No newline at end of file diff --git a/src/scoreEvent.ts b/src/scoreEvent.ts new file mode 100644 index 0000000..e58cdf1 --- /dev/null +++ b/src/scoreEvent.ts @@ -0,0 +1,4 @@ +export type ScoreEvent = { + score: number, + message: string +} \ No newline at end of file diff --git a/src/scoreboard.ts b/src/scoreboard.ts new file mode 100644 index 0000000..8b22951 --- /dev/null +++ b/src/scoreboard.ts @@ -0,0 +1,88 @@ +import {AdvancedDynamicTexture, Control, StackPanel, TextBlock} from "@babylonjs/gui"; +import {DefaultScene} from "./defaultScene"; +import { + AbstractMesh, + ActionManager, + Angle, + ExecuteCodeAction, + MeshBuilder, + Observable, + TransformNode, + Vector3, +} from "@babylonjs/core"; +import {ScoreEvent} from "./scoreEvent"; + +export class Scoreboard { + private _score: number = 0; + private _lastMessage: string = null; + public onscoreObservable: Observable = new Observable(); + constructor() { + DefaultScene.MainScene.onNewMeshAddedObservable.add((mesh) => { + if (mesh.id == 'RightUpperDisplay') { + window.setTimeout(() => { + //mesh.material = null; + this.initialize(); + },1000); + + } + }); + //this.initialize(camera); + } + private initialize() { + const scene = DefaultScene.MainScene; + + const parent = scene.getMeshById('RightUpperDisplay'); + const scoreboard = MeshBuilder.CreatePlane("scoreboard", {width: 1, height: 1}, scene); + scoreboard.parent =parent; + //DefaultScene.MainScene.onBeforeDrawPhaseObservable.add(() => { + + //}); + //scoreboard.parent = camera; + scoreboard.position.x = -.76; + scoreboard.position.y = 4.19; + scoreboard.position.z = .53; + scoreboard.rotation.x = Angle.FromDegrees(108).radians(); + scoreboard.rotation.z = Math.PI; + scoreboard.scaling = new Vector3(.5, .5, .5); + //scoreboard.position = camera.getFrontPosition(1); + + const advancedTexture = AdvancedDynamicTexture.CreateForMesh(scoreboard); + advancedTexture.background = "black"; + const scoreText = this.createText(); + advancedTexture.addControl(scoreText); + const fpsText = this.createText(); + fpsText.top = '120px'; + const panel = new StackPanel(); + panel.isVertical = true; + advancedTexture.addControl(fpsText); + advancedTexture.addControl(scoreText); + advancedTexture.addControl(panel); + + scene.onAfterRenderObservable.add(() => { + scoreText.text = `Score: ${this.calculateScore()}`; + if (this._lastMessage != null) { + fpsText.text = this._lastMessage; + } else { + fpsText.text = ''; + } + + }); + + this.onscoreObservable.add((score) => { + this._score += score.score; + this._lastMessage = score.message; + }); + } + private createText(): TextBlock { + const text1 = new TextBlock(); + + text1.color = "white"; + text1.fontSize = 90; + text1.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT; + text1.textVerticalAlignment = Control.VERTICAL_ALIGNMENT_TOP; + return text1; + } + private calculateScore() { + return Math.floor(this._score); + } +} \ No newline at end of file diff --git a/src/ship.ts b/src/ship.ts new file mode 100644 index 0000000..0a76f49 --- /dev/null +++ b/src/ship.ts @@ -0,0 +1,438 @@ +import { + AbstractMesh, Color3, + DirectionalLight, Engine, + + FreeCamera, GlowLayer, + Matrix, MeshBuilder, + Observable, + PhysicsAggregate, + PhysicsMotionType, + PhysicsShapeType, + SceneLoader, Sound, + SpotLight, StandardMaterial, + TransformNode, + Vector2, + Vector3, + WebXRAbstractMotionController, + WebXRControllerComponent, + WebXRInputSource +} from "@babylonjs/core"; +import {DefaultScene} from "./defaultScene"; +import {Radar} from "./radar"; +import {ShipEngine} from "./shipEngine"; +import {Mirror} from "./mirror"; + +const controllerComponents = [ + 'a-button', + 'b-button', + 'x-button', + 'y-button', + 'thumbrest', + 'xr-standard-squeeze', + 'xr-standard-thumbstick', + 'xr-standard-trigger', +] +type ControllerEvent = { + hand: 'right' | 'left' | 'none', + type: 'thumbstick' | 'button', + controller: WebXRAbstractMotionController, + component: WebXRControllerComponent, + value: number, + axisData: { x: number, y: number }, + pressed: boolean, + touched: boolean + +} + +enum ControllerStickMode { + ARCADE, + REALISTIC +} + +export class Ship { + private _ship: TransformNode; + private _controllerObservable: Observable = new Observable(); + public onReadyObservable: Observable = new Observable(); + private _engine: ShipEngine; + + private _forwardNode: TransformNode; + private _rotationNode: TransformNode; + private _onscore: Observable; + private _ammo: Array = []; + private _glowLayer: GlowLayer; + private _thrust: Sound; + private _thrust2: Sound; + private _shot: Sound; + private _shooting: boolean = false; + constructor() { + this._ship = new TransformNode("ship", DefaultScene.MainScene); + this._glowLayer = new GlowLayer('bullets', DefaultScene.MainScene); + this._glowLayer.intensity = 1; + this._thrust = new Sound("thrust", "/thrust.mp3", DefaultScene.MainScene, null, {loop: true, autoplay: false}); + this._thrust2 = new Sound("thrust2", "/thrust2.mp3", DefaultScene.MainScene, null, {loop: true, autoplay: false}); + this._shot = new Sound("shot", "/shot.mp3", DefaultScene.MainScene, null, + {loop: false, autoplay: false}); + this.initialize(); + + } + private shoot() { + const ammo = MeshBuilder.CreateCapsule("bullet", { radius: .05, height: 1.5}, DefaultScene.MainScene); + ammo.parent = this._ship + ammo.position.y =2; + ammo.rotation.x = Math.PI / 2; + ammo.setParent(null); + const ammoAggregate = new PhysicsAggregate(ammo, PhysicsShapeType.CONVEX_HULL, {mass: 1}, DefaultScene.MainScene); + const material = new StandardMaterial("ammoMaterial", DefaultScene.MainScene); + material.emissiveColor = new Color3(1,1,0); + ammo.material = material; + ammoAggregate.body.setMotionType(PhysicsMotionType.DYNAMIC); + ammoAggregate.body.setLinearVelocity(this._ship.forward.scale(100).add(this._ship.physicsBody.getLinearVelocity())); + this._shot.play(); + window.setTimeout(() =>{ ammoAggregate.dispose(); ammo.dispose()}, 5000) + } + public set position(newPosition: Vector3) { + const body = this._ship.physicsBody; + body.disablePreStep = false; + body.transformNode.position.copyFrom(newPosition); + DefaultScene.MainScene.onAfterRenderObservable.addOnce(() => { + body.disablePreStep = true; + }) + + } + + private async initialize() { + const light = new DirectionalLight("light", new Vector3(.1, -1, 0), DefaultScene.MainScene); + const ship = this._ship; + const landingLight = new SpotLight("landingLight", new Vector3(0,0,0), new Vector3(0, -.5, .5),1.5, .5, DefaultScene.MainScene); + landingLight.parent = ship; + landingLight.position.z = 5; + + //const lightCode = MeshBuilder.CreateCylinder("lightCode", {diameterBottom: 0, diameterTop: .5, height: 1}, DefaultScene.MainScene); + //lightCode.parent = ship; + //lightCode.position.z = 5; + //this._engine = new ShipEngine(ship); + //ship.position = new Vector3(0, 0, -1000); + //const landingLight = new DirectionalLight("landingLight", new Vector3(0, -1, 0), DefaultScene.MainScene); + //landingLight.parent = ship; + const importMesh = await SceneLoader.ImportMeshAsync(null, "./", "cockpit3.glb", DefaultScene.MainScene); + const shipMesh = importMesh.meshes[0]; + shipMesh.id = "shipMesh"; + shipMesh.name = "shipMesh"; + shipMesh.parent = ship; + + shipMesh.rotation.y = Math.PI; + shipMesh.position.y = 1; + shipMesh.position.z = -1; + DefaultScene.MainScene.getMaterialById('glass_mat.002').alpha = .7; + + const camera = new FreeCamera("Flat Camera", + new Vector3(0, 0, -10), + DefaultScene.MainScene); + camera.parent = ship; + camera.position.y = .5; + camera.position.z = 0; + + + + + //right.attachToMesh(rightTransform); + + + //camera.rotation.x = -Math.PI / 2; + const body = new PhysicsAggregate(ship, PhysicsShapeType.BOX, { + mass: 100, + extents: new Vector3(5, 2, 5) + }, DefaultScene.MainScene); + + body.body.setMotionType(PhysicsMotionType.DYNAMIC); + body.body.setLinearDamping(.1); + body.body.setAngularDamping(.2); + body.body.setAngularVelocity(new Vector3(0, 0, 0)); + body.body.setCollisionCallbackEnabled(true) + //body.shape.filterCollideMask = 1; + /*const sight = MeshBuilder.CreateDisc("sight", { + radius: .1, + sideOrientation: Mesh.DOUBLESIDE + }, DefaultScene.MainScene); + const sightMaterial = new StandardMaterial("sightMaterial", DefaultScene.MainScene); + sightMaterial.ambientColor = new Color3(1, 1, 1); + sightMaterial.alpha = .5; + sight.material = sightMaterial; + sight.parent = ship; + sight.rotation.x = Math.PI; + sight.position.z = 10; + const line = MeshBuilder.CreateLines("line", {points: [Vector3.Zero(), new Vector3(0, 0, 10)]}, DefaultScene.MainScene); + line.parent = ship; + line.material = sightMaterial; */ + DefaultScene.MainScene.setActiveCameraByName("Flat Camera"); + + + this.setupKeyboard(); + this.setupMouse(); + this._controllerObservable.add(this.controllerCallback); + this._forwardNode = new TransformNode("forward", DefaultScene.MainScene); + this._rotationNode = new TransformNode("rotation", DefaultScene.MainScene); + this._forwardNode.parent = this._ship; + this._rotationNode.parent = this._ship; + + //const radar = new Radar(this._ship); + window.setInterval(() => { + this.applyForce(); + }, 50); + this.onReadyObservable.notifyObservers(true); + //const mirror = new Mirror(this._ship); + const radar = new Radar(this._ship); + + document.querySelector('#loadingDiv').remove(); + const startButton = document.querySelector('#startButton'); + startButton.classList.add('ready'); + + const background = new Sound("background", "/background.mp3", DefaultScene.MainScene, () => { + const startButton = document.querySelector('#startButton'); + startButton.classList.add('ready'); + startButton.addEventListener('click', () => { + Engine.audioEngine.unlock(); + background.play(); + DefaultScene.XR.baseExperience.enterXRAsync('immersive-vr', 'local-floor'); + }); + }, {loop: true, autoplay: false, volume: .1}); + } + + private _leftStickVector = Vector2.Zero().clone(); + private _rightStickVector = Vector2.Zero().clone(); + private _forwardValue = 0; + private _yawValue = 0; + private _rollValue = 0; + private _pitchValue = 0; + private _mouseDown = false; + private _mousePos = new Vector2(0, 0); + + private scale(value: number) { + return value * .8; + } + + + public get transformNode() { + return this._ship; + } + + private adjust(value: number, increment: number = .8): number { + if (Math.abs(value) < .001) { + return 0; + } else { + return value * increment; + } + } + + private applyForce() { + if (!this?._ship?.physicsBody) { + return; + } + const body = this._ship.physicsBody; + if (Math.abs(this._forwardValue) > 40) { + this._forwardValue = Math.sign(this._forwardValue) * 40; + } + + if (Math.abs(this._forwardValue) <= 40) { + if (Math.abs(this._leftStickVector.y) > .1) { + if (!this._thrust.isPlaying) { + this._thrust.play(); + } + this._thrust.setVolume(Math.abs(this._leftStickVector.y)); + this._forwardValue += this._leftStickVector.y * .4; + } else { + if (this._thrust.isPlaying) { + this._thrust.pause(); + } + this._forwardValue = this.adjust(this._forwardValue, .98); + } + } + + if (Math.abs(this._leftStickVector.x) > .1) { + this._yawValue += this._leftStickVector.x * .03; + } else { + + this._yawValue = this.adjust(this._yawValue); + } + + if (Math.abs(this._rightStickVector.x) > .1) { + this._rollValue += this._rightStickVector.x * .03; + } else { + this._rollValue = this.adjust(this._rollValue); + } + + if (Math.abs(this._rightStickVector.y) > .1) { + this._pitchValue += this._rightStickVector.y * .03; + } else { + this._pitchValue = this.adjust(this._pitchValue); + } + + this._forwardNode.position.z = this._forwardValue; + this._rotationNode.position.y = this._yawValue; + this._rotationNode.position.z = -this._rollValue; + this._rotationNode.position.x = -this._pitchValue; + + const thrust2 = Math.abs(this._rightStickVector.y) + + Math.abs(this._rightStickVector.x) + + Math.abs(this._leftStickVector.x); + + if (thrust2 > .01) { + if (!this._thrust2.isPlaying) { + this._thrust2.play(); + } + this._thrust2.setVolume(thrust2 * .4); + } else { + if (this._thrust2.isPlaying) { + this._thrust2.pause(); + } + + } + + body.setAngularVelocity(this._rotationNode.absolutePosition.subtract(this._ship.absolutePosition)); + body.setLinearVelocity(this._forwardNode.absolutePosition.subtract(this._ship.absolutePosition).scale(-1)); + //this._engine.forwardback(this._forwardValue); + } + private controllerCallback = (controllerEvent: ControllerEvent) => { + if (controllerEvent.type == 'thumbstick') { + if (controllerEvent.hand == 'left') { + this._leftStickVector.x = controllerEvent.axisData.x; + this._leftStickVector.y = controllerEvent.axisData.y; + } + + if (controllerEvent.hand == 'right') { + this._rightStickVector.x = controllerEvent.axisData.x; + this._rightStickVector.y = controllerEvent.axisData.y; + + } + this.applyForce(); + } + if (controllerEvent.type == 'button') { + if (controllerEvent.component.type == 'trigger') { + if (controllerEvent.value > .9 && !this._shooting) { + this._shooting = true; + this.shoot(); + } + if (controllerEvent.value < .1) { + this._shooting = false; + } + } + } + } + private setupMouse() { + this._ship.getScene().onPointerDown = (evt, pickInfo, type) => { + this._mousePos.x = evt.x; + this._mousePos.y = evt.y; + this._mouseDown = true; + + } + this._ship.getScene().onPointerUp = (evt, pickInfo, type) => { + this._mouseDown = false; + } + this._ship.getScene().onPointerMove = (evt, pickInfo, type) => { + + }; + this._ship.getScene().onPointerMove = (ev, pickInfo, type) => { + if (!this._mouseDown) {return}; + const xInc = this._rightStickVector.x = (ev.x - this._mousePos.x) / 100; + const yInc = this._rightStickVector.y = (ev.y - this._mousePos.y) / 100; + if (Math.abs(xInc) <= 1) { + this._rightStickVector.x = xInc; + } else { + this._rightStickVector.x = Math.sign(xInc); + } + if (Math.abs(yInc) <= 1) { + this._rightStickVector.y = yInc; + } else { + this._rightStickVector.y = Math.sign(yInc); + } + + }; + } + private setupKeyboard() { + document.onkeydown = (ev) => { + switch (ev.key) { + case ' ': + this.shoot(); + break; + case 'e': + + break; + case 'w': + this._leftStickVector.y =-1; + break; + case 's': + this._leftStickVector.y =1; + break; + case 'a': + this._leftStickVector.x =-1; + break; + case 'd': + this._leftStickVector.x =1; + break; + case 'ArrowUp': + + break; + case 'ArrowDown': + + break; + + } + }; + } + + private _leftInputSource: WebXRInputSource; + private _rightInputSource: WebXRInputSource; + + public addController(controller: WebXRInputSource) { + if (controller.inputSource.handedness == "left") { + this._leftInputSource = controller; + this._leftInputSource.onMotionControllerInitObservable.add((motionController) => { + console.log(motionController); + this.mapMotionController(motionController); + }); + } + if (controller.inputSource.handedness == "right") { + this._rightInputSource = controller; + this._rightInputSource.onMotionControllerInitObservable.add((motionController) => { + console.log(motionController); + this.mapMotionController(motionController); + }); + } + } + + private mapMotionController(controller: WebXRAbstractMotionController) { + controllerComponents.forEach((component) => { + const comp = controller.components[component]; + const observable = this._controllerObservable; + + if (comp && comp.onAxisValueChangedObservable) { + comp.onAxisValueChangedObservable.add((axisData) => { + observable.notifyObservers({ + controller: controller, + hand: controller.handness, + type: 'thumbstick', + component: comp, + value: comp.value, + axisData: {x: axisData.x, y: axisData.y}, + pressed: comp.pressed, + touched: comp.touched + }) + }); + } + if (comp && comp.onButtonStateChangedObservable) { + comp.onButtonStateChangedObservable.add((component) => { + observable.notifyObservers({ + controller: controller, + hand: controller.handness, + type: 'button', + component: comp, + value: component.value, + axisData: {x: component.axes.x, y: component.axes.y}, + pressed: component.pressed, + touched: component.touched + }); + }); + } + }); + } +} \ No newline at end of file diff --git a/src/shipEngine.ts b/src/shipEngine.ts new file mode 100644 index 0000000..fed0e73 --- /dev/null +++ b/src/shipEngine.ts @@ -0,0 +1,81 @@ +import { + AbstractMesh, Color3, GlowLayer, + MeshBuilder, + ParticleSystem, + StandardMaterial, + Texture, + TransformNode, + Vector3 +} from "@babylonjs/core"; +import {DefaultScene} from "./defaultScene"; + +type MainEngine = { + transformNode: TransformNode; + particleSystem: ParticleSystem; +} +export class ShipEngine { + private _ship: TransformNode; + private _leftMainEngine: MainEngine; + private _rightMainEngine: MainEngine; + private _gl: GlowLayer; + constructor(ship: TransformNode) { + this._ship = ship; + this.initialize(); + } + + private initialize() { + this._gl = new GlowLayer("glow", DefaultScene.MainScene); + this._gl.intensity =1; + this._leftMainEngine = this.createEngine(new Vector3(-.44, .37, -1.1)); + this._rightMainEngine = this.createEngine(new Vector3(.44, .37, -1.1)); + } + public idle() { + this._leftMainEngine.particleSystem.emitRate = 1; + this._rightMainEngine.particleSystem.emitRate = 1; + } + public forwardback(value: number) { + + if (Math.sign(value) > 0) { + (this._leftMainEngine.particleSystem.emitter as AbstractMesh).rotation.y = 0; + (this._rightMainEngine.particleSystem.emitter as AbstractMesh).rotation.y = 0; + } else { + (this._leftMainEngine.particleSystem.emitter as AbstractMesh).rotation.y = Math.PI; + (this._rightMainEngine.particleSystem.emitter as AbstractMesh).rotation.y = Math.PI; + } + this._leftMainEngine.particleSystem.emitRate = Math.abs(value) * 10; + this._rightMainEngine.particleSystem.emitRate = Math.abs(value) * 10; + } + + private createEngine(position: Vector3) : MainEngine{ + const MAIN_ROTATION = Math.PI / 2; + const engine = new TransformNode("engine", DefaultScene.MainScene); + engine.parent = this._ship; + engine.position = position; + const leftDisc = MeshBuilder.CreateIcoSphere("engineSphere", {radius: .07}, DefaultScene.MainScene); + this._gl.addIncludedOnlyMesh(leftDisc); + const material = new StandardMaterial("material", DefaultScene.MainScene); + material.emissiveColor = new Color3(.5, .5, .1); + leftDisc.material = material; + leftDisc.parent = engine; + leftDisc.rotation.x = MAIN_ROTATION; + const particleSystem = this.createParticleSystem(leftDisc); + return {transformNode: engine, particleSystem: particleSystem}; + } + private createParticleSystem(mesh: AbstractMesh): ParticleSystem { + const myParticleSystem = new ParticleSystem("particles", 1000, DefaultScene.MainScene); + myParticleSystem.emitRate = 1; + //myParticleSystem.minEmitPower = 2; + //myParticleSystem.maxEmitPower = 10; + + myParticleSystem.particleTexture = new Texture("./flare.png"); + myParticleSystem.emitter = mesh; + const coneEmitter = myParticleSystem.createConeEmitter(0.1, Math.PI / 9); + myParticleSystem.addSizeGradient(0, .01); + myParticleSystem.addSizeGradient(1, .3); + myParticleSystem.isLocal = true; + + myParticleSystem.start(); //S + return myParticleSystem; + + } +} \ No newline at end of file diff --git a/src/starfield.ts b/src/starfield.ts new file mode 100644 index 0000000..90245a4 --- /dev/null +++ b/src/starfield.ts @@ -0,0 +1,30 @@ +import { + AbstractMesh, + PhysicsAggregate, + PhysicsMotionType, + PhysicsShapeType, + SceneLoader, + Vector3 +} from "@babylonjs/core"; +import {DefaultScene} from "./defaultScene"; + +export async function createRock(i: number, position: Vector3, size: Vector3): Promise { + const importMesh = await SceneLoader.ImportMeshAsync(null, "./", "asteroid.glb", DefaultScene.MainScene); + const rock = importMesh.meshes[1]; + + rock.scaling = size; + rock.position = position; + rock.setParent(null); + importMesh.meshes[0].dispose(); + rock.name = "asteroid-" + i; + rock.id = "asteroid-" + i; + const agg = new PhysicsAggregate(rock, PhysicsShapeType.CONVEX_HULL, {mass: 10000}, DefaultScene.MainScene); + const body =agg.body; + body.setLinearDamping(.001); + body.setAngularDamping(.00001); + body.setMotionType(PhysicsMotionType.DYNAMIC); + body.setCollisionCallbackEnabled(true); + //body.setAngularVelocity(new Vector3(Math.random(), Math.random(), Math.random())); + // body.setLinearVelocity(Vector3.Random(-10, 10)); + return rock; +} diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..be51b5b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,44 @@ +{ + "compilerOptions": { + "target": "es6", + "outDir": "./dist", + // choose our ECMA/JavaScript version (all modern browsers support ES6 so it's your best bet) + "allowSyntheticDefaultImports": true, + "lib": [ + // choose our default ECMA/libraries to import + "dom", + // mandatory for all browser-based apps + "es6" + // mandatory for targeting ES6 + ], + "useDefineForClassFields": true, + // enable latest ECMA runtime behavior with older ECMA/JavaScript versions (delete this line if target: "ESNext" or "ES2022"+) + "module": "ESNext", + // use the latest ECMA/JavaScript syntax for our import statements and such + "moduleResolution": "node", + // ensures we are using CommonJS for our npm packages + "noResolve": false, + // disable TypeScript from automatically detecting/adding files based on import statements and etc (it's less helpful than you think) + "isolatedModules": false, + // allows our code to be processed by other transpilers, such as preventing non-module TS files (you could delete this since we're only using base TypeScript) + "removeComments": true, + // remove comments from our outputted code to save on space (look into terser if you want to protect the outputted JS even more) + "esModuleInterop": true, + // treats non-ES6 modules separately from ES6 modules (helpful if module: "ESNext") + "noImplicitAny": false, + // usually prevents code from using "any" type fallbacks to prevent untraceable JS errors, but we'll need this disabled for our example code + "noUnusedLocals": false, + // usually raises an error for any unused local variables, but we'll need this disabled for our example code + "noUnusedParameters": true, + // raises an error for unused parameters + "noImplicitReturns": true, + // raises an error for functions that return nothing + "skipLibCheck": true + // skip type-checking of .d.ts files (it speeds up transpiling) + }, + "include": [ + "src", + "server" + ], + // specify location(s) of .ts files +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..7d638ad --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,32 @@ +import {defineConfig} from "vite"; + +/** @type {import('vite').UserConfig} */ +export default defineConfig({ + test: {}, + define: {}, + build: { + sourcemap: true, + rollupOptions: { + output: { + manualChunks: { + 'babylon': ['@babylonjs/core'] + } + } + } + }, + optimizeDeps: { + esbuildOptions: { + define: { + global: 'window', + } + } + }, + server: { + port: 3001, + }, + preview: { + port: 3001, + }, + base: "/" + +}) \ No newline at end of file