diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 39b94732d..40a09b63f 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -115,4 +115,4 @@ jobs: run: | for alias in $(echo ${{ steps.alias.outputs.alias }} | tr "," "\n"); do vercel alias set ${{ steps.deploy.outputs.stdout }} $alias --token=${{ secrets.VERCEL_TOKEN }} --scope=zaro - done \ No newline at end of file + done diff --git a/.gitignore b/.gitignore index 33734572f..49c3b97f1 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ config.local.json logs/ src/react/npmReactComponents.ts +.env*.local diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a5a3482db..7a3985393 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,32 +33,6 @@ Paths: - `src` - main app source code - `src/react` - React components - almost all UI is in this folder. Almost every component has its base (reused in app and storybook) and `Provider` - which is a component that provides context to its children. Consider looking at DeathScreen component to see how it's used. -### Renderer: Playground & Mesher (`renderer`) - -- Playground Scripts: - - Start: `pnpm run-playground` (playground, mesher + server) or `pnpm watch-playground` - - Build: `pnpm build-playground` or `node renderer/esbuild.mjs` - -- Mesher Scripts: - - Start: `pnpm watch-mesher` - - Build: `pnpm build-mesher` - -Paths: - -- `renderer` - Improved and refactored version of . Here is everything related to rendering the game world itself (no ui at all). Two most important parts here are: -- `renderer/viewer/lib/worldrenderer.ts` - adding new objects to three.js happens here (sections) -- `renderer/viewer/lib/models.ts` - preparing data for rendering (blocks) - happens in worker: out file - `worker.js`, building - `renderer/buildWorker.mjs` -- `renderer/playground/playground.ts` - Playground (source of ) Use this for testing any rendering changes. You can also modify the playground code. - -### Storybook (`.storybook`) - -Storybook is a tool for easier developing and testing React components. -Path of all Storybook stories is `src/react/**/*.stories.tsx`. - -- Scripts: - - Start: `pnpm storybook` - - Build: `pnpm build-storybook` - ## Core-related How different modules are used: @@ -69,7 +43,7 @@ How different modules are used: To start the main web app and playground, run `pnpm run-all`. Note is doesn't start storybook and tests. -## Cypress Tests (E2E) +## Cypress Tests (Browser Integration) Cypress tests are located in `cypress` folder. To run them, run `pnpm test-mc-server` and then `pnpm test:cypress` when the `pnpm prod-start` is running (or change the port to 3000 to test with the dev server). Usually you don't need to run these until you get issues on the CI. diff --git a/config.json b/config.json index 817a0ba55..aa177d4db 100644 --- a/config.json +++ b/config.json @@ -31,7 +31,7 @@ } ], "rightSideText": "A Minecraft client clone in the browser!", - "splashText": "Thanks for testing my chaos!", + "splashText": "Mind the bugs and have fun!", "splashTextFallback": "Welcome!", "pauseLinks": [ [ diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index e55f5d268..6bde42b07 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -2,7 +2,7 @@ const { cypressEsbuildPreprocessor } = require('cypress-esbuild-preprocessor') const { initPlugin } = require('cypress-plugin-snapshots/plugin') const polyfill = require('esbuild-plugin-polyfill-node') -const { startMinecraftServer } = require('./startServer') +// const { startMinecraftServer } = require('./startServer') module.exports = (on, config) => { initPlugin(on, config) @@ -24,10 +24,10 @@ module.exports = (on, config) => { return null }, }) - on('task', { - async startServer([version, port]) { - return startMinecraftServer(version, port) - } - }) + // on('task', { + // async startServer([version, port]) { + // return startMinecraftServer(version, port) + // } + // }) return config } diff --git a/cypress/plugins/startServer.ts b/cypress/plugins/startServer.ts.ignore similarity index 100% rename from cypress/plugins/startServer.ts rename to cypress/plugins/startServer.ts.ignore diff --git a/experiments/state.ts b/experiments/state.ts index b01523fce..dd2e0d6f0 100644 --- a/experiments/state.ts +++ b/experiments/state.ts @@ -1,4 +1,4 @@ -import { SmoothSwitcher } from '../renderer/viewer/lib/smoothSwitcher' +import { SmoothSwitcher } from 'minecraft-renderer/src/lib/smoothSwitcher' const div = document.createElement('div') div.style.width = '100px' diff --git a/experiments/three-fireworks.ts b/experiments/three-fireworks.ts index 2af13de75..9190c8954 100644 --- a/experiments/three-fireworks.ts +++ b/experiments/three-fireworks.ts @@ -1,6 +1,6 @@ import * as THREE from 'three' import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js' -import { FireworksManager } from '../renderer/viewer/three/fireworks' +import { FireworksManager } from 'minecraft-renderer/src/three/fireworks' // Create scene, camera and renderer const scene = new THREE.Scene() diff --git a/experiments/three-item.ts b/experiments/three-item.ts index b9d492fe1..ed878f00f 100644 --- a/experiments/three-item.ts +++ b/experiments/three-item.ts @@ -1,7 +1,7 @@ import * as THREE from 'three' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' import itemsAtlas from 'mc-assets/dist/itemsAtlasLegacy.png' -import { createItemMeshFromCanvas, createItemMesh } from '../renderer/viewer/three/itemMesh' +import { createItemMeshFromCanvas, createItemMesh } from 'minecraft-renderer/src/three/itemMesh' // Create scene, camera and renderer const scene = new THREE.Scene() diff --git a/experiments/three-labels.ts b/experiments/three-labels.ts index b69dc95ba..af28d8192 100644 --- a/experiments/three-labels.ts +++ b/experiments/three-labels.ts @@ -1,6 +1,6 @@ import * as THREE from 'three' import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js' -import { createWaypointSprite, WAYPOINT_CONFIG } from '../renderer/viewer/three/waypointSprite' +import { createWaypointSprite, WAYPOINT_CONFIG } from 'minecraft-renderer/src/three/waypointSprite' // Create scene, camera and renderer const scene = new THREE.Scene() diff --git a/package.json b/package.json index 82fbd5e2d..0b0e4ca65 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,10 @@ "scripts": { "dev-rsbuild": "rsbuild dev", "dev-proxy": "node server.js", - "start": "run-p dev-proxy dev-rsbuild watch-mesher", - "start2": "run-p dev-rsbuild watch-mesher", + "start": "run-p dev-proxy dev-rsbuild", + "start2": "run-p dev-rsbuild", "start-metrics": "ENABLE_METRICS=true rsbuild dev", - "build": "pnpm build-other-workers && rsbuild build", + "build": "rsbuild build", "build-analyze": "BUNDLE_ANALYZE=true rsbuild build && pnpm build-other-workers", "build-single-file": "SINGLE_FILE_BUILD=true rsbuild build", "prepare-project": "tsx scripts/genShims.ts && tsx scripts/makeOptimizedMcData.mjs && tsx scripts/genLargeDataAliases.ts", @@ -20,20 +20,14 @@ "test:e2e": "start-test http-get://localhost:8080 test:cypress", "prod-start": "node server.js --prod", "test-mc-server": "tsx cypress/minecraft-server.mjs", - "lint": "eslint \"{src,cypress,renderer}/**/*.{ts,js,jsx,tsx}\"", + "lint": "eslint \"{src,cypress}/**/*.{ts,js,jsx,tsx}\"", "lint-fix": "pnpm lint --fix", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build && node scripts/build.js moveStorybookFiles", "start-experiments": "vite --config experiments/vite.config.ts --host", - "watch-other-workers": "echo NOT IMPLEMENTED", - "build-other-workers": "echo NOT IMPLEMENTED", - "build-mesher": "node renderer/buildMesherWorker.mjs", - "watch-mesher": "pnpm build-mesher -w", - "run-playground": "run-p watch-mesher watch-other-workers watch-playground", - "run-all": "run-p start run-playground", - "watch-playground": "rsbuild dev --config renderer/rsbuild.config.ts", "update-git-deps": "tsx scripts/updateGitDeps.ts", - "request-data": "tsx scripts/requestData.ts" + "request-data": "tsx scripts/requestData.ts", + "check-bundled-duplicates": "node scripts/findBundledDuplicateDeps.mjs" }, "keywords": [ "prismarine", @@ -90,6 +84,7 @@ "minecraft-data": "0.0.0", "minecraft-inventory": "^0.1.45", "minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master", + "minecraft-renderer": "^0.1.52", "mineflayer-item-map-downloader": "github:zardoy/mineflayer-item-map-downloader", "mojangson": "^2.0.4", "net-browserify": "github:zardoy/prismarinejs-net-browserify", @@ -163,7 +158,6 @@ "path-browserify": "^1.0.1", "path-exists-cli": "^2.0.0", "process": "github:PrismarineJS/node-process", - "renderer": "link:renderer", "rimraf": "^5.0.1", "storybook": "^7.4.6", "stream-browserify": "^3.0.0", @@ -202,6 +196,7 @@ "buffer": "^6.0.3", "vec3": "0.1.10", "three": "0.154.0", + "@types/three": "0.154.0", "diamond-square": "github:zardoy/diamond-square", "prismarine-block": "github:zardoy/prismarine-block#next-era", "prismarine-world": "github:zardoy/prismarine-world#next-era", @@ -211,7 +206,8 @@ "minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master", "react": "^18.2.0", "prismarine-chunk": "github:zardoy/prismarine-chunk#master", - "prismarine-item": "latest" + "prismarine-item": "latest", + "valtio": "1.13.2" }, "updateConfig": { "ignoreDependencies": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd0dbbcf4..7131d1bcf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,6 +10,7 @@ overrides: buffer: ^6.0.3 vec3: 0.1.10 three: 0.154.0 + '@types/three': 0.154.0 diamond-square: github:zardoy/diamond-square prismarine-block: github:zardoy/prismarine-block#next-era prismarine-world: github:zardoy/prismarine-world#next-era @@ -20,6 +21,7 @@ overrides: react: ^18.2.0 prismarine-chunk: github:zardoy/prismarine-chunk#master prismarine-item: latest + valtio: 1.13.2 patchedDependencies: minecraft-protocol: @@ -153,6 +155,9 @@ importers: minecraft-protocol: specifier: github:PrismarineJS/node-minecraft-protocol#master version: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/ee40987dde124cd2f560bb944cfffb29946fef81(patch_hash=a0fc92234601e93b1e536d8d7cc9bf80a9df670d821e1d12746f261d15954fae)(encoding@0.1.13) + minecraft-renderer: + specifier: ^0.1.52 + version: 0.1.52(@types/react@18.3.18)(contro-max@0.1.12(typescript@5.5.4))(mc-assets@0.2.72)(minecraft-data@3.105.0)(react@18.3.1)(three@0.154.0) mineflayer-item-map-downloader: specifier: github:zardoy/mineflayer-item-map-downloader version: https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824(patch_hash=a731ebbace2d8790c973ab3a5ba33494a6e9658533a9710dd8ba36f86db061ad)(encoding@0.1.13) @@ -238,7 +243,7 @@ importers: specifier: ^4.0.2 version: 4.0.2(react@18.3.1)(typescript@5.5.4) valtio: - specifier: ^1.11.1 + specifier: 1.13.2 version: 1.13.2(@types/react@18.3.18)(react@18.3.1) vec3: specifier: 0.1.10 @@ -367,9 +372,6 @@ importers: process: specifier: github:PrismarineJS/node-process version: https://codeload.github.com/PrismarineJS/node-process/tar.gz/380d0b4f4c86f1b65b216c311bf00431f314e88e - renderer: - specifier: link:renderer - version: link:renderer rimraf: specifier: ^5.0.1 version: 5.0.10 @@ -408,83 +410,6 @@ importers: specifier: ^5.21.22 version: 5.25.11 - renderer: - dependencies: - '@tweenjs/tween.js': - specifier: ^20.0.3 - version: 20.0.3 - assert: - specifier: ^2.0.0 - version: 2.1.0 - buffer: - specifier: ^6.0.3 - version: 6.0.3 - filesize: - specifier: ^10.0.12 - version: 10.1.6 - fs-extra: - specifier: ^11.0.0 - version: 11.3.0 - lil-gui: - specifier: ^0.18.2 - version: 0.18.2 - minecraft-wrap: - specifier: ^1.3.0 - version: 1.6.0(encoding@0.1.13) - minecrafthawkeye: - specifier: ^1.3.6 - version: 1.3.9 - prismarine-block: - specifier: github:zardoy/prismarine-block#next-era - version: https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad - prismarine-chunk: - specifier: github:zardoy/prismarine-chunk#master - version: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/1eb3a5d85dffe18b7b504c6e5871c4b36681df1a(minecraft-data@3.105.0) - prismarine-schematic: - specifier: ^1.2.0 - version: 1.2.3 - process: - specifier: ^0.11.10 - version: 0.11.10 - renderer: - specifier: link:./ - version: 'link:' - socket.io: - specifier: ^4.0.0 - version: 4.8.1 - socket.io-client: - specifier: ^4.0.0 - version: 4.8.1 - three-stdlib: - specifier: ^2.26.11 - version: 2.35.14(three@0.154.0) - three.meshline: - specifier: ^1.3.0 - version: 1.4.0 - tsx: - specifier: ^4.7.0 - version: 4.19.3 - vec3: - specifier: 0.1.10 - version: 0.1.10 - devDependencies: - live-server: - specifier: ^1.2.2 - version: 1.2.2 - optionalDependencies: - canvas: - specifier: ^2.11.2 - version: 2.11.2(encoding@0.1.13) - node-canvas-webgl: - specifier: ^0.3.0 - version: 0.3.0(encoding@0.1.13) - - renderer/viewer/sign-renderer: - dependencies: - vite: - specifier: ^4.4.9 - version: 4.5.9(@types/node@22.13.9)(terser@5.39.0) - packages: '@ampproject/remapping@2.3.0': @@ -1595,9 +1520,6 @@ packages: '@floating-ui/utils@0.2.9': resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} - '@gar/promisify@1.1.3': - resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} - '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -1980,10 +1902,6 @@ packages: '@juggle/resize-observer@3.4.0': resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==} - '@mapbox/node-pre-gyp@1.0.11': - resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} - hasBin: true - '@mdx-js/react@2.3.0': resolution: {integrity: sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g==} peerDependencies: @@ -2036,15 +1954,6 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@npmcli/fs@2.1.2': - resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - '@npmcli/move-file@2.0.1': - resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - deprecated: This functionality has been moved to @npmcli/fs - '@nxg-org/mineflayer-auto-jump@0.7.18': resolution: {integrity: sha512-O/nRCyWrRwFpcCXXSJhmt844c4a8KhkK4OJPAOKSc63tExIIQU/sipHgjgpy0B+gVDjSmLMPYXe71CN0W327Wg==} @@ -2762,9 +2671,6 @@ packages: '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - '@socket.io/component-emitter@3.1.2': - resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} - '@storybook/addon-actions@7.6.20': resolution: {integrity: sha512-c/GkEQ2U9BC/Ew/IMdh+zvsh4N6y6n7Zsn2GIhJgcu9YEAa5aF2a9/pNgEGBMOABH959XE8DAOMERw/5qiLR8g==} @@ -2991,9 +2897,6 @@ packages: '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - '@types/cors@2.8.17': - resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} - '@types/cross-spawn@6.0.6': resolution: {integrity: sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==} @@ -3033,6 +2936,9 @@ packages: '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/events@3.0.3': + resolution: {integrity: sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==} + '@types/express-serve-static-core@4.19.6': resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} @@ -3147,9 +3053,6 @@ packages: '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - '@types/rbush@3.0.4': - resolution: {integrity: sha512-knSt9cCW8jj1ZSFcFeBZaX++OucmfPxxHiRwTahZfJlnQsek7O0bazTJHWD2RVj9LEoejUYF2de3/stf+QXcXw==} - '@types/react-dom@18.3.5': resolution: {integrity: sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==} peerDependencies: @@ -3172,9 +3075,6 @@ packages: '@types/resolve@1.20.6': resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} - '@types/sat@0.0.31': - resolution: {integrity: sha512-P4SVw79XheP1p92useDVpLYYOUQ6lpw2L7IdQz4dD23DZ8DiC1STgPOh72hjR5IZJBPQbzlICAbmjCKbwyYuxg==} - '@types/semver@7.5.8': resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} @@ -3196,9 +3096,6 @@ packages: '@types/three@0.154.0': resolution: {integrity: sha512-IioqpGhch6FdLDh4zazRn3rXHj6Vn2nVOziJdXVbJFi9CaI65LtP9qqUtpzbsHK2Ezlox8NtsLNHSw3AQzucjA==} - '@types/three@0.156.0': - resolution: {integrity: sha512-733bXDSRdlrxqOmQuOmfC1UBRuJ2pREPk8sWnx9MtIJEVDQMx8U0NQO5MVVaOrjzDPyLI+cFPim2X/ss9v0+LQ==} - '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -3497,14 +3394,6 @@ packages: resolution: {integrity: sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==} engines: {node: '>= 6.0.0'} - agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - - agentkeepalive@4.6.0: - resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} - engines: {node: '>= 8.0.0'} - aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} @@ -3553,43 +3442,16 @@ packages: any-base@1.1.0: resolution: {integrity: sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==} - any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - - anymatch@2.0.0: - resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==} - anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} - apache-crypt@1.2.6: - resolution: {integrity: sha512-072WetlM4blL8PREJVeY+WHiUh1R5VNt2HfceGS8aKqttPHcmqE5pkKuXPz/ULmJOFkc8Hw3kfKl6vy7Qka6DA==} - engines: {node: '>=8'} - - apache-md5@1.1.8: - resolution: {integrity: sha512-FCAJojipPn0bXjuEpjOOOMN8FZDkxfWWp4JGN9mifU2IhxvKyXZYqpzPHdnTSUpmPDy+tsslB6Z1g+Vg6nVbYA==} - engines: {node: '>=8'} - app-root-dir@1.0.2: resolution: {integrity: sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g==} - aproba@2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - arch@2.2.0: resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} - are-we-there-yet@2.0.0: - resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} - engines: {node: '>=10'} - deprecated: This package is no longer supported. - - are-we-there-yet@3.0.1: - resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - deprecated: This package is no longer supported. - argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -3600,18 +3462,6 @@ packages: resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==} engines: {node: '>=10'} - arr-diff@4.0.0: - resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} - engines: {node: '>=0.10.0'} - - arr-flatten@1.1.0: - resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} - engines: {node: '>=0.10.0'} - - arr-union@3.1.0: - resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} - engines: {node: '>=0.10.0'} - array-buffer-byte-length@1.0.2: resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} engines: {node: '>= 0.4'} @@ -3631,10 +3481,6 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - array-unique@0.3.2: - resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} - engines: {node: '>=0.10.0'} - array.prototype.findlast@1.2.5: resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} engines: {node: '>= 0.4'} @@ -3681,10 +3527,6 @@ packages: assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - assign-symbols@1.0.0: - resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} - engines: {node: '>=0.10.0'} - ast-types@0.16.1: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} @@ -3693,9 +3535,6 @@ packages: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} - async-each@1.0.6: - resolution: {integrity: sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==} - async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} @@ -3716,11 +3555,6 @@ packages: resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} engines: {node: '>= 4.0.0'} - atob@2.1.2: - resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} - engines: {node: '>= 4.5.0'} - hasBin: true - available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -3782,23 +3616,13 @@ packages: resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} engines: {node: ^4.5.0 || >= 5.9} - base@0.11.2: - resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} - engines: {node: '>=0.10.0'} - basic-auth@2.0.1: resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} engines: {node: '>= 0.8'} - batch@0.6.1: - resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} - bcrypt-pbkdf@1.0.2: resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} - bcryptjs@2.4.3: - resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==} - better-opn@3.0.2: resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} engines: {node: '>=12.0.0'} @@ -3807,20 +3631,10 @@ packages: resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} engines: {node: '>=0.6'} - binary-extensions@1.13.1: - resolution: {integrity: sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==} - engines: {node: '>=0.10.0'} - binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - bindings@1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - - bit-twiddle@1.0.2: - resolution: {integrity: sha512-B9UhK0DKFZhoTFcfvAzhqsjStvGJp9vYWf3+6SNTtdSQnvIgfkHbgHrg/e4+TH71N2GDu8tpmCVoyfrL1d7ntA==} - bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -3859,10 +3673,6 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - braces@2.3.2: - resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} - engines: {node: '>=0.10.0'} - braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -3951,14 +3761,6 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - cacache@16.1.3: - resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - cache-base@1.0.1: - resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} - engines: {node: '>=0.10.0'} - cachedir@2.4.0: resolution: {integrity: sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==} engines: {node: '>=6'} @@ -3997,10 +3799,6 @@ packages: caniuse-lite@1.0.30001713: resolution: {integrity: sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q==} - canvas@2.11.2: - resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} - engines: {node: '>=6'} - capital-case@1.0.4: resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} @@ -4045,9 +3843,6 @@ packages: resolution: {integrity: sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==} engines: {node: '>= 0.8.0'} - chokidar@2.1.8: - resolution: {integrity: sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==} - chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -4070,10 +3865,6 @@ packages: citty@0.1.6: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} - class-utils@0.3.6: - resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} - engines: {node: '>=0.10.0'} - classnames@2.5.1: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} @@ -4117,10 +3908,6 @@ packages: resolution: {integrity: sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==} engines: {node: '>=6'} - collection-visit@1.0.0: - resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} - engines: {node: '>=0.10.0'} - color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -4137,10 +3924,6 @@ packages: color-string@1.9.1: resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - color-support@1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - color@4.2.3: resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} engines: {node: '>=12.5.0'} @@ -4148,10 +3931,6 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - colors@1.4.0: - resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} - engines: {node: '>=0.1.90'} - combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -4207,10 +3986,6 @@ packages: confusing-browser-globals@1.0.11: resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} - connect@3.7.0: - resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} - engines: {node: '>= 0.10.0'} - consola@3.4.0: resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==} engines: {node: ^14.18.0 || >=16.10.0} @@ -4218,9 +3993,6 @@ packages: console-browserify@1.2.0: resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} - console-control-strings@1.1.0: - resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - constant-case@3.0.4: resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==} @@ -4256,14 +4028,6 @@ packages: resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} - cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} - engines: {node: '>= 0.6'} - - copy-descriptor@0.1.1: - resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} - engines: {node: '>=0.10.0'} - copy-to-clipboard@3.3.3: resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} @@ -4283,10 +4047,6 @@ packages: resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} engines: {node: '>= 0.10'} - cors@2.8.6: - resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} - engines: {node: '>= 0.10'} - corser@2.0.1: resolution: {integrity: sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==} engines: {node: '>= 0.4.0'} @@ -4412,8 +4172,8 @@ packages: supports-color: optional: true - debug@4.3.7: - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -4421,8 +4181,8 @@ packages: supports-color: optional: true - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -4454,14 +4214,6 @@ packages: decode-named-character-reference@1.1.0: resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==} - decode-uri-component@0.2.2: - resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} - engines: {node: '>=0.10'} - - decompress-response@4.2.1: - resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==} - engines: {node: '>=8'} - decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} @@ -4484,6 +4236,9 @@ packages: deepslate@0.23.5: resolution: {integrity: sha512-FjBBbuPUI1Y/dXtUc4WiCJSA7s7yRAXepD7qWRF6wX5m/q7AVRauMEShu8lphRvqCtJyxcYFZmISwX5OOH/tWw==} + deepslate@0.24.0: + resolution: {integrity: sha512-j0Ej3N06dJ0zhY8UW3KtTRFadpGmk1eHNCY57tX4FKutFVzQGcieljeNiJ/slUdZBeh1HZxtJzGMbC9+RIN0Tg==} + default-browser-id@3.0.0: resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==} engines: {node: '>=12'} @@ -4503,18 +4258,6 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} - define-property@0.2.5: - resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} - engines: {node: '>=0.10.0'} - - define-property@1.0.0: - resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} - engines: {node: '>=0.10.0'} - - define-property@2.0.2: - resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} - engines: {node: '>=0.10.0'} - defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} @@ -4526,13 +4269,6 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - - depd@1.1.2: - resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} - engines: {node: '>= 0.6'} - depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -4544,7 +4280,7 @@ packages: derive-valtio@0.1.0: resolution: {integrity: sha512-OCg2UsLbXK7GmmpzMXhYkdO64vhJ1ROUUGaTFyHjVwEdMEcTTRj7W1TxLbSBxdY8QLBPCcp66MTyaSy0RpO17A==} peerDependencies: - valtio: '*' + valtio: 1.13.2 des.js@1.1.0: resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} @@ -4553,9 +4289,6 @@ packages: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - detect-collisions@7.0.5: - resolution: {integrity: sha512-RiebSYJ9Vok1uVm57bxpI69EO2ySK1rdcHpRv28IDBh/wgaF8wxjoZJV7mmqz8MOKioLwMHvcMyP1R0CLZ+RbA==} - detect-indent@6.1.0: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} @@ -4720,24 +4453,13 @@ packages: engine.io-client@3.5.4: resolution: {integrity: sha512-ydc8uuMMDxC5KCKNJN3zZKYJk2sgyTuTZQ7Aj1DJSsLKAcizA/PzWivw8fZMIjJVBo2CJOYzntv4FSjY/Lr//g==} - engine.io-client@6.6.3: - resolution: {integrity: sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==} - engine.io-parser@2.2.1: resolution: {integrity: sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==} - engine.io-parser@5.2.3: - resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} - engines: {node: '>=10.0.0'} - engine.io@3.6.2: resolution: {integrity: sha512-C4JjGQZLY3kWlIDx0BQNKizbrfpb7NahxDztGdN5jrPK2ghmXiNDN+E/t0JzDeNRZxPVaszxEng42Pmj27X/0w==} engines: {node: '>=8.0.0'} - engine.io@6.6.4: - resolution: {integrity: sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==} - engines: {node: '>=10.2.0'} - enquirer@2.4.1: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} @@ -4746,18 +4468,11 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - envinfo@7.14.0: resolution: {integrity: sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==} engines: {node: '>=4'} hasBin: true - err-code@2.0.3: - resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -4806,12 +4521,6 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} - es6-promise@4.2.8: - resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} - - es6-promisify@5.0.0: - resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} - esbuild-plugin-alias@0.2.1: resolution: {integrity: sha512-jyfL/pwPqaFXyKnj8lP8iLk6Z0m099uXR45aSN8Av1XD4vhvQutxxPzgA2bTcAwQpa1zCXDcWOlhFgyP3GKqhQ==} @@ -5044,9 +4753,6 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} - event-stream@3.3.4: - resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} - event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -5083,17 +4789,10 @@ packages: resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} engines: {node: '>=6'} - expand-brackets@2.1.4: - resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} - engines: {node: '>=0.10.0'} - expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} - exponential-backoff@3.1.2: - resolution: {integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==} - express-ws@4.0.0: resolution: {integrity: sha512-KEyUw8AwRET2iFjFsI1EJQrJ/fHeGiJtgpYgEWG3yDv4l/To/m3a2GaYfeGyB3lsWdvbesjF5XCMx+SVBgAAYw==} engines: {node: '>=4.5.0'} @@ -5104,21 +4803,9 @@ packages: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} - extend-shallow@2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} - - extend-shallow@3.0.2: - resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} - engines: {node: '>=0.10.0'} - extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - extglob@2.0.4: - resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} - engines: {node: '>=0.10.0'} - extract-zip@1.7.0: resolution: {integrity: sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==} hasBin: true @@ -5157,10 +4844,6 @@ packages: fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} - faye-websocket@0.11.4: - resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} - engines: {node: '>=0.8.0'} - fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} @@ -5188,9 +4871,6 @@ packages: resolution: {integrity: sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==} engines: {node: '>=6'} - file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} @@ -5198,18 +4878,10 @@ packages: resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} engines: {node: '>= 10.4.0'} - fill-range@4.0.0: - resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} - engines: {node: '>=0.10.0'} - fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - finalhandler@1.1.2: - resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} - engines: {node: '>= 0.8'} - finalhandler@1.3.1: resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} @@ -5264,10 +4936,6 @@ packages: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} - for-in@1.0.2: - resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} - engines: {node: '>=0.10.0'} - foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} @@ -5287,10 +4955,6 @@ packages: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} - fragment-cache@0.2.1: - resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} - engines: {node: '>=0.10.0'} - framer-motion@12.9.2: resolution: {integrity: sha512-R0O3Jdqbfwywpm45obP+8sTgafmdEcUoShQTAV+rB5pi+Y1Px/FYL5qLLRe5tPtBdN1J4jos7M+xN2VV2oEAbQ==} peerDependencies: @@ -5309,13 +4973,6 @@ packages: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} - fresh@2.0.0: - resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} - engines: {node: '>= 0.8'} - - from@0.1.7: - resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} - fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} @@ -5342,12 +4999,6 @@ packages: fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@1.2.13: - resolution: {integrity: sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==} - engines: {node: '>= 4.0'} - os: [darwin] - deprecated: Upgrade to fsevents v2 to mitigate potential security issues - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -5363,16 +5014,6 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - gauge@3.0.2: - resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} - engines: {node: '>=10'} - deprecated: This package is no longer supported. - - gauge@4.0.4: - resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - deprecated: This package is no longer supported. - gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -5426,10 +5067,6 @@ packages: get-tsconfig@4.10.0: resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} - get-value@2.0.6: - resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} - engines: {node: '>=0.10.0'} - getos@3.2.1: resolution: {integrity: sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==} @@ -5449,13 +5086,6 @@ packages: gl-matrix@3.4.3: resolution: {integrity: sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==} - gl@6.0.2: - resolution: {integrity: sha512-yBbfpChOtFvg5D+KtMaBFvj6yt3vUnheNAH+UrQH2TfDB8kr0tERdL0Tjhe0W7xJ6jR6ftQBluTZR9jXUnKe8g==} - engines: {node: '>=14.0.0'} - - glob-parent@3.1.0: - resolution: {integrity: sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==} - glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -5482,11 +5112,6 @@ packages: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - global-dirs@3.0.1: resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} engines: {node: '>=10'} @@ -5510,9 +5135,6 @@ packages: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} - glsl-tokenizer@2.1.5: - resolution: {integrity: sha512-XSZEJ/i4dmz3Pmbnpsy3cKh7cotvFlBiZnDOwnj/05EwNp2XrhQ4XKJxT7/pDt4kp4YcpRSKz8eTV7S+mwV6MA==} - gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -5573,25 +5195,6 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - has-unicode@2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - - has-value@0.3.1: - resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} - engines: {node: '>=0.10.0'} - - has-value@1.0.0: - resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} - engines: {node: '>=0.10.0'} - - has-values@0.1.4: - resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} - engines: {node: '>=0.10.0'} - - has-values@1.0.0: - resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} - engines: {node: '>=0.10.0'} - has@1.0.4: resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} engines: {node: '>= 0.4.0'} @@ -5642,35 +5245,16 @@ packages: resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} engines: {node: '>=8'} - http-auth@3.1.3: - resolution: {integrity: sha512-Jbx0+ejo2IOx+cRUYAGS1z6RGc6JfYUNkysZM4u4Sfk1uLlGv814F7/PIjQQAuThLdAWxb74JMGd5J8zex1VQg==} - engines: {node: '>=4.6.1'} - http-browserify@1.7.0: resolution: {integrity: sha512-Irf/LJXmE3cBzU1eaR4+NEX6bmVLqt1wkmDiA7kBwH7zmb0D8kBAXsDmQ88hhj/qv9iEZKlyGx/hrMcFi8sOHw==} http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - http-errors@1.6.3: - resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==} - engines: {node: '>= 0.6'} - http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} - http-errors@2.0.1: - resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} - engines: {node: '>= 0.8'} - - http-parser-js@0.5.9: - resolution: {integrity: sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==} - - http-proxy-agent@5.0.0: - resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} - engines: {node: '>= 6'} - http-proxy@1.18.1: resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} engines: {node: '>=8.0.0'} @@ -5691,10 +5275,6 @@ packages: resolution: {integrity: sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==} engines: {node: '>= 6.0.0'} - https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - human-signals@1.1.1: resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} engines: {node: '>=8.12.0'} @@ -5703,9 +5283,6 @@ packages: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} - humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - hyperdyperid@1.2.0: resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} engines: {node: '>=10.18'} @@ -5761,16 +5338,10 @@ packages: indexof@0.0.1: resolution: {integrity: sha512-i0G7hLJ1z0DE8dsqJa2rycj9dBmNKgXBvotXtZYXakU9oivfB9Uj2ZBC27qqef2U58/ZLwalxa1X/RDCdkHtVg==} - infer-owner@1.0.4: - resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} - inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - inherits@2.0.3: - resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} - inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -5788,10 +5359,6 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - ip-address@9.0.5: - resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} - engines: {node: '>= 12'} - ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -5800,10 +5367,6 @@ packages: resolution: {integrity: sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==} engines: {node: '>=8'} - is-accessor-descriptor@1.0.1: - resolution: {integrity: sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==} - engines: {node: '>= 0.10'} - is-arguments@1.2.0: resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} engines: {node: '>= 0.4'} @@ -5826,10 +5389,6 @@ packages: resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} engines: {node: '>= 0.4'} - is-binary-path@1.0.1: - resolution: {integrity: sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==} - engines: {node: '>=0.10.0'} - is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -5857,10 +5416,6 @@ packages: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} - is-data-descriptor@1.0.1: - resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==} - engines: {node: '>= 0.4'} - is-data-view@1.0.2: resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} engines: {node: '>= 0.4'} @@ -5872,27 +5427,11 @@ packages: is-deflate@1.0.0: resolution: {integrity: sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==} - is-descriptor@0.1.7: - resolution: {integrity: sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==} - engines: {node: '>= 0.4'} - - is-descriptor@1.0.3: - resolution: {integrity: sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==} - engines: {node: '>= 0.4'} - is-docker@2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} hasBin: true - is-extendable@0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} - - is-extendable@1.0.1: - resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} - engines: {node: '>=0.10.0'} - is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -5912,10 +5451,6 @@ packages: resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} engines: {node: '>= 0.4'} - is-glob@3.1.0: - resolution: {integrity: sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==} - engines: {node: '>=0.10.0'} - is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -5932,9 +5467,6 @@ packages: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} - is-lambda@1.0.1: - resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} - is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -5954,10 +5486,6 @@ packages: resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} - is-number@3.0.0: - resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} - engines: {node: '>=0.10.0'} - is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -6041,21 +5569,10 @@ packages: resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} engines: {node: '>= 0.4'} - is-windows@1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - - is-wsl@1.1.0: - resolution: {integrity: sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==} - engines: {node: '>=4'} - is-wsl@2.2.0: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} - isarray@0.0.1: - resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} - isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} @@ -6068,10 +5585,6 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - isobject@2.1.0: - resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} - engines: {node: '>=0.10.0'} - isobject@3.0.1: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} @@ -6148,9 +5661,6 @@ packages: jsbn@0.1.1: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} - jsbn@1.1.0: - resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - jscodeshift@0.15.2: resolution: {integrity: sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==} hasBin: true @@ -6241,14 +5751,6 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - kind-of@3.2.2: - resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} - engines: {node: '>=0.10.0'} - - kind-of@4.0.0: - resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} - engines: {node: '>=0.10.0'} - kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} @@ -6279,9 +5781,6 @@ packages: lil-gui@0.17.0: resolution: {integrity: sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ==} - lil-gui@0.18.2: - resolution: {integrity: sha512-DgdrLy3/KGC0PiQLKgOcJMPItP4xY4iWgJ9+91Zaxfr8GCTmMps05QS9w9jW7yspILlbscbquwjOwxmWnSx5Uw==} - lil-gui@0.21.0: resolution: {integrity: sha512-tpvxN7v1GvE/Tv+GRopfOp0W7fVEjF4PltkuX8vOCIfim22rD1ztvfkoEMcv9lzQeuNUSeIrUmUjBwmlW/oUew==} @@ -6300,11 +5799,6 @@ packages: enquirer: optional: true - live-server@1.2.2: - resolution: {integrity: sha512-t28HXLjITRGoMSrCOv4eZ88viHaBVIjKjdI5PO92Vxlu+twbk6aE0t7dVIaz6ZWkjPilYFV6OSdMYl9ybN2B4w==} - engines: {node: '>=0.10.0'} - hasBin: true - load-bmfont@1.4.2: resolution: {integrity: sha512-qElWkmjW9Oq1F9EI5Gt7aD9zcdHb9spJCW1L/dmPf7KzCCEJxq8nhHz5eCgI9aMf7vrG/wyaCqdsI+Iy9ZTlog==} @@ -6408,10 +5902,6 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} - lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - macaddress@0.5.3: resolution: {integrity: sha512-vGBKTA+jwM4KgjGZ+S/8/Mkj9rWzePyGY6jManXPGhiWu63RYwW8dKPyk5koP+8qNVhPhHgFa1y/MJ4wrjsNrg==} @@ -6433,17 +5923,9 @@ packages: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} - make-fetch-happen@10.2.1: - resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - map-cache@0.2.2: - resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} - engines: {node: '>=0.10.0'} - map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} engines: {node: '>=0.10.0'} @@ -6455,13 +5937,6 @@ packages: map-or-similar@1.5.0: resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==} - map-stream@0.1.0: - resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} - - map-visit@1.0.0: - resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} - engines: {node: '>=0.10.0'} - markdown-it@14.1.0: resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} hasBin: true @@ -6497,11 +5972,6 @@ packages: '@roamhq/wrtc': optional: true - md5-file@4.0.0: - resolution: {integrity: sha512-UC0qFwyAjn4YdPpKaDNw6gNxRf7Mcx7jC1UGCY4boCzgvU2Aoc1mOGzTtrjjLKhM5ivsnhoKpQVxKPp+1j1qwg==} - engines: {node: '>=6.0'} - hasBin: true - md5.js@1.3.5: resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} @@ -6637,10 +6107,6 @@ packages: micromark@4.0.2: resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} - micromatch@3.1.10: - resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} - engines: {node: '>=0.10.0'} - micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -6661,10 +6127,6 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} - mime-types@3.0.2: - resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} - engines: {node: '>=18'} - mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} @@ -6679,10 +6141,6 @@ packages: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} - mimic-response@2.1.0: - resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} - engines: {node: '>=8'} - mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} @@ -6717,22 +6175,31 @@ packages: version: 1.66.2 engines: {node: '>=22'} - minecraft-wrap@1.6.0: - resolution: {integrity: sha512-A1GjIR72x9H9cEaxAQsXZe5uhw7CPgq1pGwYkdbPe6mQraePinmj/jRIuntXYWEKrYamwQFT3igIafA+PEG11w==} - hasBin: true - - minecrafthawkeye@1.3.9: - resolution: {integrity: sha512-YIDHTvljQjsJH4cEcbF02/ehNRUrbzEiL/quQmdEU8ruv69R4bwHqmBB8O9FyhpQgNppmNTs3pK8h4J0/MYGpQ==} - - mineflayer-item-map-downloader@https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824: - resolution: {tarball: https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824} - version: 1.2.0 - - mineflayer-mouse@0.1.28: - resolution: {integrity: sha512-31r73CqU7eiv8cQSVA+NMR0WfA8Qs+p6of+Bd7ApWzR4a56W6fgfY3MExNmxxbb1/w9IbxTcMhDbcoKmE/5+nw==} + minecraft-renderer@0.1.52: + resolution: {integrity: sha512-XoU3JOFl+F8Fb55MiEv1Ef2s4hGUaMHm2Nr8pAgOyETvvkftcVFJBQBpqGKkdfEdJym9n87QfBGpt5+LAyOUIQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/6fe34e32c19657020cc48d95039e4b89361200b2: + peerDependencies: + contro-max: '*' + mc-assets: '>=0.2.0' + minecraft-data: 3.105.0 + three: 0.154.0 + peerDependenciesMeta: + contro-max: + optional: true + mc-assets: + optional: true + minecraft-data: + optional: true + + mineflayer-item-map-downloader@https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824: + resolution: {tarball: https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824} + version: 1.2.0 + + mineflayer-mouse@0.1.28: + resolution: {integrity: sha512-31r73CqU7eiv8cQSVA+NMR0WfA8Qs+p6of+Bd7ApWzR4a56W6fgfY3MExNmxxbb1/w9IbxTcMhDbcoKmE/5+nw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/6fe34e32c19657020cc48d95039e4b89361200b2: resolution: {tarball: https://codeload.github.com/zardoy/mineflayer/tar.gz/6fe34e32c19657020cc48d95039e4b89361200b2} version: 8.0.0 engines: {node: '>=22'} @@ -6765,26 +6232,6 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass-collect@1.0.2: - resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} - engines: {node: '>= 8'} - - minipass-fetch@2.1.2: - resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - minipass-flush@1.0.5: - resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} - engines: {node: '>= 8'} - - minipass-pipeline@1.2.4: - resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} - engines: {node: '>=8'} - - minipass-sized@1.0.3: - resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} - engines: {node: '>=8'} - minipass@3.3.6: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} @@ -6801,10 +6248,6 @@ packages: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} - mixin-deep@1.3.2: - resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} - engines: {node: '>=0.10.0'} - mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} @@ -6838,10 +6281,6 @@ packages: moo@0.5.2: resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==} - morgan@1.10.0: - resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==} - engines: {node: '>= 0.8.0'} - motion-dom@12.9.1: resolution: {integrity: sha512-xqXEwRLDYDTzOgXobSoWtytRtGlf7zdkRfFbrrdP7eojaGQZ5Go4OOKtgnx7uF8sAkfr1ZjMvbCJSCIT2h6fkQ==} @@ -6854,12 +6293,6 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - - nan@2.22.2: - resolution: {integrity: sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==} - nano-css@5.6.2: resolution: {integrity: sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==} peerDependencies: @@ -6871,10 +6304,6 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanomatch@1.2.13: - resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} - engines: {node: '>=0.10.0'} - napi-build-utils@2.0.0: resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} @@ -6916,9 +6345,6 @@ packages: node-addon-api@5.1.0: resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} - node-canvas-webgl@0.3.0: - resolution: {integrity: sha512-wDRCTEE2TCqKDeSef5cNgtLv8kgjRlnFN3aYgB9yni0kHRNnKBSSP93lT8VIV5GuMWiy5KNXBU0ilyWL5wTvFg==} - node-dir@0.1.17: resolution: {integrity: sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==} engines: {node: '>= 0.10.5'} @@ -6935,11 +6361,6 @@ packages: encoding: optional: true - node-gyp@9.4.1: - resolution: {integrity: sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==} - engines: {node: ^12.13 || ^14.13 || >=16} - hasBin: true - node-gzip@1.1.2: resolution: {integrity: sha512-ZB6zWpfZHGtxZnPMrJSKHVPrRjURoUzaDbLFj3VO70mpLTW5np96vXyHwft4Id0o+PYIzgDkBUjIzaNHhQ8srw==} @@ -6962,16 +6383,6 @@ packages: resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} hasBin: true - nopt@5.0.0: - resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} - engines: {node: '>=6'} - hasBin: true - - nopt@6.0.0: - resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - hasBin: true - normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -6979,10 +6390,6 @@ packages: resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} engines: {node: '>=10'} - normalize-path@2.1.1: - resolution: {integrity: sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==} - engines: {node: '>=0.10.0'} - normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -6996,15 +6403,6 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} - npmlog@5.0.1: - resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - deprecated: This package is no longer supported. - - npmlog@6.0.2: - resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - deprecated: This package is no longer supported. - nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} @@ -7017,10 +6415,6 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - object-copy@0.1.0: - resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} - engines: {node: '>=0.10.0'} - object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} @@ -7033,10 +6427,6 @@ packages: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - object-visit@1.0.1: - resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} - engines: {node: '>=0.10.0'} - object.assign@4.1.7: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} @@ -7049,10 +6439,6 @@ packages: resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} engines: {node: '>= 0.4'} - object.pick@1.3.0: - resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} - engines: {node: '>=0.10.0'} - object.values@1.2.1: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} @@ -7060,10 +6446,6 @@ packages: omggif@1.0.10: resolution: {integrity: sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==} - on-finished@2.3.0: - resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} - engines: {node: '>= 0.8'} - on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} @@ -7087,11 +6469,6 @@ packages: resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} hasBin: true - opn@6.0.0: - resolution: {integrity: sha512-I9PKfIZC+e4RXZ/qr1RhgyCnGgYX0UEIlXgWnCOVACIvFgaC9rz6Won7xbdhoHrd8IIhV7YEpHjreNUNkqCGkQ==} - engines: {node: '>=8'} - deprecated: The package has been renamed to `open` - optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -7201,19 +6578,12 @@ packages: pascal-case@3.1.2: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} - pascalcase@0.1.1: - resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} - engines: {node: '>=0.10.0'} - path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} path-case@3.0.4: resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} - path-dirname@1.0.2: - resolution: {integrity: sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==} - path-exists-cli@2.0.0: resolution: {integrity: sha512-qGr0A87KYCznmvabblxyxnzA/MtPZ28wH+4SCMP4tjTFAbzqwvs5xpUZExAYzq5OgHe5vIswzdH5iosCb8YF/Q==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -7270,9 +6640,6 @@ packages: pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - pause-stream@0.0.11: - resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} - pbkdf2@3.1.2: resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} engines: {node: '>=0.12'} @@ -7368,17 +6735,10 @@ packages: resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==} engines: {node: '>=10'} - poly-decomp@0.3.0: - resolution: {integrity: sha512-hWeBxGzPYiybmI4548Fca7Up/0k1qS5+79cVHI9+H33dKya5YNb9hxl0ZnDaDgvrZSuYFBhkCK/HOnqN7gefkQ==} - portfinder@1.0.33: resolution: {integrity: sha512-+2jndHT63cL5MdQOwDm9OT2dIe11zVpjV+0GGRXdtO1wpPxv260NfVqoEXtYAi/shanmm3W4+yLduIe55ektTw==} engines: {node: '>= 0.12.0'} - posix-character-classes@0.1.1: - resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} - engines: {node: '>=0.10.0'} - possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} @@ -7474,9 +6834,6 @@ packages: prismarine-registry@1.11.0: resolution: {integrity: sha512-uTvWE+bILxYv4i5MrrlxPQ0KYWINv1DJ3P2570GLC8uCdByDiDLBFfVyk4BrqOZBlDBft9CnaJMeOsC1Ly1iXw==} - prismarine-schematic@1.2.3: - resolution: {integrity: sha512-Mwpn43vEHhm3aw3cPhJjWqztkW+nX+QLajDHlTask8lEOTGl1WmpvFja4iwiws4GIvaC8x0Foptf4uvDsnjrAg==} - prismarine-windows@2.9.0: resolution: {integrity: sha512-fm4kOLjGFPov7TEJRmXHoiPabxIQrG36r2mDjlNxfkcLfMHFb3/1ML6mp4iRQa7wL0GK4DIAyiBqCWoeWDxARg==} @@ -7501,22 +6858,6 @@ packages: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} - promise-inflight@1.0.1: - resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} - peerDependencies: - bluebird: '*' - peerDependenciesMeta: - bluebird: - optional: true - - promise-queue@2.2.5: - resolution: {integrity: sha512-p/iXrPSVfnqPft24ZdNNLECw/UrtLTpT3jpAAMzl/o5/rDsGCPo3/CQS2611flL6LkoEJ3oQZw7C8Q80ZISXRQ==} - engines: {node: '>= 0.8.0'} - - promise-retry@2.0.1: - resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} - engines: {node: '>=10'} - prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} @@ -7578,9 +6919,6 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} - proxy-compare@2.5.1: - resolution: {integrity: sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA==} - proxy-compare@2.6.0: resolution: {integrity: sha512-8xuCeM3l8yqdmbPoYeLbrAXCBWu19XEYc5/F28f5qOaoAIMyfmBUkl5axiK+x9olUvRlcekvnm98AP9RDngOIw==} @@ -7590,10 +6928,6 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - proxy-middleware@0.15.0: - resolution: {integrity: sha512-EGCG8SeoIRVMhsqHQUdDigB2i7qU7fCsWASwn54+nPutYO8n4q6EiwMzyfWlC+dzRFExP+kvcnDFdBDHoZBU7Q==} - engines: {node: '>=0.8.0'} - psl@1.15.0: resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} @@ -7655,9 +6989,6 @@ packages: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} - quickselect@2.0.0: - resolution: {integrity: sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==} - railroad-diagrams@1.0.0: resolution: {integrity: sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==} @@ -7697,9 +7028,6 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} - rbush@3.0.1: - resolution: {integrity: sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==} - rc@1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true @@ -7860,9 +7188,6 @@ packages: resolution: {integrity: sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==} engines: {node: '>=12'} - readable-stream@1.0.34: - resolution: {integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==} - readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} @@ -7874,10 +7199,6 @@ packages: resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - readdirp@2.2.1: - resolution: {integrity: sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==} - engines: {node: '>=0.10'} - readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -7916,10 +7237,6 @@ packages: regenerator-transform@0.15.2: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} - regex-not@1.0.2: - resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} - engines: {node: '>=0.10.0'} - regexp-tree@0.1.27: resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true @@ -7962,17 +7279,6 @@ packages: remark@15.0.1: resolution: {integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==} - remove-trailing-separator@1.1.0: - resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} - - repeat-element@1.1.4: - resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} - engines: {node: '>=0.10.0'} - - repeat-string@1.6.1: - resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} - engines: {node: '>=0.10'} - request-progress@3.0.0: resolution: {integrity: sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==} @@ -8001,10 +7307,6 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve-url@0.2.1: - resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} - deprecated: https://github.com/lydell/resolve-url#deprecated - resolve@1.22.10: resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} engines: {node: '>= 0.4'} @@ -8022,10 +7324,6 @@ packages: resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} engines: {node: '>=0.12'} - retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -8100,18 +7398,12 @@ packages: resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} - safe-regex@1.1.0: - resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} - safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} sanitize-filename@1.6.3: resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==} - sat@0.9.0: - resolution: {integrity: sha512-mxdv5RZJO4tdMnUURGU3gAMcnDUEwcNJwE+lPO0/V+rBeDvFLH3wEZEOR0fH7cTN0zQaNxBEbHnyQL9DzupwQQ==} - sax@1.4.1: resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} @@ -8145,27 +7437,16 @@ packages: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} - send@1.2.1: - resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} - engines: {node: '>= 18'} - sentence-case@3.0.4: resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==} serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} - serve-index@1.9.1: - resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} - engines: {node: '>= 0.8.0'} - serve-static@1.16.2: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} - set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -8182,16 +7463,9 @@ packages: resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} engines: {node: '>= 0.4'} - set-value@2.0.1: - resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} - engines: {node: '>=0.10.0'} - setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - setprototypeof@1.1.0: - resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} - setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -8260,9 +7534,6 @@ packages: simple-concat@1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - simple-get@3.1.1: - resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==} - simple-get@4.0.1: resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} @@ -8278,6 +7549,9 @@ packages: skinview3d@3.1.0: resolution: {integrity: sha512-L+HXXAP4qYjLcY3YHasXKie9KXQpv/mPTMxgLOEd+hVQRdQkPs5xdWaKuOmlZY8UnyZzecQM7yrWRzgT/e7HZw==} + skinview3d@3.4.1: + resolution: {integrity: sha512-WVN1selfDSAoQB7msLs3ueJjW/pge3nsmbqxJeXPnN/qIJ1GJKpMZO8mavSvMojaMrmpSgOJWfYUkK9B34ts2g==} + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -8300,31 +7574,12 @@ packages: snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} - snapdragon-node@2.1.1: - resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} - engines: {node: '>=0.10.0'} - - snapdragon-util@3.0.1: - resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} - engines: {node: '>=0.10.0'} - - snapdragon@0.8.2: - resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} - engines: {node: '>=0.10.0'} - socket.io-adapter@1.1.2: resolution: {integrity: sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==} - socket.io-adapter@2.5.5: - resolution: {integrity: sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==} - socket.io-client@2.5.0: resolution: {integrity: sha512-lOO9clmdgssDykiOmVQQitwBAF3I6mYcQAo7hQ7AM6Ny5X7fp8hIJ3HcQs3Rjz4SoggoxA1OgrQyY8EgTbcPYw==} - socket.io-client@4.8.1: - resolution: {integrity: sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==} - engines: {node: '>=10.0.0'} - socket.io-parser@3.3.4: resolution: {integrity: sha512-z/pFQB3x+EZldRRzORYW1vwVO8m/3ILkswtnpoeU6Ve3cbMWkmHEWDAVJn4QJtchiiFTo5j7UG2QvwxvaA9vow==} @@ -8332,40 +7587,16 @@ packages: resolution: {integrity: sha512-1rE4dZN3kCI/E5wixd393hmbqa78vVpkKmnEJhLeWoS/C5hbFYAbcSfnWoaVH43u9ToUVtzKjguxEZq+1XZfCQ==} engines: {node: '>=10.0.0'} - socket.io-parser@4.2.4: - resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} - engines: {node: '>=10.0.0'} - socket.io@2.5.1: resolution: {integrity: sha512-eaTE4tBKRD6RFoetquMbxgvcpvoDtRyIlkIMI/SMK2bsKvbENTsDeeu4GJ/z9c90yOWxB7b/eC+yKLPbHnH6bA==} - socket.io@4.8.1: - resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==} - engines: {node: '>=10.2.0'} - - socks-proxy-agent@7.0.0: - resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} - engines: {node: '>= 10'} - - socks@2.8.4: - resolution: {integrity: sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map-resolve@0.5.3: - resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} - deprecated: See https://github.com/lydell/source-map-resolve#deprecated - source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - source-map-url@0.4.1: - resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} - deprecated: See https://github.com/lydell/source-map-url#deprecated - source-map@0.5.6: resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} engines: {node: '>=0.10.0'} @@ -8402,28 +7633,14 @@ packages: spdx-license-ids@3.0.21: resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} - split-string@3.1.0: - resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} - engines: {node: '>=0.10.0'} - - split@0.3.3: - resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} - sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - sshpk@1.18.0: resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} engines: {node: '>=0.10.0'} hasBin: true - ssri@9.0.1: - resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - stack-generator@2.0.10: resolution: {integrity: sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==} @@ -8442,28 +7659,16 @@ packages: state-local@1.0.7: resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} - static-extend@0.1.2: - resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} - engines: {node: '>=0.10.0'} - stats-gl@1.0.7: resolution: {integrity: sha512-vZI82CjefSxLC1bjw36z28v0+QE9rJKymGlXtfWu+ipW70ZEAwa4EbO4LxluAfLfpqiaAS04NzpYBRLDeAwYWQ==} stats.js@0.17.0: resolution: {integrity: sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==} - statuses@1.5.0: - resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} - engines: {node: '>= 0.6'} - statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} - statuses@2.0.2: - resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} - engines: {node: '>= 0.8'} - std-env@3.8.1: resolution: {integrity: sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==} @@ -8481,9 +7686,6 @@ packages: stream-browserify@3.0.0: resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} - stream-combiner@0.0.4: - resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} - stream-http@3.2.0: resolution: {integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==} @@ -8524,9 +7726,6 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} - string_decoder@0.10.31: - resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} - string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} @@ -8610,6 +7809,10 @@ packages: tabbable@6.2.0: resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + tagged-tag@1.0.0: + resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} + engines: {node: '>=20'} + tar-fs@2.1.2: resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==} @@ -8653,27 +7856,17 @@ packages: text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} - - thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - thingies@1.21.0: resolution: {integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==} engines: {node: '>=10.18'} peerDependencies: tslib: ^2 - three-stdlib@2.35.14: - resolution: {integrity: sha512-kpCaEg59M9usFTgHC+YZNKvx7nMoLI2zQxZBV8pjoNW6vNZmGyXpaLBL09A2oLCsS3KepgMFkOuk6lRoebTNvA==} + three-stdlib@2.36.1: + resolution: {integrity: sha512-XyGQrFmNQ5O/IoKm556ftwKsBg11TIb301MB5dWNicziQBEs2g3gtOYIf7pFiLa0zI2gUwhtCjv9fmjnxKZ1Cg==} peerDependencies: three: 0.154.0 - three.meshline@1.4.0: - resolution: {integrity: sha512-A8IsiMrWP8zmHisGDAJ76ZD7t/dOF/oCe/FUKNE6Bu01ZYEx8N6IlU/1Plb2aOZtAuWM2A8s8qS3hvY0OFuvOw==} - three@0.154.0: resolution: {integrity: sha512-Uzz8C/5GesJzv8i+Y2prEMYUwodwZySPcNhuJUdsVMH2Yn4Nm8qlbQe6qRN5fOhg55XB0WiLfTPBxVHxpE60ug==} @@ -8684,9 +7877,6 @@ packages: throttleit@1.0.1: resolution: {integrity: sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==} - through2@0.6.5: - resolution: {integrity: sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==} - through2@2.0.5: resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} @@ -8733,22 +7923,10 @@ packages: to-array@0.1.4: resolution: {integrity: sha512-LhVdShQD/4Mk4zXNroIQZJC+Ap3zgLcDuwEdcmLv9CCO73NWockQDwyUnW/m8VX/EElfL6FcYx7EeutN4HJA6A==} - to-object-path@0.3.0: - resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} - engines: {node: '>=0.10.0'} - - to-regex-range@2.1.1: - resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} - engines: {node: '>=0.10.0'} - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - to-regex@3.0.2: - resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} - engines: {node: '>=0.10.0'} - tocbot@4.35.0: resolution: {integrity: sha512-i8FoSaP3u60D94e/dtzCk23PIEBnc/l8XqvlK4g8gUCa9XFY4RmyMLYP6X+yN+ljcEijFbmCtNHtBoeTsQkCPg==} @@ -8873,6 +8051,10 @@ packages: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} + type-fest@5.3.0: + resolution: {integrity: sha512-d9CwU93nN0IA1QL+GSNDdwLAu1Ew5ZjTwupvedwg3WdfoH6pIDvYQ2hV0Uc2nKBLPq7NB5apCx57MLS5qlmO5g==} + engines: {node: '>=20'} + type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -8961,22 +8143,10 @@ packages: unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} - union-value@1.0.1: - resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} - engines: {node: '>=0.10.0'} - union@0.5.0: resolution: {integrity: sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==} engines: {node: '>= 0.8.0'} - unique-filename@2.0.1: - resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - unique-slug@3.0.0: - resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - unique-string@2.0.0: resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} engines: {node: '>=8'} @@ -9014,9 +8184,6 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} - unix-crypt-td-js@1.1.4: - resolution: {integrity: sha512-8rMeVYWSIyccIJscb9NdCfZKSRBKYTeVnwmiRYT2ulE3qd1RaDQ0xQDP+rI3ccIWbhu/zuo5cgN8z73belNZgw==} - unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -9025,10 +8192,6 @@ packages: resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} engines: {node: '>=14.0.0'} - unset-value@1.0.0: - resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} - engines: {node: '>=0.10.0'} - untildify@4.0.0: resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} engines: {node: '>=8'} @@ -9052,10 +8215,6 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - urix@0.1.0: - resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} - deprecated: Please see https://github.com/lydell/urix#deprecated - url-join@4.0.1: resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} @@ -9121,10 +8280,6 @@ packages: typescript: optional: true - use@3.1.1: - resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} - engines: {node: '>=0.10.0'} - utf8-byte-length@1.0.5: resolution: {integrity: sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==} @@ -9144,11 +8299,6 @@ packages: uuid-1345@1.0.2: resolution: {integrity: sha512-bA5zYZui+3nwAc0s3VdGQGBfbVsJLVX7Np7ch2aqcEWFi5lsAEcmO3+lx3djM1npgpZI8KY2FITZ2uYTnYUYyw==} - uuid@3.4.0: - resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} - deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. - hasBin: true - uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true @@ -9160,18 +8310,6 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - valtio@1.11.2: - resolution: {integrity: sha512-1XfIxnUXzyswPAPXo1P3Pdx2mq/pIqZICkWN60Hby0d9Iqb+MEIpqgYVlbflvHdrp2YR/q3jyKWRPJJ100yxaw==} - engines: {node: '>=12.20.0'} - peerDependencies: - '@types/react': '>=16.8' - react: ^18.2.0 - peerDependenciesMeta: - '@types/react': - optional: true - react: - optional: true - valtio@1.13.2: resolution: {integrity: sha512-Qik0o+DSy741TmkqmRfjq+0xpZBXi/Y6+fXZLn0xNF1z/waFMbE3rkivv5Zcf9RrMUp6zswf2J7sbh2KBlba5A==} engines: {node: '>=12.20.0'} @@ -9342,14 +8480,6 @@ packages: resolution: {integrity: sha512-1AQO+d4ElfVSXyzNVTOewgGT/tAomwwztX/6e3totvyyzXPvXIIuUUjAmyZGbKBKbZOXauuJooZm3g6IuFuiNQ==} engines: {node: '>=6.0.0', npm: '>=3.10.0'} - websocket-driver@0.7.4: - resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} - engines: {node: '>=0.8.0'} - - websocket-extensions@0.1.4: - resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} - engines: {node: '>=0.8.0'} - whatwg-encoding@2.0.0: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} engines: {node: '>=12'} @@ -9398,9 +8528,6 @@ packages: engines: {node: '>=8'} hasBin: true - wide-align@1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -9513,18 +8640,6 @@ packages: utf-8-validate: optional: true - ws@8.17.1: - resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - ws@8.18.1: resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} engines: {node: '>=10.0.0'} @@ -9555,10 +8670,6 @@ packages: resolution: {integrity: sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==} engines: {node: '>=0.4.0'} - xmlhttprequest-ssl@2.1.2: - resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==} - engines: {node: '>=0.4.0'} - xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -10356,7 +9467,7 @@ snapshots: '@babel/parser': 7.26.9 '@babel/template': 7.26.9 '@babel/types': 7.26.9 - debug: 4.4.3 + debug: 4.4.1 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -10412,7 +9523,7 @@ snapshots: react-portal: 4.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-use: 17.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-use-measure: 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - valtio: 1.11.2(@types/react@18.3.18)(react@18.3.1) + valtio: 1.13.2(@types/react@18.3.18)(react@18.3.1) zustand: 3.6.5(react@18.3.1) transitivePeerDependencies: - '@babel/core' @@ -10766,9 +9877,6 @@ snapshots: '@floating-ui/utils@0.2.9': {} - '@gar/promisify@1.1.3': - optional: true - '@hapi/hoek@9.3.0': {} '@hapi/topo@5.1.0': @@ -11278,22 +10386,6 @@ snapshots: '@juggle/resize-observer@3.4.0': {} - '@mapbox/node-pre-gyp@1.0.11(encoding@0.1.13)': - dependencies: - detect-libc: 2.0.3 - https-proxy-agent: 5.0.1 - make-dir: 3.1.0 - node-fetch: 2.7.0(encoding@0.1.13) - nopt: 5.0.0 - npmlog: 5.0.1 - rimraf: 3.0.2 - semver: 7.7.1 - tar: 6.2.1 - transitivePeerDependencies: - - encoding - - supports-color - optional: true - '@mdx-js/react@2.3.0(react@18.3.1)': dependencies: '@types/mdx': 2.0.13 @@ -11356,18 +10448,6 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 - '@npmcli/fs@2.1.2': - dependencies: - '@gar/promisify': 1.1.3 - semver: 7.7.1 - optional: true - - '@npmcli/move-file@2.0.1': - dependencies: - mkdirp: 1.0.4 - rimraf: 3.0.2 - optional: true - '@nxg-org/mineflayer-auto-jump@0.7.18': dependencies: '@nxg-org/mineflayer-physics-util': 1.8.19 @@ -12026,8 +11106,6 @@ snapshots: '@sinclair/typebox@0.27.8': {} - '@socket.io/component-emitter@3.1.2': {} - '@storybook/addon-actions@7.6.20': dependencies: '@storybook/core-events': 7.6.20 @@ -12647,10 +11725,6 @@ snapshots: dependencies: '@types/node': 22.13.9 - '@types/cors@2.8.17': - dependencies: - '@types/node': 22.13.9 - '@types/cross-spawn@6.0.6': dependencies: '@types/node': 22.13.9 @@ -12681,6 +11755,8 @@ snapshots: '@types/estree@1.0.6': {} + '@types/events@3.0.3': {} + '@types/express-serve-static-core@4.19.6': dependencies: '@types/node': 22.13.9 @@ -12793,8 +11869,6 @@ snapshots: '@types/range-parser@1.2.7': {} - '@types/rbush@3.0.4': {} - '@types/react-dom@18.3.5(@types/react@18.3.18)': dependencies: '@types/react': 18.3.18 @@ -12817,8 +11891,6 @@ snapshots: '@types/resolve@1.20.6': {} - '@types/sat@0.0.31': {} - '@types/semver@7.5.8': {} '@types/send@0.17.4': @@ -12849,13 +11921,6 @@ snapshots: lil-gui: 0.17.0 meshoptimizer: 0.18.1 - '@types/three@0.156.0': - dependencies: - '@types/stats.js': 0.17.3 - '@types/webxr': 0.5.21 - fflate: 0.6.10 - meshoptimizer: 0.18.1 - '@types/trusted-types@2.0.7': {} '@types/ua-parser-js@0.7.39': {} @@ -12937,7 +12002,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 6.1.0(typescript@5.5.4) '@typescript-eslint/utils': 6.1.0(eslint@8.57.1)(typescript@5.5.4) - debug: 4.4.3 + debug: 4.4.1 eslint: 8.57.1 ts-api-utils: 1.4.3(typescript@5.5.4) optionalDependencies: @@ -12969,7 +12034,7 @@ snapshots: dependencies: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.4.3 + debug: 4.4.1 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -12984,7 +12049,7 @@ snapshots: dependencies: '@typescript-eslint/types': 8.26.0 '@typescript-eslint/visitor-keys': 8.26.0 - debug: 4.4.3 + debug: 4.4.1 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 @@ -13265,18 +12330,6 @@ snapshots: agent-base@5.1.1: {} - agent-base@6.0.2: - dependencies: - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - optional: true - - agentkeepalive@4.6.0: - dependencies: - humanize-ms: 1.2.1 - optional: true - aggregate-error@3.1.0: dependencies: clean-stack: 2.2.0 @@ -13325,47 +12378,17 @@ snapshots: any-base@1.1.0: optional: true - any-promise@1.3.0: {} - - anymatch@2.0.0: - dependencies: - micromatch: 3.1.10 - normalize-path: 2.1.1 - transitivePeerDependencies: - - supports-color - anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - apache-crypt@1.2.6: - dependencies: - unix-crypt-td-js: 1.1.4 - - apache-md5@1.1.8: {} - app-root-dir@1.0.2: {} - aproba@2.0.0: - optional: true - arch@2.2.0: optional: true - are-we-there-yet@2.0.0: - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - optional: true - - are-we-there-yet@3.0.1: - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - optional: true - - argparse@1.0.10: + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -13375,12 +12398,6 @@ snapshots: dependencies: tslib: 2.8.1 - arr-diff@4.0.0: {} - - arr-flatten@1.1.0: {} - - arr-union@3.1.0: {} - array-buffer-byte-length@1.0.2: dependencies: call-bound: 1.0.4 @@ -13410,8 +12427,6 @@ snapshots: array-union@2.1.0: {} - array-unique@0.3.2: {} - array.prototype.findlast@1.2.5: dependencies: call-bind: 1.0.8 @@ -13483,8 +12498,6 @@ snapshots: assertion-error@1.1.0: {} - assign-symbols@1.0.0: {} - ast-types@0.16.1: dependencies: tslib: 2.8.1 @@ -13492,8 +12505,6 @@ snapshots: astral-regex@2.0.0: optional: true - async-each@1.0.6: {} - async-function@1.0.0: {} async-limiter@1.0.1: {} @@ -13508,8 +12519,6 @@ snapshots: at-least-node@1.0.0: {} - atob@2.1.2: {} - available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -13584,49 +12593,26 @@ snapshots: base64-js@1.5.1: {} - base64id@2.0.0: {} - - base@0.11.2: - dependencies: - cache-base: 1.0.1 - class-utils: 0.3.6 - component-emitter: 1.3.1 - define-property: 1.0.0 - isobject: 3.0.1 - mixin-deep: 1.3.2 - pascalcase: 0.1.1 + base64id@2.0.0: + optional: true basic-auth@2.0.1: dependencies: safe-buffer: 5.1.2 - batch@0.6.1: {} - bcrypt-pbkdf@1.0.2: dependencies: tweetnacl: 0.14.5 optional: true - bcryptjs@2.4.3: {} - better-opn@3.0.2: dependencies: open: 8.4.2 big-integer@1.6.52: {} - binary-extensions@1.13.1: {} - binary-extensions@2.3.0: {} - bindings@1.5.0: - dependencies: - file-uri-to-path: 1.0.0 - optional: true - - bit-twiddle@1.0.2: - optional: true - bl@4.1.0: dependencies: buffer: 6.0.3 @@ -13681,21 +12667,6 @@ snapshots: dependencies: balanced-match: 1.0.2 - braces@2.3.2: - dependencies: - arr-flatten: 1.1.0 - array-unique: 0.3.2 - extend-shallow: 2.0.1 - fill-range: 4.0.0 - isobject: 3.0.1 - repeat-element: 1.1.4 - snapdragon: 0.8.2 - snapdragon-node: 2.1.1 - split-string: 3.1.0 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -13796,42 +12767,6 @@ snapshots: cac@6.7.14: {} - cacache@16.1.3: - dependencies: - '@npmcli/fs': 2.1.2 - '@npmcli/move-file': 2.0.1 - chownr: 2.0.0 - fs-minipass: 2.1.0 - glob: 8.1.0 - infer-owner: 1.0.4 - lru-cache: 7.18.3 - minipass: 3.3.6 - minipass-collect: 1.0.2 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - mkdirp: 1.0.4 - p-map: 4.0.0 - promise-inflight: 1.0.1 - rimraf: 3.0.2 - ssri: 9.0.1 - tar: 6.2.1 - unique-filename: 2.0.1 - transitivePeerDependencies: - - bluebird - optional: true - - cache-base@1.0.1: - dependencies: - collection-visit: 1.0.0 - component-emitter: 1.3.1 - get-value: 2.0.6 - has-value: 1.0.0 - isobject: 3.0.1 - set-value: 2.0.1 - to-object-path: 0.3.0 - union-value: 1.0.1 - unset-value: 1.0.0 - cachedir@2.4.0: optional: true @@ -13872,16 +12807,6 @@ snapshots: caniuse-lite@1.0.30001713: {} - canvas@2.11.2(encoding@0.1.13): - dependencies: - '@mapbox/node-pre-gyp': 1.0.11(encoding@0.1.13) - nan: 2.22.2 - simple-get: 3.1.1 - transitivePeerDependencies: - - encoding - - supports-color - optional: true - capital-case@1.0.4: dependencies: no-case: 3.0.4 @@ -13949,24 +12874,6 @@ snapshots: check-more-types@2.24.0: optional: true - chokidar@2.1.8: - dependencies: - anymatch: 2.0.0 - async-each: 1.0.6 - braces: 2.3.2 - glob-parent: 3.1.0 - inherits: 2.0.4 - is-binary-path: 1.0.1 - is-glob: 4.0.3 - normalize-path: 3.0.0 - path-is-absolute: 1.0.1 - readdirp: 2.2.1 - upath: 1.2.0 - optionalDependencies: - fsevents: 1.2.13 - transitivePeerDependencies: - - supports-color - chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -13994,13 +12901,6 @@ snapshots: dependencies: consola: 3.4.0 - class-utils@0.3.6: - dependencies: - arr-union: 3.1.0 - define-property: 0.2.5 - isobject: 3.0.1 - static-extend: 0.1.2 - classnames@2.5.1: {} clean-regexp@1.0.0: @@ -14043,11 +12943,6 @@ snapshots: clsx@1.1.1: {} - collection-visit@1.0.0: - dependencies: - map-visit: 1.0.0 - object-visit: 1.0.1 - color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -14065,9 +12960,6 @@ snapshots: color-name: 1.1.4 simple-swizzle: 0.2.2 - color-support@1.1.3: - optional: true - color@4.2.3: dependencies: color-convert: 2.0.1 @@ -14076,8 +12968,6 @@ snapshots: colorette@2.0.20: optional: true - colors@1.4.0: {} - combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -14099,7 +12989,8 @@ snapshots: component-emitter@1.2.1: optional: true - component-emitter@1.3.1: {} + component-emitter@1.3.1: + optional: true component-inherit@0.0.3: optional: true @@ -14133,22 +13024,10 @@ snapshots: confusing-browser-globals@1.0.11: {} - connect@3.7.0: - dependencies: - debug: 2.6.9 - finalhandler: 1.1.2 - parseurl: 1.3.3 - utils-merge: 1.0.1 - transitivePeerDependencies: - - supports-color - consola@3.4.0: {} console-browserify@1.2.0: {} - console-control-strings@1.1.0: - optional: true - constant-case@3.0.4: dependencies: no-case: 3.0.4 @@ -14185,10 +13064,6 @@ snapshots: cookie@0.7.1: {} - cookie@0.7.2: {} - - copy-descriptor@0.1.1: {} - copy-to-clipboard@3.3.3: dependencies: toggle-selection: 1.0.6 @@ -14209,11 +13084,6 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 - cors@2.8.6: - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - corser@2.0.1: {} cosmiconfig@7.1.0: @@ -14423,16 +13293,16 @@ snapshots: ms: 2.1.3 optional: true - debug@4.3.7: - dependencies: - ms: 2.1.3 - debug@4.4.0(supports-color@8.1.1): dependencies: ms: 2.1.3 optionalDependencies: supports-color: 8.1.1 + debug@4.4.1: + dependencies: + ms: 2.1.3 + debug@4.4.3: dependencies: ms: 2.1.3 @@ -14450,13 +13320,6 @@ snapshots: dependencies: character-entities: 2.0.2 - decode-uri-component@0.2.2: {} - - decompress-response@4.2.1: - dependencies: - mimic-response: 2.1.0 - optional: true - decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 @@ -14477,6 +13340,12 @@ snapshots: md5: 2.3.0 pako: 2.1.0 + deepslate@0.24.0: + dependencies: + gl-matrix: 3.4.3 + md5: 2.3.0 + pako: 2.1.0 + default-browser-id@3.0.0: dependencies: bplist-parser: 0.2.0 @@ -14500,19 +13369,6 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 - define-property@0.2.5: - dependencies: - is-descriptor: 0.1.7 - - define-property@1.0.0: - dependencies: - is-descriptor: 1.0.3 - - define-property@2.0.2: - dependencies: - is-descriptor: 1.0.3 - isobject: 3.0.1 - defu@6.1.4: {} del@6.1.1: @@ -14528,11 +13384,6 @@ snapshots: delayed-stream@1.0.0: {} - delegates@1.0.0: - optional: true - - depd@1.1.2: {} - depd@2.0.0: {} dequal@2.0.3: {} @@ -14548,14 +13399,6 @@ snapshots: destroy@1.2.0: {} - detect-collisions@7.0.5: - dependencies: - '@types/rbush': 3.0.4 - '@types/sat': 0.0.31 - poly-decomp: 0.3.0 - rbush: 3.0.1 - sat: 0.9.0 - detect-indent@6.1.0: {} detect-libc@2.0.3: {} @@ -14747,18 +13590,6 @@ snapshots: - utf-8-validate optional: true - engine.io-client@6.6.3: - dependencies: - '@socket.io/component-emitter': 3.1.2 - debug: 4.3.7 - engine.io-parser: 5.2.3 - ws: 8.17.1 - xmlhttprequest-ssl: 2.1.2 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - engine.io-parser@2.2.1: dependencies: after: 0.8.2 @@ -14768,8 +13599,6 @@ snapshots: has-binary2: 1.0.3 optional: true - engine.io-parser@5.2.3: {} - engine.io@3.6.2: dependencies: accepts: 1.3.8 @@ -14784,22 +13613,6 @@ snapshots: - utf-8-validate optional: true - engine.io@6.6.4: - dependencies: - '@types/cors': 2.8.17 - '@types/node': 22.13.9 - accepts: 1.3.8 - base64id: 2.0.0 - cookie: 0.7.2 - cors: 2.8.6 - debug: 4.3.7 - engine.io-parser: 5.2.3 - ws: 8.17.1 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - enquirer@2.4.1: dependencies: ansi-colors: 4.1.3 @@ -14808,14 +13621,8 @@ snapshots: entities@4.5.0: {} - env-paths@2.2.1: - optional: true - envinfo@7.14.0: {} - err-code@2.0.3: - optional: true - error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -14983,12 +13790,6 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - es6-promise@4.2.8: {} - - es6-promisify@5.0.0: - dependencies: - es6-promise: 4.2.8 - esbuild-plugin-alias@0.2.1: {} esbuild-plugin-polyfill-node@0.3.0(esbuild@0.19.12): @@ -14999,7 +13800,7 @@ snapshots: esbuild-register@3.6.0(esbuild@0.18.20): dependencies: - debug: 4.4.3 + debug: 4.4.1 esbuild: 0.18.20 transitivePeerDependencies: - supports-color @@ -15348,16 +14149,6 @@ snapshots: etag@1.8.1: {} - event-stream@3.3.4: - dependencies: - duplexer: 0.1.2 - from: 0.1.7 - map-stream: 0.1.0 - pause-stream: 0.0.11 - split: 0.3.3 - stream-combiner: 0.0.4 - through: 2.3.8 - event-target-shim@5.0.1: {} eventemitter2@6.4.7: @@ -15407,23 +14198,8 @@ snapshots: exit-hook@2.2.1: {} - expand-brackets@2.1.4: - dependencies: - debug: 2.6.9 - define-property: 0.2.5 - extend-shallow: 2.0.1 - posix-character-classes: 0.1.1 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - expand-template@2.0.3: {} - exponential-backoff@3.1.2: - optional: true - express-ws@4.0.0(express@4.21.2): dependencies: express: 4.21.2 @@ -15468,30 +14244,8 @@ snapshots: transitivePeerDependencies: - supports-color - extend-shallow@2.0.1: - dependencies: - is-extendable: 0.1.1 - - extend-shallow@3.0.2: - dependencies: - assign-symbols: 1.0.0 - is-extendable: 1.0.1 - extend@3.0.2: {} - extglob@2.0.4: - dependencies: - array-unique: 0.3.2 - define-property: 1.0.0 - expand-brackets: 2.1.4 - extend-shallow: 2.0.1 - fragment-cache: 0.2.1 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - extract-zip@1.7.0: dependencies: concat-stream: 1.6.2 @@ -15510,6 +14264,7 @@ snapshots: '@types/yauzl': 2.10.3 transitivePeerDependencies: - supports-color + optional: true extsprintf@1.3.0: optional: true @@ -15538,10 +14293,6 @@ snapshots: dependencies: reusify: 1.1.0 - faye-websocket@0.11.4: - dependencies: - websocket-driver: 0.7.4 - fb-watchman@2.0.2: dependencies: bser: 2.1.1 @@ -15571,38 +14322,16 @@ snapshots: file-type@9.0.0: optional: true - file-uri-to-path@1.0.0: - optional: true - filelist@1.0.4: dependencies: minimatch: 5.1.6 filesize@10.1.6: {} - fill-range@4.0.0: - dependencies: - extend-shallow: 2.0.1 - is-number: 3.0.0 - repeat-string: 1.6.1 - to-regex-range: 2.1.1 - fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 - finalhandler@1.1.2: - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.3.0 - parseurl: 1.3.3 - statuses: 1.5.0 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - finalhandler@1.3.1: dependencies: debug: 2.6.9 @@ -15663,8 +14392,6 @@ snapshots: dependencies: is-callable: 1.2.7 - for-in@1.0.2: {} - foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 @@ -15689,10 +14416,6 @@ snapshots: forwarded@0.2.0: {} - fragment-cache@0.2.1: - dependencies: - map-cache: 0.2.2 - framer-motion@12.9.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: motion-dom: 12.9.1 @@ -15704,10 +14427,6 @@ snapshots: fresh@0.5.2: {} - fresh@2.0.0: {} - - from@0.1.7: {} - fs-constants@1.0.0: {} fs-extra@11.1.1: @@ -15742,12 +14461,6 @@ snapshots: fs.realpath@1.0.0: {} - fsevents@1.2.13: - dependencies: - bindings: 1.5.0 - nan: 2.22.2 - optional: true - fsevents@2.3.3: optional: true @@ -15764,31 +14477,6 @@ snapshots: functions-have-names@1.2.3: {} - gauge@3.0.2: - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - optional: true - - gauge@4.0.4: - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - optional: true - gensync@1.0.0-beta.2: {} get-caller-file@2.0.5: {} @@ -15826,6 +14514,7 @@ snapshots: get-stream@5.2.0: dependencies: pump: 3.0.2 + optional: true get-stream@6.0.1: {} @@ -15838,8 +14527,7 @@ snapshots: get-tsconfig@4.10.0: dependencies: resolve-pkg-maps: 1.0.0 - - get-value@2.0.6: {} + optional: true getos@3.2.1: dependencies: @@ -15867,25 +14555,6 @@ snapshots: gl-matrix@3.4.3: {} - gl@6.0.2: - dependencies: - bindings: 1.5.0 - bit-twiddle: 1.0.2 - glsl-tokenizer: 2.1.5 - nan: 2.22.2 - node-abi: 3.74.0 - node-gyp: 9.4.1 - prebuild-install: 7.1.3 - transitivePeerDependencies: - - bluebird - - supports-color - optional: true - - glob-parent@3.1.0: - dependencies: - is-glob: 3.1.0 - path-dirname: 1.0.2 - glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -15919,15 +14588,6 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 - glob@8.1.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - optional: true - global-dirs@3.0.1: dependencies: ini: 2.0.0 @@ -15959,11 +14619,6 @@ snapshots: merge2: 1.4.1 slash: 3.0.0 - glsl-tokenizer@2.1.5: - dependencies: - through2: 0.6.5 - optional: true - gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -16022,28 +14677,6 @@ snapshots: dependencies: has-symbols: 1.1.0 - has-unicode@2.0.1: - optional: true - - has-value@0.3.1: - dependencies: - get-value: 2.0.6 - has-values: 0.1.4 - isobject: 2.1.0 - - has-value@1.0.0: - dependencies: - get-value: 2.0.6 - has-values: 1.0.0 - isobject: 3.0.1 - - has-values@0.1.4: {} - - has-values@1.0.0: - dependencies: - is-number: 3.0.0 - kind-of: 4.0.0 - has@1.0.4: {} hash-base@3.0.5: @@ -16097,13 +14730,6 @@ snapshots: html-tags@3.3.1: {} - http-auth@3.1.3: - dependencies: - apache-crypt: 1.2.6 - apache-md5: 1.1.8 - bcryptjs: 2.4.3 - uuid: 3.4.0 - http-browserify@1.7.0: dependencies: Base64: 0.2.1 @@ -16111,13 +14737,6 @@ snapshots: http-cache-semantics@4.1.1: {} - http-errors@1.6.3: - dependencies: - depd: 1.1.2 - inherits: 2.0.3 - setprototypeof: 1.1.0 - statuses: 1.5.0 - http-errors@2.0.0: dependencies: depd: 2.0.0 @@ -16126,25 +14745,6 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 - http-errors@2.0.1: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.2 - toidentifier: 1.0.1 - - http-parser-js@0.5.9: {} - - http-proxy-agent@5.0.0: - dependencies: - '@tootallnate/once': 2.0.0 - agent-base: 6.0.2 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - optional: true - http-proxy@1.18.1(debug@4.4.0): dependencies: eventemitter3: 4.0.7 @@ -16188,24 +14788,11 @@ snapshots: transitivePeerDependencies: - supports-color - https-proxy-agent@5.0.1: - dependencies: - agent-base: 6.0.2 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - optional: true - human-signals@1.1.1: optional: true human-signals@2.1.0: {} - humanize-ms@1.2.1: - dependencies: - ms: 2.1.3 - optional: true - hyperdyperid@1.2.0: {} hyphenate-style-name@1.1.0: {} @@ -16245,16 +14832,11 @@ snapshots: indexof@0.0.1: optional: true - infer-owner@1.0.4: - optional: true - inflight@1.0.6: dependencies: once: 1.4.0 wrappy: 1.0.2 - inherits@2.0.3: {} - inherits@2.0.4: {} ini@1.3.8: {} @@ -16272,20 +14854,10 @@ snapshots: hasown: 2.0.2 side-channel: 1.1.0 - ip-address@9.0.5: - dependencies: - jsbn: 1.1.0 - sprintf-js: 1.1.3 - optional: true - ipaddr.js@1.9.1: {} is-absolute-url@3.0.3: {} - is-accessor-descriptor@1.0.1: - dependencies: - hasown: 2.0.2 - is-arguments@1.2.0: dependencies: call-bound: 1.0.4 @@ -16313,10 +14885,6 @@ snapshots: dependencies: has-bigints: 1.1.0 - is-binary-path@1.0.1: - dependencies: - binary-extensions: 1.13.1 - is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 @@ -16343,10 +14911,6 @@ snapshots: dependencies: hasown: 2.0.2 - is-data-descriptor@1.0.1: - dependencies: - hasown: 2.0.2 - is-data-view@1.0.2: dependencies: call-bound: 1.0.4 @@ -16360,24 +14924,8 @@ snapshots: is-deflate@1.0.0: {} - is-descriptor@0.1.7: - dependencies: - is-accessor-descriptor: 1.0.1 - is-data-descriptor: 1.0.1 - - is-descriptor@1.0.3: - dependencies: - is-accessor-descriptor: 1.0.1 - is-data-descriptor: 1.0.1 - is-docker@2.2.1: {} - is-extendable@0.1.1: {} - - is-extendable@1.0.1: - dependencies: - is-plain-object: 2.0.4 - is-extglob@2.1.1: {} is-finalizationregistry@1.1.1: @@ -16396,10 +14944,6 @@ snapshots: has-tostringtag: 1.0.2 safe-regex-test: 1.1.0 - is-glob@3.1.0: - dependencies: - is-extglob: 2.1.1 - is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -16414,9 +14958,6 @@ snapshots: is-interactive@1.0.0: {} - is-lambda@1.0.1: - optional: true - is-map@2.0.3: {} is-module@1.0.0: {} @@ -16433,10 +14974,6 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 - is-number@3.0.0: - dependencies: - kind-of: 3.2.2 - is-number@7.0.0: {} is-obj@1.0.1: {} @@ -16503,17 +15040,10 @@ snapshots: call-bound: 1.0.4 get-intrinsic: 1.3.0 - is-windows@1.0.2: {} - - is-wsl@1.1.0: {} - is-wsl@2.2.0: dependencies: is-docker: 2.2.1 - isarray@0.0.1: - optional: true - isarray@1.0.0: {} isarray@2.0.1: @@ -16523,10 +15053,6 @@ snapshots: isexe@2.0.0: {} - isobject@2.1.0: - dependencies: - isarray: 1.0.0 - isobject@3.0.1: {} isstream@0.1.2: @@ -16644,9 +15170,6 @@ snapshots: jsbn@0.1.1: optional: true - jsbn@1.1.0: - optional: true - jscodeshift@0.15.2(@babel/preset-env@7.26.9(@babel/core@7.26.9)): dependencies: '@babel/core': 7.26.9 @@ -16765,14 +15288,6 @@ snapshots: dependencies: json-buffer: 3.0.1 - kind-of@3.2.2: - dependencies: - is-buffer: 1.1.6 - - kind-of@4.0.0: - dependencies: - is-buffer: 1.1.6 - kind-of@6.0.3: {} kleur@3.0.3: {} @@ -16799,8 +15314,6 @@ snapshots: lil-gui@0.17.0: {} - lil-gui@0.18.2: {} - lil-gui@0.21.0: {} lines-and-columns@1.2.4: {} @@ -16823,24 +15336,6 @@ snapshots: enquirer: 2.4.1 optional: true - live-server@1.2.2: - dependencies: - chokidar: 2.1.8 - colors: 1.4.0 - connect: 3.7.0 - cors: 2.8.6 - event-stream: 3.3.4 - faye-websocket: 0.11.4 - http-auth: 3.1.3 - morgan: 1.10.0 - object-assign: 4.1.1 - opn: 6.0.0 - proxy-middleware: 0.15.0 - send: 1.2.1 - serve-index: 1.9.1 - transitivePeerDependencies: - - supports-color - load-bmfont@1.4.2(debug@4.4.0): dependencies: buffer-equal: 0.0.1 @@ -16946,9 +15441,6 @@ snapshots: dependencies: yallist: 4.0.0 - lru-cache@7.18.3: - optional: true - macaddress@0.5.3: {} magic-string@0.25.9: @@ -16972,47 +15464,16 @@ snapshots: dependencies: semver: 6.3.1 - make-fetch-happen@10.2.1: - dependencies: - agentkeepalive: 4.6.0 - cacache: 16.1.3 - http-cache-semantics: 4.1.1 - http-proxy-agent: 5.0.0 - https-proxy-agent: 5.0.1 - is-lambda: 1.0.1 - lru-cache: 7.18.3 - minipass: 3.3.6 - minipass-collect: 1.0.2 - minipass-fetch: 2.1.2 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - negotiator: 0.6.4 - promise-retry: 2.0.1 - socks-proxy-agent: 7.0.0 - ssri: 9.0.1 - transitivePeerDependencies: - - bluebird - - supports-color - optional: true - makeerror@1.0.12: dependencies: tmpl: 1.0.5 - map-cache@0.2.2: {} - map-obj@1.0.1: {} map-obj@4.3.0: {} map-or-similar@1.5.0: {} - map-stream@0.1.0: {} - - map-visit@1.0.0: - dependencies: - object-visit: 1.0.1 - markdown-it@14.1.0: dependencies: argparse: 2.0.1 @@ -17051,8 +15512,6 @@ snapshots: - supports-color - utf-8-validate - md5-file@4.0.0: {} - md5.js@1.3.5: dependencies: hash-base: 3.0.5 @@ -17291,24 +15750,6 @@ snapshots: transitivePeerDependencies: - supports-color - micromatch@3.1.10: - dependencies: - arr-diff: 4.0.0 - array-unique: 0.3.2 - braces: 2.3.2 - define-property: 2.0.2 - extend-shallow: 3.0.2 - extglob: 2.0.4 - fragment-cache: 0.2.1 - kind-of: 6.0.3 - nanomatch: 1.2.13 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -17327,19 +15768,12 @@ snapshots: dependencies: mime-db: 1.52.0 - mime-types@3.0.2: - dependencies: - mime-db: 1.54.0 - mime@1.6.0: {} mime@2.6.0: {} mimic-fn@2.1.0: {} - mimic-response@2.1.0: - optional: true - mimic-response@3.1.0: {} min-document@2.19.0: @@ -17386,31 +15820,36 @@ snapshots: - encoding - supports-color - minecraft-wrap@1.6.0(encoding@0.1.13): + minecraft-renderer@0.1.52(@types/react@18.3.18)(contro-max@0.1.12(typescript@5.5.4))(mc-assets@0.2.72)(minecraft-data@3.105.0)(react@18.3.1)(three@0.154.0): dependencies: - adm-zip: 0.5.16 - debug: 4.4.0(supports-color@8.1.1) - es6-promisify: 5.0.0 - extract-zip: 2.0.1(supports-color@8.1.1) - flatmap: 0.0.3 - md5-file: 4.0.0 - minecraft-folder-path: 1.2.0 - mkdirp: 0.5.6 - mz: 2.7.0 - node-fetch: 2.7.0(encoding@0.1.13) - promise-queue: 2.2.5 - rimraf: 3.0.2 - yggdrasil: 1.7.0(encoding@0.1.13) + '@tweenjs/tween.js': 20.0.3 + '@types/events': 3.0.3 + '@xmcl/text-component': 2.1.3 + deepslate: 0.24.0 + events: 3.3.0 + mc-bridge: 0.1.3(minecraft-data@3.105.0) + mineflayer-mouse: 0.1.28 + prismarine-chat: 1.11.0 + prismarine-nbt: 2.7.0 + skinview-utils: 0.7.1 + skinview3d: 3.4.1 + stats-gl: 1.0.7 + stats.js: 0.17.0 + three: 0.154.0 + three-stdlib: 2.36.1(three@0.154.0) + type-fest: 5.3.0 + typed-emitter: 2.1.0 + valtio: 1.13.2(@types/react@18.3.18)(react@18.3.1) + vec3: 0.1.10 + optionalDependencies: + contro-max: 0.1.12(typescript@5.5.4) + mc-assets: 0.2.72 + minecraft-data: 3.105.0 transitivePeerDependencies: - - encoding + - '@types/react' + - react - supports-color - minecrafthawkeye@1.3.9: - dependencies: - detect-collisions: 7.0.5 - uuid: 9.0.1 - vec3: 0.1.10 - mineflayer-item-map-downloader@https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824(patch_hash=a731ebbace2d8790c973ab3a5ba33494a6e9658533a9710dd8ba36f86db061ad)(encoding@0.1.13): dependencies: mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/6fe34e32c19657020cc48d95039e4b89361200b2(encoding@0.1.13) @@ -17482,35 +15921,6 @@ snapshots: minimist@1.2.8: {} - minipass-collect@1.0.2: - dependencies: - minipass: 3.3.6 - optional: true - - minipass-fetch@2.1.2: - dependencies: - minipass: 3.3.6 - minipass-sized: 1.0.3 - minizlib: 2.1.2 - optionalDependencies: - encoding: 0.1.13 - optional: true - - minipass-flush@1.0.5: - dependencies: - minipass: 3.3.6 - optional: true - - minipass-pipeline@1.2.4: - dependencies: - minipass: 3.3.6 - optional: true - - minipass-sized@1.0.3: - dependencies: - minipass: 3.3.6 - optional: true - minipass@3.3.6: dependencies: yallist: 4.0.0 @@ -17524,11 +15934,6 @@ snapshots: minipass: 3.3.6 yallist: 4.0.0 - mixin-deep@1.3.2: - dependencies: - for-in: 1.0.2 - is-extendable: 1.0.1 - mkdirp-classic@0.5.3: {} mkdirp@0.3.0: @@ -17557,16 +15962,6 @@ snapshots: moo@0.5.2: {} - morgan@1.10.0: - dependencies: - basic-auth: 2.0.1 - debug: 2.6.9 - depd: 2.0.0 - on-finished: 2.3.0 - on-headers: 1.0.2 - transitivePeerDependencies: - - supports-color - motion-dom@12.9.1: dependencies: motion-utils: 12.8.3 @@ -17577,15 +15972,6 @@ snapshots: ms@2.1.3: {} - mz@2.7.0: - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - - nan@2.22.2: - optional: true - nano-css@5.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -17597,25 +15983,9 @@ snapshots: react-dom: 18.3.1(react@18.3.1) rtl-css-js: 1.16.1 stacktrace-js: 2.0.2 - stylis: 4.3.6 - - nanoid@3.3.9: {} - - nanomatch@1.2.13: - dependencies: - arr-diff: 4.0.0 - array-unique: 0.3.2 - define-property: 2.0.2 - extend-shallow: 3.0.2 - fragment-cache: 0.2.1 - is-windows: 1.0.2 - kind-of: 6.0.3 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color + stylis: 4.3.6 + + nanoid@3.3.9: {} napi-build-utils@2.0.0: {} @@ -17659,16 +16029,6 @@ snapshots: node-addon-api@5.1.0: {} - node-canvas-webgl@0.3.0(encoding@0.1.13): - dependencies: - canvas: 2.11.2(encoding@0.1.13) - gl: 6.0.2 - transitivePeerDependencies: - - bluebird - - encoding - - supports-color - optional: true - node-dir@0.1.17: dependencies: minimatch: 3.1.2 @@ -17681,24 +16041,6 @@ snapshots: optionalDependencies: encoding: 0.1.13 - node-gyp@9.4.1: - dependencies: - env-paths: 2.2.1 - exponential-backoff: 3.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - make-fetch-happen: 10.2.1 - nopt: 6.0.0 - npmlog: 6.0.2 - rimraf: 3.0.2 - semver: 7.7.1 - tar: 6.2.1 - which: 2.0.2 - transitivePeerDependencies: - - bluebird - - supports-color - optional: true - node-gzip@1.1.2: {} node-html-parser@6.1.13: @@ -17723,16 +16065,6 @@ snapshots: abbrev: 1.1.1 optional: true - nopt@5.0.0: - dependencies: - abbrev: 1.1.1 - optional: true - - nopt@6.0.0: - dependencies: - abbrev: 1.1.1 - optional: true - normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 @@ -17747,10 +16079,6 @@ snapshots: semver: 7.7.1 validate-npm-package-license: 3.0.4 - normalize-path@2.1.1: - dependencies: - remove-trailing-separator: 1.1.0 - normalize-path@3.0.0: {} npm-run-all@4.1.5: @@ -17769,22 +16097,6 @@ snapshots: dependencies: path-key: 3.1.1 - npmlog@5.0.1: - dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - optional: true - - npmlog@6.0.2: - dependencies: - are-we-there-yet: 3.0.1 - console-control-strings: 1.1.0 - gauge: 4.0.4 - set-blocking: 2.0.0 - optional: true - nth-check@2.1.1: dependencies: boolbase: 1.0.0 @@ -17800,12 +16112,6 @@ snapshots: object-assign@4.1.1: {} - object-copy@0.1.0: - dependencies: - copy-descriptor: 0.1.1 - define-property: 0.2.5 - kind-of: 3.2.2 - object-inspect@1.13.4: {} object-is@1.1.6: @@ -17815,10 +16121,6 @@ snapshots: object-keys@1.1.1: {} - object-visit@1.0.1: - dependencies: - isobject: 3.0.1 - object.assign@4.1.7: dependencies: call-bind: 1.0.8 @@ -17842,10 +16144,6 @@ snapshots: es-abstract: 1.24.0 es-object-atoms: 1.1.1 - object.pick@1.3.0: - dependencies: - isobject: 3.0.1 - object.values@1.2.1: dependencies: call-bind: 1.0.8 @@ -17856,10 +16154,6 @@ snapshots: omggif@1.0.10: optional: true - on-finished@2.3.0: - dependencies: - ee-first: 1.1.1 - on-finished@2.4.1: dependencies: ee-first: 1.1.1 @@ -17882,10 +16176,6 @@ snapshots: opener@1.5.2: {} - opn@6.0.0: - dependencies: - is-wsl: 1.1.0 - optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -18016,8 +16306,6 @@ snapshots: no-case: 3.0.4 tslib: 2.8.1 - pascalcase@0.1.1: {} - path-browserify@1.0.1: {} path-case@3.0.4: @@ -18025,8 +16313,6 @@ snapshots: dot-case: 3.0.4 tslib: 2.8.1 - path-dirname@1.0.2: {} - path-exists-cli@2.0.0: dependencies: meow: 10.1.5 @@ -18065,10 +16351,6 @@ snapshots: pathval@1.1.1: {} - pause-stream@0.0.11: - dependencies: - through: 2.3.8 - pbkdf2@3.1.2: dependencies: create-hash: 1.2.0 @@ -18158,8 +16440,6 @@ snapshots: dependencies: '@babel/runtime': 7.26.9 - poly-decomp@0.3.0: {} - portfinder@1.0.33: dependencies: async: 2.6.4 @@ -18168,8 +16448,6 @@ snapshots: transitivePeerDependencies: - supports-color - posix-character-classes@0.1.1: {} - possible-typed-array-names@1.1.0: {} postcss@8.5.3: @@ -18307,14 +16585,6 @@ snapshots: prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad prismarine-nbt: 2.7.0 - prismarine-schematic@1.2.3: - dependencies: - minecraft-data: 3.105.0 - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad - prismarine-nbt: 2.7.0 - prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c - vec3: 0.1.10 - prismarine-windows@2.9.0: dependencies: prismarine-item: 1.18.0 @@ -18333,17 +16603,6 @@ snapshots: progress@2.0.3: {} - promise-inflight@1.0.1: - optional: true - - promise-queue@2.2.5: {} - - promise-retry@2.0.1: - dependencies: - err-code: 2.0.3 - retry: 0.12.0 - optional: true - prompts@2.4.2: dependencies: kleur: 3.0.3 @@ -18458,8 +16717,6 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 - proxy-compare@2.5.1: {} - proxy-compare@2.6.0: {} proxy-from-env@1.0.0: @@ -18467,8 +16724,6 @@ snapshots: proxy-from-env@1.1.0: {} - proxy-middleware@0.15.0: {} - psl@1.15.0: dependencies: punycode: 2.3.1 @@ -18508,7 +16763,7 @@ snapshots: puppeteer-core@2.1.1: dependencies: '@types/mime-types': 2.1.4 - debug: 4.4.3 + debug: 4.4.1 extract-zip: 1.7.0 https-proxy-agent: 4.0.0 mime: 2.6.0 @@ -18548,8 +16803,6 @@ snapshots: quick-lru@5.1.1: {} - quickselect@2.0.0: {} - railroad-diagrams@1.0.0: {} rambda@6.9.0: {} @@ -18587,10 +16840,6 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 - rbush@3.0.1: - dependencies: - quickselect: 2.0.0 - rc@1.2.8: dependencies: deep-extend: 0.6.0 @@ -18790,14 +17039,6 @@ snapshots: parse-json: 5.2.0 type-fest: 1.4.0 - readable-stream@1.0.34: - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 0.0.1 - string_decoder: 0.10.31 - optional: true - readable-stream@2.3.8: dependencies: core-util-is: 1.0.3 @@ -18822,14 +17063,6 @@ snapshots: process: 0.11.10 string_decoder: 1.3.0 - readdirp@2.2.1: - dependencies: - graceful-fs: 4.2.11 - micromatch: 3.1.10 - readable-stream: 2.3.8 - transitivePeerDependencies: - - supports-color - readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -18877,11 +17110,6 @@ snapshots: dependencies: '@babel/runtime': 7.26.9 - regex-not@1.0.2: - dependencies: - extend-shallow: 3.0.2 - safe-regex: 1.1.0 - regexp-tree@0.1.27: {} regexp.prototype.flags@1.5.4: @@ -18952,12 +17180,6 @@ snapshots: transitivePeerDependencies: - supports-color - remove-trailing-separator@1.1.0: {} - - repeat-element@1.1.4: {} - - repeat-string@1.6.1: {} - request-progress@3.0.0: dependencies: throttleit: 1.0.1 @@ -18975,9 +17197,8 @@ snapshots: resolve-from@5.0.0: {} - resolve-pkg-maps@1.0.0: {} - - resolve-url@0.2.1: {} + resolve-pkg-maps@1.0.0: + optional: true resolve@1.22.10: dependencies: @@ -18998,9 +17219,6 @@ snapshots: ret@0.1.15: {} - retry@0.12.0: - optional: true - reusify@1.1.0: {} rfdc@1.4.1: @@ -19097,18 +17315,12 @@ snapshots: es-errors: 1.3.0 is-regex: 1.2.1 - safe-regex@1.1.0: - dependencies: - ret: 0.1.15 - safer-buffer@2.1.2: {} sanitize-filename@1.6.3: dependencies: truncate-utf8-bytes: 1.0.2 - sat@0.9.0: {} - sax@1.4.1: optional: true @@ -19146,22 +17358,6 @@ snapshots: transitivePeerDependencies: - supports-color - send@1.2.1: - dependencies: - debug: 4.4.3 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 2.0.0 - http-errors: 2.0.1 - mime-types: 3.0.2 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - sentence-case@3.0.4: dependencies: no-case: 3.0.4 @@ -19172,18 +17368,6 @@ snapshots: dependencies: randombytes: 2.1.0 - serve-index@1.9.1: - dependencies: - accepts: 1.3.8 - batch: 0.6.1 - debug: 2.6.9 - escape-html: 1.0.3 - http-errors: 1.6.3 - mime-types: 2.1.35 - parseurl: 1.3.3 - transitivePeerDependencies: - - supports-color - serve-static@1.16.2: dependencies: encodeurl: 2.0.0 @@ -19193,9 +17377,6 @@ snapshots: transitivePeerDependencies: - supports-color - set-blocking@2.0.0: - optional: true - set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -19220,17 +17401,8 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.1.1 - set-value@2.0.1: - dependencies: - extend-shallow: 2.0.1 - is-extendable: 0.1.1 - is-plain-object: 2.0.4 - split-string: 3.1.0 - setimmediate@1.0.5: {} - setprototypeof@1.1.0: {} - setprototypeof@1.2.0: {} sha.js@2.4.11: @@ -19330,13 +17502,6 @@ snapshots: simple-concat@1.0.1: {} - simple-get@3.1.1: - dependencies: - decompress-response: 4.2.1 - once: 1.4.0 - simple-concat: 1.0.1 - optional: true - simple-get@4.0.1: dependencies: decompress-response: 6.0.0 @@ -19353,7 +17518,13 @@ snapshots: skinview3d@3.1.0: dependencies: - '@types/three': 0.156.0 + '@types/three': 0.154.0 + skinview-utils: 0.7.1 + three: 0.154.0 + + skinview3d@3.4.1: + dependencies: + '@types/three': 0.154.0 skinview-utils: 0.7.1 three: 0.154.0 @@ -19382,41 +17553,9 @@ snapshots: dot-case: 3.0.4 tslib: 2.8.1 - snapdragon-node@2.1.1: - dependencies: - define-property: 1.0.0 - isobject: 3.0.1 - snapdragon-util: 3.0.1 - - snapdragon-util@3.0.1: - dependencies: - kind-of: 3.2.2 - - snapdragon@0.8.2: - dependencies: - base: 0.11.2 - debug: 2.6.9 - define-property: 0.2.5 - extend-shallow: 2.0.1 - map-cache: 0.2.2 - source-map: 0.5.7 - source-map-resolve: 0.5.3 - use: 3.1.1 - transitivePeerDependencies: - - supports-color - socket.io-adapter@1.1.2: optional: true - socket.io-adapter@2.5.5: - dependencies: - debug: 4.3.7 - ws: 8.17.1 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - socket.io-client@2.5.0: dependencies: backo2: 1.0.2 @@ -19436,17 +17575,6 @@ snapshots: - utf-8-validate optional: true - socket.io-client@4.8.1: - dependencies: - '@socket.io/component-emitter': 3.1.2 - debug: 4.3.7 - engine.io-client: 6.6.3 - socket.io-parser: 4.2.4 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - socket.io-parser@3.3.4: dependencies: component-emitter: 1.3.1 @@ -19465,13 +17593,6 @@ snapshots: - supports-color optional: true - socket.io-parser@4.2.4: - dependencies: - '@socket.io/component-emitter': 3.1.2 - debug: 4.3.7 - transitivePeerDependencies: - - supports-color - socket.io@2.5.1: dependencies: debug: 4.1.1 @@ -19486,52 +17607,13 @@ snapshots: - utf-8-validate optional: true - socket.io@4.8.1: - dependencies: - accepts: 1.3.8 - base64id: 2.0.0 - cors: 2.8.5 - debug: 4.3.7 - engine.io: 6.6.4 - socket.io-adapter: 2.5.5 - socket.io-parser: 4.2.4 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - socks-proxy-agent@7.0.0: - dependencies: - agent-base: 6.0.2 - debug: 4.4.3 - socks: 2.8.4 - transitivePeerDependencies: - - supports-color - optional: true - - socks@2.8.4: - dependencies: - ip-address: 9.0.5 - smart-buffer: 4.2.0 - optional: true - source-map-js@1.2.1: {} - source-map-resolve@0.5.3: - dependencies: - atob: 2.1.2 - decode-uri-component: 0.2.2 - resolve-url: 0.2.1 - source-map-url: 0.4.1 - urix: 0.1.0 - source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - source-map-url@0.4.1: {} - source-map@0.5.6: {} source-map@0.5.7: {} @@ -19560,19 +17642,8 @@ snapshots: spdx-license-ids@3.0.21: {} - split-string@3.1.0: - dependencies: - extend-shallow: 3.0.2 - - split@0.3.3: - dependencies: - through: 2.3.8 - sprintf-js@1.0.3: {} - sprintf-js@1.1.3: - optional: true - sshpk@1.18.0: dependencies: asn1: 0.2.6 @@ -19586,11 +17657,6 @@ snapshots: tweetnacl: 0.14.5 optional: true - ssri@9.0.1: - dependencies: - minipass: 3.3.6 - optional: true - stack-generator@2.0.10: dependencies: stackframe: 1.3.4 @@ -19612,21 +17678,12 @@ snapshots: state-local@1.0.7: {} - static-extend@0.1.2: - dependencies: - define-property: 0.2.5 - object-copy: 0.1.0 - stats-gl@1.0.7: {} stats.js@0.17.0: {} - statuses@1.5.0: {} - statuses@2.0.1: {} - statuses@2.0.2: {} - std-env@3.8.1: {} stop-iteration-iterator@1.1.0: @@ -19650,10 +17707,6 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - stream-combiner@0.0.4: - dependencies: - duplexer: 0.1.2 - stream-http@3.2.0: dependencies: builtin-status-codes: 3.0.0 @@ -19728,9 +17781,6 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 - string_decoder@0.10.31: - optional: true - string_decoder@1.1.1: dependencies: safe-buffer: 5.1.2 @@ -19800,6 +17850,8 @@ snapshots: tabbable@6.2.0: {} + tagged-tag@1.0.0: {} + tar-fs@2.1.2: dependencies: chownr: 1.1.4 @@ -19864,19 +17916,11 @@ snapshots: text-table@0.2.0: {} - thenify-all@1.6.0: - dependencies: - thenify: 3.3.1 - - thenify@3.3.1: - dependencies: - any-promise: 1.3.0 - thingies@1.21.0(tslib@2.8.1): dependencies: tslib: 2.8.1 - three-stdlib@2.35.14(three@0.154.0): + three-stdlib@2.36.1(three@0.154.0): dependencies: '@types/draco3d': 1.4.10 '@types/offscreencanvas': 2019.7.3 @@ -19886,8 +17930,6 @@ snapshots: potpack: 1.0.2 three: 0.154.0 - three.meshline@1.4.0: {} - three@0.154.0: {} throttle-debounce@3.0.1: {} @@ -19895,18 +17937,13 @@ snapshots: throttleit@1.0.1: optional: true - through2@0.6.5: - dependencies: - readable-stream: 1.0.34 - xtend: 4.0.2 - optional: true - through2@2.0.5: dependencies: readable-stream: 2.3.8 xtend: 4.0.2 - through@2.3.8: {} + through@2.3.8: + optional: true timers-browserify@2.0.12: dependencies: @@ -19940,26 +17977,10 @@ snapshots: to-array@0.1.4: optional: true - to-object-path@0.3.0: - dependencies: - kind-of: 3.2.2 - - to-regex-range@2.1.1: - dependencies: - is-number: 3.0.0 - repeat-string: 1.6.1 - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - to-regex@3.0.2: - dependencies: - define-property: 2.0.2 - extend-shallow: 3.0.2 - regex-not: 1.0.2 - safe-regex: 1.1.0 - tocbot@4.35.0: {} toggle-selection@1.0.6: {} @@ -20033,6 +18054,7 @@ snapshots: get-tsconfig: 4.10.0 optionalDependencies: fsevents: 2.3.3 + optional: true tty-browserify@0.0.1: {} @@ -20064,6 +18086,10 @@ snapshots: type-fest@2.19.0: {} + type-fest@5.3.0: + dependencies: + tagged-tag: 1.0.0 + type-is@1.6.18: dependencies: media-typer: 0.3.0 @@ -20164,27 +18190,10 @@ snapshots: trough: 2.2.0 vfile: 6.0.3 - union-value@1.0.1: - dependencies: - arr-union: 3.1.0 - get-value: 2.0.6 - is-extendable: 0.1.1 - set-value: 2.0.1 - union@0.5.0: dependencies: qs: 6.14.0 - unique-filename@2.0.1: - dependencies: - unique-slug: 3.0.0 - optional: true - - unique-slug@3.0.0: - dependencies: - imurmurhash: 0.1.4 - optional: true - unique-string@2.0.0: dependencies: crypto-random-string: 2.0.0 @@ -20229,8 +18238,6 @@ snapshots: universalify@2.0.1: {} - unix-crypt-td-js@1.1.4: {} - unpipe@1.0.0: {} unplugin@1.16.1: @@ -20238,11 +18245,6 @@ snapshots: acorn: 8.14.1 webpack-virtual-modules: 0.6.2 - unset-value@1.0.0: - dependencies: - has-value: 0.3.1 - isobject: 3.0.1 - untildify@4.0.0: {} upath@1.2.0: {} @@ -20265,8 +18267,6 @@ snapshots: dependencies: punycode: 2.3.1 - urix@0.1.0: {} - url-join@4.0.1: {} url-parse@1.5.10: @@ -20324,8 +18324,6 @@ snapshots: optionalDependencies: typescript: 5.5.4 - use@3.1.1: {} - utf8-byte-length@1.0.5: {} utif@2.0.1: @@ -20349,8 +18347,6 @@ snapshots: dependencies: macaddress: 0.5.3 - uuid@3.4.0: {} - uuid@8.3.2: {} uuid@9.0.1: {} @@ -20360,14 +18356,6 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - valtio@1.11.2(@types/react@18.3.18)(react@18.3.1): - dependencies: - proxy-compare: 2.5.1 - use-sync-external-store: 1.2.0(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.18 - react: 18.3.1 - valtio@1.13.2(@types/react@18.3.18)(react@18.3.1): dependencies: derive-valtio: 0.1.0(valtio@1.13.2(@types/react@18.3.18)(react@18.3.1)) @@ -20515,14 +18503,6 @@ snapshots: dependencies: sdp: 3.2.0 - websocket-driver@0.7.4: - dependencies: - http-parser-js: 0.5.9 - safe-buffer: 5.2.1 - websocket-extensions: 0.1.4 - - websocket-extensions@0.1.4: {} - whatwg-encoding@2.0.0: dependencies: iconv-lite: 0.6.3 @@ -20604,11 +18584,6 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 - wide-align@1.1.5: - dependencies: - string-width: 4.2.3 - optional: true - word-wrap@1.2.5: {} wordwrap@1.0.0: {} @@ -20769,8 +18744,6 @@ snapshots: ws@7.5.10: optional: true - ws@8.17.1: {} - ws@8.18.1: {} xhr@2.6.0: @@ -20796,8 +18769,6 @@ snapshots: xmlhttprequest-ssl@1.6.3: optional: true - xmlhttprequest-ssl@2.1.2: {} - xtend@4.0.2: {} xxhash-wasm@0.4.2: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 5de14962b..ccbac807c 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,2 @@ packages: - "." - - "renderer" - - "renderer/viewer/sign-renderer/" diff --git a/renderer/.npmrc b/renderer/.npmrc deleted file mode 100644 index 3c6e1f1ab..000000000 --- a/renderer/.npmrc +++ /dev/null @@ -1,3 +0,0 @@ -public-hoist-pattern=* -shell-emulator=true -package-lock=false diff --git a/renderer/buildMesherConfig.mjs b/renderer/buildMesherConfig.mjs deleted file mode 100644 index 2c867222a..000000000 --- a/renderer/buildMesherConfig.mjs +++ /dev/null @@ -1 +0,0 @@ -export const dynamicMcDataFiles = ['blocks', 'blockCollisionShapes', 'biomes', 'version'] diff --git a/renderer/buildMesherWorker.mjs b/renderer/buildMesherWorker.mjs deleted file mode 100644 index d88297a5e..000000000 --- a/renderer/buildMesherWorker.mjs +++ /dev/null @@ -1,141 +0,0 @@ -//@ts-check -import { context } from 'esbuild' -import { build } from 'esbuild' -import { polyfillNode } from 'esbuild-plugin-polyfill-node' -import path from 'path' -import { fileURLToPath } from 'url' -import fs from 'fs' -import { dynamicMcDataFiles } from './buildMesherConfig.mjs' -import { mesherSharedPlugins } from '../scripts/esbuildPlugins.mjs' - -const allowedBundleFiles = ['legacy', 'versions', 'protocolVersions', 'features'] - -const __dirname = path.dirname(fileURLToPath(new URL(import.meta.url))) - -const watch = process.argv.includes('-w') - -/** @type {import('esbuild').BuildOptions} */ -const buildOptions = { - bundle: true, - banner: { - js: `globalThis.global = globalThis;process = {env: {}, versions: {} };`, - }, - platform: 'browser', - entryPoints: [path.join(__dirname, './viewer/lib/mesher/mesher.ts')], - minify: !watch, - logLevel: 'info', - drop: !watch ? [ - 'debugger' - ] : [], - sourcemap: 'linked', - target: watch ? undefined : ['ios14'], - write: false, - metafile: true, - outdir: path.join(__dirname, './dist'), - define: { - 'process.env.BROWSER': '"true"', - }, - loader: { - '.png': 'dataurl', - '.obj': 'text' - }, - plugins: [ - ...mesherSharedPlugins, - { - name: 'external-json', - setup(build) { - build.onResolve({ filter: /\.json$/ }, args => { - const fileName = args.path.split('/').pop().replace('.json', '') - if (args.resolveDir.includes('minecraft-data')) { - if (args.path.replaceAll('\\', '/').endsWith('bedrock/common/protocolVersions.json')) { - return - } - if (args.path.includes('bedrock')) { - return { path: args.path, namespace: 'empty-file', } - } - if (dynamicMcDataFiles.includes(fileName)) { - return { - path: args.path, - namespace: 'mc-data', - } - } - if (!allowedBundleFiles.includes(fileName)) { - return { path: args.path, namespace: 'empty-file', } - } - } - }) - build.onResolve({ - filter: /^zlib$/, - }, ({ path }) => { - return { - path, - namespace: 'empty-file', - } - }) - build.onLoad({ - filter: /.*/, - namespace: 'empty-file', - }, () => { - return { contents: 'module.exports = undefined', loader: 'js' } - }) - build.onLoad({ - namespace: 'mc-data', - filter: /.*/, - }, async ({ path }) => { - const fileName = path.split(/[\\\/]/).pop().replace('.json', '') - return { - contents: `module.exports = globalThis.mcData["${fileName}"]`, - loader: 'js', - resolveDir: process.cwd(), - } - }) - build.onResolve({ - filter: /^esbuild-data$/, - }, () => { - return { - path: 'esbuild-data', - namespace: 'esbuild-data', - } - }) - build.onLoad({ - filter: /.*/, - namespace: 'esbuild-data', - }, () => { - const data = { - // todo always use latest - tints: 'require("minecraft-data/minecraft-data/data/pc/1.16.2/tints.json")' - } - return { - contents: `module.exports = {${Object.entries(data).map(([key, code]) => `${key}: ${code}`).join(', ')}}`, - loader: 'js', - resolveDir: process.cwd(), - } - }) - build.onEnd(({ metafile, outputFiles }) => { - if (!metafile) return - fs.mkdirSync(path.join(__dirname, './dist'), { recursive: true }) - fs.writeFileSync(path.join(__dirname, './dist/metafile.json'), JSON.stringify(metafile)) - for (const outDir of ['../dist/', './dist/']) { - for (const outputFile of outputFiles) { - if (outDir === '../dist/' && outputFile.path.endsWith('.map')) { - // skip writing & browser loading sourcemap there, worker debugging should be done in playground - // continue - } - const writePath = path.join(__dirname, outDir, path.basename(outputFile.path)) - fs.mkdirSync(path.dirname(writePath), { recursive: true }) - fs.writeFileSync(writePath, outputFile.text) - } - } - }) - } - }, - polyfillNode(), - ], -} - -if (watch) { - const ctx = await context(buildOptions) - await ctx.watch() -} else { - await build(buildOptions) -} diff --git a/renderer/package.json b/renderer/package.json deleted file mode 100644 index 10049f4f8..000000000 --- a/renderer/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "renderer", - "version": "1.25.0", - "description": "Web based viewer", - "main": "index.js", - "scripts": {}, - "author": "PrismarineJS", - "license": "MIT", - "standard": { - "ignore": [ - "examples/electron/", - "examples/exporter/", - "examples/standalone/", - "examples/web_client/" - ] - }, - "dependencies": { - "@tweenjs/tween.js": "^20.0.3", - "assert": "^2.0.0", - "buffer": "^6.0.3", - "filesize": "^10.0.12", - "fs-extra": "^11.0.0", - "lil-gui": "^0.18.2", - "minecraft-wrap": "^1.3.0", - "minecrafthawkeye": "^1.3.6", - "prismarine-block": "^1.7.3", - "prismarine-chunk": "^1.22.0", - "prismarine-schematic": "^1.2.0", - "renderer": "link:./", - "process": "^0.11.10", - "socket.io": "^4.0.0", - "socket.io-client": "^4.0.0", - "three-stdlib": "^2.26.11", - "three.meshline": "^1.3.0", - "tsx": "^4.7.0", - "vec3": "^0.1.7" - }, - "optionalDependencies": { - "canvas": "^2.11.2", - "node-canvas-webgl": "^0.3.0" - }, - "devDependencies": { - "live-server": "^1.2.2" - } -} diff --git a/renderer/playground.html b/renderer/playground.html deleted file mode 100644 index 258426feb..000000000 --- a/renderer/playground.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - Renderer Playground - - - - - -
- - diff --git a/renderer/playground/allEntitiesDebug.ts b/renderer/playground/allEntitiesDebug.ts deleted file mode 100644 index 5bc56ca62..000000000 --- a/renderer/playground/allEntitiesDebug.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { EntityMesh, rendererSpecialHandled, EntityDebugFlags } from '../viewer/three/entity/EntityMesh' - -export const displayEntitiesDebugList = (version: string) => { - // Create results container - const container = document.createElement('div') - container.style.cssText = ` - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - max-height: 90vh; - overflow-y: auto; - background: rgba(0,0,0,0.8); - color: white; - padding: 20px; - border-radius: 8px; - font-family: monospace; - min-width: 400px; - z-index: 1000; - ` - document.body.appendChild(container) - - // Add title - const title = document.createElement('h2') - title.textContent = 'Minecraft Entity Support' - title.style.cssText = 'margin-top: 0; text-align: center;' - container.appendChild(title) - - // Test entities - const results: Array<{ - entity: string; - supported: boolean; - type?: 'obj' | 'bedrock' | 'special'; - mappedFrom?: string; - textureMap?: boolean; - errors?: string[]; - }> = [] - const { mcData } = window - const entityNames = Object.keys(mcData.entitiesArray.reduce((acc, entity) => { - acc[entity.name] = true - return acc - }, {})) - - // Add loading indicator - const loading = document.createElement('div') - loading.textContent = 'Testing entities...' - loading.style.textAlign = 'center' - container.appendChild(loading) - - for (const entity of entityNames) { - const debugFlags: EntityDebugFlags = {} - - if (rendererSpecialHandled.includes(entity)) { - results.push({ - entity, - supported: true, - type: 'special', - }) - continue - } - - try { - - const { mesh: entityMesh } = new EntityMesh(version, entity, undefined, {}, debugFlags) - // find the most distant pos child - window.objects ??= {} - window.objects[entity] = entityMesh - - results.push({ - entity, - supported: !!debugFlags.type || rendererSpecialHandled.includes(entity), - type: debugFlags.type, - mappedFrom: debugFlags.tempMap, - textureMap: debugFlags.textureMap, - errors: debugFlags.errors - }) - } catch (e) { - console.error(e) - results.push({ - entity, - supported: false, - mappedFrom: debugFlags.tempMap - }) - } - } - - // Remove loading indicator - loading.remove() - - const createSection = (title: string, items: any[], filter: (item: any) => boolean) => { - const section = document.createElement('div') - section.style.marginBottom = '20px' - - const sectionTitle = document.createElement('h3') - sectionTitle.textContent = title - sectionTitle.style.textAlign = 'center' - section.appendChild(sectionTitle) - - const list = document.createElement('ul') - list.style.cssText = 'padding-left: 20px; list-style-type: none; margin: 0;' - - const filteredItems = items.filter(filter) - for (const item of filteredItems) { - const listItem = document.createElement('li') - listItem.style.cssText = 'line-height: 1.4; margin: 8px 0;' - - const entityName = document.createElement('strong') - entityName.style.cssText = 'user-select: text;-webkit-user-select: text;' - entityName.textContent = item.entity - listItem.appendChild(entityName) - - let text = '' - if (item.mappedFrom) { - text += ` -> ${item.mappedFrom}` - } - if (item.type) { - text += ` - ${item.type}` - } - if (item.textureMap) { - text += ' ⚠️' - } - if (item.errors) { - text += ' ❌' - } - - listItem.appendChild(document.createTextNode(text)) - list.appendChild(listItem) - } - - section.appendChild(list) - return { section, count: filteredItems.length } - } - - // Sort results - bedrock first - results.sort((a, b) => { - if (a.type === 'bedrock' && b.type !== 'bedrock') return -1 - if (a.type !== 'bedrock' && b.type === 'bedrock') return 1 - return a.entity.localeCompare(b.entity) - }) - - // Add sections - const sections = [ - { - title: '❌ Unsupported Entities', - filter: (r: any) => !r.supported && !r.mappedFrom - }, - { - title: '⚠️ Partially Supported Entities', - filter: (r: any) => r.mappedFrom - }, - { - title: '✅ Supported Entities', - filter: (r: any) => r.supported && !r.mappedFrom - } - ] - - for (const { title, filter } of sections) { - const { section, count } = createSection(title, results, filter) - if (count > 0) { - container.appendChild(section) - } - } - - // log object with errors per entity - const errors = results.filter(r => r.errors).map(r => ({ - entity: r.entity, - errors: r.errors - })) - console.log(errors) -} diff --git a/renderer/playground/baseScene.ts b/renderer/playground/baseScene.ts deleted file mode 100644 index fbf3fb19f..000000000 --- a/renderer/playground/baseScene.ts +++ /dev/null @@ -1,577 +0,0 @@ -import { Vec3 } from 'vec3' -import * as THREE from 'three' -import '../../src/getCollisionShapes' -import { IndexedData } from 'minecraft-data' -import BlockLoader from 'prismarine-block' -import ChunkLoader from 'prismarine-chunk' -import WorldLoader from 'prismarine-world' -import { proxy } from 'valtio' - -//@ts-expect-error -import { OrbitControls } from 'three/addons/controls/OrbitControls.js' -// eslint-disable-next-line import/no-named-as-default -import GUI from 'lil-gui' -import _ from 'lodash' -import supportedVersions from '../../src/supportedVersions.mjs' -import { toMajorVersion } from '../../src/utils' -import { BlockNames } from '../../src/mcDataTypes' -import { defaultWorldRendererConfig, WorldRendererConfig } from '../viewer/lib/worldrendererCommon' -import { WorldDataEmitter } from '../viewer/lib/worldDataEmitter' -import { getInitialPlayerState } from '../viewer/lib/basePlayerState' -import { appGraphicBackends } from '../../src/appViewerLoad' -import { getSyncWorld } from './shared' - -window.THREE = THREE - -// Scene configuration interface -export interface PlaygroundSceneConfig { - version?: string - viewDistance?: number - targetPos?: Vec3 - enableCameraControls?: boolean - enableCameraOrbitControl?: boolean - worldConfig?: WorldRendererConfig - continuousRender?: boolean -} - -const includedVersions = globalThis.includedVersions ?? supportedVersions - -export class BasePlaygroundScene { - // Rendering state - continuousRender = false - stopRender = false - windowHidden = false - - // Scene configuration - viewDistance = 0 - targetPos = new Vec3(2, 90, 2) - version: string = new URLSearchParams(window.location.search).get('version') || includedVersions.at(-1)! - - // World data - Chunk: typeof import('prismarine-chunk/types/index').PCChunk - Block: typeof import('prismarine-block').Block - world: ReturnType - - // GUI - gui = new GUI() - params = {} as Record - paramOptions = {} as Partial> - onParamUpdate = {} as Record void> - alwaysIgnoreQs = [] as string[] - skipUpdateQs = false - - // Camera controls - own camera synced to backend - enableCameraControls = true - enableCameraOrbitControl = true - controls: OrbitControls | undefined - camera: THREE.PerspectiveCamera - - // World data emitter (from appViewer) - worldView: WorldDataEmitter | undefined - - // Debug FPS tracking - private debugFpsElement: HTMLElement | undefined - private frameCount = 0 - private lastSecondTime = performance.now() - private frameTimes: number[] = [] - private currentFps = 0 - private maxFrameDelay = 0 - - // Getter for worldRenderer - accesses via window.world for advanced scene features - // This allows derived scenes to access worldRenderer when needed without storing it - get worldRenderer () { - return window.world - } - - // World config - syncs with appViewer.inWorldRenderingConfig - get worldConfig () { - return appViewer.inWorldRenderingConfig - } - set worldConfig (value) { - // Merge the new values into appViewer's config to maintain reactivity - Object.assign(appViewer.inWorldRenderingConfig, value) - } - - constructor (config: PlaygroundSceneConfig = {}) { - // Apply config - if (config.version) this.version = config.version - - // Ensure version is always set (fallback to latest supported version) - if (!this.version) { - throw new Error('Minecraft version is not set') - } - - if (config.viewDistance !== undefined) this.viewDistance = config.viewDistance - if (config.targetPos) this.targetPos = config.targetPos - if (config.enableCameraControls !== undefined) this.enableCameraControls = config.enableCameraControls - if (config.enableCameraOrbitControl !== undefined) this.enableCameraOrbitControl = config.enableCameraOrbitControl - if (config.worldConfig) { - // Merge config into appViewer's config to maintain reactivity - Object.assign(appViewer.inWorldRenderingConfig, config.worldConfig) - } - appViewer.inWorldRenderingConfig.showHand = false - appViewer.inWorldRenderingConfig.isPlayground = true - appViewer.inWorldRenderingConfig.instantCameraUpdate = this.enableCameraOrbitControl - appViewer.config.statsVisible = 2 - if (config.continuousRender !== undefined) this.continuousRender = config.continuousRender - - void this.initData().then(() => { - this.addKeyboardShortcuts() - }) - } - - onParamsUpdate (paramName: string, object: any) {} - - updateQs (paramName: string, valueSet: any) { - if (this.skipUpdateQs) return - const newQs = new URLSearchParams(window.location.search) - for (const [key, value] of Object.entries({ [paramName]: valueSet })) { - if (typeof value === 'function' || this.params.skipQs?.includes(key) || this.alwaysIgnoreQs.includes(key)) continue - if (value) { - newQs.set(key, value) - } else { - newQs.delete(key) - } - } - window.history.replaceState({}, '', `${window.location.pathname}?${newQs.toString()}`) - } - - renderFinish () { - this.requestRender() - } - - initGui () { - const qs = new URLSearchParams(window.location.search) - for (const key of Object.keys(this.params)) { - const value = qs.get(key) - if (!value) continue - const parsed = /^-?\d+$/.test(value) ? Number(value) : value === 'true' ? true : value === 'false' ? false : value - this.params[key] = parsed - } - - for (const param of Object.keys(this.params)) { - const option = this.paramOptions[param] - if (option?.hide) continue - this.gui.add(this.params, param, option?.options ?? option?.min, option?.max) - } - if (window.innerHeight < 700) { - this.gui.open(false) - } else { - setTimeout(() => { - this.gui.domElement.classList.remove('transition') - }, 500) - } - - this.gui.onChange(({ property, object }) => { - if (object === this.params) { - this.onParamUpdate[property]?.() - this.onParamsUpdate(property, object) - const value = this.params[property] - if (this.paramOptions[property]?.reloadOnChange && (typeof value === 'boolean' || this.paramOptions[property].options)) { - setTimeout(() => { - window.location.reload() - }) - } - this.updateQs(property, value) - } else { - this.onParamsUpdate(property, object) - } - }) - } - - // Overridable methods - setupWorld () { } - sceneReset () {} - - // eslint-disable-next-line max-params - addWorldBlock (xOffset: number, yOffset: number, zOffset: number, blockName: BlockNames, properties?: Record) { - if (xOffset > 16 || yOffset > 16 || zOffset > 16) throw new Error('Offset too big') - const block = - properties ? - this.Block.fromProperties(loadedData.blocksByName[blockName].id, properties ?? {}, 0) : - this.Block.fromStateId(loadedData.blocksByName[blockName].defaultState, 0) - this.world.setBlock(this.targetPos.offset(xOffset, yOffset, zOffset), block) - } - - // Sync our camera state to the graphics backend - // Extract rotation from OrbitControls spherical coordinates to avoid flip issues - protected syncCameraToBackend (onlyRotation = false) { - if (!appViewer.backend || !this.camera) return - - // Extract rotation from camera's quaternion to avoid gimbal lock issues - // Get forward direction vector to extract yaw/pitch properly - const forward = new THREE.Vector3(0, 0, -1) - forward.applyQuaternion(this.camera.quaternion) - - // Calculate yaw and pitch from forward vector - // Yaw: rotation around Y axis (horizontal) - const yaw = Math.atan2(-forward.x, -forward.z) - // Pitch: angle from horizontal plane (vertical) - const pitch = Math.asin(forward.y) - - if (onlyRotation) { - appViewer.backend.updateCamera(null, yaw, pitch) - return - } - - const pos = new Vec3(this.camera.position.x, this.camera.position.y, this.camera.position.z) - appViewer.backend.updateCamera(pos, yaw, pitch) - } - - resetCamera () { - if (!this.camera) return - const { targetPos } = this - this.controls?.target.set(targetPos.x + 0.5, targetPos.y + 0.5, targetPos.z + 0.5) - - const cameraPos = targetPos.offset(2, 2, 2) - this.camera.position.set(cameraPos.x + 0.5, cameraPos.y + 0.5, cameraPos.z + 0.5) - this.camera.lookAt(targetPos.x + 0.5, targetPos.y + 0.5, targetPos.z + 0.5) - this.controls?.update() - // Sync after reset - this uses quaternion extraction which avoids flip issues - this.syncCameraToBackend() - } - - async initData () { - await window._LOAD_MC_DATA() - const mcData: IndexedData = require('minecraft-data')(this.version) - window.loadedData = window.mcData = mcData - - this.Chunk = (ChunkLoader as any)(this.version) - this.Block = (BlockLoader as any)(this.version) - - const world = getSyncWorld(this.version) - world.setBlockStateId(this.targetPos, 0) - this.world = world - - this.initGui() - - // Use appViewer for resource management and world rendering - // worldConfig is already synced with appViewer.inWorldRenderingConfig via getter/setter - - // Initialize resources manager via appViewer - appViewer.resourcesManager.currentConfig = { version: this.version, noInventoryGui: true } - await appViewer.resourcesManager.loadSourceData(this.version) - await appViewer.resourcesManager.updateAssetsData({}) - - // Load backend if not already loaded - if (!appViewer.backend) { - await appViewer.loadBackend(appGraphicBackends[0]) - } - - // Start world using appViewer - // This creates WorldDataEmitter, GraphicsBackend, and WorldRendererThree internally - await appViewer.startWorld(world, this.viewDistance, proxy(getInitialPlayerState()), this.targetPos) - - // Get world view from appViewer - this.worldView = appViewer.worldView - - // Create our own camera for OrbitControls - this is separate from the internal worldRenderer camera - // We sync our camera state to the backend via updateCamera() - this.camera = new THREE.PerspectiveCamera( - appViewer.inWorldRenderingConfig.fov || 75, - window.innerWidth / window.innerHeight, - 0.1, - 1000 - ) - - // Setup world (adds blocks, etc.) - this.setupWorld() - - // Initialize world view with target position (loads chunks after setup) - if (this.worldView) { - this.worldView.addWaitTime = 0 - await this.worldView.init(this.targetPos) - } - - // Setup camera controls with our own camera - if (this.enableCameraControls) { - const canvas = document.querySelector('#viewer-canvas') - if (canvas) { - const controls = this.enableCameraOrbitControl - ? new OrbitControls(this.camera, canvas as HTMLElement) - : undefined - this.controls = controls - - this.resetCamera() - - // Camera position from query string or localStorage - const cameraSet = this.params.camera || localStorage.camera - if (cameraSet) { - const [x, y, z, rx, ry] = cameraSet.split(',').map(Number) - this.camera.position.set(x, y, z) - this.camera.rotation.set(rx, ry, 0, 'ZYX') - this.controls?.update() - // this.syncCameraToBackend() - } - - const throttledCamQsUpdate = _.throttle(() => { - if (!this.camera) return - localStorage.camera = [ - this.camera.position.x.toFixed(2), - this.camera.position.y.toFixed(2), - this.camera.position.z.toFixed(2), - this.camera.rotation.x.toFixed(2), - this.camera.rotation.y.toFixed(2), - ].join(',') - }, 200) - - if (this.controls) { - const throttledCameraSync = _.throttle(() => { - // this.syncCameraToBackend(true) // Only sync rotation when OrbitControls changes - }, 16) // ~60fps sync rate - - this.controls.addEventListener('change', () => { - throttledCameraSync() - throttledCamQsUpdate() - this.requestRender() - }) - } else { - setInterval(() => { - throttledCamQsUpdate() - }, 200) - } - } - } - - // Manual camera controls (if orbit controls disabled) - if (!this.enableCameraOrbitControl && this.camera) { - let mouseMoveCounter = 0 - const mouseMove = (e: PointerEvent) => { - if ((e.target as HTMLElement).closest('.lil-gui')) return - if (e.buttons === 1 || e.pointerType === 'touch') { - mouseMoveCounter++ - this.camera.rotation.x -= e.movementY / 100 - this.camera.rotation.y -= e.movementX / 100 - if (this.camera.rotation.x < -Math.PI / 2) this.camera.rotation.x = -Math.PI / 2 - if (this.camera.rotation.x > Math.PI / 2) this.camera.rotation.x = Math.PI / 2 - this.syncCameraToBackend(true) - } - if (e.buttons === 2) { - this.camera.position.set(0, 0, 0) - this.syncCameraToBackend() - } - } - setInterval(() => { - mouseMoveCounter = 0 - }, 1000) - window.addEventListener('pointermove', mouseMove) - } - - // Setup resize handler - this.onResize() - window.addEventListener('resize', () => this.onResize()) - - // Setup debug FPS GUI - this.setupDebugFpsGui() - - // Wait for chunks and finish setup - // Access worldRenderer via window.world for this one-time operation - // const worldRenderer = window.world - // if (worldRenderer) { - // void worldRenderer.waitForChunksToRender().then(async () => { - // this.renderFinish() - // }) - - // // Listen for world updates to trigger on-demand renders - // worldRenderer.renderUpdateEmitter.addListener('update', () => { - // this.requestRender() - // }) - // } - - // // Start render loop if continuous, otherwise use on-demand rendering - // if (this.continuousRender) { - // this.loop() - // } - this.renderFinish() - this.mainDebugLoop() - } - - mainDebugLoop () { - requestAnimationFrame(() => this.mainDebugLoop()) - this.trackFrame() - } - - loop () { - if (this.continuousRender && !this.windowHidden) { - this.requestRender() - requestAnimationFrame(() => this.loop()) - } - } - - // Request a render from the backend (on-demand rendering) - // The DocumentRenderer loop handles actual rendering continuously - // Camera sync happens via syncCameraToBackend() which updates the internal camera - requestRender () { - // No-op: rendering is handled by DocumentRenderer's continuous loop - // This method exists for API compatibility - } - - private setupDebugFpsGui () { - // Create simple DOM element for debug FPS display in bottom left corner - this.debugFpsElement = document.createElement('div') - this.debugFpsElement.style.position = 'fixed' - this.debugFpsElement.style.bottom = '0' - this.debugFpsElement.style.left = '0' - this.debugFpsElement.style.zIndex = '1000' - this.debugFpsElement.style.backgroundColor = 'rgba(0, 0, 0, 0.7)' - this.debugFpsElement.style.color = '#fff' - this.debugFpsElement.style.padding = '4px 6px' - this.debugFpsElement.style.fontFamily = 'monospace' - this.debugFpsElement.style.fontSize = '11px' - this.debugFpsElement.style.lineHeight = '1.2' - this.debugFpsElement.style.pointerEvents = 'none' - this.debugFpsElement.style.userSelect = 'none' - this.debugFpsElement.textContent = 'FPS: 0 | Max: 0 ms' - - document.body.appendChild(this.debugFpsElement) - - // Update debug info every second - setInterval(() => { - this.updateDebugInfo() - }, 1000) - } - - private trackFrame () { - const now = performance.now() - this.frameTimes.push(now) - this.frameCount++ - - // Calculate frame delay (time since last frame) - if (this.frameTimes.length > 1) { - const delay = now - this.frameTimes.at(-2)! - if (delay > this.maxFrameDelay) { - this.maxFrameDelay = delay - } - } - - // Keep only last second of frame times - const oneSecondAgo = now - 1000 - this.frameTimes = this.frameTimes.filter(time => time > oneSecondAgo) - } - - private updateDebugInfo () { - if (!this.debugFpsElement) return - - // Calculate FPS from number of frames in the last second - // frameTimes array contains timestamps from the last second after filtering - const fps = this.frameTimes.length - - this.currentFps = fps - - const isSeriousDelay = this.maxFrameDelay > 150 - const delayText = isSeriousDelay - ? `${this.maxFrameDelay.toFixed(0)}ms` - : `${this.maxFrameDelay.toFixed(0)}ms` - - // Update the DOM element directly - single line format - this.debugFpsElement.innerHTML = `FPS: ${fps} | Max Delay: ${delayText}` - - // Reset for next second - this.lastSecondTime = performance.now() - this.maxFrameDelay = 0 - this.frameCount = 0 - } - - // Legacy render method for compatibility - render (fromLoop = false) { - this.requestRender() - } - - addKeyboardShortcuts () { - document.addEventListener('keydown', (e) => { - if (!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) { - if (e.code === 'KeyR') { - this.controls?.reset() - this.resetCamera() - } - if (e.code === 'KeyE') { // refresh block (main) - this.worldView!.setBlockStateId(this.targetPos, this.world.getBlockStateId(this.targetPos)) - } - if (e.code === 'KeyF') { // reload all chunks - this.sceneReset() - this.worldView!.unloadAllChunks() - void this.worldView!.init(this.targetPos) - } - } - }) - document.addEventListener('visibilitychange', () => { - this.windowHidden = document.visibilityState === 'hidden' - }) - document.addEventListener('blur', () => { - this.windowHidden = true - }) - document.addEventListener('focus', () => { - this.windowHidden = false - }) - - const pressedKeys = new Set() - const updateKeys = () => { - if (pressedKeys.has('ControlLeft') || pressedKeys.has('MetaLeft')) { - return - } - if (!this.camera) return - - const direction = new THREE.Vector3(0, 0, 0) - if (pressedKeys.has('KeyW')) { - direction.z = -0.5 - } - if (pressedKeys.has('KeyS')) { - direction.z += 0.5 - } - if (pressedKeys.has('KeyA')) { - direction.x -= 0.5 - } - if (pressedKeys.has('KeyD')) { - direction.x += 0.5 - } - - if (pressedKeys.has('ShiftLeft')) { - this.camera.position.y -= 0.5 - } - if (pressedKeys.has('Space')) { - this.camera.position.y += 0.5 - } - direction.applyQuaternion(this.camera.quaternion) - direction.y = 0 - - if (pressedKeys.has('ShiftLeft')) { - direction.y *= 2 - direction.x *= 2 - direction.z *= 2 - } - this.camera.position.add(direction.normalize()) - this.controls?.update() - this.syncCameraToBackend() - this.requestRender() - } - setInterval(updateKeys, 1000 / 20) - - const keys = (e: KeyboardEvent) => { - const { code } = e - const pressed = e.type === 'keydown' - if (pressed) { - pressedKeys.add(code) - } else { - pressedKeys.delete(code) - } - } - - window.addEventListener('keydown', keys) - window.addEventListener('keyup', keys) - window.addEventListener('blur', () => { - for (const key of pressedKeys) { - keys(new KeyboardEvent('keyup', { code: key })) - } - }) - } - - onResize () { - this.requestRender() - } -} diff --git a/renderer/playground/playground.ts b/renderer/playground/playground.ts deleted file mode 100644 index aba7df49e..000000000 --- a/renderer/playground/playground.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { BasePlaygroundScene } from './baseScene' -import { playgroundGlobalUiState } from './playgroundUi' -import * as scenes from './scenes' - -const qsScene = new URLSearchParams(window.location.search).get('scene') -const Scene: typeof BasePlaygroundScene = qsScene ? scenes[qsScene] : scenes.main -playgroundGlobalUiState.scenes = ['main', 'railsCobweb', 'floorRandom', 'lightingStarfield', 'transparencyIssue', 'entities', 'frequentUpdates', 'slabsOptimization', 'allEntities', 'geometryExport'] -playgroundGlobalUiState.selected = qsScene ?? 'main' - -const scene = new Scene() -globalThis.scene = scene diff --git a/renderer/playground/playgroundUi.tsx b/renderer/playground/playgroundUi.tsx deleted file mode 100644 index 3e13101d7..000000000 --- a/renderer/playground/playgroundUi.tsx +++ /dev/null @@ -1,196 +0,0 @@ -import { renderToDom } from '@zardoy/react-util' -import { useEffect, useState } from 'react' -import { proxy, useSnapshot } from 'valtio' -import { LeftTouchArea, RightTouchArea, useInterfaceState } from '@dimaka/interface' -import { css } from '@emotion/css' -import { Vec3 } from 'vec3' -import useLongPress from '../../src/react/useLongPress' -import { isMobile } from '../viewer/lib/simpleUtils' - -export const playgroundGlobalUiState = proxy({ - scenes: [] as string[], - selected: '', - selectorOpened: false, - actions: {} as Record void>, -}) - -renderToDom(, { - strictMode: false, - selector: '#react-root', -}) - -function Playground () { - useEffect(() => { - const style = document.createElement('style') - style.innerHTML = /* css */ ` - .lil-gui { - top: 60px !important; - right: 0 !important; - } - ` - document.body.appendChild(style) - return () => { - style.remove() - } - }, []) - - return
- - - -
-} - -function SceneSelector () { - const mobile = isMobile() - const { scenes, selected } = useSnapshot(playgroundGlobalUiState) - const [hidden, setHidden] = useState(false) - const longPressEvents = useLongPress(() => { - playgroundGlobalUiState.selectorOpened = true - }, () => { }) - - if (hidden) return null - - return
-
- {scenes.map(scene =>
{ - const qs = new URLSearchParams(window.location.search) - qs.set('scene', scene) - location.search = qs.toString() - }} - >{scene}
)} -
-
setHidden(true)} - >×
-
-} - -const ActionsSelector = () => { - const { actions, selectorOpened } = useSnapshot(playgroundGlobalUiState) - - if (!selectorOpened) return null - return
{Object.entries({ - ...actions, - 'Close' () { - playgroundGlobalUiState.selectorOpened = false - } - }).map(([name, action]) =>
{ - action() - playgroundGlobalUiState.selectorOpened = false - }} - >{name}
)}
-} - -const Controls = () => { - // todo setting - const usingTouch = navigator.maxTouchPoints > 0 - - useEffect(() => { - window.addEventListener('touchstart', (e) => { - e.preventDefault() - }) - - const pressedKeys = new Set() - useInterfaceState.setState({ - isFlying: false, - uiCustomization: { - touchButtonSize: 40, - }, - updateCoord ([coord, state]) { - const vec3 = new Vec3(0, 0, 0) - vec3[coord] = state - let key: string | undefined - if (vec3.z < 0) key = 'KeyW' - if (vec3.z > 0) key = 'KeyS' - if (vec3.y > 0) key = 'Space' - if (vec3.y < 0) key = 'ShiftLeft' - if (vec3.x < 0) key = 'KeyA' - if (vec3.x > 0) key = 'KeyD' - if (key) { - if (!pressedKeys.has(key)) { - pressedKeys.add(key) - window.dispatchEvent(new KeyboardEvent('keydown', { code: key })) - } - } - for (const k of pressedKeys) { - if (k !== key) { - window.dispatchEvent(new KeyboardEvent('keyup', { code: k })) - pressedKeys.delete(k) - } - } - } - }) - }, []) - - if (!usingTouch) return null - return ( -
div { - pointer-events: auto; - } - `} - > - -
- -
- ) -} diff --git a/renderer/playground/scenes/allEntities.ts b/renderer/playground/scenes/allEntities.ts deleted file mode 100644 index 281af807d..000000000 --- a/renderer/playground/scenes/allEntities.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { BasePlaygroundScene } from '../baseScene' -import { EntityDebugFlags, EntityMesh, rendererSpecialHandled } from '../../viewer/three/entity/EntityMesh' -import { displayEntitiesDebugList } from '../allEntitiesDebug' - -export default class AllEntities extends BasePlaygroundScene { - continuousRender = false - enableCameraControls = false - - async initData () { - await super.initData() - displayEntitiesDebugList(this.version) - } -} diff --git a/renderer/playground/scenes/entities.ts b/renderer/playground/scenes/entities.ts deleted file mode 100644 index 5b5d0582b..000000000 --- a/renderer/playground/scenes/entities.ts +++ /dev/null @@ -1,37 +0,0 @@ -//@ts-nocheck -import * as THREE from 'three' -import { Vec3 } from 'vec3' -import { BasePlaygroundScene } from '../baseScene' -import { WorldRendererThree } from '../../viewer/three/worldrendererThree' - -export default class extends BasePlaygroundScene { - continuousRender = true - - override initGui (): void { - this.params = { - starfield: false, - entity: 'player', - count: 4 - } - } - - override renderFinish (): void { - if (this.params.starfield) { - ;(viewer.world as WorldRendererThree).scene.background = new THREE.Color(0x00_00_00) - ;(viewer.world as WorldRendererThree).starField.enabled = true - ;(viewer.world as WorldRendererThree).starField.addToScene() - } - - for (let i = 0; i < this.params.count; i++) { - for (let j = 0; j < this.params.count; j++) { - for (let k = 0; k < this.params.count; k++) { - viewer.entities.update({ - id: i * 1000 + j * 100 + k, - name: this.params.entity, - pos: this.targetPos.offset(i, j, k) - } as any, {}) - } - } - } - } -} diff --git a/renderer/playground/scenes/floorRandom.ts b/renderer/playground/scenes/floorRandom.ts deleted file mode 100644 index c6d2ccf1c..000000000 --- a/renderer/playground/scenes/floorRandom.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { BasePlaygroundScene } from '../baseScene' - -export default class RailsCobwebScene extends BasePlaygroundScene { - viewDistance = 5 - continuousRender = true - - override initGui (): void { - this.params = { - squareSize: 50 - } - - super.initGui() - } - - setupWorld () { - const squareSize = this.params.squareSize ?? 30 - const maxSquareSize = this.viewDistance * 16 * 2 - if (squareSize > maxSquareSize) throw new Error(`Square size too big, max is ${maxSquareSize}`) - // const fullBlocks = loadedData.blocksArray.map(x => x.name) - const fullBlocks = loadedData.blocksArray.filter(block => { - const b = this.Block.fromStateId(block.defaultState, 0) - if (b.shapes?.length !== 1) return false - const shape = b.shapes[0] - return shape[0] === 0 && shape[1] === 0 && shape[2] === 0 && shape[3] === 1 && shape[4] === 1 && shape[5] === 1 - }) - for (let x = -squareSize; x <= squareSize; x++) { - for (let z = -squareSize; z <= squareSize; z++) { - const i = Math.abs(x + z) * squareSize - worldView!.world.setBlock(this.targetPos.offset(x, 0, z), this.Block.fromStateId(fullBlocks[i % fullBlocks.length].defaultState, 0)) - } - } - } -} diff --git a/renderer/playground/scenes/frequentUpdates.ts b/renderer/playground/scenes/frequentUpdates.ts deleted file mode 100644 index caaf72076..000000000 --- a/renderer/playground/scenes/frequentUpdates.ts +++ /dev/null @@ -1,148 +0,0 @@ -//@ts-nocheck -import { Vec3 } from 'vec3' -import { BasePlaygroundScene } from '../baseScene' - -export default class extends BasePlaygroundScene { - viewDistance = 5 - continuousRender = true - - override initGui (): void { - this.params = { - testActive: false, - testUpdatesPerSecond: 10, - testInitialUpdate: false, - stopGeometryUpdate: false, - manualTest: () => { - this.updateBlock() - }, - testNeighborUpdates: () => { - this.testNeighborUpdates() - } - } - - super.initGui() - } - - lastUpdatedOffset = 0 - lastUpdatedId = 2 - updateBlock () { - const x = this.lastUpdatedOffset % 16 - const z = Math.floor(this.lastUpdatedOffset / 16) - const y = 90 - worldView!.setBlockStateId(new Vec3(x, y, z), this.lastUpdatedId++) - this.lastUpdatedOffset++ - if (this.lastUpdatedOffset > 16 * 16) this.lastUpdatedOffset = 0 - if (this.lastUpdatedId > 500) this.lastUpdatedId = 1 - } - - testNeighborUpdates () { - viewer.world.setBlockStateId(new Vec3(15, 95, 15), 1) - viewer.world.setBlockStateId(new Vec3(0, 95, 15), 1) - viewer.world.setBlockStateId(new Vec3(15, 95, 0), 1) - viewer.world.setBlockStateId(new Vec3(0, 95, 0), 1) - - viewer.world.setBlockStateId(new Vec3(16, 95, 15), 1) - viewer.world.setBlockStateId(new Vec3(-1, 95, 15), 1) - viewer.world.setBlockStateId(new Vec3(15, 95, -1), 1) - viewer.world.setBlockStateId(new Vec3(-1, 95, 0), 1) - setTimeout(() => { - viewer.world.setBlockStateId(new Vec3(16, 96, 16), 1) - viewer.world.setBlockStateId(new Vec3(-1, 96, 16), 1) - viewer.world.setBlockStateId(new Vec3(16, 96, -1), 1) - viewer.world.setBlockStateId(new Vec3(-1, 96, -1), 1) - }, 3000) - } - - setupTimer () { - // this.stopRender = true - - let lastTime = 0 - const tick = () => { - viewer.world.debugStopGeometryUpdate = this.params.stopGeometryUpdate - const updateEach = 1000 / this.params.testUpdatesPerSecond - requestAnimationFrame(tick) - if (!this.params.testActive) return - const updateCount = Math.floor(performance.now() - lastTime) / updateEach - for (let i = 0; i < updateCount; i++) { - this.updateBlock() - } - lastTime = performance.now() - } - - requestAnimationFrame(tick) - - // const limit = 1000 - // const limit = 100 - // const limit = 1 - // const updatedChunks = new Set() - // const updatedBlocks = new Set() - // let lastSecond = 0 - // setInterval(() => { - // const second = Math.floor(performance.now() / 1000) - // if (lastSecond !== second) { - // lastSecond = second - // updatedChunks.clear() - // updatedBlocks.clear() - // } - // const isEven = second % 2 === 0 - // if (updatedBlocks.size > limit) { - // return - // } - // const changeBlock = (x, z) => { - // const chunkKey = `${Math.floor(x / 16)},${Math.floor(z / 16)}` - // const key = `${x},${z}` - // if (updatedBlocks.has(chunkKey)) return - - // updatedChunks.add(chunkKey) - // worldView!.world.setBlock(this.targetPos.offset(x, 0, z), this.Block.fromStateId(isEven ? 2 : 3, 0)) - // updatedBlocks.add(key) - // } - // const { squareSize } = this.params - // const xStart = -squareSize - // const zStart = -squareSize - // const xEnd = squareSize - // const zEnd = squareSize - // for (let x = xStart; x <= xEnd; x += 16) { - // for (let z = zStart; z <= zEnd; z += 16) { - // const key = `${x},${z}` - // if (updatedChunks.has(key)) continue - // changeBlock(x, z) - // return - // } - // } - // for (let x = xStart; x <= xEnd; x += 16) { - // for (let z = zStart; z <= zEnd; z += 16) { - // const key = `${x},${z}` - // if (updatedChunks.has(key)) continue - // changeBlock(x, z) - // return - // } - // } - // }, 1) - } - - setupWorld () { - this.worldConfig.showChunkBorders = true - - const maxSquareRadius = this.viewDistance * 16 - // const fullBlocks = loadedData.blocksArray.map(x => x.name) - const squareSize = maxSquareRadius - for (let x = -squareSize; x <= squareSize; x++) { - for (let z = -squareSize; z <= squareSize; z++) { - const i = Math.abs(x + z) * squareSize - worldView!.world.setBlock(this.targetPos.offset(x, 0, z), this.Block.fromStateId(1, 0)) - } - } - let done = false - viewer.world.renderUpdateEmitter.on('update', () => { - if (!viewer.world.allChunksFinished || done) return - done = true - this.setupTimer() - }) - setTimeout(() => { - if (this.params.testInitialUpdate) { - this.updateBlock() - } - }) - } -} diff --git a/renderer/playground/scenes/geometryExport.ts b/renderer/playground/scenes/geometryExport.ts deleted file mode 100644 index cc5b49cda..000000000 --- a/renderer/playground/scenes/geometryExport.ts +++ /dev/null @@ -1,154 +0,0 @@ -import * as THREE from 'three' -import { BasePlaygroundScene } from '../baseScene' -import { - downloadWorldGeometry, - loadWorldGeometryFromUrl, - createMeshesFromExport, - loadTextureFromDataUrl, - type ExportedWorldGeometry -} from '../../viewer/three/worldGeometryExport' - -/** - * Scene for exporting/importing world geometry - * - * Usage: - * - Load normally: builds world from blocks, can export geometry - * - Load with ?geometryUrl=URL: loads pre-exported geometry from file (or default world-geometry.json) - */ -export default class extends BasePlaygroundScene { - params = { - exportGeometry: () => this.exportGeometry(), - exportWithTexture: () => this.exportGeometry(true), - } - - // Loaded geometry data (when loading from URL) - private loadedGeometry: ExportedWorldGeometry | null = null - private importedMeshes: THREE.Group[] = [] - private readonly geometryUrl: string | null - - constructor () { - const qs = new URLSearchParams(window.location.search) - const geometryUrl = qs.get('geometryUrl') ?? 'world-geometry.json' - - // If loading from URL, skip normal world setup (viewDistance 0 means no chunks loaded) - super({ - viewDistance: geometryUrl ? 0 : 1, - continuousRender: false, - enableCameraOrbitControl: false, - }) - - this.geometryUrl = geometryUrl - } - - // Override initData to load geometry after base initialization completes - override async initData () { - await super.initData() - - // Now camera and worldRenderer are ready - load geometry if URL provided - if (this.geometryUrl) { - await this.loadFromUrl(this.geometryUrl) - } - } - - setupWorld () { - if (this.geometryUrl) { - return - } - // Default world setup - add some blocks for testing - this.addWorldBlock(0, 0, 0, 'stone') - this.addWorldBlock(1, 0, 0, 'grass_block') - this.addWorldBlock(0, 0, 1, 'dirt') - this.addWorldBlock(1, 0, 1, 'cobblestone') - this.addWorldBlock(0, 1, 0, 'oak_log') - this.addWorldBlock(1, 1, 0, 'oak_planks') - } - - private async loadFromUrl (url: string) { - try { - console.log('Loading geometry from:', url) - this.loadedGeometry = await loadWorldGeometryFromUrl(url) - - // Restore camera position and rotation - const { camera: camData } = this.loadedGeometry - this.camera.position.set(camData.position.x, camData.position.y, camData.position.z) - - // Apply rotation using lookAt direction - const { pitch, yaw } = camData.rotation - const forward = new THREE.Vector3( - -Math.sin(yaw) * Math.cos(pitch), - Math.sin(pitch), - -Math.cos(yaw) * Math.cos(pitch) - ) - this.camera.lookAt( - camData.position.x + forward.x, - camData.position.y + forward.y, - camData.position.z + forward.z - ) - this.controls?.update() - this.syncCameraToBackend() - - // Determine which material to use - let material: THREE.Material - if (this.loadedGeometry.textureAtlasDataUrl) { - // Use embedded texture from exported file - const texture = await loadTextureFromDataUrl(this.loadedGeometry.textureAtlasDataUrl) - material = new THREE.MeshLambertMaterial({ - map: texture, - vertexColors: true, - transparent: true, - alphaTest: 0.1 - }) - } else { - // Use worldRenderer's material (which has the texture atlas loaded) - // The UVs in exported geometry reference positions in this atlas - material = this.worldRenderer.material - } - - // Create meshes from exported geometry - this.importedMeshes = createMeshesFromExport(this.loadedGeometry, material) - - // Add meshes to scene - const { scene } = this.worldRenderer - for (const mesh of this.importedMeshes) { - scene.add(mesh) - } - - console.log(`Loaded ${this.importedMeshes.length} sections from geometry file`) - this.requestRender() - - } catch (err) { - console.error('Failed to load geometry:', err) - } - } - - private exportGeometry (includeTexture = false) { - const { worldRenderer } = this - if (!worldRenderer) { - console.error('WorldRenderer not available') - return - } - - // Get camera position and rotation - const cameraPosition = { - x: this.camera.position.x, - y: this.camera.position.y, - z: this.camera.position.z - } - - // Extract yaw/pitch from camera quaternion - const forward = new THREE.Vector3(0, 0, -1) - forward.applyQuaternion(this.camera.quaternion) - const cameraRotation = { - yaw: Math.atan2(-forward.x, -forward.z), - pitch: Math.asin(forward.y) - } - - // Generate filename with timestamp - const timestamp = new Date().toISOString().replaceAll(/[:.]/g, '-') - const filename = `world-geometry-${timestamp}.json` - - downloadWorldGeometry(worldRenderer, cameraPosition, cameraRotation, filename, includeTexture) - console.log('Geometry exported to:', filename) - } - -} diff --git a/renderer/playground/scenes/index.ts b/renderer/playground/scenes/index.ts deleted file mode 100644 index 4b308fe82..000000000 --- a/renderer/playground/scenes/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -// export { default as rotation } from './rotation' -export { default as main } from './main' -export { default as railsCobweb } from './railsCobweb' -export { default as floorRandom } from './floorRandom' -export { default as lightingStarfield } from './lightingStarfield' -export { default as transparencyIssue } from './transparencyIssue' -export { default as rotationIssue } from './rotationIssue' -export { default as entities } from './entities' -export { default as frequentUpdates } from './frequentUpdates' -export { default as slabsOptimization } from './slabsOptimization' -export { default as allEntities } from './allEntities' -export { default as geometryExport } from './geometryExport' diff --git a/renderer/playground/scenes/lightingStarfield.ts b/renderer/playground/scenes/lightingStarfield.ts deleted file mode 100644 index eec0a7d35..000000000 --- a/renderer/playground/scenes/lightingStarfield.ts +++ /dev/null @@ -1,40 +0,0 @@ -//@ts-nocheck -import * as THREE from 'three' -import { Vec3 } from 'vec3' -import { BasePlaygroundScene } from '../baseScene' -import { WorldRendererThree } from '../../viewer/three/worldrendererThree' - -export default class extends BasePlaygroundScene { - continuousRender = true - - override setupWorld (): void { - viewer.world.mesherConfig.enableLighting = true - viewer.world.mesherConfig.skyLight = 0 - this.addWorldBlock(0, 0, 0, 'stone') - this.addWorldBlock(0, 0, 1, 'stone') - this.addWorldBlock(1, 0, 0, 'stone') - this.addWorldBlock(1, 0, 1, 'stone') - // chess like - worldView?.world.setBlockLight(this.targetPos.offset(0, 1, 0), 15) - worldView?.world.setBlockLight(this.targetPos.offset(0, 1, 1), 0) - worldView?.world.setBlockLight(this.targetPos.offset(1, 1, 0), 0) - worldView?.world.setBlockLight(this.targetPos.offset(1, 1, 1), 15) - } - - override renderFinish (): void { - viewer.scene.background = new THREE.Color(0x00_00_00) - // starfield and test entities - ;(viewer.world as WorldRendererThree).starField.enabled = true - ;(viewer.world as WorldRendererThree).starField.addToScene() - viewer.entities.update({ - id: 0, - name: 'player', - pos: this.targetPos.clone() - } as any, {}) - viewer.entities.update({ - id: 1, - name: 'creeper', - pos: this.targetPos.offset(1, 0, 0) - } as any, {}) - } -} diff --git a/renderer/playground/scenes/main.ts b/renderer/playground/scenes/main.ts deleted file mode 100644 index 980a37bca..000000000 --- a/renderer/playground/scenes/main.ts +++ /dev/null @@ -1,315 +0,0 @@ -// eslint-disable-next-line import/no-named-as-default -import GUI, { Controller } from 'lil-gui' -import * as THREE from 'three' -import JSZip from 'jszip' -import { BasePlaygroundScene } from '../baseScene' -import { TWEEN_DURATION } from '../../viewer/three/entities' -import { EntityMesh } from '../../viewer/three/entity/EntityMesh' -import supportedVersions from '../../../src/supportedVersions.mjs' - -const includedVersions = globalThis.includedVersions ?? supportedVersions - -class MainScene extends BasePlaygroundScene { - // eslint-disable-next-line @typescript-eslint/no-useless-constructor - constructor (...args) { - super(...args) - } - - override initGui (): void { - // initial values - this.params = { - version: includedVersions.at(-1), - skipQs: '', - block: '', - metadata: 0, - supportBlock: false, - entity: '', - removeEntity () { - this.entity = '' - }, - entityRotate: false, - camera: '', - playSound () { }, - blockIsomorphicRenderBundle () { }, - modelVariant: 0 - } - this.metadataGui = this.gui.add(this.params, 'metadata') - this.paramOptions = { - version: { - options: includedVersions, - hide: false - }, - block: { - options: mcData.blocksArray.map(b => b.name).sort((a, b) => a.localeCompare(b)) - }, - entity: { - options: mcData.entitiesArray.map(b => b.name).sort((a, b) => a.localeCompare(b)) - }, - camera: { - hide: true, - } - } - super.initGui() - } - - blockProps = {} - metadataFolder: GUI | undefined - metadataGui: Controller - - override onParamUpdate = { - version () { - // if (initialUpdate) return - // viewer.world.texturesVersion = params.version - // viewer.world.updateTexturesData() - // todo warning - }, - block: () => { - this.blockProps = {} - this.metadataFolder?.destroy() - const block = mcData.blocksByName[this.params.block] - if (!block) return - console.log('block', block.name) - const props = new this.Block(block.id, 0, 0).getProperties() - const { states } = mcData.blocksByStateId[this.getBlock()?.minStateId] ?? {} - this.metadataFolder = this.gui.addFolder('metadata') - if (states) { - for (const state of states) { - let defaultValue: string | number | boolean - if (state.values) { // int, enum - defaultValue = state.values[0] - } else { - switch (state.type) { - case 'bool': - defaultValue = false - break - case 'int': - defaultValue = 0 - break - case 'direction': - defaultValue = 'north' - break - - default: - continue - } - } - this.blockProps[state.name] = defaultValue - if (state.values) { - this.metadataFolder.add(this.blockProps, state.name, state.values) - } else { - this.metadataFolder.add(this.blockProps, state.name) - } - } - } else { - for (const [name, value] of Object.entries(props)) { - this.blockProps[name] = value - this.metadataFolder.add(this.blockProps, name) - } - } - console.log('props', this.blockProps) - this.metadataFolder.open() - }, - entity: () => { - this.continuousRender = this.params.entity === 'player' - this.entityUpdateShared() - if (!this.params.entity) return - if (this.params.entity === 'player') { - this.worldRenderer.entities.updatePlayerSkin('id', this.worldRenderer.entities.entities.id.username, undefined, true, true) - this.worldRenderer.entities.playAnimation('id', 'running') - } - // let prev = false - // setInterval(() => { - // viewer.entities.playAnimation('id', prev ? 'running' : 'idle') - // prev = !prev - // }, 1000) - - EntityMesh.getStaticData(this.params.entity) - // entityRotationFolder.destroy() - // entityRotationFolder = gui.addFolder('entity metadata') - // entityRotationFolder.add(params, 'entityRotate') - // entityRotationFolder.open() - }, - supportBlock: () => { - this.worldView!.setBlockStateId(this.targetPos.offset(0, -1, 0), this.params.supportBlock ? 1 : 0) - }, - modelVariant: () => { - this.worldRenderer.worldRendererConfig.debugModelVariant = this.params.modelVariant === 0 ? undefined : [this.params.modelVariant] - } - } - - entityUpdateShared () { - this.worldRenderer.entities.clear() - if (!this.params.entity) return - this.worldView!.emit('entity', { - id: 'id', name: this.params.entity, pos: this.targetPos.offset(0.5, 1, 0.5), width: 1, height: 1, username: localStorage.testUsername, yaw: Math.PI, pitch: 0 - }) - const enableSkeletonDebug = (obj) => { - const { children, isSkeletonHelper } = obj - if (!Array.isArray(children)) return - if (isSkeletonHelper) { - obj.visible = true - return - } - for (const child of children) { - if (typeof child === 'object') enableSkeletonDebug(child) - } - } - enableSkeletonDebug(this.worldRenderer.entities.entities['id']) - setTimeout(() => { - this.render() - }, TWEEN_DURATION) - } - - getBlock () { - return mcData.blocksByName[this.params.block || 'air'] - } - - // applyChanges (metadataUpdate = false, skipQs = false) { - override onParamsUpdate (paramName: string, object: any) { - const metadataUpdate = paramName === 'metadata' - - const blockId = this.getBlock()?.id - let block: import('prismarine-block').Block - if (metadataUpdate) { - block = new this.Block(blockId, 0, this.params.metadata) - Object.assign(this.blockProps, block.getProperties()) - for (const _child of this.metadataFolder!.children) { - const child = _child as import('lil-gui').Controller - child.updateDisplay() - } - } else { - try { - block = this.Block.fromProperties(blockId ?? -1, this.blockProps, 0) - } catch (err) { - console.error(err) - block = this.Block.fromStateId(0, 0) - } - } - - this.worldView!.setBlockStateId(this.targetPos, block.stateId ?? 0) - console.log('up stateId', block.stateId) - this.params.metadata = block.metadata - this.metadataGui.updateDisplay() - } - - override renderFinish () { - for (const update of Object.values(this.onParamUpdate)) { - // update(true) - update() - } - this.onParamsUpdate('', {}) - this.gui.openAnimated() - } - - blockIsomorphicRenderBundle () { - const { renderer } = this.worldRenderer - - const canvas = renderer.domElement - const onlyCurrent = !confirm('Ok - render all blocks, Cancel - render only current one') - const sizeRaw = prompt('Size', '512') - if (!sizeRaw) return - const size = parseInt(sizeRaw, 10) - // const size = 512 - - canvas.width = size - canvas.height = size - renderer.setSize(size, size) - - // Temporarily replace PerspectiveCamera with OrthographicCamera for block rendering - this.worldRenderer.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 10) as any - this.worldRenderer.scene.background = null - - const rad = THREE.MathUtils.degToRad(-120) - this.worldRenderer.directionalLight.position.set( - Math.cos(rad), - Math.sin(rad), - 0.2 - ).normalize() - this.worldRenderer.directionalLight.intensity = 1 - - const cameraPos = this.targetPos.offset(2, 2, 2) - const pitch = THREE.MathUtils.degToRad(-30) - const yaw = THREE.MathUtils.degToRad(45) - this.worldRenderer.camera.rotation.set(pitch, yaw, 0, 'ZYX') - // this.worldRenderer!.camera.lookAt(center.x + 0.5, center.y + 0.5, center.z + 0.5) - this.worldRenderer.camera.position.set(cameraPos.x + 1, cameraPos.y + 0.5, cameraPos.z + 1) - - const allBlocks = mcData.blocksArray.map(b => b.name) - // const allBlocks = ['stone', 'warped_slab'] - - let blockCount = 1 - let blockName = allBlocks[0] - - const updateBlock = () => { - // viewer.setBlockStateId(targetPos, mcData.blocksByName[blockName].minStateId) - this.params.block = blockName - // todo cleanup (introduce getDefaultState) - // TODO - // onUpdate.block() - // applyChanges(false, true) - } - void this.worldRenderer.waitForChunksToRender().then(async () => { - // wait for next macro task - await new Promise(resolve => { - setTimeout(resolve, 0) - }) - if (onlyCurrent) { - this.render() - onWorldUpdate() - } else { - // will be called on every render update - this.worldRenderer.renderUpdateEmitter.addListener('update', onWorldUpdate) - updateBlock() - } - }) - - const zip = new JSZip() - zip.file('description.txt', 'Generated with mcraft.fun/playground') - - const end = async () => { - // download zip file - - const a = document.createElement('a') - const blob = await zip.generateAsync({ type: 'blob' }) - const dataUrlZip = URL.createObjectURL(blob) - a.href = dataUrlZip - a.download = 'blocks_render.zip' - a.click() - URL.revokeObjectURL(dataUrlZip) - console.log('end') - - this.worldRenderer.renderUpdateEmitter.removeListener('update', onWorldUpdate) - } - - async function onWorldUpdate () { - // await new Promise(resolve => { - // setTimeout(resolve, 50) - // }) - const dataUrl = canvas.toDataURL('image/png') - - zip.file(`${blockName}.png`, dataUrl.split(',')[1], { base64: true }) - - if (onlyCurrent) { - end() - } else { - nextBlock() - } - } - const nextBlock = async () => { - blockName = allBlocks[blockCount++] - console.log(allBlocks.length, '/', blockCount, blockName) - if (blockCount % 5 === 0) { - await new Promise(resolve => { - setTimeout(resolve, 100) - }) - } - if (blockName) { - updateBlock() - } else { - end() - } - } - } -} - -export default MainScene diff --git a/renderer/playground/scenes/railsCobweb.ts b/renderer/playground/scenes/railsCobweb.ts deleted file mode 100644 index bc1c271a3..000000000 --- a/renderer/playground/scenes/railsCobweb.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { BasePlaygroundScene } from '../baseScene' - -export default class RailsCobwebScene extends BasePlaygroundScene { - setupWorld () { - this.addWorldBlock(0, 0, 0, 'cobweb') - this.addWorldBlock(0, -1, 0, 'cobweb') - this.addWorldBlock(1, -1, 0, 'cobweb') - this.addWorldBlock(1, 0, 0, 'cobweb') - - this.addWorldBlock(0, 0, 1, 'powered_rail', { shape: 'north_south', waterlogged: false }) - this.addWorldBlock(0, 0, 2, 'powered_rail', { shape: 'ascending_south', waterlogged: false }) - this.addWorldBlock(0, 1, 3, 'powered_rail', { shape: 'north_south', waterlogged: false }) - } -} diff --git a/renderer/playground/scenes/rotationIssue.ts b/renderer/playground/scenes/rotationIssue.ts deleted file mode 100644 index 2c56876a3..000000000 --- a/renderer/playground/scenes/rotationIssue.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { BasePlaygroundScene } from '../baseScene' - -export default class RotationIssueScene extends BasePlaygroundScene { - setupWorld () { - // todo - } -} diff --git a/renderer/playground/scenes/slabsOptimization.ts b/renderer/playground/scenes/slabsOptimization.ts deleted file mode 100644 index c26d6e2c2..000000000 --- a/renderer/playground/scenes/slabsOptimization.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { BasePlaygroundScene } from '../baseScene' - -export default class extends BasePlaygroundScene { - expectedNumberOfFaces = 30 - enableCameraOrbitControl = false - - setupWorld () { - this.addWorldBlock(0, 1, 0, 'stone_slab') - this.addWorldBlock(0, 0, 0, 'stone') - this.addWorldBlock(0, -1, 0, 'stone_slab', { type: 'top', waterlogged: false }) - this.addWorldBlock(0, -1, -1, 'stone_slab', { type: 'top', waterlogged: false }) - this.addWorldBlock(0, -1, 1, 'stone_slab', { type: 'top', waterlogged: false }) - this.addWorldBlock(-1, -1, 0, 'stone_slab', { type: 'top', waterlogged: false }) - this.addWorldBlock(1, -1, 0, 'stone_slab', { type: 'top', waterlogged: false }) - } -} diff --git a/renderer/playground/scenes/transparencyIssue.ts b/renderer/playground/scenes/transparencyIssue.ts deleted file mode 100644 index 9ce1b967a..000000000 --- a/renderer/playground/scenes/transparencyIssue.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { BasePlaygroundScene } from '../baseScene' - -export default class extends BasePlaygroundScene { - setupWorld () { - this.addWorldBlock(0, 0, 0, 'water') - this.addWorldBlock(0, 1, 0, 'lime_stained_glass') - this.addWorldBlock(0, 0, -1, 'lime_stained_glass') - this.addWorldBlock(0, -1, 0, 'lime_stained_glass') - this.addWorldBlock(0, -1, -1, 'stone') - } -} diff --git a/renderer/playground/shared.ts b/renderer/playground/shared.ts deleted file mode 100644 index 9d12fae9d..000000000 --- a/renderer/playground/shared.ts +++ /dev/null @@ -1,79 +0,0 @@ -import WorldLoader, { world } from 'prismarine-world' -import ChunkLoader from 'prismarine-chunk' - -export type BlockFaceType = { - side: number - textureIndex: number - tint?: [number, number, number] - isTransparent?: boolean - - // for testing - face?: string - neighbor?: string - light?: number -} - -export type BlockType = { - faces: BlockFaceType[] - - // for testing - block: string -} - -export const makeError = (str: string) => { - reportError?.(str) -} -export const makeErrorCritical = (str: string) => { - throw new Error(str) -} - -export const getSyncWorld = (version: string): world.WorldSync => { - const World = (WorldLoader as any)(version) - const Chunk = (ChunkLoader as any)(version) - - const world = new World(version).sync - - const methods = getAllMethods(world) - for (const method of methods) { - if (method.startsWith('set') && method !== 'setColumn') { - const oldMethod = world[method].bind(world) - world[method] = (...args) => { - const arg = args[0] - if (arg.x !== undefined && !world.getColumnAt(arg)) { - world.setColumn(Math.floor(arg.x / 16), Math.floor(arg.z / 16), new Chunk(undefined as any)) - } - oldMethod(...args) - } - } - } - - return world -} - -function getAllMethods (obj) { - const methods = new Set() - let currentObj = obj - - do { - for (const name of Object.getOwnPropertyNames(currentObj)) { - if (typeof obj[name] === 'function' && name !== 'constructor') { - methods.add(name) - } - } - } while ((currentObj = Object.getPrototypeOf(currentObj))) - - return [...methods] as string[] -} - -export const delayedIterator = async (arr: T[], delay: number, exec: (item: T, index: number) => Promise, chunkSize = 1) => { - // if delay is 0 then don't use setTimeout - for (let i = 0; i < arr.length; i += chunkSize) { - if (delay) { - // eslint-disable-next-line no-await-in-loop - await new Promise(resolve => { - setTimeout(resolve, delay) - }) - } - await exec(arr[i], i) - } -} diff --git a/renderer/rsbuild.config.ts b/renderer/rsbuild.config.ts deleted file mode 100644 index 2b40e79cd..000000000 --- a/renderer/rsbuild.config.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { defineConfig, mergeRsbuildConfig, RsbuildPluginAPI } from '@rsbuild/core'; -import supportedVersions from '../src/supportedVersions.mjs' -import childProcess from 'child_process' -import path, { dirname, join } from 'path' -import { pluginReact } from '@rsbuild/plugin-react'; -import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill'; -import fs from 'fs' -import fsExtra from 'fs-extra' -import { appAndRendererSharedConfig, rspackViewerConfig } from './rsbuildSharedConfig'; - -const mcDataPath = join(__dirname, '../generated/minecraft-data-optimized.json') - -// if (!fs.existsSync('./playground/textures')) { -// fsExtra.copySync('node_modules/mc-assets/dist/other-textures/latest/entity', './playground/textures/entity') -// } - -if (!fs.existsSync(mcDataPath)) { - childProcess.execSync('tsx ./scripts/makeOptimizedMcData.mjs', { stdio: 'inherit', cwd: path.join(__dirname, '..') }) -} - -export default mergeRsbuildConfig( - appAndRendererSharedConfig(), - defineConfig({ - html: { - template: join(__dirname, './playground.html'), - }, - output: { - cleanDistPath: false, - distPath: { - root: join(__dirname, './dist'), - }, - }, - server: { - port: 9090, - }, - source: { - entry: { - index: join(__dirname, './playground/playground.ts') - }, - define: { - 'globalThis.includedVersions': JSON.stringify(supportedVersions), - }, - }, - plugins: [ - { - name: 'test', - setup (build: RsbuildPluginAPI) { - const prep = async () => { - fsExtra.copySync(join(__dirname, '../node_modules/mc-assets/dist/other-textures/latest/entity'), join(__dirname, './dist/textures/entity')) - } - build.onBeforeBuild(async () => { - await prep() - }) - build.onBeforeStartDevServer(() => prep()) - }, - }, - ], - }) -) diff --git a/renderer/viewer/.gitignore b/renderer/viewer/.gitignore deleted file mode 100644 index 7ae1b2cd2..000000000 --- a/renderer/viewer/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -public/* -!public/.empty \ No newline at end of file diff --git a/renderer/viewer/baseGraphicsBackend.ts b/renderer/viewer/baseGraphicsBackend.ts deleted file mode 100644 index 486c930f6..000000000 --- a/renderer/viewer/baseGraphicsBackend.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { proxy } from 'valtio' -import { NonReactiveState, RendererReactiveState } from '../../src/appViewer' - -export const getDefaultRendererState = (): { - reactive: RendererReactiveState - nonReactive: NonReactiveState -} => { - return { - reactive: proxy({ - world: { - chunksLoaded: new Set(), - heightmaps: new Map(), - allChunksLoaded: true, - mesherWork: false, - intersectMedia: null - }, - renderer: '', - preventEscapeMenu: false - }), - nonReactive: { - world: { - chunksLoaded: new Set(), - chunksTotalNumber: 0, - } - } - } -} diff --git a/renderer/viewer/common/utils.ts b/renderer/viewer/common/utils.ts deleted file mode 100644 index 958273f3b..000000000 --- a/renderer/viewer/common/utils.ts +++ /dev/null @@ -1,18 +0,0 @@ -export const versionToNumber = (ver: string) => { - const [x, y = '0', z = '0'] = ver.split('.') - return +`${x.padStart(2, '0')}${y.padStart(2, '0')}${z.padStart(2, '0')}` -} - -export const versionToMajor = (version: string) => { - const [x, y = '0'] = version.split('.') - return `${x.padStart(2, '0')}.${y.padStart(2, '0')}` -} - -export const versionsMapToMajor = (versionsMap: Record) => { - const majorVersions = {} as Record - for (const [ver, data] of Object.entries(versionsMap)) { - const major = versionToMajor(ver) - majorVersions[major] = data - } - return majorVersions -} diff --git a/renderer/viewer/lib/DebugGui.ts b/renderer/viewer/lib/DebugGui.ts deleted file mode 100644 index f296c8731..000000000 --- a/renderer/viewer/lib/DebugGui.ts +++ /dev/null @@ -1,174 +0,0 @@ -// eslint-disable-next-line import/no-named-as-default -import GUI from 'lil-gui' - -export interface ParamMeta { - min?: number - max?: number - step?: number -} - -export class DebugGui { - private gui: GUI - private readonly storageKey: string - private target: any - private readonly params: string[] - private readonly paramsMeta: Record - private _visible = false // Default to not visible - private readonly initialValues: Record = {} // Store initial values - private initialized = false - - constructor (id: string, target: any, params?: string[], paramsMeta?: Record) { - this.gui = new GUI() - this.storageKey = `debug_params_${id}` - this.target = target - this.paramsMeta = paramsMeta ?? {} - this.params = params ?? Object.keys(target) - - // Store initial values - for (const param of this.params) { - this.initialValues[param] = target[param] - } - - // Hide by default - this.gui.domElement.style.display = 'none' - } - - // Initialize and show the GUI - activate () { - if (!this.initialized) { - this.loadSavedValues() - this.setupControls() - this.initialized = true - } - this.show() - return this - } - - // Getter for visibility - get visible (): boolean { - return this._visible - } - - // Setter for visibility - set visible (value: boolean) { - this._visible = value - this.gui.domElement.style.display = value ? 'block' : 'none' - this.saveVisibility() - } - - private loadSavedValues () { - try { - const saved = localStorage.getItem(this.storageKey) - if (saved) { - const values = JSON.parse(saved) - // Apply saved values to target - for (const param of this.params) { - if (param in values) { - const value = values[param] - if (value !== null) { - this.target[param] = value - } - } - } - } - } catch (e) { - console.warn('Failed to load debug values:', e) - } - } - - private saveValues (deleteKey = false) { - try { - const values = {} - for (const param of this.params) { - values[param] = this.target[param] - } - if (deleteKey) { - localStorage.removeItem(this.storageKey) - } else { - localStorage.setItem(this.storageKey, JSON.stringify(values)) - } - } catch (e) { - console.warn('Failed to save debug values:', e) - } - } - - private saveVisibility () { - try { - localStorage.setItem(`${this.storageKey}_visible`, this._visible.toString()) - } catch (e) { - console.warn('Failed to save debug visibility:', e) - } - } - - private setupControls () { - // Add visibility toggle at the top - this.gui.add(this, 'visible').name('Show Controls') - this.gui.add({ resetAll: () => { - for (const param of this.params) { - this.target[param] = this.initialValues[param] - } - this.saveValues(true) - this.gui.destroy() - this.gui = new GUI() - this.setupControls() - } }, 'resetAll').name('Reset All Parameters') - - for (const param of this.params) { - const value = this.target[param] - const meta = this.paramsMeta[param] ?? {} - - if (typeof value === 'number') { - // For numbers, use meta values or calculate reasonable defaults - const min = meta.min ?? value - Math.abs(value * 2) - const max = meta.max ?? value + Math.abs(value * 2) - const step = meta.step ?? Math.abs(value) / 100 - - this.gui.add(this.target, param, min, max, step) - .onChange(() => this.saveValues()) - } else if (typeof value === 'boolean') { - // For booleans, create a checkbox - this.gui.add(this.target, param) - .onChange(() => this.saveValues()) - } else if (typeof value === 'string' && ['x', 'y', 'z'].includes(param)) { - // Special case for xyz coordinates - const min = meta.min ?? -10 - const max = meta.max ?? 10 - const step = meta.step ?? 0.1 - - this.gui.add(this.target, param, min, max, step) - .onChange(() => this.saveValues()) - } else if (Array.isArray(value)) { - // For arrays, create a dropdown - this.gui.add(this.target, param, value) - .onChange(() => this.saveValues()) - } - } - } - - // Method to manually trigger save - save () { - this.saveValues() - this.saveVisibility() - } - - // Method to destroy the GUI and clean up - destroy () { - this.saveVisibility() - this.gui.destroy() - } - - // Toggle visibility - toggle () { - this.visible = !this.visible - } - - // Show the GUI - show () { - this.visible = true - } - - // Hide the GUI - hide () { - this.visible = false - } -} diff --git a/renderer/viewer/lib/animationController.ts b/renderer/viewer/lib/animationController.ts deleted file mode 100644 index 329d0e248..000000000 --- a/renderer/viewer/lib/animationController.ts +++ /dev/null @@ -1,85 +0,0 @@ -import * as tweenJs from '@tweenjs/tween.js' - -export class AnimationController { - private currentAnimation: tweenJs.Group | null = null - private isAnimating = false - private cancelRequested = false - private completionCallbacks: Array<() => void> = [] - private currentCancelCallback: (() => void) | null = null - - /** Main method */ - async startAnimation (createAnimation: () => tweenJs.Group, onCancelled?: () => void): Promise { - if (this.isAnimating) { - await this.cancelCurrentAnimation() - } - - return new Promise((resolve) => { - this.isAnimating = true - this.cancelRequested = false - this.currentCancelCallback = onCancelled ?? null - this.currentAnimation = createAnimation() - - this.completionCallbacks.push(() => { - this.isAnimating = false - this.currentAnimation = null - resolve() - }) - }) - } - - /** Main method */ - async cancelCurrentAnimation (): Promise { - if (!this.isAnimating) return - - if (this.currentCancelCallback) { - const callback = this.currentCancelCallback - this.currentCancelCallback = null - callback() - } - - return new Promise((resolve) => { - this.cancelRequested = true - this.completionCallbacks.push(() => { - resolve() - }) - }) - } - - animationCycleFinish () { - if (this.cancelRequested) this.forceFinish() - } - - forceFinish (callComplete = true) { - if (!this.isAnimating) return - - if (this.currentAnimation) { - for (const tween of this.currentAnimation.getAll()) tween.stop() - this.currentAnimation.removeAll() - this.currentAnimation = null - } - - this.isAnimating = false - this.cancelRequested = false - - const callbacks = [...this.completionCallbacks] - this.completionCallbacks = [] - if (callComplete) { - for (const cb of callbacks) cb() - } - } - - /** Required method */ - update () { - if (this.currentAnimation) { - this.currentAnimation.update() - } - } - - get isActive () { - return this.isAnimating - } - - get shouldCancel () { - return this.cancelRequested - } -} diff --git a/renderer/viewer/lib/basePlayerState.ts b/renderer/viewer/lib/basePlayerState.ts deleted file mode 100644 index a47121c7d..000000000 --- a/renderer/viewer/lib/basePlayerState.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { ItemSelector } from 'mc-assets/dist/itemDefinitions' -import { GameMode, Team } from 'mineflayer' -import { proxy } from 'valtio' -import type { HandItemBlock } from '../three/holdingBlock' - -export type MovementState = 'NOT_MOVING' | 'WALKING' | 'SPRINTING' | 'SNEAKING' -export type ItemSpecificContextProperties = Partial> -export type CameraPerspective = 'first_person' | 'third_person_back' | 'third_person_front' - -export type BlockShape = { position: any; width: any; height: any; depth: any; } -export type BlocksShapes = BlockShape[] - -// edit src/mineflayer/playerState.ts for implementation of player state from mineflayer -export const getInitialPlayerState = () => proxy({ - playerSkin: undefined as string | undefined, - inWater: false, - waterBreathing: false, - backgroundColor: [0, 0, 0] as [number, number, number], - ambientLight: 0, - directionalLight: 0, - cardinalLight: 'default', - eyeHeight: 0, - gameMode: undefined as GameMode | undefined, - lookingAtBlock: undefined as { - x: number - y: number - z: number - face?: number - shapes: BlocksShapes - } | undefined, - diggingBlock: undefined as { - x: number - y: number - z: number - stage: number - face?: number - mergedShape: BlockShape | undefined - } | undefined, - movementState: 'NOT_MOVING' as MovementState, - onGround: true, - sneaking: false, - flying: false, - sprinting: false, - itemUsageTicks: 0, - username: '', - onlineMode: false, - lightingDisabled: false, - shouldHideHand: false, - heldItemMain: undefined as HandItemBlock | undefined, - heldItemOff: undefined as HandItemBlock | undefined, - perspective: 'first_person' as CameraPerspective, - onFire: false, - - cameraSpectatingEntity: undefined as number | undefined, - - team: undefined as Team | undefined, -}) - -export const getPlayerStateUtils = (reactive: PlayerStateReactive) => ({ - isSpectator () { - return reactive.gameMode === 'spectator' - }, - isSpectatingEntity () { - return reactive.cameraSpectatingEntity !== undefined && reactive.gameMode === 'spectator' - }, - isThirdPerson () { - if ((this as PlayerStateUtils).isSpectatingEntity()) return false - return reactive.perspective === 'third_person_back' || reactive.perspective === 'third_person_front' - } -}) - -export const getInitialPlayerStateRenderer = () => ({ - reactive: getInitialPlayerState() -}) - -export type PlayerStateReactive = ReturnType -export type PlayerStateUtils = ReturnType - -export type PlayerStateRenderer = PlayerStateReactive - -export const getItemSelector = (playerState: PlayerStateRenderer, specificProperties: ItemSpecificContextProperties, item?: import('prismarine-item').Item) => { - return { - ...specificProperties, - 'minecraft:date': new Date(), - // "minecraft:context_dimension": bot.entityp, - // 'minecraft:time': bot.time.timeOfDay / 24_000, - } -} diff --git a/renderer/viewer/lib/cameraBobbing.ts b/renderer/viewer/lib/cameraBobbing.ts deleted file mode 100644 index 6bf32c76b..000000000 --- a/renderer/viewer/lib/cameraBobbing.ts +++ /dev/null @@ -1,94 +0,0 @@ -export class CameraBobbing { - private walkDistance = 0 - private prevWalkDistance = 0 - private bobAmount = 0 - private prevBobAmount = 0 - private readonly gameTimer = new GameTimer() - - // eslint-disable-next-line max-params - constructor ( - private readonly BOB_FREQUENCY: number = Math.PI, // How fast the bob cycles - private readonly BOB_BASE_AMPLITUDE: number = 0.5, // Base amplitude of the bob - private readonly VERTICAL_MULTIPLIER: number = 1, // Vertical movement multiplier - private readonly ROTATION_MULTIPLIER_Z: number = 3, // Roll rotation multiplier - private readonly ROTATION_MULTIPLIER_X: number = 5 // Pitch rotation multiplier - ) {} - - // Call this when player is moving - public updateWalkDistance (distance: number): void { - this.prevWalkDistance = this.walkDistance - this.walkDistance = distance - } - - // Call this when player is moving to update bob amount - public updateBobAmount (isMoving: boolean): void { - const targetBob = isMoving ? 1 : 0 - this.prevBobAmount = this.bobAmount - - // Update timing - const ticks = this.gameTimer.update() - const deltaTime = ticks / 20 // Convert ticks to seconds assuming 20 TPS - - // Smooth transition for bob amount - const bobDelta = (targetBob - this.bobAmount) * Math.min(1, deltaTime * 10) - this.bobAmount += bobDelta - } - - // Call this in your render/animation loop - public getBobbing (): { position: { x: number, y: number }, rotation: { x: number, z: number } } { - // Interpolate walk distance - const walkDist = this.prevWalkDistance + - (this.walkDistance - this.prevWalkDistance) * this.gameTimer.partialTick - - // Interpolate bob amount - const bob = this.prevBobAmount + - (this.bobAmount - this.prevBobAmount) * this.gameTimer.partialTick - - // Calculate total distance for bob cycle - const totalDist = -(walkDist * this.BOB_FREQUENCY) - - // Calculate offsets - const xOffset = Math.sin(totalDist) * bob * this.BOB_BASE_AMPLITUDE - const yOffset = -Math.abs(Math.cos(totalDist) * bob) * this.VERTICAL_MULTIPLIER - - // Calculate rotations (in radians) - const zRot = (Math.sin(totalDist) * bob * this.ROTATION_MULTIPLIER_Z) * (Math.PI / 180) - const xRot = (Math.abs(Math.cos(totalDist - 0.2) * bob) * this.ROTATION_MULTIPLIER_X) * (Math.PI / 180) - - return { - position: { x: xOffset, y: yOffset }, - rotation: { x: xRot, z: zRot } - } - } -} - -class GameTimer { - private readonly msPerTick: number - private lastMs: number - public partialTick = 0 - - constructor (tickRate = 20) { - this.msPerTick = 1000 / tickRate - this.lastMs = performance.now() - } - - update (): number { - const currentMs = performance.now() - const deltaSinceLastTick = currentMs - this.lastMs - - // Calculate how much of a tick has passed - const tickDelta = deltaSinceLastTick / this.msPerTick - this.lastMs = currentMs - - // Add to accumulated partial ticks - this.partialTick += tickDelta - - // Get whole number of ticks that should occur - const wholeTicks = Math.floor(this.partialTick) - - // Keep the remainder as the new partial tick - this.partialTick -= wholeTicks - - return wholeTicks - } -} diff --git a/renderer/viewer/lib/cleanupDecorator.ts b/renderer/viewer/lib/cleanupDecorator.ts deleted file mode 100644 index 79b358280..000000000 --- a/renderer/viewer/lib/cleanupDecorator.ts +++ /dev/null @@ -1,29 +0,0 @@ -export function buildCleanupDecorator (cleanupMethod: string) { - return function () { - return function (_target: { snapshotInitialValues }, propertyKey: string) { - const target = _target as any - // Store the initial value of the property - if (!target._snapshotMethodPatched) { - target.snapshotInitialValues = function () { - this._initialValues = {} - for (const key of target._toCleanup) { - this._initialValues[key] = this[key] - } - } - target._snapshotMethodPatched = true - } - (target._toCleanup ??= []).push(propertyKey) - if (!target._cleanupPatched) { - const originalMethod = target[cleanupMethod] - target[cleanupMethod] = function () { - for (const key of target._toCleanup) { - this[key] = this._initialValues[key] - } - // eslint-disable-next-line prefer-rest-params - Reflect.apply(originalMethod, this, arguments) - } - } - target._cleanupPatched = true - } - } -} diff --git a/renderer/viewer/lib/createPlayerObject.ts b/renderer/viewer/lib/createPlayerObject.ts deleted file mode 100644 index 836c80626..000000000 --- a/renderer/viewer/lib/createPlayerObject.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { PlayerObject, PlayerAnimation } from 'skinview3d' -import * as THREE from 'three' -import { WalkingGeneralSwing } from '../three/entity/animations' -import { loadSkinImage, stevePngUrl } from './utils/skins' - -export type PlayerObjectType = PlayerObject & { - animation?: PlayerAnimation - realPlayerUuid: string - realUsername: string -} - -export function createPlayerObject (options: { - username?: string - uuid?: string - scale?: number -}): { - playerObject: PlayerObjectType - wrapper: THREE.Group - } { - const wrapper = new THREE.Group() - const playerObject = new PlayerObject() as PlayerObjectType - - playerObject.realPlayerUuid = options.uuid ?? '' - playerObject.realUsername = options.username ?? '' - playerObject.position.set(0, 16, 0) - - // fix issues with starfield - playerObject.traverse((obj) => { - if (obj instanceof THREE.Mesh && obj.material instanceof THREE.MeshStandardMaterial) { - obj.material.transparent = true - } - }) - - wrapper.add(playerObject as any) - const scale = options.scale ?? (1 / 16) - wrapper.scale.set(scale, scale, scale) - wrapper.rotation.set(0, Math.PI, 0) - - // Set up animation - playerObject.animation = new WalkingGeneralSwing() - ;(playerObject.animation as WalkingGeneralSwing).isMoving = false - playerObject.animation.update(playerObject, 0) - - return { playerObject, wrapper } -} - -export const applySkinToPlayerObject = async (playerObject: PlayerObjectType, skinUrl: string) => { - return loadSkinImage(skinUrl || stevePngUrl).then(({ canvas }) => { - const skinTexture = new THREE.CanvasTexture(canvas) - skinTexture.magFilter = THREE.NearestFilter - skinTexture.minFilter = THREE.NearestFilter - skinTexture.needsUpdate = true - playerObject.skin.map = skinTexture as any - }).catch(console.error) -} diff --git a/renderer/viewer/lib/guiRenderer.ts b/renderer/viewer/lib/guiRenderer.ts deleted file mode 100644 index 709941dcc..000000000 --- a/renderer/viewer/lib/guiRenderer.ts +++ /dev/null @@ -1,282 +0,0 @@ -// Import placeholders - replace with actual imports for your environment -import { ItemRenderer, Identifier, ItemStack, NbtString, Structure, StructureRenderer, ItemRendererResources, BlockDefinition, BlockModel, TextureAtlas, Resources, ItemModel } from 'deepslate' -import { mat4, vec3 } from 'gl-matrix' -import { AssetsParser } from 'mc-assets/dist/assetsParser' -import { getLoadedImage, versionToNumber } from 'mc-assets/dist/utils' -import { BlockModel as BlockModelMcAssets, AtlasParser } from 'mc-assets' -import { getLoadedBlockstatesStore, getLoadedModelsStore } from 'mc-assets/dist/stores' -import { makeTextureAtlas } from 'mc-assets/dist/atlasCreator' -import { proxy, ref } from 'valtio' -import { getItemDefinition } from 'mc-assets/dist/itemDefinitions' - -export const getNonFullBlocksModels = () => { - let version = appViewer.resourcesManager.currentResources!.version ?? 'latest' - if (versionToNumber(version) < versionToNumber('1.13')) version = '1.13' - const itemsDefinitions = appViewer.resourcesManager.itemsDefinitionsStore.data.latest - const blockModelsResolved = {} as Record - const itemsModelsResolved = {} as Record - const fullBlocksWithNonStandardDisplay = [] as string[] - const handledItemsWithDefinitions = new Set() - const assetsParser = new AssetsParser(version, getLoadedBlockstatesStore(appViewer.resourcesManager.currentResources!.blockstatesModels), getLoadedModelsStore(appViewer.resourcesManager.currentResources!.blockstatesModels)) - - const standardGuiDisplay = { - 'rotation': [ - 30, - 225, - 0 - ], - 'translation': [ - 0, - 0, - 0 - ], - 'scale': [ - 0.625, - 0.625, - 0.625 - ] - } - - const arrEqual = (a: number[], b: number[]) => a.length === b.length && a.every((x, i) => x === b[i]) - const addModelIfNotFullblock = (name: string, model: BlockModelMcAssets) => { - if (blockModelsResolved[name]) return - if (!model?.elements?.length) return - const isFullBlock = model.elements.length === 1 && arrEqual(model.elements[0].from, [0, 0, 0]) && arrEqual(model.elements[0].to, [16, 16, 16]) - if (isFullBlock) return - const hasBetterPrerender = assetsParser.blockModelsStore.data.latest[`item/${name}`]?.textures?.['layer0']?.startsWith('invsprite_') - if (hasBetterPrerender) return - model['display'] ??= {} - model['display']['gui'] ??= standardGuiDisplay - blockModelsResolved[name] = model - } - - for (const [name, definition] of Object.entries(itemsDefinitions)) { - const item = getItemDefinition(appViewer.resourcesManager.itemsDefinitionsStore, { - version, - name, - properties: { - 'minecraft:display_context': 'gui', - }, - }) - if (item) { - const { resolvedModel } = assetsParser.getResolvedModelsByModel((item.special ? name : item.model).replace('minecraft:', '')) ?? {} - if (resolvedModel) { - handledItemsWithDefinitions.add(name) - } - if (resolvedModel?.elements) { - let hasStandardDisplay = true - if (resolvedModel['display']?.gui) { - hasStandardDisplay = - arrEqual(resolvedModel['display'].gui.rotation, standardGuiDisplay.rotation) - && arrEqual(resolvedModel['display'].gui.translation, standardGuiDisplay.translation) - && arrEqual(resolvedModel['display'].gui.scale, standardGuiDisplay.scale) - } - - addModelIfNotFullblock(name, resolvedModel) - - if (!blockModelsResolved[name] && !hasStandardDisplay) { - fullBlocksWithNonStandardDisplay.push(name) - } - const notSideLight = resolvedModel['gui_light'] && resolvedModel['gui_light'] !== 'side' - if (!hasStandardDisplay || notSideLight) { - blockModelsResolved[name] = resolvedModel - } - } - if (!blockModelsResolved[name] && item.tints && resolvedModel) { - resolvedModel['tints'] = item.tints - if (resolvedModel.elements) { - blockModelsResolved[name] = resolvedModel - } else { - itemsModelsResolved[name] = resolvedModel - } - } - } - } - - for (const [name, blockstate] of Object.entries(appViewer.resourcesManager.currentResources!.blockstatesModels.blockstates.latest)) { - if (handledItemsWithDefinitions.has(name)) { - continue - } - const resolvedModel = assetsParser.getResolvedModelFirst({ name: name.replace('minecraft:', ''), properties: {} }, true) - if (resolvedModel) { - addModelIfNotFullblock(name, resolvedModel[0]) - } - } - - return { - blockModelsResolved, - itemsModelsResolved - } -} - -// customEvents.on('gameLoaded', () => { -// const res = getNonFullBlocksModels() -// }) - -const RENDER_SIZE = 64 - -const generateItemsGui = async (models: Record, isItems = false) => { - const { currentResources } = appViewer.resourcesManager - const imgBitmap = isItems ? currentResources!.itemsAtlasImage : currentResources!.blocksAtlasImage - const canvasTemp = document.createElement('canvas') - canvasTemp.width = imgBitmap.width - canvasTemp.height = imgBitmap.height - canvasTemp.style.imageRendering = 'pixelated' - const ctx = canvasTemp.getContext('2d')! - ctx.imageSmoothingEnabled = false - ctx.drawImage(imgBitmap, 0, 0) - - const atlasParser = isItems ? appViewer.resourcesManager.itemsAtlasParser : appViewer.resourcesManager.blocksAtlasParser - const textureAtlas = new TextureAtlas( - ctx.getImageData(0, 0, imgBitmap.width, imgBitmap.height), - Object.fromEntries(Object.entries(atlasParser.atlas.latest.textures).map(([key, value]) => { - return [key, [ - value.u, - value.v, - (value.u + (value.su ?? atlasParser.atlas.latest.suSv)), - (value.v + (value.sv ?? atlasParser.atlas.latest.suSv)), - ]] as [string, [number, number, number, number]] - })) - ) - - const PREVIEW_ID = Identifier.parse('preview:preview') - const PREVIEW_DEFINITION = new BlockDefinition({ '': { model: PREVIEW_ID.toString() } }, undefined) - - let textureWasRequested = false - let modelData: any - let currentModelName: string | undefined - const resources: ItemRendererResources = { - getBlockModel (id) { - if (id.equals(PREVIEW_ID)) { - return BlockModel.fromJson(modelData ?? {}) - } - return null - }, - getTextureUV (texture) { - textureWasRequested = true - return textureAtlas.getTextureUV(texture.toString().replace('minecraft:', '').replace('block/', '').replace('item/', '').replace('blocks/', '').replace('items/', '') as any) - }, - getTextureAtlas () { - return textureAtlas.getTextureAtlas() - }, - getItemComponents (id) { - return new Map() - }, - getItemModel (id) { - // const isSpecial = currentModelName === 'shield' || currentModelName === 'conduit' || currentModelName === 'trident' - const isSpecial = false - if (id.equals(PREVIEW_ID)) { - return ItemModel.fromJson({ - type: isSpecial ? 'minecraft:special' : 'minecraft:model', - model: isSpecial ? { - type: currentModelName, - } : PREVIEW_ID.toString(), - base: PREVIEW_ID.toString(), - tints: modelData?.tints, - }) - } - return null - }, - } - - const canvas = document.createElement('canvas') - canvas.width = RENDER_SIZE - canvas.height = RENDER_SIZE - const gl = canvas.getContext('webgl2', { preserveDrawingBuffer: true }) - if (!gl) { - throw new Error('Cannot get WebGL2 context') - } - - function resetGLContext (gl) { - gl.clearColor(0, 0, 0, 0) - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT) - } - - // const includeOnly = ['powered_repeater', 'wooden_door'] - const includeOnly = [] as string[] - - const images: Record = {} - const item = new ItemStack(PREVIEW_ID, 1, new Map(Object.entries({ - 'minecraft:item_model': new NbtString(PREVIEW_ID.toString()), - }))) - const renderer = new ItemRenderer(gl, item, resources, { display_context: 'gui' }) - const missingTextures = new Set() - for (const [modelName, model] of Object.entries(models)) { - textureWasRequested = false - if (includeOnly.length && !includeOnly.includes(modelName)) continue - - const patchMissingTextures = () => { - for (const element of model.elements ?? []) { - for (const [faceName, face] of Object.entries(element.faces)) { - if (face.texture.startsWith('#')) { - missingTextures.add(`${modelName} ${faceName}: ${face.texture}`) - face.texture = 'block/unknown' - } - } - } - } - patchMissingTextures() - // TODO eggs - - modelData = model - currentModelName = modelName - resetGLContext(gl) - if (!modelData) continue - renderer.setItem(item, { display_context: 'gui' }) - renderer.drawItem() - if (!textureWasRequested) continue - const url = canvas.toDataURL() - // eslint-disable-next-line no-await-in-loop - const img = await getLoadedImage(url) - images[modelName] = img - } - - if (missingTextures.size) { - console.warn(`[guiRenderer] Missing textures in ${[...missingTextures].join(', ')}`) - } - - return images -} - -/** - * @mainThread - */ -const generateAtlas = async (images: Record) => { - const atlas = makeTextureAtlas({ - input: Object.keys(images), - tileSize: RENDER_SIZE, - getLoadedImage (name) { - return { - image: images[name], - } - }, - }) - - // const atlasParser = new AtlasParser({ latest: atlas.json }, atlas.canvas.toDataURL()) - // const a = document.createElement('a') - // a.href = await atlasParser.createDebugImage(true) - // a.download = 'blocks_atlas.png' - // a.click() - - appViewer.resourcesManager.currentResources!.guiAtlas = { - json: atlas.json, - image: await createImageBitmap(atlas.canvas), - } - - return atlas -} - -export const generateGuiAtlas = async () => { - const { blockModelsResolved, itemsModelsResolved } = getNonFullBlocksModels() - - // Generate blocks atlas - console.time('generate blocks gui atlas') - const blockImages = await generateItemsGui(blockModelsResolved, false) - console.timeEnd('generate blocks gui atlas') - console.time('generate items gui atlas') - const itemImages = await generateItemsGui(itemsModelsResolved, true) - console.timeEnd('generate items gui atlas') - await generateAtlas({ ...blockImages, ...itemImages }) - appViewer.resourcesManager.currentResources!.guiAtlasVersion++ - // await generateAtlas(blockImages) -} diff --git a/renderer/viewer/lib/mesher/mesher.ts b/renderer/viewer/lib/mesher/mesher.ts deleted file mode 100644 index eb4d78d65..000000000 --- a/renderer/viewer/lib/mesher/mesher.ts +++ /dev/null @@ -1,249 +0,0 @@ -import { Vec3 } from 'vec3' -import { World } from './world' -import { getSectionGeometry, setBlockStatesData as setMesherData } from './models' -import { BlockStateModelInfo } from './shared' -import { INVISIBLE_BLOCKS } from './worldConstants' - -globalThis.structuredClone ??= (value) => JSON.parse(JSON.stringify(value)) - -if (module.require) { - // If we are in a node environement, we need to fake some env variables - const r = module.require - const { parentPort } = r('worker_threads') - global.self = parentPort - global.postMessage = (value, transferList) => { parentPort.postMessage(value, transferList) } - global.performance = r('perf_hooks').performance -} - -let workerIndex = 0 -let world: World -let dirtySections = new Map() -let allDataReady = false - -function sectionKey (x, y, z) { - return `${x},${y},${z}` -} - -const batchMessagesLimit = 100 - -let queuedMessages = [] as any[] -let queueWaiting = false -const postMessage = (data, transferList = []) => { - queuedMessages.push({ data, transferList }) - if (queuedMessages.length > batchMessagesLimit) { - drainQueue(0, batchMessagesLimit) - } - if (queueWaiting) return - queueWaiting = true - setTimeout(() => { - queueWaiting = false - drainQueue(0, queuedMessages.length) - }) -} - -function drainQueue (from, to) { - const messages = queuedMessages.slice(from, to) - global.postMessage(messages.map(m => m.data), messages.flatMap(m => m.transferList) as unknown as string) - queuedMessages = queuedMessages.slice(to) -} - -function setSectionDirty (pos, value = true) { - const x = Math.floor(pos.x / 16) * 16 - const y = Math.floor(pos.y / 16) * 16 - const z = Math.floor(pos.z / 16) * 16 - const key = sectionKey(x, y, z) - if (!value) { - dirtySections.delete(key) - postMessage({ type: 'sectionFinished', key, workerIndex }) - return - } - - const chunk = world.getColumn(x, z) - if (chunk?.getSection(pos)) { - dirtySections.set(key, (dirtySections.get(key) || 0) + 1) - } else { - postMessage({ type: 'sectionFinished', key, workerIndex }) - } -} - -const softCleanup = () => { - // clean block cache and loaded chunks - world = new World(world.config.version) - globalThis.world = world -} - -const handleMessage = data => { - const globalVar: any = globalThis - - if (data.type === 'mcData') { - globalVar.mcData = data.mcData - globalVar.loadedData = data.mcData - } - - if (data.config) { - if (data.type === 'mesherData' && world) { - // reset models - world.blockCache = {} - world.erroredBlockModel = undefined - } - - world ??= new World(data.config.version) - world.config = { ...world.config, ...data.config } - globalThis.world = world - globalThis.Vec3 = Vec3 - } - - switch (data.type) { - case 'mesherData': { - setMesherData(data.blockstatesModels, data.blocksAtlas, data.config.outputFormat === 'webgpu') - allDataReady = true - workerIndex = data.workerIndex - - break - } - case 'dirty': { - const loc = new Vec3(data.x, data.y, data.z) - setSectionDirty(loc, data.value) - - break - } - case 'chunk': { - world.addColumn(data.x, data.z, data.chunk) - if (data.customBlockModels) { - const chunkKey = `${data.x},${data.z}` - world.customBlockModels.set(chunkKey, data.customBlockModels) - } - break - } - case 'unloadChunk': { - world.removeColumn(data.x, data.z) - world.customBlockModels.delete(`${data.x},${data.z}`) - if (Object.keys(world.columns).length === 0) softCleanup() - break - } - case 'blockUpdate': { - const loc = new Vec3(data.pos.x, data.pos.y, data.pos.z).floored() - if (data.stateId !== undefined && data.stateId !== null) { - world?.setBlockStateId(loc, data.stateId) - } - - const chunkKey = `${Math.floor(loc.x / 16) * 16},${Math.floor(loc.z / 16) * 16}` - if (data.customBlockModels) { - world?.customBlockModels.set(chunkKey, data.customBlockModels) - } - break - } - case 'reset': { - world = undefined as any - // blocksStates = null - dirtySections = new Map() - // todo also remove cached - globalVar.mcData = null - globalVar.loadedData = null - allDataReady = false - - break - } - case 'getCustomBlockModel': { - const pos = new Vec3(data.pos.x, data.pos.y, data.pos.z) - const chunkKey = `${Math.floor(pos.x / 16) * 16},${Math.floor(pos.z / 16) * 16}` - const customBlockModel = world.customBlockModels.get(chunkKey)?.[`${pos.x},${pos.y},${pos.z}`] - global.postMessage({ type: 'customBlockModel', chunkKey, customBlockModel }) - break - } - case 'getHeightmap': { - const heightmap = new Uint8Array(256) - - const blockPos = new Vec3(0, 0, 0) - for (let z = 0; z < 16; z++) { - for (let x = 0; x < 16; x++) { - const blockX = x + data.x - const blockZ = z + data.z - blockPos.x = blockX - blockPos.z = blockZ - blockPos.y = world.config.worldMaxY - let block = world.getBlock(blockPos) - while (block && INVISIBLE_BLOCKS.has(block.name) && blockPos.y > world.config.worldMinY) { - blockPos.y -= 1 - block = world.getBlock(blockPos) - } - const index = z * 16 + x - heightmap[index] = block ? blockPos.y : 0 - } - } - postMessage({ type: 'heightmap', key: `${Math.floor(data.x / 16)},${Math.floor(data.z / 16)}`, heightmap }) - - break - } - case 'mc-web-ping': { - const replyWorkerIndex = typeof data.workerIndex === 'number' ? data.workerIndex : workerIndex - global.postMessage({ - type: 'mc-web-pong', - workerIndex: replyWorkerIndex, - t: data.t, - recvAt: typeof performance === 'undefined' ? undefined : performance.now(), - }) - break - } - // No default - } -} - -// eslint-disable-next-line no-restricted-globals -- TODO -self.onmessage = ({ data }) => { - if (Array.isArray(data)) { - // eslint-disable-next-line unicorn/no-array-for-each - data.forEach(handleMessage) - return - } - - handleMessage(data) -} - -setInterval(() => { - if (world === null || !allDataReady) return - - if (dirtySections.size === 0) return - // console.log(sections.length + ' dirty sections') - - // const start = performance.now() - for (const key of dirtySections.keys()) { - const [x, y, z] = key.split(',').map(v => parseInt(v, 10)) - const chunk = world.getColumn(x, z) - let processTime = 0 - if (chunk?.getSection(new Vec3(x, y, z))) { - const start = performance.now() - const geometry = getSectionGeometry(x, y, z, world) - const transferable = [geometry.positions?.buffer, geometry.normals?.buffer, geometry.colors?.buffer, geometry.uvs?.buffer].filter(Boolean) - //@ts-expect-error - postMessage({ type: 'geometry', key, geometry, workerIndex }, transferable) - processTime = performance.now() - start - } else { - // console.info('[mesher] Missing section', x, y, z) - } - const dirtyTimes = dirtySections.get(key) - if (!dirtyTimes) throw new Error('dirtySections.get(key) is falsy') - for (let i = 0; i < dirtyTimes; i++) { - postMessage({ type: 'sectionFinished', key, workerIndex, processTime }) - processTime = 0 - } - dirtySections.delete(key) - } - - // Send new block state model info if any - if (world.blockStateModelInfo.size > 0) { - const newBlockStateInfo: Record = {} - for (const [cacheKey, info] of world.blockStateModelInfo) { - if (!world.sentBlockStateModels.has(cacheKey)) { - newBlockStateInfo[cacheKey] = info - world.sentBlockStateModels.add(cacheKey) - } - } - if (Object.keys(newBlockStateInfo).length > 0) { - postMessage({ type: 'blockStateModelInfo', info: newBlockStateInfo }) - } - } - - // const time = performance.now() - start - // console.log(`Processed ${sections.length} sections in ${time} ms (${time / sections.length} ms/section)`) -}, 50) diff --git a/renderer/viewer/lib/mesher/models.ts b/renderer/viewer/lib/mesher/models.ts deleted file mode 100644 index b7fc4f069..000000000 --- a/renderer/viewer/lib/mesher/models.ts +++ /dev/null @@ -1,799 +0,0 @@ -import { Vec3 } from 'vec3' -import worldBlockProvider, { WorldBlockProvider } from 'mc-assets/dist/worldBlockProvider' -import legacyJson from '../../../../src/preflatMap.json' -import { BlockType } from '../../../playground/shared' -import moreBlockData from '../moreBlockDataGenerated.json' -import { INVISIBLE_BLOCKS } from './worldConstants' -import { MesherGeometryOutput, HighestBlockInfo } from './shared' -import { BlockElement, buildRotationMatrix, elemFaces, matmul3, matmulmat3, vecadd3, vecsub3 } from './modelsGeometryCommon' -import { World, BlockModelPartsResolved, WorldBlock as Block, WorldBlock } from './world' - - -let blockProvider: WorldBlockProvider - -const tints: any = {} -let needTiles = false -let semiTransparentBlocks: string[] = [] - -let tintsData -try { - tintsData = require('esbuild-data').tints -} catch (err) { - tintsData = require('minecraft-data/minecraft-data/data/pc/1.16.2/tints.json') -} -for (const key of Object.keys(tintsData)) { - tints[key] = prepareTints(tintsData[key]) -} - -type Tiles = { - [blockPos: string]: BlockType -} - -function prepareTints (tints) { - const map = new Map() - const defaultValue = tintToGl(tints.default) - for (let { keys, color } of tints.data) { - color = tintToGl(color) - for (const key of keys) { - map.set(`${key}`, color) - } - } - return new Proxy(map, { - get (target, key) { - return target.has(key) ? target.get(key) : defaultValue - } - }) -} - -const calculatedBlocksEntries = Object.entries(legacyJson.clientCalculatedBlocks) -export function preflatBlockCalculation (block: Block, world: World, position: Vec3) { - const type = calculatedBlocksEntries.find(([name, blocks]) => blocks.includes(block.name))?.[0] - if (!type) return - switch (type) { - case 'directional': { - const isSolidConnection = !block.name.includes('redstone') && !block.name.includes('tripwire') - const neighbors = [ - world.getBlock(position.offset(0, 0, 1)), - world.getBlock(position.offset(0, 0, -1)), - world.getBlock(position.offset(1, 0, 0)), - world.getBlock(position.offset(-1, 0, 0)) - ] - // set needed props to true: east:'false',north:'false',south:'false',west:'false' - const props = {} - let changed = false - for (const [i, neighbor] of neighbors.entries()) { - const isConnectedToSolid = isSolidConnection ? (neighbor && !neighbor.transparent) : false - if (isConnectedToSolid || neighbor?.name === block.name) { - props[['south', 'north', 'east', 'west'][i]] = 'true' - changed = true - } - } - return changed ? props : undefined - } - // case 'gate_in_wall': {} - case 'block_snowy': { - const aboveIsSnow = world.getBlock(position.offset(0, 1, 0))?.name === 'snow' - if (aboveIsSnow) { - return { - snowy: `${aboveIsSnow}` - } - } else { - return - } - } - case 'door': { - // upper half matches lower in - const { half } = block.getProperties() - if (half === 'upper') { - // copy other properties - const lower = world.getBlock(position.offset(0, -1, 0)) - if (lower?.name === block.name) { - return { - ...lower.getProperties(), - half: 'upper' - } - } - } - } - } -} - -function tintToGl (tint) { - const r = (tint >> 16) & 0xff - const g = (tint >> 8) & 0xff - const b = tint & 0xff - return [r / 255, g / 255, b / 255] -} - -function getLiquidRenderHeight (world: World, block: WorldBlock | null, type: number, pos: Vec3, isWater: boolean, isRealWater: boolean) { - if ((isWater && !isRealWater) || (block && isBlockWaterlogged(block))) return 8 / 9 - if (!block || block.type !== type) return 1 / 9 - if (block.metadata === 0) { // source block - const blockAbove = world.getBlock(pos.offset(0, 1, 0)) - if (blockAbove && blockAbove.type === type) return 1 - return 8 / 9 - } - return ((block.metadata >= 8 ? 8 : 7 - block.metadata) + 1) / 9 -} - - -const isCube = (block: Block) => { - if (!block || block.transparent) return false - if (block.isCube) return true - if (!block.models?.length || block.models.length !== 1) return false - // all variants - return block.models[0].every(v => v.elements.every(e => { - return e.from[0] === 0 && e.from[1] === 0 && e.from[2] === 0 && e.to[0] === 16 && e.to[1] === 16 && e.to[2] === 16 - })) -} - -const getVec = (v: Vec3, dir: Vec3) => { - for (const coord of ['x', 'y', 'z']) { - if (Math.abs(dir[coord]) > 0) v[coord] = 0 - } - return v.plus(dir) -} - -function renderLiquid (world: World, cursor: Vec3, texture: any | undefined, type: number, biome: string, water: boolean, attr: MesherGeometryOutput, isRealWater: boolean) { - const heights: number[] = [] - for (let z = -1; z <= 1; z++) { - for (let x = -1; x <= 1; x++) { - const pos = cursor.offset(x, 0, z) - heights.push(getLiquidRenderHeight(world, world.getBlock(pos), type, pos, water, isRealWater)) - } - } - const cornerHeights = [ - Math.max(Math.max(heights[0], heights[1]), Math.max(heights[3], heights[4])), - Math.max(Math.max(heights[1], heights[2]), Math.max(heights[4], heights[5])), - Math.max(Math.max(heights[3], heights[4]), Math.max(heights[6], heights[7])), - Math.max(Math.max(heights[4], heights[5]), Math.max(heights[7], heights[8])) - ] - - // eslint-disable-next-line guard-for-in - for (const face in elemFaces) { - const { dir, corners, mask1, mask2 } = elemFaces[face] - const isUp = dir[1] === 1 - - const neighborPos = cursor.offset(...dir as [number, number, number]) - const neighbor = world.getBlock(neighborPos) - if (!neighbor) continue - if (neighbor.type === type || (water && (neighbor.name === 'water' || isBlockWaterlogged(neighbor)))) continue - if (isCube(neighbor) && !isUp) continue - - let tint = [1, 1, 1] - if (water) { - let m = 1 // Fake lighting to improve lisibility - if (Math.abs(dir[0]) > 0) m = 0.6 - else if (Math.abs(dir[2]) > 0) m = 0.8 - tint = tints.water[biome] - tint = [tint[0] * m, tint[1] * m, tint[2] * m] - } - - if (needTiles) { - const tiles = attr.tiles as Tiles - tiles[`${cursor.x},${cursor.y},${cursor.z}`] ??= { - block: 'water', - faces: [], - } - tiles[`${cursor.x},${cursor.y},${cursor.z}`].faces.push({ - face, - neighbor: `${neighborPos.x},${neighborPos.y},${neighborPos.z}`, - side: 0, // todo - textureIndex: 0, - // texture: eFace.texture.name, - }) - } - - const { u } = texture - const { v } = texture - const { su } = texture - const { sv } = texture - - // Get base light value for the face - const baseLight = world.getLight(neighborPos, undefined, undefined, water ? 'water' : 'lava') / 15 - - for (const pos of corners) { - const height = cornerHeights[pos[2] * 2 + pos[0]] - const OFFSET = 0.0001 - attr.t_positions!.push( - (pos[0] ? 1 - OFFSET : OFFSET) + (cursor.x & 15) - 8, - (pos[1] ? height - OFFSET : OFFSET) + (cursor.y & 15) - 8, - (pos[2] ? 1 - OFFSET : OFFSET) + (cursor.z & 15) - 8 - ) - attr.t_normals!.push(...dir) - attr.t_uvs!.push(pos[3] * su + u, pos[4] * sv * (pos[1] ? 1 : height) + v) - - let cornerLightResult = baseLight - if (world.config.smoothLighting) { - const dx = pos[0] * 2 - 1 - const dy = pos[1] * 2 - 1 - const dz = pos[2] * 2 - 1 - const cornerDir: [number, number, number] = [dx, dy, dz] - const side1Dir: [number, number, number] = [dx * mask1[0], dy * mask1[1], dz * mask1[2]] - const side2Dir: [number, number, number] = [dx * mask2[0], dy * mask2[1], dz * mask2[2]] - - const dirVec = new Vec3(...dir as [number, number, number]) - - const side1LightDir = getVec(new Vec3(...side1Dir), dirVec) - const side1Light = world.getLight(cursor.plus(side1LightDir)) / 15 - const side2DirLight = getVec(new Vec3(...side2Dir), dirVec) - const side2Light = world.getLight(cursor.plus(side2DirLight)) / 15 - const cornerLightDir = getVec(new Vec3(...cornerDir), dirVec) - const cornerLight = world.getLight(cursor.plus(cornerLightDir)) / 15 - // interpolate - const lights = [side1Light, side2Light, cornerLight, baseLight] - cornerLightResult = lights.reduce((acc, cur) => acc + cur, 0) / lights.length - } - - // Apply light value to tint - attr.t_colors!.push(tint[0] * cornerLightResult, tint[1] * cornerLightResult, tint[2] * cornerLightResult) - } - } -} - -const identicalCull = (currentElement: BlockElement, neighbor: Block, direction: Vec3) => { - const dirStr = `${direction.x},${direction.y},${direction.z}` - const lookForOppositeSide = { - '0,1,0': 'down', - '0,-1,0': 'up', - '1,0,0': 'east', - '-1,0,0': 'west', - '0,0,1': 'south', - '0,0,-1': 'north', - }[dirStr]! - const elemCompareForm = { - '0,1,0': (e: BlockElement) => `${e.from[0]},${e.from[2]}:${e.to[0]},${e.to[2]}`, - '0,-1,0': (e: BlockElement) => `${e.to[0]},${e.to[2]}:${e.from[0]},${e.from[2]}`, - '1,0,0': (e: BlockElement) => `${e.from[2]},${e.from[1]}:${e.to[2]},${e.to[1]}`, - '-1,0,0': (e: BlockElement) => `${e.to[2]},${e.to[1]}:${e.from[2]},${e.from[1]}`, - '0,0,1': (e: BlockElement) => `${e.from[1]},${e.from[2]}:${e.to[1]},${e.to[2]}`, - '0,0,-1': (e: BlockElement) => `${e.to[1]},${e.to[2]}:${e.from[1]},${e.from[2]}`, - }[dirStr]! - const elementEdgeValidator = { - '0,1,0': (e: BlockElement) => currentElement.from[1] === 0 && e.to[2] === 16, - '0,-1,0': (e: BlockElement) => currentElement.from[1] === 0 && e.to[2] === 16, - '1,0,0': (e: BlockElement) => currentElement.from[0] === 0 && e.to[1] === 16, - '-1,0,0': (e: BlockElement) => currentElement.from[0] === 0 && e.to[1] === 16, - '0,0,1': (e: BlockElement) => currentElement.from[2] === 0 && e.to[0] === 16, - '0,0,-1': (e: BlockElement) => currentElement.from[2] === 0 && e.to[0] === 16, - }[dirStr]! - const useVar = 0 - const models = neighbor.models?.map(m => m[useVar] ?? m[0]) ?? [] - // TODO we should support it! rewrite with optimizing general pipeline - if (models.some(m => m.x || m.y || m.z)) return - return models.every(model => { - return (model.elements ?? []).every(element => { - // todo check alfa on texture - return !!(element.faces[lookForOppositeSide]?.cullface && elemCompareForm(currentElement) === elemCompareForm(element) && elementEdgeValidator(element)) - }) - }) -} - -let needSectionRecomputeOnChange = false - -function renderElement (world: World, cursor: Vec3, element: BlockElement, doAO: boolean, attr: MesherGeometryOutput, globalMatrix: any, globalShift: any, block: Block, biome: string) { - const position = cursor - // const key = `${position.x},${position.y},${position.z}` - // if (!globalThis.allowedBlocks.includes(key)) return - const cullIfIdentical = block.name.includes('glass') || block.name.includes('ice') - - // eslint-disable-next-line guard-for-in - for (const face in element.faces) { - const eFace = element.faces[face] - const { corners, mask1, mask2, side } = elemFaces[face] - const dir = matmul3(globalMatrix, elemFaces[face].dir) - - if (eFace.cullface) { - const neighbor = world.getBlock(cursor.plus(new Vec3(...dir)), blockProvider, {}) - if (neighbor) { - if (cullIfIdentical && neighbor.stateId === block.stateId) continue - if (!neighbor.transparent && (isCube(neighbor) || identicalCull(element, neighbor, new Vec3(...dir)))) continue - } else { - needSectionRecomputeOnChange = true - // continue - } - } - - const minx = element.from[0] - const miny = element.from[1] - const minz = element.from[2] - const maxx = element.to[0] - const maxy = element.to[1] - const maxz = element.to[2] - - const texture = eFace.texture as any - const { u } = texture - const { v } = texture - const { su } = texture - const { sv } = texture - - const ndx = Math.floor(attr.positions.length / 3) - - let tint = [1, 1, 1] - if (eFace.tintindex !== undefined) { - if (eFace.tintindex === 0) { - if (block.name === 'redstone_wire') { - tint = tints.redstone[`${block.getProperties().power}`] - } else if (block.name === 'birch_leaves' || - block.name === 'spruce_leaves' || - block.name === 'lily_pad') { - tint = tints.constant[block.name] - } else if (block.name.includes('leaves') || block.name === 'vine') { - tint = tints.foliage[biome] - } else { - tint = tints.grass[biome] - } - } - } - - // UV rotation - let r = eFace.rotation || 0 - if (face === 'down') { - r += 180 - } - const uvcs = Math.cos(r * Math.PI / 180) - const uvsn = -Math.sin(r * Math.PI / 180) - - let localMatrix = null as any - let localShift = null as any - - if (element.rotation && !needTiles) { - // Rescale support for block model rotations - localMatrix = buildRotationMatrix( - element.rotation.axis, - element.rotation.angle - ) - - localShift = vecsub3( - element.rotation.origin, - matmul3( - localMatrix, - element.rotation.origin - ) - ) - - // Apply rescale if specified - if (element.rotation.rescale) { - const FIT_TO_BLOCK_SCALE_MULTIPLIER = 2 - Math.sqrt(2) - const angleRad = element.rotation.angle * Math.PI / 180 - const scale = Math.abs(Math.sin(angleRad)) * FIT_TO_BLOCK_SCALE_MULTIPLIER - - // Get axis vector components (1 for the rotation axis, 0 for others) - const axisX = element.rotation.axis === 'x' ? 1 : 0 - const axisY = element.rotation.axis === 'y' ? 1 : 0 - const axisZ = element.rotation.axis === 'z' ? 1 : 0 - - // Create scale matrix: scale = (1 - axisComponent) * scaleFactor + 1 - const scaleMatrix = [ - [(1 - axisX) * scale + 1, 0, 0], - [0, (1 - axisY) * scale + 1, 0], - [0, 0, (1 - axisZ) * scale + 1] - ] - - // Apply scaling to the transformation matrix - localMatrix = matmulmat3(localMatrix, scaleMatrix) - - // Recalculate shift with the new matrix - localShift = vecsub3( - element.rotation.origin, - matmul3( - localMatrix, - element.rotation.origin - ) - ) - } - } - - const aos: number[] = [] - const neighborPos = position.plus(new Vec3(...dir)) - // 10% - const { smoothLighting, shadingTheme, cardinalLight } = world.config - const faceLight = world.getLight(neighborPos, undefined, undefined, block.name) - const sideShading = (shadingTheme === 'high-contrast') ? - (0.8 + 0.5 * Math.max(0, 0.66 * dir[0] + 0.66 * dir[1] + 0.33 * dir[2])) : //old directional light behavior - ( - cardinalLight === 'nether' ? - (0.5 + Math.abs(0.1 * dir[0] + 0.4 * dir[1] + 0.3 * dir[2])) : - (0.75 + 0.25 * dir[1] + 0.05 * (Math.abs(dir[2]) - 3 * Math.abs(dir[0]))) - ) - const baseLight = sideShading * faceLight / 15 - for (const pos of corners) { - let vertex = [ - (pos[0] ? maxx : minx), - (pos[1] ? maxy : miny), - (pos[2] ? maxz : minz) - ] - - if (!needTiles) { // 10% - vertex = vecadd3(matmul3(localMatrix, vertex), localShift) - vertex = vecadd3(matmul3(globalMatrix, vertex), globalShift) - vertex = vertex.map(v => v / 16) - - attr.positions.push( - vertex[0] + (cursor.x & 15) - 8, - vertex[1] + (cursor.y & 15) - 8, - vertex[2] + (cursor.z & 15) - 8 - ) - - attr.normals.push(...dir) - - const baseu = (pos[3] - 0.5) * uvcs - (pos[4] - 0.5) * uvsn + 0.5 - const basev = (pos[3] - 0.5) * uvsn + (pos[4] - 0.5) * uvcs + 0.5 - attr.uvs.push(baseu * su + u, basev * sv + v) - } - - let light = 1 - - // const smoothLighting = true - if (doAO) { - const dx = pos[0] * 2 - 1 - const dy = pos[1] * 2 - 1 - const dz = pos[2] * 2 - 1 - const cornerDir = matmul3(globalMatrix, [dx, dy, dz]) - const side1Dir = matmul3(globalMatrix, [dx * mask1[0], dy * mask1[1], dz * mask1[2]]) - const side2Dir = matmul3(globalMatrix, [dx * mask2[0], dy * mask2[1], dz * mask2[2]]) - const side1 = world.getBlock(cursor.offset(...side1Dir)) - const side2 = world.getBlock(cursor.offset(...side2Dir)) - const corner = world.getBlock(cursor.offset(...cornerDir)) - - let cornerLightResult = faceLight - - if (smoothLighting) { - const dirVec = new Vec3(...dir) - const getVec = (v: Vec3) => { - for (const coord of ['x', 'y', 'z']) { - if (Math.abs(dirVec[coord]) > 0) v[coord] = 0 - } - return v.plus(dirVec) - } - const side1LightDir = getVec(new Vec3(...side1Dir)) - const side1Light = world.getLight(cursor.plus(side1LightDir)) - const side2DirLight = getVec(new Vec3(...side2Dir)) - const side2Light = world.getLight(cursor.plus(side2DirLight)) - const cornerLightDir = getVec(new Vec3(...cornerDir)) - const cornerLight = world.getLight(cursor.plus(cornerLightDir)) - // interpolate - const lights = [side1Light, side2Light, cornerLight, faceLight] - cornerLightResult = lights.reduce((acc, cur) => acc + cur, 0) / lights.length - } - - const side1Block = world.shouldMakeAo(side1) ? 1 : 0 - const side2Block = world.shouldMakeAo(side2) ? 1 : 0 - const cornerBlock = world.shouldMakeAo(corner) ? 1 : 0 - - // TODO: correctly interpolate ao light based on pos (evaluate once for each corner of the block) - - const ao = (side1Block && side2Block) ? 0 : (3 - (side1Block + side2Block + cornerBlock)) - const ao_bias = (shadingTheme === 'high-contrast') ? 0.25 : 0.4 - const ao_scale = (shadingTheme === 'high-contrast') ? 0.25 : 0.2 - - // todo light should go upper on lower blocks - light = sideShading * (ao * ao_scale + ao_bias) * (cornerLightResult / 15) - aos.push(ao) - } - - if (!needTiles) { - attr.colors.push(tint[0] * light, tint[1] * light, tint[2] * light) - } - } - - const lightWithColor = [baseLight * tint[0], baseLight * tint[1], baseLight * tint[2]] as [number, number, number] - - if (needTiles) { - const tiles = attr.tiles as Tiles - tiles[`${cursor.x},${cursor.y},${cursor.z}`] ??= { - block: block.name, - faces: [], - } - const needsOnlyOneFace = false - const isTilesEmpty = tiles[`${cursor.x},${cursor.y},${cursor.z}`].faces.length < 1 - if (isTilesEmpty || !needsOnlyOneFace) { - tiles[`${cursor.x},${cursor.y},${cursor.z}`].faces.push({ - face, - side, - textureIndex: eFace.texture.tileIndex, - neighbor: `${neighborPos.x},${neighborPos.y},${neighborPos.z}`, - light: baseLight, - tint: lightWithColor, - //@ts-expect-error debug prop - texture: eFace.texture.debugName || block.name, - } satisfies BlockType['faces'][number]) - } - } - - if (!needTiles) { - if (doAO && aos[0] + aos[3] >= aos[1] + aos[2]) { - attr.indices[attr.indicesCount++] = ndx - attr.indices[attr.indicesCount++] = ndx + 3 - attr.indices[attr.indicesCount++] = ndx + 2 - attr.indices[attr.indicesCount++] = ndx - attr.indices[attr.indicesCount++] = ndx + 1 - attr.indices[attr.indicesCount++] = ndx + 3 - } else { - attr.indices[attr.indicesCount++] = ndx - attr.indices[attr.indicesCount++] = ndx + 1 - attr.indices[attr.indicesCount++] = ndx + 2 - attr.indices[attr.indicesCount++] = ndx + 2 - attr.indices[attr.indicesCount++] = ndx + 1 - attr.indices[attr.indicesCount++] = ndx + 3 - } - } - } -} - -const ALWAYS_WATERLOGGED = new Set([ - 'seagrass', - 'tall_seagrass', - 'kelp', - 'kelp_plant', - 'bubble_column' -]) -const isBlockWaterlogged = (block: Block) => { - return block.getProperties().waterlogged === true || block.getProperties().waterlogged === 'true' || ALWAYS_WATERLOGGED.has(block.name) -} - -let unknownBlockModel: BlockModelPartsResolved -export function getSectionGeometry (sx: number, sy: number, sz: number, world: World) { - let delayedRender = [] as Array<() => void> - - const attr: MesherGeometryOutput = { - sx: sx + 8, - sy: sy + 8, - sz: sz + 8, - positions: [], - normals: [], - colors: [], - uvs: [], - t_positions: [], - t_normals: [], - t_colors: [], - t_uvs: [], - indices: [], - indicesCount: 0, // Track current index position - using32Array: true, - tiles: {}, - // todo this can be removed here - heads: {}, - signs: {}, - banners: {}, - // isFull: true, - hadErrors: false, - blocksCount: 0 - } - - const cursor = new Vec3(0, 0, 0) - for (cursor.y = sy; cursor.y < sy + 16; cursor.y++) { - for (cursor.z = sz; cursor.z < sz + 16; cursor.z++) { - for (cursor.x = sx; cursor.x < sx + 16; cursor.x++) { - let block = world.getBlock(cursor, blockProvider, attr)! - if (INVISIBLE_BLOCKS.has(block.name)) continue - if ((block.name.includes('_sign') || block.name === 'sign') && !world.config.disableBlockEntityTextures) { - const key = `${cursor.x},${cursor.y},${cursor.z}` - const props: any = block.getProperties() - const facingRotationMap = { - 'north': 2, - 'south': 0, - 'west': 1, - 'east': 3 - } - const isWall = block.name.endsWith('wall_sign') || block.name.endsWith('wall_hanging_sign') - const isHanging = block.name.endsWith('hanging_sign') - attr.signs[key] = { - isWall, - isHanging, - rotation: isWall ? facingRotationMap[props.facing] : +props.rotation - } - } else if (block.name === 'player_head' || block.name === 'player_wall_head') { - const key = `${cursor.x},${cursor.y},${cursor.z}` - const props: any = block.getProperties() - const facingRotationMap = { - 'north': 0, - 'south': 2, - 'west': 3, - 'east': 1 - } - const isWall = block.name === 'player_wall_head' - attr.heads[key] = { - isWall, - rotation: isWall ? facingRotationMap[props.facing] : +props.rotation - } - } else if (block.name.includes('_banner') && !world.config.disableBlockEntityTextures) { - const key = `${cursor.x},${cursor.y},${cursor.z}` - const props: any = block.getProperties() - const facingRotationMap = { - 'north': 2, - 'south': 0, - 'west': 1, - 'east': 3 - } - const isWall = block.name.endsWith('_wall_banner') - attr.banners[key] = { - isWall, - blockName: block.name, // Pass block name for base color extraction - rotation: isWall ? facingRotationMap[props.facing] : (props.rotation === undefined ? 0 : +props.rotation) - } - } - const biome = block.biome.name - - if (world.preflat) { // 10% perf - const patchProperties = preflatBlockCalculation(block, world, cursor) - if (patchProperties) { - block._originalProperties ??= block._properties - block._properties = { ...block._originalProperties, ...patchProperties } - if (block.models && JSON.stringify(block._originalProperties) !== JSON.stringify(block._properties)) { - // recompute models - block.models = undefined - block = world.getBlock(cursor, blockProvider, attr)! - } - } else { - block._properties = block._originalProperties ?? block._properties - block._originalProperties = undefined - } - } - - const isWaterlogged = isBlockWaterlogged(block) - if (block.name === 'water' || isWaterlogged) { - const pos = cursor.clone() - // eslint-disable-next-line @typescript-eslint/no-loop-func - delayedRender.push(() => { - renderLiquid(world, pos, blockProvider.getTextureInfo('water_still'), block.type, biome, true, attr, !isWaterlogged) - }) - attr.blocksCount++ - } else if (block.name === 'lava') { - renderLiquid(world, cursor, blockProvider.getTextureInfo('lava_still'), block.type, biome, false, attr, false) - attr.blocksCount++ - } - if (block.name !== 'water' && block.name !== 'lava' && !INVISIBLE_BLOCKS.has(block.name)) { - // cache - let { models } = block - - models ??= unknownBlockModel - - const firstForceVar = world.config.debugModelVariant?.[0] - let part = 0 - for (const modelVars of models ?? []) { - const pos = cursor.clone() - // const variantRuntime = mod(Math.floor(pos.x / 16) + Math.floor(pos.y / 16) + Math.floor(pos.z / 16), modelVars.length) - const variantRuntime = 0 - const useVariant = world.config.debugModelVariant?.[part] ?? firstForceVar ?? variantRuntime - part++ - const model = modelVars[useVariant] ?? modelVars[0] - if (!model) continue - - // #region 10% - let globalMatrix = null as any - let globalShift = null as any - for (const axis of ['x', 'y', 'z'] as const) { - if (axis in model) { - globalMatrix = globalMatrix ? - matmulmat3(globalMatrix, buildRotationMatrix(axis, -(model[axis] ?? 0))) : - buildRotationMatrix(axis, -(model[axis] ?? 0)) - } - } - if (globalMatrix) { - globalShift = [8, 8, 8] - globalShift = vecsub3(globalShift, matmul3(globalMatrix, globalShift)) - } - // #endregion - - for (const element of model.elements ?? []) { - const ao = model.ao ?? block.boundingBox !== 'empty' - if (block.transparent && semiTransparentBlocks.includes(block.name)) { - const pos = cursor.clone() - delayedRender.push(() => { - renderElement(world, pos, element, ao, attr, globalMatrix, globalShift, block, biome) - }) - } else { - // 60% - renderElement(world, cursor, element, ao, attr, globalMatrix, globalShift, block, biome) - } - } - } - if (part > 0) attr.blocksCount++ - } - } - } - } - - for (const render of delayedRender) { - render() - } - delayedRender = [] - - let ndx = attr.positions.length / 3 - for (let i = 0; i < attr.t_positions!.length / 12; i++) { - attr.indices[attr.indicesCount++] = ndx - attr.indices[attr.indicesCount++] = ndx + 1 - attr.indices[attr.indicesCount++] = ndx + 2 - attr.indices[attr.indicesCount++] = ndx + 2 - attr.indices[attr.indicesCount++] = ndx + 1 - attr.indices[attr.indicesCount++] = ndx + 3 - // back face - attr.indices[attr.indicesCount++] = ndx - attr.indices[attr.indicesCount++] = ndx + 2 - attr.indices[attr.indicesCount++] = ndx + 1 - attr.indices[attr.indicesCount++] = ndx + 2 - attr.indices[attr.indicesCount++] = ndx + 3 - attr.indices[attr.indicesCount++] = ndx + 1 - ndx += 4 - } - - attr.positions.push(...attr.t_positions!) - attr.normals.push(...attr.t_normals!) - attr.colors.push(...attr.t_colors!) - attr.uvs.push(...attr.t_uvs!) - - delete attr.t_positions - delete attr.t_normals - delete attr.t_colors - delete attr.t_uvs - - attr.positions = new Float32Array(attr.positions) as any - attr.normals = new Float32Array(attr.normals) as any - attr.colors = new Float32Array(attr.colors) as any - attr.uvs = new Float32Array(attr.uvs) as any - attr.using32Array = arrayNeedsUint32(attr.indices) - if (attr.using32Array) { - attr.indices = new Uint32Array(attr.indices) - } else { - attr.indices = new Uint16Array(attr.indices) - } - - if (needTiles) { - delete attr.positions - delete attr.normals - delete attr.colors - delete attr.uvs - } - - return attr -} - -// copied from three.js -function arrayNeedsUint32 (array) { - - // assumes larger values usually on last - - for (let i = array.length - 1; i >= 0; -- i) { - - if (array[i] >= 65_535) return true // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 - - } - - return false - -} - -export const setBlockStatesData = (blockstatesModels, blocksAtlas: any, _needTiles = false, useUnknownBlockModel = true, version = 'latest', mcData = (globalThis as any).mcData) => { - blockProvider = worldBlockProvider(blockstatesModels, blocksAtlas, version) - globalThis.blockProvider = blockProvider - if (useUnknownBlockModel) { - unknownBlockModel = blockProvider.getAllResolvedModels0_1({ name: 'unknown', properties: {} }) - } - - needTiles = _needTiles - - // Cache semi-transparent blocks based on regex patterns from moreBlockDataGenerated.json - const regexPatterns = Object.keys(moreBlockData.hasSemiTransparentTextuersRegex || {}) - semiTransparentBlocks = [] - - // Get all block names from blockstatesModels - if (!Array.isArray(mcData.blocks)) throw new Error('mcData.blocks is not an array') - const allBlockNames = mcData.blocks.map(block => block.name) - - // Filter blocks that match any of the regex patterns - for (const blockName of allBlockNames) { - for (const pattern of regexPatterns) { - try { - const regex = new RegExp(pattern) - if (regex.test(blockName)) { - semiTransparentBlocks.push(blockName) - break // Only add once per block - } - } catch (err) { - // Invalid regex pattern, skip - console.warn('Invalid regex pattern in hasSemiTransparentTextuersRegex:', pattern) - } - } - } -} diff --git a/renderer/viewer/lib/mesher/modelsGeometryCommon.ts b/renderer/viewer/lib/mesher/modelsGeometryCommon.ts deleted file mode 100644 index 3df205569..000000000 --- a/renderer/viewer/lib/mesher/modelsGeometryCommon.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { BlockModelPartsResolved } from './world' - -export type BlockElement = NonNullable[0] - - -export function buildRotationMatrix (axis, degree) { - const radians = degree / 180 * Math.PI - const cos = Math.cos(radians) - const sin = Math.sin(radians) - - const axis0 = { x: 0, y: 1, z: 2 }[axis] - const axis1 = (axis0 + 1) % 3 - const axis2 = (axis0 + 2) % 3 - - const matrix = [ - [0, 0, 0], - [0, 0, 0], - [0, 0, 0] - ] - - matrix[axis0][axis0] = 1 - matrix[axis1][axis1] = cos - matrix[axis1][axis2] = -sin - matrix[axis2][axis1] = +sin - matrix[axis2][axis2] = cos - - return matrix -} - -export function vecadd3 (a, b) { - if (!b) return a - return [a[0] + b[0], a[1] + b[1], a[2] + b[2]] -} - -export function vecsub3 (a, b) { - if (!b) return a - return [a[0] - b[0], a[1] - b[1], a[2] - b[2]] -} - -export function matmul3 (matrix, vector): [number, number, number] { - if (!matrix) return vector - return [ - matrix[0][0] * vector[0] + matrix[0][1] * vector[1] + matrix[0][2] * vector[2], - matrix[1][0] * vector[0] + matrix[1][1] * vector[1] + matrix[1][2] * vector[2], - matrix[2][0] * vector[0] + matrix[2][1] * vector[1] + matrix[2][2] * vector[2] - ] -} - -export function matmulmat3 (a, b) { - const te = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] - - const a11 = a[0][0]; const a12 = a[1][0]; const a13 = a[2][0] - const a21 = a[0][1]; const a22 = a[1][1]; const a23 = a[2][1] - const a31 = a[0][2]; const a32 = a[1][2]; const a33 = a[2][2] - - const b11 = b[0][0]; const b12 = b[1][0]; const b13 = b[2][0] - const b21 = b[0][1]; const b22 = b[1][1]; const b23 = b[2][1] - const b31 = b[0][2]; const b32 = b[1][2]; const b33 = b[2][2] - - te[0][0] = a11 * b11 + a12 * b21 + a13 * b31 - te[1][0] = a11 * b12 + a12 * b22 + a13 * b32 - te[2][0] = a11 * b13 + a12 * b23 + a13 * b33 - - te[0][1] = a21 * b11 + a22 * b21 + a23 * b31 - te[1][1] = a21 * b12 + a22 * b22 + a23 * b32 - te[2][1] = a21 * b13 + a22 * b23 + a23 * b33 - - te[0][2] = a31 * b11 + a32 * b21 + a33 * b31 - te[1][2] = a31 * b12 + a32 * b22 + a33 * b32 - te[2][2] = a31 * b13 + a32 * b23 + a33 * b33 - - return te -} - -export const elemFaces = { - up: { - dir: [0, 1, 0], - mask1: [1, 1, 0], - mask2: [0, 1, 1], - corners: [ - [0, 1, 1, 0, 1], - [1, 1, 1, 1, 1], - [0, 1, 0, 0, 0], - [1, 1, 0, 1, 0] - ] - }, - down: { - dir: [0, -1, 0], - mask1: [1, 1, 0], - mask2: [0, 1, 1], - corners: [ - [1, 0, 1, 0, 1], - [0, 0, 1, 1, 1], - [1, 0, 0, 0, 0], - [0, 0, 0, 1, 0] - ] - }, - east: { - dir: [1, 0, 0], - mask1: [1, 1, 0], - mask2: [1, 0, 1], - corners: [ - [1, 1, 1, 0, 0], - [1, 0, 1, 0, 1], - [1, 1, 0, 1, 0], - [1, 0, 0, 1, 1] - ] - }, - west: { - dir: [-1, 0, 0], - mask1: [1, 1, 0], - mask2: [1, 0, 1], - corners: [ - [0, 1, 0, 0, 0], - [0, 0, 0, 0, 1], - [0, 1, 1, 1, 0], - [0, 0, 1, 1, 1] - ] - }, - north: { - dir: [0, 0, -1], - mask1: [1, 0, 1], - mask2: [0, 1, 1], - corners: [ - [1, 0, 0, 1, 1], - [0, 0, 0, 0, 1], - [1, 1, 0, 1, 0], - [0, 1, 0, 0, 0] - ] - }, - south: { - dir: [0, 0, 1], - mask1: [1, 0, 1], - mask2: [0, 1, 1], - corners: [ - [0, 0, 1, 0, 1], - [1, 0, 1, 1, 1], - [0, 1, 1, 0, 0], - [1, 1, 1, 1, 0] - ] - } -} diff --git a/renderer/viewer/lib/mesher/shared.ts b/renderer/viewer/lib/mesher/shared.ts deleted file mode 100644 index 90f9f288e..000000000 --- a/renderer/viewer/lib/mesher/shared.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { BlockType } from '../../../playground/shared' - -// only here for easier testing -export const defaultMesherConfig = { - version: '', - worldMaxY: 256, - worldMinY: 0, - enableLighting: true, - skyLight: 15, - smoothLighting: true, - shadingTheme: 'high-contrast', - cardinalLight: 'default', - outputFormat: 'threeJs' as 'threeJs' | 'webgpu', - // textureSize: 1024, // for testing - debugModelVariant: undefined as undefined | number[], - clipWorldBelowY: undefined as undefined | number, - disableBlockEntityTextures: false -} - -export type CustomBlockModels = { - [blockPosKey: string]: string // blockPosKey is "x,y,z" -> model name -} - -export type MesherConfig = typeof defaultMesherConfig - -export type MesherGeometryOutput = { - sx: number, - sy: number, - sz: number, - // resulting: float32array - positions: any, - normals: any, - colors: any, - uvs: any, - t_positions?: number[], - t_normals?: number[], - t_colors?: number[], - t_uvs?: number[], - - indices: Uint32Array | Uint16Array | number[], - indicesCount: number, - using32Array: boolean, - tiles: Record, - heads: Record, - signs: Record, - banners: Record, - // isFull: boolean - hadErrors: boolean - blocksCount: number - customBlockModels?: CustomBlockModels -} - -export interface MesherMainEvents { - geometry: { type: 'geometry'; key: string; geometry: MesherGeometryOutput; workerIndex: number }; - sectionFinished: { type: 'sectionFinished'; key: string; workerIndex: number; processTime?: number }; - blockStateModelInfo: { type: 'blockStateModelInfo'; info: Record }; - heightmap: { type: 'heightmap'; key: string; heightmap: Uint8Array }; - /** Reply to `{ type: 'mc-web-ping', t?, workerIndex? }` from the main thread (not batched in worker). */ - mcWebPong: { type: 'mc-web-pong'; workerIndex: number; t?: number; recvAt?: number }; -} - -export type MesherMainEvent = MesherMainEvents[keyof MesherMainEvents] - -export type HighestBlockInfo = { y: number, stateId: number | undefined, biomeId: number | undefined } - -export type BlockStateModelInfo = { - cacheKey: string - issues: string[] - modelNames: string[] - conditions: string[] -} - -export const getBlockAssetsCacheKey = (stateId: number, modelNameOverride?: string) => { - return modelNameOverride ? `${stateId}:${modelNameOverride}` : String(stateId) -} diff --git a/renderer/viewer/lib/mesher/standaloneRenderer.ts b/renderer/viewer/lib/mesher/standaloneRenderer.ts deleted file mode 100644 index 3d468dce4..000000000 --- a/renderer/viewer/lib/mesher/standaloneRenderer.ts +++ /dev/null @@ -1,270 +0,0 @@ -/* eslint-disable @stylistic/function-call-argument-newline */ -import { Vec3 } from 'vec3' -import { Block } from 'prismarine-block' -import { IndexedData } from 'minecraft-data' -import * as THREE from 'three' -import { BlockModelPartsResolved } from './world' -import { BlockElement, buildRotationMatrix, elemFaces, matmul3, matmulmat3, vecadd3, vecsub3 } from './modelsGeometryCommon' - -type NeighborSide = 'up' | 'down' | 'east' | 'west' | 'north' | 'south' - -function tintToGl (tint) { - const r = (tint >> 16) & 0xff - const g = (tint >> 8) & 0xff - const b = tint & 0xff - return [r / 255, g / 255, b / 255] -} - -type Neighbors = Partial> -function renderElement (element: BlockElement, doAO: boolean, attr, globalMatrix, globalShift, block: Block | undefined, biome: string, neighbors: Neighbors) { - const cursor = new Vec3(0, 0, 0) - - // const key = `${position.x},${position.y},${position.z}` - // if (!globalThis.allowedBlocks.includes(key)) return - // const cullIfIdentical = block.name.indexOf('glass') >= 0 - - // eslint-disable-next-line guard-for-in - for (const face in element.faces) { - const eFace = element.faces[face] - const { corners, mask1, mask2 } = elemFaces[face] - const dir = matmul3(globalMatrix, elemFaces[face].dir) - - if (eFace.cullface) { - if (neighbors[face]) continue - } - - const minx = element.from[0] - const miny = element.from[1] - const minz = element.from[2] - const maxx = element.to[0] - const maxy = element.to[1] - const maxz = element.to[2] - - const texture = eFace.texture as any - const { u } = texture - const { v } = texture - const { su } = texture - const { sv } = texture - - const ndx = Math.floor(attr.positions.length / 3) - - let tint = [1, 1, 1] - if (eFace.tintindex !== undefined) { - if (eFace.tintindex === 0) { - // TODO - // if (block.name === 'redstone_wire') { - // tint = tints.redstone[`${block.getProperties().power}`] - // } else if (block.name === 'birch_leaves' || - // block.name === 'spruce_leaves' || - // block.name === 'lily_pad') { - // tint = tints.constant[block.name] - // } else if (block.name.includes('leaves') || block.name === 'vine') { - // tint = tints.foliage[biome] - // } else { - // tint = tints.grass[biome] - // } - const grassTint = [145 / 255, 189 / 255, 89 / 255] - tint = grassTint - } - } - - // UV rotation - const r = eFace.rotation || 0 - const uvcs = Math.cos(r * Math.PI / 180) - const uvsn = -Math.sin(r * Math.PI / 180) - - let localMatrix = null as any - let localShift = null as any - - if (element.rotation) { - // todo do we support rescale? - localMatrix = buildRotationMatrix( - element.rotation.axis, - element.rotation.angle - ) - - localShift = vecsub3( - element.rotation.origin, - matmul3( - localMatrix, - element.rotation.origin - ) - ) - } - - const aos: number[] = [] - // const neighborPos = position.plus(new Vec3(...dir)) - // const baseLight = world.getLight(neighborPos, undefined, undefined, block.name) / 15 - const baseLight = 1 - for (const pos of corners) { - let vertex = [ - (pos[0] ? maxx : minx), - (pos[1] ? maxy : miny), - (pos[2] ? maxz : minz) - ] - - vertex = vecadd3(matmul3(localMatrix, vertex), localShift) - vertex = vecadd3(matmul3(globalMatrix, vertex), globalShift) - vertex = vertex.map(v => v / 16) - - attr.positions.push( - vertex[0]/* + (cursor.x & 15) - 8 */, - vertex[1]/* + (cursor.y & 15) x */, - vertex[2]/* + (cursor.z & 15) - 8 */ - ) - - attr.normals.push(...dir) - - const baseu = (pos[3] - 0.5) * uvcs - (pos[4] - 0.5) * uvsn + 0.5 - const basev = (pos[3] - 0.5) * uvsn + (pos[4] - 0.5) * uvcs + 0.5 - attr.uvs.push(baseu * su + u, basev * sv + v) - - let light = 1 - if (doAO) { - const cornerLightResult = 15 - - const side1Block = 0 - const side2Block = 0 - const cornerBlock = 0 - - const ao = (side1Block && side2Block) ? 0 : (3 - (side1Block + side2Block + cornerBlock)) - // todo light should go upper on lower blocks - light = (ao + 1) / 4 * (cornerLightResult / 15) - aos.push(ao) - } - - attr.colors.push(baseLight * tint[0] * light, baseLight * tint[1] * light, baseLight * tint[2] * light) - } - - // if (needTiles) { - // attr.tiles[`${cursor.x},${cursor.y},${cursor.z}`] ??= { - // block: block.name, - // faces: [], - // } - // attr.tiles[`${cursor.x},${cursor.y},${cursor.z}`].faces.push({ - // face, - // neighbor: `${neighborPos.x},${neighborPos.y},${neighborPos.z}`, - // light: baseLight - // // texture: eFace.texture.name, - // }) - // } - - if (doAO && aos[0] + aos[3] >= aos[1] + aos[2]) { - attr.indices.push( - - ndx, ndx + 3, ndx + 2, - ndx, ndx + 1, ndx + 3 - ) - } else { - attr.indices.push( - - ndx, ndx + 1, ndx + 2, - ndx + 2, ndx + 1, ndx + 3 - ) - } - } -} - -export const renderBlockThreeAttr = (models: BlockModelPartsResolved, block: Block | undefined, biome: string, mcData: IndexedData, variants = [], neighbors: Neighbors = {}) => { - const sx = 0 - const sy = 0 - const sz = 0 - - const attr = { - sx: sx + 0.5, - sy: sy + 0.5, - sz: sz + 0.5, - positions: [], - normals: [], - colors: [], - uvs: [], - t_positions: [], - t_normals: [], - t_colors: [], - t_uvs: [], - indices: [], - tiles: {}, - } as Record - - for (const [i, modelVars] of models.entries()) { - const model = modelVars[variants[i]] ?? modelVars[0] - if (!model) continue - let globalMatrix = null as any - let globalShift = null as any - for (const axis of ['x', 'y', 'z'] as const) { - if (axis in model) { - if (globalMatrix) { globalMatrix = matmulmat3(globalMatrix, buildRotationMatrix(axis, -(model[axis] ?? 0))) } else { globalMatrix = buildRotationMatrix(axis, -(model[axis] ?? 0)) } - } - } - if (globalMatrix) { - globalShift = [8, 8, 8] - globalShift = vecsub3(globalShift, matmul3(globalMatrix, globalShift)) - } - - const ao = model.ao ?? true - - for (const element of model.elements ?? []) { - renderElement(element, ao, attr, globalMatrix, globalShift, block, biome, neighbors) - } - } - - let ndx = attr.positions.length / 3 - for (let i = 0; i < attr.t_positions.length / 12; i++) { - attr.indices.push( - ndx, ndx + 1, ndx + 2, ndx + 2, ndx + 1, ndx + 3, - // back face - ndx, ndx + 2, ndx + 1, ndx + 2, ndx + 3, ndx + 1 - ) - ndx += 4 - } - - attr.positions.push(...attr.t_positions) - attr.normals.push(...attr.t_normals) - attr.colors.push(...attr.t_colors) - attr.uvs.push(...attr.t_uvs) - - delete attr.t_positions - delete attr.t_normals - delete attr.t_colors - delete attr.t_uvs - - attr.positions = new Float32Array(attr.positions) as any - attr.normals = new Float32Array(attr.normals) as any - attr.colors = new Float32Array(attr.colors) as any - attr.uvs = new Float32Array(attr.uvs) as any - - return attr -} - -export const renderBlockThree = (...args: Parameters) => { - const attr = renderBlockThreeAttr(...args) - const data = { - geometry: attr - } - - const geometry = new THREE.BufferGeometry() - geometry.setAttribute('position', new THREE.BufferAttribute(data.geometry.positions, 3)) - geometry.setAttribute('normal', new THREE.BufferAttribute(data.geometry.normals, 3)) - geometry.setAttribute('color', new THREE.BufferAttribute(data.geometry.colors, 3)) - geometry.setAttribute('uv', new THREE.BufferAttribute(data.geometry.uvs, 2)) - geometry.setIndex(data.geometry.indices) - geometry.name = 'block-geometry' - - return geometry -} - -export const getThreeBlockModelGroup = (material: THREE.Material, ...args: Parameters) => { - const geometry = renderBlockThree(...args) - const mesh = new THREE.Mesh(geometry, material) - mesh.position.set(-0.5, -0.5, -0.5) - const group = new THREE.Group() - group.add(mesh) - group.rotation.set(0, -THREE.MathUtils.degToRad(90), 0, 'ZYX') - globalThis.mesh = group - return group - // return new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshPhongMaterial({ color: 0x00_00_ff, transparent: true, opacity: 0.5 })) -} - -export const setBlockPosition = (object: THREE.Object3D, position: { x: number, y: number, z: number }) => { - object.position.set(position.x + 0.5, position.y + 0.5, position.z + 0.5) -} diff --git a/renderer/viewer/lib/mesher/test/mesherTester.ts b/renderer/viewer/lib/mesher/test/mesherTester.ts deleted file mode 100644 index bbc6161ce..000000000 --- a/renderer/viewer/lib/mesher/test/mesherTester.ts +++ /dev/null @@ -1,76 +0,0 @@ -import ChunkLoader, { PCChunk } from 'prismarine-chunk' -import { Vec3 } from 'vec3' -import MinecraftData from 'minecraft-data' -import blocksAtlasesJson from 'mc-assets/dist/blocksAtlases.json' -import { World as MesherWorld } from '../world' -import { setBlockStatesData, getSectionGeometry } from '../models' - -export const setup = (version, initialBlocks: Array<[number[], string]>) => { - const mcData = MinecraftData(version) - const blockStatesModels = require(`mc-assets/dist/blockStatesModels.json`) - const mesherWorld = new MesherWorld(version) - const Chunk = ChunkLoader(version) - const chunk1 = new Chunk(undefined as any) - - const pos = new Vec3(2, 5, 2) - for (const [addPos, name] of initialBlocks) { - chunk1.setBlockStateId(pos.offset(addPos[0], addPos[1], addPos[2]), mcData.blocksByName[name].defaultState) - } - - const getGeometry = () => { - const sectionGeometry = getSectionGeometry(0, 0, 0, mesherWorld) - const centerFaces = sectionGeometry.tiles[`${pos.x},${pos.y},${pos.z}`]?.faces.length ?? 0 - const totalTiles = Object.values(sectionGeometry.tiles).reduce((acc, val: any) => acc + val.faces.length, 0) - const centerTileNeighbors = Object.entries(sectionGeometry.tiles).reduce((acc, [key, val]: any) => { - return acc + val.faces.filter((face: any) => face.neighbor === `${pos.x},${pos.y},${pos.z}`).length - }, 0) - return { - centerFaces, - totalTiles, - centerTileNeighbors, - faces: sectionGeometry.tiles[`${pos.x},${pos.y},${pos.z}`]?.faces ?? [], - attr: sectionGeometry - } - } - - setBlockStatesData(blockStatesModels, blocksAtlasesJson, true, false, version, { blocks: mcData.blocksArray }) - const reload = () => { - mesherWorld.removeColumn(0, 0) - mesherWorld.addColumn(0, 0, chunk1.toJson()) - } - reload() - - const getLights = () => { - return Object.fromEntries(getGeometry().faces.map(({ face, light }) => ([face, (light ?? 0) * 15 - 2]))) - } - - const setLight = (x: number, y: number, z: number, val = 0) => { - // create columns first - chunk1.setBlockLight(pos.offset(x, y, z), 15) - chunk1.setSkyLight(pos.offset(x, y, z), 15) - chunk1.setBlockLight(pos.offset(x, y, z), val) - chunk1.setSkyLight(pos.offset(x, y, z), 0) - } - - return { - mesherWorld, - setLight, - getLights, - getGeometry, - pos, - mcData, - reload, - chunk: chunk1 as PCChunk - } -} - -// surround it -const addPositions = [ - // [[0, 0, 0], 'diamond_block'], - [[1, 0, 0], 'stone'], - [[-1, 0, 0], 'stone'], - [[0, 1, 0], 'stone'], - [[0, -1, 0], 'stone'], - [[0, 0, 1], 'stone'], - [[0, 0, -1], 'stone'], -] diff --git a/renderer/viewer/lib/mesher/test/playground.ts b/renderer/viewer/lib/mesher/test/playground.ts deleted file mode 100644 index 0441dd609..000000000 --- a/renderer/viewer/lib/mesher/test/playground.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { BlockNames } from '../../../../../src/mcDataTypes' -import { setup } from './mesherTester' - -const addPositions = [ - // [[0, 0, 0], 'diamond_block'], - [[1, 0, 0], 'stone'], - [[-1, 0, 0], 'stone'], - [[0, 1, 0], 'stone'], - [[0, -1, 0], 'stone'], - [[0, 0, 1], 'stone'], - [[0, 0, -1], 'stone'], -] as const - -const { mesherWorld, getGeometry, pos, mcData } = setup('1.21.1', addPositions as any) - -// mesherWorld.setBlockStateId(pos, 712) -// mesherWorld.setBlockStateId(pos, mcData.blocksByName.stone_slab.defaultState) -mesherWorld.setBlockStateId(pos, 11_225) - -console.log(getGeometry().centerTileNeighbors) diff --git a/renderer/viewer/lib/mesher/test/tests.test.ts b/renderer/viewer/lib/mesher/test/tests.test.ts deleted file mode 100644 index 6c96055c9..000000000 --- a/renderer/viewer/lib/mesher/test/tests.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { test, expect } from 'vitest' -import supportedVersions from '../../../../../src/supportedVersions.mjs' -import { INVISIBLE_BLOCKS } from '../worldConstants' -import { setup } from './mesherTester' - -// const lastVersion = supportedVersions.at(-1) -const lastVersion = '1.21' - -const addPositions = [ - // [[0, 0, 0], 'diamond_block'], - // [[1, 0, 0], 'stone'], - // [[-1, 0, 0], 'stone'], - // [[0, 1, 0], 'stone'], - // [[0, -1, 0], 'stone'], - // [[0, 0, 1], 'stone'], - // [[0, 0, -1], 'stone'], -] as const - -test('Known blocks are not rendered', () => { - const { mesherWorld, getGeometry, pos, mcData } = setup(lastVersion, addPositions as any) - const ignoreAsExpected = new Set([...INVISIBLE_BLOCKS, 'water', 'lava']) - - let time = 0 - let times = 0 - const missingBlocks = {}/* as {[number, number]} */ - const erroredBlocks = {}/* as {[number, number]} */ - for (const block of mcData.blocksArray) { - if (ignoreAsExpected.has(block.name)) continue - // if (block.maxStateId! - block.minStateId! > 100) continue - // for (let i = block.minStateId!; i <= block.maxStateId!; i++) { - for (let i = block.defaultState; i <= block.defaultState; i++) { - // if (block.transparent) continue - mesherWorld.setBlockStateId(pos, i) - const start = performance.now() - const { centerFaces, totalTiles, centerTileNeighbors, attr } = getGeometry() - time += performance.now() - start - times++ - if (centerFaces === 0) { - const objAdd = attr.hadErrors ? erroredBlocks : missingBlocks - if (objAdd[block.name]) continue - objAdd[block.name] = true - // invalidBlocks[block.name] = [i - block.defaultState!, centerTileNeighbors] - // console.log('INVALID', block.name, centerTileNeighbors, i - block.minStateId) - } - } - } - console.log('Checking blocks of version', lastVersion) - console.log('Average time', time / times) - // should be fixed, but to avoid regressions & for visibility - // TODO resolve creaking_heart issue (1.21.3) - expect(missingBlocks).toMatchInlineSnapshot(` - { - "structure_void": true, - } - `) - expect(erroredBlocks).toMatchInlineSnapshot('{}') -}) diff --git a/renderer/viewer/lib/mesher/world.ts b/renderer/viewer/lib/mesher/world.ts deleted file mode 100644 index bd54eaeb2..000000000 --- a/renderer/viewer/lib/mesher/world.ts +++ /dev/null @@ -1,270 +0,0 @@ -import Chunks from 'prismarine-chunk' -import mcData from 'minecraft-data' -import { Block } from 'prismarine-block' -import { Vec3 } from 'vec3' -import { WorldBlockProvider } from 'mc-assets/dist/worldBlockProvider' -import moreBlockDataGeneratedJson from '../moreBlockDataGenerated.json' -import legacyJson from '../../../../src/preflatMap.json' -import { defaultMesherConfig, CustomBlockModels, BlockStateModelInfo, getBlockAssetsCacheKey } from './shared' -import { INVISIBLE_BLOCKS } from './worldConstants' - -const ignoreAoBlocks = Object.keys(moreBlockDataGeneratedJson.noOcclusions) - -function columnKey (x, z) { - return `${x},${z}` -} - -function isCube (shapes) { - if (!shapes || shapes.length !== 1) return false - const shape = shapes[0] - return shape[0] === 0 && shape[1] === 0 && shape[2] === 0 && shape[3] === 1 && shape[4] === 1 && shape[5] === 1 -} - -export type BlockModelPartsResolved = ReturnType - -export type WorldBlock = Omit & { - // todo - isCube: boolean - /** cache */ - models?: BlockModelPartsResolved | null - _originalProperties?: Record - _properties?: Record -} - -export class World { - config = defaultMesherConfig - Chunk: typeof import('prismarine-chunk/types/index').PCChunk - columns = {} as { [key: string]: import('prismarine-chunk/types/index').PCChunk } - blockCache = {} - biomeCache: { [id: number]: mcData.Biome } - preflat: boolean - erroredBlockModel?: BlockModelPartsResolved - customBlockModels = new Map() // chunkKey -> blockModels - sentBlockStateModels = new Set() - blockStateModelInfo = new Map() - - constructor (version) { - this.Chunk = Chunks(version) as any - this.biomeCache = mcData(version).biomes - this.preflat = !mcData(version).supportFeature('blockStateId') - this.config.version = version - } - - getLight (pos: Vec3, isNeighbor = false, skipMoreChecks = false, curBlockName = '') { - // for easier testing - if (!(pos instanceof Vec3)) pos = new Vec3(...pos as [number, number, number]) - const { enableLighting, skyLight } = this.config - if (!enableLighting) return 15 - // const key = `${pos.x},${pos.y},${pos.z}` - // if (lightsCache.has(key)) return lightsCache.get(key) - const column = this.getColumnByPos(pos) - if (!column || !hasChunkSection(column, pos)) return 15 - let result = Math.min( - 15, - Math.max( - column.getBlockLight(posInChunk(pos)), - Math.min(skyLight, column.getSkyLight(posInChunk(pos))) - ) + 2 - ) - // lightsCache.set(key, result) - if (result === 2 && [this.getBlock(pos)?.name ?? '', curBlockName].some(x => /_stairs|slab|glass_pane/.exec(x)) && !skipMoreChecks) { // todo this is obviously wrong - const lights = [ - this.getLight(pos.offset(0, 1, 0), undefined, true), - this.getLight(pos.offset(0, -1, 0), undefined, true), - this.getLight(pos.offset(0, 0, 1), undefined, true), - this.getLight(pos.offset(0, 0, -1), undefined, true), - this.getLight(pos.offset(1, 0, 0), undefined, true), - this.getLight(pos.offset(-1, 0, 0), undefined, true) - ].filter(x => x !== 2) - if (lights.length) { - const min = Math.min(...lights) - result = min - } - } - if (isNeighbor && result === 2) result = 15 // TODO - return result - } - - addColumn (x, z, json) { - const chunk = this.Chunk.fromJson(json) - this.columns[columnKey(x, z)] = chunk as any - return chunk - } - - removeColumn (x, z) { - delete this.columns[columnKey(x, z)] - } - - getColumn (x, z) { - return this.columns[columnKey(x, z)] - } - - setBlockStateId (pos: Vec3, stateId) { - if (stateId === undefined) throw new Error('stateId is undefined') - const key = columnKey(Math.floor(pos.x / 16) * 16, Math.floor(pos.z / 16) * 16) - - const column = this.columns[key] - // null column means chunk not loaded - if (!column) return false - - column.setBlockStateId(posInChunk(pos.floored()), stateId) - - return true - } - - getColumnByPos (pos: Vec3) { - return this.getColumn(Math.floor(pos.x / 16) * 16, Math.floor(pos.z / 16) * 16) - } - - getBlock (pos: Vec3, blockProvider?: WorldBlockProvider, attr?: { hadErrors?: boolean }): WorldBlock | null { - // for easier testing - if (!(pos instanceof Vec3)) pos = new Vec3(...pos as [number, number, number]) - const key = columnKey(Math.floor(pos.x / 16) * 16, Math.floor(pos.z / 16) * 16) - const blockPosKey = `${pos.x},${pos.y},${pos.z}` - const modelOverride = this.customBlockModels.get(key)?.[blockPosKey] - - const column = this.columns[key] - // null column means chunk not loaded - if (!column) return null - - const loc = pos.floored() - const locInChunk = posInChunk(loc) - const stateId = column.getBlockStateId(locInChunk) - - const cacheKey = getBlockAssetsCacheKey(stateId, modelOverride) - - if (!this.blockCache[cacheKey]) { - const b = column.getBlock(locInChunk) as unknown as WorldBlock - if (modelOverride) { - b.name = modelOverride - } - b.isCube = isCube(b.shapes) - this.blockCache[cacheKey] = b - Object.defineProperty(b, 'position', { - get () { - throw new Error('position is not reliable, use pos parameter instead of block.position') - } - }) - if (this.preflat) { - b._properties = {} - - const namePropsStr = legacyJson.blocks[b.type + ':' + b.metadata] || findClosestLegacyBlockFallback(b.type, b.metadata, pos) - if (namePropsStr) { - b.name = namePropsStr.split('[')[0] - const propsStr = namePropsStr.split('[')?.[1]?.split(']') - if (propsStr) { - const newProperties = Object.fromEntries(propsStr.join('').split(',').map(x => { - let [key, val] = x.split('=') - if (!isNaN(val)) val = parseInt(val, 10) - return [key, val] - })) - b._properties = newProperties - } - } - } - } - - const block: WorldBlock = this.blockCache[cacheKey] - - if (block.models === undefined && blockProvider) { - if (!attr) throw new Error('attr is required') - const props = block.getProperties() - - try { - // fixme - if (this.preflat) { - if (block.name === 'cobblestone_wall') { - props.up = 'true' - for (const key of ['north', 'south', 'east', 'west']) { - const val = props[key] - if (val === 'false' || val === 'true') { - props[key] = val === 'true' ? 'low' : 'none' - } - } - } - } - - const useFallbackModel = !!(this.preflat || modelOverride) - const issues = [] as string[] - const resolvedModelNames = [] as string[] - const resolvedConditions = [] as string[] - block.models = blockProvider.getAllResolvedModels0_1( - { - name: block.name, - properties: props, - }, - useFallbackModel, - issues, - resolvedModelNames, - resolvedConditions - )! - - // Track block state model info - if (!this.sentBlockStateModels.has(cacheKey)) { - this.blockStateModelInfo.set(cacheKey, { - cacheKey, - issues, - modelNames: resolvedModelNames, - conditions: resolvedConditions - }) - } - - if (!block.models.length) { - if (block.name !== 'water' && block.name !== 'lava' && !INVISIBLE_BLOCKS.has(block.name)) { - console.debug('[mesher] block to render not found', block.name, props) - } - block.models = null - } - - if (block.models && modelOverride) { - const model = block.models[0] - block.transparent = model[0]?.['transparent'] ?? block.transparent - } - } catch (err) { - this.erroredBlockModel ??= blockProvider.getAllResolvedModels0_1({ name: 'errored', properties: {} }) - block.models ??= this.erroredBlockModel - console.error(`Critical assets error. Unable to get block model for ${block.name}[${JSON.stringify(props)}]: ` + err.message, err.stack) - attr.hadErrors = true - } - } - - if (block.name === 'flowing_water') block.name = 'water' - if (block.name === 'flowing_lava') block.name = 'lava' - if (block.name === 'bubble_column') block.name = 'water' // TODO need to distinguish between water and bubble column - // block.position = loc // it overrides position of all currently loaded blocks - //@ts-expect-error - block.biome = this.biomeCache[column.getBiome(locInChunk)] ?? this.biomeCache[1] ?? this.biomeCache[0] - if (block.name === 'redstone_ore') block.transparent = false - return block - } - - shouldMakeAo (block: WorldBlock | null) { - return block?.isCube && !ignoreAoBlocks.includes(block.name) && block.boundingBox !== 'empty' - } -} - -const findClosestLegacyBlockFallback = (id, metadata, pos) => { - console.warn(`[mesher] Unknown block with ${id}:${metadata} at ${pos}, falling back`) // todo has known issues - for (const [key, value] of Object.entries(legacyJson.blocks)) { - const [idKey, meta] = key.split(':') - if (idKey === id) return value - } - return null -} - -// todo export in chunk instead -const hasChunkSection = (column, pos) => { - if (column._getSection) return column._getSection(pos) - if (column.skyLightSections) { - return column.skyLightSections[getLightSectionIndex(pos, column.minY)] || column.blockLightSections[getLightSectionIndex(pos, column.minY)] - } - if (column.sections) return column.sections[pos.y >> 4] -} - -function posInChunk (pos) { - return new Vec3(Math.floor(pos.x) & 15, Math.floor(pos.y), Math.floor(pos.z) & 15) -} - -function getLightSectionIndex (pos, minY = 0) { - return Math.floor((pos.y - minY) / 16) + 1 -} diff --git a/renderer/viewer/lib/mesher/worldConstants.ts b/renderer/viewer/lib/mesher/worldConstants.ts deleted file mode 100644 index 6aa0e0fcd..000000000 --- a/renderer/viewer/lib/mesher/worldConstants.ts +++ /dev/null @@ -1 +0,0 @@ -export const INVISIBLE_BLOCKS = new Set(['air', 'void_air', 'cave_air', 'barrier', 'light', 'moving_piston']) diff --git a/renderer/viewer/lib/mesherlogReader.ts b/renderer/viewer/lib/mesherlogReader.ts deleted file mode 100644 index 0f1e74c02..000000000 --- a/renderer/viewer/lib/mesherlogReader.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* eslint-disable no-await-in-loop */ -import { Vec3 } from 'vec3' - -// import log from '../../../../../Downloads/mesher (2).log' -import { WorldRendererCommon } from './worldrendererCommon' -const log = '' - - -export class MesherLogReader { - chunksToReceive: Array<{ - x: number - z: number - chunkLength: number - }> = [] - messagesQueue: Array<{ - fromWorker: boolean - workerIndex: number - message: any - }> = [] - - sectionFinishedToReceive = null as { - messagesLeft: string[] - resolve: () => void - } | null - replayStarted = false - - constructor (private readonly worldRenderer: WorldRendererCommon) { - this.parseMesherLog() - } - - chunkReceived (x: number, z: number, chunkLength: number) { - // remove existing chunks with same x and z - const existingChunkIndex = this.chunksToReceive.findIndex(chunk => chunk.x === x && chunk.z === z) - if (existingChunkIndex === -1) { - // console.error('Chunk not found', x, z) - } else { - // warn if chunkLength is different - if (this.chunksToReceive[existingChunkIndex].chunkLength !== chunkLength) { - // console.warn('Chunk length mismatch', x, z, this.chunksToReceive[existingChunkIndex].chunkLength, chunkLength) - } - // remove chunk - this.chunksToReceive = this.chunksToReceive.filter((chunk, index) => chunk.x !== x || chunk.z !== z) - } - this.maybeStartReplay() - } - - async maybeStartReplay () { - if (this.chunksToReceive.length !== 0 || this.replayStarted) return - const lines = log.split('\n') - console.log('starting replay') - this.replayStarted = true - const waitForWorkersMessages = async () => { - if (!this.sectionFinishedToReceive) return - await new Promise(resolve => { - this.sectionFinishedToReceive!.resolve = resolve - }) - } - - for (const line of lines) { - if (line.includes('dispatchMessages dirty')) { - await waitForWorkersMessages() - this.worldRenderer.stopMesherMessagesProcessing = true - const message = JSON.parse(line.slice(line.indexOf('{'), line.lastIndexOf('}') + 1)) - if (!message.value) continue - const index = line.split(' ')[1] - const type = line.split(' ')[3] - // console.log('sending message', message.x, message.y, message.z) - this.worldRenderer.forceCallFromMesherReplayer = true - this.worldRenderer.setSectionDirty(new Vec3(message.x, message.y, message.z), message.value) - this.worldRenderer.forceCallFromMesherReplayer = false - } - if (line.includes('-> blockUpdate')) { - await waitForWorkersMessages() - this.worldRenderer.stopMesherMessagesProcessing = true - const message = JSON.parse(line.slice(line.indexOf('{'), line.lastIndexOf('}') + 1)) - this.worldRenderer.forceCallFromMesherReplayer = true - this.worldRenderer.setBlockStateIdInner(new Vec3(message.pos.x, message.pos.y, message.pos.z), message.stateId) - this.worldRenderer.forceCallFromMesherReplayer = false - } - - if (line.includes(' sectionFinished ')) { - if (!this.sectionFinishedToReceive) { - console.log('starting worker message processing validating') - this.worldRenderer.stopMesherMessagesProcessing = false - this.sectionFinishedToReceive = { - messagesLeft: [], - resolve: () => { - this.sectionFinishedToReceive = null - } - } - } - const parts = line.split(' ') - const coordsPart = parts.find(part => part.split(',').length === 3) - if (!coordsPart) throw new Error(`no coords part found ${line}`) - const [x, y, z] = coordsPart.split(',').map(Number) - this.sectionFinishedToReceive.messagesLeft.push(`${x},${y},${z}`) - } - } - } - - workerMessageReceived (type: string, message: any) { - if (type === 'sectionFinished') { - const { key } = message - if (!this.sectionFinishedToReceive) { - console.warn(`received sectionFinished message but no sectionFinishedToReceive ${key}`) - return - } - - const idx = this.sectionFinishedToReceive.messagesLeft.indexOf(key) - if (idx === -1) { - console.warn(`received sectionFinished message for non-outstanding section ${key}`) - return - } - this.sectionFinishedToReceive.messagesLeft.splice(idx, 1) - if (this.sectionFinishedToReceive.messagesLeft.length === 0) { - this.sectionFinishedToReceive.resolve() - } - } - } - - parseMesherLog () { - const lines = log.split('\n') - for (const line of lines) { - if (line.startsWith('-> chunk')) { - const chunk = JSON.parse(line.slice('-> chunk'.length)) - this.chunksToReceive.push(chunk) - continue - } - } - } -} diff --git a/renderer/viewer/lib/moreBlockDataGenerated.json b/renderer/viewer/lib/moreBlockDataGenerated.json deleted file mode 100644 index 55c6f1f46..000000000 --- a/renderer/viewer/lib/moreBlockDataGenerated.json +++ /dev/null @@ -1,722 +0,0 @@ -{ - "lightLevels": { - "lava": 15, - "brown_mushroom": 1, - "torch": 14, - "wall_torch": 14, - "fire": 15, - "soul_fire": 10, - "soul_torch": 10, - "soul_wall_torch": 10, - "glowstone": 15, - "nether_portal": 11, - "jack_o_lantern": 15, - "enchanting_table": 7, - "brewing_stand": 1, - "lava_cauldron": 15, - "end_portal": 15, - "end_portal_frame": 1, - "dragon_egg": 1, - "ender_chest": 7, - "beacon": 15, - "sea_lantern": 15, - "end_rod": 14, - "end_gateway": 15, - "magma_block": 3, - "conduit": 15, - "lantern": 15, - "soul_lantern": 10, - "shroomlight": 15, - "crying_obsidian": 10, - "amethyst_cluster": 5, - "large_amethyst_bud": 4, - "medium_amethyst_bud": 2, - "small_amethyst_bud": 1, - "sculk_sensor": 1, - "sculk_catalyst": 6, - "ochre_froglight": 15, - "verdant_froglight": 15, - "pearlescent_froglight": 15 - }, - "noOcclusions": { - "mangrove_roots": true, - "oak_leaves": true, - "spruce_leaves": true, - "birch_leaves": true, - "jungle_leaves": true, - "acacia_leaves": true, - "cherry_leaves": true, - "dark_oak_leaves": true, - "mangrove_leaves": true, - "azalea_leaves": true, - "flowering_azalea_leaves": true, - "glass": true, - "white_bed": true, - "orange_bed": true, - "magenta_bed": true, - "light_blue_bed": true, - "yellow_bed": true, - "lime_bed": true, - "pink_bed": true, - "gray_bed": true, - "light_gray_bed": true, - "cyan_bed": true, - "purple_bed": true, - "blue_bed": true, - "brown_bed": true, - "green_bed": true, - "red_bed": true, - "black_bed": true, - "moving_piston": true, - "spawner": true, - "oak_door": true, - "ladder": true, - "iron_door": true, - "ice": true, - "white_stained_glass": true, - "orange_stained_glass": true, - "magenta_stained_glass": true, - "light_blue_stained_glass": true, - "yellow_stained_glass": true, - "lime_stained_glass": true, - "pink_stained_glass": true, - "gray_stained_glass": true, - "light_gray_stained_glass": true, - "cyan_stained_glass": true, - "purple_stained_glass": true, - "blue_stained_glass": true, - "brown_stained_glass": true, - "green_stained_glass": true, - "red_stained_glass": true, - "black_stained_glass": true, - "oak_trapdoor": true, - "spruce_trapdoor": true, - "birch_trapdoor": true, - "jungle_trapdoor": true, - "acacia_trapdoor": true, - "cherry_trapdoor": true, - "dark_oak_trapdoor": true, - "mangrove_trapdoor": true, - "bamboo_trapdoor": true, - "iron_bars": true, - "chain": true, - "glass_pane": true, - "lily_pad": true, - "brewing_stand": true, - "cauldron": true, - "dragon_egg": true, - "cocoa": true, - "beacon": true, - "hopper": true, - "white_stained_glass_pane": true, - "orange_stained_glass_pane": true, - "magenta_stained_glass_pane": true, - "light_blue_stained_glass_pane": true, - "yellow_stained_glass_pane": true, - "lime_stained_glass_pane": true, - "pink_stained_glass_pane": true, - "gray_stained_glass_pane": true, - "light_gray_stained_glass_pane": true, - "cyan_stained_glass_pane": true, - "purple_stained_glass_pane": true, - "blue_stained_glass_pane": true, - "brown_stained_glass_pane": true, - "green_stained_glass_pane": true, - "red_stained_glass_pane": true, - "black_stained_glass_pane": true, - "slime_block": true, - "barrier": true, - "light": true, - "iron_trapdoor": true, - "spruce_door": true, - "birch_door": true, - "jungle_door": true, - "acacia_door": true, - "cherry_door": true, - "dark_oak_door": true, - "mangrove_door": true, - "bamboo_door": true, - "end_rod": true, - "chorus_plant": true, - "chorus_flower": true, - "frosted_ice": true, - "turtle_egg": true, - "sniffer_egg": true, - "sea_pickle": true, - "conduit": true, - "bamboo": true, - "lantern": true, - "soul_lantern": true, - "campfire": true, - "soul_campfire": true, - "crimson_trapdoor": true, - "warped_trapdoor": true, - "crimson_door": true, - "warped_door": true, - "honey_block": true, - "candle": true, - "white_candle": true, - "orange_candle": true, - "magenta_candle": true, - "light_blue_candle": true, - "yellow_candle": true, - "lime_candle": true, - "pink_candle": true, - "gray_candle": true, - "light_gray_candle": true, - "cyan_candle": true, - "purple_candle": true, - "blue_candle": true, - "brown_candle": true, - "green_candle": true, - "red_candle": true, - "black_candle": true, - "amethyst_cluster": true, - "tinted_glass": true, - "lightning_rod": true, - "pointed_dripstone": true, - "azalea": true, - "flowering_azalea": true, - "frogspawn": true, - "decorated_pot": true - }, - "colors": { - "stone": "rgb(112, 112, 112)", - "granite": "rgb(151, 109, 77)", - "polished_granite": "rgb(151, 109, 77)", - "diorite": "rgb(255, 252, 245)", - "polished_diorite": "rgb(255, 252, 245)", - "andesite": "rgb(112, 112, 112)", - "polished_andesite": "rgb(112, 112, 112)", - "grass_block": "rgb(127, 178, 56)", - "dirt": "rgb(151, 109, 77)", - "coarse_dirt": "rgb(151, 109, 77)", - "podzol": "rgb(129, 86, 49)", - "cobblestone": "rgb(112, 112, 112)", - "oak_planks": "rgb(143, 119, 72)", - "spruce_planks": "rgb(129, 86, 49)", - "birch_planks": "rgb(247, 233, 163)", - "jungle_planks": "rgb(151, 109, 77)", - "acacia_planks": "rgb(216, 127, 51)", - "cherry_planks": "rgb(209, 177, 161)", - "dark_oak_planks": "rgb(102, 76, 51)", - "mangrove_planks": "rgb(153, 51, 51)", - "bamboo_planks": "rgb(229, 229, 51)", - "bamboo_mosaic": "rgb(229, 229, 51)", - "oak_sapling": "rgb(0, 124, 0)", - "spruce_sapling": "rgb(0, 124, 0)", - "birch_sapling": "rgb(0, 124, 0)", - "jungle_sapling": "rgb(0, 124, 0)", - "acacia_sapling": "rgb(0, 124, 0)", - "cherry_sapling": "rgb(242, 127, 165)", - "dark_oak_sapling": "rgb(0, 124, 0)", - "mangrove_propagule": "rgb(0, 124, 0)", - "bedrock": "rgb(112, 112, 112)", - "water": "rgb(64, 64, 255)", - "lava": "rgb(255, 0, 0)", - "sand": "rgb(247, 233, 163)", - "suspicious_sand": "rgb(247, 233, 163)", - "red_sand": "rgb(216, 127, 51)", - "gravel": "rgb(112, 112, 112)", - "suspicious_gravel": "rgb(112, 112, 112)", - "gold_ore": "rgb(112, 112, 112)", - "deepslate_gold_ore": "rgb(100, 100, 100)", - "iron_ore": "rgb(112, 112, 112)", - "deepslate_iron_ore": "rgb(100, 100, 100)", - "coal_ore": "rgb(112, 112, 112)", - "deepslate_coal_ore": "rgb(100, 100, 100)", - "nether_gold_ore": "rgb(112, 2, 0)", - "mangrove_roots": "rgb(129, 86, 49)", - "muddy_mangrove_roots": "rgb(129, 86, 49)", - "oak_wood": "rgb(143, 119, 72)", - "spruce_wood": "rgb(129, 86, 49)", - "birch_wood": "rgb(247, 233, 163)", - "jungle_wood": "rgb(151, 109, 77)", - "acacia_wood": "rgb(76, 76, 76)", - "cherry_wood": "rgb(57, 41, 35)", - "dark_oak_wood": "rgb(102, 76, 51)", - "mangrove_wood": "rgb(153, 51, 51)", - "stripped_oak_wood": "rgb(143, 119, 72)", - "stripped_spruce_wood": "rgb(129, 86, 49)", - "stripped_birch_wood": "rgb(247, 233, 163)", - "stripped_jungle_wood": "rgb(151, 109, 77)", - "stripped_acacia_wood": "rgb(216, 127, 51)", - "stripped_cherry_wood": "rgb(160, 77, 78)", - "stripped_dark_oak_wood": "rgb(102, 76, 51)", - "oak_leaves": "rgb(0, 124, 0)", - "spruce_leaves": "rgb(0, 124, 0)", - "birch_leaves": "rgb(0, 124, 0)", - "jungle_leaves": "rgb(0, 124, 0)", - "acacia_leaves": "rgb(0, 124, 0)", - "cherry_leaves": "rgb(242, 127, 165)", - "dark_oak_leaves": "rgb(0, 124, 0)", - "mangrove_leaves": "rgb(0, 124, 0)", - "azalea_leaves": "rgb(0, 124, 0)", - "flowering_azalea_leaves": "rgb(0, 124, 0)", - "sponge": "rgb(229, 229, 51)", - "wet_sponge": "rgb(229, 229, 51)", - "lapis_ore": "rgb(112, 112, 112)", - "deepslate_lapis_ore": "rgb(100, 100, 100)", - "lapis_block": "rgb(74, 128, 255)", - "dispenser": "rgb(112, 112, 112)", - "sandstone": "rgb(247, 233, 163)", - "chiseled_sandstone": "rgb(247, 233, 163)", - "cut_sandstone": "rgb(247, 233, 163)", - "note_block": "rgb(143, 119, 72)", - "sticky_piston": "rgb(112, 112, 112)", - "cobweb": "rgb(199, 199, 199)", - "grass": "rgb(0, 124, 0)", - "fern": "rgb(0, 124, 0)", - "dead_bush": "rgb(143, 119, 72)", - "seagrass": "rgb(64, 64, 255)", - "tall_seagrass": "rgb(64, 64, 255)", - "piston": "rgb(112, 112, 112)", - "piston_head": "rgb(112, 112, 112)", - "white_wool": "rgb(255, 255, 255)", - "orange_wool": "rgb(216, 127, 51)", - "magenta_wool": "rgb(178, 76, 216)", - "light_blue_wool": "rgb(102, 153, 216)", - "yellow_wool": "rgb(229, 229, 51)", - "lime_wool": "rgb(127, 204, 25)", - "pink_wool": "rgb(242, 127, 165)", - "gray_wool": "rgb(76, 76, 76)", - "light_gray_wool": "rgb(153, 153, 153)", - "cyan_wool": "rgb(76, 127, 153)", - "purple_wool": "rgb(127, 63, 178)", - "blue_wool": "rgb(51, 76, 178)", - "brown_wool": "rgb(102, 76, 51)", - "green_wool": "rgb(102, 127, 51)", - "red_wool": "rgb(153, 51, 51)", - "black_wool": "rgb(25, 25, 25)", - "moving_piston": "rgb(112, 112, 112)", - "dandelion": "rgb(0, 124, 0)", - "torchflower": "rgb(0, 124, 0)", - "poppy": "rgb(0, 124, 0)", - "blue_orchid": "rgb(0, 124, 0)", - "allium": "rgb(0, 124, 0)", - "azure_bluet": "rgb(0, 124, 0)", - "red_tulip": "rgb(0, 124, 0)", - "orange_tulip": "rgb(0, 124, 0)", - "white_tulip": "rgb(0, 124, 0)", - "pink_tulip": "rgb(0, 124, 0)", - "oxeye_daisy": "rgb(0, 124, 0)", - "cornflower": "rgb(0, 124, 0)", - "wither_rose": "rgb(0, 124, 0)", - "lily_of_the_valley": "rgb(0, 124, 0)", - "brown_mushroom": "rgb(102, 76, 51)", - "red_mushroom": "rgb(153, 51, 51)", - "gold_block": "rgb(250, 238, 77)", - "iron_block": "rgb(167, 167, 167)", - "bricks": "rgb(153, 51, 51)", - "tnt": "rgb(255, 0, 0)", - "bookshelf": "rgb(143, 119, 72)", - "chiseled_bookshelf": "rgb(143, 119, 72)", - "mossy_cobblestone": "rgb(112, 112, 112)", - "obsidian": "rgb(25, 25, 25)", - "fire": "rgb(255, 0, 0)", - "soul_fire": "rgb(102, 153, 216)", - "spawner": "rgb(112, 112, 112)", - "chest": "rgb(143, 119, 72)", - "diamond_ore": "rgb(112, 112, 112)", - "deepslate_diamond_ore": "rgb(100, 100, 100)", - "diamond_block": "rgb(92, 219, 213)", - "crafting_table": "rgb(143, 119, 72)", - "wheat": "rgb(0, 124, 0)", - "farmland": "rgb(151, 109, 77)", - "furnace": "rgb(112, 112, 112)", - "oak_sign": "rgb(143, 119, 72)", - "birch_sign": "rgb(247, 233, 163)", - "acacia_sign": "rgb(216, 127, 51)", - "oak_wall_sign": "rgb(143, 119, 72)", - "birch_wall_sign": "rgb(247, 233, 163)", - "acacia_wall_sign": "rgb(216, 127, 51)", - "birch_hanging_sign": "rgb(247, 233, 163)", - "acacia_hanging_sign": "rgb(216, 127, 51)", - "cherry_hanging_sign": "rgb(160, 77, 78)", - "crimson_hanging_sign": "rgb(148, 63, 97)", - "warped_hanging_sign": "rgb(58, 142, 140)", - "bamboo_hanging_sign": "rgb(229, 229, 51)", - "spruce_wall_hanging_sign": "rgb(143, 119, 72)", - "birch_wall_hanging_sign": "rgb(247, 233, 163)", - "acacia_wall_hanging_sign": "rgb(216, 127, 51)", - "cherry_wall_hanging_sign": "rgb(160, 77, 78)", - "crimson_wall_hanging_sign": "rgb(148, 63, 97)", - "warped_wall_hanging_sign": "rgb(58, 142, 140)", - "bamboo_wall_hanging_sign": "rgb(229, 229, 51)", - "stone_pressure_plate": "rgb(112, 112, 112)", - "iron_door": "rgb(167, 167, 167)", - "redstone_ore": "rgb(112, 112, 112)", - "deepslate_redstone_ore": "rgb(100, 100, 100)", - "snow": "rgb(255, 255, 255)", - "ice": "rgb(160, 160, 255)", - "snow_block": "rgb(255, 255, 255)", - "cactus": "rgb(0, 124, 0)", - "clay": "rgb(164, 168, 184)", - "sugar_cane": "rgb(0, 124, 0)", - "jukebox": "rgb(151, 109, 77)", - "pumpkin": "rgb(216, 127, 51)", - "netherrack": "rgb(112, 2, 0)", - "soul_sand": "rgb(102, 76, 51)", - "soul_soil": "rgb(102, 76, 51)", - "basalt": "rgb(25, 25, 25)", - "polished_basalt": "rgb(25, 25, 25)", - "glowstone": "rgb(247, 233, 163)", - "carved_pumpkin": "rgb(216, 127, 51)", - "jack_o_lantern": "rgb(216, 127, 51)", - "oak_trapdoor": "rgb(143, 119, 72)", - "spruce_trapdoor": "rgb(129, 86, 49)", - "birch_trapdoor": "rgb(247, 233, 163)", - "jungle_trapdoor": "rgb(151, 109, 77)", - "acacia_trapdoor": "rgb(216, 127, 51)", - "cherry_trapdoor": "rgb(209, 177, 161)", - "dark_oak_trapdoor": "rgb(102, 76, 51)", - "mangrove_trapdoor": "rgb(153, 51, 51)", - "bamboo_trapdoor": "rgb(229, 229, 51)", - "stone_bricks": "rgb(112, 112, 112)", - "mossy_stone_bricks": "rgb(112, 112, 112)", - "cracked_stone_bricks": "rgb(112, 112, 112)", - "chiseled_stone_bricks": "rgb(112, 112, 112)", - "mud_bricks": "rgb(135, 107, 98)", - "infested_stone": "rgb(164, 168, 184)", - "infested_cobblestone": "rgb(164, 168, 184)", - "infested_stone_bricks": "rgb(164, 168, 184)", - "infested_mossy_stone_bricks": "rgb(164, 168, 184)", - "infested_cracked_stone_bricks": "rgb(164, 168, 184)", - "infested_chiseled_stone_bricks": "rgb(164, 168, 184)", - "brown_mushroom_block": "rgb(151, 109, 77)", - "red_mushroom_block": "rgb(153, 51, 51)", - "mushroom_stem": "rgb(199, 199, 199)", - "melon": "rgb(127, 204, 25)", - "attached_pumpkin_stem": "rgb(0, 124, 0)", - "attached_melon_stem": "rgb(0, 124, 0)", - "pumpkin_stem": "rgb(0, 124, 0)", - "melon_stem": "rgb(0, 124, 0)", - "vine": "rgb(0, 124, 0)", - "glow_lichen": "rgb(127, 167, 150)", - "mycelium": "rgb(127, 63, 178)", - "lily_pad": "rgb(0, 124, 0)", - "nether_bricks": "rgb(112, 2, 0)", - "nether_brick_fence": "rgb(112, 2, 0)", - "nether_wart": "rgb(153, 51, 51)", - "enchanting_table": "rgb(153, 51, 51)", - "brewing_stand": "rgb(167, 167, 167)", - "cauldron": "rgb(112, 112, 112)", - "end_portal": "rgb(25, 25, 25)", - "end_portal_frame": "rgb(102, 127, 51)", - "end_stone": "rgb(247, 233, 163)", - "dragon_egg": "rgb(25, 25, 25)", - "cocoa": "rgb(0, 124, 0)", - "emerald_ore": "rgb(112, 112, 112)", - "deepslate_emerald_ore": "rgb(100, 100, 100)", - "ender_chest": "rgb(112, 112, 112)", - "emerald_block": "rgb(0, 217, 58)", - "command_block": "rgb(102, 76, 51)", - "beacon": "rgb(92, 219, 213)", - "carrots": "rgb(0, 124, 0)", - "potatoes": "rgb(0, 124, 0)", - "anvil": "rgb(167, 167, 167)", - "chipped_anvil": "rgb(167, 167, 167)", - "damaged_anvil": "rgb(167, 167, 167)", - "trapped_chest": "rgb(143, 119, 72)", - "light_weighted_pressure_plate": "rgb(250, 238, 77)", - "heavy_weighted_pressure_plate": "rgb(167, 167, 167)", - "daylight_detector": "rgb(143, 119, 72)", - "redstone_block": "rgb(255, 0, 0)", - "nether_quartz_ore": "rgb(112, 2, 0)", - "hopper": "rgb(112, 112, 112)", - "quartz_block": "rgb(255, 252, 245)", - "chiseled_quartz_block": "rgb(255, 252, 245)", - "quartz_pillar": "rgb(255, 252, 245)", - "dropper": "rgb(112, 112, 112)", - "white_terracotta": "rgb(209, 177, 161)", - "orange_terracotta": "rgb(159, 82, 36)", - "magenta_terracotta": "rgb(149, 87, 108)", - "light_blue_terracotta": "rgb(112, 108, 138)", - "yellow_terracotta": "rgb(186, 133, 36)", - "lime_terracotta": "rgb(103, 117, 53)", - "pink_terracotta": "rgb(160, 77, 78)", - "gray_terracotta": "rgb(57, 41, 35)", - "light_gray_terracotta": "rgb(135, 107, 98)", - "cyan_terracotta": "rgb(87, 92, 92)", - "purple_terracotta": "rgb(122, 73, 88)", - "blue_terracotta": "rgb(76, 62, 92)", - "brown_terracotta": "rgb(76, 50, 35)", - "green_terracotta": "rgb(76, 82, 42)", - "red_terracotta": "rgb(142, 60, 46)", - "black_terracotta": "rgb(37, 22, 16)", - "slime_block": "rgb(127, 178, 56)", - "iron_trapdoor": "rgb(167, 167, 167)", - "prismarine": "rgb(76, 127, 153)", - "prismarine_bricks": "rgb(92, 219, 213)", - "dark_prismarine": "rgb(92, 219, 213)", - "prismarine_slab": "rgb(76, 127, 153)", - "prismarine_brick_slab": "rgb(92, 219, 213)", - "dark_prismarine_slab": "rgb(92, 219, 213)", - "sea_lantern": "rgb(255, 252, 245)", - "hay_block": "rgb(229, 229, 51)", - "white_carpet": "rgb(255, 255, 255)", - "orange_carpet": "rgb(216, 127, 51)", - "magenta_carpet": "rgb(178, 76, 216)", - "light_blue_carpet": "rgb(102, 153, 216)", - "yellow_carpet": "rgb(229, 229, 51)", - "lime_carpet": "rgb(127, 204, 25)", - "pink_carpet": "rgb(242, 127, 165)", - "gray_carpet": "rgb(76, 76, 76)", - "light_gray_carpet": "rgb(153, 153, 153)", - "cyan_carpet": "rgb(76, 127, 153)", - "purple_carpet": "rgb(127, 63, 178)", - "blue_carpet": "rgb(51, 76, 178)", - "brown_carpet": "rgb(102, 76, 51)", - "green_carpet": "rgb(102, 127, 51)", - "red_carpet": "rgb(153, 51, 51)", - "black_carpet": "rgb(25, 25, 25)", - "terracotta": "rgb(216, 127, 51)", - "coal_block": "rgb(25, 25, 25)", - "packed_ice": "rgb(160, 160, 255)", - "sunflower": "rgb(0, 124, 0)", - "lilac": "rgb(0, 124, 0)", - "rose_bush": "rgb(0, 124, 0)", - "peony": "rgb(0, 124, 0)", - "tall_grass": "rgb(0, 124, 0)", - "large_fern": "rgb(0, 124, 0)", - "white_banner": "rgb(143, 119, 72)", - "orange_banner": "rgb(143, 119, 72)", - "magenta_banner": "rgb(143, 119, 72)", - "light_blue_banner": "rgb(143, 119, 72)", - "yellow_banner": "rgb(143, 119, 72)", - "lime_banner": "rgb(143, 119, 72)", - "pink_banner": "rgb(143, 119, 72)", - "gray_banner": "rgb(143, 119, 72)", - "light_gray_banner": "rgb(143, 119, 72)", - "cyan_banner": "rgb(143, 119, 72)", - "purple_banner": "rgb(143, 119, 72)", - "blue_banner": "rgb(143, 119, 72)", - "brown_banner": "rgb(143, 119, 72)", - "green_banner": "rgb(143, 119, 72)", - "red_banner": "rgb(143, 119, 72)", - "black_banner": "rgb(143, 119, 72)", - "white_wall_banner": "rgb(143, 119, 72)", - "orange_wall_banner": "rgb(143, 119, 72)", - "magenta_wall_banner": "rgb(143, 119, 72)", - "light_blue_wall_banner": "rgb(143, 119, 72)", - "yellow_wall_banner": "rgb(143, 119, 72)", - "lime_wall_banner": "rgb(143, 119, 72)", - "pink_wall_banner": "rgb(143, 119, 72)", - "gray_wall_banner": "rgb(143, 119, 72)", - "light_gray_wall_banner": "rgb(143, 119, 72)", - "cyan_wall_banner": "rgb(143, 119, 72)", - "purple_wall_banner": "rgb(143, 119, 72)", - "blue_wall_banner": "rgb(143, 119, 72)", - "brown_wall_banner": "rgb(143, 119, 72)", - "green_wall_banner": "rgb(143, 119, 72)", - "red_wall_banner": "rgb(143, 119, 72)", - "black_wall_banner": "rgb(143, 119, 72)", - "red_sandstone": "rgb(216, 127, 51)", - "chiseled_red_sandstone": "rgb(216, 127, 51)", - "cut_red_sandstone": "rgb(216, 127, 51)", - "oak_slab": "rgb(143, 119, 72)", - "spruce_slab": "rgb(129, 86, 49)", - "birch_slab": "rgb(247, 233, 163)", - "jungle_slab": "rgb(151, 109, 77)", - "acacia_slab": "rgb(216, 127, 51)", - "cherry_slab": "rgb(209, 177, 161)", - "dark_oak_slab": "rgb(102, 76, 51)", - "mangrove_slab": "rgb(153, 51, 51)", - "bamboo_slab": "rgb(229, 229, 51)", - "bamboo_mosaic_slab": "rgb(229, 229, 51)", - "stone_slab": "rgb(112, 112, 112)", - "smooth_stone_slab": "rgb(112, 112, 112)", - "sandstone_slab": "rgb(247, 233, 163)", - "cut_sandstone_slab": "rgb(247, 233, 163)", - "petrified_oak_slab": "rgb(143, 119, 72)", - "cobblestone_slab": "rgb(112, 112, 112)", - "brick_slab": "rgb(153, 51, 51)", - "stone_brick_slab": "rgb(112, 112, 112)", - "mud_brick_slab": "rgb(135, 107, 98)", - "nether_brick_slab": "rgb(112, 2, 0)", - "quartz_slab": "rgb(255, 252, 245)", - "red_sandstone_slab": "rgb(216, 127, 51)", - "cut_red_sandstone_slab": "rgb(216, 127, 51)", - "purpur_slab": "rgb(178, 76, 216)", - "smooth_stone": "rgb(112, 112, 112)", - "smooth_sandstone": "rgb(247, 233, 163)", - "smooth_quartz": "rgb(255, 252, 245)", - "smooth_red_sandstone": "rgb(216, 127, 51)", - "chorus_plant": "rgb(127, 63, 178)", - "chorus_flower": "rgb(127, 63, 178)", - "purpur_block": "rgb(178, 76, 216)", - "purpur_pillar": "rgb(178, 76, 216)", - "end_stone_bricks": "rgb(247, 233, 163)", - "torchflower_crop": "rgb(0, 124, 0)", - "pitcher_crop": "rgb(0, 124, 0)", - "pitcher_plant": "rgb(0, 124, 0)", - "beetroots": "rgb(0, 124, 0)", - "dirt_path": "rgb(151, 109, 77)", - "end_gateway": "rgb(25, 25, 25)", - "repeating_command_block": "rgb(127, 63, 178)", - "chain_command_block": "rgb(102, 127, 51)", - "frosted_ice": "rgb(160, 160, 255)", - "magma_block": "rgb(112, 2, 0)", - "nether_wart_block": "rgb(153, 51, 51)", - "red_nether_bricks": "rgb(112, 2, 0)", - "bone_block": "rgb(247, 233, 163)", - "observer": "rgb(112, 112, 112)", - "kelp": "rgb(64, 64, 255)", - "kelp_plant": "rgb(64, 64, 255)", - "dried_kelp_block": "rgb(102, 127, 51)", - "turtle_egg": "rgb(247, 233, 163)", - "sniffer_egg": "rgb(153, 51, 51)", - "dead_tube_coral_block": "rgb(76, 76, 76)", - "dead_brain_coral_block": "rgb(76, 76, 76)", - "dead_bubble_coral_block": "rgb(76, 76, 76)", - "dead_fire_coral_block": "rgb(76, 76, 76)", - "dead_horn_coral_block": "rgb(76, 76, 76)", - "tube_coral_block": "rgb(51, 76, 178)", - "brain_coral_block": "rgb(242, 127, 165)", - "bubble_coral_block": "rgb(127, 63, 178)", - "fire_coral_block": "rgb(153, 51, 51)", - "horn_coral_block": "rgb(229, 229, 51)", - "dead_tube_coral": "rgb(76, 76, 76)", - "dead_brain_coral": "rgb(76, 76, 76)", - "dead_bubble_coral": "rgb(76, 76, 76)", - "dead_fire_coral": "rgb(76, 76, 76)", - "dead_horn_coral": "rgb(76, 76, 76)", - "tube_coral": "rgb(51, 76, 178)", - "brain_coral": "rgb(242, 127, 165)", - "bubble_coral": "rgb(127, 63, 178)", - "fire_coral": "rgb(153, 51, 51)", - "horn_coral": "rgb(229, 229, 51)", - "dead_tube_coral_fan": "rgb(76, 76, 76)", - "dead_brain_coral_fan": "rgb(76, 76, 76)", - "dead_bubble_coral_fan": "rgb(76, 76, 76)", - "dead_fire_coral_fan": "rgb(76, 76, 76)", - "dead_horn_coral_fan": "rgb(76, 76, 76)", - "tube_coral_fan": "rgb(51, 76, 178)", - "brain_coral_fan": "rgb(242, 127, 165)", - "bubble_coral_fan": "rgb(127, 63, 178)", - "fire_coral_fan": "rgb(153, 51, 51)", - "horn_coral_fan": "rgb(229, 229, 51)", - "dead_tube_coral_wall_fan": "rgb(76, 76, 76)", - "dead_brain_coral_wall_fan": "rgb(76, 76, 76)", - "dead_bubble_coral_wall_fan": "rgb(76, 76, 76)", - "dead_fire_coral_wall_fan": "rgb(76, 76, 76)", - "dead_horn_coral_wall_fan": "rgb(76, 76, 76)", - "tube_coral_wall_fan": "rgb(51, 76, 178)", - "brain_coral_wall_fan": "rgb(242, 127, 165)", - "bubble_coral_wall_fan": "rgb(127, 63, 178)", - "fire_coral_wall_fan": "rgb(153, 51, 51)", - "horn_coral_wall_fan": "rgb(229, 229, 51)", - "sea_pickle": "rgb(102, 127, 51)", - "blue_ice": "rgb(160, 160, 255)", - "conduit": "rgb(92, 219, 213)", - "bamboo_sapling": "rgb(143, 119, 72)", - "bamboo": "rgb(0, 124, 0)", - "bubble_column": "rgb(64, 64, 255)", - "scaffolding": "rgb(247, 233, 163)", - "loom": "rgb(143, 119, 72)", - "barrel": "rgb(143, 119, 72)", - "smoker": "rgb(112, 112, 112)", - "blast_furnace": "rgb(112, 112, 112)", - "cartography_table": "rgb(143, 119, 72)", - "fletching_table": "rgb(143, 119, 72)", - "grindstone": "rgb(167, 167, 167)", - "lectern": "rgb(143, 119, 72)", - "smithing_table": "rgb(143, 119, 72)", - "stonecutter": "rgb(112, 112, 112)", - "bell": "rgb(250, 238, 77)", - "lantern": "rgb(167, 167, 167)", - "soul_lantern": "rgb(167, 167, 167)", - "campfire": "rgb(129, 86, 49)", - "soul_campfire": "rgb(129, 86, 49)", - "sweet_berry_bush": "rgb(0, 124, 0)", - "warped_hyphae": "rgb(86, 44, 62)", - "stripped_warped_hyphae": "rgb(86, 44, 62)", - "warped_nylium": "rgb(22, 126, 134)", - "warped_fungus": "rgb(76, 127, 153)", - "warped_wart_block": "rgb(20, 180, 133)", - "warped_roots": "rgb(76, 127, 153)", - "nether_sprouts": "rgb(76, 127, 153)", - "crimson_hyphae": "rgb(92, 25, 29)", - "stripped_crimson_hyphae": "rgb(92, 25, 29)", - "crimson_nylium": "rgb(189, 48, 49)", - "crimson_fungus": "rgb(112, 2, 0)", - "shroomlight": "rgb(153, 51, 51)", - "weeping_vines": "rgb(112, 2, 0)", - "weeping_vines_plant": "rgb(112, 2, 0)", - "twisting_vines": "rgb(76, 127, 153)", - "twisting_vines_plant": "rgb(76, 127, 153)", - "crimson_roots": "rgb(112, 2, 0)", - "crimson_planks": "rgb(148, 63, 97)", - "warped_planks": "rgb(58, 142, 140)", - "structure_block": "rgb(153, 153, 153)", - "jigsaw": "rgb(153, 153, 153)", - "composter": "rgb(143, 119, 72)", - "target": "rgb(255, 252, 245)", - "bee_nest": "rgb(229, 229, 51)", - "beehive": "rgb(143, 119, 72)", - "honey_block": "rgb(216, 127, 51)", - "honeycomb_block": "rgb(216, 127, 51)", - "netherite_block": "rgb(25, 25, 25)", - "ancient_debris": "rgb(25, 25, 25)", - "crying_obsidian": "rgb(25, 25, 25)", - "respawn_anchor": "rgb(25, 25, 25)", - "lodestone": "rgb(167, 167, 167)", - "blackstone": "rgb(25, 25, 25)", - "polished_blackstone_pressure_plate": "rgb(25, 25, 25)", - "chiseled_nether_bricks": "rgb(112, 2, 0)", - "cracked_nether_bricks": "rgb(112, 2, 0)", - "amethyst_block": "rgb(127, 63, 178)", - "budding_amethyst": "rgb(127, 63, 178)", - "amethyst_cluster": "rgb(127, 63, 178)", - "tuff": "rgb(57, 41, 35)", - "calcite": "rgb(209, 177, 161)", - "tinted_glass": "rgb(76, 76, 76)", - "powder_snow": "rgb(255, 255, 255)", - "sculk_sensor": "rgb(76, 127, 153)", - "sculk": "rgb(25, 25, 25)", - "sculk_vein": "rgb(25, 25, 25)", - "sculk_catalyst": "rgb(25, 25, 25)", - "sculk_shrieker": "rgb(25, 25, 25)", - "oxidized_copper": "rgb(22, 126, 134)", - "weathered_copper": "rgb(58, 142, 140)", - "exposed_copper": "rgb(135, 107, 98)", - "copper_block": "rgb(216, 127, 51)", - "deepslate_copper_ore": "rgb(100, 100, 100)", - "lightning_rod": "rgb(216, 127, 51)", - "pointed_dripstone": "rgb(76, 50, 35)", - "dripstone_block": "rgb(76, 50, 35)", - "cave_vines": "rgb(0, 124, 0)", - "cave_vines_plant": "rgb(0, 124, 0)", - "spore_blossom": "rgb(0, 124, 0)", - "azalea": "rgb(0, 124, 0)", - "flowering_azalea": "rgb(0, 124, 0)", - "moss_carpet": "rgb(102, 127, 51)", - "pink_petals": "rgb(0, 124, 0)", - "moss_block": "rgb(102, 127, 51)", - "big_dripleaf": "rgb(0, 124, 0)", - "big_dripleaf_stem": "rgb(0, 124, 0)", - "small_dripleaf": "rgb(0, 124, 0)", - "hanging_roots": "rgb(151, 109, 77)", - "rooted_dirt": "rgb(151, 109, 77)", - "mud": "rgb(87, 92, 92)", - "deepslate": "rgb(100, 100, 100)", - "infested_deepslate": "rgb(100, 100, 100)", - "raw_iron_block": "rgb(216, 175, 147)", - "raw_copper_block": "rgb(216, 127, 51)", - "raw_gold_block": "rgb(250, 238, 77)", - "ochre_froglight": "rgb(247, 233, 163)", - "verdant_froglight": "rgb(127, 167, 150)", - "pearlescent_froglight": "rgb(242, 127, 165)", - "frogspawn": "rgb(64, 64, 255)", - "reinforced_deepslate": "rgb(100, 100, 100)", - "decorated_pot": "rgb(142, 60, 46)" - }, - "hasSemiTransparentTextuersRegex": { - "_stained_glass$": true, - "_stained_glass_pane$": true, - "^ice$": true, - "^tinted_glass$": true, - "^slime_block$": true, - "^honey_block$": true - } -} diff --git a/renderer/viewer/lib/simpleUtils.ts b/renderer/viewer/lib/simpleUtils.ts deleted file mode 100644 index 2d0b62554..000000000 --- a/renderer/viewer/lib/simpleUtils.ts +++ /dev/null @@ -1,35 +0,0 @@ -export async function getBufferFromStream (stream) { - return new Promise((resolve, reject) => { - let buffer = Buffer.from([]) - stream.on('data', buf => { - buffer = Buffer.concat([buffer, buf]) - }) - stream.on('end', () => resolve(buffer)) - stream.on('error', reject) - }) -} - -export function openURL (url, newTab = true) { - if (newTab) { - window.open(url, '_blank', 'noopener,noreferrer') - } else { - window.open(url, '_self') - } -} - -export const isMobile = () => { - return window.matchMedia('(pointer: coarse)').matches || navigator.userAgent.includes('Mobile') -} - -export function chunkPos (pos: { x: number, z: number }) { - const x = Math.floor(pos.x / 16) - const z = Math.floor(pos.z / 16) - return [x, z] -} - -export function sectionPos (pos: { x: number, y: number, z: number }) { - const x = Math.floor(pos.x / 16) - const y = Math.floor(pos.y / 16) - const z = Math.floor(pos.z / 16) - return [x, y, z] -} diff --git a/renderer/viewer/lib/skyLight.ts b/renderer/viewer/lib/skyLight.ts deleted file mode 100644 index 01baaf910..000000000 --- a/renderer/viewer/lib/skyLight.ts +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Calculates sky light level based on Minecraft time of day. - * - * Minecraft time reference: - * - 0 ticks = 6:00 AM (sunrise complete) - * - 6000 ticks = 12:00 PM (noon) - brightest - * - 12000 ticks = 6:00 PM (sunset begins) - * - 13000 ticks = 7:00 PM (dusk/night begins) - * - 18000 ticks = 12:00 AM (midnight) - darkest - * - 23000 ticks = 5:00 AM (dawn begins) - * - 24000 ticks = 6:00 AM (same as 0) - * - * Sky light ranges from 4 (night) to 15 (day). - */ - -/** - * Calculate celestial angle from time of day (0-1 range representing sun position) - */ -export const getCelestialAngle = (timeOfDay: number): number => { - // Normalize time to 0-1 range - let angle = ((timeOfDay % 24_000) / 24_000) - 0.25 - - if (angle < 0) angle += 1 - if (angle > 1) angle -= 1 - - // Vanilla Minecraft applies a smoothing curve - const smoothedAngle = angle + (1 - Math.cos(angle * Math.PI)) / 2 - return smoothedAngle -} - -/** - * Calculate sky light level (0-15) based on time of day in ticks. - * Matches Minecraft vanilla behavior. - * - * @param timeOfDay - Time in ticks (0-24000) - * @returns Sky light level (4-15, where 15 is brightest day, 4 is darkest night) - */ -export const calculateSkyLight = (timeOfDay: number): number => { - // Normalize time to 0-24000 range - const normalizedTime = ((timeOfDay % 24_000) + 24_000) % 24_000 - - // Calculate celestial angle (0-1, where 0.25 is noon, 0.75 is midnight) - const celestialAngle = getCelestialAngle(normalizedTime) - - // Calculate brightness factor based on celestial angle - // cos gives us smooth day/night transition - const cos = Math.cos(celestialAngle * Math.PI * 2) - - // Map cos (-1 to 1) to brightness (0 to 1) - // At noon (celestialAngle ~0.25): cos(0.5π) = 0, but we want max brightness - // At midnight (celestialAngle ~0.75): cos(1.5π) = 0, but we want min brightness - - // Vanilla-like calculation: - // brightness goes from 0 (dark) to 1 (bright) - const brightness = cos * 0.5 + 0.5 - - // Apply threshold - night should be darker - // Vanilla has minimum sky light of 4 during night - const skyLight = Math.round(4 + brightness * 11) - - return Math.max(4, Math.min(15, skyLight)) -} - -/** - * Simplified sky light calculation that more closely matches vanilla behavior. - * Uses piecewise linear interpolation based on known Minecraft light levels. - * - * @param timeOfDay - Time in ticks (0-24000) - * @returns Sky light level (4-15) - */ -export const calculateSkyLightSimple = (timeOfDay: number): number => { - // Normalize to 0-24000 - const time = ((timeOfDay % 24_000) + 24_000) % 24_000 - - // Vanilla Minecraft approximate sky light levels: - // 0-12000 (6AM-6PM): Day, sky light = 15 - // 12000-13000 (6PM-7PM): Sunset transition, 15 -> 4 - // 13000-23000 (7PM-5AM): Night, sky light = 4 - // 23000-24000 (5AM-6AM): Sunrise transition, 4 -> 15 - - if (time >= 0 && time < 12_000) { - // Day time - full brightness - return 15 - } else if (time >= 12_000 && time < 13_000) { - // Sunset transition (6PM to 7PM) - const progress = (time - 12_000) / 1000 - return Math.round(15 - progress * 11) - } else if (time >= 13_000 && time < 23_000) { - // Night time - minimum brightness - return 4 - } else { - // Sunrise transition (5AM to 6AM) - const progress = (time - 23_000) / 1000 - return Math.round(4 + progress * 11) - } -} - -// Test/debug helper - run this to see values at different times -export const debugSkyLight = () => { - const testTimes = [ - { ticks: 0, label: '6:00 AM (sunrise)' }, - { ticks: 6000, label: '12:00 PM (noon)' }, - { ticks: 12_000, label: '6:00 PM (sunset starts)' }, - { ticks: 12_500, label: '6:30 PM (sunset mid)' }, - { ticks: 13_000, label: '7:00 PM (night begins)' }, - { ticks: 18_000, label: '12:00 AM (midnight)' }, - { ticks: 19_000, label: '1:00 AM' }, - { ticks: 23_000, label: '5:00 AM (dawn begins)' }, - { ticks: 23_500, label: '5:30 AM (dawn mid)' }, - ] - - console.log('Sky Light Debug:') - console.log('================') - for (const { ticks, label } of testTimes) { - const smooth = calculateSkyLight(ticks) - const simple = calculateSkyLightSimple(ticks) - console.log(`${ticks.toString().padStart(5)} ticks (${label}): smooth=${smooth}, simple=${simple}`) - } -} - -// Export for global access in console -if (typeof window !== 'undefined') { - (window as any).debugSkyLight = debugSkyLight -} diff --git a/renderer/viewer/lib/smoothSwitcher.ts b/renderer/viewer/lib/smoothSwitcher.ts deleted file mode 100644 index 74eb11717..000000000 --- a/renderer/viewer/lib/smoothSwitcher.ts +++ /dev/null @@ -1,168 +0,0 @@ -import * as tweenJs from '@tweenjs/tween.js' -import { AnimationController } from './animationController' - -export type StateProperties = Record -export type StateGetterFn = () => StateProperties -export type StateSetterFn = (property: string, value: number) => void - -// Speed in units per second for each property type -const DEFAULT_SPEEDS = { - x: 3000, // pixels/units per second - y: 3000, - z: 3000, - rotation: Math.PI, // radians per second - scale: 1, // scale units per second - default: 3000 // default speed for unknown properties -} - -export class SmoothSwitcher { - private readonly animationController = new AnimationController() - // private readonly currentState: StateProperties = {} - private readonly defaultState: StateProperties - private readonly speeds: Record - public currentStateName = '' - public transitioningToStateName = '' - - constructor ( - public getState: StateGetterFn, - public setState: StateSetterFn, - speeds?: Partial> - ) { - - // Initialize speeds with defaults and overrides - this.speeds = { ...DEFAULT_SPEEDS } - if (speeds) { - Object.assign(this.speeds, speeds) - } - - // Store initial values - this.defaultState = this.getState() - } - - /** - * Calculate transition duration based on the largest property change - */ - private calculateDuration (newState: Partial): number { - let maxDuration = 0 - const currentState = this.getState() - - for (const [key, targetValue] of Object.entries(newState)) { - const currentValue = currentState[key] - const diff = Math.abs(targetValue! - currentValue) - const speed = this.getPropertySpeed(key) - const duration = (diff / speed) * 1000 // Convert to milliseconds - - maxDuration = Math.max(maxDuration, duration) - } - - // Ensure minimum duration of 50ms and maximum of 2000ms - return Math.min(Math.max(maxDuration, 200), 2000) - } - - private getPropertySpeed (property: string): number { - // Check for specific property speed - if (property in this.speeds) { - return this.speeds[property] - } - - // Check for property type (rotation, scale, etc.) - if (property.toLowerCase().includes('rotation')) return this.speeds.rotation - if (property.toLowerCase().includes('scale')) return this.speeds.scale - if (property.toLowerCase() === 'x' || property.toLowerCase() === 'y' || property.toLowerCase() === 'z') { - return this.speeds[property] - } - - return this.speeds.default - } - - /** - * Start a transition to a new state - * @param newState Partial state - only need to specify properties that change - * @param easing Easing function to use - */ - startTransition ( - newState: Partial, - stateName?: string, - onEnd?: () => void, - easing: (amount: number) => number = tweenJs.Easing.Linear.None, - onCancelled?: () => void - ): void { - if (this.isTransitioning) { - this.animationController.forceFinish(false) - } - - this.transitioningToStateName = stateName ?? '' - const state = this.getState() - - const duration = this.calculateDuration(newState) - // console.log('duration', duration, JSON.stringify(state), JSON.stringify(newState)) - - void this.animationController.startAnimation(() => { - const group = new tweenJs.Group() - new tweenJs.Tween(state, group) - .to(newState, duration) - .easing(easing) - .onUpdate((obj) => { - for (const key of Object.keys(obj)) { - this.setState(key, obj[key]) - } - }) - .onComplete(() => { - this.animationController.forceFinish() - this.currentStateName = this.transitioningToStateName - this.transitioningToStateName = '' - onEnd?.() - }) - .start() - return group - }, onCancelled) - } - - /** - * Reset to default state - */ - reset (): void { - this.startTransition(this.defaultState) - } - - - /** - * Update the animation (should be called in your render/update loop) - */ - update (): void { - this.animationController.update() - } - - /** - * Force finish the current transition - */ - forceFinish (): void { - this.animationController.forceFinish() - } - - /** - * Start a new transition to the specified state - */ - transitionTo ( - newState: Partial, - stateName?: string, - onEnd?: () => void, - onCancelled?: () => void - ): void { - this.startTransition(newState, stateName, onEnd, tweenJs.Easing.Linear.None, onCancelled) - } - - /** - * Get the current value of a property - */ - getCurrentValue (property: string): number { - return this.getState()[property] - } - - /** - * Check if currently transitioning - */ - get isTransitioning (): boolean { - return this.animationController.isActive - } -} diff --git a/renderer/viewer/lib/ui/newStats.ts b/renderer/viewer/lib/ui/newStats.ts deleted file mode 100644 index d07090b84..000000000 --- a/renderer/viewer/lib/ui/newStats.ts +++ /dev/null @@ -1,126 +0,0 @@ -/* eslint-disable unicorn/prefer-dom-node-text-content */ -const rightOffset = 0 - -const stats = {} - -let lastY = 40 - -/** Host app should style z-index (see prismarine-web-client `styles.css`). */ -export const MC_RENDERER_DEBUG_OVERLAY_CLASS = 'mc-renderer-debug-overlay' - -export const addNewStat = ( - id: string, - width = 80, - x = rightOffset, - y = lastY, - opts?: { className?: string }, -) => { - const pane = document.createElement('div') - pane.style.position = 'fixed' - pane.style.top = `${y ?? lastY}px` - pane.style.right = `${x}px` - // gray bg - pane.style.backgroundColor = 'rgba(0, 0, 0, 0.7)' - pane.style.color = 'white' - pane.style.padding = '2px' - pane.style.fontFamily = 'monospace' - pane.style.fontSize = '12px' - if (opts?.className) { - pane.className = opts.className - } else { - pane.style.zIndex = '100' - } - pane.style.pointerEvents = 'none' - document.body.appendChild(pane) - stats[id] = pane - if (y === undefined && x === rightOffset) { // otherwise it's a custom position - // rightOffset += width - lastY += 20 - } - - return { - updateText (text: string) { - if (pane.innerText === text) return - pane.innerText = text - }, - setVisibility (visible: boolean) { - pane.style.display = visible ? 'block' : 'none' - } - } -} - -export const addNewStat2 = (id: string, { top, bottom, right, left, displayOnlyWhenWider }: { top?: number, bottom?: number, right?: number, left?: number, displayOnlyWhenWider?: number }) => { - if (top === undefined && bottom === undefined) top = 0 - const pane = document.createElement('div') - pane.style.position = 'fixed' - if (top !== undefined) { - pane.style.top = `${top}px` - } - if (bottom !== undefined) { - pane.style.bottom = `${bottom}px` - } - if (left !== undefined) { - pane.style.left = `${left}px` - } - if (right !== undefined) { - pane.style.right = `${right}px` - } - // gray bg - pane.style.backgroundColor = 'rgba(0, 0, 0, 0.7)' - pane.style.color = 'white' - pane.style.padding = '2px' - pane.style.fontFamily = 'monospace' - pane.style.fontSize = '12px' - pane.style.zIndex = '10000' - pane.style.pointerEvents = 'none' - document.body.appendChild(pane) - stats[id] = pane - - const resizeCheck = () => { - if (!displayOnlyWhenWider) return - pane.style.display = window.innerWidth > displayOnlyWhenWider ? 'block' : 'none' - } - window.addEventListener('resize', resizeCheck) - resizeCheck() - - return { - updateText (text: string) { - pane.innerText = text - }, - setVisibility (visible: boolean) { - pane.style.display = visible ? 'block' : 'none' - } - } -} - -export const updateStatText = (id, text) => { - if (!stats[id]) return - stats[id].innerText = text -} - -export const updatePanesVisibility = (visible: boolean) => { - // eslint-disable-next-line guard-for-in - for (const id in stats) { - stats[id].style.display = visible ? 'block' : 'none' - } -} - -export const removeAllStats = () => { - // eslint-disable-next-line guard-for-in - for (const id in stats) { - removeStat(id) - } -} - -export const removeStat = (id) => { - if (!stats[id]) return - stats[id].remove() - delete stats[id] -} - -if (typeof customEvents !== 'undefined') { - customEvents.on('gameLoaded', () => { - const chunksLoaded = addNewStat('chunks-loaded', 80, 0, 0) - const chunksTotal = addNewStat('chunks-read', 80, 0, 0) - }) -} diff --git a/renderer/viewer/lib/utils.ts b/renderer/viewer/lib/utils.ts deleted file mode 100644 index f471aa9d0..000000000 --- a/renderer/viewer/lib/utils.ts +++ /dev/null @@ -1,57 +0,0 @@ -export const loadScript = async function (scriptSrc: string, highPriority = true): Promise { - const existingScript = document.querySelector(`script[src="${scriptSrc}"]`) - if (existingScript) { - return existingScript - } - - return new Promise((resolve, reject) => { - const scriptElement = document.createElement('script') - scriptElement.src = scriptSrc - - if (highPriority) { - scriptElement.fetchPriority = 'high' - } - scriptElement.async = true - - scriptElement.addEventListener('load', () => { - resolve(scriptElement) - }) - - scriptElement.onerror = (error) => { - reject(new Error(typeof error === 'string' ? error : (error as any).message)) - scriptElement.remove() - } - - document.head.appendChild(scriptElement) - }) -} - -const detectFullOffscreenCanvasSupport = () => { - if (typeof OffscreenCanvas === 'undefined') return false - try { - const canvas = new OffscreenCanvas(1, 1) - // Try to get a WebGL context - this will fail on iOS where only 2D is supported (iOS 16) - const gl = canvas.getContext('webgl2') || canvas.getContext('webgl') - return gl !== null - } catch (e) { - return false - } -} - -const hasFullOffscreenCanvasSupport = detectFullOffscreenCanvasSupport() - -export const createCanvas = (width: number, height: number): OffscreenCanvas => { - if (hasFullOffscreenCanvasSupport) { - return new OffscreenCanvas(width, height) - } - const canvas = document.createElement('canvas') - canvas.width = width - canvas.height = height - return canvas as unknown as OffscreenCanvas // todo-low -} - -export async function loadImageFromUrl (imageUrl: string): Promise { - const response = await fetch(imageUrl) - const blob = await response.blob() - return createImageBitmap(blob) -} diff --git a/renderer/viewer/lib/utils/proxy.ts b/renderer/viewer/lib/utils/proxy.ts deleted file mode 100644 index d30ceb7ea..000000000 --- a/renderer/viewer/lib/utils/proxy.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { subscribeKey } from 'valtio/utils' - -// eslint-disable-next-line max-params -export function watchProperty, K> (asyncGetter: (value: T[keyof T]) => Promise, valtioProxy: T, key: keyof T, readySetter: (res: K) => void, cleanup?: (res: K) => void) { - let i = 0 - let lastRes: K | undefined - const request = async () => { - const req = ++i - const res = await asyncGetter(valtioProxy[key]) - if (req === i) { - if (lastRes) { - cleanup?.(lastRes) - } - readySetter(res) - lastRes = res - } else { - // rejected - cleanup?.(res) - } - } - void request() - return subscribeKey(valtioProxy, key, request) -} diff --git a/renderer/viewer/lib/utils/skins.ts b/renderer/viewer/lib/utils/skins.ts deleted file mode 100644 index 3163702cd..000000000 --- a/renderer/viewer/lib/utils/skins.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { loadSkinToCanvas } from 'skinview-utils' -import { createCanvas, loadImageFromUrl } from '../utils' - -export { default as stevePngUrl } from 'mc-assets/dist/other-textures/latest/entity/player/wide/steve.png' - -const config = { - apiEnabled: true, -} - -export const setSkinsConfig = (newConfig: Partial) => { - Object.assign(config, newConfig) -} - -export async function loadSkinFromUsername (username: string, type: 'skin' | 'cape'): Promise { - if (!config.apiEnabled) return - - if (type === 'cape') return - const url = `https://playerdb.co/api/player/minecraft/${username}` - const response = await fetch(url) - if (!response.ok) return - - const data: { - data: { - player: { - skin_texture: string - } - } - } = await response.json() - return data.data.player.skin_texture -} - -export const parseSkinTexturesValue = (value: string) => { - const decodedData: { - textures: { - SKIN: { - url: string - } - } - } = JSON.parse(Buffer.from(value, 'base64').toString()) - return decodedData.textures?.SKIN?.url -} - -export async function loadSkinImage (skinUrl: string): Promise<{ canvas: OffscreenCanvas, image: ImageBitmap }> { - if (!skinUrl.startsWith('data:')) { - skinUrl = await fetchAndConvertBase64Skin(skinUrl.replace('http://', 'https://')) - } - - const image = await loadImageFromUrl(skinUrl) - const skinCanvas = createCanvas(64, 64) - loadSkinToCanvas(skinCanvas, image) - return { canvas: skinCanvas, image } -} - -const fetchAndConvertBase64Skin = async (skinUrl: string) => { - const response = await fetch(skinUrl, { }) - const arrayBuffer = await response.arrayBuffer() - const base64 = Buffer.from(arrayBuffer).toString('base64') - return `data:image/png;base64,${base64}` -} diff --git a/renderer/viewer/lib/workerProxy.ts b/renderer/viewer/lib/workerProxy.ts deleted file mode 100644 index 2b38dca93..000000000 --- a/renderer/viewer/lib/workerProxy.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { proxy, getVersion, subscribe } from 'valtio' - -export function createWorkerProxy void | Promise>> (handlers: T, channel?: MessagePort): { __workerProxy: T } { - const target = channel ?? globalThis - target.addEventListener('message', (event: any) => { - const { type, args, msgId } = event.data - if (handlers[type]) { - const result = handlers[type](...args) - if (result instanceof Promise) { - void result.then((result) => { - target.postMessage({ - type: 'result', - msgId, - args: [result] - }) - }) - } - } - }) - return null as any -} - -/** - * in main thread - * ```ts - * // either: - * import type { importedTypeWorkerProxy } from './worker' - * // or: - * type importedTypeWorkerProxy = import('./worker').importedTypeWorkerProxy - * - * const workerChannel = useWorkerProxy(worker) - * ``` - */ -export const useWorkerProxy = void> }> (worker: Worker | MessagePort, autoTransfer = true): T['__workerProxy'] & { - transfer: (...args: Transferable[]) => T['__workerProxy'] -} => { - let messageId = 0 - // in main thread - return new Proxy({} as any, { - get (target, prop) { - if (prop === 'transfer') { - return (...transferable: Transferable[]) => { - return new Proxy({}, { - get (target, prop) { - return (...args: any[]) => { - worker.postMessage({ - type: prop, - args, - }, transferable) - } - } - }) - } - } - return (...args: any[]) => { - const msgId = messageId++ - const transfer = autoTransfer ? args.filter(arg => { - return arg instanceof ArrayBuffer || arg instanceof MessagePort - || (typeof ImageBitmap !== 'undefined' && arg instanceof ImageBitmap) - || (typeof OffscreenCanvas !== 'undefined' && arg instanceof OffscreenCanvas) - || (typeof ImageData !== 'undefined' && arg instanceof ImageData) - }) : [] - worker.postMessage({ - type: prop, - msgId, - args, - }, transfer) - return { - // eslint-disable-next-line unicorn/no-thenable - then (onfulfilled: (value: any) => void) { - const handler = ({ data }: MessageEvent): void => { - if (data.type === 'result' && data.msgId === msgId) { - onfulfilled(data.args[0]) - worker.removeEventListener('message', handler as EventListener) - } - } - worker.addEventListener('message', handler as EventListener) - } - } - } - } - }) -} - -// const workerProxy = createWorkerProxy({ -// startRender (canvas: HTMLCanvasElement) { -// }, -// }) - -// const worker = useWorkerProxy(null, workerProxy) - -// worker. diff --git a/renderer/viewer/lib/worldDataEmitter.ts b/renderer/viewer/lib/worldDataEmitter.ts deleted file mode 100644 index dfbdb35c3..000000000 --- a/renderer/viewer/lib/worldDataEmitter.ts +++ /dev/null @@ -1,431 +0,0 @@ -/* eslint-disable guard-for-in */ - -// todo refactor into its own commons module -import { EventEmitter } from 'events' -import { generateSpiralMatrix, ViewRect } from 'flying-squid/dist/utils' -import { Vec3 } from 'vec3' -import { BotEvents } from 'mineflayer' -import { proxy } from 'valtio' -import TypedEmitter from 'typed-emitter' -import { Biome } from 'minecraft-data' -import { delayedIterator } from '../../playground/shared' -import { chunkPos } from './simpleUtils' - -export type ChunkPosKey = string // like '16,16' -type ChunkPos = { x: number, z: number } // like { x: 16, z: 16 } - -export type WorldDataEmitterEvents = { - chunkPosUpdate: (data: { pos: Vec3 }) => void - blockUpdate: (data: { pos: Vec3, stateId: number }) => void - entity: (data: any) => void - entityMoved: (data: any) => void - playerEntity: (data: any) => void - time: (data: number) => void - renderDistance: (viewDistance: number) => void - blockEntities: (data: Record | { blockEntities: Record }) => void - markAsLoaded: (data: { x: number, z: number }) => void - unloadChunk: (data: { x: number, z: number }) => void - loadChunk: (data: { x: number, z: number, chunk: string, blockEntities: any, worldConfig: any, isLightUpdate: boolean }) => void - updateLight: (data: { pos: Vec3 }) => void - onWorldSwitch: () => void - end: () => void - biomeUpdate: (data: { biome: Biome }) => void - biomeReset: () => void -} - -export class WorldDataEmitterWorker extends (EventEmitter as new () => TypedEmitter) { - static readonly restorerName = 'WorldDataEmitterWorker' -} - -export class WorldDataEmitter extends (EventEmitter as new () => TypedEmitter) { - spiralNumber = 0 - gotPanicLastTime = false - panicChunksReload = () => {} - loadedChunks: Record - private inLoading = false - private chunkReceiveTimes: number[] = [] - private lastChunkReceiveTime = 0 - public lastChunkReceiveTimeAvg = 0 - private panicTimeout?: NodeJS.Timeout - readonly lastPos: Vec3 - private eventListeners: Record = {} - private readonly emitter: WorldDataEmitter - debugChunksInfo: Record - // blockUpdates: number - }> = {} - - waitingSpiralChunksLoad = {} as Record void> - - addWaitTime = 1 - /* config */ keepChunksDistance = 0 - /* config */ isPlayground = false - /* config */ allowPositionUpdate = true - - constructor (public world: typeof __type_bot['world'], public viewDistance: number, position: Vec3 = new Vec3(0, 0, 0)) { - // eslint-disable-next-line constructor-super - super() - this.loadedChunks = {} - this.lastPos = new Vec3(0, 0, 0).update(position) - // todo - this.emitter = this - } - - setBlockStateId (position: Vec3, stateId: number) { - const val = this.world.setBlockStateId(position, stateId) as Promise | void - if (val) throw new Error('setBlockStateId returned promise (not supported)') - // const chunkX = Math.floor(position.x / 16) - // const chunkZ = Math.floor(position.z / 16) - // if (!this.loadedChunks[`${chunkX},${chunkZ}`] && !this.waitingSpiralChunksLoad[`${chunkX},${chunkZ}`]) { - // void this.loadChunk({ x: chunkX, z: chunkZ }) - // return - // } - - this.emit('blockUpdate', { pos: position, stateId }) - } - - updateViewDistance (viewDistance: number) { - this.viewDistance = viewDistance - this.emitter.emit('renderDistance', viewDistance) - } - - listenToBot (bot: typeof __type_bot) { - const entitiesObjectData = new Map() - bot._client.prependListener('spawn_entity', (data) => { - if (data.objectData && data.entityId !== undefined) { - entitiesObjectData.set(data.entityId, data.objectData) - } - }) - - const emitEntity = (e, name = 'entity') => { - if (!e) return - if (e === bot.entity) { - if (name === 'entity') { - this.emitter.emit('playerEntity', e) - } - return - } - if (!e.name) return // mineflayer received update for not spawned entity - e.objectData = entitiesObjectData.get(e.id) - this.emitter.emit(name as any, { - ...e, - pos: e.position, - username: e.username, - team: bot.teamMap[e.username] || bot.teamMap[e.uuid], - // set debugTree (obj) { - // e.debugTree = obj - // } - }) - } - - this.eventListeners = { - // 'move': botPosition, - entitySpawn (e: any) { - if (e.name === 'item_frame' || e.name === 'glow_item_frame') { - // Item frames use block positions in the protocol, not their center. Fix that. - e.position.translate(0.5, 0.5, 0.5) - } - emitEntity(e) - }, - entityUpdate (e: any) { - emitEntity(e) - }, - entityEquip (e: any) { - emitEntity(e) - }, - entityMoved (e: any) { - emitEntity(e, 'entityMoved') - }, - entityGone: (e: any) => { - this.emitter.emit('entity', { id: e.id, delete: true }) - }, - chunkColumnLoad: (pos: Vec3) => { - const now = performance.now() - if (this.lastChunkReceiveTime) { - this.chunkReceiveTimes.push(now - this.lastChunkReceiveTime) - } - this.lastChunkReceiveTime = now - - if (this.waitingSpiralChunksLoad[`${pos.x},${pos.z}`]) { - this.waitingSpiralChunksLoad[`${pos.x},${pos.z}`](true) - delete this.waitingSpiralChunksLoad[`${pos.x},${pos.z}`] - } else if (this.loadedChunks[`${pos.x},${pos.z}`]) { - void this.loadChunk(pos, false, 'Received another chunkColumnLoad event while already loaded') - } - this.chunkProgress() - }, - chunkColumnUnload: (pos: Vec3) => { - this.unloadChunk(pos) - }, - blockUpdate: (oldBlock: any, newBlock: any) => { - const stateId = newBlock.stateId ?? ((newBlock.type << 4) | newBlock.metadata) - this.emitter.emit('blockUpdate', { pos: oldBlock.position, stateId }) - }, - time: () => { - this.emitter.emit('time', bot.time.timeOfDay) - }, - end: () => { - this.emitter.emit('end') - }, - // when dimension might change - login: () => { - void this.updatePosition(bot.entity.position, true) - this.emitter.emit('playerEntity', bot.entity) - }, - respawn: () => { - void this.updatePosition(bot.entity.position, true) - this.emitter.emit('playerEntity', bot.entity) - this.emitter.emit('onWorldSwitch') - }, - } satisfies Partial - - - bot._client.on('update_light', ({ chunkX, chunkZ }) => { - const chunkPos = new Vec3(chunkX * 16, 0, chunkZ * 16) - if (!this.waitingSpiralChunksLoad[`${chunkX},${chunkZ}`] && this.loadedChunks[`${chunkX},${chunkZ}`]) { - void this.loadChunk(chunkPos, true, 'update_light') - } - }) - - for (const [evt, listener] of Object.entries(this.eventListeners)) { - bot.on(evt as any, listener) - } - - for (const id in bot.entities) { - const e = bot.entities[id] - try { - emitEntity(e) - } catch (err) { - // reportError?.(err) - console.error('error processing entity', err) - } - } - } - - emitterGotConnected () { - this.emitter.emit('blockEntities', new Proxy({}, { - get (_target, posKey, receiver) { - if (typeof posKey !== 'string') return - const [x, y, z] = posKey.split(',').map(Number) - return bot.world.getBlock(new Vec3(x, y, z))?.entity - }, - })) - } - - removeListenersFromBot (bot: import('mineflayer').Bot) { - for (const [evt, listener] of Object.entries(this.eventListeners)) { - bot.removeListener(evt as any, listener) - } - } - - async init (pos: Vec3) { - this.updateViewDistance(this.viewDistance) - this.emitter.emit('chunkPosUpdate', { pos }) - if (bot?.time?.timeOfDay) { - this.emitter.emit('time', bot.time.timeOfDay) - } - if (bot?.entity) { - this.emitter.emit('playerEntity', bot.entity) - } - this.emitterGotConnected() - const [botX, botZ] = chunkPos(pos) - - const positions = generateSpiralMatrix(this.viewDistance).map(([x, z]) => new Vec3((botX + x) * 16, 0, (botZ + z) * 16)) - - this.lastPos.update(pos) - await this._loadChunks(positions, pos) - } - - chunkProgress () { - if (this.panicTimeout) clearTimeout(this.panicTimeout) - if (this.chunkReceiveTimes.length >= 5) { - const avgReceiveTime = this.chunkReceiveTimes.reduce((a, b) => a + b, 0) / this.chunkReceiveTimes.length - this.lastChunkReceiveTimeAvg = avgReceiveTime - const timeoutDelay = avgReceiveTime * 2 + 1000 // 2x average + 1 second - - // Clear any existing timeout - if (this.panicTimeout) clearTimeout(this.panicTimeout) - - // Set new timeout for panic reload - this.panicTimeout = setTimeout(() => { - if (!this.gotPanicLastTime && this.inLoading) { - console.warn('Chunk loading seems stuck, triggering panic reload') - this.gotPanicLastTime = true - this.panicChunksReload() - } - }, timeoutDelay) - } - } - - async _loadChunks (positions: Vec3[], centerPos: Vec3) { - this.spiralNumber++ - const { spiralNumber } = this - // stop loading previous chunks - for (const pos of Object.keys(this.waitingSpiralChunksLoad)) { - this.waitingSpiralChunksLoad[pos](false) - delete this.waitingSpiralChunksLoad[pos] - } - - let continueLoading = true - this.inLoading = true - await delayedIterator(positions, this.addWaitTime, async (pos) => { - if (!continueLoading || this.loadedChunks[`${pos.x},${pos.z}`]) return - - // Wait for chunk to be available from server - if (!this.world.getColumnAt(pos)) { - continueLoading = await new Promise(resolve => { - this.waitingSpiralChunksLoad[`${pos.x},${pos.z}`] = resolve - }) - } - if (!continueLoading) return - await this.loadChunk(pos, undefined, `spiral ${spiralNumber} from ${centerPos.x},${centerPos.z}`) - this.chunkProgress() - }) - if (this.panicTimeout) clearTimeout(this.panicTimeout) - this.inLoading = false - this.gotPanicLastTime = false - this.chunkReceiveTimes = [] - this.lastChunkReceiveTime = 0 - } - - readdDebug () { - const clonedLoadedChunks = { ...this.loadedChunks } - this.unloadAllChunks() - console.time('readdDebug') - for (const loadedChunk in clonedLoadedChunks) { - const [x, z] = loadedChunk.split(',').map(Number) - void this.loadChunk(new Vec3(x, 0, z)) - } - const interval = setInterval(() => { - if (appViewer.rendererState.world.allChunksLoaded) { - clearInterval(interval) - console.timeEnd('readdDebug') - } - }, 100) - } - - // debugGotChunkLatency = [] as number[] - // lastTime = 0 - - async loadChunk (pos: ChunkPos, isLightUpdate = false, reason = 'spiral') { - const [botX, botZ] = chunkPos(this.lastPos) - - const dx = Math.abs(botX - Math.floor(pos.x / 16)) - const dz = Math.abs(botZ - Math.floor(pos.z / 16)) - if (dx <= this.viewDistance && dz <= this.viewDistance) { - // eslint-disable-next-line @typescript-eslint/await-thenable -- todo allow to use async world provider but not sure if needed - const column = await this.world.getColumnAt(pos['y'] ? pos as Vec3 : new Vec3(pos.x, 0, pos.z)) - if (column) { - // const latency = Math.floor(performance.now() - this.lastTime) - // this.debugGotChunkLatency.push(latency) - // this.lastTime = performance.now() - // todo optimize toJson data, make it clear why it is used - const chunk = column.toJson() - // TODO: blockEntities - const worldConfig = { - minY: column['minY'] ?? 0, - worldHeight: column['worldHeight'] ?? 256, - } - //@ts-expect-error - this.emitter.emit('loadChunk', { x: pos.x, z: pos.z, chunk, blockEntities: column.blockEntities, worldConfig, isLightUpdate }) - this.loadedChunks[`${pos.x},${pos.z}`] = true - - this.debugChunksInfo[`${pos.x},${pos.z}`] ??= { - loads: [] - } - this.debugChunksInfo[`${pos.x},${pos.z}`].loads.push({ - dataLength: chunk.length, - reason, - time: Date.now(), - }) - } else if (this.isPlayground) { // don't allow in real worlds pre-flag chunks as loaded to avoid race condition when the chunk might still be loading. In playground it's assumed we always pre-load all chunks first - this.emitter.emit('markAsLoaded', { x: pos.x, z: pos.z }) - } - } else { - // console.debug('skipped loading chunk', dx, dz, '>', this.viewDistance) - } - } - - unloadAllChunks () { - for (const coords of Object.keys(this.loadedChunks)) { - const [x, z] = coords.split(',').map(Number) - this.unloadChunk({ x, z }) - } - } - - unloadChunk (pos: ChunkPos) { - this.emitter.emit('unloadChunk', { x: pos.x, z: pos.z }) - delete this.loadedChunks[`${pos.x},${pos.z}`] - delete this.debugChunksInfo[`${pos.x},${pos.z}`] - } - - lastBiomeId: number | null = null - - udpateBiome (pos: Vec3) { - try { - const biomeId = this.world.getBiome(pos) - if (biomeId !== this.lastBiomeId) { - this.lastBiomeId = biomeId - const biomeData = loadedData.biomes[biomeId] - if (biomeData) { - this.emitter.emit('biomeUpdate', { - biome: biomeData - }) - } else { - // unknown biome - this.emitter.emit('biomeReset') - } - } - } catch (e) { - console.error('error updating biome', e) - } - } - - lastPosCheck: Vec3 | null = null - async updatePosition (pos: Vec3, force = false) { - if (!this.allowPositionUpdate) return - const posFloored = pos.floored() - if (!force && this.lastPosCheck && this.lastPosCheck.equals(posFloored)) return - this.lastPosCheck = posFloored - - this.udpateBiome(pos) - - const [lastX, lastZ] = chunkPos(this.lastPos) - const [botX, botZ] = chunkPos(pos) - if (lastX !== botX || lastZ !== botZ || force) { - this.emitter.emit('chunkPosUpdate', { pos }) - - // unload chunks that are no longer in view - const newViewToUnload = new ViewRect(botX, botZ, this.viewDistance + this.keepChunksDistance) - const chunksToUnload: Vec3[] = [] - for (const coords of Object.keys(this.loadedChunks)) { - const x = parseInt(coords.split(',')[0], 10) - const z = parseInt(coords.split(',')[1], 10) - const p = new Vec3(x, 0, z) - const [chunkX, chunkZ] = chunkPos(p) - if (!newViewToUnload.contains(chunkX, chunkZ)) { - chunksToUnload.push(p) - } - } - for (const p of chunksToUnload) { - this.unloadChunk(p) - } - - // load new chunks - const positions = generateSpiralMatrix(this.viewDistance).map(([x, z]) => { - const pos = new Vec3((botX + x) * 16, 0, (botZ + z) * 16) - if (!this.loadedChunks[`${pos.x},${pos.z}`]) return pos - return undefined! - }).filter(a => !!a) - this.lastPos.update(pos) - void this._loadChunks(positions, pos) - } else { - this.emitter.emit('chunkPosUpdate', { pos }) // todo-low - this.lastPos.update(pos) - } - } -} diff --git a/renderer/viewer/lib/worldrendererCommon.ts b/renderer/viewer/lib/worldrendererCommon.ts deleted file mode 100644 index acf40031b..000000000 --- a/renderer/viewer/lib/worldrendererCommon.ts +++ /dev/null @@ -1,1087 +0,0 @@ -/* eslint-disable guard-for-in */ -import { EventEmitter } from 'events' -import { Vec3 } from 'vec3' -import mcDataRaw from 'minecraft-data/data.js' // note: using alias -import TypedEmitter from 'typed-emitter' -import { WorldBlockProvider } from 'mc-assets/dist/worldBlockProvider' -import { generateSpiralMatrix } from 'flying-squid/dist/utils' -import { subscribeKey } from 'valtio/utils' -import { proxy } from 'valtio' -import { dynamicMcDataFiles } from '../../buildMesherConfig.mjs' -import type { ResourcesManagerTransferred } from '../../../src/resourcesManager' -import { DisplayWorldOptions, GraphicsInitOptions, RendererReactiveState } from '../../../src/appViewer' -import { SoundSystem } from '../three/threeJsSound' -import { buildCleanupDecorator } from './cleanupDecorator' -import { HighestBlockInfo, CustomBlockModels, BlockStateModelInfo, getBlockAssetsCacheKey, MesherConfig, MesherMainEvent } from './mesher/shared' -import { chunkPos } from './simpleUtils' -import { addNewStat, MC_RENDERER_DEBUG_OVERLAY_CLASS, removeAllStats, updatePanesVisibility, updateStatText } from './ui/newStats' -import { WorldDataEmitterWorker } from './worldDataEmitter' -import { getPlayerStateUtils, PlayerStateReactive, PlayerStateRenderer, PlayerStateUtils } from './basePlayerState' -import { MesherLogReader } from './mesherlogReader' -import { setSkinsConfig } from './utils/skins' -import { calculateSkyLightSimple } from './skyLight' - -function mod (x, n) { - return ((x % n) + n) % n -} - -const toMajorVersion = version => { - const [a, b] = (String(version)).split('.') - return `${a}.${b}` -} - -export const worldCleanup = buildCleanupDecorator('resetWorld') - -export const defaultWorldRendererConfig = { - // Debug settings - showChunkBorders: false, - enableDebugOverlay: false, - debugModelVariant: undefined as undefined | number[], - - // Performance settings - mesherWorkers: 4, - addChunksBatchWaitTime: 200, - _experimentalSmoothChunkLoading: true, - _renderByChunks: false, - - // Rendering engine settings - dayCycle: true, - smoothLighting: true, - shadingTheme: 'high-contrast', - cardinalLight: 'default', - enableLighting: true, - starfield: true, - defaultSkybox: true, - renderEntities: true, - extraBlockRenderers: true, - foreground: true, - fov: 75, - volume: 1, - - // Camera visual related settings - showHand: false, - viewBobbing: false, - renderEars: true, - highlightBlockColor: 'blue', - - // Player models - fetchPlayerSkins: true, - skinTexturesProxy: undefined as string | undefined, - - // VR settings - vrSupport: true, - vrPageGameRendering: true, - - // World settings - clipWorldBelowY: undefined as number | undefined, - isPlayground: false, - instantCameraUpdate: false -} - -export type WorldRendererConfig = typeof defaultWorldRendererConfig - -export abstract class WorldRendererCommon { - worldReadyResolvers = Promise.withResolvers() - worldReadyPromise = this.worldReadyResolvers.promise - timeOfTheDay = 0 - worldSizeParams = { minY: 0, worldHeight: 256 } - reactiveDebugParams = proxy({ - stopRendering: false, - chunksRenderAboveOverride: undefined as number | undefined, - chunksRenderAboveEnabled: false, - chunksRenderBelowOverride: undefined as number | undefined, - chunksRenderBelowEnabled: false, - chunksRenderDistanceOverride: undefined as number | undefined, - chunksRenderDistanceEnabled: false, - disableEntities: false, - // disableParticles: false - }) - - active = false - - // #region CHUNK & SECTIONS TRACKING - @worldCleanup() - loadedChunks = {} as Record // data is added for these chunks and they might be still processing - - @worldCleanup() - finishedChunks = {} as Record // these chunks are fully loaded into the world (scene) - - @worldCleanup() - finishedSections = {} as Record // these sections are fully loaded into the world (scene) - - @worldCleanup() - // loading sections (chunks) - sectionsWaiting = new Map() - - @worldCleanup() - queuedChunks = new Set() - queuedFunctions = [] as Array<() => void> - // #endregion - - renderUpdateEmitter = new EventEmitter() as unknown as TypedEmitter<{ - dirty (pos: Vec3, value: boolean): void - update (/* pos: Vec3, value: boolean */): void - chunkFinished (key: string): void - heightmap (key: string, heightmap: Uint8Array): void - }> - customTexturesDataUrl = undefined as string | undefined - workers: any[] = [] - viewerChunkPosition?: Vec3 - lastCamUpdate = 0 - droppedFpsPercentage = 0 - initialChunkLoadWasStartedIn: number | undefined - initialChunksLoad = true - enableChunksLoadDelay = false - texturesVersion?: string - viewDistance = -1 - chunksLength = 0 - allChunksFinished = false - messageQueue: any[] = [] - isProcessingQueue = false - ONMESSAGE_TIME_LIMIT = 30 // ms - - handleResize = () => { } - highestBlocksByChunks = new Map() - blockEntities = {} - - workersProcessAverageTime = 0 - workersProcessAverageTimeCount = 0 - maxWorkersProcessTime = 0 - geometryReceiveCount = {} as Record - allLoadedIn: undefined | number - onWorldSwitched = [] as Array<() => void> - renderTimeMax = 0 - renderTimeAvg = 0 - renderTimeAvgCount = 0 - edgeChunks = {} as Record - lastAddChunk = null as null | { - timeout: any - x: number - z: number - } - neighborChunkUpdates = true - lastChunkDistance = 0 - debugStopGeometryUpdate = false - - protocolCustomBlocks = new Map() - - @worldCleanup() - blockStateModelInfo = new Map() - - abstract outputFormat: 'threeJs' | 'webgpu' - worldBlockProvider: WorldBlockProvider - soundSystem: SoundSystem | undefined - - abstract changeBackgroundColor (color: [number, number, number]): void - abstract changeCardinalLight (string): void - - worldRendererConfig: WorldRendererConfig - playerStateReactive: PlayerStateReactive - playerStateUtils: PlayerStateUtils - reactiveState: RendererReactiveState - mesherLogReader: MesherLogReader | undefined - forceCallFromMesherReplayer = false - stopMesherMessagesProcessing = false - - abortController = new AbortController() - lastRendered = 0 - renderingActive = true - geometryReceiveCountPerSec = 0 - mesherLogger = { - contents: [] as string[], - active: new URL(location.href).searchParams.get('mesherlog') === 'true' - } - currentRenderedFrames = 0 - fpsAverage = 0 - lastFps = 0 - fpsWorst = undefined as number | undefined - fpsSamples = 0 - mainThreadRendering = true - backendInfoReport = '-' - chunksFullInfo = '-' - workerCustomHandleTime = 0 - - get version () { - return this.displayOptions.version - } - - get displayAdvancedStats () { - return (this.initOptions.config.statsVisible ?? 0) > 1 - } - - constructor (public readonly resourcesManager: ResourcesManagerTransferred, public displayOptions: DisplayWorldOptions, public initOptions: GraphicsInitOptions) { - this.snapshotInitialValues() - this.worldRendererConfig = displayOptions.inWorldRenderingConfig - this.playerStateReactive = displayOptions.playerStateReactive - this.playerStateUtils = getPlayerStateUtils(this.playerStateReactive) - this.reactiveState = displayOptions.rendererState - // this.mesherLogReader = new MesherLogReader(this) - this.renderUpdateEmitter.on('update', () => { - const loadedChunks = Object.keys(this.finishedChunks).length - updateStatText('loaded-chunks', `${loadedChunks}/${this.chunksLength} chunks (${this.lastChunkDistance}/${this.viewDistance})`) - }) - - addNewStat('downloaded-chunks', 100, 140, 20, { className: MC_RENDERER_DEBUG_OVERLAY_CLASS }) - - this.connect(this.displayOptions.worldView) - - const interval = setInterval(() => { - this.geometryReceiveCountPerSec = Object.values(this.geometryReceiveCount).reduce((acc, curr) => acc + curr, 0) - this.geometryReceiveCount = {} - updatePanesVisibility(this.displayAdvancedStats) - this.updateChunksStats() - if (this.mainThreadRendering) { - this.fpsUpdate() - } - }, 500) - this.abortController.signal.addEventListener('abort', () => { - clearInterval(interval) - }) - } - - fpsUpdate () { - this.fpsSamples++ - this.fpsAverage = (this.fpsAverage * (this.fpsSamples - 1) + this.currentRenderedFrames) / this.fpsSamples - if (this.fpsWorst === undefined) { - this.fpsWorst = this.currentRenderedFrames - } else { - this.fpsWorst = Math.min(this.fpsWorst, this.currentRenderedFrames) - } - this.lastFps = this.currentRenderedFrames - this.currentRenderedFrames = 0 - } - - logWorkerWork (message: string | (() => string)) { - if (!this.mesherLogger.active) return - this.mesherLogger.contents.push(typeof message === 'function' ? message() : message) - } - - async init () { - if (this.active) throw new Error('WorldRendererCommon is already initialized') - - await Promise.all([ - this.resetWorkers(), - (async () => { - if (this.resourcesManager.currentResources?.allReady) { - await this.updateAssetsData() - } - })() - ]) - - this.resourcesManager.on('assetsTexturesUpdated', async () => { - if (!this.active) return - await this.updateAssetsData() - }) - - this.watchReactivePlayerState() - this.watchReactiveConfig() - this.worldReadyResolvers.resolve() - } - - snapshotInitialValues () { } - - wasChunkSentToWorker (chunkKey: string) { - return this.loadedChunks[chunkKey] - } - - async getHighestBlocks (chunkKey: string) { - return this.highestBlocksByChunks.get(chunkKey) - } - - updateCustomBlock (chunkKey: string, blockPos: string, model: string) { - this.protocolCustomBlocks.set(chunkKey, { - ...this.protocolCustomBlocks.get(chunkKey), - [blockPos]: model - }) - this.logWorkerWork(() => `-> updateCustomBlock ${chunkKey} ${blockPos} ${model} ${this.wasChunkSentToWorker(chunkKey)}`) - if (this.wasChunkSentToWorker(chunkKey)) { - const [x, y, z] = blockPos.split(',').map(Number) - this.setBlockStateId(new Vec3(x, y, z), undefined) - } - } - - async getBlockInfo (blockPos: { x: number, y: number, z: number }, stateId: number) { - const chunkKey = `${Math.floor(blockPos.x / 16) * 16},${Math.floor(blockPos.z / 16) * 16}` - const customBlockName = this.protocolCustomBlocks.get(chunkKey)?.[`${blockPos.x},${blockPos.y},${blockPos.z}`] - const cacheKey = getBlockAssetsCacheKey(stateId, customBlockName) - const modelInfo = this.blockStateModelInfo.get(cacheKey) - return { - customBlockName, - modelInfo - } - } - - initWorkers (numWorkers = this.worldRendererConfig.mesherWorkers) { - // init workers - for (let i = 0; i < numWorkers + 1; i++) { - const worker = initMesherWorker((data) => { - if (Array.isArray(data)) { - this.messageQueue.push(...data) - } else { - this.messageQueue.push(data) - } - void this.processMessageQueue('worker') - }) - this.workers.push(worker) - } - } - - onReactivePlayerStateUpdated(key: T, callback: (value: PlayerStateReactive[T]) => void, initial = true) { - if (initial) { - callback(this.playerStateReactive[key]) - } - subscribeKey(this.playerStateReactive, key, callback) - } - - onReactiveConfigUpdated(key: T, callback: (value: typeof this.worldRendererConfig[T]) => void) { - callback(this.worldRendererConfig[key]) - subscribeKey(this.worldRendererConfig, key, callback) - } - - onReactiveDebugUpdated(key: T, callback: (value: typeof this.reactiveDebugParams[T]) => void) { - callback(this.reactiveDebugParams[key]) - subscribeKey(this.reactiveDebugParams, key, callback) - } - - watchReactivePlayerState () { - this.onReactivePlayerStateUpdated('backgroundColor', (value) => { - this.changeBackgroundColor(value) - }) - this.onReactivePlayerStateUpdated('cardinalLight', (value) => { - this.changeCardinalLight(value) - }) - } - - watchReactiveConfig () { - this.onReactiveConfigUpdated('fetchPlayerSkins', (value) => { - setSkinsConfig({ apiEnabled: value }) - }) - } - - async processMessageQueue (source: string) { - if (this.isProcessingQueue || this.messageQueue.length === 0) return - this.logWorkerWork(`# ${source} processing queue`) - if (this.lastRendered && performance.now() - this.lastRendered > this.ONMESSAGE_TIME_LIMIT && this.worldRendererConfig._experimentalSmoothChunkLoading && this.renderingActive) { - const start = performance.now() - await new Promise(resolve => { - requestAnimationFrame(resolve) - }) - this.logWorkerWork(`# processing got delayed by ${performance.now() - start}ms`) - } - this.isProcessingQueue = true - - const startTime = performance.now() - let processedCount = 0 - - while (this.messageQueue.length > 0) { - const processingStopped = this.stopMesherMessagesProcessing - if (!processingStopped) { - const data = this.messageQueue.shift()! - this.handleMessage(data) - processedCount++ - } - - // Check if we've exceeded the time limit - if (processingStopped || (performance.now() - startTime > this.ONMESSAGE_TIME_LIMIT && this.renderingActive && this.worldRendererConfig._experimentalSmoothChunkLoading)) { - // If we have more messages and exceeded time limit, schedule next batch - if (this.messageQueue.length > 0) { - requestAnimationFrame(async () => { - this.isProcessingQueue = false - void this.processMessageQueue('queue-delay') - }) - return - } - break - } - } - - this.isProcessingQueue = false - } - - handleMessage (rawData: any) { - const data = rawData as MesherMainEvent - if (!this.active) return - this.mesherLogReader?.workerMessageReceived(data.type, data) - if (data.type !== 'geometry' || !this.debugStopGeometryUpdate) { - const start = performance.now() - this.handleWorkerMessage(data as WorkerReceive) - this.workerCustomHandleTime += performance.now() - start - } - if (data.type === 'geometry') { - this.logWorkerWork(() => `-> ${data.workerIndex} geometry ${data.key} ${JSON.stringify({ dataSize: JSON.stringify(data).length })}`) - this.geometryReceiveCount[data.workerIndex] ??= 0 - this.geometryReceiveCount[data.workerIndex]++ - const chunkCoords = data.key.split(',').map(Number) - this.lastChunkDistance = Math.max(...this.getDistance(new Vec3(chunkCoords[0], 0, chunkCoords[2]))) - } - if (data.type === 'sectionFinished') { // on after load & unload section - this.logWorkerWork(`<- ${data.workerIndex} sectionFinished ${data.key} ${JSON.stringify({ processTime: data.processTime })}`) - if (!this.sectionsWaiting.has(data.key)) throw new Error(`sectionFinished event for non-outstanding section ${data.key}`) - this.sectionsWaiting.set(data.key, this.sectionsWaiting.get(data.key)! - 1) - if (this.sectionsWaiting.get(data.key) === 0) { - this.sectionsWaiting.delete(data.key) - this.finishedSections[data.key] = true - } - - const chunkCoords = data.key.split(',').map(Number) - const chunkKey = `${chunkCoords[0]},${chunkCoords[2]}` - if (this.loadedChunks[chunkKey]) { // ensure chunk data was added, not a neighbor chunk update - let loaded = true - for (let y = this.worldMinYRender; y < this.worldSizeParams.worldHeight; y += 16) { - if (!this.finishedSections[`${chunkCoords[0]},${y},${chunkCoords[2]}`]) { - loaded = false - break - } - } - if (loaded) { - // CHUNK FINISHED - this.finishedChunks[chunkKey] = true - this.reactiveState.world.chunksLoaded.add(`${Math.floor(chunkCoords[0] / 16)},${Math.floor(chunkCoords[2] / 16)}`) - this.renderUpdateEmitter.emit(`chunkFinished`, `${chunkCoords[0]},${chunkCoords[2]}`) - this.checkAllFinished() - // merge highest blocks by sections into highest blocks by chunks - // for (let y = this.worldMinYRender; y < this.worldSizeParams.worldHeight; y += 16) { - // const sectionKey = `${chunkCoords[0]},${y},${chunkCoords[2]}` - // for (let x = 0; x < 16; x++) { - // for (let z = 0; z < 16; z++) { - // const posInsideKey = `${chunkCoords[0] + x},${chunkCoords[2] + z}` - // let block = null as HighestBlockInfo | null - // const highestBlock = this.highestBlocksBySections[sectionKey]?.[posInsideKey] - // if (!highestBlock) continue - // if (!block || highestBlock.y > block.y) { - // block = highestBlock - // } - // if (block) { - // this.highestBlocksByChunks[chunkKey] ??= {} - // this.highestBlocksByChunks[chunkKey][posInsideKey] = block - // } - // } - // } - // delete this.highestBlocksBySections[sectionKey] - // } - } - } - - this.renderUpdateEmitter.emit('update') - if (data.processTime) { - this.workersProcessAverageTimeCount++ - this.workersProcessAverageTime = ((this.workersProcessAverageTime * (this.workersProcessAverageTimeCount - 1)) + data.processTime) / this.workersProcessAverageTimeCount - this.maxWorkersProcessTime = Math.max(this.maxWorkersProcessTime, data.processTime) - } - } - - if (data.type === 'blockStateModelInfo') { - for (const [cacheKey, info] of Object.entries(data.info)) { - this.blockStateModelInfo.set(cacheKey, info) - } - } - - if (data.type === 'heightmap') { - this.reactiveState.world.heightmaps.set(data.key, new Uint8Array(data.heightmap)) - } - } - - downloadMesherLog () { - const a = document.createElement('a') - a.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(this.mesherLogger.contents.join('\n')) - a.download = 'mesher.log' - a.click() - } - - checkAllFinished () { - if (this.sectionsWaiting.size === 0) { - this.reactiveState.world.mesherWork = false - } - // todo check exact surrounding chunks - const allFinished = Object.keys(this.finishedChunks).length >= this.chunksLength - if (allFinished) { - this.allChunksLoaded?.() - this.allChunksFinished = true - this.allLoadedIn ??= Date.now() - this.initialChunkLoadWasStartedIn! - } - this.updateChunksStats() - } - - changeHandSwingingState (isAnimationPlaying: boolean, isLeftHand: boolean): void { } - - abstract handleWorkerMessage (data: WorkerReceive): void - - abstract updateCamera (pos: Vec3 | null, yaw: number, pitch: number): void - - abstract render (): void - - /** - * Optionally update data that are depedendent on the viewer position - */ - updatePosDataChunk? (key: string): void - - allChunksLoaded? (): void - - timeUpdated? (newTime: number): void - - biomeUpdated? (biome: any): void - - biomeReset? (): void - - updateViewerPosition (pos: Vec3) { - this.viewerChunkPosition = pos - for (const [key, value] of Object.entries(this.loadedChunks)) { - if (!value) continue - this.updatePosDataChunk?.(key) - } - } - - sendWorkers (message: WorkerSend) { - for (const worker of this.workers) { - worker.postMessage(message) - } - } - - getDistance (posAbsolute: Vec3) { - const [botX, botZ] = chunkPos(this.viewerChunkPosition!) - const dx = Math.abs(botX - Math.floor(posAbsolute.x / 16)) - const dz = Math.abs(botZ - Math.floor(posAbsolute.z / 16)) - return [dx, dz] as [number, number] - } - - abstract updateShowChunksBorder (value: boolean): void - - resetWorld () { - // destroy workers - for (const worker of this.workers) { - worker.terminate() - } - this.workers = [] - } - - async resetWorkers () { - this.resetWorld() - - // for workers in single file build - if (typeof document !== 'undefined' && document?.readyState === 'loading') { - await new Promise(resolve => { - document.addEventListener('DOMContentLoaded', resolve) - }) - } - - this.initWorkers() - this.active = true - - this.sendMesherMcData() - } - - getMesherConfig (): MesherConfig { - const timeOfDay = this.timeOfTheDay - const skyLight = (timeOfDay < 0 || timeOfDay > 24_000) ? 15 : calculateSkyLightSimple(timeOfDay) - return { - version: this.version, - enableLighting: this.worldRendererConfig.enableLighting, - skyLight, - smoothLighting: this.worldRendererConfig.smoothLighting, - shadingTheme: this.worldRendererConfig.shadingTheme, - cardinalLight: this.worldRendererConfig.cardinalLight, - outputFormat: this.outputFormat, - // textureSize: this.resourcesManager.currentResources!.blocksAtlasParser.atlas.latest.width, - debugModelVariant: this.worldRendererConfig.debugModelVariant, - clipWorldBelowY: this.worldRendererConfig.clipWorldBelowY, - disableBlockEntityTextures: !this.worldRendererConfig.extraBlockRenderers, - worldMinY: this.worldMinYRender, - worldMaxY: this.worldMinYRender + this.worldSizeParams.worldHeight, - } - } - - sendMesherMcData () { - const allMcData = mcDataRaw.pc[this.version] ?? mcDataRaw.pc[toMajorVersion(this.version)] - const mcData = { - version: JSON.parse(JSON.stringify(allMcData.version)) - } - for (const key of dynamicMcDataFiles) { - mcData[key] = allMcData[key] - } - - for (const worker of this.workers) { - worker.postMessage({ type: 'mcData', mcData, config: this.getMesherConfig() }) - } - this.logWorkerWork('# mcData sent') - } - - async updateAssetsData () { - const resources = this.resourcesManager.currentResources - - if (this.workers.length === 0) throw new Error('workers not initialized yet') - for (const [i, worker] of this.workers.entries()) { - const { blockstatesModels } = resources - - worker.postMessage({ - type: 'mesherData', - workerIndex: i, - blocksAtlas: { - latest: resources.blocksAtlasJson - }, - blockstatesModels, - config: this.getMesherConfig(), - }) - } - - this.logWorkerWork('# mesherData sent') - console.log('textures loaded') - } - - get worldMinYRender () { - return Math.floor(Math.max(this.worldSizeParams.minY, this.worldRendererConfig.clipWorldBelowY ?? -Infinity) / 16) * 16 - } - - updateChunksStats () { - const loadedChunks = Object.keys(this.finishedChunks) - this.displayOptions.nonReactiveState.world.chunksLoaded = new Set(loadedChunks) - this.displayOptions.nonReactiveState.world.chunksTotalNumber = this.chunksLength - this.reactiveState.world.allChunksLoaded = this.allChunksFinished - - const text = `Q: ${this.messageQueue.length} ${Object.keys(this.loadedChunks).length}/${Object.keys(this.finishedChunks).length}/${this.chunksLength} chunks (${this.workers.length}:${this.workersProcessAverageTime.toFixed(0)}ms/${this.geometryReceiveCountPerSec}ss/${this.allLoadedIn?.toFixed(1) ?? '-'}s)` - this.chunksFullInfo = text - updateStatText('downloaded-chunks', text) - } - - addColumn (x: number, z: number, chunk: any, isLightUpdate: boolean) { - if (!this.active) return - if (this.workers.length === 0) throw new Error('workers not initialized yet') - this.initialChunksLoad = false - this.initialChunkLoadWasStartedIn ??= Date.now() - this.loadedChunks[`${x},${z}`] = true - this.updateChunksStats() - - const chunkKey = `${x},${z}` - const customBlockModels = this.protocolCustomBlocks.get(chunkKey) - - for (const worker of this.workers) { - worker.postMessage({ - type: 'chunk', - x, - z, - chunk, - customBlockModels: customBlockModels || undefined - }) - } - this.workers[0].postMessage({ - type: 'getHeightmap', - x, - z, - }) - this.logWorkerWork(() => `-> chunk ${JSON.stringify({ x, z, chunkLength: chunk.length, customBlockModelsLength: customBlockModels ? Object.keys(customBlockModels).length : 0 })}`) - this.mesherLogReader?.chunkReceived(x, z, chunk.length) - for (let y = this.worldMinYRender; y < this.worldSizeParams.worldHeight; y += 16) { - const loc = new Vec3(x, y, z) - this.setSectionDirty(loc) - if (this.neighborChunkUpdates && (!isLightUpdate || this.worldRendererConfig.smoothLighting)) { - this.setSectionDirty(loc.offset(-16, 0, 0)) - this.setSectionDirty(loc.offset(16, 0, 0)) - this.setSectionDirty(loc.offset(0, 0, -16)) - this.setSectionDirty(loc.offset(0, 0, 16)) - } - } - } - - markAsLoaded (x, z) { - this.loadedChunks[`${x},${z}`] = true - this.finishedChunks[`${x},${z}`] = true - this.logWorkerWork(`-> markAsLoaded ${JSON.stringify({ x, z })}`) - this.checkAllFinished() - } - - removeColumn (x, z) { - delete this.loadedChunks[`${x},${z}`] - for (const worker of this.workers) { - worker.postMessage({ type: 'unloadChunk', x, z }) - } - this.logWorkerWork(`-> unloadChunk ${JSON.stringify({ x, z })}`) - delete this.finishedChunks[`${x},${z}`] - this.allChunksFinished = Object.keys(this.finishedChunks).length === this.chunksLength - if (Object.keys(this.finishedChunks).length === 0) { - this.allLoadedIn = undefined - this.initialChunkLoadWasStartedIn = undefined - } - for (let y = this.worldSizeParams.minY; y < this.worldSizeParams.worldHeight; y += 16) { - this.setSectionDirty(new Vec3(x, y, z), false) - delete this.finishedSections[`${x},${y},${z}`] - } - this.highestBlocksByChunks.delete(`${x},${z}`) - - this.updateChunksStats() - - if (Object.keys(this.loadedChunks).length === 0) { - this.mesherLogger.contents = [] - this.logWorkerWork('# all chunks unloaded. New log started') - void this.mesherLogReader?.maybeStartReplay() - } - } - - setBlockStateId (pos: Vec3, stateId: number | undefined, needAoRecalculation = true) { - const set = async () => { - const sectionX = Math.floor(pos.x / 16) * 16 - const sectionZ = Math.floor(pos.z / 16) * 16 - if (this.queuedChunks.has(`${sectionX},${sectionZ}`)) { - await new Promise(resolve => { - this.queuedFunctions.push(() => { - resolve() - }) - }) - } - if (!this.loadedChunks[`${sectionX},${sectionZ}`]) { - // console.debug('[should be unreachable] setBlockStateId called for unloaded chunk', pos) - } - this.setBlockStateIdInner(pos, stateId, needAoRecalculation) - } - void set() - } - - updateEntity (e: any, isUpdate = false) { } - - abstract updatePlayerEntity? (e: any): void - - lightUpdate (chunkX: number, chunkZ: number) { } - - connect (worldView: WorldDataEmitterWorker) { - const worldEmitter = worldView - - worldEmitter.on('entity', (e) => { - this.updateEntity(e, false) - }) - worldEmitter.on('entityMoved', (e) => { - this.updateEntity(e, true) - }) - worldEmitter.on('playerEntity', (e) => { - this.updatePlayerEntity?.(e) - }) - - let currentLoadChunkBatch = null as { - timeout - data - } | null - worldEmitter.on('loadChunk', ({ x, z, chunk, worldConfig, isLightUpdate }) => { - this.worldSizeParams = worldConfig - this.queuedChunks.add(`${x},${z}`) - const args = [x, z, chunk, isLightUpdate] - if (!currentLoadChunkBatch) { - // add a setting to use debounce instead - currentLoadChunkBatch = { - data: [], - timeout: setTimeout(() => { - for (const args of currentLoadChunkBatch!.data) { - this.queuedChunks.delete(`${args[0]},${args[1]}`) - this.addColumn(...args as Parameters) - } - for (const fn of this.queuedFunctions) { - fn() - } - this.queuedFunctions = [] - currentLoadChunkBatch = null - }, this.worldRendererConfig.addChunksBatchWaitTime) - } - } - currentLoadChunkBatch.data.push(args) - }) - // todo remove and use other architecture instead so data flow is clear - worldEmitter.on('blockEntities', (blockEntities) => { - this.blockEntities = blockEntities - }) - - worldEmitter.on('unloadChunk', ({ x, z }) => { - this.removeColumn(x, z) - }) - - worldEmitter.on('blockUpdate', ({ pos, stateId }) => { - this.setBlockStateId(new Vec3(pos.x, pos.y, pos.z), stateId) - }) - - worldEmitter.on('chunkPosUpdate', ({ pos }) => { - this.updateViewerPosition(pos) - }) - - worldEmitter.on('end', () => { - this.worldStop?.() - }) - - - worldEmitter.on('renderDistance', (d) => { - this.viewDistance = d - this.chunksLength = d === 0 ? 1 : generateSpiralMatrix(d).length - }) - - worldEmitter.on('renderDistance', (d) => { - this.viewDistance = d - this.chunksLength = d === 0 ? 1 : generateSpiralMatrix(d).length - this.allChunksFinished = Object.keys(this.finishedChunks).length === this.chunksLength - }) - - worldEmitter.on('markAsLoaded', ({ x, z }) => { - this.markAsLoaded(x, z) - }) - - worldEmitter.on('updateLight', ({ pos }) => { - this.lightUpdate(pos.x, pos.z) - }) - - worldEmitter.on('onWorldSwitch', () => { - for (const fn of this.onWorldSwitched) { - try { - fn() - } catch (e) { - setTimeout(() => { - console.log('[Renderer Backend] Error in onWorldSwitched:') - throw e - }, 0) - } - } - }) - - worldEmitter.on('time', (timeOfDay) => { - if (!this.worldRendererConfig.dayCycle) return - this.timeUpdated?.(timeOfDay) - - this.timeOfTheDay = timeOfDay - - // if (this.worldRendererConfig.skyLight === skyLight) return - // this.worldRendererConfig.skyLight = skyLight - // if (this instanceof WorldRendererThree) { - // (this).rerenderAllChunks?.() - // } - }) - - worldEmitter.on('biomeUpdate', ({ biome }) => { - this.biomeUpdated?.(biome) - }) - - worldEmitter.on('biomeReset', () => { - this.biomeReset?.() - }) - } - - setBlockStateIdInner (pos: Vec3, stateId: number | undefined, needAoRecalculation = true) { - const chunkKey = `${Math.floor(pos.x / 16) * 16},${Math.floor(pos.z / 16) * 16}` - const blockPosKey = `${pos.x},${pos.y},${pos.z}` - const customBlockModels = this.protocolCustomBlocks.get(chunkKey) || {} - - for (const worker of this.workers) { - worker.postMessage({ - type: 'blockUpdate', - pos, - stateId, - customBlockModels - }) - } - this.logWorkerWork(`-> blockUpdate ${JSON.stringify({ pos, stateId, customBlockModels })}`) - this.setSectionDirty(pos, true, true) - if (this.neighborChunkUpdates) { - if ((pos.x & 15) === 0) this.setSectionDirty(pos.offset(-16, 0, 0), true, true) - if ((pos.x & 15) === 15) this.setSectionDirty(pos.offset(16, 0, 0), true, true) - if ((pos.y & 15) === 0) this.setSectionDirty(pos.offset(0, -16, 0), true, true) - if ((pos.y & 15) === 15) this.setSectionDirty(pos.offset(0, 16, 0), true, true) - if ((pos.z & 15) === 0) this.setSectionDirty(pos.offset(0, 0, -16), true, true) - if ((pos.z & 15) === 15) this.setSectionDirty(pos.offset(0, 0, 16), true, true) - - if (needAoRecalculation) { - // top view neighbors - if ((pos.x & 15) === 0 && (pos.z & 15) === 0) this.setSectionDirty(pos.offset(-16, 0, -16), true, true) - if ((pos.x & 15) === 15 && (pos.z & 15) === 0) this.setSectionDirty(pos.offset(16, 0, -16), true, true) - if ((pos.x & 15) === 0 && (pos.z & 15) === 15) this.setSectionDirty(pos.offset(-16, 0, 16), true, true) - if ((pos.x & 15) === 15 && (pos.z & 15) === 15) this.setSectionDirty(pos.offset(16, 0, 16), true, true) - - // side view neighbors (but ignore updates above) - // z view neighbors - if ((pos.x & 15) === 0 && (pos.y & 15) === 0) this.setSectionDirty(pos.offset(-16, -16, 0), true, true) - if ((pos.x & 15) === 15 && (pos.y & 15) === 0) this.setSectionDirty(pos.offset(16, -16, 0), true, true) - - // x view neighbors - if ((pos.z & 15) === 0 && (pos.y & 15) === 0) this.setSectionDirty(pos.offset(0, -16, -16), true, true) - if ((pos.z & 15) === 15 && (pos.y & 15) === 0) this.setSectionDirty(pos.offset(0, -16, 16), true, true) - - // x & z neighbors - if ((pos.y & 15) === 0 && (pos.x & 15) === 0 && (pos.z & 15) === 0) this.setSectionDirty(pos.offset(-16, -16, -16), true, true) - if ((pos.y & 15) === 0 && (pos.x & 15) === 15 && (pos.z & 15) === 0) this.setSectionDirty(pos.offset(16, -16, -16), true, true) - if ((pos.y & 15) === 0 && (pos.x & 15) === 0 && (pos.z & 15) === 15) this.setSectionDirty(pos.offset(-16, -16, 16), true, true) - if ((pos.y & 15) === 0 && (pos.x & 15) === 15 && (pos.z & 15) === 15) this.setSectionDirty(pos.offset(16, -16, 16), true, true) - } - } - } - - abstract worldStop? () - - queueAwaited = false - toWorkerMessagesQueue = {} as { [workerIndex: string]: any[] } - - getWorkerNumber (pos: Vec3, updateAction = false) { - if (updateAction) { - const key = `${Math.floor(pos.x / 16) * 16},${Math.floor(pos.y / 16) * 16},${Math.floor(pos.z / 16) * 16}` - const cantUseChangeWorker = this.sectionsWaiting.get(key) && !this.finishedSections[key] - if (!cantUseChangeWorker) return 0 - } - - const hash = mod(Math.floor(pos.x / 16) + Math.floor(pos.y / 16) + Math.floor(pos.z / 16), this.workers.length - 1) - return hash + 1 - } - - async debugGetWorkerCustomBlockModel (pos: Vec3) { - const data = [] as Array> - for (const worker of this.workers) { - data.push(new Promise((resolve) => { - worker.addEventListener('message', (e) => { - if (e.data.type === 'customBlockModel') { - resolve(e.data.customBlockModel) - } - }) - })) - worker.postMessage({ - type: 'getCustomBlockModel', - pos - }) - } - return Promise.all(data) - } - - setSectionDirty (pos: Vec3, value = true, useChangeWorker = false) { // value false is used for unloading chunks - if (!this.forceCallFromMesherReplayer && this.mesherLogReader) return - - if (this.viewDistance === -1) throw new Error('viewDistance not set') - this.reactiveState.world.mesherWork = true - const distance = this.getDistance(pos) - // todo shouldnt we check loadedChunks instead? - if (!this.workers.length || distance[0] > this.viewDistance || distance[1] > this.viewDistance) return - const key = `${Math.floor(pos.x / 16) * 16},${Math.floor(pos.y / 16) * 16},${Math.floor(pos.z / 16) * 16}` - // if (this.sectionsOutstanding.has(key)) return - this.renderUpdateEmitter.emit('dirty', pos, value) - // Dispatch sections to workers based on position - // This guarantees uniformity accross workers and that a given section - // is always dispatched to the same worker - const hash = this.getWorkerNumber(pos, useChangeWorker && this.mesherLogger.active) - this.sectionsWaiting.set(key, (this.sectionsWaiting.get(key) ?? 0) + 1) - if (this.forceCallFromMesherReplayer) { - this.workers[hash].postMessage({ - type: 'dirty', - x: pos.x, - y: pos.y, - z: pos.z, - value, - config: this.getMesherConfig(), - }) - } else { - this.toWorkerMessagesQueue[hash] ??= [] - this.toWorkerMessagesQueue[hash].push({ - // this.workers[hash].postMessage({ - type: 'dirty', - x: pos.x, - y: pos.y, - z: pos.z, - value, - config: this.getMesherConfig(), - }) - this.dispatchMessages() - } - } - - dispatchMessages () { - if (this.queueAwaited) return - this.queueAwaited = true - setTimeout(() => { - // group messages and send as one - for (const workerIndex in this.toWorkerMessagesQueue) { - const worker = this.workers[Number(workerIndex)] - worker.postMessage(this.toWorkerMessagesQueue[workerIndex]) - for (const message of this.toWorkerMessagesQueue[workerIndex]) { - this.logWorkerWork(`-> ${workerIndex} dispatchMessages ${message.type} ${JSON.stringify({ x: message.x, y: message.y, z: message.z, value: message.value })}`) - } - } - this.toWorkerMessagesQueue = {} - this.queueAwaited = false - }) - } - - // Listen for chunk rendering updates emitted if a worker finished a render and resolve if the number - // of sections not rendered are 0 - async waitForChunksToRender () { - return new Promise((resolve, reject) => { - if ([...this.sectionsWaiting].length === 0) { - resolve() - return - } - - const updateHandler = () => { - if (this.sectionsWaiting.size === 0) { - this.renderUpdateEmitter.removeListener('update', updateHandler) - resolve() - } - } - this.renderUpdateEmitter.on('update', updateHandler) - }) - } - - async waitForChunkToLoad (pos: Vec3) { - return new Promise((resolve, reject) => { - const key = `${Math.floor(pos.x / 16) * 16},${Math.floor(pos.z / 16) * 16}` - if (this.loadedChunks[key]) { - resolve() - return - } - const updateHandler = () => { - if (this.loadedChunks[key]) { - this.renderUpdateEmitter.removeListener('update', updateHandler) - resolve() - } - } - this.renderUpdateEmitter.on('update', updateHandler) - }) - } - - destroy () { - // Stop all workers - for (const worker of this.workers) { - worker.terminate() - } - this.workers = [] - - // Stop and destroy sound system - if (this.soundSystem) { - this.soundSystem.destroy() - this.soundSystem = undefined - } - - this.active = false - - this.renderUpdateEmitter.removeAllListeners() - this.abortController.abort() - removeAllStats() - } -} - -export const initMesherWorker = (onGotMessage: (data: any) => void) => { - // Node environment needs an absolute path, but browser needs the url of the file - const workerName = 'mesher.js' - - let worker: any - if (process.env.SINGLE_FILE_BUILD) { - const workerCode = document.getElementById('mesher-worker-code')!.textContent! - const blob = new Blob([workerCode], { type: 'text/javascript' }) - worker = new Worker(window.URL.createObjectURL(blob)) - } else { - worker = new Worker(workerName) - } - - worker.onmessage = ({ data }) => { - onGotMessage(data) - } - if (worker.on) worker.on('message', (data) => { worker.onmessage({ data }) }) - return worker -} - -export const meshersSendMcData = (workers: Worker[], version: string, addData = {} as Record) => { - const allMcData = mcDataRaw.pc[version] ?? mcDataRaw.pc[toMajorVersion(version)] - const mcData = { - version: JSON.parse(JSON.stringify(allMcData.version)) - } - for (const key of dynamicMcDataFiles) { - mcData[key] = allMcData[key] - } - - for (const worker of workers) { - worker.postMessage({ type: 'mcData', mcData, ...addData }) - } -} diff --git a/renderer/viewer/sign-renderer/index.html b/renderer/viewer/sign-renderer/index.html deleted file mode 100644 index 671ad05f2..000000000 --- a/renderer/viewer/sign-renderer/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - %VITE_NAME% - - - - -
test
- - - - diff --git a/renderer/viewer/sign-renderer/index.ts b/renderer/viewer/sign-renderer/index.ts deleted file mode 100644 index 7d8d59119..000000000 --- a/renderer/viewer/sign-renderer/index.ts +++ /dev/null @@ -1,219 +0,0 @@ -import type { ChatMessage } from 'prismarine-chat' -import { createCanvas } from '../lib/utils' - -type SignBlockEntity = { - Color?: string - GlowingText?: 0 | 1 - Text1?: string - Text2?: string - Text3?: string - Text4?: string -} | { - // todo - is_waxed?: 0 | 1 - front_text: { - color: string - messages: string[] - // todo - has_glowing_text?: 0 | 1 - } - // todo - // back_text: {} -} - -type JsonEncodedType = string | null | Record - -const parseSafe = (text: string, task: string) => { - try { - return JSON.parse(text) - } catch (e) { - console.warn(`Failed to parse ${task}`, e) - return null - } -} - -const LEGACY_COLORS = { - black: '#000000', - dark_blue: '#0000AA', - dark_green: '#00AA00', - dark_aqua: '#00AAAA', - dark_red: '#AA0000', - dark_purple: '#AA00AA', - gold: '#FFAA00', - gray: '#AAAAAA', - dark_gray: '#555555', - blue: '#5555FF', - green: '#55FF55', - aqua: '#55FFFF', - red: '#FF5555', - light_purple: '#FF55FF', - yellow: '#FFFF55', - white: '#FFFFFF', -} - -export const renderSign = ( - blockEntity: SignBlockEntity, - isHanging: boolean, - PrismarineChat: typeof ChatMessage, - ctxHook = (ctx) => { }, - canvasCreator = (width, height): OffscreenCanvas => { return createCanvas(width, height) } -) => { - // todo don't use texture rendering, investigate the font rendering when possible - // or increase factor when needed - const factor = 40 - const fontSize = 1.6 * factor - const signboardY = [16, 9] - const heightOffset = signboardY[0] - signboardY[1] - const heightScalar = heightOffset / 16 - // todo the text should be clipped based on it's render width (needs investigate) - - const texts = 'front_text' in blockEntity ? /* > 1.20 */ blockEntity.front_text.messages : [ - blockEntity.Text1, - blockEntity.Text2, - blockEntity.Text3, - blockEntity.Text4 - ] - - if (!texts.some((text) => text !== 'null')) { - return undefined - } - - const canvas = canvasCreator(16 * factor, heightOffset * factor) - - const _ctx = canvas.getContext('2d')! - - ctxHook(_ctx) - const defaultColor = ('front_text' in blockEntity ? blockEntity.front_text.color : blockEntity.Color) || 'black' - for (const [lineNum, text] of texts.slice(0, 4).entries()) { - if (text === 'null') continue - renderComponent(text, PrismarineChat, canvas, fontSize, defaultColor, fontSize * (lineNum + 1) + (isHanging ? 0 : -8)) - } - return canvas -} - -export const renderComponent = ( - text: JsonEncodedType | string | undefined, - PrismarineChat: typeof ChatMessage, - canvas: OffscreenCanvas, - fontSize: number, - defaultColor: string, - offset = 0 -) => { - // todo: in pre flatenning it seems the format was not json - const parsed = typeof text === 'string' && (text?.startsWith('{') || text?.startsWith('"')) ? parseSafe(text ?? '""', 'sign text') : text - if (!parsed || (typeof parsed !== 'object' && typeof parsed !== 'string')) return - // todo fix type - - const ctx = canvas.getContext('2d')! - if (!ctx) throw new Error('Could not get 2d context') - ctx.imageSmoothingEnabled = false - ctx.font = `${fontSize}px mojangles` - - type Formatting = { - color: string | undefined - underlined: boolean | undefined - strikethrough: boolean | undefined - bold: boolean | undefined - italic: boolean | undefined - } - - type Message = ChatMessage & Formatting & { text: string } - - const message = new PrismarineChat(parsed) as Message - - const toRenderCanvas: Array<{ - fontStyle: string - fillStyle: string - underlineStyle: boolean - strikeStyle: boolean - offset: number - text: string - }> = [] - let visibleFormatting = false - let plainText = '' - let textOffset = offset - const textWidths: number[] = [] - - const renderText = (component: Message, parentFormatting?: Formatting | undefined) => { - if (component.text !== null && component.text !== undefined && typeof component.text !== 'string') { - console.warn('renderText received non-string text value:', typeof component.text, component.text) - } - const text = component.text === null || component.text === undefined ? undefined : String(component.text) - const formatting = { - color: component.color ?? parentFormatting?.color, - underlined: component.underlined ?? parentFormatting?.underlined, - strikethrough: component.strikethrough ?? parentFormatting?.strikethrough, - bold: component.bold ?? parentFormatting?.bold, - italic: component.italic ?? parentFormatting?.italic - } - visibleFormatting = visibleFormatting || formatting.underlined || formatting.strikethrough || false - if (text?.includes('\n')) { - for (const line of text.split('\n')) { - addTextPart(line, formatting) - textOffset += fontSize - plainText = '' - } - } else if (text) { - addTextPart(text, formatting) - } - if (component.extra) { - for (const child of component.extra) { - renderText(child as Message, formatting) - } - } - } - - const addTextPart = (text: string, formatting: Formatting) => { - plainText += text - textWidths[textOffset] = ctx.measureText(plainText).width - let color = formatting.color ?? defaultColor - if (!color.startsWith('#')) { - color = LEGACY_COLORS[color.toLowerCase()] || color - } - toRenderCanvas.push({ - fontStyle: `${formatting.bold ? 'bold' : ''} ${formatting.italic ? 'italic' : ''}`, - fillStyle: color, - underlineStyle: formatting.underlined ?? false, - strikeStyle: formatting.strikethrough ?? false, - offset: textOffset, - text - }) - } - - renderText(message) - - // skip rendering empty lines - if (!visibleFormatting && !message.toString().trim()) return - - let renderedWidth = 0 - let previousOffsetY = 0 - for (const { fillStyle, fontStyle, underlineStyle, strikeStyle, offset: offsetY, text } of toRenderCanvas) { - if (previousOffsetY !== offsetY) { - renderedWidth = 0 - } - previousOffsetY = offsetY - ctx.fillStyle = fillStyle - ctx.textRendering = 'optimizeLegibility' - ctx.font = `${fontStyle} ${fontSize}px mojangles` - const textWidth = textWidths[offsetY] ?? ctx.measureText(text).width - const offsetX = (canvas.width - textWidth) / 2 + renderedWidth - ctx.fillText(text, offsetX, offsetY) - if (strikeStyle) { - ctx.lineWidth = fontSize / 8 - ctx.strokeStyle = fillStyle - ctx.beginPath() - ctx.moveTo(offsetX, offsetY - ctx.lineWidth * 2.5) - ctx.lineTo(offsetX + ctx.measureText(text).width, offsetY - ctx.lineWidth * 2.5) - ctx.stroke() - } - if (underlineStyle) { - ctx.lineWidth = fontSize / 8 - ctx.strokeStyle = fillStyle - ctx.beginPath() - ctx.moveTo(offsetX, offsetY + ctx.lineWidth) - ctx.lineTo(offsetX + ctx.measureText(text).width, offsetY + ctx.lineWidth) - ctx.stroke() - } - renderedWidth += ctx.measureText(text).width - } -} diff --git a/renderer/viewer/sign-renderer/noop.js b/renderer/viewer/sign-renderer/noop.js deleted file mode 100644 index 4ba52ba2c..000000000 --- a/renderer/viewer/sign-renderer/noop.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = {} diff --git a/renderer/viewer/sign-renderer/package.json b/renderer/viewer/sign-renderer/package.json deleted file mode 100644 index 7715417a5..000000000 --- a/renderer/viewer/sign-renderer/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "sign-renderer", - "version": "0.0.0", - "private": true, - "license": "MIT", - "main": "index.ts", - "scripts": { - "start": "vite" - }, - "dependencies": { - "vite": "^4.4.9" - } -} diff --git a/renderer/viewer/sign-renderer/playground.ts b/renderer/viewer/sign-renderer/playground.ts deleted file mode 100644 index a74380923..000000000 --- a/renderer/viewer/sign-renderer/playground.ts +++ /dev/null @@ -1,38 +0,0 @@ -import PrismarineChatLoader from 'prismarine-chat' -import { renderSign } from '.' - -const PrismarineChat = PrismarineChatLoader({ language: {} } as any) - -const img = new Image() -img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAMCAYAAAB4MH11AAABbElEQVR4AY3BQY6cMBBA0Q+yQZZVi+ndcJVcKGfMgegdvShKVtuokzGSWwwiUd7rfv388Vst0UgMXCobmgsSA5VaQmKgUks0EgNHji8SA9W8GJCQwVNpLhzJ4KFs4B1HEgPVvBiQkMFTaS44tYTEQDXdIkfiHbuyobmguaDPFzIWGrWExEA13SJH4h1uzS/WbPyvroM1v6jWbFRrNv7GfX5EdmXjzTvUEjJ4zjQXjiQGdmXjzTvUEjJ4HF/UEt/kQqW5UEkMzIshY08jg6dRS3yTC5XmgpsXY7pFztQSEgPNJCNv3lGpJVSfTLfImVpCYsB1HdwfxpU1G9eeNF0H94dxZc2G+/yI7MoG3vEv82LI2NNIDLyVDbzjzFE2mnkxZOy5IoNnkpFGc2FXNpp5MWTsOXJ4h1qikrGnkhjYlY1m1icy9lQSA+TCzjvUEpWMPZXEwK5suPvDOFuzcdZ1sOYX1ZqNas3GlTUbzR+jQbEAcs8ZQAAAAABJRU5ErkJggg==' - -await new Promise(resolve => { - img.onload = () => resolve() -}) - -const blockEntity = { - 'GlowingText': 0, - 'Color': 'black', - 'Text4': '{"text":""}', - 'Text3': '{"text":""}', - 'Text2': '{"text":""}', - 'Text1': '{"extra":[{"color":"dark_green","text":"Minecraft "},{"text":"Tools"}],"text":""}' -} as const - -await document.fonts.load('1em mojangles') - -const canvas = renderSign(blockEntity, false, PrismarineChat, (ctx) => { - ctx.drawImage(img, 0, 0, ctx.canvas.width, ctx.canvas.height) -}, (width, height) => { - const canvas = document.createElement('canvas') - canvas.width = width - canvas.height = height - return canvas as unknown as OffscreenCanvas -}) as unknown as HTMLCanvasElement - -if (canvas) { - canvas.style.imageRendering = 'pixelated' - document.body.appendChild(canvas) -} else { - console.log('Render skipped') -} diff --git a/renderer/viewer/sign-renderer/tests.test.ts b/renderer/viewer/sign-renderer/tests.test.ts deleted file mode 100644 index ab2688496..000000000 --- a/renderer/viewer/sign-renderer/tests.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { test, expect } from 'vitest' -import PrismarineChatLoader from 'prismarine-chat' -import { renderSign } from '.' - -const PrismarineChat = PrismarineChatLoader({ language: {} } as any) -let ctxTexts = [] as any[] - -global.document = { - createElement () { - return { - getContext () { - return { - fillText (text, x, y) { - ctxTexts.push({ text, x, y }) - }, - measureText () { return 0 } - } - } - } - } -} as any - -const render = (entity) => { - ctxTexts = [] - renderSign(entity, true, PrismarineChat) - return ctxTexts.map(({ text, y }) => [y / 64, text]) -} - -test('sign renderer', () => { - let blockEntity = { - 'GlowingText': 0, - 'Color': 'black', - 'Text4': '{"text":""}', - 'Text3': '{"text":""}', - 'Text2': '{"text":""}', - 'Text1': '{"extra":[{"color":"dark_green","text":"Minecraft "},{"text":"Tools"}],"text":""}' - } as any - expect(render(blockEntity)).toMatchInlineSnapshot(` - [ - [ - 1, - "Minecraft ", - ], - [ - 1, - "Tools", - ], - ] - `) - - blockEntity = { // pre flatenning - 'Text1': 'Welcome to', - 'Text2': '', - 'Text3': 'null', - 'Text4': '"Version 2.1"', - } as const - expect(render(blockEntity)).toMatchInlineSnapshot(` - [ - [ - 1, - "Welcome to", - ], - [ - 4, - "Version 2.1", - ], - ] - `) -}) diff --git a/renderer/viewer/sign-renderer/vite.config.ts b/renderer/viewer/sign-renderer/vite.config.ts deleted file mode 100644 index aebfc20c7..000000000 --- a/renderer/viewer/sign-renderer/vite.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from 'vite' - -export default defineConfig({ - resolve: { - alias: { - 'prismarine-registry': './noop.js', - 'prismarine-nbt': './noop.js' - }, - }, -}) diff --git a/renderer/viewer/three/appShared.ts b/renderer/viewer/three/appShared.ts deleted file mode 100644 index 5be9e10b7..000000000 --- a/renderer/viewer/three/appShared.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { BlockModel } from 'mc-assets/dist/types' -import { ItemSpecificContextProperties, PlayerStateRenderer } from 'renderer/viewer/lib/basePlayerState' -import { GeneralInputItem, getItemModelName } from '../../../src/mineflayer/items' -import { ResourcesManager, ResourcesManagerTransferred } from '../../../src/resourcesManager' -import { renderSlot } from './renderSlot' - -export const getItemUv = (item: Record, specificProps: ItemSpecificContextProperties, resourcesManager: ResourcesManagerTransferred, playerState: PlayerStateRenderer): { - u: number - v: number - su: number - sv: number - renderInfo?: ReturnType - // texture: ImageBitmap - modelName: string -} | { - resolvedModel: BlockModel - modelName: string -} => { - const resources = resourcesManager.currentResources - if (!resources) throw new Error('Resources not loaded') - const idOrName = item.itemId ?? item.blockId ?? item.name - const { blockState } = item - try { - const name = - blockState - ? loadedData.blocksByStateId[blockState]?.name - : typeof idOrName === 'number' ? loadedData.items[idOrName]?.name : idOrName - if (!name) throw new Error(`Item not found: ${idOrName}`) - - const model = getItemModelName({ - ...item, - name, - } as GeneralInputItem, specificProps, resourcesManager, playerState) - - const renderInfo = renderSlot({ - modelName: model, - }, resourcesManager, false, true) - - if (!renderInfo) throw new Error(`Failed to get render info for item ${name}`) - - const img = renderInfo.texture === 'blocks' ? resources.blocksAtlasImage : resources.itemsAtlasImage - - if (renderInfo.blockData) { - return { - resolvedModel: renderInfo.blockData.resolvedModel, - modelName: renderInfo.modelName! - } - } - if (renderInfo.slice) { - // Get slice coordinates from either block or item texture - const [x, y, w, h] = renderInfo.slice - const [u, v, su, sv] = [x / img.width, y / img.height, (w / img.width), (h / img.height)] - return { - u, v, su, sv, - renderInfo, - // texture: img, - modelName: renderInfo.modelName! - } - } - - throw new Error(`Invalid render info for item ${name}`) - } catch (err) { - reportError?.(err) - // Return default UV coordinates for missing texture - return { - u: 0, - v: 0, - su: 16 / resources.blocksAtlasImage.width, - sv: 16 / resources.blocksAtlasImage.width, - // texture: resources.blocksAtlasImage, - modelName: 'missing' - } - } -} diff --git a/renderer/viewer/three/bannerRenderer.ts b/renderer/viewer/three/bannerRenderer.ts deleted file mode 100644 index e30a95d98..000000000 --- a/renderer/viewer/three/bannerRenderer.ts +++ /dev/null @@ -1,276 +0,0 @@ -import * as THREE from 'three' -import { Vec3 } from 'vec3' -import { createCanvas } from '../lib/utils' -import type { WorldRendererThree } from './worldrendererThree' - -type BannerBlockEntity = { - Patterns?: Array<{ - Color?: number - Pattern?: string - }> -} - -// Banner cloth size is 20x40 -const BANNER_WIDTH = 20 -const BANNER_HEIGHT = 40 - -// Map banner block names to base color IDs -const BANNER_NAME_TO_COLOR: Record = { - 'white_banner': 15, - 'orange_banner': 14, - 'magenta_banner': 13, - 'light_blue_banner': 12, - 'yellow_banner': 11, - 'lime_banner': 10, - 'pink_banner': 9, - 'gray_banner': 8, - 'light_gray_banner': 7, - 'cyan_banner': 6, - 'purple_banner': 5, - 'blue_banner': 4, - 'brown_banner': 3, - 'green_banner': 2, - 'red_banner': 1, - 'black_banner': 0, -} - -// Basic Minecraft banner colors (DyeColor enum values) -const BANNER_COLORS: Record = { - 0: '#1d1d21', // black - 1: '#b02e26', // red - 2: '#5e7c16', // green - 3: '#835432', // brown - 4: '#3c44aa', // blue - 5: '#8932b8', // purple - 6: '#169c9c', // cyan - 7: '#9d9d97', // light_gray - 8: '#474f52', // gray - 9: '#f38baa', // pink - 10: '#80c71f', // lime - 11: '#fed83d', // yellow - 12: '#3ab3da', // light_blue - 13: '#c74ebd', // magenta - 14: '#f9801d', // orange - 15: '#f9fffe', // white -} - -// Extract base color from banner block name -function getBannerBaseColor (blockName: string): number { - // Remove _wall_banner suffix if present - const baseName = blockName.replace('_wall_banner', '_banner') - return BANNER_NAME_TO_COLOR[baseName] ?? 15 // Default to white -} - -// Basic pattern rendering (simplified - just solid colors for now) -const renderPattern = ( - ctx: OffscreenCanvasRenderingContext2D, - pattern: string, - color: string, - x: number, - y: number, - width: number, - height: number -) => { - ctx.fillStyle = color - // For now, just render basic patterns as solid colors - // TODO: Implement actual pattern shapes (stripes, crosses, etc.) - switch (pattern) { - case 'bs': // Base - ctx.fillRect(x, y, width, height) - break - case 'ls': // Left stripe - ctx.fillRect(x, y, width / 3, height) - break - case 'rs': // Right stripe - ctx.fillRect(x + (width * 2 / 3), y, width / 3, height) - break - case 'ts': // Top stripe - ctx.fillRect(x, y, width, height / 3) - break - case 'ms': // Middle stripe - ctx.fillRect(x, y + (height / 3), width, height / 3) - break - case 'drs': // Down-right stripe - ctx.fillRect(x, y, width / 2, height / 2) - break - case 'dls': // Down-left stripe - ctx.fillRect(x + (width / 2), y, width / 2, height / 2) - break - case 'ss': // Small stripes - for (let i = 0; i < width; i += 2) { - ctx.fillRect(x + i, y, 1, height) - } - break - case 'cr': // Cross - ctx.fillRect(x, y + (height / 3), width, height / 3) - ctx.fillRect(x + (width / 3), y, width / 3, height) - break - case 'sc': // Straight cross - ctx.fillRect(x, y + (height / 2) - 1, width, 2) - ctx.fillRect(x + (width / 2) - 1, y, 2, height) - break - default: - // Default: fill entire area - ctx.fillRect(x, y, width, height) - } -} - -// Create a cache key from banner content (base color + patterns) -function createBannerCacheKey (baseColor: number, patterns: Array<{ Color?: number, Pattern?: string }> | undefined): string { - if (!patterns || patterns.length === 0) { - return `banner_${baseColor}_empty` - } - const patternStr = patterns.map(p => `${p.Pattern ?? 'bs'}_${p.Color ?? 0}`).join(',') - return `banner_${baseColor}_${patternStr}` -} - -export const renderBanner = ( - baseColor: number, - blockEntity: BannerBlockEntity, - canvasCreator = (width: number, height: number): OffscreenCanvas => { - return createCanvas(width, height) - } -) => { - // Create canvas with banner cloth size (20x40) - const scale = 1 - const canvas = canvasCreator(BANNER_WIDTH * scale, BANNER_HEIGHT * scale) - const ctx = canvas.getContext('2d')! - - if (!ctx) { - console.warn('Failed to get 2d context for banner rendering') - return undefined - } - - ctx.imageSmoothingEnabled = false - - // Base color rendering disabled - // // Always render base color first (even if no patterns) - // const baseColorHex = BANNER_COLORS[baseColor] || BANNER_COLORS[15] - // ctx.fillStyle = baseColorHex - // ctx.fillRect(0, 0, BANNER_WIDTH * scale, BANNER_HEIGHT * scale) - - // Render patterns on top of base color (if any) - if (blockEntity?.Patterns && blockEntity.Patterns.length > 0) { - for (const patternData of blockEntity.Patterns) { - const colorId = patternData.Color ?? 0 - const pattern = patternData.Pattern ?? 'bs' - const color = BANNER_COLORS[colorId] || BANNER_COLORS[0] - - // Render each pattern on top of previous ones - renderPattern( - ctx, - pattern, - color, - 0, - 0, - BANNER_WIDTH * scale, - BANNER_HEIGHT * scale - ) - } - } - - return canvas -} - - -// Banner texture cache with reference counting -const bannerTextureCache = new Map() - -export function getBannerTexture ( - worldRenderer: WorldRendererThree, - blockName: string, - blockEntity: any -): THREE.Texture | undefined { - // Extract base color from block name - const baseColor = getBannerBaseColor(blockName) - - // Create cache key from banner content (not position) - const cacheKey = createBannerCacheKey(baseColor, blockEntity?.Patterns) - - // Check cache - const cached = bannerTextureCache.get(cacheKey) - if (cached) { - cached.refCount++ - return cached.texture - } - - // Render new banner - const canvas = renderBanner(baseColor, blockEntity) - if (!canvas) return undefined - - const tex = new THREE.Texture(canvas) - tex.magFilter = THREE.NearestFilter - tex.minFilter = THREE.NearestFilter - tex.needsUpdate = true - - // Store in cache with reference count - bannerTextureCache.set(cacheKey, { texture: tex, refCount: 1 }) - return tex -} - -export function releaseBannerTexture (texture: THREE.Texture): void { - // Find and decrement reference count - for (const [key, cached] of bannerTextureCache.entries()) { - if (cached.texture === texture) { - cached.refCount-- - if (cached.refCount <= 0) { - // Cleanup unused texture - cached.texture.dispose() - bannerTextureCache.delete(key) - } - return - } - } -} - -export function createBannerMesh ( - position: Vec3, - rotation: number, - isWall: boolean, - texture: THREE.Texture -): THREE.Group & { bannerTexture?: THREE.Texture } { - const bannerWidth = 13.6 / 16 - const bannerHeight = 28 / 16 - const clothXOffset = 0 - - let clothYOffset: number - let clothZPosition: number - let heightOffset: number - - if (isWall) { - // Wall banner: Cloth from [1.2, -14.6, 14.5] to [14.8, 13.4, 15] - clothYOffset = (-14.6 + 13.4) / 2 / 16 - 0.5 - clothZPosition = 1 - 14.75 / 16 - 0.5 - heightOffset = 1 / 2 - } else { - // Standing banner: Cloth from [1.2, 1.4, 7] to [14.8, 29.4, 7.5] - clothYOffset = (1.4 + 29.4) / 2 / 16 - clothZPosition = 1 - 7.25 / 16 - 0.5 - heightOffset = 0 - } - - const mesh = new THREE.Mesh( - new THREE.PlaneGeometry(bannerWidth, bannerHeight), - new THREE.MeshBasicMaterial({ map: texture, transparent: true }) - ) - mesh.renderOrder = 999 - - const thickness = 0.5 / 16 - const wallSpacing = 0.25 / 16 - if (isWall) { - mesh.position.set(clothXOffset, clothYOffset, clothZPosition + wallSpacing + 0.004) - } else { - mesh.position.set(clothXOffset, clothYOffset, clothZPosition + thickness / 2 + 0.004) - } - - const group = new THREE.Group() as THREE.Group & { bannerTexture?: THREE.Texture } - group.rotation.set( - 0, - -THREE.MathUtils.degToRad(rotation * (isWall ? 90 : 45 / 2)), - 0 - ) - group.add(mesh) - group.bannerTexture = texture - group.position.set(position.x + 0.5, position.y + heightOffset, position.z + 0.5) - return group -} diff --git a/renderer/viewer/three/cameraShake.ts b/renderer/viewer/three/cameraShake.ts deleted file mode 100644 index 7b1595092..000000000 --- a/renderer/viewer/three/cameraShake.ts +++ /dev/null @@ -1,120 +0,0 @@ -import * as THREE from 'three' -import { WorldRendererThree } from './worldrendererThree' - -export class CameraShake { - private rollAngle = 0 - private get damageRollAmount () { return 5 } - private get damageAnimDuration () { return 200 } - private rollAnimation?: { startTime: number, startRoll: number, targetRoll: number, duration: number, returnToZero?: boolean } - private basePitch = 0 - private baseYaw = 0 - - constructor (public worldRenderer: WorldRendererThree, public onRenderCallbacks: Array<() => void>) { - onRenderCallbacks.push(() => { - this.update() - }) - } - - setBaseRotation (pitch: number, yaw: number) { - this.basePitch = pitch - this.baseYaw = yaw - this.update() - } - - getBaseRotation () { - return { pitch: this.basePitch, yaw: this.baseYaw } - } - - shakeFromDamage (yaw?: number) { - // Add roll animation - const startRoll = this.rollAngle - const targetRoll = startRoll + (yaw ?? (Math.random() < 0.5 ? -1 : 1)) * this.damageRollAmount - - this.rollAnimation = { - startTime: performance.now(), - startRoll, - targetRoll, - duration: this.damageAnimDuration / 2 - } - } - - update () { - if (this.worldRenderer.playerStateUtils.isSpectatingEntity()) { - // Remove any shaking when spectating - this.rollAngle = 0 - this.rollAnimation = undefined - } - // Update roll animation - if (this.rollAnimation) { - const now = performance.now() - const elapsed = now - this.rollAnimation.startTime - const progress = Math.min(elapsed / this.rollAnimation.duration, 1) - - if (this.rollAnimation.returnToZero) { - // Ease back to zero - this.rollAngle = this.rollAnimation.startRoll * (1 - this.easeInOut(progress)) - if (progress === 1) { - this.rollAnimation = undefined - } - } else { - // Initial roll - this.rollAngle = this.rollAnimation.startRoll + (this.rollAnimation.targetRoll - this.rollAnimation.startRoll) * this.easeOut(progress) - if (progress === 1) { - // Start return to zero animation - this.rollAnimation = { - startTime: now, - startRoll: this.rollAngle, - targetRoll: 0, - duration: this.damageAnimDuration / 2, - returnToZero: true - } - } - } - } - - const camera = this.worldRenderer.cameraObject - - if (this.worldRenderer.cameraGroupVr) { - // For VR camera, only apply yaw rotation - const yawQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), this.baseYaw) - camera.setRotationFromQuaternion(yawQuat) - } else { - // For regular camera, apply all rotations - // Add tiny offsets to prevent z-fighting at ideal angles (90, 180, 270 degrees) - const pitchOffset = this.addAntiZfightingOffset(this.basePitch) - const yawOffset = this.addAntiZfightingOffset(this.baseYaw) - - const pitchQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), pitchOffset) - const yawQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), yawOffset) - const rollQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 0, 1), THREE.MathUtils.degToRad(this.rollAngle)) - // Combine rotations in the correct order: pitch -> yaw -> roll - const finalQuat = yawQuat.multiply(pitchQuat).multiply(rollQuat) - camera.setRotationFromQuaternion(finalQuat) - } - } - - private easeOut (t: number): number { - return 1 - (1 - t) * (1 - t) - } - - private easeInOut (t: number): number { - return t < 0.5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2 - } - - private addAntiZfightingOffset (angle: number): number { - const offset = 0.001 // Very small offset in radians (about 0.057 degrees) - - // Check if the angle is close to ideal angles (0, π/2, π, 3π/2) - const normalizedAngle = ((angle % (Math.PI * 2)) + Math.PI * 2) % (Math.PI * 2) - const tolerance = 0.01 // Tolerance for considering an angle "ideal" - - if (Math.abs(normalizedAngle) < tolerance || - Math.abs(normalizedAngle - Math.PI / 2) < tolerance || - Math.abs(normalizedAngle - Math.PI) < tolerance || - Math.abs(normalizedAngle - 3 * Math.PI / 2) < tolerance) { - return angle + offset - } - - return angle - } -} diff --git a/renderer/viewer/three/documentRenderer.ts b/renderer/viewer/three/documentRenderer.ts deleted file mode 100644 index db83a22dc..000000000 --- a/renderer/viewer/three/documentRenderer.ts +++ /dev/null @@ -1,327 +0,0 @@ -import * as THREE from 'three' -import Stats from 'stats.js' -import StatsGl from 'stats-gl' -import * as tween from '@tweenjs/tween.js' -import { GraphicsBackendConfig, GraphicsInitOptions } from '../../../src/appViewer' -import { WorldRendererConfig } from '../lib/worldrendererCommon' - -export class DocumentRenderer { - canvas: HTMLCanvasElement | OffscreenCanvas - readonly renderer: THREE.WebGLRenderer - private animationFrameId?: number - private timeoutId?: number - private lastRenderTime = 0 - - private previousCanvasWidth = 0 - private previousCanvasHeight = 0 - private currentWidth = 0 - private currentHeight = 0 - - private renderedFps = 0 - private fpsInterval: any - private readonly stats: TopRightStats | undefined - private paused = false - disconnected = false - preRender = () => { } - render = (sizeChanged: boolean) => { } - postRender = () => { } - sizeChanged = () => { } - droppedFpsPercentage: number - config: GraphicsBackendConfig - onRender = [] as Array<(sizeChanged: boolean) => void> - inWorldRenderingConfig: WorldRendererConfig | undefined - - constructor (initOptions: GraphicsInitOptions, public externalCanvas?: OffscreenCanvas) { - this.config = initOptions.config - - // Handle canvas creation/transfer based on context - if (externalCanvas) { - this.canvas = externalCanvas - } else { - this.addToPage() - } - - try { - this.renderer = new THREE.WebGLRenderer({ - canvas: this.canvas, - preserveDrawingBuffer: true, - logarithmicDepthBuffer: true, - powerPreference: this.config.powerPreference - }) - } catch (err) { - initOptions.callbacks.displayCriticalError(new Error(`Failed to create WebGL context, not possible to render (restart browser): ${err.message}`)) - throw err - } - this.renderer.useLegacyLights = true - this.renderer.outputColorSpace = THREE.LinearSRGBColorSpace - if (!externalCanvas) { - this.updatePixelRatio() - } - this.sizeUpdated() - // Initialize previous dimensions - this.previousCanvasWidth = this.canvas.width - this.previousCanvasHeight = this.canvas.height - - const supportsWebGL2 = 'WebGL2RenderingContext' in window - // Only initialize stats and DOM-related features in main thread - if (!externalCanvas && supportsWebGL2) { - this.stats = new TopRightStats(this.canvas as HTMLCanvasElement, this.config.statsVisible) - this.setupFpsTracking() - } - - this.startRenderLoop() - } - - updatePixelRatio () { - let pixelRatio = window.devicePixelRatio || 1 // todo this value is too high on ios, need to check, probably we should use avg, also need to make it configurable - if (!this.renderer.capabilities.isWebGL2) { - pixelRatio = 1 // webgl1 has issues with high pixel ratio (sometimes screen is clipped) - } - this.renderer.setPixelRatio(pixelRatio) - } - - sizeUpdated () { - this.renderer.setSize(this.currentWidth, this.currentHeight, false) - } - - private addToPage () { - this.canvas = addCanvasToPage() - this.updateCanvasSize() - } - - updateSizeExternal (newWidth: number, newHeight: number, pixelRatio: number) { - this.currentWidth = newWidth - this.currentHeight = newHeight - this.renderer.setPixelRatio(pixelRatio) - this.sizeUpdated() - } - - private updateCanvasSize () { - if (!this.externalCanvas) { - const innnerWidth = window.innerWidth - const innnerHeight = window.innerHeight - if (this.currentWidth !== innnerWidth) { - this.currentWidth = innnerWidth - } - if (this.currentHeight !== innnerHeight) { - this.currentHeight = innnerHeight - } - } - } - - private setupFpsTracking () { - let max = 0 - this.fpsInterval = setInterval(() => { - if (max > 0) { - this.droppedFpsPercentage = this.renderedFps / max - } - max = Math.max(this.renderedFps, max) - this.renderedFps = 0 - }, 1000) - } - - private startRenderLoop () { - const animate = () => { - if (this.disconnected) return - - if (this.config.timeoutRendering) { - this.timeoutId = setTimeout(animate, this.config.fpsLimit ? 1000 / this.config.fpsLimit : 0) as unknown as number - } else { - this.animationFrameId = requestAnimationFrame(animate) - } - - if (this.paused || (this.renderer.xr.isPresenting && !this.inWorldRenderingConfig?.vrPageGameRendering)) return - - // Handle FPS limiting - if (this.config.fpsLimit) { - const now = performance.now() - const elapsed = now - this.lastRenderTime - const fpsInterval = 1000 / this.config.fpsLimit - - if (elapsed < fpsInterval) { - return - } - - this.lastRenderTime = now - (elapsed % fpsInterval) - } - - let sizeChanged = false - this.updateCanvasSize() - if (this.previousCanvasWidth !== this.currentWidth || this.previousCanvasHeight !== this.currentHeight) { - this.previousCanvasWidth = this.currentWidth - this.previousCanvasHeight = this.currentHeight - this.sizeUpdated() - sizeChanged = true - } - - this.frameRender(sizeChanged) - - // Update stats visibility each frame (main thread only) - if (this.config.statsVisible !== undefined) { - this.stats?.setVisibility(this.config.statsVisible) - } - } - - animate() - } - - frameRender (sizeChanged: boolean) { - this.preRender() - this.stats?.markStart() - tween.update() - if (!globalThis.freezeRender) { - this.render(sizeChanged) - } - for (const fn of this.onRender) { - fn(sizeChanged) - } - this.renderedFps++ - this.stats?.markEnd() - this.postRender() - } - - setPaused (paused: boolean) { - this.paused = paused - } - - dispose () { - this.disconnected = true - if (this.animationFrameId) { - cancelAnimationFrame(this.animationFrameId) - } - if (this.timeoutId) { - clearTimeout(this.timeoutId) - } - if (this.canvas instanceof HTMLCanvasElement) { - this.canvas.remove() - } - clearInterval(this.fpsInterval) - this.stats?.dispose() - this.renderer.dispose() - } -} - -class TopRightStats { - private readonly stats: Stats - private readonly stats2: Stats - private readonly statsGl: StatsGl - private total = 0 - private readonly denseMode: boolean - - constructor (private readonly canvas: HTMLCanvasElement, initialStatsVisible = 0) { - this.stats = new Stats() - this.stats2 = new Stats() - this.statsGl = new StatsGl({ minimal: true }) - this.stats2.showPanel(2) - this.denseMode = process.env.NODE_ENV === 'production' || window.innerHeight < 500 - - this.initStats() - this.setVisibility(initialStatsVisible) - } - - private addStat (dom: HTMLElement, size = 80) { - dom.style.position = 'absolute' - if (this.denseMode) dom.style.height = '12px' - dom.style.overflow = 'hidden' - dom.style.left = '' - dom.style.top = '0' - dom.style.right = `${this.total}px` - dom.style.width = '80px' - dom.style.zIndex = '1' - dom.style.opacity = '0.8' - const container = document.getElementById('corner-indicator-stats') ?? document.body - container.appendChild(dom) - this.total += size - } - - private initStats () { - const hasRamPanel = this.stats2.dom.children.length === 3 - - this.addStat(this.stats.dom) - this.stats.dom.style.position = 'relative' - if (hasRamPanel) { - this.addStat(this.stats2.dom) - } - - this.statsGl.init(this.canvas) - this.statsGl.container.style.display = 'flex' - this.statsGl.container.style.justifyContent = 'flex-end' - - let i = 0 - for (const _child of this.statsGl.container.children) { - const child = _child as HTMLElement - if (i++ === 0) { - child.style.display = 'none' - } - child.style.position = '' - } - } - - setVisibility (level: number) { - const visible = level > 0 - if (visible) { - this.stats.dom.style.display = 'block' - this.stats2.dom.style.display = level >= 2 ? 'block' : 'none' - this.statsGl.container.style.display = level >= 2 ? 'block' : 'none' - } else { - this.stats.dom.style.display = 'none' - this.stats2.dom.style.display = 'none' - this.statsGl.container.style.display = 'none' - } - } - - markStart () { - this.stats.begin() - this.stats2.begin() - this.statsGl.begin() - } - - markEnd () { - this.stats.end() - this.stats2.end() - this.statsGl.end() - } - - dispose () { - this.stats.dom.remove() - this.stats2.dom.remove() - this.statsGl.container.remove() - } -} - -const addCanvasToPage = () => { - const canvas = document.createElement('canvas') - canvas.id = 'viewer-canvas' - document.body.appendChild(canvas) - return canvas -} - -export const addCanvasForWorker = () => { - const canvas = addCanvasToPage() - const transferred = canvas.transferControlToOffscreen() - let removed = false - let onSizeChanged = (w, h) => { } - let oldSize = { width: 0, height: 0 } - const checkSize = () => { - if (removed) return - if (oldSize.width !== window.innerWidth || oldSize.height !== window.innerHeight) { - onSizeChanged(window.innerWidth, window.innerHeight) - oldSize = { width: window.innerWidth, height: window.innerHeight } - } - requestAnimationFrame(checkSize) - } - requestAnimationFrame(checkSize) - return { - canvas: transferred, - destroy () { - removed = true - canvas.remove() - }, - onSizeChanged (cb: (width: number, height: number) => void) { - onSizeChanged = cb - }, - get size () { - return { width: window.innerWidth, height: window.innerHeight } - } - } -} diff --git a/renderer/viewer/three/entities.ts b/renderer/viewer/three/entities.ts deleted file mode 100644 index cb445aded..000000000 --- a/renderer/viewer/three/entities.ts +++ /dev/null @@ -1,1519 +0,0 @@ -//@ts-check -import { UnionToIntersection } from 'type-fest' -import nbt from 'prismarine-nbt' -import * as TWEEN from '@tweenjs/tween.js' -import * as THREE from 'three' -import { PlayerAnimation, PlayerObject } from 'skinview3d' -import { inferModelType, loadCapeToCanvas, loadEarsToCanvasFromSkin } from 'skinview-utils' -// todo replace with url -import { degreesToRadians } from '@nxg-org/mineflayer-tracker/lib/mathUtils' -import { NameTagObject } from 'skinview3d/libs/nametag' -import { flat, fromFormattedString } from '@xmcl/text-component' -import mojangson from 'mojangson' -import { snakeCase } from 'change-case' -import { Item } from 'prismarine-item' -import { isEntityAttackable } from 'mineflayer-mouse/dist/attackableEntity' -import { Team } from 'mineflayer' -import PrismarineChatLoader from 'prismarine-chat' -import { EntityMetadataVersions } from '../../../src/mcDataTypes' -import { ItemSpecificContextProperties } from '../lib/basePlayerState' -import { loadSkinFromUsername, loadSkinImage, stevePngUrl } from '../lib/utils/skins' -import { renderComponent } from '../sign-renderer' -import { createCanvas } from '../lib/utils' -import { PlayerObjectType } from '../lib/createPlayerObject' -import { getBlockMeshFromModel } from './holdingBlock' -import { createItemMesh } from './itemMesh' -import * as Entity from './entity/EntityMesh' -import { getMesh } from './entity/EntityMesh' -import { WalkingGeneralSwing } from './entity/animations' -import { disposeObject, loadTexture, loadThreeJsTextureFromUrl } from './threeJsUtils' -import { armorModel, armorTextures, elytraTexture } from './entity/armorModels' -import { WorldRendererThree } from './worldrendererThree' - -export const steveTexture = loadThreeJsTextureFromUrl(stevePngUrl) - -export const TWEEN_DURATION = 120 - -function convert2sComplementToHex (complement: number) { - if (complement < 0) { - complement = (0xFF_FF_FF_FF + complement + 1) >>> 0 - } - return complement.toString(16) -} - -function toRgba (color: string | undefined) { - if (color === undefined) { - return undefined - } - if (parseInt(color, 10) === 0) { - return 'rgba(0, 0, 0, 0)' - } - const hex = convert2sComplementToHex(parseInt(color, 10)) - if (hex.length === 8) { - return `#${hex.slice(2, 8)}${hex.slice(0, 2)}` - } else { - return `#${hex}` - } -} - -function toQuaternion (quaternion: any, defaultValue?: THREE.Quaternion) { - if (quaternion === undefined) { - return defaultValue - } - if (quaternion instanceof THREE.Quaternion) { - return quaternion - } - if (Array.isArray(quaternion)) { - return new THREE.Quaternion(quaternion[0], quaternion[1], quaternion[2], quaternion[3]) - } - return new THREE.Quaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w) -} - -function poseToEuler (pose: any, defaultValue?: THREE.Euler) { - if (pose === undefined) { - return defaultValue ?? new THREE.Euler() - } - if (pose instanceof THREE.Euler) { - return pose - } - if (pose['yaw'] !== undefined && pose['pitch'] !== undefined && pose['roll'] !== undefined) { - // Convert Minecraft pitch, yaw, roll definitions to our angle system - return new THREE.Euler(-degreesToRadians(pose.pitch), -degreesToRadians(pose.yaw), degreesToRadians(pose.roll), 'ZYX') - } - if (pose['x'] !== undefined && pose['y'] !== undefined && pose['z'] !== undefined) { - return new THREE.Euler(pose.z, pose.y, pose.x, 'ZYX') - } - if (Array.isArray(pose)) { - return new THREE.Euler(pose[0], pose[1], pose[2]) - } - return defaultValue ?? new THREE.Euler() -} - -function getUsernameTexture ({ - username, - nameTagBackgroundColor = 'rgba(0, 0, 0, 0.3)', - nameTagTextOpacity = 255 -}: any, { fontFamily = 'mojangles' }: any, version: string) { - const canvas = createCanvas(64, 64) - - const PrismarineChat = PrismarineChatLoader(version) - - const ctx = canvas.getContext('2d') - if (!ctx) throw new Error('Could not get 2d context') - - const fontSize = 48 - const padding = 5 - ctx.font = `${fontSize}px ${fontFamily}` - - const plainLines = String(typeof username === 'string' ? username : new PrismarineChat(username).toString()).split('\n') - let textWidth = 0 - for (const line of plainLines) { - const width = ctx.measureText(line).width + padding * 2 - if (width > textWidth) textWidth = width - } - - canvas.width = textWidth - canvas.height = (fontSize + padding) * plainLines.length - - ctx.fillStyle = nameTagBackgroundColor - ctx.fillRect(0, 0, canvas.width, canvas.height) - - ctx.globalAlpha = nameTagTextOpacity / 255 - - renderComponent(username, PrismarineChat, canvas, fontSize, 'white', -padding + fontSize) - - ctx.globalAlpha = 1 - - return canvas -} - -const addNametag = (entity, options: { fontFamily: string }, mesh, version: string) => { - for (const c of mesh.children) { - if (c.name === 'nametag') { - c.removeFromParent() - } - } - if (entity.username !== undefined) { - const canvas = getUsernameTexture(entity, options, version) - const tex = new THREE.Texture(canvas) - tex.needsUpdate = true - let nameTag: THREE.Object3D - if (entity.nameTagFixed) { - const geometry = new THREE.PlaneGeometry() - const material = new THREE.MeshBasicMaterial({ map: tex }) - material.transparent = true - nameTag = new THREE.Mesh(geometry, material) - nameTag.rotation.set(entity.pitch, THREE.MathUtils.degToRad(entity.yaw + 180), 0) - nameTag.position.y += entity.height + 0.3 - } else { - const spriteMat = new THREE.SpriteMaterial({ map: tex }) - nameTag = new THREE.Sprite(spriteMat) - nameTag.position.y += entity.height + 0.6 - } - nameTag.renderOrder = 1000 - nameTag.scale.set(canvas.width * 0.005, canvas.height * 0.005, 1) - if (entity.nameTagRotationRight) { - nameTag.applyQuaternion(entity.nameTagRotationRight) - } - if (entity.nameTagScale) { - nameTag.scale.multiply(entity.nameTagScale) - } - if (entity.nameTagRotationLeft) { - nameTag.applyQuaternion(entity.nameTagRotationLeft) - } - if (entity.nameTagTranslation) { - nameTag.position.add(entity.nameTagTranslation) - } - nameTag.name = 'nametag' - - mesh.add(nameTag) - return nameTag - } -} - -// todo cleanup -const nametags = {} - -const isFirstUpperCase = (str) => str.charAt(0) === str.charAt(0).toUpperCase() - -function getEntityMesh (entity: import('prismarine-entity').Entity & { delete?: any; pos?: any; name?: any }, world: WorldRendererThree, options: { fontFamily: string }, overrides) { - if (entity.name) { - try { - // https://github.com/PrismarineJS/prismarine-viewer/pull/410 - const entityName = (isFirstUpperCase(entity.name) ? snakeCase(entity.name) : entity.name).toLowerCase() - const e = new Entity.EntityMesh('1.16.4', entityName, world, overrides) - - if (e.mesh) { - addNametag(entity, options, e.mesh, world.version) - return e.mesh - } - } catch (err) { - reportError?.(err) - } - } - - if (!isEntityAttackable(loadedData, entity)) return - const geometry = new THREE.BoxGeometry(entity.width, entity.height, entity.width) - geometry.translate(0, entity.height / 2, 0) - const material = new THREE.MeshBasicMaterial({ color: 0xff_00_ff }) - const cube = new THREE.Mesh(geometry, material) - const nametagCount = (nametags[entity.name] = (nametags[entity.name] || 0) + 1) - if (nametagCount < 6) { - addNametag({ - username: entity.name, - height: entity.height, - }, options, cube, world.version) - } - return cube -} - -export type SceneEntity = THREE.Object3D & { - playerObject?: PlayerObjectType - username?: string - uuid?: string - additionalCleanup?: () => void - originalEntity: import('prismarine-entity').Entity & { delete?; pos?, name, team?: Team } -} - -export class Entities { - entities = {} as Record - playerEntity: SceneEntity | null = null // Special entity for the player in third person - entitiesOptions = { - fontFamily: 'mojangles' - } - debugMode: string - onSkinUpdate: () => void - clock = new THREE.Clock() - currentlyRendering = true - cachedMapsImages = {} as Record - itemFrameMaps = {} as Record>> - - get entitiesByName (): Record { - const byName: Record = {} - for (const entity of Object.values(this.entities)) { - if (!entity['realName']) continue - byName[entity['realName']] = byName[entity['realName']] || [] - byName[entity['realName']].push(entity) - } - return byName - } - - get entitiesRenderingCount (): number { - return Object.values(this.entities).filter(entity => entity.visible).length - } - - getDebugString (): string { - const totalEntities = Object.keys(this.entities).length - const visibleEntities = this.entitiesRenderingCount - - const playerEntities = Object.values(this.entities).filter(entity => entity.playerObject) - const visiblePlayerEntities = playerEntities.filter(entity => entity.visible) - - return `${visibleEntities}/${totalEntities} ${visiblePlayerEntities.length}/${playerEntities.length}` - } - - constructor (public worldRenderer: WorldRendererThree) { - this.debugMode = 'none' - this.onSkinUpdate = () => { } - this.watchResourcesUpdates() - } - - handlePlayerEntity (playerData: SceneEntity['originalEntity']) { - // Create player entity if it doesn't exist - if (!this.playerEntity) { - // Create the player entity similar to how normal entities are created - const group = new THREE.Group() as unknown as SceneEntity - group.originalEntity = { ...playerData, name: 'player' } as SceneEntity['originalEntity'] - - const wrapper = new THREE.Group() - const playerObject = this.setupPlayerObject(playerData, wrapper, {}) - group.playerObject = playerObject - group.add(wrapper) - - group.name = 'player_entity' - this.playerEntity = group - this.worldRenderer.scene.add(group) - - void this.updatePlayerSkin(playerData.id, playerData.username, playerData.uuid ?? undefined, stevePngUrl) - } - this.playerEntity.originalEntity = { ...playerData, name: 'player' } as SceneEntity['originalEntity'] - - // Update position and rotation - if (playerData.position) { - this.playerEntity.position.set(playerData.position.x, playerData.position.y, playerData.position.z) - } - if (playerData.yaw !== undefined) { - this.playerEntity.rotation.y = playerData.yaw - } - - this.updateEntityEquipment(this.playerEntity, playerData) - } - - clear () { - for (const mesh of Object.values(this.entities)) { - this.worldRenderer.scene.remove(mesh) - disposeObject(mesh) - } - this.entities = {} - this.currentSkinUrls = {} - - // Clean up player entity - if (this.playerEntity) { - this.worldRenderer.scene.remove(this.playerEntity) - disposeObject(this.playerEntity) - this.playerEntity = null - } - } - - reloadEntities () { - for (const entity of Object.values(this.entities)) { - // update all entities textures like held items, armour, etc - // todo update entity textures itself - this.update({ ...entity.originalEntity, delete: true, } as SceneEntity['originalEntity'], {}) - this.update(entity.originalEntity, {}) - } - } - - watchResourcesUpdates () { - this.worldRenderer.resourcesManager.on('assetsTexturesUpdated', () => this.reloadEntities()) - this.worldRenderer.resourcesManager.on('assetsInventoryReady', () => this.reloadEntities()) - } - - setDebugMode (mode: string, entity: THREE.Object3D | null = null) { - this.debugMode = mode - for (const mesh of entity ? [entity] : Object.values(this.entities)) { - const boxHelper = mesh.children.find(c => c.name === 'debug')! - boxHelper.visible = false - if (this.debugMode === 'basic') { - boxHelper.visible = true - } - // todo advanced - } - } - - setRendering (rendering: boolean, entity: THREE.Object3D | null = null) { - this.currentlyRendering = rendering - for (const ent of entity ? [entity] : Object.values(this.entities)) { - if (rendering) { - if (!this.worldRenderer.scene.children.includes(ent)) this.worldRenderer.scene.add(ent) - } else { - this.worldRenderer.scene.remove(ent) - } - } - } - - render () { - const renderEntitiesConfig = this.worldRenderer.worldRendererConfig.renderEntities - if (renderEntitiesConfig !== this.currentlyRendering) { - this.setRendering(renderEntitiesConfig) - } - - const dt = this.clock.getDelta() - const botPos = this.worldRenderer.viewerChunkPosition - const VISIBLE_DISTANCE = 10 * 10 - - // Update regular entities - for (const [entityId, entity] of [...Object.entries(this.entities), ['player_entity', this.playerEntity] as [string, SceneEntity | null]]) { - if (!entity) continue - const { playerObject } = entity - - // Update animations - if (playerObject?.animation) { - playerObject.animation.update(playerObject, dt) - } - - // Update visibility based on distance and chunk load status - if (botPos && entity.position) { - const dx = entity.position.x - botPos.x - const dy = entity.position.y - botPos.y - const dz = entity.position.z - botPos.z - const distanceSquared = dx * dx + dy * dy + dz * dz - - // Entity is visible if within 20 blocks OR in a finished chunk - entity.visible = !!(distanceSquared < VISIBLE_DISTANCE || this.worldRenderer.shouldObjectVisible(entity)) - - this.maybeRenderPlayerSkin(entityId) - } - - if (entity.visible) { - // Update armor positions - this.syncArmorPositions(entity) - } - - if (entityId === 'player_entity') { - entity.visible = this.worldRenderer.playerStateUtils.isThirdPerson() - - if (entity.visible) { - // sync - const yOffset = this.worldRenderer.playerStateReactive.eyeHeight - const pos = this.worldRenderer.cameraObject.position.clone().add(new THREE.Vector3(0, -yOffset, 0)) - entity.position.set(pos.x, pos.y, pos.z) - - const rotation = this.worldRenderer.cameraShake.getBaseRotation() - entity.rotation.set(0, rotation.yaw, 0) - - // Sync head rotation - entity.traverse((c) => { - if (c.name === 'head') { - c.rotation.set(-rotation.pitch, 0, 0) - } - }) - } - } - } - } - - private syncArmorPositions (entity: SceneEntity) { - if (!entity.playerObject) return - - // todo-low use property access for less loop iterations (small performance gain) - entity.traverse((armor) => { - if (!armor.name.startsWith('geometry_armor_')) return - - const { skin } = entity.playerObject! - - switch (armor.name) { - case 'geometry_armor_head': - // Head armor sync - if (armor.children[0]?.children[0]) { - armor.children[0].children[0].rotation.set( - -skin.head.rotation.x, - skin.head.rotation.y, - skin.head.rotation.z, - skin.head.rotation.order - ) - } - break - - case 'geometry_armor_legs': - // Legs armor sync - if (armor.children[0]) { - // Left leg - if (armor.children[0].children[2]) { - armor.children[0].children[2].rotation.set( - -skin.leftLeg.rotation.x, - skin.leftLeg.rotation.y, - skin.leftLeg.rotation.z, - skin.leftLeg.rotation.order - ) - } - // Right leg - if (armor.children[0].children[1]) { - armor.children[0].children[1].rotation.set( - -skin.rightLeg.rotation.x, - skin.rightLeg.rotation.y, - skin.rightLeg.rotation.z, - skin.rightLeg.rotation.order - ) - } - } - break - - case 'geometry_armor_feet': - // Boots armor sync - if (armor.children[0]) { - // Right boot - if (armor.children[0].children[0]) { - armor.children[0].children[0].rotation.set( - -skin.rightLeg.rotation.x, - skin.rightLeg.rotation.y, - skin.rightLeg.rotation.z, - skin.rightLeg.rotation.order - ) - } - // Left boot (reversed Z rotation) - if (armor.children[0].children[1]) { - armor.children[0].children[1].rotation.set( - -skin.leftLeg.rotation.x, - skin.leftLeg.rotation.y, - -skin.leftLeg.rotation.z, - skin.leftLeg.rotation.order - ) - } - } - break - } - }) - } - - getPlayerObject (entityId: string | number) { - if (this.playerEntity?.originalEntity.id === entityId) return this.playerEntity?.playerObject - const playerObject = this.entities[entityId]?.playerObject - return playerObject - } - - uuidPerSkinUrlsCache = {} as Record - currentSkinUrls = {} as Record - - private isCanvasBlank (canvas: HTMLCanvasElement): boolean { - return !canvas.getContext('2d') - ?.getImageData(0, 0, canvas.width, canvas.height).data - .some(channel => channel !== 0) - } - - // todo true/undefined doesnt reset the skin to the default one - // eslint-disable-next-line max-params - async updatePlayerSkin (entityId: string | number, username: string | undefined, uuidCache: string | undefined, skinUrl: string | true, capeUrl: string | true | undefined = undefined) { - const isCustomSkin = skinUrl !== stevePngUrl - if (isCustomSkin) { - this.loadedSkinEntityIds.add(String(entityId)) - } - if (uuidCache) { - if (typeof skinUrl === 'string' || typeof capeUrl === 'string') this.uuidPerSkinUrlsCache[uuidCache] = {} - if (typeof skinUrl === 'string') this.uuidPerSkinUrlsCache[uuidCache].skinUrl = skinUrl - if (typeof capeUrl === 'string') this.uuidPerSkinUrlsCache[uuidCache].capeUrl = capeUrl - if (skinUrl === true) { - skinUrl = this.uuidPerSkinUrlsCache[uuidCache]?.skinUrl ?? skinUrl - } - capeUrl ??= this.uuidPerSkinUrlsCache[uuidCache]?.capeUrl - } - - const playerObject = this.getPlayerObject(entityId) - if (!playerObject) return - - if (skinUrl === true) { - if (!username) return - const newSkinUrl = await loadSkinFromUsername(username, 'skin') - if (!this.getPlayerObject(entityId)) return - if (!newSkinUrl) return - skinUrl = newSkinUrl - } - - if (typeof skinUrl !== 'string') throw new Error('Invalid skin url') - - // Skip if same skin URL is already loaded for this entity - if (this.currentSkinUrls[String(entityId)] === skinUrl) { - // Still handle cape if needed - if (capeUrl) { - if (capeUrl === true && username) { - const newCapeUrl = await loadSkinFromUsername(username, 'cape') - if (!this.getPlayerObject(entityId)) return - if (!newCapeUrl) return - capeUrl = newCapeUrl - } - if (typeof capeUrl === 'string') { - void this.loadAndApplyCape(entityId, capeUrl) - } - } - return - } - - if (skinUrl !== stevePngUrl) { - this.currentSkinUrls[String(entityId)] = skinUrl - } - const renderEars = this.worldRenderer.worldRendererConfig.renderEars || username === 'deadmau5' - void this.loadAndApplySkin(entityId, skinUrl, renderEars).then(async () => { - if (capeUrl) { - if (capeUrl === true && username) { - const newCapeUrl = await loadSkinFromUsername(username, 'cape') - if (!this.getPlayerObject(entityId)) return - if (!newCapeUrl) return - capeUrl = newCapeUrl - } - if (typeof capeUrl === 'string') { - void this.loadAndApplyCape(entityId, capeUrl) - } - } - }) - - - playerObject.cape.visible = false - if (!capeUrl) { - playerObject.backEquipment = null - playerObject.elytra.map = null - if (playerObject.cape.map) { - playerObject.cape.map.dispose() - } - playerObject.cape.map = null - } - } - - private async loadAndApplySkin (entityId: string | number, skinUrl: string, renderEars: boolean) { - let playerObject = this.getPlayerObject(entityId) - if (!playerObject) return - - try { - let playerCustomSkinImage: ImageBitmap | undefined - - playerObject = this.getPlayerObject(entityId) - if (!playerObject) return - - let skinTexture: THREE.Texture - let skinCanvas: OffscreenCanvas - if (skinUrl === stevePngUrl) { - skinTexture = await steveTexture - const canvas = createCanvas(64, 64) - const ctx = canvas.getContext('2d') - if (!ctx) throw new Error('Failed to get context') - ctx.drawImage(skinTexture.image, 0, 0) - skinCanvas = canvas - } else { - const { canvas, image } = await loadSkinImage(skinUrl) - playerCustomSkinImage = image - skinTexture = new THREE.CanvasTexture(canvas) - skinCanvas = canvas - } - - skinTexture.magFilter = THREE.NearestFilter - skinTexture.minFilter = THREE.NearestFilter - skinTexture.needsUpdate = true - playerObject.skin.map = skinTexture as any - playerObject.skin.modelType = inferModelType(skinCanvas) - playerObject.skin['isCustom'] = skinUrl !== stevePngUrl - - let earsCanvas: HTMLCanvasElement | undefined - if (!playerCustomSkinImage) { - renderEars = false - } else if (renderEars) { - earsCanvas = document.createElement('canvas') - loadEarsToCanvasFromSkin(earsCanvas, playerCustomSkinImage) - renderEars = !this.isCanvasBlank(earsCanvas) - } - if (renderEars) { - const earsTexture = new THREE.CanvasTexture(earsCanvas!) - earsTexture.magFilter = THREE.NearestFilter - earsTexture.minFilter = THREE.NearestFilter - earsTexture.needsUpdate = true - //@ts-expect-error - playerObject.ears.map = earsTexture - playerObject.ears.visible = true - } else { - playerObject.ears.map = null - playerObject.ears.visible = false - } - this.onSkinUpdate?.() - } catch (error) { - console.error('Error loading skin:', error) - } - } - - private async loadAndApplyCape (entityId: string | number, capeUrl: string) { - let playerObject = this.getPlayerObject(entityId) - if (!playerObject) return - - try { - const { canvas: capeCanvas, image: capeImage } = await loadSkinImage(capeUrl) - - playerObject = this.getPlayerObject(entityId) - if (!playerObject) return - - loadCapeToCanvas(capeCanvas, capeImage) - const capeTexture = new THREE.CanvasTexture(capeCanvas) - capeTexture.magFilter = THREE.NearestFilter - capeTexture.minFilter = THREE.NearestFilter - capeTexture.needsUpdate = true - //@ts-expect-error - playerObject.cape.map = capeTexture - playerObject.cape.visible = true - //@ts-expect-error - playerObject.elytra.map = capeTexture - this.onSkinUpdate?.() - - if (!playerObject.backEquipment) { - playerObject.backEquipment = 'cape' - } - } catch (error) { - console.error('Error loading cape:', error) - } - } - - debugSwingArm () { - const playerObject = Object.values(this.entities).find(entity => entity.playerObject?.animation instanceof WalkingGeneralSwing) - if (!playerObject) return - (playerObject.playerObject!.animation as WalkingGeneralSwing).swingArm() - } - - playAnimation (entityPlayerId, animation: 'walking' | 'running' | 'oneSwing' | 'idle' | 'crouch' | 'crouchWalking') { - // TODO CLEANUP! - // Handle special player entity ID for bot entity in third person - if (entityPlayerId === 'player_entity' && this.playerEntity?.playerObject) { - const { playerObject } = this.playerEntity - if (animation === 'oneSwing') { - if (!(playerObject.animation instanceof WalkingGeneralSwing)) throw new Error('Expected WalkingGeneralSwing') - playerObject.animation.swingArm() - return - } - - if (playerObject.animation instanceof WalkingGeneralSwing) { - playerObject.animation.switchAnimationCallback = () => { - if (!(playerObject.animation instanceof WalkingGeneralSwing)) throw new Error('Expected WalkingGeneralSwing') - playerObject.animation.isMoving = animation === 'walking' || animation === 'running' || animation === 'crouchWalking' - playerObject.animation.isRunning = animation === 'running' - playerObject.animation.isCrouched = animation === 'crouch' || animation === 'crouchWalking' - } - } - return - } - - // Handle regular entities - const playerObject = this.getPlayerObject(entityPlayerId) - if (playerObject) { - if (animation === 'oneSwing') { - if (!(playerObject.animation instanceof WalkingGeneralSwing)) throw new Error('Expected WalkingGeneralSwing') - playerObject.animation.swingArm() - return - } - - if (playerObject.animation instanceof WalkingGeneralSwing) { - playerObject.animation.switchAnimationCallback = () => { - if (!(playerObject.animation instanceof WalkingGeneralSwing)) throw new Error('Expected WalkingGeneralSwing') - playerObject.animation.isMoving = animation === 'walking' || animation === 'running' || animation === 'crouchWalking' - playerObject.animation.isRunning = animation === 'running' - playerObject.animation.isCrouched = animation === 'crouch' || animation === 'crouchWalking' - } - } - return - } - - // Handle player entity (for third person view) - fallback for backwards compatibility - if (this.playerEntity?.playerObject) { - const { playerObject: playerEntityObject } = this.playerEntity - if (animation === 'oneSwing') { - if (!(playerEntityObject.animation instanceof WalkingGeneralSwing)) throw new Error('Expected WalkingGeneralSwing') - playerEntityObject.animation.swingArm() - return - } - - if (playerEntityObject.animation instanceof WalkingGeneralSwing) { - playerEntityObject.animation.switchAnimationCallback = () => { - if (!(playerEntityObject.animation instanceof WalkingGeneralSwing)) throw new Error('Expected WalkingGeneralSwing') - playerEntityObject.animation.isMoving = animation === 'walking' || animation === 'running' || animation === 'crouchWalking' - playerEntityObject.animation.isRunning = animation === 'running' - playerEntityObject.animation.isCrouched = animation === 'crouch' || animation === 'crouchWalking' - } - } - } - } - - parseEntityLabel (jsonLike) { - if (!jsonLike) return - try { - if (jsonLike.type === 'string') { - return jsonLike.value - } - const parsed = typeof jsonLike === 'string' ? mojangson.simplify(mojangson.parse(jsonLike)) : nbt.simplify(jsonLike) - const text = flat(parsed).map(this.textFromComponent) - return text.join('') - } catch (err) { - return jsonLike - } - } - - private textFromComponent (component) { - return typeof component === 'string' ? component : component.text ?? '' - } - - getItemMesh (item, specificProps: ItemSpecificContextProperties, faceCamera = false, previousModel?: string) { - if (!item.nbt && item.nbtData) item.nbt = item.nbtData - const textureUv = this.worldRenderer.getItemRenderData(item, specificProps) - if (previousModel && previousModel === textureUv?.modelName) return undefined - - if (textureUv && 'resolvedModel' in textureUv) { - const mesh = getBlockMeshFromModel(this.worldRenderer.material, textureUv.resolvedModel, textureUv.modelName, this.worldRenderer.resourcesManager.currentResources.worldBlockProvider!) - let SCALE = 1 - if (specificProps['minecraft:display_context'] === 'ground') { - SCALE = 0.5 - } else if (specificProps['minecraft:display_context'] === 'thirdperson') { - SCALE = 6 - } - mesh.scale.set(SCALE, SCALE, SCALE) - const outerGroup = new THREE.Group() - outerGroup.add(mesh) - return { - mesh: outerGroup, - isBlock: true, - modelName: textureUv.modelName, - } - } - - // Render proper 3D model for items - if (textureUv) { - const textureThree = textureUv.renderInfo?.texture === 'blocks' ? this.worldRenderer.material.map! : this.worldRenderer.itemsTexture - const { u, v, su, sv } = textureUv - const sizeX = su ?? 1 // su is actually width - const sizeY = sv ?? 1 // sv is actually height - - // Use the new unified item mesh function - const result = createItemMesh(textureThree, { - u, - v, - sizeX, - sizeY - }, { - faceCamera, - use3D: !faceCamera, // Only use 3D for non-camera-facing items - }) - - let SCALE = 1 - if (specificProps['minecraft:display_context'] === 'ground') { - SCALE = 0.5 - } else if (specificProps['minecraft:display_context'] === 'thirdperson') { - SCALE = 6 - } - result.mesh.scale.set(SCALE, SCALE, SCALE) - - return { - mesh: result.mesh, - isBlock: false, - modelName: textureUv.modelName, - cleanup: result.cleanup - } - } - } - - setVisible (mesh: THREE.Object3D, visible: boolean) { - //mesh.visible = visible - //TODO: Fix workaround for visibility setting - if (visible) { - mesh.scale.set(1, 1, 1) - } else { - mesh.scale.set(0, 0, 0) - } - } - - update (entity: SceneEntity['originalEntity'], overrides) { - const isPlayerModel = entity.name === 'player' - if (entity.name === 'zombie_villager' || entity.name === 'husk') { - overrides.texture = `textures/1.16.4/entity/${entity.name === 'zombie_villager' ? 'zombie_villager/zombie_villager.png' : `zombie/${entity.name}.png`}` - } - if (entity.name === 'glow_item_frame') { - if (!overrides.textures) overrides.textures = [] - overrides.textures['background'] = 'block:glow_item_frame' - } - // this can be undefined in case where packet entity_destroy was sent twice (so it was already deleted) - let e = this.entities[entity.id] - const justAdded = !e - - if (entity.delete) { - if (!e) return - if (e.additionalCleanup) e.additionalCleanup() - e.traverse(c => { - if (c['additionalCleanup']) c['additionalCleanup']() - }) - this.onRemoveEntity(entity) - this.worldRenderer.scene.remove(e) - disposeObject(e) - // todo dispose textures as well ? - delete this.entities[entity.id] - return - } - - let mesh: THREE.Object3D | undefined - if (e === undefined) { - const group = new THREE.Group() as unknown as SceneEntity - group.originalEntity = entity - if (entity.name === 'item' || entity.name === 'tnt' || entity.name === 'falling_block' || entity.name === 'snowball' - || entity.name === 'egg' || entity.name === 'ender_pearl' || entity.name === 'experience_bottle' - || entity.name === 'splash_potion' || entity.name === 'lingering_potion') { - const item = entity.name === 'tnt' || entity.type === 'projectile' - ? { name: entity.name } - : entity.name === 'falling_block' - ? { blockState: entity['objectData'] } - : entity.metadata?.find((m: any) => typeof m === 'object' && m?.itemCount) - if (item) { - const object = this.getItemMesh(item, { - 'minecraft:display_context': 'ground', - }, entity.type === 'projectile') - if (object) { - mesh = object.mesh - if (entity.name === 'item' || entity.type === 'projectile') { - mesh.scale.set(0.5, 0.5, 0.5) - mesh.position.set(0, entity.name === 'item' ? 0.2 : 0.1, 0) - } else { - mesh.scale.set(2, 2, 2) - mesh.position.set(0, 0.5, 0) - } - // set faces - // mesh.position.set(targetPos.x + 0.5 + 2, targetPos.y + 0.5, targetPos.z + 0.5) - // viewer.scene.add(mesh) - if (entity.name === 'item') { - const clock = new THREE.Clock() - mesh.onBeforeRender = () => { - const delta = clock.getDelta() - mesh!.rotation.y += delta - } - } - - // TNT blinking - // if (entity.name === 'tnt') { - // let lastBlink = 0 - // const blinkInterval = 500 // ms between blinks - // mesh.onBeforeRender = () => { - // const now = Date.now() - // if (now - lastBlink > blinkInterval) { - // lastBlink = now - // mesh.traverse((child) => { - // if (child instanceof THREE.Mesh) { - // const material = child.material as THREE.MeshLambertMaterial - // material.color.set(material.color?.equals(new THREE.Color(0xff_ff_ff)) - // ? new THREE.Color(0xff_00_00) - // : new THREE.Color(0xff_ff_ff)) - // } - // }) - // } - // } - // } - - group.additionalCleanup = () => { - // important: avoid texture memory leak and gpu slowdown - if (object.cleanup) { - object.cleanup() - } - } - } - } - } else if (isPlayerModel) { - const wrapper = new THREE.Group() - const playerObject = this.setupPlayerObject(entity, wrapper, overrides) - group.playerObject = playerObject - mesh = wrapper - - if (entity.username) { - const nametag = addNametag(entity, { fontFamily: 'mojangles' }, wrapper, this.worldRenderer.version) - if (nametag) { - nametag.position.y = playerObject.position.y + playerObject.scale.y * 16 + 3 - nametag.scale.multiplyScalar(12) - } - } - } else { - mesh = getEntityMesh(entity, this.worldRenderer, this.entitiesOptions, { ...overrides, customModel: entity['customModel'] }) - } - if (!mesh) return - mesh.name = 'mesh' - // set initial position so there are no weird jumps update after - const pos = entity.pos ?? entity.position - group.position.set(pos.x, pos.y, pos.z) - - // todo use width and height instead - const boxHelper = new THREE.BoxHelper( - mesh, - entity.type === 'hostile' ? 0xff_00_00 : - entity.type === 'mob' ? 0x00_ff_00 : - entity.type === 'player' ? 0x00_00_ff : - 0xff_a5_00, - ) - boxHelper.name = 'debug' - group.add(mesh) - group.add(boxHelper) - boxHelper.visible = false - this.worldRenderer.scene.add(group) - - e = group - e.name = 'entity' - e['realName'] = entity.name - this.entities[entity.id] = e - - this.onAddEntity(entity) - - if (isPlayerModel) { - void this.updatePlayerSkin(entity.id, entity.username, overrides?.texture ? entity.uuid : undefined, overrides?.texture || stevePngUrl) - } - this.setDebugMode(this.debugMode, group) - this.setRendering(this.currentlyRendering, group) - } else { - mesh = e.children.find(c => c.name === 'mesh') - } - - // Update equipment - this.updateEntityEquipment(e, entity) - - const meta = getGeneralEntitiesMetadata(entity) - - const isInvisible = ((entity.metadata?.[0] ?? 0) as unknown as number) & 0x20 || (this.worldRenderer.playerStateReactive.cameraSpectatingEntity === entity.id && this.worldRenderer.playerStateUtils.isSpectator()) - for (const child of mesh!.children ?? []) { - if (child.name !== 'nametag') { - child.visible = !isInvisible - } - } - // --- - // set baby size - if (meta.baby) { - e.scale.set(0.5, 0.5, 0.5) - } else { - e.scale.set(1, 1, 1) - } - // entity specific meta - const textDisplayMeta = getSpecificEntityMetadata('text_display', entity) - const displayTextRaw = textDisplayMeta?.text || meta.custom_name_visible && meta.custom_name - if (entity.name !== 'player' && displayTextRaw) { - const nameTagFixed = textDisplayMeta && (textDisplayMeta.billboard_render_constraints === 'fixed' || !textDisplayMeta.billboard_render_constraints) - const nameTagBackgroundColor = (textDisplayMeta && (parseInt(textDisplayMeta.style_flags, 10) & 0x04) === 0) ? toRgba(textDisplayMeta.background_color) : undefined - let nameTagTextOpacity: any - if (textDisplayMeta?.text_opacity) { - const rawOpacity = parseInt(textDisplayMeta?.text_opacity, 10) - nameTagTextOpacity = rawOpacity > 0 ? rawOpacity : 256 - rawOpacity - } - addNametag( - { ...entity, username: typeof displayTextRaw === 'string' ? mojangson.simplify(mojangson.parse(displayTextRaw)) : nbt.simplify(displayTextRaw), - nameTagBackgroundColor, nameTagTextOpacity, nameTagFixed, - nameTagScale: textDisplayMeta?.scale, nameTagTranslation: textDisplayMeta && (textDisplayMeta.translation || new THREE.Vector3(0, 0, 0)), - nameTagRotationLeft: toQuaternion(textDisplayMeta?.left_rotation), nameTagRotationRight: toQuaternion(textDisplayMeta?.right_rotation) }, - this.entitiesOptions, - mesh, - this.worldRenderer.version - ) - } - - const armorStandMeta = getSpecificEntityMetadata('armor_stand', entity) - if (armorStandMeta) { - const isSmall = (parseInt(armorStandMeta.client_flags, 10) & 0x01) !== 0 - const hasArms = (parseInt(armorStandMeta.client_flags, 10) & 0x04) !== 0 - const hasBasePlate = (parseInt(armorStandMeta.client_flags, 10) & 0x08) === 0 - const isMarker = (parseInt(armorStandMeta.client_flags, 10) & 0x10) !== 0 - mesh!.castShadow = !isMarker - mesh!.receiveShadow = !isMarker - if (isSmall) { - e.scale.set(0.5, 0.5, 0.5) - } else { - e.scale.set(1, 1, 1) - } - e.traverse(c => { - switch (c.name) { - case 'bone_baseplate': - this.setVisible(c, hasBasePlate) - c.rotation.y = -e.rotation.y - break - case 'bone_head': - if (armorStandMeta.head_pose) { - c.setRotationFromEuler(poseToEuler(armorStandMeta.head_pose)) - } - break - case 'bone_body': - if (armorStandMeta.body_pose) { - c.setRotationFromEuler(poseToEuler(armorStandMeta.body_pose)) - } - break - case 'bone_rightarm': - if (c.parent?.name !== 'bone_armor') { - this.setVisible(c, hasArms) - } - if (armorStandMeta.left_arm_pose) { - c.setRotationFromEuler(poseToEuler(armorStandMeta.left_arm_pose)) - } else { - c.setRotationFromEuler(poseToEuler({ 'yaw': -10, 'pitch': -10, 'roll': 0 })) - } - break - case 'bone_leftarm': - if (c.parent?.name !== 'bone_armor') { - this.setVisible(c, hasArms) - } - if (armorStandMeta.right_arm_pose) { - c.setRotationFromEuler(poseToEuler(armorStandMeta.right_arm_pose)) - } else { - c.setRotationFromEuler(poseToEuler({ 'yaw': 10, 'pitch': -10, 'roll': 0 })) - } - break - case 'bone_rightleg': - if (armorStandMeta.left_leg_pose) { - c.setRotationFromEuler(poseToEuler(armorStandMeta.left_leg_pose)) - } else { - c.setRotationFromEuler(poseToEuler({ 'yaw': -1, 'pitch': -1, 'roll': 0 })) - } - break - case 'bone_leftleg': - if (armorStandMeta.right_leg_pose) { - c.setRotationFromEuler(poseToEuler(armorStandMeta.right_leg_pose)) - } else { - c.setRotationFromEuler(poseToEuler({ 'yaw': 1, 'pitch': 1, 'roll': 0 })) - } - break - } - }) - } - - // todo handle map, map_chunks events - let itemFrameMeta = getSpecificEntityMetadata('item_frame', entity) - if (!itemFrameMeta) { - itemFrameMeta = getSpecificEntityMetadata('glow_item_frame', entity) - } - if (itemFrameMeta) { - // TODO: fix type - // todo! fix errors in mc-data (no entities data prior 1.18.2) - const item = (itemFrameMeta?.item ?? entity.metadata?.[8]) as any as { itemId, blockId, components, nbtData: { value: { map: { value: number } } } } - mesh!.scale.set(1, 1, 1) - mesh!.position.set(0, 0, -0.5) - - e.rotation.x = -entity.pitch - e.children.find(c => { - if (c.name.startsWith('map_')) { - disposeObject(c) - const existingMapNumber = parseInt(c.name.split('_')[1], 10) - this.itemFrameMaps[existingMapNumber] = this.itemFrameMaps[existingMapNumber]?.filter(mesh => mesh !== c) - if (c instanceof THREE.Mesh) { - c.material?.map?.dispose() - } - return true - } else if (c.name === 'item') { - disposeObject(c) - return true - } - return false - })?.removeFromParent() - - if (item && (item.itemId ?? item.blockId ?? 0) !== 0) { - // Get rotation from metadata, default to 0 if not present - // Rotation is stored in 45° increments (0-7) for items, 90° increments (0-3) for maps - const rotation = (itemFrameMeta.rotation as any as number) ?? 0 - const mapNumber = item.nbtData?.value?.map?.value ?? item.components?.find(x => x.type === 'map_id')?.data - if (mapNumber) { - // TODO: Use proper larger item frame model when a map exists - mesh!.scale.set(16 / 12, 16 / 12, 1) - // Handle map rotation (4 possibilities, 90° increments) - this.addMapModel(e, mapNumber, rotation) - } else { - // Handle regular item rotation (8 possibilities, 45° increments) - const itemMesh = this.getItemMesh(item, { - 'minecraft:display_context': 'fixed', - }) - if (itemMesh) { - itemMesh.mesh.position.set(0, 0, -0.05) - // itemMesh.mesh.position.set(0, 0, 0.43) - if (itemMesh.isBlock) { - itemMesh.mesh.scale.set(0.25, 0.25, 0.25) - } else { - itemMesh.mesh.scale.set(0.5, 0.5, 0.5) - } - // Rotate 180° around Y axis first - itemMesh.mesh.rotateY(Math.PI) - // Then apply the 45° increment rotation - itemMesh.mesh.rotateZ(-rotation * Math.PI / 4) - itemMesh.mesh.name = 'item' - e.add(itemMesh.mesh) - } - } - } - } - - if (entity.username !== undefined) { - e.username = entity.username - } - - this.updateNameTagVisibility(e) - - this.updateEntityPosition(entity, justAdded, overrides) - } - - updateEntityPosition (entity: import('prismarine-entity').Entity, justAdded: boolean, overrides: { rotation?: { head?: { y: number, x: number } } }) { - const e = this.entities[entity.id] - if (!e) return - const ANIMATION_DURATION = justAdded ? 0 : TWEEN_DURATION - if (entity.position) { - new TWEEN.Tween(e.position).to({ x: entity.position.x, y: entity.position.y, z: entity.position.z }, ANIMATION_DURATION).start() - } - if (entity.yaw) { - const da = (entity.yaw - e.rotation.y) % (Math.PI * 2) - const dy = 2 * da % (Math.PI * 2) - da - new TWEEN.Tween(e.rotation).to({ y: e.rotation.y + dy }, ANIMATION_DURATION).start() - } - - if (e?.playerObject && overrides?.rotation?.head) { - const { playerObject } = e - const headRotationDiff = overrides.rotation.head.y ? overrides.rotation.head.y - entity.yaw : 0 - playerObject.skin.head.rotation.y = -headRotationDiff - playerObject.skin.head.rotation.x = overrides.rotation.head.x ? - overrides.rotation.head.x : 0 - } - } - - onAddEntity (entity: import('prismarine-entity').Entity) { - } - - loadedSkinEntityIds = new Set() - maybeRenderPlayerSkin (entityId: string) { - let mesh = this.entities[entityId] - if (entityId === 'player_entity') { - mesh = this.playerEntity! - entityId = this.playerEntity?.originalEntity.id as any - } - if (!mesh) return - if (!mesh.playerObject) return - if (!mesh.visible) return - - const MAX_DISTANCE_SKIN_LOAD = 128 - const cameraPos = this.worldRenderer.cameraObject.position - const distance = mesh.position.distanceTo(cameraPos) - if (distance < MAX_DISTANCE_SKIN_LOAD && distance < (this.worldRenderer.viewDistance * 16)) { - if (this.loadedSkinEntityIds.has(String(entityId))) return - void this.updatePlayerSkin(entityId, mesh.playerObject.realUsername, mesh.playerObject.realPlayerUuid, true, true) - } - } - - playerPerAnimation = {} as Record - onRemoveEntity (entity: import('prismarine-entity').Entity) { - this.loadedSkinEntityIds.delete(entity.id.toString()) - delete this.currentSkinUrls[entity.id.toString()] - } - - updateMap (mapNumber: string | number, data: string) { - this.cachedMapsImages[mapNumber] = data - let itemFrameMeshes = this.itemFrameMaps[mapNumber] - if (!itemFrameMeshes) return - itemFrameMeshes = itemFrameMeshes.filter(mesh => mesh.parent) - this.itemFrameMaps[mapNumber] = itemFrameMeshes - if (itemFrameMeshes) { - for (const mesh of itemFrameMeshes) { - mesh.material.map = this.loadMap(data) - mesh.material.needsUpdate = true - mesh.visible = true - } - } - } - - updateNameTagVisibility (entity: SceneEntity) { - const playerTeam = this.worldRenderer.playerStateReactive.team - const entityTeam = entity.originalEntity.team - const nameTagVisibility = entityTeam?.nameTagVisibility || 'always' - const showNameTag = nameTagVisibility === 'always' || - (nameTagVisibility === 'hideForOwnTeam' && entityTeam?.team !== playerTeam?.team) || - (nameTagVisibility === 'hideForOtherTeams' && (entityTeam?.team === playerTeam?.team || playerTeam === undefined)) - entity.traverse(c => { - if (c.name === 'nametag') { - c.visible = showNameTag - } - }) - } - - addMapModel (entityMesh: THREE.Object3D, mapNumber: number, rotation: number) { - const imageData = this.cachedMapsImages?.[mapNumber] - let texture: THREE.Texture | null = null - if (imageData) { - texture = this.loadMap(imageData) - } - const parameters = { - transparent: true, - alphaTest: 0.1, - } - if (texture) { - parameters['map'] = texture - } - const material = new THREE.MeshLambertMaterial(parameters) - - const mapMesh = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), material) - - mapMesh.rotation.set(0, Math.PI, 0) - entityMesh.add(mapMesh) - let isInvisible = true - entityMesh.traverseVisible(c => { - if (c.name === 'geometry_frame') { - isInvisible = false - } - }) - if (isInvisible) { - mapMesh.position.set(0, 0, 0.499) - } else { - mapMesh.position.set(0, 0, 0.437) - } - // Apply 90° increment rotation for maps (0-3) - mapMesh.rotateZ(Math.PI * 2 - rotation * Math.PI / 2) - mapMesh.name = `map_${mapNumber}` - - if (!texture) { - mapMesh.visible = false - } - - if (!this.itemFrameMaps[mapNumber]) { - this.itemFrameMaps[mapNumber] = [] - } - this.itemFrameMaps[mapNumber].push(mapMesh) - } - - loadMap (data: any) { - const texture = new THREE.TextureLoader().load(data) - if (texture) { - texture.magFilter = THREE.NearestFilter - texture.minFilter = THREE.NearestFilter - texture.needsUpdate = true - } - return texture - } - - addItemModel (entityMesh: SceneEntity, hand: 'left' | 'right', item: Item, isPlayer = false) { - const bedrockParentName = `bone_${hand}item` - const itemName = `custom_item_${hand}` - - // remove existing item - entityMesh.traverse(c => { - if (c.name === itemName) { - c.removeFromParent() - if (c['additionalCleanup']) c['additionalCleanup']() - } - }) - if (!item) return - - const itemObject = this.getItemMesh(item, { - 'minecraft:display_context': 'thirdperson', - }) - if (itemObject?.mesh) { - entityMesh.traverse(c => { - if (c.name.toLowerCase() === bedrockParentName || c.name === `${hand}Arm`) { - const group = new THREE.Object3D() - group['additionalCleanup'] = () => { - // important: avoid texture memory leak and gpu slowdown - if (itemObject.cleanup) { - itemObject.cleanup() - } - } - const itemMesh = itemObject.mesh - group.rotation.z = -Math.PI / 16 - if (itemObject.isBlock) { - group.rotation.y = Math.PI / 4 - } else { - itemMesh.rotation.z = -Math.PI / 4 - group.rotation.y = Math.PI / 2 - group.scale.multiplyScalar(2) - } - - // if player, move item below and forward a bit - if (isPlayer) { - group.position.y = -8 - group.position.z = 5 - group.position.x = hand === 'left' ? 1 : -1 - group.rotation.x = Math.PI - } - - group.add(itemMesh) - - group.name = itemName - c.add(group) - } - }) - } - } - - handleDamageEvent (entityId, damageAmount) { - const entityMesh = this.entities[entityId]?.children.find(c => c.name === 'mesh') - if (entityMesh) { - entityMesh.traverse((child) => { - if (child instanceof THREE.Mesh && child.material.clone) { - const clonedMaterial = child.material.clone() - clonedMaterial.dispose() - child.material = child.material.clone() - const originalColor = child.material.color.clone() - child.material.color.set(0xff_00_00) - new TWEEN.Tween(child.material.color) - .to(originalColor, 500) - .start() - } - }) - } - } - - raycastSceneDebug () { - // return any object from scene. raycast from camera - const raycaster = new THREE.Raycaster() - raycaster.setFromCamera(new THREE.Vector2(0, 0), this.worldRenderer.camera) - const intersects = raycaster.intersectObjects(this.worldRenderer.scene.children) - return intersects[0]?.object - } - - private setupPlayerObject (entity: SceneEntity['originalEntity'], wrapper: THREE.Group, overrides: { texture?: string }): PlayerObjectType { - const playerObject = new PlayerObject() as PlayerObjectType - playerObject.realPlayerUuid = entity.uuid ?? '' - playerObject.realUsername = entity.username ?? '' - playerObject.position.set(0, 16, 0) - - // fix issues with starfield - playerObject.traverse((obj) => { - if (obj instanceof THREE.Mesh && obj.material instanceof THREE.MeshStandardMaterial) { - obj.material.transparent = true - } - }) - - wrapper.add(playerObject as any) - const scale = 1 / 16 - wrapper.scale.set(scale, scale, scale) - wrapper.rotation.set(0, Math.PI, 0) - - // Set up animation - playerObject.animation = new WalkingGeneralSwing() - //@ts-expect-error - playerObject.animation.isMoving = false - - return playerObject - } - - private updateEntityEquipment (entityMesh: SceneEntity, entity: SceneEntity['originalEntity']) { - if (!entityMesh || !entity.equipment) return - - const isPlayer = entity.type === 'player' - this.addItemModel(entityMesh, isPlayer ? 'right' : 'left', entity.equipment[0], isPlayer) - this.addItemModel(entityMesh, isPlayer ? 'left' : 'right', entity.equipment[1], isPlayer) - addArmorModel(this.worldRenderer, entityMesh, 'feet', entity.equipment[2]) - addArmorModel(this.worldRenderer, entityMesh, 'legs', entity.equipment[3], 2) - addArmorModel(this.worldRenderer, entityMesh, 'chest', entity.equipment[4]) - addArmorModel(this.worldRenderer, entityMesh, 'head', entity.equipment[5]) - - // Update player-specific equipment - if (isPlayer && entityMesh.playerObject) { - const { playerObject } = entityMesh - playerObject.backEquipment = entity.equipment.some((item) => item?.name === 'elytra') ? 'elytra' : 'cape' - if (playerObject.backEquipment === 'elytra') { - void this.loadAndApplyCape(entity.id, elytraTexture) - } - if (playerObject.cape.map === null) { - playerObject.cape.visible = false - } - } - } -} - -function getGeneralEntitiesMetadata (entity: { name; metadata }): Partial> { - const entityData = loadedData.entitiesByName[entity.name] - return new Proxy({}, { - get (target, p, receiver) { - if (typeof p !== 'string' || !entityData) return - const index = entityData.metadataKeys?.indexOf(p) - return entity.metadata?.[index ?? -1] - }, - }) -} - -function getSpecificEntityMetadata (name: T, entity): EntityMetadataVersions[T] | undefined { - if (entity.name !== name) return - return getGeneralEntitiesMetadata(entity) as any -} - -function addArmorModel (worldRenderer: WorldRendererThree, entityMesh: THREE.Object3D, slotType: string, item: Item, layer = 1, overlay = false) { - if (!item) { - removeArmorModel(entityMesh, slotType) - return - } - const itemParts = item.name.split('_') - let texturePath - const isPlayerHead = slotType === 'head' && item.name === 'player_head' - if (isPlayerHead) { - removeArmorModel(entityMesh, slotType) - if (item.nbt) { - const itemNbt = nbt.simplify(item.nbt) - try { - let textureData - if (itemNbt.SkullOwner) { - textureData = itemNbt.SkullOwner.Properties.textures[0]?.Value - } else { - textureData = itemNbt['minecraft:profile']?.Properties?.find(p => p.name === 'textures')?.value - } - if (textureData) { - const decodedData = JSON.parse(Buffer.from(textureData, 'base64').toString()) - texturePath = decodedData.textures?.SKIN?.url - const { skinTexturesProxy } = this.worldRenderer.worldRendererConfig - if (skinTexturesProxy) { - texturePath = texturePath?.replace('http://textures.minecraft.net/', skinTexturesProxy) - .replace('https://textures.minecraft.net/', skinTexturesProxy) - } - } - } catch (err) { - console.error('Error decoding player head texture:', err) - } - } else { - texturePath = stevePngUrl - } - } - const armorMaterial = itemParts[0] - if (!texturePath) { - // TODO: Support mirroring on certain parts of the model - const armorTextureName = `${armorMaterial}_layer_${layer}${overlay ? '_overlay' : ''}` - texturePath = worldRenderer.resourcesManager.currentResources.customTextures.armor?.textures[armorTextureName]?.src ?? armorTextures[armorTextureName] - } - if (!texturePath || !armorModel[slotType]) { - removeArmorModel(entityMesh, slotType) - return - } - - const meshName = `geometry_armor_${slotType}${overlay ? '_overlay' : ''}` - let mesh = entityMesh.children.findLast(c => c.name === meshName) as THREE.Mesh - let material - if (mesh) { - material = mesh.material - void loadTexture(texturePath, texture => { - texture.magFilter = THREE.NearestFilter - texture.minFilter = THREE.NearestFilter - texture.flipY = false - texture.wrapS = THREE.MirroredRepeatWrapping - texture.wrapT = THREE.MirroredRepeatWrapping - material.map = texture - }) - } else { - mesh = getMesh(worldRenderer, texturePath, armorModel[slotType]) - // // enable debug mode to see the mesh - // mesh.traverse(c => { - // if (c instanceof THREE.Mesh) { - // c.material.wireframe = true - // } - // }) - if (slotType === 'head') { - // avoid z-fighting with the head - mesh.children[0].position.y += 0.01 - } - mesh.name = meshName - material = mesh.material - if (!isPlayerHead) { - material.side = THREE.DoubleSide - } - } - if (armorMaterial === 'leather' && !overlay) { - const color = (item.nbt?.value as any)?.display?.value?.color?.value - if (color) { - const r = color >> 16 & 0xff - const g = color >> 8 & 0xff - const b = color & 0xff - material.color.setRGB(r / 255, g / 255, b / 255) - } else { - material.color.setHex(0xB5_6D_51) // default brown color - } - addArmorModel(worldRenderer, entityMesh, slotType, item, layer, true) - } else { - material.color.setHex(0xFF_FF_FF) - } - const group = new THREE.Object3D() - group.name = `armor_${slotType}${overlay ? '_overlay' : ''}` - group.add(mesh) - - entityMesh.add(mesh) -} - -function removeArmorModel (entityMesh: THREE.Object3D, slotType: string) { - for (const c of entityMesh.children) { - if (c.name === `geometry_armor_${slotType}` || c.name === `geometry_armor_${slotType}_overlay`) { - c.removeFromParent() - } - } -} diff --git a/renderer/viewer/three/entity/EntityMesh.ts b/renderer/viewer/three/entity/EntityMesh.ts deleted file mode 100644 index 229da6d5d..000000000 --- a/renderer/viewer/three/entity/EntityMesh.ts +++ /dev/null @@ -1,550 +0,0 @@ -import * as THREE from 'three' -import { OBJLoader } from 'three-stdlib' -import huskPng from 'mc-assets/dist/other-textures/latest/entity/zombie/husk.png' -import { Vec3 } from 'vec3' -import ocelotPng from '../../../../node_modules/mc-assets/dist/other-textures/latest/entity/cat/ocelot.png' -import arrowTexture from '../../../../node_modules/mc-assets/dist/other-textures/1.21.2/entity/projectiles/arrow.png' -import spectralArrowTexture from '../../../../node_modules/mc-assets/dist/other-textures/1.21.2/entity/projectiles/spectral_arrow.png' -import tippedArrowTexture from '../../../../node_modules/mc-assets/dist/other-textures/1.21.2/entity/projectiles/tipped_arrow.png' -import { loadTexture } from '../threeJsUtils' -import { WorldRendererThree } from '../worldrendererThree' -import entities from './entities.json' -import { externalModels } from './objModels' -import externalTexturesJson from './externalTextures.json' - -interface ElemFace { - dir: [number, number, number] - u0: [number, number, number] - v0: [number, number, number] - u1: [number, number, number] - v1: [number, number, number] - corners: Array<[number, number, number, number, number]> -} - -interface GeoData { - positions: number[] - normals: number[] - uvs: number[] - indices: number[] - skinIndices: number[] - skinWeights: number[] -} - -interface JsonBone { - name: string - pivot?: [number, number, number] - bind_pose_rotation?: [number, number, number] - rotation?: [number, number, number] - parent?: string - cubes?: JsonCube[] - mirror?: boolean -} - -interface JsonCube { - origin: [number, number, number] - size: [number, number, number] - uv: [number, number] - inflate?: number - rotation?: [number, number, number] -} - -interface JsonModel { - texturewidth?: number - textureheight?: number - bones: JsonBone[] -} - -interface EntityOverrides { - textures?: Record - rotation?: Record -} - -const elemFaces: Record = { - up: { - dir: [0, 1, 0], - u0: [0, 0, 1], - v0: [0, 0, 0], - u1: [1, 0, 1], - v1: [0, 0, 1], - corners: [ - [0, 1, 1, 0, 0], - [1, 1, 1, 1, 0], - [0, 1, 0, 0, 1], - [1, 1, 0, 1, 1] - ] - }, - down: { - dir: [0, -1, 0], - u0: [1, 0, 1], - v0: [0, 0, 0], - u1: [2, 0, 1], - v1: [0, 0, 1], - corners: [ - [1, 0, 1, 0, 0], - [0, 0, 1, 1, 0], - [1, 0, 0, 0, 1], - [0, 0, 0, 1, 1] - ] - }, - east: { - dir: [1, 0, 0], - u0: [0, 0, 0], - v0: [0, 0, 1], - u1: [0, 0, 1], - v1: [0, 1, 1], - corners: [ - [1, 1, 1, 0, 0], - [1, 0, 1, 0, 1], - [1, 1, 0, 1, 0], - [1, 0, 0, 1, 1] - ] - }, - west: { - dir: [-1, 0, 0], - u0: [1, 0, 1], - v0: [0, 0, 1], - u1: [1, 0, 2], - v1: [0, 1, 1], - corners: [ - [0, 1, 0, 0, 0], - [0, 0, 0, 0, 1], - [0, 1, 1, 1, 0], - [0, 0, 1, 1, 1] - ] - }, - north: { - dir: [0, 0, -1], - u0: [0, 0, 1], - v0: [0, 0, 1], - u1: [1, 0, 1], - v1: [0, 1, 1], - corners: [ - [1, 0, 0, 0, 1], - [0, 0, 0, 1, 1], - [1, 1, 0, 0, 0], - [0, 1, 0, 1, 0] - ] - }, - south: { - dir: [0, 0, 1], - u0: [1, 0, 2], - v0: [0, 0, 1], - u1: [2, 0, 2], - v1: [0, 1, 1], - corners: [ - [0, 0, 1, 0, 1], - [1, 0, 1, 1, 1], - [0, 1, 1, 0, 0], - [1, 1, 1, 1, 0] - ] - } -} - -function dot (a: number[], b: number[]): number { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] -} - -function addCube ( - attr: GeoData, - boneId: number, - bone: THREE.Bone, - cube: JsonCube, - sameTextureForAllFaces = false, - texWidth = 64, - texHeight = 64, - mirror = false, - errors: string[] = [] -): void { - const cubeRotation = new THREE.Euler(0, 0, 0) - if (cube.rotation) { - cubeRotation.x = -cube.rotation[0] * Math.PI / 180 - cubeRotation.y = -cube.rotation[1] * Math.PI / 180 - cubeRotation.z = -cube.rotation[2] * Math.PI / 180 - } - for (const { dir, corners, u0, v0, u1, v1 } of Object.values(elemFaces)) { - const ndx = Math.floor(attr.positions.length / 3) - - const eastOrWest = dir[0] !== 0 - const faceUvs: number[] = [] - for (const pos of corners) { - let u: number - let v: number - if (sameTextureForAllFaces) { - u = (cube.uv[0] + pos[3] * cube.size[0]) / texWidth - v = (cube.uv[1] + pos[4] * cube.size[1]) / texHeight - } else { - u = (cube.uv[0] + dot(pos[3] ? u1 : u0, cube.size)) / texWidth - v = (cube.uv[1] + dot(pos[4] ? v1 : v0, cube.size)) / texHeight - } - // if (isNaN(u) || isNaN(v)) { - // errors.push(`NaN u: ${u}, v: ${v}`) - // continue - // } - // if (u < 0 || u > 1 || v < 0 || v > 1) { - // errors.push(`u: ${u}, v: ${v} out of range`) - // continue - // } - - const posX = eastOrWest && mirror ? pos[0] ^ 1 : pos[0] - const posY = pos[1] - const posZ = eastOrWest && mirror ? pos[2] ^ 1 : pos[2] - const inflate = cube.inflate ?? 0 - let vecPos = new THREE.Vector3( - cube.origin[0] + posX * cube.size[0] + (posX ? inflate : -inflate), - cube.origin[1] + posY * cube.size[1] + (posY ? inflate : -inflate), - cube.origin[2] + posZ * cube.size[2] + (posZ ? inflate : -inflate) - ) - - vecPos = vecPos.applyEuler(cubeRotation) - vecPos = vecPos.sub(bone.position) - vecPos = vecPos.applyEuler(bone.rotation) - vecPos = vecPos.add(bone.position) - - attr.positions.push(vecPos.x, vecPos.y, vecPos.z) - attr.normals.push(dir[0], dir[1], dir[2]) - faceUvs.push(u, v) - attr.skinIndices.push(boneId, 0, 0, 0) - attr.skinWeights.push(1, 0, 0, 0) - } - - if (mirror) { - for (let i = 0; i + 1 < corners.length; i += 2) { - const faceIndex = i * 2 - const tempFaceUvs = faceUvs.slice(faceIndex, faceIndex + 4) - faceUvs[faceIndex] = tempFaceUvs[2] - faceUvs[faceIndex + 1] = tempFaceUvs[eastOrWest ? 1 : 3] - faceUvs[faceIndex + 2] = tempFaceUvs[0] - faceUvs[faceIndex + 3] = tempFaceUvs[eastOrWest ? 3 : 1] - } - } - attr.uvs.push(...faceUvs) - - attr.indices.push(ndx, ndx + 1, ndx + 2, ndx + 2, ndx + 1, ndx + 3) - } -} - -export function getMesh ( - worldRenderer: WorldRendererThree | undefined, - texture: string, - jsonModel: JsonModel, - overrides: EntityOverrides = {}, - debugFlags: EntityDebugFlags = {} -): THREE.SkinnedMesh { - let textureWidth = jsonModel.texturewidth ?? 64 - let textureHeight = jsonModel.textureheight ?? 64 - let textureOffset: number[] | undefined - const useBlockTexture = texture.startsWith('block:') - const blocksTexture = worldRenderer?.material.map - if (useBlockTexture) { - if (!worldRenderer) throw new Error('worldRenderer is required for block textures') - const blockName = texture.slice(6) - const textureInfo = worldRenderer.resourcesManager.currentResources.blocksAtlasJson.textures[blockName] - if (textureInfo) { - textureWidth = blocksTexture?.image.width ?? textureWidth - textureHeight = blocksTexture?.image.height ?? textureHeight - // todo support su/sv - textureOffset = [textureInfo.u, textureInfo.v] - } else { - console.error(`Unknown block ${blockName}`) - } - } - - const bones: Record = {} - - const geoData: GeoData = { - positions: [], - normals: [], - uvs: [], - indices: [], - skinIndices: [], - skinWeights: [] - } - let i = 0 - for (const jsonBone of jsonModel.bones) { - const bone = new THREE.Bone() - if (jsonBone.pivot) { - bone.position.x = jsonBone.pivot[0] - bone.position.y = jsonBone.pivot[1] - bone.position.z = jsonBone.pivot[2] - } - if (jsonBone.bind_pose_rotation) { - bone.rotation.x = -jsonBone.bind_pose_rotation[0] * Math.PI / 180 - bone.rotation.y = -jsonBone.bind_pose_rotation[1] * Math.PI / 180 - bone.rotation.z = -jsonBone.bind_pose_rotation[2] * Math.PI / 180 - } else if (jsonBone.rotation) { - bone.rotation.x = -jsonBone.rotation[0] * Math.PI / 180 - bone.rotation.y = -jsonBone.rotation[1] * Math.PI / 180 - bone.rotation.z = -jsonBone.rotation[2] * Math.PI / 180 - } - if (overrides.rotation?.[jsonBone.name]) { - bone.rotation.x -= (overrides.rotation[jsonBone.name].x ?? 0) * Math.PI / 180 - bone.rotation.y -= (overrides.rotation[jsonBone.name].y ?? 0) * Math.PI / 180 - bone.rotation.z -= (overrides.rotation[jsonBone.name].z ?? 0) * Math.PI / 180 - } - bone.name = `bone_${jsonBone.name}` - bones[jsonBone.name] = bone - - if (jsonBone.cubes) { - for (const cube of jsonBone.cubes) { - const errors: string[] = [] - addCube(geoData, i, bone, cube, useBlockTexture, textureWidth, textureHeight, jsonBone.mirror, errors) - if (errors.length) { - debugFlags.errors ??= [] - debugFlags.errors.push(...errors.map(error => `Bone ${jsonBone.name}: ${error}`)) - } - } - } - i++ - } - - const rootBones: THREE.Object3D[] = [] - for (const jsonBone of jsonModel.bones) { - if (jsonBone.parent && bones[jsonBone.parent]) { - bones[jsonBone.parent].add(bones[jsonBone.name]) - } else { - rootBones.push(bones[jsonBone.name]) - } - } - - const skeleton = new THREE.Skeleton(Object.values(bones)) - - const geometry = new THREE.BufferGeometry() - geometry.setAttribute('position', new THREE.Float32BufferAttribute(geoData.positions, 3)) - geometry.setAttribute('normal', new THREE.Float32BufferAttribute(geoData.normals, 3)) - geometry.setAttribute('uv', new THREE.Float32BufferAttribute(geoData.uvs, 2)) - geometry.setAttribute('skinIndex', new THREE.Uint16BufferAttribute(geoData.skinIndices, 4)) - geometry.setAttribute('skinWeight', new THREE.Float32BufferAttribute(geoData.skinWeights, 4)) - geometry.setIndex(geoData.indices) - - const material = new THREE.MeshLambertMaterial({ transparent: true, alphaTest: 0.1 }) - const mesh = new THREE.SkinnedMesh(geometry, material) - mesh.add(...rootBones) - mesh.bind(skeleton) - mesh.scale.set(1 / 16, 1 / 16, 1 / 16) - - if (textureOffset) { - // todo(memory) dont clone - const loadedTexture = blocksTexture!.clone() - loadedTexture.offset.set(textureOffset[0], textureOffset[1]) - loadedTexture.needsUpdate = true - material.map = loadedTexture - } else { - void loadTexture(texture, loadedTexture => { - if (material.map) { - // texture is already loaded - return - } - loadedTexture.magFilter = THREE.NearestFilter - loadedTexture.minFilter = THREE.NearestFilter - loadedTexture.flipY = false - loadedTexture.wrapS = THREE.RepeatWrapping - loadedTexture.wrapT = THREE.RepeatWrapping - material.map = loadedTexture - }, () => { - // This callback runs after the texture is fully loaded - const actualWidth = material.map!.image.width - if (actualWidth && textureWidth !== actualWidth) { - material.map!.repeat.x = textureWidth / actualWidth - } - const actualHeight = material.map!.image.height - if (actualHeight && textureHeight !== actualHeight) { - material.map!.repeat.y = textureHeight / actualHeight - } - material.needsUpdate = true - }) - } - - return mesh -} - -export const rendererSpecialHandled = ['item_frame', 'item', 'player'] - -type EntityMapping = { - pattern: string | RegExp - target: string -} - -const temporaryMappings: EntityMapping[] = [ - // Exact matches - { pattern: 'furnace_minecart', target: 'minecart' }, - { pattern: 'spawner_minecart', target: 'minecart' }, - { pattern: 'chest_minecart', target: 'minecart' }, - { pattern: 'hopper_minecart', target: 'minecart' }, - { pattern: 'command_block_minecart', target: 'minecart' }, - { pattern: 'tnt_minecart', target: 'minecart' }, - { pattern: 'glow_item_frame', target: 'item_frame' }, - { pattern: 'glow_squid', target: 'squid' }, - { pattern: 'trader_llama', target: 'llama' }, - { pattern: 'chest_boat', target: 'boat' }, - { pattern: 'spectral_arrow', target: 'arrow' }, - { pattern: 'husk', target: 'zombie' }, - { pattern: 'zombie_horse', target: 'horse' }, - { pattern: 'donkey', target: 'horse' }, - { pattern: 'skeleton_horse', target: 'horse' }, - { pattern: 'mule', target: 'horse' }, - { pattern: 'ocelot', target: 'cat' }, - // Regex patterns - { pattern: /_minecraft$/, target: 'minecraft' }, - { pattern: /_boat$/, target: 'boat' }, - { pattern: /_raft$/, target: 'boat' }, - { pattern: /_horse$/, target: 'horse' }, - { pattern: /_zombie$/, target: 'zombie' }, - { pattern: /_arrow$/, target: 'zombie' }, -] - -function getEntityMapping (type: string): string | undefined { - for (const mapping of temporaryMappings) { - if (typeof mapping.pattern === 'string') { - if (mapping.pattern === type) return mapping.target - } else if (mapping.pattern.test(type)) { return mapping.target } - } - return undefined -} - -const getEntity = (name: string) => { - return entities[name] -} - -const scaleEntity: Record = { - zombie: 1.85, - husk: 1.85, - arrow: 0.0025 -} - -const offsetEntity: Record = { - zombie: new Vec3(0, 1, 0), - husk: new Vec3(0, 1, 0), - boat: new Vec3(0, -1, 0), - arrow: new Vec3(0, -0.9, 0) -} - -interface EntityGeometry { - geometry: Array<{ - name: string; - [key: string]: any; - }>; -} - -export type EntityDebugFlags = { - type?: 'obj' | 'bedrock' - tempMap?: string - textureMap?: boolean - errors?: string[] - isHardcodedTexture?: boolean -} - -export class EntityMesh { - mesh: THREE.Object3D - - constructor ( - version: string, - type: string, - worldRenderer?: WorldRendererThree, - overrides: EntityOverrides = {}, - debugFlags: EntityDebugFlags = {} - ) { - const originalType = type - const mappedValue = getEntityMapping(type) - if (mappedValue) { - type = mappedValue - debugFlags.tempMap = mappedValue - } - - if (externalModels[type]) { - const objLoader = new OBJLoader() - const texturePathMap = { - 'zombie_horse': `textures/${version}/entity/horse/horse_zombie.png`, - 'husk': huskPng, - 'skeleton_horse': `textures/${version}/entity/horse/horse_skeleton.png`, - 'donkey': `textures/${version}/entity/horse/donkey.png`, - 'mule': `textures/${version}/entity/horse/mule.png`, - 'ocelot': ocelotPng, - 'arrow': arrowTexture, - 'spectral_arrow': spectralArrowTexture, - 'tipped_arrow': tippedArrowTexture - } - const tempTextureMap = texturePathMap[originalType] || texturePathMap[type] - if (tempTextureMap) { - debugFlags.textureMap = true - } - const texturePath = tempTextureMap || externalTexturesJson[type] - if (externalTexturesJson[type]) { - debugFlags.isHardcodedTexture = true - } - if (!texturePath) throw new Error(`No texture for ${type}`) - const texture = new THREE.TextureLoader().load(texturePath) - texture.minFilter = THREE.NearestFilter - texture.magFilter = THREE.NearestFilter - const material = new THREE.MeshBasicMaterial({ - map: texture, - transparent: true, - alphaTest: 0.1 - }) - const obj = objLoader.parse(externalModels[type]) - const scale = scaleEntity[originalType] || scaleEntity[type] - if (scale) obj.scale.set(scale, scale, scale) - const offset = offsetEntity[originalType] - if (offset) obj.position.set(offset.x, offset.y, offset.z) - obj.traverse((child) => { - if (child instanceof THREE.Mesh) { - child.material = material - // todo - if (child.name === 'Head layer') child.visible = false - if (child.name === 'Head' && overrides.rotation?.head) { // todo - child.rotation.x -= (overrides.rotation.head.x ?? 0) * Math.PI / 180 - child.rotation.y -= (overrides.rotation.head.y ?? 0) * Math.PI / 180 - child.rotation.z -= (overrides.rotation.head.z ?? 0) * Math.PI / 180 - } - } - }) - this.mesh = obj - debugFlags.type = 'obj' - return - } - - if (originalType === 'arrow') { - // overrides.textures = { - // 'default': testArrow, - // ...overrides.textures, - // } - } - - const e = getEntity(type) - if (!e) { - // if (knownNotHandled.includes(type)) return - // throw new Error(`Unknown entity ${type}`) - return - } - - this.mesh = new THREE.Object3D() - for (const [name, jsonModel] of Object.entries(e.geometry)) { - const texture = overrides.textures?.[name] ?? e.textures[name] - if (!texture) continue - // console.log(JSON.stringify(jsonModel, null, 2)) - const mesh = getMesh(worldRenderer, - texture.endsWith('.png') || texture.startsWith('data:image/') || texture.startsWith('block:') - ? texture : texture + '.png', - jsonModel, - overrides, - debugFlags) - mesh.name = `geometry_${name}` - this.mesh.add(mesh) - } - debugFlags.type = 'bedrock' - } - - static getStaticData (name: string): { boneNames: string[] } { - name = getEntityMapping(name) || name - if (externalModels[name]) { - return { - boneNames: [] // todo - } - } - const e = getEntity(name) as EntityGeometry - if (!e) throw new Error(`Unknown entity ${name}`) - return { - boneNames: Object.values(e.geometry).flatMap(x => x.name) - } - } -} -globalThis.EntityMesh = EntityMesh diff --git a/renderer/viewer/three/entity/animations.js b/renderer/viewer/three/entity/animations.js deleted file mode 100644 index 3295556f6..000000000 --- a/renderer/viewer/three/entity/animations.js +++ /dev/null @@ -1,171 +0,0 @@ -//@ts-check -import { PlayerAnimation } from 'skinview3d' - -export class WalkingGeneralSwing extends PlayerAnimation { - - switchAnimationCallback - - isRunning = false - isMoving = true - isCrouched = false - - _startArmSwing - - swingArm() { - this._startArmSwing = this.progress - } - - animate(player) { - // Multiply by animation's natural speed - let t = 0 - const updateT = () => { - if (!this.isMoving) { - t = 0 - return - } - if (this.isRunning) { - t = this.progress * 10 + Math.PI * 0.5 - } else { - t = this.progress * 8 - } - } - updateT() - let reset = false - - croughAnimation(player, this.isCrouched) - - if ((this.isRunning ? Math.cos(t) : Math.sin(t)) < 0.01) { - if (this.switchAnimationCallback) { - reset = true - this.progress = 0 - updateT() - } - } - - if (this.isRunning) { - // Leg swing with larger amplitude - player.skin.leftLeg.rotation.x = Math.cos(t + Math.PI) * 1.3 - player.skin.rightLeg.rotation.x = Math.cos(t) * 1.3 - } else { - // Leg swing - player.skin.leftLeg.rotation.x = Math.sin(t) * 0.5 - player.skin.rightLeg.rotation.x = Math.sin(t + Math.PI) * 0.5 - } - - if (this._startArmSwing) { - const tHand = (this.progress - this._startArmSwing) * 18 + Math.PI * 0.5 - // player.skin.rightArm.rotation.x = Math.cos(tHand) * 1.5 - // const basicArmRotationZ = Math.PI * 0.1 - // player.skin.rightArm.rotation.z = Math.cos(t + Math.PI) * 0.3 - basicArmRotationZ - HitAnimation.animate((this.progress - this._startArmSwing), player, this.isMoving) - - if (tHand > Math.PI + Math.PI) { - this._startArmSwing = null - player.skin.rightArm.rotation.z = 0 - } - } - - if (this.isRunning) { - player.skin.leftArm.rotation.x = Math.cos(t) * 1.5 - if (!this._startArmSwing) { - player.skin.rightArm.rotation.x = Math.cos(t + Math.PI) * 1.5 - } - const basicArmRotationZ = Math.PI * 0.1 - player.skin.leftArm.rotation.z = Math.cos(t) * 0.1 + basicArmRotationZ - if (!this._startArmSwing) { - player.skin.rightArm.rotation.z = Math.cos(t + Math.PI) * 0.1 - basicArmRotationZ - } - } else { - // Arm swing - player.skin.leftArm.rotation.x = Math.sin(t + Math.PI) * 0.5 - if (!this._startArmSwing) { - player.skin.rightArm.rotation.x = Math.sin(t) * 0.5 - } - const basicArmRotationZ = Math.PI * 0.02 - player.skin.leftArm.rotation.z = Math.cos(t) * 0.03 + basicArmRotationZ - if (!this._startArmSwing) { - player.skin.rightArm.rotation.z = Math.cos(t + Math.PI) * 0.03 - basicArmRotationZ - } - } - - if (this.isRunning) { - player.rotation.z = Math.cos(t + Math.PI) * 0.01 - } - if (this.isRunning) { - const basicCapeRotationX = Math.PI * 0.3 - player.cape.rotation.x = Math.sin(t * 2) * 0.1 + basicCapeRotationX - } else { - // Always add an angle for cape around the x axis - const basicCapeRotationX = Math.PI * 0.06 - player.cape.rotation.x = Math.sin(t / 1.5) * 0.06 + basicCapeRotationX - } - - if (reset) { - this.switchAnimationCallback() - this.switchAnimationCallback = null - } - } -} - -const HitAnimation = { - animate(progress, player, isMovingOrRunning) { - const t = progress * 18 - player.skin.rightArm.rotation.x = -0.453_786_055_2 * 2 + 2 * Math.sin(t + Math.PI) * 0.3 - - if (!isMovingOrRunning) { - const basicArmRotationZ = 0.01 * Math.PI + 0.06 - player.skin.rightArm.rotation.z = -Math.cos(t) * 0.403 + basicArmRotationZ - player.skin.body.rotation.y = -Math.cos(t) * 0.06 - player.skin.leftArm.rotation.x = Math.sin(t + Math.PI) * 0.077 - player.skin.leftArm.rotation.z = -Math.cos(t) * 0.015 + 0.13 - 0.05 - player.skin.leftArm.position.z = Math.cos(t) * 0.3 - player.skin.leftArm.position.x = 5 - Math.cos(t) * 0.05 - } - }, -} - -const croughAnimation = (player, isCrouched) => { - const erp = 0 - - // let pr = this.progress * 8; - let pr = isCrouched ? 1 : 0 - const showProgress = false - if (showProgress) { - pr = Math.floor(pr) - } - player.skin.body.rotation.x = 0.453_786_055_2 * Math.abs(Math.sin((pr * Math.PI) / 2)) - player.skin.body.position.z = - 1.325_618_1 * Math.abs(Math.sin((pr * Math.PI) / 2)) - 3.450_031_037_7 * Math.abs(Math.sin((pr * Math.PI) / 2)) - player.skin.body.position.y = -6 - 2.103_677_462 * Math.abs(Math.sin((pr * Math.PI) / 2)) - player.cape.position.y = 8 - 1.851_236_166_577_372 * Math.abs(Math.sin((pr * Math.PI) / 2)) - player.cape.rotation.x = (10.8 * Math.PI) / 180 + 0.294_220_265_771 * Math.abs(Math.sin((pr * Math.PI) / 2)) - player.cape.position.z = - -2 + 3.786_619_432 * Math.abs(Math.sin((pr * Math.PI) / 2)) - 3.450_031_037_7 * Math.abs(Math.sin((pr * Math.PI) / 2)) - player.elytra.position.x = player.cape.position.x - player.elytra.position.y = player.cape.position.y - player.elytra.position.z = player.cape.position.z - player.elytra.rotation.x = player.cape.rotation.x - (10.8 * Math.PI) / 180 - // const pr1 = this.progress / this.speed; - const pr1 = 1 - if (Math.abs(Math.sin((pr * Math.PI) / 2)) === 1) { - player.elytra.leftWing.rotation.z = - 0.261_799_44 + 0.458_200_6 * Math.abs(Math.sin((Math.min(pr1 - erp, 1) * Math.PI) / 2)) - player.elytra.updateRightWing() - } else if (isCrouched !== undefined) { - player.elytra.leftWing.rotation.z = - 0.72 - 0.458_200_6 * Math.abs(Math.sin((Math.min(pr1 - erp, 1) * Math.PI) / 2)) - player.elytra.updateRightWing() - } - player.skin.head.position.y = -3.618_325_234_674 * Math.abs(Math.sin((pr * Math.PI) / 2)) - player.skin.leftArm.position.z = - 3.618_325_234_674 * Math.abs(Math.sin((pr * Math.PI) / 2)) - 3.450_031_037_7 * Math.abs(Math.sin((pr * Math.PI) / 2)) - player.skin.rightArm.position.z = player.skin.leftArm.position.z - player.skin.leftArm.rotation.x = 0.410_367_746_202 * Math.abs(Math.sin((pr * Math.PI) / 2)) - player.skin.rightArm.rotation.x = player.skin.leftArm.rotation.x - player.skin.leftArm.rotation.z = 0.1 - player.skin.rightArm.rotation.z = -player.skin.leftArm.rotation.z - player.skin.leftArm.position.y = -2 - 2.539_433_18 * Math.abs(Math.sin((pr * Math.PI) / 2)) - player.skin.rightArm.position.y = player.skin.leftArm.position.y - player.skin.rightLeg.position.z = -3.450_031_037_7 * Math.abs(Math.sin((pr * Math.PI) / 2)) - player.skin.leftLeg.position.z = player.skin.rightLeg.position.z -} diff --git a/renderer/viewer/three/entity/armorModels.json b/renderer/viewer/three/entity/armorModels.json deleted file mode 100644 index d7a77d4c1..000000000 --- a/renderer/viewer/three/entity/armorModels.json +++ /dev/null @@ -1,204 +0,0 @@ -{ - "skull": { - "bones": [ - { - "name": "head", - "pivot": [0, 12, 0], - "cubes": [ - { - "origin": [-4, 0, -4], - "size": [8, 8, 8], - "uv": [0, 0], - "inflate": 1 - } - ] - }, - { - "name": "overlay", - "parent": "head", - "pivot": [0, 12, 0], - "cubes": [ - { - "origin": [-4, 0, -4], - "size": [8, 8, 8], - "uv": [32, 0], - "inflate": 1.2 - } - ] - } - ], - "visible_bounds_width": 1.5, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 32 - }, - "head": { - "bones": [ - {"name": "armor", "pivot": [0, 12, 0]}, - { - "name": "head", - "parent": "armor", - "pivot": [0, 12, 0], - "cubes": [ - { - "origin": [-4, 23, -4], - "size": [8, 8, 8], - "uv": [0, 0], - "inflate": 1 - } - ] - }, - { - "name": "overlay", - "parent": "head", - "pivot": [0, 12, 0], - "cubes": [ - { - "origin": [-4, 23, -4], - "size": [8, 8, 8], - "uv": [32, 0], - "inflate": 1.2 - } - ] - } - ], - "visible_bounds_width": 1.5, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 32 - }, - "chest": { - "bones": [ - {"name": "armor", "pivot": [0, 12, 0]}, - { - "name": "body", - "parent": "armor", - "pivot": [0, 13, 0], - "cubes": [ - { - "origin": [-4, 12, -2], - "size": [8, 12, 4], - "uv": [16, 16], - "inflate": 1 - } - ] - }, - { - "name": "leftarm", - "parent": "armor", - "pivot": [5, 10, 0], - "cubes": [ - { - "origin": [4, 12, -2], - "size": [4, 12, 4], - "uv": [40, 16], - "inflate": 0.85 - } - ] - }, - { - "name": "rightarm", - "parent": "armor", - "pivot": [-5, 10, 0], - "cubes": [ - { - "origin": [-8, 12, -2], - "size": [4, 12, 4], - "uv": [40, 16], - "inflate": 0.85 - } - ], - "mirror": true - } - ], - "visible_bounds_width": 1.5, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 32 - }, - "legs": { - "bones": [ - {"name": "armor", "pivot": [0, 12, 0]}, - { - "name": "body", - "parent": "armor", - "pivot": [0, 13, 0], - "cubes": [ - { - "origin": [-4, 12, -2], - "size": [8, 12, 4], - "uv": [16, 16], - "inflate": 0.5 - } - ] - }, - { - "name": "leftleg", - "parent": "armor", - "pivot": [1.9, 1, 0], - "cubes": [ - { - "origin": [-0.1, 0, -2], - "size": [4, 12, 4], - "uv": [0, 16], - "inflate": 0.5 - } - ] - }, - { - "name": "rightleg", - "parent": "armor", - "pivot": [-1.9, 1, 0], - "cubes": [ - { - "origin": [-3.9, 0, -2.01], - "size": [4, 12, 4], - "uv": [0, 16], - "inflate": 0.5 - } - ], - "mirror": true - } - ], - "visible_bounds_width": 1.5, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 32 - }, - "feet": { - "bones": [ - {"name": "armor", "pivot": [0, 12, 0]}, - { - "name": "leftleg", - "parent": "armor", - "pivot": [1.9, 1, 0], - "cubes": [ - { - "origin": [-0.1, 0, -2], - "size": [4, 12, 4], - "uv": [0, 16], - "inflate": 0.8 - } - ] - }, - { - "name": "rightleg", - "parent": "armor", - "pivot": [-1.9, 1, 0], - "cubes": [ - { - "origin": [-3.9, 0.01, -2.01], - "size": [4, 12, 4], - "uv": [0, 16], - "inflate": 0.8 - } - ], - "mirror": true - } - ], - "visible_bounds_width": 1.5, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 32 - } -} \ No newline at end of file diff --git a/renderer/viewer/three/entity/armorModels.ts b/renderer/viewer/three/entity/armorModels.ts deleted file mode 100644 index 3681344cb..000000000 --- a/renderer/viewer/three/entity/armorModels.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { default as chainmailLayer1 } from 'mc-assets/dist/other-textures/latest/models/armor/chainmail_layer_1.png' -import { default as chainmailLayer2 } from 'mc-assets/dist/other-textures/latest/models/armor/chainmail_layer_2.png' -import { default as diamondLayer1 } from 'mc-assets/dist/other-textures/latest/models/armor/diamond_layer_1.png' -import { default as diamondLayer2 } from 'mc-assets/dist/other-textures/latest/models/armor/diamond_layer_2.png' -import { default as goldenLayer1 } from 'mc-assets/dist/other-textures/latest/models/armor/gold_layer_1.png' -import { default as goldenLayer2 } from 'mc-assets/dist/other-textures/latest/models/armor/gold_layer_2.png' -import { default as ironLayer1 } from 'mc-assets/dist/other-textures/latest/models/armor/iron_layer_1.png' -import { default as ironLayer2 } from 'mc-assets/dist/other-textures/latest/models/armor/iron_layer_2.png' -import { default as leatherLayer1 } from 'mc-assets/dist/other-textures/latest/models/armor/leather_layer_1.png' -import { default as leatherLayer1Overlay } from 'mc-assets/dist/other-textures/latest/models/armor/leather_layer_1_overlay.png' -import { default as leatherLayer2 } from 'mc-assets/dist/other-textures/latest/models/armor/leather_layer_2.png' -import { default as leatherLayer2Overlay } from 'mc-assets/dist/other-textures/latest/models/armor/leather_layer_2_overlay.png' -import { default as netheriteLayer1 } from 'mc-assets/dist/other-textures/latest/models/armor/netherite_layer_1.png' -import { default as netheriteLayer2 } from 'mc-assets/dist/other-textures/latest/models/armor/netherite_layer_2.png' -import { default as turtleLayer1 } from 'mc-assets/dist/other-textures/latest/models/armor/turtle_layer_1.png' - -export { default as elytraTexture } from 'mc-assets/dist/other-textures/latest/entity/elytra.png' -export { default as armorModel } from './armorModels.json' - -export const armorTextures = { - 'leather_layer_1': leatherLayer1, - 'leather_layer_1_overlay': leatherLayer1Overlay, - 'leather_layer_2': leatherLayer2, - 'leather_layer_2_overlay': leatherLayer2Overlay, - 'chainmail_layer_1': chainmailLayer1, - 'chainmail_layer_2': chainmailLayer2, - 'iron_layer_1': ironLayer1, - 'iron_layer_2': ironLayer2, - 'diamond_layer_1': diamondLayer1, - 'diamond_layer_2': diamondLayer2, - 'golden_layer_1': goldenLayer1, - 'golden_layer_2': goldenLayer2, - 'netherite_layer_1': netheriteLayer1, - 'netherite_layer_2': netheriteLayer2, - 'turtle_layer_1': turtleLayer1 -} diff --git a/renderer/viewer/three/entity/entities.json b/renderer/viewer/three/entity/entities.json deleted file mode 100644 index feca5dc78..000000000 --- a/renderer/viewer/three/entity/entities.json +++ /dev/null @@ -1,6230 +0,0 @@ -{ - "armor_stand": { - "identifier": "minecraft:armor_stand", - "min_engine_version": "1.8.0", - "materials": {"default": "armor_stand"}, - "textures": {"default": "textures/entity/armorstand/wood"}, - "geometry": { - "default": { - "bones": [ - { - "name": "baseplate", - "parent": "waist", - "cubes": [ - {"origin": [-6, 0, -6], "size": [12, 1, 12], "uv": [0, 32]} - ] - }, - {"name": "waist", "pivot": [0, 12, 0]}, - { - "name": "body", - "parent": "waist", - "pivot": [0, 13, 0], - "cubes": [ - {"origin": [-6, 21, -1.5], "size": [12, 3, 3], "uv": [0, 26]}, - {"origin": [-3, 14, -1], "size": [2, 7, 2], "uv": [16, 0]}, - {"origin": [1, 14, -1], "size": [2, 7, 2], "uv": [48, 16]}, - {"origin": [-4, 12, -1], "size": [8, 2, 2], "uv": [0, 48]} - ] - }, - { - "name": "head", - "parent": "waist", - "pivot": [0, 12, 0], - "cubes": [{"origin": [-1, 24, -1], "size": [2, 7, 2], "uv": [0, 0]}] - }, - { - "name": "hat", - "parent": "head", - "pivot": [0, 12, 0], - "cubes": [ - {"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [32, 0]} - ] - }, - { - "name": "leftarm", - "parent": "waist", - "mirror": true, - "pivot": [5, 10, 0], - "cubes": [ - {"origin": [5, 12, -1], "size": [2, 12, 2], "uv": [32, 16]} - ] - }, - {"name": "leftitem", "parent": "leftarm", "pivot": [1, -9, -5]}, - { - "name": "leftleg", - "parent": "waist", - "mirror": true, - "pivot": [1.9, 1, 0], - "cubes": [ - {"origin": [0.9, 1, -1], "size": [2, 11, 2], "uv": [40, 16]} - ] - }, - { - "name": "rightarm", - "parent": "waist", - "pivot": [-5, 10, 0], - "cubes": [ - {"origin": [-7, 12, -1], "size": [2, 12, 2], "uv": [24, 0]} - ] - }, - {"name": "rightitem", "parent": "rightarm", "pivot": [-1, -9, -5]}, - { - "name": "rightleg", - "parent": "waist", - "pivot": [-1.9, 1, 0], - "cubes": [ - {"origin": [-2.9, 1, -1], "size": [2, 11, 2], "uv": [8, 0]} - ] - } - ], - "visible_bounds_width": 1.5, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 64 - } - }, - "render_controllers": ["controller.render.armor_stand"], - "enable_attachables": true - }, - "arrow": { - "identifier": "minecraft:arrow", - "materials": {"default": "arrow"}, - "textures": {"default": "textures/entity/arrow"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 1, 0], - "cubes": [ - { - "origin": [0, -2.5, -3], - "rotation": [0, 0, 45], - "size": [0, 5, 16], - "uv": {"east": {"uv": [0, 0]}} - }, - { - "origin": [0, -2.5, -3], - "rotation": [0, 0, -45], - "size": [0, 5, 16], - "uv": {"east": {"uv": [0, 0]}} - }, - { - "origin": [-2.5, -2.5, 12], - "rotation": [0, 0, 45], - "size": [5, 5, 0], - "uv": {"south": {"uv": [0, 5]}} - } - ] - } - ], - "texturewidth": 32, - "textureheight": 32 - } - }, - "render_controllers": ["controller.render.arrow"] - }, - "bat": { - "identifier": "minecraft:bat", - "materials": {"default": "bat"}, - "textures": {"default": "textures/entity/bat"}, - "geometry": { - "default": { - "visible_bounds_width": 1, - "visible_bounds_height": 1, - "visible_bounds_offset": [0, 0.5, 0], - "bones": [ - { - "name": "head", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-3, 21, -3], "size": [6, 6, 6], "uv": [0, 0]}] - }, - { - "name": "rightEar", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 26, -2], "size": [3, 4, 1], "uv": [24, 0]} - ], - "parent": "head" - }, - { - "name": "leftEar", - "mirror": true, - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [1, 26, -2], "size": [3, 4, 1], "uv": [24, 0]} - ], - "parent": "head" - }, - { - "name": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-3, 8, -3], "size": [6, 12, 6], "uv": [0, 16]}, - {"origin": [-5, -8, 0], "size": [10, 16, 1], "uv": [0, 34]} - ] - }, - { - "name": "rightWing", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-12, 7, 1.5], "size": [10, 16, 1], "uv": [42, 0]} - ], - "parent": "body" - }, - { - "name": "rightWingTip", - "pivot": [-12, 23, 1.5], - "cubes": [ - {"origin": [-20, 10, 1.5], "size": [8, 12, 1], "uv": [24, 16]} - ], - "parent": "rightWing" - }, - { - "name": "leftWing", - "mirror": true, - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [2, 7, 1.5], "size": [10, 16, 1], "uv": [42, 0]} - ], - "parent": "body" - }, - { - "name": "leftWingTip", - "mirror": true, - "pivot": [12, 23, 1.5], - "cubes": [ - {"origin": [12, 10, 1.5], "size": [8, 12, 1], "uv": [24, 16]} - ], - "parent": "leftWing" - } - ] - } - }, - "render_controllers": ["controller.render.bat"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 18} - }, - "bee": { - "identifier": "minecraft:bee", - "materials": {"default": "bee"}, - "textures": { - "default": "textures/entity/bee/bee", - "angry": "textures/entity/bee/bee_angry", - "nectar": "textures/entity/bee/bee_nectar", - "angry_nectar": "textures/entity/bee/bee_angry_nectar" - }, - "geometry": { - "default": { - "texturewidth": 64, - "textureheight": 64, - "visible_bounds_width": 1.5, - "visible_bounds_height": 1.5, - "visible_bounds_offset": [0, 0.25, 0], - "bones": [ - { - "name": "body", - "pivot": [0.5, 5, 0], - "cubes": [ - {"origin": [-3, 2, -5], "size": [7, 7, 10], "uv": [0, 0]}, - {"origin": [2, 7, -8], "size": [1, 2, 3], "uv": [2, 0]}, - {"origin": [-2, 7, -8], "size": [1, 2, 3], "uv": [2, 3]} - ], - "locators": {"lead": [0, 4, -1]} - }, - { - "name": "stinger", - "parent": "body", - "pivot": [0.5, 6, 1], - "cubes": [{"origin": [0.5, 5, 5], "size": [0, 1, 2], "uv": [26, 7]}] - }, - { - "name": "rightwing_bone", - "parent": "body", - "pivot": [-1, 9, -3], - "rotation": [15, -15, 0], - "cubes": [ - {"origin": [-10, 9, -3], "size": [9, 0, 6], "uv": [0, 18]} - ] - }, - { - "name": "leftwing_bone", - "parent": "body", - "pivot": [2, 9, -3], - "rotation": [15, 15, 0], - "cubes": [{"origin": [2, 9, -3], "size": [9, 0, 6], "uv": [9, 24]}] - }, - { - "name": "leg_front", - "parent": "body", - "pivot": [2, 2, -2], - "cubes": [{"origin": [-3, 0, -2], "size": [7, 2, 0], "uv": [26, 1]}] - }, - { - "name": "leg_mid", - "parent": "body", - "pivot": [2, 2, 0], - "cubes": [{"origin": [-3, 0, 0], "size": [7, 2, 0], "uv": [26, 3]}] - }, - { - "name": "leg_back", - "parent": "body", - "pivot": [2, 2, 2], - "cubes": [{"origin": [-3, 0, 2], "size": [7, 2, 0], "uv": [26, 5]}] - } - ] - } - }, - "particle_effects": {"nectar_dripping": "minecraft:nectar_drip_particle"}, - "render_controllers": ["controller.render.bee"], - "spawn_egg": {"texture": "egg_bee", "texture_index": 0} - }, - "cave_spider": { - "identifier": "minecraft:cave_spider", - "min_engine_version": "1.8.0", - "materials": {"default": "spider", "invisible": "spider_invisible"}, - "textures": {"default": "textures/entity/spider/cave_spider"}, - "geometry": { - "default": { - "visible_bounds_width": 2, - "visible_bounds_height": 1, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "head", - "pivot": [0, 9, -3], - "cubes": [ - {"origin": [-4, 5, -11], "size": [8, 8, 8], "uv": [32, 4]} - ], - "parent": "body0" - }, - { - "name": "body0", - "pivot": [0, 9, 0], - "cubes": [{"origin": [-3, 6, -3], "size": [6, 6, 6], "uv": [0, 0]}] - }, - { - "name": "body1", - "pivot": [0, 9, 9], - "cubes": [ - {"origin": [-5, 5, 3], "size": [10, 8, 12], "uv": [0, 12]} - ], - "parent": "body0" - }, - { - "name": "leg0", - "pivot": [-4, 9, 2], - "cubes": [ - {"origin": [-19, 8, 1], "size": [16, 2, 2], "uv": [18, 0]} - ], - "parent": "body0" - }, - { - "name": "leg1", - "pivot": [4, 9, 2], - "cubes": [{"origin": [3, 8, 1], "size": [16, 2, 2], "uv": [18, 0]}], - "parent": "body0" - }, - { - "name": "leg2", - "pivot": [-4, 9, 1], - "cubes": [ - {"origin": [-19, 8, 0], "size": [16, 2, 2], "uv": [18, 0]} - ], - "parent": "body0" - }, - { - "name": "leg3", - "pivot": [4, 9, 1], - "cubes": [{"origin": [3, 8, 0], "size": [16, 2, 2], "uv": [18, 0]}], - "parent": "body0" - }, - { - "name": "leg4", - "pivot": [-4, 9, 0], - "cubes": [ - {"origin": [-19, 8, -1], "size": [16, 2, 2], "uv": [18, 0]} - ], - "parent": "body0" - }, - { - "name": "leg5", - "pivot": [4, 9, 0], - "cubes": [ - {"origin": [3, 8, -1], "size": [16, 2, 2], "uv": [18, 0]} - ], - "parent": "body0" - }, - { - "name": "leg6", - "pivot": [-4, 9, -1], - "cubes": [ - {"origin": [-19, 8, -2], "size": [16, 2, 2], "uv": [18, 0]} - ], - "parent": "body0" - }, - { - "name": "leg7", - "pivot": [4, 9, -1], - "cubes": [ - {"origin": [3, 8, -2], "size": [16, 2, 2], "uv": [18, 0]} - ], - "parent": "body0" - } - ] - } - }, - "render_controllers": ["controller.render.spider"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 22} - }, - "chest_minecart": { - "identifier": "minecraft:chest_minecart", - "min_engine_version": "1.8.0", - "materials": {"default": "minecart"}, - "textures": {"default": "textures/entity/minecart"}, - "geometry": { - "default": { - "bones": [ - { - "name": "bottom", - "pivot": [0, 6, 0], - "cubes": [ - { - "origin": [-10, -6.5, -1], - "size": [20, 16, 2], - "rotation": [90, 0, 0], - "uv": [0, 10] - } - ] - }, - { - "name": "back", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-17, 2.5, -1], - "size": [16, 8, 2], - "rotation": [0, 270, 0], - "uv": [0, 0] - } - ], - "parent": "bottom" - }, - { - "name": "front", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [1, 2.5, -1], - "size": [16, 8, 2], - "rotation": [0, 90, 0], - "uv": [0, 0] - } - ], - "parent": "bottom" - }, - { - "name": "right", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, 2.5, -8], - "size": [16, 8, 2], - "rotation": [0, 180, 0], - "uv": [0, 0] - } - ], - "parent": "bottom" - }, - { - "name": "left", - "pivot": [0, 0, 0], - "cubes": [ - {"origin": [-8, 2.5, 6], "size": [16, 8, 2], "uv": [0, 0]} - ], - "parent": "bottom" - } - ], - "texturewidth": 64, - "textureheight": 32 - } - }, - "render_controllers": ["controller.render.minecart"] - }, - "command_block_minecart": { - "identifier": "minecraft:command_block_minecart", - "min_engine_version": "1.8.0", - "materials": {"default": "minecart"}, - "textures": {"default": "textures/entity/minecart"}, - "geometry": { - "default": { - "bones": [ - { - "name": "bottom", - "pivot": [0, 6, 0], - "cubes": [ - { - "origin": [-10, -6.5, -1], - "size": [20, 16, 2], - "rotation": [90, 0, 0], - "uv": [0, 10] - } - ] - }, - { - "name": "back", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-17, 2.5, -1], - "size": [16, 8, 2], - "rotation": [0, 270, 0], - "uv": [0, 0] - } - ], - "parent": "bottom" - }, - { - "name": "front", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [1, 2.5, -1], - "size": [16, 8, 2], - "rotation": [0, 90, 0], - "uv": [0, 0] - } - ], - "parent": "bottom" - }, - { - "name": "right", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, 2.5, -8], - "size": [16, 8, 2], - "rotation": [0, 180, 0], - "uv": [0, 0] - } - ], - "parent": "bottom" - }, - { - "name": "left", - "pivot": [0, 0, 0], - "cubes": [ - {"origin": [-8, 2.5, 6], "size": [16, 8, 2], "uv": [0, 0]} - ], - "parent": "bottom" - } - ], - "texturewidth": 64, - "textureheight": 32 - } - }, - "render_controllers": ["controller.render.minecart"] - }, - "cow": { - "identifier": "minecraft:cow", - "min_engine_version": "1.8.0", - "materials": {"default": "cow"}, - "textures": {"default": "textures/entity/cow/cow"}, - "geometry": { - "default": { - "visible_bounds_width": 2, - "visible_bounds_height": 1.75, - "visible_bounds_offset": [0, 0.75, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "body", - "pivot": [0, 19, 2], - "bind_pose_rotation": [90, 0, 0], - "cubes": [ - {"origin": [-6, 11, -5], "size": [12, 18, 10], "uv": [18, 4]}, - {"origin": [-2, 11, -6], "size": [4, 6, 1], "uv": [52, 0]} - ] - }, - { - "name": "head", - "parent": "body", - "pivot": [0, 20, -8], - "locators": {"lead": [0, 20, -8]}, - "cubes": [ - {"origin": [-4, 16, -14], "size": [8, 8, 6], "uv": [0, 0]}, - {"origin": [-5, 22, -12], "size": [1, 3, 1], "uv": [22, 0]}, - {"origin": [4, 22, -12], "size": [1, 3, 1], "uv": [22, 0]} - ] - }, - { - "name": "leg0", - "parent": "body", - "pivot": [-4, 12, 7], - "cubes": [{"origin": [-6, 0, 5], "size": [4, 12, 4], "uv": [0, 16]}] - }, - { - "name": "leg1", - "parent": "body", - "mirror": true, - "pivot": [4, 12, 7], - "cubes": [{"origin": [2, 0, 5], "size": [4, 12, 4], "uv": [0, 16]}] - }, - { - "name": "leg2", - "parent": "body", - "pivot": [-4, 12, -6], - "cubes": [ - {"origin": [-6, 0, -7], "size": [4, 12, 4], "uv": [0, 16]} - ] - }, - { - "name": "leg3", - "parent": "body", - "mirror": true, - "pivot": [4, 12, -6], - "cubes": [{"origin": [2, 0, -7], "size": [4, 12, 4], "uv": [0, 16]}] - } - ] - } - }, - "render_controllers": ["controller.render.cow"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 1} - }, - "dragon_fireball": { - "identifier": "minecraft:dragon_fireball", - "materials": {"default": "fireball"}, - "textures": {"default": "textures/entity/enderdragon/dragon_fireball"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, -4, 0], - "size": [16, 16, 0], - "uv": {"south": {"uv": [0, 0]}} - } - ] - } - ], - "texturewidth": 16, - "textureheight": 16 - } - }, - "render_controllers": ["controller.render.fireball"] - }, - "drowned": { - "identifier": "minecraft:drowned", - "min_engine_version": "1.16.0", - "materials": {"default": "drowned"}, - "textures": {"default": "textures/entity/zombie/drowned"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]} - ] - }, - { - "name": "jacket", - "parent": "body", - "pivot": [0, 24, 0], - "cubes": [ - { - "origin": [-4, 12, -2], - "size": [8, 12, 4], - "uv": [16, 32], - "inflate": 0.5 - } - ] - }, - { - "name": "head", - "parent": "body", - "pivot": [0, 24, 0], - "cubes": [ - { - "origin": [-4, 24, -4], - "size": [8, 8, 8], - "uv": [0, 0], - "inflate": 0.5 - } - ] - }, - { - "name": "hat", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - { - "origin": [-4, 24, -4], - "size": [8, 8, 8], - "uv": [32, 0], - "inflate": 1 - } - ] - }, - { - "name": "rightArm", - "parent": "body", - "pivot": [-5, 22, 0], - "cubes": [ - {"origin": [-7, 12, -2], "size": [4, 12, 4], "uv": [0, 16]} - ] - }, - { - "name": "leftArm", - "parent": "body", - "pivot": [5, 22, 0], - "cubes": [ - { - "origin": [4, 12, -2], - "size": [4, 12, 4], - "uv": [40, 16], - "mirror": true - } - ] - }, - { - "name": "rightSleeve", - "parent": "rightArm", - "pivot": [-5, 22, 0], - "cubes": [ - { - "origin": [-7, 12, -2], - "size": [4, 12, 4], - "uv": [48, 48], - "inflate": 0.5 - } - ] - }, - { - "name": "leftSleeve", - "parent": "leftArm", - "pivot": [5, 22, 0], - "cubes": [ - { - "origin": [4, 12, -2], - "size": [4, 12, 4], - "uv": [40, 32], - "inflate": 0.5, - "mirror": true - } - ] - }, - { - "name": "rightLeg", - "parent": "body", - "pivot": [-1.9, 12, 0], - "cubes": [ - {"origin": [-4.05, 0, -2], "size": [4, 12, 4], "uv": [16, 48]} - ] - }, - { - "name": "leftLeg", - "parent": "body", - "pivot": [1.9, 12, 0], - "cubes": [ - { - "origin": [0.05, 0, -2], - "size": [4, 12, 4], - "uv": [32, 48], - "mirror": true - } - ] - }, - { - "name": "rightPants", - "parent": "rightLeg", - "pivot": [-1.9, 12, 0], - "cubes": [ - { - "origin": [-4.25, 0, -2], - "size": [4, 12, 4], - "uv": [0, 48], - "inflate": 0.25 - } - ] - }, - { - "name": "leftPants", - "parent": "leftLeg", - "pivot": [1.9, 12, 0], - "cubes": [ - { - "origin": [0.25, 0, -2], - "size": [4, 12, 4], - "uv": [0, 32], - "inflate": 0.25, - "mirror": true - } - ] - }, - {"name": "waist", "parent": "body", "pivot": [0, 12, 0]}, - {"name": "rightItem", "parent": "rightArm", "pivot": [-1, -45, -5]}, - {"name": "leftItem", "parent": "leftArm", "pivot": [1, -45, -5]} - ], - "visible_bounds_width": 2.5, - "visible_bounds_height": 2.5, - "visible_bounds_offset": [0, 1.25, 0], - "texturewidth": 64, - "textureheight": 64 - } - }, - "render_controllers": ["controller.render.drowned"], - "enable_attachables": true, - "spawn_egg": {"texture": "spawn_egg", "texture_index": 48} - }, - "egg": { - "identifier": "minecraft:egg", - "materials": {"default": "egg"}, - "textures": {"default": "textures/items/egg"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, -8, 0], - "size": [16, 16, 0], - "uv": [0, 0], - "rotation": [0, 0, 0] - } - ] - } - ], - "texturewidth": 16, - "textureheight": 16 - } - }, - "render_controllers": ["controller.render.item_sprite"] - }, - "elder_guardian": { - "identifier": "minecraft:elder_guardian", - "min_engine_version": "1.8.0", - "materials": {"default": "guardian", "ghost": "guardian_ghost"}, - "textures": { - "default": "textures/entity/guardian", - "elder": "textures/entity/guardian_elder", - "beam": "textures/entity/guardian_beam" - }, - "geometry": { - "default": { - "visible_bounds_width": 3.5, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 64, - "bones": [ - { - "name": "head", - "pivot": [0, 0, 0], - "mirror": true, - "cubes": [ - { - "mirror": false, - "origin": [-6, 2, -8], - "size": [12, 12, 16], - "uv": [0, 0] - }, - { - "mirror": false, - "origin": [-8, 2, -6], - "size": [2, 12, 12], - "uv": [0, 28] - }, - {"origin": [6, 2, -6], "size": [2, 12, 12], "uv": [0, 28]}, - {"origin": [-6, 14, -6], "size": [12, 2, 12], "uv": [16, 40]}, - {"origin": [-6, 0, -6], "size": [12, 2, 12], "uv": [16, 40]} - ] - }, - { - "name": "eye", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-1, 6, 0], "size": [2, 2, 1], "uv": [8, 0]}] - }, - { - "name": "tailpart0", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-2, 6, 7], "size": [4, 4, 8], "uv": [40, 0]}] - }, - { - "name": "tailpart1", - "parent": "tailpart0", - "pivot": [0, 24, 0], - "cubes": [{"origin": [0, 7, 0], "size": [3, 3, 7], "uv": [0, 54]}] - }, - { - "name": "tailpart2", - "parent": "tailpart1", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [0, 8, 0], "size": [2, 2, 6], "uv": [41, 32]}, - {"origin": [1, 4.5, 3], "size": [1, 9, 9], "uv": [25, 19]} - ] - }, - { - "name": "spikepart0", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart1", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart2", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart3", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart4", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart5", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart6", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart7", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart8", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart9", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart10", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart11", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - } - ] - }, - "ghost": { - "visible_bounds_width": 3.5, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 64, - "bones": [ - { - "name": "head", - "pivot": [0, 24, 0], - "mirror": true, - "cubes": [ - { - "mirror": false, - "origin": [-6, 2, -8], - "size": [12, 12, 16], - "uv": [0, 0] - }, - { - "mirror": false, - "origin": [-8, 2, -6], - "size": [2, 12, 12], - "uv": [0, 28] - }, - {"origin": [6, 2, -6], "size": [2, 12, 12], "uv": [0, 28]}, - {"origin": [-6, 14, -6], "size": [12, 2, 12], "uv": [16, 40]}, - {"origin": [-6, 0, -6], "size": [12, 2, 12], "uv": [16, 40]} - ] - }, - { - "name": "eye", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-1, 7, 0], "size": [2, 2, 1], "uv": [8, 0]}] - }, - { - "name": "tailpart0", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-2, 6, 7], "size": [4, 4, 8], "uv": [40, 0]}] - }, - { - "name": "tailpart1", - "parent": "tailpart0", - "pivot": [0, 24, 0], - "cubes": [{"origin": [0, 7, 0], "size": [3, 3, 7], "uv": [0, 54]}] - }, - { - "name": "tailpart2", - "parent": "tailpart1", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [0, 8, 0], "size": [2, 2, 6], "uv": [41, 32]}, - {"origin": [1, 4.5, 3], "size": [1, 9, 9], "uv": [25, 19]} - ] - }, - { - "name": "spikepart0", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart1", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart2", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart3", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart4", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart5", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart6", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart7", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart8", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart9", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart10", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - }, - { - "name": "spikepart11", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-1, 19.5, -1], "size": [2, 9, 2], "uv": [0, 0]} - ] - } - ] - } - }, - "render_controllers": ["controller.render.guardian"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 36} - }, - "eye_of_ender": { - "identifier": "minecraft:eye_of_ender_signal", - "materials": {"default": "eye_of_ender_signal"}, - "textures": {"default": "textures/items/ender_eye"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, -8, 0], - "size": [16, 16, 0], - "uv": [0, 0], - "rotation": [0, 0, 0] - } - ] - } - ], - "texturewidth": 16, - "textureheight": 16 - } - }, - "render_controllers": ["controller.render.item_sprite"] - }, - "ender_pearl": { - "identifier": "minecraft:ender_pearl", - "materials": {"default": "ender_pearl"}, - "textures": {"default": "textures/items/ender_pearl"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, -8, 0], - "size": [16, 16, 0], - "uv": [0, 0], - "rotation": [0, 0, 0] - } - ] - } - ], - "texturewidth": 16, - "textureheight": 16 - } - }, - "render_controllers": ["controller.render.item_sprite"] - }, - "evoker_fangs": { - "identifier": "minecraft:evocation_fang", - "materials": {"default": "fang"}, - "textures": {"default": "textures/entity/illager/evoker_fangs"}, - "geometry": { - "default": { - "visible_bounds_width": 1.5, - "visible_bounds_height": 3, - "visible_bounds_offset": [0, 1.5, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "upper_jaw", - "parent": "base", - "pivot": [0, 11, 0], - "cubes": [ - { - "origin": [-1.5, 0, -4], - "size": [4, 14, 8], - "uv": [40, 0], - "inflate": 0.01 - } - ] - }, - { - "name": "lower_jaw", - "parent": "base", - "pivot": [0, 11, 0], - "bind_pose_rotation": [0, 180, 0], - "cubes": [ - {"origin": [-1.5, 0, -4], "size": [4, 14, 8], "uv": [40, 0]} - ] - }, - { - "name": "base", - "pivot": [0, 0, 0], - "bind_pose_rotation": [0, 90, 0], - "cubes": [ - {"origin": [-5, 0, -5], "size": [10, 12, 10], "uv": [0, 0]} - ] - } - ] - } - }, - "render_controllers": ["controller.render.evocation_fang"] - }, - "evoker": { - "identifier": "minecraft:evocation_illager", - "min_engine_version": "1.8.0", - "materials": {"default": "evoker"}, - "textures": {"default": "textures/entity/illager/evoker"}, - "geometry": { - "default": { - "visible_bounds_width": 1.5, - "visible_bounds_height": 2.5, - "visible_bounds_offset": [0, 1.25, 0], - "texturewidth": 64, - "textureheight": 64, - "bones": [ - { - "name": "head", - "parent": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 24, -4], "size": [8, 10, 8], "uv": [0, 0]} - ] - }, - { - "name": "nose", - "parent": "head", - "pivot": [0, 26, 0], - "cubes": [ - {"origin": [-1, 23, -6], "size": [2, 4, 2], "uv": [24, 0]} - ] - }, - { - "name": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 12, -3], "size": [8, 12, 6], "uv": [16, 20]}, - { - "origin": [-4, 6, -3], - "size": [8, 18, 6], - "uv": [0, 38], - "inflate": 0.5 - } - ] - }, - { - "name": "arms", - "parent": "body", - "pivot": [0, 22, 0], - "cubes": [ - {"origin": [-8, 16, -2], "size": [4, 8, 4], "uv": [44, 22]}, - {"origin": [4, 16, -2], "size": [4, 8, 4], "uv": [44, 22]}, - {"origin": [-4, 16, -2], "size": [8, 4, 4], "uv": [40, 38]} - ] - }, - { - "name": "leg0", - "parent": "body", - "pivot": [-2, 12, 0], - "cubes": [ - {"origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} - ] - }, - { - "name": "leg1", - "parent": "body", - "pivot": [2, 12, 0], - "mirror": true, - "cubes": [{"origin": [0, 0, -2], "size": [4, 12, 4], "uv": [0, 22]}] - }, - { - "name": "rightArm", - "parent": "body", - "pivot": [-5, 22, 0], - "locators": {"right_hand": [-6, 12, 0]}, - "cubes": [ - {"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 46]} - ] - }, - { - "name": "rightItem", - "pivot": [-5.5, 16, 0.5], - "neverRender": true, - "parent": "rightArm" - }, - { - "name": "leftArm", - "parent": "body", - "pivot": [5, 22, 0], - "locators": {"left_hand": [6, 12, 0]}, - "mirror": true, - "cubes": [ - {"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 46]} - ] - } - ] - } - }, - "particle_effects": {"spell": "minecraft:evoker_spell"}, - "render_controllers": ["controller.render.evoker"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 40} - }, - "experience_bottle": { - "identifier": "minecraft:xp_bottle", - "materials": {"default": "xp_bottle"}, - "textures": { - "default": "textures/items/experience_bottle", - "enchanted": "textures/misc/enchanted_item_glint" - }, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, -8, 0], - "size": [16, 16, 0], - "uv": [0, 0], - "rotation": [0, 0, 0] - } - ] - } - ], - "texturewidth": 16, - "textureheight": 16 - } - }, - "render_controllers": ["controller.render.experience_bottle"] - }, - "experience_orb": { - "identifier": "minecraft:xp_orb", - "materials": {"default": "experience_orb"}, - "textures": {"default": "textures/entity/experience_orb"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [8, 8, 0], - "cubes": [ - { - "origin": [0, 0, 0], - "size": [16, 16, 0], - "uv": {"south": {"uv": [0, 0]}} - } - ] - } - ], - "texturewidth": 64, - "textureheight": 64 - } - }, - "render_controllers": ["controller.render.experience_orb"] - }, - "fireball": { - "identifier": "minecraft:fireball", - "materials": {"default": "fireball"}, - "textures": {"default": "textures/items/fire_charge"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, -4, 0], - "size": [16, 16, 0], - "uv": {"south": {"uv": [0, 0]}} - } - ] - } - ], - "texturewidth": 16, - "textureheight": 16 - } - }, - "render_controllers": ["controller.render.fireball"] - }, - "firework_rocket": { - "identifier": "minecraft:fireworks_rocket", - "materials": {"default": "fireworks_rocket"}, - "textures": {"default": "textures/entity/fireworks"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, -8, 0], - "rotation": [0, 90, 0], - "size": [16, 16, 0], - "uv": {"north": {"uv": [0, 0]}} - }, - { - "origin": [-8, -8, 0], - "rotation": [90, 90, 0], - "size": [16, 16, 0], - "uv": {"north": {"uv": [0, 0]}} - } - ] - } - ], - "texturewidth": 32, - "textureheight": 32 - } - }, - "render_controllers": ["controller.render.fireworks_rocket"] - }, - "fishing_bobber": { - "identifier": "minecraft:fishing_hook", - "materials": {"default": "fishing_hook"}, - "textures": {"default": "textures/entity/fishing_hook"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-1.5, -1.5, -1.5], - "size": [3, 3, 3], - "rotation": [0, 0, 180], - "uv": { - "up": {"uv": [0, 0]}, - "down": {"uv": [3, 0]}, - "south": {"uv": [9, 0], "uv_size": [-3, 3]}, - "north": {"uv": [9, 0]}, - "east": {"uv": [12, 0]}, - "west": {"uv": [15, 0]} - } - }, - { - "origin": [0, -4.5, -0.5], - "size": [0, 3, 3], - "uv": {"east": {"uv": [18, 0]}} - }, - { - "origin": [0, 1.5, -1.5], - "size": [0, 3, 3], - "uv": {"east": {"uv": [21, 0]}} - }, - { - "origin": [-1.5, 1.5, 0], - "size": [3, 3, 0], - "uv": {"north": {"uv": [21, 0]}} - } - ] - } - ], - "texturewidth": 24, - "textureheight": 3 - } - }, - "render_controllers": ["controller.render.fishing_hook"] - }, - "hoglin": { - "identifier": "minecraft:hoglin", - "materials": {"default": "hoglin"}, - "textures": {"default": "textures/entity/hoglin/hoglin"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 19, -3], - "cubes": [ - { - "origin": [-8, 11, -7], - "size": [16, 14, 26], - "inflate": 0.02, - "uv": [1, 1] - }, - { - "origin": [0, 22, -10], - "size": [0, 10, 19], - "inflate": 0.02, - "uv": [90, 33] - } - ], - "locators": {"lead": [0, 20, -5]} - }, - { - "name": "head", - "parent": "body", - "pivot": [0, 22, -5], - "rotation": [50, 0, 0], - "cubes": [ - {"origin": [-7, 21, -24], "size": [14, 6, 19], "uv": [61, 1]}, - {"origin": [-8, 22, -19], "size": [2, 11, 2], "uv": [1, 13]}, - {"origin": [6, 22, -19], "size": [2, 11, 2], "uv": [1, 13]} - ] - }, - { - "name": "right_ear", - "parent": "head", - "pivot": [-7, 27, -7], - "rotation": [0, 0, -50], - "cubes": [ - {"origin": [-13, 26, -10], "size": [6, 1, 4], "uv": [1, 1]} - ] - }, - { - "name": "left_ear", - "parent": "head", - "pivot": [7, 27, -7], - "rotation": [0, 0, 50], - "cubes": [{"origin": [7, 26, -10], "size": [6, 1, 4], "uv": [1, 6]}] - }, - { - "name": "leg_back_right", - "pivot": [6, 8, 17], - "cubes": [ - {"origin": [-8, 0, 13], "size": [5, 11, 5], "uv": [21, 45]} - ] - }, - { - "name": "leg_back_left", - "pivot": [-6, 8, 17], - "cubes": [{"origin": [3, 0, 13], "size": [5, 11, 5], "uv": [0, 45]}] - }, - { - "name": "leg_front_right", - "pivot": [-6, 12, -3], - "cubes": [ - {"origin": [-8, 0, -6], "size": [6, 14, 6], "uv": [66, 42]} - ] - }, - { - "name": "leg_front_left", - "pivot": [6, 12, -3], - "cubes": [ - {"origin": [2, 0, -6], "size": [6, 14, 6], "uv": [41, 42]} - ] - } - ], - "visible_bounds_width": 4, - "visible_bounds_height": 3, - "visible_bounds_offset": [0, 1.5, 0], - "texturewidth": 128, - "textureheight": 64 - } - }, - "spawn_egg": {"base_color": "#C66E55", "overlay_color": "#5f6464"}, - "render_controllers": ["controller.render.hoglin"] - }, - "hopper_minecart": { - "identifier": "minecraft:hopper_minecart", - "min_engine_version": "1.8.0", - "materials": {"default": "minecart"}, - "textures": {"default": "textures/entity/minecart"}, - "geometry": { - "default": { - "bones": [ - { - "name": "bottom", - "pivot": [0, 6, 0], - "cubes": [ - { - "origin": [-10, -6.5, -1], - "size": [20, 16, 2], - "rotation": [90, 0, 0], - "uv": [0, 10] - } - ] - }, - { - "name": "back", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-17, 2.5, -1], - "size": [16, 8, 2], - "rotation": [0, 270, 0], - "uv": [0, 0] - } - ], - "parent": "bottom" - }, - { - "name": "front", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [1, 2.5, -1], - "size": [16, 8, 2], - "rotation": [0, 90, 0], - "uv": [0, 0] - } - ], - "parent": "bottom" - }, - { - "name": "right", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, 2.5, -8], - "size": [16, 8, 2], - "rotation": [0, 180, 0], - "uv": [0, 0] - } - ], - "parent": "bottom" - }, - { - "name": "left", - "pivot": [0, 0, 0], - "cubes": [ - {"origin": [-8, 2.5, 6], "size": [16, 8, 2], "uv": [0, 0]} - ], - "parent": "bottom" - } - ], - "texturewidth": 64, - "textureheight": 32 - } - }, - "render_controllers": ["controller.render.minecart"] - }, - "husk": { - "identifier": "minecraft:husk", - "min_engine_version": "1.8.0", - "materials": {"default": "husk"}, - "textures": {"default": "textures/entity/zombie/husk"}, - "geometry": { - "default": { - "visible_bounds_width": 1.5, - "visible_bounds_height": 2.5, - "visible_bounds_offset": [0, 1.25, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]} - ], - "parent": "waist" - }, - {"name": "waist", "neverRender": true, "pivot": [0, 12, 0]}, - { - "name": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]} - ], - "parent": "body" - }, - { - "name": "hat", - "pivot": [0, 24, 0], - "cubes": [ - { - "origin": [-4, 24, -4], - "size": [8, 8, 8], - "uv": [32, 0], - "inflate": 0.5 - } - ], - "neverRender": true, - "parent": "head" - }, - { - "name": "rightArm", - "pivot": [-5, 22, 0], - "cubes": [ - {"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]} - ], - "parent": "body" - }, - { - "name": "rightItem", - "pivot": [-1, -45, -5], - "neverRender": true, - "parent": "rightArm" - }, - { - "name": "leftArm", - "pivot": [5, 22, 0], - "cubes": [ - {"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 16]} - ], - "mirror": true, - "parent": "body" - }, - { - "name": "leftItem", - "pivot": [1, -45, -5], - "neverRender": true, - "parent": "leftArm" - }, - { - "name": "rightLeg", - "pivot": [-1.9, 12, 0], - "cubes": [ - {"origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]} - ], - "parent": "body" - }, - { - "name": "leftLeg", - "pivot": [1.9, 12, 0], - "cubes": [ - {"origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 16]} - ], - "mirror": true, - "parent": "body" - } - ] - } - }, - "scripts": { - "pre_animation": [ - "variable.tcos0 = (Math.cos(query.modified_distance_moved * 38.17) * query.modified_move_speed / variable.gliding_speed_value) * 57.3;" - ] - }, - "animations": { - "humanoid_big_head": {"loop": true, "bones": {"head": {"scale": 1.4}}}, - "look_at_target_default": { - "loop": true, - "bones": { - "head": { - "relative_to": {"rotation": "entity"}, - "rotation": [ - "query.target_x_rotation", - "query.target_y_rotation", - 0 - ] - } - } - }, - "look_at_target_gliding": { - "loop": true, - "bones": {"head": {"rotation": [-45, "query.target_y_rotation", 0]}} - }, - "look_at_target_swimming": { - "loop": true, - "bones": { - "head": { - "rotation": [ - "math.lerp(query.target_x_rotation, -45.0, variable.swim_amount)", - "query.target_y_rotation", - 0 - ] - } - } - }, - "move": { - "loop": true, - "bones": { - "leftarm": {"rotation": ["variable.tcos0", 0, 0]}, - "leftleg": {"rotation": ["variable.tcos0 * -1.4", 0, 0]}, - "rightarm": {"rotation": ["-variable.tcos0", 0, 0]}, - "rightleg": {"rotation": ["variable.tcos0 * 1.4", 0, 0]} - } - }, - "riding.arms": { - "loop": true, - "bones": { - "leftarm": {"rotation": [-36, 0, 0]}, - "rightarm": {"rotation": [-36, 0, 0]} - } - }, - "riding.legs": { - "loop": true, - "bones": { - "leftleg": {"rotation": ["-72.0 - this", "-18.0 - this", "-this"]}, - "rightleg": {"rotation": ["-72.0 - this", "18.0 - this", "-this"]} - } - }, - "holding": { - "loop": true, - "bones": { - "leftarm": { - "rotation": [ - "variable.is_holding_left ? (-this * 0.5 - 18.0) : 0.0", - 0, - 0 - ] - }, - "rightarm": { - "rotation": [ - "variable.is_holding_right ? (-this * 0.5 - 18.0) : 0.0", - 0, - 0 - ] - } - } - }, - "brandish_spear": { - "loop": true, - "bones": { - "rightarm": { - "rotation": [ - "this * -0.5 - 157.5 - 22.5 * variable.charge_amount", - "-this", - 0 - ] - } - } - }, - "charging": { - "loop": true, - "bones": { - "rightarm": { - "rotation": ["22.5 * variable.charge_amount - this", "-this", 0] - } - } - }, - "attack.rotations": { - "loop": true, - "bones": { - "body": { - "rotation": [ - 0, - "math.sin(math.sqrt(variable.attack_time) * 360) * 11.46 - this", - 0 - ] - }, - "leftarm": { - "rotation": [ - "math.sin(math.sqrt(variable.attack_time) * 360) * 11.46", - 0, - 0 - ] - }, - "rightarm": { - "rotation": [ - "math.sin(1.0 - math.pow(1.0 - variable.attack_time, 3.0) * 180.0) * (variable.is_brandishing_spear ? -1.0 : 1.0 )", - "variable.is_brandishing_spear ? 0.0 : (math.sin(math.sqrt(variable.attack_time) * 360) * 11.46) * 2.0", - 0 - ] - } - } - }, - "sneaking": { - "loop": true, - "bones": { - "body": {"rotation": ["0.5 - this", 0, 0]}, - "head": {"position": [0, 1, 0]}, - "leftarm": {"rotation": [72, 0, 0]}, - "leftleg": {"position": [0, -3, 4]}, - "rightarm": {"rotation": [72, 0, 0]}, - "rightleg": {"position": [0, -3, 4]} - } - }, - "bob": { - "loop": true, - "bones": { - "leftarm": { - "rotation": [ - 0, - 0, - "((math.cos(query.life_time * 103.2) * 2.865) + 2.865) *-1.0" - ] - }, - "rightarm": { - "rotation": [ - 0, - 0, - "(math.cos(query.life_time * 103.2) * 2.865) + 2.865" - ] - } - } - }, - "damage_nearby_mobs": { - "loop": true, - "bones": { - "leftarm": {"rotation": ["-45.0-this", "-this", "-this"]}, - "leftleg": {"rotation": ["45.0-this", "-this", "-this"]}, - "rightarm": {"rotation": ["45.0-this", "-this", "-this"]}, - "rightleg": {"rotation": ["-45.0-this", "-this", "-this"]} - } - }, - "bow_and_arrow": { - "loop": true, - "bones": { - "leftarm": { - "rotation": [ - "query.target_x_rotation - 90.0 - math.sin(query.life_time * 76.8) * 2.865 - this", - "query.target_y_rotation + 28.65", - "-(math.cos(query.life_time * 103.2) * 2.865) - 2.865" - ] - }, - "rightarm": { - "rotation": [ - "query.target_x_rotation - 90.0 + math.sin(query.life_time * 76.8) * 2.865 - this", - "query.target_y_rotation - 5.73", - "(math.cos(query.life_time * 103.2) * 2.865) + 2.865" - ] - } - } - }, - "use_item_progress": { - "loop": true, - "bones": { - "rightarm": { - "rotation": [ - "variable.use_item_startup_progress * -60.0 + variable.use_item_interval_progress * 11.25", - "variable.use_item_startup_progress * -22.5 + variable.use_item_interval_progress * 11.25", - "variable.use_item_startup_progress * -5.625 + variable.use_item_interval_progress * 11.25" - ] - } - } - }, - "zombie_attack_bare_hand": { - "loop": true, - "bones": { - "leftarm": { - "rotation": [ - "-90.0 - ((math.sin(variable.attack_time * 180.0) * 57.3) * 1.2 - (math.sin((1.0 - (1.0 - variable.attack_time) * (1.0 - variable.attack_time)) * 180.0) * 57.3) * 0.4) - (math.sin(query.life_time * 76.776372) * 2.865) - this", - "5.73 - ((math.sin(variable.attack_time * 180.0) * 57.3) * 0.6) - this", - "math.cos(query.life_time * 103.13244) * -2.865 - 2.865 - this" - ] - }, - "rightarm": { - "rotation": [ - "90.0 * (variable.is_brandishing_spear - 1.0) - ((math.sin(variable.attack_time * 180.0) * 57.3) * 1.2 - (math.sin((1.0 - (1.0 - variable.attack_time) * (1.0 - variable.attack_time)) * 180.0) * 57.3) * 0.4) + (math.sin(query.life_time * 76.776372) * 2.865) - this", - "(math.sin(variable.attack_time * 180.0) * 57.3) * 0.6 - 5.73 - this", - "math.cos(query.life_time * 103.13244) * 2.865 + 2.865 - this" - ] - } - } - }, - "swimming": { - "loop": true, - "bones": { - "body": { - "position": [ - 0, - "variable.swim_amount * -10.0 - this", - "variable.swim_amount * 9.0 - this" - ], - "rotation": [ - "variable.swim_amount * (90.0 + query.target_x_rotation)", - 0, - 0 - ] - }, - "leftarm": { - "rotation": [ - "math.lerp(this, -180.0, variable.swim_amount) - (variable.swim_amount * ((math.sin(variable.attack_time * 180.0) * 57.3) * 1.2 - (math.sin((1.0 - (1.0 - variable.attack_time) * (1.0 - variable.attack_time)) * 180.0) * 57.3) * 0.4)) - (variable.swim_amount * (math.sin(query.life_time * 76.776372) * 2.865)) - this", - "math.lerp(this, 14.325, variable.swim_amount) - this", - "math.lerp(this, 14.325, variable.swim_amount) - (variable.swim_amount * (math.cos(query.life_time * 103.13244) * 2.865 + 2.865)) - this" - ] - }, - "leftleg": { - "rotation": [ - "math.lerp(this, math.cos(query.life_time * 390.0 + 180.0) * 0.3, variable.swim_amount)", - 0, - 0 - ] - }, - "rightarm": { - "rotation": [ - "math.lerp(this, -180.0, variable.swim_amount) - (variable.swim_amount * ((math.sin(variable.attack_time * 180.0) * 57.3) * 1.2 - (math.sin((1.0 - (1.0 - variable.attack_time) * (1.0 - variable.attack_time)) * 180.0) * 57.3) * 0.4)) + (variable.swim_amount * (math.sin(query.life_time * 76.776372) * 2.865)) - this", - "math.lerp(this, 14.325, variable.swim_amount) - this", - "math.lerp(this, -14.325, variable.swim_amount) + (variable.swim_amount * (math.cos(query.life_time * 103.13244) * 2.865 + 2.865)) - this" - ] - }, - "rightleg": { - "rotation": [ - "math.lerp(this, math.cos(query.life_time * 390.0) * 0.3, variable.swim_amount)", - 0, - 0 - ] - } - } - } - }, - "animation_controllers": { - "humanoid_baby_big_head": { - "initial_state": "default", - "states": { - "baby": { - "animations": ["humanoid_big_head"], - "transitions": [{"default": "!query.is_baby"}] - }, - "default": {"transitions": [{"baby": "query.is_baby"}]} - } - }, - "look_at_target": { - "initial_state": "default", - "states": { - "default": { - "animations": ["look_at_target_default"], - "transitions": [ - {"gliding": "query.is_gliding"}, - {"swimming": "query.is_swimming"} - ] - }, - "gliding": { - "animations": ["look_at_target_gliding"], - "transitions": [ - {"swimming": "query.is_swimming"}, - {"default": "!query.is_gliding"} - ] - }, - "swimming": { - "animations": ["look_at_target_swimming"], - "transitions": [ - {"gliding": "query.is_gliding"}, - {"default": "!query.is_swimming"} - ] - } - } - }, - "move": { - "initial_state": "default", - "states": {"default": {"animations": ["move"]}} - }, - "riding": { - "initial_state": "default", - "states": { - "default": {"transitions": [{"riding": "query.is_riding"}]}, - "riding": { - "animations": ["riding.arms", "riding.legs"], - "transitions": [{"default": "!query.is_riding"}] - } - } - }, - "holding": { - "initial_state": "default", - "states": {"default": {"animations": ["holding"]}} - }, - "brandish_spear": { - "initial_state": "default", - "states": { - "brandish_spear": { - "animations": ["brandish_spear"], - "transitions": [{"default": "!variable.is_brandishing_spear"}] - }, - "default": { - "transitions": [{"brandish_spear": "variable.is_brandishing_spear"}] - } - } - }, - "charging": { - "initial_state": "default", - "states": { - "charging": { - "animations": ["charging"], - "transitions": [{"default": "!query.is_charging"}] - }, - "default": {"transitions": [{"charging": "query.is_charging"}]} - } - }, - "attack": { - "initial_state": "default", - "states": { - "attacking": { - "animations": ["attack.rotations"], - "transitions": [{"default": "variable.attack_time < 0.0"}] - }, - "default": { - "transitions": [{"attacking": "variable.attack_time >= 0.0"}] - } - } - }, - "sneaking": { - "initial_state": "default", - "states": { - "default": {"transitions": [{"sneaking": "query.is_sneaking"}]}, - "sneaking": { - "animations": ["sneaking"], - "transitions": [{"default": "!query.is_sneaking"}] - } - } - }, - "bob": { - "initial_state": "default", - "states": {"default": {"animations": ["bob"]}} - }, - "damage_nearby_mobs": { - "initial_state": "default", - "states": { - "damage_nearby_mobs": { - "animations": ["damage_nearby_mobs"], - "transitions": [{"default": "!variable.damage_nearby_mobs"}] - }, - "default": { - "transitions": [ - {"damage_nearby_mobs": "variable.damage_nearby_mobs"} - ] - } - } - }, - "bow_and_arrow": { - "initial_state": "default", - "states": { - "bow_and_arrow": { - "animations": ["bow_and_arrow"], - "transitions": [{"default": "!query.has_target"}] - }, - "default": {"transitions": [{"bow_and_arrow": "query.has_target"}]} - } - }, - "use_item_progress": { - "initial_state": "default", - "states": { - "default": { - "transitions": [ - { - "use_item_progress": "( variable.use_item_interval_progress > 0.0 ) || ( variable.use_item_startup_progress > 0.0 )" - } - ] - }, - "use_item_progress": { - "animations": ["use_item_progress"], - "transitions": [ - { - "default": "( variable.use_item_interval_progress <= 0.0 ) && ( variable.use_item_startup_progress <= 0.0 )" - } - ] - } - } - }, - "zombie_attack_bare_hand": { - "initial_state": "default", - "states": { - "default": { - "transitions": [{"is_bare_hand": "variable.is_holding_left != 1.0"}] - }, - "is_bare_hand": { - "animations": ["zombie_attack_bare_hand"], - "transitions": [{"default": "variable.is_holding_left == 1.0"}] - } - } - }, - "swimming": { - "initial_state": "default", - "states": { - "default": { - "transitions": [{"is_swimming": "variable.swim_amount > 0.0"}] - }, - "is_swimming": { - "animations": ["swimming"], - "transitions": [{"default": "variable.swim_amount <= 0.0"}] - } - } - } - }, - "render_controllers": ["controller.render.husk"], - "enable_attachables": true, - "spawn_egg": {"texture": "spawn_egg", "texture_index": 28} - }, - "iron_golem": { - "identifier": "minecraft:iron_golem", - "materials": {"default": "iron_golem"}, - "textures": {"default": "textures/entity/iron_golem/iron_golem"}, - "geometry": { - "default": { - "visible_bounds_width": 3, - "visible_bounds_height": 3, - "visible_bounds_offset": [0, 1.5, 0], - "texturewidth": 128, - "textureheight": 128, - "bones": [ - { - "name": "body", - "pivot": [0, 31, 0], - "cubes": [ - {"origin": [-9, 21, -6], "size": [18, 12, 11], "uv": [0, 40]}, - { - "origin": [-4.5, 16, -3], - "size": [9, 5, 6], - "uv": [0, 70], - "inflate": 0.5 - } - ] - }, - { - "name": "head", - "parent": "body", - "pivot": [0, 31, -2], - "locators": {"lead": [0, 31, -2]}, - "cubes": [ - {"origin": [-4, 33, -7.5], "size": [8, 10, 8], "uv": [0, 0]}, - {"origin": [-1, 32, -9.5], "size": [2, 4, 2], "uv": [24, 0]} - ] - }, - { - "name": "arm0", - "parent": "body", - "pivot": [0, 31, 0], - "cubes": [ - {"origin": [-13, 3.5, -3], "size": [4, 30, 6], "uv": [60, 21]} - ] - }, - { - "name": "arm1", - "parent": "body", - "pivot": [0, 31, 0], - "cubes": [ - {"origin": [9, 3.5, -3], "size": [4, 30, 6], "uv": [60, 58]} - ] - }, - { - "name": "leg0", - "parent": "body", - "pivot": [-4, 13, 0], - "cubes": [ - {"origin": [-7.5, 0, -3], "size": [6, 16, 5], "uv": [37, 0]} - ] - }, - { - "name": "leg1", - "parent": "body", - "mirror": true, - "pivot": [5, 13, 0], - "cubes": [ - {"origin": [1.5, 0, -3], "size": [6, 16, 5], "uv": [60, 0]} - ] - } - ] - } - }, - "render_controllers": ["controller.render.iron_golem"] - }, - "item_frame": { - "identifier": "minecraft:item_frame", - "materials": {"default": "item_frame"}, - "textures": { - "background": "block:item_frame", - "frame": "block:oak_planks" - }, - "geometry": { - "background": { - "bones": [ - { - "name": "base" - }, - { - "name": "background", - "parent": "base", - "rotation": [0, 180, 0], - "pivot": [0, 0, 0], - "cubes": [ - {"origin": [-5, -5, -8], "size": [10, 10, 0.5], "uv": [3, 3]} - ] - } - ], - "texturewidth": 16, - "textureheight": 16 - }, - "frame": { - "bones": [ - { - "name": "frame", - "parent": "base", - "rotation": [0, 180, 0], - "pivot": [0, 0, 0], - "cubes": [ - {"origin": [-6, -6, -8], "size": [12, 1, 1], "uv": [2, 2]}, - {"origin": [-6, 5, -8], "size": [12, 1, 1], "uv": [2, 13]}, - {"origin": [-6, -5, -8], "size": [1, 10, 1], "uv": [2, 3]}, - {"origin": [5, -5, -8], "size": [1, 10, 1], "uv": [13, 3]} - ] - } - ], - "texturewidth": 16, - "textureheight": 16 - } - }, - "render_controllers": ["controller.render.item_frame"] - }, - "leash_knot": { - "identifier": "minecraft:leash_knot", - "materials": {"default": "leash_knot"}, - "textures": {"default": "textures/entity/lead_knot"}, - "geometry": { - "default": { - "bones": [ - { - "name": "knot", - "rotation": [0, 180, 0], - "cubes": [{"origin": [5, 6, 5], "size": [6, 8, 6], "uv": [0, 0]}] - } - ], - "texturewidth": 32, - "textureheight": 32 - } - }, - "render_controllers": ["controller.render.leash_knot"] - }, - "llama_spit": { - "identifier": "minecraft:llama_spit", - "materials": {"default": "llama_spit"}, - "textures": {"default": "textures/entity/llama/spit"}, - "geometry": { - "default": { - "visible_bounds_width": 1, - "visible_bounds_height": 1, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 64, - "bones": [ - { - "name": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 22, 0], "size": [2, 2, 2], "uv": [0, 0]}, - {"origin": [0, 26, 0], "size": [2, 2, 2], "uv": [0, 0]}, - {"origin": [0, 22, -4], "size": [2, 2, 2], "uv": [0, 0]}, - {"origin": [0, 22, 0], "size": [2, 2, 2], "uv": [0, 0]}, - {"origin": [2, 22, 0], "size": [2, 2, 2], "uv": [0, 0]}, - {"origin": [0, 20, 0], "size": [2, 2, 2], "uv": [0, 0]}, - {"origin": [0, 22, 2], "size": [2, 2, 2], "uv": [0, 0]} - ] - } - ] - } - }, - "render_controllers": ["controller.render.llama_spit"] - }, - "magma_cube": { - "identifier": "minecraft:magma_cube", - "materials": {"default": "magma_cube"}, - "textures": {"default": "textures/entity/slime/magmacube"}, - "geometry": { - "default": { - "visible_bounds_width": 2.5, - "visible_bounds_height": 5, - "visible_bounds_offset": [0, 2.5, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "bodyCube_0", - "parent": "insideCube", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-4, 7, -4], "size": [8, 1, 8], "uv": [0, 0]}] - }, - { - "name": "bodyCube_1", - "parent": "insideCube", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-4, 6, -4], "size": [8, 1, 8], "uv": [0, 1]}] - }, - { - "name": "bodyCube_2", - "parent": "insideCube", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 5, -4], "size": [8, 1, 8], "uv": [24, 10]} - ] - }, - { - "name": "bodyCube_3", - "parent": "insideCube", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 4, -4], "size": [8, 1, 8], "uv": [24, 19]} - ] - }, - { - "name": "bodyCube_4", - "parent": "insideCube", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-4, 3, -4], "size": [8, 1, 8], "uv": [0, 4]}] - }, - { - "name": "bodyCube_5", - "parent": "insideCube", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-4, 2, -4], "size": [8, 1, 8], "uv": [0, 5]}] - }, - { - "name": "bodyCube_6", - "parent": "insideCube", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-4, 1, -4], "size": [8, 1, 8], "uv": [0, 6]}] - }, - { - "name": "bodyCube_7", - "parent": "insideCube", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-4, 0, -4], "size": [8, 1, 8], "uv": [0, 7]}] - }, - { - "name": "insideCube", - "pivot": [0, 0, 0], - "cubes": [{"origin": [-2, 2, -2], "size": [4, 4, 4], "uv": [0, 16]}] - } - ] - } - }, - "render_controllers": ["controller.render.magma_cube"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 20} - }, - "mooshroom": { - "identifier": "minecraft:mooshroom", - "min_engine_version": "1.8.0", - "materials": {"default": "mooshroom"}, - "textures": { - "default": "textures/entity/cow/red_mooshroom", - "brown": "textures/entity/cow/brown_mooshroom" - }, - "geometry": { - "default": { - "visible_bounds_width": 2, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 1, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "body", - "pivot": [0, 19, 2], - "bind_pose_rotation": [90, 0, 0], - "cubes": [ - {"origin": [-6, 11, -5], "size": [12, 18, 10], "uv": [18, 4]}, - {"origin": [-2, 11, -6], "size": [4, 6, 1], "uv": [52, 0]} - ] - }, - { - "name": "head", - "pivot": [0, 20, -8], - "locators": {"lead": [0, 20, -8]}, - "cubes": [ - {"origin": [-4, 16, -14], "size": [8, 8, 6], "uv": [0, 0]}, - {"origin": [-5, 22, -12], "size": [1, 3, 1], "uv": [22, 0]}, - {"origin": [4, 22, -12], "size": [1, 3, 1], "uv": [22, 0]} - ] - }, - { - "name": "leg0", - "parent": "body", - "pivot": [-4, 12, 7], - "cubes": [{"origin": [-6, 0, 5], "size": [4, 12, 4], "uv": [0, 16]}] - }, - { - "name": "leg1", - "parent": "body", - "mirror": true, - "pivot": [4, 12, 7], - "cubes": [{"origin": [2, 0, 5], "size": [4, 12, 4], "uv": [0, 16]}] - }, - { - "name": "leg2", - "parent": "body", - "pivot": [-4, 12, -6], - "cubes": [ - {"origin": [-6, 0, -7], "size": [4, 12, 4], "uv": [0, 16]} - ] - }, - { - "name": "leg3", - "parent": "body", - "mirror": true, - "pivot": [4, 12, -6], - "cubes": [{"origin": [2, 0, -7], "size": [4, 12, 4], "uv": [0, 16]}] - } - ] - } - }, - "render_controllers": ["controller.render.mooshroom"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 5} - }, - "panda": { - "identifier": "minecraft:panda", - "materials": {"default": "panda"}, - "textures": { - "default": "textures/entity/panda/panda", - "lazy": "textures/entity/panda/lazy_panda", - "worried": "textures/entity/panda/worried_panda", - "playful": "textures/entity/panda/playful_panda", - "brown": "textures/entity/panda/brown_panda", - "weak": "textures/entity/panda/weak_panda", - "aggressive": "textures/entity/panda/aggressive_panda" - }, - "geometry": { - "default": { - "texturewidth": 64, - "textureheight": 64, - "bones": [ - { - "name": "head", - "parent": "body", - "pivot": [0, 12.5, -17], - "locators": {"lead": [0, 14, -16]}, - "cubes": [ - {"origin": [-6.5, 7.5, -21], "size": [13, 10, 9], "uv": [0, 6]}, - {"origin": [-3.5, 7.5, -23], "size": [7, 5, 2], "uv": [45, 16]}, - {"origin": [-8.5, 16.5, -18], "size": [5, 4, 1], "uv": [52, 25]}, - {"origin": [3.5, 16.5, -18], "size": [5, 4, 1], "uv": [52, 25]} - ] - }, - { - "name": "body", - "pivot": [0, 14, 0], - "bind_pose_rotation": [90, 0, 0], - "cubes": [ - {"origin": [-9.5, 1, -6.5], "size": [19, 26, 13], "uv": [0, 25]} - ] - }, - { - "name": "leg0", - "parent": "body", - "pivot": [-5.5, 9, 9], - "cubes": [ - {"origin": [-8.5, 0, 6], "size": [6, 9, 6], "uv": [40, 0]} - ] - }, - { - "name": "leg1", - "parent": "body", - "pivot": [5.5, 9, 9], - "cubes": [{"origin": [2.5, 0, 6], "size": [6, 9, 6], "uv": [40, 0]}] - }, - { - "name": "leg2", - "parent": "body", - "pivot": [-5.5, 9, -9], - "cubes": [ - {"origin": [-8.5, 0, -12], "size": [6, 9, 6], "uv": [40, 0]} - ] - }, - { - "name": "leg3", - "parent": "body", - "pivot": [5.5, 9, -9], - "cubes": [ - {"origin": [2.5, 0, -12], "size": [6, 9, 6], "uv": [40, 0]} - ] - } - ] - } - }, - "render_controllers": ["controller.render.panda"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 54} - }, - "phantom": { - "identifier": "minecraft:phantom", - "materials": {"default": "phantom", "invisible": "phantom_invisible"}, - "textures": {"default": "textures/entity/phantom"}, - "geometry": { - "default": { - "texturewidth": 64, - "textureheight": 64, - "bones": [ - { - "name": "body", - "pivot": [0, 24, 0], - "bind_pose_rotation": [0, 0, 0], - "cubes": [{"origin": [-3, 23, -8], "size": [5, 3, 9], "uv": [0, 8]}] - }, - { - "name": "wing0", - "pivot": [2, 26, -8], - "bind_pose_rotation": [0, 0, 5.7], - "cubes": [ - {"origin": [2, 24, -8], "size": [6, 2, 9], "uv": [23, 12]} - ], - "parent": "body" - }, - { - "name": "wingtip0", - "pivot": [8, 26, -8], - "bind_pose_rotation": [0, 0, 5.7], - "locators": {"left_wing": [21, 26, 0]}, - "cubes": [ - {"origin": [8, 25, -8], "size": [13, 1, 9], "uv": [16, 24]} - ], - "parent": "wing0" - }, - { - "name": "wing1", - "pivot": [-3, 26, -8], - "bind_pose_rotation": [0, 0, -5.7], - "mirror": true, - "cubes": [ - {"origin": [-9, 24, -8], "size": [6, 2, 9], "uv": [23, 12]} - ], - "parent": "body" - }, - { - "name": "wingtip1", - "pivot": [-9, 24, -8], - "bind_pose_rotation": [0, 0, -5.7], - "locators": {"right_wing": [-22, 24, 0]}, - "mirror": true, - "cubes": [ - {"origin": [-22, 25, -8], "size": [13, 1, 9], "uv": [16, 24]} - ], - "parent": "wing1" - }, - { - "name": "head", - "pivot": [0, 23, -7], - "bind_pose_rotation": [11.5, 0, 0], - "cubes": [ - {"origin": [-4, 22, -12], "size": [7, 3, 5], "uv": [0, 0]} - ], - "parent": "body" - }, - { - "name": "tail", - "pivot": [0, 26, 1], - "bind_pose_rotation": [0, 0, 0], - "cubes": [ - {"origin": [-2, 24, 1], "size": [3, 2, 6], "uv": [3, 20]} - ], - "parent": "body" - }, - { - "name": "tailtip", - "pivot": [0, 25.5, 7], - "bind_pose_rotation": [0, 0, 0], - "cubes": [ - {"origin": [-1, 24.5, 7], "size": [1, 1, 6], "uv": [4, 29]} - ], - "parent": "tail" - } - ] - } - }, - "particle_effects": {"wing_dust": "minecraft:phantom_trail_particle"}, - "sound_effects": {"flap": "mob.phantom.flap"}, - "render_controllers": ["controller.render.phantom"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 51} - }, - "pig": { - "identifier": "minecraft:pig", - "min_engine_version": "1.8.0", - "materials": {"default": "pig"}, - "textures": { - "default": "textures/entity/pig/pig", - "saddled": "textures/entity/pig/pig_saddle" - }, - "geometry": { - "default": { - "visible_bounds_width": 2, - "visible_bounds_height": 1.5, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "body", - "pivot": [0, 13, 2], - "bind_pose_rotation": [90, 0, 0], - "cubes": [ - {"origin": [-5, 7, -5], "size": [10, 16, 8], "uv": [28, 8]} - ] - }, - { - "name": "head", - "parent": "body", - "pivot": [0, 12, -6], - "locators": {"lead": [0, 14, -6]}, - "cubes": [ - {"origin": [-4, 8, -14], "size": [8, 8, 8], "uv": [0, 0]}, - {"origin": [-2, 9, -15], "size": [4, 3, 1], "uv": [16, 16]} - ] - }, - { - "name": "leg0", - "parent": "body", - "pivot": [-3, 6, 7], - "cubes": [{"origin": [-5, 0, 5], "size": [4, 6, 4], "uv": [0, 16]}] - }, - { - "name": "leg1", - "parent": "body", - "mirror": true, - "pivot": [3, 6, 7], - "cubes": [{"origin": [1, 0, 5], "size": [4, 6, 4], "uv": [0, 16]}] - }, - { - "name": "leg2", - "parent": "body", - "pivot": [-3, 6, -5], - "cubes": [{"origin": [-5, 0, -7], "size": [4, 6, 4], "uv": [0, 16]}] - }, - { - "name": "leg3", - "parent": "body", - "mirror": true, - "pivot": [3, 6, -5], - "cubes": [{"origin": [1, 0, -7], "size": [4, 6, 4], "uv": [0, 16]}] - } - ] - } - }, - "render_controllers": ["controller.render.pig"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 2} - }, - "piglin_brute": { - "identifier": "minecraft:piglin_brute", - "materials": {"default": "piglin_brute"}, - "textures": {"default": "textures/entity/piglin/piglin_brute"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}, - { - "origin": [-4, 12, -2], - "size": [8, 12, 4], - "uv": [16, 32], - "inflate": 0.25 - } - ] - }, - { - "name": "head", - "parent": "body", - "pivot": [0, 24, 0], - "cubes": [ - { - "origin": [-5, 24, -4], - "size": [10, 8, 8], - "uv": [0, 0], - "inflate": -0.02 - }, - {"origin": [-2, 24, -5], "size": [4, 4, 1], "uv": [31, 1]}, - {"origin": [2, 24, -5], "size": [1, 2, 1], "uv": [2, 4]}, - {"origin": [-3, 24, -5], "size": [1, 2, 1], "uv": [2, 0]} - ], - "inflate": -0.02 - }, - { - "name": "leftear", - "parent": "head", - "pivot": [5, 30, 0], - "rotation": [0, 0, -30], - "cubes": [{"origin": [4, 25, -2], "size": [1, 5, 4], "uv": [51, 6]}] - }, - { - "name": "rightear", - "parent": "head", - "pivot": [-5, 30, 0], - "rotation": [0, 0, 30], - "cubes": [ - {"origin": [-5, 25, -2], "size": [1, 5, 4], "uv": [39, 6]} - ] - }, - {"name": "hat", "parent": "head", "pivot": [0, 24, 0]}, - { - "name": "rightarm", - "parent": "body", - "pivot": [-5, 22, 0], - "cubes": [ - {"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}, - { - "origin": [-8, 12, -2], - "size": [4, 12, 4], - "uv": [40, 32], - "inflate": 0.25 - } - ] - }, - {"name": "rightItem", "parent": "rightarm", "pivot": [-1, -45, -5]}, - { - "name": "leftarm", - "parent": "body", - "pivot": [5, 22, 0], - "cubes": [ - {"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [32, 48]}, - { - "origin": [4, 12, -2], - "size": [4, 12, 4], - "uv": [48, 48], - "inflate": 0.25 - } - ] - }, - {"name": "leftItem", "parent": "leftArm", "pivot": [1, -45, -5]}, - { - "name": "rightleg", - "parent": "body", - "pivot": [-1.9, 12, 0], - "cubes": [ - {"origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}, - { - "origin": [-4, 0, -2], - "size": [4, 12, 4], - "uv": [0, 32], - "inflate": 0.25 - } - ] - }, - { - "name": "leftleg", - "parent": "body", - "pivot": [1.9, 12, 0], - "cubes": [ - {"origin": [0, 0, -2], "size": [4, 12, 4], "uv": [16, 48]}, - { - "origin": [0, 0, -2], - "size": [4, 12, 4], - "uv": [0, 48], - "inflate": 0.25 - } - ] - } - ], - "visible_bounds_width": 2, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 1, 0], - "texturewidth": 64, - "textureheight": 64 - } - }, - "spawn_egg": {"base_color": "#592A10", "overlay_color": "#F9F3A4"}, - "render_controllers": ["controller.render.piglin_brute"], - "enable_attachables": true - }, - "polar_bear": { - "identifier": "minecraft:polar_bear", - "materials": {"default": "polar_bear"}, - "textures": {"default": "textures/entity/bear/polarbear"}, - "geometry": { - "default": { - "visible_bounds_width": 3, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 128, - "textureheight": 64, - "bones": [ - { - "name": "head", - "parent": "body", - "pivot": [0, 14, -16], - "locators": {"lead": [0, 14, -16]}, - "mirror": true, - "cubes": [ - { - "mirror": false, - "origin": [-3.5, 10, -19], - "size": [7, 7, 7], - "uv": [0, 0] - }, - { - "mirror": false, - "origin": [-2.5, 10, -22], - "size": [5, 3, 3], - "uv": [0, 44] - }, - { - "mirror": false, - "origin": [-4.5, 16, -17], - "size": [2, 2, 1], - "uv": [26, 0] - }, - {"origin": [2.5, 16, -17], "size": [2, 2, 1], "uv": [26, 0]} - ] - }, - { - "name": "body", - "pivot": [-2, 15, 12], - "bind_pose_rotation": [90, 0, 0], - "cubes": [ - {"origin": [-7, 14, 5], "size": [14, 14, 11], "uv": [0, 19]}, - {"origin": [-6, 28, 5], "size": [12, 12, 10], "uv": [39, 0]} - ] - }, - { - "name": "leg0", - "parent": "body", - "pivot": [-4.5, 10, 6], - "cubes": [ - {"origin": [-6.5, 0, 4], "size": [4, 10, 8], "uv": [50, 22]} - ] - }, - { - "name": "leg1", - "parent": "body", - "pivot": [4.5, 10, 6], - "cubes": [ - {"origin": [2.5, 0, 4], "size": [4, 10, 8], "uv": [50, 22]} - ] - }, - { - "name": "leg2", - "parent": "body", - "pivot": [-3.5, 10, -8], - "cubes": [ - {"origin": [-5.5, 0, -10], "size": [4, 10, 6], "uv": [50, 40]} - ] - }, - { - "name": "leg3", - "parent": "body", - "pivot": [3.5, 10, -8], - "cubes": [ - {"origin": [1.5, 0, -10], "size": [4, 10, 6], "uv": [50, 40]} - ] - } - ] - } - }, - "render_controllers": ["controller.render.polarbear"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 37} - }, - "pufferfish": { - "identifier": "minecraft:pufferfish", - "min_engine_version": "1.8.0", - "materials": {"default": "pufferfish"}, - "textures": {"default": "textures/entity/fish/pufferfish"}, - "geometry": { - "default": { - "visible_bounds_width": 0.5, - "visible_bounds_height": 0.5, - "texturewidth": 32, - "textureheight": 32, - "bones": [ - { - "name": "body", - "cubes": [ - {"origin": [-1.5, 0, -1.5], "size": [3, 2, 3], "uv": [0, 27]}, - {"origin": [0.5, 2, -1.5], "size": [1, 1, 1], "uv": [24, 6]}, - {"origin": [-1.5, 2, -1.5], "size": [1, 1, 1], "uv": [28, 6]} - ], - "locators": {"lead": [0, 0, 0]} - }, - { - "name": "tailfin", - "parent": "body", - "cubes": [ - {"origin": [-1.5, 1, 1.5], "size": [3, 0, 3], "uv": [-3, 0]} - ] - }, - { - "name": "leftFin", - "parent": "body", - "pivot": [6.5, 5, 0.5], - "cubes": [ - { - "origin": [1.5, 0, -1.5], - "size": [1, 1, 2], - "uv": [25, 0], - "mirror": true - } - ] - }, - { - "name": "rightFin", - "parent": "body", - "pivot": [-6.5, 5, 0.5], - "cubes": [ - {"origin": [-2.5, 0, -1.5], "size": [1, 1, 2], "uv": [25, 0]} - ] - } - ] - }, - "mid": { - "visible_bounds_width": 0.5, - "visible_bounds_height": 0.5, - "texturewidth": 32, - "textureheight": 32, - "bones": [ - { - "name": "body", - "cubes": [ - {"origin": [-2.5, 1, -2.5], "size": [5, 5, 5], "uv": [12, 22]} - ] - }, - { - "name": "leftFin", - "parent": "body", - "pivot": [2.5, 5, 0.5], - "cubes": [ - {"origin": [2.5, 4, -1.5], "size": [2, 1, 2], "uv": [24, 3]} - ] - }, - { - "name": "rightFin", - "parent": "body", - "pivot": [-2.5, 5, 0.5], - "cubes": [ - {"origin": [-4.5, 4, -1.5], "size": [2, 1, 2], "uv": [24, 0]} - ] - }, - { - "name": "spines_top_front", - "parent": "body", - "bind_pose_rotation": [45, 0, 0], - "pivot": [0, 6, -2.5], - "cubes": [ - {"origin": [-2.5, 6, -2.5], "size": [5, 1, 0], "uv": [19, 17]} - ] - }, - { - "name": "spines_top_back", - "parent": "body", - "bind_pose_rotation": [-45, 0, 0], - "pivot": [0, 6, 2.5], - "cubes": [ - {"origin": [-2.5, 6, 2.5], "size": [5, 1, 0], "uv": [11, 17]} - ] - }, - { - "name": "spines_bottom_front", - "parent": "body", - "bind_pose_rotation": [-45, 0, 0], - "pivot": [0, 1, -2.5], - "cubes": [ - {"origin": [-2.5, 0, -2.5], "size": [5, 1, 0], "uv": [18, 20]} - ] - }, - { - "name": "spines_bottom_back", - "parent": "body", - "bind_pose_rotation": [45, 0, 0], - "pivot": [0, 1, 2.5], - "rotation": [45, 0, 0], - "cubes": [ - {"origin": [-2.5, 0, 2.5], "size": [5, 1, 0], "uv": [18, 20]} - ] - }, - { - "name": "spines_left_front", - "parent": "body", - "bind_pose_rotation": [0, 45, 0], - "pivot": [2.5, 0, -2.5], - "rotation": [0, 45, 0], - "cubes": [ - {"origin": [2.5, 1, -2.5], "size": [1, 5, 0], "uv": [1, 17]} - ] - }, - { - "name": "spines_left_back", - "parent": "body", - "bind_pose_rotation": [0, -45, 0], - "pivot": [2.5, 0, 2.5], - "rotation": [0, -45, 0], - "cubes": [ - {"origin": [2.5, 1, 2.5], "size": [1, 5, 0], "uv": [1, 17]} - ] - }, - { - "name": "spines_right_front", - "parent": "body", - "bind_pose_rotation": [0, -45, 0], - "pivot": [-2.5, 0, -2.5], - "rotation": [0, -45, 0], - "cubes": [ - {"origin": [-3.5, 1, -2.5], "size": [1, 5, 0], "uv": [5, 17]} - ] - }, - { - "name": "spines_right_back", - "parent": "body", - "bind_pose_rotation": [0, 45, 0], - "pivot": [-2.5, 0, 2.5], - "rotation": [0, 45, 0], - "cubes": [ - {"origin": [-3.5, 1, 2.5], "size": [1, 5, 0], "uv": [9, 17]} - ] - } - ] - }, - "large": { - "visible_bounds_width": 0.5, - "visible_bounds_height": 0.5, - "texturewidth": 32, - "textureheight": 32, - "bones": [ - { - "name": "body", - "cubes": [{"origin": [-4, 0, -4], "size": [8, 8, 8], "uv": [0, 0]}] - }, - { - "name": "leftFin", - "parent": "body", - "pivot": [4, 7, 1], - "cubes": [ - {"origin": [4, 6, -2.9904], "size": [2, 1, 2], "uv": [24, 3]} - ] - }, - { - "name": "rightFin", - "parent": "body", - "pivot": [-4, 7, 1], - "cubes": [ - {"origin": [-5.9968, 6, -2.992], "size": [2, 1, 2], "uv": [24, 0]} - ] - }, - { - "name": "spines_top_front", - "parent": "body", - "pivot": [-4, 8, -4], - "bind_pose_rotation": [45, 0, 0], - "cubes": [ - {"origin": [-4, 8, -4], "size": [8, 1, 1], "uv": [14, 16]} - ] - }, - { - "name": "spines_top_mid", - "parent": "body", - "pivot": [0, 8, 0], - "cubes": [{"origin": [-4, 8, 0], "size": [8, 1, 1], "uv": [14, 16]}] - }, - { - "name": "spines_top_back", - "parent": "body", - "pivot": [0, 8, 4], - "bind_pose_rotation": [-45, 0, 0], - "cubes": [{"origin": [-4, 8, 4], "size": [8, 1, 1], "uv": [14, 16]}] - }, - { - "name": "spines_bottom_front", - "parent": "body", - "pivot": [0, 0, -4], - "bind_pose_rotation": [-45, 0, 0], - "cubes": [ - {"origin": [-4, -1, -4], "size": [8, 1, 1], "uv": [14, 19]} - ] - }, - { - "name": "spines_bottom_mid", - "parent": "body", - "pivot": [0, -1, 0], - "cubes": [ - {"origin": [-4, -1, 0], "size": [8, 1, 1], "uv": [14, 19]} - ] - }, - { - "name": "spines_bottom_back", - "parent": "body", - "pivot": [0, 0, 4], - "bind_pose_rotation": [45, 0, 0], - "cubes": [ - {"origin": [-4, -1, 4], "size": [8, 1, 1], "uv": [14, 19]} - ] - }, - { - "name": "spines_left_front", - "parent": "body", - "pivot": [4, 0, -4], - "bind_pose_rotation": [0, 45, 0], - "cubes": [{"origin": [4, 0, -4], "size": [1, 8, 1], "uv": [0, 16]}] - }, - { - "name": "spines_left_mid", - "parent": "body", - "pivot": [4, 0, 0], - "cubes": [ - { - "origin": [4, 0, 0], - "size": [1, 8, 1], - "uv": [4, 16], - "mirror": true - } - ] - }, - { - "name": "spines_left_back", - "parent": "body", - "pivot": [4, 0, 4], - "bind_pose_rotation": [0, -45, 0], - "cubes": [ - { - "origin": [4, 0, 4], - "size": [1, 8, 1], - "uv": [8, 16], - "mirror": true - } - ] - }, - { - "name": "spines_right_front", - "parent": "body", - "pivot": [-4, 0, -4], - "bind_pose_rotation": [0, -45, 0], - "cubes": [{"origin": [-5, 0, -4], "size": [1, 8, 1], "uv": [4, 16]}] - }, - { - "name": "spines_right_mid", - "parent": "body", - "pivot": [-4, 0, 0], - "cubes": [{"origin": [-5, 0, 0], "size": [1, 8, 1], "uv": [8, 16]}] - }, - { - "name": "spines_right_back", - "parent": "body", - "pivot": [-4, 0, 4], - "bind_pose_rotation": [0, 45, 0], - "cubes": [{"origin": [-5, 0, 4], "size": [1, 8, 1], "uv": [8, 16]}] - } - ] - } - }, - "render_controllers": [ - {"controller.render.pufferfish.small": "query.variant == 0"}, - {"controller.render.pufferfish.medium": "query.variant == 1"}, - {"controller.render.pufferfish.large": "query.variant == 2"} - ], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 46} - }, - "rabbit": { - "identifier": "minecraft:rabbit", - "min_engine_version": "1.8.0", - "materials": {"default": "rabbit"}, - "textures": { - "brown": "textures/entity/rabbit/brown", - "white": "textures/entity/rabbit/white", - "black": "textures/entity/rabbit/black", - "white_splotched": "textures/entity/rabbit/white_splotched", - "gold": "textures/entity/rabbit/gold", - "salt": "textures/entity/rabbit/salt", - "toast": "textures/entity/rabbit/toast" - }, - "geometry": { - "default": { - "visible_bounds_width": 1, - "visible_bounds_height": 1, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "rearFootLeft", - "pivot": [3, 6.5, 3.7], - "mirror": true, - "parent": "body", - "cubes": [{"origin": [2, 0, 0], "size": [2, 1, 7], "uv": [8, 24]}] - }, - { - "name": "rearFootRight", - "pivot": [-3, 6.5, 3.7], - "mirror": true, - "parent": "body", - "cubes": [{"origin": [-4, 0, 0], "size": [2, 1, 7], "uv": [26, 24]}] - }, - { - "name": "haunchLeft", - "pivot": [3, 6.5, 3.7], - "bind_pose_rotation": [-20, 0, 0], - "mirror": true, - "parent": "body", - "cubes": [ - {"origin": [2, 2.5, 3.7], "size": [2, 4, 5], "uv": [16, 15]} - ] - }, - { - "name": "haunchRight", - "pivot": [-3, 6.5, 3.7], - "bind_pose_rotation": [-20, 0, 0], - "mirror": true, - "parent": "body", - "cubes": [ - {"origin": [-4, 2.5, 3.7], "size": [2, 4, 5], "uv": [30, 15]} - ] - }, - { - "name": "body", - "pivot": [0, 5, 8], - "bind_pose_rotation": [-20, 0, 0], - "mirror": true, - "cubes": [{"origin": [-3, 2, -2], "size": [6, 5, 10], "uv": [0, 0]}] - }, - { - "name": "frontLegLeft", - "pivot": [3, 7, -1], - "bind_pose_rotation": [-10, 0, 0], - "mirror": true, - "parent": "body", - "cubes": [{"origin": [2, 0, -2], "size": [2, 7, 2], "uv": [8, 15]}] - }, - { - "name": "frontLegRight", - "pivot": [-3, 7, -1], - "bind_pose_rotation": [-10, 0, 0], - "mirror": true, - "parent": "body", - "cubes": [{"origin": [-4, 0, -2], "size": [2, 7, 2], "uv": [0, 15]}] - }, - { - "name": "head", - "pivot": [0, 8, -1], - "locators": {"lead": [0, 8, -1]}, - "mirror": true, - "parent": "body", - "cubes": [ - {"origin": [-2.5, 8, -6], "size": [5, 4, 5], "uv": [32, 0]} - ] - }, - { - "name": "earRight", - "pivot": [0, 8, -1], - "bind_pose_rotation": [0, -15, 0], - "mirror": true, - "parent": "body", - "cubes": [ - {"origin": [-2.5, 12, -2], "size": [2, 5, 1], "uv": [58, 0]} - ] - }, - { - "name": "earLeft", - "pivot": [0, 8, -1], - "bind_pose_rotation": [0, 15, 0], - "mirror": true, - "parent": "body", - "cubes": [ - {"origin": [0.5, 12, -2], "size": [2, 5, 1], "uv": [52, 0]} - ] - }, - { - "name": "tail", - "pivot": [0, 4, 7], - "bind_pose_rotation": [-20, 0, 0], - "mirror": true, - "parent": "body", - "cubes": [ - {"origin": [-1.5, 2.5, 7], "size": [3, 3, 2], "uv": [52, 6]} - ] - }, - { - "name": "nose", - "pivot": [0, 8, -1], - "mirror": true, - "parent": "body", - "cubes": [ - {"origin": [-0.5, 9.5, -6.5], "size": [1, 1, 1], "uv": [32, 9]} - ] - } - ] - } - }, - "render_controllers": ["controller.render.rabbit"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 24} - }, - "ravager": { - "identifier": "minecraft:ravager", - "textures": {"default": "textures/entity/illager/ravager"}, - "materials": {"default": "ravager"}, - "geometry": { - "default": { - "bones": [ - { - "pivot": [0, 19, 2], - "rotation": [90, 0, 0], - "cubes": [ - {"origin": [-7, 10, -2], "size": [14, 16, 20], "uv": [0, 55]}, - {"origin": [-6, -3, -2], "size": [12, 13, 18], "uv": [0, 91]} - ], - "name": "body" - }, - { - "pivot": [0, 15, -10], - "cubes": [ - {"origin": [-8, 13, -24], "size": [16, 3, 16], "uv": [0, 36]} - ], - "name": "mouth", - "parent": "head" - }, - { - "pivot": [0, 20, -20], - "cubes": [ - {"origin": [-5, 21, -10], "size": [10, 10, 18], "uv": [68, 73]} - ], - "name": "neck" - }, - { - "locators": {"stun": [0, 32, -15]}, - "pivot": [0, 28, -10], - "cubes": [ - {"origin": [-8, 14, -24], "size": [16, 20, 16], "uv": [0, 0]}, - {"origin": [-2, 12, -28], "size": [4, 8, 4], "uv": [0, 0]} - ], - "name": "head", - "parent": "neck" - }, - { - "pivot": [-12, 30, 22], - "cubes": [ - {"origin": [-12, 0, 17], "size": [8, 37, 8], "uv": [96, 0]} - ], - "name": "leg0" - }, - { - "pivot": [4, 30, 22], - "cubes": [ - {"origin": [4, 0, 17], "size": [8, 37, 8], "uv": [96, 0]} - ], - "name": "leg1" - }, - { - "pivot": [-4, 26, -4], - "cubes": [ - {"origin": [-12, 0, -8], "size": [8, 37, 8], "uv": [64, 0]} - ], - "name": "leg2" - }, - { - "pivot": [-4, 26, -4], - "cubes": [ - {"origin": [4, 0, -8], "size": [8, 37, 8], "uv": [64, 0]} - ], - "name": "leg3" - }, - { - "pivot": [-5, 27, -19], - "rotation": [60, 0, 0], - "cubes": [ - {"origin": [-10, 27, -20], "size": [2, 14, 4], "uv": [74, 55]}, - {"origin": [8, 27, -20], "size": [2, 14, 4], "uv": [74, 55]} - ], - "name": "horns", - "parent": "head" - } - ], - "texturewidth": 128, - "textureheight": 128, - "visible_bounds_width": 4, - "visible_bounds_height": 3.5, - "visible_bounds_offset": [0, 1.25, 0] - } - }, - "render_controllers": ["controller.render.ravager"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 57}, - "particle_effects": {"stun_particles": "minecraft:stunned_emitter"} - }, - "salmon": { - "identifier": "minecraft:salmon", - "materials": {"default": "salmon"}, - "textures": {"default": "textures/entity/fish/salmon"}, - "geometry": { - "default": { - "visible_bounds_width": 0.5, - "visible_bounds_height": 0.5, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 32, - "textureheight": 32, - "bones": [ - { - "name": "body_front", - "pivot": [0, 0, -4], - "cubes": [ - {"origin": [-1.5, 3.5, -4], "size": [3, 5, 8], "uv": [0, 0]} - ] - }, - { - "name": "body_back", - "parent": "body_front", - "pivot": [0, 0, 4], - "cubes": [ - {"origin": [-1.5, 3.5, 4], "size": [3, 5, 8], "uv": [0, 13]} - ] - }, - { - "name": "dorsal_front", - "parent": "body_front", - "pivot": [0, 5, 2], - "cubes": [{"origin": [0, 8.5, 2], "size": [0, 2, 2], "uv": [4, 2]}] - }, - { - "name": "dorsal_back", - "parent": "body_back", - "pivot": [0, 5, 4], - "cubes": [{"origin": [0, 8.5, 4], "size": [0, 2, 3], "uv": [2, 3]}] - }, - { - "name": "tailfin", - "parent": "body_back", - "pivot": [0, 0, 12], - "cubes": [ - {"origin": [0, 3.5, 12], "size": [0, 5, 6], "uv": [20, 10]} - ] - }, - { - "name": "head", - "parent": "body_front", - "pivot": [0, 3, -4], - "locators": {"lead": [0, 3, -4]}, - "cubes": [ - {"origin": [-1, 4.5, -7], "size": [2, 4, 3], "uv": [22, 0]} - ] - }, - { - "name": "leftFin", - "parent": "body_front", - "pivot": [1.5, 1, -4], - "rotation": [0, 0, 35], - "cubes": [ - { - "origin": [-0.50752, 3.86703, -4], - "size": [2, 0, 2], - "uv": [2, 0] - } - ] - }, - { - "name": "rightFin", - "parent": "body_front", - "pivot": [-1.5, 1, -4], - "rotation": [0, 0, -35], - "cubes": [ - { - "origin": [-1.49258, 3.86703, -4], - "size": [2, 0, 2], - "uv": [-2, 0] - } - ] - } - ] - } - }, - "render_controllers": ["controller.render.salmon"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 47} - }, - "shulker_bullet": { - "identifier": "minecraft:shulker_bullet", - "materials": {"default": "shulker_bullet"}, - "textures": {"default": "textures/entity/shulker/spark"}, - "geometry": { - "default": { - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "body", - "pivot": [0, 0, 0], - "cubes": [ - {"origin": [-4, -4, -1], "size": [8, 8, 2], "uv": [0, 0]}, - {"origin": [-1, -4, -4], "size": [2, 8, 8], "uv": [0, 10]}, - {"origin": [-4, -1, -4], "size": [8, 2, 8], "uv": [20, 0]} - ] - } - ] - } - }, - "render_controllers": ["controller.render.shulker_bullet"] - }, - "silverfish": { - "identifier": "minecraft:silverfish", - "materials": {"default": "silverfish", "body_layer": "silverfish_layers"}, - "textures": {"default": "textures/entity/silverfish"}, - "geometry": { - "default": { - "visible_bounds_width": 1.5, - "visible_bounds_height": 1, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "bodyPart_0", - "parent": "bodyPart_2", - "pivot": [0, 2, -3.5], - "cubes": [ - {"origin": [-1.5, 0, -4.5], "size": [3, 2, 2], "uv": [0, 0]} - ] - }, - { - "name": "bodyPart_1", - "parent": "bodyPart_2", - "pivot": [0, 3, -1.5], - "cubes": [ - {"origin": [-2, 0, -2.5], "size": [4, 3, 2], "uv": [0, 4]} - ] - }, - { - "name": "bodyPart_2", - "pivot": [0, 4, 1], - "cubes": [ - {"origin": [-3, 0, -0.5], "size": [6, 4, 3], "uv": [0, 9]} - ] - }, - { - "name": "bodyPart_3", - "parent": "bodyPart_2", - "pivot": [0, 3, 4], - "cubes": [ - {"origin": [-1.5, 0, 2.5], "size": [3, 3, 3], "uv": [0, 16]} - ] - }, - { - "name": "bodyPart_4", - "parent": "bodyPart_2", - "pivot": [0, 2, 7], - "cubes": [ - {"origin": [-1, 0, 5.5], "size": [2, 2, 3], "uv": [0, 22]} - ] - }, - { - "name": "bodyPart_5", - "parent": "bodyPart_2", - "pivot": [0, 1, 9.5], - "cubes": [ - {"origin": [-1, 0, 8.5], "size": [2, 1, 2], "uv": [11, 0]} - ] - }, - { - "name": "bodyPart_6", - "parent": "bodyPart_2", - "pivot": [0, 1, 11.5], - "cubes": [ - {"origin": [-0.5, 0, 10.5], "size": [1, 1, 2], "uv": [13, 4]} - ] - }, - { - "name": "bodyLayer_0", - "parent": "bodyPart_2", - "pivot": [0, 8, 1], - "cubes": [ - {"origin": [-5, 0, -0.5], "size": [10, 8, 3], "uv": [20, 0]} - ] - }, - { - "name": "bodyLayer_1", - "parent": "bodyPart_4", - "pivot": [0, 4, 7], - "cubes": [ - {"origin": [-3, 0, 5.5], "size": [6, 4, 3], "uv": [20, 11]} - ] - }, - { - "name": "bodyLayer_2", - "parent": "bodyPart_1", - "pivot": [0, 5, -1.5], - "cubes": [ - {"origin": [-3, 0, -3], "size": [6, 5, 2], "uv": [20, 18]} - ] - } - ] - } - }, - "render_controllers": ["controller.render.silverfish"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 8} - }, - "skeleton": { - "identifier": "minecraft:skeleton", - "min_engine_version": "1.8.0", - "materials": {"default": "skeleton"}, - "textures": {"default": "textures/entity/skeleton/skeleton"}, - "geometry": { - "default": { - "texturewidth": 64, - "textureheight": 32, - "visible_bounds_width": 2, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 1, 0], - "bones": [ - { - "name": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]} - ], - "parent": "waist" - }, - {"name": "waist", "pivot": [0, 12, 0]}, - { - "name": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]} - ], - "parent": "body" - }, - { - "name": "hat", - "pivot": [0, 24, 0], - "cubes": [ - { - "origin": [-4, 24, -4], - "size": [8, 8, 8], - "uv": [32, 0], - "inflate": 0.5 - } - ], - "neverRender": true, - "parent": "head" - }, - { - "name": "rightArm", - "pivot": [-5, 22, 0], - "cubes": [ - {"origin": [-6, 12, -1], "size": [2, 12, 2], "uv": [40, 16]} - ], - "parent": "body" - }, - { - "name": "rightItem", - "pivot": [-1, -45, -5], - "neverRender": true, - "parent": "rightArm" - }, - { - "name": "leftArm", - "pivot": [5, 22, 0], - "cubes": [ - {"origin": [4, 12, -1], "size": [2, 12, 2], "uv": [40, 16]} - ], - "mirror": true, - "parent": "body" - }, - { - "name": "leftItem", - "pivot": [1, -45, -5], - "neverRender": true, - "parent": "leftArm" - }, - { - "name": "rightLeg", - "pivot": [-2, 12, 0], - "cubes": [ - {"origin": [-3, 0, -1], "size": [2, 12, 2], "uv": [0, 16]} - ], - "parent": "body" - }, - { - "name": "leftLeg", - "pivot": [2, 12, 0], - "cubes": [ - {"origin": [1, 0, -1], "size": [2, 12, 2], "uv": [0, 16]} - ], - "mirror": true, - "parent": "body" - } - ] - } - }, - "spawn_egg": {"texture": "spawn_egg", "texture_index": 9}, - "render_controllers": ["controller.render.skeleton"], - "enable_attachables": true - }, - "skeleton_horse": { - "identifier": "minecraft:skeleton_horse", - "textures": { - "base_brown": "textures/entity/horse/horse_brown", - "base_white": "textures/entity/horse/horse_white", - "base_chestnut": "textures/entity/horse/horse_chestnut", - "base_creamy": "textures/entity/horse/horse_creamy", - "base_black": "textures/entity/horse/horse_black", - "base_gray": "textures/entity/horse/horse_gray", - "base_darkbrown": "textures/entity/horse/horse_darkbrown", - "markings_none": "textures/entity/horse/horse_markings_none", - "markings_white": "textures/entity/horse/horse_markings_white", - "markings_whitefield": "textures/entity/horse/horse_markings_whitefield", - "markings_whitedots": "textures/entity/horse/horse_markings_whitedots", - "markings_blackdots": "textures/entity/horse/horse_markings_blackdots", - "mule": "textures/entity/horse/mule", - "donkey": "textures/entity/horse/donkey", - "skeleton": "textures/entity/horse/horse_skeleton", - "zombie": "textures/entity/horse/horse_zombie", - "armor_none": "textures/entity/horse/armor/horse_armor_none", - "armor_leather": "textures/entity/horse/armor/horse_armor_leather", - "armor_iron": "textures/entity/horse/armor/horse_armor_iron", - "armor_gold": "textures/entity/horse/armor/horse_armor_gold", - "armor_diamond": "textures/entity/horse/armor/horse_armor_diamond" - }, - "geometry": { - "default": { - "visible_bounds_width": 2, - "visible_bounds_height": 3, - "visible_bounds_offset": [0, 1, 0], - "texturewidth": 128, - "textureheight": 128, - "bones": [ - { - "name": "Body", - "pivot": [0, 13, 9], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [-5, 11, -10], "size": [10, 10, 24], "uv": [0, 34]} - ] - }, - { - "name": "TailA", - "pivot": [0, 21, 14], - "rotation": [-65, 0, 0], - "cubes": [ - {"origin": [-1, 20, 14], "size": [2, 2, 3], "uv": [44, 0]} - ] - }, - { - "name": "TailB", - "pivot": [0, 21, 14], - "rotation": [-65, 0, 0], - "cubes": [ - {"origin": [-1.5, 19, 17], "size": [3, 4, 7], "uv": [38, 7]} - ] - }, - { - "name": "TailC", - "pivot": [0, 21, 14], - "rotation": [-80.34, 0, 0], - "cubes": [ - {"origin": [-1.5, 21.5, 23], "size": [3, 4, 7], "uv": [24, 3]} - ] - }, - { - "name": "Leg1A", - "pivot": [4, 15, 11], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [1.5, 8, 8.5], "size": [4, 9, 5], "uv": [78, 29]} - ] - }, - { - "name": "Leg1B", - "pivot": [4, 8, 11], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [2, 3, 9.5], "size": [3, 5, 3], "uv": [78, 43]} - ] - }, - { - "name": "Leg1C", - "pivot": [4, 8, 11], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [1.5, -0.1, 9], "size": [4, 3, 4], "uv": [78, 51]} - ] - }, - { - "name": "Leg2A", - "pivot": [-4, 15, 11], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [-5.5, 8, 8.5], "size": [4, 9, 5], "uv": [96, 29]} - ] - }, - { - "name": "Leg2B", - "pivot": [-4, 8, 11], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [-5, 3, 9.5], "size": [3, 5, 3], "uv": [96, 43]} - ] - }, - { - "name": "Leg2C", - "pivot": [-4, 8, 11], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [-5.5, -0.1, 9], "size": [4, 3, 4], "uv": [96, 51]} - ] - }, - { - "name": "Leg3A", - "pivot": [4, 15, -8], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [2.1, 8, -10.1], "size": [3, 8, 4], "uv": [44, 29]} - ] - }, - { - "name": "Leg3B", - "pivot": [4, 8, -8], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [2.1, 3, -9.6], "size": [3, 5, 3], "uv": [44, 41]} - ] - }, - { - "name": "Leg3C", - "pivot": [4, 8, -8], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [1.6, -0.1, -10.1], "size": [4, 3, 4], "uv": [44, 51]} - ] - }, - { - "name": "Leg4A", - "pivot": [-4, 15, -8], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [-5.1, 8, -10.1], "size": [3, 8, 4], "uv": [60, 29]} - ] - }, - { - "name": "Leg4B", - "pivot": [-4, 8, -8], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [-5.1, 3, -9.6], "size": [3, 5, 3], "uv": [60, 41]} - ] - }, - { - "name": "Leg4C", - "pivot": [-4, 8, -8], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [-5.6, -0.1, -10.1], "size": [4, 3, 4], "uv": [60, 51]} - ] - }, - { - "name": "Head", - "pivot": [0, 20, -10], - "rotation": [30, 0, 0], - "cubes": [ - {"origin": [-2.5, 25, -11.5], "size": [5, 5, 7], "uv": [0, 0]} - ] - }, - { - "name": "UMouth", - "pivot": [0, 20.05, -10], - "rotation": [30, 0, 0], - "cubes": [ - {"origin": [-2, 27.05, -17], "size": [4, 3, 6], "uv": [24, 18]} - ] - }, - { - "name": "LMouth", - "pivot": [0, 20, -10], - "rotation": [30, 0, 0], - "cubes": [ - {"origin": [-2, 25, -16.5], "size": [4, 2, 5], "uv": [24, 27]} - ] - }, - { - "name": "Ear1", - "pivot": [0, 20, -10], - "rotation": [30, 0, 0], - "cubes": [ - {"origin": [0.45, 29, -6], "size": [2, 3, 1], "uv": [0, 0]} - ] - }, - { - "name": "Ear2", - "pivot": [0, 20, -10], - "rotation": [30, 0, 0], - "cubes": [ - {"origin": [-2.45, 29, -6], "size": [2, 3, 1], "uv": [0, 0]} - ] - }, - { - "name": "MuleEarL", - "pivot": [0, 20, -10], - "rotation": [30, 0, 15], - "cubes": [ - {"origin": [-2, 29, -6], "size": [2, 7, 1], "uv": [0, 12]} - ] - }, - { - "name": "MuleEarR", - "pivot": [0, 20, -10], - "rotation": [30, 0, -15], - "cubes": [{"origin": [0, 29, -6], "size": [2, 7, 1], "uv": [0, 12]}] - }, - { - "name": "Neck", - "pivot": [0, 20, -10], - "rotation": [30, 0, 0], - "cubes": [ - {"origin": [-2.05, 15.8, -12], "size": [4, 14, 8], "uv": [0, 12]} - ] - }, - { - "name": "Bag1", - "pivot": [-7.5, 21, 10], - "rotation": [0, 90, 0], - "cubes": [ - {"origin": [-10.5, 13, 10], "size": [8, 8, 3], "uv": [0, 34]} - ] - }, - { - "name": "Bag2", - "pivot": [4.5, 21, 10], - "rotation": [0, 90, 0], - "cubes": [ - {"origin": [1.5, 13, 10], "size": [8, 8, 3], "uv": [0, 47]} - ] - }, - { - "name": "Saddle", - "pivot": [0, 22, 2], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [-5, 21, -1], "size": [10, 1, 8], "uv": [80, 0]} - ] - }, - { - "name": "SaddleB", - "pivot": [0, 22, 2], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [-1.5, 22, -1], "size": [3, 1, 2], "uv": [106, 9]} - ] - }, - { - "name": "SaddleC", - "pivot": [0, 22, 2], - "rotation": [0, 0, 0], - "cubes": [{"origin": [-4, 22, 5], "size": [8, 1, 2], "uv": [80, 9]}] - }, - { - "name": "SaddleL2", - "pivot": [5, 21, 2], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [4.5, 13, 1], "size": [1, 2, 2], "uv": [74, 0]} - ] - }, - { - "name": "SaddleL", - "pivot": [5, 21, 2], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [4.5, 15, 1.5], "size": [1, 6, 1], "uv": [70, 0]} - ] - }, - { - "name": "SaddleR2", - "pivot": [-5, 21, 2], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [-5.5, 13, 1], "size": [1, 2, 2], "uv": [74, 4]} - ] - }, - { - "name": "SaddleR", - "pivot": [-5, 21, 2], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [-5.5, 15, 1.5], "size": [1, 6, 1], "uv": [80, 0]} - ] - }, - { - "name": "SaddleMouthL", - "pivot": [0, 20, -10], - "rotation": [30, 0, 0], - "cubes": [ - {"origin": [1.5, 26, -14], "size": [1, 2, 2], "uv": [74, 13]} - ] - }, - { - "name": "SaddleMouthR", - "pivot": [0, 20, -10], - "rotation": [30, 0, 0], - "cubes": [ - {"origin": [-2.5, 26, -14], "size": [1, 2, 2], "uv": [74, 13]} - ] - }, - { - "name": "SaddleMouthLine", - "pivot": [0, 20, -10], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [2.6, 23, -16], "size": [0, 3, 16], "uv": [44, 10]} - ] - }, - { - "name": "SaddleMouthLineR", - "pivot": [0, 20, -10], - "rotation": [0, 0, 0], - "cubes": [ - {"origin": [-2.6, 23, -16], "size": [0, 3, 16], "uv": [44, 5]} - ] - }, - { - "name": "Mane", - "pivot": [0, 20, -10], - "rotation": [30, 0, 0], - "cubes": [ - {"origin": [-1, 15.5, -5], "size": [2, 16, 4], "uv": [58, 0]} - ] - }, - { - "name": "HeadSaddle", - "pivot": [0, 20, -10], - "rotation": [30, 0, 0], - "cubes": [ - { - "origin": [-2.5, 25.1, -17], - "size": [5, 5, 12], - "uv": [80, 12], - "inflate": 0.05 - } - ] - } - ] - } - }, - "spawn_egg": {"texture": "spawn_egg", "texture_index": 32} - }, - "slime": { - "identifier": "minecraft:slime", - "materials": {"default": "slime", "outer": "slime_outer"}, - "textures": {"default": "textures/entity/slime/slime"}, - "geometry": { - "default": { - "visible_bounds_width": 5, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 1, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "cube", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-3, 1, -3], "size": [6, 6, 6], "uv": [0, 16]}] - }, - { - "name": "eye0", - "parent": "cube", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-3.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 0]} - ] - }, - { - "name": "eye1", - "parent": "cube", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [1.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 4]} - ] - }, - { - "name": "mouth", - "parent": "cube", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [0, 2, -3.5], "size": [1, 1, 1], "uv": [32, 8]} - ] - } - ] - }, - "armor": { - "visible_bounds_width": 1, - "visible_bounds_height": 1, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "cube", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-4, 0, -4], "size": [8, 8, 8], "uv": [0, 0]}] - }, - { - "name": "eye0", - "parent": "cube", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-3.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 0]} - ] - }, - { - "name": "eye1", - "parent": "cube", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [1.3, 4, -3.5], "size": [2, 2, 2], "uv": [32, 4]} - ] - }, - { - "name": "mouth", - "parent": "cube", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [0, 2, -3.5], "size": [1, 1, 1], "uv": [32, 8]} - ] - } - ] - } - }, - "render_controllers": [ - "controller.render.slime", - "controller.render.slime_armor" - ], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 10} - }, - "small_fireball": { - "identifier": "minecraft:small_fireball", - "materials": {"default": "fireball"}, - "textures": {"default": "textures/items/fire_charge"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, -4, 0], - "size": [16, 16, 0], - "uv": {"south": {"uv": [0, 0]}} - } - ] - } - ], - "texturewidth": 16, - "textureheight": 16 - } - }, - "render_controllers": ["controller.render.fireball"] - }, - "snow_golem": { - "identifier": "minecraft:snow_golem", - "min_engine_version": "1.8.0", - "materials": {"default": "snow_golem", "head": "snow_golem_pumpkin"}, - "textures": {"default": "textures/entity/snow_golem"}, - "geometry": { - "default": { - "visible_bounds_width": 1, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 1, 0], - "bones": [ - { - "name": "head", - "parent": "piece1", - "pivot": [0, 20, 0], - "locators": {"lead": [0, 20, 0]}, - "cubes": [ - { - "origin": [-4, 20, -4], - "size": [8, 8, 8], - "uv": [0, 0], - "inflate": -0.5 - } - ] - }, - { - "name": "arm1", - "parent": "piece1", - "pivot": [0, 18, 0], - "bind_pose_rotation": [0, 0, 57.3], - "cubes": [ - { - "origin": [1, 20, -1], - "size": [12, 2, 2], - "uv": [32, 0], - "inflate": -0.5 - } - ] - }, - { - "name": "arm2", - "parent": "piece1", - "pivot": [0, 18, 0], - "bind_pose_rotation": [0, 180, -57.3], - "cubes": [ - { - "origin": [1, 20, -1], - "size": [12, 2, 2], - "uv": [32, 0], - "inflate": -0.5 - } - ] - }, - { - "name": "piece1", - "parent": "piece2", - "pivot": [0, 11, 0], - "cubes": [ - { - "origin": [-5, 11, -5], - "size": [10, 10, 10], - "uv": [0, 16], - "inflate": -0.5 - } - ] - }, - { - "name": "piece2", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-6, 0, -6], - "size": [12, 12, 12], - "uv": [0, 36], - "inflate": -0.5 - } - ] - } - ] - } - }, - "render_controllers": ["controller.render.snowgolem"] - }, - "snowball": { - "identifier": "minecraft:snowball", - "materials": {"default": "snowball"}, - "textures": {"default": "textures/items/snowball"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, -8, 0], - "size": [16, 16, 0], - "uv": [0, 0], - "rotation": [0, 0, 0] - } - ] - } - ], - "texturewidth": 16, - "textureheight": 16 - } - }, - "render_controllers": ["controller.render.item_sprite"] - }, - "potion": { - "identifier": "minecraft:splash_potion", - "materials": {"default": "splash_potion_enchanted"}, - "textures": { - "moveSlowdown": "textures/items/potion_bottle_splash_moveSlowdown", - "moveSpeed": "textures/items/potion_bottle_splash_moveSpeed", - "digSlowdown": "textures/items/potion_bottle_splash_digSlowdown", - "digSpeed": "textures/items/potion_bottle_splash_digSpeed", - "damageBoost": "textures/items/potion_bottle_splash_damageBoost", - "heal": "textures/items/potion_bottle_splash_heal", - "harm": "textures/items/potion_bottle_splash_harm", - "jump": "textures/items/potion_bottle_splash_jump", - "confusion": "textures/items/potion_bottle_splash_confusion", - "regeneration": "textures/items/potion_bottle_splash_regeneration", - "resistance": "textures/items/potion_bottle_splash_resistance", - "fireResistance": "textures/items/potion_bottle_splash_fireResistance", - "waterBreathing": "textures/items/potion_bottle_splash_waterBreathing", - "invisibility": "textures/items/potion_bottle_splash_invisibility", - "blindness": "textures/items/potion_bottle_splash_blindness", - "nightVision": "textures/items/potion_bottle_splash_nightVision", - "hunger": "textures/items/potion_bottle_splash_hunger", - "weakness": "textures/items/potion_bottle_splash_weakness", - "poison": "textures/items/potion_bottle_splash_poison", - "wither": "textures/items/potion_bottle_splash_wither", - "healthBoost": "textures/items/potion_bottle_splash_healthBoost", - "absorption": "textures/items/potion_bottle_splash_absorption", - "saturation": "textures/items/potion_bottle_splash_saturation", - "levitation": "textures/items/potion_bottle_splash_levitation", - "turtleMaster": "textures/items/potion_bottle_splash_turtleMaster", - "slowFall": "textures/items/potion_bottle_splash_slowFall", - "default": "textures/items/potion_bottle_splash", - "enchanted": "textures/misc/enchanted_item_glint" - }, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, -8, 0], - "size": [16, 16, 0], - "uv": [0, 0], - "rotation": [0, 0, 0] - } - ] - } - ], - "texturewidth": 16, - "textureheight": 16 - } - }, - "render_controllers": ["controller.render.splash_potion"] - }, - "squid": { - "identifier": "minecraft:squid", - "materials": {"default": "squid"}, - "textures": {"default": "textures/entity/squid"}, - "geometry": { - "default": { - "visible_bounds_width": 3, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 0.5, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "body", - "cubes": [ - {"origin": [-6, -8, -6], "size": [12, 16, 12], "uv": [0, 0]} - ] - }, - { - "name": "tentacle1", - "parent": "body", - "pivot": [5, -7, 0], - "cubes": [ - {"origin": [4, -25, -1], "size": [2, 18, 2], "uv": [48, 0]} - ], - "rotation": [0, 90, 0] - }, - { - "name": "tentacle2", - "parent": "body", - "pivot": [3.5, -7, 3.5], - "cubes": [ - {"origin": [2.5, -25, 2.5], "size": [2, 18, 2], "uv": [48, 0]} - ], - "rotation": [0, 45, 0] - }, - { - "name": "tentacle3", - "parent": "body", - "pivot": [0, -7, 5], - "cubes": [ - {"origin": [-1, -25, 4], "size": [2, 18, 2], "uv": [48, 0]} - ], - "rotation": [0, 0, 0] - }, - { - "name": "tentacle4", - "parent": "body", - "pivot": [-3.5, -7, 3.5], - "cubes": [ - {"origin": [-4.5, -25, 2.5], "size": [2, 18, 2], "uv": [48, 0]} - ], - "rotation": [0, -45, 0] - }, - { - "name": "tentacle5", - "parent": "body", - "pivot": [-5, -7, 0], - "cubes": [ - {"origin": [-6, -25, -1], "size": [2, 18, 2], "uv": [48, 0]} - ], - "rotation": [0, -90, 0] - }, - { - "name": "tentacle6", - "parent": "body", - "pivot": [-3.5, -7, -3.5], - "cubes": [ - {"origin": [-4.5, -25, -4.5], "size": [2, 18, 2], "uv": [48, 0]} - ], - "rotation": [0, -135, 0] - }, - { - "name": "tentacle7", - "parent": "body", - "pivot": [0, -7, -5], - "cubes": [ - {"origin": [-1, -25, -6], "size": [2, 18, 2], "uv": [48, 0]} - ], - "rotation": [0, -180, 0] - }, - { - "name": "tentacle8", - "parent": "body", - "pivot": [3.5, -7, -3.5], - "cubes": [ - {"origin": [2.5, -25, -4.5], "size": [2, 18, 2], "uv": [48, 0]} - ], - "rotation": [0, -225, 0] - } - ] - } - }, - "render_controllers": ["controller.render.squid"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 15} - }, - "stray": { - "identifier": "minecraft:stray", - "min_engine_version": "1.8.0", - "materials": {"default": "stray", "overlay": "stray_clothes"}, - "textures": { - "default": "textures/entity/skeleton/stray", - "overlay": "textures/entity/skeleton/stray_overlay" - }, - "geometry": { - "default": { - "visible_bounds_width": 1.5, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 1, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]} - ], - "parent": "waist" - }, - {"name": "waist", "pivot": [0, 12, 0]}, - { - "name": "head", - "pivot": [0, 24, 0], - "locators": {"lead": [0, 24, 0]}, - "cubes": [ - {"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]} - ], - "parent": "body" - }, - { - "name": "hat", - "pivot": [0, 24, 0], - "cubes": [ - { - "origin": [-4, 24, -4], - "size": [8, 8, 8], - "uv": [32, 0], - "inflate": 0.5 - } - ], - "neverRender": true, - "parent": "head" - }, - { - "name": "rightArm", - "pivot": [-5, 22, 0], - "cubes": [ - {"origin": [-6, 12, -1], "size": [2, 12, 2], "uv": [40, 16]} - ], - "parent": "body" - }, - { - "name": "rightItem", - "pivot": [-1, -45, -5], - "neverRender": true, - "parent": "rightArm" - }, - { - "name": "leftArm", - "pivot": [5, 22, 0], - "cubes": [ - {"origin": [4, 12, -1], "size": [2, 12, 2], "uv": [40, 16]} - ], - "mirror": true, - "parent": "body" - }, - { - "name": "leftItem", - "pivot": [1, -45, -5], - "neverRender": true, - "parent": "leftArm" - }, - { - "name": "rightLeg", - "pivot": [-2, 12, 0], - "cubes": [ - {"origin": [-3, 0, -1], "size": [2, 12, 2], "uv": [0, 16]} - ], - "parent": "body" - }, - { - "name": "leftLeg", - "pivot": [2, 12, 0], - "cubes": [ - {"origin": [1, 0, -1], "size": [2, 12, 2], "uv": [0, 16]} - ], - "mirror": true, - "parent": "body" - } - ] - }, - "overlay": { - "visible_bounds_width": 2, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 1, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "body", - "parent": "waist", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]} - ], - "inflate": 0.25 - }, - {"name": "waist", "neverRender": true, "pivot": [0, 12, 0]}, - { - "name": "head", - "parent": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]} - ], - "inflate": 0.25 - }, - { - "name": "hat", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - { - "origin": [-4, 24, -4], - "size": [8, 8, 8], - "uv": [32, 0], - "inflate": 0.5 - } - ], - "neverRender": true - }, - { - "name": "rightArm", - "parent": "body", - "pivot": [-5, 22, 0], - "cubes": [ - {"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]} - ], - "inflate": 0.25 - }, - { - "name": "rightItem", - "parent": "rightArm", - "pivot": [-6, 15, 1], - "neverRender": true - }, - { - "name": "leftArm", - "parent": "body", - "pivot": [5, 22, 0], - "cubes": [ - {"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 16]} - ], - "mirror": true, - "inflate": 0.25 - }, - { - "name": "rightLeg", - "parent": "body", - "pivot": [-1.9, 12, 0], - "cubes": [ - {"origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]} - ], - "inflate": 0.25 - }, - { - "name": "leftLeg", - "parent": "body", - "pivot": [1.9, 12, 0], - "cubes": [ - {"origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 16]} - ], - "inflate": 0.25, - "mirror": true - } - ] - } - }, - "spawn_egg": {"texture": "spawn_egg", "texture_index": 27}, - "render_controllers": [ - "controller.render.stray_clothes", - "controller.render.stray" - ], - "enable_attachables": true - }, - "strider": { - "identifier": "minecraft:strider", - "materials": {"default": "strider"}, - "textures": { - "default": "textures/entity/strider/strider", - "saddled": "textures/entity/strider/strider", - "suffocated": "textures/entity/strider/strider_cold", - "suffocated_saddled": "textures/entity/strider/strider_cold" - }, - "geometry": { - "default": { - "bones": [ - { - "name": "right_leg", - "pivot": [-4, 16, 0], - "cubes": [ - {"origin": [-6, 0, -2], "size": [4, 16, 4], "uv": [0, 32]} - ] - }, - { - "name": "left_leg", - "pivot": [4, 16, 0], - "cubes": [{"origin": [2, 0, -2], "size": [4, 16, 4], "uv": [0, 55]}] - }, - { - "name": "body", - "pivot": [0, 16, 0], - "cubes": [ - {"origin": [-8, 14, -8], "size": [16, 14, 16], "uv": [0, 0]} - ], - "locators": {"lead": [0, 15, -1]} - }, - { - "name": "bristle5", - "parent": "body", - "pivot": [8, 19, 0], - "cubes": [ - { - "origin": [8, 19, -8], - "size": [12, 0, 16], - "pivot": [8, 19, 0], - "rotation": [0, 0, 70], - "uv": [16, 65] - } - ] - }, - { - "name": "bristle4", - "parent": "body", - "pivot": [8, 24, 0], - "cubes": [ - { - "origin": [8, 24, -8], - "size": [12, 0, 16], - "pivot": [8, 24, 0], - "rotation": [0, 0, 65], - "uv": [16, 49] - } - ] - }, - { - "name": "bristle3", - "parent": "body", - "pivot": [8, 28, 0], - "cubes": [ - { - "origin": [8, 28, -8], - "size": [12, 0, 16], - "pivot": [8, 28, 0], - "rotation": [0, 0, 50], - "uv": [16, 33] - } - ] - }, - { - "name": "bristle2", - "parent": "body", - "pivot": [-8, 28, 0], - "cubes": [ - { - "origin": [-20, 28, -8], - "size": [12, 0, 16], - "pivot": [-8, 28, 0], - "rotation": [0, 0, -50], - "uv": [16, 33], - "mirror": true - } - ] - }, - { - "name": "bristle1", - "parent": "body", - "pivot": [-8, 24, 0], - "cubes": [ - { - "origin": [-20, 24, -8], - "size": [12, 0, 16], - "pivot": [-8, 24, 0], - "rotation": [0, 0, -65], - "uv": [16, 49], - "mirror": true - } - ] - }, - { - "name": "bristle0", - "parent": "body", - "pivot": [-8, 19, 0], - "cubes": [ - { - "origin": [-20, 19, -8], - "size": [12, 0, 16], - "pivot": [-8, 19, 0], - "rotation": [0, 0, -70], - "uv": [16, 65], - "mirror": true - } - ] - } - ], - "visible_bounds_width": 3, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 1, 0], - "texturewidth": 64, - "textureheight": 128 - } - }, - "spawn_egg": {"base_color": "#9c3436", "overlay_color": "#4d494d"}, - "render_controllers": ["controller.render.strider"] - }, - "text_display": { - "identifier": "minecraft:text_display", - "geometry": {} - }, - "trident": { - "identifier": "minecraft:thrown_trident", - "textures": { - "default": "textures/entity/trident", - "loyalty_rope": "textures/entity/lead_knot" - }, - "geometry": { - "default": { - "texturewidth": 32, - "textureheight": 32, - "bones": [ - { - "name": "pole", - "pivot": [0, 24, 0], - "cubes": [ - { - "origin": [-0.5, -3, -0.5], - "size": [1, 31, 1], - "inflate": 0.01, - "uv": [0, 0] - }, - {"origin": [-1.5, 22, -0.5], "size": [3, 2, 1], "uv": [4, 0]}, - {"origin": [-2.5, 23, -0.5], "size": [1, 4, 1], "uv": [4, 3]}, - {"origin": [1.5, 23, -0.5], "size": [1, 4, 1], "uv": [4, 3]} - ] - } - ] - } - } - }, - "tnt_minecart": { - "identifier": "minecraft:tnt_minecart", - "min_engine_version": "1.8.0", - "materials": {"default": "minecart"}, - "textures": {"default": "textures/entity/minecart"}, - "geometry": { - "default": { - "bones": [ - { - "name": "bottom", - "pivot": [0, 6, 0], - "cubes": [ - { - "origin": [-10, -6.5, -1], - "size": [20, 16, 2], - "rotation": [90, 0, 0], - "uv": [0, 10] - } - ] - }, - { - "name": "back", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-17, 2.5, -1], - "size": [16, 8, 2], - "rotation": [0, 270, 0], - "uv": [0, 0] - } - ], - "parent": "bottom" - }, - { - "name": "front", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [1, 2.5, -1], - "size": [16, 8, 2], - "rotation": [0, 90, 0], - "uv": [0, 0] - } - ], - "parent": "bottom" - }, - { - "name": "right", - "pivot": [0, 0, 0], - "cubes": [ - { - "origin": [-8, 2.5, -8], - "size": [16, 8, 2], - "rotation": [0, 180, 0], - "uv": [0, 0] - } - ], - "parent": "bottom" - }, - { - "name": "left", - "pivot": [0, 0, 0], - "cubes": [ - {"origin": [-8, 2.5, 6], "size": [16, 8, 2], "uv": [0, 0]} - ], - "parent": "bottom" - } - ], - "texturewidth": 64, - "textureheight": 32 - } - }, - "render_controllers": ["controller.render.minecart"] - }, - "tropical_fish": { - "identifier": "minecraft:tropicalfish", - "materials": {"default": "tropicalfish"}, - "textures": { - "typeA": "textures/entity/fish/tropical_a", - "typeB": "textures/entity/fish/tropical_b", - "aPattern1": "textures/entity/fish/tropical_a_pattern_1", - "aPattern2": "textures/entity/fish/tropical_a_pattern_2", - "aPattern3": "textures/entity/fish/tropical_a_pattern_3", - "aPattern4": "textures/entity/fish/tropical_a_pattern_4", - "aPattern5": "textures/entity/fish/tropical_a_pattern_5", - "aPattern6": "textures/entity/fish/tropical_a_pattern_6", - "bPattern1": "textures/entity/fish/tropical_b_pattern_1", - "bPattern2": "textures/entity/fish/tropical_b_pattern_2", - "bPattern3": "textures/entity/fish/tropical_b_pattern_3", - "bPattern4": "textures/entity/fish/tropical_b_pattern_4", - "bPattern5": "textures/entity/fish/tropical_b_pattern_5", - "bPattern6": "textures/entity/fish/tropical_b_pattern_6" - }, - "geometry": { - "typeA": { - "visible_bounds_width": 0.5, - "visible_bounds_height": 0.5, - "bones": [ - { - "pivot": [-0.5, 0, 0], - "cubes": [ - {"origin": [-1, 0, -3], "size": [2, 3, 6], "uv": [0, 0]}, - {"origin": [0, 3, -2.9992], "size": [0, 4, 6], "uv": [10, -6]} - ], - "name": "body" - }, - { - "pivot": [0, 0, 3], - "cubes": [{"origin": [0, 0, 3], "size": [0, 3, 4], "uv": [24, -4]}], - "name": "tailfin", - "parent": "body" - }, - { - "pivot": [0.5, 0, 1], - "bind_pose_rotation": [0, -35, 0], - "cubes": [ - {"origin": [0.336, 0, -0.10594], "size": [2, 2, 0], "uv": [2, 12]} - ], - "name": "leftFin", - "parent": "body" - }, - { - "pivot": [-0.5, 0, 1], - "bind_pose_rotation": [0, 35, 0], - "cubes": [ - { - "origin": [-2.336, 0, -0.10594], - "size": [2, 2, 0], - "uv": [2, 16] - } - ], - "name": "rightFin", - "parent": "body" - } - ], - "texturewidth": 32, - "textureheight": 32 - }, - "typeB": { - "visible_bounds_width": 0.5, - "visible_bounds_height": 0.5, - "bones": [ - { - "pivot": [-0.5, 0, 0], - "cubes": [ - {"origin": [-1, 0, -0.0008], "size": [2, 6, 6], "uv": [0, 20]}, - {"origin": [0, -5, -0.0008], "size": [0, 5, 6], "uv": [20, 21]}, - {"origin": [0, 6, -0.0008], "size": [0, 5, 6], "uv": [20, 10]} - ], - "name": "body" - }, - { - "pivot": [0, 0, 6], - "cubes": [ - {"origin": [0, 0.0008, 6], "size": [0, 6, 5], "uv": [21, 16]} - ], - "name": "tailfin", - "parent": "body" - }, - { - "pivot": [0.5, 0, 1], - "bind_pose_rotation": [0, -35, 0], - "cubes": [ - { - "origin": [2.05673, 0, 2.35152], - "size": [2, 2, 0], - "uv": [2, 12] - } - ], - "name": "leftFin", - "parent": "body" - }, - { - "pivot": [-0.5, 0, 1], - "bind_pose_rotation": [0, 35, 0], - "cubes": [ - { - "origin": [-4.05673, 0, 2.35152], - "size": [2, 2, 0], - "uv": [2, 16] - } - ], - "name": "rightFin", - "parent": "body" - } - ], - "texturewidth": 32, - "textureheight": 32 - } - }, - "render_controllers": ["controller.render.tropicalfish"], - "spawn_egg": {"texture": "spawn_egg", "texture_index": 44} - }, - "vindicator": { - "identifier": "minecraft:vindicator", - "min_engine_version": "1.8.0", - "materials": {"default": "vindicator"}, - "textures": {"default": "textures/entity/illager/vindicator"}, - "geometry": { - "default": { - "visible_bounds_width": 1.5, - "visible_bounds_height": 2.5, - "visible_bounds_offset": [0, 1.25, 0], - "texturewidth": 64, - "textureheight": 64, - "bones": [ - { - "name": "head", - "parent": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 24, -4], "size": [8, 10, 8], "uv": [0, 0]} - ] - }, - { - "name": "nose", - "parent": "head", - "pivot": [0, 26, 0], - "cubes": [ - {"origin": [-1, 23, -6], "size": [2, 4, 2], "uv": [24, 0]} - ] - }, - { - "name": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 12, -3], "size": [8, 12, 6], "uv": [16, 20]}, - { - "origin": [-4, 6, -3], - "size": [8, 18, 6], - "uv": [0, 38], - "inflate": 0.5 - } - ] - }, - { - "name": "arms", - "parent": "body", - "pivot": [0, 22, 0], - "cubes": [ - {"origin": [-8, 16, -2], "size": [4, 8, 4], "uv": [44, 22]}, - {"origin": [4, 16, -2], "size": [4, 8, 4], "uv": [44, 22]}, - {"origin": [-4, 16, -2], "size": [8, 4, 4], "uv": [40, 38]} - ] - }, - { - "name": "leg0", - "parent": "body", - "pivot": [-2, 12, 0], - "cubes": [ - {"origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} - ] - }, - { - "name": "leg1", - "parent": "body", - "pivot": [2, 12, 0], - "mirror": true, - "cubes": [{"origin": [0, 0, -2], "size": [4, 12, 4], "uv": [0, 22]}] - }, - { - "name": "rightArm", - "parent": "body", - "pivot": [-5, 22, 0], - "cubes": [ - {"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 46]} - ] - }, - { - "name": "rightItem", - "pivot": [-5.5, 16, 0.5], - "neverRender": true, - "parent": "rightArm" - }, - { - "name": "leftArm", - "parent": "body", - "pivot": [5, 22, 0], - "mirror": true, - "cubes": [ - {"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 46]} - ] - } - ] - } - }, - "spawn_egg": {"texture": "spawn_egg", "texture_index": 39}, - "render_controllers": ["controller.render.vindicator"], - "enable_attachables": true - }, - "wandering_trader": { - "identifier": "minecraft:wandering_trader", - "materials": {"default": "wandering_trader"}, - "textures": {"default": "textures/entity/wandering_trader"}, - "geometry": { - "default": { - "visible_bounds_width": 1.5, - "visible_bounds_height": 2.5, - "visible_bounds_offset": [0, 1.25, 0], - "bones": [ - { - "name": "head", - "parent": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 24, -4], "size": [8, 10, 8], "uv": [0, 0]} - ] - }, - { - "name": "helmet", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - { - "origin": [-4, 24, -4], - "size": [8, 10, 8], - "uv": [32, 0], - "inflate": 0.5 - } - ] - }, - { - "name": "brim", - "parent": "head", - "pivot": [0, 24, 0], - "bind_pose_rotation": [-90, 0, 0], - "cubes": [ - { - "origin": [-8, 16, -6], - "size": [16, 16, 1], - "uv": [30, 47], - "inflate": 0.1 - } - ] - }, - { - "name": "nose", - "parent": "head", - "pivot": [0, 26, 0], - "cubes": [ - {"origin": [-1, 23, -6], "size": [2, 4, 2], "uv": [24, 0]} - ] - }, - { - "name": "body", - "locators": {"lead_hold": [0, 40, 0]}, - "cubes": [ - {"origin": [-4, 12, -3], "size": [8, 12, 6], "uv": [16, 20]}, - { - "origin": [-4, 6, -3], - "size": [8, 18, 6], - "uv": [0, 38], - "inflate": 0.5 - } - ] - }, - { - "name": "arms", - "parent": "body", - "pivot": [0, 22, 0], - "cubes": [ - {"origin": [-4, 16, -2], "size": [8, 4, 4], "uv": [40, 38]}, - {"origin": [-8, 16, -2], "size": [4, 8, 4], "uv": [44, 22]}, - { - "origin": [4, 16, -2], - "size": [4, 8, 4], - "uv": [44, 22], - "mirror": true - } - ] - }, - {"name": "held_item", "parent": "arms", "pivot": [0, 0, 0]}, - { - "name": "leg0", - "parent": "body", - "pivot": [-2, 12, 0], - "cubes": [ - {"origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 22]} - ] - }, - { - "name": "leg1", - "parent": "body", - "pivot": [2, 12, 0], - "cubes": [ - { - "origin": [0, 0, -2], - "size": [4, 12, 4], - "uv": [0, 22], - "mirror": true - } - ] - } - ] - } - }, - "render_controllers": ["controller.render.wandering_trader"], - "spawn_egg": {"texture": "spawn_egg_wandering_trader"} - }, - "wither": { - "identifier": "minecraft:wither", - "min_engine_version": "1.8.0", - "materials": {"default": "wither_boss", "armor": "wither_boss_armor"}, - "textures": { - "default": "textures/entity/wither/wither", - "armor_white": "textures/entity/wither/wither_armor", - "armor_blue": "textures/entity/wither/wither_armor", - "invulnerable": "textures/entity/wither/wither_invulnerable" - }, - "geometry": { - "default": { - "visible_bounds_width": 3, - "visible_bounds_height": 4, - "visible_bounds_offset": [0, 2, 0], - "texturewidth": 64, - "textureheight": 64, - "bones": [ - { - "name": "upperBodyPart1", - "cubes": [ - {"origin": [-10, 17.1, -0.5], "size": [20, 3, 3], "uv": [0, 16]} - ] - }, - { - "name": "upperBodyPart2", - "parent": "upperBodyPart1", - "pivot": [-2, 17.1, -0.5], - "cubes": [ - {"origin": [-2, 7.1, -0.5], "size": [3, 10, 3], "uv": [0, 22]}, - {"origin": [-6, 13.6, 0], "size": [11, 2, 2], "uv": [24, 22]}, - {"origin": [-6, 11.1, 0], "size": [11, 2, 2], "uv": [24, 22]}, - {"origin": [-6, 8.6, 0], "size": [11, 2, 2], "uv": [24, 22]} - ] - }, - { - "name": "upperBodyPart3", - "parent": "upperBodyPart2", - "pivot": [0, 24, 0], - "cubes": [{"origin": [0, 18, 0], "size": [3, 6, 3], "uv": [12, 22]}] - }, - { - "name": "head1", - "parent": "upperBodyPart1", - "pivot": [0, 20, 0], - "cubes": [{"origin": [-4, 20, -4], "size": [8, 8, 8], "uv": [0, 0]}] - }, - { - "name": "head2", - "parent": "upperBodyPart1", - "pivot": [-9, 18, -1], - "cubes": [ - {"origin": [-12, 18, -4], "size": [6, 6, 6], "uv": [32, 0]} - ] - }, - { - "name": "head3", - "parent": "upperBodyPart1", - "pivot": [9, 18, -1], - "cubes": [{"origin": [6, 18, -4], "size": [6, 6, 6], "uv": [32, 0]}] - } - ] - }, - "armor": { - "visible_bounds_width": 3, - "visible_bounds_height": 4, - "visible_bounds_offset": [0, 2, 0], - "texturewidth": 64, - "textureheight": 64, - "bones": [ - { - "name": "upperBodyPart1", - "cubes": [ - {"origin": [-10, 17.1, -0.5], "size": [20, 3, 3], "uv": [0, 16]} - ], - "inflate": 2 - }, - { - "name": "upperBodyPart2", - "parent": "upperBodyPart1", - "pivot": [-2, 17.1, -0.5], - "cubes": [ - {"origin": [-2, 7.1, -0.5], "size": [3, 10, 3], "uv": [0, 22]}, - {"origin": [-6, 13.6, 0], "size": [11, 2, 2], "uv": [24, 22]}, - {"origin": [-6, 11.1, 0], "size": [11, 2, 2], "uv": [24, 22]}, - {"origin": [-6, 8.6, 0], "size": [11, 2, 2], "uv": [24, 22]} - ], - "inflate": 2 - }, - { - "name": "upperBodyPart3", - "parent": "upperBodyPart2", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [0, 18, 0], "size": [3, 6, 3], "uv": [12, 22]} - ], - "inflate": 2 - }, - { - "name": "head1", - "parent": "upperBodyPart1", - "pivot": [0, 20, 0], - "cubes": [ - {"origin": [-4, 20, -4], "size": [8, 8, 8], "uv": [0, 0]} - ], - "inflate": 2 - }, - { - "name": "head2", - "parent": "upperBodyPart1", - "pivot": [-9, 18, -1], - "cubes": [ - {"origin": [-12, 18, -4], "size": [6, 6, 6], "uv": [32, 0]} - ], - "inflate": 2 - }, - { - "name": "head3", - "parent": "upperBodyPart1", - "pivot": [9, 18, -1], - "cubes": [ - {"origin": [6, 18, -4], "size": [6, 6, 6], "uv": [32, 0]} - ], - "inflate": 2 - } - ] - } - }, - "render_controllers": [ - "controller.render.wither_boss", - "controller.render.wither_boss_armor_white", - "controller.render.wither_boss_armor_blue" - ] - }, - "wither_skeleton": { - "identifier": "minecraft:wither_skeleton", - "min_engine_version": "1.8.0", - "materials": {"default": "skeleton"}, - "textures": {"default": "textures/entity/skeleton/wither_skeleton"}, - "geometry": { - "default": { - "texturewidth": 64, - "textureheight": 32, - "visible_bounds_width": 1.5, - "visible_bounds_height": 3, - "visible_bounds_offset": [0, 1.5, 0], - "bones": [ - { - "name": "body", - "parent": "waist", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]} - ] - }, - {"name": "waist", "pivot": [0, 12, 0]}, - { - "name": "head", - "parent": "body", - "pivot": [0, 24, 0], - "cubes": [{"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]}] - }, - { - "name": "hat", - "parent": "head", - "pivot": [0, 24, 0], - "cubes": [ - { - "origin": [-4, 24, -4], - "size": [8, 8, 8], - "uv": [32, 0], - "inflate": 0.5 - } - ], - "neverRender": true - }, - { - "name": "rightArm", - "parent": "body", - "pivot": [-5, 22, 0], - "cubes": [ - {"origin": [-6, 12, -1], "size": [2, 12, 2], "uv": [40, 16]} - ] - }, - { - "name": "rightItem", - "parent": "rightArm", - "pivot": [-1, -45, -5], - "neverRender": true - }, - { - "name": "leftArm", - "parent": "body", - "pivot": [5, 22, 0], - "cubes": [ - {"origin": [4, 12, -1], "size": [2, 12, 2], "uv": [40, 16]} - ], - "mirror": true - }, - { - "name": "leftItem", - "parent": "leftArm", - "pivot": [1, -45, -5], - "neverRender": true - }, - { - "name": "rightLeg", - "parent": "body", - "pivot": [-2, 12, 0], - "cubes": [ - {"origin": [-3, 0, -1], "size": [2, 12, 2], "uv": [0, 16]} - ] - }, - { - "name": "leftLeg", - "parent": "body", - "pivot": [2, 12, 0], - "cubes": [ - {"origin": [1, 0, -1], "size": [2, 12, 2], "uv": [0, 16]} - ], - "mirror": true - } - ] - } - }, - "render_controllers": ["controller.render.wither_skeleton"], - "enable_attachables": true, - "spawn_egg": {"texture": "spawn_egg", "texture_index": 29} - }, - "wither_skull": { - "identifier": "minecraft:wither_skull", - "materials": {"default": "wither_skull"}, - "textures": {"default": "textures/entity/wither/wither"}, - "geometry": { - "default": { - "bones": [ - { - "name": "head", - "cubes": [{"origin": [-4, 0, -4], "size": [8, 8, 8], "uv": [0, 35]}] - } - ], - "visible_bounds_width": 1, - "visible_bounds_height": 1, - "texturewidth": 64, - "textureheight": 64 - } - }, - "render_controllers": ["controller.render.wither_skull"] - }, - "zoglin": { - "identifier": "minecraft:zoglin", - "materials": {"default": "zoglin"}, - "textures": {"default": "textures/entity/hoglin/zoglin"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 19, -3], - "cubes": [ - { - "origin": [-8, 11, -7], - "size": [16, 14, 26], - "inflate": 0.02, - "uv": [1, 1] - }, - { - "origin": [0, 22, -10], - "size": [0, 10, 19], - "inflate": 0.02, - "uv": [90, 33] - } - ], - "locators": {"lead": [0, 20, -5]} - }, - { - "name": "head", - "parent": "body", - "pivot": [0, 22, -5], - "rotation": [50, 0, 0], - "cubes": [ - {"origin": [-7, 21, -24], "size": [14, 6, 19], "uv": [61, 1]}, - {"origin": [-8, 22, -19], "size": [2, 11, 2], "uv": [1, 13]}, - {"origin": [6, 22, -19], "size": [2, 11, 2], "uv": [1, 13]} - ] - }, - { - "name": "right_ear", - "parent": "head", - "pivot": [-7, 27, -7], - "rotation": [0, 0, -50], - "cubes": [ - {"origin": [-13, 26, -10], "size": [6, 1, 4], "uv": [1, 1]} - ] - }, - { - "name": "left_ear", - "parent": "head", - "pivot": [7, 27, -7], - "rotation": [0, 0, 50], - "cubes": [{"origin": [7, 26, -10], "size": [6, 1, 4], "uv": [1, 6]}] - }, - { - "name": "leg_back_right", - "pivot": [6, 8, 17], - "cubes": [ - {"origin": [-8, 0, 13], "size": [5, 11, 5], "uv": [21, 45]} - ] - }, - { - "name": "leg_back_left", - "pivot": [-6, 8, 17], - "cubes": [{"origin": [3, 0, 13], "size": [5, 11, 5], "uv": [0, 45]}] - }, - { - "name": "leg_front_right", - "pivot": [-6, 12, -3], - "cubes": [ - {"origin": [-8, 0, -6], "size": [6, 14, 6], "uv": [66, 42]} - ] - }, - { - "name": "leg_front_left", - "pivot": [6, 12, -3], - "cubes": [ - {"origin": [2, 0, -6], "size": [6, 14, 6], "uv": [41, 42]} - ] - } - ], - "visible_bounds_width": 4, - "visible_bounds_height": 3, - "visible_bounds_offset": [0, 1.5, 0], - "texturewidth": 128, - "textureheight": 64 - } - }, - "spawn_egg": {"base_color": "#c66e55", "overlay_color": "#e6e6e6"}, - "render_controllers": ["controller.render.zoglin"] - }, - "zombie": { - "identifier": "minecraft:zombie", - "min_engine_version": "1.8.0", - "materials": {"default": "zombie"}, - "textures": {"default": "textures/entity/zombie/zombie"}, - "geometry": { - "default": { - "visible_bounds_width": 2, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 1, 0], - "texturewidth": 64, - "textureheight": 32, - "bones": [ - { - "name": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]} - ], - "parent": "waist" - }, - {"name": "waist", "neverRender": true, "pivot": [0, 12, 0]}, - { - "name": "head", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 24, -4], "size": [8, 8, 8], "uv": [0, 0]} - ], - "parent": "body" - }, - { - "name": "hat", - "pivot": [0, 24, 0], - "cubes": [ - { - "origin": [-4, 24, -4], - "size": [8, 8, 8], - "uv": [32, 0], - "inflate": 0.5 - } - ], - "neverRender": true, - "parent": "head" - }, - { - "name": "rightArm", - "pivot": [-5, 22, 0], - "cubes": [ - {"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]} - ], - "parent": "body" - }, - { - "name": "rightItem", - "pivot": [-1, -45, -5], - "neverRender": true, - "parent": "rightArm" - }, - { - "name": "leftArm", - "pivot": [5, 22, 0], - "cubes": [ - {"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [40, 16]} - ], - "mirror": true, - "parent": "body" - }, - { - "name": "leftItem", - "pivot": [1, -45, -5], - "neverRender": true, - "parent": "leftArm" - }, - { - "name": "rightLeg", - "pivot": [-1.9, 12, 0], - "cubes": [ - {"origin": [-3.9, 0, -2], "size": [4, 12, 4], "uv": [0, 16]} - ], - "parent": "body" - }, - { - "name": "leftLeg", - "pivot": [1.9, 12, 0], - "cubes": [ - {"origin": [-0.1, 0, -2], "size": [4, 12, 4], "uv": [0, 16]} - ], - "mirror": true, - "parent": "body" - } - ] - } - }, - "spawn_egg": {"texture": "spawn_egg", "texture_index": 12}, - "scripts": { - "pre_animation": [ - "variable.tcos0 = (Math.cos(query.modified_distance_moved * 38.17) * query.modified_move_speed / variable.gliding_speed_value) * 57.3;" - ] - }, - "animations": { - "humanoid_big_head": {"loop": true, "bones": {"head": {"scale": 1.4}}}, - "look_at_target_default": { - "loop": true, - "bones": { - "head": { - "relative_to": {"rotation": "entity"}, - "rotation": [ - "query.target_x_rotation", - "query.target_y_rotation", - 0 - ] - } - } - }, - "look_at_target_gliding": { - "loop": true, - "bones": {"head": {"rotation": [-45, "query.target_y_rotation", 0]}} - }, - "look_at_target_swimming": { - "loop": true, - "bones": { - "head": { - "rotation": [ - "math.lerp(query.target_x_rotation, -45.0, variable.swim_amount)", - "query.target_y_rotation", - 0 - ] - } - } - }, - "move": { - "loop": true, - "bones": { - "leftarm": {"rotation": ["variable.tcos0", 0, 0]}, - "leftleg": {"rotation": ["variable.tcos0 * -1.4", 0, 0]}, - "rightarm": {"rotation": ["-variable.tcos0", 0, 0]}, - "rightleg": {"rotation": ["variable.tcos0 * 1.4", 0, 0]} - } - }, - "riding.arms": { - "loop": true, - "bones": { - "leftarm": {"rotation": [-36, 0, 0]}, - "rightarm": {"rotation": [-36, 0, 0]} - } - }, - "riding.legs": { - "loop": true, - "bones": { - "leftleg": {"rotation": ["-72.0 - this", "-18.0 - this", "-this"]}, - "rightleg": {"rotation": ["-72.0 - this", "18.0 - this", "-this"]} - } - }, - "holding": { - "loop": true, - "bones": { - "leftarm": { - "rotation": [ - "variable.is_holding_left ? (-this * 0.5 - 18.0) : 0.0", - 0, - 0 - ] - }, - "rightarm": { - "rotation": [ - "variable.is_holding_right ? (-this * 0.5 - 18.0) : 0.0", - 0, - 0 - ] - } - } - }, - "brandish_spear": { - "loop": true, - "bones": { - "rightarm": { - "rotation": [ - "this * -0.5 - 157.5 - 22.5 * variable.charge_amount", - "-this", - 0 - ] - } - } - }, - "charging": { - "loop": true, - "bones": { - "rightarm": { - "rotation": ["22.5 * variable.charge_amount - this", "-this", 0] - } - } - }, - "attack.rotations": { - "loop": true, - "bones": { - "body": { - "rotation": [ - 0, - "math.sin(math.sqrt(variable.attack_time) * 360) * 11.46 - this", - 0 - ] - }, - "leftarm": { - "rotation": [ - "math.sin(math.sqrt(variable.attack_time) * 360) * 11.46", - 0, - 0 - ] - }, - "rightarm": { - "rotation": [ - "math.sin(1.0 - math.pow(1.0 - variable.attack_time, 3.0) * 180.0) * (variable.is_brandishing_spear ? -1.0 : 1.0 )", - "variable.is_brandishing_spear ? 0.0 : (math.sin(math.sqrt(variable.attack_time) * 360) * 11.46) * 2.0", - 0 - ] - } - } - }, - "sneaking": { - "loop": true, - "bones": { - "body": {"rotation": ["0.5 - this", 0, 0]}, - "head": {"position": [0, 1, 0]}, - "leftarm": {"rotation": [72, 0, 0]}, - "leftleg": {"position": [0, -3, 4]}, - "rightarm": {"rotation": [72, 0, 0]}, - "rightleg": {"position": [0, -3, 4]} - } - }, - "bob": { - "loop": true, - "bones": { - "leftarm": { - "rotation": [ - 0, - 0, - "((math.cos(query.life_time * 103.2) * 2.865) + 2.865) *-1.0" - ] - }, - "rightarm": { - "rotation": [ - 0, - 0, - "(math.cos(query.life_time * 103.2) * 2.865) + 2.865" - ] - } - } - }, - "damage_nearby_mobs": { - "loop": true, - "bones": { - "leftarm": {"rotation": ["-45.0-this", "-this", "-this"]}, - "leftleg": {"rotation": ["45.0-this", "-this", "-this"]}, - "rightarm": {"rotation": ["45.0-this", "-this", "-this"]}, - "rightleg": {"rotation": ["-45.0-this", "-this", "-this"]} - } - }, - "bow_and_arrow": { - "loop": true, - "bones": { - "leftarm": { - "rotation": [ - "query.target_x_rotation - 90.0 - math.sin(query.life_time * 76.8) * 2.865 - this", - "query.target_y_rotation + 28.65", - "-(math.cos(query.life_time * 103.2) * 2.865) - 2.865" - ] - }, - "rightarm": { - "rotation": [ - "query.target_x_rotation - 90.0 + math.sin(query.life_time * 76.8) * 2.865 - this", - "query.target_y_rotation - 5.73", - "(math.cos(query.life_time * 103.2) * 2.865) + 2.865" - ] - } - } - }, - "use_item_progress": { - "loop": true, - "bones": { - "rightarm": { - "rotation": [ - "variable.use_item_startup_progress * -60.0 + variable.use_item_interval_progress * 11.25", - "variable.use_item_startup_progress * -22.5 + variable.use_item_interval_progress * 11.25", - "variable.use_item_startup_progress * -5.625 + variable.use_item_interval_progress * 11.25" - ] - } - } - }, - "zombie_attack_bare_hand": { - "loop": true, - "bones": { - "leftarm": { - "rotation": [ - "-90.0 - ((math.sin(variable.attack_time * 180.0) * 57.3) * 1.2 - (math.sin((1.0 - (1.0 - variable.attack_time) * (1.0 - variable.attack_time)) * 180.0) * 57.3) * 0.4) - (math.sin(query.life_time * 76.776372) * 2.865) - this", - "5.73 - ((math.sin(variable.attack_time * 180.0) * 57.3) * 0.6) - this", - "math.cos(query.life_time * 103.13244) * -2.865 - 2.865 - this" - ] - }, - "rightarm": { - "rotation": [ - "90.0 * (variable.is_brandishing_spear - 1.0) - ((math.sin(variable.attack_time * 180.0) * 57.3) * 1.2 - (math.sin((1.0 - (1.0 - variable.attack_time) * (1.0 - variable.attack_time)) * 180.0) * 57.3) * 0.4) + (math.sin(query.life_time * 76.776372) * 2.865) - this", - "(math.sin(variable.attack_time * 180.0) * 57.3) * 0.6 - 5.73 - this", - "math.cos(query.life_time * 103.13244) * 2.865 + 2.865 - this" - ] - } - } - }, - "swimming": { - "loop": true, - "bones": { - "body": { - "position": [ - 0, - "variable.swim_amount * -10.0 - this", - "variable.swim_amount * 9.0 - this" - ], - "rotation": [ - "variable.swim_amount * (90.0 + query.target_x_rotation)", - 0, - 0 - ] - }, - "leftarm": { - "rotation": [ - "math.lerp(this, -180.0, variable.swim_amount) - (variable.swim_amount * ((math.sin(variable.attack_time * 180.0) * 57.3) * 1.2 - (math.sin((1.0 - (1.0 - variable.attack_time) * (1.0 - variable.attack_time)) * 180.0) * 57.3) * 0.4)) - (variable.swim_amount * (math.sin(query.life_time * 76.776372) * 2.865)) - this", - "math.lerp(this, 14.325, variable.swim_amount) - this", - "math.lerp(this, 14.325, variable.swim_amount) - (variable.swim_amount * (math.cos(query.life_time * 103.13244) * 2.865 + 2.865)) - this" - ] - }, - "leftleg": { - "rotation": [ - "math.lerp(this, math.cos(query.life_time * 390.0 + 180.0) * 0.3, variable.swim_amount)", - 0, - 0 - ] - }, - "rightarm": { - "rotation": [ - "math.lerp(this, -180.0, variable.swim_amount) - (variable.swim_amount * ((math.sin(variable.attack_time * 180.0) * 57.3) * 1.2 - (math.sin((1.0 - (1.0 - variable.attack_time) * (1.0 - variable.attack_time)) * 180.0) * 57.3) * 0.4)) + (variable.swim_amount * (math.sin(query.life_time * 76.776372) * 2.865)) - this", - "math.lerp(this, 14.325, variable.swim_amount) - this", - "math.lerp(this, -14.325, variable.swim_amount) + (variable.swim_amount * (math.cos(query.life_time * 103.13244) * 2.865 + 2.865)) - this" - ] - }, - "rightleg": { - "rotation": [ - "math.lerp(this, math.cos(query.life_time * 390.0) * 0.3, variable.swim_amount)", - 0, - 0 - ] - } - } - } - }, - "animation_controllers": { - "humanoid_baby_big_head": { - "initial_state": "default", - "states": { - "baby": { - "animations": ["humanoid_big_head"], - "transitions": [{"default": "!query.is_baby"}] - }, - "default": {"transitions": [{"baby": "query.is_baby"}]} - } - }, - "look_at_target": { - "initial_state": "default", - "states": { - "default": { - "animations": ["look_at_target_default"], - "transitions": [ - {"gliding": "query.is_gliding"}, - {"swimming": "query.is_swimming"} - ] - }, - "gliding": { - "animations": ["look_at_target_gliding"], - "transitions": [ - {"swimming": "query.is_swimming"}, - {"default": "!query.is_gliding"} - ] - }, - "swimming": { - "animations": ["look_at_target_swimming"], - "transitions": [ - {"gliding": "query.is_gliding"}, - {"default": "!query.is_swimming"} - ] - } - } - }, - "move": { - "initial_state": "default", - "states": {"default": {"animations": ["move"]}} - }, - "riding": { - "initial_state": "default", - "states": { - "default": {"transitions": [{"riding": "query.is_riding"}]}, - "riding": { - "animations": ["riding.arms", "riding.legs"], - "transitions": [{"default": "!query.is_riding"}] - } - } - }, - "holding": { - "initial_state": "default", - "states": {"default": {"animations": ["holding"]}} - }, - "brandish_spear": { - "initial_state": "default", - "states": { - "brandish_spear": { - "animations": ["brandish_spear"], - "transitions": [{"default": "!variable.is_brandishing_spear"}] - }, - "default": { - "transitions": [{"brandish_spear": "variable.is_brandishing_spear"}] - } - } - }, - "charging": { - "initial_state": "default", - "states": { - "charging": { - "animations": ["charging"], - "transitions": [{"default": "!query.is_charging"}] - }, - "default": {"transitions": [{"charging": "query.is_charging"}]} - } - }, - "attack": { - "initial_state": "default", - "states": { - "attacking": { - "animations": ["attack.rotations"], - "transitions": [{"default": "variable.attack_time < 0.0"}] - }, - "default": { - "transitions": [{"attacking": "variable.attack_time >= 0.0"}] - } - } - }, - "sneaking": { - "initial_state": "default", - "states": { - "default": {"transitions": [{"sneaking": "query.is_sneaking"}]}, - "sneaking": { - "animations": ["sneaking"], - "transitions": [{"default": "!query.is_sneaking"}] - } - } - }, - "bob": { - "initial_state": "default", - "states": {"default": {"animations": ["bob"]}} - }, - "damage_nearby_mobs": { - "initial_state": "default", - "states": { - "damage_nearby_mobs": { - "animations": ["damage_nearby_mobs"], - "transitions": [{"default": "!variable.damage_nearby_mobs"}] - }, - "default": { - "transitions": [ - {"damage_nearby_mobs": "variable.damage_nearby_mobs"} - ] - } - } - }, - "bow_and_arrow": { - "initial_state": "default", - "states": { - "bow_and_arrow": { - "animations": ["bow_and_arrow"], - "transitions": [{"default": "!query.has_target"}] - }, - "default": {"transitions": [{"bow_and_arrow": "query.has_target"}]} - } - }, - "use_item_progress": { - "initial_state": "default", - "states": { - "default": { - "transitions": [ - { - "use_item_progress": "( variable.use_item_interval_progress > 0.0 ) || ( variable.use_item_startup_progress > 0.0 )" - } - ] - }, - "use_item_progress": { - "animations": ["use_item_progress"], - "transitions": [ - { - "default": "( variable.use_item_interval_progress <= 0.0 ) && ( variable.use_item_startup_progress <= 0.0 )" - } - ] - } - } - }, - "zombie_attack_bare_hand": { - "initial_state": "default", - "states": { - "default": { - "transitions": [{"is_bare_hand": "variable.is_holding_left != 1.0"}] - }, - "is_bare_hand": { - "animations": ["zombie_attack_bare_hand"], - "transitions": [{"default": "variable.is_holding_left == 1.0"}] - } - } - }, - "swimming": { - "initial_state": "default", - "states": { - "default": { - "transitions": [{"is_swimming": "variable.swim_amount > 0.0"}] - }, - "is_swimming": { - "animations": ["swimming"], - "transitions": [{"default": "variable.swim_amount <= 0.0"}] - } - } - } - }, - "render_controllers": ["controller.render.zombie"], - "enable_attachables": true - }, - "zombified_piglin": { - "identifier": "minecraft:zombie_pigman", - "min_engine_version": "1.8.0", - "materials": {"default": "zombie"}, - "textures": {"default": "textures/entity/piglin/zombified_piglin"}, - "geometry": { - "default": { - "bones": [ - { - "name": "body", - "pivot": [0, 24, 0], - "cubes": [ - {"origin": [-4, 12, -2], "size": [8, 12, 4], "uv": [16, 16]}, - { - "origin": [-4, 12, -2], - "size": [8, 12, 4], - "uv": [16, 32], - "inflate": 0.25 - } - ] - }, - { - "name": "head", - "parent": "body", - "pivot": [0, 24, 0], - "cubes": [ - { - "origin": [-5, 24, -4], - "size": [10, 8, 8], - "uv": [0, 0], - "inflate": -0.02 - }, - {"origin": [-2, 24, -5], "size": [4, 4, 1], "uv": [31, 1]}, - {"origin": [2, 24, -5], "size": [1, 2, 1], "uv": [2, 4]}, - {"origin": [-3, 24, -5], "size": [1, 2, 1], "uv": [2, 0]} - ], - "inflate": -0.02 - }, - { - "name": "leftear", - "parent": "head", - "pivot": [5, 30, 0], - "rotation": [0, 0, -30], - "cubes": [{"origin": [4, 25, -2], "size": [1, 5, 4], "uv": [51, 6]}] - }, - { - "name": "rightear", - "parent": "head", - "pivot": [-5, 30, 0], - "rotation": [0, 0, 30], - "cubes": [ - {"origin": [-5, 25, -2], "size": [1, 5, 4], "uv": [39, 6]} - ] - }, - {"name": "hat", "parent": "head", "pivot": [0, 24, 0]}, - { - "name": "rightarm", - "parent": "body", - "pivot": [-5, 22, 0], - "cubes": [ - {"origin": [-8, 12, -2], "size": [4, 12, 4], "uv": [40, 16]}, - { - "origin": [-8, 12, -2], - "size": [4, 12, 4], - "uv": [40, 32], - "inflate": 0.25 - } - ] - }, - {"name": "rightItem", "parent": "rightarm", "pivot": [-1, -45, -5]}, - { - "name": "leftarm", - "parent": "body", - "pivot": [5, 22, 0], - "cubes": [ - {"origin": [4, 12, -2], "size": [4, 12, 4], "uv": [32, 48]}, - { - "origin": [4, 12, -2], - "size": [4, 12, 4], - "uv": [48, 48], - "inflate": 0.25 - } - ] - }, - {"name": "leftItem", "parent": "leftArm", "pivot": [1, -45, -5]}, - { - "name": "rightleg", - "parent": "body", - "pivot": [-1.9, 12, 0], - "cubes": [ - {"origin": [-4, 0, -2], "size": [4, 12, 4], "uv": [0, 16]}, - { - "origin": [-4, 0, -2], - "size": [4, 12, 4], - "uv": [0, 32], - "inflate": 0.25 - } - ] - }, - { - "name": "leftleg", - "parent": "body", - "pivot": [1.9, 12, 0], - "cubes": [ - {"origin": [0, 0, -2], "size": [4, 12, 4], "uv": [16, 48]}, - { - "origin": [0, 0, -2], - "size": [4, 12, 4], - "uv": [0, 48], - "inflate": 0.25 - } - ] - } - ], - "visible_bounds_width": 2, - "visible_bounds_height": 2, - "visible_bounds_offset": [0, 1, 0], - "texturewidth": 64, - "textureheight": 64 - } - }, - "spawn_egg": {"texture": "spawn_egg", "texture_index": 13}, - "render_controllers": ["controller.render.zombie_pigman"], - "enable_attachables": true - } -} \ No newline at end of file diff --git a/renderer/viewer/three/entity/exportedModels.js b/renderer/viewer/three/entity/exportedModels.js deleted file mode 100644 index fde9391fa..000000000 --- a/renderer/viewer/three/entity/exportedModels.js +++ /dev/null @@ -1,38 +0,0 @@ -export { default as allay } from './models/allay.obj' -export { default as axolotl } from './models/axolotl.obj' -export { default as blaze } from './models/blaze.obj' -export { default as camel } from './models/camel.obj' -export { default as cat } from './models/cat.obj' -export { default as chicken } from './models/chicken.obj' -export { default as cod } from './models/cod.obj' -export { default as creeper } from './models/creeper.obj' -export { default as dolphin } from './models/dolphin.obj' -export { default as ender_dragon } from './models/ender_dragon.obj' -export { default as enderman } from './models/enderman.obj' -export { default as endermite } from './models/endermite.obj' -export { default as fox } from './models/fox.obj' -export { default as frog } from './models/frog.obj' -export { default as ghast } from './models/ghast.obj' -export { default as goat } from './models/goat.obj' -export { default as guardian } from './models/guardian.obj' -export { default as horse } from './models/horse.obj' -export { default as llama } from './models/llama.obj' -export { default as minecart } from './models/minecart.obj' -export { default as parrot } from './models/parrot.obj' -export { default as piglin } from './models/piglin.obj' -export { default as pillager } from './models/pillager.obj' -export { default as rabbit } from './models/rabbit.obj' -export { default as sheep } from './models/sheep.obj' -export { default as arrow } from './models/arrow.obj' -export { default as shulker } from './models/shulker.obj' -export { default as sniffer } from './models/sniffer.obj' -export { default as spider } from './models/spider.obj' -export { default as tadpole } from './models/tadpole.obj' -export { default as turtle } from './models/turtle.obj' -export { default as vex } from './models/vex.obj' -export { default as villager } from './models/villager.obj' -export { default as warden } from './models/warden.obj' -export { default as witch } from './models/witch.obj' -export { default as wolf } from './models/wolf.obj' -export { default as zombie_villager } from './models/zombie_villager.obj' -export { default as boat } from './models/boat.obj' diff --git a/renderer/viewer/three/entity/externalTextures.json b/renderer/viewer/three/entity/externalTextures.json deleted file mode 100644 index 82ad82a81..000000000 --- a/renderer/viewer/three/entity/externalTextures.json +++ /dev/null @@ -1 +0,0 @@ -{"allay":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAV1BMVEUAAAA4jNkuh9Ypg9FBnNpCm9r///+c/P+A/P9k+/9N8/hM6f9Q2f8+5eo94PdG0P821+4s1ewiz/8syf8ox/8bxPNNq+wQwf8os+hCnNpCm9oep9s0h8D7j8AOAAAABnRSTlMAoKCg3PODq/XXAAAA60lEQVR42tWP0W7DIAxFb9OtwdA6xQ3rzZL//84BD0nRljzsZdqxZCx8hLio3Lz4GwtYMWLDi4jnPM+vwogNKTTC43Elr6vgRMQ1wvM5ktsbvRPXN38wGxKHMmnI9M65vgxavwsg2WCpCvlSg6iqlCF4ceKbFEGZVC+5NFFXYUtxZzILl1xmiffoxUcA5DUHKULZp6iqsQzU6KNWYcxBUMnp8A2mwWxAhTPR0qRYFs6sDT+zTMZpWj5pO8L0wamexJ9xXvm10J27rrQ94dSdOqC0PSFXPV4JRuwRzIxGHMB38O14j4N9Wf4/vgDzpRGDwkNeQQAAAABJRU5ErkJggg==","axolotl":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAP1BMVEUAAACvsv+zsPmmqv+nn/+GkPXWhCt+iOyBb+d1b/9odutodOyTWuRbb+NlZfS0W0xsV+JpVuNNWc82QZ86AGw+Ir4cAAAAAXRSTlMAQObYZgAAAUdJREFUeNrtk9FugzAMRXG4twFS1jbl/791cbJUQnuAmE2VKk5cKpDukeNA9zeAhP4mwDlgahdAEoDm1dAukIzmlXaB/HBcUGbQJCBkBejgkMrt3j5WeYGD0iAglkXkehVZFlBQ2b0FkKjtE2CjIIYEUfIhESdMCUyWoyBFZPZI+Nks8OUs/f7kXSsLgCxwiRbBl9YRgddazcC5lhnc/T1VFdQObDMIwdJBRQQhYNWBTTCXYzR0AMZIyOy9c373FuQFGXLJLzYFEJQvQSHKgwKwJQAF1BWqIBC6hNlKbAg0GPXyjDHkeqoj6iVAn4DdP/NQhuHxsAr6HroAswB52QUcySTgeGQGg3J8lPY55h7Q9705XQdpEgwaHXVhtHZQX6Whew+X+mfldsn5W3fEYM9fVjfm/pXShd1g38UrdvuIGZycnJy8kW/CDQ5IMRlUUgAAAABJRU5ErkJggg==","blaze":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgBAMAAABQs2O3AAAAJ1BMVEUAAAD//////4T/+Ef/1Sj8shf8lgDReACrdQGLNAFsMQBfAgExDgs044iSAAAAAXRSTlMAQObYZgAAAPdJREFUeNrdzzFuAjEQheH3vNR4xtCkibyQA4CSCyAlfZocIjdKm4sFxAHwGKVmQo21Ts9X//IbE1evBfpBjG9ozXDlJZkKTkAr4IpShNVkMjiJ7wuUkwEJhcAmAzFGNcTJoFisJZph6heJiG7xDLT4XKRC4KiubvSf24kY6hiLnVPMVfE+NhPbo2Y3YVBfPA2/Q3PkchGGx++H4yZvd3GdNrjBr32FeDzPUdN88Mvn7QRHHiSX9SkMwnxYNTdkq7sDlMsLkZHRBEwBGaBpKnQ6GqsVegLIfrDOfOkGI0W7gQTN6JhJQlcYCOm+oJyjHyD+F7jg7v0B5TtIgi1mkx4AAAAASUVORK5CYII=","boat":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAABABAMAAAAg+GJMAAAAG1BMVEX///8AAADCbT+6YzetXTKgVjCZUCuPTCqIRyg96zNeAAAAAnRSTlMAAHaTzTgAAAPOSURBVHja7VTLbus2EBX6XOcPimGzL3jG7rbIzChdFjap3GUB65Fl0ZtY/oFr67NLqoljFVDkRXFXOZZnQI/nmOYcnqL4se/7U59xyGGy+qtI+OanHDdWvOLmEkXxnWp1DKZqj43mVB2jakiroH+8EfhZgu8t2BdVC/opWCbKq6hppfbbG8F2juApxqp9RRPDp+G0f112hyF9/9tfxr+wmiF4NvZE6VmNMdyfWoAB3oHRHs4ENrsDgzYChcYc4/3eHhq1YFWOXfr+D3/mrjueIdhHgVgVhMcYu2c1a/dRY473ZwKPGYLh6Df0MzndjvFxeFoDW1glOT4Q2n6/81TcydwOyqHvhqHfH3I6NN3jcBoSDmM6Oq2GUxAqUM5OQTjEIGBhtm28b7Sq2pgnGWJbslWJ/cnP6+C5jGKKlUXvaePrh7axJmjT1ow1r7ns0kZOvpAwt4PSOyFHxBpFtL6vYQIBx6oxq1zZJ4IvVGy2s2NkgEO0ynYcY7yvg2pVNe1zp0lh+RD7/u9EMDvGath3w6k7jOkxH2I/5AMc0/HcJavZMToLEI0rckSrx+GztcGsqncQcHfuWtmskG69c3TriDlaFbvPNUSwEw5V0/bnLtLZMSqiCrOM2wgP+1A2eYSat/G2A8YcgVngChaj5G3kyxSqJ2vbRrBrD+cux7O3cXKd4+/T69z4HZFLj3u5tGvXTwmKuEXGCv0rLn9COELBlfqXSxvlvwS0oYxbGl5xSbDsieS33hP8ypG/cyBP7C/qy54I2TFUsE5xJyrKpVzUlz0RWgsEWiprrQLWUi/qy57Y79Ohp6frcsro2ov6sidSAI8GagJhAURxUV/2RG1ijM/pXcUzLurLnlhgOyeDjGVPzDqYymBSd/owHM+eOKMDAmHlHYknELtJnfvDcIz6jici7FjApQlqQGUtk/qv2RFbfccTEWqooDRkGUxUkHGbCfYyeuK8DrqzDCYqyKC+Hw9x3hMpMNYKmIIFIuBJfdkTsw4eJjKY1Jc9sQBGJbykfoJUX/TEgjw2BHKgjSM/TJDqi55I3rmNzwyUkvPkSQj5gzvv6GbZEzH6ADgK1xCDCtISlhJUbpY9EVFWdVSwxUY4WgDXMQgHrsHxCk9sX+ygzcjpctneLCL7gVhAaRaE2QRQBpeM8TXfOPWDf6VwVsN5GRe6l3VwDYHztElvuJQchgmuIaCEDdFForu3dAUBtpIHBnAevKmkzAJAa6heRTB2ytgBE6juFGBBLSwzXf+zDsaBrwUQiAnALChFwIB+DR28X/4g+CD4ILgW/wAFIWww3uybGQAAAABJRU5ErkJggg==","camel":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAATlBMVEUAAAD8w2n1ul3prUrbnz3xi1ywmYjLkzfrdTmoilu4gieqg0Scf1DaZiyMcEV/b2OnTiFtX0h3XTNfUj5VSENfSCN/ORlJPzBRIQwvKBwTHWK4AAAAAXRSTlMAQObYZgAACApJREFUeNrtmItiqzYMho2kE7VeKbRJGX3/F110sQ0xlNC0y85Z/6aJLwJ92EYWhBC6U4iil5fjy0uYCppGPmEiRIyRtSBFkVVYC66maQCbs8JH+iuYDgngeDxuAwAwovQhInA0GpAazwAauBbgcAgGcBTNAUBOBLPrB0A+awrAaADMMwDYAkjmXQb4+wIAFQDDkgAQHKCWHnYNgGsdABpYBXgCYI58K0BUMRMicTRlAAQAXAbAx8dHfGLmpxUAaK4D4OwfkLkCwBpAqZ6ezgBPT1Iu/fsXoQOwAAAgOYH6yLeZFKQOJut8fX17ent9XQcAhD0ARAhYAAQH3t7ftfb+/gZClwHwTZgeXx8RpfxpgOcCQITqQ1YBJ4DJCCQAdIDz9aukgPjZNWBBJ68AI5DpiIEIVFEEKmEUFAyAKCswf8PyGsAtgBeLu+5fgG0VEHEQbwXA2QhFFNbUFBkANHMB6HVlgGMGkHa3YDIAZUKKMZIUzL+OwToAFE+N/+UmrQBOASTurgGgE5Ao+Qe7F8KaAJNrkTlzlLME3ucwE4QMgJCngIg5gBO4Y/sxrQMgpqtEQkLU7wwiVflUQ8h2E6iIWKRxAI1A/8mmAUQY1qReHbdIWmDWWgGwDjupSVQFVIfyXQq4FBdXMok9Nub+LPk2AA4I6ZILCC7dBSuZxB4b88zEImIDELcZIJWJkJAqgKVMYo+N+0ciGwsFmM5ALhLLnwJsbeQ7bAyAAIGYMgAnAiz+mVj11QDqH4EsCjrAljYziWJj3RyLagAktI8RMIUtbWQSRZHZt9lVAGZxTc+EhEZA2wBLmQQvAcy7DbkGiM9Hfubjc0S3C5uqMwmRpjIi9Hs7+AAROYAQ14P0fDw+H+XrYiAbFTBYQc/pIqLLTEIVfBNSC+JQ+tVadX2sUvcKAAbARUQXmYRfMjg0s1bNf14FeuD1sUq2J2iQUH8b4qnoMpMg8RIaE5OIA3m3E7AYXR+rfGdH39fTNfjv5UaOZxUAJhuB1A0GIEbboaIApG1U3bh/MoIagAjnI7AEQLQHAETEBCIFiHJmKyxlEgVANJkCQAMQo+tjlR+ZvHjcIbddzCTyIiRi4ckGnnCL0YeximcAlkawpRWN+08El5mENTqAj1SIeiw5tk3iZqwqAN7MYuMAZQSWMwmPAzGyAzAno+VoWcWq2RSgYzFj0/gApDNVmYSYCTSILZtN7k0cXAPMY5V8pgBGpABGkgGqTIItnRWB+YuBrBOdwGxmmscq8zGZAo4mRmjm/mOVSVhCb4rmTwDIbdhBLwDqWGWMDhCTHIBUalllEjOAyOs2M1WhQk1qgPouWM4kygjYFPDEhsxmH8D6CCxmEtMRiGs2M63HqnoNlEUgzcuZBJp0KtdsZlqPVfVd4P6dYDmTQJPBrtjMNI9VVSByaPYRyABmVCsDmMK2qlhVRULzawCRZkbogvwE0yBKgeQ3Nc9VAUxiVQ3gCbcGy2ozcgDKTzBi5G8TGqloq1mU73ChKlaJlwwAYHcOAfgUuOYAVN4IEBIgkdZUVACkWAOUWFUBgG2HbJsh1GtAz5sB0F9pIBFpbQ7gPVc/GdUJSfJfRiCfFwHBLpKJDZkQtZUEUcTWVwOsxyqwlIwtJQOOsQxAAdA29a5dFEk5jcHaDICjnfv6JyN7s4SMoIk5c0kIHIAFwNeQHipOSBxZFcVWARij7bY1wHqsUv+AhKAEpH3qRWTH6hVb3GPx7GKeNiMjl8fXfU9GnhVL0c5WQvEXyV+q6o8WSoMWbQq0XDq1Vo5LQv/dCeDnqAWz54LKJru/GcCvL6uUPVsldD+1XTm4AEDYI7DrnF0hpjKQrzzKLTgbIRsbx4MI+wHyO8lyJSAVL4p/JQD3KJ354ss7TDsuWh/uBGgAmTC/1wWgNOeAFE2EkNYEJTutMEKzC2BcADACBPRNldK6xwkApnuCiqH5NwABjwSwBTDUAHIK9sQIPLpaK6ImSfKFmJ9Bix0xa6t2ap8W9gHYhHuMRf2j6GsCiSPbh9DnPLqVZyZgrQAOJwUK6+pXXrJH4pxykzqBRgGSCHWWtS9bMkWwPduWMpMVkrP24eGh7YfhQwDf6/NG6/Eb9cxS1T9m5UTpy3Zi6f49qfWJrC67d79tGyrZLehZrCgngQAYI6f9V+v5CTbb6wSopO5coVb7IAr/ltqhFw1t+D7p/I6iUGsYx2GQr3A/Cdmt8on73DgO/RDuqr7t/1yAdq3WnSqAr/dSolldO5xuXgPbXsqOWtcOh677srtgWK2N7sTVjaXYnU5fEwfavu+G3gdRCl3ft63GnrYagTtEwjVqL/SC+uvXL8Gt274PSgfMh6w19Uttfy7AMPbmYRyG3jQstX3n9jOI9Ne11BZ+9KMf/eh30tj37XkLa/t+vBdAa7oXwJABhh+A/yVAOw69J3L9MPbjXGFRnrkmm9t0dpnTmHFsLxKNsKgzrxCb5a0AYXKGuzzq3x+gHwpL/wPwA/AD8F+OA22/0fW7ArTTveCjzait6KquT6mf7oYfbUb9sLGMvjsfuD/AuNH13QDDuNF1f4D7Pxd0J1F3pycjf4vbHQ4b8aKqjEPvMzDus9zWNoCfd7C3bTst9wMMVWWv5e37Xl3ZtvxjAA790FWn3WN5O8DYySry17ujlK0STKk+mqUbjl/22qAbxlM57eTNbnKQ62JZUL3/9kDUnfur8LnD8vZANI5V/L7J0r12G4XqtFXFtd/Sx32j8N0Ap9N24R/eOq3aGiGdPwAAAABJRU5ErkJggg==","cat":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAMAAACVQ462AAAATlBMVEXv9O3r8Oj72bPW1sz71Wf2ymD1yF7ywFnxv1jvt1Pqq0uvdh57bWJjSy9KMBc6Kh0RDxgAAADq6urOzs6vr7C+c3NanRJWU18kJDEcGCdfq47cAAAAEnRSTlMAAAAAAAAAAAAAAAAAAAAAAACVcz0/AAABUUlEQVR42t3T3VrCMAyA4Yi1SmtlSxSS+79Rkz6R0dEywTO/0rPyPst+IFhiMSJyAW+amJBFA08EEWBeBQtQ/1BKuRuY5yAusACo4ABSBUpFxbsCPkJKDgiLgAktANYYOFhyDlxQgFCFbUA6VaGg9lsAj3LExmBCi1i8MdDNBWJ5GBDmFmBhFuE7ANQWgInVY+q8B8wh58w8gy2rBxASIRJ2gVwBOOf3oAFQ6wL1kP0QeQU0AhRdIb5eAe+15V1vAWqB/X4E2PgrADtA3O/XgJ3WTSDeCJi8zcc4eAo+QroBsC7hC4AMOAspxGQNAUZdTDwAtkdAQrTdALQAMYX4FkIYA1VwoNZ+CynqCLeuIOSkAYyAqRZjFyDNAe8FytIOLuoCNv3hkLPtkP3k8xNc1RthZ6YiPwAMmmoAHUC028DGCKevkwg8DnxafwDmO/uHwDebkIAap1EwrQAAAABJRU5ErkJggg==","chicken":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgBAMAAABQs2O3AAAALVBMVEUAAAD////i4uL85XDT09PhzGLGxsbgu2nTrlrQqT/Bk0OWcjRjVkH/AAAAAADtfCsnAAAAAXRSTlMAQObYZgAAAO9JREFUeNrtzMFJxFAQxvFZrGAewaMwwxQg2IA7fMzZElQecxZswHZc7CAd2MM72IlJVoXEbATP+7998OMj2kmHW6LXQ9/T0AUt25UuB/D+dgQ317+AXLZ7OgxN4vmJ5vGxforGXhbgSj9ElFqjrxYXomN+GriqmqG1H3E3B7DmQN0A0Wpk0laqKlw2gKv9AdycbRNE1dgA1SOy0hTWQCIrgqaUlnGBqkLY4aeAq0FYfT/OFRBQVGERWQddAKh7ZuFVUCwqorow8166jgVzoBaZWV2FRZS5iM2BYwKwBzEfjJSYg/zOIx7hDk86948+AcUmS5dD8ZFCAAAAAElFTkSuQmCC","cod":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAAJFBMVEX///8AAADr2sPWxa3KtJXCqIW2lmusiVmScVqEZVEiHyYAAAB2QJV6AAAAAnRSTlMAAHaTzTgAAACbSURBVHja7coxCsJAEIXh5w18RSRiZQT7sAS8Rgyz2kbYIN5CiDBbx8CewHM6QS3sLf1hivl4yMc626+ZCgKQzENVF6eSsaCVkRCRfCiZhFYwcM4t+13SqFdOwS6/Vw+5HA3qFyz7beOqriX9ezFsKmlcySn4lFKMMQiJGYWwR9VQyTnGmggh3M7eeyGBQ0u4TwZkR/C7P/weVk/OOkCzBdD8ogAAAABJRU5ErkJggg==","creeper":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAYAAACinX6EAAAK2klEQVR42tWZ61NU5/3And+L3zTNdDpT08Q0NiamOtFG8cJlQa4uy22vsCzLLrssgtw0KooIMcaqFFFRXOSiQjA11lwIVRF1QRBW7gIuy9H1pLgpM9SZ/hmf7j4zzXT6Jn1jkTPzzNlzec6e7+f53s+yn9piOzdzwltJp3SdNrmZW1IHKc5E+ufvUDJhJndYR4/UTa5Pw8ePrWQ1mrjp/5qhhT76JRfLlvoWcXYzceei+EMAws7v06n070R9LpXxF0NktKSjuR1L7/wtSr3ZHBgsYNDfi8Gp5Za3gw7/1aUPIHkwjLSxKAytGg5KBZT1FOD3+/nkWTH75uwMzQ0w9sJNXk86X/nbyT5lpuqvhWSPJnFL/mrpAyh6bMI+osPUmEnetA7bPS0j824OeXdS6DbR4+ui23MDSZKYm5sT+3JvPoYuJU2e00sfQHrfdpTd4bh9A0LVi3stQsiqsV3sdtnF7wOTeZQ/ykeWZbzyY/IeGnDUOrgndy59AHG1CmxuHa1yPabmDF68eEHB5wVitXd2Z9Ev9XJkdhelXTYBQ1+nE5B2XilgcL536QPoePInrnmvsOz6MrT3NUzNj2NxWshx5uBodmB2ZmHo2c7M/BTGJgPWhmwRKfZM5nBwomDpAzD0a9gxYhQAXr/6Os8XvhcAhuUB0j/X4BjWUThnxNRjRD0Ry26fhYzzBg75Cyh/UPjqA1DPxKC/r6Td24RjVI+lJ42cOgtFY1nYh/Rcf/wFy7/9JZruBNrH24Wa1/gP8tn0XrTONEpnzOwbzaPl6VkB6Xe33iWpbjslwxby+4w898/hGDSwtzdPRI978i0+9lnZNW1FU5+2+ICyHqSgP6PjrHSUlBYV2t446qQTJN2PEgnQusa1ATAWElzh7H1UiKYhhTK/ncJ+k4Cx566D5AYl9z33gwDEuC13cGikhPl/PMfRZse90EvpkF1cW92+msrJQgrdWVzw1LL4Kt6ow+fz0em/ykXpnMj24k/GEn8+AMBTTvJoOKsy30KRvZlG+SzmS1m8q1sRPBYrWnilUHj/q1NX2dS1id989zY51VbMrZlIPi+H/1rMoYDArmnXj4CyhtScnq1h73j+4gOonCrih4UfMHuTyXmqpsN/DZd8gxb5LK2yE81UjBA4cCvFMyaSb0eK329FvUGVpzioDQJE/qwRi5TG9/5nYv7oC7fQkE/9JVQMltAr32PFzTf4xdev0/aojdimGJTuMP6vbdnPFhWAozsDkcpOWcXqKFyh2CU16uloqqUjnJZOUOgy0yTXs1L/Br/VvMmw5CblrIpcr4bM7kQhaPXf9lPeJ7RBCH3YU0qLVMdl2UnR7WwkeZY94zmUDxaKOsLQoqPoSebia0DecDoXZScJDbECwPKOX5E3qSX+dhjX59r4s9RK+kWdUPnA7WKsMq2gWDYxKPWxe9gmkh/9ZQ2Vo6UiTzgwvYMDDwuCgor0WFevERlj0YgZe4udPc9zMM4oGZOHFh9AbJOCK1Ije6d2EXVRQeaFDOJubqXaW0mDp0ZUdcVXi4Tg/z4c/QbSL2nRtKcKDbjmacXozMDeamP/QD4LCwtMShMMzw1gv2wjsS6Bsgc7xPlPPKWYXSkBGDYWXwMmdUEBRIJz1ddMu9yMsS+RG95vSGlMEit94m9lwuYbpT8Gzwsz2FYfQcmMGePkdjq912iW64MOVAh9yF3K7LwHq9PKvhk7H89YSW8w0Om/hnu+lz0PczFeNlA1Xfzq5QkZl/W0+xqEEzwmVfG+6h10Bi3bdfEoDKH8ZPXYmIA07xUFkk/2sacvlztyJ9f9X9Ar3eVLbyvai6lBkxCmUDCQyRVvCxVPCnCM6BYfSDAiqM7Fc9RTToOnmhXhb/KB4X00VdtZqfk1PzU/GDojzmyiyXdK+ABbgw31hWTOeY6z85kRw8x2kTdc9jYQcS6MzR3riHVFcdxXRlpf7OIDyD2Zy+GZErJGE0U4eztlOaEV61hr+oBVmrf5qfnbasJIm1BgH1YzK3kplIzYn6gxNOsolI0YHii5LrdRIBkJda1HRJ7eUHIGNDxaGFl8ADMLjyj63sTO/mBr6yve177DyqS3eCN0Oe9pVvxXGmCYiiPTpcITeNa+GRtlQ/kk1Megn44ht19H91xHAHAqb327nJQBFbWzxznmKRcR438ucLCo2ekxYvWoaXhaJ1bkva53yK4145YG+HjQjqYrhpOeCmESyV0Rwjeo7ilI7FaIVpnyYSiq4fDgPSJ9zn6YSlqtikfSGFGHN+NwGfjUWymumbtTRNTR9SuxdxuELyiczRDzj3krhSPdULWWNRnvCT/00gEE/1T7OJbtfwnn/PRJRNX3zWtY2yzMyjNknTeyz72DW/6vWd3+Hkc8VWgbU4WPiOvcjOF4CiFHP+DDPatIP5HGGtNqdrgzyGjS81R+QpgplKQj0XQG5oef28oV2RmYnyaSqdIHVlE3FDxLF6F395kS1ls/JGT/GrRNqQLuSwegcaZSMGIUL7Kx6SNCLm3gnq+LHZKBfRO5jM8PiZfXt2tYdWOlKIxCT29AUb+VyMBQnNmMyqUQqx92KoSPLOuprDuIZTKZ5PEoATTqQhgfFa0XYfCy9zza5lRMLUZszTnoz2pxPDBQefIgIZaPSL+kF5mpfUaDeiLm5QMom3Dw2Q+7eDo/i31Wzac/lOJocbB/No+Do0V4pRmsj1Ip8ZsIrRMtcsJPhwiBoxtCUT0MReOJFoVT5piSbF8qCls4m459yLbbm1D3JbHy9pusav0NIbYNNEunSGxMEN2irM+NZE4mElUTgq3GROa0EtOTJIQZ3n0b2+D/ICzW/r2C8gGRw1Mynv2vUPfjfmruEbl9OvIHM0W1eFE+i84TTfL9SCIDKq19vA3lnQihrmXj+aJrvKM+jy2V61HsD/mxAoy5t4XMaj364ymEVq8npGINH5jfZeOxNWwIqHxNYH6mW0VKb7S4/2df/D9bKta/fACHRoqxNdkEgP8QXuwDQxRE6XeVYvWD3wlSxxSo7oRR7SkXDdOw2hDhwAwXdFhdapHsZLgTOSkd5bWm1/j5n36OqnubmK9siEM7GUuyK1oci/mnN4lnJThjSOmKxdFsI6T2Q2Euy171LbIhTAgfcIoilT4tHSHmeAQR9VuFUOrxSKJrtlBRVyaupbQkkv/AyA3pujCbmEZFsM8gntEr3+XIuU+IyozC2mrmxvy3rz6AkKO/I++4GdWJSNLOxPJZ9RFR5YkGi+xENxVN0QML+2p2EXl0I6b7SSKcJl5IQDsdzw6fnrGFIYzjCcIciqrz6Jr/jpvSN8Fy/NUHYO7WCJtd17saU18SJdUFRBzfgPlJkugFnJKOkuPS0OG9TuSRjYSUrWVPTQlrzKtRnNhA6IH1VJ05yMZAKN1YsVZohmNCg8GTENSqVx/Altu/FwA2XQph273NQq1//+lq1u17H6fvlHBusefFt0VsPTp0dRoRYYyTcaJeUN0JF98RExpjUN6NEB2prEklCbe2cmwpAPjll78QAPJHLWxoWidyg8SuSMrO7KLs5G76JBc5ly3onGrS7kYJh2rxpKC8E0Z8QxTGVl0QlACnu6BG2RxP/M2tXJMuBfsRS6CtPhZNm+wU9noyMAKrJjrK33ivEGLdyOHnxRQ8y0DfrAmGUfElKfNuUgBUGFkziZgmVQzIvaIBUx+A853vS5J6FOI40Rn30gH8ExZbYyyH/1DEAAAAAElFTkSuQmCC","dolphin":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAP1BMVEX///+wwc2In7V8gp1ZV3NXVHBIRWP////D0uO/0Nu9y92wxNmwwc2lutCmuc2dssmSo7qKmrGAhqJrcY4ICR+8V/49AAAAB3RSTlMAAAAAAAAAVWTqWAAAAc1JREFUeNrt1GGPokAMxvFRz9sd2+kz5fb7f9ZrmYECnuDmkn3FL0oaSf8RJaT7iB6Pz8/Hg3J3u91+mzRCITtVIJwNS3JcUzMHSlkErtfr3fQAPQxB8uhVYPAA5xHf3fQNSguU6eSLwJ9hHXBpROTXR5S7F4GcLTBd5ioQP9BuwJF4gWU/wAt2tumBpnQRINoEhGUORIHeDggE0gJlWgLKPHUvLkEEqLUCIhZAVQXsaCoAP2q38yMG1Y8vdcOg7utD9VsBFgNf9zfEcO7eCuTMvdG3bb0X+K3AL3sDzGmlFNpVZskB22xxR9sRENkGUAqA4rDWPoqPk+OngIaKWdVnaVAVo2pDBKotGl+KQhurUa1zQAQjMRHICywCE3/vSrq2h0+/8KnDvC5s95m5D6ntR4BZLpfL+BgRv7WEKKY0Y03d3UWALZ5GlLMAkjPFdBQgskCOQKbl4ThQiEoEQHlEiGkRwItA3OsKalsa07cCg+/51hBTBGQvIIJxTWHUJ0Bk/V8AEXsKpD3M8Ux1ywCI8F5AwJD/CAhUtBUkFYeNMvlXQABVf3kCHgBq1YVagQgcid2N6tIxEWGXZ+ykScdie4En6XQ6nU6n00/7C3s4RNq7Xn9vAAAAAElFTkSuQmCC","ender_dragon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAMAAABrrFhUAAAAdVBMVEUAAADgefqKioqFhYV9fX17e3t2dnZ0dHRwcHBpaWliYmJdXV3MAPpXV1dNTU1LS0tHR0eWALwjIyMiIiIhISEgICAcHBwbGxsaGhoYGBgXFxcWFhYREREQEBAPDw8ODg4NDQ0MDAwLCwsKCgoJCQkICAgDAwM0IucAAAAAAXRSTlMAQObYZgAAEQRJREFUeNrtXYt22ygTdm13JSVxnKa/XQsS+1/U7fs/4goj9AkNFyFF9lqHOWcOFwFWycx8DAzqStHb2/5N5Rjn3Mfh9uH+GAc0rG+YRvZ92+/3zQCMH49HyadjnWfgaz2zt1dt6j4MZcknlT82KVP9rykI46g+jKlx9JhH/WzQBOBdkdYcmoDX11eVK0v5spp52S+72/v6oV71USmIjiPbkL4+ouOU5fC++7e3RqQ5/3U6nTQz3i+T9u0zVz/an3OZmkTac0b7DiDefYfhfZ+f3/bNAJhzLXxG2dPe7Mdc9eAViI7DWL8/GzQB5B0G9f3+/e0VAxiC2Ct72qMt6ddpU5aSf/9Tp9YXhxKRvkMnAL+FvFf493me/yXTmk3B47xftrRHW+7oB3aKIhX4vnINRQH8FvKevvvn3fPzfves0rc96wsi65Y5c7fnui0sP2Xmtt4hJRqKAuTd/X1fX9+enl53T69Pu9c6/xpCAdKetoUAU4YozoUCx0gUkIK8e3veve32V6EOoQBpT9oSAQ5bcqAAVSgw6RsYh3PaN0yc+VFgqNV1oYP/d8F8LAqopRQQB78bohgUAPHSKrTIe/rTcaajgEIZyquhRFAgYMUNy08t8GBLjvZQqDCCjPRHfMT8gmhZw6OtzQIPteSkPeMsqq8UeL3+N/0T7WMcdbvAWroVvkZ4ugLuWMNTxHD5AmEUgBKRvnGW/0RQaRCahASItrcKrdMX8K7hz5+y3fmslAh5WR/qSy1/D5WQJ1ZzGjtQgEWigHz++SnbfZ6hRDIv67197ejDnPm+1WyEBRZTCxKHEnTL2sqr8iAUQL13Aj4+ZJuPMwRY5mV9AEF8/git91hfziPKsPbUgY32BajAc24ohacv8UGQD/sFjBGr7y8zj68AjvcFjn2B56yvFGEE4SyQp+OUPUsbLJe+8iRfAAIPhYJSDEOQkuYpQlELCuZmmYXLHGV3u/Ca3BB4KNsgFHCgD3chFDU+YBbaEXK297YLr+cNgdfLGCgF42wYCtjzzMj7JqAcXSY+RBwKGAIPxPk4y/TjQ+aHoIADlcoACritN6fP3eVwvW+JRVFgOFutvQuhIlCAWnn6PJSnKKLGNPf9+8se9RwCDAe3aav3/Hvv7LT8zIVEAatOygQVSF/aDsx99UABn3JBsPFbkXnfTgyPKMPaU0sbjQ4WX4AHlAt9I/O+nRgWUYa1j/AFOEMf3jkEO/z8+fPw+fmzTj/PMv9TtjMPyGQf9Ee9f/1PEcG3E1OS8jH0fJgvgDZ2Pry/vx8+Pt7r9OMs8+94FmSMH3wfigJEwMaiAicWeIgv8CUnwp73CfsC/jV8EBWmngswhrbmya4qrwaQC4kGnRGUx5CVD6BCOe1cwIoy4NizAIJEwR0hzkO+QBgVgALxvgDHb3KO8azto30BO1qFUCBq7U9QINYX4F1rzsjvk/ZhXyCICBEoAKvqKyNfxvsC2FWSqf8cItoXsL93wBfg5FzAW55yOgwU0P1Jv0koQPNhX4BY+cCOUSQKcCsKYIlDfn8CCnDkZ/cFqNUdfC5Q6rYqlTwWBfA+9N2G7gixoC/gbR+upyig26oU449BgbBvQscM7viwAAqwqBghigIYkyEfiwK+9T9Fq8Bp8CTfgCJCwKqT8caiAP1dZz7mNDiqDOaDT4cZ6TcuLkhxB0lUvlUAKJr/XGC8L0DahX2BMApFRIdGMEEB/9o/phyut59GXwUUB3NN3oYa1v6aL79fvtX08vuCfmELGtr3D5V9J7OE+dTTaEv/E9fvggmIiAnCDg22HM2yFmpSPsWcDmPMSez1Ay6/f9Qz8PLj9wXt4mJq4tlhgX2Rosdmza9OpOXuT9O33g1SYzZl/RtqPFX2IsDl95+Xmv5ABeYnxuN8AXraXPNB5g8HxsOn097fryfgz48ff/5ABeanoC8QRBFZdzgef177hHwRf4ySnABJUIH5KTJSFKEYunz89vKtrCfgndeZkxGfZEMd724QJuB2KhARKQp0gDLU7b69vHxjdVmmsmwokM83wO8DBRTdUgVid4QCvkew7PMDMAE3VIHoc4H6Gay7HVXa/KBIVTjTnQkorZeCZqDoSFEWPC0m7QMogDU+IypALgVNp6mRojTmqM9xkarGCbNHBfb7t/08KFCOOh3WbenSCu08t9ZAxpbqpaXSci9iBhXwRIp6bpOZVp6zv1++XenlbziwQAke9iVaZcIEoJ1xNXQGIrsuodghRnyD/7cTwGzPwyjQKgEmgFmvhs5BFmsfE95wFdx2AkrynJQH+jI3RYH4GCFttS0ogOcnLtsj5UphRvLMKECtvbt+KlPnupeXKcrN786IAlxbc2LZ4QCjfvLveeKDfM9mQ4FYYfwK1OEaLbhCCSgVFFKVgSi7nQMFIFzL5vwvoIBzLQ22L2/6yxXkewrQllEPNhQETBSIXN6x+wLYByQoIC1/w9/z799l2jKx4kGO3P8fOW58jBEmQCpCixby2X632z0rllc9ZaoYiIAdnTDHWfsZxrX7AtgINU+A9b1oxfv6wr9MFQMRYFXjOLzzM8O4dl8AG6GGsrb3op92kl+fnpA3EIFHCGZ05Od4Hnz3mGMj1NiR0uv/mq9Cv9upVNZJJhsakRze+WFjxou/e8yxD0iiQeX6/8r6wr/MNzx5AsL7/5PGDZ8u0wnovkvkXeHx7LLWI1Eg/u5xdxeIRZwqT0WB8K0xNse4nHkmgESDRuzoRHH86XA8D480xQQQFIg/HY7nQIxQNMdHmmICjLV/5I5OPIdjhOZBF88E4Ddxihymuaz1SHSJjzS9tIQ+ZXkrFOCc+erH8/BIU0wA+vDZUSAcEToZXRz1ngnAVyJiUOD+vsD0GCPKYRS4my8wHV3GsedwcwYUwFp+RnRB3FIvL1OUm34zTABQ4Ia+AE6PZblU7ciuFNqGUYHx/6gv4KgfqwSeff15doQmjutEgTn29WGxSaiCbzuzbdf202M0ZYwJwcT4qMNYxju0bQ3hn2Vf/5F4tRQq8jy/Jbtf5F4TkGVZsV5nRbZeb400U7yuy0hlXf1cporrtiiD67p2PFlux1y5KF/dh/Jiu91sY7koxvZzv8j5cp8J2Gw3m2gucvSLYvffObvTBChhjeZsbD+3Ll7uMwNFAQGN4KLYjuvnfhFxPt8PBa4CmteMNM9VCguuhF/mNyhL1v2R5i33FCf3TsDlTihwIw6gQHW5qRLkRVHckakqbPLL+ZYykOcFEVZVhjDX9aYAq7LuhzpDYVR7jKvHqp/pvpuCqsI6u07AzeyAWsJgKRPF6De2P1WFbSEuUgluJQOFtuajUCAvSP+paLDNxVnJwG2EQAuzSuMY/fLR/ekEZGoCbmUJCr1WHyHA8Bmy0f2pESwqqQAt3wAF1JoeKeWu0KKueV6nqp9uo/2DXh2UBfVWFKjU3x88Nwrk92MrCmACuiyyOR1lup8/th1o3CfVgQImVxCWeYhzXGr3neaq57gY4z3kwyV6FUXqaU1RwGRR5Le4bIVQ57HtQKwTJh0Ik6AoQBVgK2aERZxKt1ue4XYq9YZ6tFu07jAJLwqAi21ezWsMGfb/h/y/A1y3DyoV2loVxo8CUIBNLmaeAOz/D/lqNGNBoeb4PwY8n2DxokCrDFmRiZn9A4Ro+4XVvEXmRQFczm8mIBYFKq0AVaEUYzUjDd3v56fP0+nMuEoDKMBlO8QnxaKAAALM5yTHfyHi83j6lNZdpj4UkG0YMz7CG4kCmIB1pvJzWf/eF+RUeiy59W7wx/H0IZ+pNLy0AkeiQNVRgKK65me2/jTlnLY/n36dT1ynY/+HmQEo0KY56mb74gSzp5zR9ufj8fPEdEqe98Mh8OFeogwBFKhaBUDdbF+c6N8Ndlr5o/yHf5yOOqWC3wusM1AAS6IwClTnJs23SgHmUQJ8PxQRpShTK3+6Wn/5TKVkPBKSwTinF2+4BwVyZQTFWaVy61DnZxABXHbvpviiHJkAZf2POiXjkfBqxjgNtmMeFMhEdwKqrFaAJi95FhSAcJKUTICy/keVuifACPMgwXoe9NAWX7QK0HOQ57hrDOG0pNzgX8r6OwPkIPhUGRBs50WBQnSWwUIqgMzPJQP4fqghpCgz8zulR2X9G8FGvSqbH/6iyqDrvCjQnYAq0+UOz+cDQEibMvmwbvn+fn5//zi805giy9VNxCupZ1AwDwps8wp+gCi2hWjy4Bm+OGFYf5SpgB8On4fD+X+H2WKLtptcSPTXCmDdIfpSFIDAQrBRXt2atutMQAGyNSxAl79wAmCpCRrAgb0hba7LnkohQNEoxIXwl/oCuE9A0eD2E4BlDxTAwnPtBDFmpqtb03otJ4AoAOUZfAFYf6SrGxJQwKUAMxyaEetPfIFbEVBAI0C+zYXKO/gLUQDWH+X7oYBWAHJGMIMlcPkAGh3uggJOBai+XhFg9a07QvdCgSrPN9oxBtvl4ct8AaAByndCAYUAPQWoxHkGRMA9gM7llxLpXVDAqgAV8hae6X7CfVBAK0AXAUSFvJUXcFcAKFBk6x4CIO/iL70rsJYp4v91GQFx9rsCTRtLH5nirkAIBVRMTgHhh0Ps5i++K1D062Q8EOoQF4Tn6Icx0Eazjg51nhGokGMshwSEf7YVwT3ignBoxlkPBZQCZLAAs04ABPm2XGK5VfZRYFszwiQG8mj9b4QbAq7TDRXg4vq8fdYKOSJF0V6PSxRL/fu4Wm5Rf2Obb4AA4NmMoD/mX+fRRrMZAm0wqeu1y+VvKuFXitBDASBADE9BgHswCZ6bSMXqYWiWJdclXz0AwQHXwo/8NMf7XGWrhyGOHaiym5/y97+IB1IB1u44cY78pO3Xy1k8hgpgG7YRfuQnbL+qSNLVw1DZuXyP/PjtVxVH9Ego0J4/MI78r5EqoDdLHh4Fjmyk8Csu1quHoc7/VgNFsKFAXvgPwbq+QL5dPQx1LT/jyNvcdGHf+dN14HyzegwCCjQHcMjTlhkOxgIssgdSgXYJBEVwBM5Vg53iqnggFYAjjAs69kM4kefYCveyKB5DBXAY16IA8rSlvCk2cAIeDQUQko38ilJVbYYpQfVQKMAh/MhbD+EuQ5VAPBQKsDYWyVgOWScASrAsFEDgnPejXLgsQ4X+cVEAjjAzlkP2pa5UAuvf/IFRABGprJt3TEC2tiqBiECBx90R6t4Y84ZKVA/qC4R2hJSji8C5LlcPjgLUKXZMwEXYY4Wqx0OB+A/v6ltjuDQDFgQFFkjN39oaMSoeDgUm7PhcQxKEdwLWqyVS5+6wvjgDrggKLI4MK69DJlBHUGBxZH5CZZ1lFVUCoMACqbfU2RZm4Fy1eBQw/975dtPzC8TSUYDs+vRukImFo0DfAaaxQ9WyUYB8Skd9+lB0jd+iUcCy9ZnJIDohMAGLRgG6CySaL74JKMGCUcD2PSlRIIiuKwP5ElHAuv9fNZ8nr4SxHMq2C1QB6xmAqAoVrVlV3fpiszwVcG2BV81HaSvRrdssRgXCEyD0h3AF6rL18lTAfRBWVSqcGbtEoi6vFkbecyDRfM1ZwE9YhAqEJwBwqC6piKa8PBSA1ZepfUmEXaJqcShgGD0hnEuiTS6qhaEAJiAwCXpJVIgFooB9CVSZdZW+pFJVS0MBt/UX5pKouZAiFoYCDutP7w8LfNt/USjgjweqKlGRJdECUMCvANQoYkmk0GABKhAxAdRBXgIKhBXA6yCvFkDYCYxhoRzkVaJEiRIlSpQoUaJEiRIlSpQoUaJEiRIlSpQoUaJEiRIlSpQoUaJEiRIlSpQoUaJEiRIlSpQoUaJEiRIlSpQo0X+M/gVoPrkgKWtroAAAAABJRU5ErkJggg==","enderman":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAYAAACinX6EAAAABGdBTUEAALGPC/xhBQAAAY5JREFUaN7lWNESgzAI8yv8/z/tXjZPHSShYitb73rXedo1AQJ0WchY17WhudQZ7TS18Qb5AXtY/yUBO8tXIaCRqRNwXlcgwDJgmAALfBUP8AjYEdHnAZUIAGdvPy+CnobJIVw9DVIPEABawuEyyvYx1sMIMP8fAbUO7ukBImZmCCEP2AhglnRip8vio7MIxYEsaVkdeYNjYfbN/BBA1twP9AxpB0qlMwj48gBP5Ji1rXc8nfBImk6A5+KqShNwdTwgKy0xYRzdS4yoY651W8EDRwGVJEDVITGtjiEAaEBq3o4SwGqRVAKsdVYIsAzDCACV6VwCFMBCpqLvgudzQ6CnjL5afmeX4pdE0LIQuYCBzZbQfT4rC6COUQGn9B3MQ28pSIxDSDdNrKdQSZJ7lDurMeZm6iEjKVENh8cQgBowBFK5gEHhsO3xFA/oKXp6vg8RoHaD2QRkiaDnAYcZAcB+E6GTRVAhQCVJyVImKOUiBLW3KL4jzU2POHp64RIQ/ADO6D6Ry1gl9tlN1Xm+AK8s2jHadDijAAAAAElFTkSuQmCC","endermite":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAYAAACinX6EAAADR0lEQVRo3u2Y61ITQRCF5wGsEhESCrkloiEhITctQG4xiQQRuRuIKPrH93+Etr8OHQOloPyQbJKu6prNzu5mz+nuMz0bwpWtL+7LVqkl69lzWU5tS3IiJ9NjL+TZ0+cyF89I6LJ66di8+qoZ5mLpkIhnuqfD6KO4+e/stvse1OqFc9EXk1rpSCAD4G1Pysx46hoBq4Vv5mvZZpifzBuYvyXgtvseDHi9qF44k7N4yXwzeyicf1dsaTY0ZDW9K5WlExvVw1buOOg1YS2zF/TeUM03yaDwdun0Gvju47vuezDTP5dq/pMBfZP+YOPyy4bsvv5u55mnJJhTANKzQO5rRBaQ5fmqFBKbUkxWZGXhvUW/VmgaaH5TFmTGXFfd3kzz21K/501T3qKoGWCCSCbUVBNUtKwcOKeiJRNPZiU+MmOORiS6BDKSBADcvHjeIcEBVwqnspE9MgIgBLCTowkjITYyLVNj8zIbW2D+j7Xf80bd4lrvDv6fMyCSte/WKH0xEfMRcXPA1Hwlf3JnBiCKCOLG4kHnOZExIs8L+0gpAN6WR40+vQHgOefNEeBjj6esR/AMWEvvGQn+nChlgC53TfGRqOOoP/2BAlMCdkTB6crwWbZLF7Y6+HWsIlzLvGZA5zlRygB7YR8BbYAU+Eb2wIBxjHMe8FzD0klvwDzHdo0e+3MiQwAR5YV99PpfvVr7iaodZz7K/soP6w+cAL8G4LaXUIL8OZEigKj62O78diy9yQCAA5RmiPTmOgjgHPNEnBaZ+5wAnhMlAtidtZc7dYRONynmCjIoAUEjHzTyJpAInp3XJRPRY2QViKwRsc3cUafOKQGEDWdOI29LG0RBAOA18qb27AsgJNIEmKJfEcCIOwnUsjY7oa+NKLt6m+Jn2moPAZBDc0Oa9zMBmtotaZS/At7qmpRWAsgOAx+pxuY+GWDKXbwwEm7u7yHCxY7a7zv7BbxljupbVuimiBECEDxteoyIvrOd8qUBZROk67+pPEABTjZo+9sBjx70tfnX3tRUOSQnsmHgbCV/aV9t+Vw9M54aPAL4Xk8GaDfYG5+s/1MjZILHqE2Q7ev53Ra/Zuj7PgDxAyhC6B80BqoPGNrQhja0Qbaf/P4PM3XaxMkAAAAASUVORK5CYII=","fox":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAgBAMAAACm+uYvAAAAJ1BMVEWAgIAAAAD59PTn2dPVtp/nj0G0j4PifCHMaSCwUSKOPyRWPzQGBA4kh8LGAAAAAnRSTlMAAHaTzTgAAAGUSURBVHjahdAxb9NAFAfw8wRIDLkFEsSCG4kMHVAzwAiV5W9gXUdA1omugPWOEdpwzxthaP2qLhnrD9ClHaKuvQ/Vv2OnrZuhf1myrJ/+vvdO6YcZ8p/4jdZqoKLB87AchKCQqA9X2+F1HJa3sNuCUv/3ZfRV/q3hMP4E0A8DSABN46knV1prUYm4FJGK/d4KyJgyTfP74FZQZOZvkiSfG2AA86xYwyHg4x0U9AgUtAlDZiYibvN7Mknyb5PJeKxGVQelIPM4RjVG1Ahl7CF41XU9j8e3IG77bfb9yssJYKHXAWCf5kctoIwnArySra3pdLqzI3UD7RwK0f0cTD/cAS7rwL5TK0D5HjzJfmK7TYhedoBPDCsiHfgf4b0LQWvnOE9S9n5WuAaSXazVgO/AFRn1piIuARUTGQNQEtTg2ekyAghAmAz1wXXgjSGAVFwPWU4WOPyXTeyx95R1cAaQhSZyNrWeiIoWShkB5gDObcpEM9qEfAXG9MC50ua2whlmD3ARzu2Ly+vzL5pZjuy+MPvC3QC9wfXEFSoo+QAAAABJRU5ErkJggg==","frog":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAAQlBMVEUAAAD9trb/ioq+rWqxnl+mkE9/oFjlXl5zlktjkC6NdEVWgCLMPj5NgDBGaypJax46Whk3VBkxRhRGKiktJi0uHRCwcSzMAAAAAXRSTlMAQObYZgAAAadJREFUeNrFleFShDAMhBEoZ1x1Qz3f/1VtQm9qgVoZf7h0pqWXr2k2M8eQJMBwSSJSvStpow0sUmdgCHMIbEQTIgCo5CMkzNM0zaEBgPf7x0SNUfUBhHmeQwOoiq4zTPOUhk32BF+VomvAlDAPT1jY+LRxXrQlqA638G3lHkKQxFL0i501vxzus2WIyunjfidUYwb8uClU98mr7CyRFGwrh4ecUwABj61Iwlt15zcwSeHjAGgS379fILxTk+I2mt0gCRmyXpNs5qeJZ4BQKQW43ToABITgEgAU4DaOt58Bwp/fAxChlAzj0zj2gOcKGK8Brh6wyBmw6bv9SCMpAybfy408ZPB4UlUpAp/pBAEbBTiqZO7V4Nm1NESU/BFYdsDSBaQCpAvIDpAWUOwnSBDwSSTt2foUICT7SqVPjx3qaeOUsHBTjOoiAdrr0BCEGK5Ilg7wtwwgrEj3ZKXscnM9AFRCBO5JZE0IGc/+xbIpCV53v8eVjQ9K3qdgV1zro8hrtuIKkC3Cr53dPFIqcxG9EjaPTIPb1DGpVmlEaUNHa924dfgHfQFwmyc0LyT5NwAAAABJRU5ErkJggg==","ghast":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgBAMAAABQs2O3AAAAIVBMVEUAAAD////5+fnw8PDl5OTk4uLd2trYzMydmZlzc3NLSkr5ldknAAAAAXRSTlMAQObYZgAAAYdJREFUeNp9ksGN2zAQRdmDO5iBfN95JlWAgeRuAkLOZuRNzgrcQYLdBoJVOoirjCmRYDYy8i//wIc/n+Q4J7gs6YgdJxFRBBNXVQENRE8yZZG187sKkEIGLi/z/HL5D/Blvt3mH+8Ay044ZgBeb3e90QDVCkz94QFgpbGugOmvDPy2vxNYgMPnDFCAloCoLgDXqf9wfJBgKwAfU/+M8S9AGQH9MXzDSskGYJQRgcMEurkmDSCxfSiABtCeegsssuJbQETFTKS6q6r/v/FOl/1wXSrRtQOESDh1F6aeZG12mKBvC6N9Bq6nBtA8xApM5vCJRxpXAAdgEfg6f/80/wS8wggrMCwjbCl33T09Zw+6dqolB5/Yw45p9xRAORMiaB2hQLTRlLSWHNTXBHICwD6Jv0Qg3E3CGTDWLffOJ7B9NFkTRP1ZYbTRkyCaUxiS6TCyaBhNwwgoOQGcMsp+RBRe38CE4axrhxhKAlYqALmEEqIpRA9D+SwTikQpt1n93R5IcTOKi/wBKsTOnkkgxrkAAAAASUVORK5CYII=","goat":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABABAMAAABYR2ztAAAAMFBMVEUAAAD////6+vrw7+zq597b1cLArJCenp6ciHaDg4OFcmF0c3NXV1dNTU1APj40MzImjJ+xAAAAAXRSTlMAQObYZgAAA5JJREFUeNqNk71u7EQUx0eb9YqKZ4jOeFPchjAze4s0rObDQrcy9ngU3QKixDNaueAFaChIFFHQR4IGci2078ADoER5g0g8ANqKHs7YeONsyIqf5HP88fP5j3dt8r+ZAAOokPxVQaDgvc/J9Q8bgsQ24oCnlFehfVWYUMrAuT0CMAZVE8JpCFer8O1HfRtFCKVUFdbeVRVuZ7O+jSfQOGEdqkrHKwm2XQHAhRYFaYzOk76Nn0Kg0GCEBW2O8lnfxk8hMCK0rjJSSrNM+razBtc0vtAppOnhpG9PQlJFmjbYAiTY5bRvO4IL+BS1qWqXJ33bFVzjv7z//f5h88fHfXsREXxOxuwKIbhd4YDSyiDaDpQUAXb4TNAaBdxiQQGQ4+H5U7CZ1kbXeL0rRQqAznZCFDDC1tZWOpbzFCPE0wQKtdHZ5/H277pSUEjnczYIBxSsMVGwUbBRoGNhmrLaZeZdVdf2g4mlECk9eiuXg7Dg/tQZ8+Gytu+rWC4WgtIL9SRIu3KZD5d1cFkshRGpkmqISLLitlmFq6v2arXKYvk5M9qWehBmzrbfN6v21za2WG5xSbW3+fN3nkrgez9Myrgkw9DQ/c3h681WONCCA+wRJlQoyvcJAJwPE3zmry79zIbTlcuHCEbVdpE2tb62iTSZM8ttBJdCkZ4UZG3lRKZHRh+OItgQYebSGj0t7Fzb5RAhmIRBcM464xPvTf20BsqVGtbw5/2P95vN8NoPEamiQP4TCsAAIMUe97oXmo/d7rQCzijITq2QYiSkwAAFilWim9LT6+vrchwRBd7BUKAvBQZM/itIBhyi8CyCoUGV4lwA7okXE1IZ71NKCRFn6fnuBCrRUFpbISSTUnUTKoA363Uv8KKUkluFApOqKBcVMhbUpCykKpVdCCnL4sAQJKF8K9hJXZbleSEW87K059OcRIQ+GYR8mkxre14sjua2TqakF7R+txVwYELK6fz4GDseJwhRNApbEjIlx8tlMhwlREIU9sDYyX4B2Jsd4eGGjPnk79eF7v1N/+oaQnpuvrm5ITPnvD9be8Uov+DATXMLKem5++nujiSZ83W+/oqDMJVm9LP3t1yMJySLrC5z/wUHjjD6aeX5gvQ8/vb4SMjbk18u4mdhBLLQzjmddZ9dTvBTuCekyZOWtHi+MsY4pLWOEGqEJJuHzYaQszyZkbZFpaNt16EhhLuFIhuEoDF78ZP9A0Obf2KBegjhAAAAAElFTkSuQmCC","guardian":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAhFBMVEX///+rjEZQjnQtWUcAAADX1c/Y1cvX1czX1MzX08vW083X08rW08vX0snW0snV0crAuq7Auq3Auaq+ua3dkET/gi+DpZy5k2Syk0/wdyjecipqlYPsZCqFhmBmiYDLZSNdf3XeSSh4dVCmXCxOeWbUQSDKPBxBcVpkW1BgVko5ZVJ5CxKoxgN0AAAABXRSTlMAAAAAAMJrBrEAAAOASURBVHjapZaJcttIDAW5lvfIHtnLYiLDee4kzwsL+///F45I66AkW467akSoIHRhhjOkuq5bLper4fL/wHAhiscBItiMIYSgm+j76GOga1xdXXWD4PNy2epHQ9q1HrAz0+mneCswfeB+K/i8Wi6HsZoEA4vFojtP4E1vO8GmvvWw5QUBEd4TrFabBj53F9LbEfZOcLt8WN2ubi8WTEu7J1g9DPUPt5cLPBM83N3e3g2C6+tu4PqYmaCPxk5w99/9XRsvCaLR9+G0Y8ID3f3916/DuO8azwmMgTA4WuQWp7uvEy8KYFObOQpsR4K7S4kJ7Izod1MYaSvwetoivk2wWAyCGR4PUNmZbawHnOWLBTQeqxgZj3PBWQEHbhPRD2TfrlNuOqCmPQs2I6M/I0hCAleAgtwKNrmeMhIux1lBLwklknpy1l0rbfXinMD0SEDTxDwXLlVt2tubwrrbY02fNZFxlEMoKpB2gsfDHz2G/fev735+/6/NcU6yC0lxVtDbv7z78aff39s6EiRylRFxdgoB//z25x/v/kKa5ygD0T778/tAYMCS5rmKsoTKz9wFYRc4kee3OBU0byJtBZr9SFkViAqsnG8yQGpDz0whWqmi0DynPU4eJmy6xUDLffz06UueP+xnBMkueXPz4UvW9ws+thZEveaBkmV2325ubj59gXqFgPV6r4OhhQ9DD4cCIZ0XPK7Xj/MO8lDgFwWzNcjZDBC6cArddBcOkcyld6Htgx+6GXq+g2z6Z8HivEDPCSyxGchInN3K50A22Iim8ZNAESnFgKTjg5URaEyiAZA4mEK4CtPcCs97rngqEukcW5gJsgzGZTEThBKaYaynEjutQ0FRxs4T5z8kmbGF5nJVumYCtdo28NFDVEjpafZ22lQWsw5Mtmo4fg8IcE6fzjKm8EwALrBPvQckV1S5QrgYMDYHAoHBzjqeQogKRVRIY49ZTjQT2K288NEiQiE1C5AeV6o83wdNXRiYC4KUhFNIZELl0SLKgKn2oflG0saaaMCYsdOZYCQlceo9gJTQrttvB4JdOAVItCcTgl0sYIqRnuKUOBJk2i1pp/fi9BS3a/va4nK6uxqReqHFq7naCix5X3B9kiNB9yToUzJvEVi8SSBDvlXwpjVAAl19h6BX3wNm2ng4/SqB3MCVU5T1OgGokfb0/LVpczpVfuqPyjdt8tQvCjuwWwAAAABJRU5ErkJggg==","horse":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAh1BMVEUAAAD///+lpaWGhoareS2nbh92dnZxcXGPaR1jY2OKVS6AXCJyVBp2SShRUVFvQh9hOh1FPC9ZMxc2NDdOLBM2MCZTJQ5OIgsrKi1JHwkqJR0/Gwg6GAUhHiEfHBcuEwQpDwMjEQcmDQEiDgMbDQUcCAAZBgAPBwMNBgMQAgAIAAABAQEAAAAaegGbAAAAAXRSTlMAQObYZgAABHpJREFUeNqllouaojgQhTOzuurYitKsNCS7pR1lF2fe//n21CUBvMznN3MISYVQP5VKEN0LKitT6Z6rKovNZlMUm6KsnCtgVlVRpbFduYMw8qIKq0zlDkAgd+WrgNKqDNiIilcBmwXXi6rAPARQKOD1CCqroNVWAd++IYJfBVQ7+IOwq55M+PmF1WKLUlRlWRRlWRUPAbufXNiutihlIRE8m8KiwjLxQqHCWVaLtJgFlr6sxqtfoYstURQvRQBgwcAxgB/GusvY8wvVo8HX9Tog+IASRTfbetp9Dqjr3wL4+nCofYxEU8BisX3anQLgf/CRoOjqEELycCuzcvex6voARKQQKGImaPJWUmPoPpb41xQgIplJ3jvuJQXOQTAAKcCErTdspPtljMT5R+w1/CPbZB03SPfv47cRLl9+IHYR1T++AKEdDO7/Ev2TWqci6G8U7XiJAM6ASASeuKOA5Xw2my/b1I4AHyjaCd5z1BFCg04g7WCwnWoCiNEAsnJZ3LPufgh9ZCbA+8fH+yQRCB1Rj7Wftfv5DKHP25Hpa68FHnzYLmDdAdoW5etXhD4yzZGLVAZgZFAAP2e5tAiW6z//WC/bkalugpDWpnA6Se7uALP523qmUzDT3P10CieIRi/yev325vZwBA2lHZleUiA1ceN42U7fz+fvJ1kPKAN0/RFPOzLFjbimyC0DTud/z+f/zifyQnCm9qE83EicI/lIEQA6nUUAgKAAn0VpfxiY/YiiFhwOPichIAuyMl4BbB/QC1GVART1iAQBENAogOS9NACccaCPYQtBAeFGznSAyBLQNPIDpYBAcQLYrlar7Ttqad+3E0CMY4AiAKABcDwenQn29YrmBgAnTgNcFZEB4RlA36JHABQFxEcR9N3n8fjZ9RNAfpsBgIQShEB3EbA/E6QT4x0gzyFQAlxVvZYLnAG5TACQ8Q2AIhEIub/KgdKhvly6z8/ucuFbWYEoeC/mQWQNACFCaDq4dz28u65Hm3IgN3ueqnxf1c8A0wjgBoB4d5DlIEWARFoEYwQ6CMAAcNPH94zIOZBlgz8RI2ALoc4QW0YMX3sGcLniHHIAwS2IP9zNURGyjBkAP10CnNMcjJJoADFqi0AUCF62kHzc5MBLEjUJFoFUDEhz0EejdGxMc+DtwyxmbRGg4CAK9tGSh+dqkgOLIJg3BAMCwFNMe/k60ZCDNIc8AwPAm68TO0O3gCEH+isfIEFoIoM0zKXhbcTbi9OanIMUAE2SCJjNLAPIwdFOFOSg7zkHtvJp8sZLyyjmeEwb7/PX0Y23b9PoLmzYsMVoGrXQGgMyf4/Dwc67rpGmwc2ocBm12kIffic9hEpax3Zjg3Kr5L6BakHZ7jSKAOEScGraXEAl4UkcHDp8feOZYIZctBswPV0ye/0AgDSGPMXGs4TTsKFJys8PqvRXLAihEQQqGPII8UTRAGVA86H+pAcMRyR7WEOGPGTQZECNDcsgsYJVLnLrs9hBx1hqycUkHrUvqxgONt9iUv+p7ocjlD66/wNdcSNfhkmkngAAAABJRU5ErkJggg==","llama":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAABACAMAAADlCI9NAAAAVFBMVEUAAAD868b14rjx3K/v2anr057jypXMqX7EonmlpaW6mnOvkW2liWaGhoareS2nbh92dnaiayOPaR2AXCJyVBpjUT1FPC9BOy82MCYzKSMqJR0fHBcP+iOkAAAAAXRSTlMAQObYZgAAA3lJREFUeNrtV0t22zAMJDAg+0ulxm7URr3/PYsPmUiMXja0vPJYJMbyAiOAGjynN7ACCmVkPO0AButlC1ueRnEkgBydAHBA45afIICJ8bEG/htvdhHRcI4APIGU7wVAauUB4wJiUX6OgAIymjaACLNLEBjPxJRZTjkDh4Ag5EHEuCUvym8pgOgTAZFWdw3Gc4EU3LQCpPhEQJbs2TXGpxTbbyygKNIhcom8UpRVbiwNQxS0AytEuvaqMs+YlWz4jQQwMdEL8wuRUgaaAIFyhkjN27ILwgvcjIhsx5AAZiL+8kWDUiiqAHddAL0AAM2TiWvVBgXw9x9PTz++814Ac61H2SFMUAFiplq2dAaYTctRC/RCawCFbQ1B4oFaopwC4OZ9uwJ49+HpowWg0QqAHCgVKdCsf18CEYn7cWbIdx61QQf3AhQQRc67FrgEA9roHK0AVXQCwIAAbj8NSt2R2xvC8R6eI6COYOwFZEEMZmlngGm0BYi3Gf0hjFZDcu58KH7xJhA5GRmCBLCjFpRqTGK3cHgEAGZhrkYA8Fjx+etXIl1MtaDOkgCsS7JsBcRcZF+ul2ngDEROejUBrxTgGuMQKnojMgAMRdWMsRYwRSt1cSy/m9gSSVbsBCjEhHH1oiEfgCVn9h3vb3bMl3oCvABdE9pAYpACAxUAwTP7jhbIQvJBAM3fIfttqS4wZkQIv4+AoI0nWP2lHEDCDaoCDAgQ1ONskQXuL4ibSRD171sQXYCA6ykEBgRYqpAB1tWiHD/U8tfxr8U0imimeNoMiImp3+VtIG3cebnM0zRf1hbTKCQjQ0R0N6Iri4SoQwFrhzSKLJLjgywwgqzL4wcBy3vplf65SRcsP8xbxFjRLS7lBwKmdZknLf28bmgaQv2H4SEr8Ri8pN6ZlnXV69u31eNyky54Ul1xOQ1eckm9M9ljX66/fl4vq9Hn5+d5uAKezD7FVv1W99Q7k2Wd5t/XaV6DXqZpVEDpbCZvQuqdabHE02xZGx0X8AlS70xLvP/zrPGdpvPQO9N6hFMF9M50bxw4033RO9PRMDoVvTMdDaNT0TvT0TA6Fb0zbSbQcpcu9M7kE8hH0LqhZwrosJlAm7mU7od47FmH0Bpz6eev6+XuAqbpMmt0ev2t9J4CZheg17qh6X6ICTSHDzR6TwHrIdIDDzzwwAMPjOA/NfpDB1xAY2EAAAAASUVORK5CYII=","minecart":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAMAAACVQ462AAAAM1BMVEUAAADBxMW2ubqvsrOprq+epKaUl5iMkJKFiYt1g4ludXlsdHhham5SVVZNUVI/QkMaGx04QmSDAAAAAXRSTlMAQObYZgAAATFJREFUeNrtk9FuwyAMRVMa7jWzwf3/rx3QLmsiOlpV2lOPk+BYypFRzLIs53A6hXA617sSzsurEABTSkRPsLxGAIEYI0ACiCAC4tqp5fbARGApJavRsLoggLHGyrWvmAoOIPSWtiamgmw7MgIhcQuAM0G+U+TcBERcY+wNgJwJPO9wBAq3Blo+E+wM7ghSIRqkVGaCPV3w9RsTQUVAMRMC+MlkUHusISVfLlkoW8ZRbRmTRFXNTG9YZ1wdCoTqXsy8dNysuJtQ7Z6JoBTV0rlmrk3gB0zHW2gCU7XS6ZlrugrKxp+Ccuyg3ATljscC0eLtM/d+aX+tVfOy46GAQwGfFsiwA5HnBRwK+O4W/k/w/m+U4SDJ84MkMhxlmY7y8TCVGy8fpsR+WnXDGuPq8mHIN8fuL8tkDiT4AAAAAElFTkSuQmCC","parrot":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAP1BMVEUAAAD/////7nn/6j3/5TPGxsa7u7vZra23t7ewsLCoqKienp6ZmZmWlpaRkZGQkJD3cwmGhoYlJSUPDw8AAAD7udxiAAAAAXRSTlMAQObYZgAAANJJREFUeNrN0tEKwjAMBdDGxpnbZqtx/v+32jYMN9QKPnkhYdBDk0EDHSIQ0CGBDkEV/pFgahtgBhxEZu7nSGj1Ajg6SAmpVQe4M98hgHCMVUAgqklbObgyXwGhXczUWlXg10Z+bj/4i3X19gra1KJrDfVGakcARdFyqyEHS353w35J2oGiBRO8++miqrU2MJdZIN6pJy+Lz3Cgs04yeaees6qeByMypZQo548jLDdl9mnE8D18B+EyBiG4+AGMduBwCi2/g+BiAAJ/BTwEW/4XPABsMA1LwNN2rAAAAABJRU5ErkJggg==","piglin":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAWlBMVEUAAAD/gID/////7aj/5bX12iryuobMzIPCwnTooHTVlXreihzJgmWHh1e6ZkWtVTKiWTplXEOhPjiESzOXQyKNNQ1rOSR6JiF2Kw08OS5TKxpgIwo6GgwhHhyEOBusAAAAAnRSTlMABHH+CSEAAAKgSURBVHja7ZZxU9swDMXDWAMSRspwYiDQ7/81pyd5Vzzf3Oz4t78GRU2kF9m5Hm8y7h8sMM34zMQrcKZj3BvTRHMVoHVVJwRm41n1eSDwYFSB2QW0AoG4psY0JgRAK5BeiV7TWCD2wLt7AXkhehE1Du1BL6CPKT0quL4HgMgFxIBAy6xt3hICsYniHBRIzET+6Ij1jxg3/NUyXxEwiK0wiITZBJC3And3d10uzCzKjOkNOzGrX6wKJoUVpiTJQ5MbVseyqpX9SEQWmHUV+4obhI8LQCd5aHJDBALCRLIaQuRfWSRhBK51M7bKQ5MbqwpLjAyB5Kmw6AoFToZAgNCE0OQQMIXEGHkFtU3UUsUU9XX6DnlocgNNql4HvEuRAzWO/Kx342xMFXbibWwb81TJOS+oOyQg9reK8mafqbLkJR8UEFEW3nRjzDBV8nJwAgGs1qoY5DKB0QrEukrJZc9BcXz7S6AiolspC8AMIJeLQME9xC9JJppL3FmKen/J1moPsOhFzfi4gXNZvMuKdiL0xmPLVjBaHTBiK1DQH8lealfyB1mIsbEqIABcBETQKjiDYsRi84I0WwYp6yeilFgSp/iFBgJVSMchBeTsR82RVgFiCIAJgMRkihBn/w0XI9ZS+/GxtK1LXyaQVnkHn3acLDhlh6TIkQms6s05/Tw9vQUfJzs+3v45Aa4mXCTCCnh3nj73T0wQOY6oQyT080WAqcKO70H2F9tsQq3zpzdLOJ/P7+/nX+84I8SqvT//2QKEv+umGzdu3ABH/cLAFxwVGPuC4xMs353AGAmM/ELvC8b0fqHzBUN6v9D7gjG9X+h8wZjeL3S+YEzvFzpfMKb3C91/5TG9XxD5zgTy3xP0fqHzBWN6v9D5gjG9X7jmC34DNs5yRa6KJBYAAAAASUVORK5CYII=","pillager":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAflBMVEWnra0CAgIAAAD////Hzs6Trq2VoKCVnJyVm5uTmZmQlpaOk5OLkZGKkJCIjo6EiYlmh4VzeXlwdXVobm5nbm5SWFhQVlYyZjx2QypfNiEmR0daLzg5Ojk5OTlPKxlLJi0fNjYqKikeKio+Hg8lJSU2GB4yFwkeHRwjEBQUFBN24XvqAAAAA3RSTlMAAAD6dsTeAAACP0lEQVR42u2VYZOaMBCG1TOCDUYQemeqRDEq8v//YN9laQYckaAzbT/ckyPEmXsfdhlnnUwbwlBKGS7CBjmZfn6m6WQ6G2DiBHUegrTmFUHIpGeQSorT9fcEixANvCt4rwVm4V5ig7/AvQRJ+AuQQPOSgjjwzYHPw4Im267AnaW3wIXbdxINC9zDZUPbADwEHMnztZTrPOc467wEa+SJc54vl3l+bgqADPgJJHf78SXl1wd/oDgb1sMCeg4yifqxXC5Vwk93DAsSMoBE/QQqkZxPEvrDNSxIWJGyIOW4Y1gwG+BfCS4Nt4YXBJso2ngLTsBe7bUlQB6GMQLkrYfAvwJq4Z0KYEDeR3C6QzOGBEb/wQCtRwjMZbVabQ7G5Qk/weFCa3fYIb874Nxa/YLj0QkuN1r49/0eEZxbq1dw/AWDp8C/haLwbMGa7XarjTa2UwGWXwXNW7a6Zqu7EQ8BPfoKDDSEfcJDAYWtIQlTMBVvXR4KIDaoHApotLmWTFWUZVGVXXoEhquHgS4nAF6C2Qi+Bd8CYi60ibIoe1mAvAmy4C2BzWB4XSCszdDDaAGHxVzE2jCxGC2IYyHimAcOBPFoAWY34MFJuxMU+5pyPhei5PPDCcRD9niiHaP34AQlJg+oRFGIqgA9A6Q9XGlrC0oSxKCi/FiBfcJdC27R5gQ49662gN8VV0ibE7jCUOWzH5KiNrgOuwJXEZ7aJ7jd4QT3pfa1oJTKAqWCDPcsU9noL5IKAhUFUaRqAvX/TKTfnHu1gRak8lQAAAAASUVORK5CYII=","rabbit":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgBAMAAABQs2O3AAAAMFBMVEUAAAD02ezy2Ovx1unxzue0pZSkjXOUgWKUfWKLdVp7aUpqWUFjVENhU0NZTDtSSDkNYhzDAAAAAXRSTlMAQObYZgAAAYBJREFUeNp10L1uE0EUxfERBdhQ0PAivAFPgUJHFT5ewC7TBJ8LBW4i3TM0VEgz09B6ptiOV+ARkjJt5GJyNbubtZLdv7zro52fJWtdq5aqENe3prV37vl2v959dK2SCsERQBrYwtoNwOdAP4AVrAsDZ7iUAWSG6B/AZtsAvsgl6VqBjGkEL84/NcAPvBoBlSnFfmL37z/Exxi/xj8x9kBVUsptBsX1DRjtCIAbUkjqSptZYflSyikA0HVdm8dM0pdaK87x7WwC9qTNZ+/ckH7G1Xv7RVCIj+3emXrzdgT0geJczaH9JcKnarlHGSDhoynOg2PJQYUqPpVuDtRjUVGIip3PAedrf7kVLtz0NYXarkUAEBBgGQgVBBeBMlKC+kUQfLQPEyGK3WYLi3RT2adDyr7kYAAbWD6dgpJKLnYr2UBfKqegDh0jx2JH96TVz9tpzLX+MYJf8+Bl+juNuV7FEeQFcPg9jbleH/YDuNvPA3s+jcd9L+1FqEiqVlZMZ/eZmCL8uK8JdAAAAABJRU5ErkJggg==","sheep":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAMAAACVQ462AAAAM1BMVEX////w+fz49vUAAAD////49vXs7Oze3t7S0tL/uLjmlJTAnoa3lHuviGtXRjoICAgAAABdC2QvAAAABHRSTlMAAAAAs5NmmgAAAhFJREFUeNqdkgFy2zAMBOMqONC+hdv/v7YRqCSMPO0kvpFEUhKWwBEv29Rl5MgcUo7U5dDLf7Qdep9cFNJINeEpQCoyx8id8BxgSJHaAXoOIMWRQ16+oUfAyNSMH08BRg5lu/jDDC6HUhEjMzWGfgQYmRE5QhkairGv1PVo/GoFNrKjsLG3bX/7AZA0rjcL25R8u3YpzZgAsANbwvEI2H/lhn6/2q9/xI02oouZAFsIBTZRnAHz90psqKzUrrYz3wEdCzZlcwJ0sVIm12v1Yq73awKEsNMCYThnoOP863ar2Qf79mN/vpvIYWBgsk6Af+tyQaCQcTFnDso29vcAKDG2yxZ0KCaDFTBad7hvb/MVICTseZloK3ohFg+0jcwGDOmUQSJCJjFB0DxhFsCmdq4z0DkDu2MKBcZWBUQQWkvYs8j7m8bYthWAbRVk2SSeHRGmlhKUYx567piHDKiykacHiTAWZmnlJnS8RmoFkBK2FdgUvYjp62Jib69j+ArQh22JwGkC265PQG/erT8fK+AwHkOY6JEG+hPgclFlCoxZASZQKKd5CMsWRCwmGibDprBXgA0gCQKZBgWBlwzALkw15wxIEhMVMtjOjo71FIr5CSj8FYCxQVHYCQSAzdrKmIIy9aaTB02WfZwfIthhImLxwEf9xT48tDImpveRBFAErCUUZeZNA76lD8B9VdX9p4C/n54rtHuYBiAAAAAASUVORK5CYII=","shulker":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAzFBMVEWOYI4AAAD////m8K3h6KjT1ZrHw426tnmzr3GsqGujdqOjdKOjcqOec56ecp6ecZ6ecJ6ebp6ebZ6Xa5eXapeXaZeXZ5eXZpeXZZePZ4+PZo+PZY+PZI+OZI6PY4+OY46OYY6OYI6MYYyMYIyMXoyJYImHYYeJX4mHYIeHX4eHXoeHXIeHW4d/XH+BWoF/W3+BWYF/Wn9/WX9/WH9/V39/Vn93V3d3VXd3VHd3Und3UHdwUHBwT3BwTnBuT25wTHBuTG5uS25uSm4AAADM1DMFAAAAAnRSTlMAAHaTzTgAAASDSURBVHja5ZN/e5s2EMdpk2Xrthg8dKfYuMVet4U7sTr86CRskuL2/b+nnUiN/Xh7nhT2574guNOdPjoJEby6ULFYlEWSbGtp5Sr5ayM6xnr7QsFlR9I4JtswuYbZunITBOc5LwMWlhGZpOUKjK1HAwpCpTWAQq2U4v1oQM3gpQBiRMzay/iLgJUlRAWAKBi2xWjA0rGK1R2AFga5ajSgYI34fAMCP44H0B0opTQqQEQevweJywCw3wJUxpWjAe8aAwBKAfR7UE/YAwC8Q+URCBOWUFKMKlaACCJqzw+SmJtv+Iy50szSSEPWlKMBya5h43ZM1nJmXTEaYIu6bauybevicV9V7Yu/c7EMk+JduCyW0bJIwmybhCtvl8l8IbGsTEKxZ6tiEa2KJJK45C3mSz9uu5xlwdKxJUeWHTnecbtyxpkdu9yxv/ZLlzXkjDXea8w+OeY6FovaYE6NQdMwsDOKXBlJBMUG6t/lTOiaLSuWnMyVoXEEvS9viQeJ7Q8/+AuQWqkIUWkQyYPalTWAIF3gZSSegyiOAaVTKiiNQp+qfBa7emsQlEIEgdyxqwqGGJWSBNCKmqrIUAN6Oorv6iBxJI4IY60cp0njfQ+RHsebd45RpMUFbWm9sKRVjH4IgvhBRE5s6YoRFdsqMo1CD9DyMk01zy0o6NNjJFuGPl8jgC+LXOUrSDdp2jdQ1EoF6dr78lTQ70mart9u0rdpisD7lSXx5ZIbNbfB1sBwOEK/5uzkz8X/kzE9+rfUFIWBwZ/5Cu6dSQeAy9f3jk6+zHYvbQBak0r+egA43gRzY0/E3FUh2VMCuTLkZohHZMsod+sBmLsy+N09nBJ+/dDeu4chIfztw/7efThN8P7h031zlv/+YR9441Kbr/L2oTscum64uxf/xkt1xCLKmTNmw58nALr80PX6fOj4MAXAncmNlxgvL2Fz4XZ5ZwTiJSR+Gg/gjg7S2AjniSdUIOP6S9afT1qCr5sOxhdiDjQNcJDLc7ibAqDOPLEcJpnfs0YDpOp+C5npMKkCX7c/SE9yC2LCUc46zpmIc8PUTQHQ8U96kuckALHpb5GhlwGXv3Mnkqll+v7570d5dhtGURRGx85ZeBvezue3Rz+chdE8nIdDfC7ZMmQAhICgENNhACoFZ/6tUggAp3iM+hgPnhMkrPTwBSONWqtzICAinIAQK1QDwBMV4NkMMwRBxCfAnfZTDBP8on3B6hmwXcoKNUAMAD8nW1Mns9DPqATy07L4Y5tE8xkoP0D9uCqzIpHFgxaiBolnQWIpZkdgHGtyvF5YFtsAO5ZG6dLbO4O0Y2QrccnLXQ7kqI8HBTfsZIQ8M0u23LKTniZrSHrJlaWxfUTiufRVEheW5R1Jy3ZlsEyrtkzL9mNayPvjp9W6eqylr07rtko/7pO0fpT4XmJttSnbZVpLbvlYie/7vh6k6+urq+vrm5s3b25uXo3SEXAl+i+Aq17/V4Df/3Ndf9W3A64uNBbw/T/0Q68RS/B6/eXq6svrZ/u7XiMBNzd+CycDjhs5BfA3y7f3PUOzujsAAAAASUVORK5CYII=","sniffer":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMAAAADACAMAAABlApw1AAAAe1BMVEUAAAD83VH6yTfyuCrpsSvopSHfnzHejyfUjifRgR/GeRxFnYrDchU4jXspiGCqVAilVAEsc02SQQBXUDOTMR1xQQIdXTwcWzpKNE6BIRhbNglENCUTRzM8LEREKxFxExMPNCosIjdgDQ0kHi5QCAgaGSJBCAg8BwYIBwb3shenAAAAAXRSTlMAQObYZgAADgFJREFUeNrUmYGK4zgMhsPOsjdXXz0nanSIBgSmsPP+T3jSL3vTpl2oZ8zA/iO7iexQfYkVJZ3ll2QZkSxDygTl7M0MO96WeSrzZ29C8J0CoUP5TwLop5+JmbHr9qcAxOnPlFNC/L7hni8AUFEzEXx+GIBAkJMbCLBv3dcAaA0K/RQAzj9n4hBRSl8BIB57xUX4BEDP34Tw13Vl38lzllA1aa1iQph3AN0wFBvG1PR0Em83UAPgSORZAOoAimVeRO8BTBuAxMRBgLaCiF0rgodrEoCqtfIQQKV68OgB4NOKqmN7e/ouBIJMfQXZ1iyAfgGKI5QiOwB1QFGn9KFSYiKu2whALwW8sotSItMkAJOWokXsb5ee/14LAEV8IgCMbqAS4w7q8ZNvpGmPEjXWgwOg3QH80wQAAUApVUcAPNi0ZbDjoBbMAnArovIAAOH/bfJP5ERRlQCw9nwSk4shoowVNBcAyVlEdgAe/V+QMSAnYmKkwEgSE0MoAQYAojkAEYloUSToYr10u8UBgCDZawXCSBLHbXSrAXlSIdOKtaBSIrZFkMtF3ORutogWMxw0UAeoZQG3KmzNNQcg7qOlRGwO4MLHPUBpAAqAsdtoLCEGQZ6XA205e7gBUEK/AShugkMG6gARGBzAtzhPzIGzqrcAKLog9q57gJMNquls9iwAzna/BHib5Hk5UFnVGpdTEQ4AifX/GIAcgM/K6vZsHYhnoUzxJMF5Yg6sFsyZz0ynwkbBixhAtzsAOREXa+uZ7Rg9P7+EyOLfnuXMMQ+Az35eiE7MJwIA9BDAZpgRTqOhrwN1gBjLHwQzC9nKq5k1IjfcKcPkQRKzh0GYv7oGrkBUAiJnpxSeKQCrmTWPjRi1Svub8AMAXnxWO2Yd+1nFjNjk/cQl5IZI2P5Mx2vdAVgjHIYDR96JuT8MrZRBNPVnFY1ibDoSHekI+aa7xMZM/XWyWFuG1OPPCbUYKQDNA8BrMervkV394fEo8KLaAaB8CIBM2ysZT63EoUu9VFEVKXTjpyLurjZ+EdXiANZ0GVKkAJtBUY3zbICL4o3gdtkf1VeQXmIcO2UcIOInQ9hqGTnERABT9fjr7gpUD7peXCpGGBAyCNCV8tVLGdFsgJ/v7++Vb/xczfezYhjVIQDKaBL36AlJQKbJSwghimjVHYB63Ii/4vyL9zIOgCrGxCZcgZxoNkC9SK1COwBy58WH1XMYJW4cIH6V4Owk222IaCZA/LZCfLjxH5hKURsLACSwyihALJh4FGoinr2EUAiE395u/G9vLCgDDoBKp6Ki4wAhZm9GMj0HtIpZUT78uPH/OLAagJq5cAeSMpzErv5fDYbINBVAxUyUX7/f+L+/srsV1m6j4wC7+FES4JoHICoIkO4ACH7YJ26j/aW4P1TkaJMBrNHh9cb/eqAYCBMkgo4/C0ENotPMBnA7PQA4dQL0Ju8iAuu6bQ506LcOE9qMjtEpuudq5HocxG1rP/d6DaosAFj2AsAicuuN0NJN9BFjSi3qRH3pJ+s6wAbtI9ahx5xwowVBp06mvoeWcp++bBI0XvbiGNljEQAShWUEQXBkAgVCii/GFELXGKkPEGIjdOChcAZ2bOFM4ZDmQSMCwF7/PeFxUdxVMuf2PUwRnltbAJxSe+5n32cMpGDckiHFVpvXnRFj3qgzYyYAURAjguWjwtqwxpnCEGNzEJMLcBhhsj46XJk4ID6BFdMwBbg5BoOBOWM8INsARwTLA728fHv5Fnp5+S0AvgYhrejjuxHrytjj/lUYCQ/C4P/buQLdxHEg6tOqQidVp1XlXcUnegOG8v+feDPvzcjUC6E6jiyR/MD2eDx23nOSkinb/StsHwc8ZYZchGMQy5nDZNDFTaLQiwJI/w9KSFfAHcSjpQkwFdxWPmvy0wp81YYAOra+z4CL9JOD7pYiIXDL32ZjPreFmhmO5qIAsNc3SroCW9DKVmGsIUBbsIgXzg530Gp2GnmMw0W+W51iq5nTAlQsDUr2uC3l+8SrAv7Q96wA23uUrbGgCnLE2tQTbqRhIGDRcXLIQf0gF2o8Tg1EgCpX4eUUS5LBdQGKWQE4LPdnt/25gxoFyJMLHKiCJiQFeRgM4V6EgHCAMSrnzfmxbWSQLsDoA9pcFbClAJDZ7rY7XVE9O/XY2maYR99oYOCtheS5o/AwZKctJ7lyko6ZfuX4qoYZAYEZAT93WIynd7fb8SDkrYYKgh6G6csMeHAhNEnqcso78MJczuBk620pwH3mxOozAn78YDUngIspYQowAtZssXbQVS8ogpaWXRMDAwVjmE8BocHnoPLLUGNQqYcMrlxCP/5RAVrNCdhCgPMA1S14g0ATAGkmwApqbTkKpwXvUGMmunBDE31UprX54KTczwJe+OkFgDsqx7eXl5dvhBovKdlC2ECuqS8DxZjH+ZkvBCCQfpDh+YEb7Lgi9Pl0W9gFWIOFQ4DHpwawCwF/K3etAOd9jpTIE5vA9XxF2CBGBtFHTaahnQ6XxWUoQJu2LLiTdrhgeJP+K8AM6/qbhQcKJQpW9NKPxj1scF2xAwHhjmWbbW92wky3wH8oEf/UoIELJrDpjtIqepq3NbTaNG1SC2bT+oDPbwJQbgsAe+CCADNiXevEYYNH6o5Pf0qNS2PujRnWwB8zYKcu8IsCXtsJOBeAozQ7liIdVBy2DtugQDcMKAxvapPQY1RzekALZ+frAl4hYHV4VfgVtFoBfhOs9AzwJuZNsE4BTcFaz8Am8Oxn4AUPEgQeRLVyfFOkp8cGj2sQYZkMKoU/CG3S0wP8jbG/zYRFBekeHK/hxoyK+nRiBcwIMHxrAHcAI8sLOIUA8q+oZwRsyF8LDLTom7HZLCxA6SrlWo0zXtbTdk7A5kU1WIFBG4C5tABSrmAP5tU6dUbA29v3t+/Ea8A6bwqtlhZQlbdBOZuOit6sgD83DXECoq9jiwvAnmsDS1/szF1CvOKt2mjRl3q05j2x+E0cCtyIakYAuBLNao7fIICcz5Xc/jEK6h04sLCAuGxi86vf0fP3wMs16F2wuADSjh8+VlV8DtyB5QXwJJgA415Px1UJ4AcxuFtrAvQcrEeAsSZOZvNCqisSUMHbysls3MurFKCGk1+XgHiO45XTPgnWJEAVYP9XK6BCAF/AmgTUyud/sraGZr06gTh87Pf7j8Ot8SUE8CcnBbACbgj4AMGPW+OLC9AX6i8IOOwPIDg7vkhKGfdu+zxbq4D4PMM5uCngY69lfnwJAeBfIYJJPdrjVwQctMyOLyaAF77y9gz/hBlrEQCYBNzJJ1SqZTUCTiFAAe5QcUGASKD4X3WrwVZKTcl6Itlgbkf28AcKwHZHTsNaXfWCgCJaSpUslSQzRIjakhLEhIAsXfiDBVQXoIjUrKYOtRSQrdz2agKUP95G0HpmZXorzkyEP1KAopJ71HhdEJCLsa7YXxNQQT0IuhkCuvDHCUAOHNR9/y8LkKysRaoYNSWX1UMfBUAOBQiIl7Pwh6aU53t/RFHzVwFTybWITGKscYnUXE2AekwA5Ey55GwxXfgiH2TVf9F+OR+YJgEfazNqmQpYqq0E1aHsJ1Tq6cIf/kHGnz0w6zUB0/tk1TsrItqUaPbjEfLYS4g7j7u5XhXwbqze9/aQ9m6PaXs6+FaCaLvxFvHIDzLfeW3OBZxSh73ioMQUe9SHw77h1vhjP4lP8SRH9rwd1pKRnU4UYFCz3c9rycj460SQR6knltNaEho8uCm0QaGh9f8r4PjbcUdG9qwCbucDQ8AQcIYkAaZgx1xylSJMA/xxujL9ysdaIjYz4gkEFGZYkYJV5VbRtnwAQ1VbG9BOgYDyNAJAKVKwyIeVa2RkUOQRFGA+lPIEAvjHwpGCWSN+1eR6JkC9TZ+F12cS0FIwI4Wrp4rkWkIA0y8IKFDqAuQJBEyfUjAjVa1SW4VRwDQh7+QoxCK70d70BAK6FExJ2Q6raS9JJnDy9EsgzBO0yZpnEDCfcc1nbM8hYD7jms/YnkDAnRnZEwi4LyN7AgF3ZGTPI+D+hKZquRv1gmMhAVKlHRQVCiEsdNGu0mLQa4u02WIVl+vWaebdGZlgISmSj8VZFKfUaMlRxDgUuNRGYQyYlljEZ6BUEQx08yCMS4rF3ZkPFKlS8Y3CMevCYMEDoKKnHAuOntVmX8AAMRpdciyi8SSJ8Vw4A3Wsgy2BWXCgewVk4VNsrrnosGSxlruVcbBiY6JOi0O/GAPGwJPbIsovixGDomzUz+dlJc2hmtWucrcAiedvAQ01+gSoCMZQaWhLhjyG+6z1xYyqm5f90RluKVaSiEBJN8HDU+r5Kc75ZR5fEI2oLgGKb6icAIhgNz1GUEq+nFF188icywnFJ7CR0k/w8JR6fkUUpfEzF95cvHQJUOyLR4I0nB4TIq5lVKXNQ8soLkqG/n++9BNcSkq/8IPexg/ljHifAMUgCXCH23dUFKK+axlVE1C4vjXm6QT8MsHDU+r5UUDwcxE1CwOKXEqAGMLrvvtKC/2ZjEpSmwcCGUs1UqmfMPmEJqDnVz7zYzKUtJeqCNrUJ0AJK2UdlZos9bBAxKAvNRZpGVViRiWf5iUcVC1zqrtop0vBhJmWiIZPRadHspbzVDWqS9DsHsEbRpLENkmxo4JHUfY2bg0iBPQZ4/1UIEttwbxibnvJ+Tx40YMGsJPUpWCeaakFn8ZaSlYmqyf1tAStgN/yWOA7sgWwwHdky+D+78gGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBtaCfwE/iN7wd4XgKAAAAABJRU5ErkJggg==","spider":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgBAMAAABQs2O3AAAAKlBMVEUAAACSiX+MgndgVEhPRTxHPjWoDg49NC0yKyYmIBsmHxoaFA88AgIiAADotIQjAAAAAXRSTlMAQObYZgAAAgpJREFUeNp10rFu1EAQBuB7B8RDUCIs0tB5rUuUNAivfBKvkI5b/eNLyVkzg6hQYGfyAkn6oDwAFUUqUvA4rHTGthTlb7b4P+3urHZV4uqqsuKbHdNNz3S9A5V1NUVIVW0leQfOCuQvhNzTDJhF3W6RlUvJV5R7przjBSBxu5KbHmV73OJaUc7DBDIVIKs5zuSU4nSIkYotgSUox25z0GAtfe+qk+GWN0PCARhI1fgwyJhjpOb7QDQBN0DVJ9BRiJmhB8CQAlhlAfZNaxAfb8ziwuSLQeqmrdx8BMJi0qsvBrms6hP3AuZIFxNYRJBj6L5W9d8UYg8SGcGmjSlRFuOB1/vqz7v6mLYbcscIEoYOAjNLoB+/6urtbwarGabB2q4juBnR5dnj+fnZ4wlDM2QEbQhdVHXOoLr69PBwVFfM0sNmgEE9g5Ve34U3dTh9IcZu/0Gsw2atboDL6f37u48vL+7E4c4jaD80YU2ult0v/NvP01d+707CGMG2DVVH5uNrPk0a2oog7vYM4G1qgN6FngEAgZmc8aQKMTSBgY62KbShCwIKaTODGPhztU6csA11FTgJQhNpBuGoNM2QIGDsQx0ktfF4ARKDIiKYmUAhdMZtxzIDYN+g5xLJVO4Aw8BYAG9L7waQeiaQGwlIZ5ARu9g7a9Yc0wYFK+kCeAbgDvfegdK7qyy+4z9b0kGP3NmJngAAAABJRU5ErkJggg==","tadpole":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAFVBMVEUAAABtUz1jSTNTOSNJLxlEKhQWCgDfr9AwAAAAAXRSTlMAQObYZgAAADdJREFUeNpjYGAyCglgAAFGRVcHMINNzMgARBuliSUZGQEZzkZGxsHODNiAs6KwA5RlYsBAOQAAqGUGQPKmAvcAAAAASUVORK5CYII=","turtle":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAABABAMAAAAg+GJMAAAAMFBMVEUAAAD////K0JHCt4ComnNHv0qUi2OCiFQ/pEI4jTopfUkwcj8gakMlZDMbWzExMTA/pVLKAAAAAXRSTlMAQObYZgAABDNJREFUeNqd1s9r40YUB/DAZr1Z3JT+By2S6XnRiJyD9ZjmtBRSUbWnQITMQlgKXeJL6aGxlpltD2VZjKY2uRW2JodAlxAxm9DD4satYnKuI7OH0qUkEfQ/6Iwk/7isrNnvSUb2h5n3pHlekqkG9AVC60vvnLuEPJsCDxMRL01pYIWQ1hRwo+T6leeBixUA234MsJV98Cxdxx5YFuDSwG3b/tzFX8nLigtoDZngpdlSAHYbOYCMmoZMBaAa+LaIQ0/i+GKpsm1ouqYhFYARCRCWAZamGcLACkD4ITn+nvzXyQCUAWvlgdWQBQGlrBNLYFn8WO7BVABGTQ/Aa56kQAUAtBoAzgHl3DI0rV4XVVQDVvyWtT4FdE0dcDbr9yaAbiJ1wN80Pkqv7riWoWsIGmrAXX9Py4BbKN2CjhQBsolmQE0dWAlaZlaDZWTUTFNDpirwDNazGnhQr2mAVWsQMjf7cgWQ2IJuYjWgGoZTwHIxbIMqwHl7AmCrpmMFYBkAHhx5YfpSt971ZL7tt8yC35Y5Vfdq97JLxoiFkNwBqJyq5Ds9B8IgIIQ89lzLQGZ5wHmqTQBGbZ+0AOmarius4CnKAR4y33E+Qyapm6R8DeietZ4DzJft2CAy5YcjbYEEKp5nU992GKEAIMu4VRLotPGP2aWF0AZlbQCsMl2rnaMJQEQC9gIZCFQAfvTgMAd8/wvKfpU9MKHkXCSs7fE2iGx8uuQ4NmX8uGVstJA5edpNE0q/W7IHtHNMZPIVpPMaewtr8tYuWHJezwD1pPN6rRiocnbm22TQ4SPO/2XsivOLOcAwFgNhNyBdxnnMTznrnPITNWCV8796vd6IixE75pyfxvEMSOf1x8XAe6PLg2ESHYwuo+RG7CJOrn+b3kznNS4G7kT9YZIk/eh3r/FtEg2T5lzT5bxetIJlgETkbxDBjWbTA1ifA3StEKiOX0H28oDIcMSvB75t0+jqMAd0ExUC798IADdFdgVwniSsG9hOl+2/zu6n8xoXrSDuAzSaMi7g81HI6B+93oCyw5IPUvXkDVgZsA2f3PAwePLcdnpkBtQWAWNAzTRfm/djzsgvsgbPaX5EyHm9CHCnwMOYd3uB/Ov600EOuHJee4VFvGx4GbDb2ImTq5eBWAHp8kkR5bzGBcDqOJqtYGcYhzSSXRjQvAbpvMaFW7h8NAW+kTVwRBfOnEkN0nldCPB5YCQAW3Th5ylQcQGKpr0EmtMapMCXogZPJFCQghXsR2kbD4blANmFeUB0IRgQ26FnndclAdkFKwdAdiH44YyQSD6JpSK70NjNa9DciTlnpBtFAe2UB8YwXcF9CTCxggErD8RvADLgkXiZRjzsMkK7jJcFVuN/5l7nm3icRCFjL4fJRdkuXPfngCi54uxP1hEzonQX4v7sRMLnMefhfpIwXrAFhXyw4P7/kgmYSeJwxJwAAAAASUVORK5CYII=","vex":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAAMFBMVEUAAABthJtgeY9Ta4H////z+Pzg6fHG2eqivNWUrMOGn7eCl6t5kqp6j6RthJtgcoMKluMvAAAABHRSTlMAoKCgEjok+wAAAPlJREFUeNq1yL1Kw1AAhuE3hxYrRYm5gmivQL0Hwa1LnAtCFpdOjuKY4KBjfnYhIUPWEnIBhgxZRSjHC8hp3KWxkg5ndfD5pu8FDqNAKQkwKXIE9Fuj3zCQjECYDCaPs4tOQP9pDME4B1MAbIwTgJEwv2yixPcCPw2igGkcljlZ3YfP33WSJTB9yhG25HaJPLUBtkCdvl5fpVlVVRy3ntdQZW+eX6e77UIcNqAke0eq+JCgGvam4apoUGqtHtC067K9Q1O+l2WMJl9RvPAnl7+0L5Ao9NBB16GxZpZloTGFeWYC47l7DzrXcUF3sHTQjW9YoHMW4zn/5QeNK1xt8XQSVQAAAABJRU5ErkJggg==","villager":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAbFBMVEX///++iGy3gnKze2J6enpra2thYWFUVFRUU1NISElMODM9LSkAAAD///++iGy3gnKUj4m1e2eze2KBfXl/e3eja01vbWqQXkNjYmAAlhFUU1N1Ry93QjVcQjpISElMODM9LSkzJBEjIyMjGBTjk4HHAAAADXRSTlMAAAAAAAAAAAAAAAAA7Uh4SAAAAn9JREFUeNrtlN1ymzAQRm3cuG5C9oMFJIW0idu+/zt2/wieiTNAk0ufgdEKs0cryWJXB0RguUEO1/Xzc871Irs3AViTQdnYLgAzGfmPkFnT9V4tiAI+IyCB/19AVgA+KyCaF9FZL3iDlfUCAl0AjpYmFgWagjkJfjNCtCwgml7niyrmcJ0gho7mQkDrBJALsAhwyYY1IAP4bahgdmKFgBme8PjE/PRI3mMGG1gWxMpnE3GetmFiWQA/yJl/CpzJutggYAYYIjAyQfu8XlAv8DWCb5sFqW2Btk2llJSKctwqIAFJ8oVFQRL+ChcCEKGlKwJSQLRfENBHFYCMZYG+2F6tAOauFgRtC8K1RYSdVqhgd6eCUmIUxTtdKknySXchOYOQEhkAmNmm4YJ5FPWM0nRdbKNGZRxHH2KElx8CRmWCvu+7roxd17nADE1qhdR0RfP1mQZMbAqwnxcT9KnYS5Lc903Tq0U6jVTt+Xo5SesWCUMvIheUMvh5GnwqqpKUJPU0jUSik57jnyswABWgitMYU2MjZlw0X9ppDbpOTMSkwCCQCXw+FBe4uGGUdehGy3950ScaEC4/duwCaWHPorEdGSM/0mMRRlKYogD2bZzGZvuJIa+/SFIQYfCjqvb7w6EKDiYAGe5h4DU4/3o9ezSzF94JGK4IC84Tr+d3PHzwTbTqvQVkqjMlSEa5KjhYLUElPJxOD8r9/cmjGQJxJmMgQVN2B0UCbUxxPJ2+OyI4BnfKEcAwxF95mARL1BcAnJmcTIRqq0DzQsCZwJsEUIgGFUCIKmiTQEceZsGwRlBPQGHY3EOQB2Jalz9XAB11crFWUH+Sm+AmuAlugi8T/AM2/NtEbUTDnAAAAABJRU5ErkJggg==","warden":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAOVBMVEUAAADR1ra7w5sp3+uir4aBmYhudXsAkpVAV2wFYl0HSFcDQVAXKC8GLjcLISoRGyERFRoNEhcFBBJsUoYuAAAAAXRSTlMAQObYZgAABmJJREFUeNrtmuti4ygMhWMChEYrjtn3f9iVEG7r4E7iSyf7wyfcbGetzxIixTuXbyqloICdiCHDJV1+U0UEgFNiAOUdAIZApObfBlAUoLwToBCVE+B1gNvl+laA6+12e68HPoTgvXOAru8FYNrpgbJCAJwIgLHwhW4Sgo8jAfCjcSMIzgXAnJGZSO1f9wFgydiP4pS4fSNnMX+Rx98JIMLUQNQYRD0Mknog2bnMdDXrh4UAOQPIZl/GvWuiGwYXJ4DL5VgAZKDkYhqBRwIwwCKA8dKqTCkE9xoAGkAZpf+QRjQHADjF4NQDLsTEwHOApBFb4QELey7lH+WwwyZoZX0gUQiJ0XtgfxZkoHa1GQuQH6YhGCyyCDwHsOdf4YEMMz9qJ70AzASNwTBoBPAKAKWwDgBoIBMA5vYtBhaBg0LQA4xFalaGDsAYRHYexwNkmGGhGBUDetQgMF8Jf2EOQAHQ7FehmwPMthIy/9YcUAoNv3R2+F2wRLQk/J05kAH1/fJK2BCZJ7DjFiJ8AejwwxC+AeDLCRwCl1cBSAnW/hjZ43+OUeZCSrDR8SHof45nMhb1gI4PBFgnMBvYGwC6deBoEd3vdyKWXkV/cVdmMrMiae/0FgC6VQQpSSj+OgCpWhDoHSEww1MM3uIBc32bjG/wgJrV5qZNeg5wvdyOzgJqifCaB2Rjfj02BDf6ss89QG//4/A5UC3fTU8BrnRo5IkSiexAC7VLVuyKXZo8QHwAADMR852ll08temCH2lpzl5rbN5pZ3Znf6MJ7AVRZpPeXponaqczI+mFmaUi/ALQkUAIizvsAckaWCjVXTRXpqvSoIGsjKmUc60mUCUCccBGEvI+gAMVqwchjgRRoq6q2pVfr9Vt6AANoDNe9LjDrKjNq4uW3JbDuG4BoL8BMI1jUUCZBy3e9fscVAFkbsCUFN5zZrs2EXwIwcfm3Sga9+r3i9Ot5EAAKq3ETd6Ff+CO52uf7/TAAyLOrxA8ovZjLXLY47gdosTb7ED0Q9CHIfwTI2zwwFuR6Tya2tyUwtv4d5aTpd2N+rz6BV2zNOAOQjtHfrP9/SXcmsU/fAHLptAoAmAYvzQF7fuJFD5jwIkC/De4VQ4gdgKbhPATo77BqRbTUIlr8DjP3bCYsjfMWAHusZYBhGLAUjHYSHcEKgH5164XBDeoF1K6UUYuJWejMNApg/VYAspndS9+Vs5c6DMkNbNlrzz4MSqUCSs6zNWMdABPRTyEIzg1JanCDspSmUXn0pDkggwhZR2s9MLY58GMIvHMuSaMM3g0oTc6FWmoIMiElUK72sSEE9/pZBhCrUaowBO8FIFdsOCcnXfUAQCknKZSBzZPwfuflEHjnozdzMm4GgODkggFkCi47KYHyawBLGc3Mi6tYEKvRe6cgUgGU0QCC90JQjIBCILP/IsD4sNhC0n0aPgL4GAQgSgkegHlAD/Tajr8Jx5bKDiySdEdjmANEr7a8lz7FYAAZiDGFmLYDmMRsqinupbo4OGEA8xwgBIEQ6z5SSp8eoETKsBnAHGBWw+CEw2kfKtFsIUoxqAvEGFEitOCBiUmv7fPA4LyYFPmkzZTb83e/lNT3UQZMjGICM4goxk0AaE+BwfsghoUjSpXeSTcHYOIkDDFxYhFKExh6aSMAGoDzwUz66M0Z0rnwAKBOSMykNjGFD9UJnDYCQM1XAK8Q3kfp1BnehzkAbNdO0j2+zFYA3gegGeakSO8FQKsM5wBgUbVf9FPy7I/6zQBjBQiaSGK7proUn2JI84mFwlLkU83PNEpFv7au8UBKFH2qa11QBrVOibqdNOx5l7QdoGAEJSIxqg4IMUWtxMRzgF77AQosgjbF1XBIOohEBH4GMFq7C6CJRYlTrHlGHLUB49c98Imv1kgYki1zicGMsgQAaw8DaAJQ85wsz2p5uIVZBSxk+A4xO8gbtmY1FQtamjPAsDs+TlilrC0BBqHVrphpbN6cVpMsH0jBwn/MRAARMZqj6hAytEFZElbvDdGs9wD0RL3/Ta9Mwp5jtLrln4Pgs8ULAE+0CmASNkzCowBW7w27hQ3WaYP1AP3e8DkAFt9NWIatA9i0NyyosGDriqV5aWmOVQD93lCV/3yPKYlrpdKl+RqATXtDeqI1ACv3hsfrx73hqVOnTp06derUqVOnTp06derU/1n/AR0CP3Q2vq+HAAAAAElFTkSuQmCC","witch":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAACACAMAAACMX59YAAAAmVBMVEUAAAD///+2qJWrn42rnYmmmoijlIOgkoCPj4+YiXeWdliWdFcltDWUc1Z6d3eAcl6PbFNra2uQXkN6XnBhYWFoWUwMixp1Ry8vaDVaTTZMTExHT0hQQy0/Pz9IPCc6OjpANSQkQCg1Lh0dPAkxKRwoKCgsKRg2F1guJxonJiYwFE0YKRoTLgEeHh4oEEIdCy8REREVByUKDAvCurIkAAAAAXRSTlMAQObYZgAAA1lJREFUeNrtloFS2kAQhiPphVJbKVq10XDG2Ba4mjvx/R+u/+5yR1U0d2SqYyefgcuO+T/2NoYxyw4PMyLPlVL5KN+gsuz8/Pg46+bw65dPtEoeginjBdFAkAvTEkwVxen1eoJRjg30FfTbgjAKQ0wlD0NQTEKQNq98ntcANhU3fQkVile1talogRJBkQsiIFG3QPnrVQHkNBhAt8BHCgKFxBURJSh8/hcjFeULECXwMzs4KYqTAwpLXgxFtwBXkWM6/gDGU0kHugUTMoDpeHx6Oh5PleQnExy0dAsmrICAmUp8S/ZeKQum/BFIFUyYWIEGP0GMYAEM+OeCgnkVQQNqCJrlcqlBDXBWqVGuKlSE1lVZVpW2wAtoeSxoWEB1XZVaKV2WqEBVleCBwNEaBFoEsm4Epaa3RgQlTvHmSGCQdxCYIKglWEOAbpdNAxclaoR8hWZwOGedgcABWkVQe0ENFY4lIIFmgVQaabw4CPzKglrX/MkNTuigAJpmQaUbrl4WIMXD07JKhHagMfiGigYmHFXVIahl9UNssANUAGdIw7FTgMslSAMAItAiCDpsCT/ZLubzppHcfD4D4tFVSV1UGwHycOwWXMwR/Hg0w3JBAuwaR83AQhORHtDjbgGYHc1mtH4DMjbN1DpUPKnseRZ+eRFjrbPWGKx88vev4gQGOQPYZJIFoQO7swNZXsSGLTzpYNEpcIA7gEHOxRY7RBFgBs4L/BycW6P0HaBar52VLxz7tAMJiUC6ySwiEBiZMucd8oR5IkAqCMS1EVi+2iwMFw5hEUTAAkuC2xsIaENUCdEC9EICRGy6wPEMsGkvWKcK1jKDrcAlbmENgoArt7/A7CFwDwRuDwFP0W+BJ5J+GyEwj+6CSRQYEZitgH6iBU4ExgtMssAaayCgR5QqK/8B2PgtWMsCePhhIB+wCX8H4PYGQdKJAG9JHYjAypNhKQ0ShshXs8DtIXCISMECrliYpbEK3AcSBS2zv6C9Y9pB8IaC/rfRkyZYRfKsoI0kspGOzrtuQdtHcEe8R0H/GfS/C23gd/uYNMH19+u9BFcbLs8+n11ePSSpgxU6WLUeea6TJsiz2xd88tsJ+m8h9osj+gvl3QnA6j7rBQ+uD9z2wMDAwMDAwH/EH571WWMJHeH4AAAAAElFTkSuQmCC","wolf":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAMAAACVQ462AAAAw1BMVEXt5+jk3t/c3Nzf2dnW0NHKxsfIwsO3t7ferIWzs7Nu1Je3q6WhoaGdnU10oIaBgYEatVh+dnBegyJlZi1iWkAodi5WVlZUVFRERERHQjs+PTBENiY5ODVDNSWAAHY/MCQzMzMtLSg1Kh8sLCo0KR4ZGRkAAAD////k2Nnd2tvV0NDTz8/Kx8jJwcLBvr7UtaTOr5bEq5ywqqefmpaalZGnj36ajIiVhnmheFuUe2iBdm2Mb1JJQjk5PD85ODUtLSgSFBY76smzAAAAJ3RSTlMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi/HzzAAADR0lEQVR42s2UbXfbNgyF6Wli41WZqm3NtkQOZ3ZVwwCFbShO6r6k/v+/ahdwtjOp/dJvvZT5gqP7HAC2GYZhWFDBYBIilsvLy5Ty8HsPiY4yirIQBgtfX1/HLlbD/xUcQIXh51JI1ut1TumiXyz6SKKkAi4AzEQGCLH7AhCpFDxMmBmAlNIffYw9MlMgPewrAPDHKWCxiAtmEFjYyogIrNd//frixU8/lyKIF4htdUAIsxIETiEAfMPGQRmDC0HzGt1Xz6AKUwAXJxC8VAgkb+TgIgIacV//7UE1K8Fsb477/fGN+Q1HAFw9e5auErZi5KcVANcsA+D3H+7vP+yFvA9CvBZhr8qmU4dP9Ukx3AzABP/DAwjE9hbGb1TcYnYCynCOksJYpwCR/cM9QfcPe3lSApWwAgJ5AbazPhhqCkgpvdwddnjOzlLKOZnEatH/CKKEgJ0w5CuA7WHrgL8dkNMVLMKj18BWxegBIgVHZQrIOb/cHDYO+CGfAIl1VMHjDYRvFATYQ9hMAb9Am08bJHF2dg6Z/wqq+9j3nf3wYmhjFWOoY+xirOowBWw3Nzc3R3w22+1utz0fHqFl09Z919e1WAqS61hBDsA6B4Bg/g36cNidP5bySKVtYmeDCkSr6nl8jiy6PkYsU8Dh+Omk4+EEIHosVFV17LouFhKlEioQapj7LoZYTwE2NaucXl9cvLa9XwSLUHW9DaERDayRd4ghdH++whzngM+f373LKwA+fnz/dvCLIIaqRgv6qGKAEJxQhVcd0ghfBSQHvH2P0I8h4O3Tt6Cqo+riZK8i9MV98HThcVZMQsyDiLVO7CjYEGYqSlSFAABYUwDx6T/YwEesTANWOIRxNCuRFLZWLtGqpmmW7QxAzGZdqllUDFBOAMvA9pgVuTRt2yyXmOYZCDOsjYqjeGAqEBPEBSIERkCaJue2BWbeA7jwcYACMbAl4CWI+NYBVAyQVmkOuNPxTvVubAUWJZQAJxh2ZAD8RKNyaVv7r+c5AH6MUbMKwW5NZKtamP26RgiPjkwruLMxpgBhvr29ZTEAmwsAtq3gMdbpNDIjfSBWaTUFrFJOVlvGQHrAm9XNPmEAwCqc7UWbpoDh2/WdAf4B+LQj08eGOFAAAAAASUVORK5CYII=","zombie":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAclBMVEUAAAAAzMyPj495nGVxlVtvlVxtlVtnkFYAr69ph1Z6d3cAqKgAnp5ae0gAmZlra2tXdUdOezZhYWFIdTJJcTVWScwAf39KaS0+aS07Yi9MTExGOqU2WiUAaGg4UiYAW1s/Pz86MYkwKHImIVsoKCgaGho5R/XAAAAAAXRSTlMAQObYZgAAAkJJREFUeNrtk2FzmzAMhpPNm+0akmjVqFRGEsPy///iXtnlml27laRfeWwswZ0eI3NsZkRFVWwUdHMrIqzKitKC3C4gVjhgOQLVOwQEAcvdAmViwZQiuKOFsj2J3i1gZWEVrAqEbxaIlkHMAni5QK15VRSpwTI/UFuYFnx/q2ZCQYyMEq5PSKWMJW8gZSv//av75rneqcJFxMqLemdiiq1zLraR6llimEtk2fdnpvZycfFyaeGScggkqKclLQjqWShG1RhR/XIKCEgWtCByLJs96tOTPiIROoogMhEvO0QWqf+AWqXdsQIEWfhP/AS/wXy//VXYji/Mz8N2G5iIPxYcC28EW0CsnxOwqnyqhTf/yQhy3/fjNE096Lru1CRl0dR0oGlSCAn5bteZYI7vCcYiGIYuhUa1CQH5kFIAVRbAHP8S9FeCoQhC2XgAKSDB8h9BroIMQc79aRhOwQwoqzkyTMt3Ke3m+CrIVWAxwzacTiZIRQBCgwyXgAgEtGAzk/tcdh6R2ETNkEyAOSCfBcykLjovyuy9j68CVPUAS4lWZB3AkQa8b1WlJMzqW9eykvhD9O8IkM1foR5Bg3wwlzlQJ967loQ0Ru+vD7EKMjJggnJsuKosYZpA2TsXiVnjdQvnsxVa+fm8B93QdbanlRUBkoBFWMk574RF/PUbPJ9R+OVhj/BsgnEap1xIoZsmyO1EcyYI0IFXQTz4+CoA+4f93uIPAMHYF3JTcyRokkmodbFVEo6HeNisrKysrKysrPyDP68WY0lh7YK7AAAAAElFTkSuQmCC","zombie_villager":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAt1BMVEVskkNwbWdVczVjW1tWYC5jVC9IYC4/WChUSSg4TSM4OyExPSUuNyQAAAD///+Iqlt3oEd2kk9skkOCe3RyhFFmij9ffzdwbWdedUVXdUdVczVjW1tUZkBOazBgXjhOaC1HZTdQVzdUTU1PUTNBWSiZKys/WChcQjpURypDTCQ4TSNKPj42TCpJQSRMODNCNzcxRB8vQh44OyExPSUsPRw7MTEyNyQqOSE9LSk2MiAzJBEgKxgjIyNApSiHAAAADnRSTlMAAAAAAAAAAAAAAAAAAKroblcAAAMeSURBVHja7dF/X9s2EMfxrGs3oGtxHXTSztIuE+mtyG1+2HNKxp7/49pXIoHSUhxe65/52E6cmHs7MpMXuxxR3p0iFF6+3Gz+vPztlxdP9AZN9h8IfQ1c/vEMgMkgItV/kYbN5upys/nw4dWhAOarGkS4Ay6vthmYfL8HAHNViD2w3VxdbbfPAGoMV1VVuz2w/fTpeUBt6ro6r4yWwtnZycnJ2dmrgwHMwqjODbmADgeIqrx6Q5XBKvALSlRyOCZjAJM5ZyJig0dgKkN3sw4HjwMEwTAFNlRfuIpDnkIF4DAOMAsRgGAMuYvzEBwmQRTG0SGAGlYX5hfv8AjfzYMT54QzwJ4OAkRFHc//Kc2ZhJQ9xvHCBwDCAkGE3r4P4f1bkuxB9ThRFR4FNCVFqQ9zFHp8wr7OX616XBsFUt+vUwbmf6M5ZtI6rYHgwqpfrQ4BUhb6eanv0rpba5dS32G8GwdOT1+f5iYjjQG/PvmHTwE/o5/Q5EFWhVnUNnc9FxBCfChgUd91/et7gDGu9AjgyNHnm8833wIQvgDoe7+A6to9CnQQvgQYgDwCmLqmGwhjS1Bh4scAMiQPgCZnse2zdmqbiHkS2Qm2URG11iEict47T6gAbRObaNvYNjhpbIyxzIsw42War8a4U/M8Nod5vQdibNs4DC0MGzNgpzGlJEiTLfMQUIwYNo68I3WexO2BdgCgQ3awNVlJuzrcGpP5FVkhckCIRLGLuwVaTaopJLyBGuK9gPmptRbfNFMc1qozZfFCglQKoIgDOeagA7Ym3zEOXa7MN1gASBBRlQwZQ96JOBwF4MCeidg5puQ4YMELPNgO5UeXsWVEgAYVJlMALkIBKIAAwHnH0SI8FE2xybddYr5tmzZFJAwAeWYIorcACzE5KC4wBwDLYVgu24gwPeR57KlFHpN1XRsiZgehACKz2wUJ+xnOF7uu/1pcL77Kq6caZUD2/0ZFAk9zM9XrfYvrb1L1TPXvNbFnhwqQEPOKZbVKaZW0aWIpvy+bZVOypUYT7vFx9tGz9zOcFuDN/+gIHIEjcASOwBH44cB/1lQM4ZNhKecAAAAASUVORK5CYII="} \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/allay.obj b/renderer/viewer/three/entity/models/allay.obj deleted file mode 100644 index 69765c223..000000000 --- a/renderer/viewer/three/entity/models/allay.obj +++ /dev/null @@ -1,325 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o head -v 0.15625 0.5631249999999999 0.15625 -v 0.15625 0.5631249999999999 -0.15625 -v 0.15625 0.250625 0.15625 -v 0.15625 0.250625 -0.15625 -v -0.15625 0.5631249999999999 -0.15625 -v -0.15625 0.5631249999999999 0.15625 -v -0.15625 0.250625 -0.15625 -v -0.15625 0.250625 0.15625 -vt 0.15625 0.84375 -vt 0.3125 0.84375 -vt 0.3125 0.6875 -vt 0.15625 0.6875 -vt 0 0.84375 -vt 0.15625 0.84375 -vt 0.15625 0.6875 -vt 0 0.6875 -vt 0.46875 0.84375 -vt 0.625 0.84375 -vt 0.625 0.6875 -vt 0.46875 0.6875 -vt 0.3125 0.84375 -vt 0.46875 0.84375 -vt 0.46875 0.6875 -vt 0.3125 0.6875 -vt 0.3125 0.84375 -vt 0.15625 0.84375 -vt 0.15625 1 -vt 0.3125 1 -vt 0.46875 1 -vt 0.3125 1 -vt 0.3125 0.84375 -vt 0.46875 0.84375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b432e290-ff98-8fcb-61cd-b0f5c289cd94 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o body -v 0.09375 0.25 0.0625 -v 0.09375 0.25 -0.0625 -v 0.09375 0 0.0625 -v 0.09375 0 -0.0625 -v -0.09375 0.25 -0.0625 -v -0.09375 0.25 0.0625 -v -0.09375 0 -0.0625 -v -0.09375 0 0.0625 -vt 0.0625 0.625 -vt 0.15625 0.625 -vt 0.15625 0.5 -vt 0.0625 0.5 -vt 0 0.625 -vt 0.0625 0.625 -vt 0.0625 0.5 -vt 0 0.5 -vt 0.21875 0.625 -vt 0.3125 0.625 -vt 0.3125 0.5 -vt 0.21875 0.5 -vt 0.15625 0.625 -vt 0.21875 0.625 -vt 0.21875 0.5 -vt 0.15625 0.5 -vt 0.15625 0.625 -vt 0.0625 0.625 -vt 0.0625 0.6875 -vt 0.15625 0.6875 -vt 0.25 0.6875 -vt 0.15625 0.6875 -vt 0.15625 0.625 -vt 0.25 0.625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b432e290-ff98-8fcb-61cd-b0f5c289cd94 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o body -v 0.08125000000000004 0.23750000000000004 0.050000000000000044 -v 0.08125000000000004 0.23750000000000004 -0.04999999999999999 -v 0.08125000000000004 -0.04999999999999999 0.050000000000000044 -v 0.08125000000000004 -0.04999999999999999 -0.04999999999999999 -v -0.08124999999999999 0.23750000000000004 -0.04999999999999999 -v -0.08124999999999999 0.23750000000000004 0.050000000000000044 -v -0.08124999999999999 -0.04999999999999999 -0.04999999999999999 -v -0.08124999999999999 -0.04999999999999999 0.050000000000000044 -vt 0.0625 0.4375 -vt 0.15625 0.4375 -vt 0.15625 0.28125 -vt 0.0625 0.28125 -vt 0 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.28125 -vt 0 0.28125 -vt 0.21875 0.4375 -vt 0.3125 0.4375 -vt 0.3125 0.28125 -vt 0.21875 0.28125 -vt 0.15625 0.4375 -vt 0.21875 0.4375 -vt 0.21875 0.28125 -vt 0.15625 0.28125 -vt 0.15625 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.5 -vt 0.15625 0.5 -vt 0.25 0.5 -vt 0.15625 0.5 -vt 0.15625 0.4375 -vt 0.25 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b432e290-ff98-8fcb-61cd-b0f5c289cd94 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o right_arm -v 0.15625 0.25 0.0625 -v 0.15625 0.25 -0.0625 -v 0.15625 0 0.0625 -v 0.15625 0 -0.0625 -v 0.09375 0.25 -0.0625 -v 0.09375 0.25 0.0625 -v 0.09375 0 -0.0625 -v 0.09375 0 0.0625 -vt 0.78125 0.9375 -vt 0.8125 0.9375 -vt 0.8125 0.8125 -vt 0.78125 0.8125 -vt 0.71875 0.9375 -vt 0.78125 0.9375 -vt 0.78125 0.8125 -vt 0.71875 0.8125 -vt 0.875 0.9375 -vt 0.90625 0.9375 -vt 0.90625 0.8125 -vt 0.875 0.8125 -vt 0.8125 0.9375 -vt 0.875 0.9375 -vt 0.875 0.8125 -vt 0.8125 0.8125 -vt 0.8125 0.9375 -vt 0.78125 0.9375 -vt 0.78125 1 -vt 0.8125 1 -vt 0.84375 1 -vt 0.8125 1 -vt 0.8125 0.9375 -vt 0.84375 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b432e290-ff98-8fcb-61cd-b0f5c289cd94 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o left_arm -v -0.09375 0.25 0.0625 -v -0.09375 0.25 -0.0625 -v -0.09375 0 0.0625 -v -0.09375 0 -0.0625 -v -0.15625 0.25 -0.0625 -v -0.15625 0.25 0.0625 -v -0.15625 0 -0.0625 -v -0.15625 0 0.0625 -vt 0.78125 0.75 -vt 0.8125 0.75 -vt 0.8125 0.625 -vt 0.78125 0.625 -vt 0.71875 0.75 -vt 0.78125 0.75 -vt 0.78125 0.625 -vt 0.71875 0.625 -vt 0.875 0.75 -vt 0.90625 0.75 -vt 0.90625 0.625 -vt 0.875 0.625 -vt 0.8125 0.75 -vt 0.875 0.75 -vt 0.875 0.625 -vt 0.8125 0.625 -vt 0.8125 0.75 -vt 0.78125 0.75 -vt 0.78125 0.8125 -vt 0.8125 0.8125 -vt 0.84375 0.8125 -vt 0.8125 0.8125 -vt 0.8125 0.75 -vt 0.84375 0.75 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b432e290-ff98-8fcb-61cd-b0f5c289cd94 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o left_wing -v -0.03125 0.1875 0.5625 -v -0.03125 0.1875 0.0625 -v -0.03125 -0.125 0.5625 -v -0.03125 -0.125 0.0625 -v -0.03125 0.1875 0.0625 -v -0.03125 0.1875 0.5625 -v -0.03125 -0.125 0.0625 -v -0.03125 -0.125 0.5625 -vt 0.75 0.3125 -vt 0.75 0.3125 -vt 0.75 0.15625 -vt 0.75 0.15625 -vt 1 0.3125 -vt 0.75 0.3125 -vt 0.75 0.15625 -vt 1 0.15625 -vt 1 0.3125 -vt 1 0.3125 -vt 1 0.15625 -vt 1 0.15625 -vt 0.75 0.3125 -vt 0.5 0.3125 -vt 0.5 0.15625 -vt 0.75 0.15625 -vt 0.75 0.3125 -vt 0.75 0.3125 -vt 0.75 0.5625 -vt 0.75 0.5625 -vt 0.75 0.5625 -vt 0.75 0.5625 -vt 0.75 0.3125 -vt 0.75 0.3125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b432e290-ff98-8fcb-61cd-b0f5c289cd94 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o right_wing -v 0.03125 0.1875 0.5625 -v 0.03125 0.1875 0.0625 -v 0.03125 -0.125 0.5625 -v 0.03125 -0.125 0.0625 -v 0.03125 0.1875 0.0625 -v 0.03125 0.1875 0.5625 -v 0.03125 -0.125 0.0625 -v 0.03125 -0.125 0.5625 -vt 0.75 0.3125 -vt 0.75 0.3125 -vt 0.75 0.15625 -vt 0.75 0.15625 -vt 0.5 0.3125 -vt 0.75 0.3125 -vt 0.75 0.15625 -vt 0.5 0.15625 -vt 1 0.3125 -vt 1 0.3125 -vt 1 0.15625 -vt 1 0.15625 -vt 0.75 0.3125 -vt 1 0.3125 -vt 1 0.15625 -vt 0.75 0.15625 -vt 0.75 0.3125 -vt 0.75 0.3125 -vt 0.75 0.5625 -vt 0.75 0.5625 -vt 0.75 0.5625 -vt 0.75 0.5625 -vt 0.75 0.3125 -vt 0.75 0.3125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b432e290-ff98-8fcb-61cd-b0f5c289cd94 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/arrow.obj b/renderer/viewer/three/entity/models/arrow.obj deleted file mode 100644 index 469dd6cd3..000000000 --- a/renderer/viewer/three/entity/models/arrow.obj +++ /dev/null @@ -1,60 +0,0 @@ -# Aspose.3D Wavefront OBJ Exporter -# Copyright 2004-2024 Aspose Pty Ltd. -# File created: 02/12/2025 20:01:28 - -mtllib material.lib -g Arrow - -# -# object Arrow -# - -v -160 8.146034E-06 50 -v 160 8.146034E-06 50 -v -160 -8.146034E-06 -50 -v 160 -8.146034E-06 -50 -v -160 -50 1.1920929E-05 -v 160 -50 1.1920929E-05 -v -160 50 -1.1920929E-05 -v 160 50 -1.1920929E-05 -v -140 -49.999992 50.000008 -v -140 50.000008 49.999992 -v -140 -50.000008 -49.999992 -v -140 49.999992 -50.000008 -# 12 vertices - -vn 0 1 -1.6292068E-07 -vn 0 1 -1.6292068E-07 -vn 0 1 -1.6292068E-07 -vn 0 1 -1.6292068E-07 -vn 0 3.1391647E-07 1 -vn 0 3.1391647E-07 1 -vn 0 3.1391647E-07 1 -vn 0 3.1391647E-07 1 -vn -1 0 0 -vn -1 0 0 -vn -1 0 0 -vn -1 0 0 -# 12 vertex normals - -vt 0 0.84375 0 -vt 0.5 1 0 -vt 0.5 1 0 -vt 0.5 0.84375 0 -vt 0 1 0 -vt 0.15625 0.84375 0 -vt 0.15625 0.6875 0 -vt 0 0.84375 0 -vt 0.5 0.84375 0 -vt 0 1 0 -vt 0 0.6875 0 -vt 0 0.84375 0 -# 12 texture coords - -usemtl Arrow -s 1 -f 1/1/1 2/9/2 4/2/3 3/10/4 -f 5/8/5 6/4/6 8/3/7 7/5/8 -f 9/11/9 10/7/10 12/6/11 11/12/12 -#3 polygons - diff --git a/renderer/viewer/three/entity/models/axolotl.obj b/renderer/viewer/three/entity/models/axolotl.obj deleted file mode 100644 index 706474b39..000000000 --- a/renderer/viewer/three/entity/models/axolotl.obj +++ /dev/null @@ -1,509 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.25 0.25 0.3125 -v 0.25 0.25 -0.3125 -v 0.25 0 0.3125 -v 0.25 0 -0.3125 -v -0.25 0.25 -0.3125 -v -0.25 0.25 0.3125 -v -0.25 0 -0.3125 -v -0.25 0 0.3125 -vt 0.15625 0.671875 -vt 0.28125 0.671875 -vt 0.28125 0.609375 -vt 0.15625 0.609375 -vt 0 0.671875 -vt 0.15625 0.671875 -vt 0.15625 0.609375 -vt 0 0.609375 -vt 0.4375 0.671875 -vt 0.5625 0.671875 -vt 0.5625 0.609375 -vt 0.4375 0.609375 -vt 0.28125 0.671875 -vt 0.4375 0.671875 -vt 0.4375 0.609375 -vt 0.28125 0.609375 -vt 0.28125 0.671875 -vt 0.15625 0.671875 -vt 0.15625 0.828125 -vt 0.28125 0.828125 -vt 0.40625 0.828125 -vt 0.28125 0.828125 -vt 0.28125 0.671875 -vt 0.40625 0.671875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_eacaae49-c631-7fce-d186-9315d408fc43 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o body -v 0 0.3125 0.25 -v 0 0.3125 -0.3125 -v 0 0 0.25 -v 0 0 -0.3125 -v 0 0.3125 -0.3125 -v 0 0.3125 0.25 -v 0 0 -0.3125 -v 0 0 0.25 -vt 0.171875 0.59375 -vt 0.171875 0.59375 -vt 0.171875 0.515625 -vt 0.171875 0.515625 -vt 0.03125 0.59375 -vt 0.171875 0.59375 -vt 0.171875 0.515625 -vt 0.03125 0.515625 -vt 0.3125 0.59375 -vt 0.3125 0.59375 -vt 0.3125 0.515625 -vt 0.3125 0.515625 -vt 0.171875 0.59375 -vt 0.3125 0.59375 -vt 0.3125 0.515625 -vt 0.171875 0.515625 -vt 0.171875 0.59375 -vt 0.171875 0.59375 -vt 0.171875 0.734375 -vt 0.171875 0.734375 -vt 0.171875 0.734375 -vt 0.171875 0.734375 -vt 0.171875 0.59375 -vt 0.171875 0.59375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_eacaae49-c631-7fce-d186-9315d408fc43 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o right_arm -v 0.25 0.0625 -0.375 -v 0.25 0.0625 -0.375 -v 0.5625 0.0625 -0.375 -v 0.5625 0.0625 -0.375 -v 0.25 0.0625 -0.1875 -v 0.25 0.0625 -0.1875 -v 0.5625 0.0625 -0.1875 -v 0.5625 0.0625 -0.1875 -vt 0.03125 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.71875 -vt 0.03125 0.71875 -vt 0.03125 0.796875 -vt 0.03125 0.796875 -vt 0.03125 0.71875 -vt 0.03125 0.71875 -vt 0.078125 0.796875 -vt 0.125 0.796875 -vt 0.125 0.71875 -vt 0.078125 0.71875 -vt 0.078125 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.71875 -vt 0.078125 0.71875 -vt 0.078125 0.796875 -vt 0.03125 0.796875 -vt 0.03125 0.796875 -vt 0.078125 0.796875 -vt 0.125 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.796875 -vt 0.125 0.796875 -vn -2.220446049250313e-16 -1 -2.220446049250313e-16 -vn 4.930380657631324e-32 2.220446049250313e-16 -1 -vn 2.220446049250313e-16 1 2.220446049250313e-16 -vn -4.930380657631324e-32 -2.220446049250313e-16 1 -vn -1 2.220446049250313e-16 4.930380657631324e-32 -vn 1 -2.220446049250313e-16 -4.930380657631324e-32 -usemtl m_eacaae49-c631-7fce-d186-9315d408fc43 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o right_leg -v 0.25 0.0625 0.3125 -v 0.25 0.0625 0.3125 -v 0.5625 0.0625 0.3125 -v 0.5625 0.0625 0.3125 -v 0.25 0.0625 0.125 -v 0.25 0.0625 0.125 -v 0.5625 0.0625 0.125 -v 0.5625 0.0625 0.125 -vt 0.03125 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.71875 -vt 0.03125 0.71875 -vt 0.03125 0.796875 -vt 0.03125 0.796875 -vt 0.03125 0.71875 -vt 0.03125 0.71875 -vt 0.078125 0.796875 -vt 0.125 0.796875 -vt 0.125 0.71875 -vt 0.078125 0.71875 -vt 0.078125 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.71875 -vt 0.078125 0.71875 -vt 0.078125 0.796875 -vt 0.03125 0.796875 -vt 0.03125 0.796875 -vt 0.078125 0.796875 -vt 0.125 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.796875 -vt 0.125 0.796875 -vn 2.220446049250313e-16 1 -2.220446049250313e-16 -vn 4.930380657631324e-32 2.220446049250313e-16 1 -vn -2.220446049250313e-16 -1 2.220446049250313e-16 -vn -4.930380657631324e-32 -2.220446049250313e-16 -1 -vn -1 2.220446049250313e-16 -4.930380657631324e-32 -vn 1 -2.220446049250313e-16 4.930380657631324e-32 -usemtl m_eacaae49-c631-7fce-d186-9315d408fc43 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o left_arm -v -0.25 0.0625 -0.1875 -v -0.25 0.0625 -0.1875 -v -0.5625 0.0625 -0.1875 -v -0.5625 0.0625 -0.1875 -v -0.25 0.0625 -0.375 -v -0.25 0.0625 -0.375 -v -0.5625 0.0625 -0.375 -v -0.5625 0.0625 -0.375 -vt 0.03125 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.71875 -vt 0.03125 0.71875 -vt 0.03125 0.796875 -vt 0.03125 0.796875 -vt 0.03125 0.71875 -vt 0.03125 0.71875 -vt 0.078125 0.796875 -vt 0.125 0.796875 -vt 0.125 0.71875 -vt 0.078125 0.71875 -vt 0.078125 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.71875 -vt 0.078125 0.71875 -vt 0.078125 0.796875 -vt 0.03125 0.796875 -vt 0.03125 0.796875 -vt 0.078125 0.796875 -vt 0.125 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.796875 -vt 0.125 0.796875 -vn 2.220446049250313e-16 -1 -2.220446049250313e-16 -vn 4.930380657631324e-32 -2.220446049250313e-16 1 -vn -2.220446049250313e-16 1 2.220446049250313e-16 -vn -4.930380657631324e-32 2.220446049250313e-16 -1 -vn 1 2.220446049250313e-16 4.930380657631324e-32 -vn -1 -2.220446049250313e-16 -4.930380657631324e-32 -usemtl m_eacaae49-c631-7fce-d186-9315d408fc43 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o left_leg -v -0.25 0.0625 0.125 -v -0.25 0.0625 0.125 -v -0.5625 0.0625 0.125 -v -0.5625 0.0625 0.125 -v -0.25 0.0625 0.3125 -v -0.25 0.0625 0.3125 -v -0.5625 0.0625 0.3125 -v -0.5625 0.0625 0.3125 -vt 0.03125 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.71875 -vt 0.03125 0.71875 -vt 0.03125 0.796875 -vt 0.03125 0.796875 -vt 0.03125 0.71875 -vt 0.03125 0.71875 -vt 0.078125 0.796875 -vt 0.125 0.796875 -vt 0.125 0.71875 -vt 0.078125 0.71875 -vt 0.078125 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.71875 -vt 0.078125 0.71875 -vt 0.078125 0.796875 -vt 0.03125 0.796875 -vt 0.03125 0.796875 -vt 0.078125 0.796875 -vt 0.125 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.796875 -vt 0.125 0.796875 -vn -2.220446049250313e-16 1 -2.220446049250313e-16 -vn 4.930380657631324e-32 -2.220446049250313e-16 -1 -vn 2.220446049250313e-16 -1 2.220446049250313e-16 -vn -4.930380657631324e-32 2.220446049250313e-16 1 -vn 1 2.220446049250313e-16 -4.930380657631324e-32 -vn -1 -2.220446049250313e-16 4.930380657631324e-32 -usemtl m_eacaae49-c631-7fce-d186-9315d408fc43 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o tail -v 0 0.3125 1 -v 0 0.3125 0.25 -v 0 0 1 -v 0 0 0.25 -v 0 0.3125 0.25 -v 0 0.3125 1 -v 0 0 0.25 -v 0 0 1 -vt 0.21875 0.515625 -vt 0.21875 0.515625 -vt 0.21875 0.4375 -vt 0.21875 0.4375 -vt 0.03125 0.515625 -vt 0.21875 0.515625 -vt 0.21875 0.4375 -vt 0.03125 0.4375 -vt 0.40625 0.515625 -vt 0.40625 0.515625 -vt 0.40625 0.4375 -vt 0.40625 0.4375 -vt 0.21875 0.515625 -vt 0.40625 0.515625 -vt 0.40625 0.4375 -vt 0.21875 0.4375 -vt 0.21875 0.515625 -vt 0.21875 0.515625 -vt 0.21875 0.703125 -vt 0.21875 0.703125 -vt 0.21875 0.703125 -vt 0.21875 0.703125 -vt 0.21875 0.515625 -vt 0.21875 0.515625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_eacaae49-c631-7fce-d186-9315d408fc43 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o head -v 0.25 0.3125 -0.3125 -v 0.25 0.3125 -0.625 -v 0.25 0 -0.3125 -v 0.25 0 -0.625 -v -0.25 0.3125 -0.625 -v -0.25 0.3125 -0.3125 -v -0.25 0 -0.625 -v -0.25 0 -0.3125 -vt 0.078125 0.90625 -vt 0.203125 0.90625 -vt 0.203125 0.828125 -vt 0.078125 0.828125 -vt 0 0.90625 -vt 0.078125 0.90625 -vt 0.078125 0.828125 -vt 0 0.828125 -vt 0.28125 0.90625 -vt 0.40625 0.90625 -vt 0.40625 0.828125 -vt 0.28125 0.828125 -vt 0.203125 0.90625 -vt 0.28125 0.90625 -vt 0.28125 0.828125 -vt 0.203125 0.828125 -vt 0.203125 0.90625 -vt 0.078125 0.90625 -vt 0.078125 0.984375 -vt 0.203125 0.984375 -vt 0.328125 0.984375 -vt 0.203125 0.984375 -vt 0.203125 0.90625 -vt 0.328125 0.90625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_eacaae49-c631-7fce-d186-9315d408fc43 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o left_gills -v -0.25 0.4375 -0.375 -v -0.25 0.4375 -0.375 -v -0.25 0 -0.375 -v -0.25 0 -0.375 -v -0.4375 0.4375 -0.375 -v -0.4375 0.4375 -0.375 -v -0.4375 0 -0.375 -v -0.4375 0 -0.375 -vt 0.171875 0.375 -vt 0.21875 0.375 -vt 0.21875 0.265625 -vt 0.171875 0.265625 -vt 0.171875 0.375 -vt 0.171875 0.375 -vt 0.171875 0.265625 -vt 0.171875 0.265625 -vt 0.21875 0.375 -vt 0.265625 0.375 -vt 0.265625 0.265625 -vt 0.21875 0.265625 -vt 0.21875 0.375 -vt 0.21875 0.375 -vt 0.21875 0.265625 -vt 0.21875 0.265625 -vt 0.21875 0.375 -vt 0.171875 0.375 -vt 0.171875 0.375 -vt 0.21875 0.375 -vt 0.265625 0.375 -vt 0.21875 0.375 -vt 0.21875 0.375 -vt 0.265625 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_eacaae49-c631-7fce-d186-9315d408fc43 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o right_gills -v 0.4375 0.4375 -0.375 -v 0.4375 0.4375 -0.375 -v 0.4375 0 -0.375 -v 0.4375 0 -0.375 -v 0.25 0.4375 -0.375 -v 0.25 0.4375 -0.375 -v 0.25 0 -0.375 -v 0.25 0 -0.375 -vt 0 0.375 -vt 0.046875 0.375 -vt 0.046875 0.265625 -vt 0 0.265625 -vt 0 0.375 -vt 0 0.375 -vt 0 0.265625 -vt 0 0.265625 -vt 0.046875 0.375 -vt 0.09375 0.375 -vt 0.09375 0.265625 -vt 0.046875 0.265625 -vt 0.046875 0.375 -vt 0.046875 0.375 -vt 0.046875 0.265625 -vt 0.046875 0.265625 -vt 0.046875 0.375 -vt 0 0.375 -vt 0 0.375 -vt 0.046875 0.375 -vt 0.09375 0.375 -vt 0.046875 0.375 -vt 0.046875 0.375 -vt 0.09375 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_eacaae49-c631-7fce-d186-9315d408fc43 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o top_gills -v 0.25 0.5 -0.375 -v 0.25 0.5 -0.375 -v 0.25 0.3125 -0.375 -v 0.25 0.3125 -0.375 -v -0.25 0.5 -0.375 -v -0.25 0.5 -0.375 -v -0.25 0.3125 -0.375 -v -0.25 0.3125 -0.375 -vt 0.046875 0.421875 -vt 0.171875 0.421875 -vt 0.171875 0.375 -vt 0.046875 0.375 -vt 0.046875 0.421875 -vt 0.046875 0.421875 -vt 0.046875 0.375 -vt 0.046875 0.375 -vt 0.171875 0.421875 -vt 0.296875 0.421875 -vt 0.296875 0.375 -vt 0.171875 0.375 -vt 0.171875 0.421875 -vt 0.171875 0.421875 -vt 0.171875 0.375 -vt 0.171875 0.375 -vt 0.171875 0.421875 -vt 0.046875 0.421875 -vt 0.046875 0.421875 -vt 0.171875 0.421875 -vt 0.296875 0.421875 -vt 0.171875 0.421875 -vt 0.171875 0.421875 -vt 0.296875 0.421875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_eacaae49-c631-7fce-d186-9315d408fc43 -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/blaze.obj b/renderer/viewer/three/entity/models/blaze.obj deleted file mode 100644 index d4037c53f..000000000 --- a/renderer/viewer/three/entity/models/blaze.obj +++ /dev/null @@ -1,601 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o upperBodyParts0 -v -0.5 1.625 -0.0625 -v -0.5 1.625 -0.1875 -v -0.5 1.125 -0.0625 -v -0.5 1.125 -0.1875 -v -0.625 1.625 -0.1875 -v -0.625 1.625 -0.0625 -v -0.625 1.125 -0.1875 -v -0.625 1.125 -0.0625 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.1875 -vt 0.03125 0.1875 -vt 0 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.1875 -vt 0 0.1875 -vt 0.09375 0.4375 -vt 0.125 0.4375 -vt 0.125 0.1875 -vt 0.09375 0.1875 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.09375 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.5 -vt 0.0625 0.5 -vt 0.09375 0.5 -vt 0.0625 0.5 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e49346a5-14a5-1082-ba30-5d05bc57359f -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o upperBodyParts1 -v 0.625 1.625 0.1875 -v 0.625 1.625 0.0625 -v 0.625 1.125 0.1875 -v 0.625 1.125 0.0625 -v 0.5 1.625 0.0625 -v 0.5 1.625 0.1875 -v 0.5 1.125 0.0625 -v 0.5 1.125 0.1875 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.1875 -vt 0.03125 0.1875 -vt 0 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.1875 -vt 0 0.1875 -vt 0.09375 0.4375 -vt 0.125 0.4375 -vt 0.125 0.1875 -vt 0.09375 0.1875 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.09375 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.5 -vt 0.0625 0.5 -vt 0.09375 0.5 -vt 0.0625 0.5 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e49346a5-14a5-1082-ba30-5d05bc57359f -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o upperBodyParts2 -v -0.0625 1.625 0.625 -v -0.0625 1.625 0.5 -v -0.0625 1.125 0.625 -v -0.0625 1.125 0.5 -v -0.1875 1.625 0.5 -v -0.1875 1.625 0.625 -v -0.1875 1.125 0.5 -v -0.1875 1.125 0.625 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.1875 -vt 0.03125 0.1875 -vt 0 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.1875 -vt 0 0.1875 -vt 0.09375 0.4375 -vt 0.125 0.4375 -vt 0.125 0.1875 -vt 0.09375 0.1875 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.09375 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.5 -vt 0.0625 0.5 -vt 0.09375 0.5 -vt 0.0625 0.5 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e49346a5-14a5-1082-ba30-5d05bc57359f -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o upperBodyParts3 -v 0.1875 1.625 -0.5 -v 0.1875 1.625 -0.625 -v 0.1875 1.125 -0.5 -v 0.1875 1.125 -0.625 -v 0.0625 1.625 -0.625 -v 0.0625 1.625 -0.5 -v 0.0625 1.125 -0.625 -v 0.0625 1.125 -0.5 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.1875 -vt 0.03125 0.1875 -vt 0 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.1875 -vt 0 0.1875 -vt 0.09375 0.4375 -vt 0.125 0.4375 -vt 0.125 0.1875 -vt 0.09375 0.1875 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.09375 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.5 -vt 0.0625 0.5 -vt 0.09375 0.5 -vt 0.0625 0.5 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e49346a5-14a5-1082-ba30-5d05bc57359f -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o upperBodyParts4 -v -0.3125 1.125 0.0625 -v -0.3125 1.125 -0.0625 -v -0.3125 0.625 0.0625 -v -0.3125 0.625 -0.0625 -v -0.4375 1.125 -0.0625 -v -0.4375 1.125 0.0625 -v -0.4375 0.625 -0.0625 -v -0.4375 0.625 0.0625 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.1875 -vt 0.03125 0.1875 -vt 0 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.1875 -vt 0 0.1875 -vt 0.09375 0.4375 -vt 0.125 0.4375 -vt 0.125 0.1875 -vt 0.09375 0.1875 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.09375 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.5 -vt 0.0625 0.5 -vt 0.09375 0.5 -vt 0.0625 0.5 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e49346a5-14a5-1082-ba30-5d05bc57359f -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o upperBodyParts5 -v 0.4375 1.125 0.0625 -v 0.4375 1.125 -0.0625 -v 0.4375 0.625 0.0625 -v 0.4375 0.625 -0.0625 -v 0.3125 1.125 -0.0625 -v 0.3125 1.125 0.0625 -v 0.3125 0.625 -0.0625 -v 0.3125 0.625 0.0625 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.1875 -vt 0.03125 0.1875 -vt 0 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.1875 -vt 0 0.1875 -vt 0.09375 0.4375 -vt 0.125 0.4375 -vt 0.125 0.1875 -vt 0.09375 0.1875 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.09375 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.5 -vt 0.0625 0.5 -vt 0.09375 0.5 -vt 0.0625 0.5 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e49346a5-14a5-1082-ba30-5d05bc57359f -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o upperBodyParts6 -v 0.0625 1.125 0.4375 -v 0.0625 1.125 0.3125 -v 0.0625 0.625 0.4375 -v 0.0625 0.625 0.3125 -v -0.0625 1.125 0.3125 -v -0.0625 1.125 0.4375 -v -0.0625 0.625 0.3125 -v -0.0625 0.625 0.4375 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.1875 -vt 0.03125 0.1875 -vt 0 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.1875 -vt 0 0.1875 -vt 0.09375 0.4375 -vt 0.125 0.4375 -vt 0.125 0.1875 -vt 0.09375 0.1875 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.09375 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.5 -vt 0.0625 0.5 -vt 0.09375 0.5 -vt 0.0625 0.5 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e49346a5-14a5-1082-ba30-5d05bc57359f -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o upperBodyParts7 -v 0.0625 1.125 -0.3125 -v 0.0625 1.125 -0.4375 -v 0.0625 0.625 -0.3125 -v 0.0625 0.625 -0.4375 -v -0.0625 1.125 -0.4375 -v -0.0625 1.125 -0.3125 -v -0.0625 0.625 -0.4375 -v -0.0625 0.625 -0.3125 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.1875 -vt 0.03125 0.1875 -vt 0 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.1875 -vt 0 0.1875 -vt 0.09375 0.4375 -vt 0.125 0.4375 -vt 0.125 0.1875 -vt 0.09375 0.1875 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.09375 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.5 -vt 0.0625 0.5 -vt 0.09375 0.5 -vt 0.0625 0.5 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e49346a5-14a5-1082-ba30-5d05bc57359f -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o upperBodyParts8 -v -0.1875 0.5 0.25 -v -0.1875 0.5 0.125 -v -0.1875 0 0.25 -v -0.1875 0 0.125 -v -0.3125 0.5 0.125 -v -0.3125 0.5 0.25 -v -0.3125 0 0.125 -v -0.3125 0 0.25 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.1875 -vt 0.03125 0.1875 -vt 0 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.1875 -vt 0 0.1875 -vt 0.09375 0.4375 -vt 0.125 0.4375 -vt 0.125 0.1875 -vt 0.09375 0.1875 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.09375 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.5 -vt 0.0625 0.5 -vt 0.09375 0.5 -vt 0.0625 0.5 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e49346a5-14a5-1082-ba30-5d05bc57359f -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o upperBodyParts9 -v 0.3125 0.5 -0.125 -v 0.3125 0.5 -0.25 -v 0.3125 0 -0.125 -v 0.3125 0 -0.25 -v 0.1875 0.5 -0.25 -v 0.1875 0.5 -0.125 -v 0.1875 0 -0.25 -v 0.1875 0 -0.125 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.1875 -vt 0.03125 0.1875 -vt 0 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.1875 -vt 0 0.1875 -vt 0.09375 0.4375 -vt 0.125 0.4375 -vt 0.125 0.1875 -vt 0.09375 0.1875 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.09375 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.5 -vt 0.0625 0.5 -vt 0.09375 0.5 -vt 0.0625 0.5 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e49346a5-14a5-1082-ba30-5d05bc57359f -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o upperBodyParts10 -v 0.25 0.5 0.3125 -v 0.25 0.5 0.1875 -v 0.25 0 0.3125 -v 0.25 0 0.1875 -v 0.125 0.5 0.1875 -v 0.125 0.5 0.3125 -v 0.125 0 0.1875 -v 0.125 0 0.3125 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.1875 -vt 0.03125 0.1875 -vt 0 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.1875 -vt 0 0.1875 -vt 0.09375 0.4375 -vt 0.125 0.4375 -vt 0.125 0.1875 -vt 0.09375 0.1875 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.09375 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.5 -vt 0.0625 0.5 -vt 0.09375 0.5 -vt 0.0625 0.5 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e49346a5-14a5-1082-ba30-5d05bc57359f -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 -o upperBodyParts11 -v -0.125 0.5 -0.1875 -v -0.125 0.5 -0.3125 -v -0.125 0 -0.1875 -v -0.125 0 -0.3125 -v -0.25 0.5 -0.3125 -v -0.25 0.5 -0.1875 -v -0.25 0 -0.3125 -v -0.25 0 -0.1875 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.1875 -vt 0.03125 0.1875 -vt 0 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.1875 -vt 0 0.1875 -vt 0.09375 0.4375 -vt 0.125 0.4375 -vt 0.125 0.1875 -vt 0.09375 0.1875 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.09375 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.5 -vt 0.0625 0.5 -vt 0.09375 0.5 -vt 0.0625 0.5 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e49346a5-14a5-1082-ba30-5d05bc57359f -f 92/268/67 95/267/67 93/266/67 90/265/67 -f 91/272/68 92/271/68 90/270/68 89/269/68 -f 96/276/69 91/275/69 89/274/69 94/273/69 -f 95/280/70 96/279/70 94/278/70 93/277/70 -f 94/284/71 89/283/71 90/282/71 93/281/71 -f 95/288/72 92/287/72 91/286/72 96/285/72 -o Head -v 0.25 1.75 0.25 -v 0.25 1.75 -0.25 -v 0.25 1.25 0.25 -v 0.25 1.25 -0.25 -v -0.25 1.75 -0.25 -v -0.25 1.75 0.25 -v -0.25 1.25 -0.25 -v -0.25 1.25 0.25 -vt 0.125 0.75 -vt 0.25 0.75 -vt 0.25 0.5 -vt 0.125 0.5 -vt 0 0.75 -vt 0.125 0.75 -vt 0.125 0.5 -vt 0 0.5 -vt 0.375 0.75 -vt 0.5 0.75 -vt 0.5 0.5 -vt 0.375 0.5 -vt 0.25 0.75 -vt 0.375 0.75 -vt 0.375 0.5 -vt 0.25 0.5 -vt 0.25 0.75 -vt 0.125 0.75 -vt 0.125 1 -vt 0.25 1 -vt 0.375 1 -vt 0.25 1 -vt 0.25 0.75 -vt 0.375 0.75 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e49346a5-14a5-1082-ba30-5d05bc57359f -f 100/292/73 103/291/73 101/290/73 98/289/73 -f 99/296/74 100/295/74 98/294/74 97/293/74 -f 104/300/75 99/299/75 97/298/75 102/297/75 -f 103/304/76 104/303/76 102/302/76 101/301/76 -f 102/308/77 97/307/77 98/306/77 101/305/77 -f 103/312/78 100/311/78 99/310/78 104/309/78 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/boat.obj b/renderer/viewer/three/entity/models/boat.obj deleted file mode 100644 index 72b2ca2ab..000000000 --- a/renderer/viewer/three/entity/models/boat.obj +++ /dev/null @@ -1,417 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o bottom -v 0.875 1.3125000000000002 -0.5 -v 0.875 1.1250000000000002 -0.5 -v 0.875 1.3125 0.5 -v 0.875 1.125 0.5 -v -0.875 1.1250000000000002 -0.5 -v -0.875 1.3125000000000002 -0.5 -v -0.875 1.125 0.5 -v -0.875 1.3125 0.5 -vt 0.2421875 0.953125 -vt 0.0234375 0.953125 -vt 0.0234375 0.703125 -vt 0.2421875 0.703125 -vt 0.265625 0.953125 -vt 0.2421875 0.953125 -vt 0.2421875 0.703125 -vt 0.265625 0.703125 -vt 0.484375 0.953125 -vt 0.265625 0.953125 -vt 0.265625 0.703125 -vt 0.484375 0.703125 -vt 0.0234375 0.953125 -vt 0 0.953125 -vt 0 0.703125 -vt 0.0234375 0.703125 -vt 0.0234375 0.953125 -vt 0.2421875 0.953125 -vt 0.2421875 1 -vt 0.0234375 1 -vt 0.2421875 1 -vt 0.4609375 1 -vt 0.4609375 0.953125 -vt 0.2421875 0.953125 -vn 0 -1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 -1 -vn 0 -2.220446049250313e-16 1 -usemtl m_e12ce080-c1e9-6394-d577-2c59cc23ff2d -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o front -v -0.9999999999999999 1.6875 0.5 -v -0.8749999999999999 1.6875 0.5 -v -0.9999999999999999 1.3125 0.5 -v -0.8749999999999999 1.3125 0.5 -v -0.8750000000000001 1.6875 -0.5 -v -1 1.6875 -0.5 -v -0.8750000000000001 1.3125 -0.5 -v -1 1.3125 -0.5 -vt 0.140625 0.546875 -vt 0.015625 0.546875 -vt 0.015625 0.453125 -vt 0.140625 0.453125 -vt 0.15625 0.546875 -vt 0.140625 0.546875 -vt 0.140625 0.453125 -vt 0.15625 0.453125 -vt 0.28125 0.546875 -vt 0.15625 0.546875 -vt 0.15625 0.453125 -vt 0.28125 0.453125 -vt 0.015625 0.546875 -vt 0 0.546875 -vt 0 0.453125 -vt 0.015625 0.453125 -vt 0.015625 0.546875 -vt 0.140625 0.546875 -vt 0.140625 0.578125 -vt 0.015625 0.578125 -vt 0.140625 0.578125 -vt 0.265625 0.578125 -vt 0.265625 0.546875 -vt 0.140625 0.546875 -vn 1 0 -2.220446049250313e-16 -vn 2.220446049250313e-16 0 1 -vn -1 0 2.220446049250313e-16 -vn -2.220446049250313e-16 0 -1 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e12ce080-c1e9-6394-d577-2c59cc23ff2d -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o back -v 1 1.6875 -0.5625 -v 0.875 1.6875 -0.5625 -v 1 1.3125 -0.5625 -v 0.875 1.3125 -0.5625 -v 0.875 1.6875 0.5625 -v 1 1.6875 0.5625 -v 0.875 1.3125 0.5625 -v 1 1.3125 0.5625 -vt 0.15625 0.671875 -vt 0.015625 0.671875 -vt 0.015625 0.578125 -vt 0.15625 0.578125 -vt 0.171875 0.671875 -vt 0.15625 0.671875 -vt 0.15625 0.578125 -vt 0.171875 0.578125 -vt 0.3125 0.671875 -vt 0.171875 0.671875 -vt 0.171875 0.578125 -vt 0.3125 0.578125 -vt 0.015625 0.671875 -vt 0 0.671875 -vt 0 0.578125 -vt 0.015625 0.578125 -vt 0.015625 0.671875 -vt 0.15625 0.671875 -vt 0.15625 0.703125 -vt 0.015625 0.703125 -vt 0.15625 0.703125 -vt 0.296875 0.703125 -vt 0.296875 0.671875 -vt 0.15625 0.671875 -vn -1 0 -2.220446049250313e-16 -vn 2.220446049250313e-16 0 -1 -vn 1 0 2.220446049250313e-16 -vn -2.220446049250313e-16 0 1 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e12ce080-c1e9-6394-d577-2c59cc23ff2d -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o right -v -0.875 1.6875 -0.6250000000000001 -v -0.875 1.6875 -0.5000000000000001 -v -0.875 1.3125 -0.6250000000000001 -v -0.875 1.3125 -0.5000000000000001 -v 0.875 1.6875 -0.4999999999999999 -v 0.875 1.6875 -0.6249999999999999 -v 0.875 1.3125 -0.4999999999999999 -v 0.875 1.3125 -0.6249999999999999 -vt 0.234375 0.421875 -vt 0.015625 0.421875 -vt 0.015625 0.328125 -vt 0.234375 0.328125 -vt 0.25 0.421875 -vt 0.234375 0.421875 -vt 0.234375 0.328125 -vt 0.25 0.328125 -vt 0.46875 0.421875 -vt 0.25 0.421875 -vt 0.25 0.328125 -vt 0.46875 0.328125 -vt 0.015625 0.421875 -vt 0 0.421875 -vt 0 0.328125 -vt 0.015625 0.328125 -vt 0.015625 0.421875 -vt 0.234375 0.421875 -vt 0.234375 0.453125 -vt 0.015625 0.453125 -vt 0.234375 0.453125 -vt 0.453125 0.453125 -vt 0.453125 0.421875 -vt 0.234375 0.421875 -vn -1.2246467991473532e-16 0 1 -vn -1 0 -1.2246467991473532e-16 -vn 1.2246467991473532e-16 0 -1 -vn 1 0 1.2246467991473532e-16 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e12ce080-c1e9-6394-d577-2c59cc23ff2d -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o left -v 0.875 1.6875 0.625 -v 0.875 1.6875 0.5 -v 0.875 1.3125 0.625 -v 0.875 1.3125 0.5 -v -0.875 1.6875 0.5 -v -0.875 1.6875 0.625 -v -0.875 1.3125 0.5 -v -0.875 1.3125 0.625 -vt 0.234375 0.296875 -vt 0.015625 0.296875 -vt 0.015625 0.203125 -vt 0.234375 0.203125 -vt 0.25 0.296875 -vt 0.234375 0.296875 -vt 0.234375 0.203125 -vt 0.25 0.203125 -vt 0.46875 0.296875 -vt 0.25 0.296875 -vt 0.25 0.203125 -vt 0.46875 0.203125 -vt 0.015625 0.296875 -vt 0 0.296875 -vt 0 0.203125 -vt 0.015625 0.203125 -vt 0.015625 0.296875 -vt 0.234375 0.296875 -vt 0.234375 0.328125 -vt 0.015625 0.328125 -vt 0.234375 0.328125 -vt 0.453125 0.328125 -vt 0.453125 0.296875 -vt 0.234375 0.296875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e12ce080-c1e9-6394-d577-2c59cc23ff2d -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o paddle_left -v 0.21875 1.4135015877365276 1.2703323467065926 -v 0.21875 1.9760015877365271 0.29605376744909906 -v 0.21875 1.3052484122634724 1.2078323467065926 -v 0.21875 1.8677484122634724 0.23355376744909906 -v 0.09375 1.9760015877365271 0.29605376744909906 -v 0.09375 1.4135015877365276 1.2703323467065926 -v 0.09375 1.8677484122634724 0.23355376744909906 -v 0.09375 1.3052484122634724 1.2078323467065926 -vt 0.640625 0.71875 -vt 0.625 0.71875 -vt 0.625 0.6875 -vt 0.640625 0.6875 -vt 0.78125 0.71875 -vt 0.640625 0.71875 -vt 0.640625 0.6875 -vt 0.78125 0.6875 -vt 0.796875 0.71875 -vt 0.78125 0.71875 -vt 0.78125 0.6875 -vt 0.796875 0.6875 -vt 0.625 0.71875 -vt 0.484375 0.71875 -vt 0.484375 0.6875 -vt 0.625 0.6875 -vt 0.625 0.71875 -vt 0.640625 0.71875 -vt 0.640625 1 -vt 0.625 1 -vt 0.640625 1 -vt 0.65625 1 -vt 0.65625 0.71875 -vt 0.640625 0.71875 -vn 0 0.49999999999999994 -0.8660254037844387 -vn 1 0 0 -vn 0 -0.49999999999999994 0.8660254037844387 -vn -1 0 0 -vn 0 0.8660254037844387 0.49999999999999994 -vn 0 -0.8660254037844387 -0.49999999999999994 -usemtl m_e12ce080-c1e9-6394-d577-2c59cc23ff2d -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o paddle_left -v 0.156875 1.4821313509461098 1.5264621099161748 -v 0.156875 1.7008813509461098 1.147575995760483 -v 0.156875 1.1573718245269453 1.3389621099161748 -v 0.156875 1.3761218245269453 0.960075995760483 -v 0.09437499999999999 1.7008813509461098 1.147575995760483 -v 0.09437499999999999 1.4821313509461098 1.5264621099161748 -v 0.09437499999999999 1.3761218245269453 0.960075995760483 -v 0.09437499999999999 1.1573718245269453 1.3389621099161748 -vt 0.546875 0.890625 -vt 0.5390625 0.890625 -vt 0.5390625 0.796875 -vt 0.546875 0.796875 -vt 0.6015625 0.890625 -vt 0.546875 0.890625 -vt 0.546875 0.796875 -vt 0.6015625 0.796875 -vt 0.609375 0.890625 -vt 0.6015625 0.890625 -vt 0.6015625 0.796875 -vt 0.609375 0.796875 -vt 0.5390625 0.890625 -vt 0.484375 0.890625 -vt 0.484375 0.796875 -vt 0.5390625 0.796875 -vt 0.5390625 0.890625 -vt 0.546875 0.890625 -vt 0.546875 1 -vt 0.5390625 1 -vt 0.546875 1 -vt 0.5546875 1 -vt 0.5546875 0.890625 -vt 0.546875 0.890625 -vn 0 0.49999999999999994 -0.8660254037844387 -vn 1 0 0 -vn 0 -0.49999999999999994 0.8660254037844387 -vn -1 0 0 -vn 0 0.8660254037844387 0.49999999999999994 -vn 0 -0.8660254037844387 -0.49999999999999994 -usemtl m_e12ce080-c1e9-6394-d577-2c59cc23ff2d -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o paddle_right -v 0.09374999999999989 1.4135015877365273 -1.2703323467065928 -v 0.09375 1.9760015877365271 -0.29605376744909917 -v 0.09374999999999989 1.3052484122634724 -1.2078323467065928 -v 0.09375 1.8677484122634724 -0.23355376744909917 -v 0.21875 1.9760015877365271 -0.29605376744909917 -v 0.2187499999999999 1.4135015877365273 -1.2703323467065928 -v 0.21875 1.8677484122634724 -0.23355376744909917 -v 0.21875 1.3052484122634724 -1.2078323467065928 -vt 0.640625 0.40625 -vt 0.625 0.40625 -vt 0.625 0.375 -vt 0.640625 0.375 -vt 0.78125 0.40625 -vt 0.640625 0.40625 -vt 0.640625 0.375 -vt 0.78125 0.375 -vt 0.796875 0.40625 -vt 0.78125 0.40625 -vt 0.78125 0.375 -vt 0.796875 0.375 -vt 0.625 0.40625 -vt 0.484375 0.40625 -vt 0.484375 0.375 -vt 0.625 0.375 -vt 0.625 0.40625 -vt 0.640625 0.40625 -vt 0.640625 0.6875 -vt 0.625 0.6875 -vt 0.640625 0.6875 -vt 0.65625 0.6875 -vt 0.65625 0.40625 -vt 0.640625 0.40625 -vn 1.0605752387249069e-16 0.49999999999999994 0.8660254037844387 -vn -1 -1.848892746611746e-32 1.224646799147353e-16 -vn -1.0605752387249069e-16 -0.49999999999999994 -0.8660254037844387 -vn 1 1.848892746611746e-32 -1.224646799147353e-16 -vn -6.123233995736765e-17 0.8660254037844388 -0.49999999999999994 -vn 6.123233995736765e-17 -0.8660254037844388 0.49999999999999994 -usemtl m_e12ce080-c1e9-6394-d577-2c59cc23ff2d -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o paddle_right -v 0.09437499999999988 1.4821313509461096 -1.526462109916175 -v 0.09437499999999988 1.7008813509461094 -1.1475759957604832 -v 0.09437499999999988 1.157371824526945 -1.338962109916175 -v 0.09437499999999988 1.376121824526945 -0.9600759957604832 -v 0.15687499999999988 1.7008813509461094 -1.1475759957604832 -v 0.15687499999999988 1.4821313509461096 -1.526462109916175 -v 0.15687499999999988 1.376121824526945 -0.9600759957604832 -v 0.15687499999999988 1.157371824526945 -1.338962109916175 -vt 0.546875 0.578125 -vt 0.5390625 0.578125 -vt 0.5390625 0.484375 -vt 0.546875 0.484375 -vt 0.6015625 0.578125 -vt 0.546875 0.578125 -vt 0.546875 0.484375 -vt 0.6015625 0.484375 -vt 0.609375 0.578125 -vt 0.6015625 0.578125 -vt 0.6015625 0.484375 -vt 0.609375 0.484375 -vt 0.5390625 0.578125 -vt 0.484375 0.578125 -vt 0.484375 0.484375 -vt 0.5390625 0.484375 -vt 0.5390625 0.578125 -vt 0.546875 0.578125 -vt 0.546875 0.6875 -vt 0.5390625 0.6875 -vt 0.546875 0.6875 -vt 0.5546875 0.6875 -vt 0.5546875 0.578125 -vt 0.546875 0.578125 -vn 1.0605752387249069e-16 0.49999999999999994 0.8660254037844387 -vn -1 -1.848892746611746e-32 1.224646799147353e-16 -vn -1.0605752387249069e-16 -0.49999999999999994 -0.8660254037844387 -vn 1 1.848892746611746e-32 -1.224646799147353e-16 -vn -6.123233995736765e-17 0.8660254037844388 -0.49999999999999994 -vn 6.123233995736765e-17 -0.8660254037844388 0.49999999999999994 -usemtl m_e12ce080-c1e9-6394-d577-2c59cc23ff2d -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/camel.obj b/renderer/viewer/three/entity/models/camel.obj deleted file mode 100644 index 8c8f050ac..000000000 --- a/renderer/viewer/three/entity/models/camel.obj +++ /dev/null @@ -1,1061 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.46875 2 0.8125 -v 0.46875 2 -0.875 -v 0.46875 1.25 0.8125 -v 0.46875 1.25 -0.875 -v -0.46875 2 -0.875 -v -0.46875 2 0.8125 -v -0.46875 1.25 -0.875 -v -0.46875 1.25 0.8125 -vt 0.2109375 0.59375 -vt 0.328125 0.59375 -vt 0.328125 0.5 -vt 0.2109375 0.5 -vt 0 0.59375 -vt 0.2109375 0.59375 -vt 0.2109375 0.5 -vt 0 0.5 -vt 0.5390625 0.59375 -vt 0.65625 0.59375 -vt 0.65625 0.5 -vt 0.5390625 0.5 -vt 0.328125 0.59375 -vt 0.5390625 0.59375 -vt 0.5390625 0.5 -vt 0.328125 0.5 -vt 0.328125 0.59375 -vt 0.2109375 0.59375 -vt 0.2109375 0.8046875 -vt 0.328125 0.8046875 -vt 0.4453125 0.8046875 -vt 0.328125 0.8046875 -vt 0.328125 0.59375 -vt 0.4453125 0.59375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o saddle layer -v 0.2875 2.31875 0.31875 -v 0.2875 2.31875 -0.38125 -v 0.2875 1.99375 0.31875 -v 0.2875 1.99375 -0.38125 -v -0.2875 2.31875 -0.38125 -v -0.2875 2.31875 0.31875 -v -0.2875 1.99375 -0.38125 -v -0.2875 1.99375 0.31875 -vt 0.6640625 0.4140625 -vt 0.734375 0.4140625 -vt 0.734375 0.375 -vt 0.6640625 0.375 -vt 0.578125 0.4140625 -vt 0.6640625 0.4140625 -vt 0.6640625 0.375 -vt 0.578125 0.375 -vt 0.8203125 0.4140625 -vt 0.890625 0.4140625 -vt 0.890625 0.375 -vt 0.8203125 0.375 -vt 0.734375 0.4140625 -vt 0.8203125 0.4140625 -vt 0.8203125 0.375 -vt 0.734375 0.375 -vt 0.734375 0.4140625 -vt 0.6640625 0.4140625 -vt 0.6640625 0.5 -vt 0.734375 0.5 -vt 0.8046875 0.5 -vt 0.734375 0.5 -vt 0.734375 0.4140625 -vt 0.8046875 0.4140625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o saddle layer -v 0.22499999999999998 2.50625 0.31875 -v 0.22499999999999998 2.50625 -0.38125 -v 0.22499999999999998 2.30625 0.31875 -v 0.22499999999999998 2.30625 -0.38125 -v -0.22499999999999998 2.50625 -0.38125 -v -0.22499999999999998 2.50625 0.31875 -v -0.22499999999999998 2.30625 -0.38125 -v -0.22499999999999998 2.30625 0.31875 -vt 0.8046875 0.0234375 -vt 0.859375 0.0234375 -vt 0.859375 0 -vt 0.8046875 0 -vt 0.71875 0.0234375 -vt 0.8046875 0.0234375 -vt 0.8046875 0 -vt 0.71875 0 -vt 0.9453125 0.0234375 -vt 1 0.0234375 -vt 1 0 -vt 0.9453125 0 -vt 0.859375 0.0234375 -vt 0.9453125 0.0234375 -vt 0.9453125 0 -vt 0.859375 0 -vt 0.859375 0.0234375 -vt 0.8046875 0.0234375 -vt 0.8046875 0.109375 -vt 0.859375 0.109375 -vt 0.9140625 0.109375 -vt 0.859375 0.109375 -vt 0.859375 0.0234375 -vt 0.9140625 0.0234375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o saddle layer -v 0.475 2.00625 0.8187500000000001 -v 0.475 2.00625 -0.88125 -v 0.475 1.24375 0.8187500000000001 -v 0.475 1.24375 -0.88125 -v -0.475 2.00625 -0.88125 -v -0.475 2.00625 0.8187500000000001 -v -0.475 1.24375 -0.88125 -v -0.475 1.24375 0.8187500000000001 -vt 0.2109375 0.09375 -vt 0.328125 0.09375 -vt 0.328125 0 -vt 0.2109375 0 -vt 0 0.09375 -vt 0.2109375 0.09375 -vt 0.2109375 0 -vt 0 0 -vt 0.5390625 0.09375 -vt 0.65625 0.09375 -vt 0.65625 0 -vt 0.5390625 0 -vt 0.328125 0.09375 -vt 0.5390625 0.09375 -vt 0.5390625 0 -vt 0.328125 0 -vt 0.328125 0.09375 -vt 0.2109375 0.09375 -vt 0.2109375 0.3046875 -vt 0.328125 0.3046875 -vt 0.4453125 0.3046875 -vt 0.328125 0.3046875 -vt 0.328125 0.09375 -vt 0.4453125 0.09375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o tail -v -0.09375 1.8125 0.8125 -v -0.09375 1.8125 0.8125 -v -0.09375 0.9375 0.8125 -v -0.09375 0.9375 0.8125 -v 0.09375 1.8125 0.8125 -v 0.09375 1.8125 0.8125 -v 0.09375 0.9375 0.8125 -v 0.09375 0.9375 0.8125 -vt 0.953125 1 -vt 0.9765625 1 -vt 0.9765625 0.890625 -vt 0.953125 0.890625 -vt 0.953125 1 -vt 0.953125 1 -vt 0.953125 0.890625 -vt 0.953125 0.890625 -vt 0.9765625 1 -vt 1 1 -vt 1 0.890625 -vt 0.9765625 0.890625 -vt 0.9765625 1 -vt 0.9765625 1 -vt 0.9765625 0.890625 -vt 0.9765625 0.890625 -vt 0.9765625 1 -vt 0.953125 1 -vt 0.953125 1 -vt 0.9765625 1 -vt 1 1 -vt 0.9765625 1 -vt 0.9765625 1 -vt 1 1 -vn 1.2246467991473532e-16 0 1 -vn -1 0 1.2246467991473532e-16 -vn -1.2246467991473532e-16 0 -1 -vn 1 0 -1.2246467991473532e-16 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o head -v 0.21875 1.875 -0.375 -v 0.21875 1.875 -1.5625 -v 0.21875 1.375 -0.375 -v 0.21875 1.375 -1.5625 -v -0.21875 1.875 -1.5625 -v -0.21875 1.875 -0.375 -v -0.21875 1.375 -1.5625 -v -0.21875 1.375 -0.375 -vt 0.6171875 0.6640625 -vt 0.671875 0.6640625 -vt 0.671875 0.6015625 -vt 0.6171875 0.6015625 -vt 0.46875 0.6640625 -vt 0.6171875 0.6640625 -vt 0.6171875 0.6015625 -vt 0.46875 0.6015625 -vt 0.8203125 0.6640625 -vt 0.875 0.6640625 -vt 0.875 0.6015625 -vt 0.8203125 0.6015625 -vt 0.671875 0.6640625 -vt 0.8203125 0.6640625 -vt 0.8203125 0.6015625 -vt 0.671875 0.6015625 -vt 0.671875 0.6640625 -vt 0.6171875 0.6640625 -vt 0.6171875 0.8125 -vt 0.671875 0.8125 -vt 0.7265625 0.8125 -vt 0.671875 0.8125 -vt 0.671875 0.6640625 -vt 0.7265625 0.6640625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o head -v 0.21875 2.75 -1.125 -v 0.21875 2.75 -1.5625 -v 0.21875 1.875 -1.125 -v 0.21875 1.875 -1.5625 -v -0.21875 2.75 -1.5625 -v -0.21875 2.75 -1.125 -v -0.21875 1.875 -1.5625 -v -0.21875 1.875 -1.125 -vt 0.21875 0.9453125 -vt 0.2734375 0.9453125 -vt 0.2734375 0.8359375 -vt 0.21875 0.8359375 -vt 0.1640625 0.9453125 -vt 0.21875 0.9453125 -vt 0.21875 0.8359375 -vt 0.1640625 0.8359375 -vt 0.328125 0.9453125 -vt 0.3828125 0.9453125 -vt 0.3828125 0.8359375 -vt 0.328125 0.8359375 -vt 0.2734375 0.9453125 -vt 0.328125 0.9453125 -vt 0.328125 0.8359375 -vt 0.2734375 0.8359375 -vt 0.2734375 0.9453125 -vt 0.21875 0.9453125 -vt 0.21875 1 -vt 0.2734375 1 -vt 0.328125 1 -vt 0.2734375 1 -vt 0.2734375 0.9453125 -vt 0.328125 0.9453125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o head -v 0.15625 2.75 -1.5625 -v 0.15625 2.75 -1.9375 -v 0.15625 2.4375 -1.5625 -v 0.15625 2.4375 -1.9375 -v -0.15625 2.75 -1.9375 -v -0.15625 2.75 -1.5625 -v -0.15625 2.4375 -1.9375 -v -0.15625 2.4375 -1.5625 -vt 0.4375 0.953125 -vt 0.4765625 0.953125 -vt 0.4765625 0.9140625 -vt 0.4375 0.9140625 -vt 0.390625 0.953125 -vt 0.4375 0.953125 -vt 0.4375 0.9140625 -vt 0.390625 0.9140625 -vt 0.5234375 0.953125 -vt 0.5625 0.953125 -vt 0.5625 0.9140625 -vt 0.5234375 0.9140625 -vt 0.4765625 0.953125 -vt 0.5234375 0.953125 -vt 0.5234375 0.9140625 -vt 0.4765625 0.9140625 -vt 0.4765625 0.953125 -vt 0.4375 0.953125 -vt 0.4375 1 -vt 0.4765625 1 -vt 0.515625 1 -vt 0.4765625 1 -vt 0.4765625 0.953125 -vt 0.515625 0.953125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o bridle layer -v 0.22499999999999998 1.88125 -0.36875 -v 0.22499999999999998 1.88125 -1.56875 -v 0.22499999999999998 1.36875 -0.36875 -v 0.22499999999999998 1.36875 -1.56875 -v -0.22499999999999998 1.88125 -1.56875 -v -0.22499999999999998 1.88125 -0.36875 -v -0.22499999999999998 1.36875 -1.56875 -v -0.22499999999999998 1.36875 -0.36875 -vt 0.6171875 0.171875 -vt 0.671875 0.171875 -vt 0.671875 0.109375 -vt 0.6171875 0.109375 -vt 0.46875 0.171875 -vt 0.6171875 0.171875 -vt 0.6171875 0.109375 -vt 0.46875 0.109375 -vt 0.8203125 0.171875 -vt 0.875 0.171875 -vt 0.875 0.109375 -vt 0.8203125 0.109375 -vt 0.671875 0.171875 -vt 0.8203125 0.171875 -vt 0.8203125 0.109375 -vt 0.671875 0.109375 -vt 0.671875 0.171875 -vt 0.6171875 0.171875 -vt 0.6171875 0.3203125 -vt 0.671875 0.3203125 -vt 0.7265625 0.3203125 -vt 0.671875 0.3203125 -vt 0.671875 0.171875 -vt 0.7265625 0.171875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o bridle layer -v 0.22499999999999998 2.75625 -1.11875 -v 0.22499999999999998 2.75625 -1.56875 -v 0.22499999999999998 1.86875 -1.11875 -v 0.22499999999999998 1.86875 -1.56875 -v -0.22499999999999998 2.75625 -1.56875 -v -0.22499999999999998 2.75625 -1.11875 -v -0.22499999999999998 1.86875 -1.56875 -v -0.22499999999999998 1.86875 -1.11875 -vt 0.21875 0.4453125 -vt 0.2734375 0.4453125 -vt 0.2734375 0.3359375 -vt 0.21875 0.3359375 -vt 0.1640625 0.4453125 -vt 0.21875 0.4453125 -vt 0.21875 0.3359375 -vt 0.1640625 0.3359375 -vt 0.328125 0.4453125 -vt 0.3828125 0.4453125 -vt 0.3828125 0.3359375 -vt 0.328125 0.3359375 -vt 0.2734375 0.4453125 -vt 0.328125 0.4453125 -vt 0.328125 0.3359375 -vt 0.2734375 0.3359375 -vt 0.2734375 0.4453125 -vt 0.21875 0.4453125 -vt 0.21875 0.5 -vt 0.2734375 0.5 -vt 0.328125 0.5 -vt 0.2734375 0.5 -vt 0.2734375 0.4453125 -vt 0.328125 0.4453125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o bridle layer -v 0.16249999999999998 2.75625 -1.5625 -v 0.16249999999999998 2.75625 -1.9500000000000002 -v 0.16249999999999998 2.43125 -1.5625 -v 0.16249999999999998 2.43125 -1.9500000000000002 -v -0.16249999999999998 2.75625 -1.9500000000000002 -v -0.16249999999999998 2.75625 -1.5625 -v -0.16249999999999998 2.43125 -1.9500000000000002 -v -0.16249999999999998 2.43125 -1.5625 -vt 0.4375 0.453125 -vt 0.4765625 0.453125 -vt 0.4765625 0.4140625 -vt 0.4375 0.4140625 -vt 0.390625 0.453125 -vt 0.4375 0.453125 -vt 0.4375 0.4140625 -vt 0.390625 0.4140625 -vt 0.5234375 0.453125 -vt 0.5625 0.453125 -vt 0.5625 0.4140625 -vt 0.5234375 0.4140625 -vt 0.4765625 0.453125 -vt 0.5234375 0.453125 -vt 0.5234375 0.4140625 -vt 0.4765625 0.4140625 -vt 0.4765625 0.453125 -vt 0.4375 0.453125 -vt 0.4375 0.5 -vt 0.4765625 0.5 -vt 0.515625 0.5 -vt 0.4765625 0.5 -vt 0.4765625 0.453125 -vt 0.515625 0.453125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 -o bridle -v -0.15625 2.625 -1.625 -v -0.15625 2.625 -1.75 -v -0.15625 2.5 -1.625 -v -0.15625 2.5 -1.75 -v -0.21875 2.625 -1.75 -v -0.21875 2.625 -1.625 -v -0.21875 2.5 -1.75 -v -0.21875 2.5 -1.625 -vt 0.59375 0.4375 -vt 0.6015625 0.4375 -vt 0.6015625 0.421875 -vt 0.59375 0.421875 -vt 0.578125 0.4375 -vt 0.59375 0.4375 -vt 0.59375 0.421875 -vt 0.578125 0.421875 -vt 0.6171875 0.4375 -vt 0.625 0.4375 -vt 0.625 0.421875 -vt 0.6171875 0.421875 -vt 0.6015625 0.4375 -vt 0.6171875 0.4375 -vt 0.6171875 0.421875 -vt 0.6015625 0.421875 -vt 0.6015625 0.4375 -vt 0.59375 0.4375 -vt 0.59375 0.453125 -vt 0.6015625 0.453125 -vt 0.609375 0.453125 -vt 0.6015625 0.453125 -vt 0.6015625 0.4375 -vt 0.609375 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 92/268/67 95/267/67 93/266/67 90/265/67 -f 91/272/68 92/271/68 90/270/68 89/269/68 -f 96/276/69 91/275/69 89/274/69 94/273/69 -f 95/280/70 96/279/70 94/278/70 93/277/70 -f 94/284/71 89/283/71 90/282/71 93/281/71 -f 95/288/72 92/287/72 91/286/72 96/285/72 -o bridle -v 0.21875 2.625 -1.625 -v 0.21875 2.625 -1.75 -v 0.21875 2.5 -1.625 -v 0.21875 2.5 -1.75 -v 0.15625 2.625 -1.75 -v 0.15625 2.625 -1.625 -v 0.15625 2.5 -1.75 -v 0.15625 2.5 -1.625 -vt 0.6015625 0.4375 -vt 0.59375 0.4375 -vt 0.59375 0.421875 -vt 0.6015625 0.421875 -vt 0.6171875 0.4375 -vt 0.6015625 0.4375 -vt 0.6015625 0.421875 -vt 0.6171875 0.421875 -vt 0.625 0.4375 -vt 0.6171875 0.4375 -vt 0.6171875 0.421875 -vt 0.625 0.421875 -vt 0.59375 0.4375 -vt 0.578125 0.4375 -vt 0.578125 0.421875 -vt 0.59375 0.421875 -vt 0.59375 0.4375 -vt 0.6015625 0.4375 -vt 0.6015625 0.453125 -vt 0.59375 0.453125 -vt 0.6015625 0.453125 -vt 0.609375 0.453125 -vt 0.609375 0.4375 -vt 0.6015625 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 100/292/73 103/291/73 101/290/73 98/289/73 -f 99/296/74 100/295/74 98/294/74 97/293/74 -f 104/300/75 99/299/75 97/298/75 102/297/75 -f 103/304/76 104/303/76 102/302/76 101/301/76 -f 102/308/77 97/307/77 98/306/77 101/305/77 -f 103/312/78 100/311/78 99/310/78 104/309/78 -o left_ear -v -0.1875 2.71875 -1.15625 -v -0.1875 2.71875 -1.28125 -v -0.1875 2.65625 -1.15625 -v -0.1875 2.65625 -1.28125 -v -0.375 2.71875 -1.28125 -v -0.375 2.71875 -1.15625 -v -0.375 2.65625 -1.28125 -v -0.375 2.65625 -1.15625 -vt 0.3671875 0.984375 -vt 0.390625 0.984375 -vt 0.390625 0.9765625 -vt 0.3671875 0.9765625 -vt 0.3515625 0.984375 -vt 0.3671875 0.984375 -vt 0.3671875 0.9765625 -vt 0.3515625 0.9765625 -vt 0.40625 0.984375 -vt 0.4296875 0.984375 -vt 0.4296875 0.9765625 -vt 0.40625 0.9765625 -vt 0.390625 0.984375 -vt 0.40625 0.984375 -vt 0.40625 0.9765625 -vt 0.390625 0.9765625 -vt 0.390625 0.984375 -vt 0.3671875 0.984375 -vt 0.3671875 1 -vt 0.390625 1 -vt 0.4140625 1 -vt 0.390625 1 -vt 0.390625 0.984375 -vt 0.4140625 0.984375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 108/316/79 111/315/79 109/314/79 106/313/79 -f 107/320/80 108/319/80 106/318/80 105/317/80 -f 112/324/81 107/323/81 105/322/81 110/321/81 -f 111/328/82 112/327/82 110/326/82 109/325/82 -f 110/332/83 105/331/83 106/330/83 109/329/83 -f 111/336/84 108/335/84 107/334/84 112/333/84 -o right_ear -v 0.375 2.71875 -1.15625 -v 0.375 2.71875 -1.28125 -v 0.375 2.65625 -1.15625 -v 0.375 2.65625 -1.28125 -v 0.1875 2.71875 -1.28125 -v 0.1875 2.71875 -1.15625 -v 0.1875 2.65625 -1.28125 -v 0.1875 2.65625 -1.15625 -vt 0.5390625 0.984375 -vt 0.5625 0.984375 -vt 0.5625 0.9765625 -vt 0.5390625 0.9765625 -vt 0.5234375 0.984375 -vt 0.5390625 0.984375 -vt 0.5390625 0.9765625 -vt 0.5234375 0.9765625 -vt 0.578125 0.984375 -vt 0.6015625 0.984375 -vt 0.6015625 0.9765625 -vt 0.578125 0.9765625 -vt 0.5625 0.984375 -vt 0.578125 0.984375 -vt 0.578125 0.9765625 -vt 0.5625 0.9765625 -vt 0.5625 0.984375 -vt 0.5390625 0.984375 -vt 0.5390625 1 -vt 0.5625 1 -vt 0.5859375 1 -vt 0.5625 1 -vt 0.5625 0.984375 -vt 0.5859375 0.984375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 116/340/85 119/339/85 117/338/85 114/337/85 -f 115/344/86 116/343/86 114/342/86 113/341/86 -f 120/348/87 115/347/87 113/346/87 118/345/87 -f 119/352/88 120/351/88 118/350/88 117/349/88 -f 118/356/89 113/355/89 114/354/89 117/353/89 -f 119/360/90 116/359/90 115/358/90 120/357/90 -o reins layer -v -0.23125 2.5625 -0.75 -v -0.23125 2.5625 -1.6875 -v -0.23125 2.125 -0.75 -v -0.23125 2.125 -1.6875 -v -0.23125 2.5625 -1.6875 -v -0.23125 2.5625 -0.75 -v -0.23125 2.125 -1.6875 -v -0.23125 2.125 -0.75 -vt 0.8828125 0.5546875 -vt 0.8828125 0.5546875 -vt 0.8828125 0.5 -vt 0.8828125 0.5 -vt 0.765625 0.5546875 -vt 0.8828125 0.5546875 -vt 0.8828125 0.5 -vt 0.765625 0.5 -vt 1 0.5546875 -vt 1 0.5546875 -vt 1 0.5 -vt 1 0.5 -vt 0.8828125 0.5546875 -vt 1 0.5546875 -vt 1 0.5 -vt 0.8828125 0.5 -vt 0.8828125 0.5546875 -vt 0.8828125 0.5546875 -vt 0.8828125 0.671875 -vt 0.8828125 0.671875 -vt 0.8828125 0.671875 -vt 0.8828125 0.671875 -vt 0.8828125 0.5546875 -vt 0.8828125 0.5546875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 124/364/91 127/363/91 125/362/91 122/361/91 -f 123/368/92 124/367/92 122/366/92 121/365/92 -f 128/372/93 123/371/93 121/370/93 126/369/93 -f 127/376/94 128/375/94 126/374/94 125/373/94 -f 126/380/95 121/379/95 122/378/95 125/377/95 -f 127/384/96 124/383/96 123/382/96 128/381/96 -o reins layer -v 0.23124999999999996 2.5625 -0.75 -v 0.23124999999999996 2.5625 -0.75 -v 0.23124999999999996 2.125 -0.75 -v 0.23124999999999996 2.125 -0.75 -v -0.23125 2.5625 -0.75 -v -0.23125 2.5625 -0.75 -v -0.23125 2.125 -0.75 -v -0.23125 2.125 -0.75 -vt 0.65625 0.5546875 -vt 0.7109375 0.5546875 -vt 0.7109375 0.5 -vt 0.65625 0.5 -vt 0.65625 0.5546875 -vt 0.65625 0.5546875 -vt 0.65625 0.5 -vt 0.65625 0.5 -vt 0.7109375 0.5546875 -vt 0.765625 0.5546875 -vt 0.765625 0.5 -vt 0.7109375 0.5 -vt 0.7109375 0.5546875 -vt 0.7109375 0.5546875 -vt 0.7109375 0.5 -vt 0.7109375 0.5 -vt 0.7109375 0.5546875 -vt 0.65625 0.5546875 -vt 0.65625 0.5546875 -vt 0.7109375 0.5546875 -vt 0.765625 0.5546875 -vt 0.7109375 0.5546875 -vt 0.7109375 0.5546875 -vt 0.765625 0.5546875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 132/388/97 135/387/97 133/386/97 130/385/97 -f 131/392/98 132/391/98 130/390/98 129/389/98 -f 136/396/99 131/395/99 129/394/99 134/393/99 -f 135/400/100 136/399/100 134/398/100 133/397/100 -f 134/404/101 129/403/101 130/402/101 133/401/101 -f 135/408/102 132/407/102 131/406/102 136/405/102 -o reins layer -v 0.23124999999999996 2.5625 -0.75 -v 0.23124999999999996 2.5625 -1.6875 -v 0.23124999999999996 2.125 -0.75 -v 0.23124999999999996 2.125 -1.6875 -v 0.23124999999999996 2.5625 -1.6875 -v 0.23124999999999996 2.5625 -0.75 -v 0.23124999999999996 2.125 -1.6875 -v 0.23124999999999996 2.125 -0.75 -vt 0.8828125 0.5546875 -vt 0.8828125 0.5546875 -vt 0.8828125 0.5 -vt 0.8828125 0.5 -vt 0.765625 0.5546875 -vt 0.8828125 0.5546875 -vt 0.8828125 0.5 -vt 0.765625 0.5 -vt 1 0.5546875 -vt 1 0.5546875 -vt 1 0.5 -vt 1 0.5 -vt 0.8828125 0.5546875 -vt 1 0.5546875 -vt 1 0.5 -vt 0.8828125 0.5 -vt 0.8828125 0.5546875 -vt 0.8828125 0.5546875 -vt 0.8828125 0.671875 -vt 0.8828125 0.671875 -vt 0.8828125 0.671875 -vt 0.8828125 0.671875 -vt 0.8828125 0.5546875 -vt 0.8828125 0.5546875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 140/412/103 143/411/103 141/410/103 138/409/103 -f 139/416/104 140/415/104 138/414/104 137/413/104 -f 144/420/105 139/419/105 137/418/105 142/417/105 -f 143/424/106 144/423/106 142/422/106 141/421/106 -f 142/428/107 137/427/107 138/426/107 141/425/107 -f 143/432/108 140/431/108 139/430/108 144/429/108 -o hump -v 0.28125 2.3125 0.3125 -v 0.28125 2.3125 -0.375 -v 0.28125 2 0.3125 -v 0.28125 2 -0.375 -v -0.28125 2.3125 -0.375 -v -0.28125 2.3125 0.3125 -v -0.28125 2 -0.375 -v -0.28125 2 0.3125 -vt 0.6640625 0.9140625 -vt 0.734375 0.9140625 -vt 0.734375 0.875 -vt 0.6640625 0.875 -vt 0.578125 0.9140625 -vt 0.6640625 0.9140625 -vt 0.6640625 0.875 -vt 0.578125 0.875 -vt 0.8203125 0.9140625 -vt 0.890625 0.9140625 -vt 0.890625 0.875 -vt 0.8203125 0.875 -vt 0.734375 0.9140625 -vt 0.8203125 0.9140625 -vt 0.8203125 0.875 -vt 0.734375 0.875 -vt 0.734375 0.9140625 -vt 0.6640625 0.9140625 -vt 0.6640625 1 -vt 0.734375 1 -vt 0.8046875 1 -vt 0.734375 1 -vt 0.734375 0.9140625 -vt 0.8046875 0.9140625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 148/436/109 151/435/109 149/434/109 146/433/109 -f 147/440/110 148/439/110 146/438/110 145/437/110 -f 152/444/111 147/443/111 145/442/111 150/441/111 -f 151/448/112 152/447/112 150/446/112 149/445/112 -f 150/452/113 145/451/113 146/450/113 149/449/113 -f 151/456/114 148/455/114 147/454/114 152/453/114 -o right_front_leg -v 0.4625 1.3125 -0.5 -v 0.4625 1.3125 -0.8125 -v 0.4625 0 -0.5 -v 0.4625 0 -0.8125 -v 0.15000000000000002 1.3125 -0.8125 -v 0.15000000000000002 1.3125 -0.5 -v 0.15000000000000002 0 -0.8125 -v 0.15000000000000002 0 -0.5 -vt 0.0390625 0.7578125 -vt 0.078125 0.7578125 -vt 0.078125 0.59375 -vt 0.0390625 0.59375 -vt 0 0.7578125 -vt 0.0390625 0.7578125 -vt 0.0390625 0.59375 -vt 0 0.59375 -vt 0.1171875 0.7578125 -vt 0.15625 0.7578125 -vt 0.15625 0.59375 -vt 0.1171875 0.59375 -vt 0.078125 0.7578125 -vt 0.1171875 0.7578125 -vt 0.1171875 0.59375 -vt 0.078125 0.59375 -vt 0.078125 0.7578125 -vt 0.0390625 0.7578125 -vt 0.0390625 0.796875 -vt 0.078125 0.796875 -vt 0.1171875 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.7578125 -vt 0.1171875 0.7578125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 156/460/115 159/459/115 157/458/115 154/457/115 -f 155/464/116 156/463/116 154/462/116 153/461/116 -f 160/468/117 155/467/117 153/466/117 158/465/117 -f 159/472/118 160/471/118 158/470/118 157/469/118 -f 158/476/119 153/475/119 154/474/119 157/473/119 -f 159/480/120 156/479/120 155/478/120 160/477/120 -o left_front_leg -v -0.15000000000000002 1.3125 -0.5 -v -0.15000000000000002 1.3125 -0.8125 -v -0.15000000000000002 0 -0.5 -v -0.15000000000000002 0 -0.8125 -v -0.4625 1.3125 -0.8125 -v -0.4625 1.3125 -0.5 -v -0.4625 0 -0.8125 -v -0.4625 0 -0.5 -vt 0.0390625 0.9609375 -vt 0.078125 0.9609375 -vt 0.078125 0.796875 -vt 0.0390625 0.796875 -vt 0 0.9609375 -vt 0.0390625 0.9609375 -vt 0.0390625 0.796875 -vt 0 0.796875 -vt 0.1171875 0.9609375 -vt 0.15625 0.9609375 -vt 0.15625 0.796875 -vt 0.1171875 0.796875 -vt 0.078125 0.9609375 -vt 0.1171875 0.9609375 -vt 0.1171875 0.796875 -vt 0.078125 0.796875 -vt 0.078125 0.9609375 -vt 0.0390625 0.9609375 -vt 0.0390625 1 -vt 0.078125 1 -vt 0.1171875 1 -vt 0.078125 1 -vt 0.078125 0.9609375 -vt 0.1171875 0.9609375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 164/484/121 167/483/121 165/482/121 162/481/121 -f 163/488/122 164/487/122 162/486/122 161/485/122 -f 168/492/123 163/491/123 161/490/123 166/489/123 -f 167/496/124 168/495/124 166/494/124 165/493/124 -f 166/500/125 161/499/125 162/498/125 165/497/125 -f 167/504/126 164/503/126 163/502/126 168/501/126 -o left_hind_leg -v -0.15000000000000002 1.3125 0.75 -v -0.15000000000000002 1.3125 0.4375 -v -0.15000000000000002 0 0.75 -v -0.15000000000000002 0 0.4375 -v -0.4625 1.3125 0.4375 -v -0.4625 1.3125 0.75 -v -0.4625 0 0.4375 -v -0.4625 0 0.75 -vt 0.4921875 0.8359375 -vt 0.53125 0.8359375 -vt 0.53125 0.671875 -vt 0.4921875 0.671875 -vt 0.453125 0.8359375 -vt 0.4921875 0.8359375 -vt 0.4921875 0.671875 -vt 0.453125 0.671875 -vt 0.5703125 0.8359375 -vt 0.609375 0.8359375 -vt 0.609375 0.671875 -vt 0.5703125 0.671875 -vt 0.53125 0.8359375 -vt 0.5703125 0.8359375 -vt 0.5703125 0.671875 -vt 0.53125 0.671875 -vt 0.53125 0.8359375 -vt 0.4921875 0.8359375 -vt 0.4921875 0.875 -vt 0.53125 0.875 -vt 0.5703125 0.875 -vt 0.53125 0.875 -vt 0.53125 0.8359375 -vt 0.5703125 0.8359375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 172/508/127 175/507/127 173/506/127 170/505/127 -f 171/512/128 172/511/128 170/510/128 169/509/128 -f 176/516/129 171/515/129 169/514/129 174/513/129 -f 175/520/130 176/519/130 174/518/130 173/517/130 -f 174/524/131 169/523/131 170/522/131 173/521/131 -f 175/528/132 172/527/132 171/526/132 176/525/132 -o right_hind_leg -v 0.4625 1.3125 0.75 -v 0.4625 1.3125 0.4375 -v 0.4625 0 0.75 -v 0.4625 0 0.4375 -v 0.15000000000000002 1.3125 0.4375 -v 0.15000000000000002 1.3125 0.75 -v 0.15000000000000002 0 0.4375 -v 0.15000000000000002 0 0.75 -vt 0.7734375 0.8359375 -vt 0.8125 0.8359375 -vt 0.8125 0.671875 -vt 0.7734375 0.671875 -vt 0.734375 0.8359375 -vt 0.7734375 0.8359375 -vt 0.7734375 0.671875 -vt 0.734375 0.671875 -vt 0.8515625 0.8359375 -vt 0.890625 0.8359375 -vt 0.890625 0.671875 -vt 0.8515625 0.671875 -vt 0.8125 0.8359375 -vt 0.8515625 0.8359375 -vt 0.8515625 0.671875 -vt 0.8125 0.671875 -vt 0.8125 0.8359375 -vt 0.7734375 0.8359375 -vt 0.7734375 0.875 -vt 0.8125 0.875 -vt 0.8515625 0.875 -vt 0.8125 0.875 -vt 0.8125 0.8359375 -vt 0.8515625 0.8359375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_ef8cbfee-18ba-edcd-78d9-3f4313675f2e -f 180/532/133 183/531/133 181/530/133 178/529/133 -f 179/536/134 180/535/134 178/534/134 177/533/134 -f 184/540/135 179/539/135 177/538/135 182/537/135 -f 183/544/136 184/543/136 182/542/136 181/541/136 -f 182/548/137 177/547/137 178/546/137 181/545/137 -f 183/552/138 180/551/138 179/550/138 184/549/138 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/cat.obj b/renderer/viewer/three/entity/models/cat.obj deleted file mode 100644 index 8067b5c62..000000000 --- a/renderer/viewer/three/entity/models/cat.obj +++ /dev/null @@ -1,509 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.125 0.625 -0.4375 -v 0.125 0.2500000000000001 -0.4375 -v 0.125 0.625 0.5625 -v 0.125 0.2499999999999999 0.5625 -v -0.125 0.2500000000000001 -0.4375 -v -0.125 0.625 -0.4375 -v -0.125 0.2499999999999999 0.5625 -v -0.125 0.625 0.5625 -vt 0.40625 0.8125 -vt 0.46875 0.8125 -vt 0.46875 0.3125 -vt 0.40625 0.3125 -vt 0.3125 0.8125 -vt 0.40625 0.8125 -vt 0.40625 0.3125 -vt 0.3125 0.3125 -vt 0.5625 0.8125 -vt 0.625 0.8125 -vt 0.625 0.3125 -vt 0.5625 0.3125 -vt 0.46875 0.8125 -vt 0.5625 0.8125 -vt 0.5625 0.3125 -vt 0.46875 0.3125 -vt 0.46875 0.8125 -vt 0.40625 0.8125 -vt 0.40625 1 -vt 0.46875 1 -vt 0.53125 1 -vt 0.46875 1 -vt 0.46875 0.8125 -vt 0.53125 0.8125 -vn 0 -1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 -1 -vn 0 -2.220446049250313e-16 1 -usemtl m_2ee28436-932f-1f18-8613-04d9bd8d8ca4 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o head -v 0.15625 0.6875 -0.4375 -v 0.15625 0.6875 -0.75 -v 0.15625 0.4375 -0.4375 -v 0.15625 0.4375 -0.75 -v -0.15625 0.6875 -0.75 -v -0.15625 0.6875 -0.4375 -v -0.15625 0.4375 -0.75 -v -0.15625 0.4375 -0.4375 -vt 0.078125 0.84375 -vt 0.15625 0.84375 -vt 0.15625 0.71875 -vt 0.078125 0.71875 -vt 0 0.84375 -vt 0.078125 0.84375 -vt 0.078125 0.71875 -vt 0 0.71875 -vt 0.234375 0.84375 -vt 0.3125 0.84375 -vt 0.3125 0.71875 -vt 0.234375 0.71875 -vt 0.15625 0.84375 -vt 0.234375 0.84375 -vt 0.234375 0.71875 -vt 0.15625 0.71875 -vt 0.15625 0.84375 -vt 0.078125 0.84375 -vt 0.078125 1 -vt 0.15625 1 -vt 0.234375 1 -vt 0.15625 1 -vt 0.15625 0.84375 -vt 0.234375 0.84375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_2ee28436-932f-1f18-8613-04d9bd8d8ca4 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o head -v 0.09375 0.5634762499999999 -0.6875 -v 0.09375 0.5634762499999999 -0.8125 -v 0.09375 0.43847625 -0.6875 -v 0.09375 0.43847625 -0.8125 -v -0.09375 0.5634762499999999 -0.8125 -v -0.09375 0.5634762499999999 -0.6875 -v -0.09375 0.43847625 -0.8125 -v -0.09375 0.43847625 -0.6875 -vt 0.03125 0.1875 -vt 0.078125 0.1875 -vt 0.078125 0.125 -vt 0.03125 0.125 -vt 0 0.1875 -vt 0.03125 0.1875 -vt 0.03125 0.125 -vt 0 0.125 -vt 0.109375 0.1875 -vt 0.15625 0.1875 -vt 0.15625 0.125 -vt 0.109375 0.125 -vt 0.078125 0.1875 -vt 0.109375 0.1875 -vt 0.109375 0.125 -vt 0.078125 0.125 -vt 0.078125 0.1875 -vt 0.03125 0.1875 -vt 0.03125 0.25 -vt 0.078125 0.25 -vt 0.125 0.25 -vt 0.078125 0.25 -vt 0.078125 0.1875 -vt 0.125 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_2ee28436-932f-1f18-8613-04d9bd8d8ca4 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o head -v 0.125 0.75 -0.4375 -v 0.125 0.75 -0.5625 -v 0.125 0.6875 -0.4375 -v 0.125 0.6875 -0.5625 -v 0.0625 0.75 -0.5625 -v 0.0625 0.75 -0.4375 -v 0.0625 0.6875 -0.5625 -v 0.0625 0.6875 -0.4375 -vt 0.03125 0.625 -vt 0.046875 0.625 -vt 0.046875 0.59375 -vt 0.03125 0.59375 -vt 0 0.625 -vt 0.03125 0.625 -vt 0.03125 0.59375 -vt 0 0.59375 -vt 0.078125 0.625 -vt 0.09375 0.625 -vt 0.09375 0.59375 -vt 0.078125 0.59375 -vt 0.046875 0.625 -vt 0.078125 0.625 -vt 0.078125 0.59375 -vt 0.046875 0.59375 -vt 0.046875 0.625 -vt 0.03125 0.625 -vt 0.03125 0.6875 -vt 0.046875 0.6875 -vt 0.0625 0.6875 -vt 0.046875 0.6875 -vt 0.046875 0.625 -vt 0.0625 0.625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_2ee28436-932f-1f18-8613-04d9bd8d8ca4 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o head -v -0.0625 0.75 -0.4375 -v -0.0625 0.75 -0.5625 -v -0.0625 0.6875 -0.4375 -v -0.0625 0.6875 -0.5625 -v -0.125 0.75 -0.5625 -v -0.125 0.75 -0.4375 -v -0.125 0.6875 -0.5625 -v -0.125 0.6875 -0.4375 -vt 0.125 0.625 -vt 0.140625 0.625 -vt 0.140625 0.59375 -vt 0.125 0.59375 -vt 0.09375 0.625 -vt 0.125 0.625 -vt 0.125 0.59375 -vt 0.09375 0.59375 -vt 0.171875 0.625 -vt 0.1875 0.625 -vt 0.1875 0.59375 -vt 0.171875 0.59375 -vt 0.140625 0.625 -vt 0.171875 0.625 -vt 0.171875 0.59375 -vt 0.140625 0.59375 -vt 0.140625 0.625 -vt 0.125 0.625 -vt 0.125 0.6875 -vt 0.140625 0.6875 -vt 0.15625 0.6875 -vt 0.140625 0.6875 -vt 0.140625 0.625 -vt 0.15625 0.625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_2ee28436-932f-1f18-8613-04d9bd8d8ca4 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o tail1 -v 0.03125 0.6066941738241591 0.5441941738241594 -v 0.03125 0.5625 0.5 -v 0.03125 0.2531407832308854 0.8977475644174331 -v 0.03125 0.20894660940672616 0.853553390593274 -v -0.03125 0.5625 0.5 -v -0.03125 0.6066941738241591 0.5441941738241594 -v -0.03125 0.20894660940672616 0.853553390593274 -v -0.03125 0.2531407832308854 0.8977475644174331 -vt 0.015625 0.5 -vt 0.03125 0.5 -vt 0.03125 0.25 -vt 0.015625 0.25 -vt 0 0.5 -vt 0.015625 0.5 -vt 0.015625 0.25 -vt 0 0.25 -vt 0.046875 0.5 -vt 0.0625 0.5 -vt 0.0625 0.25 -vt 0.046875 0.25 -vt 0.03125 0.5 -vt 0.046875 0.5 -vt 0.046875 0.25 -vt 0.03125 0.25 -vt 0.03125 0.5 -vt 0.015625 0.5 -vt 0.015625 0.53125 -vt 0.03125 0.53125 -vt 0.046875 0.53125 -vt 0.03125 0.53125 -vt 0.03125 0.5 -vt 0.046875 0.5 -vn 0 -0.7071067811865476 -0.7071067811865475 -vn 1 0 0 -vn 0 0.7071067811865476 0.7071067811865475 -vn -1 0 0 -vn 0 0.7071067811865475 -0.7071067811865476 -vn 0 -0.7071067811865475 0.7071067811865476 -usemtl m_2ee28436-932f-1f18-8613-04d9bd8d8ca4 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o tail2 -v 0.03125 0.27144660940672627 0.8535533905932737 -v 0.03125 0.20894660940672627 0.8535533905932737 -v 0.03125 0.2714466094067264 1.3535533905932737 -v 0.03125 0.20894660940672638 1.3535533905932737 -v -0.03125 0.20894660940672627 0.8535533905932737 -v -0.03125 0.27144660940672627 0.8535533905932737 -v -0.03125 0.20894660940672638 1.3535533905932737 -v -0.03125 0.2714466094067264 1.3535533905932737 -vt 0.078125 0.5 -vt 0.09375 0.5 -vt 0.09375 0.25 -vt 0.078125 0.25 -vt 0.0625 0.5 -vt 0.078125 0.5 -vt 0.078125 0.25 -vt 0.0625 0.25 -vt 0.109375 0.5 -vt 0.125 0.5 -vt 0.125 0.25 -vt 0.109375 0.25 -vt 0.09375 0.5 -vt 0.109375 0.5 -vt 0.109375 0.25 -vt 0.09375 0.25 -vt 0.09375 0.5 -vt 0.078125 0.5 -vt 0.078125 0.53125 -vt 0.09375 0.53125 -vt 0.109375 0.53125 -vt 0.09375 0.53125 -vt 0.09375 0.5 -vt 0.109375 0.5 -vn 0 -1 2.220446049250313e-16 -vn 1 0 0 -vn 0 1 -2.220446049250313e-16 -vn -1 0 0 -vn 0 -2.220446049250313e-16 -1 -vn 0 2.220446049250313e-16 1 -usemtl m_2ee28436-932f-1f18-8613-04d9bd8d8ca4 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o backLegL -v -0.006249999999999978 0.375 0.5 -v -0.006249999999999978 0.375 0.375 -v -0.006249999999999978 0 0.5 -v -0.006249999999999978 0 0.375 -v -0.13124999999999998 0.375 0.375 -v -0.13124999999999998 0.375 0.5 -v -0.13124999999999998 0 0.375 -v -0.13124999999999998 0 0.5 -vt 0.15625 0.53125 -vt 0.1875 0.53125 -vt 0.1875 0.34375 -vt 0.15625 0.34375 -vt 0.125 0.53125 -vt 0.15625 0.53125 -vt 0.15625 0.34375 -vt 0.125 0.34375 -vt 0.21875 0.53125 -vt 0.25 0.53125 -vt 0.25 0.34375 -vt 0.21875 0.34375 -vt 0.1875 0.53125 -vt 0.21875 0.53125 -vt 0.21875 0.34375 -vt 0.1875 0.34375 -vt 0.1875 0.53125 -vt 0.15625 0.53125 -vt 0.15625 0.59375 -vt 0.1875 0.59375 -vt 0.21875 0.59375 -vt 0.1875 0.59375 -vt 0.1875 0.53125 -vt 0.21875 0.53125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_2ee28436-932f-1f18-8613-04d9bd8d8ca4 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o backLegR -v 0.13124999999999998 0.375 0.5 -v 0.13124999999999998 0.375 0.375 -v 0.13124999999999998 0 0.5 -v 0.13124999999999998 0 0.375 -v 0.006249999999999978 0.375 0.375 -v 0.006249999999999978 0.375 0.5 -v 0.006249999999999978 0 0.375 -v 0.006249999999999978 0 0.5 -vt 0.15625 0.53125 -vt 0.1875 0.53125 -vt 0.1875 0.34375 -vt 0.15625 0.34375 -vt 0.125 0.53125 -vt 0.15625 0.53125 -vt 0.15625 0.34375 -vt 0.125 0.34375 -vt 0.21875 0.53125 -vt 0.25 0.53125 -vt 0.25 0.34375 -vt 0.21875 0.34375 -vt 0.1875 0.53125 -vt 0.21875 0.53125 -vt 0.21875 0.34375 -vt 0.1875 0.34375 -vt 0.1875 0.53125 -vt 0.15625 0.53125 -vt 0.15625 0.59375 -vt 0.1875 0.59375 -vt 0.21875 0.59375 -vt 0.1875 0.59375 -vt 0.1875 0.53125 -vt 0.21875 0.53125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_2ee28436-932f-1f18-8613-04d9bd8d8ca4 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o frontLegL -v -0.012500000000000011 0.6375 -0.1875 -v -0.012500000000000011 0.6375 -0.3125 -v -0.012500000000000011 0.012499999999999956 -0.1875 -v -0.012500000000000011 0.012499999999999956 -0.3125 -v -0.1375 0.6375 -0.3125 -v -0.1375 0.6375 -0.1875 -v -0.1375 0.012499999999999956 -0.3125 -v -0.1375 0.012499999999999956 -0.1875 -vt 0.65625 0.9375 -vt 0.6875 0.9375 -vt 0.6875 0.625 -vt 0.65625 0.625 -vt 0.625 0.9375 -vt 0.65625 0.9375 -vt 0.65625 0.625 -vt 0.625 0.625 -vt 0.71875 0.9375 -vt 0.75 0.9375 -vt 0.75 0.625 -vt 0.71875 0.625 -vt 0.6875 0.9375 -vt 0.71875 0.9375 -vt 0.71875 0.625 -vt 0.6875 0.625 -vt 0.6875 0.9375 -vt 0.65625 0.9375 -vt 0.65625 1 -vt 0.6875 1 -vt 0.71875 1 -vt 0.6875 1 -vt 0.6875 0.9375 -vt 0.71875 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_2ee28436-932f-1f18-8613-04d9bd8d8ca4 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o frontLegR -v 0.13749999999999996 0.6375 -0.1875 -v 0.13749999999999996 0.6375 -0.3125 -v 0.13749999999999996 0.012499999999999956 -0.1875 -v 0.13749999999999996 0.012499999999999956 -0.3125 -v 0.012499999999999956 0.6375 -0.3125 -v 0.012499999999999956 0.6375 -0.1875 -v 0.012499999999999956 0.012499999999999956 -0.3125 -v 0.012499999999999956 0.012499999999999956 -0.1875 -vt 0.65625 0.9375 -vt 0.6875 0.9375 -vt 0.6875 0.625 -vt 0.65625 0.625 -vt 0.625 0.9375 -vt 0.65625 0.9375 -vt 0.65625 0.625 -vt 0.625 0.625 -vt 0.71875 0.9375 -vt 0.75 0.9375 -vt 0.75 0.625 -vt 0.71875 0.625 -vt 0.6875 0.9375 -vt 0.71875 0.9375 -vt 0.71875 0.625 -vt 0.6875 0.625 -vt 0.6875 0.9375 -vt 0.65625 0.9375 -vt 0.65625 1 -vt 0.6875 1 -vt 0.71875 1 -vt 0.6875 1 -vt 0.6875 0.9375 -vt 0.71875 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_2ee28436-932f-1f18-8613-04d9bd8d8ca4 -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/chicken.obj b/renderer/viewer/three/entity/models/chicken.obj deleted file mode 100644 index ec873ffd3..000000000 --- a/renderer/viewer/three/entity/models/chicken.obj +++ /dev/null @@ -1,371 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.1875 0.6875 -0.25 -v 0.1875 0.3125 -0.25 -v 0.1875 0.6875 0.25 -v 0.1875 0.3125 0.25 -v -0.1875 0.3125 -0.25 -v -0.1875 0.6875 -0.25 -v -0.1875 0.3125 0.25 -v -0.1875 0.6875 0.25 -vt 0.09375 0.53125 -vt 0.1875 0.53125 -vt 0.1875 0.28125 -vt 0.09375 0.28125 -vt 0 0.53125 -vt 0.09375 0.53125 -vt 0.09375 0.28125 -vt 0 0.28125 -vt 0.28125 0.53125 -vt 0.375 0.53125 -vt 0.375 0.28125 -vt 0.28125 0.28125 -vt 0.1875 0.53125 -vt 0.28125 0.53125 -vt 0.28125 0.28125 -vt 0.1875 0.28125 -vt 0.1875 0.53125 -vt 0.09375 0.53125 -vt 0.09375 0.71875 -vt 0.1875 0.71875 -vt 0.28125 0.71875 -vt 0.1875 0.71875 -vt 0.1875 0.53125 -vt 0.28125 0.53125 -vn 0 -1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 -1 -vn 0 -2.220446049250313e-16 1 -usemtl m_a3a58acf-2885-3588-3386-06528bca041b -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o head -v 0.125 0.9375 -0.1875 -v 0.125 0.9375 -0.375 -v 0.125 0.5625 -0.1875 -v 0.125 0.5625 -0.375 -v -0.125 0.9375 -0.375 -v -0.125 0.9375 -0.1875 -v -0.125 0.5625 -0.375 -v -0.125 0.5625 -0.1875 -vt 0.046875 0.90625 -vt 0.109375 0.90625 -vt 0.109375 0.71875 -vt 0.046875 0.71875 -vt 0 0.90625 -vt 0.046875 0.90625 -vt 0.046875 0.71875 -vt 0 0.71875 -vt 0.15625 0.90625 -vt 0.21875 0.90625 -vt 0.21875 0.71875 -vt 0.15625 0.71875 -vt 0.109375 0.90625 -vt 0.15625 0.90625 -vt 0.15625 0.71875 -vt 0.109375 0.71875 -vt 0.109375 0.90625 -vt 0.046875 0.90625 -vt 0.046875 1 -vt 0.109375 1 -vt 0.171875 1 -vt 0.109375 1 -vt 0.109375 0.90625 -vt 0.171875 0.90625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_a3a58acf-2885-3588-3386-06528bca041b -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o comb -v 0.0625 0.6875 -0.3125 -v 0.0625 0.6875 -0.4375 -v 0.0625 0.5625 -0.3125 -v 0.0625 0.5625 -0.4375 -v -0.0625 0.6875 -0.4375 -v -0.0625 0.6875 -0.3125 -v -0.0625 0.5625 -0.4375 -v -0.0625 0.5625 -0.3125 -vt 0.25 0.8125 -vt 0.28125 0.8125 -vt 0.28125 0.75 -vt 0.25 0.75 -vt 0.21875 0.8125 -vt 0.25 0.8125 -vt 0.25 0.75 -vt 0.21875 0.75 -vt 0.3125 0.8125 -vt 0.34375 0.8125 -vt 0.34375 0.75 -vt 0.3125 0.75 -vt 0.28125 0.8125 -vt 0.3125 0.8125 -vt 0.3125 0.75 -vt 0.28125 0.75 -vt 0.28125 0.8125 -vt 0.25 0.8125 -vt 0.25 0.875 -vt 0.28125 0.875 -vt 0.3125 0.875 -vt 0.28125 0.875 -vt 0.28125 0.8125 -vt 0.3125 0.8125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_a3a58acf-2885-3588-3386-06528bca041b -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o beak -v 0.125 0.8224431423663936 -0.35273540157455374 -v 0.125 0.8333376102098509 -0.4772597388360219 -v 0.125 0.6979188051049254 -0.363629869418011 -v 0.125 0.7088132729483827 -0.4881542066794792 -v -0.125 0.8333376102098509 -0.4772597388360219 -v -0.125 0.8224431423663936 -0.35273540157455374 -v -0.125 0.7088132729483827 -0.4881542066794792 -v -0.125 0.6979188051049254 -0.363629869418011 -vt 0.25 0.9375 -vt 0.3125 0.9375 -vt 0.3125 0.875 -vt 0.25 0.875 -vt 0.21875 0.9375 -vt 0.25 0.9375 -vt 0.25 0.875 -vt 0.21875 0.875 -vt 0.34375 0.9375 -vt 0.40625 0.9375 -vt 0.40625 0.875 -vt 0.34375 0.875 -vt 0.3125 0.9375 -vt 0.34375 0.9375 -vt 0.34375 0.875 -vt 0.3125 0.875 -vt 0.3125 0.9375 -vt 0.25 0.9375 -vt 0.25 1 -vt 0.3125 1 -vt 0.375 1 -vt 0.3125 1 -vt 0.3125 0.9375 -vt 0.375 0.9375 -vn 0 0.08715574274765818 -0.9961946980917455 -vn 1 0 0 -vn 0 -0.08715574274765818 0.9961946980917455 -vn -1 0 0 -vn 0 0.9961946980917455 0.08715574274765818 -vn 0 -0.9961946980917455 -0.08715574274765818 -usemtl m_a3a58acf-2885-3588-3386-06528bca041b -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o leg0 -v 0.1875 0.3125 0.0625 -v 0.1875 0.3125 -0.125 -v 0.1875 0 0.0625 -v 0.1875 0 -0.125 -v 0 0.3125 -0.125 -v 0 0.3125 0.0625 -v 0 0 -0.125 -v 0 0 0.0625 -vt 0.453125 0.90625 -vt 0.5 0.90625 -vt 0.5 0.75 -vt 0.453125 0.75 -vt 0.40625 0.90625 -vt 0.453125 0.90625 -vt 0.453125 0.75 -vt 0.40625 0.75 -vt 0.546875 0.90625 -vt 0.59375 0.90625 -vt 0.59375 0.75 -vt 0.546875 0.75 -vt 0.5 0.90625 -vt 0.546875 0.90625 -vt 0.546875 0.75 -vt 0.5 0.75 -vt 0.5 0.90625 -vt 0.453125 0.90625 -vt 0.453125 1 -vt 0.5 1 -vt 0.546875 1 -vt 0.5 1 -vt 0.5 0.90625 -vt 0.546875 0.90625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_a3a58acf-2885-3588-3386-06528bca041b -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o leg1 -v 0 0.3125 0.0625 -v 0 0.3125 -0.125 -v 0 0 0.0625 -v 0 0 -0.125 -v -0.1875 0.3125 -0.125 -v -0.1875 0.3125 0.0625 -v -0.1875 0 -0.125 -v -0.1875 0 0.0625 -vt 0.453125 0.90625 -vt 0.5 0.90625 -vt 0.5 0.75 -vt 0.453125 0.75 -vt 0.40625 0.90625 -vt 0.453125 0.90625 -vt 0.453125 0.75 -vt 0.40625 0.75 -vt 0.546875 0.90625 -vt 0.59375 0.90625 -vt 0.59375 0.75 -vt 0.546875 0.75 -vt 0.5 0.90625 -vt 0.546875 0.90625 -vt 0.546875 0.75 -vt 0.5 0.75 -vt 0.5 0.90625 -vt 0.453125 0.90625 -vt 0.453125 1 -vt 0.5 1 -vt 0.546875 1 -vt 0.5 1 -vt 0.5 0.90625 -vt 0.546875 0.90625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_a3a58acf-2885-3588-3386-06528bca041b -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o wing0 -v 0.25 0.6875 0.1875 -v 0.25 0.6875 -0.1875 -v 0.25 0.4375 0.1875 -v 0.25 0.4375 -0.1875 -v 0.1875 0.6875 -0.1875 -v 0.1875 0.6875 0.1875 -v 0.1875 0.4375 -0.1875 -v 0.1875 0.4375 0.1875 -vt 0.46875 0.40625 -vt 0.484375 0.40625 -vt 0.484375 0.28125 -vt 0.46875 0.28125 -vt 0.375 0.40625 -vt 0.46875 0.40625 -vt 0.46875 0.28125 -vt 0.375 0.28125 -vt 0.578125 0.40625 -vt 0.59375 0.40625 -vt 0.59375 0.28125 -vt 0.578125 0.28125 -vt 0.484375 0.40625 -vt 0.578125 0.40625 -vt 0.578125 0.28125 -vt 0.484375 0.28125 -vt 0.484375 0.40625 -vt 0.46875 0.40625 -vt 0.46875 0.59375 -vt 0.484375 0.59375 -vt 0.5 0.59375 -vt 0.484375 0.59375 -vt 0.484375 0.40625 -vt 0.5 0.40625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_a3a58acf-2885-3588-3386-06528bca041b -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o wing1 -v -0.1875 0.6875 0.1875 -v -0.1875 0.6875 -0.1875 -v -0.1875 0.4375 0.1875 -v -0.1875 0.4375 -0.1875 -v -0.25 0.6875 -0.1875 -v -0.25 0.6875 0.1875 -v -0.25 0.4375 -0.1875 -v -0.25 0.4375 0.1875 -vt 0.46875 0.40625 -vt 0.484375 0.40625 -vt 0.484375 0.28125 -vt 0.46875 0.28125 -vt 0.375 0.40625 -vt 0.46875 0.40625 -vt 0.46875 0.28125 -vt 0.375 0.28125 -vt 0.578125 0.40625 -vt 0.59375 0.40625 -vt 0.59375 0.28125 -vt 0.578125 0.28125 -vt 0.484375 0.40625 -vt 0.578125 0.40625 -vt 0.578125 0.28125 -vt 0.484375 0.28125 -vt 0.484375 0.40625 -vt 0.46875 0.40625 -vt 0.46875 0.59375 -vt 0.484375 0.59375 -vt 0.5 0.59375 -vt 0.484375 0.59375 -vt 0.484375 0.40625 -vt 0.5 0.40625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_a3a58acf-2885-3588-3386-06528bca041b -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/cod.obj b/renderer/viewer/three/entity/models/cod.obj deleted file mode 100644 index 2b469b8b4..000000000 --- a/renderer/viewer/three/entity/models/cod.obj +++ /dev/null @@ -1,371 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.0625 0.25 0.5 -v 0.0625 0.25 0.0625 -v 0.0625 0 0.5 -v 0.0625 0 0.0625 -v -0.0625 0.25 0.0625 -v -0.0625 0.25 0.5 -v -0.0625 0 0.0625 -v -0.0625 0 0.5 -vt 0.21875 0.78125 -vt 0.28125 0.78125 -vt 0.28125 0.65625 -vt 0.21875 0.65625 -vt 0 0.78125 -vt 0.21875 0.78125 -vt 0.21875 0.65625 -vt 0 0.65625 -vt 0.5 0.78125 -vt 0.5625 0.78125 -vt 0.5625 0.65625 -vt 0.5 0.65625 -vt 0.28125 0.78125 -vt 0.5 0.78125 -vt 0.5 0.65625 -vt 0.28125 0.65625 -vt 0.28125 0.78125 -vt 0.21875 0.78125 -vt 0.21875 1 -vt 0.28125 1 -vt 0.34375 1 -vt 0.28125 1 -vt 0.28125 0.78125 -vt 0.34375 0.78125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_92191bde-46b9-ba2f-846b-1e3ee628119f -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o body -v 0 0.3125 0.375 -v 0 0.3125 0 -v 0 0.25 0.375 -v 0 0.25 0 -v 0 0.3125 0 -v 0 0.3125 0.375 -v 0 0.25 0 -v 0 0.25 0.375 -vt 0.8125 1 -vt 0.8125 1 -vt 0.8125 0.96875 -vt 0.8125 0.96875 -vt 0.625 1 -vt 0.8125 1 -vt 0.8125 0.96875 -vt 0.625 0.96875 -vt 1 1 -vt 1 1 -vt 1 0.96875 -vt 1 0.96875 -vt 0.8125 1 -vt 1 1 -vt 1 0.96875 -vt 0.8125 0.96875 -vt 0.8125 1 -vt 0.8125 1 -vt 0.8125 1.1875 -vt 0.8125 1.1875 -vt 0.8125 1.1875 -vt 0.8125 1.1875 -vt 0.8125 1 -vt 0.8125 1 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_92191bde-46b9-ba2f-846b-1e3ee628119f -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o body -v 0 0 0.3125 -v 0 0 0.1875 -v 0 -0.0625 0.3125 -v 0 -0.0625 0.1875 -v 0 0 0.1875 -v 0 0 0.3125 -v 0 -0.0625 0.1875 -v 0 -0.0625 0.3125 -vt 0.75 0.96875 -vt 0.75 0.96875 -vt 0.75 0.9375 -vt 0.75 0.9375 -vt 0.6875 0.96875 -vt 0.75 0.96875 -vt 0.75 0.9375 -vt 0.6875 0.9375 -vt 0.8125 0.96875 -vt 0.8125 0.96875 -vt 0.8125 0.9375 -vt 0.8125 0.9375 -vt 0.75 0.96875 -vt 0.8125 0.96875 -vt 0.8125 0.9375 -vt 0.75 0.9375 -vt 0.75 0.96875 -vt 0.75 0.96875 -vt 0.75 1.03125 -vt 0.75 1.03125 -vt 0.75 1.03125 -vt 0.75 1.03125 -vt 0.75 0.96875 -vt 0.75 0.96875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_92191bde-46b9-ba2f-846b-1e3ee628119f -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o head -v 0.062450000000000006 0.25005 -0.125 -v 0.062450000000000006 0.25005 -0.1875 -v 0.062450000000000006 0.06255 -0.125 -v 0.062450000000000006 0.06255 -0.1875 -v -0.06255 0.25005 -0.1875 -v -0.06255 0.25005 -0.125 -v -0.06255 0.06255 -0.1875 -v -0.06255 0.06255 -0.125 -vt 0.03125 0.96875 -vt 0.09375 0.96875 -vt 0.09375 0.875 -vt 0.03125 0.875 -vt 0 0.96875 -vt 0.03125 0.96875 -vt 0.03125 0.875 -vt 0 0.875 -vt 0.125 0.96875 -vt 0.1875 0.96875 -vt 0.1875 0.875 -vt 0.125 0.875 -vt 0.09375 0.96875 -vt 0.125 0.96875 -vt 0.125 0.875 -vt 0.09375 0.875 -vt 0.09375 0.96875 -vt 0.03125 0.96875 -vt 0.03125 1 -vt 0.09375 1 -vt 0.15625 1 -vt 0.09375 1 -vt 0.09375 0.96875 -vt 0.15625 0.96875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_92191bde-46b9-ba2f-846b-1e3ee628119f -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o head -v 0.0625 0.25 0.0625 -v 0.0625 0.25 -0.125 -v 0.0625 0 0.0625 -v 0.0625 0 -0.125 -v -0.0625 0.25 -0.125 -v -0.0625 0.25 0.0625 -v -0.0625 0 -0.125 -v -0.0625 0 0.0625 -vt 0.4375 0.90625 -vt 0.5 0.90625 -vt 0.5 0.78125 -vt 0.4375 0.78125 -vt 0.34375 0.90625 -vt 0.4375 0.90625 -vt 0.4375 0.78125 -vt 0.34375 0.78125 -vt 0.59375 0.90625 -vt 0.65625 0.90625 -vt 0.65625 0.78125 -vt 0.59375 0.78125 -vt 0.5 0.90625 -vt 0.59375 0.90625 -vt 0.59375 0.78125 -vt 0.5 0.78125 -vt 0.5 0.90625 -vt 0.4375 0.90625 -vt 0.4375 1 -vt 0.5 1 -vt 0.5625 1 -vt 0.5 1 -vt 0.5 0.90625 -vt 0.5625 0.90625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_92191bde-46b9-ba2f-846b-1e3ee628119f -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o leftFin -v -0.0625 0.0625 0.125 -v -0.0625 0.0625 0 -v -0.026651472728059622 0.011302997231938061 0.125 -v -0.026651472728059622 0.011302997231938061 0 -v -0.164894005536124 -0.009197054543880756 0 -v -0.164894005536124 -0.009197054543880756 0.125 -v -0.12904547826418356 -0.06039405731194275 0 -v -0.12904547826418356 -0.06039405731194275 0.125 -vt 0.8125 0.8125 -vt 0.875 0.8125 -vt 0.875 0.78125 -vt 0.8125 0.78125 -vt 0.75 0.8125 -vt 0.8125 0.8125 -vt 0.8125 0.78125 -vt 0.75 0.78125 -vt 0.9375 0.8125 -vt 1 0.8125 -vt 1 0.78125 -vt 0.9375 0.78125 -vt 0.875 0.8125 -vt 0.9375 0.8125 -vt 0.9375 0.78125 -vt 0.875 0.78125 -vt 0.875 0.8125 -vt 0.8125 0.8125 -vt 0.8125 0.875 -vt 0.875 0.875 -vt 0.9375 0.875 -vt 0.875 0.875 -vt 0.875 0.8125 -vt 0.9375 0.8125 -vn 0 0 -1 -vn 0.8191520442889918 0.573576436351046 0 -vn 0 0 1 -vn -0.8191520442889918 -0.573576436351046 0 -vn -0.573576436351046 0.8191520442889918 0 -vn 0.573576436351046 -0.8191520442889918 0 -usemtl m_92191bde-46b9-ba2f-846b-1e3ee628119f -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o rightFin -v 0.164894005536124 -0.009197054543880756 0.125 -v 0.164894005536124 -0.009197054543880756 0 -v 0.12904547826418356 -0.06039405731194275 0.125 -v 0.12904547826418356 -0.06039405731194275 0 -v 0.0625 0.0625 0 -v 0.0625 0.0625 0.125 -v 0.026651472728059566 0.011302997231938061 0 -v 0.026651472728059566 0.011302997231938061 0.125 -vt 0.8125 0.90625 -vt 0.875 0.90625 -vt 0.875 0.875 -vt 0.8125 0.875 -vt 0.75 0.90625 -vt 0.8125 0.90625 -vt 0.8125 0.875 -vt 0.75 0.875 -vt 0.9375 0.90625 -vt 1 0.90625 -vt 1 0.875 -vt 0.9375 0.875 -vt 0.875 0.90625 -vt 0.9375 0.90625 -vt 0.9375 0.875 -vt 0.875 0.875 -vt 0.875 0.90625 -vt 0.8125 0.90625 -vt 0.8125 0.96875 -vt 0.875 0.96875 -vt 0.9375 0.96875 -vt 0.875 0.96875 -vt 0.875 0.90625 -vt 0.9375 0.90625 -vn 0 0 -1 -vn 0.8191520442889918 -0.573576436351046 0 -vn 0 0 1 -vn -0.8191520442889918 0.573576436351046 0 -vn 0.573576436351046 0.8191520442889918 0 -vn -0.573576436351046 -0.8191520442889918 0 -usemtl m_92191bde-46b9-ba2f-846b-1e3ee628119f -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o tailfin -v 0 0.25 0.875 -v 0 0.25 0.5 -v 0 0 0.875 -v 0 0 0.5 -v 0 0.25 0.5 -v 0 0.25 0.875 -v 0 0 0.5 -v 0 0 0.875 -vt 0.8125 0.78125 -vt 0.8125 0.78125 -vt 0.8125 0.65625 -vt 0.8125 0.65625 -vt 0.625 0.78125 -vt 0.8125 0.78125 -vt 0.8125 0.65625 -vt 0.625 0.65625 -vt 1 0.78125 -vt 1 0.78125 -vt 1 0.65625 -vt 1 0.65625 -vt 0.8125 0.78125 -vt 1 0.78125 -vt 1 0.65625 -vt 0.8125 0.65625 -vt 0.8125 0.78125 -vt 0.8125 0.78125 -vt 0.8125 0.96875 -vt 0.8125 0.96875 -vt 0.8125 0.96875 -vt 0.8125 0.96875 -vt 0.8125 0.78125 -vt 0.8125 0.78125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_92191bde-46b9-ba2f-846b-1e3ee628119f -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/creeper.obj b/renderer/viewer/three/entity/models/creeper.obj deleted file mode 100644 index 2e68c50e4..000000000 --- a/renderer/viewer/three/entity/models/creeper.obj +++ /dev/null @@ -1,279 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o Body -v 0.25 1.125 0.125 -v 0.25 1.125 -0.125 -v 0.25 0.375 0.125 -v 0.25 0.375 -0.125 -v -0.25 1.125 -0.125 -v -0.25 1.125 0.125 -v -0.25 0.375 -0.125 -v -0.25 0.375 0.125 -vt 0.3125 0.375 -vt 0.4375 0.375 -vt 0.4375 0 -vt 0.3125 0 -vt 0.25 0.375 -vt 0.3125 0.375 -vt 0.3125 0 -vt 0.25 0 -vt 0.5 0.375 -vt 0.625 0.375 -vt 0.625 0 -vt 0.5 0 -vt 0.4375 0.375 -vt 0.5 0.375 -vt 0.5 0 -vt 0.4375 0 -vt 0.4375 0.375 -vt 0.3125 0.375 -vt 0.3125 0.5 -vt 0.4375 0.5 -vt 0.5625 0.5 -vt 0.4375 0.5 -vt 0.4375 0.375 -vt 0.5625 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5d56b934-8e1a-577b-049f-fb19876a8641 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o Head -v 0.25 1.625 0.25 -v 0.25 1.625 -0.25 -v 0.25 1.125 0.25 -v 0.25 1.125 -0.25 -v -0.25 1.625 -0.25 -v -0.25 1.625 0.25 -v -0.25 1.125 -0.25 -v -0.25 1.125 0.25 -vt 0.125 0.75 -vt 0.25 0.75 -vt 0.25 0.5 -vt 0.125 0.5 -vt 0 0.75 -vt 0.125 0.75 -vt 0.125 0.5 -vt 0 0.5 -vt 0.375 0.75 -vt 0.5 0.75 -vt 0.5 0.5 -vt 0.375 0.5 -vt 0.25 0.75 -vt 0.375 0.75 -vt 0.375 0.5 -vt 0.25 0.5 -vt 0.25 0.75 -vt 0.125 0.75 -vt 0.125 1 -vt 0.25 1 -vt 0.375 1 -vt 0.25 1 -vt 0.25 0.75 -vt 0.375 0.75 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5d56b934-8e1a-577b-049f-fb19876a8641 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o leg0 -v 0.25 0.375 0.375 -v 0.25 0.375 0.125 -v 0.25 0 0.375 -v 0.25 0 0.125 -v 0 0.375 0.125 -v 0 0.375 0.375 -v 0 0 0.125 -v 0 0 0.375 -vt 0.0625 0.375 -vt 0.125 0.375 -vt 0.125 0.1875 -vt 0.0625 0.1875 -vt 0 0.375 -vt 0.0625 0.375 -vt 0.0625 0.1875 -vt 0 0.1875 -vt 0.1875 0.375 -vt 0.25 0.375 -vt 0.25 0.1875 -vt 0.1875 0.1875 -vt 0.125 0.375 -vt 0.1875 0.375 -vt 0.1875 0.1875 -vt 0.125 0.1875 -vt 0.125 0.375 -vt 0.0625 0.375 -vt 0.0625 0.5 -vt 0.125 0.5 -vt 0.1875 0.5 -vt 0.125 0.5 -vt 0.125 0.375 -vt 0.1875 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5d56b934-8e1a-577b-049f-fb19876a8641 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o leg1 -v 0 0.375 0.375 -v 0 0.375 0.125 -v 0 0 0.375 -v 0 0 0.125 -v -0.25 0.375 0.125 -v -0.25 0.375 0.375 -v -0.25 0 0.125 -v -0.25 0 0.375 -vt 0.0625 0.375 -vt 0.125 0.375 -vt 0.125 0.1875 -vt 0.0625 0.1875 -vt 0 0.375 -vt 0.0625 0.375 -vt 0.0625 0.1875 -vt 0 0.1875 -vt 0.1875 0.375 -vt 0.25 0.375 -vt 0.25 0.1875 -vt 0.1875 0.1875 -vt 0.125 0.375 -vt 0.1875 0.375 -vt 0.1875 0.1875 -vt 0.125 0.1875 -vt 0.125 0.375 -vt 0.0625 0.375 -vt 0.0625 0.5 -vt 0.125 0.5 -vt 0.1875 0.5 -vt 0.125 0.5 -vt 0.125 0.375 -vt 0.1875 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5d56b934-8e1a-577b-049f-fb19876a8641 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o leg2 -v 0.25 0.375 -0.125 -v 0.25 0.375 -0.375 -v 0.25 0 -0.125 -v 0.25 0 -0.375 -v 0 0.375 -0.375 -v 0 0.375 -0.125 -v 0 0 -0.375 -v 0 0 -0.125 -vt 0.0625 0.375 -vt 0.125 0.375 -vt 0.125 0.1875 -vt 0.0625 0.1875 -vt 0 0.375 -vt 0.0625 0.375 -vt 0.0625 0.1875 -vt 0 0.1875 -vt 0.1875 0.375 -vt 0.25 0.375 -vt 0.25 0.1875 -vt 0.1875 0.1875 -vt 0.125 0.375 -vt 0.1875 0.375 -vt 0.1875 0.1875 -vt 0.125 0.1875 -vt 0.125 0.375 -vt 0.0625 0.375 -vt 0.0625 0.5 -vt 0.125 0.5 -vt 0.1875 0.5 -vt 0.125 0.5 -vt 0.125 0.375 -vt 0.1875 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5d56b934-8e1a-577b-049f-fb19876a8641 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o leg3 -v 0 0.375 -0.125 -v 0 0.375 -0.375 -v 0 0 -0.125 -v 0 0 -0.375 -v -0.25 0.375 -0.375 -v -0.25 0.375 -0.125 -v -0.25 0 -0.375 -v -0.25 0 -0.125 -vt 0.0625 0.375 -vt 0.125 0.375 -vt 0.125 0.1875 -vt 0.0625 0.1875 -vt 0 0.375 -vt 0.0625 0.375 -vt 0.0625 0.1875 -vt 0 0.1875 -vt 0.1875 0.375 -vt 0.25 0.375 -vt 0.25 0.1875 -vt 0.1875 0.1875 -vt 0.125 0.375 -vt 0.1875 0.375 -vt 0.1875 0.1875 -vt 0.125 0.1875 -vt 0.125 0.375 -vt 0.0625 0.375 -vt 0.0625 0.5 -vt 0.125 0.5 -vt 0.1875 0.5 -vt 0.125 0.5 -vt 0.125 0.375 -vt 0.1875 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5d56b934-8e1a-577b-049f-fb19876a8641 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/dolphin.obj b/renderer/viewer/three/entity/models/dolphin.obj deleted file mode 100644 index 478ce015b..000000000 --- a/renderer/viewer/three/entity/models/dolphin.obj +++ /dev/null @@ -1,371 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.25 0.4375 0.625 -v 0.25 0.4375 -0.1875 -v 0.25 0 0.625 -v 0.25 0 -0.1875 -v -0.25 0.4375 -0.1875 -v -0.25 0.4375 0.625 -v -0.25 0 -0.1875 -v -0.25 0 0.625 -vt 0.546875 0.796875 -vt 0.671875 0.796875 -vt 0.671875 0.6875 -vt 0.546875 0.6875 -vt 0.34375 0.796875 -vt 0.546875 0.796875 -vt 0.546875 0.6875 -vt 0.34375 0.6875 -vt 0.875 0.796875 -vt 1 0.796875 -vt 1 0.6875 -vt 0.875 0.6875 -vt 0.671875 0.796875 -vt 0.875 0.796875 -vt 0.875 0.6875 -vt 0.671875 0.6875 -vt 0.671875 0.796875 -vt 0.546875 0.796875 -vt 0.546875 1 -vt 0.671875 1 -vt 0.796875 1 -vt 0.671875 1 -vt 0.671875 0.796875 -vt 0.796875 0.796875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_84be203d-dd47-5073-42d4-8589a81aedb5 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o head -v 0.25 0.4375 -0.1875 -v 0.25 0.4375 -0.5625 -v 0.25 0 -0.1875 -v 0.25 0 -0.5625 -v -0.25 0.4375 -0.5625 -v -0.25 0.4375 -0.1875 -v -0.25 0 -0.5625 -v -0.25 0 -0.1875 -vt 0.09375 0.90625 -vt 0.21875 0.90625 -vt 0.21875 0.796875 -vt 0.09375 0.796875 -vt 0 0.90625 -vt 0.09375 0.90625 -vt 0.09375 0.796875 -vt 0 0.796875 -vt 0.3125 0.90625 -vt 0.4375 0.90625 -vt 0.4375 0.796875 -vt 0.3125 0.796875 -vt 0.21875 0.90625 -vt 0.3125 0.90625 -vt 0.3125 0.796875 -vt 0.21875 0.796875 -vt 0.21875 0.90625 -vt 0.09375 0.90625 -vt 0.09375 1 -vt 0.21875 1 -vt 0.34375 1 -vt 0.21875 1 -vt 0.21875 0.90625 -vt 0.34375 0.90625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_84be203d-dd47-5073-42d4-8589a81aedb5 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o nose -v 0.0625 0.125 -0.5625 -v 0.0625 0.125 -0.8125 -v 0.0625 0 -0.5625 -v 0.0625 0 -0.8125 -v -0.0625 0.125 -0.8125 -v -0.0625 0.125 -0.5625 -v -0.0625 0 -0.8125 -v -0.0625 0 -0.5625 -vt 0.0625 0.734375 -vt 0.09375 0.734375 -vt 0.09375 0.703125 -vt 0.0625 0.703125 -vt 0 0.734375 -vt 0.0625 0.734375 -vt 0.0625 0.703125 -vt 0 0.703125 -vt 0.15625 0.734375 -vt 0.1875 0.734375 -vt 0.1875 0.703125 -vt 0.15625 0.703125 -vt 0.09375 0.734375 -vt 0.15625 0.734375 -vt 0.15625 0.703125 -vt 0.09375 0.703125 -vt 0.09375 0.734375 -vt 0.0625 0.734375 -vt 0.0625 0.796875 -vt 0.09375 0.796875 -vt 0.125 0.796875 -vt 0.09375 0.796875 -vt 0.09375 0.734375 -vt 0.125 0.734375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_84be203d-dd47-5073-42d4-8589a81aedb5 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o tail -v 0.125 0.25743308235954887 1.3237397711116625 -v 0.125 0.31735265549856384 0.6388559161735876 -v 0.125 -0.0538777607941216 1.2965036015030194 -v 0.125 0.006041812344893427 0.6116197465649442 -v -0.125 0.31735265549856384 0.6388559161735876 -v -0.125 0.25743308235954887 1.3237397711116625 -v -0.125 0.006041812344893427 0.6116197465649442 -v -0.125 -0.0538777607941216 1.2965036015030194 -vt 0.171875 0.53125 -vt 0.234375 0.53125 -vt 0.234375 0.453125 -vt 0.171875 0.453125 -vt 0 0.53125 -vt 0.171875 0.53125 -vt 0.171875 0.453125 -vt 0 0.453125 -vt 0.40625 0.53125 -vt 0.46875 0.53125 -vt 0.46875 0.453125 -vt 0.40625 0.453125 -vt 0.234375 0.53125 -vt 0.40625 0.53125 -vt 0.40625 0.453125 -vt 0.234375 0.453125 -vt 0.234375 0.53125 -vt 0.171875 0.53125 -vt 0.171875 0.703125 -vt 0.234375 0.703125 -vt 0.296875 0.703125 -vt 0.234375 0.703125 -vt 0.234375 0.53125 -vt 0.296875 0.53125 -vn 0 0.08715574274765818 -0.9961946980917455 -vn 1 0 0 -vn 0 -0.08715574274765818 0.9961946980917455 -vn -1 0 0 -vn 0 0.9961946980917455 0.08715574274765818 -vn 0 -0.9961946980917455 -0.08715574274765818 -usemtl m_84be203d-dd47-5073-42d4-8589a81aedb5 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o tail_fin -v 0.3125 0.06737675474652305 1.559379883370239 -v 0.3125 0.15173340012547243 1.1939911090757758 -v 0.3125 0.006478625697445839 1.5453204424737472 -v 0.3125 0.09083527107639522 1.1799316681792842 -v -0.3125 0.15173340012547243 1.1939911090757758 -v -0.3125 0.06737675474652305 1.559379883370239 -v -0.3125 0.09083527107639522 1.1799316681792842 -v -0.3125 0.006478625697445839 1.5453204424737472 -vt 0.390625 0.59375 -vt 0.546875 0.59375 -vt 0.546875 0.578125 -vt 0.390625 0.578125 -vt 0.296875 0.59375 -vt 0.390625 0.59375 -vt 0.390625 0.578125 -vt 0.296875 0.578125 -vt 0.640625 0.59375 -vt 0.796875 0.59375 -vt 0.796875 0.578125 -vt 0.640625 0.578125 -vt 0.546875 0.59375 -vt 0.640625 0.59375 -vt 0.640625 0.578125 -vt 0.546875 0.578125 -vt 0.546875 0.59375 -vt 0.390625 0.59375 -vt 0.390625 0.6875 -vt 0.546875 0.6875 -vt 0.703125 0.6875 -vt 0.546875 0.6875 -vt 0.546875 0.59375 -vt 0.703125 0.59375 -vn 0 0.224951054343865 -0.9743700647852354 -vn 1 0 0 -vn 0 -0.224951054343865 0.9743700647852354 -vn -1 0 0 -vn 0 0.9743700647852354 0.224951054343865 -vn 0 -0.9743700647852354 -0.224951054343865 -usemtl m_84be203d-dd47-5073-42d4-8589a81aedb5 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o back_fin -v 0.03125 0.7045071448143734 0.22503005919760444 -v 0.03125 0.4338742061317362 0.06878005919760444 -v 0.03125 0.5795071448143734 0.44153641014371414 -v 0.03125 0.3088742061317362 0.28528641014371414 -v -0.03125 0.4338742061317362 0.06878005919760444 -v -0.03125 0.7045071448143734 0.22503005919760444 -v -0.03125 0.3088742061317362 0.28528641014371414 -v -0.03125 0.5795071448143734 0.44153641014371414 -vt 0.875 0.921875 -vt 0.890625 0.921875 -vt 0.890625 0.859375 -vt 0.875 0.859375 -vt 0.796875 0.921875 -vt 0.875 0.921875 -vt 0.875 0.859375 -vt 0.796875 0.859375 -vt 0.96875 0.921875 -vt 0.984375 0.921875 -vt 0.984375 0.859375 -vt 0.96875 0.859375 -vt 0.890625 0.921875 -vt 0.96875 0.921875 -vt 0.96875 0.859375 -vt 0.890625 0.859375 -vt 0.890625 0.921875 -vt 0.875 0.921875 -vt 0.875 1 -vt 0.890625 1 -vt 0.90625 1 -vt 0.890625 1 -vt 0.890625 0.921875 -vt 0.90625 0.921875 -vn 0 -0.8660254037844386 -0.5000000000000001 -vn 1 0 0 -vn 0 0.8660254037844386 0.5000000000000001 -vn -1 0 0 -vn 0 0.5000000000000001 -0.8660254037844386 -vn 0 -0.5000000000000001 0.8660254037844386 -usemtl m_84be203d-dd47-5073-42d4-8589a81aedb5 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o left_fin -v -0.5939081233075358 0.0007485675108518386 0.11737888892342419 -v -0.25118856264048317 0.1055284523428025 -0.13356080198015846 -v -0.456779654809827 0.04267294763203877 0.32216689999567216 -v -0.11406009414277446 0.14745283246398944 0.07122720909208935 -v -0.2329153310953121 0.04575940509511278 -0.13356080198015846 -v -0.5756348917623646 -0.05902047973683788 0.11737888892342419 -v -0.09578686259760338 0.08768378521629971 0.07122720909208935 -v -0.438506423264656 -0.01709609961565095 0.32216689999567216 -vt 0.859375 0.578125 -vt 0.875 0.578125 -vt 0.875 0.515625 -vt 0.859375 0.515625 -vt 0.75 0.578125 -vt 0.859375 0.578125 -vt 0.859375 0.515625 -vt 0.75 0.515625 -vt 0.984375 0.578125 -vt 1 0.578125 -vt 1 0.515625 -vt 0.984375 0.515625 -vt 0.875 0.578125 -vt 0.984375 0.578125 -vt 0.984375 0.515625 -vt 0.875 0.515625 -vt 0.875 0.578125 -vt 0.859375 0.578125 -vt 0.859375 0.6875 -vt 0.875 0.6875 -vt 0.890625 0.6875 -vt 0.875 0.6875 -vt 0.875 0.578125 -vt 0.890625 0.578125 -vn 0.7833589958104059 0.23949687961588728 -0.5735764363510463 -vn -0.2923717047227367 0.9563047559630355 -8.326672684688674e-17 -vn -0.7833589958104059 -0.23949687961588728 0.5735764363510463 -vn 0.2923717047227367 -0.9563047559630355 8.326672684688674e-17 -vn -0.5485138739908348 -0.16769752048474773 -0.8191520442889918 -vn 0.5485138739908348 0.16769752048474773 0.8191520442889918 -usemtl m_84be203d-dd47-5073-42d4-8589a81aedb5 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o left_fin -v 0.5756348917623646 -0.05902047973683788 0.11737888892342419 -v 0.23291533109531204 0.04575940509511278 -0.13356080198015846 -v 0.43850642326465605 -0.01709609961565095 0.32216689999567216 -v 0.09578686259760338 0.08768378521629971 0.07122720909208935 -v 0.25118856264048317 0.1055284523428025 -0.13356080198015846 -v 0.5939081233075358 0.0007485675108518386 0.11737888892342419 -v 0.1140600941427744 0.14745283246398944 0.07122720909208935 -v 0.4567796548098271 0.04267294763203877 0.32216689999567216 -vt 0.875 0.578125 -vt 0.859375 0.578125 -vt 0.859375 0.515625 -vt 0.875 0.515625 -vt 0.984375 0.578125 -vt 0.875 0.578125 -vt 0.875 0.515625 -vt 0.984375 0.515625 -vt 1 0.578125 -vt 0.984375 0.578125 -vt 0.984375 0.515625 -vt 1 0.515625 -vt 0.859375 0.578125 -vt 0.75 0.578125 -vt 0.75 0.515625 -vt 0.859375 0.515625 -vt 0.859375 0.578125 -vt 0.875 0.578125 -vt 0.875 0.6875 -vt 0.859375 0.6875 -vt 0.875 0.6875 -vt 0.890625 0.6875 -vt 0.890625 0.578125 -vt 0.875 0.578125 -vn -0.7833589958104059 0.23949687961588728 -0.5735764363510463 -vn -0.2923717047227367 -0.9563047559630355 8.326672684688674e-17 -vn 0.7833589958104059 -0.23949687961588728 0.5735764363510463 -vn 0.2923717047227367 0.9563047559630355 -8.326672684688674e-17 -vn 0.5485138739908348 -0.16769752048474773 -0.8191520442889918 -vn -0.5485138739908348 0.16769752048474773 0.8191520442889918 -usemtl m_84be203d-dd47-5073-42d4-8589a81aedb5 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/ender_dragon.obj b/renderer/viewer/three/entity/models/ender_dragon.obj deleted file mode 100644 index 84c909a9a..000000000 --- a/renderer/viewer/three/entity/models/ender_dragon.obj +++ /dev/null @@ -1,2993 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o neck -v 0.3125 0.7488108431536706 -0.47276383039135683 -v 0.3125 0.803283182370957 -1.0953855166986979 -v 0.3125 0.1261891568463296 -0.5272361696086432 -v 0.3125 0.18066149606361592 -1.1498578559159842 -v -0.3125 0.803283182370957 -1.0953855166986979 -v -0.3125 0.7488108431536706 -0.47276383039135683 -v -0.3125 0.18066149606361592 -1.1498578559159842 -v -0.3125 0.1261891568463296 -0.5272361696086432 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 0.08715574274765818 -0.9961946980917455 -vn 1 0 0 -vn 0 -0.08715574274765818 0.9961946980917455 -vn -1 0 0 -vn 0 0.9961946980917455 0.08715574274765818 -vn 0 -0.9961946980917455 -0.08715574274765818 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o neck -v 0.0625 1.0087539855200642 -0.5754992319659105 -v 0.0625 1.041437389050436 -0.9490722437503151 -v 0.0625 0.7597053109971279 -0.597288167652825 -v 0.0625 0.7923887145274997 -0.9708611794372296 -v -0.0625 1.041437389050436 -0.9490722437503151 -v -0.0625 1.0087539855200642 -0.5754992319659105 -v -0.0625 0.7923887145274997 -0.9708611794372296 -v -0.0625 0.7597053109971279 -0.597288167652825 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 0.08715574274765818 -0.9961946980917455 -vn 1 0 0 -vn 0 -0.08715574274765818 0.9961946980917455 -vn -1 0 0 -vn 0 0.9961946980917455 0.08715574274765818 -vn 0 -0.9961946980917455 -0.08715574274765818 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o neck -v 0.3125 0.8044723392172863 -1.1226216863073408 -v 0.3125 0.8044723392172863 -1.7476216863073408 -v 0.3125 0.17947233921728634 -1.1226216863073408 -v 0.3125 0.17947233921728634 -1.7476216863073408 -v -0.3125 0.8044723392172863 -1.7476216863073408 -v -0.3125 0.8044723392172863 -1.1226216863073408 -v -0.3125 0.17947233921728634 -1.7476216863073408 -v -0.3125 0.17947233921728634 -1.1226216863073408 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o neck -v 0.0625 1.0544723392172863 -1.2476216863073408 -v 0.0625 1.0544723392172863 -1.6226216863073408 -v 0.0625 0.8044723392172863 -1.2476216863073408 -v 0.0625 0.8044723392172863 -1.6226216863073408 -v -0.0625 1.0544723392172863 -1.6226216863073408 -v -0.0625 1.0544723392172863 -1.2476216863073408 -v -0.0625 0.8044723392172863 -1.6226216863073408 -v -0.0625 0.8044723392172863 -1.2476216863073408 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o neck -v 0.3125 0.803283182370957 -1.774857855915984 -v 0.3125 0.7488108431536706 -2.3974795422233246 -v 0.3125 0.18066149606361592 -1.7203855166986977 -v 0.3125 0.12618915684632948 -2.3430072030060387 -v -0.3125 0.7488108431536706 -2.3974795422233246 -v -0.3125 0.803283182370957 -1.774857855915984 -v -0.3125 0.12618915684632948 -2.3430072030060387 -v -0.3125 0.18066149606361592 -1.7203855166986977 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.08715574274765818 -0.9961946980917455 -vn 1 0 0 -vn 0 0.08715574274765818 0.9961946980917455 -vn -1 0 0 -vn 0 0.9961946980917455 -0.08715574274765818 -vn 0 -0.9961946980917455 0.08715574274765818 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o neck -v 0.0625 1.041437389050436 -1.9211711288643667 -v 0.0625 1.0087539855200642 -2.2947441406487714 -v 0.0625 0.7923887145274997 -1.8993821931774522 -v 0.0625 0.7597053109971279 -2.272955204961857 -v -0.0625 1.0087539855200642 -2.2947441406487714 -v -0.0625 1.041437389050436 -1.9211711288643667 -v -0.0625 0.7597053109971279 -2.272955204961857 -v -0.0625 0.7923887145274997 -1.8993821931774522 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.08715574274765818 -0.9961946980917455 -vn 1 0 0 -vn 0 0.08715574274765818 0.9961946980917455 -vn -1 0 0 -vn 0 0.9961946980917455 -0.08715574274765818 -vn 0 -0.9961946980917455 0.08715574274765818 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o neck -v 0.3125 0.7452524228163151 -2.424508428135597 -v 0.3125 0.6367223117744836 -3.0400132737682273 -v 0.3125 0.1297475771836849 -2.315978317093766 -v 0.3125 0.02121746614185338 -2.931483162726396 -v -0.3125 0.6367223117744836 -3.0400132737682273 -v -0.3125 0.7452524228163151 -2.424508428135597 -v -0.3125 0.02121746614185338 -2.931483162726396 -v -0.3125 0.1297475771836849 -2.315978317093766 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.17364817766693036 -0.9848077530122081 -vn 1 0 0 -vn 0 0.17364817766693036 0.9848077530122081 -vn -1 0 0 -vn 0 0.9848077530122081 -0.17364817766693036 -vn 0 -0.9848077530122081 0.17364817766693036 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o neck -v 0.0625 0.9697483388610009 -2.591021441678856 -v 0.0625 0.9046302722359019 -2.960324349058434 -v 0.0625 0.7235464006079488 -2.5476093972621237 -v 0.0625 0.6584283339828498 -2.9169123046417016 -v -0.0625 0.9046302722359019 -2.960324349058434 -v -0.0625 0.9697483388610009 -2.591021441678856 -v -0.0625 0.6584283339828498 -2.9169123046417016 -v -0.0625 0.7235464006079488 -2.5476093972621237 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.17364817766693036 -0.9848077530122081 -vn 1 0 0 -vn 0 0.17364817766693036 0.9848077530122081 -vn -1 0 0 -vn 0 0.9848077530122081 -0.17364817766693036 -vn 0 -0.9848077530122081 0.17364817766693036 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o neck -v 0.3125 0.6308217096735025 -3.0666291698418497 -v 0.3125 0.469059806484427 -3.670332811272517 -v 0.3125 0.027118068242834803 -2.904867266652774 -v 0.3125 -0.13464383494624066 -3.5085709080834415 -v -0.3125 0.469059806484427 -3.670332811272517 -v -0.3125 0.6308217096735025 -3.0666291698418497 -v -0.3125 -0.13464383494624066 -3.5085709080834415 -v -0.3125 0.027118068242834803 -2.904867266652774 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.25881904510252074 -0.9659258262890683 -vn 1 0 0 -vn 0 0.25881904510252074 0.9659258262890683 -vn -1 0 0 -vn 0 0.9659258262890683 -0.25881904510252074 -vn 0 -0.9659258262890683 0.25881904510252074 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o neck -v 0.0625 0.8399507856079544 -3.252074659403613 -v 0.0625 0.7428936436945093 -3.6142968442620136 -v 0.0625 0.5984693290356873 -3.187369898127983 -v 0.0625 0.5014121871222421 -3.5495920829863836 -v -0.0625 0.7428936436945093 -3.6142968442620136 -v -0.0625 0.8399507856079544 -3.252074659403613 -v -0.0625 0.5014121871222421 -3.5495920829863836 -v -0.0625 0.5984693290356873 -3.187369898127983 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.25881904510252074 -0.9659258262890683 -vn 1 0 0 -vn 0 0.25881904510252074 0.9659258262890683 -vn -1 0 0 -vn 0 0.9659258262890683 -0.25881904510252074 -vn 0 -0.9659258262890683 0.25881904510252074 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o head -v 0.375 -0.07332885084174778 -4.433059161823504 -v 0.375 -0.41534899416741644 -5.372751782609413 -v 0.375 -0.3669827948373441 -4.326177867034232 -v 0.375 -0.7090029381630127 -5.265870487820141 -v -0.375 -0.41534899416741644 -5.372751782609413 -v -0.375 -0.07332885084174778 -4.433059161823504 -v -0.375 -0.7090029381630127 -5.265870487820141 -v -0.375 -0.3669827948373441 -4.326177867034232 -vt 0.75 0.765625 -vt 0.796875 0.765625 -vt 0.796875 0.74609375 -vt 0.75 0.74609375 -vt 0.6875 0.765625 -vt 0.75 0.765625 -vt 0.75 0.74609375 -vt 0.6875 0.74609375 -vt 0.859375 0.765625 -vt 0.90625 0.765625 -vt 0.90625 0.74609375 -vt 0.859375 0.74609375 -vt 0.796875 0.765625 -vt 0.859375 0.765625 -vt 0.859375 0.74609375 -vt 0.796875 0.74609375 -vt 0.796875 0.765625 -vt 0.75 0.765625 -vt 0.75 0.828125 -vt 0.796875 0.828125 -vt 0.84375 0.828125 -vt 0.796875 0.828125 -vt 0.796875 0.765625 -vt 0.84375 0.765625 -vn 0 -0.34202014332566877 -0.9396926207859084 -vn 1 0 0 -vn 0 0.34202014332566877 0.9396926207859084 -vn -1 0 0 -vn 0 0.9396926207859084 -0.34202014332566877 -vn 0 -0.9396926207859084 0.34202014332566877 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 -o head -v 0.5 0.6370542961620473 -3.760461931340814 -v 0.5 0.2950341528363787 -4.7001545521267225 -v 0.5 -0.3026383246238611 -3.418441788015145 -v 0.5 -0.6446584679495297 -4.358134408801053 -v -0.5 0.2950341528363787 -4.7001545521267225 -v -0.5 0.6370542961620473 -3.760461931340814 -v -0.5 -0.6446584679495297 -4.358134408801053 -v -0.5 -0.3026383246238611 -3.418441788015145 -vt 0.5 0.8203125 -vt 0.5625 0.8203125 -vt 0.5625 0.7578125 -vt 0.5 0.7578125 -vt 0.4375 0.8203125 -vt 0.5 0.8203125 -vt 0.5 0.7578125 -vt 0.4375 0.7578125 -vt 0.625 0.8203125 -vt 0.6875 0.8203125 -vt 0.6875 0.7578125 -vt 0.625 0.7578125 -vt 0.5625 0.8203125 -vt 0.625 0.8203125 -vt 0.625 0.7578125 -vt 0.5625 0.7578125 -vt 0.5625 0.8203125 -vt 0.5 0.8203125 -vt 0.5 0.8828125 -vt 0.5625 0.8828125 -vt 0.625 0.8828125 -vt 0.5625 0.8828125 -vt 0.5625 0.8203125 -vt 0.625 0.8203125 -vn 0 -0.34202014332566877 -0.9396926207859084 -vn 1 0 0 -vn 0 0.34202014332566877 0.9396926207859084 -vn -1 0 0 -vn 0 0.9396926207859084 -0.34202014332566877 -vn 0 -0.9396926207859084 0.34202014332566877 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 92/268/67 95/267/67 93/266/67 90/265/67 -f 91/272/68 92/271/68 90/270/68 89/269/68 -f 96/276/69 91/275/69 89/274/69 94/273/69 -f 95/280/70 96/279/70 94/278/70 93/277/70 -f 94/284/71 89/283/71 90/282/71 93/281/71 -f 95/288/72 92/287/72 91/286/72 96/285/72 -o head -v 0.3125 0.7864724155271074 -4.080890122368709 -v 0.3125 0.6582148617799817 -4.433274855163424 -v 0.3125 0.5515492603306302 -3.9953850865372913 -v 0.3125 0.42329170658350446 -4.347769819332006 -v 0.1875 0.6582148617799817 -4.433274855163424 -v 0.1875 0.7864724155271074 -4.080890122368709 -v 0.1875 0.42329170658350446 -4.347769819332006 -v 0.1875 0.5515492603306302 -3.9953850865372913 -vt 0.03125 0.9765625 -vt 0.0234375 0.9765625 -vt 0.0234375 0.9609375 -vt 0.03125 0.9609375 -vt 0.0546875 0.9765625 -vt 0.03125 0.9765625 -vt 0.03125 0.9609375 -vt 0.0546875 0.9609375 -vt 0.0625 0.9765625 -vt 0.0546875 0.9765625 -vt 0.0546875 0.9609375 -vt 0.0625 0.9609375 -vt 0.0234375 0.9765625 -vt 0 0.9765625 -vt 0 0.9609375 -vt 0.0234375 0.9609375 -vt 0.0234375 0.9765625 -vt 0.03125 0.9765625 -vt 0.03125 1 -vt 0.0234375 1 -vt 0.03125 1 -vt 0.0390625 1 -vt 0.0390625 0.9765625 -vt 0.03125 0.9765625 -vn 0 -0.34202014332566877 -0.9396926207859084 -vn 1 0 0 -vn 0 0.34202014332566877 0.9396926207859084 -vn -1 0 0 -vn 0 0.9396926207859084 -0.34202014332566877 -vn 0 -0.9396926207859084 0.34202014332566877 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 100/292/73 103/291/73 101/290/73 98/289/73 -f 99/296/74 100/295/74 98/294/74 97/293/74 -f 104/300/75 99/299/75 97/298/75 102/297/75 -f 103/304/76 104/303/76 102/302/76 101/301/76 -f 102/308/77 97/307/77 98/306/77 101/305/77 -f 103/312/78 100/311/78 99/310/78 104/309/78 -o head -v 0.3125 -0.16962986282205206 -5.063119567730405 -v 0.3125 -0.2551348986534694 -5.298042722926883 -v 0.3125 -0.28709144042029067 -5.020367049814697 -v 0.3125 -0.372596476251708 -5.255290205011175 -v 0.1875 -0.2551348986534694 -5.298042722926883 -v 0.1875 -0.16962986282205206 -5.063119567730405 -v 0.1875 -0.372596476251708 -5.255290205011175 -v 0.1875 -0.28709144042029067 -5.020367049814697 -vt 0.4609375 0.984375 -vt 0.453125 0.984375 -vt 0.453125 0.9765625 -vt 0.4609375 0.9765625 -vt 0.4765625 0.984375 -vt 0.4609375 0.984375 -vt 0.4609375 0.9765625 -vt 0.4765625 0.9765625 -vt 0.484375 0.984375 -vt 0.4765625 0.984375 -vt 0.4765625 0.9765625 -vt 0.484375 0.9765625 -vt 0.453125 0.984375 -vt 0.4375 0.984375 -vt 0.4375 0.9765625 -vt 0.453125 0.9765625 -vt 0.453125 0.984375 -vt 0.4609375 0.984375 -vt 0.4609375 1 -vt 0.453125 1 -vt 0.4609375 1 -vt 0.46875 1 -vt 0.46875 0.984375 -vt 0.4609375 0.984375 -vn 0 -0.34202014332566877 -0.9396926207859084 -vn 1 0 0 -vn 0 0.34202014332566877 0.9396926207859084 -vn -1 0 0 -vn 0 0.9396926207859084 -0.34202014332566877 -vn 0 -0.9396926207859084 0.34202014332566877 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 108/316/79 111/315/79 109/314/79 106/313/79 -f 107/320/80 108/319/80 106/318/80 105/317/80 -f 112/324/81 107/323/81 105/322/81 110/321/81 -f 111/328/82 112/327/82 110/326/82 109/325/82 -f 110/332/83 105/331/83 106/330/83 109/329/83 -f 111/336/84 108/335/84 107/334/84 112/333/84 -o head -v -0.1875 0.7864724155271074 -4.080890122368709 -v -0.1875 0.6582148617799817 -4.433274855163424 -v -0.1875 0.5515492603306302 -3.9953850865372913 -v -0.1875 0.42329170658350446 -4.347769819332006 -v -0.3125 0.6582148617799817 -4.433274855163424 -v -0.3125 0.7864724155271074 -4.080890122368709 -v -0.3125 0.42329170658350446 -4.347769819332006 -v -0.3125 0.5515492603306302 -3.9953850865372913 -vt 0.0234375 0.9765625 -vt 0.03125 0.9765625 -vt 0.03125 0.9609375 -vt 0.0234375 0.9609375 -vt 0 0.9765625 -vt 0.0234375 0.9765625 -vt 0.0234375 0.9609375 -vt 0 0.9609375 -vt 0.0546875 0.9765625 -vt 0.0625 0.9765625 -vt 0.0625 0.9609375 -vt 0.0546875 0.9609375 -vt 0.03125 0.9765625 -vt 0.0546875 0.9765625 -vt 0.0546875 0.9609375 -vt 0.03125 0.9609375 -vt 0.03125 0.9765625 -vt 0.0234375 0.9765625 -vt 0.0234375 1 -vt 0.03125 1 -vt 0.0390625 1 -vt 0.03125 1 -vt 0.03125 0.9765625 -vt 0.0390625 0.9765625 -vn 0 -0.34202014332566877 -0.9396926207859084 -vn 1 0 0 -vn 0 0.34202014332566877 0.9396926207859084 -vn -1 0 0 -vn 0 0.9396926207859084 -0.34202014332566877 -vn 0 -0.9396926207859084 0.34202014332566877 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 116/340/85 119/339/85 117/338/85 114/337/85 -f 115/344/86 116/343/86 114/342/86 113/341/86 -f 120/348/87 115/347/87 113/346/87 118/345/87 -f 119/352/88 120/351/88 118/350/88 117/349/88 -f 118/356/89 113/355/89 114/354/89 117/353/89 -f 119/360/90 116/359/90 115/358/90 120/357/90 -o head -v -0.1875 -0.16962986282205206 -5.063119567730405 -v -0.1875 -0.2551348986534694 -5.298042722926883 -v -0.1875 -0.28709144042029067 -5.020367049814697 -v -0.1875 -0.372596476251708 -5.255290205011175 -v -0.3125 -0.2551348986534694 -5.298042722926883 -v -0.3125 -0.16962986282205206 -5.063119567730405 -v -0.3125 -0.372596476251708 -5.255290205011175 -v -0.3125 -0.28709144042029067 -5.020367049814697 -vt 0.453125 0.984375 -vt 0.4609375 0.984375 -vt 0.4609375 0.9765625 -vt 0.453125 0.9765625 -vt 0.4375 0.984375 -vt 0.453125 0.984375 -vt 0.453125 0.9765625 -vt 0.4375 0.9765625 -vt 0.4765625 0.984375 -vt 0.484375 0.984375 -vt 0.484375 0.9765625 -vt 0.4765625 0.9765625 -vt 0.4609375 0.984375 -vt 0.4765625 0.984375 -vt 0.4765625 0.9765625 -vt 0.4609375 0.9765625 -vt 0.4609375 0.984375 -vt 0.453125 0.984375 -vt 0.453125 1 -vt 0.4609375 1 -vt 0.46875 1 -vt 0.4609375 1 -vt 0.4609375 0.984375 -vt 0.46875 0.984375 -vn 0 -0.34202014332566877 -0.9396926207859084 -vn 1 0 0 -vn 0 0.34202014332566877 0.9396926207859084 -vn -1 0 0 -vn 0 0.9396926207859084 -0.34202014332566877 -vn 0 -0.9396926207859084 0.34202014332566877 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 124/364/91 127/363/91 125/362/91 122/361/91 -f 123/368/92 124/367/92 122/366/92 121/365/92 -f 128/372/93 123/371/93 121/370/93 126/369/93 -f 127/376/94 128/375/94 126/374/94 125/373/94 -f 126/380/95 121/379/95 122/378/95 125/377/95 -f 127/384/96 124/383/96 123/382/96 128/381/96 -o jaw -v 0.375 -0.3814550631514302 -4.318644081003175 -v 0.375 -0.9550314995024762 -5.137796125292168 -v 0.375 -0.5862430742236779 -4.175249971915413 -v 0.375 -1.159819510574724 -4.994402016204406 -v -0.375 -0.9550314995024762 -5.137796125292168 -v -0.375 -0.3814550631514302 -4.318644081003175 -v -0.375 -1.159819510574724 -4.994402016204406 -v -0.375 -0.5862430742236779 -4.175249971915413 -vt 0.75 0.68359375 -vt 0.796875 0.68359375 -vt 0.796875 0.66796875 -vt 0.75 0.66796875 -vt 0.6875 0.68359375 -vt 0.75 0.68359375 -vt 0.75 0.66796875 -vt 0.6875 0.66796875 -vt 0.859375 0.68359375 -vt 0.90625 0.68359375 -vt 0.90625 0.66796875 -vt 0.859375 0.66796875 -vt 0.796875 0.68359375 -vt 0.859375 0.68359375 -vt 0.859375 0.66796875 -vt 0.796875 0.66796875 -vt 0.796875 0.68359375 -vt 0.75 0.68359375 -vt 0.75 0.74609375 -vt 0.796875 0.74609375 -vt 0.84375 0.74609375 -vt 0.796875 0.74609375 -vt 0.796875 0.68359375 -vt 0.84375 0.68359375 -vn 0 -0.5735764363510462 -0.8191520442889919 -vn 1 0 0 -vn 0 0.5735764363510462 0.8191520442889919 -vn -1 0 0 -vn 0 0.8191520442889919 -0.5735764363510462 -vn 0 -0.8191520442889919 0.5735764363510462 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 132/388/97 135/387/97 133/386/97 130/385/97 -f 131/392/98 132/391/98 130/390/98 129/389/98 -f 136/396/99 131/395/99 129/394/99 134/393/99 -f 135/400/100 136/399/100 134/398/100 133/397/100 -f 134/404/101 129/403/101 130/402/101 133/401/101 -f 135/408/102 132/407/102 131/406/102 136/405/102 -o body -v 0.75 1.25 3.5 -v 0.75 1.25 -0.5 -v 0.75 -0.25 3.5 -v 0.75 -0.25 -0.5 -v -0.75 1.25 -0.5 -v -0.75 1.25 3.5 -v -0.75 -0.25 -0.5 -v -0.75 -0.25 3.5 -vt 0.25 0.75 -vt 0.34375 0.75 -vt 0.34375 0.65625 -vt 0.25 0.65625 -vt 0 0.75 -vt 0.25 0.75 -vt 0.25 0.65625 -vt 0 0.65625 -vt 0.59375 0.75 -vt 0.6875 0.75 -vt 0.6875 0.65625 -vt 0.59375 0.65625 -vt 0.34375 0.75 -vt 0.59375 0.75 -vt 0.59375 0.65625 -vt 0.34375 0.65625 -vt 0.34375 0.75 -vt 0.25 0.75 -vt 0.25 1 -vt 0.34375 1 -vt 0.4375 1 -vt 0.34375 1 -vt 0.34375 0.75 -vt 0.4375 0.75 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 140/412/103 143/411/103 141/410/103 138/409/103 -f 139/416/104 140/415/104 138/414/104 137/413/104 -f 144/420/105 139/419/105 137/418/105 142/417/105 -f 143/424/106 144/423/106 142/422/106 141/421/106 -f 142/428/107 137/427/107 138/426/107 141/425/107 -f 143/432/108 140/431/108 139/430/108 144/429/108 -o body -v 0.0625 1.625 0.625 -v 0.0625 1.625 -0.125 -v 0.0625 1.25 0.625 -v 0.0625 1.25 -0.125 -v -0.0625 1.625 -0.125 -v -0.0625 1.625 0.625 -v -0.0625 1.25 -0.125 -v -0.0625 1.25 0.625 -vt 0.90625 0.74609375 -vt 0.9140625 0.74609375 -vt 0.9140625 0.72265625 -vt 0.90625 0.72265625 -vt 0.859375 0.74609375 -vt 0.90625 0.74609375 -vt 0.90625 0.72265625 -vt 0.859375 0.72265625 -vt 0.9609375 0.74609375 -vt 0.96875 0.74609375 -vt 0.96875 0.72265625 -vt 0.9609375 0.72265625 -vt 0.9140625 0.74609375 -vt 0.9609375 0.74609375 -vt 0.9609375 0.72265625 -vt 0.9140625 0.72265625 -vt 0.9140625 0.74609375 -vt 0.90625 0.74609375 -vt 0.90625 0.79296875 -vt 0.9140625 0.79296875 -vt 0.921875 0.79296875 -vt 0.9140625 0.79296875 -vt 0.9140625 0.74609375 -vt 0.921875 0.74609375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 148/436/109 151/435/109 149/434/109 146/433/109 -f 147/440/110 148/439/110 146/438/110 145/437/110 -f 152/444/111 147/443/111 145/442/111 150/441/111 -f 151/448/112 152/447/112 150/446/112 149/445/112 -f 150/452/113 145/451/113 146/450/113 149/449/113 -f 151/456/114 148/455/114 147/454/114 152/453/114 -o body -v 0.0625 1.625 1.875 -v 0.0625 1.625 1.125 -v 0.0625 1.25 1.875 -v 0.0625 1.25 1.125 -v -0.0625 1.625 1.125 -v -0.0625 1.625 1.875 -v -0.0625 1.25 1.125 -v -0.0625 1.25 1.875 -vt 0.90625 0.74609375 -vt 0.9140625 0.74609375 -vt 0.9140625 0.72265625 -vt 0.90625 0.72265625 -vt 0.859375 0.74609375 -vt 0.90625 0.74609375 -vt 0.90625 0.72265625 -vt 0.859375 0.72265625 -vt 0.9609375 0.74609375 -vt 0.96875 0.74609375 -vt 0.96875 0.72265625 -vt 0.9609375 0.72265625 -vt 0.9140625 0.74609375 -vt 0.9609375 0.74609375 -vt 0.9609375 0.72265625 -vt 0.9140625 0.72265625 -vt 0.9140625 0.74609375 -vt 0.90625 0.74609375 -vt 0.90625 0.79296875 -vt 0.9140625 0.79296875 -vt 0.921875 0.79296875 -vt 0.9140625 0.79296875 -vt 0.9140625 0.74609375 -vt 0.921875 0.74609375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 156/460/115 159/459/115 157/458/115 154/457/115 -f 155/464/116 156/463/116 154/462/116 153/461/116 -f 160/468/117 155/467/117 153/466/117 158/465/117 -f 159/472/118 160/471/118 158/470/118 157/469/118 -f 158/476/119 153/475/119 154/474/119 157/473/119 -f 159/480/120 156/479/120 155/478/120 160/477/120 -o body -v 0.0625 1.625 3.125 -v 0.0625 1.625 2.375 -v 0.0625 1.25 3.125 -v 0.0625 1.25 2.375 -v -0.0625 1.625 2.375 -v -0.0625 1.625 3.125 -v -0.0625 1.25 2.375 -v -0.0625 1.25 3.125 -vt 0.90625 0.74609375 -vt 0.9140625 0.74609375 -vt 0.9140625 0.72265625 -vt 0.90625 0.72265625 -vt 0.859375 0.74609375 -vt 0.90625 0.74609375 -vt 0.90625 0.72265625 -vt 0.859375 0.72265625 -vt 0.9609375 0.74609375 -vt 0.96875 0.74609375 -vt 0.96875 0.72265625 -vt 0.9609375 0.72265625 -vt 0.9140625 0.74609375 -vt 0.9609375 0.74609375 -vt 0.9609375 0.72265625 -vt 0.9140625 0.72265625 -vt 0.9140625 0.74609375 -vt 0.90625 0.74609375 -vt 0.90625 0.79296875 -vt 0.9140625 0.79296875 -vt 0.921875 0.79296875 -vt 0.9140625 0.79296875 -vt 0.9140625 0.74609375 -vt 0.921875 0.74609375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 164/484/121 167/483/121 165/482/121 162/481/121 -f 163/488/122 164/487/122 162/486/122 161/485/122 -f 168/492/123 163/491/123 161/490/123 166/489/123 -f 167/496/124 168/495/124 166/494/124 165/493/124 -f 166/500/125 161/499/125 162/498/125 165/497/125 -f 167/504/126 164/503/126 163/502/126 168/501/126 -o wing -v 4.0582975240428985 2.024698766671211 0.9789705600873082 -v 4.143802559874316 2.039775611474734 0.48656668358120414 -v 4.1451216128763635 1.5322948901651068 0.9789705600873082 -v 4.230626648707781 1.5473717349686296 0.48656668358120414 -v 0.7493404734989761 1.4412403606548134 -0.12120193825305198 -v 0.6638354376675588 1.4261635158512906 0.37120193825305203 -v 0.8361645623324412 0.9488364841487094 -0.12120193825305198 -v 0.7506595265010241 0.9337596393451866 0.37120193825305203 -vt 0.46875 0.625 -vt 0.6875 0.625 -vt 0.6875 0.59375 -vt 0.46875 0.59375 -vt 0.4375 0.625 -vt 0.46875 0.625 -vt 0.46875 0.59375 -vt 0.4375 0.59375 -vt 0.71875 0.625 -vt 0.9375 0.625 -vt 0.9375 0.59375 -vt 0.71875 0.59375 -vt 0.6875 0.625 -vt 0.71875 0.625 -vt 0.71875 0.59375 -vt 0.6875 0.59375 -vt 0.6875 0.625 -vt 0.46875 0.625 -vt 0.46875 0.65625 -vt 0.6875 0.65625 -vt 0.90625 0.65625 -vt 0.6875 0.65625 -vt 0.6875 0.625 -vt 0.90625 0.625 -vn 0.17101007166283433 0.030153689607045803 -0.984807753012208 -vn 0.9698463103929543 0.17101007166283436 0.17364817766693036 -vn -0.17101007166283433 -0.030153689607045803 0.984807753012208 -vn -0.9698463103929543 -0.17101007166283436 -0.17364817766693036 -vn -0.17364817766693033 0.984807753012208 0 -vn 0.17364817766693033 -0.984807753012208 0 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 172/508/127 175/507/127 173/506/127 170/505/127 -f 171/512/128 172/511/128 170/510/128 169/509/128 -f 176/516/129 171/515/129 169/514/129 174/513/129 -f 175/520/130 176/519/130 174/518/130 173/517/130 -f 174/524/131 169/523/131 170/522/131 173/521/131 -f 175/528/132 172/527/132 171/526/132 176/525/132 -o wing -v 3.5249413191357313 1.677431666078797 4.303420761460185 -v 4.123690332545229 1.7830072718154657 0.8553626162261914 -v 3.525158379357814 1.6762006563875311 4.303420761460185 -v 4.123907392767313 1.7817762621242004 0.8553626162261914 -v 0.7280159382818976 1.184258258405967 0.24737693416985151 -v 0.12926692487239855 1.0786826526692979 3.695435079403845 -v 0.728232998503981 1.1830272487147016 0.24737693416985151 -v 0.12948398509448222 1.0774516429780323 3.695435079403845 -vt 0 0.4375 -vt 0.21875 0.4375 -vt 0.21875 0.4375 -vt 0 0.4375 -vt -0.21875 0.4375 -vt 0 0.4375 -vt 0 0.4375 -vt -0.21875 0.4375 -vt 0.4375 0.4375 -vt 0.65625 0.4375 -vt 0.65625 0.4375 -vt 0.4375 0.4375 -vt 0.21875 0.4375 -vt 0.4375 0.4375 -vt 0.4375 0.4375 -vt 0.21875 0.4375 -vt 0.21875 0.4375 -vt 0 0.4375 -vt 0 0.65625 -vt 0.21875 0.65625 -vt 0.4375 0.65625 -vt 0.21875 0.65625 -vt 0.21875 0.4375 -vt 0.4375 0.4375 -vn 0.17101007166283433 0.030153689607045803 -0.984807753012208 -vn 0.9698463103929543 0.17101007166283436 0.17364817766693036 -vn -0.17101007166283433 -0.030153689607045803 0.984807753012208 -vn -0.9698463103929543 -0.17101007166283436 -0.17364817766693036 -vn -0.17364817766693033 0.984807753012208 0 -vn 0.17364817766693033 -0.984807753012208 0 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 180/532/133 183/531/133 181/530/133 178/529/133 -f 179/536/134 180/535/134 178/534/134 177/533/134 -f 184/540/135 179/539/135 177/538/135 182/537/135 -f 183/544/136 184/543/136 182/542/136 181/541/136 -f 182/548/137 177/547/137 178/546/137 181/545/137 -f 183/552/138 180/551/138 179/550/138 184/549/138 -o wingtip -v 7.541772295535269 1.2888090706299558 1.4344091768703897 -v 7.584524813450978 1.2963474930317171 1.1882072386173377 -v 7.499639529805786 1.0428327037253111 1.4195613832169185 -v 7.542392047721496 1.0503711261270725 1.1733594449638665 -v 4.186904728197936 1.912792645473123 0.6170915495344658 -v 4.144152210282227 1.9052542230713616 0.8632934877875178 -v 4.144771962468453 1.6668162785684784 0.6022437558809948 -v 4.102019444552744 1.659277856166717 0.8484456941340466 -vt 0.453125 0.453125 -vt 0.671875 0.453125 -vt 0.671875 0.4375 -vt 0.453125 0.4375 -vt 0.4375 0.453125 -vt 0.453125 0.453125 -vt 0.453125 0.4375 -vt 0.4375 0.4375 -vt 0.6875 0.453125 -vt 0.90625 0.453125 -vt 0.90625 0.4375 -vt 0.6875 0.4375 -vt 0.671875 0.453125 -vt 0.6875 0.453125 -vt 0.6875 0.4375 -vt 0.671875 0.4375 -vt 0.671875 0.453125 -vt 0.453125 0.453125 -vt 0.453125 0.46875 -vt 0.671875 0.46875 -vt 0.890625 0.46875 -vt 0.671875 0.46875 -vt 0.671875 0.453125 -vt 0.890625 0.453125 -vn 0.17101007166283436 0.0301536896070458 -0.9848077530122081 -vn 0.9707485957865836 -0.1761271864118303 0.16317591116653485 -vn -0.17101007166283436 -0.0301536896070458 0.9848077530122081 -vn -0.9707485957865836 0.1761271864118303 -0.16317591116653485 -vn 0.16853106291793427 0.9839054676185789 0.059391174613884684 -vn -0.16853106291793427 -0.9839054676185789 -0.059391174613884684 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 188/556/139 191/555/139 189/554/139 186/553/139 -f 187/560/140 188/559/140 186/558/140 185/557/140 -f 192/564/141 187/563/141 185/562/141 190/561/141 -f 191/568/142 192/567/142 190/566/142 189/565/142 -f 190/572/143 185/571/143 186/570/143 189/569/143 -f 191/576/144 188/575/144 187/574/144 192/573/144 -o wingtip -v 6.922775830342509 1.060768988922723 4.874567024860628 -v 7.521524843752008 1.1663445946593922 1.4265088796266343 -v 6.922565166513862 1.0595391070881996 4.874492785892361 -v 7.521314179923362 1.165114712824869 1.426434640658367 -v 4.122691322754232 1.7830099060838132 0.855189220654804 -v 3.523942309344733 1.677434300347144 4.303247365888798 -v 4.122480658925585 1.7817800242492896 0.8551149816865367 -v 3.5237316455160856 1.6762044185126204 4.30317312692053 -vt 0 0.21875 -vt 0.21875 0.21875 -vt 0.21875 0.21875 -vt 0 0.21875 -vt -0.21875 0.21875 -vt 0 0.21875 -vt 0 0.21875 -vt -0.21875 0.21875 -vt 0.4375 0.21875 -vt 0.65625 0.21875 -vt 0.65625 0.21875 -vt 0.4375 0.21875 -vt 0.21875 0.21875 -vt 0.4375 0.21875 -vt 0.4375 0.21875 -vt 0.21875 0.21875 -vt 0.21875 0.21875 -vt 0 0.21875 -vt 0 0.4375 -vt 0.21875 0.4375 -vt 0.4375 0.4375 -vt 0.21875 0.4375 -vt 0.21875 0.21875 -vt 0.4375 0.21875 -vn 0.17101007166283436 0.0301536896070458 -0.9848077530122081 -vn 0.9707485957865836 -0.1761271864118303 0.16317591116653485 -vn -0.17101007166283436 -0.0301536896070458 0.9848077530122081 -vn -0.9707485957865836 0.1761271864118303 -0.16317591116653485 -vn 0.16853106291793427 0.9839054676185789 0.059391174613884684 -vn -0.16853106291793427 -0.9839054676185789 -0.059391174613884684 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 196/580/145 199/579/145 197/578/145 194/577/145 -f 195/584/146 196/583/146 194/582/146 193/581/146 -f 200/588/147 195/587/147 193/586/147 198/585/147 -f 199/592/148 200/591/148 198/590/148 197/589/148 -f 198/596/149 193/595/149 194/594/149 197/593/149 -f 199/600/150 196/599/150 195/598/150 200/597/150 -o wing1 -v -0.6638354376675588 1.4261635158512906 0.37120193825305203 -v -0.749340473498976 1.4412403606548134 -0.12120193825305198 -v -0.7506595265010241 0.9337596393451866 0.37120193825305203 -v -0.8361645623324412 0.9488364841487094 -0.12120193825305198 -v -4.143802559874316 2.039775611474734 0.48656668358120414 -v -4.0582975240428985 2.024698766671211 0.9789705600873082 -v -4.230626648707781 1.5473717349686296 0.48656668358120414 -v -4.1451216128763635 1.5322948901651068 0.9789705600873082 -vt 0.6875 0.625 -vt 0.46875 0.625 -vt 0.46875 0.59375 -vt 0.6875 0.59375 -vt 0.71875 0.625 -vt 0.6875 0.625 -vt 0.6875 0.59375 -vt 0.71875 0.59375 -vt 0.9375 0.625 -vt 0.71875 0.625 -vt 0.71875 0.59375 -vt 0.9375 0.59375 -vt 0.46875 0.625 -vt 0.4375 0.625 -vt 0.4375 0.59375 -vt 0.46875 0.59375 -vt 0.46875 0.625 -vt 0.6875 0.625 -vt 0.6875 0.65625 -vt 0.46875 0.65625 -vt 0.6875 0.65625 -vt 0.90625 0.65625 -vt 0.90625 0.625 -vt 0.6875 0.625 -vn -0.17101007166283433 0.030153689607045803 -0.984807753012208 -vn 0.9698463103929543 -0.17101007166283436 -0.17364817766693036 -vn 0.17101007166283433 -0.030153689607045803 0.984807753012208 -vn -0.9698463103929543 0.17101007166283436 0.17364817766693036 -vn 0.17364817766693033 0.984807753012208 0 -vn -0.17364817766693033 -0.984807753012208 0 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 204/604/151 207/603/151 205/602/151 202/601/151 -f 203/608/152 204/607/152 202/606/152 201/605/152 -f 208/612/153 203/611/153 201/610/153 206/609/153 -f 207/616/154 208/615/154 206/614/154 205/613/154 -f 206/620/155 201/619/155 202/618/155 205/617/155 -f 207/624/156 204/623/156 203/622/156 208/621/156 -o wing1 -v -0.1292669248723986 1.0786826526692979 3.695435079403845 -v -0.7280159382818975 1.184258258405967 0.24737693416985151 -v -0.12948398509448228 1.0774516429780323 3.695435079403845 -v -0.7282329985039812 1.1830272487147016 0.24737693416985151 -v -4.123690332545229 1.7830072718154657 0.8553626162261914 -v -3.524941319135731 1.677431666078797 4.303420761460185 -v -4.123907392767313 1.7817762621242004 0.8553626162261914 -v -3.5251583793578143 1.6762006563875311 4.303420761460185 -vt 0.21875 0.4375 -vt 0 0.4375 -vt 0 0.4375 -vt 0.21875 0.4375 -vt 0.4375 0.4375 -vt 0.21875 0.4375 -vt 0.21875 0.4375 -vt 0.4375 0.4375 -vt 0.65625 0.4375 -vt 0.4375 0.4375 -vt 0.4375 0.4375 -vt 0.65625 0.4375 -vt 0 0.4375 -vt -0.21875 0.4375 -vt -0.21875 0.4375 -vt 0 0.4375 -vt 0 0.4375 -vt 0.21875 0.4375 -vt 0.21875 0.65625 -vt 0 0.65625 -vt 0.21875 0.65625 -vt 0.4375 0.65625 -vt 0.4375 0.4375 -vt 0.21875 0.4375 -vn -0.17101007166283433 0.030153689607045803 -0.984807753012208 -vn 0.9698463103929543 -0.17101007166283436 -0.17364817766693036 -vn 0.17101007166283433 -0.030153689607045803 0.984807753012208 -vn -0.9698463103929543 0.17101007166283436 0.17364817766693036 -vn 0.17364817766693033 0.984807753012208 0 -vn -0.17364817766693033 -0.984807753012208 0 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 212/628/157 215/627/157 213/626/157 210/625/157 -f 211/632/158 212/631/158 210/630/158 209/629/158 -f 216/636/159 211/635/159 209/634/159 214/633/159 -f 215/640/160 216/639/160 214/638/160 213/637/160 -f 214/644/161 209/643/161 210/642/161 213/641/161 -f 215/648/162 212/647/162 211/646/162 216/645/162 -o wingtip1 -v -4.144152210282227 1.9052542230713616 0.8632934877875178 -v -4.186904728197936 1.912792645473123 0.6170915495344658 -v -4.102019444552744 1.659277856166717 0.8484456941340466 -v -4.144771962468453 1.6668162785684784 0.6022437558809948 -v -7.584524813450978 1.2963474930317171 1.1882072386173377 -v -7.541772295535269 1.2888090706299558 1.4344091768703897 -v -7.542392047721495 1.0503711261270725 1.1733594449638665 -v -7.499639529805786 1.0428327037253111 1.4195613832169185 -vt 0.671875 0.453125 -vt 0.453125 0.453125 -vt 0.453125 0.4375 -vt 0.671875 0.4375 -vt 0.6875 0.453125 -vt 0.671875 0.453125 -vt 0.671875 0.4375 -vt 0.6875 0.4375 -vt 0.90625 0.453125 -vt 0.6875 0.453125 -vt 0.6875 0.4375 -vt 0.90625 0.4375 -vt 0.453125 0.453125 -vt 0.4375 0.453125 -vt 0.4375 0.4375 -vt 0.453125 0.4375 -vt 0.453125 0.453125 -vt 0.671875 0.453125 -vt 0.671875 0.46875 -vt 0.453125 0.46875 -vt 0.671875 0.46875 -vt 0.890625 0.46875 -vt 0.890625 0.453125 -vt 0.671875 0.453125 -vn -0.17101007166283436 0.0301536896070458 -0.9848077530122081 -vn 0.9707485957865836 0.1761271864118303 -0.16317591116653485 -vn 0.17101007166283436 -0.0301536896070458 0.9848077530122081 -vn -0.9707485957865836 -0.1761271864118303 0.16317591116653485 -vn -0.16853106291793427 0.9839054676185789 0.059391174613884684 -vn 0.16853106291793427 -0.9839054676185789 -0.059391174613884684 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 220/652/163 223/651/163 221/650/163 218/649/163 -f 219/656/164 220/655/164 218/654/164 217/653/164 -f 224/660/165 219/659/165 217/658/165 222/657/165 -f 223/664/166 224/663/166 222/662/166 221/661/166 -f 222/668/167 217/667/167 218/666/167 221/665/167 -f 223/672/168 220/671/168 219/670/168 224/669/168 -o wingtip1 -v -3.523942309344733 1.677434300347144 4.303247365888798 -v -4.122691322754232 1.7830099060838132 0.855189220654804 -v -3.5237316455160856 1.6762044185126204 4.30317312692053 -v -4.122480658925585 1.7817800242492896 0.8551149816865367 -v -7.521524843752008 1.1663445946593922 1.4265088796266343 -v -6.922775830342509 1.060768988922723 4.874567024860628 -v -7.521314179923361 1.165114712824869 1.426434640658367 -v -6.922565166513862 1.0595391070881996 4.874492785892361 -vt 0.21875 0.21875 -vt 0 0.21875 -vt 0 0.21875 -vt 0.21875 0.21875 -vt 0.4375 0.21875 -vt 0.21875 0.21875 -vt 0.21875 0.21875 -vt 0.4375 0.21875 -vt 0.65625 0.21875 -vt 0.4375 0.21875 -vt 0.4375 0.21875 -vt 0.65625 0.21875 -vt 0 0.21875 -vt -0.21875 0.21875 -vt -0.21875 0.21875 -vt 0 0.21875 -vt 0 0.21875 -vt 0.21875 0.21875 -vt 0.21875 0.4375 -vt 0 0.4375 -vt 0.21875 0.4375 -vt 0.4375 0.4375 -vt 0.4375 0.21875 -vt 0.21875 0.21875 -vn -0.17101007166283436 0.0301536896070458 -0.9848077530122081 -vn 0.9707485957865836 0.1761271864118303 -0.16317591116653485 -vn 0.17101007166283436 -0.0301536896070458 0.9848077530122081 -vn -0.9707485957865836 -0.1761271864118303 0.16317591116653485 -vn -0.16853106291793427 0.9839054676185789 0.059391174613884684 -vn 0.16853106291793427 -0.9839054676185789 -0.059391174613884684 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 228/676/169 231/675/169 229/674/169 226/673/169 -f 227/680/170 228/679/170 226/678/170 225/677/170 -f 232/684/171 227/683/171 225/682/171 230/681/171 -f 231/688/172 232/687/172 230/686/172 229/685/172 -f 230/692/173 225/691/173 226/690/173 229/689/173 -f 231/696/174 228/695/174 227/694/174 232/693/174 -o rearleg -v 1.5 1.0580127018922192 2.6584936490538906 -v 1.5 0.1919872981077808 2.1584936490538906 -v 1.5 0.05801270189221919 4.390544456622768 -v 1.5 -0.8080127018922196 3.8905444566227683 -v 0.5 0.1919872981077808 2.1584936490538906 -v 0.5 1.0580127018922192 2.6584936490538906 -v 0.5 -0.8080127018922196 3.8905444566227683 -v 0.5 0.05801270189221919 4.390544456622768 -vt 0.0625 0.9375 -vt 0.125 0.9375 -vt 0.125 0.8125 -vt 0.0625 0.8125 -vt 0 0.9375 -vt 0.0625 0.9375 -vt 0.0625 0.8125 -vt 0 0.8125 -vt 0.1875 0.9375 -vt 0.25 0.9375 -vt 0.25 0.8125 -vt 0.1875 0.8125 -vt 0.125 0.9375 -vt 0.1875 0.9375 -vt 0.1875 0.8125 -vt 0.125 0.8125 -vt 0.125 0.9375 -vt 0.0625 0.9375 -vt 0.0625 1 -vt 0.125 1 -vt 0.1875 1 -vt 0.125 1 -vt 0.125 0.9375 -vt 0.1875 0.9375 -vn 0 -0.8660254037844386 -0.5000000000000001 -vn 1 0 0 -vn 0 0.8660254037844386 0.5000000000000001 -vn -1 0 0 -vn 0 0.5000000000000001 -0.8660254037844386 -vn 0 -0.5000000000000001 0.8660254037844386 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 236/700/175 239/699/175 237/698/175 234/697/175 -f 235/704/176 236/703/176 234/702/176 233/701/176 -f 240/708/177 235/707/177 233/706/177 238/705/177 -f 239/712/178 240/711/178 238/710/178 237/709/178 -f 238/716/179 233/715/179 234/714/179 237/713/179 -f 239/720/180 236/719/180 235/718/180 240/717/180 -o rearlegtip -v 1.375 -0.009562569109802244 4.19903062623141 -v 1.375 -0.7567085926786117 4.133663819170667 -v 1.375 -0.18387405460511896 6.191420022414902 -v 1.375 -0.9310200781739284 6.126053215354158 -v 0.625 -0.7567085926786117 4.133663819170667 -v 0.625 -0.009562569109802244 4.19903062623141 -v 0.625 -0.9310200781739284 6.126053215354158 -v 0.625 -0.18387405460511896 6.191420022414902 -vt 0.8125 0.953125 -vt 0.859375 0.953125 -vt 0.859375 0.828125 -vt 0.8125 0.828125 -vt 0.765625 0.953125 -vt 0.8125 0.953125 -vt 0.8125 0.828125 -vt 0.765625 0.828125 -vt 0.90625 0.953125 -vt 0.953125 0.953125 -vt 0.953125 0.828125 -vt 0.90625 0.828125 -vt 0.859375 0.953125 -vt 0.90625 0.953125 -vt 0.90625 0.828125 -vt 0.859375 0.828125 -vt 0.859375 0.953125 -vt 0.8125 0.953125 -vt 0.8125 1 -vt 0.859375 1 -vt 0.90625 1 -vt 0.859375 1 -vt 0.859375 0.953125 -vt 0.90625 0.953125 -vn 0 -0.9961946980917455 -0.0871557427476583 -vn 1 0 0 -vn 0 0.9961946980917455 0.0871557427476583 -vn -1 0 0 -vn 0 0.0871557427476583 -0.9961946980917455 -vn 0 -0.0871557427476583 0.9961946980917455 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 244/724/181 247/723/181 245/722/181 242/721/181 -f 243/728/182 244/727/182 242/726/182 241/725/182 -f 248/732/183 243/731/183 241/730/183 246/729/183 -f 247/736/184 248/735/184 246/734/184 245/733/184 -f 246/740/185 241/739/185 242/738/185 245/737/185 -f 247/744/186 244/743/186 243/742/186 248/741/186 -o rearfoot -v 1.5625 -0.42819812424051307 5.992592482541166 -v 1.5625 -1.5772647889189804 6.956773897070976 -v 1.5625 -0.187152770608062 6.279859148710783 -v 1.5625 -1.3362194352865284 7.244040563240592 -v 0.4375 -1.5772647889189804 6.956773897070976 -v 0.4375 -0.42819812424051307 5.992592482541166 -v 0.4375 -1.3362194352865284 7.244040563240592 -v 0.4375 -0.187152770608062 6.279859148710783 -vt 0.53125 0.90625 -vt 0.6015625 0.90625 -vt 0.6015625 0.8828125 -vt 0.53125 0.8828125 -vt 0.4375 0.90625 -vt 0.53125 0.90625 -vt 0.53125 0.8828125 -vt 0.4375 0.8828125 -vt 0.6953125 0.90625 -vt 0.765625 0.90625 -vt 0.765625 0.8828125 -vt 0.6953125 0.8828125 -vt 0.6015625 0.90625 -vt 0.6953125 0.90625 -vt 0.6953125 0.8828125 -vt 0.6015625 0.8828125 -vt 0.6015625 0.90625 -vt 0.53125 0.90625 -vt 0.53125 1 -vt 0.6015625 1 -vt 0.671875 1 -vt 0.6015625 1 -vt 0.6015625 0.90625 -vt 0.671875 0.90625 -vn 0 -0.766044443118978 0.6427876096865393 -vn 1 0 0 -vn 0 0.766044443118978 -0.6427876096865393 -vn -1 0 0 -vn 0 -0.6427876096865393 -0.766044443118978 -vn 0 0.6427876096865393 0.766044443118978 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 252/748/187 255/747/187 253/746/187 250/745/187 -f 251/752/188 252/751/188 250/750/188 249/749/188 -f 256/756/189 251/755/189 249/754/189 254/753/189 -f 255/760/190 256/759/190 254/758/190 253/757/190 -f 254/764/191 249/763/191 250/762/191 253/761/191 -f 255/768/192 252/767/192 251/766/192 256/765/192 -o rearleg1 -v -0.5 1.0580127018922192 2.6584936490538906 -v -0.5 0.1919872981077808 2.1584936490538906 -v -0.5 0.05801270189221919 4.390544456622768 -v -0.5 -0.8080127018922196 3.8905444566227683 -v -1.5 0.1919872981077808 2.1584936490538906 -v -1.5 1.0580127018922192 2.6584936490538906 -v -1.5 -0.8080127018922196 3.8905444566227683 -v -1.5 0.05801270189221919 4.390544456622768 -vt 0.125 0.9375 -vt 0.0625 0.9375 -vt 0.0625 0.8125 -vt 0.125 0.8125 -vt 0.1875 0.9375 -vt 0.125 0.9375 -vt 0.125 0.8125 -vt 0.1875 0.8125 -vt 0.25 0.9375 -vt 0.1875 0.9375 -vt 0.1875 0.8125 -vt 0.25 0.8125 -vt 0.0625 0.9375 -vt 0 0.9375 -vt 0 0.8125 -vt 0.0625 0.8125 -vt 0.0625 0.9375 -vt 0.125 0.9375 -vt 0.125 1 -vt 0.0625 1 -vt 0.125 1 -vt 0.1875 1 -vt 0.1875 0.9375 -vt 0.125 0.9375 -vn 0 -0.8660254037844386 -0.5000000000000001 -vn 1 0 0 -vn 0 0.8660254037844386 0.5000000000000001 -vn -1 0 0 -vn 0 0.5000000000000001 -0.8660254037844386 -vn 0 -0.5000000000000001 0.8660254037844386 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 260/772/193 263/771/193 261/770/193 258/769/193 -f 259/776/194 260/775/194 258/774/194 257/773/194 -f 264/780/195 259/779/195 257/778/195 262/777/195 -f 263/784/196 264/783/196 262/782/196 261/781/196 -f 262/788/197 257/787/197 258/786/197 261/785/197 -f 263/792/198 260/791/198 259/790/198 264/789/198 -o rearlegtip -v -0.625 -0.009562569109802244 4.19903062623141 -v -0.625 -0.7567085926786117 4.133663819170667 -v -0.625 -0.18387405460511896 6.191420022414902 -v -0.625 -0.9310200781739284 6.126053215354158 -v -1.375 -0.7567085926786117 4.133663819170667 -v -1.375 -0.009562569109802244 4.19903062623141 -v -1.375 -0.9310200781739284 6.126053215354158 -v -1.375 -0.18387405460511896 6.191420022414902 -vt 0.859375 0.953125 -vt 0.8125 0.953125 -vt 0.8125 0.828125 -vt 0.859375 0.828125 -vt 0.90625 0.953125 -vt 0.859375 0.953125 -vt 0.859375 0.828125 -vt 0.90625 0.828125 -vt 0.953125 0.953125 -vt 0.90625 0.953125 -vt 0.90625 0.828125 -vt 0.953125 0.828125 -vt 0.8125 0.953125 -vt 0.765625 0.953125 -vt 0.765625 0.828125 -vt 0.8125 0.828125 -vt 0.8125 0.953125 -vt 0.859375 0.953125 -vt 0.859375 1 -vt 0.8125 1 -vt 0.859375 1 -vt 0.90625 1 -vt 0.90625 0.953125 -vt 0.859375 0.953125 -vn 0 -0.9961946980917455 -0.0871557427476583 -vn 1 0 0 -vn 0 0.9961946980917455 0.0871557427476583 -vn -1 0 0 -vn 0 0.0871557427476583 -0.9961946980917455 -vn 0 -0.0871557427476583 0.9961946980917455 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 268/796/199 271/795/199 269/794/199 266/793/199 -f 267/800/200 268/799/200 266/798/200 265/797/200 -f 272/804/201 267/803/201 265/802/201 270/801/201 -f 271/808/202 272/807/202 270/806/202 269/805/202 -f 270/812/203 265/811/203 266/810/203 269/809/203 -f 271/816/204 268/815/204 267/814/204 272/813/204 -o rearfoot -v -0.4375 -0.42819812424051307 5.992592482541166 -v -0.4375 -1.5772647889189804 6.956773897070976 -v -0.4375 -0.187152770608062 6.279859148710783 -v -0.4375 -1.3362194352865284 7.244040563240592 -v -1.5625 -1.5772647889189804 6.956773897070976 -v -1.5625 -0.42819812424051307 5.992592482541166 -v -1.5625 -1.3362194352865284 7.244040563240592 -v -1.5625 -0.187152770608062 6.279859148710783 -vt 0.6015625 0.90625 -vt 0.53125 0.90625 -vt 0.53125 0.8828125 -vt 0.6015625 0.8828125 -vt 0.6953125 0.90625 -vt 0.6015625 0.90625 -vt 0.6015625 0.8828125 -vt 0.6953125 0.8828125 -vt 0.765625 0.90625 -vt 0.6953125 0.90625 -vt 0.6953125 0.8828125 -vt 0.765625 0.8828125 -vt 0.53125 0.90625 -vt 0.4375 0.90625 -vt 0.4375 0.8828125 -vt 0.53125 0.8828125 -vt 0.53125 0.90625 -vt 0.6015625 0.90625 -vt 0.6015625 1 -vt 0.53125 1 -vt 0.6015625 1 -vt 0.671875 1 -vt 0.671875 0.90625 -vt 0.6015625 0.90625 -vn 0 -0.766044443118978 0.6427876096865393 -vn 1 0 0 -vn 0 0.766044443118978 -0.6427876096865393 -vn -1 0 0 -vn 0 -0.6427876096865393 -0.766044443118978 -vn 0 0.6427876096865393 0.766044443118978 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 276/820/205 279/819/205 277/818/205 274/817/205 -f 275/824/206 276/823/206 274/822/206 273/821/206 -f 280/828/207 275/827/207 273/826/207 278/825/207 -f 279/832/208 280/831/208 278/830/208 277/829/208 -f 278/836/209 273/835/209 274/834/209 277/833/209 -f 279/840/210 276/839/210 275/838/210 280/837/210 -o frontleg -v 1 0.5822315121943373 0.004077618676012307 -v 1 0.1290776186760123 -0.20723151219433733 -v 1 -0.05169588041671158 1.3635392992309874 -v 1 -0.5048497739350366 1.1522301683606377 -v 0.5 0.1290776186760123 -0.20723151219433733 -v 0.5 0.5822315121943373 0.004077618676012307 -v 0.5 -0.5048497739350366 1.1522301683606377 -v 0.5 -0.05169588041671158 1.3635392992309874 -vt 0.46875 0.5625 -vt 0.5 0.5625 -vt 0.5 0.46875 -vt 0.46875 0.46875 -vt 0.4375 0.5625 -vt 0.46875 0.5625 -vt 0.46875 0.46875 -vt 0.4375 0.46875 -vt 0.53125 0.5625 -vt 0.5625 0.5625 -vt 0.5625 0.46875 -vt 0.53125 0.46875 -vt 0.5 0.5625 -vt 0.53125 0.5625 -vt 0.53125 0.46875 -vt 0.5 0.46875 -vt 0.5 0.5625 -vt 0.46875 0.5625 -vt 0.46875 0.59375 -vt 0.5 0.59375 -vt 0.53125 0.59375 -vt 0.5 0.59375 -vt 0.5 0.5625 -vt 0.53125 0.5625 -vn 0 -0.90630778703665 -0.4226182617406993 -vn 1 0 0 -vn 0 0.90630778703665 0.4226182617406993 -vn -1 0 0 -vn 0 0.4226182617406993 -0.90630778703665 -vn 0 -0.4226182617406993 0.90630778703665 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 284/844/211 287/843/211 285/842/211 282/841/211 -f 283/848/212 284/847/212 282/846/212 281/845/212 -f 288/852/213 283/851/213 281/850/213 286/849/213 -f 287/856/214 288/855/214 286/854/214 285/853/214 -f 286/860/215 281/859/215 282/858/215 285/857/215 -f 287/864/216 284/863/216 283/862/216 288/861/216 -o frontlegtip -v 0.9375 -0.10149613187923717 1.346273081444131 -v 0.9375 -0.3666611748241926 1.0811080384991758 -v 0.9375 -1.1621563036590583 2.4069332532239525 -v 0.9375 -1.4273213466040136 2.141768210278997 -v 0.5625 -0.3666611748241926 1.0811080384991758 -v 0.5625 -0.10149613187923717 1.346273081444131 -v 0.5625 -1.4273213466040136 2.141768210278997 -v 0.5625 -1.1621563036590583 2.4069332532239525 -vt 0.90625 0.4375 -vt 0.9296875 0.4375 -vt 0.9296875 0.34375 -vt 0.90625 0.34375 -vt 0.8828125 0.4375 -vt 0.90625 0.4375 -vt 0.90625 0.34375 -vt 0.8828125 0.34375 -vt 0.953125 0.4375 -vt 0.9765625 0.4375 -vt 0.9765625 0.34375 -vt 0.953125 0.34375 -vt 0.9296875 0.4375 -vt 0.953125 0.4375 -vt 0.953125 0.34375 -vt 0.9296875 0.34375 -vt 0.9296875 0.4375 -vt 0.90625 0.4375 -vt 0.90625 0.4609375 -vt 0.9296875 0.4609375 -vt 0.953125 0.4609375 -vt 0.9296875 0.4609375 -vt 0.9296875 0.4375 -vt 0.953125 0.4375 -vn 0 -0.7071067811865477 -0.7071067811865474 -vn 1 0 0 -vn 0 0.7071067811865477 0.7071067811865474 -vn -1 0 0 -vn 0 0.7071067811865474 -0.7071067811865477 -vn 0 -0.7071067811865474 0.7071067811865477 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 292/868/217 295/867/217 293/866/217 290/865/217 -f 291/872/218 292/871/218 290/870/218 289/869/218 -f 296/876/219 291/875/219 289/874/219 294/873/219 -f 295/880/220 296/879/220 294/878/220 293/877/220 -f 294/884/221 289/883/221 290/882/221 293/881/221 -f 295/888/222 292/887/222 291/886/222 296/885/222 -o frontfoot -v 1 -1.0005446513073766 2.2301565579273155 -v 1 -2.0005446513073766 2.2301565579273155 -v 1 -1.0005446513073766 2.4801565579273155 -v 1 -2.0005446513073766 2.4801565579273155 -v 0.5 -2.0005446513073766 2.2301565579273155 -v 0.5 -1.0005446513073766 2.2301565579273155 -v 0.5 -2.0005446513073766 2.4801565579273155 -v 0.5 -1.0005446513073766 2.4801565579273155 -vt 0.625 0.53125 -vt 0.65625 0.53125 -vt 0.65625 0.515625 -vt 0.625 0.515625 -vt 0.5625 0.53125 -vt 0.625 0.53125 -vt 0.625 0.515625 -vt 0.5625 0.515625 -vt 0.71875 0.53125 -vt 0.75 0.53125 -vt 0.75 0.515625 -vt 0.71875 0.515625 -vt 0.65625 0.53125 -vt 0.71875 0.53125 -vt 0.71875 0.515625 -vt 0.65625 0.515625 -vt 0.65625 0.53125 -vt 0.625 0.53125 -vt 0.625 0.59375 -vt 0.65625 0.59375 -vt 0.6875 0.59375 -vt 0.65625 0.59375 -vt 0.65625 0.53125 -vt 0.6875 0.53125 -vn 0 -1 2.7755575615628914e-16 -vn 1 0 0 -vn 0 1 -2.7755575615628914e-16 -vn -1 0 0 -vn 0 -2.7755575615628914e-16 -1 -vn 0 2.7755575615628914e-16 1 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 300/892/223 303/891/223 301/890/223 298/889/223 -f 299/896/224 300/895/224 298/894/224 297/893/224 -f 304/900/225 299/899/225 297/898/225 302/897/225 -f 303/904/226 304/903/226 302/902/226 301/901/226 -f 302/908/227 297/907/227 298/906/227 301/905/227 -f 303/912/228 300/911/228 299/910/228 304/909/228 -o frontleg1 -v -0.5 0.5822315121943373 0.004077618676012307 -v -0.5 0.1290776186760123 -0.20723151219433733 -v -0.5 -0.05169588041671158 1.3635392992309874 -v -0.5 -0.5048497739350366 1.1522301683606377 -v -1 0.1290776186760123 -0.20723151219433733 -v -1 0.5822315121943373 0.004077618676012307 -v -1 -0.5048497739350366 1.1522301683606377 -v -1 -0.05169588041671158 1.3635392992309874 -vt 0.5 0.5625 -vt 0.46875 0.5625 -vt 0.46875 0.46875 -vt 0.5 0.46875 -vt 0.53125 0.5625 -vt 0.5 0.5625 -vt 0.5 0.46875 -vt 0.53125 0.46875 -vt 0.5625 0.5625 -vt 0.53125 0.5625 -vt 0.53125 0.46875 -vt 0.5625 0.46875 -vt 0.46875 0.5625 -vt 0.4375 0.5625 -vt 0.4375 0.46875 -vt 0.46875 0.46875 -vt 0.46875 0.5625 -vt 0.5 0.5625 -vt 0.5 0.59375 -vt 0.46875 0.59375 -vt 0.5 0.59375 -vt 0.53125 0.59375 -vt 0.53125 0.5625 -vt 0.5 0.5625 -vn 0 -0.90630778703665 -0.4226182617406993 -vn 1 0 0 -vn 0 0.90630778703665 0.4226182617406993 -vn -1 0 0 -vn 0 0.4226182617406993 -0.90630778703665 -vn 0 -0.4226182617406993 0.90630778703665 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 308/916/229 311/915/229 309/914/229 306/913/229 -f 307/920/230 308/919/230 306/918/230 305/917/230 -f 312/924/231 307/923/231 305/922/231 310/921/231 -f 311/928/232 312/927/232 310/926/232 309/925/232 -f 310/932/233 305/931/233 306/930/233 309/929/233 -f 311/936/234 308/935/234 307/934/234 312/933/234 -o frontlegtip -v -0.5625 -0.10149613187923717 1.346273081444131 -v -0.5625 -0.3666611748241926 1.0811080384991758 -v -0.5625 -1.1621563036590583 2.4069332532239525 -v -0.5625 -1.4273213466040136 2.141768210278997 -v -0.9375 -0.3666611748241926 1.0811080384991758 -v -0.9375 -0.10149613187923717 1.346273081444131 -v -0.9375 -1.4273213466040136 2.141768210278997 -v -0.9375 -1.1621563036590583 2.4069332532239525 -vt 0.9296875 0.4375 -vt 0.90625 0.4375 -vt 0.90625 0.34375 -vt 0.9296875 0.34375 -vt 0.953125 0.4375 -vt 0.9296875 0.4375 -vt 0.9296875 0.34375 -vt 0.953125 0.34375 -vt 0.9765625 0.4375 -vt 0.953125 0.4375 -vt 0.953125 0.34375 -vt 0.9765625 0.34375 -vt 0.90625 0.4375 -vt 0.8828125 0.4375 -vt 0.8828125 0.34375 -vt 0.90625 0.34375 -vt 0.90625 0.4375 -vt 0.9296875 0.4375 -vt 0.9296875 0.4609375 -vt 0.90625 0.4609375 -vt 0.9296875 0.4609375 -vt 0.953125 0.4609375 -vt 0.953125 0.4375 -vt 0.9296875 0.4375 -vn 0 -0.7071067811865477 -0.7071067811865474 -vn 1 0 0 -vn 0 0.7071067811865477 0.7071067811865474 -vn -1 0 0 -vn 0 0.7071067811865474 -0.7071067811865477 -vn 0 -0.7071067811865474 0.7071067811865477 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 316/940/235 319/939/235 317/938/235 314/937/235 -f 315/944/236 316/943/236 314/942/236 313/941/236 -f 320/948/237 315/947/237 313/946/237 318/945/237 -f 319/952/238 320/951/238 318/950/238 317/949/238 -f 318/956/239 313/955/239 314/954/239 317/953/239 -f 319/960/240 316/959/240 315/958/240 320/957/240 -o frontfoot -v -0.5 -1.0005446513073766 2.2301565579273155 -v -0.5 -2.0005446513073766 2.2301565579273155 -v -0.5 -1.0005446513073766 2.4801565579273155 -v -0.5 -2.0005446513073766 2.4801565579273155 -v -1 -2.0005446513073766 2.2301565579273155 -v -1 -1.0005446513073766 2.2301565579273155 -v -1 -2.0005446513073766 2.4801565579273155 -v -1 -1.0005446513073766 2.4801565579273155 -vt 0.65625 0.53125 -vt 0.625 0.53125 -vt 0.625 0.515625 -vt 0.65625 0.515625 -vt 0.71875 0.53125 -vt 0.65625 0.53125 -vt 0.65625 0.515625 -vt 0.71875 0.515625 -vt 0.75 0.53125 -vt 0.71875 0.53125 -vt 0.71875 0.515625 -vt 0.75 0.515625 -vt 0.625 0.53125 -vt 0.5625 0.53125 -vt 0.5625 0.515625 -vt 0.625 0.515625 -vt 0.625 0.53125 -vt 0.65625 0.53125 -vt 0.65625 0.59375 -vt 0.625 0.59375 -vt 0.65625 0.59375 -vt 0.6875 0.59375 -vt 0.6875 0.53125 -vt 0.65625 0.53125 -vn 0 -1 2.7755575615628914e-16 -vn 1 0 0 -vn 0 1 -2.7755575615628914e-16 -vn -1 0 0 -vn 0 -2.7755575615628914e-16 -1 -vn 0 2.7755575615628914e-16 1 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 324/964/241 327/963/241 325/962/241 322/961/241 -f 323/968/242 324/967/242 322/966/242 321/965/242 -f 328/972/243 323/971/243 321/970/243 326/969/243 -f 327/976/244 328/975/244 326/974/244 325/973/244 -f 326/980/245 321/979/245 322/978/245 325/977/245 -f 327/984/246 324/983/246 323/982/246 328/981/246 -o tail -v 0.3125 1.1875 4.125 -v 0.3125 1.1875 3.5 -v 0.3125 0.5625 4.125 -v 0.3125 0.5625 3.5 -v -0.3125 1.1875 3.5 -v -0.3125 1.1875 4.125 -v -0.3125 0.5625 3.5 -v -0.3125 0.5625 4.125 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 332/988/247 335/987/247 333/986/247 330/985/247 -f 331/992/248 332/991/248 330/990/248 329/989/248 -f 336/996/249 331/995/249 329/994/249 334/993/249 -f 335/1000/250 336/999/250 334/998/250 333/997/250 -f 334/1004/251 329/1003/251 330/1002/251 333/1001/251 -f 335/1008/252 332/1007/252 331/1006/252 336/1005/252 -o tail -v 0.0625 1.4375 4 -v 0.0625 1.4375 3.625 -v 0.0625 1.1875 4 -v 0.0625 1.1875 3.625 -v -0.0625 1.4375 3.625 -v -0.0625 1.4375 4 -v -0.0625 1.1875 3.625 -v -0.0625 1.1875 4 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 340/1012/253 343/1011/253 341/1010/253 338/1009/253 -f 339/1016/254 340/1015/254 338/1014/254 337/1013/254 -f 344/1020/255 339/1019/255 337/1018/255 342/1017/255 -f 343/1024/256 344/1023/256 342/1022/256 341/1021/256 -f 342/1028/257 337/1027/257 338/1026/257 341/1025/257 -f 343/1032/258 340/1031/258 339/1030/258 344/1029/258 -o tail -v 0.3125 1.1983601587596744 4.744450932461093 -v 0.3125 1.1874524047363721 4.119546122988348 -v 0.3125 0.5734553492869299 4.755358686484396 -v 0.3125 0.5625475952636276 4.130453877011651 -v -0.3125 1.1874524047363721 4.119546122988348 -v -0.3125 1.1983601587596744 4.744450932461093 -v -0.3125 0.5625475952636276 4.130453877011651 -v -0.3125 0.5734553492869299 4.755358686484396 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.01745240643728351 -0.9998476951563913 -vn 1 0 0 -vn 0 0.01745240643728351 0.9998476951563913 -vn -1 0 0 -vn 0 0.9998476951563913 -0.01745240643728351 -vn 0 -0.9998476951563913 0.01745240643728351 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 348/1036/259 351/1035/259 349/1034/259 346/1033/259 -f 347/1040/260 348/1039/260 346/1038/260 345/1037/260 -f 352/1044/261 347/1043/261 345/1042/261 350/1041/261 -f 351/1048/262 352/1047/262 350/1046/262 349/1045/262 -f 350/1052/263 345/1051/263 346/1050/263 349/1049/263 -f 351/1056/264 348/1055/264 347/1054/264 352/1053/264 -o tail -v 0.0625 1.4461405317441118 4.615106868957223 -v 0.0625 1.4395958793301304 4.240163983273576 -v 0.0625 1.196178607955014 4.619469970566544 -v 0.0625 1.1896339555410327 4.244527084882897 -v -0.0625 1.4395958793301304 4.240163983273576 -v -0.0625 1.4461405317441118 4.615106868957223 -v -0.0625 1.1896339555410327 4.244527084882897 -v -0.0625 1.196178607955014 4.619469970566544 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.01745240643728351 -0.9998476951563913 -vn 1 0 0 -vn 0 0.01745240643728351 0.9998476951563913 -vn -1 0 0 -vn 0 0.9998476951563913 -0.01745240643728351 -vn 0 -0.9998476951563913 0.01745240643728351 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 356/1060/265 359/1059/265 357/1058/265 354/1057/265 -f 355/1064/266 356/1063/266 354/1062/266 353/1061/266 -f 360/1068/267 355/1067/267 353/1066/267 358/1065/267 -f 359/1072/268 360/1071/268 358/1070/268 357/1069/268 -f 358/1076/269 353/1075/269 354/1074/269 357/1073/269 -f 359/1080/270 356/1079/270 355/1078/270 360/1077/270 -o tail -v 0.3125 1.2200295729058328 5.363617983640148 -v 0.3125 1.1982173874667696 4.738998716753213 -v 0.3125 0.595410306018898 5.385430169079211 -v 0.3125 0.5735981205798348 4.760810902192276 -v -0.3125 1.1982173874667696 4.738998716753213 -v -0.3125 1.2200295729058328 5.363617983640148 -v -0.3125 0.5735981205798348 4.760810902192276 -v -0.3125 0.595410306018898 5.385430169079211 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.03489949670250097 -0.9993908270190958 -vn 1 0 0 -vn 0 0.03489949670250097 0.9993908270190958 -vn -1 0 0 -vn 0 0.9993908270190958 -0.03489949670250097 -vn 0 -0.9993908270190958 0.03489949670250097 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 364/1084/271 367/1083/271 365/1082/271 362/1081/271 -f 363/1088/272 364/1087/272 362/1086/272 361/1085/272 -f 368/1092/273 363/1091/273 361/1090/273 366/1089/273 -f 367/1096/274 368/1095/274 366/1094/274 365/1093/274 -f 366/1100/275 361/1099/275 362/1098/275 365/1097/275 -f 367/1104/276 364/1103/276 363/1102/276 368/1101/276 -o tail -v 0.0625 1.465514842572794 5.229969256087136 -v 0.0625 1.4524275313093562 4.855197695954975 -v 0.0625 1.21566713581802 5.238694130262761 -v 0.0625 1.2025798245545822 4.8639225701306 -v -0.0625 1.4524275313093562 4.855197695954975 -v -0.0625 1.465514842572794 5.229969256087136 -v -0.0625 1.2025798245545822 4.8639225701306 -v -0.0625 1.21566713581802 5.238694130262761 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.03489949670250097 -0.9993908270190958 -vn 1 0 0 -vn 0 0.03489949670250097 0.9993908270190958 -vn -1 0 0 -vn 0 0.9993908270190958 -0.03489949670250097 -vn 0 -0.9993908270190958 0.03489949670250097 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 372/1108/277 375/1107/277 373/1106/277 370/1105/277 -f 371/1112/278 372/1111/278 370/1110/278 369/1109/278 -f 376/1116/279 371/1115/279 369/1114/279 374/1113/279 -f 375/1120/280 376/1119/280 374/1118/280 373/1117/280 -f 374/1124/281 369/1123/281 370/1122/281 373/1121/281 -f 375/1128/282 372/1127/282 371/1126/282 376/1125/282 -o tail -v 0.3125 1.2525016417250097 5.982312549255369 -v 0.3125 1.2197916690731698 5.35816909003376 -v 0.3125 0.628358182503401 6.015022521907208 -v 0.3125 0.5956482098515612 5.3908790626856 -v -0.3125 1.2197916690731698 5.35816909003376 -v -0.3125 1.2525016417250097 5.982312549255369 -v -0.3125 0.5956482098515612 5.3908790626856 -v -0.3125 0.628358182503401 6.015022521907208 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.05233595624294383 -0.9986295347545739 -vn 1 0 0 -vn 0 0.05233595624294383 0.9986295347545739 -vn -1 0 0 -vn 0 0.9986295347545739 -0.05233595624294383 -vn 0 -0.9986295347545739 0.05233595624294383 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 380/1132/283 383/1131/283 381/1130/283 378/1129/283 -f 379/1136/284 380/1135/284 378/1134/284 377/1133/284 -f 384/1140/285 379/1139/285 377/1138/285 382/1137/285 -f 383/1144/286 384/1143/286 382/1142/286 381/1141/286 -f 382/1148/287 377/1147/287 378/1146/287 381/1145/287 -f 383/1152/288 380/1151/288 379/1150/288 384/1149/288 -o tail -v 0.0625 1.4956170308832855 5.844399868350311 -v 0.0625 1.4759910472921813 5.469913792817346 -v 0.0625 1.245959647194642 5.857483857411047 -v 0.0625 1.2263336636035378 5.482997781878082 -v -0.0625 1.4759910472921813 5.469913792817346 -v -0.0625 1.4956170308832855 5.844399868350311 -v -0.0625 1.2263336636035378 5.482997781878082 -v -0.0625 1.245959647194642 5.857483857411047 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.05233595624294383 -0.9986295347545739 -vn 1 0 0 -vn 0 0.05233595624294383 0.9986295347545739 -vn -1 0 0 -vn 0 0.9986295347545739 -0.05233595624294383 -vn 0 -0.9986295347545739 0.05233595624294383 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 388/1156/289 391/1155/289 389/1154/289 386/1153/289 -f 387/1160/290 388/1159/290 386/1158/290 385/1157/290 -f 392/1164/291 387/1163/291 385/1162/291 390/1161/291 -f 391/1168/292 392/1167/292 390/1166/292 389/1165/292 -f 390/1172/293 385/1171/293 386/1170/293 389/1169/293 -f 391/1176/294 388/1175/294 387/1174/294 392/1173/294 -o tail -v 0.3125 1.3062130944851622 6.594053052279986 -v 0.3125 1.2517407552678759 5.971431365972645 -v 0.3125 0.6835914081778212 6.648525391497273 -v 0.3125 0.6291190689605348 6.025903705189932 -v -0.3125 1.2517407552678759 5.971431365972645 -v -0.3125 1.3062130944851622 6.594053052279986 -v -0.3125 0.6291190689605348 6.025903705189932 -v -0.3125 0.6835914081778212 6.648525391497273 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.08715574274765817 -0.9961946980917457 -vn 1 0 0 -vn 0 0.08715574274765817 0.9961946980917457 -vn -1 0 0 -vn 0 0.9961946980917457 -0.08715574274765817 -vn 0 -0.9961946980917457 0.08715574274765817 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 396/1180/295 399/1179/295 397/1178/295 394/1177/295 -f 395/1184/296 396/1183/296 394/1182/296 393/1181/296 -f 400/1188/297 395/1187/297 393/1186/297 398/1185/297 -f 399/1192/298 400/1191/298 398/1190/298 397/1189/298 -f 398/1196/299 393/1195/299 394/1194/299 397/1193/299 -f 399/1200/300 396/1199/300 395/1198/300 400/1197/300 -o tail -v 0.0625 1.544367301164641 6.447739779331603 -v 0.0625 1.5116838976342697 6.074166767547199 -v 0.0625 1.295318626641705 6.469528715018518 -v 0.0625 1.2626352231113331 6.095955703234114 -v -0.0625 1.5116838976342697 6.074166767547199 -v -0.0625 1.544367301164641 6.447739779331603 -v -0.0625 1.2626352231113331 6.095955703234114 -v -0.0625 1.295318626641705 6.469528715018518 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.08715574274765817 -0.9961946980917457 -vn 1 0 0 -vn 0 0.08715574274765817 0.9961946980917457 -vn -1 0 0 -vn 0 0.9961946980917457 -0.08715574274765817 -vn 0 -0.9961946980917457 0.08715574274765817 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 404/1204/301 407/1203/301 405/1202/301 402/1201/301 -f 403/1208/302 404/1207/302 402/1206/302 401/1205/302 -f 408/1212/303 403/1211/303 401/1210/303 406/1209/303 -f 407/1216/304 408/1215/304 406/1214/304 405/1213/304 -f 406/1220/305 401/1219/305 402/1218/305 405/1217/305 -f 407/1224/306 404/1223/306 403/1222/306 408/1221/306 -o tail -v 0.3125 1.3913442109132734 7.196715170802091 -v 0.3125 1.304361022813232 6.577797627838609 -v 0.3125 0.772426667949792 7.283698358902132 -v 0.3125 0.6854434798497508 6.66478081593865 -v -0.3125 1.304361022813232 6.577797627838609 -v -0.3125 1.3913442109132734 7.196715170802091 -v -0.3125 0.6854434798497508 6.66478081593865 -v -0.3125 0.772426667949792 7.283698358902132 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.13917310096006544 -0.9902680687415704 -vn 1 0 0 -vn 0 0.13917310096006544 0.9902680687415704 -vn -1 0 0 -vn 0 0.9902680687415704 -0.13917310096006544 -vn 0 -0.9902680687415704 0.13917310096006544 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 412/1228/307 415/1227/307 413/1226/307 410/1225/307 -f 411/1232/308 412/1231/308 410/1230/308 409/1229/308 -f 416/1236/309 411/1235/309 409/1234/309 414/1233/309 -f 415/1240/310 416/1239/310 414/1238/310 413/1237/310 -f 414/1244/311 409/1243/311 410/1242/311 413/1241/311 -f 415/1248/312 412/1247/312 411/1246/312 416/1245/312 -o tail -v 0.0625 1.6215145904786574 7.038138386969378 -v 0.0625 1.5693246776186331 6.666787861191289 -v 0.0625 1.373947573293265 7.0729316622093945 -v 0.0625 1.3217576604332402 6.701581136431305 -v -0.0625 1.5693246776186331 6.666787861191289 -v -0.0625 1.6215145904786574 7.038138386969378 -v -0.0625 1.3217576604332402 6.701581136431305 -v -0.0625 1.373947573293265 7.0729316622093945 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.13917310096006544 -0.9902680687415704 -vn 1 0 0 -vn 0 0.13917310096006544 0.9902680687415704 -vn -1 0 0 -vn 0 0.9902680687415704 -0.13917310096006544 -vn 0 -0.9902680687415704 0.13917310096006544 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 420/1252/313 423/1251/313 421/1250/313 418/1249/313 -f 419/1256/314 420/1255/314 418/1254/314 417/1253/314 -f 424/1260/315 419/1259/315 417/1258/315 422/1257/315 -f 423/1264/316 424/1263/316 422/1262/316 421/1261/316 -f 422/1268/317 417/1267/317 418/1266/317 421/1265/317 -f 423/1272/318 420/1271/318 419/1270/318 424/1269/318 -o tail -v 0.3125 1.507899556369268 7.79409594345173 -v 0.3125 1.3886439342589278 7.180578953796941 -v 0.3125 0.894382566714478 7.9133515655620705 -v 0.3125 0.7751269446041376 7.299834575907282 -v -0.3125 1.3886439342589278 7.180578953796941 -v -0.3125 1.507899556369268 7.79409594345173 -v -0.3125 0.7751269446041376 7.299834575907282 -v -0.3125 0.894382566714478 7.9133515655620705 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.1908089953765448 -0.981627183447664 -vn 1 0 0 -vn 0 0.1908089953765448 0.981627183447664 -vn -1 0 0 -vn 0 0.981627183447664 -0.1908089953765448 -vn 0 -0.981627183447664 0.1908089953765448 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 428/1276/319 431/1275/319 429/1274/319 426/1273/319 -f 427/1280/320 428/1279/320 426/1278/320 425/1277/320 -f 432/1284/321 427/1283/321 425/1282/321 430/1281/321 -f 431/1288/322 432/1287/322 430/1286/322 429/1285/322 -f 430/1292/323 425/1291/323 426/1290/323 429/1289/323 -f 431/1296/324 428/1295/324 427/1294/324 432/1293/324 -o tail -v 0.0625 1.7294552278091162 7.623690296676635 -v 0.0625 1.6579018545429118 7.255580102883762 -v 0.0625 1.4840484319472 7.6713925455207725 -v 0.0625 1.4124950586809957 7.303282351727899 -v -0.0625 1.6579018545429118 7.255580102883762 -v -0.0625 1.7294552278091162 7.623690296676635 -v -0.0625 1.4124950586809957 7.303282351727899 -v -0.0625 1.4840484319472 7.6713925455207725 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.1908089953765448 -0.981627183447664 -vn 1 0 0 -vn 0 0.1908089953765448 0.981627183447664 -vn -1 0 0 -vn 0 0.981627183447664 -0.1908089953765448 -vn 0 -0.981627183447664 0.1908089953765448 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 436/1300/325 439/1299/325 437/1298/325 434/1297/325 -f 435/1304/326 436/1303/326 434/1302/326 433/1301/326 -f 440/1308/327 435/1307/327 433/1306/327 438/1305/327 -f 439/1312/328 440/1311/328 438/1310/328 437/1309/328 -f 438/1316/329 433/1315/329 434/1314/329 437/1313/329 -f 439/1320/330 436/1319/330 435/1318/330 440/1317/330 -o tail -v 0.3125 1.6367569935322868 8.40009360158498 -v 0.3125 1.506812186771187 7.788751351126351 -v 0.3125 1.025414743073658 8.53003840834608 -v 0.3125 0.8954699363125587 7.918696157887451 -v -0.3125 1.506812186771187 7.788751351126351 -v -0.3125 1.6367569935322868 8.40009360158498 -v -0.3125 0.8954699363125587 7.918696157887451 -v -0.3125 1.025414743073658 8.53003840834608 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.20791169081775934 -0.9781476007338057 -vn 1 0 0 -vn 0 0.20791169081775934 0.9781476007338057 -vn -1 0 0 -vn 0 0.9781476007338057 -0.20791169081775934 -vn 0 -0.9781476007338057 0.20791169081775934 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 444/1324/331 447/1323/331 445/1322/331 442/1321/331 -f 443/1328/332 444/1327/332 442/1326/332 441/1325/332 -f 448/1332/333 443/1331/333 441/1330/333 446/1329/333 -f 447/1336/334 448/1335/334 446/1334/334 445/1333/334 -f 446/1340/335 441/1339/335 442/1338/335 445/1337/335 -f 447/1344/336 444/1343/336 443/1342/336 448/1341/336 -o tail -v 0.0625 1.8553049323635182 8.225847228788815 -v 0.0625 1.7773380483068584 7.8590418785136364 -v 0.0625 1.6107680321800668 8.277825151493253 -v 0.0625 1.532801148123407 7.911019801218078 -v -0.0625 1.7773380483068584 7.8590418785136364 -v -0.0625 1.8553049323635182 8.225847228788815 -v -0.0625 1.532801148123407 7.911019801218078 -v -0.0625 1.6107680321800668 8.277825151493253 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.20791169081775934 -0.9781476007338057 -vn 1 0 0 -vn 0 0.20791169081775934 0.9781476007338057 -vn -1 0 0 -vn 0 0.9781476007338057 -0.20791169081775934 -vn 0 -0.9781476007338057 0.20791169081775934 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 452/1348/337 455/1347/337 453/1346/337 450/1345/337 -f 451/1352/338 452/1351/338 450/1350/338 449/1349/338 -f 456/1356/339 451/1355/339 449/1354/339 454/1353/339 -f 455/1360/340 456/1359/340 454/1358/340 453/1357/340 -f 454/1364/341 449/1363/341 450/1362/341 453/1361/341 -f 455/1368/342 452/1367/342 451/1366/342 456/1365/342 -o tail -v 0.3125 1.7570999852407079 9.018955183565149 -v 0.3125 1.6378443631303679 8.405438193910358 -v 0.3125 1.143582995585918 9.13821080567549 -v 0.3125 1.0243273734755776 8.524693816020699 -v -0.3125 1.6378443631303679 8.405438193910358 -v -0.3125 1.7570999852407079 9.018955183565149 -v -0.3125 1.0243273734755776 8.524693816020699 -v -0.3125 1.143582995585918 9.13821080567549 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.1908089953765448 -0.981627183447664 -vn 1 0 0 -vn 0 0.1908089953765448 0.981627183447664 -vn -1 0 0 -vn 0 0.981627183447664 -0.1908089953765448 -vn 0 -0.981627183447664 0.1908089953765448 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 460/1372/343 463/1371/343 461/1370/343 458/1369/343 -f 459/1376/344 460/1375/344 458/1374/344 457/1373/344 -f 464/1380/345 459/1379/345 457/1378/345 462/1377/345 -f 463/1384/346 464/1383/346 462/1382/346 461/1381/346 -f 462/1388/347 457/1387/347 458/1386/347 461/1385/347 -f 463/1392/348 460/1391/348 459/1390/348 464/1389/348 -o tail -v 0.0625 1.978655656680556 8.848549536790054 -v 0.0625 1.9071022834143516 8.480439342997181 -v 0.0625 1.73324886081864 8.89625178563419 -v 0.0625 1.6616954875524357 8.528141591841317 -v -0.0625 1.9071022834143516 8.480439342997181 -v -0.0625 1.978655656680556 8.848549536790054 -v -0.0625 1.6616954875524357 8.528141591841317 -v -0.0625 1.73324886081864 8.89625178563419 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.1908089953765448 -0.981627183447664 -vn 1 0 0 -vn 0 0.1908089953765448 0.981627183447664 -vn -1 0 0 -vn 0 0.981627183447664 -0.1908089953765448 -vn 0 -0.981627183447664 0.1908089953765448 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 468/1396/349 471/1395/349 469/1394/349 466/1393/349 -f 467/1400/350 468/1399/350 466/1398/350 465/1397/350 -f 472/1404/351 467/1403/351 465/1402/351 470/1401/351 -f 471/1408/352 472/1407/352 470/1406/352 469/1405/352 -f 470/1412/353 465/1411/353 466/1410/353 469/1409/353 -f 471/1416/354 468/1415/354 467/1414/354 472/1413/354 -o tail -v 0.3125 1.8567656374994383 9.64700243716721 -v 0.3125 1.7589940968492939 9.029697224295248 -v 0.3125 1.239460424627477 9.744773977817353 -v 0.3125 1.1416888839773327 9.127468764945391 -v -0.3125 1.7589940968492939 9.029697224295248 -v -0.3125 1.8567656374994383 9.64700243716721 -v -0.3125 1.1416888839773327 9.127468764945391 -v -0.3125 1.239460424627477 9.744773977817353 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.15643446504023087 -0.9876883405951378 -vn 1 0 0 -vn 0 0.15643446504023087 0.9876883405951378 -vn -1 0 0 -vn 0 0.9876883405951378 -0.15643446504023087 -vn 0 -0.9876883405951378 0.15643446504023087 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 476/1420/355 479/1419/355 477/1418/355 474/1417/355 -f 475/1424/356 476/1423/356 474/1422/356 473/1421/356 -f 480/1428/357 475/1427/357 473/1426/357 478/1425/357 -f 479/1432/358 480/1431/358 478/1430/358 477/1429/358 -f 478/1436/359 473/1435/359 474/1434/359 477/1433/359 -f 479/1440/360 476/1439/360 475/1438/360 480/1437/360 -o tail -v 0.0625 2.084133414518194 9.484432778332758 -v 0.0625 2.025470490128107 9.114049650609582 -v 0.0625 1.8372113293694095 9.523541394592817 -v 0.0625 1.7785484049793228 9.15315826686964 -v -0.0625 2.025470490128107 9.114049650609582 -v -0.0625 2.084133414518194 9.484432778332758 -v -0.0625 1.7785484049793228 9.15315826686964 -v -0.0625 1.8372113293694095 9.523541394592817 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.15643446504023087 -0.9876883405951378 -vn 1 0 0 -vn 0 0.15643446504023087 0.9876883405951378 -vn -1 0 0 -vn 0 0.9876883405951378 -0.15643446504023087 -vn 0 -0.9876883405951378 0.15643446504023087 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 484/1444/361 487/1443/361 485/1442/361 482/1441/361 -f 483/1448/362 484/1447/362 482/1446/362 481/1445/362 -f 488/1452/363 483/1451/363 481/1450/363 486/1449/363 -f 487/1456/364 488/1455/364 486/1454/364 485/1453/364 -f 486/1460/365 481/1459/365 482/1458/365 485/1457/365 -f 487/1464/366 484/1463/366 483/1462/366 488/1461/366 -o tail -v 0.3125 1.924231412908326 10.284799247326308 -v 0.3125 1.858901123366043 9.663223062721139 -v 0.3125 1.3026552283031554 10.350129536868593 -v 0.3125 1.237324938760872 9.728553352263424 -v -0.3125 1.858901123366043 9.663223062721139 -v -0.3125 1.924231412908326 10.284799247326308 -v -0.3125 1.237324938760872 9.728553352263424 -v -0.3125 1.3026552283031554 10.350129536868593 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.10452846326765347 -0.9945218953682733 -vn 1 0 0 -vn 0 0.10452846326765347 0.9945218953682733 -vn -1 0 0 -vn 0 0.9945218953682733 -0.10452846326765347 -vn 0 -0.9945218953682733 0.10452846326765347 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 492/1468/367 495/1467/367 493/1466/367 490/1465/367 -f 491/1472/368 492/1471/368 490/1470/368 489/1469/368 -f 496/1476/369 491/1475/369 489/1474/369 494/1473/369 -f 495/1480/370 496/1479/370 494/1478/370 493/1477/370 -f 494/1484/371 489/1483/371 490/1482/371 493/1481/371 -f 495/1488/372 492/1487/372 491/1486/372 496/1485/372 -o tail -v 0.0625 2.159795828841938 10.134351894588363 -v 0.0625 2.120597655116568 9.76140618382526 -v 0.0625 1.91116535499987 10.160484010405275 -v 0.0625 1.8719671812745 9.787538299642172 -v -0.0625 2.120597655116568 9.76140618382526 -v -0.0625 2.159795828841938 10.134351894588363 -v -0.0625 1.8719671812745 9.787538299642172 -v -0.0625 1.91116535499987 10.160484010405275 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.10452846326765347 -0.9945218953682733 -vn 1 0 0 -vn 0 0.10452846326765347 0.9945218953682733 -vn -1 0 0 -vn 0 0.9945218953682733 -0.10452846326765347 -vn 0 -0.9945218953682733 0.10452846326765347 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 500/1492/373 503/1491/373 501/1490/373 498/1489/373 -f 499/1496/374 500/1495/374 498/1494/374 497/1493/374 -f 504/1500/375 499/1499/375 497/1498/375 502/1497/375 -f 503/1504/376 504/1503/376 502/1502/376 501/1501/376 -f 502/1508/377 497/1507/377 498/1506/377 501/1505/377 -f 503/1512/378 500/1511/378 499/1510/378 504/1509/378 -o tail -v 0.3125 1.958225022868385 10.92525286499314 -v 0.3125 1.9255150502165446 10.301109405771532 -v 0.3125 1.3340815636467762 10.957962837644981 -v 0.3125 1.3013715909949364 10.333819378423373 -v -0.3125 1.9255150502165446 10.301109405771532 -v -0.3125 1.958225022868385 10.92525286499314 -v -0.3125 1.3013715909949364 10.333819378423373 -v -0.3125 1.3340815636467762 10.957962837644981 -vt 0.7890625 0.5546875 -vt 0.828125 0.5546875 -vt 0.828125 0.515625 -vt 0.7890625 0.515625 -vt 0.75 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.515625 -vt 0.75 0.515625 -vt 0.8671875 0.5546875 -vt 0.90625 0.5546875 -vt 0.90625 0.515625 -vt 0.8671875 0.515625 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vt 0.8671875 0.515625 -vt 0.828125 0.515625 -vt 0.828125 0.5546875 -vt 0.7890625 0.5546875 -vt 0.7890625 0.59375 -vt 0.828125 0.59375 -vt 0.8671875 0.59375 -vt 0.828125 0.59375 -vt 0.828125 0.5546875 -vt 0.8671875 0.5546875 -vn 0 -0.05233595624294385 -0.998629534754574 -vn 1 0 0 -vn 0 0.05233595624294385 0.998629534754574 -vn -1 0 0 -vn 0 0.998629534754574 -0.05233595624294385 -vn 0 -0.998629534754574 0.05233595624294385 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 508/1516/379 511/1515/379 509/1514/379 506/1513/379 -f 507/1520/380 508/1519/380 506/1518/380 505/1517/380 -f 512/1524/381 507/1523/381 505/1522/381 510/1521/381 -f 511/1528/382 512/1527/382 510/1526/382 509/1525/382 -f 510/1532/383 505/1531/383 506/1530/383 509/1529/383 -f 511/1536/384 508/1535/384 507/1534/384 512/1533/384 -o tail -v 0.0625 2.20134041202666 10.787340184088084 -v 0.0625 2.1817144284355567 10.412854108555118 -v 0.0625 1.9516830283380169 10.80042417314882 -v 0.0625 1.9320570447469132 10.425938097615854 -v -0.0625 2.1817144284355567 10.412854108555118 -v -0.0625 2.20134041202666 10.787340184088084 -v -0.0625 1.9320570447469132 10.425938097615854 -v -0.0625 1.9516830283380169 10.80042417314882 -vt 0.2109375 0.9765625 -vt 0.21875 0.9765625 -vt 0.21875 0.9609375 -vt 0.2109375 0.9609375 -vt 0.1875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 0.9609375 -vt 0.1875 0.9609375 -vt 0.2421875 0.9765625 -vt 0.25 0.9765625 -vt 0.25 0.9609375 -vt 0.2421875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2421875 0.9765625 -vt 0.2421875 0.9609375 -vt 0.21875 0.9609375 -vt 0.21875 0.9765625 -vt 0.2109375 0.9765625 -vt 0.2109375 1 -vt 0.21875 1 -vt 0.2265625 1 -vt 0.21875 1 -vt 0.21875 0.9765625 -vt 0.2265625 0.9765625 -vn 0 -0.05233595624294385 -0.998629534754574 -vn 1 0 0 -vn 0 0.05233595624294385 0.998629534754574 -vn -1 0 0 -vn 0 0.998629534754574 -0.05233595624294385 -vn 0 -0.998629534754574 0.05233595624294385 -usemtl m_e48612ca-0475-df4f-6d9d-44f43691817f -f 516/1540/385 519/1539/385 517/1538/385 514/1537/385 -f 515/1544/386 516/1543/386 514/1542/386 513/1541/386 -f 520/1548/387 515/1547/387 513/1546/387 518/1545/387 -f 519/1552/388 520/1551/388 518/1550/388 517/1549/388 -f 518/1556/389 513/1555/389 514/1554/389 517/1553/389 -f 519/1560/390 516/1559/390 515/1558/390 520/1557/390 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/enderman.obj b/renderer/viewer/three/entity/models/enderman.obj deleted file mode 100644 index 6b4056745..000000000 --- a/renderer/viewer/three/entity/models/enderman.obj +++ /dev/null @@ -1,325 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o Head -v 0.21875 2.96875 0.21875 -v 0.21875 2.96875 -0.21875 -v 0.21875 2.53125 0.21875 -v 0.21875 2.53125 -0.21875 -v -0.21875 2.96875 -0.21875 -v -0.21875 2.96875 0.21875 -v -0.21875 2.53125 -0.21875 -v -0.21875 2.53125 0.21875 -vt 0.125 0.75 -vt 0.25 0.75 -vt 0.25 0.5 -vt 0.125 0.5 -vt 0 0.75 -vt 0.125 0.75 -vt 0.125 0.5 -vt 0 0.5 -vt 0.375 0.75 -vt 0.5 0.75 -vt 0.5 0.5 -vt 0.375 0.5 -vt 0.25 0.75 -vt 0.375 0.75 -vt 0.375 0.5 -vt 0.25 0.5 -vt 0.25 0.75 -vt 0.125 0.75 -vt 0.125 1 -vt 0.25 1 -vt 0.375 1 -vt 0.25 1 -vt 0.25 0.75 -vt 0.375 0.75 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_981d8dac-1361-c897-71b0-9983b6b479fc -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o Head layer -v 0.21875 2.84375 0.21875 -v 0.21875 2.84375 -0.21875 -v 0.21875 2.40625 0.21875 -v 0.21875 2.40625 -0.21875 -v -0.21875 2.84375 -0.21875 -v -0.21875 2.84375 0.21875 -v -0.21875 2.40625 -0.21875 -v -0.21875 2.40625 0.21875 -vt 0.125 0.25 -vt 0.25 0.25 -vt 0.25 0 -vt 0.125 0 -vt 0 0.25 -vt 0.125 0.25 -vt 0.125 0 -vt 0 0 -vt 0.375 0.25 -vt 0.5 0.25 -vt 0.5 0 -vt 0.375 0 -vt 0.25 0.25 -vt 0.375 0.25 -vt 0.375 0 -vt 0.25 0 -vt 0.25 0.25 -vt 0.125 0.25 -vt 0.125 0.5 -vt 0.25 0.5 -vt 0.375 0.5 -vt 0.25 0.5 -vt 0.25 0.25 -vt 0.375 0.25 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_981d8dac-1361-c897-71b0-9983b6b479fc -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o Body -v 0.25 2.375 0.125 -v 0.25 2.375 -0.125 -v 0.25 1.625 0.125 -v 0.25 1.625 -0.125 -v -0.25 2.375 -0.125 -v -0.25 2.375 0.125 -v -0.25 1.625 -0.125 -v -0.25 1.625 0.125 -vt 0.5625 0.375 -vt 0.6875 0.375 -vt 0.6875 0 -vt 0.5625 0 -vt 0.5 0.375 -vt 0.5625 0.375 -vt 0.5625 0 -vt 0.5 0 -vt 0.75 0.375 -vt 0.875 0.375 -vt 0.875 0 -vt 0.75 0 -vt 0.6875 0.375 -vt 0.75 0.375 -vt 0.75 0 -vt 0.6875 0 -vt 0.6875 0.375 -vt 0.5625 0.375 -vt 0.5625 0.5 -vt 0.6875 0.5 -vt 0.8125 0.5 -vt 0.6875 0.5 -vt 0.6875 0.375 -vt 0.8125 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_981d8dac-1361-c897-71b0-9983b6b479fc -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o RightArm -v 0.375 2.375 0.0625 -v 0.375 2.375 -0.0625 -v 0.375 0.5 0.0625 -v 0.375 0.5 -0.0625 -v 0.25 2.375 -0.0625 -v 0.25 2.375 0.0625 -v 0.25 0.5 -0.0625 -v 0.25 0.5 0.0625 -vt 0.90625 0.9375 -vt 0.9375 0.9375 -vt 0.9375 0 -vt 0.90625 0 -vt 0.875 0.9375 -vt 0.90625 0.9375 -vt 0.90625 0 -vt 0.875 0 -vt 0.96875 0.9375 -vt 1 0.9375 -vt 1 0 -vt 0.96875 0 -vt 0.9375 0.9375 -vt 0.96875 0.9375 -vt 0.96875 0 -vt 0.9375 0 -vt 0.9375 0.9375 -vt 0.90625 0.9375 -vt 0.90625 1 -vt 0.9375 1 -vt 0.96875 1 -vt 0.9375 1 -vt 0.9375 0.9375 -vt 0.96875 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_981d8dac-1361-c897-71b0-9983b6b479fc -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o LeftArm -v -0.25 2.375 0.0625 -v -0.25 2.375 -0.0625 -v -0.25 0.5 0.0625 -v -0.25 0.5 -0.0625 -v -0.375 2.375 -0.0625 -v -0.375 2.375 0.0625 -v -0.375 0.5 -0.0625 -v -0.375 0.5 0.0625 -vt 0.9375 0.9375 -vt 0.90625 0.9375 -vt 0.90625 0 -vt 0.9375 0 -vt 0.96875 0.9375 -vt 0.9375 0.9375 -vt 0.9375 0 -vt 0.96875 0 -vt 1 0.9375 -vt 0.96875 0.9375 -vt 0.96875 0 -vt 1 0 -vt 0.90625 0.9375 -vt 0.875 0.9375 -vt 0.875 0 -vt 0.90625 0 -vt 0.90625 0.9375 -vt 0.9375 0.9375 -vt 0.9375 1 -vt 0.90625 1 -vt 0.9375 1 -vt 0.96875 1 -vt 0.96875 0.9375 -vt 0.9375 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_981d8dac-1361-c897-71b0-9983b6b479fc -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o RightLeg -v 0.1875 1.625 0.0625 -v 0.1875 1.625 -0.0625 -v 0.1875 -0.25 0.0625 -v 0.1875 -0.25 -0.0625 -v 0.0625 1.625 -0.0625 -v 0.0625 1.625 0.0625 -v 0.0625 -0.25 -0.0625 -v 0.0625 -0.25 0.0625 -vt 0.90625 0.9375 -vt 0.9375 0.9375 -vt 0.9375 0 -vt 0.90625 0 -vt 0.875 0.9375 -vt 0.90625 0.9375 -vt 0.90625 0 -vt 0.875 0 -vt 0.96875 0.9375 -vt 1 0.9375 -vt 1 0 -vt 0.96875 0 -vt 0.9375 0.9375 -vt 0.96875 0.9375 -vt 0.96875 0 -vt 0.9375 0 -vt 0.9375 0.9375 -vt 0.90625 0.9375 -vt 0.90625 1 -vt 0.9375 1 -vt 0.96875 1 -vt 0.9375 1 -vt 0.9375 0.9375 -vt 0.96875 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_981d8dac-1361-c897-71b0-9983b6b479fc -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o LeftLeg -v -0.0625 1.625 0.0625 -v -0.0625 1.625 -0.0625 -v -0.0625 -0.25 0.0625 -v -0.0625 -0.25 -0.0625 -v -0.1875 1.625 -0.0625 -v -0.1875 1.625 0.0625 -v -0.1875 -0.25 -0.0625 -v -0.1875 -0.25 0.0625 -vt 0.9375 0.9375 -vt 0.90625 0.9375 -vt 0.90625 0 -vt 0.9375 0 -vt 0.96875 0.9375 -vt 0.9375 0.9375 -vt 0.9375 0 -vt 0.96875 0 -vt 1 0.9375 -vt 0.96875 0.9375 -vt 0.96875 0 -vt 1 0 -vt 0.90625 0.9375 -vt 0.875 0.9375 -vt 0.875 0 -vt 0.90625 0 -vt 0.90625 0.9375 -vt 0.9375 0.9375 -vt 0.9375 1 -vt 0.90625 1 -vt 0.9375 1 -vt 0.96875 1 -vt 0.96875 0.9375 -vt 0.9375 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_981d8dac-1361-c897-71b0-9983b6b479fc -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/endermite.obj b/renderer/viewer/three/entity/models/endermite.obj deleted file mode 100644 index 595376cd2..000000000 --- a/renderer/viewer/three/entity/models/endermite.obj +++ /dev/null @@ -1,187 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o section_2 -v 0.09375 0.1875 0.21875 -v 0.09375 0.1875 0.15625 -v 0.09375 0 0.21875 -v 0.09375 0 0.15625 -v -0.09375 0.1875 0.15625 -v -0.09375 0.1875 0.21875 -v -0.09375 0 0.15625 -v -0.09375 0 0.21875 -vt 0.015625 0.53125 -vt 0.0625 0.53125 -vt 0.0625 0.4375 -vt 0.015625 0.4375 -vt 0 0.53125 -vt 0.015625 0.53125 -vt 0.015625 0.4375 -vt 0 0.4375 -vt 0.078125 0.53125 -vt 0.125 0.53125 -vt 0.125 0.4375 -vt 0.078125 0.4375 -vt 0.0625 0.53125 -vt 0.078125 0.53125 -vt 0.078125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.53125 -vt 0.015625 0.53125 -vt 0.015625 0.5625 -vt 0.0625 0.5625 -vt 0.109375 0.5625 -vt 0.0625 0.5625 -vt 0.0625 0.53125 -vt 0.109375 0.53125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_50f00cc5-283b-b301-14d6-d02da334960b -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o section_0 -v 0.125 0.1875 -0.15000000000000002 -v 0.125 0.1875 -0.275 -v 0.125 0 -0.15000000000000002 -v 0.125 0 -0.275 -v -0.125 0.1875 -0.275 -v -0.125 0.1875 -0.15000000000000002 -v -0.125 0 -0.275 -v -0.125 0 -0.15000000000000002 -vt 0.03125 0.9375 -vt 0.09375 0.9375 -vt 0.09375 0.84375 -vt 0.03125 0.84375 -vt 0 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.84375 -vt 0 0.84375 -vt 0.125 0.9375 -vt 0.1875 0.9375 -vt 0.1875 0.84375 -vt 0.125 0.84375 -vt 0.09375 0.9375 -vt 0.125 0.9375 -vt 0.125 0.84375 -vt 0.09375 0.84375 -vt 0.09375 0.9375 -vt 0.03125 0.9375 -vt 0.03125 1 -vt 0.09375 1 -vt 0.15625 1 -vt 0.09375 1 -vt 0.09375 0.9375 -vt 0.15625 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_50f00cc5-283b-b301-14d6-d02da334960b -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o section_1 -v 0.1875 0.25 0.16249999999999998 -v 0.1875 0.25 -0.15000000000000002 -v 0.1875 0 0.16249999999999998 -v 0.1875 0 -0.15000000000000002 -v -0.1875 0.25 -0.15000000000000002 -v -0.1875 0.25 0.16249999999999998 -v -0.1875 0 -0.15000000000000002 -v -0.1875 0 0.16249999999999998 -vt 0.078125 0.6875 -vt 0.171875 0.6875 -vt 0.171875 0.5625 -vt 0.078125 0.5625 -vt 0 0.6875 -vt 0.078125 0.6875 -vt 0.078125 0.5625 -vt 0 0.5625 -vt 0.25 0.6875 -vt 0.34375 0.6875 -vt 0.34375 0.5625 -vt 0.25 0.5625 -vt 0.171875 0.6875 -vt 0.25 0.6875 -vt 0.25 0.5625 -vt 0.171875 0.5625 -vt 0.171875 0.6875 -vt 0.078125 0.6875 -vt 0.078125 0.84375 -vt 0.171875 0.84375 -vt 0.265625 0.84375 -vt 0.171875 0.84375 -vt 0.171875 0.6875 -vt 0.265625 0.6875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_50f00cc5-283b-b301-14d6-d02da334960b -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o section_3 -v 0.03125 0.125 0.28125 -v 0.03125 0.125 0.21875 -v 0.03125 0 0.28125 -v 0.03125 0 0.21875 -v -0.03125 0.125 0.21875 -v -0.03125 0.125 0.28125 -v -0.03125 0 0.21875 -v -0.03125 0 0.28125 -vt 0.015625 0.40625 -vt 0.03125 0.40625 -vt 0.03125 0.34375 -vt 0.015625 0.34375 -vt 0 0.40625 -vt 0.015625 0.40625 -vt 0.015625 0.34375 -vt 0 0.34375 -vt 0.046875 0.40625 -vt 0.0625 0.40625 -vt 0.0625 0.34375 -vt 0.046875 0.34375 -vt 0.03125 0.40625 -vt 0.046875 0.40625 -vt 0.046875 0.34375 -vt 0.03125 0.34375 -vt 0.03125 0.40625 -vt 0.015625 0.40625 -vt 0.015625 0.4375 -vt 0.03125 0.4375 -vt 0.046875 0.4375 -vt 0.03125 0.4375 -vt 0.03125 0.40625 -vt 0.046875 0.40625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_50f00cc5-283b-b301-14d6-d02da334960b -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/fox.obj b/renderer/viewer/three/entity/models/fox.obj deleted file mode 100644 index a0645b37f..000000000 --- a/renderer/viewer/three/entity/models/fox.obj +++ /dev/null @@ -1,463 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.1875 0.6875 -0.1875 -v 0.1875 0.3125 -0.1875 -v 0.1875 0.6875 0.5 -v 0.1875 0.3124999999999999 0.5 -v -0.1875 0.3125 -0.1875 -v -0.1875 0.6875 -0.1875 -v -0.1875 0.3124999999999999 0.5 -v -0.1875 0.6875 0.5 -vt 0.625 0.34375 -vt 0.75 0.34375 -vt 0.75 0 -vt 0.625 0 -vt 0.5 0.34375 -vt 0.625 0.34375 -vt 0.625 0 -vt 0.5 0 -vt 0.875 0.34375 -vt 1 0.34375 -vt 1 0 -vt 0.875 0 -vt 0.75 0.34375 -vt 0.875 0.34375 -vt 0.875 0 -vt 0.75 0 -vt 0.75 0.34375 -vt 0.625 0.34375 -vt 0.625 0.53125 -vt 0.75 0.53125 -vt 0.875 0.53125 -vt 0.75 0.53125 -vt 0.75 0.34375 -vt 0.875 0.34375 -vn 0 -1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 -1 -vn 0 -2.220446049250313e-16 1 -usemtl m_55d42d08-0bdc-6d16-75c7-074abfaa1062 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o head -v 0.25 0.625 -0.1875 -v 0.25 0.625 -0.5625 -v 0.25 0.25 -0.1875 -v 0.25 0.25 -0.5625 -v -0.25 0.625 -0.5625 -v -0.25 0.625 -0.1875 -v -0.25 0.25 -0.5625 -v -0.25 0.25 -0.1875 -vt 0.14583333333333334 0.65625 -vt 0.3125 0.65625 -vt 0.3125 0.46875 -vt 0.14583333333333334 0.46875 -vt 0.020833333333333332 0.65625 -vt 0.14583333333333334 0.65625 -vt 0.14583333333333334 0.46875 -vt 0.020833333333333332 0.46875 -vt 0.4375 0.65625 -vt 0.6041666666666666 0.65625 -vt 0.6041666666666666 0.46875 -vt 0.4375 0.46875 -vt 0.3125 0.65625 -vt 0.4375 0.65625 -vt 0.4375 0.46875 -vt 0.3125 0.46875 -vt 0.3125 0.65625 -vt 0.14583333333333334 0.65625 -vt 0.14583333333333334 0.84375 -vt 0.3125 0.84375 -vt 0.4791666666666667 0.84375 -vt 0.3125 0.84375 -vt 0.3125 0.65625 -vt 0.4791666666666667 0.65625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_55d42d08-0bdc-6d16-75c7-074abfaa1062 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o head -v 0.25 0.75 -0.4375 -v 0.25 0.75 -0.5 -v 0.25 0.625 -0.4375 -v 0.25 0.625 -0.5 -v 0.125 0.75 -0.5 -v 0.125 0.75 -0.4375 -v 0.125 0.625 -0.5 -v 0.125 0.625 -0.4375 -vt 0.1875 0.9375 -vt 0.22916666666666666 0.9375 -vt 0.22916666666666666 0.875 -vt 0.1875 0.875 -vt 0.16666666666666666 0.9375 -vt 0.1875 0.9375 -vt 0.1875 0.875 -vt 0.16666666666666666 0.875 -vt 0.25 0.9375 -vt 0.2916666666666667 0.9375 -vt 0.2916666666666667 0.875 -vt 0.25 0.875 -vt 0.22916666666666666 0.9375 -vt 0.25 0.9375 -vt 0.25 0.875 -vt 0.22916666666666666 0.875 -vt 0.22916666666666666 0.9375 -vt 0.1875 0.9375 -vt 0.1875 0.96875 -vt 0.22916666666666666 0.96875 -vt 0.2708333333333333 0.96875 -vt 0.22916666666666666 0.96875 -vt 0.22916666666666666 0.9375 -vt 0.2708333333333333 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_55d42d08-0bdc-6d16-75c7-074abfaa1062 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o head -v -0.125 0.75 -0.4375 -v -0.125 0.75 -0.5 -v -0.125 0.625 -0.4375 -v -0.125 0.625 -0.5 -v -0.25 0.75 -0.5 -v -0.25 0.75 -0.4375 -v -0.25 0.625 -0.5 -v -0.25 0.625 -0.4375 -vt 0.3333333333333333 0.9375 -vt 0.375 0.9375 -vt 0.375 0.875 -vt 0.3333333333333333 0.875 -vt 0.3125 0.9375 -vt 0.3333333333333333 0.9375 -vt 0.3333333333333333 0.875 -vt 0.3125 0.875 -vt 0.3958333333333333 0.9375 -vt 0.4375 0.9375 -vt 0.4375 0.875 -vt 0.3958333333333333 0.875 -vt 0.375 0.9375 -vt 0.3958333333333333 0.9375 -vt 0.3958333333333333 0.875 -vt 0.375 0.875 -vt 0.375 0.9375 -vt 0.3333333333333333 0.9375 -vt 0.3333333333333333 0.96875 -vt 0.375 0.96875 -vt 0.4166666666666667 0.96875 -vt 0.375 0.96875 -vt 0.375 0.9375 -vt 0.4166666666666667 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_55d42d08-0bdc-6d16-75c7-074abfaa1062 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o head -v 0.125 0.375 -0.5625 -v 0.125 0.375 -0.75 -v 0.125 0.25 -0.5625 -v 0.125 0.25 -0.75 -v -0.125 0.375 -0.75 -v -0.125 0.375 -0.5625 -v -0.125 0.25 -0.75 -v -0.125 0.25 -0.5625 -vt 0.1875 0.34375 -vt 0.2708333333333333 0.34375 -vt 0.2708333333333333 0.28125 -vt 0.1875 0.28125 -vt 0.125 0.34375 -vt 0.1875 0.34375 -vt 0.1875 0.28125 -vt 0.125 0.28125 -vt 0.3333333333333333 0.34375 -vt 0.4166666666666667 0.34375 -vt 0.4166666666666667 0.28125 -vt 0.3333333333333333 0.28125 -vt 0.2708333333333333 0.34375 -vt 0.3333333333333333 0.34375 -vt 0.3333333333333333 0.28125 -vt 0.2708333333333333 0.28125 -vt 0.2708333333333333 0.34375 -vt 0.1875 0.34375 -vt 0.1875 0.4375 -vt 0.2708333333333333 0.4375 -vt 0.3541666666666667 0.4375 -vt 0.2708333333333333 0.4375 -vt 0.2708333333333333 0.34375 -vt 0.3541666666666667 0.34375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_55d42d08-0bdc-6d16-75c7-074abfaa1062 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o leg0 -v 0.18781249999999994 0.375 0.4375 -v 0.18781249999999994 0.375 0.3125 -v 0.18781249999999994 0 0.4375 -v 0.18781249999999994 0 0.3125 -v 0.06281249999999994 0.375 0.3125 -v 0.06281249999999994 0.375 0.4375 -v 0.06281249999999994 0 0.3125 -v 0.06281249999999994 0 0.4375 -vt 0.3125 0.1875 -vt 0.3541666666666667 0.1875 -vt 0.3541666666666667 0 -vt 0.3125 0 -vt 0.2708333333333333 0.1875 -vt 0.3125 0.1875 -vt 0.3125 0 -vt 0.2708333333333333 0 -vt 0.3958333333333333 0.1875 -vt 0.4375 0.1875 -vt 0.4375 0 -vt 0.3958333333333333 0 -vt 0.3541666666666667 0.1875 -vt 0.3958333333333333 0.1875 -vt 0.3958333333333333 0 -vt 0.3541666666666667 0 -vt 0.3541666666666667 0.1875 -vt 0.3125 0.1875 -vt 0.3125 0.25 -vt 0.3541666666666667 0.25 -vt 0.3958333333333333 0.25 -vt 0.3541666666666667 0.25 -vt 0.3541666666666667 0.1875 -vt 0.3958333333333333 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_55d42d08-0bdc-6d16-75c7-074abfaa1062 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o leg1 -v -0.0628125 0.375 0.4375 -v -0.0628125 0.375 0.3125 -v -0.0628125 0 0.4375 -v -0.0628125 0 0.3125 -v -0.1878125 0.375 0.3125 -v -0.1878125 0.375 0.4375 -v -0.1878125 0 0.3125 -v -0.1878125 0 0.4375 -vt 0.125 0.1875 -vt 0.16666666666666666 0.1875 -vt 0.16666666666666666 0 -vt 0.125 0 -vt 0.08333333333333333 0.1875 -vt 0.125 0.1875 -vt 0.125 0 -vt 0.08333333333333333 0 -vt 0.20833333333333334 0.1875 -vt 0.25 0.1875 -vt 0.25 0 -vt 0.20833333333333334 0 -vt 0.16666666666666666 0.1875 -vt 0.20833333333333334 0.1875 -vt 0.20833333333333334 0 -vt 0.16666666666666666 0 -vt 0.16666666666666666 0.1875 -vt 0.125 0.1875 -vt 0.125 0.25 -vt 0.16666666666666666 0.25 -vt 0.20833333333333334 0.25 -vt 0.16666666666666666 0.25 -vt 0.16666666666666666 0.1875 -vt 0.20833333333333334 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_55d42d08-0bdc-6d16-75c7-074abfaa1062 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o leg2 -v 0.18781249999999994 0.375 0 -v 0.18781249999999994 0.375 -0.125 -v 0.18781249999999994 0 0 -v 0.18781249999999994 0 -0.125 -v 0.06281249999999994 0.375 -0.125 -v 0.06281249999999994 0.375 0 -v 0.06281249999999994 0 -0.125 -v 0.06281249999999994 0 0 -vt 0.3125 0.1875 -vt 0.3541666666666667 0.1875 -vt 0.3541666666666667 0 -vt 0.3125 0 -vt 0.2708333333333333 0.1875 -vt 0.3125 0.1875 -vt 0.3125 0 -vt 0.2708333333333333 0 -vt 0.3958333333333333 0.1875 -vt 0.4375 0.1875 -vt 0.4375 0 -vt 0.3958333333333333 0 -vt 0.3541666666666667 0.1875 -vt 0.3958333333333333 0.1875 -vt 0.3958333333333333 0 -vt 0.3541666666666667 0 -vt 0.3541666666666667 0.1875 -vt 0.3125 0.1875 -vt 0.3125 0.25 -vt 0.3541666666666667 0.25 -vt 0.3958333333333333 0.25 -vt 0.3541666666666667 0.25 -vt 0.3541666666666667 0.1875 -vt 0.3958333333333333 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_55d42d08-0bdc-6d16-75c7-074abfaa1062 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o leg3 -v -0.0628125 0.375 0 -v -0.0628125 0.375 -0.125 -v -0.0628125 0 0 -v -0.0628125 0 -0.125 -v -0.1878125 0.375 -0.125 -v -0.1878125 0.375 0 -v -0.1878125 0 -0.125 -v -0.1878125 0 0 -vt 0.125 0.1875 -vt 0.16666666666666666 0.1875 -vt 0.16666666666666666 0 -vt 0.125 0 -vt 0.08333333333333333 0.1875 -vt 0.125 0.1875 -vt 0.125 0 -vt 0.08333333333333333 0 -vt 0.20833333333333334 0.1875 -vt 0.25 0.1875 -vt 0.25 0 -vt 0.20833333333333334 0 -vt 0.16666666666666666 0.1875 -vt 0.20833333333333334 0.1875 -vt 0.20833333333333334 0 -vt 0.16666666666666666 0 -vt 0.16666666666666666 0.1875 -vt 0.125 0.1875 -vt 0.125 0.25 -vt 0.16666666666666666 0.25 -vt 0.20833333333333334 0.25 -vt 0.16666666666666666 0.25 -vt 0.16666666666666666 0.1875 -vt 0.20833333333333334 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_55d42d08-0bdc-6d16-75c7-074abfaa1062 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o tail -v 0.125 0.671875 0.5 -v 0.125 0.359375 0.5 -v 0.125 0.671875 1.0625 -v 0.125 0.3593749999999999 1.0625 -v -0.125 0.359375 0.5 -v -0.125 0.671875 0.5 -v -0.125 0.3593749999999999 1.0625 -v -0.125 0.671875 1.0625 -vt 0.7291666666666666 0.84375 -vt 0.8125 0.84375 -vt 0.8125 0.5625 -vt 0.7291666666666666 0.5625 -vt 0.625 0.84375 -vt 0.7291666666666666 0.84375 -vt 0.7291666666666666 0.5625 -vt 0.625 0.5625 -vt 0.9166666666666666 0.84375 -vt 1 0.84375 -vt 1 0.5625 -vt 0.9166666666666666 0.5625 -vt 0.8125 0.84375 -vt 0.9166666666666666 0.84375 -vt 0.9166666666666666 0.5625 -vt 0.8125 0.5625 -vt 0.8125 0.84375 -vt 0.7291666666666666 0.84375 -vt 0.7291666666666666 1 -vt 0.8125 1 -vt 0.8958333333333334 1 -vt 0.8125 1 -vt 0.8125 0.84375 -vt 0.8958333333333334 0.84375 -vn 0 -1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 -1 -vn 0 -2.220446049250313e-16 1 -usemtl m_55d42d08-0bdc-6d16-75c7-074abfaa1062 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/frog.obj b/renderer/viewer/three/entity/models/frog.obj deleted file mode 100644 index e76a114e1..000000000 --- a/renderer/viewer/three/entity/models/frog.obj +++ /dev/null @@ -1,739 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.21875 0.25 0.3125 -v 0.21875 0.25 -0.25 -v 0.21875 0.0625 0.3125 -v 0.21875 0.0625 -0.25 -v -0.21875 0.25 -0.25 -v -0.21875 0.25 0.3125 -v -0.21875 0.0625 -0.25 -v -0.21875 0.0625 0.3125 -vt 0.25 0.7916666666666666 -vt 0.3958333333333333 0.7916666666666666 -vt 0.3958333333333333 0.7291666666666667 -vt 0.25 0.7291666666666667 -vt 0.0625 0.7916666666666666 -vt 0.25 0.7916666666666666 -vt 0.25 0.7291666666666667 -vt 0.0625 0.7291666666666667 -vt 0.5833333333333334 0.7916666666666666 -vt 0.7291666666666666 0.7916666666666666 -vt 0.7291666666666666 0.7291666666666667 -vt 0.5833333333333334 0.7291666666666667 -vt 0.3958333333333333 0.7916666666666666 -vt 0.5833333333333334 0.7916666666666666 -vt 0.5833333333333334 0.7291666666666667 -vt 0.3958333333333333 0.7291666666666667 -vt 0.3958333333333333 0.7916666666666666 -vt 0.25 0.7916666666666666 -vt 0.25 0.9791666666666666 -vt 0.3958333333333333 0.9791666666666666 -vt 0.5416666666666666 0.9791666666666666 -vt 0.3958333333333333 0.9791666666666666 -vt 0.3958333333333333 0.7916666666666666 -vt 0.5416666666666666 0.7916666666666666 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o body -v 0.21875 0.1875 0.3125 -v 0.21875 0.1875 -0.25 -v 0.21875 0.1875 0.3125 -v 0.21875 0.1875 -0.25 -v -0.21875 0.1875 -0.25 -v -0.21875 0.1875 0.3125 -v -0.21875 0.1875 -0.25 -v -0.21875 0.1875 0.3125 -vt 0.6666666666666666 0.35416666666666663 -vt 0.8125 0.35416666666666663 -vt 0.8125 0.35416666666666663 -vt 0.6666666666666666 0.35416666666666663 -vt 0.4791666666666667 0.35416666666666663 -vt 0.6666666666666666 0.35416666666666663 -vt 0.6666666666666666 0.35416666666666663 -vt 0.4791666666666667 0.35416666666666663 -vt 1 0.35416666666666663 -vt 1.1458333333333333 0.35416666666666663 -vt 1.1458333333333333 0.35416666666666663 -vt 1 0.35416666666666663 -vt 0.8125 0.35416666666666663 -vt 1 0.35416666666666663 -vt 1 0.35416666666666663 -vt 0.8125 0.35416666666666663 -vt 0.8125 0.35416666666666663 -vt 0.6666666666666666 0.35416666666666663 -vt 0.6666666666666666 0.5416666666666667 -vt 0.8125 0.5416666666666667 -vt 0.9583333333333334 0.5416666666666667 -vt 0.8125 0.5416666666666667 -vt 0.8125 0.35416666666666663 -vt 0.9583333333333334 0.35416666666666663 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o head -v 0.21875 0.3125 0.3125 -v 0.21875 0.3125 -0.25 -v 0.21875 0.3125 0.3125 -v 0.21875 0.3125 -0.25 -v -0.21875 0.3125 -0.25 -v -0.21875 0.3125 0.3125 -v -0.21875 0.3125 -0.25 -v -0.21875 0.3125 0.3125 -vt 0.6666666666666666 0.5416666666666667 -vt 0.8125 0.5416666666666667 -vt 0.8125 0.5416666666666667 -vt 0.6666666666666666 0.5416666666666667 -vt 0.4791666666666667 0.5416666666666667 -vt 0.6666666666666666 0.5416666666666667 -vt 0.6666666666666666 0.5416666666666667 -vt 0.4791666666666667 0.5416666666666667 -vt 1 0.5416666666666667 -vt 1.1458333333333333 0.5416666666666667 -vt 1.1458333333333333 0.5416666666666667 -vt 1 0.5416666666666667 -vt 0.8125 0.5416666666666667 -vt 1 0.5416666666666667 -vt 1 0.5416666666666667 -vt 0.8125 0.5416666666666667 -vt 0.8125 0.5416666666666667 -vt 0.6666666666666666 0.5416666666666667 -vt 0.6666666666666666 0.7291666666666667 -vt 0.8125 0.7291666666666667 -vt 0.9583333333333334 0.7291666666666667 -vt 0.8125 0.7291666666666667 -vt 0.8125 0.5416666666666667 -vt 0.9583333333333334 0.5416666666666667 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o head -v 0.21875 0.375 0.3125 -v 0.21875 0.375 -0.25 -v 0.21875 0.1875 0.3125 -v 0.21875 0.1875 -0.25 -v -0.21875 0.375 -0.25 -v -0.21875 0.375 0.3125 -v -0.21875 0.1875 -0.25 -v -0.21875 0.1875 0.3125 -vt 0.1875 0.5416666666666667 -vt 0.3333333333333333 0.5416666666666667 -vt 0.3333333333333333 0.47916666666666663 -vt 0.1875 0.47916666666666663 -vt 0 0.5416666666666667 -vt 0.1875 0.5416666666666667 -vt 0.1875 0.47916666666666663 -vt 0 0.47916666666666663 -vt 0.5208333333333334 0.5416666666666667 -vt 0.6666666666666666 0.5416666666666667 -vt 0.6666666666666666 0.47916666666666663 -vt 0.5208333333333334 0.47916666666666663 -vt 0.3333333333333333 0.5416666666666667 -vt 0.5208333333333334 0.5416666666666667 -vt 0.5208333333333334 0.47916666666666663 -vt 0.3333333333333333 0.47916666666666663 -vt 0.3333333333333333 0.5416666666666667 -vt 0.1875 0.5416666666666667 -vt 0.1875 0.7291666666666667 -vt 0.3333333333333333 0.7291666666666667 -vt 0.4791666666666667 0.7291666666666667 -vt 0.3333333333333333 0.7291666666666667 -vt 0.3333333333333333 0.5416666666666667 -vt 0.4791666666666667 0.5416666666666667 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o right_eye -v 0.21875 0.5 0 -v 0.21875 0.5 -0.1875 -v 0.21875 0.375 0 -v 0.21875 0.375 -0.1875 -v 0.03125 0.5 -0.1875 -v 0.03125 0.5 0 -v 0.03125 0.375 -0.1875 -v 0.03125 0.375 0 -vt 0.0625 0.9375 -vt 0.125 0.9375 -vt 0.125 0.8958333333333334 -vt 0.0625 0.8958333333333334 -vt 0 0.9375 -vt 0.0625 0.9375 -vt 0.0625 0.8958333333333334 -vt 0 0.8958333333333334 -vt 0.1875 0.9375 -vt 0.25 0.9375 -vt 0.25 0.8958333333333334 -vt 0.1875 0.8958333333333334 -vt 0.125 0.9375 -vt 0.1875 0.9375 -vt 0.1875 0.8958333333333334 -vt 0.125 0.8958333333333334 -vt 0.125 0.9375 -vt 0.0625 0.9375 -vt 0.0625 1 -vt 0.125 1 -vt 0.1875 1 -vt 0.125 1 -vt 0.125 0.9375 -vt 0.1875 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o left_eye -v -0.03125 0.5 0 -v -0.03125 0.5 -0.1875 -v -0.03125 0.375 0 -v -0.03125 0.375 -0.1875 -v -0.21875 0.5 -0.1875 -v -0.21875 0.5 0 -v -0.21875 0.375 -0.1875 -v -0.21875 0.375 0 -vt 0.0625 0.8333333333333334 -vt 0.125 0.8333333333333334 -vt 0.125 0.7916666666666666 -vt 0.0625 0.7916666666666666 -vt 0 0.8333333333333334 -vt 0.0625 0.8333333333333334 -vt 0.0625 0.7916666666666666 -vt 0 0.7916666666666666 -vt 0.1875 0.8333333333333334 -vt 0.25 0.8333333333333334 -vt 0.25 0.7916666666666666 -vt 0.1875 0.7916666666666666 -vt 0.125 0.8333333333333334 -vt 0.1875 0.8333333333333334 -vt 0.1875 0.7916666666666666 -vt 0.125 0.7916666666666666 -vt 0.125 0.8333333333333334 -vt 0.0625 0.8333333333333334 -vt 0.0625 0.8958333333333334 -vt 0.125 0.8958333333333334 -vt 0.1875 0.8958333333333334 -vt 0.125 0.8958333333333334 -vt 0.125 0.8333333333333334 -vt 0.1875 0.8333333333333334 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o croaking_body -v 0.21250000000000002 0.1875 -0.0625 -v 0.21250000000000002 0.1875 -0.2375 -v 0.21250000000000002 0.07499999999999996 -0.0625 -v 0.21250000000000002 0.07499999999999996 -0.2375 -v -0.21250000000000002 0.1875 -0.2375 -v -0.21250000000000002 0.1875 -0.0625 -v -0.21250000000000002 0.07499999999999996 -0.2375 -v -0.21250000000000002 0.07499999999999996 -0.0625 -vt 0.6041666666666666 0.8333333333333334 -vt 0.75 0.8333333333333334 -vt 0.75 0.7916666666666666 -vt 0.6041666666666666 0.7916666666666666 -vt 0.5416666666666666 0.8333333333333334 -vt 0.6041666666666666 0.8333333333333334 -vt 0.6041666666666666 0.7916666666666666 -vt 0.5416666666666666 0.7916666666666666 -vt 0.8125 0.8333333333333334 -vt 0.9583333333333334 0.8333333333333334 -vt 0.9583333333333334 0.7916666666666666 -vt 0.8125 0.7916666666666666 -vt 0.75 0.8333333333333334 -vt 0.8125 0.8333333333333334 -vt 0.8125 0.7916666666666666 -vt 0.75 0.7916666666666666 -vt 0.75 0.8333333333333334 -vt 0.6041666666666666 0.8333333333333334 -vt 0.6041666666666666 0.8958333333333334 -vt 0.75 0.8958333333333334 -vt 0.8958333333333334 0.8958333333333334 -vt 0.75 0.8958333333333334 -vt 0.75 0.8333333333333334 -vt 0.8958333333333334 0.8333333333333334 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o tongue -v 0.125 0.19374999999999998 0.30625 -v 0.125 0.19374999999999998 -0.13124999999999998 -v 0.125 0.19374999999999998 0.30625 -v 0.125 0.19374999999999998 -0.13124999999999998 -v -0.125 0.19374999999999998 -0.13124999999999998 -v -0.125 0.19374999999999998 0.30625 -v -0.125 0.19374999999999998 -0.13124999999999998 -v -0.125 0.19374999999999998 0.30625 -vt 0.5 0.5833333333333333 -vt 0.5833333333333334 0.5833333333333333 -vt 0.5833333333333334 0.5833333333333333 -vt 0.5 0.5833333333333333 -vt 0.3541666666666667 0.5833333333333333 -vt 0.5 0.5833333333333333 -vt 0.5 0.5833333333333333 -vt 0.3541666666666667 0.5833333333333333 -vt 0.7291666666666666 0.5833333333333333 -vt 0.8125 0.5833333333333333 -vt 0.8125 0.5833333333333333 -vt 0.7291666666666666 0.5833333333333333 -vt 0.5833333333333334 0.5833333333333333 -vt 0.7291666666666666 0.5833333333333333 -vt 0.7291666666666666 0.5833333333333333 -vt 0.5833333333333334 0.5833333333333333 -vt 0.5833333333333334 0.5833333333333333 -vt 0.5 0.5833333333333333 -vt 0.5 0.7291666666666667 -vt 0.5833333333333334 0.7291666666666667 -vt 0.6666666666666666 0.7291666666666667 -vt 0.5833333333333334 0.7291666666666667 -vt 0.5833333333333334 0.5833333333333333 -vt 0.6666666666666666 0.5833333333333333 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o left_arm -v -0.1875 0.1875 -0.03125 -v -0.1875 0.1875 -0.21875 -v -0.1875 0 -0.03125 -v -0.1875 0 -0.21875 -v -0.3125 0.1875 -0.21875 -v -0.3125 0.1875 -0.03125 -v -0.3125 0 -0.21875 -v -0.3125 0 -0.03125 -vt 0.0625 0.27083333333333337 -vt 0.10416666666666667 0.27083333333333337 -vt 0.10416666666666667 0.20833333333333337 -vt 0.0625 0.20833333333333337 -vt 0 0.27083333333333337 -vt 0.0625 0.27083333333333337 -vt 0.0625 0.20833333333333337 -vt 0 0.20833333333333337 -vt 0.16666666666666666 0.27083333333333337 -vt 0.20833333333333334 0.27083333333333337 -vt 0.20833333333333334 0.20833333333333337 -vt 0.16666666666666666 0.20833333333333337 -vt 0.10416666666666667 0.27083333333333337 -vt 0.16666666666666666 0.27083333333333337 -vt 0.16666666666666666 0.20833333333333337 -vt 0.10416666666666667 0.20833333333333337 -vt 0.10416666666666667 0.27083333333333337 -vt 0.0625 0.27083333333333337 -vt 0.0625 0.33333333333333337 -vt 0.10416666666666667 0.33333333333333337 -vt 0.14583333333333334 0.33333333333333337 -vt 0.10416666666666667 0.33333333333333337 -vt 0.10416666666666667 0.27083333333333337 -vt 0.14583333333333334 0.27083333333333337 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o left_arm -v 0 -0.0006249999999999867 0.03125 -v 0 -0.0006249999999999867 -0.46875 -v 0 -0.0006249999999999867 0.03125 -v 0 -0.0006249999999999867 -0.46875 -v -0.5 -0.0006249999999999867 -0.46875 -v -0.5 -0.0006249999999999867 0.03125 -v -0.5 -0.0006249999999999867 -0.46875 -v -0.5 -0.0006249999999999867 0.03125 -vt 0.5416666666666666 0 -vt 0.7083333333333334 0 -vt 0.7083333333333334 0 -vt 0.5416666666666666 0 -vt 0.375 0 -vt 0.5416666666666666 0 -vt 0.5416666666666666 0 -vt 0.375 0 -vt 0.875 0 -vt 1.0416666666666667 0 -vt 1.0416666666666667 0 -vt 0.875 0 -vt 0.7083333333333334 0 -vt 0.875 0 -vt 0.875 0 -vt 0.7083333333333334 0 -vt 0.7083333333333334 0 -vt 0.5416666666666666 0 -vt 0.5416666666666666 0.16666666666666663 -vt 0.7083333333333334 0.16666666666666663 -vt 0.875 0.16666666666666663 -vt 0.7083333333333334 0.16666666666666663 -vt 0.7083333333333334 0 -vt 0.875 0 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o right_arm -v 0.3125 0.1875 -0.03125 -v 0.3125 0.1875 -0.21875 -v 0.3125 0 -0.03125 -v 0.3125 0 -0.21875 -v 0.1875 0.1875 -0.21875 -v 0.1875 0.1875 -0.03125 -v 0.1875 0 -0.21875 -v 0.1875 0 -0.03125 -vt 0.0625 0.14583333333333337 -vt 0.10416666666666667 0.14583333333333337 -vt 0.10416666666666667 0.08333333333333337 -vt 0.0625 0.08333333333333337 -vt 0 0.14583333333333337 -vt 0.0625 0.14583333333333337 -vt 0.0625 0.08333333333333337 -vt 0 0.08333333333333337 -vt 0.16666666666666666 0.14583333333333337 -vt 0.20833333333333334 0.14583333333333337 -vt 0.20833333333333334 0.08333333333333337 -vt 0.16666666666666666 0.08333333333333337 -vt 0.10416666666666667 0.14583333333333337 -vt 0.16666666666666666 0.14583333333333337 -vt 0.16666666666666666 0.08333333333333337 -vt 0.10416666666666667 0.08333333333333337 -vt 0.10416666666666667 0.14583333333333337 -vt 0.0625 0.14583333333333337 -vt 0.0625 0.20833333333333337 -vt 0.10416666666666667 0.20833333333333337 -vt 0.14583333333333334 0.20833333333333337 -vt 0.10416666666666667 0.20833333333333337 -vt 0.10416666666666667 0.14583333333333337 -vt 0.14583333333333334 0.14583333333333337 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 -o right_arm -v 0.5 -0.0006249999999999867 0.03125 -v 0.5 -0.0006249999999999867 -0.46875 -v 0.5 -0.0006249999999999867 0.03125 -v 0.5 -0.0006249999999999867 -0.46875 -v 0 -0.0006249999999999867 -0.46875 -v 0 -0.0006249999999999867 0.03125 -v 0 -0.0006249999999999867 -0.46875 -v 0 -0.0006249999999999867 0.03125 -vt 0.20833333333333334 0 -vt 0.375 0 -vt 0.375 0 -vt 0.20833333333333334 0 -vt 0.041666666666666664 0 -vt 0.20833333333333334 0 -vt 0.20833333333333334 0 -vt 0.041666666666666664 0 -vt 0.5416666666666666 0 -vt 0.7083333333333334 0 -vt 0.7083333333333334 0 -vt 0.5416666666666666 0 -vt 0.375 0 -vt 0.5416666666666666 0 -vt 0.5416666666666666 0 -vt 0.375 0 -vt 0.375 0 -vt 0.20833333333333334 0 -vt 0.20833333333333334 0.16666666666666663 -vt 0.375 0.16666666666666663 -vt 0.5416666666666666 0.16666666666666663 -vt 0.375 0.16666666666666663 -vt 0.375 0 -vt 0.5416666666666666 0 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 92/268/67 95/267/67 93/266/67 90/265/67 -f 91/272/68 92/271/68 90/270/68 89/269/68 -f 96/276/69 91/275/69 89/274/69 94/273/69 -f 95/280/70 96/279/70 94/278/70 93/277/70 -f 94/284/71 89/283/71 90/282/71 93/281/71 -f 95/288/72 92/287/72 91/286/72 96/285/72 -o left_leg -v -0.15625 0.1875 0.375 -v -0.15625 0.1875 0.125 -v -0.15625 0 0.375 -v -0.15625 0 0.125 -v -0.34375 0.1875 0.125 -v -0.34375 0.1875 0.375 -v -0.34375 0 0.125 -v -0.34375 0 0.375 -vt 0.375 0.39583333333333337 -vt 0.4375 0.39583333333333337 -vt 0.4375 0.33333333333333337 -vt 0.375 0.33333333333333337 -vt 0.2916666666666667 0.39583333333333337 -vt 0.375 0.39583333333333337 -vt 0.375 0.33333333333333337 -vt 0.2916666666666667 0.33333333333333337 -vt 0.5208333333333334 0.39583333333333337 -vt 0.5833333333333334 0.39583333333333337 -vt 0.5833333333333334 0.33333333333333337 -vt 0.5208333333333334 0.33333333333333337 -vt 0.4375 0.39583333333333337 -vt 0.5208333333333334 0.39583333333333337 -vt 0.5208333333333334 0.33333333333333337 -vt 0.4375 0.33333333333333337 -vt 0.4375 0.39583333333333337 -vt 0.375 0.39583333333333337 -vt 0.375 0.47916666666666663 -vt 0.4375 0.47916666666666663 -vt 0.5 0.47916666666666663 -vt 0.4375 0.47916666666666663 -vt 0.4375 0.39583333333333337 -vt 0.5 0.39583333333333337 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 100/292/73 103/291/73 101/290/73 98/289/73 -f 99/296/74 100/295/74 98/294/74 97/293/74 -f 104/300/75 99/299/75 97/298/75 102/297/75 -f 103/304/76 104/303/76 102/302/76 101/301/76 -f 102/308/77 97/307/77 98/306/77 101/305/77 -f 103/312/78 100/311/78 99/310/78 104/309/78 -o left_leg -v -0.09375 -0.0006249999999999867 0.5 -v -0.09375 -0.0006249999999999867 0 -v -0.09375 -0.0006249999999999867 0.5 -v -0.09375 -0.0006249999999999867 0 -v -0.59375 -0.0006249999999999867 0 -v -0.59375 -0.0006249999999999867 0.5 -v -0.59375 -0.0006249999999999867 0 -v -0.59375 -0.0006249999999999867 0.5 -vt 0.20833333333333334 0.16666666666666663 -vt 0.375 0.16666666666666663 -vt 0.375 0.16666666666666663 -vt 0.20833333333333334 0.16666666666666663 -vt 0.041666666666666664 0.16666666666666663 -vt 0.20833333333333334 0.16666666666666663 -vt 0.20833333333333334 0.16666666666666663 -vt 0.041666666666666664 0.16666666666666663 -vt 0.5416666666666666 0.16666666666666663 -vt 0.7083333333333334 0.16666666666666663 -vt 0.7083333333333334 0.16666666666666663 -vt 0.5416666666666666 0.16666666666666663 -vt 0.375 0.16666666666666663 -vt 0.5416666666666666 0.16666666666666663 -vt 0.5416666666666666 0.16666666666666663 -vt 0.375 0.16666666666666663 -vt 0.375 0.16666666666666663 -vt 0.20833333333333334 0.16666666666666663 -vt 0.20833333333333334 0.33333333333333337 -vt 0.375 0.33333333333333337 -vt 0.5416666666666666 0.33333333333333337 -vt 0.375 0.33333333333333337 -vt 0.375 0.16666666666666663 -vt 0.5416666666666666 0.16666666666666663 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 108/316/79 111/315/79 109/314/79 106/313/79 -f 107/320/80 108/319/80 106/318/80 105/317/80 -f 112/324/81 107/323/81 105/322/81 110/321/81 -f 111/328/82 112/327/82 110/326/82 109/325/82 -f 110/332/83 105/331/83 106/330/83 109/329/83 -f 111/336/84 108/335/84 107/334/84 112/333/84 -o right_leg -v 0.34375 0.1875 0.375 -v 0.34375 0.1875 0.125 -v 0.34375 0 0.375 -v 0.34375 0 0.125 -v 0.15625 0.1875 0.125 -v 0.15625 0.1875 0.375 -v 0.15625 0 0.125 -v 0.15625 0 0.375 -vt 0.08333333333333333 0.39583333333333337 -vt 0.14583333333333334 0.39583333333333337 -vt 0.14583333333333334 0.33333333333333337 -vt 0.08333333333333333 0.33333333333333337 -vt 0 0.39583333333333337 -vt 0.08333333333333333 0.39583333333333337 -vt 0.08333333333333333 0.33333333333333337 -vt 0 0.33333333333333337 -vt 0.22916666666666666 0.39583333333333337 -vt 0.2916666666666667 0.39583333333333337 -vt 0.2916666666666667 0.33333333333333337 -vt 0.22916666666666666 0.33333333333333337 -vt 0.14583333333333334 0.39583333333333337 -vt 0.22916666666666666 0.39583333333333337 -vt 0.22916666666666666 0.33333333333333337 -vt 0.14583333333333334 0.33333333333333337 -vt 0.14583333333333334 0.39583333333333337 -vt 0.08333333333333333 0.39583333333333337 -vt 0.08333333333333333 0.47916666666666663 -vt 0.14583333333333334 0.47916666666666663 -vt 0.20833333333333334 0.47916666666666663 -vt 0.14583333333333334 0.47916666666666663 -vt 0.14583333333333334 0.39583333333333337 -vt 0.20833333333333334 0.39583333333333337 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 116/340/85 119/339/85 117/338/85 114/337/85 -f 115/344/86 116/343/86 114/342/86 113/341/86 -f 120/348/87 115/347/87 113/346/87 118/345/87 -f 119/352/88 120/351/88 118/350/88 117/349/88 -f 118/356/89 113/355/89 114/354/89 117/353/89 -f 119/360/90 116/359/90 115/358/90 120/357/90 -o right_leg -v 0.59375 -0.0006249999999999867 0.5 -v 0.59375 -0.0006249999999999867 0 -v 0.59375 -0.0006249999999999867 0.5 -v 0.59375 -0.0006249999999999867 0 -v 0.09375 -0.0006249999999999867 0 -v 0.09375 -0.0006249999999999867 0.5 -v 0.09375 -0.0006249999999999867 0 -v 0.09375 -0.0006249999999999867 0.5 -vt 0.5416666666666666 0.16666666666666663 -vt 0.7083333333333334 0.16666666666666663 -vt 0.7083333333333334 0.16666666666666663 -vt 0.5416666666666666 0.16666666666666663 -vt 0.375 0.16666666666666663 -vt 0.5416666666666666 0.16666666666666663 -vt 0.5416666666666666 0.16666666666666663 -vt 0.375 0.16666666666666663 -vt 0.875 0.16666666666666663 -vt 1.0416666666666667 0.16666666666666663 -vt 1.0416666666666667 0.16666666666666663 -vt 0.875 0.16666666666666663 -vt 0.7083333333333334 0.16666666666666663 -vt 0.875 0.16666666666666663 -vt 0.875 0.16666666666666663 -vt 0.7083333333333334 0.16666666666666663 -vt 0.7083333333333334 0.16666666666666663 -vt 0.5416666666666666 0.16666666666666663 -vt 0.5416666666666666 0.33333333333333337 -vt 0.7083333333333334 0.33333333333333337 -vt 0.875 0.33333333333333337 -vt 0.7083333333333334 0.33333333333333337 -vt 0.7083333333333334 0.16666666666666663 -vt 0.875 0.16666666666666663 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_4288dcd0-d35c-c2c4-0fee-38c374635ee1 -f 124/364/91 127/363/91 125/362/91 122/361/91 -f 123/368/92 124/367/92 122/366/92 121/365/92 -f 128/372/93 123/371/93 121/370/93 126/369/93 -f 127/376/94 128/375/94 126/374/94 125/373/94 -f 126/380/95 121/379/95 122/378/95 125/377/95 -f 127/384/96 124/383/96 123/382/96 128/381/96 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/ghast.obj b/renderer/viewer/three/entity/models/ghast.obj deleted file mode 100644 index bed7ccb2c..000000000 --- a/renderer/viewer/three/entity/models/ghast.obj +++ /dev/null @@ -1,463 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.5 1 0.5 -v 0.5 1 -0.5 -v 0.5 0 0.5 -v 0.5 0 -0.5 -v -0.5 1 -0.5 -v -0.5 1 0.5 -v -0.5 0 -0.5 -v -0.5 0 0.5 -vt 0.25 0.5 -vt 0.5 0.5 -vt 0.5 0 -vt 0.25 0 -vt 0 0.5 -vt 0.25 0.5 -vt 0.25 0 -vt 0 0 -vt 0.75 0.5 -vt 1 0.5 -vt 1 0 -vt 0.75 0 -vt 0.5 0.5 -vt 0.75 0.5 -vt 0.75 0 -vt 0.5 0 -vt 0.5 0.5 -vt 0.25 0.5 -vt 0.25 1 -vt 0.5 1 -vt 0.75 1 -vt 0.5 1 -vt 0.5 0.5 -vt 0.75 0.5 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_be60a09e-8083-c62f-16c0-359ca5c36498 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o tentacles_0 -v 0.30000000000000004 0.0625 -0.25 -v 0.30000000000000004 0.0625 -0.375 -v 0.30000000000000004 -0.5 -0.25 -v 0.30000000000000004 -0.5 -0.375 -v 0.17500000000000004 0.0625 -0.375 -v 0.17500000000000004 0.0625 -0.25 -v 0.17500000000000004 -0.5 -0.375 -v 0.17500000000000004 -0.5 -0.25 -vt 0.03125 0.9375 -vt 0.0625 0.9375 -vt 0.0625 0.65625 -vt 0.03125 0.65625 -vt 0 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.65625 -vt 0 0.65625 -vt 0.09375 0.9375 -vt 0.125 0.9375 -vt 0.125 0.65625 -vt 0.09375 0.65625 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vt 0.09375 0.65625 -vt 0.0625 0.65625 -vt 0.0625 0.9375 -vt 0.03125 0.9375 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_be60a09e-8083-c62f-16c0-359ca5c36498 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o tentacles_1 -v -0.01874999999999999 0.0625 -0.25 -v -0.01874999999999999 0.0625 -0.375 -v -0.01874999999999999 -0.625 -0.25 -v -0.01874999999999999 -0.625 -0.375 -v -0.14375 0.0625 -0.375 -v -0.14375 0.0625 -0.25 -v -0.14375 -0.625 -0.375 -v -0.14375 -0.625 -0.25 -vt 0.03125 0.9375 -vt 0.0625 0.9375 -vt 0.0625 0.59375 -vt 0.03125 0.59375 -vt 0 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.59375 -vt 0 0.59375 -vt 0.09375 0.9375 -vt 0.125 0.9375 -vt 0.125 0.59375 -vt 0.09375 0.59375 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vt 0.09375 0.59375 -vt 0.0625 0.59375 -vt 0.0625 0.9375 -vt 0.03125 0.9375 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_be60a09e-8083-c62f-16c0-359ca5c36498 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o tentacles_2 -v -0.33125 0.0625 -0.25 -v -0.33125 0.0625 -0.375 -v -0.33125 -0.4375 -0.25 -v -0.33125 -0.4375 -0.375 -v -0.45625 0.0625 -0.375 -v -0.45625 0.0625 -0.25 -v -0.45625 -0.4375 -0.375 -v -0.45625 -0.4375 -0.25 -vt 0.03125 0.9375 -vt 0.0625 0.9375 -vt 0.0625 0.6875 -vt 0.03125 0.6875 -vt 0 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.6875 -vt 0 0.6875 -vt 0.09375 0.9375 -vt 0.125 0.9375 -vt 0.125 0.6875 -vt 0.09375 0.6875 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vt 0.09375 0.6875 -vt 0.0625 0.6875 -vt 0.0625 0.9375 -vt 0.03125 0.9375 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_be60a09e-8083-c62f-16c0-359ca5c36498 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o tentacles_3 -v 0.45625000000000004 0.0625 0.0625 -v 0.45625000000000004 0.0625 -0.0625 -v 0.45625000000000004 -0.5 0.0625 -v 0.45625000000000004 -0.5 -0.0625 -v 0.33125000000000004 0.0625 -0.0625 -v 0.33125000000000004 0.0625 0.0625 -v 0.33125000000000004 -0.5 -0.0625 -v 0.33125000000000004 -0.5 0.0625 -vt 0.03125 0.9375 -vt 0.0625 0.9375 -vt 0.0625 0.65625 -vt 0.03125 0.65625 -vt 0 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.65625 -vt 0 0.65625 -vt 0.09375 0.9375 -vt 0.125 0.9375 -vt 0.125 0.65625 -vt 0.09375 0.65625 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vt 0.09375 0.65625 -vt 0.0625 0.65625 -vt 0.0625 0.9375 -vt 0.03125 0.9375 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_be60a09e-8083-c62f-16c0-359ca5c36498 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o tentacles_4 -v 0.14375000000000004 0.0625 0.0625 -v 0.14375000000000004 0.0625 -0.0625 -v 0.14375000000000004 -0.75 0.0625 -v 0.14375000000000004 -0.75 -0.0625 -v 0.018750000000000044 0.0625 -0.0625 -v 0.018750000000000044 0.0625 0.0625 -v 0.018750000000000044 -0.75 -0.0625 -v 0.018750000000000044 -0.75 0.0625 -vt 0.03125 0.9375 -vt 0.0625 0.9375 -vt 0.0625 0.53125 -vt 0.03125 0.53125 -vt 0 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.53125 -vt 0 0.53125 -vt 0.09375 0.9375 -vt 0.125 0.9375 -vt 0.125 0.53125 -vt 0.09375 0.53125 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vt 0.09375 0.53125 -vt 0.0625 0.53125 -vt 0.0625 0.9375 -vt 0.03125 0.9375 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_be60a09e-8083-c62f-16c0-359ca5c36498 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o tentacles_5 -v -0.175 0.0625 0.0625 -v -0.175 0.0625 -0.0625 -v -0.175 -0.625 0.0625 -v -0.175 -0.625 -0.0625 -v -0.3 0.0625 -0.0625 -v -0.3 0.0625 0.0625 -v -0.3 -0.625 -0.0625 -v -0.3 -0.625 0.0625 -vt 0.03125 0.9375 -vt 0.0625 0.9375 -vt 0.0625 0.59375 -vt 0.03125 0.59375 -vt 0 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.59375 -vt 0 0.59375 -vt 0.09375 0.9375 -vt 0.125 0.9375 -vt 0.125 0.59375 -vt 0.09375 0.59375 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vt 0.09375 0.59375 -vt 0.0625 0.59375 -vt 0.0625 0.9375 -vt 0.03125 0.9375 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_be60a09e-8083-c62f-16c0-359ca5c36498 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o tentacles_6 -v 0.30000000000000004 0.0625 0.375 -v 0.30000000000000004 0.0625 0.25 -v 0.30000000000000004 -0.6875 0.375 -v 0.30000000000000004 -0.6875 0.25 -v 0.17500000000000004 0.0625 0.25 -v 0.17500000000000004 0.0625 0.375 -v 0.17500000000000004 -0.6875 0.25 -v 0.17500000000000004 -0.6875 0.375 -vt 0.03125 0.9375 -vt 0.0625 0.9375 -vt 0.0625 0.5625 -vt 0.03125 0.5625 -vt 0 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.5625 -vt 0 0.5625 -vt 0.09375 0.9375 -vt 0.125 0.9375 -vt 0.125 0.5625 -vt 0.09375 0.5625 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vt 0.09375 0.5625 -vt 0.0625 0.5625 -vt 0.0625 0.9375 -vt 0.03125 0.9375 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_be60a09e-8083-c62f-16c0-359ca5c36498 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o tentacles_7 -v -0.01874999999999999 0.0625 0.375 -v -0.01874999999999999 0.0625 0.25 -v -0.01874999999999999 -0.6875 0.375 -v -0.01874999999999999 -0.6875 0.25 -v -0.14375 0.0625 0.25 -v -0.14375 0.0625 0.375 -v -0.14375 -0.6875 0.25 -v -0.14375 -0.6875 0.375 -vt 0.03125 0.9375 -vt 0.0625 0.9375 -vt 0.0625 0.5625 -vt 0.03125 0.5625 -vt 0 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.5625 -vt 0 0.5625 -vt 0.09375 0.9375 -vt 0.125 0.9375 -vt 0.125 0.5625 -vt 0.09375 0.5625 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vt 0.09375 0.5625 -vt 0.0625 0.5625 -vt 0.0625 0.9375 -vt 0.03125 0.9375 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_be60a09e-8083-c62f-16c0-359ca5c36498 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o tentacles_8 -v -0.33125 0.0625 0.375 -v -0.33125 0.0625 0.25 -v -0.33125 -0.75 0.375 -v -0.33125 -0.75 0.25 -v -0.45625 0.0625 0.25 -v -0.45625 0.0625 0.375 -v -0.45625 -0.75 0.25 -v -0.45625 -0.75 0.375 -vt 0.03125 0.9375 -vt 0.0625 0.9375 -vt 0.0625 0.53125 -vt 0.03125 0.53125 -vt 0 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.53125 -vt 0 0.53125 -vt 0.09375 0.9375 -vt 0.125 0.9375 -vt 0.125 0.53125 -vt 0.09375 0.53125 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vt 0.09375 0.53125 -vt 0.0625 0.53125 -vt 0.0625 0.9375 -vt 0.03125 0.9375 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.9375 -vt 0.09375 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_be60a09e-8083-c62f-16c0-359ca5c36498 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/goat.obj b/renderer/viewer/three/entity/models/goat.obj deleted file mode 100644 index adb8910cb..000000000 --- a/renderer/viewer/three/entity/models/goat.obj +++ /dev/null @@ -1,601 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o left_back_leg -v -0.0625 0.375 0.4375 -v -0.0625 0.375 0.25 -v -0.0625 0 0.4375 -v -0.0625 0 0.25 -v -0.25 0.375 0.25 -v -0.25 0.375 0.4375 -v -0.25 0 0.25 -v -0.25 0 0.4375 -vt 0.609375 0.5 -vt 0.65625 0.5 -vt 0.65625 0.40625 -vt 0.609375 0.40625 -vt 0.5625 0.5 -vt 0.609375 0.5 -vt 0.609375 0.40625 -vt 0.5625 0.40625 -vt 0.703125 0.5 -vt 0.75 0.5 -vt 0.75 0.40625 -vt 0.703125 0.40625 -vt 0.65625 0.5 -vt 0.703125 0.5 -vt 0.703125 0.40625 -vt 0.65625 0.40625 -vt 0.65625 0.5 -vt 0.609375 0.5 -vt 0.609375 0.546875 -vt 0.65625 0.546875 -vt 0.703125 0.546875 -vt 0.65625 0.546875 -vt 0.65625 0.5 -vt 0.703125 0.5 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd56fb3d-3403-c92f-d539-6df121464423 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o right_back_leg -v 0.1875 0.375 0.4375 -v 0.1875 0.375 0.25 -v 0.1875 0 0.4375 -v 0.1875 0 0.25 -v 0 0.375 0.25 -v 0 0.375 0.4375 -v 0 0 0.25 -v 0 0 0.4375 -vt 0.8125 0.5 -vt 0.859375 0.5 -vt 0.859375 0.40625 -vt 0.8125 0.40625 -vt 0.765625 0.5 -vt 0.8125 0.5 -vt 0.8125 0.40625 -vt 0.765625 0.40625 -vt 0.90625 0.5 -vt 0.953125 0.5 -vt 0.953125 0.40625 -vt 0.90625 0.40625 -vt 0.859375 0.5 -vt 0.90625 0.5 -vt 0.90625 0.40625 -vt 0.859375 0.40625 -vt 0.859375 0.5 -vt 0.8125 0.5 -vt 0.8125 0.546875 -vt 0.859375 0.546875 -vt 0.90625 0.546875 -vt 0.859375 0.546875 -vt 0.859375 0.5 -vt 0.90625 0.5 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd56fb3d-3403-c92f-d539-6df121464423 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o right_front_leg -v 0.1875 0.625 -0.1875 -v 0.1875 0.625 -0.375 -v 0.1875 0 -0.1875 -v 0.1875 0 -0.375 -v 0 0.625 -0.375 -v 0 0.625 -0.1875 -v 0 0 -0.375 -v 0 0 -0.1875 -vt 0.8125 0.921875 -vt 0.859375 0.921875 -vt 0.859375 0.765625 -vt 0.8125 0.765625 -vt 0.765625 0.921875 -vt 0.8125 0.921875 -vt 0.8125 0.765625 -vt 0.765625 0.765625 -vt 0.90625 0.921875 -vt 0.953125 0.921875 -vt 0.953125 0.765625 -vt 0.90625 0.765625 -vt 0.859375 0.921875 -vt 0.90625 0.921875 -vt 0.90625 0.765625 -vt 0.859375 0.765625 -vt 0.859375 0.921875 -vt 0.8125 0.921875 -vt 0.8125 0.96875 -vt 0.859375 0.96875 -vt 0.90625 0.96875 -vt 0.859375 0.96875 -vt 0.859375 0.921875 -vt 0.90625 0.921875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd56fb3d-3403-c92f-d539-6df121464423 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o left_front_leg -v -0.0625 0.625 -0.1875 -v -0.0625 0.625 -0.375 -v -0.0625 0 -0.1875 -v -0.0625 0 -0.375 -v -0.25 0.625 -0.375 -v -0.25 0.625 -0.1875 -v -0.25 0 -0.375 -v -0.25 0 -0.1875 -vt 0.59375 0.921875 -vt 0.640625 0.921875 -vt 0.640625 0.765625 -vt 0.59375 0.765625 -vt 0.546875 0.921875 -vt 0.59375 0.921875 -vt 0.59375 0.765625 -vt 0.546875 0.765625 -vt 0.6875 0.921875 -vt 0.734375 0.921875 -vt 0.734375 0.765625 -vt 0.6875 0.765625 -vt 0.640625 0.921875 -vt 0.6875 0.921875 -vt 0.6875 0.765625 -vt 0.640625 0.765625 -vt 0.640625 0.921875 -vt 0.59375 0.921875 -vt 0.59375 0.96875 -vt 0.640625 0.96875 -vt 0.6875 0.96875 -vt 0.640625 0.96875 -vt 0.640625 0.921875 -vt 0.6875 0.921875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd56fb3d-3403-c92f-d539-6df121464423 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o body -v 0.25 1.0625 0.5625 -v 0.25 1.0625 -0.4375 -v 0.25 0.375 0.5625 -v 0.25 0.375 -0.4375 -v -0.3125 1.0625 -0.4375 -v -0.3125 1.0625 0.5625 -v -0.3125 0.375 -0.4375 -v -0.3125 0.375 0.5625 -vt 0.265625 0.734375 -vt 0.40625 0.734375 -vt 0.40625 0.5625 -vt 0.265625 0.5625 -vt 0.015625 0.734375 -vt 0.265625 0.734375 -vt 0.265625 0.5625 -vt 0.015625 0.5625 -vt 0.65625 0.734375 -vt 0.796875 0.734375 -vt 0.796875 0.5625 -vt 0.65625 0.5625 -vt 0.40625 0.734375 -vt 0.65625 0.734375 -vt 0.65625 0.5625 -vt 0.40625 0.5625 -vt 0.40625 0.734375 -vt 0.265625 0.734375 -vt 0.265625 0.984375 -vt 0.40625 0.984375 -vt 0.546875 0.984375 -vt 0.40625 0.984375 -vt 0.40625 0.734375 -vt 0.546875 0.734375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd56fb3d-3403-c92f-d539-6df121464423 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o body -v 0.3125 1.125 0.1875 -v 0.3125 1.125 -0.5 -v 0.3125 0.25 0.1875 -v 0.3125 0.25 -0.5 -v -0.375 1.125 -0.5 -v -0.375 1.125 0.1875 -v -0.375 0.25 -0.5 -v -0.375 0.25 0.1875 -vt 0.171875 0.390625 -vt 0.34375 0.390625 -vt 0.34375 0.171875 -vt 0.171875 0.171875 -vt 0 0.390625 -vt 0.171875 0.390625 -vt 0.171875 0.171875 -vt 0 0.171875 -vt 0.515625 0.390625 -vt 0.6875 0.390625 -vt 0.6875 0.171875 -vt 0.515625 0.171875 -vt 0.34375 0.390625 -vt 0.515625 0.390625 -vt 0.515625 0.171875 -vt 0.34375 0.171875 -vt 0.34375 0.390625 -vt 0.171875 0.390625 -vt 0.171875 0.5625 -vt 0.34375 0.5625 -vt 0.515625 0.5625 -vt 0.34375 0.5625 -vt 0.34375 0.390625 -vt 0.515625 0.390625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd56fb3d-3403-c92f-d539-6df121464423 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o Head -v 0.125 1.3707881146238856 -0.6330909565283671 -v 0.125 0.8588180869432658 -0.991576229247771 -v 0.125 1.1198484237203028 -0.2747119371519333 -v 0.125 0.607878396039683 -0.6331972098713372 -v -0.1875 0.8588180869432658 -0.991576229247771 -v -0.1875 1.3707881146238856 -0.6330909565283671 -v -0.1875 0.607878396039683 -0.6331972098713372 -v -0.1875 1.1198484237203028 -0.2747119371519333 -vt 0.6875 0.125 -vt 0.765625 0.125 -vt 0.765625 0.015625 -vt 0.6875 0.015625 -vt 0.53125 0.125 -vt 0.6875 0.125 -vt 0.6875 0.015625 -vt 0.53125 0.015625 -vt 0.921875 0.125 -vt 1 0.125 -vt 1 0.015625 -vt 0.921875 0.015625 -vt 0.765625 0.125 -vt 0.921875 0.125 -vt 0.921875 0.015625 -vt 0.765625 0.015625 -vt 0.765625 0.125 -vt 0.6875 0.125 -vt 0.6875 0.28125 -vt 0.765625 0.28125 -vt 0.84375 0.28125 -vt 0.765625 0.28125 -vt 0.765625 0.125 -vt 0.84375 0.125 -vn 0 -0.8191520442889917 -0.5735764363510463 -vn 1 0 0 -vn 0 0.8191520442889917 0.5735764363510463 -vn -1 0 0 -vn 0 0.5735764363510463 -0.8191520442889917 -vn 0 -0.5735764363510463 0.8191520442889917 -usemtl m_bd56fb3d-3403-c92f-d539-6df121464423 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o Head -v 0.12437500000000001 1.625 -0.5 -v 0.12437500000000001 1.625 -0.625 -v 0.12437500000000001 1.1875 -0.5 -v 0.12437500000000001 1.1875 -0.625 -v -0.0006249999999999867 1.625 -0.625 -v -0.0006249999999999867 1.625 -0.5 -v -0.0006249999999999867 1.1875 -0.625 -v -0.0006249999999999867 1.1875 -0.5 -vt 0.21875 0.109375 -vt 0.25 0.109375 -vt 0.25 0 -vt 0.21875 0 -vt 0.1875 0.109375 -vt 0.21875 0.109375 -vt 0.21875 0 -vt 0.1875 0 -vt 0.28125 0.109375 -vt 0.3125 0.109375 -vt 0.3125 0 -vt 0.28125 0 -vt 0.25 0.109375 -vt 0.28125 0.109375 -vt 0.28125 0 -vt 0.25 0 -vt 0.25 0.109375 -vt 0.21875 0.109375 -vt 0.21875 0.140625 -vt 0.25 0.140625 -vt 0.28125 0.140625 -vt 0.25 0.140625 -vt 0.25 0.109375 -vt 0.28125 0.109375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd56fb3d-3403-c92f-d539-6df121464423 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o Head -v -0.06187500000000001 1.625 -0.5 -v -0.06187500000000001 1.625 -0.625 -v -0.06187500000000001 1.1875 -0.5 -v -0.06187500000000001 1.1875 -0.625 -v -0.186875 1.625 -0.625 -v -0.186875 1.625 -0.5 -v -0.186875 1.1875 -0.625 -v -0.186875 1.1875 -0.5 -vt 0.21875 0.109375 -vt 0.25 0.109375 -vt 0.25 0 -vt 0.21875 0 -vt 0.1875 0.109375 -vt 0.21875 0.109375 -vt 0.21875 0 -vt 0.1875 0 -vt 0.28125 0.109375 -vt 0.3125 0.109375 -vt 0.3125 0 -vt 0.28125 0 -vt 0.25 0.109375 -vt 0.28125 0.109375 -vt 0.28125 0 -vt 0.25 0 -vt 0.25 0.109375 -vt 0.21875 0.109375 -vt 0.21875 0.140625 -vt 0.25 0.140625 -vt 0.28125 0.140625 -vt 0.25 0.140625 -vt 0.25 0.109375 -vt 0.28125 0.109375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd56fb3d-3403-c92f-d539-6df121464423 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o Head -v -0.1875 1.3125 -0.5625 -v -0.1875 1.3125 -0.625 -v -0.1875 1.1875 -0.5625 -v -0.1875 1.1875 -0.625 -v -0.375 1.3125 -0.625 -v -0.375 1.3125 -0.5625 -v -0.375 1.1875 -0.625 -v -0.375 1.1875 -0.5625 -vt 0.09375 0.03125 -vt 0.046875 0.03125 -vt 0.046875 0 -vt 0.09375 0 -vt 0.109375 0.03125 -vt 0.09375 0.03125 -vt 0.09375 0 -vt 0.109375 0 -vt 0.15625 0.03125 -vt 0.109375 0.03125 -vt 0.109375 0 -vt 0.15625 0 -vt 0.046875 0.03125 -vt 0.03125 0.03125 -vt 0.03125 0 -vt 0.046875 0 -vt 0.046875 0.03125 -vt 0.09375 0.03125 -vt 0.09375 0.046875 -vt 0.046875 0.046875 -vt 0.09375 0.046875 -vt 0.140625 0.046875 -vt 0.140625 0.03125 -vt 0.09375 0.03125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd56fb3d-3403-c92f-d539-6df121464423 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o Head -v 0.3125 1.3125 -0.5625 -v 0.3125 1.3125 -0.625 -v 0.3125 1.1875 -0.5625 -v 0.3125 1.1875 -0.625 -v 0.125 1.3125 -0.625 -v 0.125 1.3125 -0.5625 -v 0.125 1.1875 -0.625 -v 0.125 1.1875 -0.5625 -vt 0.046875 0.03125 -vt 0.09375 0.03125 -vt 0.09375 0 -vt 0.046875 0 -vt 0.03125 0.03125 -vt 0.046875 0.03125 -vt 0.046875 0 -vt 0.03125 0 -vt 0.109375 0.03125 -vt 0.15625 0.03125 -vt 0.15625 0 -vt 0.109375 0 -vt 0.09375 0.03125 -vt 0.109375 0.03125 -vt 0.109375 0 -vt 0.09375 0 -vt 0.09375 0.03125 -vt 0.046875 0.03125 -vt 0.046875 0.046875 -vt 0.09375 0.046875 -vt 0.140625 0.046875 -vt 0.09375 0.046875 -vt 0.09375 0.03125 -vt 0.140625 0.03125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd56fb3d-3403-c92f-d539-6df121464423 -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 -o Head -v -0.03125 0.8125 -0.5625 -v -0.03125 0.8125 -0.875 -v -0.03125 0.375 -0.5625 -v -0.03125 0.375 -0.875 -v -0.03125 0.8125 -0.875 -v -0.03125 0.8125 -0.5625 -v -0.03125 0.375 -0.875 -v -0.03125 0.375 -0.5625 -vt 0.4375 0.109375 -vt 0.4375 0.109375 -vt 0.4375 0 -vt 0.4375 0 -vt 0.359375 0.109375 -vt 0.4375 0.109375 -vt 0.4375 0 -vt 0.359375 0 -vt 0.515625 0.109375 -vt 0.515625 0.109375 -vt 0.515625 0 -vt 0.515625 0 -vt 0.4375 0.109375 -vt 0.515625 0.109375 -vt 0.515625 0 -vt 0.4375 0 -vt 0.4375 0.109375 -vt 0.4375 0.109375 -vt 0.4375 0.1875 -vt 0.4375 0.1875 -vt 0.4375 0.1875 -vt 0.4375 0.1875 -vt 0.4375 0.109375 -vt 0.4375 0.109375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd56fb3d-3403-c92f-d539-6df121464423 -f 92/268/67 95/267/67 93/266/67 90/265/67 -f 91/272/68 92/271/68 90/270/68 89/269/68 -f 96/276/69 91/275/69 89/274/69 94/273/69 -f 95/280/70 96/279/70 94/278/70 93/277/70 -f 94/284/71 89/283/71 90/282/71 93/281/71 -f 95/288/72 92/287/72 91/286/72 96/285/72 -o HeadMain -v 0.125 1.3707881146238856 -0.6330909565283671 -v 0.125 0.8588180869432658 -0.991576229247771 -v 0.125 1.1198484237203028 -0.2747119371519333 -v 0.125 0.607878396039683 -0.6331972098713372 -v -0.1875 0.8588180869432658 -0.991576229247771 -v -0.1875 1.3707881146238856 -0.6330909565283671 -v -0.1875 0.607878396039683 -0.6331972098713372 -v -0.1875 1.1198484237203028 -0.2747119371519333 -vt 0.6875 0.125 -vt 0.765625 0.125 -vt 0.765625 0.015625 -vt 0.6875 0.015625 -vt 0.53125 0.125 -vt 0.6875 0.125 -vt 0.6875 0.015625 -vt 0.53125 0.015625 -vt 0.921875 0.125 -vt 1 0.125 -vt 1 0.015625 -vt 0.921875 0.015625 -vt 0.765625 0.125 -vt 0.921875 0.125 -vt 0.921875 0.015625 -vt 0.765625 0.015625 -vt 0.765625 0.125 -vt 0.6875 0.125 -vt 0.6875 0.28125 -vt 0.765625 0.28125 -vt 0.84375 0.28125 -vt 0.765625 0.28125 -vt 0.765625 0.125 -vt 0.84375 0.125 -vn 0 -0.8191520442889917 -0.5735764363510463 -vn 1 0 0 -vn 0 0.8191520442889917 0.5735764363510463 -vn -1 0 0 -vn 0 0.5735764363510463 -0.8191520442889917 -vn 0 -0.5735764363510463 0.8191520442889917 -usemtl m_bd56fb3d-3403-c92f-d539-6df121464423 -f 100/292/73 103/291/73 101/290/73 98/289/73 -f 99/296/74 100/295/74 98/294/74 97/293/74 -f 104/300/75 99/299/75 97/298/75 102/297/75 -f 103/304/76 104/303/76 102/302/76 101/301/76 -f 102/308/77 97/307/77 98/306/77 101/305/77 -f 103/312/78 100/311/78 99/310/78 104/309/78 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/guardian.obj b/renderer/viewer/three/entity/models/guardian.obj deleted file mode 100644 index 0addde29b..000000000 --- a/renderer/viewer/three/entity/models/guardian.obj +++ /dev/null @@ -1,1015 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o head -v 0.375 0.875 0.5 -v 0.375 0.875 -0.5 -v 0.375 0.125 0.5 -v 0.375 0.125 -0.5 -v -0.375 0.875 -0.5 -v -0.375 0.875 0.5 -v -0.375 0.125 -0.5 -v -0.375 0.125 0.5 -vt 0.25 0.75 -vt 0.4375 0.75 -vt 0.4375 0.5625 -vt 0.25 0.5625 -vt 0 0.75 -vt 0.25 0.75 -vt 0.25 0.5625 -vt 0 0.5625 -vt 0.6875 0.75 -vt 0.875 0.75 -vt 0.875 0.5625 -vt 0.6875 0.5625 -vt 0.4375 0.75 -vt 0.6875 0.75 -vt 0.6875 0.5625 -vt 0.4375 0.5625 -vt 0.4375 0.75 -vt 0.25 0.75 -vt 0.25 1 -vt 0.4375 1 -vt 0.625 1 -vt 0.4375 1 -vt 0.4375 0.75 -vt 0.625 0.75 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o head -v 0.5 0.875 0.375 -v 0.5 0.875 -0.375 -v 0.5 0.125 0.375 -v 0.5 0.125 -0.375 -v 0.375 0.875 -0.375 -v 0.375 0.875 0.375 -v 0.375 0.125 -0.375 -v 0.375 0.125 0.375 -vt 0.1875 0.375 -vt 0.21875 0.375 -vt 0.21875 0.1875 -vt 0.1875 0.1875 -vt 0 0.375 -vt 0.1875 0.375 -vt 0.1875 0.1875 -vt 0 0.1875 -vt 0.40625 0.375 -vt 0.4375 0.375 -vt 0.4375 0.1875 -vt 0.40625 0.1875 -vt 0.21875 0.375 -vt 0.40625 0.375 -vt 0.40625 0.1875 -vt 0.21875 0.1875 -vt 0.21875 0.375 -vt 0.1875 0.375 -vt 0.1875 0.5625 -vt 0.21875 0.5625 -vt 0.25 0.5625 -vt 0.21875 0.5625 -vt 0.21875 0.375 -vt 0.25 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o head -v -0.375 0.875 0.375 -v -0.375 0.875 -0.375 -v -0.375 0.125 0.375 -v -0.375 0.125 -0.375 -v -0.5 0.875 -0.375 -v -0.5 0.875 0.375 -v -0.5 0.125 -0.375 -v -0.5 0.125 0.375 -vt 0.21875 0.375 -vt 0.1875 0.375 -vt 0.1875 0.1875 -vt 0.21875 0.1875 -vt 0.40625 0.375 -vt 0.21875 0.375 -vt 0.21875 0.1875 -vt 0.40625 0.1875 -vt 0.4375 0.375 -vt 0.40625 0.375 -vt 0.40625 0.1875 -vt 0.4375 0.1875 -vt 0.1875 0.375 -vt 0 0.375 -vt 0 0.1875 -vt 0.1875 0.1875 -vt 0.1875 0.375 -vt 0.21875 0.375 -vt 0.21875 0.5625 -vt 0.1875 0.5625 -vt 0.21875 0.5625 -vt 0.25 0.5625 -vt 0.25 0.375 -vt 0.21875 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o head -v 0.375 1 0.375 -v 0.375 1 -0.375 -v 0.375 0.875 0.375 -v 0.375 0.875 -0.375 -v -0.375 1 -0.375 -v -0.375 1 0.375 -v -0.375 0.875 -0.375 -v -0.375 0.875 0.375 -vt 0.625 0.1875 -vt 0.4375 0.1875 -vt 0.4375 0.15625 -vt 0.625 0.15625 -vt 0.8125 0.1875 -vt 0.625 0.1875 -vt 0.625 0.15625 -vt 0.8125 0.15625 -vt 1 0.1875 -vt 0.8125 0.1875 -vt 0.8125 0.15625 -vt 1 0.15625 -vt 0.4375 0.1875 -vt 0.25 0.1875 -vt 0.25 0.15625 -vt 0.4375 0.15625 -vt 0.4375 0.1875 -vt 0.625 0.1875 -vt 0.625 0.375 -vt 0.4375 0.375 -vt 0.625 0.375 -vt 0.8125 0.375 -vt 0.8125 0.1875 -vt 0.625 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o head -v 0.375 0.125 0.375 -v 0.375 0.125 -0.375 -v 0.375 0 0.375 -v 0.375 0 -0.375 -v -0.375 0.125 -0.375 -v -0.375 0.125 0.375 -v -0.375 0 -0.375 -v -0.375 0 0.375 -vt 0.625 0.1875 -vt 0.4375 0.1875 -vt 0.4375 0.15625 -vt 0.625 0.15625 -vt 0.8125 0.1875 -vt 0.625 0.1875 -vt 0.625 0.15625 -vt 0.8125 0.15625 -vt 1 0.1875 -vt 0.8125 0.1875 -vt 0.8125 0.15625 -vt 1 0.15625 -vt 0.4375 0.1875 -vt 0.25 0.1875 -vt 0.25 0.15625 -vt 0.4375 0.15625 -vt 0.4375 0.1875 -vt 0.625 0.1875 -vt 0.625 0.375 -vt 0.4375 0.375 -vt 0.625 0.375 -vt 0.8125 0.375 -vt 0.8125 0.1875 -vt 0.625 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o eye -v 0.0625 0.5625 -0.453125 -v 0.0625 0.5625 -0.515625 -v 0.0625 0.4375 -0.453125 -v 0.0625 0.4375 -0.515625 -v -0.0625 0.5625 -0.515625 -v -0.0625 0.5625 -0.453125 -v -0.0625 0.4375 -0.515625 -v -0.0625 0.4375 -0.453125 -vt 0.140625 0.984375 -vt 0.171875 0.984375 -vt 0.171875 0.953125 -vt 0.140625 0.953125 -vt 0.125 0.984375 -vt 0.140625 0.984375 -vt 0.140625 0.953125 -vt 0.125 0.953125 -vt 0.1875 0.984375 -vt 0.21875 0.984375 -vt 0.21875 0.953125 -vt 0.1875 0.953125 -vt 0.171875 0.984375 -vt 0.1875 0.984375 -vt 0.1875 0.953125 -vt 0.171875 0.953125 -vt 0.171875 0.984375 -vt 0.140625 0.984375 -vt 0.140625 1 -vt 0.171875 1 -vt 0.203125 1 -vt 0.171875 1 -vt 0.171875 0.984375 -vt 0.203125 0.984375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o tailpart0 -v 0.125 0.625 1 -v 0.125 0.625 0.5 -v 0.125 0.375 1 -v 0.125 0.375 0.5 -v -0.125 0.625 0.5 -v -0.125 0.625 1 -v -0.125 0.375 0.5 -v -0.125 0.375 1 -vt 0.75 0.875 -vt 0.8125 0.875 -vt 0.8125 0.8125 -vt 0.75 0.8125 -vt 0.625 0.875 -vt 0.75 0.875 -vt 0.75 0.8125 -vt 0.625 0.8125 -vt 0.9375 0.875 -vt 1 0.875 -vt 1 0.8125 -vt 0.9375 0.8125 -vt 0.8125 0.875 -vt 0.9375 0.875 -vt 0.9375 0.8125 -vt 0.8125 0.8125 -vt 0.8125 0.875 -vt 0.75 0.875 -vt 0.75 1 -vt 0.8125 1 -vt 0.875 1 -vt 0.8125 1 -vt 0.8125 0.875 -vt 0.875 0.875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o tailpart1 -v 0.09375 0.625 1.4375 -v 0.09375 0.625 1 -v 0.09375 0.4375 1.4375 -v 0.09375 0.4375 1 -v -0.09375 0.625 1 -v -0.09375 0.625 1.4375 -v -0.09375 0.4375 1 -v -0.09375 0.4375 1.4375 -vt 0.109375 0.046875 -vt 0.15625 0.046875 -vt 0.15625 0 -vt 0.109375 0 -vt 0 0.046875 -vt 0.109375 0.046875 -vt 0.109375 0 -vt 0 0 -vt 0.265625 0.046875 -vt 0.3125 0.046875 -vt 0.3125 0 -vt 0.265625 0 -vt 0.15625 0.046875 -vt 0.265625 0.046875 -vt 0.265625 0 -vt 0.15625 0 -vt 0.15625 0.046875 -vt 0.109375 0.046875 -vt 0.109375 0.15625 -vt 0.15625 0.15625 -vt 0.203125 0.15625 -vt 0.15625 0.15625 -vt 0.15625 0.046875 -vt 0.203125 0.046875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o tailpart2 -v 0.0625 0.625 1.8125 -v 0.0625 0.625 1.4375 -v 0.0625 0.5 1.8125 -v 0.0625 0.5 1.4375 -v -0.0625 0.625 1.4375 -v -0.0625 0.625 1.8125 -v -0.0625 0.5 1.4375 -v -0.0625 0.5 1.8125 -vt 0.734375 0.40625 -vt 0.765625 0.40625 -vt 0.765625 0.375 -vt 0.734375 0.375 -vt 0.640625 0.40625 -vt 0.734375 0.40625 -vt 0.734375 0.375 -vt 0.640625 0.375 -vt 0.859375 0.40625 -vt 0.890625 0.40625 -vt 0.890625 0.375 -vt 0.859375 0.375 -vt 0.765625 0.40625 -vt 0.859375 0.40625 -vt 0.859375 0.375 -vt 0.765625 0.375 -vt 0.765625 0.40625 -vt 0.734375 0.40625 -vt 0.734375 0.5 -vt 0.765625 0.5 -vt 0.796875 0.5 -vt 0.765625 0.5 -vt 0.765625 0.40625 -vt 0.796875 0.40625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o tailpart2 -v 0 0.84375 2.1875 -v 0 0.84375 1.625 -v 0 0.28125 2.1875 -v 0 0.28125 1.625 -v -0.0625 0.84375 1.625 -v -0.0625 0.84375 2.1875 -v -0.0625 0.28125 1.625 -v -0.0625 0.28125 2.1875 -vt 0.53125 0.5625 -vt 0.546875 0.5625 -vt 0.546875 0.421875 -vt 0.53125 0.421875 -vt 0.390625 0.5625 -vt 0.53125 0.5625 -vt 0.53125 0.421875 -vt 0.390625 0.421875 -vt 0.6875 0.5625 -vt 0.703125 0.5625 -vt 0.703125 0.421875 -vt 0.6875 0.421875 -vt 0.546875 0.5625 -vt 0.6875 0.5625 -vt 0.6875 0.421875 -vt 0.546875 0.421875 -vt 0.546875 0.5625 -vt 0.53125 0.5625 -vt 0.53125 0.703125 -vt 0.546875 0.703125 -vt 0.5625 0.703125 -vt 0.546875 0.703125 -vt 0.546875 0.5625 -vt 0.5625 0.5625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o spikepart0 -v -0.6518640639063484 1.2458835005110844 0.0625 -v -0.6518640639063484 1.2458835005110844 -0.0625 -v -0.25411649948891535 0.8481359360936516 0.0625 -v -0.25411649948891535 0.8481359360936516 -0.0625 -v -0.7402524115546669 1.157495152862766 -0.0625 -v -0.7402524115546669 1.157495152862766 0.0625 -v -0.34250484713723384 0.7597475884453331 -0.0625 -v -0.34250484713723384 0.7597475884453331 0.0625 -vt 0.03125 0.96875 -vt 0.0625 0.96875 -vt 0.0625 0.828125 -vt 0.03125 0.828125 -vt 0 0.96875 -vt 0.03125 0.96875 -vt 0.03125 0.828125 -vt 0 0.828125 -vt 0.09375 0.96875 -vt 0.125 0.96875 -vt 0.125 0.828125 -vt 0.09375 0.828125 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vt 0.09375 0.828125 -vt 0.0625 0.828125 -vt 0.0625 0.96875 -vt 0.03125 0.96875 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vn 0 0 -1 -vn 0.7071067811865475 0.7071067811865476 0 -vn 0 0 1 -vn -0.7071067811865475 -0.7071067811865476 0 -vn -0.7071067811865476 0.7071067811865475 0 -vn 0.7071067811865476 -0.7071067811865475 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 -o spikepart1 -v 0.7402524115546669 1.157495152862766 0.0625 -v 0.7402524115546669 1.157495152862766 -0.0625 -v 0.34250484713723384 0.7597475884453331 0.0625 -v 0.34250484713723384 0.7597475884453331 -0.0625 -v 0.6518640639063484 1.2458835005110844 -0.0625 -v 0.6518640639063484 1.2458835005110844 0.0625 -v 0.25411649948891535 0.8481359360936516 -0.0625 -v 0.25411649948891535 0.8481359360936516 0.0625 -vt 0.03125 0.96875 -vt 0.0625 0.96875 -vt 0.0625 0.828125 -vt 0.03125 0.828125 -vt 0 0.96875 -vt 0.03125 0.96875 -vt 0.03125 0.828125 -vt 0 0.828125 -vt 0.09375 0.96875 -vt 0.125 0.96875 -vt 0.125 0.828125 -vt 0.09375 0.828125 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vt 0.09375 0.828125 -vt 0.0625 0.828125 -vt 0.0625 0.96875 -vt 0.03125 0.96875 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vn 0 0 -1 -vn 0.7071067811865475 -0.7071067811865476 0 -vn 0 0 1 -vn -0.7071067811865475 0.7071067811865476 0 -vn 0.7071067811865476 0.7071067811865475 0 -vn -0.7071067811865476 -0.7071067811865475 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 92/268/67 95/267/67 93/266/67 90/265/67 -f 91/272/68 92/271/68 90/270/68 89/269/68 -f 96/276/69 91/275/69 89/274/69 94/273/69 -f 95/280/70 96/279/70 94/278/70 93/277/70 -f 94/284/71 89/283/71 90/282/71 93/281/71 -f 95/288/72 92/287/72 91/286/72 96/285/72 -o spikepart2 -v 0.0625 1.2458835005110844 -0.6518640639063484 -v 0.0625 1.157495152862766 -0.7402524115546669 -v 0.0625 0.8481359360936516 -0.25411649948891535 -v 0.0625 0.7597475884453331 -0.34250484713723384 -v -0.0625 1.157495152862766 -0.7402524115546669 -v -0.0625 1.2458835005110844 -0.6518640639063484 -v -0.0625 0.7597475884453331 -0.34250484713723384 -v -0.0625 0.8481359360936516 -0.25411649948891535 -vt 0.03125 0.96875 -vt 0.0625 0.96875 -vt 0.0625 0.828125 -vt 0.03125 0.828125 -vt 0 0.96875 -vt 0.03125 0.96875 -vt 0.03125 0.828125 -vt 0 0.828125 -vt 0.09375 0.96875 -vt 0.125 0.96875 -vt 0.125 0.828125 -vt 0.09375 0.828125 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vt 0.09375 0.828125 -vt 0.0625 0.828125 -vt 0.0625 0.96875 -vt 0.03125 0.96875 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vn 0 -0.7071067811865476 -0.7071067811865475 -vn 1 0 0 -vn 0 0.7071067811865476 0.7071067811865475 -vn -1 0 0 -vn 0 0.7071067811865475 -0.7071067811865476 -vn 0 -0.7071067811865475 0.7071067811865476 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 100/292/73 103/291/73 101/290/73 98/289/73 -f 99/296/74 100/295/74 98/294/74 97/293/74 -f 104/300/75 99/299/75 97/298/75 102/297/75 -f 103/304/76 104/303/76 102/302/76 101/301/76 -f 102/308/77 97/307/77 98/306/77 101/305/77 -f 103/312/78 100/311/78 99/310/78 104/309/78 -o spikepart3 -v 0.0625 1.1464466094067263 0.7513009550107066 -v 0.0625 1.2348349570550448 0.6629126073623883 -v 0.0625 0.7486990449892934 0.3535533905932735 -v 0.0625 0.8370873926376117 0.26516504294495524 -v -0.0625 1.2348349570550448 0.6629126073623883 -v -0.0625 1.1464466094067263 0.7513009550107066 -v -0.0625 0.8370873926376117 0.26516504294495524 -v -0.0625 0.7486990449892934 0.3535533905932735 -vt 0.03125 0.96875 -vt 0.0625 0.96875 -vt 0.0625 0.828125 -vt 0.03125 0.828125 -vt 0 0.96875 -vt 0.03125 0.96875 -vt 0.03125 0.828125 -vt 0 0.828125 -vt 0.09375 0.96875 -vt 0.125 0.96875 -vt 0.125 0.828125 -vt 0.09375 0.828125 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vt 0.09375 0.828125 -vt 0.0625 0.828125 -vt 0.0625 0.96875 -vt 0.03125 0.96875 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vn 0 0.7071067811865476 -0.7071067811865475 -vn 1 0 0 -vn 0 -0.7071067811865476 0.7071067811865475 -vn -1 0 0 -vn 0 0.7071067811865475 0.7071067811865476 -vn 0 -0.7071067811865475 -0.7071067811865476 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 108/316/79 111/315/79 109/314/79 106/313/79 -f 107/320/80 108/319/80 106/318/80 105/317/80 -f 112/324/81 107/323/81 105/322/81 110/321/81 -f 111/328/82 112/327/82 110/326/82 109/325/82 -f 110/332/83 105/331/83 106/330/83 109/329/83 -f 111/336/84 108/335/84 107/334/84 112/333/84 -o spikepart4 -v -0.7623494984667472 -0.16833006186201072 0.0625 -v -0.7623494984667472 -0.16833006186201072 -0.0625 -v -0.36460193404931407 0.22941750255542193 0.0625 -v -0.36460193404931407 0.22941750255542193 -0.0625 -v -0.6739611508184287 -0.256718409510329 -0.0625 -v -0.6739611508184287 -0.256718409510329 0.0625 -v -0.2762135864009956 0.14102915490710366 -0.0625 -v -0.2762135864009956 0.14102915490710366 0.0625 -vt 0.03125 0.96875 -vt 0.0625 0.96875 -vt 0.0625 0.828125 -vt 0.03125 0.828125 -vt 0 0.96875 -vt 0.03125 0.96875 -vt 0.03125 0.828125 -vt 0 0.828125 -vt 0.09375 0.96875 -vt 0.125 0.96875 -vt 0.125 0.828125 -vt 0.09375 0.828125 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vt 0.09375 0.828125 -vt 0.0625 0.828125 -vt 0.0625 0.96875 -vt 0.03125 0.96875 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vn 0 0 -1 -vn -0.7071067811865475 0.7071067811865477 0 -vn 0 0 1 -vn 0.7071067811865475 -0.7071067811865477 0 -vn -0.7071067811865477 -0.7071067811865475 0 -vn 0.7071067811865477 0.7071067811865475 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 116/340/85 119/339/85 117/338/85 114/337/85 -f 115/344/86 116/343/86 114/342/86 113/341/86 -f 120/348/87 115/347/87 113/346/87 118/345/87 -f 119/352/88 120/351/88 118/350/88 117/349/88 -f 118/356/89 113/355/89 114/354/89 117/353/89 -f 119/360/90 116/359/90 115/358/90 120/357/90 -o spikepart5 -v 0.6739611508184287 -0.256718409510329 0.0625 -v 0.6739611508184287 -0.256718409510329 -0.0625 -v 0.2762135864009956 0.14102915490710366 0.0625 -v 0.2762135864009956 0.14102915490710366 -0.0625 -v 0.7623494984667472 -0.16833006186201072 -0.0625 -v 0.7623494984667472 -0.16833006186201072 0.0625 -v 0.36460193404931407 0.22941750255542193 -0.0625 -v 0.36460193404931407 0.22941750255542193 0.0625 -vt 0.03125 0.96875 -vt 0.0625 0.96875 -vt 0.0625 0.828125 -vt 0.03125 0.828125 -vt 0 0.96875 -vt 0.03125 0.96875 -vt 0.03125 0.828125 -vt 0 0.828125 -vt 0.09375 0.96875 -vt 0.125 0.96875 -vt 0.125 0.828125 -vt 0.09375 0.828125 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vt 0.09375 0.828125 -vt 0.0625 0.828125 -vt 0.0625 0.96875 -vt 0.03125 0.96875 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vn 0 0 -1 -vn -0.7071067811865475 -0.7071067811865477 0 -vn 0 0 1 -vn 0.7071067811865475 0.7071067811865477 0 -vn 0.7071067811865477 -0.7071067811865475 0 -vn -0.7071067811865477 0.7071067811865475 0 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 124/364/91 127/363/91 125/362/91 122/361/91 -f 123/368/92 124/367/92 122/366/92 121/365/92 -f 128/372/93 123/371/93 121/370/93 126/369/93 -f 127/376/94 128/375/94 126/374/94 125/373/94 -f 126/380/95 121/379/95 122/378/95 125/377/95 -f 127/384/96 124/383/96 123/382/96 128/381/96 -o spikepart6 -v 0.0625 -0.21252423568616985 -0.8065436722909063 -v 0.0625 -0.30091258333448856 -0.7181553246425878 -v 0.0625 0.18522332873126324 -0.4087961078734732 -v 0.0625 0.09683498108294453 -0.3204077602251547 -v -0.0625 -0.30091258333448856 -0.7181553246425878 -v -0.0625 -0.21252423568616985 -0.8065436722909063 -v -0.0625 0.09683498108294453 -0.3204077602251547 -v -0.0625 0.18522332873126324 -0.4087961078734732 -vt 0.03125 0.96875 -vt 0.0625 0.96875 -vt 0.0625 0.828125 -vt 0.03125 0.828125 -vt 0 0.96875 -vt 0.03125 0.96875 -vt 0.03125 0.828125 -vt 0 0.828125 -vt 0.09375 0.96875 -vt 0.125 0.96875 -vt 0.125 0.828125 -vt 0.09375 0.828125 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vt 0.09375 0.828125 -vt 0.0625 0.828125 -vt 0.0625 0.96875 -vt 0.03125 0.96875 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vn 0 -0.7071067811865477 0.7071067811865475 -vn 1 0 0 -vn 0 0.7071067811865477 -0.7071067811865475 -vn -1 0 0 -vn 0 -0.7071067811865475 -0.7071067811865477 -vn 0 0.7071067811865475 0.7071067811865477 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 132/388/97 135/387/97 133/386/97 130/385/97 -f 131/392/98 132/391/98 130/390/98 129/389/98 -f 136/396/99 131/395/99 129/394/99 134/393/99 -f 135/400/100 136/399/100 134/398/100 133/397/100 -f 134/404/101 129/403/101 130/402/101 133/401/101 -f 135/408/102 132/407/102 131/406/102 136/405/102 -o spikepart7 -v 0.0625 -0.256718409510329 0.6739611508184287 -v 0.0625 -0.16833006186201072 0.7623494984667472 -v 0.0625 0.14102915490710366 0.2762135864009956 -v 0.0625 0.22941750255542193 0.36460193404931407 -v -0.0625 -0.16833006186201072 0.7623494984667472 -v -0.0625 -0.256718409510329 0.6739611508184287 -v -0.0625 0.22941750255542193 0.36460193404931407 -v -0.0625 0.14102915490710366 0.2762135864009956 -vt 0.03125 0.96875 -vt 0.0625 0.96875 -vt 0.0625 0.828125 -vt 0.03125 0.828125 -vt 0 0.96875 -vt 0.03125 0.96875 -vt 0.03125 0.828125 -vt 0 0.828125 -vt 0.09375 0.96875 -vt 0.125 0.96875 -vt 0.125 0.828125 -vt 0.09375 0.828125 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vt 0.09375 0.828125 -vt 0.0625 0.828125 -vt 0.0625 0.96875 -vt 0.03125 0.96875 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vn 0 0.7071067811865477 0.7071067811865475 -vn 1 0 0 -vn 0 -0.7071067811865477 -0.7071067811865475 -vn -1 0 0 -vn 0 -0.7071067811865475 0.7071067811865477 -vn 0 0.7071067811865475 -0.7071067811865477 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 140/412/103 143/411/103 141/410/103 138/409/103 -f 139/416/104 140/415/104 138/414/104 137/413/104 -f 144/420/105 139/419/105 137/418/105 142/417/105 -f 143/424/106 144/423/106 142/422/106 141/421/106 -f 142/428/107 137/427/107 138/426/107 141/425/107 -f 143/432/108 140/431/108 139/430/108 144/429/108 -o spikepart8 -v -0.7292038680986273 0.5625000000000004 -0.8175922157469457 -v -0.7292038680986275 0.43750000000000044 -0.8175922157469457 -v -0.33145630368119416 0.5625000000000002 -0.41984465132951265 -v -0.3314563036811944 0.4375000000000002 -0.41984465132951265 -v -0.8175922157469457 0.43750000000000044 -0.7292038680986275 -v -0.8175922157469455 0.5625000000000004 -0.7292038680986275 -v -0.41984465132951265 0.4375000000000002 -0.3314563036811944 -v -0.41984465132951243 0.5625000000000002 -0.3314563036811944 -vt 0.03125 0.96875 -vt 0.0625 0.96875 -vt 0.0625 0.828125 -vt 0.03125 0.828125 -vt 0 0.96875 -vt 0.03125 0.96875 -vt 0.03125 0.828125 -vt 0 0.828125 -vt 0.09375 0.96875 -vt 0.125 0.96875 -vt 0.125 0.828125 -vt 0.09375 0.828125 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vt 0.09375 0.828125 -vt 0.0625 0.828125 -vt 0.0625 0.96875 -vt 0.03125 0.96875 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vn -2.355138688025663e-16 -1 -2.3551386880256634e-16 -vn 0.7071067811865476 7.850462293418876e-17 -0.7071067811865476 -vn 2.355138688025663e-16 1 2.3551386880256634e-16 -vn -0.7071067811865476 -7.850462293418876e-17 0.7071067811865476 -vn -0.7071067811865475 2.355138688025663e-16 -0.7071067811865476 -vn 0.7071067811865475 -2.355138688025663e-16 0.7071067811865476 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 148/436/109 151/435/109 149/434/109 146/433/109 -f 147/440/110 148/439/110 146/438/110 145/437/110 -f 152/444/111 147/443/111 145/442/111 150/441/111 -f 151/448/112 152/447/112 150/446/112 149/445/112 -f 150/452/113 145/451/113 146/450/113 149/449/113 -f 151/456/114 148/455/114 147/454/114 152/453/114 -o spikepart8 -v 0.8175922157469455 0.5625000000000004 -0.7292038680986275 -v 0.8175922157469457 0.43750000000000044 -0.7292038680986275 -v 0.41984465132951243 0.5625000000000002 -0.3314563036811944 -v 0.41984465132951265 0.4375000000000002 -0.3314563036811944 -v 0.7292038680986275 0.43750000000000044 -0.8175922157469457 -v 0.7292038680986273 0.5625000000000004 -0.8175922157469457 -v 0.3314563036811944 0.4375000000000002 -0.41984465132951265 -v 0.33145630368119416 0.5625000000000002 -0.41984465132951265 -vt 0.03125 0.96875 -vt 0.0625 0.96875 -vt 0.0625 0.828125 -vt 0.03125 0.828125 -vt 0 0.96875 -vt 0.03125 0.96875 -vt 0.03125 0.828125 -vt 0 0.828125 -vt 0.09375 0.96875 -vt 0.125 0.96875 -vt 0.125 0.828125 -vt 0.09375 0.828125 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vt 0.09375 0.828125 -vt 0.0625 0.828125 -vt 0.0625 0.96875 -vt 0.03125 0.96875 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vn 2.355138688025663e-16 -1 -2.3551386880256634e-16 -vn 0.7071067811865476 -7.850462293418876e-17 0.7071067811865476 -vn -2.355138688025663e-16 1 2.3551386880256634e-16 -vn -0.7071067811865476 7.850462293418876e-17 -0.7071067811865476 -vn 0.7071067811865475 2.355138688025663e-16 -0.7071067811865476 -vn -0.7071067811865475 -2.355138688025663e-16 0.7071067811865476 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 156/460/115 159/459/115 157/458/115 154/457/115 -f 155/464/116 156/463/116 154/462/116 153/461/116 -f 160/468/117 155/467/117 153/466/117 158/465/117 -f 159/472/118 160/471/118 158/470/118 157/469/118 -f 158/476/119 153/475/119 154/474/119 157/473/119 -f 159/480/120 156/479/120 155/478/120 160/477/120 -o spikepart8 -v -0.8175922157469455 0.5625 0.7292038680986273 -v -0.8175922157469457 0.4375000000000002 0.7292038680986273 -v -0.41984465132951243 0.5625 0.33145630368119416 -v -0.41984465132951265 0.4375 0.33145630368119416 -v -0.7292038680986275 0.4375000000000002 0.8175922157469455 -v -0.7292038680986273 0.5625 0.8175922157469455 -v -0.3314563036811944 0.4375 0.41984465132951243 -v -0.33145630368119416 0.5625 0.41984465132951243 -vt 0.03125 0.96875 -vt 0.0625 0.96875 -vt 0.0625 0.828125 -vt 0.03125 0.828125 -vt 0 0.96875 -vt 0.03125 0.96875 -vt 0.03125 0.828125 -vt 0 0.828125 -vt 0.09375 0.96875 -vt 0.125 0.96875 -vt 0.125 0.828125 -vt 0.09375 0.828125 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vt 0.09375 0.828125 -vt 0.0625 0.828125 -vt 0.0625 0.96875 -vt 0.03125 0.96875 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vn -1.5700924586837752e-16 -1 1.570092458683775e-16 -vn -0.7071067811865475 7.850462293418875e-17 -0.7071067811865476 -vn 1.5700924586837752e-16 1 -1.570092458683775e-16 -vn 0.7071067811865475 -7.850462293418875e-17 0.7071067811865476 -vn -0.7071067811865476 7.850462293418876e-17 0.7071067811865475 -vn 0.7071067811865476 -7.850462293418876e-17 -0.7071067811865475 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 164/484/121 167/483/121 165/482/121 162/481/121 -f 163/488/122 164/487/122 162/486/122 161/485/122 -f 168/492/123 163/491/123 161/490/123 166/489/123 -f 167/496/124 168/495/124 166/494/124 165/493/124 -f 166/500/125 161/499/125 162/498/125 165/497/125 -f 167/504/126 164/503/126 163/502/126 168/501/126 -o spikepart8 -v 0.7292038680986273 0.5625 0.8175922157469455 -v 0.7292038680986275 0.4375000000000002 0.8175922157469455 -v 0.33145630368119416 0.5625 0.41984465132951243 -v 0.3314563036811944 0.4375 0.41984465132951243 -v 0.8175922157469457 0.4375000000000002 0.7292038680986273 -v 0.8175922157469455 0.5625 0.7292038680986273 -v 0.41984465132951265 0.4375 0.33145630368119416 -v 0.41984465132951243 0.5625 0.33145630368119416 -vt 0.03125 0.96875 -vt 0.0625 0.96875 -vt 0.0625 0.828125 -vt 0.03125 0.828125 -vt 0 0.96875 -vt 0.03125 0.96875 -vt 0.03125 0.828125 -vt 0 0.828125 -vt 0.09375 0.96875 -vt 0.125 0.96875 -vt 0.125 0.828125 -vt 0.09375 0.828125 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vt 0.09375 0.828125 -vt 0.0625 0.828125 -vt 0.0625 0.96875 -vt 0.03125 0.96875 -vt 0.03125 1 -vt 0.0625 1 -vt 0.09375 1 -vt 0.0625 1 -vt 0.0625 0.96875 -vt 0.09375 0.96875 -vn 1.5700924586837752e-16 -1 1.570092458683775e-16 -vn -0.7071067811865475 -7.850462293418875e-17 0.7071067811865476 -vn -1.5700924586837752e-16 1 -1.570092458683775e-16 -vn 0.7071067811865475 7.850462293418875e-17 -0.7071067811865476 -vn 0.7071067811865476 7.850462293418876e-17 0.7071067811865475 -vn -0.7071067811865476 -7.850462293418876e-17 -0.7071067811865475 -usemtl m_18bfdc93-cc40-fa86-b211-05ac08cf8255 -f 172/508/127 175/507/127 173/506/127 170/505/127 -f 171/512/128 172/511/128 170/510/128 169/509/128 -f 176/516/129 171/515/129 169/514/129 174/513/129 -f 175/520/130 176/519/130 174/518/130 173/517/130 -f 174/524/131 169/523/131 170/522/131 173/521/131 -f 175/528/132 172/527/132 171/526/132 176/525/132 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/horse.obj b/renderer/viewer/three/entity/models/horse.obj deleted file mode 100644 index bb08e9137..000000000 --- a/renderer/viewer/three/entity/models/horse.obj +++ /dev/null @@ -1,1061 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o Body -v 0.3125 1.3125 0.6875 -v 0.3125 1.3125 -0.6875 -v 0.3125 0.6875 0.6875 -v 0.3125 0.6875 -0.6875 -v -0.3125 1.3125 -0.6875 -v -0.3125 1.3125 0.6875 -v -0.3125 0.6875 -0.6875 -v -0.3125 0.6875 0.6875 -vt 0.34375 0.15625 -vt 0.5 0.15625 -vt 0.5 0 -vt 0.34375 0 -vt 0 0.15625 -vt 0.34375 0.15625 -vt 0.34375 0 -vt 0 0 -vt 0.84375 0.15625 -vt 1 0.15625 -vt 1 0 -vt 0.84375 0 -vt 0.5 0.15625 -vt 0.84375 0.15625 -vt 0.84375 0 -vt 0.5 0 -vt 0.5 0.15625 -vt 0.34375 0.15625 -vt 0.34375 0.5 -vt 0.5 0.5 -vt 0.65625 0.5 -vt 0.5 0.5 -vt 0.5 0.15625 -vt 0.65625 0.15625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o TailA -v 0.09375 1.3125 0.7957531754730547 -v 0.09375 1.1875 0.5792468245269451 -v 0.09375 0.5547277716886161 1.2332531754730547 -v 0.09375 0.4297277716886161 1.0167468245269449 -v -0.09375 1.1875 0.5792468245269451 -v -0.09375 1.3125 0.7957531754730547 -v -0.09375 0.4297277716886161 1.0167468245269449 -v -0.09375 0.5547277716886161 1.2332531754730547 -vt 0.71875 0.375 -vt 0.765625 0.375 -vt 0.765625 0.15625 -vt 0.71875 0.15625 -vt 0.65625 0.375 -vt 0.71875 0.375 -vt 0.71875 0.15625 -vt 0.65625 0.15625 -vt 0.828125 0.375 -vt 0.875 0.375 -vt 0.875 0.15625 -vt 0.828125 0.15625 -vt 0.765625 0.375 -vt 0.828125 0.375 -vt 0.828125 0.15625 -vt 0.765625 0.15625 -vt 0.765625 0.375 -vt 0.71875 0.375 -vt 0.71875 0.4375 -vt 0.765625 0.4375 -vt 0.8125 0.4375 -vt 0.765625 0.4375 -vt 0.765625 0.375 -vt 0.8125 0.375 -vn 0 -0.49999999999999994 -0.8660254037844387 -vn 1 0 0 -vn 0 0.49999999999999994 0.8660254037844387 -vn -1 0 0 -vn 0 0.8660254037844387 -0.49999999999999994 -vn 0 -0.8660254037844387 0.49999999999999994 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o Leg1A -v -0.0625 0.6875 0.6875 -v -0.0625 0.6875 0.4375 -v -0.0625 0 0.6875 -v -0.0625 0 0.4375 -v -0.3125 0.6875 0.4375 -v -0.3125 0.6875 0.6875 -v -0.3125 0 0.4375 -v -0.3125 0 0.6875 -vt 0.875 0.609375 -vt 0.8125 0.609375 -vt 0.8125 0.4375 -vt 0.875 0.4375 -vt 0.9375 0.609375 -vt 0.875 0.609375 -vt 0.875 0.4375 -vt 0.9375 0.4375 -vt 1 0.609375 -vt 0.9375 0.609375 -vt 0.9375 0.4375 -vt 1 0.4375 -vt 0.8125 0.609375 -vt 0.75 0.609375 -vt 0.75 0.4375 -vt 0.8125 0.4375 -vt 0.8125 0.609375 -vt 0.875 0.609375 -vt 0.875 0.671875 -vt 0.8125 0.671875 -vt 0.875 0.671875 -vt 0.9375 0.671875 -vt 0.9375 0.609375 -vt 0.875 0.609375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o Leg2A -v 0.3125 0.6875 0.6875 -v 0.3125 0.6875 0.4375 -v 0.3125 0 0.6875 -v 0.3125 0 0.4375 -v 0.0625 0.6875 0.4375 -v 0.0625 0.6875 0.6875 -v 0.0625 0 0.4375 -v 0.0625 0 0.6875 -vt 0.8125 0.609375 -vt 0.875 0.609375 -vt 0.875 0.4375 -vt 0.8125 0.4375 -vt 0.75 0.609375 -vt 0.8125 0.609375 -vt 0.8125 0.4375 -vt 0.75 0.4375 -vt 0.9375 0.609375 -vt 1 0.609375 -vt 1 0.4375 -vt 0.9375 0.4375 -vt 0.875 0.609375 -vt 0.9375 0.609375 -vt 0.9375 0.4375 -vt 0.875 0.4375 -vt 0.875 0.609375 -vt 0.8125 0.609375 -vt 0.8125 0.671875 -vt 0.875 0.671875 -vt 0.9375 0.671875 -vt 0.875 0.671875 -vt 0.875 0.609375 -vt 0.9375 0.609375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o Leg3A -v -0.0625 0.6875 -0.4375 -v -0.0625 0.6875 -0.6875 -v -0.0625 0 -0.4375 -v -0.0625 0 -0.6875 -v -0.3125 0.6875 -0.6875 -v -0.3125 0.6875 -0.4375 -v -0.3125 0 -0.6875 -v -0.3125 0 -0.4375 -vt 0.875 0.609375 -vt 0.8125 0.609375 -vt 0.8125 0.4375 -vt 0.875 0.4375 -vt 0.9375 0.609375 -vt 0.875 0.609375 -vt 0.875 0.4375 -vt 0.9375 0.4375 -vt 1 0.609375 -vt 0.9375 0.609375 -vt 0.9375 0.4375 -vt 1 0.4375 -vt 0.8125 0.609375 -vt 0.75 0.609375 -vt 0.75 0.4375 -vt 0.8125 0.4375 -vt 0.8125 0.609375 -vt 0.875 0.609375 -vt 0.875 0.671875 -vt 0.8125 0.671875 -vt 0.875 0.671875 -vt 0.9375 0.671875 -vt 0.9375 0.609375 -vt 0.875 0.609375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o Leg4A -v 0.3125 0.6875 -0.4375 -v 0.3125 0.6875 -0.6875 -v 0.3125 0 -0.4375 -v 0.3125 0 -0.6875 -v 0.0625 0.6875 -0.6875 -v 0.0625 0.6875 -0.4375 -v 0.0625 0 -0.6875 -v 0.0625 0 -0.4375 -vt 0.8125 0.609375 -vt 0.875 0.609375 -vt 0.875 0.4375 -vt 0.8125 0.4375 -vt 0.75 0.609375 -vt 0.8125 0.609375 -vt 0.8125 0.4375 -vt 0.75 0.4375 -vt 0.9375 0.609375 -vt 1 0.609375 -vt 1 0.4375 -vt 0.9375 0.4375 -vt 0.875 0.609375 -vt 0.9375 0.609375 -vt 0.9375 0.4375 -vt 0.875 0.4375 -vt 0.875 0.609375 -vt 0.8125 0.609375 -vt 0.8125 0.671875 -vt 0.875 0.671875 -vt 0.9375 0.671875 -vt 0.875 0.671875 -vt 0.875 0.609375 -vt 0.9375 0.609375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o Head -v 0.1875 2.051882938682637 -0.7896234122634724 -v 0.1875 1.833132938682637 -1.1685095264191645 -v 0.1875 1.78125 -0.6333734122634727 -v 0.1875 1.5625 -1.0122595264191645 -v -0.1875 1.833132938682637 -1.1685095264191645 -v -0.1875 2.051882938682637 -0.7896234122634724 -v -0.1875 1.5625 -1.0122595264191645 -v -0.1875 1.78125 -0.6333734122634727 -vt 0.109375 0.6875 -vt 0.203125 0.6875 -vt 0.203125 0.609375 -vt 0.109375 0.609375 -vt 0 0.6875 -vt 0.109375 0.6875 -vt 0.109375 0.609375 -vt 0 0.609375 -vt 0.3125 0.6875 -vt 0.40625 0.6875 -vt 0.40625 0.609375 -vt 0.3125 0.609375 -vt 0.203125 0.6875 -vt 0.3125 0.6875 -vt 0.3125 0.609375 -vt 0.203125 0.609375 -vt 0.203125 0.6875 -vt 0.109375 0.6875 -vt 0.109375 0.796875 -vt 0.203125 0.796875 -vt 0.296875 0.796875 -vt 0.203125 0.796875 -vt 0.203125 0.6875 -vt 0.296875 0.6875 -vn 0 -0.49999999999999994 -0.8660254037844387 -vn 1 0 0 -vn 0 0.49999999999999994 0.8660254037844387 -vn -1 0 0 -vn 0 0.8660254037844387 -0.49999999999999994 -vn 0 -0.8660254037844387 0.49999999999999994 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o UMouth -v 0.125 1.833132938682637 -1.1685095264191645 -v 0.125 1.676882938682637 -1.4391424651018014 -v 0.125 1.5625 -1.0122595264191645 -v 0.125 1.40625 -1.2828924651018019 -v -0.125 1.676882938682637 -1.4391424651018014 -v -0.125 1.833132938682637 -1.1685095264191645 -v -0.125 1.40625 -1.2828924651018019 -v -0.125 1.5625 -1.0122595264191645 -vt 0.078125 0.53125 -vt 0.140625 0.53125 -vt 0.140625 0.453125 -vt 0.078125 0.453125 -vt 0 0.53125 -vt 0.078125 0.53125 -vt 0.078125 0.453125 -vt 0 0.453125 -vt 0.21875 0.53125 -vt 0.28125 0.53125 -vt 0.28125 0.453125 -vt 0.21875 0.453125 -vt 0.140625 0.53125 -vt 0.21875 0.53125 -vt 0.21875 0.453125 -vt 0.140625 0.453125 -vt 0.140625 0.53125 -vt 0.078125 0.53125 -vt 0.078125 0.609375 -vt 0.140625 0.609375 -vt 0.203125 0.609375 -vt 0.140625 0.609375 -vt 0.140625 0.53125 -vt 0.203125 0.53125 -vn 0 -0.49999999999999994 -0.8660254037844387 -vn 1 0 0 -vn 0 0.49999999999999994 0.8660254037844387 -vn -1 0 0 -vn 0 0.8660254037844387 -0.49999999999999994 -vn 0 -0.8660254037844387 0.49999999999999994 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o Ear1 -v -0.06465012057680164 2.1600077984998522 -0.8465349149312555 -v -0.06192650361593727 2.1288767141844853 -0.9006615026677829 -v -0.050497791707081574 1.9982459393130734 -0.7527849149312555 -v -0.04777417474621726 1.9671148549977064 -0.8069115026677829 -v -0.1864508408774055 2.117982246341028 -0.9006615026677829 -v -0.1891744578382698 2.149113330656395 -0.8465349149312555 -v -0.17229851200768548 1.9562203871542492 -0.8069115026677829 -v -0.1750221289685498 1.987351471469616 -0.7527849149312555 -vt 0.34375 0.734375 -vt 0.3125 0.734375 -vt 0.3125 0.6875 -vt 0.34375 0.6875 -vt 0.359375 0.734375 -vt 0.34375 0.734375 -vt 0.34375 0.6875 -vt 0.359375 0.6875 -vt 0.390625 0.734375 -vt 0.359375 0.734375 -vt 0.359375 0.6875 -vt 0.390625 0.6875 -vt 0.3125 0.734375 -vt 0.296875 0.734375 -vt 0.296875 0.6875 -vt 0.3125 0.6875 -vt 0.3125 0.734375 -vt 0.34375 0.734375 -vt 0.34375 0.75 -vt 0.3125 0.75 -vt 0.34375 0.75 -vt 0.375 0.75 -vt 0.375 0.734375 -vt 0.34375 0.734375 -vn 0.0435778713738291 -0.4980973490458729 -0.8660254037844388 -vn 0.9961946980917455 0.0871557427476582 -1.3877787807814457e-17 -vn -0.0435778713738291 0.4980973490458729 0.8660254037844388 -vn -0.9961946980917455 -0.0871557427476582 1.3877787807814457e-17 -vn -0.07547908730517335 0.862729915662821 -0.5 -vn 0.07547908730517335 -0.862729915662821 0.5 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o Ear2 -v 0.1891744578382698 2.149113330656395 -0.8465349149312555 -v 0.1864508408774055 2.117982246341028 -0.9006615026677829 -v 0.17502212896854985 1.987351471469616 -0.7527849149312555 -v 0.17229851200768542 1.9562203871542492 -0.8069115026677829 -v 0.06192650361593732 2.1288767141844853 -0.9006615026677829 -v 0.06465012057680164 2.1600077984998522 -0.8465349149312555 -v 0.04777417474621726 1.9671148549977064 -0.8069115026677829 -v 0.050497791707081574 1.9982459393130734 -0.7527849149312555 -vt 0.3125 0.734375 -vt 0.34375 0.734375 -vt 0.34375 0.6875 -vt 0.3125 0.6875 -vt 0.296875 0.734375 -vt 0.3125 0.734375 -vt 0.3125 0.6875 -vt 0.296875 0.6875 -vt 0.359375 0.734375 -vt 0.390625 0.734375 -vt 0.390625 0.6875 -vt 0.359375 0.6875 -vt 0.34375 0.734375 -vt 0.359375 0.734375 -vt 0.359375 0.6875 -vt 0.34375 0.6875 -vt 0.34375 0.734375 -vt 0.3125 0.734375 -vt 0.3125 0.75 -vt 0.34375 0.75 -vt 0.375 0.75 -vt 0.34375 0.75 -vt 0.34375 0.734375 -vt 0.375 0.734375 -vn -0.0435778713738291 -0.4980973490458729 -0.8660254037844388 -vn 0.9961946980917455 -0.0871557427476582 1.3877787807814457e-17 -vn 0.0435778713738291 0.4980973490458729 0.8660254037844388 -vn -0.9961946980917455 0.0871557427476582 -1.3877787807814457e-17 -vn 0.07547908730517335 0.862729915662821 -0.5 -vn -0.07547908730517335 -0.862729915662821 0.5 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o MuleEarL -v -0.15935822581478865 2.3816773650616265 -0.9715349149312555 -v -0.15127013065533484 2.351492182990093 -1.0256615026677829 -v -0.061295283546407786 2.0157014821763357 -0.7527849149312555 -v -0.05320718838695404 1.9855163001048024 -0.8069115026677829 -v -0.27201085894146837 2.3191398023522782 -1.0256615026677829 -v -0.28009895410092217 2.3493249844238115 -0.9715349149312555 -v -0.1739479166730875 1.9531639194669874 -0.8069115026677829 -v -0.1820360118325413 1.9833491015385207 -0.7527849149312555 -vt 0.046875 0.796875 -vt 0.015625 0.796875 -vt 0.015625 0.6875 -vt 0.046875 0.6875 -vt 0.0625 0.796875 -vt 0.046875 0.796875 -vt 0.046875 0.6875 -vt 0.0625 0.6875 -vt 0.09375 0.796875 -vt 0.0625 0.796875 -vt 0.0625 0.6875 -vt 0.09375 0.6875 -vt 0.015625 0.796875 -vt 0 0.796875 -vt 0 0.6875 -vt 0.015625 0.6875 -vt 0.015625 0.796875 -vt 0.046875 0.796875 -vt 0.046875 0.8125 -vt 0.015625 0.8125 -vt 0.046875 0.8125 -vt 0.078125 0.8125 -vt 0.078125 0.796875 -vt 0.046875 0.796875 -vn 0.12940952255126037 -0.48296291314453416 -0.8660254037844387 -vn 0.9659258262890683 0.25881904510252074 1.3877787807814457e-17 -vn -0.12940952255126037 0.48296291314453416 0.8660254037844387 -vn -0.9659258262890683 -0.25881904510252074 -1.3877787807814457e-17 -vn -0.2241438680420134 0.8365163037378079 -0.5 -vn 0.2241438680420134 -0.8365163037378079 0.5 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 -o MuleEarR -v 0.2800989541009222 2.3493249844238115 -0.9715349149312555 -v 0.27201085894146837 2.3191398023522782 -1.0256615026677829 -v 0.18203601183254126 1.9833491015385207 -0.7527849149312555 -v 0.1739479166730875 1.9531639194669874 -0.8069115026677829 -v 0.1512701306553348 2.351492182990093 -1.0256615026677829 -v 0.15935822581478865 2.3816773650616265 -0.9715349149312555 -v 0.05320718838695404 1.9855163001048024 -0.8069115026677829 -v 0.061295283546407786 2.0157014821763357 -0.7527849149312555 -vt 0.015625 0.796875 -vt 0.046875 0.796875 -vt 0.046875 0.6875 -vt 0.015625 0.6875 -vt 0 0.796875 -vt 0.015625 0.796875 -vt 0.015625 0.6875 -vt 0 0.6875 -vt 0.0625 0.796875 -vt 0.09375 0.796875 -vt 0.09375 0.6875 -vt 0.0625 0.6875 -vt 0.046875 0.796875 -vt 0.0625 0.796875 -vt 0.0625 0.6875 -vt 0.046875 0.6875 -vt 0.046875 0.796875 -vt 0.015625 0.796875 -vt 0.015625 0.8125 -vt 0.046875 0.8125 -vt 0.078125 0.8125 -vt 0.046875 0.8125 -vt 0.046875 0.796875 -vt 0.078125 0.796875 -vn -0.12940952255126037 -0.48296291314453416 -0.8660254037844387 -vn 0.9659258262890683 -0.25881904510252074 -1.3877787807814457e-17 -vn 0.12940952255126037 0.48296291314453416 0.8660254037844387 -vn -0.9659258262890683 0.25881904510252074 1.3877787807814457e-17 -vn 0.2241438680420134 0.8365163037378079 -0.5 -vn -0.2241438680420134 -0.8365163037378079 0.5 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 92/268/67 95/267/67 93/266/67 90/265/67 -f 91/272/68 92/271/68 90/270/68 89/269/68 -f 96/276/69 91/275/69 89/274/69 94/273/69 -f 95/280/70 96/279/70 94/278/70 93/277/70 -f 94/284/71 89/283/71 90/282/71 93/281/71 -f 95/288/72 92/287/72 91/286/72 96/285/72 -o Neck -v 0.125 1.7828924651018019 -0.6272436490538904 -v 0.125 1.5641424651018019 -1.0061297632095823 -v 0.125 1.1333734122634724 -0.2522436490538904 -v 0.125 0.9146234122634727 -0.6311297632095825 -v -0.125 1.5641424651018019 -1.0061297632095823 -v -0.125 1.7828924651018019 -0.6272436490538904 -v -0.125 0.9146234122634727 -0.6311297632095825 -v -0.125 1.1333734122634724 -0.2522436490538904 -vt 0.109375 0.34375 -vt 0.171875 0.34375 -vt 0.171875 0.15625 -vt 0.109375 0.15625 -vt 0 0.34375 -vt 0.109375 0.34375 -vt 0.109375 0.15625 -vt 0 0.15625 -vt 0.28125 0.34375 -vt 0.34375 0.34375 -vt 0.34375 0.15625 -vt 0.28125 0.15625 -vt 0.171875 0.34375 -vt 0.28125 0.34375 -vt 0.28125 0.15625 -vt 0.171875 0.15625 -vt 0.171875 0.34375 -vt 0.109375 0.34375 -vt 0.109375 0.453125 -vt 0.171875 0.453125 -vt 0.234375 0.453125 -vt 0.171875 0.453125 -vt 0.171875 0.34375 -vt 0.234375 0.34375 -vn 0 -0.49999999999999994 -0.8660254037844387 -vn 1 0 0 -vn 0 0.49999999999999994 0.8660254037844387 -vn -1 0 0 -vn 0 0.8660254037844387 -0.49999999999999994 -vn 0 -0.8660254037844387 0.49999999999999994 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 100/292/73 103/291/73 101/290/73 98/289/73 -f 99/296/74 100/295/74 98/294/74 97/293/74 -f 104/300/75 99/299/75 97/298/75 102/297/75 -f 103/304/76 104/303/76 102/302/76 101/301/76 -f 102/308/77 97/307/77 98/306/77 101/305/77 -f 103/312/78 100/311/78 99/310/78 104/309/78 -o Mane -v 0.0625 2.1160254037844384 -0.6752404735808355 -v 0.0625 2.0535254037844384 -0.7834936490538902 -v 0.0625 1.25 -0.1752404735808355 -v 0.0625 1.1875 -0.2834936490538904 -v -0.0625 2.0535254037844384 -0.7834936490538902 -v -0.0625 2.1160254037844384 -0.6752404735808355 -v -0.0625 1.1875 -0.2834936490538904 -v -0.0625 1.25 -0.1752404735808355 -vt 0.90625 0.40625 -vt 0.9375 0.40625 -vt 0.9375 0.15625 -vt 0.90625 0.15625 -vt 0.875 0.40625 -vt 0.90625 0.40625 -vt 0.90625 0.15625 -vt 0.875 0.15625 -vt 0.96875 0.40625 -vt 1 0.40625 -vt 1 0.15625 -vt 0.96875 0.15625 -vt 0.9375 0.40625 -vt 0.96875 0.40625 -vt 0.96875 0.15625 -vt 0.9375 0.15625 -vt 0.9375 0.40625 -vt 0.90625 0.40625 -vt 0.90625 0.4375 -vt 0.9375 0.4375 -vt 0.96875 0.4375 -vt 0.9375 0.4375 -vt 0.9375 0.40625 -vt 0.96875 0.40625 -vn 0 -0.49999999999999994 -0.8660254037844387 -vn 1 0 0 -vn 0 0.49999999999999994 0.8660254037844387 -vn -1 0 0 -vn 0 0.8660254037844387 -0.49999999999999994 -vn 0 -0.8660254037844387 0.49999999999999994 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 108/316/79 111/315/79 109/314/79 106/313/79 -f 107/320/80 108/319/80 106/318/80 105/317/80 -f 112/324/81 107/323/81 105/322/81 110/321/81 -f 111/328/82 112/327/82 110/326/82 109/325/82 -f 110/332/83 105/331/83 106/330/83 109/329/83 -f 111/336/84 108/335/84 107/334/84 112/333/84 -o Bag1 -v 0.5 1.3125 0.125 -v 0.3125000000000001 1.3125 0.12499999999999989 -v 0.5 0.8125 0.125 -v 0.3125000000000001 0.8125 0.12499999999999989 -v 0.3125 1.3125 0.625 -v 0.5 1.3125 0.625 -v 0.3125 0.8125 0.625 -v 0.5 0.8125 0.625 -vt 0.453125 0.625 -vt 0.578125 0.625 -vt 0.578125 0.5 -vt 0.453125 0.5 -vt 0.40625 0.625 -vt 0.453125 0.625 -vt 0.453125 0.5 -vt 0.40625 0.5 -vt 0.625 0.625 -vt 0.75 0.625 -vt 0.75 0.5 -vt 0.625 0.5 -vt 0.578125 0.625 -vt 0.625 0.625 -vt 0.625 0.5 -vt 0.578125 0.5 -vt 0.578125 0.625 -vt 0.453125 0.625 -vt 0.453125 0.671875 -vt 0.578125 0.671875 -vt 0.703125 0.671875 -vt 0.578125 0.671875 -vt 0.578125 0.625 -vt 0.703125 0.625 -vn -1 0 -2.220446049250313e-16 -vn 2.220446049250313e-16 0 -1 -vn 1 0 2.220446049250313e-16 -vn -2.220446049250313e-16 0 1 -vn 0 1 0 -vn 0 -1 0 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 116/340/85 119/339/85 117/338/85 114/337/85 -f 115/344/86 116/343/86 114/342/86 113/341/86 -f 120/348/87 115/347/87 113/346/87 118/345/87 -f 119/352/88 120/351/88 118/350/88 117/349/88 -f 118/356/89 113/355/89 114/354/89 117/353/89 -f 119/360/90 116/359/90 115/358/90 120/357/90 -o Bag2 -v -0.5 1.3125 0.625 -v -0.3125 1.3125 0.625 -v -0.5 0.8125 0.625 -v -0.3125 0.8125 0.625 -v -0.3125000000000001 1.3125 0.12499999999999989 -v -0.5000000000000001 1.3125 0.125 -v -0.3125000000000001 0.8125 0.12499999999999989 -v -0.5000000000000001 0.8125 0.125 -vt 0.578125 0.625 -vt 0.453125 0.625 -vt 0.453125 0.5 -vt 0.578125 0.5 -vt 0.625 0.625 -vt 0.578125 0.625 -vt 0.578125 0.5 -vt 0.625 0.5 -vt 0.75 0.625 -vt 0.625 0.625 -vt 0.625 0.5 -vt 0.75 0.5 -vt 0.453125 0.625 -vt 0.40625 0.625 -vt 0.40625 0.5 -vt 0.453125 0.5 -vt 0.453125 0.625 -vt 0.578125 0.625 -vt 0.578125 0.671875 -vt 0.453125 0.671875 -vt 0.578125 0.671875 -vt 0.703125 0.671875 -vt 0.703125 0.625 -vt 0.578125 0.625 -vn 1 0 -2.220446049250313e-16 -vn 2.220446049250313e-16 0 1 -vn -1 0 2.220446049250313e-16 -vn -2.220446049250313e-16 0 -1 -vn 0 1 0 -vn 0 -1 0 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 124/364/91 127/363/91 125/362/91 122/361/91 -f 123/368/92 124/367/92 122/366/92 121/365/92 -f 128/372/93 123/371/93 121/370/93 126/369/93 -f 127/376/94 128/375/94 126/374/94 125/373/94 -f 126/380/95 121/379/95 122/378/95 125/377/95 -f 127/384/96 124/383/96 123/382/96 128/381/96 -o Saddle -v 0.34375 1.34375 0.375 -v 0.34375 1.34375 -0.25 -v 0.34375 0.71875 0.375 -v 0.34375 0.71875 -0.25 -v -0.34375 1.34375 -0.25 -v -0.34375 1.34375 0.375 -v -0.34375 0.71875 -0.25 -v -0.34375 0.71875 0.375 -vt 0.546875 0.859375 -vt 0.703125 0.859375 -vt 0.703125 0.71875 -vt 0.546875 0.71875 -vt 0.40625 0.859375 -vt 0.546875 0.859375 -vt 0.546875 0.71875 -vt 0.40625 0.71875 -vt 0.84375 0.859375 -vt 1 0.859375 -vt 1 0.71875 -vt 0.84375 0.71875 -vt 0.703125 0.859375 -vt 0.84375 0.859375 -vt 0.84375 0.71875 -vt 0.703125 0.71875 -vt 0.703125 0.859375 -vt 0.546875 0.859375 -vt 0.546875 1 -vt 0.703125 1 -vt 0.859375 1 -vt 0.703125 1 -vt 0.703125 0.859375 -vt 0.859375 0.859375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 132/388/97 135/387/97 133/386/97 130/385/97 -f 131/392/98 132/391/98 130/390/98 129/389/98 -f 136/396/99 131/395/99 129/394/99 134/393/99 -f 135/400/100 136/399/100 134/398/100 133/397/100 -f 134/404/101 129/403/101 130/402/101 133/401/101 -f 135/408/102 132/407/102 131/406/102 136/405/102 -o SaddleMouthL -v -0.125 1.6952722283113841 -1.1540063509461098 -v -0.125 1.6327722283113841 -1.2622595264191645 -v -0.125 1.587019052838329 -1.0915063509461098 -v -0.125 1.524519052838329 -1.1997595264191645 -v -0.1875 1.6327722283113841 -1.2622595264191645 -v -0.1875 1.6952722283113841 -1.1540063509461098 -v -0.1875 1.524519052838329 -1.1997595264191645 -v -0.1875 1.587019052838329 -1.0915063509461098 -vt 0.484375 0.890625 -vt 0.5 0.890625 -vt 0.5 0.859375 -vt 0.484375 0.859375 -vt 0.453125 0.890625 -vt 0.484375 0.890625 -vt 0.484375 0.859375 -vt 0.453125 0.859375 -vt 0.53125 0.890625 -vt 0.546875 0.890625 -vt 0.546875 0.859375 -vt 0.53125 0.859375 -vt 0.5 0.890625 -vt 0.53125 0.890625 -vt 0.53125 0.859375 -vt 0.5 0.859375 -vt 0.5 0.890625 -vt 0.484375 0.890625 -vt 0.484375 0.921875 -vt 0.5 0.921875 -vt 0.515625 0.921875 -vt 0.5 0.921875 -vt 0.5 0.890625 -vt 0.515625 0.890625 -vn 0 -0.49999999999999994 -0.8660254037844387 -vn 1 0 0 -vn 0 0.49999999999999994 0.8660254037844387 -vn -1 0 0 -vn 0 0.8660254037844387 -0.49999999999999994 -vn 0 -0.8660254037844387 0.49999999999999994 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 140/412/103 143/411/103 141/410/103 138/409/103 -f 139/416/104 140/415/104 138/414/104 137/413/104 -f 144/420/105 139/419/105 137/418/105 142/417/105 -f 143/424/106 144/423/106 142/422/106 141/421/106 -f 142/428/107 137/427/107 138/426/107 141/425/107 -f 143/432/108 140/431/108 139/430/108 144/429/108 -o SaddleMouthR -v 0.1875 1.6952722283113841 -1.1540063509461098 -v 0.1875 1.6327722283113841 -1.2622595264191645 -v 0.1875 1.587019052838329 -1.0915063509461098 -v 0.1875 1.524519052838329 -1.1997595264191645 -v 0.125 1.6327722283113841 -1.2622595264191645 -v 0.125 1.6952722283113841 -1.1540063509461098 -v 0.125 1.524519052838329 -1.1997595264191645 -v 0.125 1.587019052838329 -1.0915063509461098 -vt 0.484375 0.890625 -vt 0.5 0.890625 -vt 0.5 0.859375 -vt 0.484375 0.859375 -vt 0.453125 0.890625 -vt 0.484375 0.890625 -vt 0.484375 0.859375 -vt 0.453125 0.859375 -vt 0.53125 0.890625 -vt 0.546875 0.890625 -vt 0.546875 0.859375 -vt 0.53125 0.859375 -vt 0.5 0.890625 -vt 0.53125 0.890625 -vt 0.53125 0.859375 -vt 0.5 0.859375 -vt 0.5 0.890625 -vt 0.484375 0.890625 -vt 0.484375 0.921875 -vt 0.5 0.921875 -vt 0.515625 0.921875 -vt 0.5 0.921875 -vt 0.5 0.890625 -vt 0.515625 0.890625 -vn 0 -0.49999999999999994 -0.8660254037844387 -vn 1 0 0 -vn 0 0.49999999999999994 0.8660254037844387 -vn -1 0 0 -vn 0 0.8660254037844387 -0.49999999999999994 -vn 0 -0.8660254037844387 0.49999999999999994 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 148/436/109 151/435/109 149/434/109 146/433/109 -f 147/440/110 148/439/110 146/438/110 145/437/110 -f 152/444/111 147/443/111 145/442/111 150/441/111 -f 151/448/112 152/447/112 150/446/112 149/445/112 -f 150/452/113 145/451/113 146/450/113 149/449/113 -f 151/456/114 148/455/114 147/454/114 152/453/114 -o SaddleMouthLine -v -0.19374999999999998 1.6875 -0.21875 -v -0.19374999999999998 1.6875 -1.21875 -v -0.19374999999999998 1.5 -0.21875 -v -0.19374999999999998 1.5 -1.21875 -v -0.19374999999999998 1.6875 -1.21875 -v -0.19374999999999998 1.6875 -0.21875 -v -0.19374999999999998 1.5 -1.21875 -v -0.19374999999999998 1.5 -0.21875 -vt 0.75 0.71875 -vt 0.75 0.71875 -vt 0.75 0.671875 -vt 0.75 0.671875 -vt 0.5 0.71875 -vt 0.75 0.71875 -vt 0.75 0.671875 -vt 0.5 0.671875 -vt 1 0.71875 -vt 1 0.71875 -vt 1 0.671875 -vt 1 0.671875 -vt 0.75 0.71875 -vt 1 0.71875 -vt 1 0.671875 -vt 0.75 0.671875 -vt 0.75 0.71875 -vt 0.75 0.71875 -vt 0.75 0.96875 -vt 0.75 0.96875 -vt 0.75 0.96875 -vt 0.75 0.96875 -vt 0.75 0.71875 -vt 0.75 0.71875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 156/460/115 159/459/115 157/458/115 154/457/115 -f 155/464/116 156/463/116 154/462/116 153/461/116 -f 160/468/117 155/467/117 153/466/117 158/465/117 -f 159/472/118 160/471/118 158/470/118 157/469/118 -f 158/476/119 153/475/119 154/474/119 157/473/119 -f 159/480/120 156/479/120 155/478/120 160/477/120 -o SaddleMouthLineR -v 0.19374999999999998 1.6875 -0.21875 -v 0.19374999999999998 1.6875 -1.21875 -v 0.19374999999999998 1.5 -0.21875 -v 0.19374999999999998 1.5 -1.21875 -v 0.19374999999999998 1.6875 -1.21875 -v 0.19374999999999998 1.6875 -0.21875 -v 0.19374999999999998 1.5 -1.21875 -v 0.19374999999999998 1.5 -0.21875 -vt 0.75 0.71875 -vt 0.75 0.71875 -vt 0.75 0.671875 -vt 0.75 0.671875 -vt 0.5 0.71875 -vt 0.75 0.71875 -vt 0.75 0.671875 -vt 0.5 0.671875 -vt 1 0.71875 -vt 1 0.71875 -vt 1 0.671875 -vt 1 0.671875 -vt 0.75 0.71875 -vt 1 0.71875 -vt 1 0.671875 -vt 0.75 0.671875 -vt 0.75 0.71875 -vt 0.75 0.71875 -vt 0.75 0.96875 -vt 0.75 0.96875 -vt 0.75 0.96875 -vt 0.75 0.96875 -vt 0.75 0.71875 -vt 0.75 0.71875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 164/484/121 167/483/121 165/482/121 162/481/121 -f 163/488/122 164/487/122 162/486/122 161/485/122 -f 168/492/123 163/491/123 161/490/123 166/489/123 -f 167/496/124 168/495/124 166/494/124 165/493/124 -f 166/500/125 161/499/125 162/498/125 165/497/125 -f 167/504/126 164/503/126 163/502/126 168/501/126 -o HeadSaddle -v 0.140625 1.8561195507185708 -1.1566606162754502 -v 0.140625 1.7779945507185708 -1.291977085616769 -v 0.140625 1.5584233181676694 -0.9847856162754505 -v 0.140625 1.4802983181676697 -1.120102085616769 -v -0.140625 1.7779945507185708 -1.291977085616769 -v -0.140625 1.8561195507185708 -1.1566606162754502 -v -0.140625 1.4802983181676697 -1.120102085616769 -v -0.140625 1.5584233181676694 -0.9847856162754505 -vt 0.328125 0.96875 -vt 0.390625 0.96875 -vt 0.390625 0.890625 -vt 0.328125 0.890625 -vt 0.296875 0.96875 -vt 0.328125 0.96875 -vt 0.328125 0.890625 -vt 0.296875 0.890625 -vt 0.421875 0.96875 -vt 0.484375 0.96875 -vt 0.484375 0.890625 -vt 0.421875 0.890625 -vt 0.390625 0.96875 -vt 0.421875 0.96875 -vt 0.421875 0.890625 -vt 0.390625 0.890625 -vt 0.390625 0.96875 -vt 0.328125 0.96875 -vt 0.328125 1 -vt 0.390625 1 -vt 0.453125 1 -vt 0.390625 1 -vt 0.390625 0.96875 -vt 0.453125 0.96875 -vn 0 -0.49999999999999994 -0.8660254037844387 -vn 1 0 0 -vn 0 0.49999999999999994 0.8660254037844387 -vn -1 0 0 -vn 0 0.8660254037844387 -0.49999999999999994 -vn 0 -0.8660254037844387 0.49999999999999994 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 172/508/127 175/507/127 173/506/127 170/505/127 -f 171/512/128 172/511/128 170/510/128 169/509/128 -f 176/516/129 171/515/129 169/514/129 174/513/129 -f 175/520/130 176/519/130 174/518/130 173/517/130 -f 174/524/131 169/523/131 170/522/131 173/521/131 -f 175/528/132 172/527/132 171/526/132 176/525/132 -o HeadSaddle -v 0.203125 2.074869550718571 -0.7777745021197584 -v 0.203125 1.8404945507185708 -1.183723910143714 -v 0.203125 1.7771733181676694 -0.6058995021197586 -v 0.203125 1.5427983181676694 -1.0118489101437143 -v -0.203125 1.8404945507185708 -1.183723910143714 -v -0.203125 2.074869550718571 -0.7777745021197584 -v -0.203125 1.5427983181676694 -1.0118489101437143 -v -0.203125 1.7771733181676694 -0.6058995021197586 -vt 0.109375 0.890625 -vt 0.203125 0.890625 -vt 0.203125 0.8125 -vt 0.109375 0.8125 -vt 0 0.890625 -vt 0.109375 0.890625 -vt 0.109375 0.8125 -vt 0 0.8125 -vt 0.3125 0.890625 -vt 0.40625 0.890625 -vt 0.40625 0.8125 -vt 0.3125 0.8125 -vt 0.203125 0.890625 -vt 0.3125 0.890625 -vt 0.3125 0.8125 -vt 0.203125 0.8125 -vt 0.203125 0.890625 -vt 0.109375 0.890625 -vt 0.109375 1 -vt 0.203125 1 -vt 0.296875 1 -vt 0.203125 1 -vt 0.203125 0.890625 -vt 0.296875 0.890625 -vn 0 -0.49999999999999994 -0.8660254037844387 -vn 1 0 0 -vn 0 0.49999999999999994 0.8660254037844387 -vn -1 0 0 -vn 0 0.8660254037844387 -0.49999999999999994 -vn 0 -0.8660254037844387 0.49999999999999994 -usemtl m_1e01f934-e3cf-9457-589b-e2903555a409 -f 180/532/133 183/531/133 181/530/133 178/529/133 -f 179/536/134 180/535/134 178/534/134 177/533/134 -f 184/540/135 179/539/135 177/538/135 182/537/135 -f 183/544/136 184/543/136 182/542/136 181/541/136 -f 182/548/137 177/547/137 178/546/137 181/545/137 -f 183/552/138 180/551/138 179/550/138 184/549/138 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/llama.obj b/renderer/viewer/three/entity/models/llama.obj deleted file mode 100644 index 1ef48ac5d..000000000 --- a/renderer/viewer/three/entity/models/llama.obj +++ /dev/null @@ -1,509 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o head -v 0.125 1.9375 -0.4375 -v 0.125 1.9375 -1 -v 0.125 1.6875 -0.4375 -v 0.125 1.6875 -1 -v -0.125 1.9375 -1 -v -0.125 1.9375 -0.4375 -v -0.125 1.6875 -1 -v -0.125 1.6875 -0.4375 -vt 0.0703125 0.859375 -vt 0.1015625 0.859375 -vt 0.1015625 0.796875 -vt 0.0703125 0.796875 -vt 0 0.859375 -vt 0.0703125 0.859375 -vt 0.0703125 0.796875 -vt 0 0.796875 -vt 0.171875 0.859375 -vt 0.203125 0.859375 -vt 0.203125 0.796875 -vt 0.171875 0.796875 -vt 0.1015625 0.859375 -vt 0.171875 0.859375 -vt 0.171875 0.796875 -vt 0.1015625 0.796875 -vt 0.1015625 0.859375 -vt 0.0703125 0.859375 -vt 0.0703125 1 -vt 0.1015625 1 -vt 0.1328125 1 -vt 0.1015625 1 -vt 0.1015625 0.859375 -vt 0.1328125 0.859375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c2c1ddb5-5693-7a64-a950-f7fec476ea98 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o head -v 0.25 2.0625 -0.375 -v 0.25 2.0625 -0.75 -v 0.25 0.9375 -0.375 -v 0.25 0.9375 -0.75 -v -0.25 2.0625 -0.75 -v -0.25 2.0625 -0.375 -v -0.25 0.9375 -0.75 -v -0.25 0.9375 -0.375 -vt 0.046875 0.6875 -vt 0.109375 0.6875 -vt 0.109375 0.40625 -vt 0.046875 0.40625 -vt 0 0.6875 -vt 0.046875 0.6875 -vt 0.046875 0.40625 -vt 0 0.40625 -vt 0.15625 0.6875 -vt 0.21875 0.6875 -vt 0.21875 0.40625 -vt 0.15625 0.40625 -vt 0.109375 0.6875 -vt 0.15625 0.6875 -vt 0.15625 0.40625 -vt 0.109375 0.40625 -vt 0.109375 0.6875 -vt 0.046875 0.6875 -vt 0.046875 0.78125 -vt 0.109375 0.78125 -vt 0.171875 0.78125 -vt 0.109375 0.78125 -vt 0.109375 0.6875 -vt 0.171875 0.6875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c2c1ddb5-5693-7a64-a950-f7fec476ea98 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o head -v 0.25 2.25 -0.5 -v 0.25 2.25 -0.625 -v 0.25 2.0625 -0.5 -v 0.25 2.0625 -0.625 -v 0.0625 2.25 -0.625 -v 0.0625 2.25 -0.5 -v 0.0625 2.0625 -0.625 -v 0.0625 2.0625 -0.5 -vt 0.1484375 0.96875 -vt 0.171875 0.96875 -vt 0.171875 0.921875 -vt 0.1484375 0.921875 -vt 0.1328125 0.96875 -vt 0.1484375 0.96875 -vt 0.1484375 0.921875 -vt 0.1328125 0.921875 -vt 0.1875 0.96875 -vt 0.2109375 0.96875 -vt 0.2109375 0.921875 -vt 0.1875 0.921875 -vt 0.171875 0.96875 -vt 0.1875 0.96875 -vt 0.1875 0.921875 -vt 0.171875 0.921875 -vt 0.171875 0.96875 -vt 0.1484375 0.96875 -vt 0.1484375 1 -vt 0.171875 1 -vt 0.1953125 1 -vt 0.171875 1 -vt 0.171875 0.96875 -vt 0.1953125 0.96875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c2c1ddb5-5693-7a64-a950-f7fec476ea98 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o head -v -0.0625 2.25 -0.5 -v -0.0625 2.25 -0.625 -v -0.0625 2.0625 -0.5 -v -0.0625 2.0625 -0.625 -v -0.25 2.25 -0.625 -v -0.25 2.25 -0.5 -v -0.25 2.0625 -0.625 -v -0.25 2.0625 -0.5 -vt 0.1484375 0.96875 -vt 0.171875 0.96875 -vt 0.171875 0.921875 -vt 0.1484375 0.921875 -vt 0.1328125 0.96875 -vt 0.1484375 0.96875 -vt 0.1484375 0.921875 -vt 0.1328125 0.921875 -vt 0.1875 0.96875 -vt 0.2109375 0.96875 -vt 0.2109375 0.921875 -vt 0.1875 0.921875 -vt 0.171875 0.96875 -vt 0.1875 0.96875 -vt 0.1875 0.921875 -vt 0.171875 0.921875 -vt 0.171875 0.96875 -vt 0.1484375 0.96875 -vt 0.1484375 1 -vt 0.171875 1 -vt 0.1953125 1 -vt 0.171875 1 -vt 0.171875 0.96875 -vt 0.1953125 0.96875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c2c1ddb5-5693-7a64-a950-f7fec476ea98 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o chest1 -v 0.34375 1.3125 0.3750000000000001 -v 0.53125 1.3125 0.375 -v 0.34375 0.8125 0.3750000000000001 -v 0.53125 0.8125 0.375 -v 0.53125 1.3125 -0.12499999999999994 -v 0.34375 1.3125 -0.12499999999999989 -v 0.53125 0.8125 -0.12499999999999994 -v 0.34375 0.8125 -0.12499999999999989 -vt 0.375 0.515625 -vt 0.4375 0.515625 -vt 0.4375 0.390625 -vt 0.375 0.390625 -vt 0.3515625 0.515625 -vt 0.375 0.515625 -vt 0.375 0.390625 -vt 0.3515625 0.390625 -vt 0.4609375 0.515625 -vt 0.5234375 0.515625 -vt 0.5234375 0.390625 -vt 0.4609375 0.390625 -vt 0.4375 0.515625 -vt 0.4609375 0.515625 -vt 0.4609375 0.390625 -vt 0.4375 0.390625 -vt 0.4375 0.515625 -vt 0.375 0.515625 -vt 0.375 0.5625 -vt 0.4375 0.5625 -vt 0.5 0.5625 -vt 0.4375 0.5625 -vt 0.4375 0.515625 -vt 0.5 0.515625 -vn 1 0 -2.220446049250313e-16 -vn 2.220446049250313e-16 0 1 -vn -1 0 2.220446049250313e-16 -vn -2.220446049250313e-16 0 -1 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c2c1ddb5-5693-7a64-a950-f7fec476ea98 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o chest2 -v -0.53125 1.3125 0.3750000000000001 -v -0.34374999999999994 1.3125 0.375 -v -0.53125 0.8125 0.3750000000000001 -v -0.34374999999999994 0.8125 0.375 -v -0.34375000000000006 1.3125 -0.125 -v -0.5312500000000001 1.3125 -0.12499999999999989 -v -0.34375000000000006 0.8125 -0.125 -v -0.5312500000000001 0.8125 -0.12499999999999989 -vt 0.375 0.3125 -vt 0.4375 0.3125 -vt 0.4375 0.1875 -vt 0.375 0.1875 -vt 0.3515625 0.3125 -vt 0.375 0.3125 -vt 0.375 0.1875 -vt 0.3515625 0.1875 -vt 0.4609375 0.3125 -vt 0.5234375 0.3125 -vt 0.5234375 0.1875 -vt 0.4609375 0.1875 -vt 0.4375 0.3125 -vt 0.4609375 0.3125 -vt 0.4609375 0.1875 -vt 0.4375 0.1875 -vt 0.4375 0.3125 -vt 0.375 0.3125 -vt 0.375 0.359375 -vt 0.4375 0.359375 -vt 0.5 0.359375 -vt 0.4375 0.359375 -vt 0.4375 0.3125 -vt 0.5 0.3125 -vn 1 0 -2.220446049250313e-16 -vn 2.220446049250313e-16 0 1 -vn -1 0 2.220446049250313e-16 -vn -2.220446049250313e-16 0 -1 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c2c1ddb5-5693-7a64-a950-f7fec476ea98 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o body -v 0.375 1.3750000000000002 -0.5 -v 0.375 0.7500000000000002 -0.5 -v 0.375 1.375 0.625 -v 0.375 0.75 0.625 -v -0.375 0.7500000000000002 -0.5 -v -0.375 1.3750000000000002 -0.5 -v -0.375 0.75 0.625 -v -0.375 1.375 0.625 -vt 0.3046875 0.84375 -vt 0.3984375 0.84375 -vt 0.3984375 0.5625 -vt 0.3046875 0.5625 -vt 0.2265625 0.84375 -vt 0.3046875 0.84375 -vt 0.3046875 0.5625 -vt 0.2265625 0.5625 -vt 0.4765625 0.84375 -vt 0.5703125 0.84375 -vt 0.5703125 0.5625 -vt 0.4765625 0.5625 -vt 0.3984375 0.84375 -vt 0.4765625 0.84375 -vt 0.4765625 0.5625 -vt 0.3984375 0.5625 -vt 0.3984375 0.84375 -vt 0.3046875 0.84375 -vt 0.3046875 1 -vt 0.3984375 1 -vt 0.4921875 1 -vt 0.3984375 1 -vt 0.3984375 0.84375 -vt 0.4921875 0.84375 -vn 0 -1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 -1 -vn 0 -2.220446049250313e-16 1 -usemtl m_c2c1ddb5-5693-7a64-a950-f7fec476ea98 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o leg0 -v 0.34375 0.875 0.5 -v 0.34375 0.875 0.25 -v 0.34375 0 0.5 -v 0.34375 0 0.25 -v 0.09375 0.875 0.25 -v 0.09375 0.875 0.5 -v 0.09375 0 0.25 -v 0.09375 0 0.5 -vt 0.2578125 0.484375 -vt 0.2890625 0.484375 -vt 0.2890625 0.265625 -vt 0.2578125 0.265625 -vt 0.2265625 0.484375 -vt 0.2578125 0.484375 -vt 0.2578125 0.265625 -vt 0.2265625 0.265625 -vt 0.3203125 0.484375 -vt 0.3515625 0.484375 -vt 0.3515625 0.265625 -vt 0.3203125 0.265625 -vt 0.2890625 0.484375 -vt 0.3203125 0.484375 -vt 0.3203125 0.265625 -vt 0.2890625 0.265625 -vt 0.2890625 0.484375 -vt 0.2578125 0.484375 -vt 0.2578125 0.546875 -vt 0.2890625 0.546875 -vt 0.3203125 0.546875 -vt 0.2890625 0.546875 -vt 0.2890625 0.484375 -vt 0.3203125 0.484375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c2c1ddb5-5693-7a64-a950-f7fec476ea98 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o leg1 -v -0.09375 0.875 0.5 -v -0.09375 0.875 0.25 -v -0.09375 0 0.5 -v -0.09375 0 0.25 -v -0.34375 0.875 0.25 -v -0.34375 0.875 0.5 -v -0.34375 0 0.25 -v -0.34375 0 0.5 -vt 0.2578125 0.484375 -vt 0.2890625 0.484375 -vt 0.2890625 0.265625 -vt 0.2578125 0.265625 -vt 0.2265625 0.484375 -vt 0.2578125 0.484375 -vt 0.2578125 0.265625 -vt 0.2265625 0.265625 -vt 0.3203125 0.484375 -vt 0.3515625 0.484375 -vt 0.3515625 0.265625 -vt 0.3203125 0.265625 -vt 0.2890625 0.484375 -vt 0.3203125 0.484375 -vt 0.3203125 0.265625 -vt 0.2890625 0.265625 -vt 0.2890625 0.484375 -vt 0.2578125 0.484375 -vt 0.2578125 0.546875 -vt 0.2890625 0.546875 -vt 0.3203125 0.546875 -vt 0.2890625 0.546875 -vt 0.2890625 0.484375 -vt 0.3203125 0.484375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c2c1ddb5-5693-7a64-a950-f7fec476ea98 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o leg2 -v 0.34375 0.875 -0.1875 -v 0.34375 0.875 -0.4375 -v 0.34375 0 -0.1875 -v 0.34375 0 -0.4375 -v 0.09375 0.875 -0.4375 -v 0.09375 0.875 -0.1875 -v 0.09375 0 -0.4375 -v 0.09375 0 -0.1875 -vt 0.2578125 0.484375 -vt 0.2890625 0.484375 -vt 0.2890625 0.265625 -vt 0.2578125 0.265625 -vt 0.2265625 0.484375 -vt 0.2578125 0.484375 -vt 0.2578125 0.265625 -vt 0.2265625 0.265625 -vt 0.3203125 0.484375 -vt 0.3515625 0.484375 -vt 0.3515625 0.265625 -vt 0.3203125 0.265625 -vt 0.2890625 0.484375 -vt 0.3203125 0.484375 -vt 0.3203125 0.265625 -vt 0.2890625 0.265625 -vt 0.2890625 0.484375 -vt 0.2578125 0.484375 -vt 0.2578125 0.546875 -vt 0.2890625 0.546875 -vt 0.3203125 0.546875 -vt 0.2890625 0.546875 -vt 0.2890625 0.484375 -vt 0.3203125 0.484375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c2c1ddb5-5693-7a64-a950-f7fec476ea98 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o leg3 -v -0.09375 0.875 -0.1875 -v -0.09375 0.875 -0.4375 -v -0.09375 0 -0.1875 -v -0.09375 0 -0.4375 -v -0.34375 0.875 -0.4375 -v -0.34375 0.875 -0.1875 -v -0.34375 0 -0.4375 -v -0.34375 0 -0.1875 -vt 0.2578125 0.484375 -vt 0.2890625 0.484375 -vt 0.2890625 0.265625 -vt 0.2578125 0.265625 -vt 0.2265625 0.484375 -vt 0.2578125 0.484375 -vt 0.2578125 0.265625 -vt 0.2265625 0.265625 -vt 0.3203125 0.484375 -vt 0.3515625 0.484375 -vt 0.3515625 0.265625 -vt 0.3203125 0.265625 -vt 0.2890625 0.484375 -vt 0.3203125 0.484375 -vt 0.3203125 0.265625 -vt 0.2890625 0.265625 -vt 0.2890625 0.484375 -vt 0.2578125 0.484375 -vt 0.2578125 0.546875 -vt 0.2890625 0.546875 -vt 0.3203125 0.546875 -vt 0.2890625 0.546875 -vt 0.2890625 0.484375 -vt 0.3203125 0.484375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c2c1ddb5-5693-7a64-a950-f7fec476ea98 -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/minecart.obj b/renderer/viewer/three/entity/models/minecart.obj deleted file mode 100644 index 0dd2f4c83..000000000 --- a/renderer/viewer/three/entity/models/minecart.obj +++ /dev/null @@ -1,233 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o bottom -v 0.625 0.12500000000000022 -0.5000000000000002 -v 0.625 2.220446049250313e-16 -0.5000000000000002 -v 0.625 0.125 0.4999999999999998 -v 0.625 0 0.4999999999999998 -v -0.625 2.220446049250313e-16 -0.5000000000000002 -v -0.625 0.12500000000000022 -0.5000000000000002 -v -0.625 0 0.4999999999999998 -v -0.625 0.125 0.4999999999999998 -vt 0.34375 0.625 -vt 0.03125 0.625 -vt 0.03125 0.125 -vt 0.34375 0.125 -vt 0.375 0.625 -vt 0.34375 0.625 -vt 0.34375 0.125 -vt 0.375 0.125 -vt 0.6875 0.625 -vt 0.375 0.625 -vt 0.375 0.125 -vt 0.6875 0.125 -vt 0.03125 0.625 -vt 0 0.625 -vt 0 0.125 -vt 0.03125 0.125 -vt 0.03125 0.625 -vt 0.34375 0.625 -vt 0.34375 0.6875 -vt 0.03125 0.6875 -vt 0.34375 0.6875 -vt 0.65625 0.6875 -vt 0.65625 0.625 -vt 0.34375 0.625 -vn 0 -1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 -1 -vn 0 -2.220446049250313e-16 1 -usemtl m_51fd1571-03b7-0fcd-9442-72fc6c7ce0a3 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o front -v 0.625 0.625 -0.5 -v 0.5 0.625 -0.5 -v 0.625 0.125 -0.5 -v 0.5 0.125 -0.5 -v 0.4999999999999999 0.625 0.5 -v 0.625 0.625 0.5 -v 0.4999999999999999 0.125 0.5 -v 0.625 0.125 0.5 -vt 0.28125 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.6875 -vt 0.28125 0.6875 -vt 0.3125 0.9375 -vt 0.28125 0.9375 -vt 0.28125 0.6875 -vt 0.3125 0.6875 -vt 0.5625 0.9375 -vt 0.3125 0.9375 -vt 0.3125 0.6875 -vt 0.5625 0.6875 -vt 0.03125 0.9375 -vt 0 0.9375 -vt 0 0.6875 -vt 0.03125 0.6875 -vt 0.03125 0.9375 -vt 0.28125 0.9375 -vt 0.28125 1 -vt 0.03125 1 -vt 0.28125 1 -vt 0.53125 1 -vt 0.53125 0.9375 -vt 0.28125 0.9375 -vn -1 0 -2.220446049250313e-16 -vn 2.220446049250313e-16 0 -1 -vn 1 0 2.220446049250313e-16 -vn -2.220446049250313e-16 0 1 -vn 0 1 0 -vn 0 -1 0 -usemtl m_51fd1571-03b7-0fcd-9442-72fc6c7ce0a3 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o back -v -0.6249999999999999 0.625 0.5 -v -0.4999999999999999 0.625 0.5 -v -0.6249999999999999 0.125 0.5 -v -0.4999999999999999 0.125 0.5 -v -0.5000000000000001 0.625 -0.5 -v -0.6250000000000001 0.625 -0.5 -v -0.5000000000000001 0.125 -0.5 -v -0.6250000000000001 0.125 -0.5 -vt 0.28125 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.6875 -vt 0.28125 0.6875 -vt 0.3125 0.9375 -vt 0.28125 0.9375 -vt 0.28125 0.6875 -vt 0.3125 0.6875 -vt 0.5625 0.9375 -vt 0.3125 0.9375 -vt 0.3125 0.6875 -vt 0.5625 0.6875 -vt 0.03125 0.9375 -vt 0 0.9375 -vt 0 0.6875 -vt 0.03125 0.6875 -vt 0.03125 0.9375 -vt 0.28125 0.9375 -vt 0.28125 1 -vt 0.03125 1 -vt 0.28125 1 -vt 0.53125 1 -vt 0.53125 0.9375 -vt 0.28125 0.9375 -vn 1 0 -2.220446049250313e-16 -vn 2.220446049250313e-16 0 1 -vn -1 0 2.220446049250313e-16 -vn -2.220446049250313e-16 0 -1 -vn 0 1 0 -vn 0 -1 0 -usemtl m_51fd1571-03b7-0fcd-9442-72fc6c7ce0a3 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o right -v -0.49999999999999994 0.625 -0.5 -v -0.5000000000000001 0.625 -0.37500000000000006 -v -0.49999999999999994 0.125 -0.5 -v -0.5000000000000001 0.125 -0.37500000000000006 -v 0.5 0.625 -0.3749999999999999 -v 0.5 0.625 -0.49999999999999994 -v 0.5 0.125 -0.3749999999999999 -v 0.5 0.125 -0.49999999999999994 -vt 0.28125 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.6875 -vt 0.28125 0.6875 -vt 0.3125 0.9375 -vt 0.28125 0.9375 -vt 0.28125 0.6875 -vt 0.3125 0.6875 -vt 0.5625 0.9375 -vt 0.3125 0.9375 -vt 0.3125 0.6875 -vt 0.5625 0.6875 -vt 0.03125 0.9375 -vt 0 0.9375 -vt 0 0.6875 -vt 0.03125 0.6875 -vt 0.03125 0.9375 -vt 0.28125 0.9375 -vt 0.28125 1 -vt 0.03125 1 -vt 0.28125 1 -vt 0.53125 1 -vt 0.53125 0.9375 -vt 0.28125 0.9375 -vn -1.2246467991473532e-16 0 1 -vn -1 0 -1.2246467991473532e-16 -vn 1.2246467991473532e-16 0 -1 -vn 1 0 1.2246467991473532e-16 -vn 0 1 0 -vn 0 -1 0 -usemtl m_51fd1571-03b7-0fcd-9442-72fc6c7ce0a3 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o left -v 0.5 0.625 0.5 -v 0.5 0.625 0.375 -v 0.5 0.125 0.5 -v 0.5 0.125 0.375 -v -0.5 0.625 0.375 -v -0.5 0.625 0.5 -v -0.5 0.125 0.375 -v -0.5 0.125 0.5 -vt 0.28125 0.9375 -vt 0.03125 0.9375 -vt 0.03125 0.6875 -vt 0.28125 0.6875 -vt 0.3125 0.9375 -vt 0.28125 0.9375 -vt 0.28125 0.6875 -vt 0.3125 0.6875 -vt 0.5625 0.9375 -vt 0.3125 0.9375 -vt 0.3125 0.6875 -vt 0.5625 0.6875 -vt 0.03125 0.9375 -vt 0 0.9375 -vt 0 0.6875 -vt 0.03125 0.6875 -vt 0.03125 0.9375 -vt 0.28125 0.9375 -vt 0.28125 1 -vt 0.03125 1 -vt 0.28125 1 -vt 0.53125 1 -vt 0.53125 0.9375 -vt 0.28125 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_51fd1571-03b7-0fcd-9442-72fc6c7ce0a3 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/parrot.obj b/renderer/viewer/three/entity/models/parrot.obj deleted file mode 100644 index 35d14a5dc..000000000 --- a/renderer/viewer/three/entity/models/parrot.obj +++ /dev/null @@ -1,509 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.09375 0.5083704620381906 -0.10253364496531403 -v 0.09375 0.4291295379618094 -0.2724663550346859 -v 0.09375 0.16850504189944682 0.05594820318744831 -v 0.09375 0.08926411782306565 -0.11398450688192363 -v -0.09375 0.4291295379618094 -0.2724663550346859 -v -0.09375 0.5083704620381906 -0.10253364496531403 -v -0.09375 0.08926411782306565 -0.11398450688192363 -v -0.09375 0.16850504189944682 0.05594820318744831 -vt 0.15625 0.65625 -vt 0.25 0.65625 -vt 0.25 0.46875 -vt 0.15625 0.46875 -vt 0.0625 0.65625 -vt 0.15625 0.65625 -vt 0.15625 0.46875 -vt 0.0625 0.46875 -vt 0.34375 0.65625 -vt 0.4375 0.65625 -vt 0.4375 0.46875 -vt 0.34375 0.46875 -vt 0.25 0.65625 -vt 0.34375 0.65625 -vt 0.34375 0.46875 -vt 0.25 0.46875 -vt 0.25 0.65625 -vt 0.15625 0.65625 -vt 0.15625 0.75 -vt 0.25 0.75 -vt 0.34375 0.75 -vt 0.25 0.75 -vt 0.25 0.65625 -vt 0.34375 0.65625 -vn 0 -0.42261826174069944 -0.9063077870366499 -vn 1 0 0 -vn 0 0.42261826174069944 0.9063077870366499 -vn -1 0 0 -vn 0 0.9063077870366499 -0.42261826174069944 -vn 0 -0.9063077870366499 0.42261826174069944 -usemtl m_c341d2fe-028b-bd76-6b34-40c8c9b3653b -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o wing0 -v -0.0625 0.5051478245037531 -0.08881019196643142 -v -0.0625 0.3976022426879319 -0.24240120027061735 -v -0.0625 0.24916281066344315 0.09043244439327047 -v -0.0625 0.14161722884762196 -0.06315856391091551 -v -0.125 0.3976022426879319 -0.24240120027061735 -v -0.125 0.5051478245037531 -0.08881019196643142 -v -0.125 0.14161722884762196 -0.06315856391091551 -v -0.125 0.24916281066344315 0.09043244439327047 -vt 0.6875 0.65625 -vt 0.71875 0.65625 -vt 0.71875 0.5 -vt 0.6875 0.5 -vt 0.59375 0.65625 -vt 0.6875 0.65625 -vt 0.6875 0.5 -vt 0.59375 0.5 -vt 0.8125 0.65625 -vt 0.84375 0.65625 -vt 0.84375 0.5 -vt 0.8125 0.5 -vt 0.71875 0.65625 -vt 0.8125 0.65625 -vt 0.8125 0.5 -vt 0.71875 0.5 -vt 0.71875 0.65625 -vt 0.6875 0.65625 -vt 0.6875 0.75 -vt 0.71875 0.75 -vt 0.75 0.75 -vt 0.71875 0.75 -vt 0.71875 0.65625 -vt 0.75 0.65625 -vn 0 -0.5735764363510462 -0.8191520442889919 -vn 1 0 0 -vn 0 0.5735764363510462 0.8191520442889919 -vn -1 0 0 -vn 0 0.8191520442889919 -0.5735764363510462 -vn 0 -0.8191520442889919 0.5735764363510462 -usemtl m_c341d2fe-028b-bd76-6b34-40c8c9b3653b -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o wing1 -v 0.125 0.5051478245037531 -0.08881019196643142 -v 0.125 0.3976022426879319 -0.24240120027061735 -v 0.125 0.24916281066344315 0.09043244439327047 -v 0.125 0.14161722884762196 -0.06315856391091551 -v 0.0625 0.3976022426879319 -0.24240120027061735 -v 0.0625 0.5051478245037531 -0.08881019196643142 -v 0.0625 0.14161722884762196 -0.06315856391091551 -v 0.0625 0.24916281066344315 0.09043244439327047 -vt 0.6875 0.65625 -vt 0.71875 0.65625 -vt 0.71875 0.5 -vt 0.6875 0.5 -vt 0.59375 0.65625 -vt 0.6875 0.65625 -vt 0.6875 0.5 -vt 0.59375 0.5 -vt 0.8125 0.65625 -vt 0.84375 0.65625 -vt 0.84375 0.5 -vt 0.8125 0.5 -vt 0.71875 0.65625 -vt 0.8125 0.65625 -vt 0.8125 0.5 -vt 0.71875 0.5 -vt 0.71875 0.65625 -vt 0.6875 0.65625 -vt 0.6875 0.75 -vt 0.71875 0.75 -vt 0.75 0.75 -vt 0.71875 0.75 -vt 0.71875 0.65625 -vt 0.75 0.65625 -vn 0 -0.5735764363510462 -0.8191520442889919 -vn 1 0 0 -vn 0 0.5735764363510462 0.8191520442889919 -vn -1 0 0 -vn 0 0.8191520442889919 -0.5735764363510462 -vn 0 -0.8191520442889919 0.5735764363510462 -usemtl m_c341d2fe-028b-bd76-6b34-40c8c9b3653b -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o head -v 0.0625 0.6125 -0.11249999999999999 -v 0.0625 0.6125 -0.2375 -v 0.0625 0.42500000000000004 -0.11249999999999999 -v 0.0625 0.42500000000000004 -0.2375 -v -0.0625 0.6125 -0.2375 -v -0.0625 0.6125 -0.11249999999999999 -v -0.0625 0.42500000000000004 -0.2375 -v -0.0625 0.42500000000000004 -0.11249999999999999 -vt 0.125 0.875 -vt 0.1875 0.875 -vt 0.1875 0.78125 -vt 0.125 0.78125 -vt 0.0625 0.875 -vt 0.125 0.875 -vt 0.125 0.78125 -vt 0.0625 0.78125 -vt 0.25 0.875 -vt 0.3125 0.875 -vt 0.3125 0.78125 -vt 0.25 0.78125 -vt 0.1875 0.875 -vt 0.25 0.875 -vt 0.25 0.78125 -vt 0.1875 0.78125 -vt 0.1875 0.875 -vt 0.125 0.875 -vt 0.125 0.9375 -vt 0.1875 0.9375 -vt 0.25 0.9375 -vt 0.1875 0.9375 -vt 0.1875 0.875 -vt 0.25 0.875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c341d2fe-028b-bd76-6b34-40c8c9b3653b -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o head2 -v 0.0625 0.675 -0.11249999999999999 -v 0.0625 0.675 -0.3625 -v 0.0625 0.6125 -0.11249999999999999 -v 0.0625 0.6125 -0.3625 -v -0.0625 0.675 -0.3625 -v -0.0625 0.675 -0.11249999999999999 -v -0.0625 0.6125 -0.3625 -v -0.0625 0.6125 -0.11249999999999999 -vt 0.4375 0.875 -vt 0.5 0.875 -vt 0.5 0.84375 -vt 0.4375 0.84375 -vt 0.3125 0.875 -vt 0.4375 0.875 -vt 0.4375 0.84375 -vt 0.3125 0.84375 -vt 0.625 0.875 -vt 0.6875 0.875 -vt 0.6875 0.84375 -vt 0.625 0.84375 -vt 0.5 0.875 -vt 0.625 0.875 -vt 0.625 0.84375 -vt 0.5 0.84375 -vt 0.5 0.875 -vt 0.4375 0.875 -vt 0.4375 1 -vt 0.5 1 -vt 0.5625 1 -vt 0.5 1 -vt 0.5 0.875 -vt 0.5625 0.875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c341d2fe-028b-bd76-6b34-40c8c9b3653b -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o beak1 -v 0.03125 0.6125 -0.23125 -v 0.03125 0.6125 -0.29375 -v 0.03125 0.48750000000000004 -0.23125 -v 0.03125 0.48750000000000004 -0.29375 -v -0.03125 0.6125 -0.29375 -v -0.03125 0.6125 -0.23125 -v -0.03125 0.48750000000000004 -0.29375 -v -0.03125 0.48750000000000004 -0.23125 -vt 0.375 0.75 -vt 0.40625 0.75 -vt 0.40625 0.6875 -vt 0.375 0.6875 -vt 0.34375 0.75 -vt 0.375 0.75 -vt 0.375 0.6875 -vt 0.34375 0.6875 -vt 0.4375 0.75 -vt 0.46875 0.75 -vt 0.46875 0.6875 -vt 0.4375 0.6875 -vt 0.40625 0.75 -vt 0.4375 0.75 -vt 0.4375 0.6875 -vt 0.40625 0.6875 -vt 0.40625 0.75 -vt 0.375 0.75 -vt 0.375 0.78125 -vt 0.40625 0.78125 -vt 0.4375 0.78125 -vt 0.40625 0.78125 -vt 0.40625 0.75 -vt 0.4375 0.75 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c341d2fe-028b-bd76-6b34-40c8c9b3653b -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o beak2 -v 0.03125 0.6124999999999998 -0.29375 -v 0.03125 0.6124999999999998 -0.35625 -v 0.03125 0.5062500000000001 -0.29375 -v 0.03125 0.5062500000000001 -0.35625 -v -0.03125 0.6124999999999998 -0.35625 -v -0.03125 0.6124999999999998 -0.29375 -v -0.03125 0.5062500000000001 -0.35625 -v -0.03125 0.5062500000000001 -0.29375 -vt 0.53125 0.75 -vt 0.5625 0.75 -vt 0.5625 0.71875 -vt 0.53125 0.71875 -vt 0.5 0.75 -vt 0.53125 0.75 -vt 0.53125 0.71875 -vt 0.5 0.71875 -vt 0.59375 0.75 -vt 0.625 0.75 -vt 0.625 0.71875 -vt 0.59375 0.71875 -vt 0.5625 0.75 -vt 0.59375 0.75 -vt 0.59375 0.71875 -vt 0.5625 0.71875 -vt 0.5625 0.75 -vt 0.53125 0.75 -vt 0.53125 0.78125 -vt 0.5625 0.78125 -vt 0.59375 0.78125 -vt 0.5625 0.78125 -vt 0.5625 0.75 -vt 0.59375 0.75 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c341d2fe-028b-bd76-6b34-40c8c9b3653b -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o feather -v 0 0.8812500000000001 -0.05625000000000002 -v 0 0.8812500000000001 -0.30625 -v 0 0.5687500000000001 -0.05625000000000002 -v 0 0.5687500000000001 -0.30625 -v 0 0.8812500000000001 -0.30625 -v 0 0.8812500000000001 -0.05625000000000002 -v 0 0.5687500000000001 -0.30625 -v 0 0.5687500000000001 -0.05625000000000002 -vt 0.1875 0.3125 -vt 0.1875 0.3125 -vt 0.1875 0.15625 -vt 0.1875 0.15625 -vt 0.0625 0.3125 -vt 0.1875 0.3125 -vt 0.1875 0.15625 -vt 0.0625 0.15625 -vt 0.3125 0.3125 -vt 0.3125 0.3125 -vt 0.3125 0.15625 -vt 0.3125 0.15625 -vt 0.1875 0.3125 -vt 0.3125 0.3125 -vt 0.3125 0.15625 -vt 0.1875 0.15625 -vt 0.1875 0.3125 -vt 0.1875 0.3125 -vt 0.1875 0.4375 -vt 0.1875 0.4375 -vt 0.1875 0.4375 -vt 0.1875 0.4375 -vt 0.1875 0.3125 -vt 0.1875 0.3125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c341d2fe-028b-bd76-6b34-40c8c9b3653b -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o tail -v 0.09375 0.22142422560540864 0.027122222305063892 -v 0.09375 0.17354644791047258 -0.013052003300344839 -v 0.09375 0.06072732318377394 0.21863333308480837 -v 0.09375 0.012849545488837766 0.17845910747939964 -v -0.09375 0.17354644791047258 -0.013052003300344839 -v -0.09375 0.22142422560540864 0.027122222305063892 -v -0.09375 0.012849545488837766 0.17845910747939964 -v -0.09375 0.06072732318377394 0.21863333308480837 -vt 0.71875 0.9375 -vt 0.8125 0.9375 -vt 0.8125 0.8125 -vt 0.71875 0.8125 -vt 0.6875 0.9375 -vt 0.71875 0.9375 -vt 0.71875 0.8125 -vt 0.6875 0.8125 -vt 0.84375 0.9375 -vt 0.9375 0.9375 -vt 0.9375 0.8125 -vt 0.84375 0.8125 -vt 0.8125 0.9375 -vt 0.84375 0.9375 -vt 0.84375 0.8125 -vt 0.8125 0.8125 -vt 0.8125 0.9375 -vt 0.71875 0.9375 -vt 0.71875 0.96875 -vt 0.8125 0.96875 -vt 0.90625 0.96875 -vt 0.8125 0.96875 -vt 0.8125 0.9375 -vt 0.90625 0.9375 -vn 0 -0.766044443118978 -0.6427876096865393 -vn 1 0 0 -vn 0 0.766044443118978 0.6427876096865393 -vn -1 0 0 -vn 0 0.6427876096865393 -0.766044443118978 -vn 0 -0.6427876096865393 0.766044443118978 -usemtl m_c341d2fe-028b-bd76-6b34-40c8c9b3653b -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o leg0 -v -0.03125 0.09375 -0.03125 -v -0.03125 0.09375 -0.09375 -v -0.03125 -0.03125 -0.03125 -v -0.03125 -0.03125 -0.09375 -v -0.09375 0.09375 -0.09375 -v -0.09375 0.09375 -0.03125 -v -0.09375 -0.03125 -0.09375 -v -0.09375 -0.03125 -0.03125 -vt 0.46875 0.40625 -vt 0.5 0.40625 -vt 0.5 0.34375 -vt 0.46875 0.34375 -vt 0.4375 0.40625 -vt 0.46875 0.40625 -vt 0.46875 0.34375 -vt 0.4375 0.34375 -vt 0.53125 0.40625 -vt 0.5625 0.40625 -vt 0.5625 0.34375 -vt 0.53125 0.34375 -vt 0.5 0.40625 -vt 0.53125 0.40625 -vt 0.53125 0.34375 -vt 0.5 0.34375 -vt 0.5 0.40625 -vt 0.46875 0.40625 -vt 0.46875 0.4375 -vt 0.5 0.4375 -vt 0.53125 0.4375 -vt 0.5 0.4375 -vt 0.5 0.40625 -vt 0.53125 0.40625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c341d2fe-028b-bd76-6b34-40c8c9b3653b -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o leg1 -v 0.09375 0.09375 -0.03125 -v 0.09375 0.09375 -0.09375 -v 0.09375 -0.03125 -0.03125 -v 0.09375 -0.03125 -0.09375 -v 0.03125 0.09375 -0.09375 -v 0.03125 0.09375 -0.03125 -v 0.03125 -0.03125 -0.09375 -v 0.03125 -0.03125 -0.03125 -vt 0.46875 0.40625 -vt 0.5 0.40625 -vt 0.5 0.34375 -vt 0.46875 0.34375 -vt 0.4375 0.40625 -vt 0.46875 0.40625 -vt 0.46875 0.34375 -vt 0.4375 0.34375 -vt 0.53125 0.40625 -vt 0.5625 0.40625 -vt 0.5625 0.34375 -vt 0.53125 0.34375 -vt 0.5 0.40625 -vt 0.53125 0.40625 -vt 0.53125 0.34375 -vt 0.5 0.34375 -vt 0.5 0.40625 -vt 0.46875 0.40625 -vt 0.46875 0.4375 -vt 0.5 0.4375 -vt 0.53125 0.4375 -vt 0.5 0.4375 -vt 0.5 0.40625 -vt 0.53125 0.40625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_c341d2fe-028b-bd76-6b34-40c8c9b3653b -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/piglin.obj b/renderer/viewer/three/entity/models/piglin.obj deleted file mode 100644 index 2f68f4c1e..000000000 --- a/renderer/viewer/three/entity/models/piglin.obj +++ /dev/null @@ -1,739 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o Body -v 0.25 1.5 0.125 -v 0.25 1.5 -0.125 -v 0.25 0.75 0.125 -v 0.25 0.75 -0.125 -v -0.25 1.5 -0.125 -v -0.25 1.5 0.125 -v -0.25 0.75 -0.125 -v -0.25 0.75 0.125 -vt 0.3125 0.6875 -vt 0.4375 0.6875 -vt 0.4375 0.5 -vt 0.3125 0.5 -vt 0.25 0.6875 -vt 0.3125 0.6875 -vt 0.3125 0.5 -vt 0.25 0.5 -vt 0.5 0.6875 -vt 0.625 0.6875 -vt 0.625 0.5 -vt 0.5 0.5 -vt 0.4375 0.6875 -vt 0.5 0.6875 -vt 0.5 0.5 -vt 0.4375 0.5 -vt 0.4375 0.6875 -vt 0.3125 0.6875 -vt 0.3125 0.75 -vt 0.4375 0.75 -vt 0.5625 0.75 -vt 0.4375 0.75 -vt 0.4375 0.6875 -vt 0.5625 0.6875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o Body -v 0.265625 1.515625 0.140625 -v 0.265625 1.515625 -0.140625 -v 0.265625 0.734375 0.140625 -v 0.265625 0.734375 -0.140625 -v -0.265625 1.515625 -0.140625 -v -0.265625 1.515625 0.140625 -v -0.265625 0.734375 -0.140625 -v -0.265625 0.734375 0.140625 -vt 0.3125 0.4375 -vt 0.4375 0.4375 -vt 0.4375 0.25 -vt 0.3125 0.25 -vt 0.25 0.4375 -vt 0.3125 0.4375 -vt 0.3125 0.25 -vt 0.25 0.25 -vt 0.5 0.4375 -vt 0.625 0.4375 -vt 0.625 0.25 -vt 0.5 0.25 -vt 0.4375 0.4375 -vt 0.5 0.4375 -vt 0.5 0.25 -vt 0.4375 0.25 -vt 0.4375 0.4375 -vt 0.3125 0.4375 -vt 0.3125 0.5 -vt 0.4375 0.5 -vt 0.5625 0.5 -vt 0.4375 0.5 -vt 0.4375 0.4375 -vt 0.5625 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o head -v 0.31125 1.9987500000000002 0.24875000000000003 -v 0.31125 1.9987500000000002 -0.24875000000000003 -v 0.31125 1.5012499999999998 0.24875000000000003 -v 0.31125 1.5012499999999998 -0.24875000000000003 -v -0.31125 1.9987500000000002 -0.24875000000000003 -v -0.31125 1.9987500000000002 0.24875000000000003 -v -0.31125 1.5012499999999998 -0.24875000000000003 -v -0.31125 1.5012499999999998 0.24875000000000003 -vt 0.125 0.875 -vt 0.28125 0.875 -vt 0.28125 0.75 -vt 0.125 0.75 -vt 0 0.875 -vt 0.125 0.875 -vt 0.125 0.75 -vt 0 0.75 -vt 0.40625 0.875 -vt 0.5625 0.875 -vt 0.5625 0.75 -vt 0.40625 0.75 -vt 0.28125 0.875 -vt 0.40625 0.875 -vt 0.40625 0.75 -vt 0.28125 0.75 -vt 0.28125 0.875 -vt 0.125 0.875 -vt 0.125 1 -vt 0.28125 1 -vt 0.4375 1 -vt 0.28125 1 -vt 0.28125 0.875 -vt 0.4375 0.875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o head -v 0.125 1.75 -0.25 -v 0.125 1.75 -0.3125 -v 0.125 1.5 -0.25 -v 0.125 1.5 -0.3125 -v -0.125 1.75 -0.3125 -v -0.125 1.75 -0.25 -v -0.125 1.5 -0.3125 -v -0.125 1.5 -0.25 -vt 0.5 0.96875 -vt 0.5625 0.96875 -vt 0.5625 0.90625 -vt 0.5 0.90625 -vt 0.484375 0.96875 -vt 0.5 0.96875 -vt 0.5 0.90625 -vt 0.484375 0.90625 -vt 0.578125 0.96875 -vt 0.640625 0.96875 -vt 0.640625 0.90625 -vt 0.578125 0.90625 -vt 0.5625 0.96875 -vt 0.578125 0.96875 -vt 0.578125 0.90625 -vt 0.5625 0.90625 -vt 0.5625 0.96875 -vt 0.5 0.96875 -vt 0.5 0.984375 -vt 0.5625 0.984375 -vt 0.625 0.984375 -vt 0.5625 0.984375 -vt 0.5625 0.96875 -vt 0.625 0.96875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o head -v -0.125 1.625 -0.25 -v -0.125 1.625 -0.3125 -v -0.125 1.5 -0.25 -v -0.125 1.5 -0.3125 -v -0.1875 1.625 -0.3125 -v -0.1875 1.625 -0.25 -v -0.1875 1.5 -0.3125 -v -0.1875 1.5 -0.25 -vt 0.046875 0.921875 -vt 0.0625 0.921875 -vt 0.0625 0.890625 -vt 0.046875 0.890625 -vt 0.03125 0.921875 -vt 0.046875 0.921875 -vt 0.046875 0.890625 -vt 0.03125 0.890625 -vt 0.078125 0.921875 -vt 0.09375 0.921875 -vt 0.09375 0.890625 -vt 0.078125 0.890625 -vt 0.0625 0.921875 -vt 0.078125 0.921875 -vt 0.078125 0.890625 -vt 0.0625 0.890625 -vt 0.0625 0.921875 -vt 0.046875 0.921875 -vt 0.046875 0.9375 -vt 0.0625 0.9375 -vt 0.078125 0.9375 -vt 0.0625 0.9375 -vt 0.0625 0.921875 -vt 0.078125 0.921875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o head -v 0.1875 1.625 -0.25 -v 0.1875 1.625 -0.3125 -v 0.1875 1.5 -0.25 -v 0.1875 1.5 -0.3125 -v 0.125 1.625 -0.3125 -v 0.125 1.625 -0.25 -v 0.125 1.5 -0.3125 -v 0.125 1.5 -0.25 -vt 0.046875 0.984375 -vt 0.0625 0.984375 -vt 0.0625 0.953125 -vt 0.046875 0.953125 -vt 0.03125 0.984375 -vt 0.046875 0.984375 -vt 0.046875 0.953125 -vt 0.03125 0.953125 -vt 0.078125 0.984375 -vt 0.09375 0.984375 -vt 0.09375 0.953125 -vt 0.078125 0.953125 -vt 0.0625 0.984375 -vt 0.078125 0.984375 -vt 0.078125 0.953125 -vt 0.0625 0.953125 -vt 0.0625 0.984375 -vt 0.046875 0.984375 -vt 0.046875 1 -vt 0.0625 1 -vt 0.078125 1 -vt 0.0625 1 -vt 0.0625 0.984375 -vt 0.078125 0.984375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o leftear -v -0.25837341226347266 1.84375 0.125 -v -0.25837341226347266 1.84375 -0.125 -v -0.41462341226347266 1.573117061317363 0.125 -v -0.41462341226347266 1.573117061317363 -0.125 -v -0.3125 1.875 -0.125 -v -0.3125 1.875 0.125 -v -0.46875 1.604367061317363 -0.125 -v -0.46875 1.604367061317363 0.125 -vt 0.859375 0.84375 -vt 0.875 0.84375 -vt 0.875 0.765625 -vt 0.859375 0.765625 -vt 0.796875 0.84375 -vt 0.859375 0.84375 -vt 0.859375 0.765625 -vt 0.796875 0.765625 -vt 0.9375 0.84375 -vt 0.953125 0.84375 -vt 0.953125 0.765625 -vt 0.9375 0.765625 -vt 0.875 0.84375 -vt 0.9375 0.84375 -vt 0.9375 0.765625 -vt 0.875 0.765625 -vt 0.875 0.84375 -vt 0.859375 0.84375 -vt 0.859375 0.90625 -vt 0.875 0.90625 -vt 0.890625 0.90625 -vt 0.875 0.90625 -vt 0.875 0.84375 -vt 0.890625 0.84375 -vn 0 0 -1 -vn 0.8660254037844387 -0.49999999999999994 0 -vn 0 0 1 -vn -0.8660254037844387 0.49999999999999994 0 -vn 0.49999999999999994 0.8660254037844387 0 -vn -0.49999999999999994 -0.8660254037844387 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o rightear -v 0.3125 1.875 0.125 -v 0.3125 1.875 -0.125 -v 0.46875 1.604367061317363 0.125 -v 0.46875 1.604367061317363 -0.125 -v 0.25837341226347266 1.84375 -0.125 -v 0.25837341226347266 1.84375 0.125 -v 0.41462341226347266 1.573117061317363 -0.125 -v 0.41462341226347266 1.573117061317363 0.125 -vt 0.671875 0.84375 -vt 0.6875 0.84375 -vt 0.6875 0.765625 -vt 0.671875 0.765625 -vt 0.609375 0.84375 -vt 0.671875 0.84375 -vt 0.671875 0.765625 -vt 0.609375 0.765625 -vt 0.75 0.84375 -vt 0.765625 0.84375 -vt 0.765625 0.765625 -vt 0.75 0.765625 -vt 0.6875 0.84375 -vt 0.75 0.84375 -vt 0.75 0.765625 -vt 0.6875 0.765625 -vt 0.6875 0.84375 -vt 0.671875 0.84375 -vt 0.671875 0.90625 -vt 0.6875 0.90625 -vt 0.703125 0.90625 -vt 0.6875 0.90625 -vt 0.6875 0.84375 -vt 0.703125 0.84375 -vn 0 0 -1 -vn 0.8660254037844387 0.49999999999999994 0 -vn 0 0 1 -vn -0.8660254037844387 -0.49999999999999994 0 -vn -0.49999999999999994 0.8660254037844387 0 -vn 0.49999999999999994 -0.8660254037844387 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o RightArm -v 0.5 1.5 0.125 -v 0.5 1.5 -0.125 -v 0.5 0.75 0.125 -v 0.5 0.75 -0.125 -v 0.25 1.5 -0.125 -v 0.25 1.5 0.125 -v 0.25 0.75 -0.125 -v 0.25 0.75 0.125 -vt 0.6875 0.6875 -vt 0.75 0.6875 -vt 0.75 0.5 -vt 0.6875 0.5 -vt 0.625 0.6875 -vt 0.6875 0.6875 -vt 0.6875 0.5 -vt 0.625 0.5 -vt 0.8125 0.6875 -vt 0.875 0.6875 -vt 0.875 0.5 -vt 0.8125 0.5 -vt 0.75 0.6875 -vt 0.8125 0.6875 -vt 0.8125 0.5 -vt 0.75 0.5 -vt 0.75 0.6875 -vt 0.6875 0.6875 -vt 0.6875 0.75 -vt 0.75 0.75 -vt 0.8125 0.75 -vt 0.75 0.75 -vt 0.75 0.6875 -vt 0.8125 0.6875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o RightArm -v 0.515625 1.515625 0.140625 -v 0.515625 1.515625 -0.140625 -v 0.515625 0.734375 0.140625 -v 0.515625 0.734375 -0.140625 -v 0.234375 1.515625 -0.140625 -v 0.234375 1.515625 0.140625 -v 0.234375 0.734375 -0.140625 -v 0.234375 0.734375 0.140625 -vt 0.6875 0.4375 -vt 0.75 0.4375 -vt 0.75 0.25 -vt 0.6875 0.25 -vt 0.625 0.4375 -vt 0.6875 0.4375 -vt 0.6875 0.25 -vt 0.625 0.25 -vt 0.8125 0.4375 -vt 0.875 0.4375 -vt 0.875 0.25 -vt 0.8125 0.25 -vt 0.75 0.4375 -vt 0.8125 0.4375 -vt 0.8125 0.25 -vt 0.75 0.25 -vt 0.75 0.4375 -vt 0.6875 0.4375 -vt 0.6875 0.5 -vt 0.75 0.5 -vt 0.8125 0.5 -vt 0.75 0.5 -vt 0.75 0.4375 -vt 0.8125 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o LeftArm -v -0.25 1.5 0.125 -v -0.25 1.5 -0.125 -v -0.25 0.75 0.125 -v -0.25 0.75 -0.125 -v -0.5 1.5 -0.125 -v -0.5 1.5 0.125 -v -0.5 0.75 -0.125 -v -0.5 0.75 0.125 -vt 0.5625 0.1875 -vt 0.625 0.1875 -vt 0.625 0 -vt 0.5625 0 -vt 0.5 0.1875 -vt 0.5625 0.1875 -vt 0.5625 0 -vt 0.5 0 -vt 0.6875 0.1875 -vt 0.75 0.1875 -vt 0.75 0 -vt 0.6875 0 -vt 0.625 0.1875 -vt 0.6875 0.1875 -vt 0.6875 0 -vt 0.625 0 -vt 0.625 0.1875 -vt 0.5625 0.1875 -vt 0.5625 0.25 -vt 0.625 0.25 -vt 0.6875 0.25 -vt 0.625 0.25 -vt 0.625 0.1875 -vt 0.6875 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 -o LeftArm -v -0.234375 1.515625 0.140625 -v -0.234375 1.515625 -0.140625 -v -0.234375 0.734375 0.140625 -v -0.234375 0.734375 -0.140625 -v -0.515625 1.515625 -0.140625 -v -0.515625 1.515625 0.140625 -v -0.515625 0.734375 -0.140625 -v -0.515625 0.734375 0.140625 -vt 0.8125 0.1875 -vt 0.875 0.1875 -vt 0.875 0 -vt 0.8125 0 -vt 0.75 0.1875 -vt 0.8125 0.1875 -vt 0.8125 0 -vt 0.75 0 -vt 0.9375 0.1875 -vt 1 0.1875 -vt 1 0 -vt 0.9375 0 -vt 0.875 0.1875 -vt 0.9375 0.1875 -vt 0.9375 0 -vt 0.875 0 -vt 0.875 0.1875 -vt 0.8125 0.1875 -vt 0.8125 0.25 -vt 0.875 0.25 -vt 0.9375 0.25 -vt 0.875 0.25 -vt 0.875 0.1875 -vt 0.9375 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 92/268/67 95/267/67 93/266/67 90/265/67 -f 91/272/68 92/271/68 90/270/68 89/269/68 -f 96/276/69 91/275/69 89/274/69 94/273/69 -f 95/280/70 96/279/70 94/278/70 93/277/70 -f 94/284/71 89/283/71 90/282/71 93/281/71 -f 95/288/72 92/287/72 91/286/72 96/285/72 -o RightLeg -v 0.25 0.75 0.125 -v 0.25 0.75 -0.125 -v 0.25 0 0.125 -v 0.25 0 -0.125 -v 0 0.75 -0.125 -v 0 0.75 0.125 -v 0 0 -0.125 -v 0 0 0.125 -vt 0.0625 0.6875 -vt 0.125 0.6875 -vt 0.125 0.5 -vt 0.0625 0.5 -vt 0 0.6875 -vt 0.0625 0.6875 -vt 0.0625 0.5 -vt 0 0.5 -vt 0.1875 0.6875 -vt 0.25 0.6875 -vt 0.25 0.5 -vt 0.1875 0.5 -vt 0.125 0.6875 -vt 0.1875 0.6875 -vt 0.1875 0.5 -vt 0.125 0.5 -vt 0.125 0.6875 -vt 0.0625 0.6875 -vt 0.0625 0.75 -vt 0.125 0.75 -vt 0.1875 0.75 -vt 0.125 0.75 -vt 0.125 0.6875 -vt 0.1875 0.6875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 100/292/73 103/291/73 101/290/73 98/289/73 -f 99/296/74 100/295/74 98/294/74 97/293/74 -f 104/300/75 99/299/75 97/298/75 102/297/75 -f 103/304/76 104/303/76 102/302/76 101/301/76 -f 102/308/77 97/307/77 98/306/77 101/305/77 -f 103/312/78 100/311/78 99/310/78 104/309/78 -o RightLeg -v 0.265625 0.765625 0.140625 -v 0.265625 0.765625 -0.140625 -v 0.265625 -0.015625 0.140625 -v 0.265625 -0.015625 -0.140625 -v -0.015625 0.765625 -0.140625 -v -0.015625 0.765625 0.140625 -v -0.015625 -0.015625 -0.140625 -v -0.015625 -0.015625 0.140625 -vt 0.0625 0.4375 -vt 0.125 0.4375 -vt 0.125 0.25 -vt 0.0625 0.25 -vt 0 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.25 -vt 0 0.25 -vt 0.1875 0.4375 -vt 0.25 0.4375 -vt 0.25 0.25 -vt 0.1875 0.25 -vt 0.125 0.4375 -vt 0.1875 0.4375 -vt 0.1875 0.25 -vt 0.125 0.25 -vt 0.125 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.5 -vt 0.125 0.5 -vt 0.1875 0.5 -vt 0.125 0.5 -vt 0.125 0.4375 -vt 0.1875 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 108/316/79 111/315/79 109/314/79 106/313/79 -f 107/320/80 108/319/80 106/318/80 105/317/80 -f 112/324/81 107/323/81 105/322/81 110/321/81 -f 111/328/82 112/327/82 110/326/82 109/325/82 -f 110/332/83 105/331/83 106/330/83 109/329/83 -f 111/336/84 108/335/84 107/334/84 112/333/84 -o LeftLeg -v 0 0.75 0.125 -v 0 0.75 -0.125 -v 0 0 0.125 -v 0 0 -0.125 -v -0.25 0.75 -0.125 -v -0.25 0.75 0.125 -v -0.25 0 -0.125 -v -0.25 0 0.125 -vt 0.3125 0.1875 -vt 0.375 0.1875 -vt 0.375 0 -vt 0.3125 0 -vt 0.25 0.1875 -vt 0.3125 0.1875 -vt 0.3125 0 -vt 0.25 0 -vt 0.4375 0.1875 -vt 0.5 0.1875 -vt 0.5 0 -vt 0.4375 0 -vt 0.375 0.1875 -vt 0.4375 0.1875 -vt 0.4375 0 -vt 0.375 0 -vt 0.375 0.1875 -vt 0.3125 0.1875 -vt 0.3125 0.25 -vt 0.375 0.25 -vt 0.4375 0.25 -vt 0.375 0.25 -vt 0.375 0.1875 -vt 0.4375 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 116/340/85 119/339/85 117/338/85 114/337/85 -f 115/344/86 116/343/86 114/342/86 113/341/86 -f 120/348/87 115/347/87 113/346/87 118/345/87 -f 119/352/88 120/351/88 118/350/88 117/349/88 -f 118/356/89 113/355/89 114/354/89 117/353/89 -f 119/360/90 116/359/90 115/358/90 120/357/90 -o LeftLeg -v 0.015625 0.765625 0.140625 -v 0.015625 0.765625 -0.140625 -v 0.015625 -0.015625 0.140625 -v 0.015625 -0.015625 -0.140625 -v -0.265625 0.765625 -0.140625 -v -0.265625 0.765625 0.140625 -v -0.265625 -0.015625 -0.140625 -v -0.265625 -0.015625 0.140625 -vt 0.0625 0.1875 -vt 0.125 0.1875 -vt 0.125 0 -vt 0.0625 0 -vt 0 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0 -vt 0 0 -vt 0.1875 0.1875 -vt 0.25 0.1875 -vt 0.25 0 -vt 0.1875 0 -vt 0.125 0.1875 -vt 0.1875 0.1875 -vt 0.1875 0 -vt 0.125 0 -vt 0.125 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.25 -vt 0.125 0.25 -vt 0.1875 0.25 -vt 0.125 0.25 -vt 0.125 0.1875 -vt 0.1875 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_bd9b2175-46cc-d3be-0d85-ed94b50a7825 -f 124/364/91 127/363/91 125/362/91 122/361/91 -f 123/368/92 124/367/92 122/366/92 121/365/92 -f 128/372/93 123/371/93 121/370/93 126/369/93 -f 127/376/94 128/375/94 126/374/94 125/373/94 -f 126/380/95 121/379/95 122/378/95 125/377/95 -f 127/384/96 124/383/96 123/382/96 128/381/96 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/pillager.obj b/renderer/viewer/three/entity/models/pillager.obj deleted file mode 100644 index 213a3b941..000000000 --- a/renderer/viewer/three/entity/models/pillager.obj +++ /dev/null @@ -1,371 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o Body -v 0.25 1.5 0.1875 -v 0.25 1.5 -0.1875 -v 0.25 0.75 0.1875 -v 0.25 0.75 -0.1875 -v -0.25 1.5 -0.1875 -v -0.25 1.5 0.1875 -v -0.25 0.75 -0.1875 -v -0.25 0.75 0.1875 -vt 0.34375 0.59375 -vt 0.46875 0.59375 -vt 0.46875 0.40625 -vt 0.34375 0.40625 -vt 0.25 0.59375 -vt 0.34375 0.59375 -vt 0.34375 0.40625 -vt 0.25 0.40625 -vt 0.5625 0.59375 -vt 0.6875 0.59375 -vt 0.6875 0.40625 -vt 0.5625 0.40625 -vt 0.46875 0.59375 -vt 0.5625 0.59375 -vt 0.5625 0.40625 -vt 0.46875 0.40625 -vt 0.46875 0.59375 -vt 0.34375 0.59375 -vt 0.34375 0.6875 -vt 0.46875 0.6875 -vt 0.59375 0.6875 -vt 0.46875 0.6875 -vt 0.46875 0.59375 -vt 0.59375 0.59375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_0e7f3cc8-7af8-21a7-d2f3-04bee5fb4aae -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o Body -v 0.28125 1.53125 0.21875 -v 0.28125 1.53125 -0.21875 -v 0.28125 0.34375 0.21875 -v 0.28125 0.34375 -0.21875 -v -0.28125 1.53125 -0.21875 -v -0.28125 1.53125 0.21875 -v -0.28125 0.34375 -0.21875 -v -0.28125 0.34375 0.21875 -vt 0.09375 0.3125 -vt 0.21875 0.3125 -vt 0.21875 0.03125 -vt 0.09375 0.03125 -vt 0 0.3125 -vt 0.09375 0.3125 -vt 0.09375 0.03125 -vt 0 0.03125 -vt 0.3125 0.3125 -vt 0.4375 0.3125 -vt 0.4375 0.03125 -vt 0.3125 0.03125 -vt 0.21875 0.3125 -vt 0.3125 0.3125 -vt 0.3125 0.03125 -vt 0.21875 0.03125 -vt 0.21875 0.3125 -vt 0.09375 0.3125 -vt 0.09375 0.40625 -vt 0.21875 0.40625 -vt 0.34375 0.40625 -vt 0.21875 0.40625 -vt 0.21875 0.3125 -vt 0.34375 0.3125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_0e7f3cc8-7af8-21a7-d2f3-04bee5fb4aae -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o head -v 0.25 2.125 0.25 -v 0.25 2.125 -0.25 -v 0.25 1.5 0.25 -v 0.25 1.5 -0.25 -v -0.25 2.125 -0.25 -v -0.25 2.125 0.25 -v -0.25 1.5 -0.25 -v -0.25 1.5 0.25 -vt 0.125 0.875 -vt 0.25 0.875 -vt 0.25 0.71875 -vt 0.125 0.71875 -vt 0 0.875 -vt 0.125 0.875 -vt 0.125 0.71875 -vt 0 0.71875 -vt 0.375 0.875 -vt 0.5 0.875 -vt 0.5 0.71875 -vt 0.375 0.71875 -vt 0.25 0.875 -vt 0.375 0.875 -vt 0.375 0.71875 -vt 0.25 0.71875 -vt 0.25 0.875 -vt 0.125 0.875 -vt 0.125 1 -vt 0.25 1 -vt 0.375 1 -vt 0.25 1 -vt 0.25 0.875 -vt 0.375 0.875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_0e7f3cc8-7af8-21a7-d2f3-04bee5fb4aae -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o nose -v 0.0625 1.6875 -0.25 -v 0.0625 1.6875 -0.375 -v 0.0625 1.4375 -0.25 -v 0.0625 1.4375 -0.375 -v -0.0625 1.6875 -0.375 -v -0.0625 1.6875 -0.25 -v -0.0625 1.4375 -0.375 -v -0.0625 1.4375 -0.25 -vt 0.40625 0.96875 -vt 0.4375 0.96875 -vt 0.4375 0.90625 -vt 0.40625 0.90625 -vt 0.375 0.96875 -vt 0.40625 0.96875 -vt 0.40625 0.90625 -vt 0.375 0.90625 -vt 0.46875 0.96875 -vt 0.5 0.96875 -vt 0.5 0.90625 -vt 0.46875 0.90625 -vt 0.4375 0.96875 -vt 0.46875 0.96875 -vt 0.46875 0.90625 -vt 0.4375 0.90625 -vt 0.4375 0.96875 -vt 0.40625 0.96875 -vt 0.40625 1 -vt 0.4375 1 -vt 0.46875 1 -vt 0.4375 1 -vt 0.4375 0.96875 -vt 0.46875 0.96875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_0e7f3cc8-7af8-21a7-d2f3-04bee5fb4aae -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o LeftLeg -v 0 0.75 0.125 -v 0 0.75 -0.125 -v 0 0 0.125 -v 0 0 -0.125 -v -0.25 0.75 -0.125 -v -0.25 0.75 0.125 -v -0.25 0 -0.125 -v -0.25 0 0.125 -vt 0.0625 0.59375 -vt 0.125 0.59375 -vt 0.125 0.40625 -vt 0.0625 0.40625 -vt 0 0.59375 -vt 0.0625 0.59375 -vt 0.0625 0.40625 -vt 0 0.40625 -vt 0.1875 0.59375 -vt 0.25 0.59375 -vt 0.25 0.40625 -vt 0.1875 0.40625 -vt 0.125 0.59375 -vt 0.1875 0.59375 -vt 0.1875 0.40625 -vt 0.125 0.40625 -vt 0.125 0.59375 -vt 0.0625 0.59375 -vt 0.0625 0.65625 -vt 0.125 0.65625 -vt 0.1875 0.65625 -vt 0.125 0.65625 -vt 0.125 0.59375 -vt 0.1875 0.59375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_0e7f3cc8-7af8-21a7-d2f3-04bee5fb4aae -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o RightLeg -v 0.25 0.75 0.125 -v 0.25 0.75 -0.125 -v 0.25 0 0.125 -v 0.25 0 -0.125 -v 0 0.75 -0.125 -v 0 0.75 0.125 -v 0 0 -0.125 -v 0 0 0.125 -vt 0.125 0.59375 -vt 0.0625 0.59375 -vt 0.0625 0.40625 -vt 0.125 0.40625 -vt 0.1875 0.59375 -vt 0.125 0.59375 -vt 0.125 0.40625 -vt 0.1875 0.40625 -vt 0.25 0.59375 -vt 0.1875 0.59375 -vt 0.1875 0.40625 -vt 0.25 0.40625 -vt 0.0625 0.59375 -vt 0 0.59375 -vt 0 0.40625 -vt 0.0625 0.40625 -vt 0.0625 0.59375 -vt 0.125 0.59375 -vt 0.125 0.65625 -vt 0.0625 0.65625 -vt 0.125 0.65625 -vt 0.1875 0.65625 -vt 0.1875 0.59375 -vt 0.125 0.59375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_0e7f3cc8-7af8-21a7-d2f3-04bee5fb4aae -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o RightArm -v 0.5 1.5 0.125 -v 0.5 1.5 -0.125 -v 0.5 0.75 0.125 -v 0.5 0.75 -0.125 -v 0.25 1.5 -0.125 -v 0.25 1.5 0.125 -v 0.25 0.75 -0.125 -v 0.25 0.75 0.125 -vt 0.6875 0.21875 -vt 0.75 0.21875 -vt 0.75 0.03125 -vt 0.6875 0.03125 -vt 0.625 0.21875 -vt 0.6875 0.21875 -vt 0.6875 0.03125 -vt 0.625 0.03125 -vt 0.8125 0.21875 -vt 0.875 0.21875 -vt 0.875 0.03125 -vt 0.8125 0.03125 -vt 0.75 0.21875 -vt 0.8125 0.21875 -vt 0.8125 0.03125 -vt 0.75 0.03125 -vt 0.75 0.21875 -vt 0.6875 0.21875 -vt 0.6875 0.28125 -vt 0.75 0.28125 -vt 0.8125 0.28125 -vt 0.75 0.28125 -vt 0.75 0.21875 -vt 0.8125 0.21875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_0e7f3cc8-7af8-21a7-d2f3-04bee5fb4aae -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o LeftArm -v -0.25 1.5 0.125 -v -0.25 1.5 -0.125 -v -0.25 0.75 0.125 -v -0.25 0.75 -0.125 -v -0.5 1.5 -0.125 -v -0.5 1.5 0.125 -v -0.5 0.75 -0.125 -v -0.5 0.75 0.125 -vt 0.75 0.21875 -vt 0.6875 0.21875 -vt 0.6875 0.03125 -vt 0.75 0.03125 -vt 0.8125 0.21875 -vt 0.75 0.21875 -vt 0.75 0.03125 -vt 0.8125 0.03125 -vt 0.875 0.21875 -vt 0.8125 0.21875 -vt 0.8125 0.03125 -vt 0.875 0.03125 -vt 0.6875 0.21875 -vt 0.625 0.21875 -vt 0.625 0.03125 -vt 0.6875 0.03125 -vt 0.6875 0.21875 -vt 0.75 0.21875 -vt 0.75 0.28125 -vt 0.6875 0.28125 -vt 0.75 0.28125 -vt 0.8125 0.28125 -vt 0.8125 0.21875 -vt 0.75 0.21875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_0e7f3cc8-7af8-21a7-d2f3-04bee5fb4aae -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/rabbit.obj b/renderer/viewer/three/entity/models/rabbit.obj deleted file mode 100644 index 545c4b5dc..000000000 --- a/renderer/viewer/three/entity/models/rabbit.obj +++ /dev/null @@ -1,555 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o rearFootLeft -v -0.125 0.0625 0.4375 -v -0.125 0.0625 0 -v -0.125 0 0.4375 -v -0.125 0 0 -v -0.25 0.0625 0 -v -0.25 0.0625 0.4375 -v -0.25 0 0 -v -0.25 0 0.4375 -vt 0.265625 0.03125 -vt 0.234375 0.03125 -vt 0.234375 0 -vt 0.265625 0 -vt 0.375 0.03125 -vt 0.265625 0.03125 -vt 0.265625 0 -vt 0.375 0 -vt 0.40625 0.03125 -vt 0.375 0.03125 -vt 0.375 0 -vt 0.40625 0 -vt 0.234375 0.03125 -vt 0.125 0.03125 -vt 0.125 0 -vt 0.234375 0 -vt 0.234375 0.03125 -vt 0.265625 0.03125 -vt 0.265625 0.25 -vt 0.234375 0.25 -vt 0.265625 0.25 -vt 0.296875 0.25 -vt 0.296875 0.03125 -vt 0.265625 0.03125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_a200089f-c989-c3f8-c313-2c45240e78d7 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o rearFootRight -v 0.25 0.0625 0.4375 -v 0.25 0.0625 0 -v 0.25 0 0.4375 -v 0.25 0 0 -v 0.125 0.0625 0 -v 0.125 0.0625 0.4375 -v 0.125 0 0 -v 0.125 0 0.4375 -vt 0.546875 0.03125 -vt 0.515625 0.03125 -vt 0.515625 0 -vt 0.546875 0 -vt 0.65625 0.03125 -vt 0.546875 0.03125 -vt 0.546875 0 -vt 0.65625 0 -vt 0.6875 0.03125 -vt 0.65625 0.03125 -vt 0.65625 0 -vt 0.6875 0 -vt 0.515625 0.03125 -vt 0.40625 0.03125 -vt 0.40625 0 -vt 0.515625 0 -vt 0.515625 0.03125 -vt 0.546875 0.03125 -vt 0.546875 0.25 -vt 0.515625 0.25 -vt 0.546875 0.25 -vt 0.578125 0.25 -vt 0.578125 0.03125 -vt 0.546875 0.03125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_a200089f-c989-c3f8-c313-2c45240e78d7 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o haunchLeft -v -0.125 0.29936870521072856 0.5249039439955965 -v -0.125 0.40625 0.23124999999999996 -v -0.125 0.06444555001425145 0.43939890816417915 -v -0.125 0.1713268448035229 0.14574496416858285 -v -0.25 0.40625 0.23124999999999996 -v -0.25 0.29936870521072856 0.5249039439955965 -v -0.25 0.1713268448035229 0.14574496416858285 -v -0.25 0.06444555001425145 0.43939890816417915 -vt 0.359375 0.375 -vt 0.328125 0.375 -vt 0.328125 0.25 -vt 0.359375 0.25 -vt 0.4375 0.375 -vt 0.359375 0.375 -vt 0.359375 0.25 -vt 0.4375 0.25 -vt 0.46875 0.375 -vt 0.4375 0.375 -vt 0.4375 0.25 -vt 0.46875 0.25 -vt 0.328125 0.375 -vt 0.25 0.375 -vt 0.25 0.25 -vt 0.328125 0.25 -vt 0.328125 0.375 -vt 0.359375 0.375 -vt 0.359375 0.53125 -vt 0.328125 0.53125 -vt 0.359375 0.53125 -vt 0.390625 0.53125 -vt 0.390625 0.375 -vt 0.359375 0.375 -vn 0 0.34202014332566866 -0.9396926207859084 -vn 1 0 0 -vn 0 -0.34202014332566866 0.9396926207859084 -vn -1 0 0 -vn 0 0.9396926207859084 0.34202014332566866 -vn 0 -0.9396926207859084 -0.34202014332566866 -usemtl m_a200089f-c989-c3f8-c313-2c45240e78d7 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o haunchRight -v 0.25 0.29936870521072856 0.5249039439955965 -v 0.25 0.40625 0.23124999999999996 -v 0.25 0.06444555001425145 0.43939890816417915 -v 0.25 0.1713268448035229 0.14574496416858285 -v 0.125 0.40625 0.23124999999999996 -v 0.125 0.29936870521072856 0.5249039439955965 -v 0.125 0.1713268448035229 0.14574496416858285 -v 0.125 0.06444555001425145 0.43939890816417915 -vt 0.578125 0.375 -vt 0.546875 0.375 -vt 0.546875 0.25 -vt 0.578125 0.25 -vt 0.65625 0.375 -vt 0.578125 0.375 -vt 0.578125 0.25 -vt 0.65625 0.25 -vt 0.6875 0.375 -vt 0.65625 0.375 -vt 0.65625 0.25 -vt 0.6875 0.25 -vt 0.546875 0.375 -vt 0.46875 0.375 -vt 0.46875 0.25 -vt 0.546875 0.25 -vt 0.546875 0.375 -vt 0.578125 0.375 -vt 0.578125 0.53125 -vt 0.546875 0.53125 -vt 0.578125 0.53125 -vt 0.609375 0.53125 -vt 0.609375 0.375 -vt 0.578125 0.375 -vn 0 0.34202014332566866 -0.9396926207859084 -vn 1 0 0 -vn 0 -0.34202014332566866 0.9396926207859084 -vn -1 0 0 -vn 0 0.9396926207859084 0.34202014332566866 -vn 0 -0.9396926207859084 -0.34202014332566866 -usemtl m_a200089f-c989-c3f8-c313-2c45240e78d7 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o body -v 0.1875 0.4299615775982385 0.5427525179157087 -v 0.1875 0.6437241671767815 -0.04455537007548416 -v 0.1875 0.1363076336026421 0.4358712231264371 -v 0.1875 0.3500702231811851 -0.1514366648647556 -v -0.1875 0.6437241671767815 -0.04455537007548416 -v -0.1875 0.4299615775982385 0.5427525179157087 -v -0.1875 0.3500702231811851 -0.1514366648647556 -v -0.1875 0.1363076336026421 0.4358712231264371 -vt 0.25 0.6875 -vt 0.15625 0.6875 -vt 0.15625 0.53125 -vt 0.25 0.53125 -vt 0.40625 0.6875 -vt 0.25 0.6875 -vt 0.25 0.53125 -vt 0.40625 0.53125 -vt 0.5 0.6875 -vt 0.40625 0.6875 -vt 0.40625 0.53125 -vt 0.5 0.53125 -vt 0.15625 0.6875 -vt 0 0.6875 -vt 0 0.53125 -vt 0.15625 0.53125 -vt 0.15625 0.6875 -vt 0.25 0.6875 -vt 0.25 1 -vt 0.15625 1 -vt 0.25 1 -vt 0.34375 1 -vt 0.34375 0.6875 -vt 0.25 0.6875 -vn 0 0.34202014332566866 -0.9396926207859084 -vn 1 0 0 -vn 0 -0.34202014332566866 0.9396926207859084 -vn -1 0 0 -vn 0 0.9396926207859084 0.34202014332566866 -vn 0 -0.9396926207859084 -0.34202014332566866 -usemtl m_a200089f-c989-c3f8-c313-2c45240e78d7 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o frontLegLeft -v -0.125 0.42664698889581687 -0.0009495154367369918 -v -0.125 0.44835301110418313 -0.12405048456326301 -v -0.125 -0.004206403047024132 -0.07692059316601901 -v -0.125 0.017499619161342128 -0.20002156229254503 -v -0.25 0.44835301110418313 -0.12405048456326301 -v -0.25 0.42664698889581687 -0.0009495154367369918 -v -0.25 0.017499619161342128 -0.20002156229254503 -v -0.25 -0.004206403047024132 -0.07692059316601901 -vt 0.1875 0.46875 -vt 0.15625 0.46875 -vt 0.15625 0.25 -vt 0.1875 0.25 -vt 0.21875 0.46875 -vt 0.1875 0.46875 -vt 0.1875 0.25 -vt 0.21875 0.25 -vt 0.25 0.46875 -vt 0.21875 0.46875 -vt 0.21875 0.25 -vt 0.25 0.25 -vt 0.15625 0.46875 -vt 0.125 0.46875 -vt 0.125 0.25 -vt 0.15625 0.25 -vt 0.15625 0.46875 -vt 0.1875 0.46875 -vt 0.1875 0.53125 -vt 0.15625 0.53125 -vt 0.1875 0.53125 -vt 0.21875 0.53125 -vt 0.21875 0.46875 -vt 0.1875 0.46875 -vn 0 0.17364817766693033 -0.984807753012208 -vn 1 0 0 -vn 0 -0.17364817766693033 0.984807753012208 -vn -1 0 0 -vn 0 0.984807753012208 0.17364817766693033 -vn 0 -0.984807753012208 -0.17364817766693033 -usemtl m_a200089f-c989-c3f8-c313-2c45240e78d7 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o frontLegRight -v 0.25 0.42664698889581687 -0.0009495154367369918 -v 0.25 0.44835301110418313 -0.12405048456326301 -v 0.25 -0.004206403047024132 -0.07692059316601901 -v 0.25 0.017499619161342128 -0.20002156229254503 -v 0.125 0.44835301110418313 -0.12405048456326301 -v 0.125 0.42664698889581687 -0.0009495154367369918 -v 0.125 0.017499619161342128 -0.20002156229254503 -v 0.125 -0.004206403047024132 -0.07692059316601901 -vt 0.0625 0.46875 -vt 0.03125 0.46875 -vt 0.03125 0.25 -vt 0.0625 0.25 -vt 0.09375 0.46875 -vt 0.0625 0.46875 -vt 0.0625 0.25 -vt 0.09375 0.25 -vt 0.125 0.46875 -vt 0.09375 0.46875 -vt 0.09375 0.25 -vt 0.125 0.25 -vt 0.03125 0.46875 -vt 0 0.46875 -vt 0 0.25 -vt 0.03125 0.25 -vt 0.03125 0.46875 -vt 0.0625 0.46875 -vt 0.0625 0.53125 -vt 0.03125 0.53125 -vt 0.0625 0.53125 -vt 0.09375 0.53125 -vt 0.09375 0.46875 -vt 0.0625 0.46875 -vn 0 0.17364817766693033 -0.984807753012208 -vn 1 0 0 -vn 0 -0.17364817766693033 0.984807753012208 -vn -1 0 0 -vn 0 0.984807753012208 0.17364817766693033 -vn 0 -0.984807753012208 -0.17364817766693033 -usemtl m_a200089f-c989-c3f8-c313-2c45240e78d7 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o head -v 0.15625 0.75 -0.0625 -v 0.15625 0.75 -0.375 -v 0.15625 0.5 -0.0625 -v 0.15625 0.5 -0.375 -v -0.15625 0.75 -0.375 -v -0.15625 0.75 -0.0625 -v -0.15625 0.5 -0.375 -v -0.15625 0.5 -0.0625 -vt 0.65625 0.84375 -vt 0.578125 0.84375 -vt 0.578125 0.71875 -vt 0.65625 0.71875 -vt 0.734375 0.84375 -vt 0.65625 0.84375 -vt 0.65625 0.71875 -vt 0.734375 0.71875 -vt 0.8125 0.84375 -vt 0.734375 0.84375 -vt 0.734375 0.71875 -vt 0.8125 0.71875 -vt 0.578125 0.84375 -vt 0.5 0.84375 -vt 0.5 0.71875 -vt 0.578125 0.71875 -vt 0.578125 0.84375 -vt 0.65625 0.84375 -vt 0.65625 1 -vt 0.578125 1 -vt 0.65625 1 -vt 0.734375 1 -vt 0.734375 0.84375 -vt 0.65625 0.84375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_a200089f-c989-c3f8-c313-2c45240e78d7 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o earRight -v 0.1509259103576669 1.0625 -0.10294047579726884 -v 0.1347497200387594 1.0625 -0.16331083994033568 -v 0.1509259103576669 0.75 -0.10294047579726884 -v 0.1347497200387594 0.75 -0.16331083994033568 -v 0.014008991752625821 1.0625 -0.1309584593025206 -v 0.030185182071533423 1.0625 -0.07058809515945375 -v 0.014008991752625821 0.75 -0.1309584593025206 -v 0.030185182071533423 0.75 -0.07058809515945375 -vt 0.953125 0.96875 -vt 0.921875 0.96875 -vt 0.921875 0.8125 -vt 0.953125 0.8125 -vt 0.96875 0.96875 -vt 0.953125 0.96875 -vt 0.953125 0.8125 -vt 0.96875 0.8125 -vt 1 0.96875 -vt 0.96875 0.96875 -vt 0.96875 0.8125 -vt 1 0.8125 -vt 0.921875 0.96875 -vt 0.90625 0.96875 -vt 0.90625 0.8125 -vt 0.921875 0.8125 -vt 0.921875 0.96875 -vt 0.953125 0.96875 -vt 0.953125 1 -vt 0.921875 1 -vt 0.953125 1 -vt 0.984375 1 -vt 0.984375 0.96875 -vt 0.953125 0.96875 -vn -0.25881904510252074 0 -0.9659258262890683 -vn 0.9659258262890683 0 -0.25881904510252074 -vn 0.25881904510252074 0 0.9659258262890683 -vn -0.9659258262890683 0 0.25881904510252074 -vn 0 1 0 -vn 0 -1 0 -usemtl m_a200089f-c989-c3f8-c313-2c45240e78d7 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o earLeft -v -0.030185182071533367 1.0625 -0.07058809515945375 -v -0.014008991752625821 1.0625 -0.1309584593025206 -v -0.030185182071533367 0.75 -0.07058809515945375 -v -0.014008991752625821 0.75 -0.1309584593025206 -v -0.1347497200387594 1.0625 -0.16331083994033568 -v -0.1509259103576669 1.0625 -0.10294047579726884 -v -0.1347497200387594 0.75 -0.16331083994033568 -v -0.1509259103576669 0.75 -0.10294047579726884 -vt 0.859375 0.96875 -vt 0.828125 0.96875 -vt 0.828125 0.8125 -vt 0.859375 0.8125 -vt 0.875 0.96875 -vt 0.859375 0.96875 -vt 0.859375 0.8125 -vt 0.875 0.8125 -vt 0.90625 0.96875 -vt 0.875 0.96875 -vt 0.875 0.8125 -vt 0.90625 0.8125 -vt 0.828125 0.96875 -vt 0.8125 0.96875 -vt 0.8125 0.8125 -vt 0.828125 0.8125 -vt 0.828125 0.96875 -vt 0.859375 0.96875 -vt 0.859375 1 -vt 0.828125 1 -vt 0.859375 1 -vt 0.890625 1 -vt 0.890625 0.96875 -vt 0.859375 0.96875 -vn 0.25881904510252074 0 -0.9659258262890683 -vn 0.9659258262890683 0 0.25881904510252074 -vn -0.25881904510252074 0 0.9659258262890683 -vn -0.9659258262890683 0 -0.25881904510252074 -vn 0 1 0 -vn 0 -1 0 -usemtl m_a200089f-c989-c3f8-c313-2c45240e78d7 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o tail -v 0.09375 0.2953436652829704 0.5870259660350201 -v 0.09375 0.33809618319867885 0.4695643884367815 -v 0.09375 0.11915129888561249 0.5228971891614571 -v 0.09375 0.16190381680132115 0.4054356115632185 -v -0.09375 0.33809618319867885 0.4695643884367815 -v -0.09375 0.2953436652829704 0.5870259660350201 -v -0.09375 0.16190381680132115 0.4054356115632185 -v -0.09375 0.11915129888561249 0.5228971891614571 -vt 0.890625 0.75 -vt 0.84375 0.75 -vt 0.84375 0.65625 -vt 0.890625 0.65625 -vt 0.921875 0.75 -vt 0.890625 0.75 -vt 0.890625 0.65625 -vt 0.921875 0.65625 -vt 0.96875 0.75 -vt 0.921875 0.75 -vt 0.921875 0.65625 -vt 0.96875 0.65625 -vt 0.84375 0.75 -vt 0.8125 0.75 -vt 0.8125 0.65625 -vt 0.84375 0.65625 -vt 0.84375 0.75 -vt 0.890625 0.75 -vt 0.890625 0.8125 -vt 0.84375 0.8125 -vt 0.890625 0.8125 -vt 0.9375 0.8125 -vt 0.9375 0.75 -vt 0.890625 0.75 -vn 0 0.34202014332566866 -0.9396926207859084 -vn 1 0 0 -vn 0 -0.34202014332566866 0.9396926207859084 -vn -1 0 0 -vn 0 0.9396926207859084 0.34202014332566866 -vn 0 -0.9396926207859084 -0.34202014332566866 -usemtl m_a200089f-c989-c3f8-c313-2c45240e78d7 -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 -o nose -v 0.03125 0.65625 -0.34375 -v 0.03125 0.65625 -0.40625 -v 0.03125 0.59375 -0.34375 -v 0.03125 0.59375 -0.40625 -v -0.03125 0.65625 -0.40625 -v -0.03125 0.65625 -0.34375 -v -0.03125 0.59375 -0.40625 -v -0.03125 0.59375 -0.34375 -vt 0.53125 0.6875 -vt 0.515625 0.6875 -vt 0.515625 0.65625 -vt 0.53125 0.65625 -vt 0.546875 0.6875 -vt 0.53125 0.6875 -vt 0.53125 0.65625 -vt 0.546875 0.65625 -vt 0.5625 0.6875 -vt 0.546875 0.6875 -vt 0.546875 0.65625 -vt 0.5625 0.65625 -vt 0.515625 0.6875 -vt 0.5 0.6875 -vt 0.5 0.65625 -vt 0.515625 0.65625 -vt 0.515625 0.6875 -vt 0.53125 0.6875 -vt 0.53125 0.71875 -vt 0.515625 0.71875 -vt 0.53125 0.71875 -vt 0.546875 0.71875 -vt 0.546875 0.6875 -vt 0.53125 0.6875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_a200089f-c989-c3f8-c313-2c45240e78d7 -f 92/268/67 95/267/67 93/266/67 90/265/67 -f 91/272/68 92/271/68 90/270/68 89/269/68 -f 96/276/69 91/275/69 89/274/69 94/273/69 -f 95/280/70 96/279/70 94/278/70 93/277/70 -f 94/284/71 89/283/71 90/282/71 93/281/71 -f 95/288/72 92/287/72 91/286/72 96/285/72 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/sheep.obj b/renderer/viewer/three/entity/models/sheep.obj deleted file mode 100644 index 66a2175fd..000000000 --- a/renderer/viewer/three/entity/models/sheep.obj +++ /dev/null @@ -1,555 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.25 1.1250000000000002 -0.5 -v 0.25 0.7500000000000002 -0.5 -v 0.25 1.125 0.5 -v 0.25 0.75 0.4999999999999999 -v -0.25 0.7500000000000002 -0.5 -v -0.25 1.1250000000000002 -0.5 -v -0.25 0.75 0.4999999999999999 -v -0.25 1.125 0.5 -vt 0.53125 0.78125 -vt 0.65625 0.78125 -vt 0.65625 0.53125 -vt 0.53125 0.53125 -vt 0.4375 0.78125 -vt 0.53125 0.78125 -vt 0.53125 0.53125 -vt 0.4375 0.53125 -vt 0.75 0.78125 -vt 0.875 0.78125 -vt 0.875 0.53125 -vt 0.75 0.53125 -vt 0.65625 0.78125 -vt 0.75 0.78125 -vt 0.75 0.53125 -vt 0.65625 0.53125 -vt 0.65625 0.78125 -vt 0.53125 0.78125 -vt 0.53125 0.875 -vt 0.65625 0.875 -vt 0.78125 0.875 -vt 0.65625 0.875 -vt 0.65625 0.78125 -vt 0.78125 0.78125 -vn 0 -1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 -1 -vn 0 -2.220446049250313e-16 1 -usemtl m_801e22d5-c057-fde3-2edb-c11e082736eb -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o body -v 0.359375 1.2343750000000002 -0.609375 -v 0.359375 0.6406250000000002 -0.609375 -v 0.359375 1.234375 0.609375 -v 0.359375 0.640625 0.609375 -v -0.359375 0.6406250000000002 -0.609375 -v -0.359375 1.2343750000000002 -0.609375 -v -0.359375 0.640625 0.609375 -v -0.359375 1.234375 0.609375 -vt 0.53125 0.28125 -vt 0.65625 0.28125 -vt 0.65625 0.03125 -vt 0.53125 0.03125 -vt 0.4375 0.28125 -vt 0.53125 0.28125 -vt 0.53125 0.03125 -vt 0.4375 0.03125 -vt 0.75 0.28125 -vt 0.875 0.28125 -vt 0.875 0.03125 -vt 0.75 0.03125 -vt 0.65625 0.28125 -vt 0.75 0.28125 -vt 0.75 0.03125 -vt 0.65625 0.03125 -vt 0.65625 0.28125 -vt 0.53125 0.28125 -vt 0.53125 0.375 -vt 0.65625 0.375 -vt 0.78125 0.375 -vt 0.65625 0.375 -vt 0.65625 0.28125 -vt 0.78125 0.28125 -vn 0 -1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 -1 -vn 0 -2.220446049250313e-16 1 -usemtl m_801e22d5-c057-fde3-2edb-c11e082736eb -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o head -v 0.1875 1.375 -0.375 -v 0.1875 1.375 -0.875 -v 0.1875 1 -0.375 -v 0.1875 1 -0.875 -v -0.1875 1.375 -0.875 -v -0.1875 1.375 -0.375 -v -0.1875 1 -0.875 -v -0.1875 1 -0.375 -vt 0.125 0.875 -vt 0.21875 0.875 -vt 0.21875 0.78125 -vt 0.125 0.78125 -vt 0 0.875 -vt 0.125 0.875 -vt 0.125 0.78125 -vt 0 0.78125 -vt 0.34375 0.875 -vt 0.4375 0.875 -vt 0.4375 0.78125 -vt 0.34375 0.78125 -vt 0.21875 0.875 -vt 0.34375 0.875 -vt 0.34375 0.78125 -vt 0.21875 0.78125 -vt 0.21875 0.875 -vt 0.125 0.875 -vt 0.125 1 -vt 0.21875 1 -vt 0.3125 1 -vt 0.21875 1 -vt 0.21875 0.875 -vt 0.3125 0.875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_801e22d5-c057-fde3-2edb-c11e082736eb -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o head -v 0.22499999999999998 1.4125 -0.3375 -v 0.22499999999999998 1.4125 -0.7875 -v 0.22499999999999998 0.9624999999999999 -0.3375 -v 0.22499999999999998 0.9624999999999999 -0.7875 -v -0.22499999999999998 1.4125 -0.7875 -v -0.22499999999999998 1.4125 -0.3375 -v -0.22499999999999998 0.9624999999999999 -0.7875 -v -0.22499999999999998 0.9624999999999999 -0.3375 -vt 0.09375 0.40625 -vt 0.1875 0.40625 -vt 0.1875 0.3125 -vt 0.09375 0.3125 -vt 0 0.40625 -vt 0.09375 0.40625 -vt 0.09375 0.3125 -vt 0 0.3125 -vt 0.28125 0.40625 -vt 0.375 0.40625 -vt 0.375 0.3125 -vt 0.28125 0.3125 -vt 0.1875 0.40625 -vt 0.28125 0.40625 -vt 0.28125 0.3125 -vt 0.1875 0.3125 -vt 0.1875 0.40625 -vt 0.09375 0.40625 -vt 0.09375 0.5 -vt 0.1875 0.5 -vt 0.28125 0.5 -vt 0.1875 0.5 -vt 0.1875 0.40625 -vt 0.28125 0.40625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_801e22d5-c057-fde3-2edb-c11e082736eb -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o leg0 -v 0.3125 0.75 0.5625 -v 0.3125 0.75 0.3125 -v 0.3125 0 0.5625 -v 0.3125 0 0.3125 -v 0.0625 0.75 0.3125 -v 0.0625 0.75 0.5625 -v 0.0625 0 0.3125 -v 0.0625 0 0.5625 -vt 0.0625 0.6875 -vt 0.125 0.6875 -vt 0.125 0.5 -vt 0.0625 0.5 -vt 0 0.6875 -vt 0.0625 0.6875 -vt 0.0625 0.5 -vt 0 0.5 -vt 0.1875 0.6875 -vt 0.25 0.6875 -vt 0.25 0.5 -vt 0.1875 0.5 -vt 0.125 0.6875 -vt 0.1875 0.6875 -vt 0.1875 0.5 -vt 0.125 0.5 -vt 0.125 0.6875 -vt 0.0625 0.6875 -vt 0.0625 0.75 -vt 0.125 0.75 -vt 0.1875 0.75 -vt 0.125 0.75 -vt 0.125 0.6875 -vt 0.1875 0.6875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_801e22d5-c057-fde3-2edb-c11e082736eb -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o leg0 -v 0.34375 0.78125 0.59375 -v 0.34375 0.78125 0.28125 -v 0.34375 0.34375 0.59375 -v 0.34375 0.34375 0.28125 -v 0.03125 0.78125 0.28125 -v 0.03125 0.78125 0.59375 -v 0.03125 0.34375 0.28125 -v 0.03125 0.34375 0.59375 -vt 0.0625 0.1875 -vt 0.125 0.1875 -vt 0.125 0.09375 -vt 0.0625 0.09375 -vt 0 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.09375 -vt 0 0.09375 -vt 0.1875 0.1875 -vt 0.25 0.1875 -vt 0.25 0.09375 -vt 0.1875 0.09375 -vt 0.125 0.1875 -vt 0.1875 0.1875 -vt 0.1875 0.09375 -vt 0.125 0.09375 -vt 0.125 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.25 -vt 0.125 0.25 -vt 0.1875 0.25 -vt 0.125 0.25 -vt 0.125 0.1875 -vt 0.1875 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_801e22d5-c057-fde3-2edb-c11e082736eb -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o leg1 -v -0.0625 0.75 0.5625 -v -0.0625 0.75 0.3125 -v -0.0625 0 0.5625 -v -0.0625 0 0.3125 -v -0.3125 0.75 0.3125 -v -0.3125 0.75 0.5625 -v -0.3125 0 0.3125 -v -0.3125 0 0.5625 -vt 0.0625 0.6875 -vt 0.125 0.6875 -vt 0.125 0.5 -vt 0.0625 0.5 -vt 0 0.6875 -vt 0.0625 0.6875 -vt 0.0625 0.5 -vt 0 0.5 -vt 0.1875 0.6875 -vt 0.25 0.6875 -vt 0.25 0.5 -vt 0.1875 0.5 -vt 0.125 0.6875 -vt 0.1875 0.6875 -vt 0.1875 0.5 -vt 0.125 0.5 -vt 0.125 0.6875 -vt 0.0625 0.6875 -vt 0.0625 0.75 -vt 0.125 0.75 -vt 0.1875 0.75 -vt 0.125 0.75 -vt 0.125 0.6875 -vt 0.1875 0.6875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_801e22d5-c057-fde3-2edb-c11e082736eb -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o leg1 -v -0.03125 0.78125 0.59375 -v -0.03125 0.78125 0.28125 -v -0.03125 0.34375 0.59375 -v -0.03125 0.34375 0.28125 -v -0.34375 0.78125 0.28125 -v -0.34375 0.78125 0.59375 -v -0.34375 0.34375 0.28125 -v -0.34375 0.34375 0.59375 -vt 0.0625 0.1875 -vt 0.125 0.1875 -vt 0.125 0.09375 -vt 0.0625 0.09375 -vt 0 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.09375 -vt 0 0.09375 -vt 0.1875 0.1875 -vt 0.25 0.1875 -vt 0.25 0.09375 -vt 0.1875 0.09375 -vt 0.125 0.1875 -vt 0.1875 0.1875 -vt 0.1875 0.09375 -vt 0.125 0.09375 -vt 0.125 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.25 -vt 0.125 0.25 -vt 0.1875 0.25 -vt 0.125 0.25 -vt 0.125 0.1875 -vt 0.1875 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_801e22d5-c057-fde3-2edb-c11e082736eb -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o leg2 -v 0.3125 0.75 -0.1875 -v 0.3125 0.75 -0.4375 -v 0.3125 0 -0.1875 -v 0.3125 0 -0.4375 -v 0.0625 0.75 -0.4375 -v 0.0625 0.75 -0.1875 -v 0.0625 0 -0.4375 -v 0.0625 0 -0.1875 -vt 0.0625 0.6875 -vt 0.125 0.6875 -vt 0.125 0.5 -vt 0.0625 0.5 -vt 0 0.6875 -vt 0.0625 0.6875 -vt 0.0625 0.5 -vt 0 0.5 -vt 0.1875 0.6875 -vt 0.25 0.6875 -vt 0.25 0.5 -vt 0.1875 0.5 -vt 0.125 0.6875 -vt 0.1875 0.6875 -vt 0.1875 0.5 -vt 0.125 0.5 -vt 0.125 0.6875 -vt 0.0625 0.6875 -vt 0.0625 0.75 -vt 0.125 0.75 -vt 0.1875 0.75 -vt 0.125 0.75 -vt 0.125 0.6875 -vt 0.1875 0.6875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_801e22d5-c057-fde3-2edb-c11e082736eb -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o leg2 -v 0.34375 0.78125 -0.15625 -v 0.34375 0.78125 -0.46875 -v 0.34375 0.34375 -0.15625 -v 0.34375 0.34375 -0.46875 -v 0.03125 0.78125 -0.46875 -v 0.03125 0.78125 -0.15625 -v 0.03125 0.34375 -0.46875 -v 0.03125 0.34375 -0.15625 -vt 0.0625 0.1875 -vt 0.125 0.1875 -vt 0.125 0.09375 -vt 0.0625 0.09375 -vt 0 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.09375 -vt 0 0.09375 -vt 0.1875 0.1875 -vt 0.25 0.1875 -vt 0.25 0.09375 -vt 0.1875 0.09375 -vt 0.125 0.1875 -vt 0.1875 0.1875 -vt 0.1875 0.09375 -vt 0.125 0.09375 -vt 0.125 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.25 -vt 0.125 0.25 -vt 0.1875 0.25 -vt 0.125 0.25 -vt 0.125 0.1875 -vt 0.1875 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_801e22d5-c057-fde3-2edb-c11e082736eb -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o leg3 -v -0.0625 0.75 -0.1875 -v -0.0625 0.75 -0.4375 -v -0.0625 0 -0.1875 -v -0.0625 0 -0.4375 -v -0.3125 0.75 -0.4375 -v -0.3125 0.75 -0.1875 -v -0.3125 0 -0.4375 -v -0.3125 0 -0.1875 -vt 0.0625 0.6875 -vt 0.125 0.6875 -vt 0.125 0.5 -vt 0.0625 0.5 -vt 0 0.6875 -vt 0.0625 0.6875 -vt 0.0625 0.5 -vt 0 0.5 -vt 0.1875 0.6875 -vt 0.25 0.6875 -vt 0.25 0.5 -vt 0.1875 0.5 -vt 0.125 0.6875 -vt 0.1875 0.6875 -vt 0.1875 0.5 -vt 0.125 0.5 -vt 0.125 0.6875 -vt 0.0625 0.6875 -vt 0.0625 0.75 -vt 0.125 0.75 -vt 0.1875 0.75 -vt 0.125 0.75 -vt 0.125 0.6875 -vt 0.1875 0.6875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_801e22d5-c057-fde3-2edb-c11e082736eb -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 -o leg3 -v -0.03125 0.78125 -0.15625 -v -0.03125 0.78125 -0.46875 -v -0.03125 0.34375 -0.15625 -v -0.03125 0.34375 -0.46875 -v -0.34375 0.78125 -0.46875 -v -0.34375 0.78125 -0.15625 -v -0.34375 0.34375 -0.46875 -v -0.34375 0.34375 -0.15625 -vt 0.0625 0.1875 -vt 0.125 0.1875 -vt 0.125 0.09375 -vt 0.0625 0.09375 -vt 0 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.09375 -vt 0 0.09375 -vt 0.1875 0.1875 -vt 0.25 0.1875 -vt 0.25 0.09375 -vt 0.1875 0.09375 -vt 0.125 0.1875 -vt 0.1875 0.1875 -vt 0.1875 0.09375 -vt 0.125 0.09375 -vt 0.125 0.1875 -vt 0.0625 0.1875 -vt 0.0625 0.25 -vt 0.125 0.25 -vt 0.1875 0.25 -vt 0.125 0.25 -vt 0.125 0.1875 -vt 0.1875 0.1875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_801e22d5-c057-fde3-2edb-c11e082736eb -f 92/268/67 95/267/67 93/266/67 90/265/67 -f 91/272/68 92/271/68 90/270/68 89/269/68 -f 96/276/69 91/275/69 89/274/69 94/273/69 -f 95/280/70 96/279/70 94/278/70 93/277/70 -f 94/284/71 89/283/71 90/282/71 93/281/71 -f 95/288/72 92/287/72 91/286/72 96/285/72 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/shulker.obj b/renderer/viewer/three/entity/models/shulker.obj deleted file mode 100644 index 0287fddb5..000000000 --- a/renderer/viewer/three/entity/models/shulker.obj +++ /dev/null @@ -1,141 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o base -v 0.5 0.5 0.5 -v 0.5 0.5 -0.5 -v 0.5 0 0.5 -v 0.5 0 -0.5 -v -0.5 0.5 -0.5 -v -0.5 0.5 0.5 -v -0.5 0 -0.5 -v -0.5 0 0.5 -vt 0.25 0.3125 -vt 0.5 0.3125 -vt 0.5 0.1875 -vt 0.25 0.1875 -vt 0 0.3125 -vt 0.25 0.3125 -vt 0.25 0.1875 -vt 0 0.1875 -vt 0.75 0.3125 -vt 1 0.3125 -vt 1 0.1875 -vt 0.75 0.1875 -vt 0.5 0.3125 -vt 0.75 0.3125 -vt 0.75 0.1875 -vt 0.5 0.1875 -vt 0.5 0.3125 -vt 0.25 0.3125 -vt 0.25 0.5625 -vt 0.5 0.5625 -vt 0.75 0.5625 -vt 0.5 0.5625 -vt 0.5 0.3125 -vt 0.75 0.3125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_1c25eeea-87e5-6114-747e-b8cdb1a56a09 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o lid -v 0.5 1.5625 0.5 -v 0.5 1.5625 -0.5 -v 0.5 0.8125 0.5 -v 0.5 0.8125 -0.5 -v -0.5 1.5625 -0.5 -v -0.5 1.5625 0.5 -v -0.5 0.8125 -0.5 -v -0.5 0.8125 0.5 -vt 0.25 0.75 -vt 0.5 0.75 -vt 0.5 0.5625 -vt 0.25 0.5625 -vt 0 0.75 -vt 0.25 0.75 -vt 0.25 0.5625 -vt 0 0.5625 -vt 0.75 0.75 -vt 1 0.75 -vt 1 0.5625 -vt 0.75 0.5625 -vt 0.5 0.75 -vt 0.75 0.75 -vt 0.75 0.5625 -vt 0.5 0.5625 -vt 0.5 0.75 -vt 0.25 0.75 -vt 0.25 1 -vt 0.5 1 -vt 0.75 1 -vt 0.5 1 -vt 0.5 0.75 -vt 0.75 0.75 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_1c25eeea-87e5-6114-747e-b8cdb1a56a09 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o head -v 0.1875 0.75 0.1875 -v 0.1875 0.75 -0.1875 -v 0.1875 0.375 0.1875 -v 0.1875 0.375 -0.1875 -v -0.1875 0.75 -0.1875 -v -0.1875 0.75 0.1875 -v -0.1875 0.375 -0.1875 -v -0.1875 0.375 0.1875 -vt 0.09375 0.09375 -vt 0.1875 0.09375 -vt 0.1875 0 -vt 0.09375 0 -vt 0 0.09375 -vt 0.09375 0.09375 -vt 0.09375 0 -vt 0 0 -vt 0.28125 0.09375 -vt 0.375 0.09375 -vt 0.375 0 -vt 0.28125 0 -vt 0.1875 0.09375 -vt 0.28125 0.09375 -vt 0.28125 0 -vt 0.1875 0 -vt 0.1875 0.09375 -vt 0.09375 0.09375 -vt 0.09375 0.1875 -vt 0.1875 0.1875 -vt 0.28125 0.1875 -vt 0.1875 0.1875 -vt 0.1875 0.09375 -vt 0.28125 0.09375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_1c25eeea-87e5-6114-747e-b8cdb1a56a09 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/sniffer.obj b/renderer/viewer/three/entity/models/sniffer.obj deleted file mode 100644 index 6fe8ed154..000000000 --- a/renderer/viewer/three/entity/models/sniffer.obj +++ /dev/null @@ -1,693 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.8125 2.09375 1.28125 -v 0.8125 2.09375 -1.28125 -v 0.8125 0.53125 1.28125 -v 0.8125 0.53125 -1.28125 -v -0.8125 2.09375 -1.28125 -v -0.8125 2.09375 1.28125 -v -0.8125 0.53125 -1.28125 -v -0.8125 0.53125 1.28125 -vt 0.53125 0.7916666666666666 -vt 0.6614583333333334 0.7916666666666666 -vt 0.6614583333333334 0.6666666666666667 -vt 0.53125 0.6666666666666667 -vt 0.3229166666666667 0.7916666666666666 -vt 0.53125 0.7916666666666666 -vt 0.53125 0.6666666666666667 -vt 0.3229166666666667 0.6666666666666667 -vt 0.8697916666666666 0.7916666666666666 -vt 1 0.7916666666666666 -vt 1 0.6666666666666667 -vt 0.8697916666666666 0.6666666666666667 -vt 0.6614583333333334 0.7916666666666666 -vt 0.8697916666666666 0.7916666666666666 -vt 0.8697916666666666 0.6666666666666667 -vt 0.6614583333333334 0.6666666666666667 -vt 0.6614583333333334 0.7916666666666666 -vt 0.53125 0.7916666666666666 -vt 0.53125 1 -vt 0.6614583333333334 1 -vt 0.7916666666666666 1 -vt 0.6614583333333334 1 -vt 0.6614583333333334 0.7916666666666666 -vt 0.7916666666666666 0.7916666666666666 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o body -v 0.78125 2.0625 1.25 -v 0.78125 2.0625 -1.25 -v 0.78125 0.25 1.25 -v 0.78125 0.25 -1.25 -v -0.78125 2.0625 -1.25 -v -0.78125 2.0625 1.25 -v -0.78125 0.25 -1.25 -v -0.78125 0.25 1.25 -vt 0.53125 0.4375 -vt 0.6614583333333334 0.4375 -vt 0.6614583333333334 0.28645833333333337 -vt 0.53125 0.28645833333333337 -vt 0.3229166666666667 0.4375 -vt 0.53125 0.4375 -vt 0.53125 0.28645833333333337 -vt 0.3229166666666667 0.28645833333333337 -vt 0.8697916666666666 0.4375 -vt 1 0.4375 -vt 1 0.28645833333333337 -vt 0.8697916666666666 0.28645833333333337 -vt 0.6614583333333334 0.4375 -vt 0.8697916666666666 0.4375 -vt 0.8697916666666666 0.28645833333333337 -vt 0.6614583333333334 0.28645833333333337 -vt 0.6614583333333334 0.4375 -vt 0.53125 0.4375 -vt 0.53125 0.6458333333333333 -vt 0.6614583333333334 0.6458333333333333 -vt 0.7916666666666666 0.6458333333333333 -vt 0.6614583333333334 0.6458333333333333 -vt 0.6614583333333334 0.4375 -vt 0.7916666666666666 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o body -v 0.78125 0.5 1.25 -v 0.78125 0.5 -1.25 -v 0.78125 0.5 1.25 -v 0.78125 0.5 -1.25 -v -0.78125 0.5 -1.25 -v -0.78125 0.5 1.25 -v -0.78125 0.5 -1.25 -v -0.78125 0.5 1.25 -vt 0.6614583333333334 0.4375 -vt 0.7916666666666666 0.4375 -vt 0.7916666666666666 0.4375 -vt 0.6614583333333334 0.4375 -vt 0.453125 0.4375 -vt 0.6614583333333334 0.4375 -vt 0.6614583333333334 0.4375 -vt 0.453125 0.4375 -vt 1 0.4375 -vt 1.1302083333333333 0.4375 -vt 1.1302083333333333 0.4375 -vt 1 0.4375 -vt 0.7916666666666666 0.4375 -vt 1 0.4375 -vt 1 0.4375 -vt 0.7916666666666666 0.4375 -vt 0.7916666666666666 0.4375 -vt 0.6614583333333334 0.4375 -vt 0.6614583333333334 0.6458333333333333 -vt 0.7916666666666666 0.6458333333333333 -vt 0.921875 0.6458333333333333 -vt 0.7916666666666666 0.6458333333333333 -vt 0.7916666666666666 0.4375 -vt 0.921875 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o head -v 0.40625 1.3125 -1.24375 -v 0.40625 1.3125 -1.93125 -v 0.40625 0.1875 -1.24375 -v 0.40625 0.1875 -1.93125 -v -0.40625 1.3125 -1.93125 -v -0.40625 1.3125 -1.24375 -v -0.40625 0.1875 -1.93125 -v -0.40625 0.1875 -1.24375 -vt 0.09895833333333333 0.8645833333333334 -vt 0.16666666666666666 0.8645833333333334 -vt 0.16666666666666666 0.7708333333333334 -vt 0.09895833333333333 0.7708333333333334 -vt 0.041666666666666664 0.8645833333333334 -vt 0.09895833333333333 0.8645833333333334 -vt 0.09895833333333333 0.7708333333333334 -vt 0.041666666666666664 0.7708333333333334 -vt 0.22395833333333334 0.8645833333333334 -vt 0.2916666666666667 0.8645833333333334 -vt 0.2916666666666667 0.7708333333333334 -vt 0.22395833333333334 0.7708333333333334 -vt 0.16666666666666666 0.8645833333333334 -vt 0.22395833333333334 0.8645833333333334 -vt 0.22395833333333334 0.7708333333333334 -vt 0.16666666666666666 0.7708333333333334 -vt 0.16666666666666666 0.8645833333333334 -vt 0.09895833333333333 0.8645833333333334 -vt 0.09895833333333333 0.921875 -vt 0.16666666666666666 0.921875 -vt 0.234375 0.921875 -vt 0.16666666666666666 0.921875 -vt 0.16666666666666666 0.8645833333333334 -vt 0.234375 0.8645833333333334 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o head -v 0.40625 0.375 -1.24375 -v 0.40625 0.375 -1.93125 -v 0.40625 0.375 -1.24375 -v 0.40625 0.375 -1.93125 -v -0.40625 0.375 -1.93125 -v -0.40625 0.375 -1.24375 -v -0.40625 0.375 -1.93125 -v -0.40625 0.375 -1.24375 -vt 0.09895833333333333 0.921875 -vt 0.16666666666666666 0.921875 -vt 0.16666666666666666 0.921875 -vt 0.09895833333333333 0.921875 -vt 0.041666666666666664 0.921875 -vt 0.09895833333333333 0.921875 -vt 0.09895833333333333 0.921875 -vt 0.041666666666666664 0.921875 -vt 0.22395833333333334 0.921875 -vt 0.2916666666666667 0.921875 -vt 0.2916666666666667 0.921875 -vt 0.22395833333333334 0.921875 -vt 0.16666666666666666 0.921875 -vt 0.22395833333333334 0.921875 -vt 0.22395833333333334 0.921875 -vt 0.16666666666666666 0.921875 -vt 0.16666666666666666 0.921875 -vt 0.09895833333333333 0.921875 -vt 0.09895833333333333 0.9791666666666666 -vt 0.16666666666666666 0.9791666666666666 -vt 0.234375 0.9791666666666666 -vt 0.16666666666666666 0.9791666666666666 -vt 0.16666666666666666 0.921875 -vt 0.234375 0.921875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o left_ear -v -0.4 1.3125 -1.24375 -v -0.4 1.3125 -1.68125 -v -0.4 0.125 -1.24375 -v -0.4 0.125 -1.68125 -v -0.4625 1.3125 -1.68125 -v -0.4625 1.3125 -1.24375 -v -0.4625 0.125 -1.68125 -v -0.4625 0.125 -1.24375 -vt 0.046875 0.9635416666666666 -vt 0.052083333333333336 0.9635416666666666 -vt 0.052083333333333336 0.8645833333333334 -vt 0.046875 0.8645833333333334 -vt 0.010416666666666666 0.9635416666666666 -vt 0.046875 0.9635416666666666 -vt 0.046875 0.8645833333333334 -vt 0.010416666666666666 0.8645833333333334 -vt 0.08854166666666667 0.9635416666666666 -vt 0.09375 0.9635416666666666 -vt 0.09375 0.8645833333333334 -vt 0.08854166666666667 0.8645833333333334 -vt 0.052083333333333336 0.9635416666666666 -vt 0.08854166666666667 0.9635416666666666 -vt 0.08854166666666667 0.8645833333333334 -vt 0.052083333333333336 0.8645833333333334 -vt 0.052083333333333336 0.9635416666666666 -vt 0.046875 0.9635416666666666 -vt 0.046875 1 -vt 0.052083333333333336 1 -vt 0.057291666666666664 1 -vt 0.052083333333333336 1 -vt 0.052083333333333336 0.9635416666666666 -vt 0.057291666666666664 0.9635416666666666 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o right_ear -v 0.4625 1.3125 -1.24375 -v 0.4625 1.3125 -1.68125 -v 0.4625 0.125 -1.24375 -v 0.4625 0.125 -1.68125 -v 0.4 1.3125 -1.68125 -v 0.4 1.3125 -1.24375 -v 0.4 0.125 -1.68125 -v 0.4 0.125 -1.24375 -vt 0.2864583333333333 0.9635416666666666 -vt 0.2916666666666667 0.9635416666666666 -vt 0.2916666666666667 0.8645833333333334 -vt 0.2864583333333333 0.8645833333333334 -vt 0.25 0.9635416666666666 -vt 0.2864583333333333 0.9635416666666666 -vt 0.2864583333333333 0.8645833333333334 -vt 0.25 0.8645833333333334 -vt 0.328125 0.9635416666666666 -vt 0.3333333333333333 0.9635416666666666 -vt 0.3333333333333333 0.8645833333333334 -vt 0.328125 0.8645833333333334 -vt 0.2916666666666667 0.9635416666666666 -vt 0.328125 0.9635416666666666 -vt 0.328125 0.8645833333333334 -vt 0.2916666666666667 0.8645833333333334 -vt 0.2916666666666667 0.9635416666666666 -vt 0.2864583333333333 0.9635416666666666 -vt 0.2864583333333333 1 -vt 0.2916666666666667 1 -vt 0.296875 1 -vt 0.2916666666666667 1 -vt 0.2916666666666667 0.9635416666666666 -vt 0.296875 0.9635416666666666 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o nose -v 0.40625 1.25 -1.93125 -v 0.40625 1.25 -2.49375 -v 0.40625 1.125 -1.93125 -v 0.40625 1.125 -2.49375 -v -0.40625 1.25 -2.49375 -v -0.40625 1.25 -1.93125 -v -0.40625 1.125 -2.49375 -v -0.40625 1.125 -1.93125 -vt 0.09895833333333333 0.71875 -vt 0.16666666666666666 0.71875 -vt 0.16666666666666666 0.7083333333333333 -vt 0.09895833333333333 0.7083333333333333 -vt 0.052083333333333336 0.71875 -vt 0.09895833333333333 0.71875 -vt 0.09895833333333333 0.7083333333333333 -vt 0.052083333333333336 0.7083333333333333 -vt 0.21354166666666666 0.71875 -vt 0.28125 0.71875 -vt 0.28125 0.7083333333333333 -vt 0.21354166666666666 0.7083333333333333 -vt 0.16666666666666666 0.71875 -vt 0.21354166666666666 0.71875 -vt 0.21354166666666666 0.7083333333333333 -vt 0.16666666666666666 0.7083333333333333 -vt 0.16666666666666666 0.71875 -vt 0.09895833333333333 0.71875 -vt 0.09895833333333333 0.765625 -vt 0.16666666666666666 0.765625 -vt 0.234375 0.765625 -vt 0.16666666666666666 0.765625 -vt 0.16666666666666666 0.71875 -vt 0.234375 0.71875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o lower_beak -v 0.40625 1.125 -1.93125 -v 0.40625 1.125 -2.49375 -v 0.40625 0.375 -1.93125 -v 0.40625 0.375 -2.49375 -v -0.40625 1.125 -2.49375 -v -0.40625 1.125 -1.93125 -v -0.40625 0.375 -2.49375 -v -0.40625 0.375 -1.93125 -vt 0.09895833333333333 0.65625 -vt 0.16666666666666666 0.65625 -vt 0.16666666666666666 0.59375 -vt 0.09895833333333333 0.59375 -vt 0.052083333333333336 0.65625 -vt 0.09895833333333333 0.65625 -vt 0.09895833333333333 0.59375 -vt 0.052083333333333336 0.59375 -vt 0.21354166666666666 0.65625 -vt 0.28125 0.65625 -vt 0.28125 0.59375 -vt 0.21354166666666666 0.59375 -vt 0.16666666666666666 0.65625 -vt 0.21354166666666666 0.65625 -vt 0.21354166666666666 0.59375 -vt 0.16666666666666666 0.59375 -vt 0.16666666666666666 0.65625 -vt 0.09895833333333333 0.65625 -vt 0.09895833333333333 0.703125 -vt 0.16666666666666666 0.703125 -vt 0.234375 0.703125 -vt 0.16666666666666666 0.703125 -vt 0.16666666666666666 0.65625 -vt 0.234375 0.65625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o right_front_leg -v 0.6875 0.625 -0.6875 -v 0.6875 0.625 -1.1875 -v 0.6875 0 -0.6875 -v 0.6875 0 -1.1875 -v 0.25 0.625 -1.1875 -v 0.25 0.625 -0.6875 -v 0.25 0 -1.1875 -v 0.25 0 -0.6875 -vt 0.20833333333333334 0.5052083333333333 -vt 0.24479166666666666 0.5052083333333333 -vt 0.24479166666666666 0.453125 -vt 0.20833333333333334 0.453125 -vt 0.16666666666666666 0.5052083333333333 -vt 0.20833333333333334 0.5052083333333333 -vt 0.20833333333333334 0.453125 -vt 0.16666666666666666 0.453125 -vt 0.2864583333333333 0.5052083333333333 -vt 0.3229166666666667 0.5052083333333333 -vt 0.3229166666666667 0.453125 -vt 0.2864583333333333 0.453125 -vt 0.24479166666666666 0.5052083333333333 -vt 0.2864583333333333 0.5052083333333333 -vt 0.2864583333333333 0.453125 -vt 0.24479166666666666 0.453125 -vt 0.24479166666666666 0.5052083333333333 -vt 0.20833333333333334 0.5052083333333333 -vt 0.20833333333333334 0.546875 -vt 0.24479166666666666 0.546875 -vt 0.28125 0.546875 -vt 0.24479166666666666 0.546875 -vt 0.24479166666666666 0.5052083333333333 -vt 0.28125 0.5052083333333333 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o right_mid_leg -v 0.6875 0.625 0.25 -v 0.6875 0.625 -0.25 -v 0.6875 0 0.25 -v 0.6875 0 -0.25 -v 0.25 0.625 -0.25 -v 0.25 0.625 0.25 -v 0.25 0 -0.25 -v 0.25 0 0.25 -vt 0.20833333333333334 0.41145833333333337 -vt 0.24479166666666666 0.41145833333333337 -vt 0.24479166666666666 0.359375 -vt 0.20833333333333334 0.359375 -vt 0.16666666666666666 0.41145833333333337 -vt 0.20833333333333334 0.41145833333333337 -vt 0.20833333333333334 0.359375 -vt 0.16666666666666666 0.359375 -vt 0.2864583333333333 0.41145833333333337 -vt 0.3229166666666667 0.41145833333333337 -vt 0.3229166666666667 0.359375 -vt 0.2864583333333333 0.359375 -vt 0.24479166666666666 0.41145833333333337 -vt 0.2864583333333333 0.41145833333333337 -vt 0.2864583333333333 0.359375 -vt 0.24479166666666666 0.359375 -vt 0.24479166666666666 0.41145833333333337 -vt 0.20833333333333334 0.41145833333333337 -vt 0.20833333333333334 0.453125 -vt 0.24479166666666666 0.453125 -vt 0.28125 0.453125 -vt 0.24479166666666666 0.453125 -vt 0.24479166666666666 0.41145833333333337 -vt 0.28125 0.41145833333333337 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 -o right_hind_leg -v 0.6875 0.625 1.1875 -v 0.6875 0.625 0.6875 -v 0.6875 0 1.1875 -v 0.6875 0 0.6875 -v 0.25 0.625 0.6875 -v 0.25 0.625 1.1875 -v 0.25 0 0.6875 -v 0.25 0 1.1875 -vt 0.20833333333333334 0.31770833333333337 -vt 0.24479166666666666 0.31770833333333337 -vt 0.24479166666666666 0.265625 -vt 0.20833333333333334 0.265625 -vt 0.16666666666666666 0.31770833333333337 -vt 0.20833333333333334 0.31770833333333337 -vt 0.20833333333333334 0.265625 -vt 0.16666666666666666 0.265625 -vt 0.2864583333333333 0.31770833333333337 -vt 0.3229166666666667 0.31770833333333337 -vt 0.3229166666666667 0.265625 -vt 0.2864583333333333 0.265625 -vt 0.24479166666666666 0.31770833333333337 -vt 0.2864583333333333 0.31770833333333337 -vt 0.2864583333333333 0.265625 -vt 0.24479166666666666 0.265625 -vt 0.24479166666666666 0.31770833333333337 -vt 0.20833333333333334 0.31770833333333337 -vt 0.20833333333333334 0.359375 -vt 0.24479166666666666 0.359375 -vt 0.28125 0.359375 -vt 0.24479166666666666 0.359375 -vt 0.24479166666666666 0.31770833333333337 -vt 0.28125 0.31770833333333337 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 92/268/67 95/267/67 93/266/67 90/265/67 -f 91/272/68 92/271/68 90/270/68 89/269/68 -f 96/276/69 91/275/69 89/274/69 94/273/69 -f 95/280/70 96/279/70 94/278/70 93/277/70 -f 94/284/71 89/283/71 90/282/71 93/281/71 -f 95/288/72 92/287/72 91/286/72 96/285/72 -o left_front_leg -v -0.25 0.625 -0.6875 -v -0.25 0.625 -1.1875 -v -0.25 0 -0.6875 -v -0.25 0 -1.1875 -v -0.6875 0.625 -1.1875 -v -0.6875 0.625 -0.6875 -v -0.6875 0 -1.1875 -v -0.6875 0 -0.6875 -vt 0.041666666666666664 0.5052083333333333 -vt 0.078125 0.5052083333333333 -vt 0.078125 0.453125 -vt 0.041666666666666664 0.453125 -vt 0 0.5052083333333333 -vt 0.041666666666666664 0.5052083333333333 -vt 0.041666666666666664 0.453125 -vt 0 0.453125 -vt 0.11979166666666667 0.5052083333333333 -vt 0.15625 0.5052083333333333 -vt 0.15625 0.453125 -vt 0.11979166666666667 0.453125 -vt 0.078125 0.5052083333333333 -vt 0.11979166666666667 0.5052083333333333 -vt 0.11979166666666667 0.453125 -vt 0.078125 0.453125 -vt 0.078125 0.5052083333333333 -vt 0.041666666666666664 0.5052083333333333 -vt 0.041666666666666664 0.546875 -vt 0.078125 0.546875 -vt 0.11458333333333333 0.546875 -vt 0.078125 0.546875 -vt 0.078125 0.5052083333333333 -vt 0.11458333333333333 0.5052083333333333 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 100/292/73 103/291/73 101/290/73 98/289/73 -f 99/296/74 100/295/74 98/294/74 97/293/74 -f 104/300/75 99/299/75 97/298/75 102/297/75 -f 103/304/76 104/303/76 102/302/76 101/301/76 -f 102/308/77 97/307/77 98/306/77 101/305/77 -f 103/312/78 100/311/78 99/310/78 104/309/78 -o left_mid_leg -v -0.25 0.625 0.25 -v -0.25 0.625 -0.25 -v -0.25 0 0.25 -v -0.25 0 -0.25 -v -0.6875 0.625 -0.25 -v -0.6875 0.625 0.25 -v -0.6875 0 -0.25 -v -0.6875 0 0.25 -vt 0.041666666666666664 0.41145833333333337 -vt 0.078125 0.41145833333333337 -vt 0.078125 0.359375 -vt 0.041666666666666664 0.359375 -vt 0 0.41145833333333337 -vt 0.041666666666666664 0.41145833333333337 -vt 0.041666666666666664 0.359375 -vt 0 0.359375 -vt 0.11979166666666667 0.41145833333333337 -vt 0.15625 0.41145833333333337 -vt 0.15625 0.359375 -vt 0.11979166666666667 0.359375 -vt 0.078125 0.41145833333333337 -vt 0.11979166666666667 0.41145833333333337 -vt 0.11979166666666667 0.359375 -vt 0.078125 0.359375 -vt 0.078125 0.41145833333333337 -vt 0.041666666666666664 0.41145833333333337 -vt 0.041666666666666664 0.453125 -vt 0.078125 0.453125 -vt 0.11458333333333333 0.453125 -vt 0.078125 0.453125 -vt 0.078125 0.41145833333333337 -vt 0.11458333333333333 0.41145833333333337 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 108/316/79 111/315/79 109/314/79 106/313/79 -f 107/320/80 108/319/80 106/318/80 105/317/80 -f 112/324/81 107/323/81 105/322/81 110/321/81 -f 111/328/82 112/327/82 110/326/82 109/325/82 -f 110/332/83 105/331/83 106/330/83 109/329/83 -f 111/336/84 108/335/84 107/334/84 112/333/84 -o left_hind_leg -v -0.25 0.625 1.1875 -v -0.25 0.625 0.6875 -v -0.25 0 1.1875 -v -0.25 0 0.6875 -v -0.6875 0.625 0.6875 -v -0.6875 0.625 1.1875 -v -0.6875 0 0.6875 -v -0.6875 0 1.1875 -vt 0.041666666666666664 0.31770833333333337 -vt 0.078125 0.31770833333333337 -vt 0.078125 0.265625 -vt 0.041666666666666664 0.265625 -vt 0 0.31770833333333337 -vt 0.041666666666666664 0.31770833333333337 -vt 0.041666666666666664 0.265625 -vt 0 0.265625 -vt 0.11979166666666667 0.31770833333333337 -vt 0.15625 0.31770833333333337 -vt 0.15625 0.265625 -vt 0.11979166666666667 0.265625 -vt 0.078125 0.31770833333333337 -vt 0.11979166666666667 0.31770833333333337 -vt 0.11979166666666667 0.265625 -vt 0.078125 0.265625 -vt 0.078125 0.31770833333333337 -vt 0.041666666666666664 0.31770833333333337 -vt 0.041666666666666664 0.359375 -vt 0.078125 0.359375 -vt 0.11458333333333333 0.359375 -vt 0.078125 0.359375 -vt 0.078125 0.31770833333333337 -vt 0.11458333333333333 0.31770833333333337 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_583c9f26-fb84-68dc-a891-67c1661cee33 -f 116/340/85 119/339/85 117/338/85 114/337/85 -f 115/344/86 116/343/86 114/342/86 113/341/86 -f 120/348/87 115/347/87 113/346/87 118/345/87 -f 119/352/88 120/351/88 118/350/88 117/349/88 -f 118/356/89 113/355/89 114/354/89 117/353/89 -f 119/360/90 116/359/90 115/358/90 120/357/90 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/spider.obj b/renderer/viewer/three/entity/models/spider.obj deleted file mode 100644 index eb636839c..000000000 --- a/renderer/viewer/three/entity/models/spider.obj +++ /dev/null @@ -1,509 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o head -v 0.25 0.8125 -0.1875 -v 0.25 0.8125 -0.6875 -v 0.25 0.3125 -0.1875 -v 0.25 0.3125 -0.6875 -v -0.25 0.8125 -0.6875 -v -0.25 0.8125 -0.1875 -v -0.25 0.3125 -0.6875 -v -0.25 0.3125 -0.1875 -vt 0.625 0.625 -vt 0.75 0.625 -vt 0.75 0.375 -vt 0.625 0.375 -vt 0.5 0.625 -vt 0.625 0.625 -vt 0.625 0.375 -vt 0.5 0.375 -vt 0.875 0.625 -vt 1 0.625 -vt 1 0.375 -vt 0.875 0.375 -vt 0.75 0.625 -vt 0.875 0.625 -vt 0.875 0.375 -vt 0.75 0.375 -vt 0.75 0.625 -vt 0.625 0.625 -vt 0.625 0.875 -vt 0.75 0.875 -vt 0.875 0.875 -vt 0.75 0.875 -vt 0.75 0.625 -vt 0.875 0.625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_9855f90d-c537-3611-ecbb-abc7e6cc7b17 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o body0 -v 0.1875 0.75 0.1875 -v 0.1875 0.75 -0.1875 -v 0.1875 0.375 0.1875 -v 0.1875 0.375 -0.1875 -v -0.1875 0.75 -0.1875 -v -0.1875 0.75 0.1875 -v -0.1875 0.375 -0.1875 -v -0.1875 0.375 0.1875 -vt 0.09375 0.8125 -vt 0.1875 0.8125 -vt 0.1875 0.625 -vt 0.09375 0.625 -vt 0 0.8125 -vt 0.09375 0.8125 -vt 0.09375 0.625 -vt 0 0.625 -vt 0.28125 0.8125 -vt 0.375 0.8125 -vt 0.375 0.625 -vt 0.28125 0.625 -vt 0.1875 0.8125 -vt 0.28125 0.8125 -vt 0.28125 0.625 -vt 0.1875 0.625 -vt 0.1875 0.8125 -vt 0.09375 0.8125 -vt 0.09375 1 -vt 0.1875 1 -vt 0.28125 1 -vt 0.1875 1 -vt 0.1875 0.8125 -vt 0.28125 0.8125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_9855f90d-c537-3611-ecbb-abc7e6cc7b17 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o body1 -v 0.3125 0.8125 0.9375 -v 0.3125 0.8125 0.1875 -v 0.3125 0.3125 0.9375 -v 0.3125 0.3125 0.1875 -v -0.3125 0.8125 0.1875 -v -0.3125 0.8125 0.9375 -v -0.3125 0.3125 0.1875 -v -0.3125 0.3125 0.9375 -vt 0.1875 0.25 -vt 0.34375 0.25 -vt 0.34375 0 -vt 0.1875 0 -vt 0 0.25 -vt 0.1875 0.25 -vt 0.1875 0 -vt 0 0 -vt 0.53125 0.25 -vt 0.6875 0.25 -vt 0.6875 0 -vt 0.53125 0 -vt 0.34375 0.25 -vt 0.53125 0.25 -vt 0.53125 0 -vt 0.34375 0 -vt 0.34375 0.25 -vt 0.1875 0.25 -vt 0.1875 0.625 -vt 0.34375 0.625 -vt 0.5 0.625 -vt 0.34375 0.625 -vt 0.34375 0.25 -vt 0.5 0.25 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_9855f90d-c537-3611-ecbb-abc7e6cc7b17 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o leg0 -v 0.7316941738241591 0.16919417382415936 0.8321067811865475 -v 0.7941941738241591 0.10669417382415936 0.743718433538229 -v 0.6433058261758406 0.08080582617584087 0.8321067811865475 -v 0.7058058261758406 0.018305826175840867 0.743718433538229 -v 0.29419417382415913 0.6066941738241591 0.03661165235168151 -v 0.23169417382415913 0.6691941738241591 0.125 -v 0.20580582617584076 0.5183058261758409 0.03661165235168151 -v 0.14330582617584076 0.5808058261758409 0.125 -vt 0.3125 0.9375 -vt 0.5625 0.9375 -vt 0.5625 0.875 -vt 0.3125 0.875 -vt 0.28125 0.9375 -vt 0.3125 0.9375 -vt 0.3125 0.875 -vt 0.28125 0.875 -vt 0.59375 0.9375 -vt 0.84375 0.9375 -vt 0.84375 0.875 -vt 0.59375 0.875 -vt 0.5625 0.9375 -vt 0.59375 0.9375 -vt 0.59375 0.875 -vt 0.5625 0.875 -vt 0.5625 0.9375 -vt 0.3125 0.9375 -vt 0.3125 1 -vt 0.5625 1 -vt 0.8125 1 -vt 0.5625 1 -vt 0.5625 0.9375 -vt 0.8125 0.9375 -vn 0.5 -0.5 -0.7071067811865476 -vn 0.5 -0.5 0.7071067811865477 -vn -0.5 0.5 0.7071067811865476 -vn -0.5 0.5 -0.7071067811865477 -vn 0.7071067811865477 0.7071067811865476 0 -vn -0.7071067811865477 -0.7071067811865476 0 -usemtl m_9855f90d-c537-3611-ecbb-abc7e6cc7b17 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o leg1 -v -0.23169417382415913 0.6691941738241591 0.125 -v -0.29419417382415913 0.6066941738241591 0.03661165235168151 -v -0.14330582617584076 0.5808058261758409 0.125 -v -0.20580582617584076 0.5183058261758409 0.03661165235168151 -v -0.794194173824159 0.10669417382415936 0.743718433538229 -v -0.731694173824159 0.16919417382415936 0.8321067811865475 -v -0.7058058261758406 0.018305826175840867 0.743718433538229 -v -0.6433058261758406 0.08080582617584087 0.8321067811865475 -vt 0.3125 0.9375 -vt 0.5625 0.9375 -vt 0.5625 0.875 -vt 0.3125 0.875 -vt 0.28125 0.9375 -vt 0.3125 0.9375 -vt 0.3125 0.875 -vt 0.28125 0.875 -vt 0.59375 0.9375 -vt 0.84375 0.9375 -vt 0.84375 0.875 -vt 0.59375 0.875 -vt 0.5625 0.9375 -vt 0.59375 0.9375 -vt 0.59375 0.875 -vt 0.5625 0.875 -vt 0.5625 0.9375 -vt 0.3125 0.9375 -vt 0.3125 1 -vt 0.5625 1 -vt 0.8125 1 -vt 0.5625 1 -vt 0.5625 0.9375 -vt 0.8125 0.9375 -vn -0.5 -0.5 -0.7071067811865476 -vn 0.5 0.5 -0.7071067811865477 -vn 0.5 0.5 0.7071067811865476 -vn -0.5 -0.5 0.7071067811865477 -vn -0.7071067811865477 0.7071067811865476 0 -vn 0.7071067811865477 -0.7071067811865476 0 -usemtl m_9855f90d-c537-3611-ecbb-abc7e6cc7b17 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o leg2 -v 1.0143853759373593 0.10357000946898909 0.36551321892668 -v 1.0408868946744412 0.08501344627527851 0.2447724906405464 -v 0.9426883213934785 0.0011760039328650995 0.36551321892668 -v 0.9691898401305603 -0.017380559260845474 0.2447724906405464 -v 0.24964677943821734 0.6390457394976019 -0.014046554461974337 -v 0.2231452607011355 0.6576023026913125 0.10669417382415924 -v 0.17794972489433658 0.5366517339614778 -0.014046554461974337 -v 0.15144820615725474 0.5552082971551884 0.10669417382415924 -vt 0.3125 0.9375 -vt 0.5625 0.9375 -vt 0.5625 0.875 -vt 0.3125 0.875 -vt 0.28125 0.9375 -vt 0.3125 0.9375 -vt 0.3125 0.875 -vt 0.28125 0.875 -vt 0.59375 0.9375 -vt 0.84375 0.9375 -vt 0.84375 0.875 -vt 0.59375 0.875 -vt 0.5625 0.9375 -vt 0.59375 0.9375 -vt 0.59375 0.875 -vt 0.5625 0.875 -vt 0.5625 0.9375 -vt 0.3125 0.9375 -vt 0.3125 1 -vt 0.5625 1 -vt 0.8125 1 -vt 0.5625 1 -vt 0.5625 0.9375 -vt 0.8125 0.9375 -vn 0.21201214989665462 -0.1484525055496845 -0.9659258262890683 -vn 0.7912401152362238 -0.5540322932223234 0.25881904510252074 -vn -0.21201214989665462 0.1484525055496845 0.9659258262890683 -vn -0.7912401152362238 0.5540322932223234 -0.25881904510252074 -vn 0.5735764363510462 0.8191520442889919 1.387778780781446e-17 -vn -0.5735764363510462 -0.8191520442889919 -1.387778780781446e-17 -usemtl m_9855f90d-c537-3611-ecbb-abc7e6cc7b17 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o leg3 -v -0.2231452607011355 0.6576023026913125 0.10669417382415924 -v -0.24964677943821734 0.6390457394976019 -0.014046554461974337 -v -0.15144820615725474 0.5552082971551884 0.10669417382415924 -v -0.17794972489433658 0.5366517339614778 -0.014046554461974337 -v -1.0408868946744412 0.08501344627527851 0.2447724906405464 -v -1.0143853759373593 0.10357000946898909 0.36551321892668 -v -0.9691898401305603 -0.017380559260845474 0.2447724906405464 -v -0.9426883213934785 0.0011760039328650995 0.36551321892668 -vt 0.3125 0.9375 -vt 0.5625 0.9375 -vt 0.5625 0.875 -vt 0.3125 0.875 -vt 0.28125 0.9375 -vt 0.3125 0.9375 -vt 0.3125 0.875 -vt 0.28125 0.875 -vt 0.59375 0.9375 -vt 0.84375 0.9375 -vt 0.84375 0.875 -vt 0.59375 0.875 -vt 0.5625 0.9375 -vt 0.59375 0.9375 -vt 0.59375 0.875 -vt 0.5625 0.875 -vt 0.5625 0.9375 -vt 0.3125 0.9375 -vt 0.3125 1 -vt 0.5625 1 -vt 0.8125 1 -vt 0.5625 1 -vt 0.5625 0.9375 -vt 0.8125 0.9375 -vn -0.21201214989665462 -0.1484525055496845 -0.9659258262890683 -vn 0.7912401152362238 0.5540322932223234 -0.25881904510252074 -vn 0.21201214989665462 0.1484525055496845 0.9659258262890683 -vn -0.7912401152362238 -0.5540322932223234 0.25881904510252074 -vn -0.5735764363510462 0.8191520442889919 1.387778780781446e-17 -vn 0.5735764363510462 -0.8191520442889919 -1.387778780781446e-17 -usemtl m_9855f90d-c537-3611-ecbb-abc7e6cc7b17 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o leg4 -v 1.0408868946744412 0.08501344627527851 -0.1822724906405464 -v 1.0143853759373593 0.10357000946898909 -0.30301321892668 -v 0.9691898401305603 -0.017380559260845474 -0.1822724906405464 -v 0.9426883213934785 0.0011760039328650995 -0.30301321892668 -v 0.2231452607011355 0.6576023026913125 -0.044194173824159244 -v 0.24964677943821734 0.6390457394976019 0.07654655446197434 -v 0.15144820615725474 0.5552082971551884 -0.044194173824159244 -v 0.17794972489433658 0.5366517339614778 0.07654655446197434 -vt 0.3125 0.9375 -vt 0.5625 0.9375 -vt 0.5625 0.875 -vt 0.3125 0.875 -vt 0.28125 0.9375 -vt 0.3125 0.9375 -vt 0.3125 0.875 -vt 0.28125 0.875 -vt 0.59375 0.9375 -vt 0.84375 0.9375 -vt 0.84375 0.875 -vt 0.59375 0.875 -vt 0.5625 0.9375 -vt 0.59375 0.9375 -vt 0.59375 0.875 -vt 0.5625 0.875 -vt 0.5625 0.9375 -vt 0.3125 0.9375 -vt 0.3125 1 -vt 0.5625 1 -vt 0.8125 1 -vt 0.5625 1 -vt 0.5625 0.9375 -vt 0.8125 0.9375 -vn -0.21201214989665462 0.1484525055496845 -0.9659258262890683 -vn 0.7912401152362238 -0.5540322932223234 -0.25881904510252074 -vn 0.21201214989665462 -0.1484525055496845 0.9659258262890683 -vn -0.7912401152362238 0.5540322932223234 0.25881904510252074 -vn 0.5735764363510462 0.8191520442889919 -1.387778780781446e-17 -vn -0.5735764363510462 -0.8191520442889919 1.387778780781446e-17 -usemtl m_9855f90d-c537-3611-ecbb-abc7e6cc7b17 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o leg5 -v -0.24964677943821734 0.6390457394976019 0.07654655446197434 -v -0.2231452607011355 0.6576023026913125 -0.044194173824159244 -v -0.17794972489433658 0.5366517339614778 0.07654655446197434 -v -0.15144820615725474 0.5552082971551884 -0.044194173824159244 -v -1.0143853759373593 0.10357000946898909 -0.30301321892668 -v -1.0408868946744412 0.08501344627527851 -0.1822724906405464 -v -0.9426883213934785 0.0011760039328650995 -0.30301321892668 -v -0.9691898401305603 -0.017380559260845474 -0.1822724906405464 -vt 0.3125 0.9375 -vt 0.5625 0.9375 -vt 0.5625 0.875 -vt 0.3125 0.875 -vt 0.28125 0.9375 -vt 0.3125 0.9375 -vt 0.3125 0.875 -vt 0.28125 0.875 -vt 0.59375 0.9375 -vt 0.84375 0.9375 -vt 0.84375 0.875 -vt 0.59375 0.875 -vt 0.5625 0.9375 -vt 0.59375 0.9375 -vt 0.59375 0.875 -vt 0.5625 0.875 -vt 0.5625 0.9375 -vt 0.3125 0.9375 -vt 0.3125 1 -vt 0.5625 1 -vt 0.8125 1 -vt 0.5625 1 -vt 0.5625 0.9375 -vt 0.8125 0.9375 -vn 0.21201214989665462 0.1484525055496845 -0.9659258262890683 -vn 0.7912401152362238 0.5540322932223234 0.25881904510252074 -vn -0.21201214989665462 -0.1484525055496845 0.9659258262890683 -vn -0.7912401152362238 -0.5540322932223234 -0.25881904510252074 -vn -0.5735764363510462 0.8191520442889919 -1.387778780781446e-17 -vn 0.5735764363510462 -0.8191520442889919 1.387778780781446e-17 -usemtl m_9855f90d-c537-3611-ecbb-abc7e6cc7b17 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o leg6 -v 0.7941941738241591 0.10669417382415936 -0.681218433538229 -v 0.7316941738241591 0.16919417382415936 -0.7696067811865475 -v 0.7058058261758406 0.018305826175840867 -0.681218433538229 -v 0.6433058261758406 0.08080582617584087 -0.7696067811865475 -v 0.23169417382415913 0.6691941738241591 -0.0625 -v 0.29419417382415913 0.6066941738241591 0.025888347648318488 -v 0.14330582617584076 0.5808058261758409 -0.0625 -v 0.20580582617584076 0.5183058261758409 0.025888347648318488 -vt 0.3125 0.9375 -vt 0.5625 0.9375 -vt 0.5625 0.875 -vt 0.3125 0.875 -vt 0.28125 0.9375 -vt 0.3125 0.9375 -vt 0.3125 0.875 -vt 0.28125 0.875 -vt 0.59375 0.9375 -vt 0.84375 0.9375 -vt 0.84375 0.875 -vt 0.59375 0.875 -vt 0.5625 0.9375 -vt 0.59375 0.9375 -vt 0.59375 0.875 -vt 0.5625 0.875 -vt 0.5625 0.9375 -vt 0.3125 0.9375 -vt 0.3125 1 -vt 0.5625 1 -vt 0.8125 1 -vt 0.5625 1 -vt 0.5625 0.9375 -vt 0.8125 0.9375 -vn -0.5 0.5 -0.7071067811865476 -vn 0.5 -0.5 -0.7071067811865477 -vn 0.5 -0.5 0.7071067811865476 -vn -0.5 0.5 0.7071067811865477 -vn 0.7071067811865477 0.7071067811865476 0 -vn -0.7071067811865477 -0.7071067811865476 0 -usemtl m_9855f90d-c537-3611-ecbb-abc7e6cc7b17 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o leg7 -v -0.29419417382415913 0.6066941738241591 0.025888347648318488 -v -0.23169417382415913 0.6691941738241591 -0.0625 -v -0.20580582617584076 0.5183058261758409 0.025888347648318488 -v -0.14330582617584076 0.5808058261758409 -0.0625 -v -0.731694173824159 0.16919417382415936 -0.7696067811865475 -v -0.794194173824159 0.10669417382415936 -0.681218433538229 -v -0.6433058261758406 0.08080582617584087 -0.7696067811865475 -v -0.7058058261758406 0.018305826175840867 -0.681218433538229 -vt 0.3125 0.9375 -vt 0.5625 0.9375 -vt 0.5625 0.875 -vt 0.3125 0.875 -vt 0.28125 0.9375 -vt 0.3125 0.9375 -vt 0.3125 0.875 -vt 0.28125 0.875 -vt 0.59375 0.9375 -vt 0.84375 0.9375 -vt 0.84375 0.875 -vt 0.59375 0.875 -vt 0.5625 0.9375 -vt 0.59375 0.9375 -vt 0.59375 0.875 -vt 0.5625 0.875 -vt 0.5625 0.9375 -vt 0.3125 0.9375 -vt 0.3125 1 -vt 0.5625 1 -vt 0.8125 1 -vt 0.5625 1 -vt 0.5625 0.9375 -vt 0.8125 0.9375 -vn 0.5 0.5 -0.7071067811865476 -vn 0.5 0.5 0.7071067811865477 -vn -0.5 -0.5 0.7071067811865476 -vn -0.5 -0.5 -0.7071067811865477 -vn -0.7071067811865477 0.7071067811865476 0 -vn 0.7071067811865477 -0.7071067811865476 0 -usemtl m_9855f90d-c537-3611-ecbb-abc7e6cc7b17 -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/tadpole.obj b/renderer/viewer/three/entity/models/tadpole.obj deleted file mode 100644 index b38c8a269..000000000 --- a/renderer/viewer/three/entity/models/tadpole.obj +++ /dev/null @@ -1,95 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.09375 0.1875 0.03125 -v 0.09375 0.1875 -0.15625 -v 0.09375 0.0625 0.03125 -v 0.09375 0.0625 -0.15625 -v -0.09375 0.1875 -0.15625 -v -0.09375 0.1875 0.03125 -v -0.09375 0.0625 -0.15625 -v -0.09375 0.0625 0.03125 -vt 0.1875 0.8125 -vt 0.375 0.8125 -vt 0.375 0.6875 -vt 0.1875 0.6875 -vt 0 0.8125 -vt 0.1875 0.8125 -vt 0.1875 0.6875 -vt 0 0.6875 -vt 0.5625 0.8125 -vt 0.75 0.8125 -vt 0.75 0.6875 -vt 0.5625 0.6875 -vt 0.375 0.8125 -vt 0.5625 0.8125 -vt 0.5625 0.6875 -vt 0.375 0.6875 -vt 0.375 0.8125 -vt 0.1875 0.8125 -vt 0.1875 1 -vt 0.375 1 -vt 0.5625 1 -vt 0.375 1 -vt 0.375 0.8125 -vt 0.5625 0.8125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_71a3df64-a731-05a3-e848-ff24e21209ec -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o tail -v 0 0.1875 0.40625 -v 0 0.1875 -0.03125 -v 0 0.0625 0.40625 -v 0 0.0625 -0.03125 -v 0 0.1875 -0.03125 -v 0 0.1875 0.40625 -v 0 0.0625 -0.03125 -v 0 0.0625 0.40625 -vt 0.4375 0.5625 -vt 0.4375 0.5625 -vt 0.4375 0.4375 -vt 0.4375 0.4375 -vt 0 0.5625 -vt 0.4375 0.5625 -vt 0.4375 0.4375 -vt 0 0.4375 -vt 0.875 0.5625 -vt 0.875 0.5625 -vt 0.875 0.4375 -vt 0.875 0.4375 -vt 0.4375 0.5625 -vt 0.875 0.5625 -vt 0.875 0.4375 -vt 0.4375 0.4375 -vt 0.4375 0.5625 -vt 0.4375 0.5625 -vt 0.4375 1 -vt 0.4375 1 -vt 0.4375 1 -vt 0.4375 1 -vt 0.4375 0.5625 -vt 0.4375 0.5625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_71a3df64-a731-05a3-e848-ff24e21209ec -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/turtle.obj b/renderer/viewer/three/entity/models/turtle.obj deleted file mode 100644 index ac0d41b9b..000000000 --- a/renderer/viewer/three/entity/models/turtle.obj +++ /dev/null @@ -1,371 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.59375 0.5625 -0.4375000000000001 -v 0.59375 0.1875 -0.4375000000000001 -v 0.59375 0.5624999999999996 0.8125 -v 0.59375 0.18749999999999956 0.8125 -v -0.59375 0.1875 -0.4375000000000001 -v -0.59375 0.5625 -0.4375000000000001 -v -0.59375 0.18749999999999956 0.8125 -v -0.59375 0.5624999999999996 0.8125 -vt 0.1015625 0.328125 -vt 0.25 0.328125 -vt 0.25 0.015625 -vt 0.1015625 0.015625 -vt 0.0546875 0.328125 -vt 0.1015625 0.328125 -vt 0.1015625 0.015625 -vt 0.0546875 0.015625 -vt 0.296875 0.328125 -vt 0.4453125 0.328125 -vt 0.4453125 0.015625 -vt 0.296875 0.015625 -vt 0.25 0.328125 -vt 0.296875 0.328125 -vt 0.296875 0.015625 -vt 0.25 0.015625 -vt 0.25 0.328125 -vt 0.1015625 0.328125 -vt 0.1015625 0.421875 -vt 0.25 0.421875 -vt 0.3984375 0.421875 -vt 0.25 0.421875 -vt 0.25 0.328125 -vt 0.3984375 0.328125 -vn 0 -1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 -1 -vn 0 -2.220446049250313e-16 1 -usemtl m_d5e023f1-fe9e-4631-8a6b-282685c9cca4 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o body -v 0.34375 0.1875 -0.4375000000000001 -v 0.34375 0 -0.4375000000000002 -v 0.34375 0.18749999999999978 0.6874999999999998 -v 0.34375 -2.220446049250313e-16 0.6874999999999998 -v -0.34375 0 -0.4375000000000002 -v -0.34375 0.1875 -0.4375000000000001 -v -0.34375 -2.220446049250313e-16 0.6874999999999998 -v -0.34375 0.18749999999999978 0.6874999999999998 -vt 0.265625 0.9375 -vt 0.3515625 0.9375 -vt 0.3515625 0.65625 -vt 0.265625 0.65625 -vt 0.2421875 0.9375 -vt 0.265625 0.9375 -vt 0.265625 0.65625 -vt 0.2421875 0.65625 -vt 0.375 0.9375 -vt 0.4609375 0.9375 -vt 0.4609375 0.65625 -vt 0.375 0.65625 -vt 0.3515625 0.9375 -vt 0.375 0.9375 -vt 0.375 0.65625 -vt 0.3515625 0.65625 -vt 0.3515625 0.9375 -vt 0.265625 0.9375 -vt 0.265625 0.984375 -vt 0.3515625 0.984375 -vt 0.4375 0.984375 -vt 0.3515625 0.984375 -vt 0.3515625 0.9375 -vt 0.4375 0.9375 -vn 0 -1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 -1 -vn 0 -2.220446049250313e-16 1 -usemtl m_d5e023f1-fe9e-4631-8a6b-282685c9cca4 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o eggbelly -v 0.28125 0 -0.4375000000000002 -v 0.28125 -0.0625 -0.4375000000000002 -v 0.28125 -2.220446049250313e-16 0.6874999999999998 -v 0.28125 -0.06250000000000022 0.6874999999999998 -v -0.28125 -0.0625 -0.4375000000000002 -v -0.28125 0 -0.4375000000000002 -v -0.28125 -0.06250000000000022 0.6874999999999998 -v -0.28125 -2.220446049250313e-16 0.6874999999999998 -vt 0.5546875 0.46875 -vt 0.625 0.46875 -vt 0.625 0.1875 -vt 0.5546875 0.1875 -vt 0.546875 0.46875 -vt 0.5546875 0.46875 -vt 0.5546875 0.1875 -vt 0.546875 0.1875 -vt 0.6328125 0.46875 -vt 0.703125 0.46875 -vt 0.703125 0.1875 -vt 0.6328125 0.1875 -vt 0.625 0.46875 -vt 0.6328125 0.46875 -vt 0.6328125 0.1875 -vt 0.625 0.1875 -vt 0.625 0.46875 -vt 0.5546875 0.46875 -vt 0.5546875 0.484375 -vt 0.625 0.484375 -vt 0.6953125 0.484375 -vt 0.625 0.484375 -vt 0.625 0.46875 -vt 0.6953125 0.46875 -vn 0 -1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 -1 -vn 0 -2.220446049250313e-16 1 -usemtl m_d5e023f1-fe9e-4631-8a6b-282685c9cca4 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o head -v 0.1875 0.375 -0.4375 -v 0.1875 0.375 -0.8125 -v 0.1875 0.0625 -0.4375 -v 0.1875 0.0625 -0.8125 -v -0.1875 0.375 -0.8125 -v -0.1875 0.375 -0.4375 -v -0.1875 0.0625 -0.8125 -v -0.1875 0.0625 -0.4375 -vt 0.0703125 0.90625 -vt 0.1171875 0.90625 -vt 0.1171875 0.828125 -vt 0.0703125 0.828125 -vt 0.0234375 0.90625 -vt 0.0703125 0.90625 -vt 0.0703125 0.828125 -vt 0.0234375 0.828125 -vt 0.1640625 0.90625 -vt 0.2109375 0.90625 -vt 0.2109375 0.828125 -vt 0.1640625 0.828125 -vt 0.1171875 0.90625 -vt 0.1640625 0.90625 -vt 0.1640625 0.828125 -vt 0.1171875 0.828125 -vt 0.1171875 0.90625 -vt 0.0703125 0.90625 -vt 0.0703125 1 -vt 0.1171875 1 -vt 0.1640625 1 -vt 0.1171875 1 -vt 0.1171875 0.90625 -vt 0.1640625 0.90625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_d5e023f1-fe9e-4631-8a6b-282685c9cca4 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o leg0 -v 0.34375 0.125 1.3125 -v 0.34375 0.125 0.6875 -v 0.34375 0.0625 1.3125 -v 0.34375 0.0625 0.6875 -v 0.09375 0.125 0.6875 -v 0.09375 0.125 1.3125 -v 0.09375 0.0625 0.6875 -v 0.09375 0.0625 1.3125 -vt 0.0859375 0.484375 -vt 0.1171875 0.484375 -vt 0.1171875 0.46875 -vt 0.0859375 0.46875 -vt 0.0078125 0.484375 -vt 0.0859375 0.484375 -vt 0.0859375 0.46875 -vt 0.0078125 0.46875 -vt 0.1953125 0.484375 -vt 0.2265625 0.484375 -vt 0.2265625 0.46875 -vt 0.1953125 0.46875 -vt 0.1171875 0.484375 -vt 0.1953125 0.484375 -vt 0.1953125 0.46875 -vt 0.1171875 0.46875 -vt 0.1171875 0.484375 -vt 0.0859375 0.484375 -vt 0.0859375 0.640625 -vt 0.1171875 0.640625 -vt 0.1484375 0.640625 -vt 0.1171875 0.640625 -vt 0.1171875 0.484375 -vt 0.1484375 0.484375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_d5e023f1-fe9e-4631-8a6b-282685c9cca4 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o leg1 -v -0.09375 0.125 1.3125 -v -0.09375 0.125 0.6875 -v -0.09375 0.0625 1.3125 -v -0.09375 0.0625 0.6875 -v -0.34375 0.125 0.6875 -v -0.34375 0.125 1.3125 -v -0.34375 0.0625 0.6875 -v -0.34375 0.0625 1.3125 -vt 0.0859375 0.65625 -vt 0.1171875 0.65625 -vt 0.1171875 0.640625 -vt 0.0859375 0.640625 -vt 0.0078125 0.65625 -vt 0.0859375 0.65625 -vt 0.0859375 0.640625 -vt 0.0078125 0.640625 -vt 0.1953125 0.65625 -vt 0.2265625 0.65625 -vt 0.2265625 0.640625 -vt 0.1953125 0.640625 -vt 0.1171875 0.65625 -vt 0.1953125 0.65625 -vt 0.1953125 0.640625 -vt 0.1171875 0.640625 -vt 0.1171875 0.65625 -vt 0.0859375 0.65625 -vt 0.0859375 0.8125 -vt 0.1171875 0.8125 -vt 0.1484375 0.8125 -vt 0.1171875 0.8125 -vt 0.1171875 0.65625 -vt 0.1484375 0.65625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_d5e023f1-fe9e-4631-8a6b-282685c9cca4 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o leg2 -v 1.0800972660098695 0.1875 0.07574059804416988 -v 1.1343623215307852 0.1875 -0.2320118247721451 -v 1.0800972660098695 0.125 0.07574059804416988 -v 1.1343623215307852 0.125 -0.2320118247721451 -v 0.33420602220836626 0.1875 -0.373100969126526 -v 0.2799409666874506 0.1875 -0.06534854631021103 -v 0.33420602220836626 0.125 -0.373100969126526 -v 0.2799409666874506 0.125 -0.06534854631021103 -vt 0.25 0.453125 -vt 0.3515625 0.453125 -vt 0.3515625 0.4375 -vt 0.25 0.4375 -vt 0.2109375 0.453125 -vt 0.25 0.453125 -vt 0.25 0.4375 -vt 0.2109375 0.4375 -vt 0.390625 0.453125 -vt 0.4921875 0.453125 -vt 0.4921875 0.4375 -vt 0.390625 0.4375 -vt 0.3515625 0.453125 -vt 0.390625 0.453125 -vt 0.390625 0.4375 -vt 0.3515625 0.4375 -vt 0.3515625 0.453125 -vt 0.25 0.453125 -vt 0.25 0.53125 -vt 0.3515625 0.53125 -vt 0.453125 0.53125 -vt 0.3515625 0.53125 -vt 0.3515625 0.453125 -vt 0.453125 0.453125 -vn 0.17364817766693033 0 -0.984807753012208 -vn 0.984807753012208 0 0.17364817766693033 -vn -0.17364817766693033 0 0.984807753012208 -vn -0.984807753012208 0 -0.17364817766693033 -vn 0 1 0 -vn 0 -1 0 -usemtl m_d5e023f1-fe9e-4631-8a6b-282685c9cca4 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o leg3 -v -0.27994096668745055 0.1875 -0.06534854631021103 -v -0.3342060222083663 0.1875 -0.373100969126526 -v -0.27994096668745055 0.125 -0.06534854631021103 -v -0.3342060222083663 0.125 -0.373100969126526 -v -1.1343623215307852 0.1875 -0.2320118247721451 -v -1.0800972660098695 0.1875 0.07574059804416988 -v -1.1343623215307852 0.125 -0.2320118247721451 -v -1.0800972660098695 0.125 0.07574059804416988 -vt 0.25 0.546875 -vt 0.3515625 0.546875 -vt 0.3515625 0.53125 -vt 0.25 0.53125 -vt 0.2109375 0.546875 -vt 0.25 0.546875 -vt 0.25 0.53125 -vt 0.2109375 0.53125 -vt 0.390625 0.546875 -vt 0.4921875 0.546875 -vt 0.4921875 0.53125 -vt 0.390625 0.53125 -vt 0.3515625 0.546875 -vt 0.390625 0.546875 -vt 0.390625 0.53125 -vt 0.3515625 0.53125 -vt 0.3515625 0.546875 -vt 0.25 0.546875 -vt 0.25 0.625 -vt 0.3515625 0.625 -vt 0.453125 0.625 -vt 0.3515625 0.625 -vt 0.3515625 0.546875 -vt 0.453125 0.546875 -vn -0.17364817766693033 0 -0.984807753012208 -vn 0.984807753012208 0 -0.17364817766693033 -vn 0.17364817766693033 0 0.984807753012208 -vn -0.984807753012208 0 0.17364817766693033 -vn 0 1 0 -vn 0 -1 0 -usemtl m_d5e023f1-fe9e-4631-8a6b-282685c9cca4 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/vex.obj b/renderer/viewer/three/entity/models/vex.obj deleted file mode 100644 index 63d99f88f..000000000 --- a/renderer/viewer/three/entity/models/vex.obj +++ /dev/null @@ -1,325 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.09375 0.25 0.0625 -v 0.09375 0.25 -0.0625 -v 0.09375 0 0.0625 -v 0.09375 0 -0.0625 -v -0.09375 0.25 -0.0625 -v -0.09375 0.25 0.0625 -v -0.09375 0 -0.0625 -v -0.09375 0 0.0625 -vt 0.0625 0.625 -vt 0.15625 0.625 -vt 0.15625 0.5 -vt 0.0625 0.5 -vt 0 0.625 -vt 0.0625 0.625 -vt 0.0625 0.5 -vt 0 0.5 -vt 0.21875 0.625 -vt 0.3125 0.625 -vt 0.3125 0.5 -vt 0.21875 0.5 -vt 0.15625 0.625 -vt 0.21875 0.625 -vt 0.21875 0.5 -vt 0.15625 0.5 -vt 0.15625 0.625 -vt 0.0625 0.625 -vt 0.0625 0.6875 -vt 0.15625 0.6875 -vt 0.25 0.6875 -vt 0.15625 0.6875 -vt 0.15625 0.625 -vt 0.25 0.625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_f88b8145-cdbb-8011-03d2-81deb45b4e43 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o body -v 0.08125000000000004 0.17500000000000004 0.050000000000000044 -v 0.08125000000000004 0.17500000000000004 -0.04999999999999999 -v 0.08125000000000004 -0.11249999999999999 0.050000000000000044 -v 0.08125000000000004 -0.11249999999999999 -0.04999999999999999 -v -0.08124999999999999 0.17500000000000004 -0.04999999999999999 -v -0.08124999999999999 0.17500000000000004 0.050000000000000044 -v -0.08124999999999999 -0.11249999999999999 -0.04999999999999999 -v -0.08124999999999999 -0.11249999999999999 0.050000000000000044 -vt 0.0625 0.4375 -vt 0.15625 0.4375 -vt 0.15625 0.28125 -vt 0.0625 0.28125 -vt 0 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.28125 -vt 0 0.28125 -vt 0.21875 0.4375 -vt 0.3125 0.4375 -vt 0.3125 0.28125 -vt 0.21875 0.28125 -vt 0.15625 0.4375 -vt 0.21875 0.4375 -vt 0.21875 0.28125 -vt 0.15625 0.28125 -vt 0.15625 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.5 -vt 0.15625 0.5 -vt 0.25 0.5 -vt 0.15625 0.5 -vt 0.15625 0.4375 -vt 0.25 0.4375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_f88b8145-cdbb-8011-03d2-81deb45b4e43 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o head -v 0.15625 0.5625 0.15625 -v 0.15625 0.5625 -0.15625 -v 0.15625 0.25 0.15625 -v 0.15625 0.25 -0.15625 -v -0.15625 0.5625 -0.15625 -v -0.15625 0.5625 0.15625 -v -0.15625 0.25 -0.15625 -v -0.15625 0.25 0.15625 -vt 0.15625 0.84375 -vt 0.3125 0.84375 -vt 0.3125 0.6875 -vt 0.15625 0.6875 -vt 0 0.84375 -vt 0.15625 0.84375 -vt 0.15625 0.6875 -vt 0 0.6875 -vt 0.46875 0.84375 -vt 0.625 0.84375 -vt 0.625 0.6875 -vt 0.46875 0.6875 -vt 0.3125 0.84375 -vt 0.46875 0.84375 -vt 0.46875 0.6875 -vt 0.3125 0.6875 -vt 0.3125 0.84375 -vt 0.15625 0.84375 -vt 0.15625 1 -vt 0.3125 1 -vt 0.46875 1 -vt 0.3125 1 -vt 0.3125 0.84375 -vt 0.46875 0.84375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_f88b8145-cdbb-8011-03d2-81deb45b4e43 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o rightArm -v 0.18125000000000002 0.259375 0.05625000000000002 -v 0.18125000000000002 0.259375 -0.05625000000000002 -v 0.18125000000000002 0.021874999999999978 0.05625000000000002 -v 0.18125000000000002 0.021874999999999978 -0.05625000000000002 -v 0.06874999999999998 0.259375 -0.05625000000000002 -v 0.06874999999999998 0.259375 0.05625000000000002 -v 0.06874999999999998 0.021874999999999978 -0.05625000000000002 -v 0.06874999999999998 0.021874999999999978 0.05625000000000002 -vt 0.78125 0.9375 -vt 0.84375 0.9375 -vt 0.84375 0.8125 -vt 0.78125 0.8125 -vt 0.71875 0.9375 -vt 0.78125 0.9375 -vt 0.78125 0.8125 -vt 0.71875 0.8125 -vt 0.90625 0.9375 -vt 0.96875 0.9375 -vt 0.96875 0.8125 -vt 0.90625 0.8125 -vt 0.84375 0.9375 -vt 0.90625 0.9375 -vt 0.90625 0.8125 -vt 0.84375 0.8125 -vt 0.84375 0.9375 -vt 0.78125 0.9375 -vt 0.78125 1 -vt 0.84375 1 -vt 0.90625 1 -vt 0.84375 1 -vt 0.84375 0.9375 -vt 0.90625 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_f88b8145-cdbb-8011-03d2-81deb45b4e43 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o leftArm -v -0.06874999999999998 0.259375 0.05625000000000002 -v -0.06874999999999998 0.259375 -0.05625000000000002 -v -0.06874999999999998 0.021874999999999978 0.05625000000000002 -v -0.06874999999999998 0.021874999999999978 -0.05625000000000002 -v -0.18125000000000002 0.259375 -0.05625000000000002 -v -0.18125000000000002 0.259375 0.05625000000000002 -v -0.18125000000000002 0.021874999999999978 -0.05625000000000002 -v -0.18125000000000002 0.021874999999999978 0.05625000000000002 -vt 0.78125 0.75 -vt 0.84375 0.75 -vt 0.84375 0.625 -vt 0.78125 0.625 -vt 0.71875 0.75 -vt 0.78125 0.75 -vt 0.78125 0.625 -vt 0.71875 0.625 -vt 0.90625 0.75 -vt 0.96875 0.75 -vt 0.96875 0.625 -vt 0.90625 0.625 -vt 0.84375 0.75 -vt 0.90625 0.75 -vt 0.90625 0.625 -vt 0.84375 0.625 -vt 0.84375 0.75 -vt 0.78125 0.75 -vt 0.78125 0.8125 -vt 0.84375 0.8125 -vt 0.90625 0.8125 -vt 0.84375 0.8125 -vt 0.84375 0.75 -vt 0.90625 0.75 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_f88b8145-cdbb-8011-03d2-81deb45b4e43 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o leftWing -v -0.03125 0.1875 0.0625 -v -0.03125 0.1875 0.0625 -v -0.03125 -0.125 0.0625 -v -0.03125 -0.125 0.0625 -v -0.53125 0.1875 0.0625 -v -0.53125 0.1875 0.0625 -v -0.53125 -0.125 0.0625 -v -0.53125 -0.125 0.0625 -vt 0.75 0.3125 -vt 0.5 0.3125 -vt 0.5 0.15625 -vt 0.75 0.15625 -vt 0.75 0.3125 -vt 0.75 0.3125 -vt 0.75 0.15625 -vt 0.75 0.15625 -vt 1 0.3125 -vt 0.75 0.3125 -vt 0.75 0.15625 -vt 1 0.15625 -vt 0.5 0.3125 -vt 0.5 0.3125 -vt 0.5 0.15625 -vt 0.5 0.15625 -vt 0.5 0.3125 -vt 0.75 0.3125 -vt 0.75 0.3125 -vt 0.5 0.3125 -vt 0.75 0.3125 -vt 1 0.3125 -vt 1 0.3125 -vt 0.75 0.3125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_f88b8145-cdbb-8011-03d2-81deb45b4e43 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o rightWing -v 0.53125 0.1875 0.0625 -v 0.53125 0.1875 0.0625 -v 0.53125 -0.125 0.0625 -v 0.53125 -0.125 0.0625 -v 0.03125 0.1875 0.0625 -v 0.03125 0.1875 0.0625 -v 0.03125 -0.125 0.0625 -v 0.03125 -0.125 0.0625 -vt 0.5 0.3125 -vt 0.75 0.3125 -vt 0.75 0.15625 -vt 0.5 0.15625 -vt 0.5 0.3125 -vt 0.5 0.3125 -vt 0.5 0.15625 -vt 0.5 0.15625 -vt 0.75 0.3125 -vt 1 0.3125 -vt 1 0.15625 -vt 0.75 0.15625 -vt 0.75 0.3125 -vt 0.75 0.3125 -vt 0.75 0.15625 -vt 0.75 0.15625 -vt 0.75 0.3125 -vt 0.5 0.3125 -vt 0.5 0.3125 -vt 0.75 0.3125 -vt 1 0.3125 -vt 0.75 0.3125 -vt 0.75 0.3125 -vt 1 0.3125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_f88b8145-cdbb-8011-03d2-81deb45b4e43 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/villager.obj b/renderer/viewer/three/entity/models/villager.obj deleted file mode 100644 index 734624726..000000000 --- a/renderer/viewer/three/entity/models/villager.obj +++ /dev/null @@ -1,509 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.25 1.5 0.1875 -v 0.25 1.5 -0.1875 -v 0.25 0.75 0.1875 -v 0.25 0.75 -0.1875 -v -0.25 1.5 -0.1875 -v -0.25 1.5 0.1875 -v -0.25 0.75 -0.1875 -v -0.25 0.75 0.1875 -vt 0.34375 0.59375 -vt 0.46875 0.59375 -vt 0.46875 0.40625 -vt 0.34375 0.40625 -vt 0.25 0.59375 -vt 0.34375 0.59375 -vt 0.34375 0.40625 -vt 0.25 0.40625 -vt 0.5625 0.59375 -vt 0.6875 0.59375 -vt 0.6875 0.40625 -vt 0.5625 0.40625 -vt 0.46875 0.59375 -vt 0.5625 0.59375 -vt 0.5625 0.40625 -vt 0.46875 0.40625 -vt 0.46875 0.59375 -vt 0.34375 0.59375 -vt 0.34375 0.6875 -vt 0.46875 0.6875 -vt 0.59375 0.6875 -vt 0.46875 0.6875 -vt 0.46875 0.59375 -vt 0.59375 0.59375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b4465c9b-59e0-9882-a652-f0428980cb6e -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o body -v 0.28125 1.53125 0.21875 -v 0.28125 1.53125 -0.21875 -v 0.28125 0.34375 0.21875 -v 0.28125 0.34375 -0.21875 -v -0.28125 1.53125 -0.21875 -v -0.28125 1.53125 0.21875 -v -0.28125 0.34375 -0.21875 -v -0.28125 0.34375 0.21875 -vt 0.09375 0.3125 -vt 0.21875 0.3125 -vt 0.21875 0.03125 -vt 0.09375 0.03125 -vt 0 0.3125 -vt 0.09375 0.3125 -vt 0.09375 0.03125 -vt 0 0.03125 -vt 0.3125 0.3125 -vt 0.4375 0.3125 -vt 0.4375 0.03125 -vt 0.3125 0.03125 -vt 0.21875 0.3125 -vt 0.3125 0.3125 -vt 0.3125 0.03125 -vt 0.21875 0.03125 -vt 0.21875 0.3125 -vt 0.09375 0.3125 -vt 0.09375 0.40625 -vt 0.21875 0.40625 -vt 0.34375 0.40625 -vt 0.21875 0.40625 -vt 0.21875 0.3125 -vt 0.34375 0.3125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b4465c9b-59e0-9882-a652-f0428980cb6e -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o head -v 0.25 2.125 0.25 -v 0.25 2.125 -0.25 -v 0.25 1.5 0.25 -v 0.25 1.5 -0.25 -v -0.25 2.125 -0.25 -v -0.25 2.125 0.25 -v -0.25 1.5 -0.25 -v -0.25 1.5 0.25 -vt 0.125 0.875 -vt 0.25 0.875 -vt 0.25 0.71875 -vt 0.125 0.71875 -vt 0 0.875 -vt 0.125 0.875 -vt 0.125 0.71875 -vt 0 0.71875 -vt 0.375 0.875 -vt 0.5 0.875 -vt 0.5 0.71875 -vt 0.375 0.71875 -vt 0.25 0.875 -vt 0.375 0.875 -vt 0.375 0.71875 -vt 0.25 0.71875 -vt 0.25 0.875 -vt 0.125 0.875 -vt 0.125 1 -vt 0.25 1 -vt 0.375 1 -vt 0.25 1 -vt 0.25 0.875 -vt 0.375 0.875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b4465c9b-59e0-9882-a652-f0428980cb6e -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o helmet -v 0.28125 2.15625 0.28125 -v 0.28125 2.15625 -0.28125 -v 0.28125 1.46875 0.28125 -v 0.28125 1.46875 -0.28125 -v -0.28125 2.15625 -0.28125 -v -0.28125 2.15625 0.28125 -v -0.28125 1.46875 -0.28125 -v -0.28125 1.46875 0.28125 -vt 0.625 0.875 -vt 0.75 0.875 -vt 0.75 0.71875 -vt 0.625 0.71875 -vt 0.5 0.875 -vt 0.625 0.875 -vt 0.625 0.71875 -vt 0.5 0.71875 -vt 0.875 0.875 -vt 1 0.875 -vt 1 0.71875 -vt 0.875 0.71875 -vt 0.75 0.875 -vt 0.875 0.875 -vt 0.875 0.71875 -vt 0.75 0.71875 -vt 0.75 0.875 -vt 0.625 0.875 -vt 0.625 1 -vt 0.75 1 -vt 0.875 1 -vt 0.75 1 -vt 0.75 0.875 -vt 0.875 0.875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b4465c9b-59e0-9882-a652-f0428980cb6e -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o brim -v 0.5062500000000001 1.80625 0.5062500000000001 -v 0.5062500000000001 1.88125 0.5062500000000001 -v 0.5062500000000001 1.80625 -0.5062500000000001 -v 0.5062500000000001 1.8812499999999996 -0.5062500000000001 -v -0.50625 1.88125 0.5062500000000001 -v -0.50625 1.80625 0.5062500000000001 -v -0.50625 1.8812499999999996 -0.5062500000000001 -v -0.50625 1.80625 -0.5062500000000001 -vt 0.484375 0.25 -vt 0.734375 0.25 -vt 0.734375 0 -vt 0.484375 0 -vt 0.46875 0.25 -vt 0.484375 0.25 -vt 0.484375 0 -vt 0.46875 0 -vt 0.75 0.25 -vt 1 0.25 -vt 1 0 -vt 0.75 0 -vt 0.734375 0.25 -vt 0.75 0.25 -vt 0.75 0 -vt 0.734375 0 -vt 0.734375 0.25 -vt 0.484375 0.25 -vt 0.484375 0.265625 -vt 0.734375 0.265625 -vt 0.984375 0.265625 -vt 0.734375 0.265625 -vt 0.734375 0.25 -vt 0.984375 0.25 -vn 0 1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 -1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 1 -vn 0 -2.220446049250313e-16 -1 -usemtl m_b4465c9b-59e0-9882-a652-f0428980cb6e -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o nose -v 0.0625 1.6875 -0.25 -v 0.0625 1.6875 -0.375 -v 0.0625 1.4375 -0.25 -v 0.0625 1.4375 -0.375 -v -0.0625 1.6875 -0.375 -v -0.0625 1.6875 -0.25 -v -0.0625 1.4375 -0.375 -v -0.0625 1.4375 -0.25 -vt 0.40625 0.96875 -vt 0.4375 0.96875 -vt 0.4375 0.90625 -vt 0.40625 0.90625 -vt 0.375 0.96875 -vt 0.40625 0.96875 -vt 0.40625 0.90625 -vt 0.375 0.90625 -vt 0.46875 0.96875 -vt 0.5 0.96875 -vt 0.5 0.90625 -vt 0.46875 0.90625 -vt 0.4375 0.96875 -vt 0.46875 0.96875 -vt 0.46875 0.90625 -vt 0.4375 0.90625 -vt 0.4375 0.96875 -vt 0.40625 0.96875 -vt 0.40625 1 -vt 0.4375 1 -vt 0.46875 1 -vt 0.4375 1 -vt 0.4375 0.96875 -vt 0.46875 0.96875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b4465c9b-59e0-9882-a652-f0428980cb6e -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o arms -v 0.25 1.198223304703363 0 -v 0.25 1.375 -0.17677669529663698 -v 0.25 1.0214466094067263 -0.17677669529663698 -v 0.25 1.1982233047033632 -0.35355339059327373 -v -0.25 1.375 -0.17677669529663698 -v -0.25 1.198223304703363 0 -v -0.25 1.1982233047033632 -0.35355339059327373 -v -0.25 1.0214466094067263 -0.17677669529663698 -vt 0.6875 0.34375 -vt 0.8125 0.34375 -vt 0.8125 0.28125 -vt 0.6875 0.28125 -vt 0.625 0.34375 -vt 0.6875 0.34375 -vt 0.6875 0.28125 -vt 0.625 0.28125 -vt 0.875 0.34375 -vt 1 0.34375 -vt 1 0.28125 -vt 0.875 0.28125 -vt 0.8125 0.34375 -vt 0.875 0.34375 -vt 0.875 0.28125 -vt 0.8125 0.28125 -vt 0.8125 0.34375 -vt 0.6875 0.34375 -vt 0.6875 0.40625 -vt 0.8125 0.40625 -vt 0.9375 0.40625 -vt 0.8125 0.40625 -vt 0.8125 0.34375 -vt 0.9375 0.34375 -vn 0 0.7071067811865476 -0.7071067811865475 -vn 1 0 0 -vn 0 -0.7071067811865476 0.7071067811865475 -vn -1 0 0 -vn 0 0.7071067811865475 0.7071067811865476 -vn 0 -0.7071067811865475 -0.7071067811865476 -usemtl m_b4465c9b-59e0-9882-a652-f0428980cb6e -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o arms -v 0.5 1.375 0.17677669529663698 -v 0.5 1.551776695296637 0 -v 0.5 1.0214466094067263 -0.17677669529663698 -v 0.5 1.1982233047033632 -0.35355339059327373 -v 0.25 1.551776695296637 0 -v 0.25 1.375 0.17677669529663698 -v 0.25 1.1982233047033632 -0.35355339059327373 -v 0.25 1.0214466094067263 -0.17677669529663698 -vt 0.75 0.59375 -vt 0.8125 0.59375 -vt 0.8125 0.46875 -vt 0.75 0.46875 -vt 0.6875 0.59375 -vt 0.75 0.59375 -vt 0.75 0.46875 -vt 0.6875 0.46875 -vt 0.875 0.59375 -vt 0.9375 0.59375 -vt 0.9375 0.46875 -vt 0.875 0.46875 -vt 0.8125 0.59375 -vt 0.875 0.59375 -vt 0.875 0.46875 -vt 0.8125 0.46875 -vt 0.8125 0.59375 -vt 0.75 0.59375 -vt 0.75 0.65625 -vt 0.8125 0.65625 -vt 0.875 0.65625 -vt 0.8125 0.65625 -vt 0.8125 0.59375 -vt 0.875 0.59375 -vn 0 0.7071067811865476 -0.7071067811865475 -vn 1 0 0 -vn 0 -0.7071067811865476 0.7071067811865475 -vn -1 0 0 -vn 0 0.7071067811865475 0.7071067811865476 -vn 0 -0.7071067811865475 -0.7071067811865476 -usemtl m_b4465c9b-59e0-9882-a652-f0428980cb6e -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o arms -v -0.25 1.375 0.17677669529663698 -v -0.25 1.551776695296637 0 -v -0.25 1.0214466094067263 -0.17677669529663698 -v -0.25 1.1982233047033632 -0.35355339059327373 -v -0.5 1.551776695296637 0 -v -0.5 1.375 0.17677669529663698 -v -0.5 1.1982233047033632 -0.35355339059327373 -v -0.5 1.0214466094067263 -0.17677669529663698 -vt 0.8125 0.59375 -vt 0.75 0.59375 -vt 0.75 0.46875 -vt 0.8125 0.46875 -vt 0.875 0.59375 -vt 0.8125 0.59375 -vt 0.8125 0.46875 -vt 0.875 0.46875 -vt 0.9375 0.59375 -vt 0.875 0.59375 -vt 0.875 0.46875 -vt 0.9375 0.46875 -vt 0.75 0.59375 -vt 0.6875 0.59375 -vt 0.6875 0.46875 -vt 0.75 0.46875 -vt 0.75 0.59375 -vt 0.8125 0.59375 -vt 0.8125 0.65625 -vt 0.75 0.65625 -vt 0.8125 0.65625 -vt 0.875 0.65625 -vt 0.875 0.59375 -vt 0.8125 0.59375 -vn 0 0.7071067811865476 -0.7071067811865475 -vn 1 0 0 -vn 0 -0.7071067811865476 0.7071067811865475 -vn -1 0 0 -vn 0 0.7071067811865475 0.7071067811865476 -vn 0 -0.7071067811865475 -0.7071067811865476 -usemtl m_b4465c9b-59e0-9882-a652-f0428980cb6e -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o leg0 -v 0.25 0.75 0.125 -v 0.25 0.75 -0.125 -v 0.25 0 0.125 -v 0.25 0 -0.125 -v 0 0.75 -0.125 -v 0 0.75 0.125 -v 0 0 -0.125 -v 0 0 0.125 -vt 0.0625 0.59375 -vt 0.125 0.59375 -vt 0.125 0.40625 -vt 0.0625 0.40625 -vt 0 0.59375 -vt 0.0625 0.59375 -vt 0.0625 0.40625 -vt 0 0.40625 -vt 0.1875 0.59375 -vt 0.25 0.59375 -vt 0.25 0.40625 -vt 0.1875 0.40625 -vt 0.125 0.59375 -vt 0.1875 0.59375 -vt 0.1875 0.40625 -vt 0.125 0.40625 -vt 0.125 0.59375 -vt 0.0625 0.59375 -vt 0.0625 0.65625 -vt 0.125 0.65625 -vt 0.1875 0.65625 -vt 0.125 0.65625 -vt 0.125 0.59375 -vt 0.1875 0.59375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b4465c9b-59e0-9882-a652-f0428980cb6e -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o leg1 -v 0 0.75 0.125 -v 0 0.75 -0.125 -v 0 0 0.125 -v 0 0 -0.125 -v -0.25 0.75 -0.125 -v -0.25 0.75 0.125 -v -0.25 0 -0.125 -v -0.25 0 0.125 -vt 0.125 0.59375 -vt 0.0625 0.59375 -vt 0.0625 0.40625 -vt 0.125 0.40625 -vt 0.1875 0.59375 -vt 0.125 0.59375 -vt 0.125 0.40625 -vt 0.1875 0.40625 -vt 0.25 0.59375 -vt 0.1875 0.59375 -vt 0.1875 0.40625 -vt 0.25 0.40625 -vt 0.0625 0.59375 -vt 0 0.59375 -vt 0 0.40625 -vt 0.0625 0.40625 -vt 0.0625 0.59375 -vt 0.125 0.59375 -vt 0.125 0.65625 -vt 0.0625 0.65625 -vt 0.125 0.65625 -vt 0.1875 0.65625 -vt 0.1875 0.59375 -vt 0.125 0.59375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b4465c9b-59e0-9882-a652-f0428980cb6e -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/warden.obj b/renderer/viewer/three/entity/models/warden.obj deleted file mode 100644 index da0b2656c..000000000 --- a/renderer/viewer/three/entity/models/warden.obj +++ /dev/null @@ -1,463 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o body -v 0.5625 2.125 0.4375 -v 0.5625 2.125 -0.25 -v 0.5625 0.8125 0.4375 -v 0.5625 0.8125 -0.25 -v -0.5625 2.125 -0.25 -v -0.5625 2.125 0.4375 -v -0.5625 0.8125 -0.25 -v -0.5625 0.8125 0.4375 -vt 0.0859375 0.9140625 -vt 0.2265625 0.9140625 -vt 0.2265625 0.75 -vt 0.0859375 0.75 -vt 0 0.9140625 -vt 0.0859375 0.9140625 -vt 0.0859375 0.75 -vt 0 0.75 -vt 0.3125 0.9140625 -vt 0.453125 0.9140625 -vt 0.453125 0.75 -vt 0.3125 0.75 -vt 0.2265625 0.9140625 -vt 0.3125 0.9140625 -vt 0.3125 0.75 -vt 0.2265625 0.75 -vt 0.2265625 0.9140625 -vt 0.0859375 0.9140625 -vt 0.0859375 1 -vt 0.2265625 1 -vt 0.3671875 1 -vt 0.2265625 1 -vt 0.2265625 0.9140625 -vt 0.3671875 0.9140625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b8aa60f9-5a7d-baf1-aee9-852f731e91b8 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o right_ribcage -v 0.5625 2.125 -0.25625 -v 0.5625 2.125 -0.25625 -v 0.5625 0.8125 -0.25625 -v 0.5625 0.8125 -0.25625 -v 0 2.125 -0.25625 -v 0 2.125 -0.25625 -v 0 0.8125 -0.25625 -v 0 0.8125 -0.25625 -vt 0.703125 0.9140625 -vt 0.7734375 0.9140625 -vt 0.7734375 0.75 -vt 0.703125 0.75 -vt 0.703125 0.9140625 -vt 0.703125 0.9140625 -vt 0.703125 0.75 -vt 0.703125 0.75 -vt 0.7734375 0.9140625 -vt 0.84375 0.9140625 -vt 0.84375 0.75 -vt 0.7734375 0.75 -vt 0.7734375 0.9140625 -vt 0.7734375 0.9140625 -vt 0.7734375 0.75 -vt 0.7734375 0.75 -vt 0.7734375 0.9140625 -vt 0.703125 0.9140625 -vt 0.703125 0.9140625 -vt 0.7734375 0.9140625 -vt 0.84375 0.9140625 -vt 0.7734375 0.9140625 -vt 0.7734375 0.9140625 -vt 0.84375 0.9140625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b8aa60f9-5a7d-baf1-aee9-852f731e91b8 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o left_ribcage -v 0 2.125 -0.25625 -v 0 2.125 -0.25625 -v 0 0.8125 -0.25625 -v 0 0.8125 -0.25625 -v -0.5625 2.125 -0.25625 -v -0.5625 2.125 -0.25625 -v -0.5625 0.8125 -0.25625 -v -0.5625 0.8125 -0.25625 -vt 0.7734375 0.9140625 -vt 0.703125 0.9140625 -vt 0.703125 0.75 -vt 0.7734375 0.75 -vt 0.7734375 0.9140625 -vt 0.7734375 0.9140625 -vt 0.7734375 0.75 -vt 0.7734375 0.75 -vt 0.84375 0.9140625 -vt 0.7734375 0.9140625 -vt 0.7734375 0.75 -vt 0.84375 0.75 -vt 0.703125 0.9140625 -vt 0.703125 0.9140625 -vt 0.703125 0.75 -vt 0.703125 0.75 -vt 0.703125 0.9140625 -vt 0.7734375 0.9140625 -vt 0.7734375 0.9140625 -vt 0.703125 0.9140625 -vt 0.7734375 0.9140625 -vt 0.84375 0.9140625 -vt 0.84375 0.9140625 -vt 0.7734375 0.9140625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b8aa60f9-5a7d-baf1-aee9-852f731e91b8 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o head -v 0.5 3.125 0.3125 -v 0.5 3.125 -0.3125 -v 0.5 2.125 0.3125 -v 0.5 2.125 -0.3125 -v -0.5 3.125 -0.3125 -v -0.5 3.125 0.3125 -v -0.5 2.125 -0.3125 -v -0.5 2.125 0.3125 -vt 0.078125 0.671875 -vt 0.203125 0.671875 -vt 0.203125 0.546875 -vt 0.078125 0.546875 -vt 0 0.671875 -vt 0.078125 0.671875 -vt 0.078125 0.546875 -vt 0 0.546875 -vt 0.28125 0.671875 -vt 0.40625 0.671875 -vt 0.40625 0.546875 -vt 0.28125 0.546875 -vt 0.203125 0.671875 -vt 0.28125 0.671875 -vt 0.28125 0.546875 -vt 0.203125 0.546875 -vt 0.203125 0.671875 -vt 0.078125 0.671875 -vt 0.078125 0.75 -vt 0.203125 0.75 -vt 0.328125 0.75 -vt 0.203125 0.75 -vt 0.203125 0.671875 -vt 0.328125 0.671875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b8aa60f9-5a7d-baf1-aee9-852f731e91b8 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o right_tendril -v 1.5 3.6875 0 -v 1.5 3.6875 0 -v 1.5 2.6875 0 -v 1.5 2.6875 0 -v 0.5 3.6875 0 -v 0.5 3.6875 0 -v 0.5 2.6875 0 -v 0.5 2.6875 0 -vt 0.40625 0.75 -vt 0.53125 0.75 -vt 0.53125 0.625 -vt 0.40625 0.625 -vt 0.40625 0.75 -vt 0.40625 0.75 -vt 0.40625 0.625 -vt 0.40625 0.625 -vt 0.53125 0.75 -vt 0.65625 0.75 -vt 0.65625 0.625 -vt 0.53125 0.625 -vt 0.53125 0.75 -vt 0.53125 0.75 -vt 0.53125 0.625 -vt 0.53125 0.625 -vt 0.53125 0.75 -vt 0.40625 0.75 -vt 0.40625 0.75 -vt 0.53125 0.75 -vt 0.65625 0.75 -vt 0.53125 0.75 -vt 0.53125 0.75 -vt 0.65625 0.75 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b8aa60f9-5a7d-baf1-aee9-852f731e91b8 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o left_tendril -v -0.5 3.6875 0 -v -0.5 3.6875 0 -v -0.5 2.6875 0 -v -0.5 2.6875 0 -v -1.5 3.6875 0 -v -1.5 3.6875 0 -v -1.5 2.6875 0 -v -1.5 2.6875 0 -vt 0.453125 1 -vt 0.578125 1 -vt 0.578125 0.875 -vt 0.453125 0.875 -vt 0.453125 1 -vt 0.453125 1 -vt 0.453125 0.875 -vt 0.453125 0.875 -vt 0.578125 1 -vt 0.703125 1 -vt 0.703125 0.875 -vt 0.578125 0.875 -vt 0.578125 1 -vt 0.578125 1 -vt 0.578125 0.875 -vt 0.578125 0.875 -vt 0.578125 1 -vt 0.453125 1 -vt 0.453125 1 -vt 0.578125 1 -vt 0.703125 1 -vt 0.578125 1 -vt 0.578125 1 -vt 0.703125 1 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b8aa60f9-5a7d-baf1-aee9-852f731e91b8 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o right_arm -v 1.0625 2.125 0.3125 -v 1.0625 2.125 -0.1875 -v 1.0625 0.375 0.3125 -v 1.0625 0.375 -0.1875 -v 0.5625 2.125 -0.1875 -v 0.5625 2.125 0.3125 -v 0.5625 0.375 -0.1875 -v 0.5625 0.375 0.3125 -vt 0.40625 0.546875 -vt 0.46875 0.546875 -vt 0.46875 0.328125 -vt 0.40625 0.328125 -vt 0.34375 0.546875 -vt 0.40625 0.546875 -vt 0.40625 0.328125 -vt 0.34375 0.328125 -vt 0.53125 0.546875 -vt 0.59375 0.546875 -vt 0.59375 0.328125 -vt 0.53125 0.328125 -vt 0.46875 0.546875 -vt 0.53125 0.546875 -vt 0.53125 0.328125 -vt 0.46875 0.328125 -vt 0.46875 0.546875 -vt 0.40625 0.546875 -vt 0.40625 0.609375 -vt 0.46875 0.609375 -vt 0.53125 0.609375 -vt 0.46875 0.609375 -vt 0.46875 0.546875 -vt 0.53125 0.546875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b8aa60f9-5a7d-baf1-aee9-852f731e91b8 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o left_arm -v -0.5625 2.125 0.3125 -v -0.5625 2.125 -0.1875 -v -0.5625 0.375 0.3125 -v -0.5625 0.375 -0.1875 -v -1.0625 2.125 -0.1875 -v -1.0625 2.125 0.3125 -v -1.0625 0.375 -0.1875 -v -1.0625 0.375 0.3125 -vt 0.0625 0.484375 -vt 0.125 0.484375 -vt 0.125 0.265625 -vt 0.0625 0.265625 -vt 0 0.484375 -vt 0.0625 0.484375 -vt 0.0625 0.265625 -vt 0 0.265625 -vt 0.1875 0.484375 -vt 0.25 0.484375 -vt 0.25 0.265625 -vt 0.1875 0.265625 -vt 0.125 0.484375 -vt 0.1875 0.484375 -vt 0.1875 0.265625 -vt 0.125 0.265625 -vt 0.125 0.484375 -vt 0.0625 0.484375 -vt 0.0625 0.546875 -vt 0.125 0.546875 -vt 0.1875 0.546875 -vt 0.125 0.546875 -vt 0.125 0.484375 -vt 0.1875 0.484375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b8aa60f9-5a7d-baf1-aee9-852f731e91b8 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o right_leg -v 0.5625 0.8125 0.1875 -v 0.5625 0.8125 -0.1875 -v 0.5625 0 0.1875 -v 0.5625 0 -0.1875 -v 0.1875 0.8125 -0.1875 -v 0.1875 0.8125 0.1875 -v 0.1875 0 -0.1875 -v 0.1875 0 0.1875 -vt 0.640625 0.578125 -vt 0.6875 0.578125 -vt 0.6875 0.4765625 -vt 0.640625 0.4765625 -vt 0.59375 0.578125 -vt 0.640625 0.578125 -vt 0.640625 0.4765625 -vt 0.59375 0.4765625 -vt 0.734375 0.578125 -vt 0.78125 0.578125 -vt 0.78125 0.4765625 -vt 0.734375 0.4765625 -vt 0.6875 0.578125 -vt 0.734375 0.578125 -vt 0.734375 0.4765625 -vt 0.6875 0.4765625 -vt 0.6875 0.578125 -vt 0.640625 0.578125 -vt 0.640625 0.625 -vt 0.6875 0.625 -vt 0.734375 0.625 -vt 0.6875 0.625 -vt 0.6875 0.578125 -vt 0.734375 0.578125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b8aa60f9-5a7d-baf1-aee9-852f731e91b8 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o left_leg -v -0.1875 0.8125 0.1875 -v -0.1875 0.8125 -0.1875 -v -0.1875 0 0.1875 -v -0.1875 0 -0.1875 -v -0.5625 0.8125 -0.1875 -v -0.5625 0.8125 0.1875 -v -0.5625 0 -0.1875 -v -0.5625 0 0.1875 -vt 0.640625 0.359375 -vt 0.6875 0.359375 -vt 0.6875 0.2578125 -vt 0.640625 0.2578125 -vt 0.59375 0.359375 -vt 0.640625 0.359375 -vt 0.640625 0.2578125 -vt 0.59375 0.2578125 -vt 0.734375 0.359375 -vt 0.78125 0.359375 -vt 0.78125 0.2578125 -vt 0.734375 0.2578125 -vt 0.6875 0.359375 -vt 0.734375 0.359375 -vt 0.734375 0.2578125 -vt 0.6875 0.2578125 -vt 0.6875 0.359375 -vt 0.640625 0.359375 -vt 0.640625 0.40625 -vt 0.6875 0.40625 -vt 0.734375 0.40625 -vt 0.6875 0.40625 -vt 0.6875 0.359375 -vt 0.734375 0.359375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_b8aa60f9-5a7d-baf1-aee9-852f731e91b8 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/witch.obj b/renderer/viewer/three/entity/models/witch.obj deleted file mode 100644 index 275da6438..000000000 --- a/renderer/viewer/three/entity/models/witch.obj +++ /dev/null @@ -1,647 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o head -v 0.25 2.125 0.25 -v 0.25 2.125 -0.25 -v 0.25 1.5 0.25 -v 0.25 1.5 -0.25 -v -0.25 2.125 -0.25 -v -0.25 2.125 0.25 -v -0.25 1.5 -0.25 -v -0.25 1.5 0.25 -vt 0.125 0.9375 -vt 0.25 0.9375 -vt 0.25 0.859375 -vt 0.125 0.859375 -vt 0 0.9375 -vt 0.125 0.9375 -vt 0.125 0.859375 -vt 0 0.859375 -vt 0.375 0.9375 -vt 0.5 0.9375 -vt 0.5 0.859375 -vt 0.375 0.859375 -vt 0.25 0.9375 -vt 0.375 0.9375 -vt 0.375 0.859375 -vt 0.25 0.859375 -vt 0.25 0.9375 -vt 0.125 0.9375 -vt 0.125 1 -vt 0.25 1 -vt 0.375 1 -vt 0.25 1 -vt 0.25 0.9375 -vt 0.375 0.9375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o nose -v 0.0625 1.6875 -0.25 -v 0.0625 1.6875 -0.375 -v 0.0625 1.4375 -0.25 -v 0.0625 1.4375 -0.375 -v -0.0625 1.6875 -0.375 -v -0.0625 1.6875 -0.25 -v -0.0625 1.4375 -0.375 -v -0.0625 1.4375 -0.25 -vt 0.40625 0.984375 -vt 0.4375 0.984375 -vt 0.4375 0.953125 -vt 0.40625 0.953125 -vt 0.375 0.984375 -vt 0.40625 0.984375 -vt 0.40625 0.953125 -vt 0.375 0.953125 -vt 0.46875 0.984375 -vt 0.5 0.984375 -vt 0.5 0.953125 -vt 0.46875 0.953125 -vt 0.4375 0.984375 -vt 0.46875 0.984375 -vt 0.46875 0.953125 -vt 0.4375 0.953125 -vt 0.4375 0.984375 -vt 0.40625 0.984375 -vt 0.40625 1 -vt 0.4375 1 -vt 0.46875 1 -vt 0.4375 1 -vt 0.4375 0.984375 -vt 0.46875 0.984375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o nose -v -0.015625 1.609375 -0.375 -v -0.015625 1.609375 -0.40625 -v -0.015625 1.578125 -0.375 -v -0.015625 1.578125 -0.40625 -v -0.046875 1.609375 -0.40625 -v -0.046875 1.609375 -0.375 -v -0.046875 1.578125 -0.40625 -v -0.046875 1.578125 -0.375 -vt 0.015625 0.9921875 -vt 0.03125 0.9921875 -vt 0.03125 0.984375 -vt 0.015625 0.984375 -vt 0 0.9921875 -vt 0.015625 0.9921875 -vt 0.015625 0.984375 -vt 0 0.984375 -vt 0.046875 0.9921875 -vt 0.0625 0.9921875 -vt 0.0625 0.984375 -vt 0.046875 0.984375 -vt 0.03125 0.9921875 -vt 0.046875 0.9921875 -vt 0.046875 0.984375 -vt 0.03125 0.984375 -vt 0.03125 0.9921875 -vt 0.015625 0.9921875 -vt 0.015625 1 -vt 0.03125 1 -vt 0.046875 1 -vt 0.03125 1 -vt 0.03125 0.9921875 -vt 0.046875 0.9921875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o hat -v 0.3125 2.128125 0.3125 -v 0.3125 2.128125 -0.3125 -v 0.3125 2.003125 0.3125 -v 0.3125 2.003125 -0.3125 -v -0.3125 2.128125 -0.3125 -v -0.3125 2.128125 0.3125 -v -0.3125 2.003125 -0.3125 -v -0.3125 2.003125 0.3125 -vt 0.15625 0.421875 -vt 0.3125 0.421875 -vt 0.3125 0.40625 -vt 0.15625 0.40625 -vt 0 0.421875 -vt 0.15625 0.421875 -vt 0.15625 0.40625 -vt 0 0.40625 -vt 0.46875 0.421875 -vt 0.625 0.421875 -vt 0.625 0.40625 -vt 0.46875 0.40625 -vt 0.3125 0.421875 -vt 0.46875 0.421875 -vt 0.46875 0.40625 -vt 0.3125 0.40625 -vt 0.3125 0.421875 -vt 0.15625 0.421875 -vt 0.15625 0.5 -vt 0.3125 0.5 -vt 0.46875 0.5 -vt 0.3125 0.5 -vt 0.3125 0.421875 -vt 0.46875 0.421875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o hat2 -v 0.19420316941970583 2.3448018130595334 0.26781917680283374 -v 0.19360379633542446 2.367690947692347 -0.16908124465229235 -v 0.20073843784720224 2.0952299807209473 0.2547351877420978 -v 0.20013906476292087 2.118119115353761 -0.18216523371302834 -v -0.24374628334138193 2.3562385328076525 -0.16908124465229235 -v -0.24314691025710045 2.333349398174839 0.26781917680283374 -v -0.2372110149138854 2.1066667004690665 -0.18216523371302834 -v -0.23661164182960404 2.083777565836253 0.2547351877420978 -vt 0.109375 0.3515625 -vt 0.21875 0.3515625 -vt 0.21875 0.3203125 -vt 0.109375 0.3203125 -vt 0 0.3515625 -vt 0.109375 0.3515625 -vt 0.109375 0.3203125 -vt 0 0.3203125 -vt 0.328125 0.3515625 -vt 0.4375 0.3515625 -vt 0.4375 0.3203125 -vt 0.328125 0.3203125 -vt 0.21875 0.3515625 -vt 0.328125 0.3515625 -vt 0.328125 0.3203125 -vt 0.21875 0.3203125 -vt 0.21875 0.3515625 -vt 0.109375 0.3515625 -vt 0.109375 0.40625 -vt 0.21875 0.40625 -vt 0.328125 0.40625 -vt 0.21875 0.40625 -vt 0.21875 0.3515625 -vt 0.328125 0.3515625 -vn -0.0013699956212146517 0.052318022017859046 -0.998629534754574 -vn 0.9996573249755573 0.026176948307873146 -2.168404344971009e-19 -vn 0.0013699956212146517 -0.052318022017859046 0.998629534754574 -vn -0.9996573249755573 -0.026176948307873146 2.168404344971009e-19 -vn -0.02614107370998589 0.9982873293543426 0.05233595624294382 -vn 0.02614107370998589 -0.9982873293543426 -0.05233595624294382 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o hat3 -v 0.06205916642018039 2.5318108508382715 0.25085017875105275 -v 0.059669177777630145 2.5708345128476795 0.003926219286475963 -v 0.08152178038959057 2.2856541582304613 0.21175939541454591 -v 0.07913179174704033 2.3246778202398692 -0.03516456405003088 -v -0.1895606250384982 2.5512376639234398 0.0032414562075101516 -v -0.187170636395948 2.5122140019140318 0.25016541567208694 -v -0.17009801106908795 2.3050809713156295 -0.03584932712899669 -v -0.1677080224265377 2.2660573093062215 0.2110746323355801 -vt 0.0625 0.2890625 -vt 0.125 0.2890625 -vt 0.125 0.2578125 -vt 0.0625 0.2578125 -vt 0 0.2890625 -vt 0.0625 0.2890625 -vt 0.0625 0.2578125 -vt 0 0.2578125 -vt 0.1875 0.2890625 -vt 0.25 0.2890625 -vt 0.25 0.2578125 -vt 0.1875 0.2578125 -vt 0.125 0.2890625 -vt 0.1875 0.2890625 -vt 0.1875 0.2578125 -vt 0.125 0.2578125 -vt 0.125 0.2890625 -vt 0.0625 0.2890625 -vt 0.0625 0.3203125 -vt 0.125 0.3203125 -vt 0.1875 0.3203125 -vt 0.125 0.3203125 -vt 0.125 0.2890625 -vt 0.1875 0.2890625 -vn -0.009559954570200835 0.156094648037632 -0.9876958378583074 -vn 0.9969192112645133 0.07838739569696003 0.002739052315863333 -vn 0.009559954570200835 -0.156094648037632 0.9876958378583074 -vn -0.9969192112645133 -0.07838739569696003 -0.002739052315863333 -vn -0.07785045587764094 0.9846267704312412 0.1563631333460272 -vn 0.07785045587764094 -0.9846267704312412 -0.1563631333460272 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o hat4 -v -0.06724991963009147 2.6297151428282426 0.2756843667494786 -v -0.07166686964939262 2.6629564553960905 0.18813684713130974 -v -0.03980089941132947 2.486376747492985 0.21987470619018534 -v -0.04421784943063062 2.519618060060833 0.1323271865720166 -v -0.16385315668047867 2.645999001844819 0.18634918036183534 -v -0.15943620666117758 2.6127576892769713 0.2738966999800041 -v -0.13640413646171662 2.502660606509562 0.1305395198025422 -v -0.13198718644241553 2.469419293941714 0.21808703942071106 -vt 0.015625 0.25 -vt 0.03125 0.25 -vt 0.03125 0.234375 -vt 0.015625 0.234375 -vt 0 0.25 -vt 0.015625 0.25 -vt 0.015625 0.234375 -vt 0 0.234375 -vt 0.046875 0.25 -vt 0.0625 0.25 -vt 0.0625 0.234375 -vt 0.046875 0.234375 -vt 0.03125 0.25 -vt 0.046875 0.25 -vt 0.046875 0.234375 -vt 0.03125 0.234375 -vt 0.03125 0.25 -vt 0.015625 0.25 -vt 0.015625 0.2578125 -vt 0.03125 0.2578125 -vt 0.046875 0.2578125 -vt 0.03125 0.2578125 -vt 0.03125 0.25 -vt 0.046875 0.25 -vn -0.04711413353921201 0.3545740007237079 -0.9338402092604674 -vn 0.9833203949982517 0.18087950454689375 0.019068445541060658 -vn 0.04711413353921201 -0.3545740007237079 0.9338402092604674 -vn -0.9833203949982517 -0.18087950454689375 -0.019068445541060658 -vn -0.17567372940007692 0.9173657301456462 0.3571818275794757 -vn 0.17567372940007692 -0.9173657301456462 -0.3571818275794757 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o body -v 0.25 1.5 0.1875 -v 0.25 1.5 -0.1875 -v 0.25 0.75 0.1875 -v 0.25 0.75 -0.1875 -v -0.25 1.5 -0.1875 -v -0.25 1.5 0.1875 -v -0.25 0.75 -0.1875 -v -0.25 0.75 0.1875 -vt 0.34375 0.796875 -vt 0.46875 0.796875 -vt 0.46875 0.703125 -vt 0.34375 0.703125 -vt 0.25 0.796875 -vt 0.34375 0.796875 -vt 0.34375 0.703125 -vt 0.25 0.703125 -vt 0.5625 0.796875 -vt 0.6875 0.796875 -vt 0.6875 0.703125 -vt 0.5625 0.703125 -vt 0.46875 0.796875 -vt 0.5625 0.796875 -vt 0.5625 0.703125 -vt 0.46875 0.703125 -vt 0.46875 0.796875 -vt 0.34375 0.796875 -vt 0.34375 0.84375 -vt 0.46875 0.84375 -vt 0.59375 0.84375 -vt 0.46875 0.84375 -vt 0.46875 0.796875 -vt 0.59375 0.796875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o body -v 0.28125 1.53125 0.21875 -v 0.28125 1.53125 -0.21875 -v 0.28125 0.34375 0.21875 -v 0.28125 0.34375 -0.21875 -v -0.28125 1.53125 -0.21875 -v -0.28125 1.53125 0.21875 -v -0.28125 0.34375 -0.21875 -v -0.28125 0.34375 0.21875 -vt 0.09375 0.65625 -vt 0.21875 0.65625 -vt 0.21875 0.515625 -vt 0.09375 0.515625 -vt 0 0.65625 -vt 0.09375 0.65625 -vt 0.09375 0.515625 -vt 0 0.515625 -vt 0.3125 0.65625 -vt 0.4375 0.65625 -vt 0.4375 0.515625 -vt 0.3125 0.515625 -vt 0.21875 0.65625 -vt 0.3125 0.65625 -vt 0.3125 0.515625 -vt 0.21875 0.515625 -vt 0.21875 0.65625 -vt 0.09375 0.65625 -vt 0.09375 0.703125 -vt 0.21875 0.703125 -vt 0.34375 0.703125 -vt 0.21875 0.703125 -vt 0.21875 0.65625 -vt 0.34375 0.65625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o arms -v 0.25 1.198223304703363 0 -v 0.25 1.375 -0.17677669529663698 -v 0.25 1.0214466094067263 -0.17677669529663698 -v 0.25 1.1982233047033632 -0.35355339059327373 -v -0.25 1.375 -0.17677669529663698 -v -0.25 1.198223304703363 0 -v -0.25 1.1982233047033632 -0.35355339059327373 -v -0.25 1.0214466094067263 -0.17677669529663698 -vt 0.6875 0.671875 -vt 0.8125 0.671875 -vt 0.8125 0.640625 -vt 0.6875 0.640625 -vt 0.625 0.671875 -vt 0.6875 0.671875 -vt 0.6875 0.640625 -vt 0.625 0.640625 -vt 0.875 0.671875 -vt 1 0.671875 -vt 1 0.640625 -vt 0.875 0.640625 -vt 0.8125 0.671875 -vt 0.875 0.671875 -vt 0.875 0.640625 -vt 0.8125 0.640625 -vt 0.8125 0.671875 -vt 0.6875 0.671875 -vt 0.6875 0.703125 -vt 0.8125 0.703125 -vt 0.9375 0.703125 -vt 0.8125 0.703125 -vt 0.8125 0.671875 -vt 0.9375 0.671875 -vn 0 0.7071067811865476 -0.7071067811865475 -vn 1 0 0 -vn 0 -0.7071067811865476 0.7071067811865475 -vn -1 0 0 -vn 0 0.7071067811865475 0.7071067811865476 -vn 0 -0.7071067811865475 -0.7071067811865476 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o arms -v 0.5 1.375 0.17677669529663698 -v 0.5 1.551776695296637 0 -v 0.5 1.0214466094067263 -0.17677669529663698 -v 0.5 1.1982233047033632 -0.35355339059327373 -v 0.25 1.551776695296637 0 -v 0.25 1.375 0.17677669529663698 -v 0.25 1.1982233047033632 -0.35355339059327373 -v 0.25 1.0214466094067263 -0.17677669529663698 -vt 0.75 0.796875 -vt 0.8125 0.796875 -vt 0.8125 0.734375 -vt 0.75 0.734375 -vt 0.6875 0.796875 -vt 0.75 0.796875 -vt 0.75 0.734375 -vt 0.6875 0.734375 -vt 0.875 0.796875 -vt 0.9375 0.796875 -vt 0.9375 0.734375 -vt 0.875 0.734375 -vt 0.8125 0.796875 -vt 0.875 0.796875 -vt 0.875 0.734375 -vt 0.8125 0.734375 -vt 0.8125 0.796875 -vt 0.75 0.796875 -vt 0.75 0.828125 -vt 0.8125 0.828125 -vt 0.875 0.828125 -vt 0.8125 0.828125 -vt 0.8125 0.796875 -vt 0.875 0.796875 -vn 0 0.7071067811865476 -0.7071067811865475 -vn 1 0 0 -vn 0 -0.7071067811865476 0.7071067811865475 -vn -1 0 0 -vn 0 0.7071067811865475 0.7071067811865476 -vn 0 -0.7071067811865475 -0.7071067811865476 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 -o arms -v -0.25 1.375 0.17677669529663698 -v -0.25 1.551776695296637 0 -v -0.25 1.0214466094067263 -0.17677669529663698 -v -0.25 1.1982233047033632 -0.35355339059327373 -v -0.5 1.551776695296637 0 -v -0.5 1.375 0.17677669529663698 -v -0.5 1.1982233047033632 -0.35355339059327373 -v -0.5 1.0214466094067263 -0.17677669529663698 -vt 0.75 0.796875 -vt 0.8125 0.796875 -vt 0.8125 0.734375 -vt 0.75 0.734375 -vt 0.6875 0.796875 -vt 0.75 0.796875 -vt 0.75 0.734375 -vt 0.6875 0.734375 -vt 0.875 0.796875 -vt 0.9375 0.796875 -vt 0.9375 0.734375 -vt 0.875 0.734375 -vt 0.8125 0.796875 -vt 0.875 0.796875 -vt 0.875 0.734375 -vt 0.8125 0.734375 -vt 0.8125 0.796875 -vt 0.75 0.796875 -vt 0.75 0.828125 -vt 0.8125 0.828125 -vt 0.875 0.828125 -vt 0.8125 0.828125 -vt 0.8125 0.796875 -vt 0.875 0.796875 -vn 0 0.7071067811865476 -0.7071067811865475 -vn 1 0 0 -vn 0 -0.7071067811865476 0.7071067811865475 -vn -1 0 0 -vn 0 0.7071067811865475 0.7071067811865476 -vn 0 -0.7071067811865475 -0.7071067811865476 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 92/268/67 95/267/67 93/266/67 90/265/67 -f 91/272/68 92/271/68 90/270/68 89/269/68 -f 96/276/69 91/275/69 89/274/69 94/273/69 -f 95/280/70 96/279/70 94/278/70 93/277/70 -f 94/284/71 89/283/71 90/282/71 93/281/71 -f 95/288/72 92/287/72 91/286/72 96/285/72 -o leg0 -v 0.25 0.75 0.125 -v 0.25 0.75 -0.125 -v 0.25 0 0.125 -v 0.25 0 -0.125 -v 0 0.75 -0.125 -v 0 0.75 0.125 -v 0 0 -0.125 -v 0 0 0.125 -vt 0.0625 0.796875 -vt 0.125 0.796875 -vt 0.125 0.703125 -vt 0.0625 0.703125 -vt 0 0.796875 -vt 0.0625 0.796875 -vt 0.0625 0.703125 -vt 0 0.703125 -vt 0.1875 0.796875 -vt 0.25 0.796875 -vt 0.25 0.703125 -vt 0.1875 0.703125 -vt 0.125 0.796875 -vt 0.1875 0.796875 -vt 0.1875 0.703125 -vt 0.125 0.703125 -vt 0.125 0.796875 -vt 0.0625 0.796875 -vt 0.0625 0.828125 -vt 0.125 0.828125 -vt 0.1875 0.828125 -vt 0.125 0.828125 -vt 0.125 0.796875 -vt 0.1875 0.796875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 100/292/73 103/291/73 101/290/73 98/289/73 -f 99/296/74 100/295/74 98/294/74 97/293/74 -f 104/300/75 99/299/75 97/298/75 102/297/75 -f 103/304/76 104/303/76 102/302/76 101/301/76 -f 102/308/77 97/307/77 98/306/77 101/305/77 -f 103/312/78 100/311/78 99/310/78 104/309/78 -o leg1 -v 0 0.75 0.125 -v 0 0.75 -0.125 -v 0 0 0.125 -v 0 0 -0.125 -v -0.25 0.75 -0.125 -v -0.25 0.75 0.125 -v -0.25 0 -0.125 -v -0.25 0 0.125 -vt 0.0625 0.796875 -vt 0.125 0.796875 -vt 0.125 0.703125 -vt 0.0625 0.703125 -vt 0 0.796875 -vt 0.0625 0.796875 -vt 0.0625 0.703125 -vt 0 0.703125 -vt 0.1875 0.796875 -vt 0.25 0.796875 -vt 0.25 0.703125 -vt 0.1875 0.703125 -vt 0.125 0.796875 -vt 0.1875 0.796875 -vt 0.1875 0.703125 -vt 0.125 0.703125 -vt 0.125 0.796875 -vt 0.0625 0.796875 -vt 0.0625 0.828125 -vt 0.125 0.828125 -vt 0.1875 0.828125 -vt 0.125 0.828125 -vt 0.125 0.796875 -vt 0.1875 0.796875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_5cc249a3-cb80-69af-8be3-aeafeadc66a1 -f 108/316/79 111/315/79 109/314/79 106/313/79 -f 107/320/80 108/319/80 106/318/80 105/317/80 -f 112/324/81 107/323/81 105/322/81 110/321/81 -f 111/328/82 112/327/82 110/326/82 109/325/82 -f 110/332/83 105/331/83 106/330/83 109/329/83 -f 111/336/84 108/335/84 107/334/84 112/333/84 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/wolf.obj b/renderer/viewer/three/entity/models/wolf.obj deleted file mode 100644 index 086cda39d..000000000 --- a/renderer/viewer/three/entity/models/wolf.obj +++ /dev/null @@ -1,509 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o head -v 0.25 0.84375 -0.3125 -v 0.25 0.84375 -0.5625 -v 0.25 0.46875 -0.3125 -v 0.25 0.46875 -0.5625 -v -0.125 0.84375 -0.5625 -v -0.125 0.84375 -0.3125 -v -0.125 0.46875 -0.5625 -v -0.125 0.46875 -0.3125 -vt 0.0625 0.875 -vt 0.15625 0.875 -vt 0.15625 0.6875 -vt 0.0625 0.6875 -vt 0 0.875 -vt 0.0625 0.875 -vt 0.0625 0.6875 -vt 0 0.6875 -vt 0.21875 0.875 -vt 0.3125 0.875 -vt 0.3125 0.6875 -vt 0.21875 0.6875 -vt 0.15625 0.875 -vt 0.21875 0.875 -vt 0.21875 0.6875 -vt 0.15625 0.6875 -vt 0.15625 0.875 -vt 0.0625 0.875 -vt 0.0625 1 -vt 0.15625 1 -vt 0.25 1 -vt 0.15625 1 -vt 0.15625 0.875 -vt 0.25 0.875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_94c40dbc-0261-544f-e827-6e5c4aaaa4dd -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o head -v 0.25 0.96875 -0.375 -v 0.25 0.96875 -0.4375 -v 0.25 0.84375 -0.375 -v 0.25 0.84375 -0.4375 -v 0.125 0.96875 -0.4375 -v 0.125 0.96875 -0.375 -v 0.125 0.84375 -0.4375 -v 0.125 0.84375 -0.375 -vt 0.265625 0.53125 -vt 0.296875 0.53125 -vt 0.296875 0.46875 -vt 0.265625 0.46875 -vt 0.25 0.53125 -vt 0.265625 0.53125 -vt 0.265625 0.46875 -vt 0.25 0.46875 -vt 0.3125 0.53125 -vt 0.34375 0.53125 -vt 0.34375 0.46875 -vt 0.3125 0.46875 -vt 0.296875 0.53125 -vt 0.3125 0.53125 -vt 0.3125 0.46875 -vt 0.296875 0.46875 -vt 0.296875 0.53125 -vt 0.265625 0.53125 -vt 0.265625 0.5625 -vt 0.296875 0.5625 -vt 0.328125 0.5625 -vt 0.296875 0.5625 -vt 0.296875 0.53125 -vt 0.328125 0.53125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_94c40dbc-0261-544f-e827-6e5c4aaaa4dd -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o head -v 0 0.96875 -0.375 -v 0 0.96875 -0.4375 -v 0 0.84375 -0.375 -v 0 0.84375 -0.4375 -v -0.125 0.96875 -0.4375 -v -0.125 0.96875 -0.375 -v -0.125 0.84375 -0.4375 -v -0.125 0.84375 -0.375 -vt 0.265625 0.53125 -vt 0.296875 0.53125 -vt 0.296875 0.46875 -vt 0.265625 0.46875 -vt 0.25 0.53125 -vt 0.265625 0.53125 -vt 0.265625 0.46875 -vt 0.25 0.46875 -vt 0.3125 0.53125 -vt 0.34375 0.53125 -vt 0.34375 0.46875 -vt 0.3125 0.46875 -vt 0.296875 0.53125 -vt 0.3125 0.53125 -vt 0.3125 0.46875 -vt 0.296875 0.46875 -vt 0.296875 0.53125 -vt 0.265625 0.53125 -vt 0.265625 0.5625 -vt 0.296875 0.5625 -vt 0.328125 0.5625 -vt 0.296875 0.5625 -vt 0.296875 0.53125 -vt 0.328125 0.53125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_94c40dbc-0261-544f-e827-6e5c4aaaa4dd -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o head -v 0.15625 0.6572268750000001 -0.5 -v 0.15625 0.6572268750000001 -0.75 -v 0.15625 0.469726875 -0.5 -v 0.15625 0.469726875 -0.75 -v -0.03125 0.6572268750000001 -0.75 -v -0.03125 0.6572268750000001 -0.5 -v -0.03125 0.469726875 -0.75 -v -0.03125 0.469726875 -0.5 -vt 0.0625 0.5625 -vt 0.109375 0.5625 -vt 0.109375 0.46875 -vt 0.0625 0.46875 -vt 0 0.5625 -vt 0.0625 0.5625 -vt 0.0625 0.46875 -vt 0 0.46875 -vt 0.171875 0.5625 -vt 0.21875 0.5625 -vt 0.21875 0.46875 -vt 0.171875 0.46875 -vt 0.109375 0.5625 -vt 0.171875 0.5625 -vt 0.171875 0.46875 -vt 0.109375 0.46875 -vt 0.109375 0.5625 -vt 0.0625 0.5625 -vt 0.0625 0.6875 -vt 0.109375 0.6875 -vt 0.15625 0.6875 -vt 0.109375 0.6875 -vt 0.109375 0.5625 -vt 0.15625 0.5625 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_94c40dbc-0261-544f-e827-6e5c4aaaa4dd -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o body -v 0.25 0.8125 1.1102230246251565e-16 -v 0.25 0.4375 0 -v 0.25 0.8125 0.5625 -v 0.25 0.4375 0.5625 -v -0.125 0.4375 0 -v -0.125 0.8125 1.1102230246251565e-16 -v -0.125 0.4375 0.5625 -v -0.125 0.8125 0.5625 -vt 0.375 0.375 -vt 0.46875 0.375 -vt 0.46875 0.09375 -vt 0.375 0.09375 -vt 0.28125 0.375 -vt 0.375 0.375 -vt 0.375 0.09375 -vt 0.28125 0.09375 -vt 0.5625 0.375 -vt 0.65625 0.375 -vt 0.65625 0.09375 -vt 0.5625 0.09375 -vt 0.46875 0.375 -vt 0.5625 0.375 -vt 0.5625 0.09375 -vt 0.46875 0.09375 -vt 0.46875 0.375 -vt 0.375 0.375 -vt 0.375 0.5625 -vt 0.46875 0.5625 -vt 0.5625 0.5625 -vt 0.46875 0.5625 -vt 0.46875 0.375 -vt 0.5625 0.375 -vn 0 -1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 -1 -vn 0 -2.220446049250313e-16 1 -usemtl m_94c40dbc-0261-544f-e827-6e5c4aaaa4dd -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o upperBody -v 0.3125 0.4375 1.1102230246251565e-16 -v 0.3125 0.875 0 -v 0.3125 0.4374999999999999 -0.37499999999999994 -v 0.3125 0.875 -0.375 -v -0.1875 0.875 0 -v -0.1875 0.4375 1.1102230246251565e-16 -v -0.1875 0.875 -0.375 -v -0.1875 0.4374999999999999 -0.37499999999999994 -vt 0.4375 0.78125 -vt 0.5625 0.78125 -vt 0.5625 0.59375 -vt 0.4375 0.59375 -vt 0.328125 0.78125 -vt 0.4375 0.78125 -vt 0.4375 0.59375 -vt 0.328125 0.59375 -vt 0.671875 0.78125 -vt 0.796875 0.78125 -vt 0.796875 0.59375 -vt 0.671875 0.59375 -vt 0.5625 0.78125 -vt 0.671875 0.78125 -vt 0.671875 0.59375 -vt 0.5625 0.59375 -vt 0.5625 0.78125 -vt 0.4375 0.78125 -vt 0.4375 1 -vt 0.5625 1 -vt 0.6875 1 -vt 0.5625 1 -vt 0.5625 0.78125 -vt 0.6875 0.78125 -vn 0 1 -2.220446049250313e-16 -vn 1 0 0 -vn 0 -1 2.220446049250313e-16 -vn -1 0 0 -vn 0 2.220446049250313e-16 1 -vn 0 -2.220446049250313e-16 -1 -usemtl m_94c40dbc-0261-544f-e827-6e5c4aaaa4dd -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o leg0 -v 0.21875 0.5 0.5 -v 0.21875 0.5 0.375 -v 0.21875 0 0.5 -v 0.21875 0 0.375 -v 0.09375 0.5 0.375 -v 0.09375 0.5 0.5 -v 0.09375 0 0.375 -v 0.09375 0 0.5 -vt 0.03125 0.375 -vt 0.0625 0.375 -vt 0.0625 0.125 -vt 0.03125 0.125 -vt 0 0.375 -vt 0.03125 0.375 -vt 0.03125 0.125 -vt 0 0.125 -vt 0.09375 0.375 -vt 0.125 0.375 -vt 0.125 0.125 -vt 0.09375 0.125 -vt 0.0625 0.375 -vt 0.09375 0.375 -vt 0.09375 0.125 -vt 0.0625 0.125 -vt 0.0625 0.375 -vt 0.03125 0.375 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.375 -vt 0.09375 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_94c40dbc-0261-544f-e827-6e5c4aaaa4dd -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o leg1 -v 0.03125 0.5 0.5 -v 0.03125 0.5 0.375 -v 0.03125 0 0.5 -v 0.03125 0 0.375 -v -0.09375 0.5 0.375 -v -0.09375 0.5 0.5 -v -0.09375 0 0.375 -v -0.09375 0 0.5 -vt 0.03125 0.375 -vt 0.0625 0.375 -vt 0.0625 0.125 -vt 0.03125 0.125 -vt 0 0.375 -vt 0.03125 0.375 -vt 0.03125 0.125 -vt 0 0.125 -vt 0.09375 0.375 -vt 0.125 0.375 -vt 0.125 0.125 -vt 0.09375 0.125 -vt 0.0625 0.375 -vt 0.09375 0.375 -vt 0.09375 0.125 -vt 0.0625 0.125 -vt 0.0625 0.375 -vt 0.03125 0.375 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.375 -vt 0.09375 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_94c40dbc-0261-544f-e827-6e5c4aaaa4dd -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o leg2 -v 0.21875 0.5 -0.1875 -v 0.21875 0.5 -0.3125 -v 0.21875 0 -0.1875 -v 0.21875 0 -0.3125 -v 0.09375 0.5 -0.3125 -v 0.09375 0.5 -0.1875 -v 0.09375 0 -0.3125 -v 0.09375 0 -0.1875 -vt 0.03125 0.375 -vt 0.0625 0.375 -vt 0.0625 0.125 -vt 0.03125 0.125 -vt 0 0.375 -vt 0.03125 0.375 -vt 0.03125 0.125 -vt 0 0.125 -vt 0.09375 0.375 -vt 0.125 0.375 -vt 0.125 0.125 -vt 0.09375 0.125 -vt 0.0625 0.375 -vt 0.09375 0.375 -vt 0.09375 0.125 -vt 0.0625 0.125 -vt 0.0625 0.375 -vt 0.03125 0.375 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.375 -vt 0.09375 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_94c40dbc-0261-544f-e827-6e5c4aaaa4dd -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o leg3 -v 0.03125 0.5 -0.1875 -v 0.03125 0.5 -0.3125 -v 0.03125 0 -0.1875 -v 0.03125 0 -0.3125 -v -0.09375 0.5 -0.3125 -v -0.09375 0.5 -0.1875 -v -0.09375 0 -0.3125 -v -0.09375 0 -0.1875 -vt 0.03125 0.375 -vt 0.0625 0.375 -vt 0.0625 0.125 -vt 0.03125 0.125 -vt 0 0.375 -vt 0.03125 0.375 -vt 0.03125 0.125 -vt 0 0.125 -vt 0.09375 0.375 -vt 0.125 0.375 -vt 0.125 0.125 -vt 0.09375 0.125 -vt 0.0625 0.375 -vt 0.09375 0.375 -vt 0.09375 0.125 -vt 0.0625 0.125 -vt 0.0625 0.375 -vt 0.03125 0.375 -vt 0.03125 0.4375 -vt 0.0625 0.4375 -vt 0.09375 0.4375 -vt 0.0625 0.4375 -vt 0.0625 0.375 -vt 0.09375 0.375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_94c40dbc-0261-544f-e827-6e5c4aaaa4dd -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 -o tail -v 0.125 0.8011970027680619 0.5358485272719404 -v 0.125 0.6988029972319381 0.46415147272805957 -v 0.125 0.5144087845925389 0.9454245494164362 -v 0.125 0.4120147790564149 0.8737274948725555 -v 0 0.6988029972319381 0.46415147272805957 -v 0 0.8011970027680619 0.5358485272719404 -v 0 0.4120147790564149 0.8737274948725555 -v 0 0.5144087845925389 0.9454245494164362 -vt 0.171875 0.375 -vt 0.203125 0.375 -vt 0.203125 0.125 -vt 0.171875 0.125 -vt 0.140625 0.375 -vt 0.171875 0.375 -vt 0.171875 0.125 -vt 0.140625 0.125 -vt 0.234375 0.375 -vt 0.265625 0.375 -vt 0.265625 0.125 -vt 0.234375 0.125 -vt 0.203125 0.375 -vt 0.234375 0.375 -vt 0.234375 0.125 -vt 0.203125 0.125 -vt 0.203125 0.375 -vt 0.171875 0.375 -vt 0.171875 0.4375 -vt 0.203125 0.4375 -vt 0.234375 0.4375 -vt 0.203125 0.4375 -vt 0.203125 0.375 -vt 0.234375 0.375 -vn 0 -0.8191520442889917 -0.5735764363510463 -vn 1 0 0 -vn 0 0.8191520442889917 0.5735764363510463 -vn -1 0 0 -vn 0 0.5735764363510463 -0.8191520442889917 -vn 0 -0.5735764363510463 0.8191520442889917 -usemtl m_94c40dbc-0261-544f-e827-6e5c4aaaa4dd -f 84/244/61 87/243/61 85/242/61 82/241/61 -f 83/248/62 84/247/62 82/246/62 81/245/62 -f 88/252/63 83/251/63 81/250/63 86/249/63 -f 87/256/64 88/255/64 86/254/64 85/253/64 -f 86/260/65 81/259/65 82/258/65 85/257/65 -f 87/264/66 84/263/66 83/262/66 88/261/66 \ No newline at end of file diff --git a/renderer/viewer/three/entity/models/zombie_villager.obj b/renderer/viewer/three/entity/models/zombie_villager.obj deleted file mode 100644 index 22282802c..000000000 --- a/renderer/viewer/three/entity/models/zombie_villager.obj +++ /dev/null @@ -1,463 +0,0 @@ -# Made in Blockbench 4.9.4 -mtllib materials.mtl - -o Body -v 0.25 1.5 0.1875 -v 0.25 1.5 -0.1875 -v 0.25 0.75 0.1875 -v 0.25 0.75 -0.1875 -v -0.25 1.5 -0.1875 -v -0.25 1.5 0.1875 -v -0.25 0.75 -0.1875 -v -0.25 0.75 0.1875 -vt 0.34375 0.59375 -vt 0.46875 0.59375 -vt 0.46875 0.40625 -vt 0.34375 0.40625 -vt 0.25 0.59375 -vt 0.34375 0.59375 -vt 0.34375 0.40625 -vt 0.25 0.40625 -vt 0.5625 0.59375 -vt 0.6875 0.59375 -vt 0.6875 0.40625 -vt 0.5625 0.40625 -vt 0.46875 0.59375 -vt 0.5625 0.59375 -vt 0.5625 0.40625 -vt 0.46875 0.40625 -vt 0.46875 0.59375 -vt 0.34375 0.59375 -vt 0.34375 0.6875 -vt 0.46875 0.6875 -vt 0.59375 0.6875 -vt 0.46875 0.6875 -vt 0.46875 0.59375 -vt 0.59375 0.59375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_dabf2b9e-3dd1-eda4-ab17-56ae6660288d -f 4/4/1 7/3/1 5/2/1 2/1/1 -f 3/8/2 4/7/2 2/6/2 1/5/2 -f 8/12/3 3/11/3 1/10/3 6/9/3 -f 7/16/4 8/15/4 6/14/4 5/13/4 -f 6/20/5 1/19/5 2/18/5 5/17/5 -f 7/24/6 4/23/6 3/22/6 8/21/6 -o Body -v 0.28125 1.53125 0.21875 -v 0.28125 1.53125 -0.21875 -v 0.28125 0.34375 0.21875 -v 0.28125 0.34375 -0.21875 -v -0.28125 1.53125 -0.21875 -v -0.28125 1.53125 0.21875 -v -0.28125 0.34375 -0.21875 -v -0.28125 0.34375 0.21875 -vt 0.09375 0.3125 -vt 0.21875 0.3125 -vt 0.21875 0.03125 -vt 0.09375 0.03125 -vt 0 0.3125 -vt 0.09375 0.3125 -vt 0.09375 0.03125 -vt 0 0.03125 -vt 0.3125 0.3125 -vt 0.4375 0.3125 -vt 0.4375 0.03125 -vt 0.3125 0.03125 -vt 0.21875 0.3125 -vt 0.3125 0.3125 -vt 0.3125 0.03125 -vt 0.21875 0.03125 -vt 0.21875 0.3125 -vt 0.09375 0.3125 -vt 0.09375 0.40625 -vt 0.21875 0.40625 -vt 0.34375 0.40625 -vt 0.21875 0.40625 -vt 0.21875 0.3125 -vt 0.34375 0.3125 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_dabf2b9e-3dd1-eda4-ab17-56ae6660288d -f 12/28/7 15/27/7 13/26/7 10/25/7 -f 11/32/8 12/31/8 10/30/8 9/29/8 -f 16/36/9 11/35/9 9/34/9 14/33/9 -f 15/40/10 16/39/10 14/38/10 13/37/10 -f 14/44/11 9/43/11 10/42/11 13/41/11 -f 15/48/12 12/47/12 11/46/12 16/45/12 -o Head -v 0.265625 2.140625 0.265625 -v 0.265625 2.140625 -0.265625 -v 0.265625 1.484375 0.265625 -v 0.265625 1.484375 -0.265625 -v -0.265625 2.140625 -0.265625 -v -0.265625 2.140625 0.265625 -v -0.265625 1.484375 -0.265625 -v -0.265625 1.484375 0.265625 -vt 0.125 0.875 -vt 0.25 0.875 -vt 0.25 0.71875 -vt 0.125 0.71875 -vt 0 0.875 -vt 0.125 0.875 -vt 0.125 0.71875 -vt 0 0.71875 -vt 0.375 0.875 -vt 0.5 0.875 -vt 0.5 0.71875 -vt 0.375 0.71875 -vt 0.25 0.875 -vt 0.375 0.875 -vt 0.375 0.71875 -vt 0.25 0.71875 -vt 0.25 0.875 -vt 0.125 0.875 -vt 0.125 1 -vt 0.25 1 -vt 0.375 1 -vt 0.25 1 -vt 0.25 0.875 -vt 0.375 0.875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_dabf2b9e-3dd1-eda4-ab17-56ae6660288d -f 20/52/13 23/51/13 21/50/13 18/49/13 -f 19/56/14 20/55/14 18/54/14 17/53/14 -f 24/60/15 19/59/15 17/58/15 22/57/15 -f 23/64/16 24/63/16 22/62/16 21/61/16 -f 22/68/17 17/67/17 18/66/17 21/65/17 -f 23/72/18 20/71/18 19/70/18 24/69/18 -o Head -v 0.078125 1.703125 -0.234375 -v 0.078125 1.703125 -0.390625 -v 0.078125 1.421875 -0.234375 -v 0.078125 1.421875 -0.390625 -v -0.078125 1.703125 -0.390625 -v -0.078125 1.703125 -0.234375 -v -0.078125 1.421875 -0.390625 -v -0.078125 1.421875 -0.234375 -vt 0.40625 0.96875 -vt 0.4375 0.96875 -vt 0.4375 0.90625 -vt 0.40625 0.90625 -vt 0.375 0.96875 -vt 0.40625 0.96875 -vt 0.40625 0.90625 -vt 0.375 0.90625 -vt 0.46875 0.96875 -vt 0.5 0.96875 -vt 0.5 0.90625 -vt 0.46875 0.90625 -vt 0.4375 0.96875 -vt 0.46875 0.96875 -vt 0.46875 0.90625 -vt 0.4375 0.90625 -vt 0.4375 0.96875 -vt 0.40625 0.96875 -vt 0.40625 1 -vt 0.4375 1 -vt 0.46875 1 -vt 0.4375 1 -vt 0.4375 0.96875 -vt 0.46875 0.96875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_dabf2b9e-3dd1-eda4-ab17-56ae6660288d -f 28/76/19 31/75/19 29/74/19 26/73/19 -f 27/80/20 28/79/20 26/78/20 25/77/20 -f 32/84/21 27/83/21 25/82/21 30/81/21 -f 31/88/22 32/87/22 30/86/22 29/85/22 -f 30/92/23 25/91/23 26/90/23 29/89/23 -f 31/96/24 28/95/24 27/94/24 32/93/24 -o Head Layer -v 0.28125 2.15625 0.28125 -v 0.28125 2.15625 -0.28125 -v 0.28125 1.46875 0.28125 -v 0.28125 1.46875 -0.28125 -v -0.28125 2.15625 -0.28125 -v -0.28125 2.15625 0.28125 -v -0.28125 1.46875 -0.28125 -v -0.28125 1.46875 0.28125 -vt 0.625 0.875 -vt 0.75 0.875 -vt 0.75 0.71875 -vt 0.625 0.71875 -vt 0.5 0.875 -vt 0.625 0.875 -vt 0.625 0.71875 -vt 0.5 0.71875 -vt 0.875 0.875 -vt 1 0.875 -vt 1 0.71875 -vt 0.875 0.71875 -vt 0.75 0.875 -vt 0.875 0.875 -vt 0.875 0.71875 -vt 0.75 0.71875 -vt 0.75 0.875 -vt 0.625 0.875 -vt 0.625 1 -vt 0.75 1 -vt 0.875 1 -vt 0.75 1 -vt 0.75 0.875 -vt 0.875 0.875 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_dabf2b9e-3dd1-eda4-ab17-56ae6660288d -f 36/100/25 39/99/25 37/98/25 34/97/25 -f 35/104/26 36/103/26 34/102/26 33/101/26 -f 40/108/27 35/107/27 33/106/27 38/105/27 -f 39/112/28 40/111/28 38/110/28 37/109/28 -f 38/116/29 33/115/29 34/114/29 37/113/29 -f 39/120/30 36/119/30 35/118/30 40/117/30 -o brim -v 0.5062500000000001 2.00625 -0.30625 -v 0.5062500000000001 2.00625 -0.38125 -v 0.5062500000000001 0.9937499999999999 -0.30625 -v 0.5062500000000001 0.9937499999999999 -0.38125 -v -0.50625 2.00625 -0.38125 -v -0.50625 2.00625 -0.30625 -v -0.50625 0.9937499999999999 -0.38125 -v -0.50625 0.9937499999999999 -0.30625 -vt 0.484375 0.25 -vt 0.734375 0.25 -vt 0.734375 0 -vt 0.484375 0 -vt 0.46875 0.25 -vt 0.484375 0.25 -vt 0.484375 0 -vt 0.46875 0 -vt 0.75 0.25 -vt 1 0.25 -vt 1 0 -vt 0.75 0 -vt 0.734375 0.25 -vt 0.75 0.25 -vt 0.75 0 -vt 0.734375 0 -vt 0.734375 0.25 -vt 0.484375 0.25 -vt 0.484375 0.265625 -vt 0.734375 0.265625 -vt 0.984375 0.265625 -vt 0.734375 0.265625 -vt 0.734375 0.25 -vt 0.984375 0.25 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_dabf2b9e-3dd1-eda4-ab17-56ae6660288d -f 44/124/31 47/123/31 45/122/31 42/121/31 -f 43/128/32 44/127/32 42/126/32 41/125/32 -f 48/132/33 43/131/33 41/130/33 46/129/33 -f 47/136/34 48/135/34 46/134/34 45/133/34 -f 46/140/35 41/139/35 42/138/35 45/137/35 -f 47/144/36 44/143/36 43/142/36 48/141/36 -o RightArm -v 0.5 1.5 0.125 -v 0.5 1.5 -0.125 -v 0.5 0.75 0.125 -v 0.5 0.75 -0.125 -v 0.25 1.5 -0.125 -v 0.25 1.5 0.125 -v 0.25 0.75 -0.125 -v 0.25 0.75 0.125 -vt 0.75 0.59375 -vt 0.8125 0.59375 -vt 0.8125 0.40625 -vt 0.75 0.40625 -vt 0.6875 0.59375 -vt 0.75 0.59375 -vt 0.75 0.40625 -vt 0.6875 0.40625 -vt 0.875 0.59375 -vt 0.9375 0.59375 -vt 0.9375 0.40625 -vt 0.875 0.40625 -vt 0.8125 0.59375 -vt 0.875 0.59375 -vt 0.875 0.40625 -vt 0.8125 0.40625 -vt 0.8125 0.59375 -vt 0.75 0.59375 -vt 0.75 0.65625 -vt 0.8125 0.65625 -vt 0.875 0.65625 -vt 0.8125 0.65625 -vt 0.8125 0.59375 -vt 0.875 0.59375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_dabf2b9e-3dd1-eda4-ab17-56ae6660288d -f 52/148/37 55/147/37 53/146/37 50/145/37 -f 51/152/38 52/151/38 50/150/38 49/149/38 -f 56/156/39 51/155/39 49/154/39 54/153/39 -f 55/160/40 56/159/40 54/158/40 53/157/40 -f 54/164/41 49/163/41 50/162/41 53/161/41 -f 55/168/42 52/167/42 51/166/42 56/165/42 -o LeftArm -v -0.25 1.5 0.125 -v -0.25 1.5 -0.125 -v -0.25 0.75 0.125 -v -0.25 0.75 -0.125 -v -0.5 1.5 -0.125 -v -0.5 1.5 0.125 -v -0.5 0.75 -0.125 -v -0.5 0.75 0.125 -vt 0.8125 0.59375 -vt 0.75 0.59375 -vt 0.75 0.40625 -vt 0.8125 0.40625 -vt 0.875 0.59375 -vt 0.8125 0.59375 -vt 0.8125 0.40625 -vt 0.875 0.40625 -vt 0.9375 0.59375 -vt 0.875 0.59375 -vt 0.875 0.40625 -vt 0.9375 0.40625 -vt 0.75 0.59375 -vt 0.6875 0.59375 -vt 0.6875 0.40625 -vt 0.75 0.40625 -vt 0.75 0.59375 -vt 0.8125 0.59375 -vt 0.8125 0.65625 -vt 0.75 0.65625 -vt 0.8125 0.65625 -vt 0.875 0.65625 -vt 0.875 0.59375 -vt 0.8125 0.59375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_dabf2b9e-3dd1-eda4-ab17-56ae6660288d -f 60/172/43 63/171/43 61/170/43 58/169/43 -f 59/176/44 60/175/44 58/174/44 57/173/44 -f 64/180/45 59/179/45 57/178/45 62/177/45 -f 63/184/46 64/183/46 62/182/46 61/181/46 -f 62/188/47 57/187/47 58/186/47 61/185/47 -f 63/192/48 60/191/48 59/190/48 64/189/48 -o RightLeg -v 0.25 0.75 0.125 -v 0.25 0.75 -0.125 -v 0.25 0 0.125 -v 0.25 0 -0.125 -v 0 0.75 -0.125 -v 0 0.75 0.125 -v 0 0 -0.125 -v 0 0 0.125 -vt 0.0625 0.59375 -vt 0.125 0.59375 -vt 0.125 0.40625 -vt 0.0625 0.40625 -vt 0 0.59375 -vt 0.0625 0.59375 -vt 0.0625 0.40625 -vt 0 0.40625 -vt 0.1875 0.59375 -vt 0.25 0.59375 -vt 0.25 0.40625 -vt 0.1875 0.40625 -vt 0.125 0.59375 -vt 0.1875 0.59375 -vt 0.1875 0.40625 -vt 0.125 0.40625 -vt 0.125 0.59375 -vt 0.0625 0.59375 -vt 0.0625 0.65625 -vt 0.125 0.65625 -vt 0.1875 0.65625 -vt 0.125 0.65625 -vt 0.125 0.59375 -vt 0.1875 0.59375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_dabf2b9e-3dd1-eda4-ab17-56ae6660288d -f 68/196/49 71/195/49 69/194/49 66/193/49 -f 67/200/50 68/199/50 66/198/50 65/197/50 -f 72/204/51 67/203/51 65/202/51 70/201/51 -f 71/208/52 72/207/52 70/206/52 69/205/52 -f 70/212/53 65/211/53 66/210/53 69/209/53 -f 71/216/54 68/215/54 67/214/54 72/213/54 -o LeftLeg -v 0 0.75 0.125 -v 0 0.75 -0.125 -v 0 0 0.125 -v 0 0 -0.125 -v -0.25 0.75 -0.125 -v -0.25 0.75 0.125 -v -0.25 0 -0.125 -v -0.25 0 0.125 -vt 0.125 0.59375 -vt 0.0625 0.59375 -vt 0.0625 0.40625 -vt 0.125 0.40625 -vt 0.1875 0.59375 -vt 0.125 0.59375 -vt 0.125 0.40625 -vt 0.1875 0.40625 -vt 0.25 0.59375 -vt 0.1875 0.59375 -vt 0.1875 0.40625 -vt 0.25 0.40625 -vt 0.0625 0.59375 -vt 0 0.59375 -vt 0 0.40625 -vt 0.0625 0.40625 -vt 0.0625 0.59375 -vt 0.125 0.59375 -vt 0.125 0.65625 -vt 0.0625 0.65625 -vt 0.125 0.65625 -vt 0.1875 0.65625 -vt 0.1875 0.59375 -vt 0.125 0.59375 -vn 0 0 -1 -vn 1 0 0 -vn 0 0 1 -vn -1 0 0 -vn 0 1 0 -vn 0 -1 0 -usemtl m_dabf2b9e-3dd1-eda4-ab17-56ae6660288d -f 76/220/55 79/219/55 77/218/55 74/217/55 -f 75/224/56 76/223/56 74/222/56 73/221/56 -f 80/228/57 75/227/57 73/226/57 78/225/57 -f 79/232/58 80/231/58 78/230/58 77/229/58 -f 78/236/59 73/235/59 74/234/59 77/233/59 -f 79/240/60 76/239/60 75/238/60 80/237/60 \ No newline at end of file diff --git a/renderer/viewer/three/entity/objModels.js b/renderer/viewer/three/entity/objModels.js deleted file mode 100644 index edff440b9..000000000 --- a/renderer/viewer/three/entity/objModels.js +++ /dev/null @@ -1 +0,0 @@ -export * as externalModels from './exportedModels' diff --git a/renderer/viewer/three/fireworks.ts b/renderer/viewer/three/fireworks.ts deleted file mode 100644 index 363be6f3b..000000000 --- a/renderer/viewer/three/fireworks.ts +++ /dev/null @@ -1,662 +0,0 @@ -import * as THREE from 'three' - -// Shader code -const vertexShader = ` -precision highp float; -attribute vec3 position; -attribute vec4 color; -attribute vec3 velocity; -attribute float adjustSize; -attribute float mass; - -uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; -uniform float size; - -varying vec4 vColor; - -void main() { - vColor = color; - vec4 mvPosition = modelViewMatrix * vec4(position, 1.0); - gl_PointSize = size * adjustSize * (300.0 / length(mvPosition.xyz)); - gl_Position = projectionMatrix * mvPosition; -} -` - -const fragmentShader = ` -precision highp float; -uniform sampler2D texture; -varying vec4 vColor; - -void main() { - vec4 texColor = texture2D(texture, gl_PointCoord); - gl_FragColor = vColor * texColor; -} -` - -// Configuration interfaces -export interface FireworkLaunchOptions { - /** Position to launch the firework from */ - position?: THREE.Vector3 - /** Particle size (100-600, default: 300) */ - particleSize?: number - /** Force rich fireworks type (with trails) */ - forceRich?: boolean - /** Force basic fireworks type (no trails) */ - forceBasic?: boolean -} - -export interface FireworksManagerConfig { - /** Maximum number of active fireworks at once */ - maxActiveFireworks?: number - /** Default particle size for fireworks */ - defaultParticleSize?: number -} - -// Constants -export const FIREWORKS_CONFIG = { - textureSize: 128, - gravity: new THREE.Vector3(0, -0.005, 0), - friction: 0.998, - defaultParticleSize: 300, - maxActiveFireworks: 5, -} - -// Utility functions -const getOffsetXYZ = (i: number) => { - const offset = 3 - const index = i * offset - return { x: index, y: index + 1, z: index + 2 } -} - -const getOffsetRGBA = (i: number) => { - const offset = 4 - const index = i * offset - return { r: index, g: index + 1, b: index + 2, a: index + 3 } -} - -const getRandomNum = (max = 0, min = 0) => Math.floor(Math.random() * (max + 1 - min)) + min - -// Texture generation -const drawRadialGradation = (ctx: CanvasRenderingContext2D, canvasRadius: number, canvasW: number, canvasH: number) => { - ctx.save() - const gradient = ctx.createRadialGradient(canvasRadius, canvasRadius, 0, canvasRadius, canvasRadius, canvasRadius) - gradient.addColorStop(0, 'rgba(255,255,255,1.0)') - gradient.addColorStop(0.5, 'rgba(255,255,255,0.5)') - gradient.addColorStop(1, 'rgba(255,255,255,0)') - ctx.fillStyle = gradient - ctx.fillRect(0, 0, canvasW, canvasH) - ctx.restore() -} - -export const createFireworksTexture = () => { - const canvas = document.createElement('canvas') - const ctx = canvas.getContext('2d')! - const diameter = FIREWORKS_CONFIG.textureSize - canvas.width = diameter - canvas.height = diameter - const canvasRadius = diameter / 2 - - drawRadialGradation(ctx, canvasRadius, canvas.width, canvas.height) - const texture = new THREE.Texture(canvas) - texture.needsUpdate = true - return texture -} - -// Point mesh creation -const getPointMesh = (num: number, vels: THREE.Vector3[], type: 'seed' | 'trail' | 'default', texture: THREE.Texture, particleSize = FIREWORKS_CONFIG.defaultParticleSize) => { - const bufferGeometry = new THREE.BufferGeometry() - const vertices: number[] = [] - const velocities: number[] = [] - const colors: number[] = [] - const adjustSizes: number[] = [] - const masses: number[] = [] - - const colorType = Math.random() > 0.3 ? 'single' : 'multiple' - const singleColor = getRandomNum(100, 20) * 0.01 - const multipleColor = () => getRandomNum(100, 1) * 0.01 - - let rgbType: 'red' | 'green' | 'blue' = 'red' - const rgbTypeDice = Math.random() - if (rgbTypeDice > 0.66) { - rgbType = 'red' - } else if (rgbTypeDice > 0.33) { - rgbType = 'green' - } else { - rgbType = 'blue' - } - - for (let i = 0; i < num; i++) { - const pos = new THREE.Vector3(0, 0, 0) - vertices.push(pos.x, pos.y, pos.z) - velocities.push(vels[i].x, vels[i].y, vels[i].z) - - if (type === 'seed') { - let size = vels[i].y ** 2 * 0.04 - if (i === 0) size *= 1.1 - adjustSizes.push(size) - masses.push(size * 0.017) - colors.push(1, 1, 1, 1) - } else if (type === 'trail') { - const size = Math.random() * 0.1 + 0.1 - adjustSizes.push(size) - masses.push(size * 0.017) - colors.push(1, 1, 1, 1) - } else { - const size = getRandomNum(particleSize, 10) * 0.001 - adjustSizes.push(size) - masses.push(size * 0.017) - - if (colorType === 'multiple') { - colors.push(multipleColor(), multipleColor(), multipleColor(), 1) - } else { - switch (rgbType) { - case 'red': - colors.push(singleColor, 0.1, 0.1, 1) - break - case 'green': - colors.push(0.1, singleColor, 0.1, 1) - break - case 'blue': - colors.push(0.1, 0.1, singleColor, 1) - break - } - } - } - } - - bufferGeometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3)) - bufferGeometry.setAttribute('velocity', new THREE.Float32BufferAttribute(velocities, 3)) - bufferGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 4)) - bufferGeometry.setAttribute('adjustSize', new THREE.Float32BufferAttribute(adjustSizes, 1)) - bufferGeometry.setAttribute('mass', new THREE.Float32BufferAttribute(masses, 1)) - - const shaderMaterial = new THREE.RawShaderMaterial({ - uniforms: { - size: { value: FIREWORKS_CONFIG.textureSize }, - texture: { value: texture }, - }, - transparent: true, - depthWrite: false, - blending: THREE.AdditiveBlending, - vertexShader, - fragmentShader, - }) - - return new THREE.Points(bufferGeometry, shaderMaterial) -} - -// Particle mesh classes -export class ParticleMesh { - particleNum: number - timerStartFading: number - mesh: THREE.Points - - constructor (num: number, vels: THREE.Vector3[], type: 'seed' | 'trail' | 'default', texture: THREE.Texture, particleSize?: number) { - this.particleNum = num - this.timerStartFading = 10 - this.mesh = getPointMesh(num, vels, type, texture, particleSize) - } - - update (gravity: THREE.Vector3) { - if (this.timerStartFading > 0) this.timerStartFading -= 0.3 - - const position = this.mesh.geometry.attributes.position as THREE.BufferAttribute - const velocity = this.mesh.geometry.attributes.velocity as THREE.BufferAttribute - const color = this.mesh.geometry.attributes.color as THREE.BufferAttribute - const mass = this.mesh.geometry.attributes.mass as THREE.BufferAttribute - - const decrementRandom = () => (Math.random() > 0.5 ? 0.98 : 0.96) - const decrementByVel = (v: number) => (Math.random() > 0.5 ? 0 : (1 - v) * 0.1) - - for (let i = 0; i < this.particleNum; i++) { - const { x, y, z } = getOffsetXYZ(i) - - velocity.array[y] += gravity.y - mass.array[i] - velocity.array[x] *= FIREWORKS_CONFIG.friction - velocity.array[z] *= FIREWORKS_CONFIG.friction - velocity.array[y] *= FIREWORKS_CONFIG.friction - - position.array[x] += velocity.array[x] - position.array[y] += velocity.array[y] - position.array[z] += velocity.array[z] - - const { a } = getOffsetRGBA(i) - if (this.timerStartFading <= 0) { - color.array[a] *= decrementRandom() - decrementByVel(color.array[a]) - if (color.array[a] < 0.001) color.array[a] = 0 - } - } - - position.needsUpdate = true - velocity.needsUpdate = true - color.needsUpdate = true - } - - disposeAll () { - this.mesh.geometry.dispose() - ;(this.mesh.material as THREE.Material).dispose() - } -} - -export class ParticleSeedMesh extends ParticleMesh { - constructor (num: number, vels: THREE.Vector3[], texture: THREE.Texture) { - super(num, vels, 'seed', texture) - } - - update (gravity: THREE.Vector3) { - const position = this.mesh.geometry.attributes.position as THREE.BufferAttribute - const velocity = this.mesh.geometry.attributes.velocity as THREE.BufferAttribute - const color = this.mesh.geometry.attributes.color as THREE.BufferAttribute - const mass = this.mesh.geometry.attributes.mass as THREE.BufferAttribute - - const decrementRandom = () => (Math.random() > 0.3 ? 0.99 : 0.96) - const decrementByVel = (v: number) => (Math.random() > 0.3 ? 0 : (1 - v) * 0.1) - const shake = () => (Math.random() > 0.5 ? 0.05 : -0.05) - const dice = () => Math.random() > 0.1 - const _f = FIREWORKS_CONFIG.friction * 0.98 - - for (let i = 0; i < this.particleNum; i++) { - const { x, y, z } = getOffsetXYZ(i) - - velocity.array[y] += gravity.y - mass.array[i] - velocity.array[x] *= _f - velocity.array[z] *= _f - velocity.array[y] *= _f - - position.array[x] += velocity.array[x] - position.array[y] += velocity.array[y] - position.array[z] += velocity.array[z] - - if (dice()) position.array[x] += shake() - if (dice()) position.array[z] += shake() - - const { a } = getOffsetRGBA(i) - color.array[a] *= decrementRandom() - decrementByVel(color.array[a]) - if (color.array[a] < 0.001) color.array[a] = 0 - } - - position.needsUpdate = true - velocity.needsUpdate = true - color.needsUpdate = true - } -} - -export class ParticleTailMesh extends ParticleMesh { - constructor (num: number, vels: THREE.Vector3[], texture: THREE.Texture) { - super(num, vels, 'trail', texture) - } - - update (gravity: THREE.Vector3) { - const position = this.mesh.geometry.attributes.position as THREE.BufferAttribute - const velocity = this.mesh.geometry.attributes.velocity as THREE.BufferAttribute - const color = this.mesh.geometry.attributes.color as THREE.BufferAttribute - const mass = this.mesh.geometry.attributes.mass as THREE.BufferAttribute - - const decrementRandom = () => (Math.random() > 0.3 ? 0.98 : 0.95) - const shake = () => (Math.random() > 0.5 ? 0.05 : -0.05) - const dice = () => Math.random() > 0.2 - - for (let i = 0; i < this.particleNum; i++) { - const { x, y, z } = getOffsetXYZ(i) - - velocity.array[y] += gravity.y - mass.array[i] - velocity.array[x] *= FIREWORKS_CONFIG.friction - velocity.array[z] *= FIREWORKS_CONFIG.friction - velocity.array[y] *= FIREWORKS_CONFIG.friction - - position.array[x] += velocity.array[x] - position.array[y] += velocity.array[y] - position.array[z] += velocity.array[z] - - if (dice()) position.array[x] += shake() - if (dice()) position.array[z] += shake() - - const { a } = getOffsetRGBA(i) - color.array[a] *= decrementRandom() - if (color.array[a] < 0.001) color.array[a] = 0 - } - - position.needsUpdate = true - velocity.needsUpdate = true - color.needsUpdate = true - } -} - -// Fireworks classes -export class BasicFireworks { - meshGroup: THREE.Group - isExplode: boolean - petalsNum: number - life: number - seed: ParticleSeedMesh - flowerSizeRate: number - flower?: ParticleMesh - texture: THREE.Texture - particleSize: number - - constructor (texture: THREE.Texture, particleSize = FIREWORKS_CONFIG.defaultParticleSize, startPosition?: THREE.Vector3) { - this.meshGroup = new THREE.Group() - this.isExplode = false - this.texture = texture - this.particleSize = particleSize - - const max = 400 - const min = 150 - this.petalsNum = getRandomNum(max, min) - this.life = 150 - this.seed = this.getSeed(startPosition) - this.meshGroup.add(this.seed.mesh) - this.flowerSizeRate = THREE.MathUtils.mapLinear(this.petalsNum, min, max, 0.4, 0.7) - } - - getSeed (startPosition?: THREE.Vector3): ParticleSeedMesh { - const num = 40 - const vels: THREE.Vector3[] = [] - - for (let i = 0; i < num; i++) { - const vx = 0 - const vy = i === 0 ? Math.random() * 2.5 + 0.9 : Math.random() * 2 + 0.4 - const vz = 0 - vels.push(new THREE.Vector3(vx, vy, vz)) - } - - const pm = new ParticleSeedMesh(num, vels, this.texture) - if (startPosition) { - pm.mesh.position.set(startPosition.x, startPosition.y, startPosition.z) - } else { - const x = Math.random() * 80 - 40 - const y = -50 - const z = Math.random() * 80 - 40 - pm.mesh.position.set(x, y, z) - } - - return pm - } - - explode (pos: THREE.Vector3) { - this.isExplode = true - this.flower = this.getFlower(pos) - this.meshGroup.add(this.flower.mesh) - this.meshGroup.remove(this.seed.mesh) - this.seed.disposeAll() - } - - getFlower (pos: THREE.Vector3): ParticleMesh { - const num = this.petalsNum - const vels: THREE.Vector3[] = [] - let radius: number - const dice = Math.random() - - if (dice > 0.5) { - for (let i = 0; i < num; i++) { - radius = getRandomNum(120, 60) * 0.01 - const theta = THREE.MathUtils.degToRad(Math.random() * 180) - const phi = THREE.MathUtils.degToRad(Math.random() * 360) - const vx = Math.sin(theta) * Math.cos(phi) * radius - const vy = Math.sin(theta) * Math.sin(phi) * radius - const vz = Math.cos(theta) * radius - const vel = new THREE.Vector3(vx, vy, vz) - vel.multiplyScalar(this.flowerSizeRate) - vels.push(vel) - } - } else { - const zStep = 180 / num - const trad = (360 * (Math.random() * 20 + 1)) / num - const xStep = trad - const yStep = trad - radius = getRandomNum(120, 60) * 0.01 - - for (let i = 0; i < num; i++) { - const sphereRate = Math.sin(THREE.MathUtils.degToRad(zStep * i)) - const vz = Math.cos(THREE.MathUtils.degToRad(zStep * i)) * radius - const vx = Math.cos(THREE.MathUtils.degToRad(xStep * i)) * sphereRate * radius - const vy = Math.sin(THREE.MathUtils.degToRad(yStep * i)) * sphereRate * radius - const vel = new THREE.Vector3(vx, vy, vz) - vel.multiplyScalar(this.flowerSizeRate) - vels.push(vel) - } - } - - const particleMesh = new ParticleMesh(num, vels, 'default', this.texture, this.particleSize) - particleMesh.mesh.position.set(pos.x, pos.y, pos.z) - return particleMesh - } - - update (gravity: THREE.Vector3) { - if (this.isExplode) { - this.flower!.update(gravity) - if (this.life > 0) this.life -= 1 - } else { - this.drawTail() - } - } - - drawTail () { - this.seed.update(FIREWORKS_CONFIG.gravity) - - const position = this.seed.mesh.geometry.attributes.position as THREE.BufferAttribute - const velocity = this.seed.mesh.geometry.attributes.velocity as THREE.BufferAttribute - - let count = 0 - - // Check if the y-axis speed is down for all particles - for (let i = 0, l = velocity.array.length; i < l; i++) { - const v = velocity.array[i] - const index = i % 3 - if (index === 1 && v > 0) { - count++ - } - } - - const isComplete = count === 0 - if (!isComplete) return - - const { x, y, z } = this.seed.mesh.position - const flowerPos = new THREE.Vector3(x, y, z) - let highestPos = 0 - let offsetPos: THREE.Vector3 | undefined - - for (let i = 0, l = position.array.length; i < l; i++) { - const p = position.array[i] - const index = i % 3 - if (index === 1 && p > highestPos) { - highestPos = p - offsetPos = new THREE.Vector3(position.array[i - 1], p, position.array[i + 2]) - } - } - - if (offsetPos) { - flowerPos.add(offsetPos) - this.explode(flowerPos) - } - } -} - -export class RichFireworks extends BasicFireworks { - tailMeshGroup: THREE.Group - tails: ParticleTailMesh[] - - constructor (texture: THREE.Texture, particleSize = FIREWORKS_CONFIG.defaultParticleSize, startPosition?: THREE.Vector3) { - super(texture, particleSize, startPosition) - - const max = 150 - const min = 100 - this.petalsNum = getRandomNum(max, min) - this.flowerSizeRate = THREE.MathUtils.mapLinear(this.petalsNum, min, max, 0.4, 0.7) - this.tailMeshGroup = new THREE.Group() - this.tails = [] - } - - explode (pos: THREE.Vector3) { - this.isExplode = true - this.flower = this.getFlower(pos) - this.tails = this.getTail() - this.meshGroup.add(this.flower.mesh) - this.meshGroup.add(this.tailMeshGroup) - } - - getTail (): ParticleTailMesh[] { - const tails: ParticleTailMesh[] = [] - const num = 20 - const petalColor = this.flower!.mesh.geometry.attributes.color as THREE.BufferAttribute - - for (let i = 0; i < this.petalsNum; i++) { - const vels: THREE.Vector3[] = [] - for (let j = 0; j < num; j++) { - vels.push(new THREE.Vector3(0, 0, 0)) - } - - const tail = new ParticleTailMesh(num, vels, this.texture) - const { r, g, b, a } = getOffsetRGBA(i) - - const petalR = petalColor.array[r] - const petalG = petalColor.array[g] - const petalB = petalColor.array[b] - const petalA = petalColor.array[a] - - const position = tail.mesh.geometry.attributes.position as THREE.BufferAttribute - const color = tail.mesh.geometry.attributes.color as THREE.BufferAttribute - - for (let k = 0; k < position.count; k++) { - const rgba = getOffsetRGBA(k) - color.array[rgba.r] = petalR - color.array[rgba.g] = petalG - color.array[rgba.b] = petalB - color.array[rgba.a] = petalA - } - - const { x, y, z } = this.flower!.mesh.position - tail.mesh.position.set(x, y, z) - tails.push(tail) - this.tailMeshGroup.add(tail.mesh) - } - - return tails - } - - update (gravity: THREE.Vector3) { - if (this.isExplode) { - this.flower!.update(gravity) - - const flowerGeometry = this.flower!.mesh.geometry.attributes.position as THREE.BufferAttribute - - for (let i = 0, l = this.tails.length; i < l; i++) { - const tail = this.tails[i] - tail.update(gravity) - - const { x, y, z } = getOffsetXYZ(i) - const flowerPos = new THREE.Vector3( - flowerGeometry.array[x], - flowerGeometry.array[y], - flowerGeometry.array[z] - ) - - const position = tail.mesh.geometry.attributes.position as THREE.BufferAttribute - const velocity = tail.mesh.geometry.attributes.velocity as THREE.BufferAttribute - - for (let k = 0; k < position.count; k++) { - const offset = getOffsetXYZ(k) - const desiredVelocity = new THREE.Vector3() - const tailPos = new THREE.Vector3(position.array[offset.x], position.array[offset.y], position.array[offset.z]) - const tailVel = new THREE.Vector3(velocity.array[offset.x], velocity.array[offset.y], velocity.array[offset.z]) - desiredVelocity.subVectors(flowerPos, tailPos) - const steer = desiredVelocity.sub(tailVel) - steer.normalize() - steer.multiplyScalar(Math.random() * 0.0003 * this.life) - velocity.array[offset.x] += steer.x - velocity.array[offset.y] += steer.y - velocity.array[offset.z] += steer.z - } - velocity.needsUpdate = true - } - - if (this.life > 0) this.life -= 1.2 - } else { - this.drawTail() - } - } -} - -// Manager class for handling multiple fireworks -export class FireworksManager { - fireworksInstances: Array - scene: THREE.Scene - texture: THREE.Texture - particleSize: number - maxFireworks: number - - constructor (scene: THREE.Scene, config?: FireworksManagerConfig) { - this.fireworksInstances = [] - this.scene = scene - this.texture = createFireworksTexture() - this.particleSize = config?.defaultParticleSize ?? FIREWORKS_CONFIG.defaultParticleSize - this.maxFireworks = config?.maxActiveFireworks ?? FIREWORKS_CONFIG.maxActiveFireworks - } - - launchFirework (options?: FireworkLaunchOptions) { - if (this.fireworksInstances.length >= this.maxFireworks) return - - const particleSize = options?.particleSize ?? this.particleSize - const position = options?.position - - let fw: BasicFireworks | RichFireworks - if (options?.forceRich) { - fw = new RichFireworks(this.texture, particleSize, position) - } else if (options?.forceBasic) { - fw = new BasicFireworks(this.texture, particleSize, position) - } else { - fw = Math.random() > 0.5 ? new BasicFireworks(this.texture, particleSize, position) : new RichFireworks(this.texture, particleSize, position) - } - - this.fireworksInstances.push(fw) - this.scene.add(fw.meshGroup) - } - - update () { - const explodedIndexList: number[] = [] - - for (let i = this.fireworksInstances.length - 1; i >= 0; i--) { - const instance = this.fireworksInstances[i] - instance.update(FIREWORKS_CONFIG.gravity) - if (instance.isExplode) explodedIndexList.push(i) - } - - for (let i = 0, l = explodedIndexList.length; i < l; i++) { - const index = explodedIndexList[i] - const instance = this.fireworksInstances[index] - if (!instance) continue - - instance.meshGroup.remove(instance.seed.mesh) - instance.seed.disposeAll() - - if (instance.life <= 0) { - this.scene.remove(instance.meshGroup) - if (instance instanceof RichFireworks && instance.tailMeshGroup) { - for (const v of instance.tails) { - v.disposeAll() - } - } - instance.flower?.disposeAll() - this.fireworksInstances.splice(index, 1) - } - } - } - - clear () { - for (const instance of this.fireworksInstances) { - this.scene.remove(instance.meshGroup) - instance.seed.disposeAll() - if (instance.flower) instance.flower.disposeAll() - if (instance instanceof RichFireworks) { - for (const v of instance.tails) v.disposeAll() - } - } - this.fireworksInstances = [] - } - - dispose () { - this.clear() - this.texture.dispose() - } -} diff --git a/renderer/viewer/three/graphicsBackend.ts b/renderer/viewer/three/graphicsBackend.ts deleted file mode 100644 index 22bcab0ce..000000000 --- a/renderer/viewer/three/graphicsBackend.ts +++ /dev/null @@ -1,168 +0,0 @@ -import * as THREE from 'three' -import { Vec3 } from 'vec3' -import { GraphicsBackendLoader, GraphicsBackend, GraphicsInitOptions, DisplayWorldOptions } from '../../../src/appViewer' -import { ProgressReporter } from '../../../src/core/progressReporter' -import { showNotification } from '../../../src/react/NotificationProvider' -import { displayEntitiesDebugList } from '../../playground/allEntitiesDebug' -import supportedVersions from '../../../src/supportedVersions.mjs' -import { ResourcesManager } from '../../../src/resourcesManager' -import { WorldRendererThree } from './worldrendererThree' -import { DocumentRenderer } from './documentRenderer' -import { PanoramaRenderer } from './panorama' -import { initVR } from './world/vr' - -// https://discourse.threejs.org/t/updates-to-color-management-in-three-js-r152/50791 -THREE.ColorManagement.enabled = false -globalThis.THREE = THREE - -const getBackendMethods = (worldRenderer: WorldRendererThree) => { - return { - updateMap: worldRenderer.entities.updateMap.bind(worldRenderer.entities), - updateCustomBlock: worldRenderer.updateCustomBlock.bind(worldRenderer), - getBlockInfo: worldRenderer.getBlockInfo.bind(worldRenderer), - playEntityAnimation: worldRenderer.entities.playAnimation.bind(worldRenderer.entities), - damageEntity: worldRenderer.entities.handleDamageEvent.bind(worldRenderer.entities), - updatePlayerSkin: worldRenderer.entities.updatePlayerSkin.bind(worldRenderer.entities), - changeHandSwingingState: worldRenderer.changeHandSwingingState.bind(worldRenderer), - getHighestBlocks: worldRenderer.getHighestBlocks.bind(worldRenderer), - reloadWorld: worldRenderer.reloadWorld.bind(worldRenderer), - - addMedia: worldRenderer.media.addMedia.bind(worldRenderer.media), - destroyMedia: worldRenderer.media.destroyMedia.bind(worldRenderer.media), - setVideoPlaying: worldRenderer.media.setVideoPlaying.bind(worldRenderer.media), - setVideoSeeking: worldRenderer.media.setVideoSeeking.bind(worldRenderer.media), - setVideoVolume: worldRenderer.media.setVideoVolume.bind(worldRenderer.media), - setVideoSpeed: worldRenderer.media.setVideoSpeed.bind(worldRenderer.media), - - addSectionAnimation (id: string, animation: typeof worldRenderer.sectionsOffsetsAnimations[string]) { - worldRenderer.sectionsOffsetsAnimations[id] = animation - }, - removeSectionAnimation (id: string) { - delete worldRenderer.sectionsOffsetsAnimations[id] - }, - - shakeFromDamage: worldRenderer.cameraShake.shakeFromDamage.bind(worldRenderer.cameraShake), - onPageInteraction: worldRenderer.media.onPageInteraction.bind(worldRenderer.media), - downloadMesherLog: worldRenderer.downloadMesherLog.bind(worldRenderer), - - addWaypoint: worldRenderer.waypoints.addWaypoint.bind(worldRenderer.waypoints), - removeWaypoint: worldRenderer.waypoints.removeWaypoint.bind(worldRenderer.waypoints), - - launchFirework: worldRenderer.fireworks.launchFirework.bind(worldRenderer.fireworks), - - // New method for updating skybox - setSkyboxImage: worldRenderer.skyboxRenderer.setSkyboxImage.bind(worldRenderer.skyboxRenderer) - } -} - -export type ThreeJsBackendMethods = ReturnType - -const createGraphicsBackend: GraphicsBackendLoader = (initOptions: GraphicsInitOptions) => { - // Private state - const documentRenderer = new DocumentRenderer(initOptions) - globalThis.renderer = documentRenderer.renderer - - let panoramaRenderer: PanoramaRenderer | null = null - let worldRenderer: WorldRendererThree | null = null - - const startPanorama = async () => { - if (!documentRenderer) throw new Error('Document renderer not initialized') - if (worldRenderer) return - const qs = new URLSearchParams(location.search) - if (qs.get('debugEntities')) { - const fullResourceManager = initOptions.resourcesManager as ResourcesManager - fullResourceManager.currentConfig = { version: qs.get('version') || supportedVersions.at(-1)!, noInventoryGui: true } - await fullResourceManager.updateAssetsData({ }) - - displayEntitiesDebugList(fullResourceManager.currentConfig.version) - return - } - - if (!panoramaRenderer) { - panoramaRenderer = new PanoramaRenderer(documentRenderer, initOptions, !!process.env.SINGLE_FILE_BUILD_MODE) - globalThis.panoramaRenderer = panoramaRenderer - callModsMethod('panoramaCreated', panoramaRenderer) - await panoramaRenderer.start() - callModsMethod('panoramaReady', panoramaRenderer) - } - } - - const startWorld = async (displayOptions: DisplayWorldOptions) => { - if (panoramaRenderer) { - panoramaRenderer.dispose() - panoramaRenderer = null - } - worldRenderer = new WorldRendererThree(documentRenderer.renderer, initOptions, displayOptions) - void initVR(worldRenderer, documentRenderer) - await worldRenderer.worldReadyPromise - documentRenderer.render = (sizeChanged: boolean) => { - worldRenderer?.render(sizeChanged) - } - documentRenderer.inWorldRenderingConfig = displayOptions.inWorldRenderingConfig - window.world = worldRenderer - callModsMethod('worldReady', worldRenderer) - } - - const disconnect = () => { - if (panoramaRenderer) { - panoramaRenderer.dispose() - panoramaRenderer = null - } - if (documentRenderer) { - documentRenderer.dispose() - } - if (worldRenderer) { - worldRenderer.destroy() - worldRenderer = null - } - } - - // Public interface - const backend: GraphicsBackend = { - id: 'threejs', - displayName: `three.js ${THREE.REVISION}`, - startPanorama, - startWorld, - disconnect, - setRendering (rendering) { - documentRenderer.setPaused(!rendering) - if (worldRenderer) worldRenderer.renderingActive = rendering - }, - getDebugOverlay: () => ({ - get entitiesString () { - return worldRenderer?.entities.getDebugString() - }, - }), - updateCamera (pos: Vec3 | null, yaw: number, pitch: number) { - worldRenderer?.setFirstPersonCamera(pos, yaw, pitch) - }, - get soundSystem () { - return worldRenderer?.soundSystem - }, - get backendMethods () { - if (!worldRenderer) return undefined - return getBackendMethods(worldRenderer) - } - } - - globalThis.threeJsBackend = backend - globalThis.resourcesManager = initOptions.resourcesManager - callModsMethod('default', backend) - - return backend -} - -const callModsMethod = (method: string, ...args: any[]) => { - for (const mod of Object.values((window.loadedMods ?? {}) as Record)) { - try { - mod.threeJsBackendModule?.[method]?.(...args) - } catch (err) { - const errorMessage = `[mod three.js] Error calling ${method} on ${mod.name}: ${err}` - showNotification(errorMessage, 'error') - throw new Error(errorMessage) - } - } -} - -createGraphicsBackend.id = 'threejs' -export default createGraphicsBackend diff --git a/renderer/viewer/three/hand.ts b/renderer/viewer/three/hand.ts deleted file mode 100644 index 2bd3832b6..000000000 --- a/renderer/viewer/three/hand.ts +++ /dev/null @@ -1,89 +0,0 @@ -import * as THREE from 'three' -import { loadSkinFromUsername, loadSkinImage } from '../lib/utils/skins' -import { steveTexture } from './entities' - - -export const getMyHand = async (image?: string, userName?: string) => { - let newMap: THREE.Texture - if (!image && !userName) { - newMap = await steveTexture - } else { - if (!image) { - image = await loadSkinFromUsername(userName!, 'skin') - } - if (!image) { - return - } - const { canvas } = await loadSkinImage(image) - newMap = new THREE.CanvasTexture(canvas) - } - - newMap.magFilter = THREE.NearestFilter - newMap.minFilter = THREE.NearestFilter - // right arm - const box = new THREE.BoxGeometry() - const material = new THREE.MeshStandardMaterial() - const slim = false - const mesh = new THREE.Mesh(box, material) - mesh.scale.x = slim ? 3 : 4 - mesh.scale.y = 12 - mesh.scale.z = 4 - setSkinUVs(box, 40, 16, slim ? 3 : 4, 12, 4) - material.map = newMap - material.needsUpdate = true - const group = new THREE.Group() - group.add(mesh) - group.scale.set(0.1, 0.1, 0.1) - mesh.rotation.z = Math.PI - return group -} - -function setUVs ( - box: THREE.BoxGeometry, - u: number, - v: number, - width: number, - height: number, - depth: number, - textureWidth: number, - textureHeight: number -): void { - const toFaceVertices = (x1: number, y1: number, x2: number, y2: number) => [ - new THREE.Vector2(x1 / textureWidth, 1 - y2 / textureHeight), - new THREE.Vector2(x2 / textureWidth, 1 - y2 / textureHeight), - new THREE.Vector2(x2 / textureWidth, 1 - y1 / textureHeight), - new THREE.Vector2(x1 / textureWidth, 1 - y1 / textureHeight), - ] - - const top = toFaceVertices(u + depth, v, u + width + depth, v + depth) - const bottom = toFaceVertices(u + width + depth, v, u + width * 2 + depth, v + depth) - const left = toFaceVertices(u, v + depth, u + depth, v + depth + height) - const front = toFaceVertices(u + depth, v + depth, u + width + depth, v + depth + height) - const right = toFaceVertices(u + width + depth, v + depth, u + width + depth * 2, v + height + depth) - const back = toFaceVertices(u + width + depth * 2, v + depth, u + width * 2 + depth * 2, v + height + depth) - - const uvAttr = box.attributes.uv as THREE.BufferAttribute - const uvRight = [right[3], right[2], right[0], right[1]] - const uvLeft = [left[3], left[2], left[0], left[1]] - const uvTop = [top[3], top[2], top[0], top[1]] - const uvBottom = [bottom[0], bottom[1], bottom[3], bottom[2]] - const uvFront = [front[3], front[2], front[0], front[1]] - const uvBack = [back[3], back[2], back[0], back[1]] - - // Create a new array to hold the modified UV data - const newUVData = [] as number[] - - // Iterate over the arrays and copy the data to uvData - for (const uvArray of [uvRight, uvLeft, uvTop, uvBottom, uvFront, uvBack]) { - for (const uv of uvArray) { - newUVData.push(uv.x, uv.y) - } - } - - uvAttr.set(new Float32Array(newUVData)) - uvAttr.needsUpdate = true -} - -function setSkinUVs (box: THREE.BoxGeometry, u: number, v: number, width: number, height: number, depth: number): void { - setUVs(box, u, v, width, height, depth, 64, 64) -} diff --git a/renderer/viewer/three/holdingBlock.ts b/renderer/viewer/three/holdingBlock.ts deleted file mode 100644 index f9d00f0e0..000000000 --- a/renderer/viewer/three/holdingBlock.ts +++ /dev/null @@ -1,933 +0,0 @@ -import * as THREE from 'three' -import * as tweenJs from '@tweenjs/tween.js' -import PrismarineItem from 'prismarine-item' -import worldBlockProvider, { WorldBlockProvider } from 'mc-assets/dist/worldBlockProvider' -import { BlockModel } from 'mc-assets' -import { getThreeBlockModelGroup, renderBlockThree, setBlockPosition } from '../lib/mesher/standaloneRenderer' -import { MovementState, PlayerStateRenderer } from '../lib/basePlayerState' -import { DebugGui } from '../lib/DebugGui' -import { SmoothSwitcher } from '../lib/smoothSwitcher' -import { watchProperty } from '../lib/utils/proxy' -import { WorldRendererConfig } from '../lib/worldrendererCommon' -import { getMyHand } from './hand' -import { WorldRendererThree } from './worldrendererThree' -import { disposeObject } from './threeJsUtils' - -export type HandItemBlock = { - name? - properties? - fullItem? - type: 'block' | 'item' | 'hand' - id?: number -} - -const rotationPositionData = { - itemRight: { - 'rotation': [ - 0, - -90, - 25 - ], - 'translation': [ - 1.13, - 3.2, - 1.13 - ], - 'scale': [ - 0.68, - 0.68, - 0.68 - ] - }, - itemLeft: { - 'rotation': [ - 0, - 90, - -25 - ], - 'translation': [ - 1.13, - 3.2, - 1.13 - ], - 'scale': [ - 0.68, - 0.68, - 0.68 - ] - }, - blockRight: { - 'rotation': [ - 0, - 45, - 0 - ], - 'translation': [ - 0, - 0, - 0 - ], - 'scale': [ - 0.4, - 0.4, - 0.4 - ] - }, - blockLeft: { - 'rotation': [ - 0, - 225, - 0 - ], - 'translation': [ - 0, - 0, - 0 - ], - 'scale': [ - 0.4, - 0.4, - 0.4 - ] - } -} - -export default class HoldingBlock { - // TODO refactor with the tree builder for better visual understanding - holdingBlock: THREE.Object3D | undefined = undefined - blockSwapAnimation: { - switcher: SmoothSwitcher - // hidden: boolean - } | undefined = undefined - cameraGroup = new THREE.Mesh() - objectOuterGroup = new THREE.Group() // 3 - objectInnerGroup = new THREE.Group() // 4 - holdingBlockInnerGroup = new THREE.Group() // 5 - camera = new THREE.PerspectiveCamera(75, 1, 0.1, 100) - stopUpdate = false - lastHeldItem: HandItemBlock | undefined - isSwinging = false - nextIterStopCallbacks: Array<() => void> | undefined - idleAnimator: HandIdleAnimator | undefined - ready = false - lastUpdate = 0 - playerHand: THREE.Object3D | undefined - offHandDisplay = false - offHandModeLegacy = false - - swingAnimator: HandSwingAnimator | undefined - config: WorldRendererConfig - - constructor (public worldRenderer: WorldRendererThree, public offHand = false) { - this.initCameraGroup() - this.worldRenderer.onReactivePlayerStateUpdated('heldItemMain', () => { - if (!this.offHand) { - this.updateItem() - } - }, false) - this.worldRenderer.onReactivePlayerStateUpdated('heldItemOff', () => { - if (this.offHand) { - this.updateItem() - } - }, false) - this.config = worldRenderer.displayOptions.inWorldRenderingConfig - - this.offHandDisplay = this.offHand - // this.offHandDisplay = true - if (!this.offHand) { - // load default hand - void getMyHand().then((hand) => { - this.playerHand = hand - // trigger update - this.updateItem() - }).then(() => { - // now watch over the player skin - watchProperty( - async () => { - return getMyHand(this.worldRenderer.playerStateReactive.playerSkin, this.worldRenderer.playerStateReactive.onlineMode ? this.worldRenderer.playerStateReactive.username : undefined) - }, - this.worldRenderer.playerStateReactive, - 'playerSkin', - (newHand) => { - if (newHand) { - this.playerHand = newHand - // trigger update - this.updateItem() - } - }, - (oldHand) => { - disposeObject(oldHand!, true) - } - ) - }) - } - } - - updateItem () { - if (!this.ready) return - const item = this.offHand ? this.worldRenderer.playerStateReactive.heldItemOff : this.worldRenderer.playerStateReactive.heldItemMain - if (item) { - void this.setNewItem(item) - } else if (this.offHand) { - void this.setNewItem() - } else { - void this.setNewItem({ - type: 'hand', - }) - } - } - - initCameraGroup () { - this.cameraGroup = new THREE.Mesh() - } - - startSwing () { - this.swingAnimator?.startSwing() - } - - stopSwing () { - this.swingAnimator?.stopSwing() - } - - render (originalCamera: THREE.PerspectiveCamera, renderer: THREE.WebGLRenderer, ambientLight: THREE.AmbientLight, directionalLight: THREE.DirectionalLight) { - if (!this.lastHeldItem) return - const now = performance.now() - if (this.lastUpdate && now - this.lastUpdate > 50) { // one tick - void this.replaceItemModel(this.lastHeldItem) - } - - // Only update idle animation if not swinging - if (this.swingAnimator?.isCurrentlySwinging() || this.swingAnimator?.debugParams.animationStage) { - this.swingAnimator?.update() - } else { - this.idleAnimator?.update() - } - - this.blockSwapAnimation?.switcher.update() - - const scene = new THREE.Scene() - scene.add(this.cameraGroup) - // if (this.camera.aspect !== originalCamera.aspect) { - // this.camera.aspect = originalCamera.aspect - // this.camera.updateProjectionMatrix() - // } - this.updateCameraGroup() - scene.add(ambientLight.clone()) - scene.add(directionalLight.clone()) - - const viewerSize = renderer.getSize(new THREE.Vector2()) - const minSize = Math.min(viewerSize.width, viewerSize.height) - const x = viewerSize.width - minSize - - // Mirror the scene for offhand by scaling - const { offHandDisplay } = this - if (offHandDisplay) { - this.cameraGroup.scale.x = -1 - } - - renderer.autoClear = false - renderer.clearDepth() - if (this.offHandDisplay) { - renderer.setViewport(0, 0, minSize, minSize) - } else { - const x = viewerSize.width - minSize - // if (x) x -= x / 4 - renderer.setViewport(x, 0, minSize, minSize) - } - renderer.render(scene, this.camera) - renderer.setViewport(0, 0, viewerSize.width, viewerSize.height) - - // Reset the mirroring after rendering - if (offHandDisplay) { - this.cameraGroup.scale.x = 1 - } - } - - // worldTest () { - // const mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshPhongMaterial({ color: 0x00_00_ff, transparent: true, opacity: 0.5 })) - // mesh.position.set(0.5, 0.5, 0.5) - // const group = new THREE.Group() - // group.add(mesh) - // group.position.set(-0.5, -0.5, -0.5) - // const outerGroup = new THREE.Group() - // outerGroup.add(group) - // outerGroup.position.set(this.camera.position.x, this.camera.position.y, this.camera.position.z) - // this.scene.add(outerGroup) - - // new tweenJs.Tween(group.rotation).to({ z: THREE.MathUtils.degToRad(90) }, 1000).yoyo(true).repeat(Infinity).start() - // } - - async playBlockSwapAnimation (forceState: 'appeared' | 'disappeared') { - this.blockSwapAnimation ??= { - switcher: new SmoothSwitcher( - () => ({ - y: this.objectInnerGroup.position.y - }), - (property, value) => { - if (property === 'y') this.objectInnerGroup.position.y = value - }, - { - y: 16 // units per second - } - ) - } - - const newState = forceState - // if (forceState && newState !== forceState) { - // throw new Error(`forceState does not match current state ${forceState} !== ${newState}`) - // } - - const targetY = this.objectInnerGroup.position.y + (this.objectInnerGroup.scale.y * 1.5 * (newState === 'appeared' ? 1 : -1)) - - // if (newState === this.blockSwapAnimation.switcher.transitioningToStateName) { - // return false - // } - - let cancelled = false - return new Promise((resolve) => { - this.blockSwapAnimation!.switcher.transitionTo( - { y: targetY }, - newState, - () => { - if (!cancelled) { - resolve(true) - } - }, - () => { - cancelled = true - resolve(false) - } - ) - }) - } - - isDifferentItem (block: HandItemBlock | undefined) { - const Item = PrismarineItem(this.worldRenderer.version) - if (!this.lastHeldItem) { - return true - } - if (this.lastHeldItem.name !== block?.name) { - return true - } - // eslint-disable-next-line sonarjs/prefer-single-boolean-return - if (!Item.equal(this.lastHeldItem.fullItem, block?.fullItem ?? {}) || JSON.stringify(this.lastHeldItem.fullItem.components) !== JSON.stringify(block?.fullItem?.components)) { - return true - } - - return false - } - - updateCameraGroup () { - if (this.stopUpdate) return - const { camera } = this - this.cameraGroup.position.copy(camera.position) - this.cameraGroup.rotation.copy(camera.rotation) - - // const viewerSize = viewer.renderer.getSize(new THREE.Vector2()) - // const aspect = viewerSize.width / viewerSize.height - const aspect = 1 - - - // Adjust the position based on the aspect ratio - const { position, scale: scaleData } = this.getHandHeld3d() - const distance = -position.z - const side = this.offHandModeLegacy ? -1 : 1 - this.objectOuterGroup.position.set( - distance * position.x * aspect * side, - distance * position.y, - -distance - ) - - // const scale = Math.min(0.8, Math.max(1, 1 * aspect)) - const scale = scaleData * 2.22 * 0.2 - this.objectOuterGroup.scale.set(scale, scale, scale) - } - - lastItemModelName: string | undefined - private async createItemModel (handItem: HandItemBlock): Promise<{ model: THREE.Object3D; type: 'hand' | 'block' | 'item' } | undefined> { - this.lastUpdate = performance.now() - if (!handItem || (handItem.type === 'hand' && !this.playerHand)) return undefined - - let blockInner: THREE.Object3D | undefined - if (handItem.type === 'item' || handItem.type === 'block') { - const result = this.worldRenderer.entities.getItemMesh({ - ...handItem.fullItem, - itemId: handItem.id, - }, { - 'minecraft:display_context': 'firstperson', - 'minecraft:use_duration': this.worldRenderer.playerStateReactive.itemUsageTicks, - 'minecraft:using_item': !!this.worldRenderer.playerStateReactive.itemUsageTicks, - }, false, this.lastItemModelName) - if (result) { - const { mesh: itemMesh, isBlock, modelName } = result - if (isBlock) { - blockInner = itemMesh - handItem.type = 'block' - } else { - itemMesh.position.set(0.5, 0.5, 0.5) - blockInner = itemMesh - handItem.type = 'item' - } - this.lastItemModelName = modelName - } - } else { - blockInner = this.playerHand! - } - if (!blockInner) return - blockInner.name = 'holdingBlock' - - const rotationDeg = this.getHandHeld3d().rotation - blockInner.rotation.x = THREE.MathUtils.degToRad(rotationDeg.x) - blockInner.rotation.y = THREE.MathUtils.degToRad(rotationDeg.y) - blockInner.rotation.z = THREE.MathUtils.degToRad(rotationDeg.z) - - return { model: blockInner, type: handItem.type } - } - - async replaceItemModel (handItem?: HandItemBlock): Promise { - // if switch animation is in progress, do not replace the item - if (this.blockSwapAnimation?.switcher.isTransitioning) return - - if (!handItem) { - this.holdingBlock?.removeFromParent() - this.holdingBlock = undefined - this.swingAnimator?.stopSwing() - this.swingAnimator = undefined - this.idleAnimator = undefined - return - } - - const result = await this.createItemModel(handItem) - if (!result) return - - // Update the model without changing the group structure - this.holdingBlock?.removeFromParent() - this.holdingBlock = result.model - this.holdingBlockInnerGroup.add(result.model) - - - } - - testUnknownBlockSwitch () { - void this.setNewItem({ - type: 'item', - name: 'minecraft:some-unknown-block', - id: 0, - fullItem: {} - }) - } - - switchRequest = 0 - async setNewItem (handItem?: HandItemBlock) { - if (!this.isDifferentItem(handItem)) return - this.lastItemModelName = undefined - const switchRequest = ++this.switchRequest - this.lastHeldItem = handItem - let playAppearAnimation = false - if (this.holdingBlock) { - // play disappear animation - playAppearAnimation = true - const result = await this.playBlockSwapAnimation('disappeared') - if (!result) return - this.holdingBlock?.removeFromParent() - this.holdingBlock = undefined - } - - if (!handItem) { - this.swingAnimator?.stopSwing() - this.swingAnimator = undefined - this.idleAnimator = undefined - this.blockSwapAnimation = undefined - return - } - - if (switchRequest !== this.switchRequest) return - const result = await this.createItemModel(handItem) - if (!result || switchRequest !== this.switchRequest) return - - const blockOuterGroup = new THREE.Group() - this.holdingBlockInnerGroup.removeFromParent() - this.holdingBlockInnerGroup = new THREE.Group() - this.holdingBlockInnerGroup.add(result.model) - blockOuterGroup.add(this.holdingBlockInnerGroup) - this.holdingBlock = result.model - this.objectInnerGroup = new THREE.Group() - this.objectInnerGroup.add(blockOuterGroup) - this.objectInnerGroup.position.set(-0.5, -0.5, -0.5) - if (playAppearAnimation) { - this.objectInnerGroup.position.y -= this.objectInnerGroup.scale.y * 1.5 - } - Object.assign(blockOuterGroup.position, { x: 0.5, y: 0.5, z: 0.5 }) - - this.objectOuterGroup = new THREE.Group() - this.objectOuterGroup.add(this.objectInnerGroup) - - this.cameraGroup.add(this.objectOuterGroup) - const rotationDeg = this.getHandHeld3d().rotation - this.objectOuterGroup.rotation.y = THREE.MathUtils.degToRad(rotationDeg.yOuter) - - if (playAppearAnimation) { - await this.playBlockSwapAnimation('appeared') - } - - this.swingAnimator = new HandSwingAnimator(this.holdingBlockInnerGroup) - this.swingAnimator.type = result.type - if (this.config.viewBobbing) { - this.idleAnimator = new HandIdleAnimator(this.holdingBlockInnerGroup, this.worldRenderer.playerStateReactive) - } - } - - getHandHeld3d () { - const type = this.lastHeldItem?.type ?? 'hand' - const side = this.offHandModeLegacy ? 'Left' : 'Right' - - let scale = 0.8 * 1.15 // default scale for hand - let position = { - x: 0.4, - y: -0.7, - z: -0.45 - } - let rotation = { - x: -32.4, - y: 42.8, - z: -41.3, - yOuter: 0 - } - - if (type === 'item') { - const itemData = rotationPositionData[`item${side}`] - position = { - x: -0.05, - y: -0.7, - z: -0.45 - } - rotation = { - x: itemData.rotation[0], - y: itemData.rotation[1], - z: itemData.rotation[2], - yOuter: 0 - } - scale = itemData.scale[0] * 1.15 - } else if (type === 'block') { - const blockData = rotationPositionData[`block${side}`] - position = { - x: 0.4, - y: -0.7, - z: -0.45 - } - rotation = { - x: blockData.rotation[0], - y: blockData.rotation[1], - z: blockData.rotation[2], - yOuter: 0 - } - scale = blockData.scale[0] * 1.15 - } - - return { - rotation, - position, - scale - } - } -} - -class HandIdleAnimator { - globalTime = 0 - lastTime = 0 - currentState: MovementState - targetState: MovementState - defaultPosition: { x: number; y: number; z: number; rotationX: number; rotationY: number; rotationZ: number } - private readonly idleOffset = { y: 0, rotationZ: 0 } - private readonly tween = new tweenJs.Group() - private idleTween: tweenJs.Tween<{ y: number; rotationZ: number }> | null = null - private readonly stateSwitcher: SmoothSwitcher - - // Debug parameters - private readonly debugParams = { - // Transition durations for different state changes - walkingSpeed: 8, - sprintingSpeed: 16, - walkingAmplitude: { x: 1 / 30, y: 1 / 10, rotationZ: 0.25 }, - sprintingAmplitude: { x: 1 / 30, y: 1 / 10, rotationZ: 0.4 } - } - - private readonly debugGui: DebugGui - - constructor (public handMesh: THREE.Object3D, public playerState: PlayerStateRenderer) { - this.handMesh = handMesh - this.globalTime = 0 - this.currentState = 'NOT_MOVING' - this.targetState = 'NOT_MOVING' - - this.defaultPosition = { - x: handMesh.position.x, - y: handMesh.position.y, - z: handMesh.position.z, - rotationX: handMesh.rotation.x, - rotationY: handMesh.rotation.y, - rotationZ: handMesh.rotation.z - } - - // Initialize state switcher with appropriate speeds - this.stateSwitcher = new SmoothSwitcher( - () => { - return { - x: this.handMesh.position.x, - y: this.handMesh.position.y, - z: this.handMesh.position.z, - rotationX: this.handMesh.rotation.x, - rotationY: this.handMesh.rotation.y, - rotationZ: this.handMesh.rotation.z - } - }, - (property, value) => { - switch (property) { - case 'x': this.handMesh.position.x = value; break - case 'y': this.handMesh.position.y = value; break - case 'z': this.handMesh.position.z = value; break - case 'rotationX': this.handMesh.rotation.x = value; break - case 'rotationY': this.handMesh.rotation.y = value; break - case 'rotationZ': this.handMesh.rotation.z = value; break - } - }, - { - x: 2, // units per second - y: 2, - z: 2, - rotation: Math.PI // radians per second - } - ) - - // Initialize debug GUI - this.debugGui = new DebugGui('idle_animator', this.debugParams) - // this.debugGui.activate() - } - - private startIdleAnimation () { - if (this.idleTween) { - this.idleTween.stop() - } - - // Start from current position for smooth transition - this.idleOffset.y = this.handMesh.position.y - this.defaultPosition.y - this.idleOffset.rotationZ = this.handMesh.rotation.z - this.defaultPosition.rotationZ - - this.idleTween = new tweenJs.Tween(this.idleOffset, this.tween) - .to({ - y: 0.05, - rotationZ: 0.05 - }, 3000) - .easing(tweenJs.Easing.Sinusoidal.InOut) - .yoyo(true) - .repeat(Infinity) - .start() - } - - private stopIdleAnimation () { - if (this.idleTween) { - this.idleTween.stop() - this.idleOffset.y = 0 - this.idleOffset.rotationZ = 0 - } - } - - private getStateTransform (state: MovementState, time: number) { - switch (state) { - case 'NOT_MOVING': - case 'SNEAKING': - return { - x: this.defaultPosition.x, - y: this.defaultPosition.y, - z: this.defaultPosition.z, - rotationX: this.defaultPosition.rotationX, - rotationY: this.defaultPosition.rotationY, - rotationZ: this.defaultPosition.rotationZ - } - case 'WALKING': - case 'SPRINTING': { - const speed = state === 'SPRINTING' ? this.debugParams.sprintingSpeed : this.debugParams.walkingSpeed - const amplitude = state === 'SPRINTING' ? this.debugParams.sprintingAmplitude : this.debugParams.walkingAmplitude - - return { - x: this.defaultPosition.x + Math.sin(time * speed) * amplitude.x, - y: this.defaultPosition.y - Math.abs(Math.cos(time * speed)) * amplitude.y, - z: this.defaultPosition.z, - rotationX: this.defaultPosition.rotationX, - rotationY: this.defaultPosition.rotationY, - // rotationZ: this.defaultPosition.rotationZ + Math.sin(time * speed) * amplitude.rotationZ - rotationZ: this.defaultPosition.rotationZ - } - } - } - } - - setState (newState: MovementState) { - if (newState === this.targetState) return - - this.targetState = newState - const noTransition = false - if (this.currentState !== newState) { - // Stop idle animation during state transitions - this.stopIdleAnimation() - - // Calculate new state transform - if (!noTransition) { - // this.globalTime = 0 - const stateTransform = this.getStateTransform(newState, this.globalTime) - - // Start transition to new state - this.stateSwitcher.transitionTo(stateTransform, newState) - // this.updated = false - } - this.currentState = newState - } - } - - updated = false - update () { - this.stateSwitcher.update() - - const now = performance.now() - const deltaTime = (now - this.lastTime) / 1000 - this.lastTime = now - - // Update global time based on current state - if (!this.stateSwitcher.isTransitioning) { - switch (this.currentState) { - case 'NOT_MOVING': - case 'SNEAKING': - this.globalTime = Math.PI / 4 - break - case 'SPRINTING': - case 'WALKING': - this.globalTime += deltaTime - break - } - } - - // Check for state changes from player state - if (this.playerState) { - const newState = this.playerState.movementState - if (newState !== this.targetState) { - this.setState(newState) - } - } - - // If we're not transitioning between states and in a stable state that should have idle animation - if (!this.stateSwitcher.isTransitioning && - (this.currentState === 'NOT_MOVING' || this.currentState === 'SNEAKING')) { - // Start idle animation if not already running - if (!this.idleTween?.isPlaying()) { - this.startIdleAnimation() - } - // Update idle animation - this.tween.update() - - // Apply idle offsets - this.handMesh.position.y = this.defaultPosition.y + this.idleOffset.y - this.handMesh.rotation.z = this.defaultPosition.rotationZ + this.idleOffset.rotationZ - } - - // If we're in a movement state and not transitioning, update the movement animation - if (!this.stateSwitcher.isTransitioning && - (this.currentState === 'WALKING' || this.currentState === 'SPRINTING')) { - const stateTransform = this.getStateTransform(this.currentState, this.globalTime) - Object.assign(this.handMesh.position, stateTransform) - Object.assign(this.handMesh.rotation, { - x: stateTransform.rotationX, - y: stateTransform.rotationY, - z: stateTransform.rotationZ - }) - // this.stateSwitcher.transitionTo(stateTransform, this.currentState) - } - } - - getCurrentState () { - return this.currentState - } - - destroy () { - this.stopIdleAnimation() - this.stateSwitcher.forceFinish() - } -} - -class HandSwingAnimator { - private readonly PI = Math.PI - private animationTimer = 0 - private lastTime = 0 - private isAnimating = false - private stopRequested = false - private readonly originalRotation: THREE.Euler - private readonly originalPosition: THREE.Vector3 - private readonly originalScale: THREE.Vector3 - - readonly debugParams = { - // Animation timing - animationTime: 250, - animationStage: 0, - useClassicSwing: true, - - // Item/Block animation parameters - itemSwingXPosScale: -0.8, - itemSwingYPosScale: 0.2, - itemSwingZPosScale: -0.2, - itemHeightScale: -0.6, - itemPreswingRotY: 45, - itemSwingXRotAmount: -30, - itemSwingYRotAmount: -35, - itemSwingZRotAmount: -5, - - // Hand/Arm animation parameters - armSwingXPosScale: -0.3, - armSwingYPosScale: 0.4, - armSwingZPosScale: -0.4, - armSwingYRotAmount: 70, - armSwingZRotAmount: -20, - armHeightScale: -0.6 - } - - private readonly debugGui: DebugGui - - public type: 'hand' | 'block' | 'item' = 'hand' - - constructor (public handMesh: THREE.Object3D) { - this.handMesh = handMesh - // Store initial transforms - this.originalRotation = handMesh.rotation.clone() - this.originalPosition = handMesh.position.clone() - this.originalScale = handMesh.scale.clone() - - // Initialize debug GUI - this.debugGui = new DebugGui('hand_animator', this.debugParams, undefined, { - animationStage: { - min: 0, - max: 1, - step: 0.01 - }, - // Add ranges for all animation parameters - itemSwingXPosScale: { min: -2, max: 2, step: 0.1 }, - itemSwingYPosScale: { min: -2, max: 2, step: 0.1 }, - itemSwingZPosScale: { min: -2, max: 2, step: 0.1 }, - itemHeightScale: { min: -2, max: 2, step: 0.1 }, - itemPreswingRotY: { min: -180, max: 180, step: 5 }, - itemSwingXRotAmount: { min: -180, max: 180, step: 5 }, - itemSwingYRotAmount: { min: -180, max: 180, step: 5 }, - itemSwingZRotAmount: { min: -180, max: 180, step: 5 }, - armSwingXPosScale: { min: -2, max: 2, step: 0.1 }, - armSwingYPosScale: { min: -2, max: 2, step: 0.1 }, - armSwingZPosScale: { min: -2, max: 2, step: 0.1 }, - armSwingYRotAmount: { min: -180, max: 180, step: 5 }, - armSwingZRotAmount: { min: -180, max: 180, step: 5 }, - armHeightScale: { min: -2, max: 2, step: 0.1 } - }) - // this.debugGui.activate() - } - - update () { - if (!this.isAnimating && !this.debugParams.animationStage) { - // If not animating, ensure we're at original position - this.handMesh.rotation.copy(this.originalRotation) - this.handMesh.position.copy(this.originalPosition) - this.handMesh.scale.copy(this.originalScale) - return - } - - const now = performance.now() - const deltaTime = (now - this.lastTime) / 1000 - this.lastTime = now - - // Update animation progress - this.animationTimer += deltaTime * 1000 // Convert to ms - - // Calculate animation stage (0 to 1) - const stage = this.debugParams.animationStage || Math.min(this.animationTimer / this.debugParams.animationTime, 1) - - if (stage >= 1) { - // Animation complete - if (this.stopRequested) { - // If stop was requested, actually stop now that we've completed a swing - this.isAnimating = false - this.stopRequested = false - this.animationTimer = 0 - this.handMesh.rotation.copy(this.originalRotation) - this.handMesh.position.copy(this.originalPosition) - this.handMesh.scale.copy(this.originalScale) - return - } - // Otherwise reset timer and continue - this.animationTimer = 0 - return - } - - // Start from original transforms - this.handMesh.rotation.copy(this.originalRotation) - this.handMesh.position.copy(this.originalPosition) - this.handMesh.scale.copy(this.originalScale) - - // Calculate swing progress - const swingProgress = stage - const sqrtProgress = Math.sqrt(swingProgress) - const sinProgress = Math.sin(swingProgress * this.PI) - const sinSqrtProgress = Math.sin(sqrtProgress * this.PI) - - if (this.type === 'hand') { - // Hand animation - const xOffset = this.debugParams.armSwingXPosScale * sinSqrtProgress - const yOffset = this.debugParams.armSwingYPosScale * Math.sin(sqrtProgress * this.PI * 2) - const zOffset = this.debugParams.armSwingZPosScale * sinProgress - - this.handMesh.position.x += xOffset - this.handMesh.position.y += yOffset + this.debugParams.armHeightScale * swingProgress - this.handMesh.position.z += zOffset - - // Rotations - this.handMesh.rotation.y += THREE.MathUtils.degToRad(this.debugParams.armSwingYRotAmount * sinSqrtProgress) - this.handMesh.rotation.z += THREE.MathUtils.degToRad(this.debugParams.armSwingZRotAmount * sinProgress) - } else { - // Item/Block animation - const xOffset = this.debugParams.itemSwingXPosScale * sinSqrtProgress - const yOffset = this.debugParams.itemSwingYPosScale * Math.sin(sqrtProgress * this.PI * 2) - const zOffset = this.debugParams.itemSwingZPosScale * sinProgress - - this.handMesh.position.x += xOffset - this.handMesh.position.y += yOffset + this.debugParams.itemHeightScale * swingProgress - this.handMesh.position.z += zOffset - - // Pre-swing rotation - this.handMesh.rotation.y += THREE.MathUtils.degToRad(this.debugParams.itemPreswingRotY) - - // Swing rotations - this.handMesh.rotation.x += THREE.MathUtils.degToRad(this.debugParams.itemSwingXRotAmount * sinProgress) - this.handMesh.rotation.y += THREE.MathUtils.degToRad(this.debugParams.itemSwingYRotAmount * sinSqrtProgress) - this.handMesh.rotation.z += THREE.MathUtils.degToRad(this.debugParams.itemSwingZRotAmount * sinProgress) - } - } - - startSwing () { - this.stopRequested = false - if (this.isAnimating) return - - this.isAnimating = true - this.animationTimer = 0 - this.lastTime = performance.now() - } - - stopSwing () { - if (!this.isAnimating) return - this.stopRequested = true - } - - isCurrentlySwinging () { - return this.isAnimating - } -} - -export const getBlockMeshFromModel = (material: THREE.Material, model: BlockModel, name: string, blockProvider: WorldBlockProvider) => { - const worldRenderModel = blockProvider.transformModel(model, { - name, - properties: {} - }) as any - return getThreeBlockModelGroup(material, [[worldRenderModel]], undefined, 'plains', loadedData) -} diff --git a/renderer/viewer/three/itemMesh.ts b/renderer/viewer/three/itemMesh.ts deleted file mode 100644 index 3fa069b99..000000000 --- a/renderer/viewer/three/itemMesh.ts +++ /dev/null @@ -1,427 +0,0 @@ -import * as THREE from 'three' - -export interface Create3DItemMeshOptions { - depth: number - pixelSize?: number -} - -export interface Create3DItemMeshResult { - geometry: THREE.BufferGeometry - totalVertices: number - totalTriangles: number -} - -/** - * Creates a 3D item geometry with front/back faces and connecting edges - * from a canvas containing the item texture - */ -export function create3DItemMesh ( - canvas: HTMLCanvasElement, - options: Create3DItemMeshOptions -): Create3DItemMeshResult { - const { depth, pixelSize } = options - - // Validate canvas dimensions - if (canvas.width <= 0 || canvas.height <= 0) { - throw new Error(`Invalid canvas dimensions: ${canvas.width}x${canvas.height}`) - } - - const ctx = canvas.getContext('2d')! - const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height) - const { data } = imageData - - const w = canvas.width - const h = canvas.height - const halfDepth = depth / 2 - const actualPixelSize = pixelSize ?? (1 / Math.max(w, h)) - - // Find opaque pixels - const isOpaque = (x: number, y: number) => { - if (x < 0 || y < 0 || x >= w || y >= h) return false - const i = (y * w + x) * 4 - return data[i + 3] > 128 // alpha > 128 - } - - const vertices: number[] = [] - const indices: number[] = [] - const uvs: number[] = [] - const normals: number[] = [] - - let vertexIndex = 0 - - // Helper to add a vertex - const addVertex = (x: number, y: number, z: number, u: number, v: number, nx: number, ny: number, nz: number) => { - vertices.push(x, y, z) - uvs.push(u, v) - normals.push(nx, ny, nz) - return vertexIndex++ - } - - // Helper to add a quad (two triangles) - const addQuad = (v0: number, v1: number, v2: number, v3: number) => { - indices.push(v0, v1, v2, v0, v2, v3) - } - - // Convert pixel coordinates to world coordinates - const pixelToWorld = (px: number, py: number) => { - const x = (px / w - 0.5) * actualPixelSize * w - const y = -(py / h - 0.5) * actualPixelSize * h - return { x, y } - } - - // Create a grid of vertices for front and back faces - const frontVertices: Array> = Array.from({ length: h + 1 }, () => Array.from({ length: w + 1 }, () => null)) - const backVertices: Array> = Array.from({ length: h + 1 }, () => Array.from({ length: w + 1 }, () => null)) - - // Create vertices at pixel corners - for (let py = 0; py <= h; py++) { - for (let px = 0; px <= w; px++) { - const { x, y } = pixelToWorld(px - 0.5, py - 0.5) - - // UV coordinates should map to the texture space of the extracted tile - const u = px / w - const v = py / h - - // Check if this vertex is needed for any face or edge - let needVertex = false - - // Check all 4 adjacent pixels to see if any are opaque - const adjacentPixels = [ - [px - 1, py - 1], // top-left pixel - [px, py - 1], // top-right pixel - [px - 1, py], // bottom-left pixel - [px, py] // bottom-right pixel - ] - - for (const [adjX, adjY] of adjacentPixels) { - if (isOpaque(adjX, adjY)) { - needVertex = true - break - } - } - - if (needVertex) { - frontVertices[py][px] = addVertex(x, y, halfDepth, u, v, 0, 0, 1) - backVertices[py][px] = addVertex(x, y, -halfDepth, u, v, 0, 0, -1) - } - } - } - - // Create front and back faces - for (let py = 0; py < h; py++) { - for (let px = 0; px < w; px++) { - if (!isOpaque(px, py)) continue - - const v00 = frontVertices[py][px] - const v10 = frontVertices[py][px + 1] - const v11 = frontVertices[py + 1][px + 1] - const v01 = frontVertices[py + 1][px] - - const b00 = backVertices[py][px] - const b10 = backVertices[py][px + 1] - const b11 = backVertices[py + 1][px + 1] - const b01 = backVertices[py + 1][px] - - if (v00 !== null && v10 !== null && v11 !== null && v01 !== null) { - // Front face - addQuad(v00, v10, v11, v01) - } - - if (b00 !== null && b10 !== null && b11 !== null && b01 !== null) { - // Back face (reversed winding) - addQuad(b10, b00, b01, b11) - } - } - } - - // Create edge faces for each side of the pixel with proper UVs - for (let py = 0; py < h; py++) { - for (let px = 0; px < w; px++) { - if (!isOpaque(px, py)) continue - - const pixelU = (px + 0.5) / w // Center of current pixel - const pixelV = (py + 0.5) / h - - // Left edge (x = px) - if (!isOpaque(px - 1, py)) { - const f0 = frontVertices[py][px] - const f1 = frontVertices[py + 1][px] - const b0 = backVertices[py][px] - const b1 = backVertices[py + 1][px] - - if (f0 !== null && f1 !== null && b0 !== null && b1 !== null) { - // Create new vertices for edge with current pixel's UV - const ef0 = addVertex(vertices[f0 * 3], vertices[f0 * 3 + 1], vertices[f0 * 3 + 2], pixelU, pixelV, -1, 0, 0) - const ef1 = addVertex(vertices[f1 * 3], vertices[f1 * 3 + 1], vertices[f1 * 3 + 2], pixelU, pixelV, -1, 0, 0) - const eb1 = addVertex(vertices[b1 * 3], vertices[b1 * 3 + 1], vertices[b1 * 3 + 2], pixelU, pixelV, -1, 0, 0) - const eb0 = addVertex(vertices[b0 * 3], vertices[b0 * 3 + 1], vertices[b0 * 3 + 2], pixelU, pixelV, -1, 0, 0) - addQuad(ef0, ef1, eb1, eb0) - } - } - - // Right edge (x = px + 1) - if (!isOpaque(px + 1, py)) { - const f0 = frontVertices[py + 1][px + 1] - const f1 = frontVertices[py][px + 1] - const b0 = backVertices[py + 1][px + 1] - const b1 = backVertices[py][px + 1] - - if (f0 !== null && f1 !== null && b0 !== null && b1 !== null) { - const ef0 = addVertex(vertices[f0 * 3], vertices[f0 * 3 + 1], vertices[f0 * 3 + 2], pixelU, pixelV, 1, 0, 0) - const ef1 = addVertex(vertices[f1 * 3], vertices[f1 * 3 + 1], vertices[f1 * 3 + 2], pixelU, pixelV, 1, 0, 0) - const eb1 = addVertex(vertices[b1 * 3], vertices[b1 * 3 + 1], vertices[b1 * 3 + 2], pixelU, pixelV, 1, 0, 0) - const eb0 = addVertex(vertices[b0 * 3], vertices[b0 * 3 + 1], vertices[b0 * 3 + 2], pixelU, pixelV, 1, 0, 0) - addQuad(ef0, ef1, eb1, eb0) - } - } - - // Top edge (y = py) - if (!isOpaque(px, py - 1)) { - const f0 = frontVertices[py][px] - const f1 = frontVertices[py][px + 1] - const b0 = backVertices[py][px] - const b1 = backVertices[py][px + 1] - - if (f0 !== null && f1 !== null && b0 !== null && b1 !== null) { - const ef0 = addVertex(vertices[f0 * 3], vertices[f0 * 3 + 1], vertices[f0 * 3 + 2], pixelU, pixelV, 0, -1, 0) - const ef1 = addVertex(vertices[f1 * 3], vertices[f1 * 3 + 1], vertices[f1 * 3 + 2], pixelU, pixelV, 0, -1, 0) - const eb1 = addVertex(vertices[b1 * 3], vertices[b1 * 3 + 1], vertices[b1 * 3 + 2], pixelU, pixelV, 0, -1, 0) - const eb0 = addVertex(vertices[b0 * 3], vertices[b0 * 3 + 1], vertices[b0 * 3 + 2], pixelU, pixelV, 0, -1, 0) - addQuad(ef0, ef1, eb1, eb0) - } - } - - // Bottom edge (y = py + 1) - if (!isOpaque(px, py + 1)) { - const f0 = frontVertices[py + 1][px + 1] - const f1 = frontVertices[py + 1][px] - const b0 = backVertices[py + 1][px + 1] - const b1 = backVertices[py + 1][px] - - if (f0 !== null && f1 !== null && b0 !== null && b1 !== null) { - const ef0 = addVertex(vertices[f0 * 3], vertices[f0 * 3 + 1], vertices[f0 * 3 + 2], pixelU, pixelV, 0, 1, 0) - const ef1 = addVertex(vertices[f1 * 3], vertices[f1 * 3 + 1], vertices[f1 * 3 + 2], pixelU, pixelV, 0, 1, 0) - const eb1 = addVertex(vertices[b1 * 3], vertices[b1 * 3 + 1], vertices[b1 * 3 + 2], pixelU, pixelV, 0, 1, 0) - const eb0 = addVertex(vertices[b0 * 3], vertices[b0 * 3 + 1], vertices[b0 * 3 + 2], pixelU, pixelV, 0, 1, 0) - addQuad(ef0, ef1, eb1, eb0) - } - } - } - } - - const geometry = new THREE.BufferGeometry() - geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3)) - geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2)) - geometry.setAttribute('normal', new THREE.Float32BufferAttribute(normals, 3)) - geometry.setIndex(indices) - - // Compute normals properly - geometry.computeVertexNormals() - - return { - geometry, - totalVertices: vertexIndex, - totalTriangles: indices.length / 3 - } -} - -export interface ItemTextureInfo { - u: number - v: number - sizeX: number - sizeY: number -} - -export interface ItemMeshResult { - mesh: THREE.Object3D - itemsTexture?: THREE.Texture - itemsTextureFlipped?: THREE.Texture - cleanup?: () => void -} - -/** - * Extracts item texture region to a canvas - */ -export function extractItemTextureToCanvas ( - sourceTexture: THREE.Texture, - textureInfo: ItemTextureInfo -): HTMLCanvasElement { - const { u, v, sizeX, sizeY } = textureInfo - - // Calculate canvas size - fix the calculation - const canvasWidth = Math.max(1, Math.floor(sizeX * sourceTexture.image.width)) - const canvasHeight = Math.max(1, Math.floor(sizeY * sourceTexture.image.height)) - - const canvas = document.createElement('canvas') - canvas.width = canvasWidth - canvas.height = canvasHeight - - const ctx = canvas.getContext('2d')! - ctx.imageSmoothingEnabled = false - - // Draw the item texture region to canvas - ctx.drawImage( - sourceTexture.image, - u * sourceTexture.image.width, - v * sourceTexture.image.height, - sizeX * sourceTexture.image.width, - sizeY * sourceTexture.image.height, - 0, - 0, - canvas.width, - canvas.height - ) - - return canvas -} - -/** - * Creates either a 2D or 3D item mesh based on parameters - */ -export function createItemMesh ( - sourceTexture: THREE.Texture, - textureInfo: ItemTextureInfo, - options: { - faceCamera?: boolean - use3D?: boolean - depth?: number - } = {} -): ItemMeshResult { - const { faceCamera = false, use3D = true, depth = 0.04 } = options - const { u, v, sizeX, sizeY } = textureInfo - - if (faceCamera) { - // Create sprite for camera-facing items - const itemsTexture = sourceTexture.clone() - itemsTexture.flipY = true - itemsTexture.offset.set(u, 1 - v - sizeY) - itemsTexture.repeat.set(sizeX, sizeY) - itemsTexture.needsUpdate = true - itemsTexture.magFilter = THREE.NearestFilter - itemsTexture.minFilter = THREE.NearestFilter - - const spriteMat = new THREE.SpriteMaterial({ - map: itemsTexture, - transparent: true, - alphaTest: 0.1, - }) - const mesh = new THREE.Sprite(spriteMat) - - return { - mesh, - itemsTexture, - cleanup () { - itemsTexture.dispose() - } - } - } - - if (use3D) { - // Try to create 3D mesh - try { - const canvas = extractItemTextureToCanvas(sourceTexture, textureInfo) - const { geometry } = create3DItemMesh(canvas, { depth }) - - // Create texture from canvas for the 3D mesh - const itemsTexture = new THREE.CanvasTexture(canvas) - itemsTexture.magFilter = THREE.NearestFilter - itemsTexture.minFilter = THREE.NearestFilter - itemsTexture.wrapS = itemsTexture.wrapT = THREE.ClampToEdgeWrapping - itemsTexture.flipY = false - itemsTexture.needsUpdate = true - - const material = new THREE.MeshStandardMaterial({ - map: itemsTexture, - side: THREE.DoubleSide, - transparent: true, - alphaTest: 0.1, - }) - - const mesh = new THREE.Mesh(geometry, material) - - return { - mesh, - itemsTexture, - cleanup () { - itemsTexture.dispose() - geometry.dispose() - if (material.map) material.map.dispose() - material.dispose() - } - } - } catch (error) { - console.warn('Failed to create 3D item mesh, falling back to 2D:', error) - // Fall through to 2D rendering - } - } - - // Fallback to 2D flat rendering - const itemsTexture = sourceTexture.clone() - itemsTexture.flipY = true - itemsTexture.offset.set(u, 1 - v - sizeY) - itemsTexture.repeat.set(sizeX, sizeY) - itemsTexture.needsUpdate = true - itemsTexture.magFilter = THREE.NearestFilter - itemsTexture.minFilter = THREE.NearestFilter - - const itemsTextureFlipped = itemsTexture.clone() - itemsTextureFlipped.repeat.x *= -1 - itemsTextureFlipped.needsUpdate = true - itemsTextureFlipped.offset.set(u + sizeX, 1 - v - sizeY) - - const material = new THREE.MeshStandardMaterial({ - map: itemsTexture, - transparent: true, - alphaTest: 0.1, - }) - const materialFlipped = new THREE.MeshStandardMaterial({ - map: itemsTextureFlipped, - transparent: true, - alphaTest: 0.1, - }) - const mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 0), [ - new THREE.MeshBasicMaterial({ color: 0x00_00_00 }), new THREE.MeshBasicMaterial({ color: 0x00_00_00 }), - new THREE.MeshBasicMaterial({ color: 0x00_00_00 }), new THREE.MeshBasicMaterial({ color: 0x00_00_00 }), - material, materialFlipped, - ]) - - return { - mesh, - itemsTexture, - itemsTextureFlipped, - cleanup () { - itemsTexture.dispose() - itemsTextureFlipped.dispose() - material.dispose() - materialFlipped.dispose() - } - } -} - -/** - * Creates a complete 3D item mesh from a canvas texture - */ -export function createItemMeshFromCanvas ( - canvas: HTMLCanvasElement, - options: Create3DItemMeshOptions -): THREE.Mesh { - const { geometry } = create3DItemMesh(canvas, options) - - // Base color texture for the item - const colorTexture = new THREE.CanvasTexture(canvas) - colorTexture.magFilter = THREE.NearestFilter - colorTexture.minFilter = THREE.NearestFilter - colorTexture.wrapS = colorTexture.wrapT = THREE.ClampToEdgeWrapping - colorTexture.flipY = false // Important for canvas textures - colorTexture.needsUpdate = true - - // Material - no transparency, no alpha test needed for edges - const material = new THREE.MeshBasicMaterial({ - map: colorTexture, - side: THREE.DoubleSide, - transparent: true, - alphaTest: 0.1 - }) - - return new THREE.Mesh(geometry, material) -} diff --git a/renderer/viewer/three/panorama.ts b/renderer/viewer/three/panorama.ts deleted file mode 100644 index 44c0c59e7..000000000 --- a/renderer/viewer/three/panorama.ts +++ /dev/null @@ -1,307 +0,0 @@ -import { join } from 'path' -import * as THREE from 'three' -import { getSyncWorld } from 'renderer/playground/shared' -import { Vec3 } from 'vec3' -import * as tweenJs from '@tweenjs/tween.js' -import type { GraphicsInitOptions } from '../../../src/appViewer' -import { WorldDataEmitter } from '../lib/worldDataEmitter' -import { defaultWorldRendererConfig, WorldRendererCommon } from '../lib/worldrendererCommon' -import { getDefaultRendererState } from '../baseGraphicsBackend' -import { ResourcesManager } from '../../../src/resourcesManager' -import { getInitialPlayerStateRenderer } from '../lib/basePlayerState' -import { loadThreeJsTextureFromUrl, loadThreeJsTextureFromUrlSync } from './threeJsUtils' -import { WorldRendererThree } from './worldrendererThree' -import { EntityMesh } from './entity/EntityMesh' -import { DocumentRenderer } from './documentRenderer' -import { PANORAMA_VERSION } from './panoramaShared' - -const date = new Date() -const isChristmas = date.getMonth() === 11 && date.getDate() >= 24 && date.getDate() <= 26 - -const panoramaFiles = [ - 'panorama_3.webp', // right (+x) - 'panorama_1.webp', // left (-x) - 'panorama_4.webp', // top (+y) - 'panorama_5.webp', // bottom (-y) - 'panorama_0.webp', // front (+z) - 'panorama_2.webp', // back (-z) -] - -export class PanoramaRenderer { - private readonly camera: THREE.PerspectiveCamera - private scene: THREE.Scene - private readonly ambientLight: THREE.AmbientLight - private readonly directionalLight: THREE.DirectionalLight - private panoramaGroup: THREE.Object3D | null = null - private time = 0 - private readonly abortController = new AbortController() - private worldRenderer: WorldRendererCommon | WorldRendererThree | undefined - public WorldRendererClass = WorldRendererThree - public startTimes = new Map() - - constructor (private readonly documentRenderer: DocumentRenderer, private readonly options: GraphicsInitOptions, private readonly doWorldBlocksPanorama = false) { - this.scene = new THREE.Scene() - // #324568 - this.scene.background = new THREE.Color(0x32_45_68) - - // Add ambient light - this.ambientLight = new THREE.AmbientLight(0xcc_cc_cc) - this.scene.add(this.ambientLight) - - // Add directional light - this.directionalLight = new THREE.DirectionalLight(0xff_ff_ff, 0.5) - this.directionalLight.position.set(1, 1, 0.5).normalize() - this.directionalLight.castShadow = true - this.scene.add(this.directionalLight) - - this.camera = new THREE.PerspectiveCamera(85, this.documentRenderer.canvas.width / this.documentRenderer.canvas.height, 0.05, 1000) - this.camera.position.set(0, 0, 0) - this.camera.rotation.set(0, 0, 0) - } - - async start () { - if (this.doWorldBlocksPanorama) { - await this.worldBlocksPanorama() - } else { - this.addClassicPanorama() - } - - - this.documentRenderer.render = (sizeChanged = false) => { - if (sizeChanged) { - this.camera.aspect = this.documentRenderer.canvas.width / this.documentRenderer.canvas.height - this.camera.updateProjectionMatrix() - } - this.documentRenderer.renderer.render(this.scene, this.camera) - } - } - - async debugImageInFrontOfCamera () { - const image = await loadThreeJsTextureFromUrl(join('background', 'panorama_0.webp')) - const mesh = new THREE.Mesh(new THREE.PlaneGeometry(1000, 1000), new THREE.MeshBasicMaterial({ map: image })) - mesh.position.set(0, 0, -500) - mesh.rotation.set(0, 0, 0) - this.scene.add(mesh) - } - - addClassicPanorama () { - const panorGeo = new THREE.BoxGeometry(1000, 1000, 1000) - const panorMaterials = [] as THREE.MeshBasicMaterial[] - const fadeInDuration = 200 - - // void this.debugImageInFrontOfCamera() - - for (const file of panoramaFiles) { - const load = async () => { - const { texture } = loadThreeJsTextureFromUrlSync(join('background', isChristmas ? 'christmas' : '', file)) - - // Instead of using repeat/offset to flip, we'll use the texture matrix - texture.matrixAutoUpdate = false - texture.matrix.set( - -1, 0, 1, 0, 1, 0, 0, 0, 1 - ) - - texture.wrapS = THREE.ClampToEdgeWrapping - texture.wrapT = THREE.ClampToEdgeWrapping - texture.minFilter = THREE.LinearFilter - texture.magFilter = THREE.LinearFilter - - const material = new THREE.MeshBasicMaterial({ - map: texture, - transparent: true, - side: THREE.DoubleSide, - depthWrite: false, - opacity: 0 // Start with 0 opacity - }) - - // Start fade-in when texture is loaded - this.startTimes.set(material, Date.now()) - panorMaterials.push(material) - } - - void load() - } - - const panoramaBox = new THREE.Mesh(panorGeo, panorMaterials) - panoramaBox.onBeforeRender = () => { - this.time += 0.01 - panoramaBox.rotation.y = Math.PI + this.time * 0.01 - panoramaBox.rotation.z = Math.sin(-this.time * 0.001) * 0.001 - - // Time-based fade in animation for each material - for (const material of panorMaterials) { - const startTime = this.startTimes.get(material) - if (startTime) { - const elapsed = Date.now() - startTime - const progress = Math.min(1, elapsed / fadeInDuration) - material.opacity = progress - } - } - } - - const group = new THREE.Object3D() - group.add(panoramaBox) - - if (!isChristmas) { - // Add entities - for (let i = 0; i < 20; i++) { - const m = new EntityMesh('1.16.4', 'squid').mesh - m.position.set(Math.random() * 30 - 15, Math.random() * 20 - 10, Math.random() * 10 - 17) - m.rotation.set(0, Math.PI + Math.random(), -Math.PI / 4, 'ZYX') - const v = Math.random() * 0.01 - m.children[0].onBeforeRender = () => { - m.rotation.y += v - m.rotation.z = Math.cos(panoramaBox.rotation.y * 3) * Math.PI / 4 - Math.PI / 2 - } - group.add(m) - } - } - - this.scene.add(group) - this.panoramaGroup = group - } - - async worldBlocksPanorama () { - const version = PANORAMA_VERSION - const fullResourceManager = this.options.resourcesManager as ResourcesManager - fullResourceManager.currentConfig = { version, noInventoryGui: true, } - await fullResourceManager.updateAssetsData({ }) - if (this.abortController.signal.aborted) return - console.time('load panorama scene') - const world = getSyncWorld(version) - const PrismarineBlock = require('prismarine-block') - const Block = PrismarineBlock(version) - const fullBlocks = loadedData.blocksArray.filter(block => { - // if (block.name.includes('leaves')) return false - if (/* !block.name.includes('wool') && */!block.name.includes('stained_glass')/* && !block.name.includes('terracotta') */) return false - const b = Block.fromStateId(block.defaultState, 0) - if (b.shapes?.length !== 1) return false - const shape = b.shapes[0] - return shape[0] === 0 && shape[1] === 0 && shape[2] === 0 && shape[3] === 1 && shape[4] === 1 && shape[5] === 1 - }) - const Z = -15 - const sizeX = 100 - const sizeY = 100 - for (let x = -sizeX; x < sizeX; x++) { - for (let y = -sizeY; y < sizeY; y++) { - const block = fullBlocks[Math.floor(Math.random() * fullBlocks.length)] - world.setBlockStateId(new Vec3(x, y, Z), block.defaultState) - } - } - this.camera.updateProjectionMatrix() - this.camera.position.set(0.5, sizeY / 2 + 0.5, 0.5) - this.camera.rotation.set(0, 0, 0) - const initPos = new Vec3(...this.camera.position.toArray()) - const worldView = new WorldDataEmitter(world, 2, initPos) - // worldView.addWaitTime = 0 - if (this.abortController.signal.aborted) return - - this.worldRenderer = new this.WorldRendererClass( - this.documentRenderer.renderer, - this.options, - { - version, - worldView, - inWorldRenderingConfig: defaultWorldRendererConfig, - playerStateReactive: getInitialPlayerStateRenderer().reactive, - rendererState: getDefaultRendererState().reactive, - nonReactiveState: getDefaultRendererState().nonReactive - } - ) - if (this.worldRenderer instanceof WorldRendererThree) { - this.scene = this.worldRenderer.scene - } - void worldView.init(initPos) - - await this.worldRenderer.waitForChunksToRender() - if (this.abortController.signal.aborted) return - // add small camera rotation to side on mouse move depending on absolute position of the cursor - const { camera } = this - const initX = camera.position.x - const initY = camera.position.y - let prevTwin: tweenJs.Tween | undefined - document.body.addEventListener('pointermove', (e) => { - if (e.pointerType !== 'mouse') return - const pos = new THREE.Vector2(e.clientX, e.clientY) - const SCALE = 0.2 - /* -0.5 - 0.5 */ - const xRel = pos.x / window.innerWidth - 0.5 - const yRel = -(pos.y / window.innerHeight - 0.5) - prevTwin?.stop() - const to = { - x: initX + (xRel * SCALE), - y: initY + (yRel * SCALE) - } - prevTwin = new tweenJs.Tween(camera.position).to(to, 0) // todo use the number depending on diff // todo use the number depending on diff - // prevTwin.easing(tweenJs.Easing.Exponential.InOut) - prevTwin.start() - camera.updateProjectionMatrix() - }, { - signal: this.abortController.signal - }) - - console.timeEnd('load panorama scene') - } - - dispose () { - this.scene.clear() - this.worldRenderer?.destroy() - this.abortController.abort() - } -} - -// export class ClassicPanoramaRenderer { -// panoramaGroup: THREE.Object3D - -// constructor (private readonly backgroundFiles: string[], onRender: Array<(sizeChanged: boolean) => void>, addSquids = true) { -// const panorGeo = new THREE.BoxGeometry(1000, 1000, 1000) -// const loader = new THREE.TextureLoader() -// const panorMaterials = [] as THREE.MeshBasicMaterial[] - -// for (const file of this.backgroundFiles) { -// const texture = loader.load(file) - -// // Instead of using repeat/offset to flip, we'll use the texture matrix -// texture.matrixAutoUpdate = false -// texture.matrix.set( -// -1, 0, 1, 0, 1, 0, 0, 0, 1 -// ) - -// texture.wrapS = THREE.ClampToEdgeWrapping // Changed from RepeatWrapping -// texture.wrapT = THREE.ClampToEdgeWrapping // Changed from RepeatWrapping -// texture.minFilter = THREE.LinearFilter -// texture.magFilter = THREE.LinearFilter - -// panorMaterials.push(new THREE.MeshBasicMaterial({ -// map: texture, -// transparent: true, -// side: THREE.DoubleSide, -// depthWrite: false, -// })) -// } - -// const panoramaBox = new THREE.Mesh(panorGeo, panorMaterials) -// panoramaBox.onBeforeRender = () => { -// } - -// const group = new THREE.Object3D() -// group.add(panoramaBox) - -// if (addSquids) { -// // Add squids -// for (let i = 0; i < 20; i++) { -// const m = new EntityMesh('1.16.4', 'squid').mesh -// m.position.set(Math.random() * 30 - 15, Math.random() * 20 - 10, Math.random() * 10 - 17) -// m.rotation.set(0, Math.PI + Math.random(), -Math.PI / 4, 'ZYX') -// const v = Math.random() * 0.01 -// onRender.push(() => { -// m.rotation.y += v -// m.rotation.z = Math.cos(panoramaBox.rotation.y * 3) * Math.PI / 4 - Math.PI / 2 -// }) -// group.add(m) -// } -// } - -// this.panoramaGroup = group -// } -// } diff --git a/renderer/viewer/three/panoramaShared.ts b/renderer/viewer/three/panoramaShared.ts deleted file mode 100644 index ad80367f3..000000000 --- a/renderer/viewer/three/panoramaShared.ts +++ /dev/null @@ -1 +0,0 @@ -export const PANORAMA_VERSION = '1.21.4' diff --git a/renderer/viewer/three/primitives.js b/renderer/viewer/three/primitives.js deleted file mode 100644 index 08c1c49ee..000000000 --- a/renderer/viewer/three/primitives.js +++ /dev/null @@ -1,142 +0,0 @@ -/* eslint-disable unicorn/no-abusive-eslint-disable */ -/* eslint-disable */ -const THREE = require('three') -const { MeshLine, MeshLineMaterial } = require('three.meshline') - -function getMesh(primitive, camera) { - if (primitive.type === 'line') { - const color = primitive.color ? primitive.color : 0xff0000 - const resolution = new THREE.Vector2(window.innerWidth / camera.zoom, window.innerHeight / camera.zoom) - const material = new MeshLineMaterial({ color, resolution, sizeAttenuation: false, lineWidth: 8 }) - - const points = [] - for (const p of primitive.points) { - points.push(p.x, p.y, p.z) - } - - const line = new MeshLine() - line.setPoints(points) - return new THREE.Mesh(line, material) - } else if (primitive.type === 'boxgrid') { - const color = primitive.color ? primitive.color : 'aqua' - - const sx = primitive.end.x - primitive.start.x - const sy = primitive.end.y - primitive.start.y - const sz = primitive.end.z - primitive.start.z - - const boxGeometry = new THREE.BoxBufferGeometry(sx, sy, sz, sx, sy, sz) - boxGeometry.attributes.positionStart = boxGeometry.attributes.position.clone() - - const gridGeometry = GridBoxGeometry(boxGeometry, false) - const grid = new THREE.LineSegments(gridGeometry, new THREE.LineBasicMaterial({ color })) - grid.position.x = primitive.start.x + sx / 2 - grid.position.y = primitive.start.y + sy / 2 - grid.position.z = primitive.start.z + sz / 2 - return grid - } else if (primitive.type === 'points') { - const color = primitive.color ? primitive.color : 'aqua' - const size = primitive.size ? primitive.size : 5 - const points = [] - for (const p of primitive.points) { - points.push(p.x, p.y, p.z) - } - const geometry = new THREE.BufferGeometry() - geometry.setAttribute('position', new THREE.Float32BufferAttribute(points, 3)) - const material = new THREE.PointsMaterial({ color, size, sizeAttenuation: false }) - return new THREE.Points(geometry, material) - } - return null -} - -class Primitives { - constructor(scene, camera) { - this.scene = scene - this.camera = camera - this.primitives = {} - } - - clear() { - for (const mesh of Object.values(this.primitives)) { - this.scene.remove(mesh) - disposeObject(mesh) - } - this.primitives = {} - } - - update(primitive) { - if (this.primitives[primitive.id]) { - this.scene.remove(this.primitives[primitive.id]) - disposeObject(this.primitives[primitive.id]) - delete this.primitives[primitive.id] - } - - const mesh = getMesh(primitive, this.camera) - if (!mesh) return - this.primitives[primitive.id] = mesh - this.scene.add(mesh) - } -} - -function GridBoxGeometry(geometry, independent) { - if (!(geometry instanceof THREE.BoxBufferGeometry)) { - console.log("GridBoxGeometry: the parameter 'geometry' has to be of the type THREE.BoxBufferGeometry") - return geometry - } - independent = independent !== undefined ? independent : false - - const newGeometry = new THREE.BoxBufferGeometry() - const position = geometry.attributes.position - newGeometry.attributes.position = independent === false ? position : position.clone() - - const segmentsX = geometry.parameters.widthSegments || 1 - const segmentsY = geometry.parameters.heightSegments || 1 - const segmentsZ = geometry.parameters.depthSegments || 1 - - let startIndex = 0 - const indexSide1 = indexSide(segmentsZ, segmentsY, startIndex) - startIndex += (segmentsZ + 1) * (segmentsY + 1) - const indexSide2 = indexSide(segmentsZ, segmentsY, startIndex) - startIndex += (segmentsZ + 1) * (segmentsY + 1) - const indexSide3 = indexSide(segmentsX, segmentsZ, startIndex) - startIndex += (segmentsX + 1) * (segmentsZ + 1) - const indexSide4 = indexSide(segmentsX, segmentsZ, startIndex) - startIndex += (segmentsX + 1) * (segmentsZ + 1) - const indexSide5 = indexSide(segmentsX, segmentsY, startIndex) - startIndex += (segmentsX + 1) * (segmentsY + 1) - const indexSide6 = indexSide(segmentsX, segmentsY, startIndex) - - let fullIndices = [] - fullIndices = fullIndices.concat(indexSide1) - fullIndices = fullIndices.concat(indexSide2) - fullIndices = fullIndices.concat(indexSide3) - fullIndices = fullIndices.concat(indexSide4) - fullIndices = fullIndices.concat(indexSide5) - fullIndices = fullIndices.concat(indexSide6) - - newGeometry.setIndex(fullIndices) - - function indexSide(x, y, shift) { - const indices = [] - for (let i = 0; i < y + 1; i++) { - let index11 = 0 - let index12 = 0 - for (let j = 0; j < x; j++) { - index11 = (x + 1) * i + j - index12 = index11 + 1 - const index21 = index11 - const index22 = index11 + (x + 1) - indices.push(shift + index11, shift + index12) - if (index22 < ((x + 1) * (y + 1) - 1)) { - indices.push(shift + index21, shift + index22) - } - } - if ((index12 + x + 1) <= ((x + 1) * (y + 1) - 1)) { - indices.push(shift + index12, shift + index12 + x + 1) - } - } - return indices - } - return newGeometry -} - -module.exports = { Primitives } diff --git a/renderer/viewer/three/renderSlot.ts b/renderer/viewer/three/renderSlot.ts deleted file mode 100644 index 321633ebf..000000000 --- a/renderer/viewer/three/renderSlot.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { getRenamedData } from 'flying-squid/dist/blockRenames' -import { BlockModel } from 'mc-assets' -import { versionToNumber } from 'mc-assets/dist/utils' -import type { ResourcesManagerCommon } from '../../../src/resourcesManager' - -export type ResolvedItemModelRender = { - modelName: string, - originalItemName?: string -} - -export const renderSlot = (model: ResolvedItemModelRender, resourcesManager: ResourcesManagerCommon, debugIsQuickbar = false, fullBlockModelSupport = false): { - texture: string, - blockData: Record & { resolvedModel: BlockModel } | null, - scale: number | null, - slice: number[] | null, - modelName: string | null, -} => { - let itemModelName = model.modelName - const isItem = loadedData.itemsByName[itemModelName] - - // #region normalize item name - if (versionToNumber(bot.version) < versionToNumber('1.13')) itemModelName = getRenamedData(isItem ? 'items' : 'blocks', itemModelName, bot.version, '1.13.1') as string - // #endregion - - - let itemTexture - - if (!fullBlockModelSupport) { - const atlas = resourcesManager.currentResources?.guiAtlas?.json - // todo atlas holds all rendered blocks, not all possibly rendered item/block models, need to request this on demand instead (this is how vanilla works) - const tryGetAtlasTexture = (name?: string) => name && atlas?.textures[name.replace('minecraft:', '').replace('block/', '').replace('blocks/', '').replace('item/', '').replace('items/', '').replace('_inventory', '')] - const item = tryGetAtlasTexture(itemModelName) ?? tryGetAtlasTexture(model.originalItemName) - if (item) { - const x = item.u * atlas.width - const y = item.v * atlas.height - return { - texture: 'gui', - slice: [x, y, atlas.tileSize, atlas.tileSize], - scale: 0.25, - blockData: null, - modelName: null - } - } - } - - const blockToTopTexture = (r) => r.top ?? r - - try { - if (!appViewer.resourcesManager.currentResources?.itemsRenderer) throw new Error('Items renderer is not available') - itemTexture = - appViewer.resourcesManager.currentResources.itemsRenderer.getItemTexture(itemModelName, {}, false, fullBlockModelSupport) - ?? (model.originalItemName ? appViewer.resourcesManager.currentResources.itemsRenderer.getItemTexture(model.originalItemName, {}, false, fullBlockModelSupport) : undefined) - ?? appViewer.resourcesManager.currentResources.itemsRenderer.getItemTexture('item/missing_texture')! - } catch (err) { - // get resourcepack from resource manager - reportError?.(`Failed to render item ${itemModelName} (original: ${model.originalItemName}) on ${bot.version} (resourcepack: TODO!): ${err.stack}`) - itemTexture = blockToTopTexture(appViewer.resourcesManager.currentResources!.itemsRenderer.getItemTexture('errored')!) - } - - itemTexture ??= blockToTopTexture(appViewer.resourcesManager.currentResources!.itemsRenderer.getItemTexture('unknown')!) - - - if ('type' in itemTexture) { - // is item - return { - texture: itemTexture.type, - slice: itemTexture.slice, - modelName: itemModelName, - blockData: null, - scale: null - } - } else { - // is block - return { - texture: 'blocks', - blockData: itemTexture, - modelName: itemModelName, - slice: null, - scale: null - } - } -} diff --git a/renderer/viewer/three/skyboxRenderer.ts b/renderer/viewer/three/skyboxRenderer.ts deleted file mode 100644 index fb9edae6f..000000000 --- a/renderer/viewer/three/skyboxRenderer.ts +++ /dev/null @@ -1,406 +0,0 @@ -import * as THREE from 'three' -import { DebugGui } from '../lib/DebugGui' - -export const DEFAULT_TEMPERATURE = 0.75 - -export class SkyboxRenderer { - private texture: THREE.Texture | null = null - private mesh: THREE.Mesh | null = null - private skyMesh: THREE.Mesh | null = null - private voidMesh: THREE.Mesh | null = null - - // World state - private worldTime = 0 - private partialTicks = 0 - private viewDistance = 4 - private temperature = DEFAULT_TEMPERATURE - private inWater = false - private waterBreathing = false - private fogBrightness = 0 - private prevFogBrightness = 0 - private readonly fogOrangeness = 0 // Debug property to control sky color orangeness - private readonly distanceFactor = 2.7 - - private readonly brightnessAtPosition = 1 - debugGui: DebugGui - - constructor (private readonly scene: THREE.Scene, public defaultSkybox: boolean, public initialImage: string | null) { - this.debugGui = new DebugGui('skybox_renderer', this, [ - 'temperature', - 'worldTime', - 'inWater', - 'waterBreathing', - 'fogOrangeness', - 'brightnessAtPosition', - 'distanceFactor' - ], { - brightnessAtPosition: { min: 0, max: 1, step: 0.01 }, - temperature: { min: 0, max: 1, step: 0.01 }, - worldTime: { min: 0, max: 24_000, step: 1 }, - fogOrangeness: { min: -1, max: 1, step: 0.01 }, - distanceFactor: { min: 0, max: 5, step: 0.01 }, - }) - - if (!initialImage) { - this.createGradientSky() - } - // this.debugGui.activate() - } - - async init () { - if (this.initialImage) { - await this.setSkyboxImage(this.initialImage) - } - } - - async setSkyboxImage (imageUrl: string) { - // Dispose old textures if they exist - if (this.texture) { - this.texture.dispose() - } - - // Load the equirectangular texture - const textureLoader = new THREE.TextureLoader() - this.texture = await new Promise((resolve) => { - textureLoader.load( - imageUrl, - (texture) => { - texture.mapping = THREE.EquirectangularReflectionMapping - texture.encoding = THREE.sRGBEncoding - // Keep pixelated look - texture.minFilter = THREE.NearestFilter - texture.magFilter = THREE.NearestFilter - texture.needsUpdate = true - resolve(texture) - } - ) - }) - - // Create or update the skybox - if (this.mesh) { - // Just update the texture on the existing material - this.mesh.material.map = this.texture - this.mesh.material.needsUpdate = true - } else { - // Create a large sphere geometry for the skybox - const geometry = new THREE.SphereGeometry(500, 60, 40) - // Flip the geometry inside out - geometry.scale(-1, 1, 1) - - // Create material using the loaded texture - const material = new THREE.MeshBasicMaterial({ - map: this.texture, - side: THREE.FrontSide // Changed to FrontSide since we're flipping the geometry - }) - - // Create and add the skybox mesh - this.mesh = new THREE.Mesh(geometry, material) - this.scene.add(this.mesh) - } - } - - update (cameraPosition: THREE.Vector3, newViewDistance: number) { - if (newViewDistance !== this.viewDistance) { - this.viewDistance = newViewDistance - this.updateSkyColors() - } - - if (this.mesh) { - // Update skybox position - this.mesh.position.copy(cameraPosition) - } else if (this.skyMesh) { - // Update gradient sky position - this.skyMesh.position.copy(cameraPosition) - this.voidMesh?.position.copy(cameraPosition) - this.updateSkyColors() // Update colors based on time of day - } - } - - // Update world time - updateTime (timeOfDay: number, partialTicks = 0) { - if (this.debugGui.visible) return - this.worldTime = timeOfDay - this.partialTicks = partialTicks - this.updateSkyColors() - } - - // Update view distance - updateViewDistance (viewDistance: number) { - this.viewDistance = viewDistance - this.updateSkyColors() - } - - // Update temperature (for biome support) - updateTemperature (temperature: number) { - if (this.debugGui.visible) return - this.temperature = temperature - this.updateSkyColors() - } - - // Update water state - updateWaterState (inWater: boolean, waterBreathing: boolean) { - if (this.debugGui.visible) return - this.inWater = inWater - this.waterBreathing = waterBreathing - this.updateSkyColors() - } - - // Update default skybox setting - updateDefaultSkybox (defaultSkybox: boolean) { - if (this.debugGui.visible) return - this.defaultSkybox = defaultSkybox - this.updateSkyColors() - } - - private createGradientSky () { - const size = 64 - const scale = 256 / size + 2 - - { - const geometry = new THREE.PlaneGeometry(size * scale * 2, size * scale * 2) - geometry.rotateX(-Math.PI / 2) - geometry.translate(0, 16, 0) - - const material = new THREE.MeshBasicMaterial({ - color: 0xff_ff_ff, - side: THREE.DoubleSide, - depthTest: false - }) - - this.skyMesh = new THREE.Mesh(geometry, material) - this.scene.add(this.skyMesh) - } - - { - const geometry = new THREE.PlaneGeometry(size * scale * 2, size * scale * 2) - geometry.rotateX(-Math.PI / 2) - geometry.translate(0, -16, 0) - - const material = new THREE.MeshBasicMaterial({ - color: 0xff_ff_ff, - side: THREE.DoubleSide, - depthTest: false - }) - - this.voidMesh = new THREE.Mesh(geometry, material) - this.scene.add(this.voidMesh) - } - - this.updateSkyColors() - } - - private getFogColor (partialTicks = 0): THREE.Vector3 { - const angle = this.getCelestialAngle(partialTicks) - let rotation = Math.cos(angle * Math.PI * 2) * 2 + 0.5 - rotation = Math.max(0, Math.min(1, rotation)) - - let x = 0.752_941_2 - let y = 0.847_058_83 - let z = 1 - - x *= (rotation * 0.94 + 0.06) - y *= (rotation * 0.94 + 0.06) - z *= (rotation * 0.91 + 0.09) - - return new THREE.Vector3(x, y, z) - } - - private getSkyColor (x = 0, z = 0, partialTicks = 0): THREE.Vector3 { - const angle = this.getCelestialAngle(partialTicks) - let brightness = Math.cos(angle * 3.141_593 * 2) * 2 + 0.5 - - if (brightness < 0) brightness = 0 - if (brightness > 1) brightness = 1 - - const temperature = this.getTemperature(x, z) - const rgb = this.getSkyColorByTemp(temperature) - - const red = ((rgb >> 16) & 0xff) / 255 - const green = ((rgb >> 8) & 0xff) / 255 - const blue = (rgb & 0xff) / 255 - - return new THREE.Vector3( - red * brightness, - green * brightness, - blue * brightness - ) - } - - private calculateCelestialAngle (time: number, partialTicks: number): number { - const modTime = (time % 24_000) - let angle = (modTime + partialTicks) / 24_000 - 0.25 - - if (angle < 0) { - angle++ - } - if (angle > 1) { - angle-- - } - - angle = 1 - ((Math.cos(angle * Math.PI) + 1) / 2) - angle += (angle - angle) / 3 - - return angle - } - - private getCelestialAngle (partialTicks: number): number { - return this.calculateCelestialAngle(this.worldTime, partialTicks) - } - - private getTemperature (x: number, z: number): number { - return this.temperature - } - - private getSkyColorByTemp (temperature: number): number { - temperature /= 3 - if (temperature < -1) temperature = -1 - if (temperature > 1) temperature = 1 - - // Apply debug fog orangeness to hue - positive values make it more orange, negative make it less orange - const baseHue = 0.622_222_2 - temperature * 0.05 - // Orange is around hue 0.08-0.15, so we need to shift from blue-purple (0.62) toward orange - // Use a more dramatic shift and also increase saturation for more noticeable effect - const orangeHue = 0.12 // Orange hue value - const hue = this.fogOrangeness > 0 - ? baseHue + (orangeHue - baseHue) * this.fogOrangeness * 0.8 // Blend toward orange - : baseHue + this.fogOrangeness * 0.1 // Subtle shift for negative values - const saturation = 0.5 + temperature * 0.1 + Math.abs(this.fogOrangeness) * 0.3 // Increase saturation with orangeness - const brightness = 1 - - return this.hsbToRgb(hue, saturation, brightness) - } - - private hsbToRgb (hue: number, saturation: number, brightness: number): number { - let r = 0; let g = 0; let b = 0 - if (saturation === 0) { - r = g = b = Math.floor(brightness * 255 + 0.5) - } else { - const h = (hue - Math.floor(hue)) * 6 - const f = h - Math.floor(h) - const p = brightness * (1 - saturation) - const q = brightness * (1 - saturation * f) - const t = brightness * (1 - (saturation * (1 - f))) - switch (Math.floor(h)) { - case 0: - r = Math.floor(brightness * 255 + 0.5) - g = Math.floor(t * 255 + 0.5) - b = Math.floor(p * 255 + 0.5) - break - case 1: - r = Math.floor(q * 255 + 0.5) - g = Math.floor(brightness * 255 + 0.5) - b = Math.floor(p * 255 + 0.5) - break - case 2: - r = Math.floor(p * 255 + 0.5) - g = Math.floor(brightness * 255 + 0.5) - b = Math.floor(t * 255 + 0.5) - break - case 3: - r = Math.floor(p * 255 + 0.5) - g = Math.floor(q * 255 + 0.5) - b = Math.floor(brightness * 255 + 0.5) - break - case 4: - r = Math.floor(t * 255 + 0.5) - g = Math.floor(p * 255 + 0.5) - b = Math.floor(brightness * 255 + 0.5) - break - case 5: - r = Math.floor(brightness * 255 + 0.5) - g = Math.floor(p * 255 + 0.5) - b = Math.floor(q * 255 + 0.5) - break - } - } - return 0xff_00_00_00 | (r << 16) | (g << 8) | (Math.trunc(b)) - } - - private updateSkyColors () { - if (!this.skyMesh || !this.voidMesh) return - - // If default skybox is disabled, hide the skybox meshes - if (!this.defaultSkybox) { - this.skyMesh.visible = false - this.voidMesh.visible = false - if (this.mesh) { - this.mesh.visible = false - } - return - } - - // Show skybox meshes when default skybox is enabled - this.skyMesh.visible = true - this.voidMesh.visible = true - if (this.mesh) { - this.mesh.visible = true - } - - // Update fog brightness with smooth transition - this.prevFogBrightness = this.fogBrightness - const renderDistance = this.viewDistance / 32 - const targetBrightness = this.brightnessAtPosition * (1 - renderDistance) + renderDistance - this.fogBrightness += (targetBrightness - this.fogBrightness) * 0.1 - - // Handle water fog - if (this.inWater) { - const waterViewDistance = this.waterBreathing ? 100 : 5 - this.scene.fog = new THREE.Fog(new THREE.Color(0, 0, 1), 0.0025, waterViewDistance) - this.scene.background = new THREE.Color(0, 0, 1) - - // Update sky and void colors for underwater effect - ;(this.skyMesh.material as THREE.MeshBasicMaterial).color.set(new THREE.Color(0, 0, 1)) - ;(this.voidMesh.material as THREE.MeshBasicMaterial).color.set(new THREE.Color(0, 0, 0.6)) - return - } - - // Normal sky colors - const viewDistance = this.viewDistance * 16 - const viewFactor = 1 - (0.25 + 0.75 * this.viewDistance / 32) ** 0.25 - - const angle = this.getCelestialAngle(this.partialTicks) - const skyColor = this.getSkyColor(0, 0, this.partialTicks) - const fogColor = this.getFogColor(this.partialTicks) - - const brightness = Math.cos(angle * Math.PI * 2) * 2 + 0.5 - const clampedBrightness = Math.max(0, Math.min(1, brightness)) - - // Interpolate fog brightness - const interpolatedBrightness = this.prevFogBrightness + (this.fogBrightness - this.prevFogBrightness) * this.partialTicks - - const red = (fogColor.x + (skyColor.x - fogColor.x) * viewFactor) * clampedBrightness * interpolatedBrightness - const green = (fogColor.y + (skyColor.y - fogColor.y) * viewFactor) * clampedBrightness * interpolatedBrightness - const blue = (fogColor.z + (skyColor.z - fogColor.z) * viewFactor) * clampedBrightness * interpolatedBrightness - - this.scene.background = new THREE.Color(red, green, blue) - this.scene.fog = new THREE.Fog(new THREE.Color(red, green, blue), 0.0025, viewDistance * this.distanceFactor) - - ;(this.skyMesh.material as THREE.MeshBasicMaterial).color.set(new THREE.Color(skyColor.x, skyColor.y, skyColor.z)) - ;(this.voidMesh.material as THREE.MeshBasicMaterial).color.set(new THREE.Color( - skyColor.x * 0.2 + 0.04, - skyColor.y * 0.2 + 0.04, - skyColor.z * 0.6 + 0.1 - )) - } - - dispose () { - if (this.texture) { - this.texture.dispose() - } - if (this.mesh) { - this.mesh.geometry.dispose() - ;(this.mesh.material as THREE.Material).dispose() - this.scene.remove(this.mesh) - } - if (this.skyMesh) { - this.skyMesh.geometry.dispose() - ;(this.skyMesh.material as THREE.Material).dispose() - this.scene.remove(this.skyMesh) - } - if (this.voidMesh) { - this.voidMesh.geometry.dispose() - ;(this.voidMesh.material as THREE.Material).dispose() - this.scene.remove(this.voidMesh) - } - } -} diff --git a/renderer/viewer/three/threeJsMedia.ts b/renderer/viewer/three/threeJsMedia.ts deleted file mode 100644 index 582273d19..000000000 --- a/renderer/viewer/three/threeJsMedia.ts +++ /dev/null @@ -1,599 +0,0 @@ -import * as THREE from 'three' -import { sendVideoPlay, sendVideoStop } from '../../../src/customChannels' -import { WorldRendererThree } from './worldrendererThree' -import { ThreeJsSound } from './threeJsSound' - -interface MediaProperties { - position: { x: number, y: number, z: number } - size: { width: number, height: number } - src: string - rotation?: 0 | 1 | 2 | 3 // 0-3 for 0°, 90°, 180°, 270° - doubleSide?: boolean - background?: number // Hexadecimal color (e.g., 0x000000 for black) - opacity?: number // 0-1 value for transparency - uvMapping?: { startU: number, endU: number, startV: number, endV: number } - allowOrigins?: string[] | boolean - loop?: boolean - volume?: number - autoPlay?: boolean - - allowLighting?: boolean -} - -export class ThreeJsMedia { - customMedia = new Map void - positionalAudio?: THREE.PositionalAudio - hadAutoPlayError?: boolean - }>() - - constructor (private readonly worldRenderer: WorldRendererThree) { - this.worldRenderer.onWorldSwitched.push(() => { - this.onWorldGone() - }) - - this.worldRenderer.onRender.push(() => { - this.render() - }) - } - - onWorldGone () { - for (const [id, videoData] of this.customMedia.entries()) { - this.destroyMedia(id) - } - } - - onWorldStop () { - for (const [id, videoData] of this.customMedia.entries()) { - this.setVideoPlaying(id, false) - } - } - - private createErrorTexture (width: number, height: number, background = 0x00_00_00, error = 'Failed to load'): THREE.CanvasTexture { - const canvas = document.createElement('canvas') - const MAX_DIMENSION = 100 - - canvas.width = MAX_DIMENSION - canvas.height = MAX_DIMENSION - - const ctx = canvas.getContext('2d') - if (!ctx) return new THREE.CanvasTexture(canvas) - - // Clear with transparent background - ctx.clearRect(0, 0, canvas.width, canvas.height) - - // Add background color - ctx.fillStyle = `rgba(${background >> 16 & 255}, ${background >> 8 & 255}, ${background & 255}, 0.5)` - ctx.fillRect(0, 0, canvas.width, canvas.height) - - // Add red text with size relative to canvas dimensions - ctx.fillStyle = '#ff0000' - ctx.font = 'bold 10px sans-serif' - ctx.textAlign = 'center' - ctx.textBaseline = 'middle' - ctx.fillText(error, canvas.width / 2, canvas.height / 2, canvas.width) - - const texture = new THREE.CanvasTexture(canvas) - texture.minFilter = THREE.LinearFilter - texture.magFilter = THREE.LinearFilter - return texture - } - - private createBackgroundTexture (width: number, height: number, color = 0x00_00_00, opacity = 1): THREE.CanvasTexture { - const canvas = document.createElement('canvas') - canvas.width = 1 - canvas.height = 1 - - const ctx = canvas.getContext('2d') - if (!ctx) return new THREE.CanvasTexture(canvas) - - // Convert hex color to rgba - const r = (color >> 16) & 255 - const g = (color >> 8) & 255 - const b = color & 255 - - ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${opacity})` - ctx.fillRect(0, 0, 1, 1) - - const texture = new THREE.CanvasTexture(canvas) - texture.minFilter = THREE.NearestFilter - texture.magFilter = THREE.NearestFilter - return texture - } - - validateOrigin (src: string, allowOrigins: string[] | boolean) { - if (allowOrigins === true) return true - if (allowOrigins === false) return false - const url = new URL(src) - return allowOrigins.some(origin => url.origin.endsWith(origin)) - } - - onPageInteraction () { - for (const [id, videoData] of this.customMedia.entries()) { - if (videoData.hadAutoPlayError) { - videoData.hadAutoPlayError = false - void videoData.video?.play() - .catch(err => { - if (err.name === 'AbortError') return - console.error('Failed to play video:', err) - videoData.hadAutoPlayError = true - return true - }) - .then((fromCatch) => { - if (fromCatch) return - if (videoData.positionalAudio) { - // workaround: audio has to be recreated - this.addMedia(id, videoData.props) - } - }) - } - } - } - - addMedia (id: string, props: MediaProperties) { - const originalProps = structuredClone(props) - this.destroyMedia(id) - - const { scene } = this.worldRenderer - - const originSecurityError = props.allowOrigins !== undefined && !this.validateOrigin(props.src, props.allowOrigins) - if (originSecurityError) { - console.warn('Remote resource blocked due to security policy', props.src, 'allowed origins:', props.allowOrigins, 'you can control it with `remoteContentNotSameOrigin` option') - props.src = '' - } - - const isImage = props.src.endsWith('.png') || props.src.endsWith('.jpg') || props.src.endsWith('.jpeg') - - let video: HTMLVideoElement | undefined - let positionalAudio: THREE.PositionalAudio | undefined - if (!isImage) { - video = document.createElement('video') - video.src = props.src.endsWith('.gif') ? props.src.replace('.gif', '.mp4') : props.src - video.loop = props.loop ?? true - video.volume = props.volume ?? 1 - video.playsInline = true - video.crossOrigin = 'anonymous' - - // Create positional audio - const soundSystem = this.worldRenderer.soundSystem as ThreeJsSound - soundSystem.initAudioListener() - if (!soundSystem.audioListener) throw new Error('Audio listener not initialized') - positionalAudio = new THREE.PositionalAudio(soundSystem.audioListener) - positionalAudio.setRefDistance(6) - positionalAudio.setVolume(props.volume ?? 1) - scene.add(positionalAudio) - positionalAudio.position.set(props.position.x, props.position.y, props.position.z) - - // Connect video to positional audio - positionalAudio.setMediaElementSource(video) - positionalAudio.connect() - - video.addEventListener('pause', () => { - positionalAudio?.pause() - sendVideoStop(id, 'paused', video!.currentTime) - }) - video.addEventListener('play', () => { - positionalAudio?.play() - sendVideoPlay(id) - }) - video.addEventListener('seeked', () => { - if (positionalAudio && video) { - positionalAudio.offset = video.currentTime - } - }) - video.addEventListener('stalled', () => { - sendVideoStop(id, 'stalled', video!.currentTime) - }) - video.addEventListener('waiting', () => { - sendVideoStop(id, 'waiting', video!.currentTime) - }) - video.addEventListener('error', ({ error }) => { - sendVideoStop(id, `error: ${error}`, video!.currentTime) - }) - video.addEventListener('ended', () => { - sendVideoStop(id, 'ended', video!.currentTime) - }) - } - - - // Create background texture first - const backgroundTexture = this.createBackgroundTexture( - props.size.width, - props.size.height, - props.background, - // props.opacity ?? 1 - ) - - const handleError = (text?: string) => { - const errorTexture = this.createErrorTexture(props.size.width, props.size.height, props.background, text) - material.map = errorTexture - material.needsUpdate = true - } - - // Create a plane geometry with configurable UV mapping - const geometry = new THREE.PlaneGeometry(1, 1) - - // Create material with initial properties using background texture - const MaterialClass = props.allowLighting ? THREE.MeshLambertMaterial : THREE.MeshBasicMaterial - const material = new MaterialClass({ - map: backgroundTexture, - transparent: true, - side: props.doubleSide ? THREE.DoubleSide : THREE.FrontSide, - alphaTest: 0.1 - }) - - const texture = video - ? new THREE.VideoTexture(video) - : new THREE.TextureLoader().load(props.src, () => { - if (this.customMedia.get(id)?.texture === texture) { - material.map = texture - material.needsUpdate = true - } - }, undefined, () => handleError()) // todo cache - texture.minFilter = THREE.NearestFilter - texture.magFilter = THREE.NearestFilter - // texture.format = THREE.RGBAFormat - // texture.colorSpace = THREE.SRGBColorSpace - texture.generateMipmaps = false - - // Create inner mesh for offsets - const mesh = new THREE.Mesh(geometry, material) - - const { mesh: panel } = this.positionMeshExact(mesh, THREE.MathUtils.degToRad((props.rotation ?? 0) * 90), props.position, props.size.width, props.size.height) - - scene.add(panel) - - if (video) { - // Start playing the video - video.play().catch(err => { - if (err.name === 'AbortError') return - console.error('Failed to play video:', err) - videoData.hadAutoPlayError = true - handleError(err.name === 'NotAllowedError' ? 'Waiting for user interaction' : 'Failed to auto play') - }) - - // Update texture in animation loop - mesh.onBeforeRender = () => { - if (video.readyState === video.HAVE_ENOUGH_DATA && (!video.paused || !videoData?.hadAutoPlayError)) { - if (material.map !== texture) { - material.map = texture - material.needsUpdate = true - } - texture.needsUpdate = true - - // Sync audio position with video position - if (positionalAudio) { - positionalAudio.position.copy(panel.position) - positionalAudio.rotation.copy(panel.rotation) - } - } - } - } - - // UV mapping configuration - const updateUVMapping = (config: { startU: number, endU: number, startV: number, endV: number }) => { - const uvs = geometry.attributes.uv.array as Float32Array - uvs[0] = config.startU - uvs[1] = config.startV - uvs[2] = config.endU - uvs[3] = config.startV - uvs[4] = config.endU - uvs[5] = config.endV - uvs[6] = config.startU - uvs[7] = config.endV - geometry.attributes.uv.needsUpdate = true - } - - // Apply initial UV mapping if provided - if (props.uvMapping) { - updateUVMapping(props.uvMapping) - } - - const videoData = { - mesh: panel, - video, - texture, - updateUVMapping, - positionalAudio, - props: originalProps, - hadAutoPlayError: false - } - // Store video data - this.customMedia.set(id, videoData) - - return id - } - - render () { - for (const [id, videoData] of this.customMedia.entries()) { - const chunkX = Math.floor(videoData.props.position.x / 16) * 16 - const chunkZ = Math.floor(videoData.props.position.z / 16) * 16 - const sectionY = Math.floor(videoData.props.position.y / 16) * 16 - - const chunkKey = `${chunkX},${chunkZ}` - const sectionKey = `${chunkX},${sectionY},${chunkZ}` - videoData.mesh.visible = !!this.worldRenderer.sectionObjects[sectionKey] || !!this.worldRenderer.finishedChunks[chunkKey] - } - } - - setVideoPlaying (id: string, playing: boolean) { - const videoData = this.customMedia.get(id) - if (videoData?.video) { - if (playing) { - videoData.video.play().catch(console.error) - } else { - videoData.video.pause() - } - } - } - - setVideoSeeking (id: string, seconds: number) { - const videoData = this.customMedia.get(id) - if (videoData?.video) { - videoData.video.currentTime = seconds - } - } - - setVideoVolume (id: string, volume: number) { - const videoData = this.customMedia.get(id) - if (videoData?.video) { - videoData.video.volume = volume - } - } - - setVideoSpeed (id: string, speed: number) { - const videoData = this.customMedia.get(id) - if (videoData?.video) { - videoData.video.playbackRate = speed - } - } - - destroyMedia (id: string) { - const { scene } = this.worldRenderer - const mediaData = this.customMedia.get(id) - if (mediaData) { - if (mediaData.video) { - mediaData.video.pause() - mediaData.video.src = '' - mediaData.video.remove() - } - if (mediaData.positionalAudio) { - // mediaData.positionalAudio.stop() - // mediaData.positionalAudio.disconnect() - scene.remove(mediaData.positionalAudio) - } - scene.remove(mediaData.mesh) - mediaData.texture.dispose() - - // Get the inner mesh from the group - const mesh = mediaData.mesh.children[0] as THREE.Mesh - if (mesh) { - mesh.geometry.dispose() - if (mesh.material instanceof THREE.Material) { - mesh.material.dispose() - } - } - - this.customMedia.delete(id) - } - } - - /** - * Positions a mesh exactly at startPosition and extends it along the rotation direction - * with the specified width and height - * - * @param mesh The mesh to position - * @param rotation Rotation in radians (applied to Y axis) - * @param startPosition The exact starting position (corner) of the mesh - * @param width Width of the mesh - * @param height Height of the mesh - * @param depth Depth of the mesh (default: 1) - * @returns The positioned mesh for chaining - */ - positionMeshExact ( - mesh: THREE.Mesh, - rotation: number, - startPosition: { x: number, y: number, z: number }, - width: number, - height: number, - depth = 1 - ) { - // avoid z-fighting with the ground plane - if (rotation === 0) { - startPosition.z += 0.001 - } - if (rotation === Math.PI / 2) { - startPosition.x -= 0.001 - } - if (rotation === Math.PI) { - startPosition.z -= 0.001 - } - if (rotation === 3 * Math.PI / 2) { - startPosition.x += 0.001 - } - - // rotation normalize coordinates - if (rotation === 0) { - startPosition.z += 1 - } - if (rotation === Math.PI) { - startPosition.x += 1 - } - if (rotation === 3 * Math.PI / 2) { - startPosition.z += 1 - startPosition.x += 1 - } - - - // First, clean up any previous transformations - mesh.matrix.identity() - mesh.position.set(0, 0, 0) - mesh.rotation.set(0, 0, 0) - mesh.scale.set(1, 1, 1) - - // By default, PlaneGeometry creates a plane in the XY plane (facing +Z) - // We need to set up the proper orientation for our use case - // Rotate the plane to face the correct direction based on the rotation parameter - mesh.rotateY(rotation) - if (rotation === Math.PI / 2 || rotation === 3 * Math.PI / 2) { - mesh.rotateZ(-Math.PI) - mesh.rotateX(-Math.PI) - } - - // Scale it to the desired size - mesh.scale.set(width, height, depth) - - // For a PlaneGeometry, if we want the corner at the origin, we need to offset - // by half the dimensions after scaling - mesh.geometry.translate(0.5, 0.5, 0) - mesh.geometry.attributes.position.needsUpdate = true - - // Now place the mesh at the start position - mesh.position.set(startPosition.x, startPosition.y, startPosition.z) - - // Create a group to hold our mesh and markers - const debugGroup = new THREE.Group() - debugGroup.add(mesh) - - // Add a marker at the starting position (should be exactly at pos) - const startMarker = new THREE.Mesh( - new THREE.BoxGeometry(0.1, 0.1, 0.1), - new THREE.MeshBasicMaterial({ color: 0xff_00_00 }) - ) - startMarker.position.copy(new THREE.Vector3(startPosition.x, startPosition.y, startPosition.z)) - debugGroup.add(startMarker) - - // Add a marker at the end position (width units away in the rotated direction) - const endX = startPosition.x + Math.cos(rotation) * width - const endZ = startPosition.z + Math.sin(rotation) * width - const endYMarker = new THREE.Mesh( - new THREE.BoxGeometry(0.1, 0.1, 0.1), - new THREE.MeshBasicMaterial({ color: 0x00_00_ff }) - ) - endYMarker.position.set(startPosition.x, startPosition.y + height, startPosition.z) - debugGroup.add(endYMarker) - - // Add a marker at the width endpoint - const endWidthMarker = new THREE.Mesh( - new THREE.BoxGeometry(0.1, 0.1, 0.1), - new THREE.MeshBasicMaterial({ color: 0xff_ff_00 }) - ) - endWidthMarker.position.set(endX, startPosition.y, endZ) - debugGroup.add(endWidthMarker) - - // Add a marker at the corner diagonal endpoint (both width and height) - const endCornerMarker = new THREE.Mesh( - new THREE.BoxGeometry(0.1, 0.1, 0.1), - new THREE.MeshBasicMaterial({ color: 0xff_00_ff }) - ) - endCornerMarker.position.set(endX, startPosition.y + height, endZ) - debugGroup.add(endCornerMarker) - - // Also add a visual helper to show the rotation direction - const directionHelper = new THREE.ArrowHelper( - new THREE.Vector3(Math.cos(rotation), 0, Math.sin(rotation)), - new THREE.Vector3(startPosition.x, startPosition.y, startPosition.z), - 1, - 0xff_00_00 - ) - debugGroup.add(directionHelper) - - return { - mesh, - debugGroup - } - } - - createTestCanvasTexture () { - const canvas = document.createElement('canvas') - canvas.width = 100 - canvas.height = 100 - const ctx = canvas.getContext('2d') - if (!ctx) return null - ctx.font = '10px Arial' - ctx.fillStyle = 'red' - ctx.fillText('Hello World', 0, 10) // at - return new THREE.CanvasTexture(canvas) - } - - /** - * Creates a test mesh that demonstrates the exact positioning - */ - addTestMeshExact (rotationNum: number) { - const pos = window.cursorBlockRel().position - console.log('Creating exact positioned test mesh at:', pos) - - // Create a plane mesh with a wireframe to visualize boundaries - const plane = new THREE.Mesh( - new THREE.PlaneGeometry(1, 1), - new THREE.MeshBasicMaterial({ - // side: THREE.DoubleSide, - map: this.createTestCanvasTexture() - }) - ) - - const width = 2 - const height = 1 - const rotation = THREE.MathUtils.degToRad(rotationNum * 90) // 90 degrees in radians - - // Position the mesh exactly where we want it - const { debugGroup } = this.positionMeshExact(plane, rotation, pos, width, height) - - this.worldRenderer.scene.add(debugGroup) - console.log('Exact test mesh added with dimensions:', width, height, 'and rotation:', rotation) - } - - lastCheck = 0 - THROTTLE_TIME = 100 - tryIntersectMedia () { - // hack: need to optimize this by pulling only in distance of interaction instead and throttle - if (this.customMedia.size === 0) return - if (Date.now() - this.lastCheck < this.THROTTLE_TIME) return - this.lastCheck = Date.now() - - const { camera, scene } = this.worldRenderer - const raycaster = new THREE.Raycaster() - - // Get mouse position at center of screen - const mouse = new THREE.Vector2(0, 0) - - // Update the raycaster - raycaster.setFromCamera(mouse, camera) - - // Check intersection with all objects in scene - const intersects = raycaster.intersectObjects(scene.children, true) - if (intersects.length > 0) { - const intersection = intersects[0] - const intersectedObject = intersection.object - - // Find if this object belongs to any media - for (const [id, videoData] of this.customMedia.entries()) { - // Check if the intersected object is part of our media mesh - if (intersectedObject === videoData.mesh || - videoData.mesh.children.includes(intersectedObject)) { - const { uv } = intersection - if (uv) { - const result = { - id, - x: uv.x, - y: uv.y - } - this.worldRenderer.reactiveState.world.intersectMedia = result - this.worldRenderer['debugVideo'] = videoData - this.worldRenderer.cursorBlock.cursorLinesHidden = true - return - } - } - } - } - - // No media intersection found - this.worldRenderer.reactiveState.world.intersectMedia = null - this.worldRenderer['debugVideo'] = null - this.worldRenderer.cursorBlock.cursorLinesHidden = false - } -} diff --git a/renderer/viewer/three/threeJsMethods.ts b/renderer/viewer/three/threeJsMethods.ts deleted file mode 100644 index 629909c98..000000000 --- a/renderer/viewer/three/threeJsMethods.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { GraphicsBackend } from '../../../src/appViewer' -import type { ThreeJsBackendMethods } from './graphicsBackend' - -export function getThreeJsRendererMethods (): ThreeJsBackendMethods | undefined { - const renderer = appViewer.backend - if (renderer?.id !== 'threejs' || !renderer.backendMethods) return - return new Proxy(renderer.backendMethods, { - get (target, prop) { - return async (...args) => { - const result = await (target[prop as any] as any)(...args) - return result - } - } - }) as ThreeJsBackendMethods -} diff --git a/renderer/viewer/three/threeJsParticles.ts b/renderer/viewer/three/threeJsParticles.ts deleted file mode 100644 index 993f2b626..000000000 --- a/renderer/viewer/three/threeJsParticles.ts +++ /dev/null @@ -1,160 +0,0 @@ -import * as THREE from 'three' - -interface ParticleMesh extends THREE.Mesh { - velocity: THREE.Vector3; -} - -interface ParticleConfig { - fountainHeight: number; - resetHeight: number; - xVelocityRange: number; - zVelocityRange: number; - particleCount: number; - particleRadiusRange: { min: number; max: number }; - yVelocityRange: { min: number; max: number }; -} - -export interface FountainOptions { - position?: { x: number, y: number, z: number } - particleConfig?: Partial; -} - -export class Fountain { - private readonly particles: ParticleMesh[] = [] - private readonly config: { particleConfig: ParticleConfig } - private readonly position: THREE.Vector3 - container: THREE.Object3D | undefined - - constructor (public sectionId: string, options: FountainOptions = {}) { - this.position = options.position ? new THREE.Vector3(options.position.x, options.position.y, options.position.z) : new THREE.Vector3(0, 0, 0) - this.config = this.createConfig(options.particleConfig) - } - - private createConfig ( - particleConfigOverride?: Partial - ): { particleConfig: ParticleConfig } { - const particleConfig: ParticleConfig = { - fountainHeight: 10, - resetHeight: 0, - xVelocityRange: 0.4, - zVelocityRange: 0.4, - particleCount: 400, - particleRadiusRange: { min: 0.1, max: 0.6 }, - yVelocityRange: { min: 0.1, max: 2 }, - ...particleConfigOverride - } - - return { particleConfig } - } - - - createParticles (container: THREE.Object3D): void { - this.container = container - const colorStart = new THREE.Color(0xff_ff_00) - const colorEnd = new THREE.Color(0xff_a5_00) - - for (let i = 0; i < this.config.particleConfig.particleCount; i++) { - const radius = Math.random() * - (this.config.particleConfig.particleRadiusRange.max - this.config.particleConfig.particleRadiusRange.min) + - this.config.particleConfig.particleRadiusRange.min - const geometry = new THREE.SphereGeometry(radius) - const material = new THREE.MeshBasicMaterial({ - color: colorStart.clone().lerp(colorEnd, Math.random()) - }) - const mesh = new THREE.Mesh(geometry, material) - const particle = mesh as unknown as ParticleMesh - - particle.position.set( - this.position.x + (Math.random() - 0.5) * this.config.particleConfig.xVelocityRange * 2, - this.position.y + this.config.particleConfig.fountainHeight, - this.position.z + (Math.random() - 0.5) * this.config.particleConfig.zVelocityRange * 2 - ) - - particle.velocity = new THREE.Vector3( - (Math.random() - 0.5) * this.config.particleConfig.xVelocityRange, - -Math.random() * this.config.particleConfig.yVelocityRange.max, - (Math.random() - 0.5) * this.config.particleConfig.zVelocityRange - ) - - this.particles.push(particle) - this.container.add(particle) - - // this.container.onBeforeRender = () => { - // this.render() - // } - } - } - - render (): void { - for (const particle of this.particles) { - particle.velocity.y -= 0.01 + Math.random() * 0.1 - particle.position.add(particle.velocity) - - if (particle.position.y < this.position.y + this.config.particleConfig.resetHeight) { - particle.position.set( - this.position.x + (Math.random() - 0.5) * this.config.particleConfig.xVelocityRange * 2, - this.position.y + this.config.particleConfig.fountainHeight, - this.position.z + (Math.random() - 0.5) * this.config.particleConfig.zVelocityRange * 2 - ) - particle.velocity.set( - (Math.random() - 0.5) * this.config.particleConfig.xVelocityRange, - -Math.random() * this.config.particleConfig.yVelocityRange.max, - (Math.random() - 0.5) * this.config.particleConfig.zVelocityRange - ) - } - } - } - - private updateParticleCount (newCount: number): void { - if (newCount !== this.config.particleConfig.particleCount) { - this.config.particleConfig.particleCount = newCount - const currentCount = this.particles.length - - if (newCount > currentCount) { - this.addParticles(newCount - currentCount) - } else if (newCount < currentCount) { - this.removeParticles(currentCount - newCount) - } - } - } - - private addParticles (count: number): void { - const geometry = new THREE.SphereGeometry(0.1) - const material = new THREE.MeshBasicMaterial({ color: 0x00_ff_00 }) - - for (let i = 0; i < count; i++) { - const mesh = new THREE.Mesh(geometry, material) - const particle = mesh as unknown as ParticleMesh - particle.position.copy(this.position) - particle.velocity = new THREE.Vector3( - Math.random() * this.config.particleConfig.xVelocityRange - - this.config.particleConfig.xVelocityRange / 2, - Math.random() * 2, - Math.random() * this.config.particleConfig.zVelocityRange - - this.config.particleConfig.zVelocityRange / 2 - ) - this.particles.push(particle) - this.container!.add(particle) - } - } - - private removeParticles (count: number): void { - for (let i = 0; i < count; i++) { - const particle = this.particles.pop() - if (particle) { - this.container!.remove(particle) - } - } - } - - public dispose (): void { - for (const particle of this.particles) { - particle.geometry.dispose() - if (Array.isArray(particle.material)) { - for (const material of particle.material) material.dispose() - } else { - particle.material.dispose() - } - } - } -} diff --git a/renderer/viewer/three/threeJsSound.ts b/renderer/viewer/three/threeJsSound.ts deleted file mode 100644 index 699bb2cc1..000000000 --- a/renderer/viewer/three/threeJsSound.ts +++ /dev/null @@ -1,99 +0,0 @@ -import * as THREE from 'three' -import { WorldRendererThree } from './worldrendererThree' - -export interface SoundSystem { - playSound: (position: { x: number, y: number, z: number }, path: string, volume?: number, pitch?: number, timeout?: number) => void - destroy: () => void -} - -export class ThreeJsSound implements SoundSystem { - audioListener: THREE.AudioListener | undefined - private readonly activeSounds = new Set() - private readonly audioContext: AudioContext | undefined - private readonly soundVolumes = new Map() - baseVolume = 1 - - constructor (public worldRenderer: WorldRendererThree) { - worldRenderer.onWorldSwitched.push(() => { - this.stopAll() - }) - - worldRenderer.onReactiveConfigUpdated('volume', (volume) => { - this.changeVolume(volume) - }) - } - - initAudioListener () { - if (this.audioListener) return - this.audioListener = new THREE.AudioListener() - this.worldRenderer.camera.add(this.audioListener) - } - - playSound (position: { x: number, y: number, z: number }, path: string, volume = 1, pitch = 1, timeout = 500) { - this.initAudioListener() - - const sound = new THREE.PositionalAudio(this.audioListener!) - this.activeSounds.add(sound) - this.soundVolumes.set(sound, volume) - - const audioLoader = new THREE.AudioLoader() - const start = Date.now() - void audioLoader.loadAsync(path).then((buffer) => { - if (Date.now() - start > timeout) { - console.warn('Ignored playing sound', path, 'due to timeout:', timeout, 'ms <', Date.now() - start, 'ms') - return - } - // play - sound.setBuffer(buffer) - sound.setRefDistance(20) - sound.setVolume(volume * this.baseVolume) - sound.setPlaybackRate(pitch) // set the pitch - this.worldRenderer.scene.add(sound) - // set sound position - sound.position.set(position.x, position.y, position.z) - sound.onEnded = () => { - this.worldRenderer.scene.remove(sound) - if (sound.source) { - sound.disconnect() - } - this.activeSounds.delete(sound) - this.soundVolumes.delete(sound) - audioLoader.manager.itemEnd(path) - } - sound.play() - }) - } - - stopAll () { - for (const sound of this.activeSounds) { - if (!sound) continue - sound.stop() - if (sound.source) { - sound.disconnect() - } - this.worldRenderer.scene.remove(sound) - } - this.activeSounds.clear() - this.soundVolumes.clear() - } - - changeVolume (volume: number) { - this.baseVolume = volume - for (const [sound, individualVolume] of this.soundVolumes) { - sound.setVolume(individualVolume * this.baseVolume) - } - } - - destroy () { - this.stopAll() - // Remove and cleanup audio listener - if (this.audioListener) { - this.audioListener.removeFromParent() - this.audioListener = undefined - } - } - - playTestSound () { - this.playSound(this.worldRenderer.camera.position, '/sound.mp3') - } -} diff --git a/renderer/viewer/three/threeJsUtils.ts b/renderer/viewer/three/threeJsUtils.ts deleted file mode 100644 index cbef9065e..000000000 --- a/renderer/viewer/three/threeJsUtils.ts +++ /dev/null @@ -1,73 +0,0 @@ -import * as THREE from 'three' -import { getLoadedImage } from 'mc-assets/dist/utils' -import { createCanvas } from '../lib/utils' - -export const disposeObject = (obj: THREE.Object3D, cleanTextures = false) => { - // not cleaning texture there as it might be used by other objects, but would be good to also do that - if (obj instanceof THREE.Mesh) { - obj.geometry?.dispose?.() - obj.material?.dispose?.() - } - if (obj.children) { - // eslint-disable-next-line unicorn/no-array-for-each - obj.children.forEach(child => disposeObject(child, cleanTextures)) - } - if (cleanTextures) { - if (obj instanceof THREE.Mesh) { - obj.material?.map?.dispose?.() - } - } -} - -let textureCache: Record = {} -let imagesPromises: Record> = {} - -export const loadThreeJsTextureFromUrlSync = (imageUrl: string) => { - const texture = new THREE.Texture() - const promise = getLoadedImage(imageUrl).then(image => { - texture.image = image - texture.needsUpdate = true - return texture - }) - return { - texture, - promise - } -} - -export const loadThreeJsTextureFromUrl = async (imageUrl: string) => { - const loaded = new THREE.TextureLoader().loadAsync(imageUrl) - return loaded -} - -export const loadThreeJsTextureFromBitmap = (image: ImageBitmap) => { - const canvas = createCanvas(image.width, image.height) - const ctx = canvas.getContext('2d')! - ctx.drawImage(image, 0, 0) - const texture = new THREE.Texture(canvas) - texture.magFilter = THREE.NearestFilter - texture.minFilter = THREE.NearestFilter - return texture -} - -export async function loadTexture (texture: string, cb: (texture: THREE.Texture) => void, onLoad?: () => void): Promise { - const cached = textureCache[texture] - if (!cached) { - const { promise, resolve } = Promise.withResolvers() - const t = loadThreeJsTextureFromUrlSync(texture) - textureCache[texture] = t.texture - void t.promise.then(resolve) - imagesPromises[texture] = promise - } - - cb(textureCache[texture]) - void imagesPromises[texture].then(() => { - onLoad?.() - }) -} - -export const clearTextureCache = () => { - textureCache = {} - imagesPromises = {} -} - diff --git a/renderer/viewer/three/waypointSprite.ts b/renderer/viewer/three/waypointSprite.ts deleted file mode 100644 index e6c7bffe4..000000000 --- a/renderer/viewer/three/waypointSprite.ts +++ /dev/null @@ -1,459 +0,0 @@ -import * as THREE from 'three' - -// Centralized visual configuration (in screen pixels) -export const WAYPOINT_CONFIG = { - // Target size in screen pixels (this controls the final sprite size) - TARGET_SCREEN_PX: 150, - // Canvas size for internal rendering (keep power of 2 for textures) - CANVAS_SIZE: 256, - // Relative positions in canvas (0-1) - LAYOUT: { - DOT_Y: 0.3, - NAME_Y: 0.45, - DISTANCE_Y: 0.55, - }, - // Multiplier for canvas internal resolution to keep text crisp - CANVAS_SCALE: 2, - ARROW: { - enabledDefault: false, - pixelSize: 50, - paddingPx: 50, - }, - // Default visual scale factor (can be overridden globally or per-waypoint) - DEFAULT_VISUAL_SCALE: 1, - // Default opacity (can be overridden globally or per-waypoint) - DEFAULT_OPACITY: 1, -} - -export type WaypointSprite = { - group: THREE.Group - sprite: THREE.Sprite - // Offscreen arrow controls - enableOffscreenArrow: (enabled: boolean) => void - setArrowParent: (parent: THREE.Object3D | null) => void - // Convenience combined updater - updateForCamera: ( - cameraPosition: THREE.Vector3, - camera: THREE.PerspectiveCamera, - viewportWidthPx: number, - viewportHeightPx: number - ) => boolean - // Utilities - setColor: (color: number) => void - setLabel: (label?: string) => void - updateDistanceText: (label: string, distanceText: string) => void - setVisible: (visible: boolean) => void - setPosition: (x: number, y: number, z: number) => void - dispose: () => void -} - -export function createWaypointSprite (options: { - position: THREE.Vector3 | { x: number, y: number, z: number }, - color?: number, - label?: string, - depthTest?: boolean, - // Y offset in world units used by updateScaleWorld only (screen-pixel API ignores this) - labelYOffset?: number, - metadata?: any, - visualScale?: number, - opacity?: number, -}): WaypointSprite { - const color = options.color ?? 0xFF_00_00 - const depthTest = options.depthTest ?? false - const labelYOffset = options.labelYOffset ?? 1.5 - - // Get visual scale from options, metadata, server metadata, or default - // Priority: options.visualScale > metadata.visualScale > window.serverMetadata?.waypointVisualScale > DEFAULT - const visualScale = options.visualScale - ?? options.metadata?.visualScale - ?? (typeof window === 'undefined' ? undefined : (window as any).serverMetadata?.waypointVisualScale) - ?? WAYPOINT_CONFIG.DEFAULT_VISUAL_SCALE - - // Get opacity from options, metadata, server metadata, or default - // Priority: options.opacity > metadata.opacity > window.serverMetadata?.waypointOpacity > DEFAULT - const opacity = options.opacity - ?? options.metadata?.opacity - ?? (typeof window === 'undefined' ? undefined : (window as any).serverMetadata?.waypointOpacity) - ?? WAYPOINT_CONFIG.DEFAULT_OPACITY - - // Build combined sprite - const sprite = createCombinedSprite(color, options.label ?? '', '0m', depthTest, visualScale) - sprite.renderOrder = 10 - sprite.material.opacity = opacity - let currentLabel = options.label ?? '' - - // Performance optimization: cache distance text to avoid unnecessary updates - let lastDistanceText = '0m' - let lastDistance = 0 - - // Offscreen arrow (detached by default) - let arrowSprite: THREE.Sprite | undefined - let arrowParent: THREE.Object3D | null = null - let arrowEnabled = WAYPOINT_CONFIG.ARROW.enabledDefault - - // Group for easy add/remove - const group = new THREE.Group() - group.add(sprite) - - // Initial position - const { x, y, z } = options.position - group.position.set(x, y, z) - - function setColor (newColor: number) { - const canvas = drawCombinedCanvas(newColor, currentLabel, '0m', visualScale) - const texture = new THREE.CanvasTexture(canvas) - const mat = sprite.material - mat.map?.dispose() - mat.map = texture - mat.needsUpdate = true - } - - function setLabel (newLabel?: string) { - currentLabel = newLabel ?? '' - const canvas = drawCombinedCanvas(color, currentLabel, '0m', visualScale) - const texture = new THREE.CanvasTexture(canvas) - const mat = sprite.material - mat.map?.dispose() - mat.map = texture - mat.needsUpdate = true - } - - function updateDistanceText (label: string, distanceText: string) { - // Performance optimization: only update if distance text actually changed - if (distanceText === lastDistanceText) { - return - } - lastDistanceText = distanceText - - const canvas = drawCombinedCanvas(color, label, distanceText, visualScale) - const texture = new THREE.CanvasTexture(canvas) - const mat = sprite.material - mat.map?.dispose() - mat.map = texture - mat.needsUpdate = true - } - - function setVisible (visible: boolean) { - sprite.visible = visible - } - - function setPosition (nx: number, ny: number, nz: number) { - group.position.set(nx, ny, nz) - } - - // Keep constant pixel size on screen using global config - function updateScaleScreenPixels ( - cameraPosition: THREE.Vector3, - cameraFov: number, - distance: number, - viewportHeightPx: number - ) { - const vFovRad = cameraFov * Math.PI / 180 - const worldUnitsPerScreenHeightAtDist = Math.tan(vFovRad / 2) * 2 * distance - // Use configured target screen size with visual scale multiplier - const scale = worldUnitsPerScreenHeightAtDist * (WAYPOINT_CONFIG.TARGET_SCREEN_PX * visualScale / viewportHeightPx) - sprite.scale.set(scale, scale, 1) - } - - function ensureArrow () { - if (arrowSprite) return - const size = 128 - const canvas = document.createElement('canvas') - canvas.width = size - canvas.height = size - const ctx = canvas.getContext('2d')! - ctx.clearRect(0, 0, size, size) - - // Draw arrow shape - ctx.beginPath() - ctx.moveTo(size * 0.15, size * 0.5) - ctx.lineTo(size * 0.85, size * 0.5) - ctx.lineTo(size * 0.5, size * 0.15) - ctx.closePath() - - // Use waypoint color for arrow - const colorHex = `#${color.toString(16).padStart(6, '0')}` - ctx.lineWidth = 6 - ctx.strokeStyle = 'black' - ctx.stroke() - ctx.fillStyle = colorHex - ctx.fill() - - const texture = new THREE.CanvasTexture(canvas) - const material = new THREE.SpriteMaterial({ map: texture, transparent: true, depthTest: false, depthWrite: false, opacity }) - arrowSprite = new THREE.Sprite(material) - arrowSprite.renderOrder = 12 - arrowSprite.visible = false - if (arrowParent) arrowParent.add(arrowSprite) - } - - function enableOffscreenArrow (enabled: boolean) { - arrowEnabled = enabled - if (!enabled && arrowSprite) arrowSprite.visible = false - } - - function setArrowParent (parent: THREE.Object3D | null) { - if (arrowSprite?.parent) arrowSprite.parent.remove(arrowSprite) - arrowParent = parent - if (arrowSprite && parent) parent.add(arrowSprite) - } - - function updateOffscreenArrow ( - camera: THREE.PerspectiveCamera, - viewportWidthPx: number, - viewportHeightPx: number - ): boolean { - if (!arrowEnabled) return true - ensureArrow() - if (!arrowSprite) return true - - // Check if onlyLeftRight is enabled in metadata - const onlyLeftRight = options.metadata?.onlyLeftRight === true - - // Build camera basis using camera.up to respect custom orientations - const forward = new THREE.Vector3() - camera.getWorldDirection(forward) // camera look direction - const upWorld = camera.up.clone().normalize() - const right = new THREE.Vector3().copy(forward).cross(upWorld).normalize() - const upCam = new THREE.Vector3().copy(right).cross(forward).normalize() - - // Vector from camera to waypoint - const camPos = new THREE.Vector3().setFromMatrixPosition(camera.matrixWorld) - const toWp = new THREE.Vector3(group.position.x, group.position.y, group.position.z).sub(camPos) - - // Components in camera basis - const z = toWp.dot(forward) - const x = toWp.dot(right) - const y = toWp.dot(upCam) - - const aspect = viewportWidthPx / viewportHeightPx - const vFovRad = camera.fov * Math.PI / 180 - const hFovRad = 2 * Math.atan(Math.tan(vFovRad / 2) * aspect) - - // Determine if waypoint is inside view frustum using angular checks - const thetaX = Math.atan2(x, z) - const thetaY = Math.atan2(y, z) - const visible = z > 0 && Math.abs(thetaX) <= hFovRad / 2 && Math.abs(thetaY) <= vFovRad / 2 - if (visible) { - arrowSprite.visible = false - return true - } - - // Direction on screen in normalized frustum units - let rx = thetaX / (hFovRad / 2) - let ry = thetaY / (vFovRad / 2) - - // If behind the camera, snap to dominant axis to avoid confusing directions - if (z <= 0) { - if (Math.abs(rx) > Math.abs(ry)) { - rx = Math.sign(rx) - ry = 0 - } else { - rx = 0 - ry = Math.sign(ry) - } - } - - // Apply onlyLeftRight logic - restrict arrows to left/right edges only - if (onlyLeftRight) { - // Force the arrow to appear only on left or right edges - if (Math.abs(rx) > Math.abs(ry)) { - // Horizontal direction is dominant, keep it - ry = 0 - } else { - // Vertical direction is dominant, but we want only left/right - // So choose left or right based on the sign of rx - rx = rx >= 0 ? 1 : -1 - ry = 0 - } - } - - // Place on the rectangle border [-1,1]x[-1,1] - const s = Math.max(Math.abs(rx), Math.abs(ry)) || 1 - let ndcX = rx / s - let ndcY = ry / s - - // Apply padding in pixel space by clamping - const padding = WAYPOINT_CONFIG.ARROW.paddingPx - const pxX = ((ndcX + 1) * 0.5) * viewportWidthPx - const pxY = ((1 - ndcY) * 0.5) * viewportHeightPx - const clampedPxX = Math.min(Math.max(pxX, padding), viewportWidthPx - padding) - const clampedPxY = Math.min(Math.max(pxY, padding), viewportHeightPx - padding) - ndcX = (clampedPxX / viewportWidthPx) * 2 - 1 - ndcY = -(clampedPxY / viewportHeightPx) * 2 + 1 - - // Compute world position at a fixed distance in front of the camera using camera basis - const placeDist = Math.max(2, camera.near * 4) - const halfPlaneHeight = Math.tan(vFovRad / 2) * placeDist - const halfPlaneWidth = halfPlaneHeight * aspect - const pos = camPos.clone() - .add(forward.clone().multiplyScalar(placeDist)) - .add(right.clone().multiplyScalar(ndcX * halfPlaneWidth)) - .add(upCam.clone().multiplyScalar(ndcY * halfPlaneHeight)) - - // Update arrow sprite - arrowSprite.visible = true - arrowSprite.position.copy(pos) - - // Angle for rotation relative to screen right/up (derived from camera up vector) - const angle = Math.atan2(ry, rx) - arrowSprite.material.rotation = angle - Math.PI / 2 - - // Constant pixel size for arrow (use fixed placement distance) with visual scale - const worldUnitsPerScreenHeightAtDist = Math.tan(vFovRad / 2) * 2 * placeDist - const sPx = worldUnitsPerScreenHeightAtDist * (WAYPOINT_CONFIG.ARROW.pixelSize * visualScale / viewportHeightPx) - arrowSprite.scale.set(sPx, sPx, 1) - return false - } - - function computeDistance (cameraPosition: THREE.Vector3): number { - return cameraPosition.distanceTo(group.position) - } - - function updateForCamera ( - cameraPosition: THREE.Vector3, - camera: THREE.PerspectiveCamera, - viewportWidthPx: number, - viewportHeightPx: number - ): boolean { - const distance = computeDistance(cameraPosition) - // Keep constant pixel size - updateScaleScreenPixels(cameraPosition, camera.fov, distance, viewportHeightPx) - - // Performance optimization: only update distance text if distance changed significantly - const roundedDistance = Math.round(distance) - if (Math.abs(roundedDistance - lastDistance) >= 1) { - lastDistance = roundedDistance - updateDistanceText(currentLabel, `${roundedDistance}m`) - } - - // Update arrow and visibility - const onScreen = updateOffscreenArrow(camera, viewportWidthPx, viewportHeightPx) - setVisible(onScreen) - return onScreen - } - - function dispose () { - const mat = sprite.material - mat.map?.dispose() - mat.dispose() - if (arrowSprite) { - // Remove arrow from parent before disposing - if (arrowSprite.parent) { - arrowSprite.parent.remove(arrowSprite) - } - const am = arrowSprite.material - am.map?.dispose() - am.dispose() - } - } - - return { - group, - sprite, - enableOffscreenArrow, - setArrowParent, - updateForCamera, - setColor, - setLabel, - updateDistanceText, - setVisible, - setPosition, - dispose, - } -} - -// Internal helpers -function drawCombinedCanvas (color: number, id: string, distance: string, visualScale = 1): HTMLCanvasElement { - const scale = WAYPOINT_CONFIG.CANVAS_SCALE * (globalThis.devicePixelRatio || 1) - const size = WAYPOINT_CONFIG.CANVAS_SIZE * scale - const canvas = document.createElement('canvas') - canvas.width = size - canvas.height = size - const ctx = canvas.getContext('2d')! - - // Clear canvas - ctx.clearRect(0, 0, size, size) - - // Draw dot with visual scale applied - const centerX = size / 2 - const dotY = Math.round(size * WAYPOINT_CONFIG.LAYOUT.DOT_Y) - const radius = Math.round(size * 0.05 * visualScale) // Dot takes up ~5% of canvas height, scaled - const borderWidth = Math.max(2, Math.round(4 * scale * visualScale)) - - // Outer border (black) - ctx.beginPath() - ctx.arc(centerX, dotY, radius + borderWidth, 0, Math.PI * 2) - ctx.fillStyle = 'black' - ctx.fill() - - // Inner circle (colored) - ctx.beginPath() - ctx.arc(centerX, dotY, radius, 0, Math.PI * 2) - ctx.fillStyle = `#${color.toString(16).padStart(6, '0')}` - ctx.fill() - - // Text properties - ctx.textAlign = 'center' - ctx.textBaseline = 'middle' - - // Title with visual scale applied - const nameFontPx = Math.round(size * 0.08 * visualScale) // ~8% of canvas height, scaled - const distanceFontPx = Math.round(size * 0.06 * visualScale) // ~6% of canvas height, scaled - ctx.font = `bold ${nameFontPx}px mojangles` - ctx.lineWidth = Math.max(2, Math.round(3 * scale * visualScale)) - const nameY = Math.round(size * WAYPOINT_CONFIG.LAYOUT.NAME_Y) - - ctx.strokeStyle = 'black' - ctx.strokeText(id, centerX, nameY) - ctx.fillStyle = 'white' - ctx.fillText(id, centerX, nameY) - - // Distance with visual scale applied - ctx.font = `bold ${distanceFontPx}px mojangles` - ctx.lineWidth = Math.max(2, Math.round(2 * scale * visualScale)) - const distanceY = Math.round(size * WAYPOINT_CONFIG.LAYOUT.DISTANCE_Y) - - ctx.strokeStyle = 'black' - ctx.strokeText(distance, centerX, distanceY) - ctx.fillStyle = '#CCCCCC' - ctx.fillText(distance, centerX, distanceY) - - return canvas -} - -function createCombinedSprite (color: number, id: string, distance: string, depthTest: boolean, visualScale = 1): THREE.Sprite { - const canvas = drawCombinedCanvas(color, id, distance, visualScale) - const texture = new THREE.CanvasTexture(canvas) - texture.anisotropy = 1 - texture.magFilter = THREE.LinearFilter - texture.minFilter = THREE.LinearFilter - const material = new THREE.SpriteMaterial({ - map: texture, - transparent: true, - opacity: 1, - depthTest, - depthWrite: false, - }) - const sprite = new THREE.Sprite(material) - sprite.position.set(0, 0, 0) - return sprite -} - -export const WaypointHelpers = { - // World-scale constant size helper - computeWorldScale (distance: number, fixedReference = 10) { - return Math.max(0.0001, distance / fixedReference) - }, - // Screen-pixel constant size helper - computeScreenPixelScale ( - camera: THREE.PerspectiveCamera, - distance: number, - pixelSize: number, - viewportHeightPx: number - ) { - const vFovRad = camera.fov * Math.PI / 180 - const worldUnitsPerScreenHeightAtDist = Math.tan(vFovRad / 2) * 2 * distance - return worldUnitsPerScreenHeightAtDist * (pixelSize / viewportHeightPx) - } -} diff --git a/renderer/viewer/three/waypoints.ts b/renderer/viewer/three/waypoints.ts deleted file mode 100644 index 8d98b235f..000000000 --- a/renderer/viewer/three/waypoints.ts +++ /dev/null @@ -1,164 +0,0 @@ -import * as THREE from 'three' -import { WorldRendererThree } from './worldrendererThree' -import { createWaypointSprite, type WaypointSprite } from './waypointSprite' - -interface Waypoint { - id: string - x: number - y: number - z: number - minDistance: number - maxDistance: number - color: number - label?: string - sprite: WaypointSprite -} - -interface WaypointOptions { - color?: number - label?: string - minDistance?: number - maxDistance?: number - metadata?: any -} - -export class WaypointsRenderer { - private readonly waypoints = new Map() - private readonly waypointScene = new THREE.Scene() - - // Performance optimization: cache camera position to reduce update frequency - private readonly lastCameraPosition = new THREE.Vector3() - private lastUpdateTime = 0 - private readonly UPDATE_THROTTLE_MS = 16 // ~60fps max update rate - - constructor ( - private readonly worldRenderer: WorldRendererThree - ) { - } - - private updateWaypoints () { - const currentTime = performance.now() - const playerPos = this.worldRenderer.cameraObject.position - - // Performance optimization: throttle updates and check for significant camera movement - const cameraMovedSignificantly = this.lastCameraPosition.distanceTo(playerPos) > 0.5 - const timeToUpdate = currentTime - this.lastUpdateTime > this.UPDATE_THROTTLE_MS - - if (!cameraMovedSignificantly && !timeToUpdate) { - return // Skip update if camera hasn't moved much and not enough time passed - } - - this.lastCameraPosition.copy(playerPos) - this.lastUpdateTime = currentTime - - const sizeVec = this.worldRenderer.renderer.getSize(new THREE.Vector2()) - - for (const waypoint of this.waypoints.values()) { - const waypointPos = new THREE.Vector3(waypoint.x, waypoint.y, waypoint.z) - const distance = playerPos.distanceTo(waypointPos) - const visible = (!waypoint.minDistance || distance >= waypoint.minDistance) && - (waypoint.maxDistance === Infinity || distance <= waypoint.maxDistance) - - waypoint.sprite.setVisible(visible) - - if (visible) { - // Update position - waypoint.sprite.setPosition(waypoint.x, waypoint.y, waypoint.z) - // Ensure camera-based update each frame - waypoint.sprite.updateForCamera(this.worldRenderer.getCameraPosition(), this.worldRenderer.camera, sizeVec.width, sizeVec.height) - } - } - } - - render () { - if (this.waypoints.size === 0) return - - // Update waypoint scaling - this.updateWaypoints() - - // Render waypoints scene with the world camera - this.worldRenderer.renderer.render(this.waypointScene, this.worldRenderer.camera) - } - - // Removed sprite/label texture creation. Use utils/waypointSprite.ts - - addWaypoint ( - id: string, - x: number, - y: number, - z: number, - options: WaypointOptions = {} - ) { - // Remove existing waypoint if it exists - this.removeWaypoint(id) - - const color = options.color ?? 0xFF_00_00 - const { label, metadata } = options - const minDistance = options.minDistance ?? 0 - const maxDistance = options.maxDistance ?? Infinity - - const sprite = createWaypointSprite({ - position: new THREE.Vector3(x, y, z), - color, - label: (label || id), - metadata, - }) - sprite.enableOffscreenArrow(true) - sprite.setArrowParent(this.waypointScene) - - this.waypointScene.add(sprite.group) - - this.waypoints.set(id, { - id, x: x + 0.5, y: y + 0.5, z: z + 0.5, minDistance, maxDistance, - color, label, - sprite, - }) - } - - removeWaypoint (id: string) { - const waypoint = this.waypoints.get(id) - if (waypoint) { - this.waypointScene.remove(waypoint.sprite.group) - waypoint.sprite.dispose() - this.waypoints.delete(id) - } - } - - clear () { - for (const id of this.waypoints.keys()) { - this.removeWaypoint(id) - } - } - - testWaypoint () { - this.addWaypoint('Test Point', 0, 70, 0, { color: 0x00_FF_00, label: 'Test Point' }) - this.addWaypoint('Spawn', 0, 64, 0, { color: 0xFF_FF_00, label: 'Spawn' }) - this.addWaypoint('Far Point', 100, 70, 100, { color: 0x00_00_FF, label: 'Far Point' }) - this.addWaypoint('Far Point 2', 180, 170, 100, { color: 0x00_00_FF, label: 'Far Point 2' }) - this.addWaypoint('Far Point 3', 1000, 100, 1000, { color: 0x00_00_FF, label: 'Far Point 3' }) - } - - getWaypoint (id: string): Waypoint | undefined { - return this.waypoints.get(id) - } - - getAllWaypoints (): Waypoint[] { - return [...this.waypoints.values()] - } - - setWaypointColor (id: string, color: number) { - const waypoint = this.waypoints.get(id) - if (waypoint) { - waypoint.sprite.setColor(color) - waypoint.color = color - } - } - - setWaypointLabel (id: string, label?: string) { - const waypoint = this.waypoints.get(id) - if (waypoint) { - waypoint.label = label - waypoint.sprite.setLabel(label) - } - } -} diff --git a/renderer/viewer/three/world/cursorBlock.ts b/renderer/viewer/three/world/cursorBlock.ts deleted file mode 100644 index 4ebf06334..000000000 --- a/renderer/viewer/three/world/cursorBlock.ts +++ /dev/null @@ -1,170 +0,0 @@ -import * as THREE from 'three' -import { LineMaterial, LineSegmentsGeometry, Wireframe } from 'three-stdlib' -import { Vec3 } from 'vec3' -import { BlockShape, BlocksShapes } from 'renderer/viewer/lib/basePlayerState' -import { WorldRendererThree } from '../worldrendererThree' -import { loadThreeJsTextureFromUrl } from '../threeJsUtils' -import destroyStage0 from '../../../../assets/destroy_stage_0.png' -import destroyStage1 from '../../../../assets/destroy_stage_1.png' -import destroyStage2 from '../../../../assets/destroy_stage_2.png' -import destroyStage3 from '../../../../assets/destroy_stage_3.png' -import destroyStage4 from '../../../../assets/destroy_stage_4.png' -import destroyStage5 from '../../../../assets/destroy_stage_5.png' -import destroyStage6 from '../../../../assets/destroy_stage_6.png' -import destroyStage7 from '../../../../assets/destroy_stage_7.png' -import destroyStage8 from '../../../../assets/destroy_stage_8.png' -import destroyStage9 from '../../../../assets/destroy_stage_9.png' - -export class CursorBlock { - _cursorLinesHidden = false - get cursorLinesHidden () { - return this._cursorLinesHidden - } - set cursorLinesHidden (value: boolean) { - if (this.interactionLines) { - this.interactionLines.mesh.visible = !value - } - this._cursorLinesHidden = value - } - - cursorLineMaterial: LineMaterial - interactionLines: null | { blockPos: Vec3, mesh: THREE.Group, shapePositions: BlocksShapes | undefined } = null - prevColor: string | undefined - blockBreakMesh: THREE.Mesh - breakTextures: THREE.Texture[] = [] - - constructor (public readonly worldRenderer: WorldRendererThree) { - // Initialize break mesh and textures - const destroyStagesImages = [ - destroyStage0, destroyStage1, destroyStage2, destroyStage3, destroyStage4, - destroyStage5, destroyStage6, destroyStage7, destroyStage8, destroyStage9 - ] - - for (let i = 0; i < 10; i++) { - void loadThreeJsTextureFromUrl(destroyStagesImages[i]).then((texture) => { - texture.magFilter = THREE.NearestFilter - texture.minFilter = THREE.NearestFilter - this.breakTextures.push(texture) - }) - } - - const breakMaterial = new THREE.MeshBasicMaterial({ - transparent: true, - blending: THREE.MultiplyBlending, - alphaTest: 0.5, - }) - this.blockBreakMesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), breakMaterial) - this.blockBreakMesh.visible = false - this.blockBreakMesh.renderOrder = 999 - this.blockBreakMesh.name = 'blockBreakMesh' - this.worldRenderer.scene.add(this.blockBreakMesh) - - this.worldRenderer.onReactivePlayerStateUpdated('gameMode', () => { - this.updateLineMaterial() - }) - // todo figure out why otherwise fog from skybox breaks it - setTimeout(() => { - this.updateLineMaterial() - if (this.interactionLines) { - this.setHighlightCursorBlock(this.interactionLines.blockPos, this.interactionLines.shapePositions, true) - } - }) - } - - // Update functions - updateLineMaterial () { - const inCreative = this.worldRenderer.playerStateReactive.gameMode === 'creative' - const pixelRatio = this.worldRenderer.renderer.getPixelRatio() - - if (this.cursorLineMaterial) { - this.cursorLineMaterial.dispose() - } - this.cursorLineMaterial = new LineMaterial({ - color: (() => { - switch (this.worldRenderer.worldRendererConfig.highlightBlockColor) { - case 'blue': - return 0x40_80_ff - case 'classic': - return 0x00_00_00 - default: - return inCreative ? 0x40_80_ff : 0x00_00_00 - } - })(), - linewidth: Math.max(pixelRatio * 0.7, 1) * 2, - // dashed: true, - // dashSize: 5, - }) - this.prevColor = this.worldRenderer.worldRendererConfig.highlightBlockColor - } - - updateBreakAnimation (blockPosition: { x: number, y: number, z: number } | undefined, stage: number | null, mergedShape?: BlockShape) { - this.hideBreakAnimation() - if (stage === null || !blockPosition || !mergedShape) return - - const { position, width, height, depth } = mergedShape - this.blockBreakMesh.scale.set(width * 1.001, height * 1.001, depth * 1.001) - position.add(blockPosition) - this.blockBreakMesh.position.set(position.x, position.y, position.z) - this.blockBreakMesh.visible = true; - - (this.blockBreakMesh.material as THREE.MeshBasicMaterial).map = this.breakTextures[stage] ?? this.breakTextures.at(-1); - (this.blockBreakMesh.material as THREE.MeshBasicMaterial).needsUpdate = true - } - - hideBreakAnimation () { - if (this.blockBreakMesh) { - this.blockBreakMesh.visible = false - } - } - - updateDisplay () { - if (this.cursorLineMaterial) { - const { renderer } = this.worldRenderer - this.cursorLineMaterial.resolution.set(renderer.domElement.width, renderer.domElement.height) - this.cursorLineMaterial.dashOffset = performance.now() / 750 - } - } - - setHighlightCursorBlock (blockPos: Vec3 | null, shapePositions?: BlocksShapes, force = false): void { - if (blockPos && this.interactionLines && blockPos.equals(this.interactionLines.blockPos) && sameArray(shapePositions ?? [], this.interactionLines.shapePositions ?? []) && !force) { - return - } - if (this.interactionLines !== null) { - this.worldRenderer.scene.remove(this.interactionLines.mesh) - this.interactionLines = null - } - if (blockPos === null) { - return - } - - const group = new THREE.Group() - for (const { position, width, height, depth } of shapePositions ?? []) { - const scale = [1.0001 * width, 1.0001 * height, 1.0001 * depth] as const - const geometry = new THREE.BoxGeometry(...scale) - const lines = new LineSegmentsGeometry().fromEdgesGeometry(new THREE.EdgesGeometry(geometry)) - const wireframe = new Wireframe(lines, this.cursorLineMaterial) - const pos = blockPos.plus(position) - wireframe.position.set(pos.x, pos.y, pos.z) - wireframe.computeLineDistances() - group.add(wireframe) - } - this.worldRenderer.scene.add(group) - group.visible = !this.cursorLinesHidden - this.interactionLines = { blockPos, mesh: group, shapePositions } - } - - render () { - if (this.prevColor !== this.worldRenderer.worldRendererConfig.highlightBlockColor) { - this.updateLineMaterial() - } - this.updateDisplay() - } -} - -const sameArray = (a: any[], b: any[]) => { - if (a.length !== b.length) return false - for (const [i, element] of a.entries()) { - if (element !== b[i]) return false - } - return true -} diff --git a/renderer/viewer/three/world/vr.ts b/renderer/viewer/three/world/vr.ts deleted file mode 100644 index ecf1b299d..000000000 --- a/renderer/viewer/three/world/vr.ts +++ /dev/null @@ -1,257 +0,0 @@ -import { VRButton } from 'three/examples/jsm/webxr/VRButton.js' -import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js' -import { XRControllerModelFactory } from 'three/examples/jsm/webxr/XRControllerModelFactory.js' -import { buttonMap as standardButtonsMap } from 'contro-max/build/gamepad' -import * as THREE from 'three' -import { WorldRendererThree } from '../worldrendererThree' -import { DocumentRenderer } from '../documentRenderer' - -export async function initVR (worldRenderer: WorldRendererThree, documentRenderer: DocumentRenderer) { - if (!('xr' in navigator) || !worldRenderer.worldRendererConfig.vrSupport) return - const { renderer } = worldRenderer - - const isSupported = await checkVRSupport() - if (!isSupported) return - - enableVr() - - const vrButtonContainer = createVrButtonContainer(renderer) - const updateVrButtons = () => { - const newHidden = !worldRenderer.worldRendererConfig.vrSupport || !worldRenderer.worldRendererConfig.foreground - if (vrButtonContainer.hidden !== newHidden) { - vrButtonContainer.hidden = newHidden - } - } - - worldRenderer.onRender.push(updateVrButtons) - - function enableVr () { - renderer.xr.enabled = true - // renderer.xr.setReferenceSpaceType('local-floor') - worldRenderer.reactiveState.preventEscapeMenu = true - } - - function disableVr () { - renderer.xr.enabled = false - worldRenderer.cameraGroupVr = undefined - worldRenderer.reactiveState.preventEscapeMenu = false - worldRenderer.scene.remove(user) - vrButtonContainer.hidden = true - } - - function createVrButtonContainer (renderer) { - const container = document.createElement('div') - const vrButton = VRButton.createButton(renderer) - styleContainer(container) - - const closeButton = createCloseButton(container) - - container.appendChild(vrButton) - container.appendChild(closeButton) - document.body.appendChild(container) - - return container - } - - function styleContainer (container: HTMLElement) { - typedAssign(container.style, { - position: 'absolute', - bottom: '80px', - left: '0', - right: '0', - display: 'flex', - justifyContent: 'center', - zIndex: '8', - gap: '8px', - }) - } - - function createCloseButton (container: HTMLElement) { - const closeButton = document.createElement('button') - closeButton.textContent = 'X' - typedAssign(closeButton.style, { - padding: '0 12px', - color: 'white', - fontSize: '14px', - lineHeight: '20px', - cursor: 'pointer', - background: 'transparent', - border: '1px solid rgb(255, 255, 255)', - borderRadius: '4px', - opacity: '0.7', - }) - - closeButton.addEventListener('click', () => { - container.hidden = true - worldRenderer.worldRendererConfig.vrSupport = false - }) - - return closeButton - } - - - async function checkVRSupport () { - try { - const supported = await navigator.xr?.isSessionSupported('immersive-vr') - return supported && !!XRSession.prototype.updateRenderState - } catch (err) { - console.error('Error checking if VR is supported', err) - return false - } - } - - // hack for vr camera - const user = new THREE.Group() - user.name = 'vr-camera-container' - worldRenderer.scene.add(user) - const controllerModelFactory = new XRControllerModelFactory(new GLTFLoader()) - const controller1 = renderer.xr.getControllerGrip(0) - const controller2 = renderer.xr.getControllerGrip(1) - - // todo the logic written here can be hard to understand as it was designed to work in gamepad api emulation mode, will be refactored once there is a contro-max rewrite is done - const virtualGamepadIndex = 4 - let connectedVirtualGamepad - //@ts-expect-error - const manageXrInputSource = ({ gamepad, handedness = defaultHandedness }, defaultHandedness, removeAction = false) => { - if (handedness === 'right') { - const event: any = new Event(removeAction ? 'gamepaddisconnected' : 'gamepadconnected') // todo need to expose and use external gamepads api in contro-max instead - event.gamepad = removeAction ? connectedVirtualGamepad : { ...gamepad, mapping: 'standard', index: virtualGamepadIndex } - connectedVirtualGamepad = event.gamepad - window.dispatchEvent(event) - } - } - let hand1: any = controllerModelFactory.createControllerModel(controller1) - controller1.addEventListener('connected', (event) => { - hand1.xrInputSource = event.data - manageXrInputSource(event.data, 'left') - user.add(controller1) - }) - controller1.add(hand1) - let hand2: any = controllerModelFactory.createControllerModel(controller2) - controller2.addEventListener('connected', (event) => { - hand2.xrInputSource = event.data - manageXrInputSource(event.data, 'right') - user.add(controller2) - }) - controller2.add(hand2) - - controller1.addEventListener('disconnected', () => { - // don't handle removal of gamepads for now as is don't affect contro-max - manageXrInputSource(hand1.xrInputSource, 'left', true) - hand1.xrInputSource = undefined - }) - controller2.addEventListener('disconnected', () => { - manageXrInputSource(hand1.xrInputSource, 'right', true) - hand2.xrInputSource = undefined - }) - - const originalGetGamepads = navigator.getGamepads.bind(navigator) - // is it okay to patch this? - //@ts-expect-error - navigator.getGamepads = () => { - const originalGamepads = originalGetGamepads() - if (!hand1.xrInputSource || !hand2.xrInputSource) return originalGamepads - return [ - ...originalGamepads, - { - axes: remapAxes(hand2.xrInputSource.gamepad.axes, hand1.xrInputSource.gamepad.axes), - buttons: remapButtons(hand2.xrInputSource.gamepad.buttons, hand1.xrInputSource.gamepad.buttons), - connected: true, - mapping: 'standard', - id: '', - index: virtualGamepadIndex - } - ] - } - - let rotSnapReset = true - let yawOffset = 0 - renderer.setAnimationLoop(() => { - if (!renderer.xr.isPresenting) return - if (hand1.xrInputSource && hand2.xrInputSource) { - hand1.xAxis = hand1.xrInputSource.gamepad.axes[2] - hand1.yAxis = hand1.xrInputSource.gamepad.axes[3] - hand2.xAxis = hand2.xrInputSource.gamepad.axes[2] - hand2.yAxis = hand2.xrInputSource.gamepad.axes[3] - // hand2 should be right - if (hand1.xrInputSource.handedness === 'right') { - const tmp = hand2 - hand2 = hand1 - hand1 = tmp - } - } - - if (rotSnapReset) { - if (Math.abs(hand1.xAxis) > 0.8) { - yawOffset -= Math.PI / 4 * Math.sign(hand1.xAxis) - rotSnapReset = false - } - } else if (Math.abs(hand1.xAxis) < 0.1) { - rotSnapReset = true - } - - // appViewer.backend?.updateCamera(null, yawOffset, 0) - // worldRenderer.updateCamera(null, bot.entity.yaw, bot.entity.pitch) - - // todo restore this logic (need to preserve ability to move camera) - // const xrCamera = renderer.xr.getCamera() - // const d = xrCamera.getWorldDirection(new THREE.Vector3()) - // bot.entity.yaw = Math.atan2(-d.x, -d.z) - // bot.entity.pitch = Math.asin(d.y) - - documentRenderer.frameRender(false) - }) - renderer.xr.addEventListener('sessionstart', () => { - user.add(worldRenderer.camera) - worldRenderer.cameraGroupVr = user - }) - renderer.xr.addEventListener('sessionend', () => { - worldRenderer.cameraGroupVr = undefined - user.remove(worldRenderer.camera) - }) - - worldRenderer.abortController.signal.addEventListener('abort', disableVr) -} - -const xrStandardRightButtonsMap = [ - [0 /* trigger */, 'Right Trigger'], - [1 /* squeeze */, 'Right Bumper'], - // need to think of a way to support touchpad input - [3 /* Thumbstick Press */, 'Right Stick'], - [4 /* A */, 'A'], - [5 /* B */, 'B'], -] -const xrStandardLeftButtonsMap = [ - [0 /* trigger */, 'Left Trigger'], - [1 /* squeeze */, 'Left Bumper'], - // need to think of a way to support touchpad input - [3 /* Thumbstick Press */, 'Left Stick'], - [4 /* A */, 'X'], - [5 /* B */, 'Y'], -] -const remapButtons = (rightButtons: any[], leftButtons: any[]) => { - // return remapped buttons - const remapped = [] as string[] - const remapWithMap = (buttons, map) => { - for (const [index, standardName] of map) { - const standardMappingIndex = standardButtonsMap.findIndex((aliases) => aliases.find(alias => standardName === alias)) - remapped[standardMappingIndex] = buttons[index] - } - } - remapWithMap(rightButtons, xrStandardRightButtonsMap) - remapWithMap(leftButtons, xrStandardLeftButtonsMap) - return remapped -} -const remapAxes = (axesRight, axesLeft) => { - // 0, 1 are reserved for touch - return [ - axesLeft[2], - axesLeft[3], - axesRight[2], - axesRight[3] - ] -} - -function typedAssign> (target: T, source: Partial) { - Object.assign(target, source) -} diff --git a/renderer/viewer/three/worldGeometryExport.ts b/renderer/viewer/three/worldGeometryExport.ts deleted file mode 100644 index 90eef8a46..000000000 --- a/renderer/viewer/three/worldGeometryExport.ts +++ /dev/null @@ -1,190 +0,0 @@ -import * as THREE from 'three' -import type { WorldRendererThree } from './worldrendererThree' - -// Format for exported world geometry -export interface ExportedWorldGeometry { - version: string - exportedAt: string - camera: { - position: { x: number, y: number, z: number } - rotation: { pitch: number, yaw: number } - } - sections: ExportedSection[] - textureAtlasDataUrl?: string -} - -export interface ExportedSection { - key: string - position: { x: number, y: number, z: number } - geometry: { - positions: number[] - normals: number[] - colors: number[] - uvs: number[] - indices: number[] - } -} - -/** - * Export world geometry to a downloadable file - */ -export function exportWorldGeometry ( - worldRenderer: WorldRendererThree, - cameraPosition: { x: number, y: number, z: number }, - cameraRotation: { pitch: number, yaw: number }, - includeTexture = false -): ExportedWorldGeometry { - const sections: ExportedSection[] = [] - - for (const [key, sectionObject] of Object.entries(worldRenderer.sectionObjects)) { - const mesh = sectionObject.children.find(child => child.name === 'mesh') as THREE.Mesh | undefined - if (!mesh?.geometry) continue - - const { geometry } = mesh - const positionAttr = geometry.getAttribute('position') as THREE.BufferAttribute - const normalAttr = geometry.getAttribute('normal') as THREE.BufferAttribute - const colorAttr = geometry.getAttribute('color') as THREE.BufferAttribute - const uvAttr = geometry.getAttribute('uv') as THREE.BufferAttribute - const indexAttr = geometry.index! - - if (!positionAttr || !indexAttr) continue - - sections.push({ - key, - position: { - x: mesh.position.x, - y: mesh.position.y, - z: mesh.position.z - }, - geometry: { - positions: [...positionAttr.array], - normals: normalAttr ? [...normalAttr.array] : [], - colors: colorAttr ? [...colorAttr.array] : [], - uvs: uvAttr ? [...uvAttr.array] : [], - indices: [...indexAttr.array] - } - }) - } - - const exportData: ExportedWorldGeometry = { - version: worldRenderer.version ?? 'unknown', - exportedAt: new Date().toISOString(), - camera: { - position: cameraPosition, - rotation: cameraRotation - }, - sections - } - - // Optionally include texture atlas as data URL - if (includeTexture && worldRenderer.material.map) { - const canvas = document.createElement('canvas') - const texture = worldRenderer.material.map - const { image } = texture - if (image) { - canvas.width = image.width - canvas.height = image.height - const ctx = canvas.getContext('2d')! - ctx.drawImage(image, 0, 0) - exportData.textureAtlasDataUrl = canvas.toDataURL('image/png') - } - } - - return exportData -} - -/** - * Download world geometry as JSON file - */ -export function downloadWorldGeometry ( - worldRenderer: WorldRendererThree, - cameraPosition: { x: number, y: number, z: number }, - cameraRotation: { pitch: number, yaw: number }, - filename = 'world-geometry.json', - includeTexture = false -) { - const exportData = exportWorldGeometry(worldRenderer, cameraPosition, cameraRotation, includeTexture) - const json = JSON.stringify(exportData) - const blob = new Blob([json], { type: 'application/json' }) - const url = URL.createObjectURL(blob) - - const a = document.createElement('a') - a.href = url - a.download = filename - a.click() - - URL.revokeObjectURL(url) -} - -/** - * Load world geometry from URL - */ -export async function loadWorldGeometryFromUrl (url: string): Promise { - const response = await fetch(url) - if (!response.ok) { - throw new Error(`Failed to fetch world geometry: ${response.statusText}`) - } - return response.json() -} - -/** - * Recreate THREE.js meshes from exported geometry - * Returns an array of mesh groups that can be added to a scene - */ -export function createMeshesFromExport ( - exportData: ExportedWorldGeometry, - material: THREE.Material -): THREE.Group[] { - const groups: THREE.Group[] = [] - - for (const section of exportData.sections) { - const geometry = new THREE.BufferGeometry() - - geometry.setAttribute('position', new THREE.Float32BufferAttribute(section.geometry.positions, 3)) - if (section.geometry.normals.length) { - geometry.setAttribute('normal', new THREE.Float32BufferAttribute(section.geometry.normals, 3)) - } - if (section.geometry.colors.length) { - geometry.setAttribute('color', new THREE.Float32BufferAttribute(section.geometry.colors, 3)) - } - if (section.geometry.uvs.length) { - geometry.setAttribute('uv', new THREE.Float32BufferAttribute(section.geometry.uvs, 2)) - } - - // Use appropriate index type based on vertex count - const maxIndex = Math.max(...section.geometry.indices) - const IndexArrayType = maxIndex > 65_535 ? Uint32Array : Uint16Array - geometry.setIndex(new THREE.BufferAttribute(new IndexArrayType(section.geometry.indices), 1)) - - const mesh = new THREE.Mesh(geometry, material) - mesh.position.set(section.position.x, section.position.y, section.position.z) - mesh.name = 'mesh' - - const group = new THREE.Group() - group.name = 'chunk' - group.add(mesh) - - groups.push(group) - } - - return groups -} - -/** - * Load texture from data URL and create THREE.js texture - */ -export async function loadTextureFromDataUrl (dataUrl: string): Promise { - return new Promise((resolve, reject) => { - const image = new Image() - image.onload = () => { - const texture = new THREE.Texture(image) - texture.magFilter = THREE.NearestFilter - texture.minFilter = THREE.NearestFilter - texture.needsUpdate = true - texture.flipY = false - resolve(texture) - } - image.onerror = reject - image.src = dataUrl - }) -} diff --git a/renderer/viewer/three/worldrendererThree.ts b/renderer/viewer/three/worldrendererThree.ts deleted file mode 100644 index 258d24666..000000000 --- a/renderer/viewer/three/worldrendererThree.ts +++ /dev/null @@ -1,1202 +0,0 @@ -import * as THREE from 'three' -import { Vec3 } from 'vec3' -import nbt from 'prismarine-nbt' -import PrismarineChatLoader from 'prismarine-chat' -import * as tweenJs from '@tweenjs/tween.js' -import { Biome } from 'minecraft-data' -import { renderSign } from '../sign-renderer' -import { DisplayWorldOptions, GraphicsInitOptions } from '../../../src/appViewer' -import { chunkPos, sectionPos } from '../lib/simpleUtils' -import { WorldRendererCommon } from '../lib/worldrendererCommon' -import { addNewStat, MC_RENDERER_DEBUG_OVERLAY_CLASS } from '../lib/ui/newStats' -import { MesherGeometryOutput } from '../lib/mesher/shared' -import { ItemSpecificContextProperties } from '../lib/basePlayerState' -import { setBlockPosition } from '../lib/mesher/standaloneRenderer' -import { getBannerTexture, createBannerMesh, releaseBannerTexture } from './bannerRenderer' -import { getMyHand } from './hand' -import HoldingBlock from './holdingBlock' -import { getMesh } from './entity/EntityMesh' -import { armorModel } from './entity/armorModels' -import { disposeObject, loadThreeJsTextureFromBitmap } from './threeJsUtils' -import { CursorBlock } from './world/cursorBlock' -import { getItemUv } from './appShared' -import { Entities } from './entities' -import { ThreeJsSound } from './threeJsSound' -import { CameraShake } from './cameraShake' -import { ThreeJsMedia } from './threeJsMedia' -import { Fountain } from './threeJsParticles' -import { WaypointsRenderer } from './waypoints' -import { DEFAULT_TEMPERATURE, SkyboxRenderer } from './skyboxRenderer' -import { FireworksManager } from './fireworks' -import { downloadWorldGeometry } from './worldGeometryExport' - -type SectionKey = string - -export class WorldRendererThree extends WorldRendererCommon { - outputFormat = 'threeJs' as const - sectionObjects: Record = {} - chunkTextures = new Map() - signsCache = new Map() - starField: StarField - cameraSectionPos: Vec3 = new Vec3(0, 0, 0) - holdingBlock: HoldingBlock - holdingBlockLeft: HoldingBlock - scene = new THREE.Scene() - ambientLight = new THREE.AmbientLight(0xcc_cc_cc) - directionalLight = new THREE.DirectionalLight(0xff_ff_ff, 0.5) - entities = new Entities(this) - cameraGroupVr?: THREE.Object3D - material = new THREE.MeshBasicMaterial({ vertexColors: true, transparent: true, alphaTest: 0.1 }) - itemsTexture: THREE.Texture - cursorBlock: CursorBlock - onRender: Array<() => void> = [] - cameraShake: CameraShake - cameraContainer: THREE.Object3D - media: ThreeJsMedia - waitingChunksToDisplay = {} as { [chunkKey: string]: SectionKey[] } - waypoints: WaypointsRenderer - camera: THREE.PerspectiveCamera - renderTimeAvg = 0 - sectionsOffsetsAnimations = {} as { - [chunkKey: string]: { - time: number, - // also specifies direction - speedX: number, - speedY: number, - speedZ: number, - - currentOffsetX: number, - currentOffsetY: number, - currentOffsetZ: number, - - limitX?: number, - limitY?: number, - limitZ?: number, - } - } - fountains: Fountain[] = [] - DEBUG_RAYCAST = false - skyboxRenderer: SkyboxRenderer - fireworks: FireworksManager - - private currentPosTween?: tweenJs.Tween - private currentRotTween?: tweenJs.Tween<{ pitch: number, yaw: number }> - - get tilesRendered () { - return Object.values(this.sectionObjects).reduce((acc, obj) => acc + (obj as any).tilesCount, 0) - } - - get blocksRendered () { - return Object.values(this.sectionObjects).reduce((acc, obj) => acc + (obj as any).blocksCount, 0) - } - - constructor (public renderer: THREE.WebGLRenderer, public initOptions: GraphicsInitOptions, public displayOptions: DisplayWorldOptions) { - if (!initOptions.resourcesManager) throw new Error('resourcesManager is required') - super(initOptions.resourcesManager, displayOptions, initOptions) - - this.renderer = renderer - displayOptions.rendererState.renderer = WorldRendererThree.getRendererInfo(renderer) ?? '...' - this.starField = new StarField(this) - this.cursorBlock = new CursorBlock(this) - this.holdingBlock = new HoldingBlock(this) - this.holdingBlockLeft = new HoldingBlock(this, true) - - // Initialize skybox renderer - this.skyboxRenderer = new SkyboxRenderer(this.scene, this.worldRendererConfig.defaultSkybox, null) - void this.skyboxRenderer.init() - - this.addDebugOverlay() - this.resetScene() - void this.init() - - this.soundSystem = new ThreeJsSound(this) - this.cameraShake = new CameraShake(this, this.onRender) - this.media = new ThreeJsMedia(this) - this.waypoints = new WaypointsRenderer(this) - this.fireworks = new FireworksManager(this.scene) - - // this.fountain = new Fountain(this.scene, this.scene, { - // position: new THREE.Vector3(0, 10, 0), - // }) - - this.renderUpdateEmitter.on('chunkFinished', (chunkKey: string) => { - this.finishChunk(chunkKey) - }) - this.worldSwitchActions() - } - - get cameraObject () { - return this.cameraGroupVr ?? this.cameraContainer - } - - worldSwitchActions () { - this.onWorldSwitched.push(() => { - // clear custom blocks - this.protocolCustomBlocks.clear() - // Reset section animations - this.sectionsOffsetsAnimations = {} - // Clear waypoints - this.waypoints.clear() - // Clear fireworks - this.fireworks.clear() - }) - } - - downloadWorldGeometry () { - downloadWorldGeometry(this, this.cameraObject.position, this.cameraShake.getBaseRotation(), 'world-geometry.json') - } - - updateEntity (e, isPosUpdate = false) { - const overrides = { - rotation: { - head: { - x: e.headPitch ?? e.pitch, - y: e.headYaw, - z: 0 - } - } - } - if (isPosUpdate) { - this.entities.updateEntityPosition(e, false, overrides) - } else { - this.entities.update(e, overrides) - } - } - - updatePlayerEntity (e: any) { - this.entities.handlePlayerEntity(e) - } - - resetScene () { - this.scene.matrixAutoUpdate = false // for perf - this.scene.background = new THREE.Color(this.initOptions.config.sceneBackground) - this.scene.add(this.ambientLight) - this.directionalLight.position.set(1, 1, 0.5).normalize() - this.directionalLight.castShadow = true - this.scene.add(this.directionalLight) - - const size = this.renderer.getSize(new THREE.Vector2()) - this.camera = new THREE.PerspectiveCamera(75, size.x / size.y, 0.1, 1000) - this.cameraContainer = new THREE.Object3D() - this.cameraContainer.add(this.camera) - this.scene.add(this.cameraContainer) - } - - override watchReactivePlayerState () { - super.watchReactivePlayerState() - this.onReactivePlayerStateUpdated('inWater', (value) => { - this.skyboxRenderer.updateWaterState(value, this.playerStateReactive.waterBreathing) - }) - this.onReactivePlayerStateUpdated('waterBreathing', (value) => { - this.skyboxRenderer.updateWaterState(this.playerStateReactive.inWater, value) - }) - this.onReactivePlayerStateUpdated('ambientLight', (value) => { - if (!value) return - this.ambientLight.intensity = value - }) - this.onReactivePlayerStateUpdated('directionalLight', (value) => { - if (!value) return - this.directionalLight.intensity = value - }) - this.onReactivePlayerStateUpdated('lookingAtBlock', (value) => { - this.cursorBlock.setHighlightCursorBlock(value ? new Vec3(value.x, value.y, value.z) : null, value?.shapes) - }) - this.onReactivePlayerStateUpdated('diggingBlock', (value) => { - this.cursorBlock.updateBreakAnimation(value ? { x: value.x, y: value.y, z: value.z } : undefined, value?.stage ?? null, value?.mergedShape) - }) - this.onReactivePlayerStateUpdated('perspective', (value) => { - // Update camera perspective when it changes - const vecPos = new Vec3(this.cameraObject.position.x, this.cameraObject.position.y, this.cameraObject.position.z) - this.updateCamera(vecPos, this.cameraShake.getBaseRotation().yaw, this.cameraShake.getBaseRotation().pitch) - // todo also update camera when block within camera was changed - }) - } - - override watchReactiveConfig () { - super.watchReactiveConfig() - this.onReactiveConfigUpdated('showChunkBorders', (value) => { - this.updateShowChunksBorder(value) - }) - this.onReactiveConfigUpdated('defaultSkybox', (value) => { - this.skyboxRenderer.updateDefaultSkybox(value) - }) - } - - changeHandSwingingState (isAnimationPlaying: boolean, isLeft = false) { - const holdingBlock = isLeft ? this.holdingBlockLeft : this.holdingBlock - if (isAnimationPlaying) { - holdingBlock.startSwing() - } else { - holdingBlock.stopSwing() - } - } - - async updateAssetsData (): Promise { - const resources = this.resourcesManager.currentResources - - const oldTexture = this.material.map - const oldItemsTexture = this.itemsTexture - - const texture = loadThreeJsTextureFromBitmap(resources.blocksAtlasImage) - texture.needsUpdate = true - texture.flipY = false - this.material.map = texture - - const itemsTexture = loadThreeJsTextureFromBitmap(resources.itemsAtlasImage) - itemsTexture.needsUpdate = true - itemsTexture.flipY = false - this.itemsTexture = itemsTexture - - if (oldTexture) { - oldTexture.dispose() - } - if (oldItemsTexture) { - oldItemsTexture.dispose() - } - - await super.updateAssetsData() - this.onAllTexturesLoaded() - if (Object.keys(this.loadedChunks).length > 0) { - console.log('rerendering chunks because of texture update') - this.rerenderAllChunks() - } - } - - onAllTexturesLoaded () { - this.holdingBlock.ready = true - this.holdingBlock.updateItem() - this.holdingBlockLeft.ready = true - this.holdingBlockLeft.updateItem() - } - - changeBackgroundColor (color: [number, number, number]): void { - this.scene.background = new THREE.Color(color[0], color[1], color[2]) - } - changeCardinalLight (cardinalLight: string): void { - this.worldRendererConfig.cardinalLight = cardinalLight - } - - timeUpdated (newTime: number): void { - const nightTime = 13_500 - const morningStart = 23_000 - const displayStars = newTime > nightTime && newTime < morningStart - if (displayStars) { - this.starField.addToScene() - } else { - this.starField.remove() - } - - this.skyboxRenderer.updateTime(newTime) - } - - biomeUpdated (biome: Biome): void { - if (biome?.temperature !== undefined) { - this.skyboxRenderer.updateTemperature(biome.temperature) - } - } - - biomeReset (): void { - // Reset to default temperature when biome is unknown - this.skyboxRenderer.updateTemperature(DEFAULT_TEMPERATURE) - } - - getItemRenderData (item: Record, specificProps: ItemSpecificContextProperties) { - return getItemUv(item, specificProps, this.resourcesManager, this.playerStateReactive) - } - - async demoModel () { - //@ts-expect-error - const pos = cursorBlockRel(0, 1, 0).position - - const mesh = (await getMyHand())! - // mesh.rotation.y = THREE.MathUtils.degToRad(90) - setBlockPosition(mesh, pos) - const helper = new THREE.BoxHelper(mesh, 0xff_ff_00) - mesh.add(helper) - this.scene.add(mesh) - } - - demoItem () { - //@ts-expect-error - const pos = cursorBlockRel(0, 1, 0).position - const { mesh } = this.entities.getItemMesh({ - itemId: 541, - }, {})! - mesh.position.set(pos.x + 0.5, pos.y + 0.5, pos.z + 0.5) - // mesh.scale.set(0.5, 0.5, 0.5) - const helper = new THREE.BoxHelper(mesh, 0xff_ff_00) - mesh.add(helper) - this.scene.add(mesh) - } - - debugOverlayAdded = false - addDebugOverlay () { - if (this.debugOverlayAdded) return - this.debugOverlayAdded = true - const pane = addNewStat('debug-overlay', 80, 0, undefined, { className: MC_RENDERER_DEBUG_OVERLAY_CLASS }) - setInterval(() => { - pane.setVisibility(this.displayAdvancedStats) - if (this.displayAdvancedStats) { - const formatFull = (num: number) => new Intl.NumberFormat('en-US', {}).format(num) - const formatCompact = (num: number) => new Intl.NumberFormat('en-US', { notation: 'compact', maximumFractionDigits: 1 }).format(num) - const text = `TE: ${formatFull(this.renderer.info.memory.textures)} ` - + `F: ${formatCompact(this.tilesRendered)} ` - + `B: ${formatCompact(this.blocksRendered)}` - pane.updateText(text) - this.backendInfoReport = text - } - }, 200) - } - - /** - * Optionally update data that are depedendent on the viewer position - */ - updatePosDataChunk (key: string) { - const [x, y, z] = key.split(',').map(x => Math.floor(+x / 16)) - // sum of distances: x + y + z - const chunkDistance = Math.abs(x - this.cameraSectionPos.x) + Math.abs(y - this.cameraSectionPos.y) + Math.abs(z - this.cameraSectionPos.z) - const section = this.sectionObjects[key].children.find(child => child.name === 'mesh')! - section.renderOrder = 500 - chunkDistance - } - - override updateViewerPosition (pos: Vec3): void { - this.viewerChunkPosition = pos - } - - cameraSectionPositionUpdate () { - // eslint-disable-next-line guard-for-in - for (const key in this.sectionObjects) { - const value = this.sectionObjects[key] - if (!value) continue - this.updatePosDataChunk(key) - } - } - - getDir (current: number, origin: number) { - if (current === origin) return 0 - return current < origin ? 1 : -1 - } - - finishChunk (chunkKey: string) { - for (const sectionKey of this.waitingChunksToDisplay[chunkKey] ?? []) { - this.sectionObjects[sectionKey].visible = true - } - delete this.waitingChunksToDisplay[chunkKey] - } - - // debugRecomputedDeletedObjects = 0 - handleWorkerMessage (data: { geometry: MesherGeometryOutput, key, type }): void { - if (data.type !== 'geometry') return - let object: THREE.Object3D = this.sectionObjects[data.key] - if (object) { - // Cleanup banner textures before disposing - object.traverse((child) => { - if ((child as any).bannerTexture) { - releaseBannerTexture((child as any).bannerTexture) - } - }) - this.scene.remove(object) - disposeObject(object) - delete this.sectionObjects[data.key] - } - - const chunkCoords = data.key.split(',') - if (!this.loadedChunks[chunkCoords[0] + ',' + chunkCoords[2]] || !data.geometry.positions.length || !this.active) return - - // if (object) { - // this.debugRecomputedDeletedObjects++ - // } - - const geometry = new THREE.BufferGeometry() - geometry.setAttribute('position', new THREE.BufferAttribute(data.geometry.positions, 3)) - geometry.setAttribute('normal', new THREE.BufferAttribute(data.geometry.normals, 3)) - geometry.setAttribute('color', new THREE.BufferAttribute(data.geometry.colors, 3)) - geometry.setAttribute('uv', new THREE.BufferAttribute(data.geometry.uvs, 2)) - geometry.index = new THREE.BufferAttribute(data.geometry.indices as Uint32Array | Uint16Array, 1) - - const mesh = new THREE.Mesh(geometry, this.material) - mesh.position.set(data.geometry.sx, data.geometry.sy, data.geometry.sz) - mesh.name = 'mesh' - object = new THREE.Group() - object.add(mesh) - // mesh with static dimensions: 16x16x16 - const staticChunkMesh = new THREE.Mesh(new THREE.BoxGeometry(16, 16, 16), new THREE.MeshBasicMaterial({ color: 0x00_00_00, transparent: true, opacity: 0 })) - staticChunkMesh.position.set(data.geometry.sx, data.geometry.sy, data.geometry.sz) - const boxHelper = new THREE.BoxHelper(staticChunkMesh, 0xff_ff_00) - boxHelper.name = 'helper' - object.add(boxHelper) - object.name = 'chunk'; - (object as any).tilesCount = data.geometry.positions.length / 3 / 4; - (object as any).blocksCount = data.geometry.blocksCount - if (!this.displayOptions.inWorldRenderingConfig.showChunkBorders) { - boxHelper.visible = false - } - // should not compute it once - if (Object.keys(data.geometry.signs).length) { - for (const [posKey, { isWall, isHanging, rotation }] of Object.entries(data.geometry.signs)) { - const signBlockEntity = this.blockEntities[posKey] - if (!signBlockEntity) continue - const [x, y, z] = posKey.split(',') - const sign = this.renderSign(new Vec3(+x, +y, +z), rotation, isWall, isHanging, nbt.simplify(signBlockEntity)) - if (!sign) continue - object.add(sign) - } - } - if (Object.keys(data.geometry.heads).length) { - for (const [posKey, { isWall, rotation }] of Object.entries(data.geometry.heads)) { - const headBlockEntity = this.blockEntities[posKey] - if (!headBlockEntity) continue - const [x, y, z] = posKey.split(',') - const head = this.renderHead(new Vec3(+x, +y, +z), rotation, isWall, nbt.simplify(headBlockEntity)) - if (!head) continue - object.add(head) - } - } - if (Object.keys(data.geometry.banners).length) { - for (const [posKey, { isWall, rotation, blockName }] of Object.entries(data.geometry.banners)) { - const bannerBlockEntity = this.blockEntities[posKey] - if (!bannerBlockEntity) continue - const [x, y, z] = posKey.split(',') - const bannerTexture = getBannerTexture(this, blockName, nbt.simplify(bannerBlockEntity)) - if (!bannerTexture) continue - const banner = createBannerMesh(new Vec3(+x, +y, +z), rotation, isWall, bannerTexture) - object.add(banner) - } - } - this.sectionObjects[data.key] = object - // Store section key on object for easier lookup - ;(object as any).sectionKey = data.key - if (this.displayOptions.inWorldRenderingConfig._renderByChunks) { - object.visible = false - const chunkKey = `${chunkCoords[0]},${chunkCoords[2]}` - this.waitingChunksToDisplay[chunkKey] ??= [] - this.waitingChunksToDisplay[chunkKey].push(data.key) - if (this.finishedChunks[chunkKey]) { - // todo it might happen even when it was not an update - this.finishChunk(chunkKey) - } - } - - this.updatePosDataChunk(data.key) - object.matrixAutoUpdate = false - mesh.onAfterRender = (renderer, scene, camera, geometry, material, group) => { - // mesh.matrixAutoUpdate = false - } - - this.scene.add(object) - } - - getSignTexture (position: Vec3, blockEntity, isHanging, backSide = false) { - const chunk = chunkPos(position) - let textures = this.chunkTextures.get(`${chunk[0]},${chunk[1]}`) - if (!textures) { - textures = {} - this.chunkTextures.set(`${chunk[0]},${chunk[1]}`, textures) - } - const texturekey = `${position.x},${position.y},${position.z}` - // todo investigate bug and remove this so don't need to clean in section dirty - if (textures[texturekey]) return textures[texturekey] - - const PrismarineChat = PrismarineChatLoader(this.version) - const canvas = renderSign(blockEntity, isHanging, PrismarineChat) - if (!canvas) return - const tex = new THREE.Texture(canvas) - tex.magFilter = THREE.NearestFilter - tex.minFilter = THREE.NearestFilter - tex.needsUpdate = true - textures[texturekey] = tex - return tex - } - - getCameraPosition () { - const worldPos = new THREE.Vector3() - this.camera.getWorldPosition(worldPos) - return worldPos - } - - getSectionCameraPosition () { - const pos = this.getCameraPosition() - return new Vec3( - Math.floor(pos.x / 16), - Math.floor(pos.y / 16), - Math.floor(pos.z / 16) - ) - } - - updateCameraSectionPos () { - const newSectionPos = this.getSectionCameraPosition() - if (!this.cameraSectionPos.equals(newSectionPos)) { - this.cameraSectionPos = newSectionPos - this.cameraSectionPositionUpdate() - } - } - - setFirstPersonCamera (pos: Vec3 | null, yaw: number, pitch: number) { - const yOffset = this.playerStateReactive.eyeHeight - - this.updateCamera(pos?.offset(0, yOffset, 0) ?? null, yaw, pitch) - // this.media.tryIntersectMedia() - this.updateCameraSectionPos() - } - - getThirdPersonCamera (pos: THREE.Vector3 | null, yaw: number, pitch: number) { - pos ??= this.cameraObject.position - - // Calculate camera offset based on perspective - const isBack = this.playerStateReactive.perspective === 'third_person_back' - const distance = 4 // Default third person distance - - // Calculate direction vector using proper world orientation - // We need to get the camera's current look direction and use that for positioning - - // Create a direction vector that represents where the camera is looking - // This matches the Three.js camera coordinate system - const direction = new THREE.Vector3(0, 0, -1) // Forward direction in camera space - - // Apply the same rotation that's applied to the camera container - const pitchQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), pitch) - const yawQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), yaw) - const finalQuat = new THREE.Quaternion().multiplyQuaternions(yawQuat, pitchQuat) - - // Transform the direction vector by the camera's rotation - direction.applyQuaternion(finalQuat) - - // For back view, we want the camera behind the player (opposite to view direction) - // For front view, we want the camera in front of the player (same as view direction) - if (isBack) { - direction.multiplyScalar(-1) - } - - // Create debug visualization if advanced stats are enabled - if (this.DEBUG_RAYCAST) { - this.debugRaycast(pos, direction, distance) - } - - // Perform raycast to avoid camera going through blocks - const raycaster = new THREE.Raycaster() - raycaster.set(pos, direction) - raycaster.far = distance // Limit raycast distance - - // Filter to only nearby chunks for performance - const nearbyChunks = Object.values(this.sectionObjects) - .filter(obj => obj.name === 'chunk' && obj.visible) - .filter(obj => { - // Get the mesh child which has the actual geometry - const mesh = obj.children.find(child => child.name === 'mesh') - if (!mesh) return false - - // Check distance from player position to chunk - const chunkWorldPos = new THREE.Vector3() - mesh.getWorldPosition(chunkWorldPos) - const distance = pos.distanceTo(chunkWorldPos) - return distance < 80 // Only check chunks within 80 blocks - }) - - // Get all mesh children for raycasting - const meshes: THREE.Object3D[] = [] - for (const chunk of nearbyChunks) { - const mesh = chunk.children.find(child => child.name === 'mesh') - if (mesh) meshes.push(mesh) - } - - const intersects = raycaster.intersectObjects(meshes, false) - - let finalDistance = distance - if (intersects.length > 0) { - // Use intersection distance minus a small offset to prevent clipping - finalDistance = Math.max(0.5, intersects[0].distance - 0.2) - } - - const finalPos = new Vec3( - pos.x + direction.x * finalDistance, - pos.y + direction.y * finalDistance, - pos.z + direction.z * finalDistance - ) - - return finalPos - } - - private debugRaycastHelper?: THREE.ArrowHelper - private debugHitPoint?: THREE.Mesh - - private debugRaycast (pos: THREE.Vector3, direction: THREE.Vector3, distance: number) { - // Remove existing debug objects - if (this.debugRaycastHelper) { - this.scene.remove(this.debugRaycastHelper) - this.debugRaycastHelper = undefined - } - if (this.debugHitPoint) { - this.scene.remove(this.debugHitPoint) - this.debugHitPoint = undefined - } - - // Create raycast arrow - this.debugRaycastHelper = new THREE.ArrowHelper( - direction.clone().normalize(), - pos, - distance, - 0xff_00_00, // Red color - distance * 0.1, - distance * 0.05 - ) - this.scene.add(this.debugRaycastHelper) - - // Create hit point indicator - const hitGeometry = new THREE.SphereGeometry(0.2, 8, 8) - const hitMaterial = new THREE.MeshBasicMaterial({ color: 0x00_ff_00 }) - this.debugHitPoint = new THREE.Mesh(hitGeometry, hitMaterial) - this.debugHitPoint.position.copy(pos).add(direction.clone().multiplyScalar(distance)) - this.scene.add(this.debugHitPoint) - } - - prevFramePerspective = null as string | null - - updateCamera (pos: Vec3 | null, yaw: number, pitch: number): void { - // if (this.freeFlyMode) { - // pos = this.freeFlyState.position - // pitch = this.freeFlyState.pitch - // yaw = this.freeFlyState.yaw - // } - - if (pos) { - if (this.renderer.xr.isPresenting) { - pos.y -= this.camera.position.y // Fix Y position of camera in world - } - - this.currentPosTween?.stop() - // Use instant camera updates (0 delay) in playground mode when camera controls are enabled - const tweenDelay = this.displayOptions.inWorldRenderingConfig.instantCameraUpdate - ? 0 - : (this.playerStateUtils.isSpectatingEntity() ? 150 : 50) - this.currentPosTween = new tweenJs.Tween(this.cameraObject.position).to({ x: pos.x, y: pos.y, z: pos.z }, tweenDelay).start() - // this.freeFlyState.position = pos - } - - if (this.playerStateUtils.isSpectatingEntity()) { - const rotation = this.cameraShake.getBaseRotation() - // wrap in the correct direction - let yawOffset = 0 - const halfPi = Math.PI / 2 - if (rotation.yaw < halfPi && yaw > Math.PI + halfPi) { - yawOffset = -Math.PI * 2 - } else if (yaw < halfPi && rotation.yaw > Math.PI + halfPi) { - yawOffset = Math.PI * 2 - } - this.currentRotTween?.stop() - this.currentRotTween = new tweenJs.Tween(rotation).to({ pitch, yaw: yaw + yawOffset }, 100) - .onUpdate(params => this.cameraShake.setBaseRotation(params.pitch, params.yaw - yawOffset)).start() - } else { - this.currentRotTween?.stop() - this.cameraShake.setBaseRotation(pitch, yaw) - - const { perspective } = this.playerStateReactive - if (perspective === 'third_person_back' || perspective === 'third_person_front') { - // Use getThirdPersonCamera for proper raycasting with max distance of 4 - const currentCameraPos = this.cameraObject.position - const thirdPersonPos = this.getThirdPersonCamera( - new THREE.Vector3(currentCameraPos.x, currentCameraPos.y, currentCameraPos.z), - yaw, - pitch - ) - - const distance = currentCameraPos.distanceTo(new THREE.Vector3(thirdPersonPos.x, thirdPersonPos.y, thirdPersonPos.z)) - // Apply Z offset based on perspective and calculated distance - const zOffset = perspective === 'third_person_back' ? distance : -distance - this.camera.position.set(0, 0, zOffset) - - if (perspective === 'third_person_front') { - // Flip camera view 180 degrees around Y axis for front view - this.camera.rotation.set(0, Math.PI, 0) - } else { - this.camera.rotation.set(0, 0, 0) - } - } else { - this.camera.position.set(0, 0, 0) - this.camera.rotation.set(0, 0, 0) - - // remove any debug raycasting - if (this.debugRaycastHelper) { - this.scene.remove(this.debugRaycastHelper) - this.debugRaycastHelper = undefined - } - if (this.debugHitPoint) { - this.scene.remove(this.debugHitPoint) - this.debugHitPoint = undefined - } - } - } - - this.updateCameraSectionPos() - } - - debugChunksVisibilityOverride () { - const { chunksRenderAboveOverride, chunksRenderBelowOverride, chunksRenderDistanceOverride, chunksRenderAboveEnabled, chunksRenderBelowEnabled, chunksRenderDistanceEnabled } = this.reactiveDebugParams - - const baseY = this.cameraSectionPos.y * 16 - - if ( - this.displayOptions.inWorldRenderingConfig.enableDebugOverlay && - chunksRenderAboveOverride !== undefined || - chunksRenderBelowOverride !== undefined || - chunksRenderDistanceOverride !== undefined - ) { - for (const [key, object] of Object.entries(this.sectionObjects)) { - const [x, y, z] = key.split(',').map(Number) - const isVisible = - // eslint-disable-next-line no-constant-binary-expression, sonarjs/no-redundant-boolean - (chunksRenderAboveEnabled && chunksRenderAboveOverride !== undefined) ? y <= (baseY + chunksRenderAboveOverride) : true && - // eslint-disable-next-line @stylistic/indent-binary-ops, no-constant-binary-expression, sonarjs/no-redundant-boolean - (chunksRenderBelowEnabled && chunksRenderBelowOverride !== undefined) ? y >= (baseY - chunksRenderBelowOverride) : true && - // eslint-disable-next-line @stylistic/indent-binary-ops - (chunksRenderDistanceEnabled && chunksRenderDistanceOverride !== undefined) ? Math.abs(y - baseY) <= chunksRenderDistanceOverride : true - - object.visible = isVisible - } - } else { - for (const object of Object.values(this.sectionObjects)) { - object.visible = true - } - } - } - - render (sizeChanged = false) { - if (this.reactiveDebugParams.stopRendering) return - this.debugChunksVisibilityOverride() - const start = performance.now() - this.lastRendered = performance.now() - this.cursorBlock.render() - this.updateSectionOffsets() - - // Update skybox position to follow camera - const cameraPos = this.getCameraPosition() - this.skyboxRenderer.update(cameraPos, this.viewDistance) - - const sizeOrFovChanged = sizeChanged || this.displayOptions.inWorldRenderingConfig.fov !== this.camera.fov - if (sizeOrFovChanged) { - const size = this.renderer.getSize(new THREE.Vector2()) - this.camera.aspect = size.width / size.height - this.camera.fov = this.displayOptions.inWorldRenderingConfig.fov - this.camera.updateProjectionMatrix() - } - - if (!this.reactiveDebugParams.disableEntities) { - this.entities.render() - } - - // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style - const cam = this.cameraGroupVr instanceof THREE.Group ? this.cameraGroupVr.children.find(child => child instanceof THREE.PerspectiveCamera) as THREE.PerspectiveCamera : this.camera - this.renderer.render(this.scene, cam) - - if ( - this.displayOptions.inWorldRenderingConfig.showHand && - this.playerStateReactive.gameMode !== 'spectator' && - this.playerStateReactive.perspective === 'first_person' && - // !this.freeFlyMode && - !this.renderer.xr.isPresenting - ) { - this.holdingBlock.render(this.camera, this.renderer, this.ambientLight, this.directionalLight) - this.holdingBlockLeft.render(this.camera, this.renderer, this.ambientLight, this.directionalLight) - } - - for (const fountain of this.fountains) { - if (this.sectionObjects[fountain.sectionId] && !this.sectionObjects[fountain.sectionId].foutain) { - fountain.createParticles(this.sectionObjects[fountain.sectionId]) - this.sectionObjects[fountain.sectionId].foutain = true - } - fountain.render() - } - - this.waypoints.render() - this.fireworks.update() - - for (const onRender of this.onRender) { - onRender() - } - const end = performance.now() - const totalTime = end - start - this.renderTimeAvgCount++ - this.renderTimeAvg = ((this.renderTimeAvg * (this.renderTimeAvgCount - 1)) + totalTime) / this.renderTimeAvgCount - this.renderTimeMax = Math.max(this.renderTimeMax, totalTime) - this.currentRenderedFrames++ - } - - renderHead (position: Vec3, rotation: number, isWall: boolean, blockEntity) { - let textureData: string - if (blockEntity.SkullOwner) { - textureData = blockEntity.SkullOwner.Properties?.textures?.[0]?.Value - } else { - textureData = blockEntity.profile?.properties?.find(p => p.name === 'textures')?.value - } - if (!textureData) return - - try { - const decodedData = JSON.parse(Buffer.from(textureData, 'base64').toString()) - let skinUrl = decodedData.textures?.SKIN?.url - const { skinTexturesProxy } = this.worldRendererConfig - if (skinTexturesProxy) { - skinUrl = skinUrl?.replace('http://textures.minecraft.net/', skinTexturesProxy) - .replace('https://textures.minecraft.net/', skinTexturesProxy) - } - - const mesh = getMesh(this, skinUrl, armorModel.head) - const group = new THREE.Group() - if (isWall) { - mesh.position.set(0, 0.3125, 0.3125) - } - // move head model down as armor have a different offset than blocks - mesh.position.y -= 23 / 16 - group.add(mesh) - group.position.set(position.x + 0.5, position.y + 0.045, position.z + 0.5) - group.rotation.set( - 0, - -THREE.MathUtils.degToRad(rotation * (isWall ? 90 : 45 / 2)), - 0 - ) - group.scale.set(0.8, 0.8, 0.8) - return group - } catch (err) { - console.error('Error decoding player texture:', err) - } - } - - renderSign (position: Vec3, rotation: number, isWall: boolean, isHanging: boolean, blockEntity) { - const tex = this.getSignTexture(position, blockEntity, isHanging) - - if (!tex) return - - // todo implement - // const key = JSON.stringify({ position, rotation, isWall }) - // if (this.signsCache.has(key)) { - // console.log('cached', key) - // } else { - // this.signsCache.set(key, tex) - // } - - const mesh = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), new THREE.MeshBasicMaterial({ map: tex, transparent: true })) - mesh.renderOrder = 999 - - const lineHeight = 7 / 16 - const scaleFactor = isHanging ? 1.3 : 1 - mesh.scale.set(1 * scaleFactor, lineHeight * scaleFactor, 1 * scaleFactor) - - const thickness = (isHanging ? 2 : 1.5) / 16 - const wallSpacing = 0.25 / 16 - if (isWall && !isHanging) { - mesh.position.set(0, 0, -0.5 + thickness + wallSpacing + 0.0001) - } else { - mesh.position.set(0, 0, thickness / 2 + 0.0001) - } - - const group = new THREE.Group() - group.rotation.set( - 0, - -THREE.MathUtils.degToRad(rotation * (isWall ? 90 : 45 / 2)), - 0 - ) - group.add(mesh) - const height = (isHanging ? 10 : 8) / 16 - const heightOffset = (isHanging ? 0 : isWall ? 4.333 : 9.333) / 16 - const textPosition = height / 2 + heightOffset - group.position.set(position.x + 0.5, position.y + textPosition, position.z + 0.5) - return group - } - - lightUpdate (chunkX: number, chunkZ: number) { - // set all sections in the chunk dirty - for (let y = this.worldSizeParams.minY; y < this.worldSizeParams.worldHeight; y += 16) { - this.setSectionDirty(new Vec3(chunkX, y, chunkZ)) - } - } - - rerenderAllChunks () { // todo not clear what to do with loading chunks - for (const key of Object.keys(this.sectionObjects)) { - const [x, y, z] = key.split(',').map(Number) - this.setSectionDirty(new Vec3(x, y, z)) - } - } - - updateShowChunksBorder (value: boolean) { - for (const object of Object.values(this.sectionObjects)) { - for (const child of object.children) { - if (child.name === 'helper') { - child.visible = value - } - } - } - } - - resetWorld () { - super.resetWorld() - - for (const mesh of Object.values(this.sectionObjects)) { - this.scene.remove(mesh) - } - - // Clean up debug objects - if (this.debugRaycastHelper) { - this.scene.remove(this.debugRaycastHelper) - this.debugRaycastHelper = undefined - } - if (this.debugHitPoint) { - this.scene.remove(this.debugHitPoint) - this.debugHitPoint = undefined - } - } - - getLoadedChunksRelative (pos: Vec3, includeY = false) { - const [currentX, currentY, currentZ] = sectionPos(pos) - return Object.fromEntries(Object.entries(this.sectionObjects).map(([key, o]) => { - const [xRaw, yRaw, zRaw] = key.split(',').map(Number) - const [x, y, z] = sectionPos({ x: xRaw, y: yRaw, z: zRaw }) - const setKey = includeY ? `${x - currentX},${y - currentY},${z - currentZ}` : `${x - currentX},${z - currentZ}` - return [setKey, o] - })) - } - - cleanChunkTextures (x, z) { - const textures = this.chunkTextures.get(`${Math.floor(x / 16)},${Math.floor(z / 16)}`) ?? {} - for (const key of Object.keys(textures)) { - textures[key].dispose() - delete textures[key] - } - } - - readdChunks () { - for (const key of Object.keys(this.sectionObjects)) { - this.scene.remove(this.sectionObjects[key]) - } - setTimeout(() => { - for (const key of Object.keys(this.sectionObjects)) { - this.scene.add(this.sectionObjects[key]) - } - }, 500) - } - - disableUpdates (children = this.scene.children) { - for (const child of children) { - child.matrixWorldNeedsUpdate = false - this.disableUpdates(child.children ?? []) - } - } - - removeColumn (x, z) { - super.removeColumn(x, z) - - this.cleanChunkTextures(x, z) - for (let y = this.worldSizeParams.minY; y < this.worldSizeParams.worldHeight; y += 16) { - this.setSectionDirty(new Vec3(x, y, z), false) - const key = `${x},${y},${z}` - const mesh = this.sectionObjects[key] - if (mesh) { - // Cleanup banner textures before disposing - mesh.traverse((child) => { - if ((child as any).bannerTexture) { - releaseBannerTexture((child as any).bannerTexture) - } - }) - this.scene.remove(mesh) - disposeObject(mesh) - } - delete this.sectionObjects[key] - } - } - - setSectionDirty (...args: Parameters) { - const [pos] = args - this.cleanChunkTextures(pos.x, pos.z) // todo don't do this! - super.setSectionDirty(...args) - } - - static getRendererInfo (renderer: THREE.WebGLRenderer) { - try { - const gl = renderer.getContext() - return `${gl.getParameter(gl.getExtension('WEBGL_debug_renderer_info')!.UNMASKED_RENDERER_WEBGL)}` - } catch (err) { - console.warn('Failed to get renderer info', err) - } - } - - worldStop () { - this.media.onWorldStop() - } - - destroy (): void { - super.destroy() - this.skyboxRenderer.dispose() - this.fireworks.dispose() - } - - shouldObjectVisible (object: THREE.Object3D) { - // Get chunk coordinates - const chunkX = Math.floor(object.position.x / 16) * 16 - const chunkZ = Math.floor(object.position.z / 16) * 16 - const sectionY = Math.floor(object.position.y / 16) * 16 - - const chunkKey = `${chunkX},${chunkZ}` - const sectionKey = `${chunkX},${sectionY},${chunkZ}` - - return !!this.finishedChunks[chunkKey] || !!this.sectionObjects[sectionKey] - } - - updateSectionOffsets () { - const currentTime = performance.now() - for (const [key, anim] of Object.entries(this.sectionsOffsetsAnimations)) { - const timeDelta = (currentTime - anim.time) / 1000 // Convert to seconds - anim.time = currentTime - - // Update offsets based on speed and time delta - anim.currentOffsetX += anim.speedX * timeDelta - anim.currentOffsetY += anim.speedY * timeDelta - anim.currentOffsetZ += anim.speedZ * timeDelta - - // Apply limits if they exist - if (anim.limitX !== undefined) { - if (anim.speedX > 0) { - anim.currentOffsetX = Math.min(anim.currentOffsetX, anim.limitX) - } else { - anim.currentOffsetX = Math.max(anim.currentOffsetX, anim.limitX) - } - } - if (anim.limitY !== undefined) { - if (anim.speedY > 0) { - anim.currentOffsetY = Math.min(anim.currentOffsetY, anim.limitY) - } else { - anim.currentOffsetY = Math.max(anim.currentOffsetY, anim.limitY) - } - } - if (anim.limitZ !== undefined) { - if (anim.speedZ > 0) { - anim.currentOffsetZ = Math.min(anim.currentOffsetZ, anim.limitZ) - } else { - anim.currentOffsetZ = Math.max(anim.currentOffsetZ, anim.limitZ) - } - } - - // Apply the offset to the section object - const section = this.sectionObjects[key] - if (section) { - section.position.set( - anim.currentOffsetX, - anim.currentOffsetY, - anim.currentOffsetZ - ) - section.updateMatrix() - } - } - } - - reloadWorld () { - this.entities.reloadEntities() - } -} - -class StarField { - points?: THREE.Points - private _enabled = true - get enabled () { - return this._enabled - } - - set enabled (value) { - this._enabled = value - if (this.points) { - this.points.visible = value - } - } - - constructor ( - private readonly worldRenderer: WorldRendererThree - ) { - const clock = new THREE.Clock() - const speed = 0.2 - this.worldRenderer.onRender.push(() => { - if (!this.points) return - this.points.position.copy(this.worldRenderer.getCameraPosition()); - (this.points.material as StarfieldMaterial).uniforms.time.value = clock.getElapsedTime() * speed - }) - } - - addToScene () { - if (this.points || !this.enabled) return - - const radius = 80 - const depth = 50 - const count = 7000 - const factor = 7 - const saturation = 10 - - const geometry = new THREE.BufferGeometry() - - const genStar = r => new THREE.Vector3().setFromSpherical(new THREE.Spherical(r, Math.acos(1 - Math.random() * 2), Math.random() * 2 * Math.PI)) - - const positions = [] as number[] - const colors = [] as number[] - const sizes = Array.from({ length: count }, () => (0.5 + 0.5 * Math.random()) * factor) - const color = new THREE.Color() - let r = radius + depth - const increment = depth / count - for (let i = 0; i < count; i++) { - r -= increment * Math.random() - positions.push(...genStar(r).toArray()) - color.setHSL(i / count, saturation, 0.9) - colors.push(color.r, color.g, color.b) - } - - geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3)) - geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3)) - geometry.setAttribute('size', new THREE.Float32BufferAttribute(sizes, 1)) - - // Create a material - const material = new StarfieldMaterial() - material.blending = THREE.AdditiveBlending - material.depthTest = false - material.transparent = true - - // Create points and add them to the scene - this.points = new THREE.Points(geometry, material) - this.worldRenderer.scene.add(this.points) - - this.points.renderOrder = -1 - } - - remove () { - if (this.points) { - this.points.geometry.dispose(); - (this.points.material as THREE.Material).dispose() - this.worldRenderer.scene.remove(this.points) - - this.points = undefined - } - } -} - -const version = parseInt(THREE.REVISION.replaceAll(/\D+/g, ''), 10) -class StarfieldMaterial extends THREE.ShaderMaterial { - constructor () { - super({ - uniforms: { time: { value: 0 }, fade: { value: 1 } }, - vertexShader: /* glsl */ ` - uniform float time; - attribute float size; - varying vec3 vColor; - attribute vec3 color; - void main() { - vColor = color; - vec4 mvPosition = modelViewMatrix * vec4(position, 0.5); - gl_PointSize = 0.7 * size * (30.0 / -mvPosition.z) * (3.0 + sin(time + 100.0)); - gl_Position = projectionMatrix * mvPosition; - }`, - fragmentShader: /* glsl */ ` - uniform sampler2D pointTexture; - uniform float fade; - varying vec3 vColor; - void main() { - float opacity = 1.0; - gl_FragColor = vec4(vColor, 1.0); - - #include - #include <${version >= 154 ? 'colorspace_fragment' : 'encodings_fragment'}> - }`, - }) - } -} diff --git a/rsbuild.config.ts b/rsbuild.config.ts index 8fcdbe3ea..6e2928917 100644 --- a/rsbuild.config.ts +++ b/rsbuild.config.ts @@ -11,7 +11,7 @@ import fsExtra from 'fs-extra' import { promisify } from 'util' import { generateSW } from 'workbox-build' import { getSwAdditionalEntries } from './scripts/build' -import { appAndRendererSharedConfig } from './renderer/rsbuildSharedConfig' +import { appAndRendererSharedConfig } from './rsbuildSharedConfig' import { genLargeDataAliases } from './scripts/genLargeDataAliases' import sharp from 'sharp' import supportedVersions from './src/supportedVersions.mjs' @@ -87,7 +87,7 @@ const faviconPath = 'favicon.png' const enableMetrics = process.env.ENABLE_METRICS === 'true' -// base options are in ./renderer/rsbuildSharedConfig.ts +// base options are in ./rsbuildSharedConfig.ts const appConfig = defineConfig({ html: { template: './index.html', @@ -245,12 +245,22 @@ const appConfig = defineConfig({ // childProcess.execSync('./scripts/prepareSounds.mjs', { stdio: 'inherit' }) // childProcess.execSync('tsx ./scripts/genMcDataTypes.ts', { stdio: 'inherit' }) // childProcess.execSync('tsx ./scripts/genPixelartTypes.ts', { stdio: 'inherit' }) - if (fs.existsSync('./renderer/dist/mesher.js') && dev) { + // copy mesher worker + if (fs.existsSync('./node_modules/minecraft-renderer/src/wasm-mesher/runtime-build/wasm_mesher_bg.wasm')) { + fs.copyFileSync('./node_modules/minecraft-renderer/src/wasm-mesher/runtime-build/wasm_mesher_bg.wasm', './dist/wasm_mesher_bg.wasm') + } else { + console.warn('wasm_mesher_bg.wasm not found') + } + if (fs.existsSync('./node_modules/minecraft-renderer/dist/mesherWasm.js')) { + fs.copyFileSync('./node_modules/minecraft-renderer/dist/mesherWasm.js', './dist/mesherWasm.js') + } + if (fs.existsSync('./node_modules/minecraft-renderer/dist/mesher.js')) { // copy mesher - fs.copyFileSync('./renderer/dist/mesher.js', './dist/mesher.js') - fs.copyFileSync('./renderer/dist/mesher.js.map', './dist/mesher.js.map') - } else if (!dev) { - await execAsync('pnpm run build-mesher') + fs.copyFileSync('./node_modules/minecraft-renderer/dist/mesher.js', './dist/mesher.js') + fs.copyFileSync('./node_modules/minecraft-renderer/dist/mesher.js.map', './dist/mesher.js.map') + fs.copyFileSync('./node_modules/minecraft-renderer/dist/threeWorker.js', './dist/threeWorker.js') + } else { + throw new Error('mesher.js not found') } fs.writeFileSync('./dist/version.txt', buildingVersion, 'utf-8') diff --git a/renderer/rsbuildSharedConfig.ts b/rsbuildSharedConfig.ts similarity index 80% rename from renderer/rsbuildSharedConfig.ts rename to rsbuildSharedConfig.ts index 203b32087..f9825cdce 100644 --- a/renderer/rsbuildSharedConfig.ts +++ b/rsbuildSharedConfig.ts @@ -10,8 +10,8 @@ export const appAndRendererSharedConfig = () => defineConfig({ writeToDisk: true, watchFiles: { paths: [ - path.join(__dirname, './dist/webgpuRendererWorker.js'), - path.join(__dirname, './dist/mesher.js'), + // path.join(__dirname, './dist/webgpuRendererWorker.js'), + // path.join(__dirname, './dist/mesher.js'), ] }, }, @@ -23,18 +23,18 @@ export const appAndRendererSharedConfig = () => defineConfig({ }, source: { alias: { - fs: path.join(__dirname, `../src/shims/fs.js`), + fs: path.join(__dirname, `./src/shims/fs.js`), http: 'http-browserify', stream: 'stream-browserify', net: 'net-browserify', 'minecraft-protocol$': 'minecraft-protocol/src/index.js', 'buffer$': 'buffer', // avoid bundling, not used on client side - 'prismarine-auth': path.join(__dirname, `../src/shims/prismarineAuthReplacement.ts`), - perf_hooks: path.join(__dirname, `../src/shims/perf_hooks_replacement.js`), - crypto: path.join(__dirname, `../src/shims/crypto.js`), - dns: path.join(__dirname, `../src/shims/dns.js`), - yggdrasil: path.join(__dirname, `../src/shims/yggdrasilReplacement.ts`), + 'prismarine-auth': path.join(__dirname, `./src/shims/prismarineAuthReplacement.ts`), + perf_hooks: path.join(__dirname, `./src/shims/perf_hooks_replacement.js`), + crypto: path.join(__dirname, `./src/shims/crypto.js`), + dns: path.join(__dirname, `./src/shims/dns.js`), + yggdrasil: path.join(__dirname, `./src/shims/yggdrasilReplacement.ts`), 'three$': 'three/src/Three.js', 'stats.js$': 'stats.js/src/Stats.js', }, @@ -42,7 +42,7 @@ export const appAndRendererSharedConfig = () => defineConfig({ 'process.platform': '"browser"', }, decorators: { - version: 'legacy', // default is a lie + version: 'legacy', }, }, server: { @@ -63,7 +63,7 @@ export const appAndRendererSharedConfig = () => defineConfig({ ], tools: { rspack (config, helpers) { - const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf8')) + const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, './package.json'), 'utf8')) const hasFileProtocol = Object.values(packageJson.pnpm.overrides).some((dep) => (dep as string).startsWith('file:')) if (hasFileProtocol) { // enable node_modules watching @@ -85,13 +85,13 @@ export const rspackViewerConfig = (config, { appendPlugins, addRules, rspack }: // throw new Error(`${resource.request} was requested by ${resource.contextInfo.issuer}`) } if (absolute.endsWith('/minecraft-data/data.js')) { - resource.request = path.join(__dirname, `../src/shims/minecraftData.ts`) + resource.request = path.join(__dirname, `./src/shims/minecraftData.ts`) } if (absolute.endsWith('/minecraft-data/data/bedrock/common/legacy.json')) { - resource.request = path.join(__dirname, `../src/shims/empty.ts`) + resource.request = path.join(__dirname, `./src/shims/empty.ts`) } if (absolute.endsWith('/minecraft-data/data/pc/common/legacy.json')) { - resource.request = path.join(__dirname, `../src/preflatMap.json`) + resource.request = path.join(__dirname, `./src/preflatMap.json`) } })) addRules([ diff --git a/scripts/dockerPrepare.mjs b/scripts/dockerPrepare.mjs index 62a4f5e4e..48baf205f 100644 --- a/scripts/dockerPrepare.mjs +++ b/scripts/dockerPrepare.mjs @@ -29,7 +29,3 @@ fs.writeFileSync('./assets/release.json', JSON.stringify({ const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8')) delete packageJson.optionalDependencies fs.writeFileSync('./package.json', JSON.stringify(packageJson, null, 2), 'utf8') - -const packageJsonViewer = JSON.parse(fs.readFileSync('./renderer/package.json', 'utf8')) -delete packageJsonViewer.optionalDependencies -fs.writeFileSync('./renderer/package.json', JSON.stringify(packageJsonViewer, null, 2), 'utf8') diff --git a/scripts/findBundledDuplicateDeps.mjs b/scripts/findBundledDuplicateDeps.mjs new file mode 100644 index 000000000..21681744f --- /dev/null +++ b/scripts/findBundledDuplicateDeps.mjs @@ -0,0 +1,178 @@ +/** + * Scan dist/ output for duplicate npm packages bundled more than once. + * + * Detects pnpm virtual-store paths embedded in JS bundles, e.g.: + * node_modules/.pnpm/valtio@1.13.2_@types+react@18.3.18_react@18.3.1/... + * + * Usage: + * node scripts/findBundledDuplicateDeps.mjs [--dist=dist] [--fail] [--json] + * + * Exit code 1 with --fail when any package name appears with multiple versions + * or multiple distinct pnpm install paths (peer-resolution duplicates). + */ + +import fs from 'fs' +import path from 'path' +import { fileURLToPath } from 'url' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const rootDir = path.join(__dirname, '..') + +const args = process.argv.slice(2) +const distArg = args.find(a => a.startsWith('--dist='))?.slice('--dist='.length) +const distDir = path.resolve(rootDir, distArg ?? 'dist') +const failOnDuplicates = args.includes('--fail') +const jsonOutput = args.includes('--json') + +/** @typedef {{ name: string, version: string, folder: string }} ParsedPackage */ + +/** + * @param {string} folder pnpm .pnpm folder segment (no trailing slash) + * @returns {ParsedPackage | null} + */ +function parsePnpmFolder(folder) { + if (!folder || folder.includes('node_modules')) return null + + const scoped = folder.match(/^(@[^+@/]+)\+([^@/]+)@([^_/]+)/) + if (scoped) { + return { + name: `${scoped[1]}/${scoped[2]}`, + version: scoped[3], + folder, + } + } + + const at = folder.indexOf('@') + if (at <= 0) return null + + const name = folder.slice(0, at) + const rest = folder.slice(at + 1) + const version = rest.split('_')[0] + if (!version) return null + + return { name, version, folder } +} + +/** @param {string} dir @returns {string[]} */ +function walkJsFiles(dir) { + /** @type {string[]} */ + const out = [] + if (!fs.existsSync(dir)) return out + + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const full = path.join(dir, entry.name) + if (entry.isDirectory()) { + out.push(...walkJsFiles(full)) + } else if (entry.isFile() && entry.name.endsWith('.js')) { + out.push(full) + } + } + return out +} + +/** @type {RegExp} */ +const PNPM_PATH_RE = /node_modules[/\\]\.pnpm[/\\]([^/\\"'`\s]+)/g + +/** + * @param {string} distRoot + * @returns {Map, files: Set }>>} + */ +function scanDist(distRoot) { + /** @type {Map, files: Set }>>} */ + const byName = new Map() + + const addHit = (parsed, file) => { + if (!parsed?.name) return + if (!byName.has(parsed.name)) byName.set(parsed.name, new Map()) + const byVersion = byName.get(parsed.name) + if (!byVersion.has(parsed.version)) { + byVersion.set(parsed.version, { folders: new Set(), files: new Set() }) + } + const entry = byVersion.get(parsed.version) + entry.folders.add(parsed.folder) + entry.files.add(path.relative(distRoot, file)) + } + + for (const file of walkJsFiles(distRoot)) { + const text = fs.readFileSync(file, 'utf8') + + for (const match of text.matchAll(PNPM_PATH_RE)) { + const parsed = parsePnpmFolder(match[1]) + addHit(parsed, file) + } + + // Chunk filenames also encode pnpm paths, e.g. vendors-..._pnpm_valtio@1.13.2_... + const base = path.basename(file, '.js') + for (const match of base.matchAll(/_pnpm_([a-zA-Z0-9@+._-]+?)@([\d.]+(?:_[\w.+@-]+)?)/g)) { + const parsed = parsePnpmFolder(`${match[1]}@${match[2]}`) + addHit(parsed, file) + } + } + + return byName +} + +/** + * @param {Map, files: Set }>>} byName + */ +function findDuplicates(byName) { + /** @type {Array<{ name: string, versions: string[], folders: string[], files: string[] }>} */ + const duplicates = [] + + for (const [name, byVersion] of [...byName.entries()].sort((a, b) => a[0].localeCompare(b[0]))) { + const versions = [...byVersion.keys()].sort() + const allFolders = versions.flatMap(v => [...byVersion.get(v).folders]) + const hasMultipleVersions = versions.length > 1 + const hasMultipleInstallPaths = versions.some(v => byVersion.get(v).folders.size > 1) + + if (!hasMultipleVersions && !hasMultipleInstallPaths) continue + + duplicates.push({ + name, + versions, + folders: [...new Set(allFolders)].sort(), + files: [...new Set(versions.flatMap(v => [...byVersion.get(v).files]))].sort(), + }) + } + + return duplicates +} + +function main() { + if (!fs.existsSync(distDir)) { + console.error(`dist directory not found: ${distDir}`) + console.error('Run a build first (pnpm build).') + process.exit(failOnDuplicates ? 1 : 0) + } + + const byName = scanDist(distDir) + const duplicates = findDuplicates(byName) + + if (jsonOutput) { + console.log(JSON.stringify({ distDir, duplicateCount: duplicates.length, duplicates }, null, 2)) + } else { + console.log(`Scanned ${walkJsFiles(distDir).length} JS files in ${distDir}`) + console.log(`Found ${duplicates.length} package name(s) bundled more than once:\n`) + + if (duplicates.length === 0) { + console.log('No duplicate bundled dependencies detected.') + } else { + for (const dup of duplicates) { + console.log(`• ${dup.name}`) + console.log(` versions: ${dup.versions.join(', ')}`) + console.log(` pnpm paths (${dup.folders.length}):`) + for (const folder of dup.folders) { + console.log(` - ${folder}`) + } + console.log(` chunks (${dup.files.length}): ${dup.files.slice(0, 4).join(', ')}${dup.files.length > 4 ? ', …' : ''}`) + console.log() + } + } + } + + if (failOnDuplicates && duplicates.length > 0) { + process.exit(1) + } +} + +main() diff --git a/scripts/githubActions.mjs b/scripts/githubActions.mjs index a3b63ee67..9b434316d 100644 --- a/scripts/githubActions.mjs +++ b/scripts/githubActions.mjs @@ -26,6 +26,102 @@ const fns = { } else { setOutput('alias', final(tag)) } + }, + /** + * Generic JSON parser that extracts structured data from PR body codeblocks + * Supports: + * - deployAlwaysUpdate: array of package names + * - config: object to override config.json + */ + parsePrConfig() { + const prBody = process.env.PR_BODY || '' + if (!prBody) { + console.log('No PR body found, using defaults') + return + } + + // Strict regex for JSON codeblocks: ```json, ```javascript, or ```js followed by JSON content + const codeBlockRegex = /```(?:json|javascript|js)?\s*\n([\s\S]*?)```/g + let match + const configs = [] + const packages = [] + + // Parse all JSON codeblocks + while ((match = codeBlockRegex.exec(prBody)) !== null) { + const codeContent = match[1].trim() + if (!codeContent) continue + + try { + const parsed = JSON.parse(codeContent) + + // Extract deployAlwaysUpdate if present + if (parsed.deployAlwaysUpdate) { + if (Array.isArray(parsed.deployAlwaysUpdate)) { + packages.push(...parsed.deployAlwaysUpdate.filter(pkg => typeof pkg === 'string')) + } else { + console.warn('deployAlwaysUpdate must be an array, ignoring') + } + } + + // Extract config if present + if (parsed.config && typeof parsed.config === 'object' && !Array.isArray(parsed.config)) { + configs.push(parsed.config) + } + } catch (e) { + // Not valid JSON, skip this codeblock + console.warn(`Failed to parse JSON codeblock: ${e.message}`) + } + } + + // Also check for inline JSON at the bottom (last 30 lines) + const bottomSection = prBody.split('\n').slice(-30).join('\n') + const jsonMatch = bottomSection.match(/\{[\s\S]{0,5000}\}/) + if (jsonMatch) { + try { + const parsed = JSON.parse(jsonMatch[0]) + + if (parsed.deployAlwaysUpdate && Array.isArray(parsed.deployAlwaysUpdate)) { + packages.push(...parsed.deployAlwaysUpdate.filter(pkg => typeof pkg === 'string')) + } + + if (parsed.config && typeof parsed.config === 'object' && !Array.isArray(parsed.config)) { + configs.push(parsed.config) + } + } catch (e) { + // Ignore parse errors for inline JSON + } + } + + // Process deployAlwaysUpdate + const uniquePackages = [...new Set(packages)] + if (uniquePackages.length > 0) { + console.log(`Found deployAlwaysUpdate packages: ${uniquePackages.join(', ')}`) + setOutput('packages', uniquePackages.join(' ')) + } else { + // Fallback to package.json + if (fs.existsSync('./package.json')) { + try { + const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8')) + if (pkg.deployAlwaysUpdate && Array.isArray(pkg.deployAlwaysUpdate)) { + console.log(`Using deployAlwaysUpdate from package.json: ${pkg.deployAlwaysUpdate.join(', ')}`) + setOutput('packages', pkg.deployAlwaysUpdate.join(' ')) + } + } catch (e) { + console.warn('Failed to read package.json:', e.message) + } + } + } + + // Process config overrides + if (configs.length > 0) { + // Merge all config objects (later ones override earlier ones) + const mergedConfig = configs.reduce((acc, config) => ({ ...acc, ...config }), {}) + const configJson = JSON.stringify(mergedConfig) + + // Output as JSON string for CONFIG_JSON env var (highest precedence) + setOutput('configJson', configJson) + console.log(`Config JSON available as CONFIG_JSON environment variable (highest precedence)`) + } } } @@ -35,9 +131,18 @@ function setOutput (key, value) { fs.appendFileSync(output, `${key}=${value}${os.EOL}`) } +// Backward compatibility: map old function name to new one +if (process.argv[2] === 'getDeployAlwaysUpdate') { + process.argv[2] = 'parsePrConfig' +} + const fn = fns[process.argv[2]] if (fn) { - fn() + Promise.resolve(fn()).catch(err => { + console.error(err) + process.exit(1) + }) } else { console.error('Function not found') + process.exit(1) } diff --git a/server.js b/server.js index 49699cdbc..71a70500c 100644 --- a/server.js +++ b/server.js @@ -62,9 +62,24 @@ if (isProd) { app.use((req, res, next) => { res.setHeader('Cross-Origin-Opener-Policy', 'same-origin') res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp') + // wasm-pack/instantiateStreaming requires the correct mime type + if (req.path.endsWith('.wasm')) { + res.setHeader('Content-Type', 'application/wasm') + } next() }) + // Serve minecraft-renderer wasm mesher artifacts from the installed package. + // (Needed when using file: dependency, where these assets may not be in the web-client dist root) + try { + const rendererPkg = require.resolve('minecraft-renderer/package.json') + const rendererDir = path.dirname(rendererPkg) + app.get('/wasm_mesher.js', (req, res) => res.sendFile(path.join(rendererDir, 'public/wasm_mesher.js'))) + app.get('/wasm_mesher_bg.wasm', (req, res) => res.sendFile(path.join(rendererDir, 'public/wasm_mesher_bg.wasm'))) + } catch (err) { + console.warn('Failed to locate minecraft-renderer package for wasm mesher assets', err) + } + // First serve from the override directory (volume mount) app.use(express.static(path.join(__dirname, './public'))) diff --git a/src/appConfig.ts b/src/appConfig.ts index c92fe62da..ac37b26e6 100644 --- a/src/appConfig.ts +++ b/src/appConfig.ts @@ -4,6 +4,7 @@ import { miscUiState } from './globalState' import { setLoadingScreenStatus } from './appStatus' import { setStorageDataOnAppConfigLoad } from './react/appStorageProvider' import { customKeymaps, updateBinds } from './controls' +import { onAppViewerConfigUpdate } from './appViewer' export type CustomAction = { readonly type: string @@ -133,7 +134,7 @@ export const loadAppConfig = (appConfig: AppConfig) => { updateBinds(customKeymaps) } - appViewer?.appConfigUdpate() + onAppViewerConfigUpdate() setStorageDataOnAppConfigLoad(appConfig) setWatermarkFromConfig(miscUiState.appConfig) diff --git a/src/appStatus.ts b/src/appStatus.ts index f0742dd4a..d187b234c 100644 --- a/src/appStatus.ts +++ b/src/appStatus.ts @@ -6,21 +6,19 @@ import { appStatusState, resetAppStatusState } from './react/AppStatusProvider' let ourLastStatus: string | undefined = '' const formatErrorDetail = (err: unknown): string => { + const formatStack = (stack: string, fallbackMessage: string) => { + const lines = stack.split('\n') + const frame = lines[1]?.trim() + return frame ? `${lines[0]}\n\n${frame}` : fallbackMessage + } + if (err instanceof Error) { - if (err.stack) { - const lines = err.stack.split('\n') - const trace = lines.slice(1, 6).join('\n') - return trace ? `${lines[0]}\n${trace}` : err.message - } + if (err.stack) return formatStack(err.stack, err.message) return err.message } if (typeof err === 'object' && err !== null && 'message' in err && typeof (err as { message: unknown }).message === 'string') { const withMessage = err as { message: string, stack?: string } - if (withMessage.stack) { - const lines = withMessage.stack.split('\n') - const trace = lines.slice(1, 6).join('\n') - return trace ? `${lines[0]}\n${trace}` : withMessage.message - } + if (withMessage.stack) return formatStack(withMessage.stack, withMessage.message) return withMessage.message } return String(err) diff --git a/src/appViewer.ts b/src/appViewer.ts index 025650b15..3af1cb132 100644 --- a/src/appViewer.ts +++ b/src/appViewer.ts @@ -1,331 +1,61 @@ -import { WorldDataEmitter, WorldDataEmitterWorker } from 'renderer/viewer/lib/worldDataEmitter' -import { getInitialPlayerState, PlayerStateRenderer, PlayerStateReactive } from 'renderer/viewer/lib/basePlayerState' -import { subscribeKey } from 'valtio/utils' -import { defaultWorldRendererConfig, WorldRendererConfig } from 'renderer/viewer/lib/worldrendererCommon' import { Vec3 } from 'vec3' -import { SoundSystem } from 'renderer/viewer/three/threeJsSound' -import { proxy, subscribe } from 'valtio' -import { getDefaultRendererState } from 'renderer/viewer/baseGraphicsBackend' -import { getSyncWorld } from 'renderer/playground/shared' -import { MaybePromise } from 'contro-max/build/types/store' -import { PANORAMA_VERSION } from 'renderer/viewer/three/panoramaShared' -import { playerState } from './mineflayer/playerState' -import { createNotificationProgressReporter, ProgressReporter } from './core/progressReporter' -import { setLoadingScreenStatus } from './appStatus' +import { subscribe } from 'valtio' +import { + AppViewer, + getInitialPlayerState, + MENU_BACKGROUND_MC_VERSION, + menuBackgroundOptionsFromStorage, + type MenuBackgroundOptions +} from 'minecraft-renderer/src' +import { generateGuiAtlas } from 'minecraft-renderer/src/lib/guiRenderer' +import { BotEvents } from 'mineflayer' import { activeModalStack, miscUiState } from './globalState' import { options } from './optionsStorage' -import { ResourcesManager, ResourcesManagerTransferred } from './resourcesManager' import { watchOptionsAfterWorldViewInit } from './watchOptions' -import { loadMinecraftData } from './connect' -import { reloadChunks } from './utils' -import { displayClientChat } from './botUtils' -import { isPlayground } from './playgroundIntegration' -export interface RendererReactiveState { - world: { - chunksLoaded: Set - // chunksTotalNumber: number - heightmaps: Map - allChunksLoaded: boolean - mesherWork: boolean - intersectMedia: { id: string, x: number, y: number } | null - } - renderer: string - preventEscapeMenu: boolean -} -export interface NonReactiveState { - world: { - chunksLoaded: Set - chunksTotalNumber: number - } -} - -export interface GraphicsBackendConfig { - fpsLimit?: number - powerPreference?: 'high-performance' | 'low-power' - statsVisible?: number - sceneBackground: string - timeoutRendering?: boolean -} - -const defaultGraphicsBackendConfig: GraphicsBackendConfig = { - fpsLimit: undefined, - powerPreference: undefined, - sceneBackground: 'lightblue', - timeoutRendering: false +// do not import this. Use global appViewer instead (without window prefix). +export const appViewer = new AppViewer() +appViewer.resourcesManager.generateGuiTextures = async () => { + await generateGuiAtlas(appViewer) } +window.appViewer = appViewer -export interface GraphicsInitOptions { - resourcesManager: ResourcesManagerTransferred - config: GraphicsBackendConfig - rendererSpecificSettings: S - - callbacks: { - displayCriticalError: (error: Error) => void - setRendererSpecificSettings: (key: string, value: any) => void +appViewer.onWorldStart = () => { + connectAppWorldViewToBot() - fireCustomEvent: (eventName: string, ...args: any[]) => void + if (appViewer.worldView) { + watchOptionsAfterWorldViewInit(appViewer.worldView) } } -export interface DisplayWorldOptions { - version: string - worldView: WorldDataEmitterWorker - inWorldRenderingConfig: WorldRendererConfig - playerStateReactive: PlayerStateReactive - rendererState: RendererReactiveState - nonReactiveState: NonReactiveState -} - -export type GraphicsBackendLoader = ((options: GraphicsInitOptions) => MaybePromise) & { - id: string -} - -// no sync methods -export interface GraphicsBackend { - id: string - displayName?: string - startPanorama: () => void - // prepareResources: (version: string, progressReporter: ProgressReporter) => Promise - startWorld: (options: DisplayWorldOptions) => Promise | void - disconnect: () => void - setRendering: (rendering: boolean) => void - getDebugOverlay?: () => Record - updateCamera: (pos: Vec3 | null, yaw: number, pitch: number) => void - setRoll?: (roll: number) => void - soundSystem: SoundSystem | undefined - - backendMethods: Record | undefined -} - -export class AppViewer { - waitBackendLoadPromises = [] as Array> - - resourcesManager = new ResourcesManager() - worldView: WorldDataEmitter | undefined - readonly config: GraphicsBackendConfig = { - ...defaultGraphicsBackendConfig, - powerPreference: options.gpuPreference === 'default' ? undefined : options.gpuPreference - } - backend?: GraphicsBackend - backendLoader?: GraphicsBackendLoader - private currentState?: { - method: string - args: any[] - } - currentDisplay = null as 'menu' | 'world' | null - inWorldRenderingConfig: WorldRendererConfig = proxy(defaultWorldRendererConfig) - lastCamUpdate = 0 - playerState = playerState - rendererState = getDefaultRendererState().reactive - nonReactiveState: NonReactiveState = getDefaultRendererState().nonReactive - worldReady: Promise - private resolveWorldReady: () => void - - constructor () { - this.disconnectBackend() - } - - async loadBackend (loader: GraphicsBackendLoader) { - if (this.backend) { - this.disconnectBackend() - } - - await Promise.all(this.waitBackendLoadPromises) - this.waitBackendLoadPromises = [] - - this.backendLoader = loader - const rendererSpecificSettings = {} as Record - const rendererSettingsKey = `renderer.${this.backendLoader?.id}` - for (const key in options) { - if (key.startsWith(rendererSettingsKey)) { - rendererSpecificSettings[key.slice(rendererSettingsKey.length + 1)] = options[key] - } - } - const loaderOptions: GraphicsInitOptions = { // todo! - resourcesManager: this.resourcesManager as ResourcesManagerTransferred, - config: this.config, - callbacks: { - displayCriticalError (error) { - console.error(error) - setLoadingScreenStatus(error.message, true) - }, - setRendererSpecificSettings (key: string, value: any) { - options[`${rendererSettingsKey}.${key}`] = value - }, - fireCustomEvent (eventName, ...args) { - // this.callbacks.fireCustomEvent(eventName, ...args) - } - }, - rendererSpecificSettings, - } - this.backend = await loader(loaderOptions) - - // if (this.resourcesManager.currentResources) { - // void this.prepareResources(this.resourcesManager.currentResources.version, createNotificationProgressReporter()) - // } - - // Execute queued action if exists - if (this.currentState) { - if (this.currentState.method === 'startPanorama') { - this.startPanorama() - } else { - const { method, args } = this.currentState - this.backend[method](...args) - if (method === 'startWorld') { - // Only auto-init if bot exists (main app mode) - // Playground mode will call init explicitly with its position - if (bot?.entity?.position) { - void this.worldView!.init(bot.entity.position) - } - // void this.worldView!.init(args[0].playerState.getPosition()) - } - } - } - - // todo - modalStackUpdateChecks() - } - - async startWithBot () { - const renderDistance = miscUiState.singleplayer ? options.renderDistance : options.multiplayerRenderDistance - await this.startWorld(bot.world, renderDistance) - this.worldView!.listenToBot(bot) - } - - appConfigUdpate () { - if (miscUiState.appConfig) { - this.inWorldRenderingConfig.skinTexturesProxy = miscUiState.appConfig.skinTexturesProxy - } - } - - async startWorld (world, renderDistance: number, playerStateSend: PlayerStateRenderer = this.playerState.reactive, startPosition?: Vec3) { - if (this.currentDisplay === 'world') throw new Error('World already started') - this.currentDisplay = 'world' - const finalStartPosition = startPosition ?? bot?.entity?.position ?? new Vec3(0, 64, 0) - this.worldView = new WorldDataEmitter(world, renderDistance, finalStartPosition) - this.worldView.panicChunksReload = () => { - if (!options.experimentalClientSelfReload) return - if (process.env.NODE_ENV === 'development') { - displayClientChat(`[client] client panicked due to too long loading time. Soft reloading chunks...`) - } - void reloadChunks() - } - window.worldView = this.worldView - if (!isPlayground) { - watchOptionsAfterWorldViewInit(this.worldView) - } - this.appConfigUdpate() - - const displayWorldOptions: DisplayWorldOptions = { - version: this.resourcesManager.currentConfig!.version, - worldView: this.worldView, - inWorldRenderingConfig: this.inWorldRenderingConfig, - playerStateReactive: playerStateSend, - rendererState: this.rendererState, - nonReactiveState: this.nonReactiveState - } - let promise: undefined | Promise - if (this.backend) { - promise = this.backend.startWorld(displayWorldOptions) ?? undefined - // void this.worldView.init(startPosition) - } - this.currentState = { method: 'startWorld', args: [displayWorldOptions] } - - await promise - // Resolve the promise after world is started - this.resolveWorldReady() - return !!promise - } - - resetBackend (cleanState = false) { - this.disconnectBackend(cleanState) - if (this.backendLoader) { - void this.loadBackend(this.backendLoader) - } - } - - startPanorama () { - if (this.currentDisplay === 'menu') return - if (options.disableAssets) return - if (this.backend && !hasAppStatus()) { - this.currentDisplay = 'menu' - if (process.env.SINGLE_FILE_BUILD_MODE) { - void loadMinecraftData(PANORAMA_VERSION).then(() => { - this.backend?.startPanorama() - }) - } else { - this.backend.startPanorama() - } - } - this.currentState = { method: 'startPanorama', args: [] } - } - - // async prepareResources (version: string, progressReporter: ProgressReporter) { - // if (this.backend) { - // await this.backend.prepareResources(version, progressReporter) - // } - // } - - destroyAll () { - this.disconnectBackend() - this.resourcesManager.destroy() - } - - disconnectBackend (cleanState = false) { - if (cleanState) { - this.currentState = undefined - this.currentDisplay = null - this.worldView = undefined - } - if (this.backend) { - this.backend.disconnect() - this.backend = undefined - } - this.currentDisplay = null - const { promise, resolve } = Promise.withResolvers() - this.worldReady = promise - this.resolveWorldReady = resolve - this.rendererState = proxy(getDefaultRendererState().reactive) - this.nonReactiveState = getDefaultRendererState().nonReactive - // this.queuedDisplay = undefined - } - - get utils () { - return { - async waitingForChunks () { - if (this.backend?.worldState.allChunksLoaded) return - return new Promise((resolve) => { - const interval = setInterval(() => { - if (this.backend?.worldState.allChunksLoaded) { - clearInterval(interval) - resolve(true) - } - }, 100) - }) - } - } +const prepareMenuBackgroundAssets = async (opts: MenuBackgroundOptions) => { + if (!opts.useMinecraftTextures) return + const { loadMinecraftData } = await import('./connect') + await loadMinecraftData(MENU_BACKGROUND_MC_VERSION) + appViewer.resourcesManager.currentConfig = { + version: MENU_BACKGROUND_MC_VERSION, + texturesVersion: options.useVersionsTextures || undefined, + noInventoryGui: true } + await appViewer.resourcesManager.updateAssetsData({}) } -// do not import this. Use global appViewer instead (without window prefix). -export const appViewer = new AppViewer() -window.appViewer = appViewer - const initialMenuStart = async () => { if (appViewer.currentDisplay === 'world') { appViewer.resetBackend(true) } const demo = new URLSearchParams(window.location.search).get('demo') if (!demo) { - appViewer.startPanorama() + const menuBackgroundOpts = menuBackgroundOptionsFromStorage(options) + await prepareMenuBackgroundAssets(menuBackgroundOpts) + appViewer.startMenuBackground(menuBackgroundOpts) return } // const version = '1.18.2' const version = '1.21.4' const { loadMinecraftData } = await import('./connect') - const { getSyncWorld } = await import('../renderer/playground/shared') + const { getSyncWorld } = await import('minecraft-renderer/src/playground/shared') await loadMinecraftData(version) const world = getSyncWorld(version) world.setBlockStateId(new Vec3(0, 64, 0), loadedData.blocksByName.water.defaultState) @@ -339,6 +69,7 @@ const initialMenuStart = async () => { appViewer.playerState.reactive = getInitialPlayerState() await appViewer.resourcesManager.updateAssetsData({}) await appViewer.startWorld(world, 3) + if (appViewer.worldView) watchOptionsAfterWorldViewInit(appViewer.worldView) appViewer.backend!.updateCamera(new Vec3(0, 65.7, 0), 0, -Math.PI / 2) // Y+1 and pitch = PI/2 to look down void appViewer.worldView!.init(new Vec3(0, 64, 0)) } @@ -346,8 +77,11 @@ window.initialMenuStart = initialMenuStart const hasAppStatus = () => activeModalStack.some(m => m.reactType === 'app-status') -const modalStackUpdateChecks = () => { - // maybe start panorama +export const onAppViewerConfigUpdate = () => { + appViewer.inWorldRenderingConfig.skinTexturesProxy = miscUiState.appConfig?.skinTexturesProxy +} + +export const modalStackUpdateChecks = () => { if (!miscUiState.gameLoaded && !hasAppStatus()) { void initialMenuStart() } @@ -359,3 +93,112 @@ const modalStackUpdateChecks = () => { appViewer.inWorldRenderingConfig.foreground = activeModalStack.length === 0 } subscribe(activeModalStack, modalStackUpdateChecks) + +const connectAppWorldViewToBot = () => { + const entitiesObjectData = new Map() + bot._client.prependListener('spawn_entity', (data) => { + if (data.objectData && data.entityId !== undefined) { + entitiesObjectData.set(data.entityId, data.objectData) + } + }) + + const emitEntity = (e, name = 'entity') => { + if (!e) return + if (e === bot.entity) { + if (name === 'entity') { + appViewer.worldView?.emit('playerEntity', e) + } + return + } + if (!e.name) return // mineflayer received update for not spawned entity + e.objectData = entitiesObjectData.get(e.id) + appViewer.worldView?.emit(name as any, { + ...e, + pos: e.position, + username: e.username, + team: bot.teamMap[e.username] || bot.teamMap[e.uuid], + }) + } + + const eventListeners = { + entitySpawn (e: any) { + if (e.name === 'item_frame' || e.name === 'glow_item_frame') { + e.position.translate(0.5, 0.5, 0.5) + } + emitEntity(e) + }, + entityUpdate (e: any) { + emitEntity(e) + }, + entityEquip (e: any) { + emitEntity(e) + }, + entityMoved (e: any) { + emitEntity(e, 'entityMoved') + }, + entityGone (e: any) { + appViewer.worldView?.emit('entity', { id: e.id, delete: true }) + }, + chunkColumnLoad (pos: Vec3) { + const now = performance.now() + if (appViewer.worldView?.lastChunkReceiveTime) { + appViewer.worldView.chunkReceiveTimes.push(now - appViewer.worldView.lastChunkReceiveTime) + } + appViewer.worldView!.lastChunkReceiveTime = now + + if (appViewer.worldView?.waitingSpiralChunksLoad[`${pos.x},${pos.z}`]) { + appViewer.worldView?.waitingSpiralChunksLoad[`${pos.x},${pos.z}`](true) + delete appViewer.worldView?.waitingSpiralChunksLoad[`${pos.x},${pos.z}`] + } else if (appViewer.worldView?.loadedChunks[`${pos.x},${pos.z}`]) { + void appViewer.worldView?.loadChunk(pos, false, 'Received another chunkColumnLoad event while already loaded') + } else { + void appViewer.worldView?.loadChunk(pos, false, 'chunkColumnLoad') + } + appViewer.worldView?.chunkProgress() + }, + chunkColumnUnload (pos: Vec3) { + appViewer.worldView?.unloadChunk(pos) + }, + blockUpdate (oldBlock: any, newBlock: any) { + const stateId = newBlock.stateId ?? ((newBlock.type << 4) | newBlock.metadata) + appViewer.worldView?.emit('blockUpdate', { pos: oldBlock.position, stateId }) + }, + time () { + appViewer.worldView?.emit('time', bot.time.timeOfDay) + }, + end () { + appViewer.worldView?.emit('end') + }, + login () { + void appViewer.worldView?.updatePosition(bot.entity.position, true) + appViewer.worldView?.emit('playerEntity', bot.entity) + }, + respawn () { + void appViewer.worldView?.updatePosition(bot.entity.position, true) + appViewer.worldView?.emit('playerEntity', bot.entity) + appViewer.worldView?.emit('onWorldSwitch') + }, + } satisfies Partial + + + bot._client.on('update_light', ({ chunkX, chunkZ }) => { + const chunkPos = new Vec3(chunkX * 16, 0, chunkZ * 16) + if (!appViewer.worldView?.waitingSpiralChunksLoad[`${chunkX},${chunkZ}`] && appViewer.worldView?.loadedChunks[`${chunkX},${chunkZ}`]) { + void appViewer.worldView?.loadChunk(chunkPos, true, 'update_light') + } + }) + + for (const [evt, listener] of Object.entries(eventListeners)) { + bot.on(evt as any, listener) + } + + // eslint-disable-next-line guard-for-in + for (const id in bot.entities) { + const e = bot.entities[id] + try { + emitEntity(e) + } catch (err) { + console.error('error processing entity', err) + } + } +} diff --git a/src/appViewerLoad.ts b/src/appViewerLoad.ts index 23deb4f30..f467425ce 100644 --- a/src/appViewerLoad.ts +++ b/src/appViewerLoad.ts @@ -1,21 +1,42 @@ import { subscribeKey } from 'valtio/utils' -import createGraphicsBackend from 'renderer/viewer/three/graphicsBackend' +import { createGraphicsBackendSingleThread, createGraphicsBackendOffThread } from 'minecraft-renderer/src' +import { beforeRenderFrame } from './beforeRenderFrame' import { options } from './optionsStorage' -import { appViewer } from './appViewer' +import { appViewer, modalStackUpdateChecks } from './appViewer' import { miscUiState } from './globalState' import { watchOptionsAfterViewerInit } from './watchOptions' import { showNotification } from './react/NotificationProvider' export const appGraphicBackends = [ - createGraphicsBackend, + createGraphicsBackendSingleThread, + createGraphicsBackendOffThread, ] + +export const getCurrentGraphicsBackend = () => { + const id = options.activeRenderer === 'auto' ? appGraphicBackends[0].id : options.activeRenderer + + const backend = appGraphicBackends.find(backend => backend.id === id) + return { + id, + name: backend?.displayName ?? id ?? '', + backend, + noFallback: options.activeRenderer + } +} + const loadBackend = async () => { - let backend = appGraphicBackends.find(backend => backend.id === options.activeRenderer) - if (!backend) { + let { backend, noFallback } = getCurrentGraphicsBackend() + if (!backend && !noFallback) { showNotification(`No backend found for renderer ${options.activeRenderer}`, `Falling back to ${appGraphicBackends[0].id}`, true) backend = appGraphicBackends[0] } - await appViewer.loadBackend(backend) + if (appViewer.backend) { + appViewer.disconnectBackend() + } + if (backend) { + await appViewer.loadBackend(backend) + } + modalStackUpdateChecks() } window.loadBackend = loadBackend @@ -41,7 +62,8 @@ export const appLoadBackend = async () => { if (appViewer.currentDisplay === 'world' && bot) { appViewer.resetBackend(true) await loadBackend() - void appViewer.startWithBot() + const renderDistance = miscUiState.singleplayer ? options.renderDistance : options.multiplayerRenderDistance + void appViewer.startWithBot(bot, renderDistance) } }) } diff --git a/src/beforeRenderFrame.ts b/src/beforeRenderFrame.ts new file mode 100644 index 000000000..92b895fd9 --- /dev/null +++ b/src/beforeRenderFrame.ts @@ -0,0 +1,6 @@ +/** Per-frame hooks run from the main-thread animation loop (see appViewerLoad). */ +export const beforeRenderFrame: Array<() => void> = [] + +if (typeof window !== 'undefined') { + window.beforeRenderFrame = beforeRenderFrame +} diff --git a/src/benchmark.ts b/src/benchmark.ts index 42603a107..02a906e79 100644 --- a/src/benchmark.ts +++ b/src/benchmark.ts @@ -1,5 +1,5 @@ import { Vec3 } from 'vec3' -import { WorldRendererCommon } from 'renderer/viewer/lib/worldrendererCommon' +import { WorldRendererCommon } from 'minecraft-renderer/src/lib/worldrendererCommon' import prettyBytes from 'pretty-bytes' import { subscribe } from 'valtio' import { downloadAndOpenMapFromUrl } from './downloadAndOpenFile' diff --git a/src/botUtils.ts b/src/botUtils.ts index b97891754..571bbb806 100644 --- a/src/botUtils.ts +++ b/src/botUtils.ts @@ -1,4 +1,4 @@ -import { versionToNumber } from 'renderer/viewer/common/utils' +import { versionToNumber } from 'minecraft-renderer/src/lib/utils' import * as nbt from 'prismarine-nbt' export const displayClientChat = (textOrJson: string | Record) => { diff --git a/src/builtinCommands.ts b/src/builtinCommands.ts index a292c5cd0..5128fb1d7 100644 --- a/src/builtinCommands.ts +++ b/src/builtinCommands.ts @@ -1,7 +1,7 @@ import fs from 'fs' import { join } from 'path' import JSZip from 'jszip' -import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' +import { getThreeJsRendererMethods } from 'minecraft-renderer/src/three/threeJsMethods' import { fsState, readLevelDat } from './loadSave' import { closeWan, openToWanAndCopyJoinLink } from './localServerMultiplayer' import { copyFilesAsync, uniqueFileNameFromWorldName } from './browserfs' diff --git a/src/cameraRotationControls.ts b/src/cameraRotationControls.ts index 679a3a440..0d563d305 100644 --- a/src/cameraRotationControls.ts +++ b/src/cameraRotationControls.ts @@ -1,3 +1,4 @@ +import { getPlayerStateUtils } from 'minecraft-renderer/src' import { contro } from './controls' import { activeModalStack, isGameActive, miscUiState, showModal } from './globalState' import { options } from './optionsStorage' @@ -18,7 +19,7 @@ export function onCameraMove (e: MouseEvent | CameraMoveEvent) { if (!isGameActive(true)) return if (e.type === 'mousemove' && !document.pointerLockElement) return e.stopPropagation?.() - if (appViewer.playerState.utils.isSpectatingEntity()) return + if (getPlayerStateUtils(appViewer.playerState.reactive).isSpectatingEntity()) return const now = performance.now() // todo: limit camera movement for now to avoid unexpected jumps if (now - lastMouseMove < 4 && !options.preciseMouseInput) return diff --git a/src/chatUtils.ts b/src/chatUtils.ts index 849d58473..e968dd2a4 100644 --- a/src/chatUtils.ts +++ b/src/chatUtils.ts @@ -2,7 +2,7 @@ import { fromFormattedString, TextComponent } from '@xmcl/text-component' import type { IndexedData } from 'minecraft-data' -import { versionToNumber } from 'renderer/viewer/common/utils' +import { versionToNumber } from 'minecraft-renderer/src/lib/utils' export interface MessageFormatOptions { doShadow?: boolean diff --git a/src/controls.ts b/src/controls.ts index c478258db..195a09fc4 100644 --- a/src/controls.ts +++ b/src/controls.ts @@ -7,7 +7,8 @@ import { ControMax } from 'contro-max/build/controMax' import { CommandEventArgument, SchemaCommandInput } from 'contro-max/build/types' import { stringStartsWith } from 'contro-max/build/stringUtils' import { GameMode } from 'mineflayer' -import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' +import { getThreeJsRendererMethods } from 'minecraft-renderer/src/three/threeJsMethods' +import { getPlayerStateUtils } from 'minecraft-renderer/src' import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal, miscUiState, hideModal, hideAllModals } from './globalState' import { goFullscreen, isInRealGameSession, pointerLock, reloadChunks } from './utils' import { options } from './optionsStorage' @@ -144,7 +145,7 @@ const setSprinting = (state: boolean) => { } const isSpectatingEntity = () => { - return appViewer.playerState.utils.isSpectatingEntity() + return getPlayerStateUtils(playerState.reactive).isSpectatingEntity() } let lastScreenshotAt = 0 @@ -658,10 +659,11 @@ export const f3Keybinds: Array<{ { key: 'KeyA', action () { - //@ts-expect-error - const loadedChunks = Object.entries(worldView.loadedChunks).filter(([, v]) => v).map(([key]) => key.split(',').map(Number)) + const wv = appViewer.worldView + if (!wv) return + const loadedChunks = Object.entries(wv.loadedChunks).filter(([, v]) => v).map(([key]) => key.split(',').map(Number)) for (const [x, z] of loadedChunks) { - worldView!.unloadChunk({ x, z }) + wv.unloadChunk({ x, z }) } // for (const child of viewer.scene.children) { // if (child.name === 'chunk') { // should not happen diff --git a/src/customChannels.ts b/src/customChannels.ts index 6741c9ffd..e0bc4f5ac 100644 --- a/src/customChannels.ts +++ b/src/customChannels.ts @@ -1,6 +1,6 @@ import PItem from 'prismarine-item' import * as THREE from 'three' -import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' +import { getThreeJsRendererMethods } from 'minecraft-renderer/src/three/threeJsMethods' import { options, serverChangedSettings } from './optionsStorage' import { jeiCustomCategories } from './inventoryWindows' import { registerIdeChannels } from './core/ideChannels' diff --git a/src/defaultOptions.ts b/src/defaultOptions.ts index 14e3affe1..6b99ebb2a 100644 --- a/src/defaultOptions.ts +++ b/src/defaultOptions.ts @@ -1,6 +1,10 @@ +import { + RENDERER_DEFAULT_OPTIONS, + RENDERER_OPTIONS_META +} from 'minecraft-renderer/src/graphicsBackend/rendererDefaultOptions' + export const defaultOptions = { renderDistance: 3, - keepChunksDistance: 1, multiplayerRenderDistance: 3, closeConfirmation: true, autoFullScreen: false, @@ -19,7 +23,6 @@ export const defaultOptions = { volume: 50, enableMusic: true, musicVolume: 25, - fov: 75, defaultPerspective: 'first_person' as 'first_person' | 'third_person_back' | 'third_person_front', guiScale: 3, autoRequestCompletions: true, @@ -30,24 +33,15 @@ export const defaultOptions = { touchControlsSize: getTouchControlsSize(), touchMovementType: 'modern' as 'modern' | 'classic', touchInteractionType: 'classic' as 'classic' | 'buttons', - gpuPreference: 'default' as 'default' | 'high-performance' | 'low-power', - backgroundRendering: '20fps' as 'full' | '20fps' | '5fps', /** @unstable */ disableAssets: false, /** @unstable */ debugLogNotFrequentPackets: false, unimplementedContainers: false, - dayCycleAndLighting: true, - loadPlayerSkins: true, - renderEars: true, - lowMemoryMode: false, - starfieldRendering: true, - defaultSkybox: true, + ...RENDERER_DEFAULT_OPTIONS, enabledResourcepack: null as string | null, useVersionsTextures: 'latest', serverResourcePacks: 'prompt' as 'prompt' | 'always' | 'never', - showHand: true, - viewBobbing: true, displayRecordButton: true, packetsLoggerPreset: 'all' as 'all' | 'no-buffers', serversAutoVersionSelect: 'auto' as 'auto' | 'latest' | '1.20.4' | string, @@ -77,16 +71,11 @@ export const defaultOptions = { // antiAliasing: false, topRightTimeDisplay: 'only-fullscreen' as 'only-fullscreen' | 'always' | 'never', - clipWorldBelowY: undefined as undefined | number, // will be removed - disableBlockEntityTextures: false, singleplayerAutoSave: false, - showChunkBorders: false, // todo rename option - frameLimit: false as number | false, alwaysBackupWorldBeforeLoading: undefined as boolean | undefined | null, alwaysShowMobileControls: false, excludeCommunicationDebugEvents: [] as string[], preventDevReloadWhilePlaying: false, - numWorkers: 4, localServerOptions: { gameMode: 1 } as any, @@ -101,19 +90,10 @@ export const defaultOptions = { errorReporting: true, /** Actually might be useful */ showCursorBlockInSpectator: false, - renderEntities: true, - smoothLighting: true, - vanillaLook: false, - newVersionsLighting: false, chatSelect: true, autoOpenAuthModal: false, autoJump: 'auto' as 'auto' | 'always' | 'never', autoParkour: false, - vrSupport: true, // doesn't directly affect the VR mode, should only disable the button which is annoying to android users - vrPageGameRendering: false, - renderDebug: 'basic' as 'none' | 'advanced' | 'basic', - rendererPerfDebugOverlay: false, - // advanced bot options autoRespawn: false, mutedSounds: [] as string[], @@ -126,12 +106,7 @@ export const defaultOptions = { displayBossBars: true, disabledUiParts: [] as string[], neighborChunkUpdates: true, - highlightBlockColor: 'auto' as 'auto' | 'blue' | 'classic', - activeRenderer: 'threejs', - rendererSharedOptions: { - _experimentalSmoothChunkLoading: true, - _renderByChunks: false - } + activeRenderer: 'auto' as 'auto' | string | null } function getDefaultTouchControlsPositions () { @@ -225,37 +200,18 @@ export type OptionMeta = { } export const optionsMeta: Partial> = { - gpuPreference: { - possibleValues: [['default', 'Auto'], ['high-performance', 'Dedicated'], ['low-power', 'Low Power']] - }, - backgroundRendering: { - possibleValues: [ - ['full', 'NO'], - ['5fps', '5 FPS'], - ['20fps', '20 FPS'], - ] - }, + ...RENDERER_OPTIONS_META, activeRenderer: { possibleValues: [ ['threejs', 'Three.js (stable)'], ] }, - renderDebug: { - possibleValues: ['advanced', 'basic', 'none'] - }, serverResourcePacks: { possibleValues: ['prompt', 'always', 'never'] }, showMinimap: { possibleValues: ['always', 'singleplayer', 'never'] }, - highlightBlockColor: { - possibleValues: [ - ['auto', 'Auto'], - ['blue', 'Blue'], - ['classic', 'Classic'] - ] - }, wysiwygSignEditor: { possibleValues: ['auto', 'always', 'never'] }, diff --git a/src/devReload.ts b/src/devReload.ts index e778d8d4a..a1141a568 100644 --- a/src/devReload.ts +++ b/src/devReload.ts @@ -1,4 +1,4 @@ -import { isMobile } from 'renderer/viewer/lib/simpleUtils' +import { isMobile } from 'minecraft-renderer/src/lib/simpleUtils' if (process.env.NODE_ENV === 'development') { // mobile devtools diff --git a/src/devtools.ts b/src/devtools.ts index 1f8ef8e82..beb7b50f9 100644 --- a/src/devtools.ts +++ b/src/devtools.ts @@ -1,7 +1,7 @@ // global variables useful for debugging import fs from 'fs' -import { WorldRendererThree } from 'renderer/viewer/three/worldrendererThree' +import { WorldRendererThree } from 'minecraft-renderer/src/three/worldRendererThree' import { enable, disable, enabled } from 'debug' import { Vec3 } from 'vec3' diff --git a/src/dragndrop.ts b/src/dragndrop.ts index 5a16bc05d..22490f21c 100644 --- a/src/dragndrop.ts +++ b/src/dragndrop.ts @@ -3,7 +3,7 @@ import fs from 'fs' import * as nbt from 'prismarine-nbt' import RegionFile from 'prismarine-provider-anvil/src/region' import { versions } from 'minecraft-data' -import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' +import { getThreeJsRendererMethods } from 'minecraft-renderer/src/three/threeJsMethods' import { openWorldDirectory, openWorldZip } from './browserfs' import { isGameActive } from './globalState' import { showNotification } from './react/NotificationProvider' diff --git a/src/entities.ts b/src/entities.ts index 3f3db00ed..8a87c117d 100644 --- a/src/entities.ts +++ b/src/entities.ts @@ -1,10 +1,11 @@ import { Entity } from 'prismarine-entity' -import { versionToNumber } from 'renderer/viewer/common/utils' +import { versionToNumber } from 'minecraft-renderer/src/lib/utils' import tracker from '@nxg-org/mineflayer-tracker' import { loader as autoJumpPlugin } from '@nxg-org/mineflayer-auto-jump' import { subscribeKey } from 'valtio/utils' -import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' +import { getThreeJsRendererMethods } from 'minecraft-renderer/src/three/threeJsMethods' import { Team } from 'mineflayer' +import { getPlayerStateUtils } from 'minecraft-renderer/src' import { options, watchValue } from './optionsStorage' import { gameAdditionalState, miscUiState } from './globalState' import { EntityStatus } from './mineflayer/entityStatus' @@ -204,7 +205,7 @@ customEvents.on('gameLoaded', () => { bot._client.on('camera', (packet) => { if (bot.player.entity.id === packet.cameraId) { - if (appViewer.playerState.utils.isSpectatingEntity() && appViewer.playerState.reactive.cameraSpectatingEntity) { + if (getPlayerStateUtils(appViewer.playerState.reactive).isSpectatingEntity() && appViewer.playerState.reactive.cameraSpectatingEntity) { const entity = bot.entities[appViewer.playerState.reactive.cameraSpectatingEntity] appViewer.playerState.reactive.cameraSpectatingEntity = undefined if (entity) { @@ -285,7 +286,7 @@ customEvents.on('gameLoaded', () => { bot.on('teamMemberAdded', (team: Team, members: string[]) => { if (members.includes(bot.username) && appViewer.playerState.reactive.team?.team !== team.team) { - appViewer.playerState.reactive.team = team + appViewer.playerState.reactive.team = team as any // Player was added to a team, need to check if any entities need updating updateEntityNameTags(team) } else if (doEntitiesNeedUpdating(team)) { diff --git a/src/env.d.ts b/src/env.d.ts index 5dbe3311b..fb7e2b3be 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -10,6 +10,7 @@ declare namespace NodeJS { DISABLE_SERVICE_WORKER?: 'true' | 'false' CONFIG_JSON_SOURCE?: 'BUNDLED' | 'REMOTE' LOCAL_CONFIG_FILE?: string + CONFIG_JSON?: string BUILD_VERSION?: string /** Set at compile time: DD.MM.YY (local date when the config ran). */ BUILD_DISPLAY_DATE?: string diff --git a/src/getCollisionShapes.ts b/src/getCollisionShapes.ts index 383adc0ee..bbf3e9211 100644 --- a/src/getCollisionShapes.ts +++ b/src/getCollisionShapes.ts @@ -1,4 +1,5 @@ import { getRenamedData } from 'flying-squid/dist/blockRenames' +import { versionToNumber } from 'minecraft-renderer/src/lib/utils' import collisionShapesInit from '../generated/latestBlockCollisionsShapes.json' // defining globally to be used in loaded data, not sure of better workaround @@ -6,9 +7,23 @@ window.globalGetCollisionShapes = (version) => { // todo use the same in resourcepack const versionFrom = collisionShapesInit.version const renamedBlocks = getRenamedData('blocks', Object.keys(collisionShapesInit.blocks), versionFrom, version) + const blocks = Object.fromEntries(Object.entries(collisionShapesInit.blocks).map(([, shape], i) => [renamedBlocks[i], shape])) + + // Compatibility fallbacks for renames that `getRenamedData` does not + // (yet) cover. Without these, `prismarine-block` spams + // `No shape found for block ` and falls back to a default shape, + // which is also visually/functionally wrong (e.g. an invisible cube + // hitbox where a thin pillar should be). + // + // chain -> iron_chain in 1.21.9. Shapes are identical across all 6 + // axis states. + if (versionToNumber(version) < versionToNumber('1.21.9') && blocks.iron_chain && !blocks.chain) { + blocks.chain = blocks.iron_chain + } + const collisionShapes = { ...collisionShapesInit, - blocks: Object.fromEntries(Object.entries(collisionShapesInit.blocks).map(([, shape], i) => [renamedBlocks[i], shape])) + blocks } return collisionShapes } diff --git a/src/globals.d.ts b/src/globals.d.ts index 7a2c6f1f1..3dab50200 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -11,8 +11,7 @@ declare const bot: Omit & { } } declare const __type_bot: typeof bot -declare const appViewer: import('./appViewer').AppViewer -declare const worldView: import('renderer/viewer/lib/worldDataEmitter').WorldDataEmitter | undefined +declare const appViewer: import('minecraft-renderer/src').AppViewer declare const addStatPerSec: (name: string) => void declare const localServer: import('flying-squid/dist/index').FullServer & { options } | undefined /** all currently loaded mc data */ diff --git a/src/googledrive.ts b/src/googledrive.ts index 5e5e9ae96..307bab4f5 100644 --- a/src/googledrive.ts +++ b/src/googledrive.ts @@ -1,7 +1,7 @@ import { GoogleOAuthProvider, useGoogleLogin } from '@react-oauth/google' import { proxy, ref, subscribe } from 'valtio' import React from 'react' -import { loadScript } from 'renderer/viewer/lib/utils' +import { loadScript } from 'minecraft-renderer/src/lib/utils' import { loadGoogleDriveApi, loadInMemorySave } from './react/SingleplayerProvider' import { setLoadingScreenStatus } from './appStatus' import { showOptionsModal } from './react/SelectOption' diff --git a/src/index.ts b/src/index.ts index 0aaa3c668..97bf7cbca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -67,7 +67,6 @@ import { registerServiceWorker } from './serviceWorker' import { appStatusState, quickDevReconnect } from './react/AppStatusProvider' import { fsState } from './loadSave' -import { watchFov } from './rendererUtils' import { loadInMemorySave } from './react/SingleplayerProvider' import { possiblyHandleStateVariable } from './googledrive' @@ -106,7 +105,6 @@ import { appLoadBackend } from './appViewerLoad' import { FORBIDDEN_VERSION_THRESHOLD } from './supportedVersions.mjs' window.debug = debug -window.beforeRenderFrame = [] // ACTUAL CODE @@ -114,13 +112,12 @@ if (!isPlayground) { void appLoadBackend() } if (isPlayground) { - void import('renderer/playground/playground') + void import('minecraft-renderer/src/playground/playground') } void registerServiceWorker().then(() => { mainMenuState.serviceWorkerLoaded = true }) -watchFov() initCollisionShapes() initializePacketsReplay() onAppLoad() @@ -847,9 +844,8 @@ export async function connect (connectOptions: ConnectOptions) { console.log('bot spawned - starting viewer') await appViewer.startWorld(bot.world, renderDistance) - appViewer.worldView!.listenToBot(bot) if (appViewer.backend) { - void appViewer.worldView!.init(bot.entity.position) + void appViewer.worldView!.init(bot.entity.position, bot) } initMotionTracking() diff --git a/src/inventoryWindows.ts b/src/inventoryWindows.ts index 1e4984f0f..718e6dd43 100644 --- a/src/inventoryWindows.ts +++ b/src/inventoryWindows.ts @@ -4,7 +4,8 @@ import { RecipeItem } from 'minecraft-data' import { flat } from '@xmcl/text-component' import { splitEvery, equals } from 'rambda' import PItem, { Item } from 'prismarine-item' -import { versionToNumber } from 'renderer/viewer/common/utils' +import { versionToNumber } from 'minecraft-renderer/src/lib/utils' +import { renderSlot } from 'minecraft-renderer/src/three/renderSlot' import { getInventoryType } from 'minecraft-inventory/src/registry' import type { RecipeGuide, ItemStack as InventoryItemStack } from 'minecraft-inventory/src/types' import type { JEIItem } from 'minecraft-inventory/src/components/JEI/JEI' diff --git a/src/loadSave.ts b/src/loadSave.ts index f1676cff3..2a98b7ba9 100644 --- a/src/loadSave.ts +++ b/src/loadSave.ts @@ -3,7 +3,7 @@ import path from 'path' import * as nbt from 'prismarine-nbt' import { proxy } from 'valtio' import { gzip } from 'node-gzip' -import { versionToNumber } from 'renderer/viewer/common/utils' +import { versionToNumber } from 'minecraft-renderer/src/lib/utils' import { options } from './optionsStorage' import { nameToMcOfflineUUID, disconnect } from './flyingSquidUtils' import { existsViaStats, forceCachedDataPaths, forceRedirectPaths, mkdirRecursive } from './browserfs' diff --git a/src/mineflayer/cameraShake.ts b/src/mineflayer/cameraShake.ts index 9e271da57..9cfdcc46e 100644 --- a/src/mineflayer/cameraShake.ts +++ b/src/mineflayer/cameraShake.ts @@ -1,4 +1,4 @@ -import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' +import { getThreeJsRendererMethods } from 'minecraft-renderer/src/three/threeJsMethods' customEvents.on('mineflayerBotCreated', () => { customEvents.on('hurtAnimation', (yaw) => { diff --git a/src/mineflayer/items.ts b/src/mineflayer/items.ts index 48d0dfe03..359c6bfb4 100644 --- a/src/mineflayer/items.ts +++ b/src/mineflayer/items.ts @@ -1,10 +1,11 @@ import mojangson from 'mojangson' import nbt from 'prismarine-nbt' import { fromFormattedString } from '@xmcl/text-component' -import { getItemSelector, ItemSpecificContextProperties, PlayerStateRenderer } from 'renderer/viewer/lib/basePlayerState' +import { getItemSelector, PlayerStateRenderer } from 'minecraft-renderer/src/playerState/playerState' import { getItemDefinition } from 'mc-assets/dist/itemDefinitions' +import { ItemSpecificContextProperties } from 'minecraft-renderer/src/playerState/types' +import { ResourcesManagerCommon } from 'minecraft-renderer/src/resourcesManager' import { MessageFormatPart } from '../chatUtils' -import { ResourcesManager, ResourcesManagerCommon, ResourcesManagerTransferred } from '../resourcesManager' type RenderSlotComponent = { type: string, @@ -129,7 +130,7 @@ export const getItemModelName = (item: GeneralInputItem, specificProps: ItemSpec const itemSelector = getItemSelector(playerState, { ...specificProps }) - const modelFromDef = getItemDefinition(appViewer.resourcesManager.itemsDefinitionsStore, { + const modelFromDef = getItemDefinition(appViewer.resourcesManager.currentResources!.itemsDefinitionsStore, { name: itemModelName, version: appViewer.resourcesManager.currentResources!.version, properties: itemSelector diff --git a/src/mineflayer/maps.ts b/src/mineflayer/maps.ts index 5e9682055..748f89bb8 100644 --- a/src/mineflayer/maps.ts +++ b/src/mineflayer/maps.ts @@ -1,6 +1,6 @@ import { mapDownloader } from 'mineflayer-item-map-downloader' import { setImageConverter } from 'mineflayer-item-map-downloader/lib/util' -import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' +import { getThreeJsRendererMethods } from 'minecraft-renderer/src/three/threeJsMethods' setImageConverter((buf: Uint8Array) => { const canvas = document.createElement('canvas') diff --git a/src/mineflayer/playerState.ts b/src/mineflayer/playerState.ts index f472d4233..2014fafe1 100644 --- a/src/mineflayer/playerState.ts +++ b/src/mineflayer/playerState.ts @@ -1,10 +1,67 @@ -import { HandItemBlock } from 'renderer/viewer/three/holdingBlock' -import { getInitialPlayerState, getPlayerStateUtils, PlayerStateReactive, PlayerStateRenderer, PlayerStateUtils } from 'renderer/viewer/lib/basePlayerState' +import { getInitialPlayerState, getPlayerStateUtils, PlayerStateReactive, PlayerStateRenderer, PlayerStateUtils } from 'minecraft-renderer/src/playerState/playerState' import { subscribe } from 'valtio' import { subscribeKey } from 'valtio/utils' +import { HandItemBlock } from 'minecraft-renderer/src/playerState/types' +import { beforeRenderFrame } from '../beforeRenderFrame' import { gameAdditionalState } from '../globalState' import { options } from '../optionsStorage' +const BASE_MOVEMENT_SPEED = 0.1 +const FOV_EFFECT_SCALE = 1 +const ZOOM_FOV = 30 + +const updateFovMultiplier = () => { + if (!playerState.ready || !playerState.reactive) return + + let fovModifier = 1 + + if (playerState.reactive.flying) { + fovModifier *= 1.05 + } + + const movementSpeedAttr = ( + bot.entity?.attributes?.['generic.movement_speed'] + ?? bot.entity?.attributes?.['minecraft:movement_speed'] + ?? bot.entity?.attributes?.['movement_speed'] + ?? bot.entity?.attributes?.['minecraft:movementSpeed'] + )?.value ?? BASE_MOVEMENT_SPEED + + let currentSpeed = BASE_MOVEMENT_SPEED + if (bot.controlState?.sprint && !bot.controlState?.sneak) { + currentSpeed *= 1.3 + } + fovModifier *= (currentSpeed / movementSpeedAttr + 1) / 2 + + if (Math.abs(BASE_MOVEMENT_SPEED) < Number.EPSILON || !Number.isFinite(fovModifier)) { + fovModifier = 1 + } + + const heldItem = playerState.reactive.heldItemMain + if (heldItem?.name === 'bow' && playerState.reactive.itemUsageTicks > 0) { + let usageProgress = playerState.reactive.itemUsageTicks / 20 + if (usageProgress > 1) { + usageProgress = 1 + } else { + usageProgress *= usageProgress + } + fovModifier *= 1 - usageProgress * 0.15 + } + + fovModifier = 1 + (fovModifier - 1) * FOV_EFFECT_SCALE + + const baseFov = gameAdditionalState.isZooming ? ZOOM_FOV : options.fov + playerState.reactive.fovMultiplier = (baseFov / options.fov) * fovModifier +} + +const startFovMultiplierUpdates = () => { + if (!beforeRenderFrame.includes(updateFovMultiplier)) { + beforeRenderFrame.push(updateFovMultiplier) + } + customEvents.on('gameLoaded', () => { + updateFovMultiplier() + }) +} + /** * can be used only in main thread. Mainly for more convenient reactive state updates. * In renderer/ directory, use PlayerStateControllerRenderer type or worldRenderer.playerState. @@ -42,9 +99,13 @@ export class PlayerStateControllerMain { private botCreated () { console.log('bot created & plugins injected') - this.reactive = getInitialPlayerState() - this.reactive.perspective = options.defaultPerspective + + this.reactive = appViewer.playerState.reactive this.utils = getPlayerStateUtils(this.reactive) + + const fresh = getInitialPlayerState() + Object.assign(this.reactive, fresh) + this.reactive.perspective = options.defaultPerspective this.onBotCreatedOrGameJoined() const handleDimensionData = (data) => { @@ -91,6 +152,7 @@ export class PlayerStateControllerMain { bot.on('physicsTick', () => { if (this.isUsingItem) this.reactive.itemUsageTicks++ updateSneakingOrFlying() + this.updateWalkDistAndBob() }) // todo move from gameAdditionalState to reactive directly subscribeKey(gameAdditionalState, 'isSneaking', () => { @@ -110,7 +172,7 @@ export class PlayerStateControllerMain { this.reactive.gameMode = bot.game?.gameMode customEvents.on('gameLoaded', () => { - this.reactive.team = bot.teamMap[bot.username] + this.reactive.team = bot.teamMap[bot.username] as any }) this.watchReactive() @@ -150,6 +212,27 @@ export class PlayerStateControllerMain { } } + private updateWalkDistAndBob () { + if (!bot?.entity || this.disableStateUpdates) return + + const { velocity } = bot.entity + const horizontalDist = Math.hypot(velocity.x, velocity.z) + + // Save previous values for interpolation + this.reactive.prevWalkDist = this.reactive.walkDist + this.reactive.prevBob = this.reactive.bob + + // Accumulate walk distance with dampening factor + this.reactive.walkDist += horizontalDist * 0.6 + + // Smooth bob amplitude — vanilla: onGround && !isDeadOrDying && !isSwimming + // isSwimming = sprinting + in water (not just touching water) + const isSwimming = bot.controlState.sprint && this.reactive.inWater + const isDeadOrDying = (bot.entity.health ?? 20) <= 0 + const bobTarget = (bot.entity.onGround && !isDeadOrDying && !isSwimming) ? Math.min(0.1, horizontalDist) : 0 + this.reactive.bob += (bobTarget - this.reactive.bob) * 0.4 + } + // #region Held Item State private updateHeldItem (isLeftHand: boolean) { const newItem = isLeftHand ? bot.inventory.slots[45] : bot.heldItem @@ -206,3 +289,5 @@ export class PlayerStateControllerMain { export const playerState = new PlayerStateControllerMain() window.playerState = playerState + +startFovMultiplierUpdates() diff --git a/src/mineflayer/plugins/index.ts b/src/mineflayer/plugins/index.ts index 5004f9689..8c9d3fe2f 100644 --- a/src/mineflayer/plugins/index.ts +++ b/src/mineflayer/plugins/index.ts @@ -1,6 +1,7 @@ import { lastConnectOptions } from '../../appStatus' import mouse from './mouse' import packetsPatcher from './packetsPatcher' +import mapChunkListener from './mapChunkListener' import { localRelayServerPlugin } from './packetsRecording' import ping from './ping' import webFeatures from './webFeatures' @@ -8,6 +9,7 @@ import webFeatures from './webFeatures' // register webFeatures() packetsPatcher() +mapChunkListener() customEvents.on('mineflayerBotCreated', () => { diff --git a/src/mineflayer/plugins/mapChunkListener.ts b/src/mineflayer/plugins/mapChunkListener.ts new file mode 100644 index 000000000..4dd86144e --- /dev/null +++ b/src/mineflayer/plugins/mapChunkListener.ts @@ -0,0 +1,273 @@ +/** + * Capture raw `map_chunk` packet bytes from mineflayer and forward them + * to the WASM mesher worker (via worldView → worldrendererCommon → + * worker.postMessage). The worker can then call `parseMapChunkV18Plus` + * directly on those bytes and skip the JS hot loop `convertChunkToWasm` + * for protocol >= 757 (1.18+). + * + * For protocol 756 (1.17/1.17.1) the wire format differs (separate + * `update_light` packet, flat biomes, explicit section bit-mask), so we + * subscribe to the parsed `map_chunk` event instead and forward the + * already-extracted `chunkData` + `bitMap` to the worker, which calls + * `parseChunkSectionsV17`. + * + * Mineflayer is left untouched: it keeps parsing the column for + * `bot.blockAt`, physics, inventory, etc. We just piggy-back on the same + * packet event. + */ + +import { appViewer } from '../../appViewer' + +// 1.17 max bits per block (long-array values use 15 bpv when bitsPerBlock +// exceeds the per-section palette threshold of 8). Matches +// `wasm-mesher/src/parser_v17.rs::MAX_BITS_PER_BLOCK_V17`. +const MAX_BITS_PER_BLOCK_V17 = 15 + +const readVarInt = (buf: Buffer, offset: number): { value: number, bytesRead: number } | null => { + let value = 0 + let shift = 0 + let pos = offset + while (pos < buf.length) { + const b = buf.readUInt8(pos++) + value |= (b & 0x7F) << shift + if ((b & 0x80) === 0) return { value, bytesRead: pos - offset } + shift += 7 + if (shift > 35) return null + } + return null +} + +// minecraft-protocol parses `i64` either as a `[hi, lo]` number pair or as +// a native bigint depending on the build. Normalise to flat +// `[lo0, hi0, lo1, hi1, ...]` u32 pairs the WASM parser expects. +const bitMapToLoHi = (bitMap: any[]): Uint32Array | null => { + if (!Array.isArray(bitMap)) return null + const out = new Uint32Array(bitMap.length * 2) + for (const [i, entry] of bitMap.entries()) { + if (typeof entry === 'bigint') { + out[i * 2] = Number(entry & 0xff_ff_ff_ffn) >>> 0 + out[i * 2 + 1] = Number((entry >> 32n) & 0xff_ff_ff_ffn) >>> 0 + } else if (Array.isArray(entry) && entry.length === 2) { + // protodef i64 → [hi, lo] + const [hi, lo] = entry + out[i * 2] = (lo as number) >>> 0 + out[i * 2 + 1] = (hi as number) >>> 0 + } else { + return null + } + } + return out +} + +const resolveNumSections = (chunkX: number, chunkZ: number, fallback: number): number => { + try { + const column: any = (bot as any).world?.getColumn?.(chunkX, chunkZ) + if (column) { + const n = column.numSections + ?? (column.worldHeight ? column.worldHeight >> 4 : undefined) + if (typeof n === 'number') return n + } + } catch {} + const worldHeight = (bot as any).game?.height + ?? (bot as any).world?.worldHeight + return typeof worldHeight === 'number' ? worldHeight >> 4 : fallback +} + +export default () => { + customEvents.on('mineflayerBotCreated', () => { + botInit() + }) +} + +const botInit = () => { + bot._client.on('raw.map_chunk', (rawBuffer: Buffer | Uint8Array) => { + try { + const buf = Buffer.isBuffer(rawBuffer) ? rawBuffer : Buffer.from(rawBuffer) + // Skip the leading varint packet-id; the WASM parser expects the + // body to start with chunkX (i32 BE) chunkZ (i32 BE). + const pid = readVarInt(buf, 0) + if (!pid || buf.length < pid.bytesRead + 8) return + const chunkX = buf.readInt32BE(pid.bytesRead) + const chunkZ = buf.readInt32BE(pid.bytesRead + 4) + + const protocol = (bot as any).protocolVersion as number | undefined + // 1.18+ (protocol 757+): the raw bytes go straight to + // `parseMapChunkV18Plus`. Earlier protocols use a different wire + // format and are handled by the parsed-packet listener below. + if (typeof protocol !== 'number' || protocol < 757) return + + // Block-coord origin used by the renderer's chunk pipeline. + const x = chunkX * 16 + const z = chunkZ * 16 + + const numSections = resolveNumSections(chunkX, chunkZ, 24) + + // Copy out of mineflayer's buffer so the WASM worker can keep the + // bytes around (mineflayer may pool/reuse the underlying memory). + const rawPacket = new Uint8Array(buf.byteLength) + rawPacket.set(buf) + + appViewer.backend?.backendMethods?.feedChunkPacket?.({ + kind: 'setRawMapChunk', + x, z, rawPacket, protocol, numSections, + }) + } catch (err) { + console.warn('[mapChunkListener] failed to forward raw map_chunk:', err) + } + }) + + // 1.17 / 1.17.1 path. mineflayer's parsed packet already extracted the + // bit-mask, biomes and the chunkData buffer; we hand them straight to + // the worker so it can call `parseChunkSectionsV17`. + bot._client.on('map_chunk' as any, (packet: any) => { + try { + const protocol = (bot as any).protocolVersion as number | undefined + if (typeof protocol !== 'number' || protocol >= 757) return + // We only support 1.17/1.17.1 (protocol 755/756) for now. Older + // protocols have yet another packet shape and stay on the JS path. + if (protocol < 755) return + + const chunkX = packet.x as number + const chunkZ = packet.z as number + if (typeof chunkX !== 'number' || typeof chunkZ !== 'number') return + + const bitMapLoHi = bitMapToLoHi(packet.bitMap) + if (!bitMapLoHi) return + + const chunkDataBuf: Buffer | undefined = packet.chunkData + if (!chunkDataBuf || chunkDataBuf.length === 0) return + const chunkData = new Uint8Array(chunkDataBuf.byteLength) + chunkData.set(chunkDataBuf) + + const numSections = resolveNumSections(chunkX, chunkZ, 16) + + let biomes: Int32Array | undefined + if (Array.isArray(packet.biomes) && packet.biomes.length > 0) { + biomes = Int32Array.from(packet.biomes as number[]) + } + + appViewer.backend?.backendMethods?.feedChunkPacket?.({ + kind: 'setParsedMapChunkV17', + x: chunkX * 16, + z: chunkZ * 16, + protocol, + numSections, + maxBitsPerBlock: MAX_BITS_PER_BLOCK_V17, + chunkData, + bitMapLoHi, + biomes, + }) + } catch (err) { + console.warn('[mapChunkListener] failed to forward parsed map_chunk (1.17):', err) + } + }) + + // 1.17 light arrives in a separate `update_light` packet. We forward the + // raw bytes (including the leading varint packet-id) to the worker — it + // calls `parseUpdateLightV17` which extracts chunkX/Z and the per-block + // sky/block-light arrays in one shot. The worker keys the cache by the + // (x, z) it gets back from WASM, so JS doesn't need to peek at varints. + bot._client.on('raw.update_light' as any, (rawBuffer: Buffer | Uint8Array) => { + try { + const protocol = (bot as any).protocolVersion as number | undefined + if (typeof protocol !== 'number' || protocol >= 757 || protocol < 755) return + + const buf = Buffer.isBuffer(rawBuffer) ? rawBuffer : Buffer.from(rawBuffer) + if (buf.length === 0) return + + const rawPacket = new Uint8Array(buf.byteLength) + rawPacket.set(buf) + + // 1.17 always has worldHeight=256 → 16 sections; resolveNumSections + // would need (chunkX, chunkZ) which we don't decode in JS. The + // game-level fallback is exactly what we want here. + const numSections = ((bot as any).game?.height + ?? (bot as any).world?.worldHeight + ?? 256) >> 4 + + appViewer.backend?.backendMethods?.feedChunkPacket?.({ + kind: 'setUpdateLightV17', + protocol, + numSections, + rawPacket, + }) + } catch (err) { + console.warn('[mapChunkListener] failed to forward raw update_light (1.17):', err) + } + }) + + // 1.16.x (protocol 735..754) parsed map_chunk path. The 1.16 wire format + // uses a varint bit-mask (single number, only 16 sections) and inline + // biomes as a flat varint[1024]. Hand the parsed payload to the worker + // so `parser_v16_v17` can decode the section blob. + bot._client.on('map_chunk' as any, (packet: any) => { + try { + const protocol = (bot as any).protocolVersion as number | undefined + if (typeof protocol !== 'number' || protocol < 735 || protocol > 754) return + + const chunkX = packet.x as number + const chunkZ = packet.z as number + if (typeof chunkX !== 'number' || typeof chunkZ !== 'number') return + + const chunkDataBuf: Buffer | undefined = packet.chunkData + if (!chunkDataBuf || chunkDataBuf.length === 0) return + const chunkData = new Uint8Array(chunkDataBuf.byteLength) + chunkData.set(chunkDataBuf) + + const bitMap = typeof packet.bitMap === 'number' ? packet.bitMap : Number(packet.bitMap) + if (!Number.isFinite(bitMap)) return + + const biomesSrc: number[] | undefined = Array.isArray(packet.biomes) ? packet.biomes : undefined + const biomes = Int32Array.from(biomesSrc ?? []) + + appViewer.backend?.backendMethods?.feedChunkPacket?.({ + kind: 'setParsedMapChunkV16', + x: chunkX, + z: chunkZ, + chunkData, + bitMap, + biomes, + protocol, + }) + } catch (err) { + console.warn('[mapChunkListener] failed to forward parsed map_chunk (1.16):', err) + } + }) + + // 1.16.x update_light. Same shape as the 1.17 raw forward, but we also + // extract chunkX/Z in JS (skip the varint packet-id, then two varints). + bot._client.on('raw.update_light' as any, (rawBuffer: Buffer | Uint8Array) => { + try { + const protocol = (bot as any).protocolVersion as number | undefined + if (typeof protocol !== 'number' || protocol < 735 || protocol > 754) return + + const buf = Buffer.isBuffer(rawBuffer) ? rawBuffer : Buffer.from(rawBuffer) + if (buf.length === 0) return + + const pid = readVarInt(buf, 0) + if (!pid) return + const xv = readVarInt(buf, pid.bytesRead) + if (!xv) return + const zv = readVarInt(buf, pid.bytesRead + xv.bytesRead) + if (!zv) return + // varints encode signed values via zig-zag in some packets, but + // mineflayer-protocol's update_light uses plain varint for chunkX/Z + // (which is what the WASM parser expects to receive verbatim). + const x = Math.trunc(xv.value) + const z = Math.trunc(zv.value) + + const rawPacket = new Uint8Array(buf.byteLength) + rawPacket.set(buf) + + appViewer.backend?.backendMethods?.feedChunkPacket?.({ + kind: 'setUpdateLightV16', + x, + z, + rawPacket, + protocol, + }) + } catch (err) { + console.warn('[mapChunkListener] failed to forward raw update_light (1.16):', err) + } + }) +} diff --git a/src/mineflayer/plugins/mouse.ts b/src/mineflayer/plugins/mouse.ts index 1ca73ceb2..83f09728b 100644 --- a/src/mineflayer/plugins/mouse.ts +++ b/src/mineflayer/plugins/mouse.ts @@ -1,7 +1,7 @@ import { createMouse } from 'mineflayer-mouse' import { Bot } from 'mineflayer' import { Block } from 'prismarine-block' -import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' +import { getThreeJsRendererMethods } from 'minecraft-renderer/src/three/threeJsMethods' import { isGameActive, showModal } from '../../globalState' import { isCypress } from '../../standaloneUtils' diff --git a/src/mineflayer/plugins/ping.ts b/src/mineflayer/plugins/ping.ts index d6a23554b..e902dbf21 100644 --- a/src/mineflayer/plugins/ping.ts +++ b/src/mineflayer/plugins/ping.ts @@ -1,4 +1,4 @@ -import { versionToNumber } from 'renderer/viewer/common/utils' +import { versionToNumber } from 'minecraft-renderer/src/lib/utils' export default () => { let i = 0 diff --git a/src/optimizeJson.ts b/src/optimizeJson.ts index a7fe7d4e5..b948b3b1a 100644 --- a/src/optimizeJson.ts +++ b/src/optimizeJson.ts @@ -1,4 +1,4 @@ -import { versionToNumber } from 'renderer/viewer/common/utils' +import { versionToNumber } from 'minecraft-renderer/src/lib/utils' type IdMap = Record diff --git a/src/optionsGuiScheme.tsx b/src/optionsGuiScheme.tsx index e28f10f68..1af21cd87 100644 --- a/src/optionsGuiScheme.tsx +++ b/src/optionsGuiScheme.tsx @@ -1,8 +1,9 @@ -import { useEffect, useRef, useState } from 'react' +import { useEffect, useMemo, useRef, useState } from 'react' import { useSnapshot } from 'valtio' -import { openURL } from 'renderer/viewer/lib/simpleUtils' import { noCase } from 'change-case' import { versionToNumber } from 'mc-assets/dist/utils' +import { openURL } from 'minecraft-renderer/src/lib/simpleUtils' +import Logo from 'minecraft-renderer/logo.webp' import { gameAdditionalState, miscUiState, openOptionsMenu, showModal } from './globalState' import { AppOptions, getChangedSettings, options } from './optionsStorage' import { showResetSettingsModal } from './react/AllSettingsEditor' @@ -22,11 +23,58 @@ import { createNotificationProgressReporter } from './core/progressReporter' import { customKeymaps } from './controls' import { appStorage } from './react/appStorageProvider' import { exportData, importData } from './core/importExport' +import { appGraphicBackends, getCurrentGraphicsBackend } from './appViewerLoad' export const guiOptionsScheme: { [t in OptionsGroupType]: Array<{ [K in keyof AppOptions]?: Partial> } & { custom? }> } = { render: [ + { + custom () { + const { activeRenderer } = useSnapshot(options) + const { name, id } = useMemo(() => getCurrentGraphicsBackend(), [activeRenderer]) + + return
diff --git a/src/react/MessageFormatted.tsx b/src/react/MessageFormatted.tsx index 40bf14043..df0678feb 100644 --- a/src/react/MessageFormatted.tsx +++ b/src/react/MessageFormatted.tsx @@ -2,7 +2,7 @@ import { ComponentProps } from 'react' import { render } from '@xmcl/text-component' import { noCase } from 'change-case' import mojangson from 'mojangson' -import { openURL } from 'renderer/viewer/lib/simpleUtils' +import { openURL } from 'minecraft-renderer/src/lib/simpleUtils' import { MessageFormatOptions, MessageFormatPart } from '../chatUtils' import { lastConnectOptions } from '../appStatus' import { runAuthFlow } from '../core/authModal' diff --git a/src/react/MinimapDrawer.ts b/src/react/MinimapDrawer.ts index 113954dab..3ea6e4c65 100644 --- a/src/react/MinimapDrawer.ts +++ b/src/react/MinimapDrawer.ts @@ -27,7 +27,7 @@ export interface DrawerAdapter extends TypedEventEmitter { } export type ChunkInfo = { - heightmap: Uint8Array, + heightmap: Int16Array | Uint8Array, colors: string[], } diff --git a/src/react/MinimapProvider.tsx b/src/react/MinimapProvider.tsx index 58e50d2f7..4db2ed443 100644 --- a/src/react/MinimapProvider.tsx +++ b/src/react/MinimapProvider.tsx @@ -2,18 +2,18 @@ import { useEffect } from 'react' import { simplify } from 'prismarine-nbt' import RegionFile from 'prismarine-provider-anvil/src/region' import { Vec3 } from 'vec3' -import { versionToNumber } from 'renderer/viewer/common/utils' +import { versionToNumber } from 'minecraft-renderer/src/lib/utils' import { WorldWarp } from 'flying-squid/dist/lib/modules/warps' import { TypedEventEmitter } from 'contro-max/build/typedEventEmitter' import { PCChunk } from 'prismarine-chunk' import { Chunk } from 'prismarine-world/types/world' import { Block } from 'prismarine-block' -import { INVISIBLE_BLOCKS } from 'renderer/viewer/lib/mesher/worldConstants' +import { INVISIBLE_BLOCKS } from 'minecraft-renderer/src/mesher-shared/worldConstants' import { getRenamedData } from 'flying-squid/dist/blockRenames' import { useSnapshot, subscribe } from 'valtio' import { subscribeKey } from 'valtio/utils' -import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' -import BlockData from '../../renderer/viewer/lib/moreBlockDataGenerated.json' +import { getThreeJsRendererMethods } from 'minecraft-renderer/src/three/threeJsMethods' +import BlockData from 'minecraft-renderer/src/lib/moreBlockDataGenerated.json' import preflatMap from '../preflatMap.json' import { contro } from '../controls' import { gameAdditionalState, miscUiState } from '../globalState' @@ -233,7 +233,7 @@ export class DrawerAdapterImpl extends TypedEventEmitter implements colors[index] = this.setColor(block) } } - const chunk = { heightmap, colors } + const chunk: ChunkInfo = { heightmap, colors } this.applyShadows(chunk) this.chunksStore.set(key, chunk) this.emit(`chunkReady`, `${chunkX},${chunkZ}`) @@ -250,7 +250,7 @@ export class DrawerAdapterImpl extends TypedEventEmitter implements const chunkWorldZ = chunkZ * 16 const chunkInfo = await this.getChunkSingleplayer(chunkX, chunkZ) if (chunkInfo === 'unavailable') return null - const heightmap = new Uint8Array(256) + const heightmap = new Int16Array(256) const colors = Array.from({ length: 256 }).fill('') as string[] for (let z = 0; z < 16; z += 1) { for (let x = 0; x < 16; x += 1) { diff --git a/src/react/ModsPage.tsx b/src/react/ModsPage.tsx index bdcc30c46..c48641ae2 100644 --- a/src/react/ModsPage.tsx +++ b/src/react/ModsPage.tsx @@ -1,6 +1,6 @@ import { useEffect, useState, useMemo, useRef } from 'react' import { useSnapshot } from 'valtio' -import { openURL } from 'renderer/viewer/lib/simpleUtils' +import { openURL } from 'minecraft-renderer/src/lib/simpleUtils' import { addRepositoryAction, setEnabledModAction, getAllModsDisplayList, installModByName, selectAndRemoveRepository, uninstallModAction, fetchAllRepositories, modsReactiveUpdater, modsErrors, fetchRepository, getModModifiableFields, saveClientModData, getAllModsModifiableFields, callMethodAction } from '../clientMods' import { createNotificationProgressReporter, ProgressReporter } from '../core/progressReporter' import { hideModal } from '../globalState' diff --git a/src/react/ModuleSignsViewer.tsx b/src/react/ModuleSignsViewer.tsx index aa7bb2da1..6f61bc3eb 100644 --- a/src/react/ModuleSignsViewer.tsx +++ b/src/react/ModuleSignsViewer.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from 'react' -import { WorldRendererThree } from 'renderer/viewer/three/worldrendererThree' +import { WorldRendererThree } from 'minecraft-renderer/src/three/worldRendererThree' import FullScreenWidget from './FullScreenWidget' export const name = 'loaded world signs' diff --git a/src/react/OptionsItems.tsx b/src/react/OptionsItems.tsx index 3feb3bd6c..33c987063 100644 --- a/src/react/OptionsItems.tsx +++ b/src/react/OptionsItems.tsx @@ -3,10 +3,10 @@ import { noCase } from 'change-case' import { titleCase } from 'title-case' import { useMemo } from 'react' import { defaultOptions, disabledSettings, options, qsOptions } from '../optionsStorage' -import { appStorage } from './appStorageProvider' import { hideAllModals, miscUiState } from '../globalState' import { reloadChunksAction } from '../controls' import { optionsMeta } from '../defaultOptions' +import { appStorage } from './appStorageProvider' import Button from './Button' import Slider from './Slider' import Screen from './Screen' @@ -79,6 +79,7 @@ const ChangedIndicator = () => ( }} /> ) +/** Prompt at most once per session per setting for restart/chunks-reload nags */ const ignoreReloadWarningsCache = new Set() // Helper functions for option value extraction @@ -185,15 +186,15 @@ export const OptionButton = ({ item, onClick, valueText, cacheKey }: { } } - const toCacheKey = cacheKey ?? item.id ?? '' - if (toCacheKey && !ignoreReloadWarningsCache.has(toCacheKey)) { - ignoreReloadWarningsCache.add(toCacheKey) + const reloadNagKey = cacheKey ?? item.id ?? '' + if (reloadNagKey && !ignoreReloadWarningsCache.has(reloadNagKey)) { + ignoreReloadWarningsCache.add(reloadNagKey) if (item.requiresRestart) { const result = await showOptionsModal(translate('The option requires a restart to take effect'), ['Restart', 'I will do it later'], { cancel: false, }) - if (result) { + if (result === 'Restart') { reconnectReload() } } @@ -201,7 +202,7 @@ export const OptionButton = ({ item, onClick, valueText, cacheKey }: { const result = await showOptionsModal(translate('The option requires a chunks reload to take effect'), ['Reload', 'I will do it later'], { cancel: false, }) - if (result) { + if (result === 'Reload') { reloadChunksAction() } } @@ -265,7 +266,11 @@ const OptionElement = ({ item }: { item: Extract React.ReactNode } }) => { const { gameLoaded } = useSnapshot(miscUiState) if (item.id) { - item.text ??= titleCase(noCase(item.id)) + const storedMeta = optionsMeta[item.id as keyof typeof optionsMeta] + item.text ??= storedMeta?.text ?? titleCase(noCase(item.id)) + item.tooltip ??= storedMeta?.tooltip + item.requiresRestart ??= storedMeta?.requiresRestart + item.requiresChunksReload ??= storedMeta?.requiresChunksReload } if (item.disabledDuringGame && gameLoaded) { item.disabledReason = 'Cannot be changed during game' diff --git a/src/react/OverlayModelViewer.tsx b/src/react/OverlayModelViewer.tsx index 19f1bc1c8..0918c1715 100644 --- a/src/react/OverlayModelViewer.tsx +++ b/src/react/OverlayModelViewer.tsx @@ -4,7 +4,7 @@ import * as THREE from 'three' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader' import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' -import { applySkinToPlayerObject, createPlayerObject, PlayerObjectType } from '../../renderer/viewer/lib/createPlayerObject' +import { applySkinToPlayerObject, createPlayerObject, PlayerObjectType } from 'minecraft-renderer/src/lib/createPlayerObject' import { currentScaling } from '../scaleInterface' import { activeModalStack } from '../globalState' diff --git a/src/react/PauseLinkButtons.tsx b/src/react/PauseLinkButtons.tsx index 18331f2dc..96f52e584 100644 --- a/src/react/PauseLinkButtons.tsx +++ b/src/react/PauseLinkButtons.tsx @@ -1,5 +1,5 @@ import { useSnapshot } from 'valtio' -import { openURL } from 'renderer/viewer/lib/simpleUtils' +import { openURL } from 'minecraft-renderer/src/lib/simpleUtils' import { ErrorBoundary } from '@zardoy/react-util' import { miscUiState } from '../globalState' import { openGithub } from '../utils' diff --git a/src/react/PauseScreen.tsx b/src/react/PauseScreen.tsx index 5638a231b..03868f1e7 100644 --- a/src/react/PauseScreen.tsx +++ b/src/react/PauseScreen.tsx @@ -3,7 +3,7 @@ import fs from 'fs' import { useEffect } from 'react' import { subscribe, useSnapshot } from 'valtio' import { usedServerPathsV1 } from 'flying-squid/dist/lib/modules/world' -import { openURL } from 'renderer/viewer/lib/simpleUtils' +import { openURL } from 'minecraft-renderer/src/lib/simpleUtils' import { Vec3 } from 'vec3' import { generateSpiralMatrix } from 'flying-squid/dist/utils' import { subscribeKey } from 'valtio/utils' diff --git a/src/react/RendererDebugMenu.tsx b/src/react/RendererDebugMenu.tsx index f4bf78764..70bc40e1c 100644 --- a/src/react/RendererDebugMenu.tsx +++ b/src/react/RendererDebugMenu.tsx @@ -1,4 +1,4 @@ -import { WorldRendererCommon } from 'renderer/viewer/lib/worldrendererCommon' +import { WorldRendererCommon } from 'minecraft-renderer/src/lib/worldrendererCommon' import { useState } from 'react' import { useSnapshot } from 'valtio' import { options } from '../optionsStorage' diff --git a/src/react/SelectOption.tsx b/src/react/SelectOption.tsx index 2073719c7..49f314d70 100644 --- a/src/react/SelectOption.tsx +++ b/src/react/SelectOption.tsx @@ -13,18 +13,20 @@ import Input, { InputWithLabel } from './Input' const state = proxy({ title: '', options: [] as string[], + descriptions: [] as string[], showCancel: true, minecraftJsonMessage: null as null | Record, behavior: 'resolve-close' as 'resolve-close' | 'close-resolve', inputs: {} as Record, - inputsConfirmButton: '' + inputsConfirmButton: '', + hoveredOptionIndex: -1 }) let resolve export const showOptionsModal = async ( title: string, options: T[], - { cancel = true, minecraftJsonMessage }: { cancel?: boolean, minecraftJsonMessage? } = {} + { cancel = true, descriptions = [], minecraftJsonMessage, hoveredOptionIndex = -1 }: Partial> & { cancel?: boolean } = {} ): Promise => { showModal({ reactType: 'general-select' }) let minecraftJsonMessageParsed @@ -40,10 +42,12 @@ export const showOptionsModal = async ( Object.assign(state, { title, options, + descriptions, showCancel: cancel, minecraftJsonMessage: minecraftJsonMessageParsed, inputs: {}, - inputsConfirmButton: '' + inputsConfirmButton: '', + hoveredOptionIndex }) }) } @@ -95,13 +99,15 @@ export const showInputsModal = async >( showCancel: cancel, minecraftJsonMessage: minecraftJsonMessageParsed, options: [], - inputsConfirmButton: showConfirm ? confirmLabel : '' + descriptions: [], + inputsConfirmButton: showConfirm ? confirmLabel : '', + hoveredOptionIndex: -1 }) }) } export default () => { - const { title, options, showCancel, minecraftJsonMessage, inputs, inputsConfirmButton } = useSnapshot(state) + const { title, options, descriptions, showCancel, minecraftJsonMessage, inputs, inputsConfirmButton, hoveredOptionIndex } = useSnapshot(state) const isModalActive = useIsModalActive('general-select') const inputValues = useRef({}) @@ -121,16 +127,28 @@ export default () => { } } + const description = descriptions[hoveredOptionIndex] return {minecraftJsonMessage &&
} -
+
{options.length > 0 &&
- {options.map(option => )}
} @@ -195,6 +213,19 @@ export default () => { Cancel )} + {hoveredOptionIndex >= 0 && description && ( +
+ {description} +
+ )}
} diff --git a/src/react/SingleplayerProvider.tsx b/src/react/SingleplayerProvider.tsx index 09639b8d1..fc29f5df3 100644 --- a/src/react/SingleplayerProvider.tsx +++ b/src/react/SingleplayerProvider.tsx @@ -1,7 +1,7 @@ import fs from 'fs' import { proxy, subscribe, useSnapshot } from 'valtio' import { useEffect, useRef, useState } from 'react' -import { loadScript } from 'renderer/viewer/lib/utils' +import { loadScript } from 'minecraft-renderer/src/lib/utils' import { fsState, loadSave, longArrayToNumber, readLevelDat } from '../loadSave' import { googleDriveGetFileIdFromPath, mountExportFolder, mountGoogleDriveFolder, removeFileRecursiveAsync } from '../browserfs' import { hideCurrentModal, showModal } from '../globalState' diff --git a/src/react/inventory/PlayerModelViewer.tsx b/src/react/inventory/PlayerModelViewer.tsx index 8fd743e21..a72f9c601 100644 --- a/src/react/inventory/PlayerModelViewer.tsx +++ b/src/react/inventory/PlayerModelViewer.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react' import { subscribeKey } from 'valtio/utils' -import { loadSkinFromUsername } from '../../../renderer/viewer/lib/utils/skins' +import { loadSkinFromUsername } from 'minecraft-renderer/src/lib/utils/skins' import { PlayerModelCanvas } from '../OverlayModelViewer' /** diff --git a/src/react/inventory/sharedConnectorSetup.ts b/src/react/inventory/sharedConnectorSetup.ts index da99ff789..875584f1b 100644 --- a/src/react/inventory/sharedConnectorSetup.ts +++ b/src/react/inventory/sharedConnectorSetup.ts @@ -2,7 +2,7 @@ import type { ItemStack, BlockTextureRender } from 'minecraft-inventory/src/type import { flat } from '@xmcl/text-component' import PItem from 'prismarine-item' import type { Item } from 'prismarine-item' -import { renderSlot } from 'renderer/viewer/three/renderSlot' +import { renderSlot } from 'minecraft-renderer/src/three/renderSlot' import { getItemModelName, getItemNameRaw, RenderItem } from '../../mineflayer/items' import { inventoryBundledConfig } from './inventoryTexturesConfig' diff --git a/src/react/utils.ts b/src/react/utils.ts index 851ef0e49..bff98078a 100644 --- a/src/react/utils.ts +++ b/src/react/utils.ts @@ -21,7 +21,8 @@ export const ua = new UAParser(navigator.userAgent) export const isIos = ua.getOS().name === 'iOS' -// Safari (desktop or iOS) — WebKit memory limits are strict +// Safari (desktop or iOS) — WebKit memory limits are strict, used to gate +// memory-heavy features such as the WASM mesher conversion cache. export const isSafari = ua.getBrowser().name === 'Safari' || isIos export const reactKeyForMessage = (message) => { diff --git a/src/rendererUtils.ts b/src/rendererUtils.ts deleted file mode 100644 index 0a49fc783..000000000 --- a/src/rendererUtils.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { subscribeKey } from 'valtio/utils' -import { gameAdditionalState } from './globalState' -import { options } from './optionsStorage' -import { playerState } from './mineflayer/playerState' - -let currentFov = 0 -let targetFov = 0 -let lastUpdateTime = 0 -const FOV_TRANSITION_DURATION = 200 // milliseconds - -// TODO: These should be configured based on your game's settings -const BASE_MOVEMENT_SPEED = 0.1 // Default walking speed in Minecraft -const FOV_EFFECT_SCALE = 1 // Equivalent to Minecraft's FOV Effects slider - -const updateFovAnimation = () => { - if (!playerState.ready) return - - // Calculate base FOV modifier - let fovModifier = 1 - - // Flying modifier - if (gameAdditionalState.isFlying) { - fovModifier *= 1.05 - } - - // Movement speed modifier - // TODO: Get actual movement speed attribute value - const movementSpeedAttr = (bot.entity?.attributes?.['generic.movement_speed'] || bot.entity?.attributes?.['minecraft:movement_speed'] || bot.entity?.attributes?.['movement_speed'] || bot.entity?.attributes?.['minecraft:movementSpeed'])?.value || BASE_MOVEMENT_SPEED - let currentSpeed = BASE_MOVEMENT_SPEED - // todo - if (bot.controlState?.sprint && !bot.controlState?.sneak) { - currentSpeed *= 1.3 - } - fovModifier *= (currentSpeed / movementSpeedAttr + 1) / 2 - - // Validate fov modifier - if (Math.abs(BASE_MOVEMENT_SPEED) < Number.EPSILON || isNaN(fovModifier) || !isFinite(fovModifier)) { - fovModifier = 1 - } - - // Item usage modifier - if (playerState.reactive.heldItemMain) { - const heldItem = playerState.reactive.heldItemMain - if (heldItem?.name === 'bow' && playerState.reactive.itemUsageTicks > 0) { - const ticksUsingItem = playerState.reactive.itemUsageTicks - let usageProgress = ticksUsingItem / 20 - if (usageProgress > 1) { - usageProgress = 1 - } else { - usageProgress *= usageProgress - } - fovModifier *= 1 - usageProgress * 0.15 - } - // TODO: Add spyglass/scope check here if needed - } - - // Apply FOV effect scale - fovModifier = 1 + (fovModifier - 1) * FOV_EFFECT_SCALE - - // Calculate target FOV - const baseFov = gameAdditionalState.isZooming ? 30 : options.fov - targetFov = baseFov * fovModifier - - // Smooth transition - const now = performance.now() - if (currentFov !== targetFov) { - const elapsed = now - lastUpdateTime - const progress = Math.min(elapsed / FOV_TRANSITION_DURATION, 1) - const easeOutCubic = (t: number) => 1 - (1 - t) ** 3 - - currentFov += (targetFov - currentFov) * easeOutCubic(progress) - - if (Math.abs(currentFov - targetFov) < 0.01) { - currentFov = targetFov - } - - appViewer.inWorldRenderingConfig.fov = currentFov - } - lastUpdateTime = now -} - -export const watchFov = () => { - // Initial FOV setup - if (!beforeRenderFrame.includes(updateFovAnimation)) { - beforeRenderFrame.push(updateFovAnimation) - } - - customEvents.on('gameLoaded', () => { - updateFovAnimation() - }) -} diff --git a/src/resourcePack.ts b/src/resourcePack.ts index 955f56770..45c7640bc 100644 --- a/src/resourcePack.ts +++ b/src/resourcePack.ts @@ -3,7 +3,7 @@ import { join, dirname, basename } from 'path' import fs from 'fs' import JSZip from 'jszip' import { proxy, subscribe } from 'valtio' -import { armorTextures } from 'renderer/viewer/three/entity/armorModels' +import { armorTextures } from 'minecraft-renderer/src/three/entity/armorModels' import { allTexturePaths } from 'minecraft-inventory/src/bundledTexturesConfig' import { copyFilesAsyncWithProgress, mkdirRecursive, removeFileRecursiveAsync } from './browserfs' import { showNotification } from './react/NotificationProvider' diff --git a/src/resourcesManager.ts b/src/resourcesManager.ts deleted file mode 100644 index ef3dd7ce4..000000000 --- a/src/resourcesManager.ts +++ /dev/null @@ -1,242 +0,0 @@ -import { EventEmitter } from 'events' -import TypedEmitter from 'typed-emitter' -import blocksAtlases from 'mc-assets/dist/blocksAtlases.json' -import itemsAtlases from 'mc-assets/dist/itemsAtlases.json' -import itemDefinitionsJson from 'mc-assets/dist/itemDefinitions.json' -import blocksAtlasLatest from 'mc-assets/dist/blocksAtlasLatest.png' -import blocksAtlasLegacy from 'mc-assets/dist/blocksAtlasLegacy.png' -import itemsAtlasLatest from 'mc-assets/dist/itemsAtlasLatest.png' -import itemsAtlasLegacy from 'mc-assets/dist/itemsAtlasLegacy.png' -import christmasPack from 'mc-assets/dist/textureReplacements/christmas' -import { AtlasParser, ItemsAtlasesOutputJson } from 'mc-assets/dist/atlasParser' -import worldBlockProvider, { WorldBlockProvider } from 'mc-assets/dist/worldBlockProvider' -import { ItemsRenderer } from 'mc-assets/dist/itemsRenderer' -import { getLoadedItemDefinitionsStore } from 'mc-assets' -import { generateGuiAtlas } from 'renderer/viewer/lib/guiRenderer' -import { importLargeData } from '../generated/large-data-aliases' - -type ResourceManagerEvents = { - assetsTexturesUpdated: () => void - assetsInventoryStarted: () => void - assetsInventoryReady: () => void -} - -export class LoadedResourcesTransferrable { - allReady = false - // Atlas parsers - itemsAtlasImage: ImageBitmap - blocksAtlasImage: ImageBitmap - blocksAtlasJson: ItemsAtlasesOutputJson - // User data (specific to current resourcepack/version) - customBlockStates?: Record - customModels?: Record - /** array where the index represents the custom model data value, and the element at that index is the model path to use */ - customItemModelNames: Record = {} - customTextures: { - items?: { tileSize: number | undefined, textures: Record } - blocks?: { tileSize: number | undefined, textures: Record } - armor?: { tileSize: number | undefined, textures: Record } - } = {} - guiAtlas: { json: any, image: ImageBitmap } | null = null - guiAtlasVersion = 0 - - itemsRenderer: ItemsRenderer - worldBlockProvider?: WorldBlockProvider - blockstatesModels: any = null - - version: string - texturesVersion: string -} - -export interface ResourcesCurrentConfig { - version: string - texturesVersion?: string - // noBlockstatesModels?: boolean - noInventoryGui?: boolean - includeOnlyBlocks?: string[] -} - -export interface UpdateAssetsRequest { - _?: false -} - -export interface ResourcesManagerTransferred extends TypedEmitter { - currentResources: LoadedResourcesTransferrable -} -export interface ResourcesManagerCommon extends TypedEmitter { - currentResources: LoadedResourcesTransferrable | undefined -} - -const STABLE_MODELS_VERSION = '1.21.4' -export class ResourcesManager extends (EventEmitter as new () => TypedEmitter) { - static restorerName = 'ResourcesManager' - - // Source data (imported, not changing) - sourceBlockStatesModels: any = null - readonly sourceBlocksAtlases: any = blocksAtlases - readonly sourceItemsAtlases: any = itemsAtlases - readonly sourceItemDefinitionsJson: any = itemDefinitionsJson - readonly itemsDefinitionsStore = getLoadedItemDefinitionsStore(this.sourceItemDefinitionsJson) - - currentResources: LoadedResourcesTransferrable | undefined - itemsAtlasParser: AtlasParser - blocksAtlasParser: AtlasParser - currentConfig: ResourcesCurrentConfig | undefined - abortController = new AbortController() - _promiseAssetsReadyResolvers = Promise.withResolvers() - get promiseAssetsReady () { - return this._promiseAssetsReadyResolvers.promise - } - - async loadSourceData (version: string) { - this.sourceBlockStatesModels ??= await importLargeData('blockStatesModels') - } - - resetResources () { - this.currentResources = new LoadedResourcesTransferrable() - } - - async updateAssetsData (request: UpdateAssetsRequest, unstableSkipEvent = false) { - if (!this.currentConfig) throw new Error('No config loaded') - this._promiseAssetsReadyResolvers = Promise.withResolvers() - const abortController = new AbortController() - await this.loadSourceData(this.currentConfig.version) - if (abortController.signal.aborted) return - - const resources = this.currentResources ?? new LoadedResourcesTransferrable() - resources.version = this.currentConfig.version - resources.texturesVersion = this.currentConfig.texturesVersion ?? resources.version - - resources.blockstatesModels = { - blockstates: {}, - models: {} - } - // todo-low resolve version - resources.blockstatesModels.blockstates.latest = { - ...this.sourceBlockStatesModels.blockstates.latest, - ...resources.customBlockStates - } - - resources.blockstatesModels.models.latest = { - ...this.sourceBlockStatesModels.models.latest, - ...resources.customModels - } - - console.time('recreateAtlases') - await Promise.all([ - this.recreateBlockAtlas(resources), - this.recreateItemsAtlas(resources) - ]) - console.timeEnd('recreateAtlases') - - if (abortController.signal.aborted) return - - if (resources.version && resources.blockstatesModels && this.itemsAtlasParser && this.blocksAtlasParser) { - resources.itemsRenderer = new ItemsRenderer( - resources.version, - resources.blockstatesModels, - this.itemsAtlasParser, - this.blocksAtlasParser - ) - } - - if (abortController.signal.aborted) return - - this.currentResources = resources - resources.allReady = true - if (!unstableSkipEvent) { // todo rework resourcepack optimization - this.emit('assetsTexturesUpdated') - } - - if (this.currentConfig.noInventoryGui) { - this._promiseAssetsReadyResolvers.resolve() - } else { - this.emit('assetsInventoryStarted') - void this.generateGuiTextures().then(() => { - if (abortController.signal.aborted) return - if (!unstableSkipEvent) { - this.emit('assetsInventoryReady') - } - this._promiseAssetsReadyResolvers.resolve() - }) - } - } - - async recreateBlockAtlas (resources: LoadedResourcesTransferrable = this.currentResources!) { - const blockTexturesChanges = {} as Record - const date = new Date() - if ((date.getMonth() === 11 && date.getDate() >= 24) || (date.getMonth() === 0 && date.getDate() <= 6)) { - Object.assign(blockTexturesChanges, christmasPack) - } - - const blocksAssetsParser = new AtlasParser(this.sourceBlocksAtlases, blocksAtlasLatest, blocksAtlasLegacy) - - const customBlockTextures = Object.keys(resources.customTextures.blocks?.textures ?? {}) - console.time('createBlocksAtlas') - const { atlas: blocksAtlas, canvas: blocksCanvas } = await blocksAssetsParser.makeNewAtlas( - resources.texturesVersion, - (textureName) => { - if (this.currentConfig!.includeOnlyBlocks && !this.currentConfig!.includeOnlyBlocks.includes(textureName)) return false - const texture = resources.customTextures.blocks?.textures[textureName] - return blockTexturesChanges[textureName] ?? texture - }, - undefined, - undefined, - customBlockTextures, - { - needHorizontalIndexes: !!this.currentConfig!.includeOnlyBlocks, - } - ) - console.timeEnd('createBlocksAtlas') - - this.blocksAtlasParser = new AtlasParser({ latest: blocksAtlas }, blocksCanvas.toDataURL()) - resources.blocksAtlasImage = await createImageBitmap(blocksCanvas) - resources.blocksAtlasJson = this.blocksAtlasParser.atlas.latest - - resources.worldBlockProvider = worldBlockProvider( - resources.blockstatesModels, - this.blocksAtlasParser.atlas, - STABLE_MODELS_VERSION - ) - } - - async recreateItemsAtlas (resources: LoadedResourcesTransferrable = this.currentResources!) { - const itemsAssetsParser = new AtlasParser(this.sourceItemsAtlases, itemsAtlasLatest, itemsAtlasLegacy) - const customItemTextures = Object.keys(resources.customTextures.items?.textures ?? {}) - const { atlas: itemsAtlas, canvas: itemsCanvas } = await itemsAssetsParser.makeNewAtlas( - resources.texturesVersion, - (textureName) => { - const texture = resources.customTextures.items?.textures[textureName] - if (!texture) return - return texture - }, - resources.customTextures.items?.tileSize, - undefined, - customItemTextures - ) - - this.itemsAtlasParser = new AtlasParser({ latest: itemsAtlas }, itemsCanvas.toDataURL()) - resources.itemsAtlasImage = await createImageBitmap(itemsCanvas) - } - - async generateGuiTextures () { - await generateGuiAtlas() - } - - async downloadDebugAtlas (isItems = false) { - const resources = this.currentResources - if (!resources) throw new Error('No resources loaded') - const atlasParser = (isItems ? this.itemsAtlasParser : this.blocksAtlasParser)! - const dataUrl = await atlasParser.createDebugImage(true) - const a = document.createElement('a') - a.href = dataUrl - a.download = `atlas-debug-${isItems ? 'items' : 'blocks'}.png` - a.click() - } - - destroy () { - this.abortController.abort() - this.currentResources = undefined - this.abortController = new AbortController() - } -} diff --git a/src/shims/minecraftData.ts b/src/shims/minecraftData.ts index 33dff5fef..cdeb31992 100644 --- a/src/shims/minecraftData.ts +++ b/src/shims/minecraftData.ts @@ -1,4 +1,4 @@ -import { versionToNumber } from 'renderer/viewer/common/utils' +import { versionToNumber } from 'minecraft-renderer/src/lib/utils' import { restoreMinecraftData } from '../optimizeJson' // import minecraftInitialDataJson from '../../generated/minecraft-initial-data.json' import { toMajorVersion } from '../utils' diff --git a/src/sounds/botSoundSystem.ts b/src/sounds/botSoundSystem.ts index 6205691b2..63c4ca5ff 100644 --- a/src/sounds/botSoundSystem.ts +++ b/src/sounds/botSoundSystem.ts @@ -1,6 +1,6 @@ import { Vec3 } from 'vec3' -import { versionToNumber } from 'renderer/viewer/common/utils' -import { loadScript } from 'renderer/viewer/lib/utils' +import { versionToNumber, loadScript } from 'minecraft-renderer/src/lib/utils' +import { getThreeJsRendererMethods } from 'minecraft-renderer/src/three/threeJsMethods' import type { Block } from 'prismarine-block' import { subscribeKey } from 'valtio/utils' import { miscUiState } from '../globalState' @@ -222,6 +222,73 @@ subscribeKey(miscUiState, 'gameLoaded', async () => { registerEvents() }) +// Break particles: registered independently of sound system +subscribeKey(miscUiState, 'gameLoaded', () => { + if (!miscUiState.gameLoaded) return + + function buildFloorMap (x: number, y: number, z: number): number[] { + const floorMap: number[] = [] + for (let dz = -2; dz <= 2; dz++) { + for (let dx = -2; dx <= 2; dx++) { + const columnX = x + dx + const columnZ = z + dz + let floorY = y - 20 // fallback: deep below + for (let scanY = y; scanY >= y - 20; scanY--) { + try { + const block = bot.world.getBlock(new Vec3(columnX, scanY, columnZ)) + if (block && block.boundingBox === 'block') { + floorY = scanY + 1 + break + } + } catch { + break + } + } + floorMap.push(floorY) + } + } + return floorMap + } + + let diggingBlock: Block | null = null + customEvents.on('digStart', () => { + diggingBlock = bot.blockAtCursor(5) + }) + bot.on('diggingCompleted', () => { + if (diggingBlock) { + const pos = diggingBlock.position + const floorMap = buildFloorMap(pos.x, pos.y, pos.z) + const biomeName = (diggingBlock as any).biome?.name ?? 'plains' + getThreeJsRendererMethods()?.spawnBlockBreakParticles(pos.x, pos.y, pos.z, diggingBlock.name, floorMap, biomeName) + } + }) + bot._client.on('world_event', ({ effectId, location, data, global: disablePosVolume }) => { + if (effectId === 2001 && !disablePosVolume) { + const block = loadedData.blocksByStateId[data] + if (block) { + const x = Math.floor(location.x) + const y = Math.floor(location.y) + const z = Math.floor(location.z) + const floorMap = buildFloorMap(x, y, z) + let biomeName = 'plains' + try { + const worldBlock = bot.world.getBlock(new Vec3(x, y, z)) + biomeName = (worldBlock as any)?.biome?.name ?? 'plains' + } catch {} + getThreeJsRendererMethods()?.spawnBlockBreakParticles(x, y, z, block.name, floorMap, biomeName) + } + } + }) + bot.on('blockBreakProgressStage', (block, stage) => { + if (stage === null) return + const pos = block.position + const face = (block as any).face ?? 1 + const floorMap = buildFloorMap(pos.x, pos.y, pos.z) + const biomeName = (block as any).biome?.name ?? 'plains' + getThreeJsRendererMethods()?.spawnBlockCrackParticle(pos.x, pos.y, pos.z, face, block.name, floorMap, biomeName) + }) +}) + subscribeKey(resourcePackState, 'resourcePackInstalled', async () => { await updateResourcePack() }) diff --git a/src/sounds/soundsMap.ts b/src/sounds/soundsMap.ts index 470289710..0eb869838 100644 --- a/src/sounds/soundsMap.ts +++ b/src/sounds/soundsMap.ts @@ -1,6 +1,6 @@ import fs from 'fs' import path from 'path' -import { versionsMapToMajor, versionToMajor, versionToNumber } from 'renderer/viewer/common/utils' +import { versionsMapToMajor, versionToMajor, versionToNumber } from 'minecraft-renderer/src/lib/utils' import { stopAllSounds } from '../basicSounds' import { musicSystem } from './musicSystem' diff --git a/src/utils.ts b/src/utils.ts index 3ccc7fc4c..5d7672bff 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -139,7 +139,7 @@ export const toMajorVersion = version => { let prevRenderDistance = options.renderDistance export const setRenderDistance = () => { - assertDefined(worldView) + assertDefined(appViewer.worldView) const { renderDistance: singleplayerRenderDistance, multiplayerRenderDistance } = options let renderDistance = miscUiState.singleplayer ? singleplayerRenderDistance : multiplayerRenderDistance const zeroRenderDistance = miscUiState.singleplayer && renderDistance === 0 @@ -153,13 +153,13 @@ export const setRenderDistance = () => { localServer!.players[0].view = 0 renderDistance = 0 } - worldView?.updateViewDistance(renderDistance) + appViewer.worldView?.updateViewDistance(renderDistance) prevRenderDistance = renderDistance } export const reloadChunks = async () => { - if (!bot || !worldView) return + if (!bot || !appViewer.worldView) return setRenderDistance() - await worldView.updatePosition(bot.entity.position, true) + await appViewer.worldView.updatePosition(bot.entity.position, true) } export const openGithub = (addUrl = '') => { diff --git a/src/watchOptions.ts b/src/watchOptions.ts index 359fd027d..31008e970 100644 --- a/src/watchOptions.ts +++ b/src/watchOptions.ts @@ -1,13 +1,18 @@ // not all options are watched here import { subscribeKey } from 'valtio/utils' -import { isMobile } from 'renderer/viewer/lib/simpleUtils' -import { WorldDataEmitter } from 'renderer/viewer/lib/worldDataEmitter' -import { setSkinsConfig } from 'renderer/viewer/lib/utils/skins' +import { isMobile } from 'minecraft-renderer/src/lib/simpleUtils' +import { + applyRendererEnableLighting, + applyRendererWorldViewOptions, + subscribeRendererOptions +} from 'minecraft-renderer/src/graphicsBackend/rendererOptionsSync' +import { WorldView } from 'minecraft-renderer/src/worldView/worldView' import { options, watchValue } from './optionsStorage' import { reloadChunks } from './utils' import { miscUiState } from './globalState' import { isCypress } from './standaloneUtils' +import { isSafari } from './react/utils' subscribeKey(options, 'renderDistance', reloadChunks) subscribeKey(options, 'multiplayerRenderDistance', reloadChunks) @@ -28,117 +33,56 @@ window.matchMedia('(pointer: coarse)').addEventListener('change', (e) => { /** happens once */ export const watchOptionsAfterViewerInit = () => { - watchValue(options, o => { - appViewer.inWorldRenderingConfig.showChunkBorders = o.showChunkBorders - }) - - watchValue(options, o => { - appViewer.inWorldRenderingConfig.mesherWorkers = o.lowMemoryMode ? 1 : o.numWorkers - }) - - watchValue(options, o => { - appViewer.inWorldRenderingConfig.renderEntities = o.renderEntities - }) - - watchValue(options, o => { - const { renderDebug } = o - if (renderDebug === 'none' || isCypress()) { - appViewer.config.statsVisible = 0 - } else if (o.renderDebug === 'basic') { - appViewer.config.statsVisible = 1 - } else if (o.renderDebug === 'advanced') { - appViewer.config.statsVisible = 2 - } - }) - - // Track window focus state and update FPS limit accordingly - let windowFocused = true - const updateFpsLimit = (o: typeof options) => { - const backgroundFpsLimit = o.backgroundRendering - const normalFpsLimit = o.frameLimit - - if (windowFocused) { - appViewer.config.fpsLimit = normalFpsLimit || undefined - } else if (backgroundFpsLimit === '5fps') { - appViewer.config.fpsLimit = 5 - } else if (backgroundFpsLimit === '20fps') { - appViewer.config.fpsLimit = 20 - } else { - appViewer.config.fpsLimit = undefined - } - } - - window.addEventListener('focus', () => { - windowFocused = true - updateFpsLimit(options) - }) - window.addEventListener('blur', () => { - windowFocused = false - updateFpsLimit(options) - }) - - watchValue(options, o => { - updateFpsLimit(o) + subscribeRendererOptions(appViewer, options, { + isSafari, + isCypress: isCypress(), + onRegisterFocusHandlers ({ onFocus, onBlur }) { + window.addEventListener('focus', onFocus) + window.addEventListener('blur', onBlur) + }, }) + // Volume — app-only (not in renderer sync) watchValue(options, o => { appViewer.inWorldRenderingConfig.volume = Math.max(o.volume / 100, 0) }) - watchValue(options, o => { - appViewer.inWorldRenderingConfig.vrSupport = o.vrSupport - appViewer.inWorldRenderingConfig.vrPageGameRendering = o.vrPageGameRendering - appViewer.inWorldRenderingConfig.enableDebugOverlay = o.rendererPerfDebugOverlay - }) - - watchValue(options, (o, isChanged) => { - appViewer.inWorldRenderingConfig.clipWorldBelowY = o.clipWorldBelowY - appViewer.inWorldRenderingConfig.extraBlockRenderers = !o.disableBlockEntityTextures - appViewer.inWorldRenderingConfig.fetchPlayerSkins = o.loadPlayerSkins - appViewer.inWorldRenderingConfig.highlightBlockColor = o.highlightBlockColor - appViewer.inWorldRenderingConfig._experimentalSmoothChunkLoading = o.rendererSharedOptions._experimentalSmoothChunkLoading - appViewer.inWorldRenderingConfig._renderByChunks = o.rendererSharedOptions._renderByChunks - - setSkinsConfig({ apiEnabled: o.loadPlayerSkins }) - }) - - appViewer.inWorldRenderingConfig.smoothLighting = options.smoothLighting - subscribeKey(options, 'smoothLighting', () => { - appViewer.inWorldRenderingConfig.smoothLighting = options.smoothLighting - }) - - watchValue(options, o => { - appViewer.inWorldRenderingConfig.shadingTheme = o.vanillaLook ? 'vanilla' : 'high-contrast' - }) - subscribeKey(options, 'newVersionsLighting', () => { - appViewer.inWorldRenderingConfig.enableLighting = !bot.supportFeature('blockStateId') || options.newVersionsLighting + applyRendererEnableLighting( + appViewer, + options.newVersionsLighting, + bot.supportFeature('blockStateId') + ) }) customEvents.on('mineflayerBotCreated', () => { - appViewer.inWorldRenderingConfig.enableLighting = !bot.supportFeature('blockStateId') || options.newVersionsLighting - }) - - watchValue(options, o => { - appViewer.inWorldRenderingConfig.starfield = o.starfieldRendering - }) + applyRendererEnableLighting( + appViewer, + options.newVersionsLighting, + bot.supportFeature('blockStateId') + ) + + const updateRaining = () => { + if (bot.isRaining !== undefined) { + appViewer.inWorldRenderingConfig.isRaining = bot.isRaining + } + } - watchValue(options, o => { - appViewer.inWorldRenderingConfig.defaultSkybox = o.defaultSkybox - }) + updateRaining() - watchValue(options, o => { - // appViewer.inWorldRenderingConfig.neighborChunkUpdates = o.neighborChunkUpdates + //@ts-expect-error - weatherUpdate is not in the type definition yet + bot.on('weatherUpdate', () => { + updateRaining() + }) + bot.on('rain', () => { + updateRaining() + }) }) } -export const watchOptionsAfterWorldViewInit = (worldView: WorldDataEmitter) => { +export const watchOptionsAfterWorldViewInit = (worldView: WorldView) => { watchValue(options, o => { if (!worldView) return - worldView.keepChunksDistance = o.keepChunksDistance - appViewer.inWorldRenderingConfig.renderEars = o.renderEars - appViewer.inWorldRenderingConfig.showHand = o.showHand - appViewer.inWorldRenderingConfig.viewBobbing = o.viewBobbing - appViewer.inWorldRenderingConfig.dayCycle = o.dayCycleAndLighting + applyRendererWorldViewOptions(appViewer, worldView, o) }) } diff --git a/tsconfig.json b/tsconfig.json index 249261802..e54e83870 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,8 +25,6 @@ "include": [ "src", "cypress", - "renderer/viewer", - "renderer/playground" ], "exclude": [ "node_modules" diff --git a/vitest.config.ts b/vitest.config.ts index 7da461992..545d4bfed 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,16 +1,7 @@ import { defineConfig } from 'vitest/config' export default defineConfig({ - root: 'renderer/viewer', + root: 'src', test: { - include: [ - '../../src/botUtils.test.ts', - '../../src/markdownToFormattedText.test.ts', - '../../src/react/parseKeybindingName.test.ts', - '../../src/chatUtils.test.ts', - 'lib/mesher/test/tests.test.ts', - 'sign-renderer/tests.test.ts', - '../../src/utils.test.ts' - ], }, })