diff --git a/.eslintignore b/.eslintignore index 4c431739f..9aa16166f 100644 --- a/.eslintignore +++ b/.eslintignore @@ -6,3 +6,4 @@ generated dist public **/*/rsbuildSharedConfig.ts +src/mcDataTypes.ts \ No newline at end of file diff --git a/.github/workflows/next-deploy.yml b/.github/workflows/next-deploy.yml index d829fc1f5..488af273b 100644 --- a/.github/workflows/next-deploy.yml +++ b/.github/workflows/next-deploy.yml @@ -38,9 +38,8 @@ jobs: with: run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} id: deploy - - name: Set deployment alias - run: vercel alias set ${{ steps.deploy.outputs.stdout }} ${{ secrets.TEST_PREVIEW_DOMAIN }} --token=${{ secrets.VERCEL_TOKEN }} --scope=zaro - # - uses: mshick/add-pr-comment@v2 - # with: - # message: | - # Deployed to Vercel Preview: ${{ steps.deploy.outputs.stdout }} + - name: Set deployment aliases + run: | + for alias in $(echo ${{ secrets.TEST_PREVIEW_DOMAIN }} | tr "," "\n"); do + vercel alias set ${{ steps.deploy.outputs.stdout }} $alias --token=${{ secrets.VERCEL_TOKEN }} --scope=zaro + done diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index ddb386b7d..f03b80f8a 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -55,6 +55,9 @@ jobs: run: npm install --global vercel - name: Pull Vercel Environment Information run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} + - name: Write Release Info + run: | + echo "{\"latestTag\": \"$(git rev-parse --short ${{ github.event.pull_request.head.sha }})\"}" > assets/release.json - name: Build Project Artifacts run: vercel build --token=${{ secrets.VERCEL_TOKEN }} - run: pnpm build-storybook @@ -63,6 +66,14 @@ jobs: mkdir -p .vercel/output/static/playground pnpm build-playground cp -r prismarine-viewer/dist/* .vercel/output/static/playground/ + - name: Write pr redirect index.html + run: | + mkdir -p .vercel/output/static/pr + echo "" > .vercel/output/static/pr/index.html + - name: Write commit redirect index.html + run: | + mkdir -p .vercel/output/static/commit + echo "" > .vercel/output/static/commit/index.html - name: Download Generated Sounds map run: node scripts/downloadSoundsMap.mjs - name: Deploy Project Artifacts to Vercel @@ -81,4 +92,7 @@ jobs: # - run: git checkout next scripts/githubActions.mjs - name: Set deployment alias if: ${{ steps.alias.outputs.alias != '' && steps.alias.outputs.alias != 'mcraft.fun' && steps.alias.outputs.alias != 's.mcraft.fun' }} - run: vercel alias set ${{ steps.deploy.outputs.stdout }} ${{ steps.alias.outputs.alias }} --token=${{ secrets.VERCEL_TOKEN }} --scope=zaro + 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 diff --git a/README.MD b/README.MD index 77f680323..ceba1c6c9 100644 --- a/README.MD +++ b/README.MD @@ -128,6 +128,10 @@ Press `Y` to set query parameters to url of your current game state. There are some parameters you can set in the url to archive some specific behaviors: +General: + +- **`?setting=:`** - Set and lock the setting on load. You can set multiple settings by separating them with `&` e.g. `?setting=autoParkour:true&setting=renderDistance:4` + Server specific: - `?ip=` - Display connect screen to the server on load with predefined server ip. `:` is optional and can be added to the ip. @@ -137,6 +141,7 @@ Server specific: - `?username=` - Set the username for the server - `?lockConnect=true` - Only works then `ip` parameter is set. Disables cancel/save buttons and all inputs in the connect screen already set as parameters. Useful for integrates iframes. - `?reconnect=true` - Reconnect to the server on page reloads. Available in **dev mode only** and very useful on server testing. +- `?serversList=` - `` can be a list of servers in the format `ip:version,ip` or a url to a json file with the same format (array) or a txt file with line-delimited list of server IPs. Single player specific: @@ -171,10 +176,6 @@ In this case you must use `?mapDirBaseUrl` to specify the base URL to fetch the -General: - -- `?setting=:` - Set and lock the setting on load. You can set multiple settings by separating them with `&` e.g. `?setting=autoParkour:true&setting=renderDistance:4` - ### Notable Things that Power this Project - [Mineflayer](https://github.com/PrismarineJS/mineflayer) - Handles all client-side communications with the server (including the builtin one) - forked diff --git a/package.json b/package.json index 53b4b70d9..4ed5a4494 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "scripts": { "dev-rsbuild": "rsbuild dev", "dev-proxy": "node server.js", - "start": "run-p dev-rsbuild dev-proxy watch-mesher", + "start": "run-p dev-proxy dev-rsbuild watch-mesher", + "start2": "run-p dev-rsbuild watch-mesher", "build": "pnpm build-other-workers && rsbuild build", "build-analyze": "BUNDLE_ANALYZE=true rsbuild build && pnpm build-other-workers", "check-build": "tsx scripts/genShims.ts && tsc && pnpm build", @@ -67,12 +68,12 @@ "esbuild-plugin-polyfill-node": "^0.3.0", "express": "^4.18.2", "filesize": "^10.0.12", - "flying-squid": "npm:@zardoy/flying-squid@^0.0.47", + "flying-squid": "npm:@zardoy/flying-squid@^0.0.49", "fs-extra": "^11.1.1", "google-drive-browserfs": "github:zardoy/browserfs#google-drive", "jszip": "^3.10.1", "lodash-es": "^4.17.21", - "minecraft-data": "3.78.0", + "minecraft-data": "3.80.0", "minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master", "mineflayer-item-map-downloader": "github:zardoy/mineflayer-item-map-downloader", "mojangson": "^2.0.4", @@ -92,6 +93,7 @@ "react-dom": "^18.2.0", "react-select": "^5.8.0", "react-transition-group": "^4.4.5", + "react-zoom-pan-pinch": "3.4.4", "remark": "^15.0.1", "sanitize-filename": "^1.6.3", "skinview3d": "^3.0.1", @@ -140,7 +142,7 @@ "http-browserify": "^1.7.0", "http-server": "^14.1.1", "https-browserify": "^1.0.0", - "mc-assets": "^0.2.12", + "mc-assets": "^0.2.23", "minecraft-inventory-gui": "github:zardoy/minecraft-inventory-gui#next", "mineflayer": "github:zardoy/mineflayer", "mineflayer-pathfinder": "^2.4.4", @@ -172,7 +174,7 @@ "diamond-square": "github:zardoy/diamond-square", "prismarine-block": "github:zardoy/prismarine-block#next-era", "prismarine-world": "github:zardoy/prismarine-world#next-era", - "minecraft-data": "3.78.0", + "minecraft-data": "3.80.0", "prismarine-provider-anvil": "github:zardoy/prismarine-provider-anvil#everything", "prismarine-physics": "github:zardoy/prismarine-physics", "minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master", @@ -187,7 +189,7 @@ "three@0.154.0": "patches/three@0.154.0.patch", "pixelarticons@1.8.1": "patches/pixelarticons@1.8.1.patch", "mineflayer-item-map-downloader@1.2.0": "patches/mineflayer-item-map-downloader@1.2.0.patch", - "minecraft-protocol@1.50.0": "patches/minecraft-protocol@1.49.0.patch" + "minecraft-protocol@1.51.0": "patches/minecraft-protocol@1.49.0.patch" } }, "packageManager": "pnpm@9.0.4" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dfb34dcac..7a89eb6df 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,7 +11,7 @@ overrides: diamond-square: github:zardoy/diamond-square prismarine-block: github:zardoy/prismarine-block#next-era prismarine-world: github:zardoy/prismarine-world#next-era - minecraft-data: 3.78.0 + minecraft-data: 3.80.0 prismarine-provider-anvil: github:zardoy/prismarine-provider-anvil#everything prismarine-physics: github:zardoy/prismarine-physics minecraft-protocol: github:PrismarineJS/node-minecraft-protocol#master @@ -20,7 +20,7 @@ overrides: prismarine-item: latest patchedDependencies: - minecraft-protocol@1.50.0: + minecraft-protocol@1.51.0: hash: 7sh5krubuk2vjuogjioaktvwzi path: patches/minecraft-protocol@1.49.0.patch mineflayer-item-map-downloader@1.2.0: @@ -119,8 +119,8 @@ importers: specifier: ^10.0.12 version: 10.0.12 flying-squid: - specifier: npm:@zardoy/flying-squid@^0.0.47 - version: '@zardoy/flying-squid@0.0.47(encoding@0.1.13)' + specifier: npm:@zardoy/flying-squid@^0.0.49 + version: '@zardoy/flying-squid@0.0.49(encoding@0.1.13)' fs-extra: specifier: ^11.1.1 version: 11.1.1 @@ -134,11 +134,11 @@ importers: specifier: ^4.17.21 version: 4.17.21 minecraft-data: - specifier: 3.78.0 - version: 3.78.0 + specifier: 3.80.0 + version: 3.80.0 minecraft-protocol: specifier: github:PrismarineJS/node-minecraft-protocol#master - version: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/590dc33fed2100e77ef58e7db716dfc45eb61159(patch_hash=7sh5krubuk2vjuogjioaktvwzi)(encoding@0.1.13) + version: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/f258c76b3a15badd902e82cd892168849444d79d(patch_hash=7sh5krubuk2vjuogjioaktvwzi)(encoding@0.1.13) mineflayer-item-map-downloader: specifier: github:zardoy/mineflayer-item-map-downloader version: https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/642fd4f7023a98a96da4caf8f993f8e19361a1e7(patch_hash=bck55yjvd4wrgz46x7o4vfur5q)(encoding@0.1.13) @@ -147,7 +147,7 @@ importers: version: 2.0.4 net-browserify: specifier: github:zardoy/prismarinejs-net-browserify - version: https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/d3f7f77d8ac751bc171173bba639086c931a62f7 + version: https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/ab3721ca833308a0be099d14ea0053fbd8459ace node-gzip: specifier: ^1.1.2 version: 1.1.2 @@ -162,7 +162,7 @@ importers: version: 6.1.1 prismarine-provider-anvil: specifier: github:zardoy/prismarine-provider-anvil#everything - version: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/d807fc339a3d95a7aef91468d4d64d367e7c682a(minecraft-data@3.78.0) + version: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/d807fc339a3d95a7aef91468d4d64d367e7c682a(minecraft-data@3.80.0) prosemirror-example-setup: specifier: ^1.2.2 version: 1.2.2 @@ -193,6 +193,9 @@ importers: react-transition-group: specifier: ^4.4.5 version: 4.4.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react-zoom-pan-pinch: + specifier: 3.4.4 + version: 3.4.4(react-dom@18.2.0(react@18.2.0))(react@18.2.0) remark: specifier: ^15.0.1 version: 15.0.1 @@ -343,14 +346,14 @@ importers: specifier: ^1.0.0 version: 1.0.0 mc-assets: - specifier: ^0.2.12 - version: 0.2.12 + specifier: ^0.2.23 + version: 0.2.23 minecraft-inventory-gui: specifier: github:zardoy/minecraft-inventory-gui#next version: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/75e940a4cd50d89e0ba03db3733d5d704917a3c8(@types/react@18.2.20)(react@18.2.0) mineflayer: specifier: github:zardoy/mineflayer - version: https://codeload.github.com/zardoy/mineflayer/tar.gz/ece6755d94931116924874d9f55bc024998cc1ae(encoding@0.1.13) + version: https://codeload.github.com/zardoy/mineflayer/tar.gz/390ce12c1e1f25e440a94ba422e45c874f8bbd2b(encoding@0.1.13) mineflayer-pathfinder: specifier: ^2.4.4 version: 2.4.4 @@ -428,7 +431,7 @@ importers: version: https://codeload.github.com/zardoy/prismarine-block/tar.gz/23849d4d24af91f45a5bd38781a6f82d40316c05 prismarine-chunk: specifier: github:zardoy/prismarine-chunk#master - version: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.78.0) + version: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.80.0) prismarine-schematic: specifier: ^1.2.0 version: 1.2.3 @@ -3041,6 +3044,9 @@ packages: '@types/node-fetch@2.6.6': resolution: {integrity: sha512-95X8guJYhfqiuVVhRFxVQcf4hW/2bCuoPwDasMf/531STFoNoWTT7YDnWdXHEZKqAGUigmpG31r2FE70LwnzJw==} + '@types/node-rsa@1.1.4': + resolution: {integrity: sha512-dB0ECel6JpMnq5ULvpUTunx3yNm8e/dIkv8Zu9p2c8me70xIRUUG3q+qXRwcSf9rN3oqamv4116iHy90dJGRpA==} + '@types/node@14.18.56': resolution: {integrity: sha512-+k+57NVS9opgrEn5l9c0gvD1r6C+PtyhVE4BTnMMRwiEA8ZO8uFcs6Yy2sXIy0eC95ZurBtRSvhZiHXBysbl6w==} @@ -3395,8 +3401,8 @@ packages: resolution: {integrity: sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==} engines: {node: '>=12 <14 || 14.2 - 14.9 || >14.10.0'} - '@zardoy/flying-squid@0.0.47': - resolution: {integrity: sha512-VUtOqPGZ/20tQEjRLFpbz0taoTMi0GgoUM7002wn8RjuVmowg0pMUjdy0YwcFPGla8z1sOwjsF9cOtU4hQ8pUg==} + '@zardoy/flying-squid@0.0.49': + resolution: {integrity: sha512-Kt4wr5/R+44tcLU9gjuNG2an9weWeKEpIoKXfsgJN2GGQqdnbd5nBpxfGDdgZ9aMdFugsVW8BsyPZNhj9vbMXA==} engines: {node: '>=8'} hasBin: true @@ -4870,10 +4876,6 @@ packages: engines: {node: '>=12'} hasBin: true - escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} @@ -6580,8 +6582,8 @@ packages: peerDependencies: react: ^18.2.0 - mc-assets@0.2.12: - resolution: {integrity: sha512-ZbiodI0vgcwGT0M3AGc+0N2h7JsnrfjzhlA5AzpSQfkGbNp3wp/VeFmI4/lGm0JPJi9+LgXGDUuspRQzQwhobg==} + mc-assets@0.2.23: + resolution: {integrity: sha512-sLbPhsSOYdW8nYllIyPZbVPnLu7V3bZTgIO4mI4nlG525q17NIbUNEjItHKtdi60u0vI6qLgHKjf0CoNRqa/Nw==} engines: {node: '>=18.0.0'} md5-file@4.0.0: @@ -6770,8 +6772,8 @@ packages: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} - minecraft-data@3.78.0: - resolution: {integrity: sha512-Ssks8QD31lsoxqa7LySTqeP9romsfAbfsSGiUHiGMeqfxRi/PtOxGLyKD1BXB8V/tXLztFcbQYqzIhprDkPguw==} + minecraft-data@3.80.0: + resolution: {integrity: sha512-UYq+ADpS9K1+cqiJiz6tqkht4y4cRYF3qOYanG9eIiHY+VC+qIAC7/UcW6G3adayvj5YBOCurlqaw3E0TMAtHg==} minecraft-folder-path@1.2.0: resolution: {integrity: sha512-qaUSbKWoOsH9brn0JQuBhxNAzTDMwrOXorwuRxdJKKKDYvZhtml+6GVCUrY5HRiEsieBEjCUnhVpDuQiKsiFaw==} @@ -6780,9 +6782,9 @@ packages: resolution: {tarball: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/75e940a4cd50d89e0ba03db3733d5d704917a3c8} version: 1.0.1 - minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/590dc33fed2100e77ef58e7db716dfc45eb61159: - resolution: {tarball: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/590dc33fed2100e77ef58e7db716dfc45eb61159} - version: 1.50.0 + minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/f258c76b3a15badd902e82cd892168849444d79d: + resolution: {tarball: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/f258c76b3a15badd902e82cd892168849444d79d} + version: 1.51.0 engines: {node: '>=14'} minecraft-wrap@1.5.1: @@ -6803,8 +6805,8 @@ packages: resolution: {integrity: sha512-wSchhS59hK+oPs8tFg847H82YEvxU7zYKdDKj4e5FVo3CxJ74eXJVT+JcFwEvoqFO7kXiQlhJITxEvO13GOSKA==} engines: {node: '>=18'} - mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/ece6755d94931116924874d9f55bc024998cc1ae: - resolution: {tarball: https://codeload.github.com/zardoy/mineflayer/tar.gz/ece6755d94931116924874d9f55bc024998cc1ae} + mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/390ce12c1e1f25e440a94ba422e45c874f8bbd2b: + resolution: {tarball: https://codeload.github.com/zardoy/mineflayer/tar.gz/390ce12c1e1f25e440a94ba422e45c874f8bbd2b} version: 4.23.0 engines: {node: '>=18'} @@ -6969,8 +6971,8 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - net-browserify@https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/d3f7f77d8ac751bc171173bba639086c931a62f7: - resolution: {tarball: https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/d3f7f77d8ac751bc171173bba639086c931a62f7} + net-browserify@https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/ab3721ca833308a0be099d14ea0053fbd8459ace: + resolution: {tarball: https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/ab3721ca833308a0be099d14ea0053fbd8459ace} version: 0.2.4 nice-try@1.0.5: @@ -7516,7 +7518,7 @@ packages: prismarine-biome@1.3.0: resolution: {integrity: sha512-GY6nZxq93mTErT7jD7jt8YS1aPrOakbJHh39seYsJFXvueIOdHAmW16kYQVrTVMW5MlWLQVxV/EquRwOgr4MnQ==} peerDependencies: - minecraft-data: 3.78.0 + minecraft-data: 3.80.0 prismarine-registry: ^1.1.0 prismarine-block@https://codeload.github.com/zardoy/prismarine-block/tar.gz/23849d4d24af91f45a5bd38781a6f82d40316c05: @@ -7931,6 +7933,13 @@ packages: react: ^18.2.0 react-dom: ^16.8.0 || ^17.0.0 + react-zoom-pan-pinch@3.4.4: + resolution: {integrity: sha512-lGTu7D9lQpYEQ6sH+NSlLA7gicgKRW8j+D/4HO1AbSV2POvKRFzdWQ8eI0r3xmOsl4dYQcY+teV6MhULeg1xBw==} + engines: {node: '>=8', npm: '>=5'} + peerDependencies: + react: ^18.2.0 + react-dom: '*' + react@18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} engines: {node: '>=0.10.0'} @@ -9853,7 +9862,7 @@ snapshots: '@babel/core': 7.22.11 '@babel/helper-compilation-targets': 7.22.10 '@babel/helper-plugin-utils': 7.22.5 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 lodash.debounce: 4.0.8 resolve: 1.22.4 transitivePeerDependencies: @@ -10580,7 +10589,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.22.6 '@babel/parser': 7.22.13 '@babel/types': 7.23.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -11117,7 +11126,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.2 - '@types/node': 20.12.8 + '@types/node': 22.8.1 '@types/yargs': 17.0.28 chalk: 4.1.2 @@ -12823,7 +12832,7 @@ snapshots: '@types/body-parser@1.19.3': dependencies: '@types/connect': 3.4.36 - '@types/node': 20.12.8 + '@types/node': 22.8.1 '@types/chai-subset@1.3.3': dependencies: @@ -12833,17 +12842,17 @@ snapshots: '@types/connect@3.4.36': dependencies: - '@types/node': 20.12.8 + '@types/node': 22.8.1 '@types/cookie@0.4.1': {} '@types/cors@2.8.15': dependencies: - '@types/node': 20.12.8 + '@types/node': 22.8.1 '@types/cross-spawn@6.0.3': dependencies: - '@types/node': 20.12.8 + '@types/node': 22.8.1 '@types/debug@4.1.12': dependencies: @@ -12883,7 +12892,7 @@ snapshots: '@types/express-serve-static-core@4.17.37': dependencies: - '@types/node': 20.12.8 + '@types/node': 22.8.1 '@types/qs': 6.9.8 '@types/range-parser': 1.2.5 '@types/send': 0.17.2 @@ -12902,11 +12911,11 @@ snapshots: '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.12.8 + '@types/node': 22.8.1 '@types/graceful-fs@4.1.7': dependencies: - '@types/node': 20.12.8 + '@types/node': 22.8.1 '@types/http-cache-semantics@4.0.2': {} @@ -12954,9 +12963,13 @@ snapshots: '@types/node-fetch@2.6.6': dependencies: - '@types/node': 20.8.0 + '@types/node': 22.8.1 form-data: 4.0.0 + '@types/node-rsa@1.1.4': + dependencies: + '@types/node': 22.8.1 + '@types/node@14.18.56': optional: true @@ -12971,7 +12984,6 @@ snapshots: '@types/node@22.8.1': dependencies: undici-types: 6.19.8 - optional: true '@types/normalize-package-data@2.4.2': {} @@ -13012,7 +13024,7 @@ snapshots: '@types/resolve@1.17.1': dependencies: - '@types/node': 20.12.8 + '@types/node': 22.8.1 '@types/sat@0.0.31': {} @@ -13023,13 +13035,13 @@ snapshots: '@types/send@0.17.2': dependencies: '@types/mime': 1.3.3 - '@types/node': 20.12.8 + '@types/node': 22.8.1 '@types/serve-static@1.15.3': dependencies: '@types/http-errors': 2.0.2 '@types/mime': 3.0.2 - '@types/node': 20.12.8 + '@types/node': 22.8.1 '@types/sinonjs__fake-timers@8.1.1': optional: true @@ -13079,11 +13091,11 @@ snapshots: '@types/yauzl@2.10.1': dependencies: - '@types/node': 20.8.0 + '@types/node': 22.8.1 '@types/yauzl@2.10.3': dependencies: - '@types/node': 20.12.8 + '@types/node': 22.8.1 optional: true '@typescript-eslint/eslint-plugin@6.1.0(@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.5.4))(eslint@8.50.0)(typescript@5.5.4)': @@ -13139,7 +13151,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 6.1.0(typescript@5.5.4) '@typescript-eslint/utils': 6.1.0(eslint@8.50.0)(typescript@5.5.4) - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 eslint: 8.50.0 ts-api-utils: 1.0.3(typescript@5.5.4) optionalDependencies: @@ -13157,7 +13169,7 @@ snapshots: dependencies: '@typescript-eslint/types': 6.1.0 '@typescript-eslint/visitor-keys': 6.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.0 @@ -13171,7 +13183,7 @@ snapshots: dependencies: '@typescript-eslint/types': 6.7.3 '@typescript-eslint/visitor-keys': 6.7.3 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.0 @@ -13185,7 +13197,7 @@ snapshots: dependencies: '@typescript-eslint/types': 8.0.0 '@typescript-eslint/visitor-keys': 8.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.5 @@ -13419,7 +13431,7 @@ snapshots: '@types/emscripten': 1.39.8 tslib: 1.14.1 - '@zardoy/flying-squid@0.0.47(encoding@0.1.13)': + '@zardoy/flying-squid@0.0.49(encoding@0.1.13)': dependencies: '@tootallnate/once': 2.0.0 chalk: 5.3.0 @@ -13429,16 +13441,16 @@ snapshots: exit-hook: 2.2.1 flatmap: 0.0.3 long: 5.2.3 - minecraft-data: 3.78.0 - minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/590dc33fed2100e77ef58e7db716dfc45eb61159(patch_hash=7sh5krubuk2vjuogjioaktvwzi)(encoding@0.1.13) + minecraft-data: 3.80.0 + minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/f258c76b3a15badd902e82cd892168849444d79d(patch_hash=7sh5krubuk2vjuogjioaktvwzi)(encoding@0.1.13) mkdirp: 2.1.6 node-gzip: 1.1.2 node-rsa: 1.1.1 - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.78.0) + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.80.0) prismarine-entity: 2.3.1 prismarine-item: 1.15.0 prismarine-nbt: 2.5.0 - prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/d807fc339a3d95a7aef91468d4d64d367e7c682a(minecraft-data@3.78.0) + prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/d807fc339a3d95a7aef91468d4d64d367e7c682a(minecraft-data@3.80.0) prismarine-windows: 2.9.0 prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/6221e049e2ad0f508edc23c7f5bda7fd6d9566be rambda: 9.2.0 @@ -14912,7 +14924,7 @@ snapshots: detect-port@1.5.1: dependencies: address: 1.2.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 transitivePeerDependencies: - supports-color @@ -14922,8 +14934,8 @@ snapshots: diamond-square@https://codeload.github.com/zardoy/diamond-square/tar.gz/cfaad2d1d5909fdfa63c8cc7bc05fb5e87782d71: dependencies: - minecraft-data: 3.78.0 - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.78.0) + minecraft-data: 3.80.0 + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.80.0) prismarine-registry: 1.10.0 random-seed: 0.3.0 vec3: 0.1.8 @@ -15127,7 +15139,7 @@ snapshots: dependencies: '@types/cookie': 0.4.1 '@types/cors': 2.8.15 - '@types/node': 20.12.8 + '@types/node': 22.8.1 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.4.2 @@ -15418,8 +15430,6 @@ snapshots: '@esbuild/win32-ia32': 0.19.3 '@esbuild/win32-x64': 0.19.3 - escalade@3.1.1: {} - escalade@3.1.2: {} escape-html@1.0.3: {} @@ -16567,7 +16577,7 @@ snapshots: https-proxy-agent@4.0.0: dependencies: agent-base: 5.1.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 transitivePeerDependencies: - supports-color @@ -16582,7 +16592,7 @@ snapshots: https-proxy-agent@7.0.2: dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 transitivePeerDependencies: - supports-color @@ -16978,7 +16988,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.7 - '@types/node': 20.12.8 + '@types/node': 22.8.1 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -16995,7 +17005,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.8 + '@types/node': 22.8.1 chalk: 4.1.2 ci-info: 3.8.0 graceful-fs: 4.2.11 @@ -17003,19 +17013,19 @@ snapshots: jest-worker@26.6.2: dependencies: - '@types/node': 20.12.8 + '@types/node': 22.8.1 merge-stream: 2.0.0 supports-color: 7.2.0 jest-worker@27.5.1: dependencies: - '@types/node': 20.12.8 + '@types/node': 22.8.1 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 20.12.8 + '@types/node': 22.8.1 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -17443,7 +17453,7 @@ snapshots: dependencies: react: 18.2.0 - mc-assets@0.2.12: {} + mc-assets@0.2.23: {} md5-file@4.0.0: {} @@ -17656,7 +17666,7 @@ snapshots: micromark@4.0.0: dependencies: '@types/debug': 4.1.12 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.7 decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.0 @@ -17727,7 +17737,7 @@ snapshots: min-indent@1.0.1: {} - minecraft-data@3.78.0: {} + minecraft-data@3.80.0: {} minecraft-folder-path@1.2.0: {} @@ -17738,8 +17748,9 @@ snapshots: - '@types/react' - react - minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/590dc33fed2100e77ef58e7db716dfc45eb61159(patch_hash=7sh5krubuk2vjuogjioaktvwzi)(encoding@0.1.13): + minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/f258c76b3a15badd902e82cd892168849444d79d(patch_hash=7sh5krubuk2vjuogjioaktvwzi)(encoding@0.1.13): dependencies: + '@types/node-rsa': 1.1.4 '@types/readable-stream': 4.0.12 aes-js: 3.1.2 buffer-equal: 1.0.1 @@ -17747,7 +17758,7 @@ snapshots: endian-toggle: 0.0.0 lodash.get: 4.4.2 lodash.merge: 4.6.2 - minecraft-data: 3.78.0 + minecraft-data: 3.80.0 minecraft-folder-path: 1.2.0 node-fetch: 2.7.0(encoding@0.1.13) node-rsa: 0.4.2 @@ -17796,7 +17807,7 @@ snapshots: mineflayer-pathfinder@2.4.4: dependencies: - minecraft-data: 3.78.0 + minecraft-data: 3.80.0 prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/23849d4d24af91f45a5bd38781a6f82d40316c05 prismarine-entity: 2.3.1 prismarine-item: 1.15.0 @@ -17806,12 +17817,12 @@ snapshots: mineflayer@4.23.0(encoding@0.1.13): dependencies: - minecraft-data: 3.78.0 - minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/590dc33fed2100e77ef58e7db716dfc45eb61159(patch_hash=7sh5krubuk2vjuogjioaktvwzi)(encoding@0.1.13) - prismarine-biome: 1.3.0(minecraft-data@3.78.0)(prismarine-registry@1.10.0) + minecraft-data: 3.80.0 + minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/f258c76b3a15badd902e82cd892168849444d79d(patch_hash=7sh5krubuk2vjuogjioaktvwzi)(encoding@0.1.13) + prismarine-biome: 1.3.0(minecraft-data@3.80.0)(prismarine-registry@1.10.0) prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/23849d4d24af91f45a5bd38781a6f82d40316c05 prismarine-chat: 1.10.1 - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.78.0) + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.80.0) prismarine-entity: 2.3.1 prismarine-item: 1.15.0 prismarine-nbt: 2.5.0 @@ -17827,14 +17838,14 @@ snapshots: - encoding - supports-color - mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/ece6755d94931116924874d9f55bc024998cc1ae(encoding@0.1.13): + mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/390ce12c1e1f25e440a94ba422e45c874f8bbd2b(encoding@0.1.13): dependencies: - minecraft-data: 3.78.0 - minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/590dc33fed2100e77ef58e7db716dfc45eb61159(patch_hash=7sh5krubuk2vjuogjioaktvwzi)(encoding@0.1.13) - prismarine-biome: 1.3.0(minecraft-data@3.78.0)(prismarine-registry@1.10.0) + minecraft-data: 3.80.0 + minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/f258c76b3a15badd902e82cd892168849444d79d(patch_hash=7sh5krubuk2vjuogjioaktvwzi)(encoding@0.1.13) + prismarine-biome: 1.3.0(minecraft-data@3.80.0)(prismarine-registry@1.10.0) prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/23849d4d24af91f45a5bd38781a6f82d40316c05 prismarine-chat: 1.10.1 - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.78.0) + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.80.0) prismarine-entity: 2.3.1 prismarine-item: 1.15.0 prismarine-nbt: 2.5.0 @@ -18028,7 +18039,7 @@ snapshots: neo-async@2.6.2: {} - net-browserify@https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/d3f7f77d8ac751bc171173bba639086c931a62f7: + net-browserify@https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/ab3721ca833308a0be099d14ea0053fbd8459ace: dependencies: body-parser: 1.20.2 express: 4.18.2 @@ -18630,20 +18641,20 @@ snapshots: - encoding - supports-color - prismarine-biome@1.3.0(minecraft-data@3.78.0)(prismarine-registry@1.10.0): + prismarine-biome@1.3.0(minecraft-data@3.80.0)(prismarine-registry@1.10.0): dependencies: - minecraft-data: 3.78.0 + minecraft-data: 3.80.0 prismarine-registry: 1.10.0 - prismarine-biome@1.3.0(minecraft-data@3.78.0)(prismarine-registry@1.7.0): + prismarine-biome@1.3.0(minecraft-data@3.80.0)(prismarine-registry@1.7.0): dependencies: - minecraft-data: 3.78.0 + minecraft-data: 3.80.0 prismarine-registry: 1.7.0 prismarine-block@https://codeload.github.com/zardoy/prismarine-block/tar.gz/23849d4d24af91f45a5bd38781a6f82d40316c05: dependencies: - minecraft-data: 3.78.0 - prismarine-biome: 1.3.0(minecraft-data@3.78.0)(prismarine-registry@1.7.0) + minecraft-data: 3.80.0 + prismarine-biome: 1.3.0(minecraft-data@3.80.0)(prismarine-registry@1.7.0) prismarine-chat: 1.10.1 prismarine-item: 1.15.0 prismarine-nbt: 2.5.0 @@ -18655,9 +18666,9 @@ snapshots: prismarine-nbt: 2.5.0 prismarine-registry: 1.10.0 - prismarine-chunk@https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.78.0): + prismarine-chunk@https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.80.0): dependencies: - prismarine-biome: 1.3.0(minecraft-data@3.78.0)(prismarine-registry@1.10.0) + prismarine-biome: 1.3.0(minecraft-data@3.80.0)(prismarine-registry@1.10.0) prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/23849d4d24af91f45a5bd38781a6f82d40316c05 prismarine-nbt: 2.5.0 prismarine-registry: 1.10.0 @@ -18690,14 +18701,14 @@ snapshots: prismarine-physics@https://codeload.github.com/zardoy/prismarine-physics/tar.gz/353e25b800149393f40539ec381218be44cbb03b: dependencies: - minecraft-data: 3.78.0 + minecraft-data: 3.80.0 prismarine-nbt: 2.5.0 vec3: 0.1.8 - prismarine-provider-anvil@https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/d807fc339a3d95a7aef91468d4d64d367e7c682a(minecraft-data@3.78.0): + prismarine-provider-anvil@https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/d807fc339a3d95a7aef91468d4d64d367e7c682a(minecraft-data@3.80.0): dependencies: prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/23849d4d24af91f45a5bd38781a6f82d40316c05 - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.78.0) + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/416dd49bec42f4cc9f50ccf79527e6e4c01cebcb(minecraft-data@3.80.0) prismarine-nbt: 2.5.0 prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/6221e049e2ad0f508edc23c7f5bda7fd6d9566be uint4: 0.1.2 @@ -18719,17 +18730,17 @@ snapshots: prismarine-registry@1.10.0: dependencies: - minecraft-data: 3.78.0 + minecraft-data: 3.80.0 prismarine-nbt: 2.5.0 prismarine-registry@1.7.0: dependencies: - minecraft-data: 3.78.0 + minecraft-data: 3.80.0 prismarine-nbt: 2.5.0 prismarine-schematic@1.2.3: dependencies: - minecraft-data: 3.78.0 + minecraft-data: 3.80.0 prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/23849d4d24af91f45a5bd38781a6f82d40316c05 prismarine-nbt: 2.2.1 prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/6221e049e2ad0f508edc23c7f5bda7fd6d9566be @@ -19181,6 +19192,11 @@ snapshots: ts-easing: 0.2.0 tslib: 2.6.2 + react-zoom-pan-pinch@3.4.4(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react@18.2.0: dependencies: loose-envify: 1.4.0 @@ -20577,8 +20593,7 @@ snapshots: undici-types@5.26.5: {} - undici-types@6.19.8: - optional: true + undici-types@6.19.8: {} undici@5.25.4: dependencies: @@ -20698,7 +20713,7 @@ snapshots: update-browserslist-db@1.0.11(browserslist@4.21.10): dependencies: browserslist: 4.21.10 - escalade: 3.1.1 + escalade: 3.1.2 picocolors: 1.0.1 update-browserslist-db@1.1.0(browserslist@4.23.2): @@ -21310,7 +21325,7 @@ snapshots: yargs@16.2.0: dependencies: cliui: 7.0.4 - escalade: 3.1.1 + escalade: 3.1.2 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 diff --git a/prismarine-viewer/examples/baseScene.ts b/prismarine-viewer/examples/baseScene.ts index 1db68eb82..4b01abcd2 100644 --- a/prismarine-viewer/examples/baseScene.ts +++ b/prismarine-viewer/examples/baseScene.ts @@ -17,6 +17,7 @@ import { WorldDataEmitter } from '../viewer' import { Viewer } from '../viewer/lib/viewer' import { BlockNames } from '../../src/mcDataTypes' import { initWithRenderer, statsEnd, statsStart } from '../../src/topRightStats' +import { defaultWorldRendererConfig } from '../viewer/lib/worldrendererCommon' import { getSyncWorld } from './shared' window.THREE = THREE @@ -158,7 +159,7 @@ export class BasePlaygroundScene { renderer.setSize(window.innerWidth, window.innerHeight) // Create viewer - const viewer = new Viewer(renderer, { numWorkers: 6, showChunkBorders: false, }) + const viewer = new Viewer(renderer, { ...defaultWorldRendererConfig, numWorkers: 6 }) window.viewer = viewer const isWebgpu = false const promises = [] as Array> diff --git a/prismarine-viewer/examples/playgroundUi.tsx b/prismarine-viewer/examples/playgroundUi.tsx index 0de20d62d..ed183d780 100644 --- a/prismarine-viewer/examples/playgroundUi.tsx +++ b/prismarine-viewer/examples/playgroundUi.tsx @@ -4,10 +4,14 @@ 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: '' + selected: '', + selectorOpened: false, + actions: {} as Record void>, }) renderToDom() @@ -17,7 +21,7 @@ function Playground () { const style = document.createElement('style') style.innerHTML = /* css */ ` .lil-gui { - top: 40px !important; + top: 60px !important; right: 0 !important; } ` @@ -33,24 +37,31 @@ function Playground () { }}> + } function SceneSelector () { + const mobile = isMobile() const { scenes, selected } = useSnapshot(playgroundGlobalUiState) + const longPressEvents = useLongPress(() => { + playgroundGlobalUiState.selectorOpened = true + }, () => { }) - return
+ return
{scenes.map(scene =>
{ const qs = new URLSearchParams(window.location.search) @@ -61,6 +72,41 @@ function SceneSelector () {
} +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 diff --git a/prismarine-viewer/viewer/lib/entities.ts b/prismarine-viewer/viewer/lib/entities.ts index ef73faf7f..47a0303ef 100644 --- a/prismarine-viewer/viewer/lib/entities.ts +++ b/prismarine-viewer/viewer/lib/entities.ts @@ -1,5 +1,6 @@ //@ts-check import EventEmitter from 'events' +import { UnionToIntersection } from 'type-fest' import nbt from 'prismarine-nbt' import * as TWEEN from '@tweenjs/tween.js' import * as THREE from 'three' @@ -11,6 +12,7 @@ import { NameTagObject } from 'skinview3d/libs/nametag' import { flat, fromFormattedString } from '@xmcl/text-component' import mojangson from 'mojangson' import { snakeCase } from 'change-case' +import { EntityMetadataVersions } from '../../../src/mcDataTypes' import * as Entity from './entity/EntityMesh' import { WalkingGeneralSwing } from './entity/animations' import externalTexturesJson from './entity/externalTextures.json' @@ -20,12 +22,51 @@ export const TWEEN_DURATION = 120 type PlayerObjectType = PlayerObject & { animation?: PlayerAnimation } -function getUsernameTexture (username: string, { fontFamily = 'sans-serif' }: any) { +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 getUsernameTexture ({ + username, + nameTagBackgroundColor = 'rgba(0, 0, 0, 0.3)', + nameTagTextOpacity = 255 +}: any, { fontFamily = 'sans-serif' }: any) { const canvas = document.createElement('canvas') const ctx = canvas.getContext('2d') if (!ctx) throw new Error('Could not get 2d context') - const fontSize = 50 + const fontSize = 48 const padding = 5 ctx.font = `${fontSize}px ${fontFamily}` @@ -38,17 +79,17 @@ function getUsernameTexture (username: string, { fontFamily = 'sans-serif' }: an } canvas.width = textWidth - canvas.height = (fontSize + padding * 2) * lines.length + canvas.height = (fontSize + padding) * lines.length - ctx.fillStyle = 'rgba(0, 0, 0, 0.3)' + ctx.fillStyle = nameTagBackgroundColor ctx.fillRect(0, 0, canvas.width, canvas.height) ctx.font = `${fontSize}px ${fontFamily}` - ctx.fillStyle = 'white' + ctx.fillStyle = `rgba(255, 255, 255, ${nameTagTextOpacity / 255})` let i = 0 for (const line of lines) { i++ - ctx.fillText(line, padding + (textWidth - ctx.measureText(line).width) / 2, fontSize * i) + ctx.fillText(line, (textWidth - ctx.measureText(line).width) / 2, -padding + fontSize * i) } return canvas @@ -57,17 +98,39 @@ function getUsernameTexture (username: string, { fontFamily = 'sans-serif' }: an const addNametag = (entity, options, mesh) => { if (entity.username !== undefined) { if (mesh.children.some(c => c.name === 'nametag')) return // todo update - const canvas = getUsernameTexture(entity.username, options) + const canvas = getUsernameTexture(entity, options) const tex = new THREE.Texture(canvas) tex.needsUpdate = true - const spriteMat = new THREE.SpriteMaterial({ map: tex }) - const sprite = new THREE.Sprite(spriteMat) - sprite.renderOrder = 1000 - sprite.scale.set(canvas.width * 0.005, canvas.height * 0.005, 1) - sprite.position.y += entity.height + 0.6 - sprite.name = 'nametag' - - mesh.add(sprite) + let nameTag + 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) } } @@ -302,6 +365,9 @@ export class Entities extends EventEmitter { 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(x => x.text) return text.join('') @@ -352,7 +418,7 @@ export class Entities extends EventEmitter { } } - update (entity: import('prismarine-entity').Entity & { delete?; pos }, overrides) { + update (entity: import('prismarine-entity').Entity & { delete?; pos, name }, overrides) { const isPlayerModel = entity.name === 'player' if (entity.name === 'zombie' || 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`}` @@ -453,6 +519,8 @@ export class Entities extends EventEmitter { this.setRendering(this.rendering, group) } + const meta = getGeneralEntitiesMetadata(entity) + //@ts-expect-error // set visibility const isInvisible = entity.metadata?.[0] & 0x20 @@ -463,10 +531,24 @@ export class Entities extends EventEmitter { } // --- // not player - const displayText = entity.metadata?.[3] && this.parseEntityLabel(entity.metadata[2]) - || entity.metadata?.[23] && this.parseEntityLabel(entity.metadata[23]) // text displays + const textDisplayMeta = getSpecificEntityMetadata('text_display', entity) + const displayTextRaw = textDisplayMeta?.text || meta.custom_name_visible && meta.custom_name + const displayText = this.parseEntityLabel(displayTextRaw) if (entity.name !== 'player' && displayText) { - addNametag({ ...entity, username: displayText }, this.entitiesOptions, this.entities[entity.id].children.find(c => c.name === 'mesh')) + const nameTagFixed = textDisplayMeta && (textDisplayMeta.billboard_render_constraints === 'fixed' || !textDisplayMeta.billboard_render_constraints) + const nameTagBackgroundColor = textDisplayMeta && toRgba(textDisplayMeta.background_color) + let nameTagTextOpacity: any + if (textDisplayMeta?.text_opacity) { + const rawOpacity = parseInt(textDisplayMeta?.text_opacity, 10) + nameTagTextOpacity = rawOpacity > 0 ? rawOpacity : 256 - rawOpacity + } + addNametag( + { ...entity, username: displayText, 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, + this.entities[entity.id].children.find(c => c.name === 'mesh') + ) } // todo handle map, map_chunks events @@ -547,3 +629,19 @@ export class Entities extends EventEmitter { } } } + +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 +} diff --git a/prismarine-viewer/viewer/lib/hand.ts b/prismarine-viewer/viewer/lib/hand.ts new file mode 100644 index 000000000..6c9aacc53 --- /dev/null +++ b/prismarine-viewer/viewer/lib/hand.ts @@ -0,0 +1,96 @@ +import * as THREE from 'three' +import { loadSkinToCanvas } from 'skinview-utils' +import stevePng from 'mc-assets/dist/other-textures/latest/entity/player/wide/steve.png' + +let steveTexture: THREE.Texture +export const getMyHand = async (image?: string) => { + let newMap: THREE.Texture + if (!image && steveTexture) { + newMap = steveTexture + } else { + image ??= stevePng + const skinCanvas = document.createElement('canvas') + const img = new Image() + img.src = image + await new Promise(resolve => { + img.onload = () => { + resolve() + } + }) + loadSkinToCanvas(skinCanvas, img) + newMap = new THREE.CanvasTexture(skinCanvas) + // newMap.flipY = false + newMap.magFilter = THREE.NearestFilter + newMap.minFilter = THREE.NearestFilter + if (!image) { + steveTexture = newMap + } + } + + // 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/prismarine-viewer/viewer/lib/holdingBlock.ts b/prismarine-viewer/viewer/lib/holdingBlock.ts index f5a0ca799..5fc3e03c0 100644 --- a/prismarine-viewer/viewer/lib/holdingBlock.ts +++ b/prismarine-viewer/viewer/lib/holdingBlock.ts @@ -1,14 +1,19 @@ import * as THREE from 'three' import * as tweenJs from '@tweenjs/tween.js' import worldBlockProvider from 'mc-assets/dist/worldBlockProvider' +import { GUI } from 'lil-gui' import { getThreeBlockModelGroup, renderBlockThree, setBlockPosition } from './mesher/standaloneRenderer' +import { getMyHand } from './hand' export type HandItemBlock = { - name - properties + name? + properties? + type: 'block' | 'item' | 'hand' + id?: number } export default class HoldingBlock { + // TODO refactor with the tree builder for better visual understanding holdingBlock: THREE.Object3D | undefined = undefined swingAnimation: tweenJs.Group | undefined = undefined blockSwapAnimation: { @@ -16,22 +21,25 @@ export default class HoldingBlock { hidden: boolean } | undefined = undefined cameraGroup = new THREE.Mesh() - objectOuterGroup = new THREE.Group() - objectInnerGroup = new THREE.Group() - camera: THREE.Group | THREE.PerspectiveCamera + 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 toBeRenderedItem: HandItemBlock | undefined isSwinging = false nextIterStopCallbacks: Array<() => void> | undefined + rightSide = true - constructor (public scene: THREE.Scene) { + debug = {} as Record + + constructor () { this.initCameraGroup() } initCameraGroup () { this.cameraGroup = new THREE.Mesh() - this.scene.add(this.cameraGroup) } startSwing () { @@ -44,17 +52,18 @@ export default class HoldingBlock { // const DURATION = 1000 * 0.35 / 2 const DURATION = 1000 * 0.35 / 3 // const DURATION = 1000 + const { position, rotation, object } = this.getFinalSwingPositionRotation() const initialPos = { - x: this.objectInnerGroup.position.x, - y: this.objectInnerGroup.position.y, - z: this.objectInnerGroup.position.z + x: object.position.x, + y: object.position.y, + z: object.position.z } const initialRot = { - x: this.objectInnerGroup.rotation.x, - y: this.objectInnerGroup.rotation.y, - z: this.objectInnerGroup.rotation.z + x: object.rotation.x, + y: object.rotation.y, + z: object.rotation.z } - const mainAnim = new tweenJs.Tween(this.objectInnerGroup.position, this.swingAnimation).to({ y: this.objectInnerGroup.position.y - this.objectInnerGroup.scale.y / 2 }, DURATION).yoyo(true).repeat(Infinity).start() + const mainAnim = new tweenJs.Tween(object.position, this.swingAnimation).to(position, DURATION).yoyo(true).repeat(Infinity).start() let i = 0 mainAnim.onRepeat(() => { i++ @@ -67,14 +76,66 @@ export default class HoldingBlock { this.swingAnimation!.removeAll() this.swingAnimation = undefined // todo refactor to be more generic for animations - this.objectInnerGroup.position.set(initialPos.x, initialPos.y, initialPos.z) - // this.objectInnerGroup.rotation.set(initialRot.x, initialRot.y, initialRot.z) - Object.assign(this.objectInnerGroup.rotation, initialRot) + object.position.set(initialPos.x, initialPos.y, initialPos.z) + // object.rotation.set(initialRot.x, initialRot.y, initialRot.z) + Object.assign(object.rotation, initialRot) } }) - new tweenJs.Tween(this.objectInnerGroup.rotation, this.swingAnimation).to({ z: THREE.MathUtils.degToRad(90) }, DURATION).yoyo(true).repeat(Infinity).start() - new tweenJs.Tween(this.objectInnerGroup.rotation, this.swingAnimation).to({ x: -THREE.MathUtils.degToRad(90) }, DURATION).yoyo(true).repeat(Infinity).start() + new tweenJs.Tween(object.rotation, this.swingAnimation).to(rotation, DURATION).yoyo(true).repeat(Infinity).start() + } + } + + getFinalSwingPositionRotation (origPosition?: THREE.Vector3) { + const object = this.objectInnerGroup + if (this.lastHeldItem?.type === 'block') { + origPosition ??= object.position + return { + position: { y: origPosition.y - this.objectInnerGroup.scale.y / 2 }, + rotation: { z: THREE.MathUtils.degToRad(90), x: -THREE.MathUtils.degToRad(90) }, + object + } + } + if (this.lastHeldItem?.type === 'item') { + const object = this.holdingBlockInnerGroup + origPosition ??= object.position + return { + position: { + y: origPosition.y - object.scale.y * 2, + // z: origPosition.z - window.zFinal, + // x: origPosition.x - window.xFinal, + }, + // rotation: { z: THREE.MathUtils.degToRad(90), x: -THREE.MathUtils.degToRad(90) } + rotation: { + // z: THREE.MathUtils.degToRad(window.zRotationFinal ?? 0), + // x: THREE.MathUtils.degToRad(window.xRotationFinal ?? 0), + // y: THREE.MathUtils.degToRad(window.yRotationFinal ?? 0), + x: THREE.MathUtils.degToRad(-120) + }, + object + } + } + if (this.lastHeldItem?.type === 'hand') { + const object = this.holdingBlockInnerGroup + origPosition ??= object.position + return { + position: { + y: origPosition.y - (window.yFinal ?? 0.15), + z: origPosition.z - window.zFinal, + x: origPosition.x - window.xFinal, + }, + rotation: { + x: THREE.MathUtils.degToRad(window.xRotationFinal || -14.7), + y: THREE.MathUtils.degToRad(window.yRotationFinal || 33.95), + z: THREE.MathUtils.degToRad(window.zRotationFinal || -28), + }, + object + } + } + return { + position: {}, + rotation: {}, + object } } @@ -89,11 +150,35 @@ export default class HoldingBlock { }) } - update (camera: typeof this.camera) { - this.camera = camera + render (originalCamera: THREE.PerspectiveCamera, renderer: THREE.WebGLRenderer, ambientLight: THREE.AmbientLight, directionalLight: THREE.DirectionalLight) { + if (!this.lastHeldItem) return this.swingAnimation?.update() this.blockSwapAnimation?.tween.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) + + renderer.autoClear = false + renderer.clearDepth() + if (this.rightSide) { + const x = viewerSize.width - minSize + // if (x) x -= x / 4 + renderer.setViewport(x, 0, minSize, minSize) + } else { + renderer.setViewport(0, 0, minSize, minSize) + } + renderer.render(scene, this.camera) + renderer.setViewport(0, 0, viewerSize.width, viewerSize.height) } // worldTest () { @@ -142,23 +227,36 @@ export default class HoldingBlock { this.cameraGroup.position.copy(camera.position) this.cameraGroup.rotation.copy(camera.rotation) - const viewerSize = viewer.renderer.getSize(new THREE.Vector2()) - // const x = window.x ?? 0.25 * viewerSize.width / viewerSize.height - // const x = 0 * viewerSize.width / viewerSize.height - const x = 0.2 * viewerSize.width / viewerSize.height - this.objectOuterGroup.position.set(x, -0.3, -0.45) + // 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.rightSide ? 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) } - async initHandObject (material: THREE.Material, blockstatesModels: any, blocksAtlases: any, block?: HandItemBlock) { + async initHandObject (material: THREE.Material, blockstatesModels: any, blocksAtlases: any, handItem?: HandItemBlock) { let animatingCurrent = false - if (!this.swingAnimation && !this.blockSwapAnimation && this.isDifferentItem(block)) { + if (!this.swingAnimation && !this.blockSwapAnimation && this.isDifferentItem(handItem)) { animatingCurrent = true await this.playBlockSwapAnimation() this.holdingBlock?.removeFromParent() this.holdingBlock = undefined } - this.lastHeldItem = block - if (!block) { + this.lastHeldItem = handItem + if (!handItem) { this.holdingBlock?.removeFromParent() this.holdingBlock = undefined this.swingAnimation = undefined @@ -166,16 +264,28 @@ export default class HoldingBlock { return } const blockProvider = worldBlockProvider(blockstatesModels, blocksAtlases, 'latest') - const models = blockProvider.getAllResolvedModels0_1(block, true) - const blockInner = getThreeBlockModelGroup(material, models, undefined, 'plains', loadedData) - // const { mesh: itemMesh } = viewer.entities.getItemMesh({ - // itemId: 541, - // })! - // itemMesh.position.set(0.5, 0.5, 0.5) - // const blockInner = itemMesh + let blockInner + if (handItem.type === 'block') { + const models = blockProvider.getAllResolvedModels0_1({ + name: handItem.name, + properties: handItem.properties ?? {} + }, true) + blockInner = getThreeBlockModelGroup(material, models, undefined, 'plains', loadedData) + } else if (handItem.type === 'item') { + const { mesh: itemMesh } = viewer.entities.getItemMesh({ + itemId: handItem.id, + })! + itemMesh.position.set(0.5, 0.5, 0.5) + blockInner = itemMesh + } else { + blockInner = await getMyHand() + } blockInner.name = 'holdingBlock' const blockOuterGroup = new THREE.Group() - blockOuterGroup.add(blockInner) + this.holdingBlockInnerGroup.removeFromParent() + this.holdingBlockInnerGroup = new THREE.Group() + this.holdingBlockInnerGroup.add(blockInner) + blockOuterGroup.add(this.holdingBlockInnerGroup) this.holdingBlock = blockInner this.objectInnerGroup = new THREE.Group() this.objectInnerGroup.add(blockOuterGroup) @@ -190,18 +300,113 @@ export default class HoldingBlock { this.objectOuterGroup.add(this.objectInnerGroup) this.cameraGroup.add(this.objectOuterGroup) - const rotation = -45 + -90 - // const rotation = -45 // should be for item - this.holdingBlock.rotation.set(0, THREE.MathUtils.degToRad(rotation), 0, 'ZYX') + const rotationDeg = this.getHandHeld3d().rotation + let origPosition + const setRotation = () => { + const final = this.getFinalSwingPositionRotation(origPosition) + origPosition ??= final.object.position.clone() + if (this.debug.displayFinal) { + Object.assign(final.object.position, final.position) + Object.assign(final.object.rotation, final.rotation) + } else if (this.debug.displayFinal === false) { + final.object.rotation.set(0, 0, 0) + } - // const scale = window.scale ?? 0.2 - const scale = 0.2 - this.objectOuterGroup.scale.set(scale, scale, scale) - // this.objectOuterGroup.position.set(x, window.y ?? -0.41, window.z ?? -0.45) - // this.objectOuterGroup.position.set(x, 0, -0.45) + this.holdingBlock!.rotation.x = THREE.MathUtils.degToRad(rotationDeg.x) + this.holdingBlock!.rotation.y = THREE.MathUtils.degToRad(rotationDeg.y) + this.holdingBlock!.rotation.z = THREE.MathUtils.degToRad(rotationDeg.z) + this.objectOuterGroup.rotation.y = THREE.MathUtils.degToRad(rotationDeg.yOuter) + } + // const gui = new GUI() + // gui.add(rotationDeg, 'x', -180, 180, 0.1) + // gui.add(rotationDeg, 'y', -180, 180, 0.1) + // gui.add(rotationDeg, 'z', -180, 180, 0.1) + // gui.add(rotationDeg, 'yOuter', -180, 180, 0.1) + // Object.assign(window, { xFinal: 0, yFinal: 0, zFinal: 0, xRotationFinal: 0, yRotationFinal: 0, zRotationFinal: 0, displayFinal: true }) + // gui.add(window, 'xFinal', -10, 10, 0.05) + // gui.add(window, 'yFinal', -10, 10, 0.05) + // gui.add(window, 'zFinal', -10, 10, 0.05) + // gui.add(window, 'xRotationFinal', -180, 180, 0.05) + // gui.add(window, 'yRotationFinal', -180, 180, 0.05) + // gui.add(window, 'zRotationFinal', -180, 180, 0.05) + // gui.add(window, 'displayFinal') + // gui.onChange(setRotation) + setRotation() if (animatingCurrent) { await this.playBlockSwapAnimation() } } + + getHandHeld3d () { + const type = this.lastHeldItem?.type ?? 'hand' + const { debug } = this + + let scale = type === 'item' ? 0.68 : 0.45 + + const position = { + x: debug.x ?? 0.4, + y: debug.y ?? -0.7, + z: -0.45 + } + + if (type === 'item') { + position.x = -0.05 + // position.y -= 3.2 / 10 + // position.z += 1.13 / 10 + } + + if (type === 'hand') { + // position.x = viewer.camera.aspect > 1 ? 0.7 : 1.1 + position.y = -0.8 + scale = 0.8 + } + + const rotations = { + block: { + x: 0, + y: -45 + 90, + z: 0, + yOuter: 0 + }, + // hand: { + // x: 166.7, + // // y: -180, + // y: -165.2, + // // z: -156.3, + // z: -134.2, + // yOuter: -81.1 + // }, + hand: { + x: -32.4, + // y: 25.1 + y: 42.8, + z: -41.3, + yOuter: 0 + }, + // item: { + // x: -174, + // y: 47.3, + // z: -134.2, + // yOuter: -41.2 + // } + item: { + // x: -174, + // y: 47.3, + // z: -134.2, + // yOuter: -41.2 + x: 0, + // y: -90, // todo thats the correct one but we don't make it look too cheap because of no depth + y: -70, + z: window.z ?? 25, + yOuter: 0 + } + } + + return { + rotation: rotations[type], + position, + scale + } + } } diff --git a/prismarine-viewer/viewer/lib/mesher/mesher.ts b/prismarine-viewer/viewer/lib/mesher/mesher.ts index b38f04274..7c120abc1 100644 --- a/prismarine-viewer/viewer/lib/mesher/mesher.ts +++ b/prismarine-viewer/viewer/lib/mesher/mesher.ts @@ -159,7 +159,7 @@ setInterval(() => { 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 }, transferable) + postMessage({ type: 'geometry', key, geometry, workerIndex }, transferable) processTime = performance.now() - start } else { // console.info('[mesher] Missing section', x, y, z) diff --git a/prismarine-viewer/viewer/lib/mesher/models.ts b/prismarine-viewer/viewer/lib/mesher/models.ts index 91c0cf40f..51a00a448 100644 --- a/prismarine-viewer/viewer/lib/mesher/models.ts +++ b/prismarine-viewer/viewer/lib/mesher/models.ts @@ -4,7 +4,9 @@ import legacyJson from '../../../../src/preflatMap.json' import { BlockType } from '../../../examples/shared' import { World, BlockModelPartsResolved, WorldBlock as Block } from './world' import { BlockElement, buildRotationMatrix, elemFaces, matmul3, matmulmat3, vecadd3, vecsub3 } from './modelsGeometryCommon' -import { MesherGeometryOutput } from './shared' +import { INVISIBLE_BLOCKS } from './worldConstants' +import { MesherGeometryOutput, HighestBlockInfo } from './shared' + let blockProvider: WorldBlockProvider @@ -226,14 +228,12 @@ const identicalCull = (currentElement: BlockElement, neighbor: Block, direction: 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 - for (const model of models) { - for (const element of model.elements ?? []) { + return models.every(model => { + return (model.elements ?? []).every(element => { // todo check alfa on texture - if (element.faces[lookForOppositeSide]?.cullface && elemCompareForm(currentElement) === elemCompareForm(element) && elementEdgeValidator(element)) { - return true - } - } - } + return !!(element.faces[lookForOppositeSide]?.cullface && elemCompareForm(currentElement) === elemCompareForm(element) && elementEdgeValidator(element)) + }) + }) } let needSectionRecomputeOnChange = false @@ -439,8 +439,6 @@ function renderElement (world: World, cursor: Vec3, element: BlockElement, doAO: } } -const invisibleBlocks = new Set(['air', 'cave_air', 'void_air', 'barrier']) - const isBlockWaterlogged = (block: Block) => block.getProperties().waterlogged === true || block.getProperties().waterlogged === 'true' let unknownBlockModel: BlockModelPartsResolved @@ -464,7 +462,7 @@ export function getSectionGeometry (sx, sy, sz, world: World) { // todo this can be removed here signs: {}, // isFull: true, - highestBlocks: {}, // todo migrate to map for 2% boost perf + highestBlocks: new Map([]), hadErrors: false, blocksCount: 0 } @@ -474,16 +472,13 @@ export function getSectionGeometry (sx, sy, sz, world: World) { 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 (!invisibleBlocks.has(block.name)) { - const highest = attr.highestBlocks[`${cursor.x},${cursor.z}`] + if (!INVISIBLE_BLOCKS.has(block.name)) { + const highest = attr.highestBlocks.get(`${cursor.x},${cursor.z}`) if (!highest || highest.y < cursor.y) { - attr.highestBlocks[`${cursor.x},${cursor.z}`] = { - y: cursor.y, - name: block.name - } + attr.highestBlocks.set(`${cursor.x},${cursor.z}`, { y: cursor.y, stateId: block.stateId, biomeId: block.biome.id }) } } - if (invisibleBlocks.has(block.name)) continue + if (INVISIBLE_BLOCKS.has(block.name)) continue if ((block.name.includes('_sign') || block.name === 'sign') && !world.config.disableSignsMapsSupport) { const key = `${cursor.x},${cursor.y},${cursor.z}` const props: any = block.getProperties() @@ -531,7 +526,7 @@ export function getSectionGeometry (sx, sy, sz, world: World) { renderLiquid(world, cursor, blockProvider.getTextureInfo('lava_still'), block.type, biome, false, attr) attr.blocksCount++ } - if (block.name !== 'water' && block.name !== 'lava' && !invisibleBlocks.has(block.name)) { + if (block.name !== 'water' && block.name !== 'lava' && !INVISIBLE_BLOCKS.has(block.name)) { // cache let { models } = block @@ -624,8 +619,8 @@ export function getSectionGeometry (sx, sy, sz, world: World) { return attr } -export const setBlockStatesData = (blockstatesModels, blocksAtlas: any, _needTiles = false, useUnknownBlockModel = true) => { - blockProvider = worldBlockProvider(blockstatesModels, blocksAtlas, 'latest') +export const setBlockStatesData = (blockstatesModels, blocksAtlas: any, _needTiles = false, useUnknownBlockModel = true, version = 'latest') => { + blockProvider = worldBlockProvider(blockstatesModels, blocksAtlas, version) globalThis.blockProvider = blockProvider if (useUnknownBlockModel) { unknownBlockModel = blockProvider.getAllResolvedModels0_1({ name: 'unknown', properties: {} }) diff --git a/prismarine-viewer/viewer/lib/mesher/shared.ts b/prismarine-viewer/viewer/lib/mesher/shared.ts index b08a2bd76..57d7d6a44 100644 --- a/prismarine-viewer/viewer/lib/mesher/shared.ts +++ b/prismarine-viewer/viewer/lib/mesher/shared.ts @@ -32,7 +32,9 @@ export type MesherGeometryOutput = { tiles: Record, signs: Record, // isFull: boolean - highestBlocks: Record + highestBlocks: Map hadErrors: boolean blocksCount: number } + +export type HighestBlockInfo = { y: number, stateId: number | undefined, biomeId: number | undefined } diff --git a/prismarine-viewer/viewer/lib/mesher/test/mesherTester.ts b/prismarine-viewer/viewer/lib/mesher/test/mesherTester.ts index ef91b1919..e75d803de 100644 --- a/prismarine-viewer/viewer/lib/mesher/test/mesherTester.ts +++ b/prismarine-viewer/viewer/lib/mesher/test/mesherTester.ts @@ -33,7 +33,7 @@ export const setup = (version, initialBlocks: Array<[number[], string]>) => { } } - setBlockStatesData(blockStatesModels, blocksAtlasesJson, true, false) + setBlockStatesData(blockStatesModels, blocksAtlasesJson, true, false, version) const reload = () => { mesherWorld.removeColumn(0, 0) mesherWorld.addColumn(0, 0, chunk1.toJson()) diff --git a/prismarine-viewer/viewer/lib/mesher/test/tests.test.ts b/prismarine-viewer/viewer/lib/mesher/test/tests.test.ts index e1d51f223..78374b6bd 100644 --- a/prismarine-viewer/viewer/lib/mesher/test/tests.test.ts +++ b/prismarine-viewer/viewer/lib/mesher/test/tests.test.ts @@ -1,5 +1,6 @@ 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) @@ -16,7 +17,7 @@ const addPositions = [ test('Known blocks are not rendered', () => { const { mesherWorld, getGeometry, pos, mcData } = setup(lastVersion, addPositions as any) - const ignoreAsExpected = new Set(['air', 'cave_air', 'void_air', 'barrier', 'water', 'lava', 'moving_piston', 'light']) + const ignoreAsExpected = new Set([...INVISIBLE_BLOCKS, 'water', 'lava', 'moving_piston', 'light']) let time = 0 let times = 0 @@ -42,11 +43,14 @@ test('Known blocks are not rendered', () => { } } } + 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(` { "bubble_column": true, + "creaking_heart": true, "end_gateway": true, "end_portal": true, "structure_void": true, diff --git a/prismarine-viewer/viewer/lib/mesher/worldConstants.ts b/prismarine-viewer/viewer/lib/mesher/worldConstants.ts new file mode 100644 index 000000000..75f08e89e --- /dev/null +++ b/prismarine-viewer/viewer/lib/mesher/worldConstants.ts @@ -0,0 +1 @@ +export const INVISIBLE_BLOCKS = new Set(['air', 'void_air', 'cave_air', 'barrier']) diff --git a/prismarine-viewer/viewer/lib/viewer.ts b/prismarine-viewer/viewer/lib/viewer.ts index d16dbe811..20f10284e 100644 --- a/prismarine-viewer/viewer/lib/viewer.ts +++ b/prismarine-viewer/viewer/lib/viewer.ts @@ -3,12 +3,14 @@ import * as THREE from 'three' import { Vec3 } from 'vec3' import { generateSpiralMatrix } from 'flying-squid/dist/utils' import worldBlockProvider from 'mc-assets/dist/worldBlockProvider' +import stevePng from 'mc-assets/dist/other-textures/latest/entity/player/wide/steve.png' import { Entities } from './entities' import { Primitives } from './primitives' import { WorldRendererThree } from './worldrendererThree' import { WorldRendererCommon, WorldRendererConfig, defaultWorldRendererConfig } from './worldrendererCommon' import { getThreeBlockModelGroup, renderBlockThree, setBlockPosition } from './mesher/standaloneRenderer' import { addNewStat } from './ui/newStats' +import { getMyHand } from './hand' export class Viewer { scene: THREE.Scene @@ -26,6 +28,8 @@ export class Viewer { renderingUntilNoUpdates = false processEntityOverrides = (e, overrides) => overrides + getMineflayerBot (): void | Record {} // to be overridden + get camera () { return this.world.camera } @@ -78,15 +82,16 @@ export class Viewer { // this.primitives.clear() } - setVersion (userVersion: string, texturesVersion = userVersion) { + setVersion (userVersion: string, texturesVersion = userVersion): void | Promise { console.log('[viewer] Using version:', userVersion, 'textures:', texturesVersion) - void this.world.setVersion(userVersion, texturesVersion).then(async () => { + this.entities.clear() + // this.primitives.clear() + return this.world.setVersion(userVersion, texturesVersion).then(async () => { return new THREE.TextureLoader().loadAsync(this.world.itemsAtlasParser!.latestImage) }).then((texture) => { this.entities.itemsTexture = texture + this.world.renderUpdateEmitter.emit('itemsTextureDownloaded') }) - this.entities.clear() - // this.primitives.clear() } addColumn (x, z, chunk, isLightUpdate = false) { @@ -98,24 +103,26 @@ export class Viewer { } setBlockStateId (pos: Vec3, stateId: number) { - if (!this.world.loadedChunks[`${Math.floor(pos.x / 16) * 16},${Math.floor(pos.z / 16) * 16}`]) { - console.debug('[should be unreachable] setBlockStateId called for unloaded chunk', pos) + const set = async () => { + const sectionX = Math.floor(pos.x / 16) * 16 + const sectionZ = Math.floor(pos.z / 16) * 16 + if (this.world.queuedChunks.has(`${sectionX},${sectionZ}`)) { + await this.world.waitForChunkToLoad(pos) + } + if (!this.world.loadedChunks[`${sectionX},${sectionZ}`]) { + console.debug('[should be unreachable] setBlockStateId called for unloaded chunk', pos) + } + this.world.setBlockStateId(pos, stateId) } - this.world.setBlockStateId(pos, stateId) + void set() } - demoModel () { + async demoModel () { //@ts-expect-error const pos = cursorBlockRel(0, 1, 0).position const blockProvider = worldBlockProvider(this.world.blockstatesModels, this.world.blocksAtlases, 'latest') - const models = blockProvider.getAllResolvedModels0_1({ - name: 'item_frame', - properties: { - // map: false - } - }, true) - const { material } = this.world - const mesh = getThreeBlockModelGroup(material, models, undefined, 'plains', loadedData) + + const mesh = await getMyHand() // mesh.rotation.y = THREE.MathUtils.degToRad(90) setBlockPosition(mesh, pos) const helper = new THREE.BoxHelper(mesh, 0xff_ff_00) @@ -150,12 +157,11 @@ export class Viewer { setFirstPersonCamera (pos: Vec3 | null, yaw: number, pitch: number, roll = 0) { const cam = this.cameraObjectOverride || this.camera - let yOffset = this.playerHeight + let yOffset = this.getMineflayerBot()?.entity?.eyeHeight ?? this.playerHeight if (this.isSneaking) yOffset -= 0.3 - if (this.world instanceof WorldRendererThree) { - this.world.camera = cam as THREE.PerspectiveCamera - } + this.world.camera = cam as THREE.PerspectiveCamera + this.world.updateCamera(pos?.offset(0, yOffset, 0) ?? null, yaw, pitch) } @@ -205,6 +211,7 @@ export class Viewer { } | null worldEmitter.on('loadChunk', ({ x, z, chunk, worldConfig, isLightUpdate }) => { this.world.worldConfig = worldConfig + this.world.queuedChunks.add(`${x},${z}`) const args = [x, z, chunk, isLightUpdate] if (!currentLoadChunkBatch) { // add a setting to use debounce instead @@ -212,6 +219,7 @@ export class Viewer { data: [], timeout: setTimeout(() => { for (const args of currentLoadChunkBatch!.data) { + this.world.queuedChunks.delete(`${args[0]},${args[1]}`) this.addColumn(...args as Parameters) } currentLoadChunkBatch = null @@ -222,7 +230,7 @@ export class Viewer { }) // todo remove and use other architecture instead so data flow is clear worldEmitter.on('blockEntities', (blockEntities) => { - if (this.world instanceof WorldRendererThree) this.world.blockEntities = blockEntities + if (this.world instanceof WorldRendererThree) (this.world).blockEntities = blockEntities }) worldEmitter.on('unloadChunk', ({ x, z }) => { @@ -237,14 +245,24 @@ export class Viewer { this.world.updateViewerPosition(pos) }) + + worldEmitter.on('renderDistance', (d) => { + this.world.viewDistance = d + this.world.chunksLength = d === 0 ? 1 : generateSpiralMatrix(d).length + }) + worldEmitter.on('renderDistance', (d) => { this.world.viewDistance = d this.world.chunksLength = d === 0 ? 1 : generateSpiralMatrix(d).length this.world.allChunksFinished = Object.keys(this.world.finishedChunks).length === this.world.chunksLength }) + worldEmitter.on('markAsLoaded', ({ x, z }) => { + this.world.markAsLoaded(x, z) + }) + worldEmitter.on('updateLight', ({ pos }) => { - if (this.world instanceof WorldRendererThree) this.world.updateLight(pos.x, pos.z) + if (this.world instanceof WorldRendererThree) (this.world).updateLight(pos.x, pos.z) }) worldEmitter.on('time', (timeOfDay) => { @@ -264,16 +282,20 @@ export class Viewer { skyLight = Math.floor(skyLight) // todo: remove this after optimization if (this.world.mesherConfig.skyLight === skyLight) return - this.world.mesherConfig.skyLight = skyLight; - (this.world as WorldRendererThree).rerenderAllChunks?.() + this.world.mesherConfig.skyLight = skyLight + if (this.world instanceof WorldRendererThree) { + (this.world).rerenderAllChunks?.() + } }) worldEmitter.emit('listening') } render () { - this.world.render() - this.entities.render() + if (this.world instanceof WorldRendererThree) { + (this.world).render() + this.entities.render() + } } async waitForChunksToRender () { diff --git a/prismarine-viewer/viewer/lib/worldDataEmitter.ts b/prismarine-viewer/viewer/lib/worldDataEmitter.ts index 51c0a08b8..61d5a503a 100644 --- a/prismarine-viewer/viewer/lib/worldDataEmitter.ts +++ b/prismarine-viewer/viewer/lib/worldDataEmitter.ts @@ -6,6 +6,7 @@ import { generateSpiralMatrix, ViewRect } from 'flying-squid/dist/utils' import { Vec3 } from 'vec3' import { BotEvents } from 'mineflayer' import { getItemFromBlock } from '../../../src/chatUtils' +import { delayedIterator } from '../../examples/shared' import { chunkPos } from './simpleUtils' export type ChunkPosKey = string @@ -22,14 +23,7 @@ export class WorldDataEmitter extends EventEmitter { private readonly emitter: WorldDataEmitter keepChunksDistance = 0 addWaitTime = 1 - _handDisplay = false - get handDisplay () { - return this._handDisplay - } - set handDisplay (newVal) { - this._handDisplay = newVal - this.eventListeners.heldItemChanged?.() - } + isPlayground = false constructor (public world: typeof __type_bot['world'], public viewDistance: number, position: Vec3 = new Vec3(0, 0, 0)) { super() @@ -105,23 +99,29 @@ export class WorldDataEmitter extends EventEmitter { time: () => { this.emitter.emit('time', bot.time.timeOfDay) }, - heldItemChanged: () => { - if (!this.handDisplay) { - viewer.world.onHandItemSwitch(undefined) - return - } - const newItem = bot.heldItem - if (!newItem) { - viewer.world.onHandItemSwitch(undefined) - return - } - const block = loadedData.blocksByName[newItem.name] - // todo clean types - const blockProperties = block ? new window.PrismarineBlock(block.id, 'void', newItem.metadata).getProperties() : {} - viewer.world.onHandItemSwitch({ name: newItem.name, properties: blockProperties }) + heldItemChanged () { + handChanged(false) }, } satisfies Partial - this.eventListeners.heldItemChanged() + const handChanged = (isLeftHand: boolean) => { + const newItem = isLeftHand ? bot.inventory.slots[45] : bot.heldItem + if (!newItem) { + viewer.world.onHandItemSwitch(undefined, isLeftHand) + return + } + const block = loadedData.blocksByName[newItem.name] + // todo clean types + const blockProperties = block ? new window.PrismarineBlock(block.id, 'void', newItem.metadata).getProperties() : {} + // todo item props + viewer.world.onHandItemSwitch({ name: newItem.name, properties: blockProperties, id: newItem.type, type: block ? 'block' : 'item', }, isLeftHand) + } + bot.inventory.on('updateSlot', (index) => { + if (index === 45) { + handChanged(true) + } + }) + handChanged(false) + handChanged(true) bot._client.on('update_light', ({ chunkX, chunkZ }) => { @@ -173,19 +173,11 @@ export class WorldDataEmitter extends EventEmitter { } async _loadChunks (positions: Vec3[], sliceSize = 5) { - let i = 0 const promises = [] as Array> - return new Promise(resolve => { - const interval = setInterval(() => { - if (i >= positions.length) { - clearInterval(interval) - void Promise.all(promises).then(() => resolve()) - return - } - promises.push(this.loadChunk(positions[i])) - i++ - }, this.addWaitTime) + await delayedIterator(positions, this.addWaitTime, (pos) => { + promises.push(this.loadChunk(pos)) }) + await Promise.all(promises) } readdDebug () { @@ -221,6 +213,8 @@ export class WorldDataEmitter extends EventEmitter { //@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 + } 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) diff --git a/prismarine-viewer/viewer/lib/worldrendererCommon.ts b/prismarine-viewer/viewer/lib/worldrendererCommon.ts index 65546de4f..ec649a14f 100644 --- a/prismarine-viewer/viewer/lib/worldrendererCommon.ts +++ b/prismarine-viewer/viewer/lib/worldrendererCommon.ts @@ -11,13 +11,15 @@ import itemsAtlasLatest from 'mc-assets/dist/itemsAtlasLatest.png' import itemsAtlasLegacy from 'mc-assets/dist/itemsAtlasLegacy.png' import { AtlasParser } from 'mc-assets' import TypedEmitter from 'typed-emitter' +import { LineMaterial } from 'three-stdlib' import { dynamicMcDataFiles } from '../../buildMesherConfig.mjs' import { toMajorVersion } from '../../../src/utils' import { buildCleanupDecorator } from './cleanupDecorator' -import { MesherGeometryOutput, defaultMesherConfig } from './mesher/shared' +import { defaultMesherConfig, HighestBlockInfo, MesherGeometryOutput } from './mesher/shared' import { chunkPos } from './simpleUtils' import { HandItemBlock } from './holdingBlock' import { updateStatText } from './ui/newStats' +import { WorldRendererThree } from './worldrendererThree' function mod (x, n) { return ((x % n) + n) % n @@ -27,7 +29,9 @@ export const worldCleanup = buildCleanupDecorator('resetWorld') export const defaultWorldRendererConfig = { showChunkBorders: false, - numWorkers: 4 + numWorkers: 4, + // game renderer setting actually + displayHand: false } export type WorldRendererConfig = typeof defaultWorldRendererConfig @@ -38,8 +42,14 @@ type CustomTexturesData = { } export abstract class WorldRendererCommon { + // todo + @worldCleanup() + threejsCursorLineMaterial: LineMaterial + @worldCleanup() + cursorBlock = null as Vec3 | null isPlayground = false displayStats = true + @worldCleanup() worldConfig = { minY: 0, worldHeight: 256 } // todo need to cleanup material = new THREE.MeshLambertMaterial({ vertexColors: true, transparent: true, alphaTest: 0.1 }) @@ -49,27 +59,37 @@ export abstract class WorldRendererCommon version = undefined as string | undefined @worldCleanup() - loadedChunks = {} as Record + loadedChunks = {} as Record // data is added for these chunks and they might be still processing @worldCleanup() - finishedChunks = {} as Record + finishedChunks = {} as Record // these chunks are fully loaded into the world (scene) @worldCleanup() - sectionsOutstanding = new Map() + // loading sections (chunks) + sectionsWaiting = new Map() + + @worldCleanup() + queuedChunks = new Set() @worldCleanup() renderUpdateEmitter = new EventEmitter() as unknown as TypedEmitter<{ dirty (pos: Vec3, value: boolean): void update (/* pos: Vec3, value: boolean */): void textureDownloaded (): void + itemsTextureDownloaded (): void + chunkFinished (key: string): void }> customTexturesDataUrl = undefined as string | undefined @worldCleanup() currentTextureImage = undefined as any workers: any[] = [] + @worldCleanup() viewerPosition?: Vec3 lastCamUpdate = 0 droppedFpsPercentage = 0 + @worldCleanup() + initialChunkLoadWasStartedIn: number | undefined + @worldCleanup() initialChunksLoad = true enableChunksLoadDelay = false texturesVersion?: string @@ -81,7 +101,7 @@ export abstract class WorldRendererCommon handleResize = () => { } mesherConfig = defaultMesherConfig camera: THREE.PerspectiveCamera - highestBlocks: Record = {} + highestBlocks = new Map() blockstatesModels: any customBlockStates: Record | undefined customModels: Record | undefined @@ -97,6 +117,10 @@ export abstract class WorldRendererCommon workersProcessAverageTime = 0 workersProcessAverageTimeCount = 0 maxWorkersProcessTime = 0 + geometryReceiveCount = {} + allLoadedIn: undefined | number + rendererDevice = '...' + edgeChunks = {} as Record lastAddChunk = null as null | { timeout: any @@ -108,13 +132,15 @@ export abstract class WorldRendererCommon abstract outputFormat: 'threeJs' | 'webgpu' + abstract changeBackgroundColor (color: [number, number, number]): void + constructor (public config: WorldRendererConfig) { // this.initWorkers(1) // preload script on page load this.snapshotInitialValues() this.renderUpdateEmitter.on('update', () => { const loadedChunks = Object.keys(this.finishedChunks).length - updateStatText('loaded-chunks', `${loadedChunks}/${this.chunksLength} chunks (${this.lastChunkDistance})`) + updateStatText('loaded-chunks', `${loadedChunks}/${this.chunksLength} chunks (${this.lastChunkDistance}/${this.viewDistance})`) }) } @@ -122,7 +148,7 @@ export abstract class WorldRendererCommon initWorkers (numWorkers = this.config.numWorkers) { // init workers - for (let i = 0; i < numWorkers; i++) { + for (let i = 0; i < numWorkers + 1; i++) { // Node environment needs an absolute path, but browser needs the url of the file const workerName = 'mesher.js' // eslint-disable-next-line node/no-path-concat @@ -133,6 +159,8 @@ export abstract class WorldRendererCommon if (!this.active) return this.handleWorkerMessage(data) if (data.type === 'geometry') { + this.geometryReceiveCount[data.workerIndex] ??= 0 + this.geometryReceiveCount[data.workerIndex]++ const geometry = data.geometry as MesherGeometryOutput for (const key in geometry.highestBlocks) { const highest = geometry.highestBlocks[key] @@ -144,13 +172,13 @@ export abstract class WorldRendererCommon this.lastChunkDistance = Math.max(...this.getDistance(new Vec3(chunkCoords[0], 0, chunkCoords[2]))) } if (data.type === 'sectionFinished') { // on after load & unload section - if (!this.sectionsOutstanding.get(data.key)) throw new Error(`sectionFinished event for non-outstanding section ${data.key}`) - this.sectionsOutstanding.set(data.key, this.sectionsOutstanding.get(data.key)! - 1) - if (this.sectionsOutstanding.get(data.key) === 0) this.sectionsOutstanding.delete(data.key) + if (!this.sectionsWaiting.get(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) const chunkCoords = data.key.split(',').map(Number) if (this.loadedChunks[`${chunkCoords[0]},${chunkCoords[2]}`]) { // ensure chunk data was added, not a neighbor chunk update - const loadingKeys = [...this.sectionsOutstanding.keys()] + const loadingKeys = [...this.sectionsWaiting.keys()] if (!loadingKeys.some(key => { const [x, y, z] = key.split(',').map(Number) return x === chunkCoords[0] && z === chunkCoords[2] @@ -158,13 +186,7 @@ export abstract class WorldRendererCommon this.finishedChunks[`${chunkCoords[0]},${chunkCoords[2]}`] = true } } - if (this.sectionsOutstanding.size === 0) { - const allFinished = Object.keys(this.finishedChunks).length === this.chunksLength - if (allFinished) { - this.allChunksLoaded?.() - this.allChunksFinished = true - } - } + this.checkAllFinished() this.renderUpdateEmitter.emit('update') if (data.processTime) { @@ -187,8 +209,18 @@ export abstract class WorldRendererCommon } } - onHandItemSwitch (item: HandItemBlock | undefined): void { } - changeHandSwingingState (isAnimationPlaying: boolean): void { } + checkAllFinished () { + if (this.sectionsWaiting.size === 0) { + const allFinished = Object.keys(this.finishedChunks).length === this.chunksLength + if (allFinished) { + this.allChunksLoaded?.() + this.allChunksFinished = true + } + } + } + + onHandItemSwitch (item: HandItemBlock | undefined, isLeftHand: boolean): void { } + changeHandSwingingState (isAnimationPlaying: boolean, isLeftHand: boolean): void { } abstract handleWorkerMessage (data: WorkerReceive): void @@ -268,7 +300,7 @@ export abstract class WorldRendererCommon } } - async updateTexturesData () { + async updateTexturesData (resourcePackUpdate = false) { const blocksAssetsParser = new AtlasParser(this.blocksAtlases, blocksAtlasLatest, blocksAtlasLegacy) const itemsAssetsParser = new AtlasParser(this.itemsAtlases, itemsAtlasLatest, itemsAtlasLegacy) const { atlas: blocksAtlas, canvas: blocksCanvas } = await blocksAssetsParser.makeNewAtlas(this.texturesVersion ?? this.version ?? 'latest', (textureName) => { @@ -325,11 +357,17 @@ export abstract class WorldRendererCommon return Math.floor(Math.max(this.worldConfig.minY, this.mesherConfig.clipWorldBelowY ?? -Infinity) / 16) * 16 } + updateChunksStatsText () { + updateStatText('downloaded-chunks', `${Object.keys(this.loadedChunks).length}/${this.chunksLength} chunks D (${this.workers.length}:${this.workersProcessAverageTime.toFixed(0)}ms/${this.allLoadedIn?.toFixed(1) ?? '-'}s)`) + } + 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.updateChunksStatsText() for (const worker of this.workers) { // todo optimize worker.postMessage({ type: 'chunk', x, z, chunk }) @@ -346,13 +384,19 @@ export abstract class WorldRendererCommon } } + markAsLoaded (x, z) { + this.loadedChunks[`${x},${z}`] = true + this.finishedChunks[`${x},${z}`] = true + this.checkAllFinished() + } + removeColumn (x, z) { delete this.loadedChunks[`${x},${z}`] for (const worker of this.workers) { worker.postMessage({ type: 'unloadChunk', x, z }) } - this.allChunksFinished = Object.keys(this.finishedChunks).length === this.chunksLength delete this.finishedChunks[`${x},${z}`] + this.allChunksFinished = Object.keys(this.finishedChunks).length === this.chunksLength for (let y = this.worldConfig.minY; y < this.worldConfig.worldHeight; y += 16) { this.setSectionDirty(new Vec3(x, y, z), false) } @@ -369,24 +413,31 @@ export abstract class WorldRendererCommon } setBlockStateId (pos: Vec3, stateId: number) { + const key = `${Math.floor(pos.x / 16) * 16},${Math.floor(pos.y / 16) * 16},${Math.floor(pos.z / 16) * 16}` + const useChangeWorker = !this.sectionsWaiting[key] for (const worker of this.workers) { worker.postMessage({ type: 'blockUpdate', pos, stateId }) } - this.setSectionDirty(pos) + this.setSectionDirty(pos, true, useChangeWorker) if (this.neighborChunkUpdates) { - if ((pos.x & 15) === 0) this.setSectionDirty(pos.offset(-16, 0, 0)) - if ((pos.x & 15) === 15) this.setSectionDirty(pos.offset(16, 0, 0)) - if ((pos.y & 15) === 0) this.setSectionDirty(pos.offset(0, -16, 0)) - if ((pos.y & 15) === 15) this.setSectionDirty(pos.offset(0, 16, 0)) - if ((pos.z & 15) === 0) this.setSectionDirty(pos.offset(0, 0, -16)) - if ((pos.z & 15) === 15) this.setSectionDirty(pos.offset(0, 0, 16)) + if ((pos.x & 15) === 0) this.setSectionDirty(pos.offset(-16, 0, 0), true, useChangeWorker) + if ((pos.x & 15) === 15) this.setSectionDirty(pos.offset(16, 0, 0), true, useChangeWorker) + if ((pos.y & 15) === 0) this.setSectionDirty(pos.offset(0, -16, 0), true, useChangeWorker) + if ((pos.y & 15) === 15) this.setSectionDirty(pos.offset(0, 16, 0), true, useChangeWorker) + if ((pos.z & 15) === 0) this.setSectionDirty(pos.offset(0, 0, -16), true, useChangeWorker) + if ((pos.z & 15) === 15) this.setSectionDirty(pos.offset(0, 0, 16), true, useChangeWorker) } } queueAwaited = false messagesQueue = {} as { [workerIndex: string]: any[] } - setSectionDirty (pos: Vec3, value = true) { // value false is used for unloading chunks + getWorkerNumber (pos: Vec3) { + 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 + } + + setSectionDirty (pos: Vec3, value = true, useChangeWorker = false) { // value false is used for unloading chunks if (this.viewDistance === -1) throw new Error('viewDistance not set') this.allChunksFinished = false const distance = this.getDistance(pos) @@ -397,8 +448,8 @@ export abstract class WorldRendererCommon // 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 = mod(Math.floor(pos.x / 16) + Math.floor(pos.y / 16) + Math.floor(pos.z / 16), this.workers.length) - this.sectionsOutstanding.set(key, (this.sectionsOutstanding.get(key) ?? 0) + 1) + const hash = useChangeWorker ? 0 : this.getWorkerNumber(pos) + this.sectionsWaiting.set(key, (this.sectionsWaiting.get(key) ?? 0) + 1) this.messagesQueue[hash] ??= [] this.messagesQueue[hash].push({ // this.workers[hash].postMessage({ @@ -430,13 +481,13 @@ export abstract class WorldRendererCommon // of sections not rendered are 0 async waitForChunksToRender () { return new Promise((resolve, reject) => { - if ([...this.sectionsOutstanding].length === 0) { + if ([...this.sectionsWaiting].length === 0) { resolve() return } const updateHandler = () => { - if (this.sectionsOutstanding.size === 0) { + if (this.sectionsWaiting.size === 0) { this.renderUpdateEmitter.removeListener('update', updateHandler) resolve() } @@ -444,4 +495,27 @@ export abstract class WorldRendererCommon 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 () { + console.warn('world destroy is not implemented') + } + + abstract setHighlightCursorBlock (block: typeof this.cursorBlock, shapePositions?: Array<{ position; width; height; depth }>): void } diff --git a/prismarine-viewer/viewer/lib/worldrendererThree.ts b/prismarine-viewer/viewer/lib/worldrendererThree.ts index e8769c888..4d317354e 100644 --- a/prismarine-viewer/viewer/lib/worldrendererThree.ts +++ b/prismarine-viewer/viewer/lib/worldrendererThree.ts @@ -3,7 +3,7 @@ import { Vec3 } from 'vec3' import nbt from 'prismarine-nbt' import PrismarineChatLoader from 'prismarine-chat' import * as tweenJs from '@tweenjs/tween.js' -import { BloomPass, RenderPass, UnrealBloomPass, EffectComposer, WaterPass, GlitchPass } from 'three-stdlib' +import { BloomPass, RenderPass, UnrealBloomPass, EffectComposer, WaterPass, GlitchPass, LineSegmentsGeometry, Wireframe, LineMaterial } from 'three-stdlib' import worldBlockProvider from 'mc-assets/dist/worldBlockProvider' import { renderSign } from '../sign-renderer' import { chunkPos, sectionPos } from './simpleUtils' @@ -14,6 +14,7 @@ import { addNewStat } from './ui/newStats' import { MesherGeometryOutput } from './mesher/shared' export class WorldRendererThree extends WorldRendererCommon { + interactionLines: null | { blockPos; mesh } = null outputFormat = 'threeJs' as const blockEntities = {} sectionObjects: Record = {} @@ -22,6 +23,8 @@ export class WorldRendererThree extends WorldRendererCommon { starField: StarField cameraSectionPos: Vec3 = new Vec3(0, 0, 0) holdingBlock: HoldingBlock + holdingBlockLeft: HoldingBlock + rendererDevice = '...' get tilesRendered () { return Object.values(this.sectionObjects).reduce((acc, obj) => acc + (obj as any).tilesCount, 0) @@ -33,35 +36,53 @@ export class WorldRendererThree extends WorldRendererCommon { constructor (public scene: THREE.Scene, public renderer: THREE.WebGLRenderer, public config: WorldRendererConfig) { super(config) + this.rendererDevice = String(WorldRendererThree.getRendererInfo(this.renderer)) this.starField = new StarField(scene) - this.holdingBlock = new HoldingBlock(this.scene) + this.holdingBlock = new HoldingBlock() + this.holdingBlockLeft = new HoldingBlock() + this.holdingBlockLeft.rightSide = false - this.renderUpdateEmitter.on('textureDownloaded', () => { + this.renderUpdateEmitter.on('itemsTextureDownloaded', () => { if (this.holdingBlock.toBeRenderedItem) { this.onHandItemSwitch(this.holdingBlock.toBeRenderedItem) this.holdingBlock.toBeRenderedItem = undefined } + if (this.holdingBlockLeft.toBeRenderedItem) { + this.onHandItemSwitch(this.holdingBlock.toBeRenderedItem, true) + this.holdingBlockLeft.toBeRenderedItem = undefined + } }) this.addDebugOverlay() } - onHandItemSwitch (item: HandItemBlock | undefined) { + onHandItemSwitch (item: HandItemBlock | undefined, isLeft = false) { + if (!isLeft) { + item ??= { + type: 'hand', + } + } + const holdingBlock = isLeft ? this.holdingBlockLeft : this.holdingBlock if (!this.currentTextureImage) { - this.holdingBlock.toBeRenderedItem = item + holdingBlock.toBeRenderedItem = item return } - void this.holdingBlock.initHandObject(this.material, this.blockstatesModels, this.blocksAtlases, item) + void holdingBlock.initHandObject(this.material, this.blockstatesModels, this.blocksAtlases, item) } - changeHandSwingingState (isAnimationPlaying: boolean) { + changeHandSwingingState (isAnimationPlaying: boolean, isLeft = false) { + const holdingBlock = isLeft ? this.holdingBlockLeft : this.holdingBlock if (isAnimationPlaying) { - this.holdingBlock.startSwing() + holdingBlock.startSwing() } else { - void this.holdingBlock.stopSwing() + void holdingBlock.stopSwing() } } + changeBackgroundColor (color: [number, number, number]): void { + this.scene.background = new THREE.Color(color[0], color[1], color[2]) + } + timeUpdated (newTime: number): void { const nightTime = 13_500 const morningStart = 23_000 @@ -216,10 +237,13 @@ export class WorldRendererThree extends WorldRendererCommon { render () { tweenJs.update() - this.holdingBlock.update(this.camera) // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style const cam = this.camera instanceof THREE.Group ? this.camera.children.find(child => child instanceof THREE.PerspectiveCamera) as THREE.PerspectiveCamera : this.camera this.renderer.render(this.scene, cam) + if (this.config.displayHand) { + this.holdingBlock.render(this.camera, this.renderer, viewer.ambientLight, viewer.directionalLight) + this.holdingBlockLeft.render(this.camera, this.renderer, viewer.ambientLight, viewer.directionalLight) + } } renderSign (position: Vec3, rotation: number, isWall: boolean, isHanging: boolean, blockEntity) { @@ -361,9 +385,47 @@ export class WorldRendererThree extends WorldRendererCommon { } } - setSectionDirty (pos, value = true) { + setSectionDirty (...args: Parameters) { + const [pos] = args this.cleanChunkTextures(pos.x, pos.z) // todo don't do this! - super.setSectionDirty(pos, value) + super.setSectionDirty(...args) + } + + setHighlightCursorBlock (blockPos: typeof this.cursorBlock, shapePositions?: Array<{ position: any; width: any; height: any; depth: any; }>): void { + this.cursorBlock = blockPos + if (blockPos && this.interactionLines && blockPos.equals(this.interactionLines.blockPos)) { + return + } + if (this.interactionLines !== null) { + this.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.threejsCursorLineMaterial) + const pos = blockPos.plus(position) + wireframe.position.set(pos.x, pos.y, pos.z) + wireframe.computeLineDistances() + group.add(wireframe) + } + this.scene.add(group) + this.interactionLines = { blockPos, mesh: group } + } + + static getRendererInfo (renderer: THREE.WebGLRenderer) { + try { + const gl = renderer.getContext() + return `${gl.getParameter(gl.getExtension('WEBGL_debug_renderer_info')!.UNMASKED_RENDERER_WEBGL)} powered by three.js r{THREE.REVISION}` + } catch (err) { + console.warn('Failed to get renderer info', err) + } } } diff --git a/rsbuild.config.ts b/rsbuild.config.ts index b95942429..1085e3fcf 100644 --- a/rsbuild.config.ts +++ b/rsbuild.config.ts @@ -105,6 +105,7 @@ const appConfig = defineConfig({ if (fs.existsSync('./prismarine-viewer/dist/mesher.js') && dev) { // copy mesher fs.copyFileSync('./prismarine-viewer/dist/mesher.js', './dist/mesher.js') + fs.copyFileSync('./prismarine-viewer/dist/mesher.js.map', './dist/mesher.js.map') } else if (!dev) { await execAsync('pnpm run build-mesher') } diff --git a/scripts/genMcDataTypes.ts b/scripts/genMcDataTypes.ts index f5b150696..82b5b8785 100644 --- a/scripts/genMcDataTypes.ts +++ b/scripts/genMcDataTypes.ts @@ -1,5 +1,6 @@ import minecraftData from 'minecraft-data' import fs from 'fs' +import supportedVersions from '../src/supportedVersions.mjs' const data = minecraftData('1.20.1') @@ -10,4 +11,41 @@ types += `\nexport type EntityNames = ${Object.keys(data.entitiesByName).map(blo types += `\nexport type BiomesNames = ${Object.keys(data.biomesByName).map(blockName => `'${blockName}'`).join(' | ')};` types += `\nexport type EnchantmentNames = ${Object.keys(data.enchantmentsByName).map(blockName => `'${blockName}'`).join(' | ')};` +type Version = string +const allVersionsEntitiesMetadata = {} as Record> +for (const version of supportedVersions) { + const data = minecraftData(version) + for (const { name, metadataKeys } of data.entitiesArray) { + allVersionsEntitiesMetadata[name] ??= {} + if (!metadataKeys) { + // console.warn('Entity has no metadata', name, version) + } + for (const [i, key] of (metadataKeys ?? []).entries()) { + allVersionsEntitiesMetadata[name][key] ??= { + version: version, + firstKey: i, + } + } + } +} + +types += '\n\nexport type EntityMetadataVersions = {\n' +for (const [name, versions] of Object.entries(allVersionsEntitiesMetadata)) { + types += `'${name}': {` + for (const [key, v] of Object.entries(versions)) { + types += `\n/** ${v.version}+ (${v.firstKey}) */\n` + types += `'${key}': string;` + } + types += '},' +} +types += '\n}' + +const minify = false +if (minify) { + types = types.replaceAll(/[\t]/g, '') +} + fs.writeFileSync('./src/mcDataTypes.ts', types, 'utf8') diff --git a/src/browserfs.ts b/src/browserfs.ts index e3675b4c3..7e66dfe04 100644 --- a/src/browserfs.ts +++ b/src/browserfs.ts @@ -389,7 +389,7 @@ export const copyFilesAsyncWithProgress = async (pathSrc: string, pathDest: stri return } if (!stat.isDirectory()) { - await fs.promises.writeFile(pathDest, await fs.promises.readFile(pathSrc)) + await fs.promises.writeFile(pathDest, await fs.promises.readFile(pathSrc) as any) console.debug('copied single file', pathSrc, pathDest) return } @@ -464,7 +464,7 @@ export const copyFilesAsync = async (pathSrc: string, pathDest: string, fileCopi } else { // Copy file try { - await fs.promises.writeFile(curPathDest, await fs.promises.readFile(curPathSrc)) + await fs.promises.writeFile(curPathDest, await fs.promises.readFile(curPathSrc) as any) console.debug('copied file', curPathSrc, curPathDest) } catch (err) { console.error('Error copying file', curPathSrc, curPathDest, err) @@ -475,17 +475,36 @@ export const copyFilesAsync = async (pathSrc: string, pathDest: string, fileCopi })) } -export const openWorldFromHttpDir = async (fileDescriptorUrl: string/* | undefined */, baseUrl = fileDescriptorUrl.split('/').slice(0, -1).join('/')) => { +export const openWorldFromHttpDir = async (fileDescriptorUrls: string[]/* | undefined */, baseUrlParam) => { // todo try go guess mode let index - const file = await fetch(fileDescriptorUrl).then(async a => a.json()) - if (file.baseUrl) { - baseUrl = new URL(file.baseUrl, baseUrl).toString() - index = file.index - } else { - index = file + let baseUrl + for (const url of fileDescriptorUrls) { + let file + try { + setLoadingScreenStatus(`Trying to get world descriptor from ${new URL(url).host}`) + const controller = new AbortController() + setTimeout(() => { + controller.abort() + }, 3000) + // eslint-disable-next-line no-await-in-loop + const response = await fetch(url, { signal: controller.signal }) + // eslint-disable-next-line no-await-in-loop + file = await response.json() + } catch (err) { + console.error('Error fetching file descriptor', url, err) + } + if (!file) continue + if (file.baseUrl) { + baseUrl = new URL(file.baseUrl, baseUrl).toString() + index = file.index + } else { + index = file + baseUrl = baseUrlParam ?? url.split('/').slice(0, -1).join('/') + } + break } - if (!index) throw new Error(`The provided mapDir file is not valid descriptor file! ${fileDescriptorUrl}`) + if (!index) throw new Error(`The provided mapDir file is not valid descriptor file! ${fileDescriptorUrls.join(', ')}`) await new Promise(async resolve => { browserfs.configure({ fs: 'MountableFileSystem', diff --git a/src/controls.ts b/src/controls.ts index 602ea81d2..cb1c132bc 100644 --- a/src/controls.ts +++ b/src/controls.ts @@ -7,7 +7,7 @@ import { ControMax } from 'contro-max/build/controMax' import { CommandEventArgument, SchemaCommandInput } from 'contro-max/build/types' import { stringStartsWith } from 'contro-max/build/stringUtils' import { UserOverrideCommand, UserOverridesConfig } from 'contro-max/build/types/store' -import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal, miscUiState, loadedGameState } from './globalState' +import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal, miscUiState, loadedGameState, hideModal } from './globalState' import { goFullscreen, pointerLock, reloadChunks } from './utils' import { options } from './optionsStorage' import { openPlayerInventory } from './inventoryWindows' @@ -54,6 +54,7 @@ export const contro = new ControMax({ ui: { toggleFullscreen: ['F11'], back: [null/* 'Escape' */, 'B'], + toggleMap: ['KeyM'], leftClick: [null, 'A'], rightClick: [null, 'Y'], speedupCursor: [null, 'Left Stick'], @@ -299,7 +300,7 @@ const alwaysPressedHandledCommand = (command: Command) => { } } -function lockUrl () { +export function lockUrl () { let newQs = '' if (fsState.saveLoaded) { const save = localServer!.options.worldFolder.split('/').at(-1) @@ -424,6 +425,14 @@ contro.on('trigger', ({ command }) => { if (command === 'ui.toggleFullscreen') { void goFullscreen(true) } + + if (command === 'ui.toggleMap') { + if (activeModalStack.at(-1)?.reactType === 'full-map') { + hideModal({ reactType: 'full-map' }) + } else { + showModal({ reactType: 'full-map' }) + } + } }) contro.on('release', ({ command }) => { @@ -514,6 +523,15 @@ export const f3Keybinds = [ } }, mobileTitle: 'Cycle Game Mode' + }, + { + key: 'KeyP', + async action () { + const { uuid, ping: playerPing, username } = bot.player + const proxyPing = await bot['pingProxy']() + void showOptionsModal(`${username}: last known total latency (ping): ${playerPing}. Connected to ${lastConnectOptions.value?.proxy} with current ping ${proxyPing}. Player UUID: ${uuid}`, []) + }, + mobileTitle: 'Show Proxy & Ping Details' } ] diff --git a/src/defaultLocalServerOptions.js b/src/defaultLocalServerOptions.js index 130726e0f..cd9495673 100644 --- a/src/defaultLocalServerOptions.js +++ b/src/defaultLocalServerOptions.js @@ -33,6 +33,6 @@ module.exports = { keepAlive: false, 'everybody-op': true, 'max-entities': 100, - 'version': '1.14.4', - versionMajor: '1.14' + 'version': '1.18.2', + versionMajor: '1.18' } diff --git a/src/devtools.ts b/src/devtools.ts index 16337c1d7..e87b6d333 100644 --- a/src/devtools.ts +++ b/src/devtools.ts @@ -46,7 +46,7 @@ customEvents.on('gameLoaded', () => { window.inspectPacket = (packetName, full = false) => { const listener = (...args) => console.log('packet', packetName, full ? args : args[0]) const attach = () => { - bot?._client.on(packetName, listener) + bot?._client.prependListener(packetName, listener) } attach() customEvents.on('mineflayerBotCreated', attach) diff --git a/src/downloadAndOpenFile.ts b/src/downloadAndOpenFile.ts index 49fc5c35a..6e59ea025 100644 --- a/src/downloadAndOpenFile.ts +++ b/src/downloadAndOpenFile.ts @@ -9,10 +9,10 @@ export const getFixedFilesize = (bytes: number) => { const inner = async () => { const qs = new URLSearchParams(window.location.search) - const mapUrlDir = qs.get('mapDir') + const mapUrlDir = qs.getAll('mapDir') const mapUrlDirGuess = qs.get('mapDirGuess') const mapUrlDirBaseUrl = qs.get('mapDirBaseUrl') - if (mapUrlDir) { + if (mapUrlDir.length) { await openWorldFromHttpDir(mapUrlDir, mapUrlDirBaseUrl ?? undefined) return true } diff --git a/src/flyingSquidUtils.ts b/src/flyingSquidUtils.ts index 78254cf23..012830d9f 100644 --- a/src/flyingSquidUtils.ts +++ b/src/flyingSquidUtils.ts @@ -27,8 +27,10 @@ export async function savePlayers (autoSave: boolean) { export const saveServer = async (autoSave = true) => { if (!localServer || fsState.isReadonly) return // todo + console.time('save server') const worlds = [(localServer as any).overworld] as Array await Promise.all([localServer.writeLevelDat(), savePlayers(autoSave), ...worlds.map(async world => world.saveNow())]) + console.timeEnd('save server') } export const disconnect = async () => { if (localServer) { diff --git a/src/globalState.ts b/src/globalState.ts index cefa78103..90e3e359c 100644 --- a/src/globalState.ts +++ b/src/globalState.ts @@ -1,6 +1,7 @@ //@ts-check import { proxy, ref, subscribe } from 'valtio' +import { WorldWarp } from 'flying-squid/dist/lib/modules/warps' import { pointerLock } from './utils' import type { OptionsGroupType } from './optionsGuiScheme' @@ -153,6 +154,7 @@ export const gameAdditionalState = proxy({ isFlying: false, isSprinting: false, isSneaking: false, + warps: [] as WorldWarp[] }) window.gameAdditionalState = gameAdditionalState diff --git a/src/index.ts b/src/index.ts index 1b65bb007..93bbe6b90 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,7 +22,7 @@ import PrismarineItem from 'prismarine-item' import { options, watchValue } from './optionsStorage' import './reactUi' -import { contro, onBotCreate } from './controls' +import { contro, lockUrl, onBotCreate } from './controls' import './dragndrop' import { possiblyCleanHandle, resetStateAfterDisconnect } from './browserfs' import { watchOptionsAfterViewerInit, watchOptionsAfterWorldViewInit } from './watchOptions' @@ -157,6 +157,7 @@ if (isIphone) { // Create viewer const viewer: import('prismarine-viewer/viewer/lib/viewer').Viewer = new Viewer(renderer) window.viewer = viewer +viewer.getMineflayerBot = () => bot // todo unify viewer.entities.getItemUv = (idOrName: number | string) => { try { @@ -420,7 +421,7 @@ async function connect (connectOptions: ConnectOptions) { } } viewer.world.blockstatesModels = await import('mc-assets/dist/blockStatesModels.json') - viewer.setVersion(version, options.useVersionsTextures === 'latest' ? version : options.useVersionsTextures) + void viewer.setVersion(version, options.useVersionsTextures === 'latest' ? version : options.useVersionsTextures) } const downloadVersion = connectOptions.botVersion || (singleplayer ? serverOptions.version : undefined) @@ -692,6 +693,9 @@ async function connect (connectOptions: ConnectOptions) { setLoadingScreenStatus('Placing blocks (starting viewer)') localStorage.lastConnectOptions = JSON.stringify(connectOptions) connectOptions.onSuccessfulPlay?.() + if (process.env.NODE_ENV === 'development' && !localStorage.lockUrl && new URLSearchParams(location.search).size === 0) { + lockUrl() + } updateDataAfterJoin() if (connectOptions.autoLoginPassword) { bot.chat(`/login ${connectOptions.autoLoginPassword}`) @@ -1046,6 +1050,10 @@ downloadAndOpenFile().then((downloadAction) => { }) } }) + + if (qs.get('serversList')) { + showModal({ reactType: 'serversList' }) + } }, (err) => { console.error(err) alert(`Failed to download file: ${err}`) diff --git a/src/mcDataTypes.ts b/src/mcDataTypes.ts index 7c70e0f04..3375cf28e 100644 --- a/src/mcDataTypes.ts +++ b/src/mcDataTypes.ts @@ -1,6 +1,4318 @@ -export type BlockNames = 'air' | 'stone' | 'granite' | 'polished_granite' | 'diorite' | 'polished_diorite' | 'andesite' | 'polished_andesite' | 'grass_block' | 'dirt' | 'coarse_dirt' | 'podzol' | 'cobblestone' | 'oak_planks' | 'spruce_planks' | 'birch_planks' | 'jungle_planks' | 'acacia_planks' | 'cherry_planks' | 'dark_oak_planks' | 'mangrove_planks' | 'bamboo_planks' | 'bamboo_mosaic' | 'oak_sapling' | 'spruce_sapling' | 'birch_sapling' | 'jungle_sapling' | 'acacia_sapling' | 'cherry_sapling' | 'dark_oak_sapling' | 'mangrove_propagule' | 'bedrock' | 'water' | 'lava' | 'sand' | 'suspicious_sand' | 'red_sand' | 'gravel' | 'suspicious_gravel' | 'gold_ore' | 'deepslate_gold_ore' | 'iron_ore' | 'deepslate_iron_ore' | 'coal_ore' | 'deepslate_coal_ore' | 'nether_gold_ore' | 'oak_log' | 'spruce_log' | 'birch_log' | 'jungle_log' | 'acacia_log' | 'cherry_log' | 'dark_oak_log' | 'mangrove_log' | 'mangrove_roots' | 'muddy_mangrove_roots' | 'bamboo_block' | 'stripped_spruce_log' | 'stripped_birch_log' | 'stripped_jungle_log' | 'stripped_acacia_log' | 'stripped_cherry_log' | 'stripped_dark_oak_log' | 'stripped_oak_log' | 'stripped_mangrove_log' | 'stripped_bamboo_block' | 'oak_wood' | 'spruce_wood' | 'birch_wood' | 'jungle_wood' | 'acacia_wood' | 'cherry_wood' | 'dark_oak_wood' | 'mangrove_wood' | 'stripped_oak_wood' | 'stripped_spruce_wood' | 'stripped_birch_wood' | 'stripped_jungle_wood' | 'stripped_acacia_wood' | 'stripped_cherry_wood' | 'stripped_dark_oak_wood' | 'stripped_mangrove_wood' | 'oak_leaves' | 'spruce_leaves' | 'birch_leaves' | 'jungle_leaves' | 'acacia_leaves' | 'cherry_leaves' | 'dark_oak_leaves' | 'mangrove_leaves' | 'azalea_leaves' | 'flowering_azalea_leaves' | 'sponge' | 'wet_sponge' | 'glass' | 'lapis_ore' | 'deepslate_lapis_ore' | 'lapis_block' | 'dispenser' | 'sandstone' | 'chiseled_sandstone' | 'cut_sandstone' | 'note_block' | 'white_bed' | 'orange_bed' | 'magenta_bed' | 'light_blue_bed' | 'yellow_bed' | 'lime_bed' | 'pink_bed' | 'gray_bed' | 'light_gray_bed' | 'cyan_bed' | 'purple_bed' | 'blue_bed' | 'brown_bed' | 'green_bed' | 'red_bed' | 'black_bed' | 'powered_rail' | 'detector_rail' | 'sticky_piston' | 'cobweb' | 'grass' | 'fern' | 'dead_bush' | 'seagrass' | 'tall_seagrass' | 'piston' | 'piston_head' | 'white_wool' | 'orange_wool' | 'magenta_wool' | 'light_blue_wool' | 'yellow_wool' | 'lime_wool' | 'pink_wool' | 'gray_wool' | 'light_gray_wool' | 'cyan_wool' | 'purple_wool' | 'blue_wool' | 'brown_wool' | 'green_wool' | 'red_wool' | 'black_wool' | 'moving_piston' | 'dandelion' | 'torchflower' | 'poppy' | 'blue_orchid' | 'allium' | 'azure_bluet' | 'red_tulip' | 'orange_tulip' | 'white_tulip' | 'pink_tulip' | 'oxeye_daisy' | 'cornflower' | 'wither_rose' | 'lily_of_the_valley' | 'brown_mushroom' | 'red_mushroom' | 'gold_block' | 'iron_block' | 'bricks' | 'tnt' | 'bookshelf' | 'chiseled_bookshelf' | 'mossy_cobblestone' | 'obsidian' | 'torch' | 'wall_torch' | 'fire' | 'soul_fire' | 'spawner' | 'oak_stairs' | 'chest' | 'redstone_wire' | 'diamond_ore' | 'deepslate_diamond_ore' | 'diamond_block' | 'crafting_table' | 'wheat' | 'farmland' | 'furnace' | 'oak_sign' | 'spruce_sign' | 'birch_sign' | 'acacia_sign' | 'cherry_sign' | 'jungle_sign' | 'dark_oak_sign' | 'mangrove_sign' | 'bamboo_sign' | 'oak_door' | 'ladder' | 'rail' | 'cobblestone_stairs' | 'oak_wall_sign' | 'spruce_wall_sign' | 'birch_wall_sign' | 'acacia_wall_sign' | 'cherry_wall_sign' | 'jungle_wall_sign' | 'dark_oak_wall_sign' | 'mangrove_wall_sign' | 'bamboo_wall_sign' | 'oak_hanging_sign' | 'spruce_hanging_sign' | 'birch_hanging_sign' | 'acacia_hanging_sign' | 'cherry_hanging_sign' | 'jungle_hanging_sign' | 'dark_oak_hanging_sign' | 'crimson_hanging_sign' | 'warped_hanging_sign' | 'mangrove_hanging_sign' | 'bamboo_hanging_sign' | 'oak_wall_hanging_sign' | 'spruce_wall_hanging_sign' | 'birch_wall_hanging_sign' | 'acacia_wall_hanging_sign' | 'cherry_wall_hanging_sign' | 'jungle_wall_hanging_sign' | 'dark_oak_wall_hanging_sign' | 'mangrove_wall_hanging_sign' | 'crimson_wall_hanging_sign' | 'warped_wall_hanging_sign' | 'bamboo_wall_hanging_sign' | 'lever' | 'stone_pressure_plate' | 'iron_door' | 'oak_pressure_plate' | 'spruce_pressure_plate' | 'birch_pressure_plate' | 'jungle_pressure_plate' | 'acacia_pressure_plate' | 'cherry_pressure_plate' | 'dark_oak_pressure_plate' | 'mangrove_pressure_plate' | 'bamboo_pressure_plate' | 'redstone_ore' | 'deepslate_redstone_ore' | 'redstone_torch' | 'redstone_wall_torch' | 'stone_button' | 'snow' | 'ice' | 'snow_block' | 'cactus' | 'clay' | 'sugar_cane' | 'jukebox' | 'oak_fence' | 'pumpkin' | 'netherrack' | 'soul_sand' | 'soul_soil' | 'basalt' | 'polished_basalt' | 'soul_torch' | 'soul_wall_torch' | 'glowstone' | 'nether_portal' | 'carved_pumpkin' | 'jack_o_lantern' | 'cake' | 'repeater' | 'white_stained_glass' | 'orange_stained_glass' | 'magenta_stained_glass' | 'light_blue_stained_glass' | 'yellow_stained_glass' | 'lime_stained_glass' | 'pink_stained_glass' | 'gray_stained_glass' | 'light_gray_stained_glass' | 'cyan_stained_glass' | 'purple_stained_glass' | 'blue_stained_glass' | 'brown_stained_glass' | 'green_stained_glass' | 'red_stained_glass' | 'black_stained_glass' | 'oak_trapdoor' | 'spruce_trapdoor' | 'birch_trapdoor' | 'jungle_trapdoor' | 'acacia_trapdoor' | 'cherry_trapdoor' | 'dark_oak_trapdoor' | 'mangrove_trapdoor' | 'bamboo_trapdoor' | 'stone_bricks' | 'mossy_stone_bricks' | 'cracked_stone_bricks' | 'chiseled_stone_bricks' | 'packed_mud' | 'mud_bricks' | 'infested_stone' | 'infested_cobblestone' | 'infested_stone_bricks' | 'infested_mossy_stone_bricks' | 'infested_cracked_stone_bricks' | 'infested_chiseled_stone_bricks' | 'brown_mushroom_block' | 'red_mushroom_block' | 'mushroom_stem' | 'iron_bars' | 'chain' | 'glass_pane' | 'melon' | 'attached_pumpkin_stem' | 'attached_melon_stem' | 'pumpkin_stem' | 'melon_stem' | 'vine' | 'glow_lichen' | 'oak_fence_gate' | 'brick_stairs' | 'stone_brick_stairs' | 'mud_brick_stairs' | 'mycelium' | 'lily_pad' | 'nether_bricks' | 'nether_brick_fence' | 'nether_brick_stairs' | 'nether_wart' | 'enchanting_table' | 'brewing_stand' | 'cauldron' | 'water_cauldron' | 'lava_cauldron' | 'powder_snow_cauldron' | 'end_portal' | 'end_portal_frame' | 'end_stone' | 'dragon_egg' | 'redstone_lamp' | 'cocoa' | 'sandstone_stairs' | 'emerald_ore' | 'deepslate_emerald_ore' | 'ender_chest' | 'tripwire_hook' | 'tripwire' | 'emerald_block' | 'spruce_stairs' | 'birch_stairs' | 'jungle_stairs' | 'command_block' | 'beacon' | 'cobblestone_wall' | 'mossy_cobblestone_wall' | 'flower_pot' | 'potted_torchflower' | 'potted_oak_sapling' | 'potted_spruce_sapling' | 'potted_birch_sapling' | 'potted_jungle_sapling' | 'potted_acacia_sapling' | 'potted_cherry_sapling' | 'potted_dark_oak_sapling' | 'potted_mangrove_propagule' | 'potted_fern' | 'potted_dandelion' | 'potted_poppy' | 'potted_blue_orchid' | 'potted_allium' | 'potted_azure_bluet' | 'potted_red_tulip' | 'potted_orange_tulip' | 'potted_white_tulip' | 'potted_pink_tulip' | 'potted_oxeye_daisy' | 'potted_cornflower' | 'potted_lily_of_the_valley' | 'potted_wither_rose' | 'potted_red_mushroom' | 'potted_brown_mushroom' | 'potted_dead_bush' | 'potted_cactus' | 'carrots' | 'potatoes' | 'oak_button' | 'spruce_button' | 'birch_button' | 'jungle_button' | 'acacia_button' | 'cherry_button' | 'dark_oak_button' | 'mangrove_button' | 'bamboo_button' | 'skeleton_skull' | 'skeleton_wall_skull' | 'wither_skeleton_skull' | 'wither_skeleton_wall_skull' | 'zombie_head' | 'zombie_wall_head' | 'player_head' | 'player_wall_head' | 'creeper_head' | 'creeper_wall_head' | 'dragon_head' | 'dragon_wall_head' | 'piglin_head' | 'piglin_wall_head' | 'anvil' | 'chipped_anvil' | 'damaged_anvil' | 'trapped_chest' | 'light_weighted_pressure_plate' | 'heavy_weighted_pressure_plate' | 'comparator' | 'daylight_detector' | 'redstone_block' | 'nether_quartz_ore' | 'hopper' | 'quartz_block' | 'chiseled_quartz_block' | 'quartz_pillar' | 'quartz_stairs' | 'activator_rail' | 'dropper' | 'white_terracotta' | 'orange_terracotta' | 'magenta_terracotta' | 'light_blue_terracotta' | 'yellow_terracotta' | 'lime_terracotta' | 'pink_terracotta' | 'gray_terracotta' | 'light_gray_terracotta' | 'cyan_terracotta' | 'purple_terracotta' | 'blue_terracotta' | 'brown_terracotta' | 'green_terracotta' | 'red_terracotta' | 'black_terracotta' | 'white_stained_glass_pane' | 'orange_stained_glass_pane' | 'magenta_stained_glass_pane' | 'light_blue_stained_glass_pane' | 'yellow_stained_glass_pane' | 'lime_stained_glass_pane' | 'pink_stained_glass_pane' | 'gray_stained_glass_pane' | 'light_gray_stained_glass_pane' | 'cyan_stained_glass_pane' | 'purple_stained_glass_pane' | 'blue_stained_glass_pane' | 'brown_stained_glass_pane' | 'green_stained_glass_pane' | 'red_stained_glass_pane' | 'black_stained_glass_pane' | 'acacia_stairs' | 'cherry_stairs' | 'dark_oak_stairs' | 'mangrove_stairs' | 'bamboo_stairs' | 'bamboo_mosaic_stairs' | 'slime_block' | 'barrier' | 'light' | 'iron_trapdoor' | 'prismarine' | 'prismarine_bricks' | 'dark_prismarine' | 'prismarine_stairs' | 'prismarine_brick_stairs' | 'dark_prismarine_stairs' | 'prismarine_slab' | 'prismarine_brick_slab' | 'dark_prismarine_slab' | 'sea_lantern' | 'hay_block' | 'white_carpet' | 'orange_carpet' | 'magenta_carpet' | 'light_blue_carpet' | 'yellow_carpet' | 'lime_carpet' | 'pink_carpet' | 'gray_carpet' | 'light_gray_carpet' | 'cyan_carpet' | 'purple_carpet' | 'blue_carpet' | 'brown_carpet' | 'green_carpet' | 'red_carpet' | 'black_carpet' | 'terracotta' | 'coal_block' | 'packed_ice' | 'sunflower' | 'lilac' | 'rose_bush' | 'peony' | 'tall_grass' | 'large_fern' | 'white_banner' | 'orange_banner' | 'magenta_banner' | 'light_blue_banner' | 'yellow_banner' | 'lime_banner' | 'pink_banner' | 'gray_banner' | 'light_gray_banner' | 'cyan_banner' | 'purple_banner' | 'blue_banner' | 'brown_banner' | 'green_banner' | 'red_banner' | 'black_banner' | 'white_wall_banner' | 'orange_wall_banner' | 'magenta_wall_banner' | 'light_blue_wall_banner' | 'yellow_wall_banner' | 'lime_wall_banner' | 'pink_wall_banner' | 'gray_wall_banner' | 'light_gray_wall_banner' | 'cyan_wall_banner' | 'purple_wall_banner' | 'blue_wall_banner' | 'brown_wall_banner' | 'green_wall_banner' | 'red_wall_banner' | 'black_wall_banner' | 'red_sandstone' | 'chiseled_red_sandstone' | 'cut_red_sandstone' | 'red_sandstone_stairs' | 'oak_slab' | 'spruce_slab' | 'birch_slab' | 'jungle_slab' | 'acacia_slab' | 'cherry_slab' | 'dark_oak_slab' | 'mangrove_slab' | 'bamboo_slab' | 'bamboo_mosaic_slab' | 'stone_slab' | 'smooth_stone_slab' | 'sandstone_slab' | 'cut_sandstone_slab' | 'petrified_oak_slab' | 'cobblestone_slab' | 'brick_slab' | 'stone_brick_slab' | 'mud_brick_slab' | 'nether_brick_slab' | 'quartz_slab' | 'red_sandstone_slab' | 'cut_red_sandstone_slab' | 'purpur_slab' | 'smooth_stone' | 'smooth_sandstone' | 'smooth_quartz' | 'smooth_red_sandstone' | 'spruce_fence_gate' | 'birch_fence_gate' | 'jungle_fence_gate' | 'acacia_fence_gate' | 'cherry_fence_gate' | 'dark_oak_fence_gate' | 'mangrove_fence_gate' | 'bamboo_fence_gate' | 'spruce_fence' | 'birch_fence' | 'jungle_fence' | 'acacia_fence' | 'cherry_fence' | 'dark_oak_fence' | 'mangrove_fence' | 'bamboo_fence' | 'spruce_door' | 'birch_door' | 'jungle_door' | 'acacia_door' | 'cherry_door' | 'dark_oak_door' | 'mangrove_door' | 'bamboo_door' | 'end_rod' | 'chorus_plant' | 'chorus_flower' | 'purpur_block' | 'purpur_pillar' | 'purpur_stairs' | 'end_stone_bricks' | 'torchflower_crop' | 'pitcher_crop' | 'pitcher_plant' | 'beetroots' | 'dirt_path' | 'end_gateway' | 'repeating_command_block' | 'chain_command_block' | 'frosted_ice' | 'magma_block' | 'nether_wart_block' | 'red_nether_bricks' | 'bone_block' | 'structure_void' | 'observer' | 'shulker_box' | 'white_shulker_box' | 'orange_shulker_box' | 'magenta_shulker_box' | 'light_blue_shulker_box' | 'yellow_shulker_box' | 'lime_shulker_box' | 'pink_shulker_box' | 'gray_shulker_box' | 'light_gray_shulker_box' | 'cyan_shulker_box' | 'purple_shulker_box' | 'blue_shulker_box' | 'brown_shulker_box' | 'green_shulker_box' | 'red_shulker_box' | 'black_shulker_box' | 'white_glazed_terracotta' | 'orange_glazed_terracotta' | 'magenta_glazed_terracotta' | 'light_blue_glazed_terracotta' | 'yellow_glazed_terracotta' | 'lime_glazed_terracotta' | 'pink_glazed_terracotta' | 'gray_glazed_terracotta' | 'light_gray_glazed_terracotta' | 'cyan_glazed_terracotta' | 'purple_glazed_terracotta' | 'blue_glazed_terracotta' | 'brown_glazed_terracotta' | 'green_glazed_terracotta' | 'red_glazed_terracotta' | 'black_glazed_terracotta' | 'white_concrete' | 'orange_concrete' | 'magenta_concrete' | 'light_blue_concrete' | 'yellow_concrete' | 'lime_concrete' | 'pink_concrete' | 'gray_concrete' | 'light_gray_concrete' | 'cyan_concrete' | 'purple_concrete' | 'blue_concrete' | 'brown_concrete' | 'green_concrete' | 'red_concrete' | 'black_concrete' | 'white_concrete_powder' | 'orange_concrete_powder' | 'magenta_concrete_powder' | 'light_blue_concrete_powder' | 'yellow_concrete_powder' | 'lime_concrete_powder' | 'pink_concrete_powder' | 'gray_concrete_powder' | 'light_gray_concrete_powder' | 'cyan_concrete_powder' | 'purple_concrete_powder' | 'blue_concrete_powder' | 'brown_concrete_powder' | 'green_concrete_powder' | 'red_concrete_powder' | 'black_concrete_powder' | 'kelp' | 'kelp_plant' | 'dried_kelp_block' | 'turtle_egg' | 'sniffer_egg' | 'dead_tube_coral_block' | 'dead_brain_coral_block' | 'dead_bubble_coral_block' | 'dead_fire_coral_block' | 'dead_horn_coral_block' | 'tube_coral_block' | 'brain_coral_block' | 'bubble_coral_block' | 'fire_coral_block' | 'horn_coral_block' | 'dead_tube_coral' | 'dead_brain_coral' | 'dead_bubble_coral' | 'dead_fire_coral' | 'dead_horn_coral' | 'tube_coral' | 'brain_coral' | 'bubble_coral' | 'fire_coral' | 'horn_coral' | 'dead_tube_coral_fan' | 'dead_brain_coral_fan' | 'dead_bubble_coral_fan' | 'dead_fire_coral_fan' | 'dead_horn_coral_fan' | 'tube_coral_fan' | 'brain_coral_fan' | 'bubble_coral_fan' | 'fire_coral_fan' | 'horn_coral_fan' | 'dead_tube_coral_wall_fan' | 'dead_brain_coral_wall_fan' | 'dead_bubble_coral_wall_fan' | 'dead_fire_coral_wall_fan' | 'dead_horn_coral_wall_fan' | 'tube_coral_wall_fan' | 'brain_coral_wall_fan' | 'bubble_coral_wall_fan' | 'fire_coral_wall_fan' | 'horn_coral_wall_fan' | 'sea_pickle' | 'blue_ice' | 'conduit' | 'bamboo_sapling' | 'bamboo' | 'potted_bamboo' | 'void_air' | 'cave_air' | 'bubble_column' | 'polished_granite_stairs' | 'smooth_red_sandstone_stairs' | 'mossy_stone_brick_stairs' | 'polished_diorite_stairs' | 'mossy_cobblestone_stairs' | 'end_stone_brick_stairs' | 'stone_stairs' | 'smooth_sandstone_stairs' | 'smooth_quartz_stairs' | 'granite_stairs' | 'andesite_stairs' | 'red_nether_brick_stairs' | 'polished_andesite_stairs' | 'diorite_stairs' | 'polished_granite_slab' | 'smooth_red_sandstone_slab' | 'mossy_stone_brick_slab' | 'polished_diorite_slab' | 'mossy_cobblestone_slab' | 'end_stone_brick_slab' | 'smooth_sandstone_slab' | 'smooth_quartz_slab' | 'granite_slab' | 'andesite_slab' | 'red_nether_brick_slab' | 'polished_andesite_slab' | 'diorite_slab' | 'brick_wall' | 'prismarine_wall' | 'red_sandstone_wall' | 'mossy_stone_brick_wall' | 'granite_wall' | 'stone_brick_wall' | 'mud_brick_wall' | 'nether_brick_wall' | 'andesite_wall' | 'red_nether_brick_wall' | 'sandstone_wall' | 'end_stone_brick_wall' | 'diorite_wall' | 'scaffolding' | 'loom' | 'barrel' | 'smoker' | 'blast_furnace' | 'cartography_table' | 'fletching_table' | 'grindstone' | 'lectern' | 'smithing_table' | 'stonecutter' | 'bell' | 'lantern' | 'soul_lantern' | 'campfire' | 'soul_campfire' | 'sweet_berry_bush' | 'warped_stem' | 'stripped_warped_stem' | 'warped_hyphae' | 'stripped_warped_hyphae' | 'warped_nylium' | 'warped_fungus' | 'warped_wart_block' | 'warped_roots' | 'nether_sprouts' | 'crimson_stem' | 'stripped_crimson_stem' | 'crimson_hyphae' | 'stripped_crimson_hyphae' | 'crimson_nylium' | 'crimson_fungus' | 'shroomlight' | 'weeping_vines' | 'weeping_vines_plant' | 'twisting_vines' | 'twisting_vines_plant' | 'crimson_roots' | 'crimson_planks' | 'warped_planks' | 'crimson_slab' | 'warped_slab' | 'crimson_pressure_plate' | 'warped_pressure_plate' | 'crimson_fence' | 'warped_fence' | 'crimson_trapdoor' | 'warped_trapdoor' | 'crimson_fence_gate' | 'warped_fence_gate' | 'crimson_stairs' | 'warped_stairs' | 'crimson_button' | 'warped_button' | 'crimson_door' | 'warped_door' | 'crimson_sign' | 'warped_sign' | 'crimson_wall_sign' | 'warped_wall_sign' | 'structure_block' | 'jigsaw' | 'composter' | 'target' | 'bee_nest' | 'beehive' | 'honey_block' | 'honeycomb_block' | 'netherite_block' | 'ancient_debris' | 'crying_obsidian' | 'respawn_anchor' | 'potted_crimson_fungus' | 'potted_warped_fungus' | 'potted_crimson_roots' | 'potted_warped_roots' | 'lodestone' | 'blackstone' | 'blackstone_stairs' | 'blackstone_wall' | 'blackstone_slab' | 'polished_blackstone' | 'polished_blackstone_bricks' | 'cracked_polished_blackstone_bricks' | 'chiseled_polished_blackstone' | 'polished_blackstone_brick_slab' | 'polished_blackstone_brick_stairs' | 'polished_blackstone_brick_wall' | 'gilded_blackstone' | 'polished_blackstone_stairs' | 'polished_blackstone_slab' | 'polished_blackstone_pressure_plate' | 'polished_blackstone_button' | 'polished_blackstone_wall' | 'chiseled_nether_bricks' | 'cracked_nether_bricks' | 'quartz_bricks' | 'candle' | 'white_candle' | 'orange_candle' | 'magenta_candle' | 'light_blue_candle' | 'yellow_candle' | 'lime_candle' | 'pink_candle' | 'gray_candle' | 'light_gray_candle' | 'cyan_candle' | 'purple_candle' | 'blue_candle' | 'brown_candle' | 'green_candle' | 'red_candle' | 'black_candle' | 'candle_cake' | 'white_candle_cake' | 'orange_candle_cake' | 'magenta_candle_cake' | 'light_blue_candle_cake' | 'yellow_candle_cake' | 'lime_candle_cake' | 'pink_candle_cake' | 'gray_candle_cake' | 'light_gray_candle_cake' | 'cyan_candle_cake' | 'purple_candle_cake' | 'blue_candle_cake' | 'brown_candle_cake' | 'green_candle_cake' | 'red_candle_cake' | 'black_candle_cake' | 'amethyst_block' | 'budding_amethyst' | 'amethyst_cluster' | 'large_amethyst_bud' | 'medium_amethyst_bud' | 'small_amethyst_bud' | 'tuff' | 'calcite' | 'tinted_glass' | 'powder_snow' | 'sculk_sensor' | 'calibrated_sculk_sensor' | 'sculk' | 'sculk_vein' | 'sculk_catalyst' | 'sculk_shrieker' | 'oxidized_copper' | 'weathered_copper' | 'exposed_copper' | 'copper_block' | 'copper_ore' | 'deepslate_copper_ore' | 'oxidized_cut_copper' | 'weathered_cut_copper' | 'exposed_cut_copper' | 'cut_copper' | 'oxidized_cut_copper_stairs' | 'weathered_cut_copper_stairs' | 'exposed_cut_copper_stairs' | 'cut_copper_stairs' | 'oxidized_cut_copper_slab' | 'weathered_cut_copper_slab' | 'exposed_cut_copper_slab' | 'cut_copper_slab' | 'waxed_copper_block' | 'waxed_weathered_copper' | 'waxed_exposed_copper' | 'waxed_oxidized_copper' | 'waxed_oxidized_cut_copper' | 'waxed_weathered_cut_copper' | 'waxed_exposed_cut_copper' | 'waxed_cut_copper' | 'waxed_oxidized_cut_copper_stairs' | 'waxed_weathered_cut_copper_stairs' | 'waxed_exposed_cut_copper_stairs' | 'waxed_cut_copper_stairs' | 'waxed_oxidized_cut_copper_slab' | 'waxed_weathered_cut_copper_slab' | 'waxed_exposed_cut_copper_slab' | 'waxed_cut_copper_slab' | 'lightning_rod' | 'pointed_dripstone' | 'dripstone_block' | 'cave_vines' | 'cave_vines_plant' | 'spore_blossom' | 'azalea' | 'flowering_azalea' | 'moss_carpet' | 'pink_petals' | 'moss_block' | 'big_dripleaf' | 'big_dripleaf_stem' | 'small_dripleaf' | 'hanging_roots' | 'rooted_dirt' | 'mud' | 'deepslate' | 'cobbled_deepslate' | 'cobbled_deepslate_stairs' | 'cobbled_deepslate_slab' | 'cobbled_deepslate_wall' | 'polished_deepslate' | 'polished_deepslate_stairs' | 'polished_deepslate_slab' | 'polished_deepslate_wall' | 'deepslate_tiles' | 'deepslate_tile_stairs' | 'deepslate_tile_slab' | 'deepslate_tile_wall' | 'deepslate_bricks' | 'deepslate_brick_stairs' | 'deepslate_brick_slab' | 'deepslate_brick_wall' | 'chiseled_deepslate' | 'cracked_deepslate_bricks' | 'cracked_deepslate_tiles' | 'infested_deepslate' | 'smooth_basalt' | 'raw_iron_block' | 'raw_copper_block' | 'raw_gold_block' | 'potted_azalea_bush' | 'potted_flowering_azalea_bush' | 'ochre_froglight' | 'verdant_froglight' | 'pearlescent_froglight' | 'frogspawn' | 'reinforced_deepslate' | 'decorated_pot' -export type ItemNames = 'air' | 'stone' | 'granite' | 'polished_granite' | 'diorite' | 'polished_diorite' | 'andesite' | 'polished_andesite' | 'deepslate' | 'cobbled_deepslate' | 'polished_deepslate' | 'calcite' | 'tuff' | 'dripstone_block' | 'grass_block' | 'dirt' | 'coarse_dirt' | 'podzol' | 'rooted_dirt' | 'mud' | 'crimson_nylium' | 'warped_nylium' | 'cobblestone' | 'oak_planks' | 'spruce_planks' | 'birch_planks' | 'jungle_planks' | 'acacia_planks' | 'cherry_planks' | 'dark_oak_planks' | 'mangrove_planks' | 'bamboo_planks' | 'crimson_planks' | 'warped_planks' | 'bamboo_mosaic' | 'oak_sapling' | 'spruce_sapling' | 'birch_sapling' | 'jungle_sapling' | 'acacia_sapling' | 'cherry_sapling' | 'dark_oak_sapling' | 'mangrove_propagule' | 'bedrock' | 'sand' | 'suspicious_sand' | 'suspicious_gravel' | 'red_sand' | 'gravel' | 'coal_ore' | 'deepslate_coal_ore' | 'iron_ore' | 'deepslate_iron_ore' | 'copper_ore' | 'deepslate_copper_ore' | 'gold_ore' | 'deepslate_gold_ore' | 'redstone_ore' | 'deepslate_redstone_ore' | 'emerald_ore' | 'deepslate_emerald_ore' | 'lapis_ore' | 'deepslate_lapis_ore' | 'diamond_ore' | 'deepslate_diamond_ore' | 'nether_gold_ore' | 'nether_quartz_ore' | 'ancient_debris' | 'coal_block' | 'raw_iron_block' | 'raw_copper_block' | 'raw_gold_block' | 'amethyst_block' | 'budding_amethyst' | 'iron_block' | 'copper_block' | 'gold_block' | 'diamond_block' | 'netherite_block' | 'exposed_copper' | 'weathered_copper' | 'oxidized_copper' | 'cut_copper' | 'exposed_cut_copper' | 'weathered_cut_copper' | 'oxidized_cut_copper' | 'cut_copper_stairs' | 'exposed_cut_copper_stairs' | 'weathered_cut_copper_stairs' | 'oxidized_cut_copper_stairs' | 'cut_copper_slab' | 'exposed_cut_copper_slab' | 'weathered_cut_copper_slab' | 'oxidized_cut_copper_slab' | 'waxed_copper_block' | 'waxed_exposed_copper' | 'waxed_weathered_copper' | 'waxed_oxidized_copper' | 'waxed_cut_copper' | 'waxed_exposed_cut_copper' | 'waxed_weathered_cut_copper' | 'waxed_oxidized_cut_copper' | 'waxed_cut_copper_stairs' | 'waxed_exposed_cut_copper_stairs' | 'waxed_weathered_cut_copper_stairs' | 'waxed_oxidized_cut_copper_stairs' | 'waxed_cut_copper_slab' | 'waxed_exposed_cut_copper_slab' | 'waxed_weathered_cut_copper_slab' | 'waxed_oxidized_cut_copper_slab' | 'oak_log' | 'spruce_log' | 'birch_log' | 'jungle_log' | 'acacia_log' | 'cherry_log' | 'dark_oak_log' | 'mangrove_log' | 'mangrove_roots' | 'muddy_mangrove_roots' | 'crimson_stem' | 'warped_stem' | 'bamboo_block' | 'stripped_oak_log' | 'stripped_spruce_log' | 'stripped_birch_log' | 'stripped_jungle_log' | 'stripped_acacia_log' | 'stripped_cherry_log' | 'stripped_dark_oak_log' | 'stripped_mangrove_log' | 'stripped_crimson_stem' | 'stripped_warped_stem' | 'stripped_oak_wood' | 'stripped_spruce_wood' | 'stripped_birch_wood' | 'stripped_jungle_wood' | 'stripped_acacia_wood' | 'stripped_cherry_wood' | 'stripped_dark_oak_wood' | 'stripped_mangrove_wood' | 'stripped_crimson_hyphae' | 'stripped_warped_hyphae' | 'stripped_bamboo_block' | 'oak_wood' | 'spruce_wood' | 'birch_wood' | 'jungle_wood' | 'acacia_wood' | 'cherry_wood' | 'dark_oak_wood' | 'mangrove_wood' | 'crimson_hyphae' | 'warped_hyphae' | 'oak_leaves' | 'spruce_leaves' | 'birch_leaves' | 'jungle_leaves' | 'acacia_leaves' | 'cherry_leaves' | 'dark_oak_leaves' | 'mangrove_leaves' | 'azalea_leaves' | 'flowering_azalea_leaves' | 'sponge' | 'wet_sponge' | 'glass' | 'tinted_glass' | 'lapis_block' | 'sandstone' | 'chiseled_sandstone' | 'cut_sandstone' | 'cobweb' | 'grass' | 'fern' | 'azalea' | 'flowering_azalea' | 'dead_bush' | 'seagrass' | 'sea_pickle' | 'white_wool' | 'orange_wool' | 'magenta_wool' | 'light_blue_wool' | 'yellow_wool' | 'lime_wool' | 'pink_wool' | 'gray_wool' | 'light_gray_wool' | 'cyan_wool' | 'purple_wool' | 'blue_wool' | 'brown_wool' | 'green_wool' | 'red_wool' | 'black_wool' | 'dandelion' | 'poppy' | 'blue_orchid' | 'allium' | 'azure_bluet' | 'red_tulip' | 'orange_tulip' | 'white_tulip' | 'pink_tulip' | 'oxeye_daisy' | 'cornflower' | 'lily_of_the_valley' | 'wither_rose' | 'torchflower' | 'pitcher_plant' | 'spore_blossom' | 'brown_mushroom' | 'red_mushroom' | 'crimson_fungus' | 'warped_fungus' | 'crimson_roots' | 'warped_roots' | 'nether_sprouts' | 'weeping_vines' | 'twisting_vines' | 'sugar_cane' | 'kelp' | 'moss_carpet' | 'pink_petals' | 'moss_block' | 'hanging_roots' | 'big_dripleaf' | 'small_dripleaf' | 'bamboo' | 'oak_slab' | 'spruce_slab' | 'birch_slab' | 'jungle_slab' | 'acacia_slab' | 'cherry_slab' | 'dark_oak_slab' | 'mangrove_slab' | 'bamboo_slab' | 'bamboo_mosaic_slab' | 'crimson_slab' | 'warped_slab' | 'stone_slab' | 'smooth_stone_slab' | 'sandstone_slab' | 'cut_sandstone_slab' | 'petrified_oak_slab' | 'cobblestone_slab' | 'brick_slab' | 'stone_brick_slab' | 'mud_brick_slab' | 'nether_brick_slab' | 'quartz_slab' | 'red_sandstone_slab' | 'cut_red_sandstone_slab' | 'purpur_slab' | 'prismarine_slab' | 'prismarine_brick_slab' | 'dark_prismarine_slab' | 'smooth_quartz' | 'smooth_red_sandstone' | 'smooth_sandstone' | 'smooth_stone' | 'bricks' | 'bookshelf' | 'chiseled_bookshelf' | 'decorated_pot' | 'mossy_cobblestone' | 'obsidian' | 'torch' | 'end_rod' | 'chorus_plant' | 'chorus_flower' | 'purpur_block' | 'purpur_pillar' | 'purpur_stairs' | 'spawner' | 'chest' | 'crafting_table' | 'farmland' | 'furnace' | 'ladder' | 'cobblestone_stairs' | 'snow' | 'ice' | 'snow_block' | 'cactus' | 'clay' | 'jukebox' | 'oak_fence' | 'spruce_fence' | 'birch_fence' | 'jungle_fence' | 'acacia_fence' | 'cherry_fence' | 'dark_oak_fence' | 'mangrove_fence' | 'bamboo_fence' | 'crimson_fence' | 'warped_fence' | 'pumpkin' | 'carved_pumpkin' | 'jack_o_lantern' | 'netherrack' | 'soul_sand' | 'soul_soil' | 'basalt' | 'polished_basalt' | 'smooth_basalt' | 'soul_torch' | 'glowstone' | 'infested_stone' | 'infested_cobblestone' | 'infested_stone_bricks' | 'infested_mossy_stone_bricks' | 'infested_cracked_stone_bricks' | 'infested_chiseled_stone_bricks' | 'infested_deepslate' | 'stone_bricks' | 'mossy_stone_bricks' | 'cracked_stone_bricks' | 'chiseled_stone_bricks' | 'packed_mud' | 'mud_bricks' | 'deepslate_bricks' | 'cracked_deepslate_bricks' | 'deepslate_tiles' | 'cracked_deepslate_tiles' | 'chiseled_deepslate' | 'reinforced_deepslate' | 'brown_mushroom_block' | 'red_mushroom_block' | 'mushroom_stem' | 'iron_bars' | 'chain' | 'glass_pane' | 'melon' | 'vine' | 'glow_lichen' | 'brick_stairs' | 'stone_brick_stairs' | 'mud_brick_stairs' | 'mycelium' | 'lily_pad' | 'nether_bricks' | 'cracked_nether_bricks' | 'chiseled_nether_bricks' | 'nether_brick_fence' | 'nether_brick_stairs' | 'sculk' | 'sculk_vein' | 'sculk_catalyst' | 'sculk_shrieker' | 'enchanting_table' | 'end_portal_frame' | 'end_stone' | 'end_stone_bricks' | 'dragon_egg' | 'sandstone_stairs' | 'ender_chest' | 'emerald_block' | 'oak_stairs' | 'spruce_stairs' | 'birch_stairs' | 'jungle_stairs' | 'acacia_stairs' | 'cherry_stairs' | 'dark_oak_stairs' | 'mangrove_stairs' | 'bamboo_stairs' | 'bamboo_mosaic_stairs' | 'crimson_stairs' | 'warped_stairs' | 'command_block' | 'beacon' | 'cobblestone_wall' | 'mossy_cobblestone_wall' | 'brick_wall' | 'prismarine_wall' | 'red_sandstone_wall' | 'mossy_stone_brick_wall' | 'granite_wall' | 'stone_brick_wall' | 'mud_brick_wall' | 'nether_brick_wall' | 'andesite_wall' | 'red_nether_brick_wall' | 'sandstone_wall' | 'end_stone_brick_wall' | 'diorite_wall' | 'blackstone_wall' | 'polished_blackstone_wall' | 'polished_blackstone_brick_wall' | 'cobbled_deepslate_wall' | 'polished_deepslate_wall' | 'deepslate_brick_wall' | 'deepslate_tile_wall' | 'anvil' | 'chipped_anvil' | 'damaged_anvil' | 'chiseled_quartz_block' | 'quartz_block' | 'quartz_bricks' | 'quartz_pillar' | 'quartz_stairs' | 'white_terracotta' | 'orange_terracotta' | 'magenta_terracotta' | 'light_blue_terracotta' | 'yellow_terracotta' | 'lime_terracotta' | 'pink_terracotta' | 'gray_terracotta' | 'light_gray_terracotta' | 'cyan_terracotta' | 'purple_terracotta' | 'blue_terracotta' | 'brown_terracotta' | 'green_terracotta' | 'red_terracotta' | 'black_terracotta' | 'barrier' | 'light' | 'hay_block' | 'white_carpet' | 'orange_carpet' | 'magenta_carpet' | 'light_blue_carpet' | 'yellow_carpet' | 'lime_carpet' | 'pink_carpet' | 'gray_carpet' | 'light_gray_carpet' | 'cyan_carpet' | 'purple_carpet' | 'blue_carpet' | 'brown_carpet' | 'green_carpet' | 'red_carpet' | 'black_carpet' | 'terracotta' | 'packed_ice' | 'dirt_path' | 'sunflower' | 'lilac' | 'rose_bush' | 'peony' | 'tall_grass' | 'large_fern' | 'white_stained_glass' | 'orange_stained_glass' | 'magenta_stained_glass' | 'light_blue_stained_glass' | 'yellow_stained_glass' | 'lime_stained_glass' | 'pink_stained_glass' | 'gray_stained_glass' | 'light_gray_stained_glass' | 'cyan_stained_glass' | 'purple_stained_glass' | 'blue_stained_glass' | 'brown_stained_glass' | 'green_stained_glass' | 'red_stained_glass' | 'black_stained_glass' | 'white_stained_glass_pane' | 'orange_stained_glass_pane' | 'magenta_stained_glass_pane' | 'light_blue_stained_glass_pane' | 'yellow_stained_glass_pane' | 'lime_stained_glass_pane' | 'pink_stained_glass_pane' | 'gray_stained_glass_pane' | 'light_gray_stained_glass_pane' | 'cyan_stained_glass_pane' | 'purple_stained_glass_pane' | 'blue_stained_glass_pane' | 'brown_stained_glass_pane' | 'green_stained_glass_pane' | 'red_stained_glass_pane' | 'black_stained_glass_pane' | 'prismarine' | 'prismarine_bricks' | 'dark_prismarine' | 'prismarine_stairs' | 'prismarine_brick_stairs' | 'dark_prismarine_stairs' | 'sea_lantern' | 'red_sandstone' | 'chiseled_red_sandstone' | 'cut_red_sandstone' | 'red_sandstone_stairs' | 'repeating_command_block' | 'chain_command_block' | 'magma_block' | 'nether_wart_block' | 'warped_wart_block' | 'red_nether_bricks' | 'bone_block' | 'structure_void' | 'shulker_box' | 'white_shulker_box' | 'orange_shulker_box' | 'magenta_shulker_box' | 'light_blue_shulker_box' | 'yellow_shulker_box' | 'lime_shulker_box' | 'pink_shulker_box' | 'gray_shulker_box' | 'light_gray_shulker_box' | 'cyan_shulker_box' | 'purple_shulker_box' | 'blue_shulker_box' | 'brown_shulker_box' | 'green_shulker_box' | 'red_shulker_box' | 'black_shulker_box' | 'white_glazed_terracotta' | 'orange_glazed_terracotta' | 'magenta_glazed_terracotta' | 'light_blue_glazed_terracotta' | 'yellow_glazed_terracotta' | 'lime_glazed_terracotta' | 'pink_glazed_terracotta' | 'gray_glazed_terracotta' | 'light_gray_glazed_terracotta' | 'cyan_glazed_terracotta' | 'purple_glazed_terracotta' | 'blue_glazed_terracotta' | 'brown_glazed_terracotta' | 'green_glazed_terracotta' | 'red_glazed_terracotta' | 'black_glazed_terracotta' | 'white_concrete' | 'orange_concrete' | 'magenta_concrete' | 'light_blue_concrete' | 'yellow_concrete' | 'lime_concrete' | 'pink_concrete' | 'gray_concrete' | 'light_gray_concrete' | 'cyan_concrete' | 'purple_concrete' | 'blue_concrete' | 'brown_concrete' | 'green_concrete' | 'red_concrete' | 'black_concrete' | 'white_concrete_powder' | 'orange_concrete_powder' | 'magenta_concrete_powder' | 'light_blue_concrete_powder' | 'yellow_concrete_powder' | 'lime_concrete_powder' | 'pink_concrete_powder' | 'gray_concrete_powder' | 'light_gray_concrete_powder' | 'cyan_concrete_powder' | 'purple_concrete_powder' | 'blue_concrete_powder' | 'brown_concrete_powder' | 'green_concrete_powder' | 'red_concrete_powder' | 'black_concrete_powder' | 'turtle_egg' | 'sniffer_egg' | 'dead_tube_coral_block' | 'dead_brain_coral_block' | 'dead_bubble_coral_block' | 'dead_fire_coral_block' | 'dead_horn_coral_block' | 'tube_coral_block' | 'brain_coral_block' | 'bubble_coral_block' | 'fire_coral_block' | 'horn_coral_block' | 'tube_coral' | 'brain_coral' | 'bubble_coral' | 'fire_coral' | 'horn_coral' | 'dead_brain_coral' | 'dead_bubble_coral' | 'dead_fire_coral' | 'dead_horn_coral' | 'dead_tube_coral' | 'tube_coral_fan' | 'brain_coral_fan' | 'bubble_coral_fan' | 'fire_coral_fan' | 'horn_coral_fan' | 'dead_tube_coral_fan' | 'dead_brain_coral_fan' | 'dead_bubble_coral_fan' | 'dead_fire_coral_fan' | 'dead_horn_coral_fan' | 'blue_ice' | 'conduit' | 'polished_granite_stairs' | 'smooth_red_sandstone_stairs' | 'mossy_stone_brick_stairs' | 'polished_diorite_stairs' | 'mossy_cobblestone_stairs' | 'end_stone_brick_stairs' | 'stone_stairs' | 'smooth_sandstone_stairs' | 'smooth_quartz_stairs' | 'granite_stairs' | 'andesite_stairs' | 'red_nether_brick_stairs' | 'polished_andesite_stairs' | 'diorite_stairs' | 'cobbled_deepslate_stairs' | 'polished_deepslate_stairs' | 'deepslate_brick_stairs' | 'deepslate_tile_stairs' | 'polished_granite_slab' | 'smooth_red_sandstone_slab' | 'mossy_stone_brick_slab' | 'polished_diorite_slab' | 'mossy_cobblestone_slab' | 'end_stone_brick_slab' | 'smooth_sandstone_slab' | 'smooth_quartz_slab' | 'granite_slab' | 'andesite_slab' | 'red_nether_brick_slab' | 'polished_andesite_slab' | 'diorite_slab' | 'cobbled_deepslate_slab' | 'polished_deepslate_slab' | 'deepslate_brick_slab' | 'deepslate_tile_slab' | 'scaffolding' | 'redstone' | 'redstone_torch' | 'redstone_block' | 'repeater' | 'comparator' | 'piston' | 'sticky_piston' | 'slime_block' | 'honey_block' | 'observer' | 'hopper' | 'dispenser' | 'dropper' | 'lectern' | 'target' | 'lever' | 'lightning_rod' | 'daylight_detector' | 'sculk_sensor' | 'calibrated_sculk_sensor' | 'tripwire_hook' | 'trapped_chest' | 'tnt' | 'redstone_lamp' | 'note_block' | 'stone_button' | 'polished_blackstone_button' | 'oak_button' | 'spruce_button' | 'birch_button' | 'jungle_button' | 'acacia_button' | 'cherry_button' | 'dark_oak_button' | 'mangrove_button' | 'bamboo_button' | 'crimson_button' | 'warped_button' | 'stone_pressure_plate' | 'polished_blackstone_pressure_plate' | 'light_weighted_pressure_plate' | 'heavy_weighted_pressure_plate' | 'oak_pressure_plate' | 'spruce_pressure_plate' | 'birch_pressure_plate' | 'jungle_pressure_plate' | 'acacia_pressure_plate' | 'cherry_pressure_plate' | 'dark_oak_pressure_plate' | 'mangrove_pressure_plate' | 'bamboo_pressure_plate' | 'crimson_pressure_plate' | 'warped_pressure_plate' | 'iron_door' | 'oak_door' | 'spruce_door' | 'birch_door' | 'jungle_door' | 'acacia_door' | 'cherry_door' | 'dark_oak_door' | 'mangrove_door' | 'bamboo_door' | 'crimson_door' | 'warped_door' | 'iron_trapdoor' | 'oak_trapdoor' | 'spruce_trapdoor' | 'birch_trapdoor' | 'jungle_trapdoor' | 'acacia_trapdoor' | 'cherry_trapdoor' | 'dark_oak_trapdoor' | 'mangrove_trapdoor' | 'bamboo_trapdoor' | 'crimson_trapdoor' | 'warped_trapdoor' | 'oak_fence_gate' | 'spruce_fence_gate' | 'birch_fence_gate' | 'jungle_fence_gate' | 'acacia_fence_gate' | 'cherry_fence_gate' | 'dark_oak_fence_gate' | 'mangrove_fence_gate' | 'bamboo_fence_gate' | 'crimson_fence_gate' | 'warped_fence_gate' | 'powered_rail' | 'detector_rail' | 'rail' | 'activator_rail' | 'saddle' | 'minecart' | 'chest_minecart' | 'furnace_minecart' | 'tnt_minecart' | 'hopper_minecart' | 'carrot_on_a_stick' | 'warped_fungus_on_a_stick' | 'elytra' | 'oak_boat' | 'oak_chest_boat' | 'spruce_boat' | 'spruce_chest_boat' | 'birch_boat' | 'birch_chest_boat' | 'jungle_boat' | 'jungle_chest_boat' | 'acacia_boat' | 'acacia_chest_boat' | 'cherry_boat' | 'cherry_chest_boat' | 'dark_oak_boat' | 'dark_oak_chest_boat' | 'mangrove_boat' | 'mangrove_chest_boat' | 'bamboo_raft' | 'bamboo_chest_raft' | 'structure_block' | 'jigsaw' | 'turtle_helmet' | 'scute' | 'flint_and_steel' | 'apple' | 'bow' | 'arrow' | 'coal' | 'charcoal' | 'diamond' | 'emerald' | 'lapis_lazuli' | 'quartz' | 'amethyst_shard' | 'raw_iron' | 'iron_ingot' | 'raw_copper' | 'copper_ingot' | 'raw_gold' | 'gold_ingot' | 'netherite_ingot' | 'netherite_scrap' | 'wooden_sword' | 'wooden_shovel' | 'wooden_pickaxe' | 'wooden_axe' | 'wooden_hoe' | 'stone_sword' | 'stone_shovel' | 'stone_pickaxe' | 'stone_axe' | 'stone_hoe' | 'golden_sword' | 'golden_shovel' | 'golden_pickaxe' | 'golden_axe' | 'golden_hoe' | 'iron_sword' | 'iron_shovel' | 'iron_pickaxe' | 'iron_axe' | 'iron_hoe' | 'diamond_sword' | 'diamond_shovel' | 'diamond_pickaxe' | 'diamond_axe' | 'diamond_hoe' | 'netherite_sword' | 'netherite_shovel' | 'netherite_pickaxe' | 'netherite_axe' | 'netherite_hoe' | 'stick' | 'bowl' | 'mushroom_stew' | 'string' | 'feather' | 'gunpowder' | 'wheat_seeds' | 'wheat' | 'bread' | 'leather_helmet' | 'leather_chestplate' | 'leather_leggings' | 'leather_boots' | 'chainmail_helmet' | 'chainmail_chestplate' | 'chainmail_leggings' | 'chainmail_boots' | 'iron_helmet' | 'iron_chestplate' | 'iron_leggings' | 'iron_boots' | 'diamond_helmet' | 'diamond_chestplate' | 'diamond_leggings' | 'diamond_boots' | 'golden_helmet' | 'golden_chestplate' | 'golden_leggings' | 'golden_boots' | 'netherite_helmet' | 'netherite_chestplate' | 'netherite_leggings' | 'netherite_boots' | 'flint' | 'porkchop' | 'cooked_porkchop' | 'painting' | 'golden_apple' | 'enchanted_golden_apple' | 'oak_sign' | 'spruce_sign' | 'birch_sign' | 'jungle_sign' | 'acacia_sign' | 'cherry_sign' | 'dark_oak_sign' | 'mangrove_sign' | 'bamboo_sign' | 'crimson_sign' | 'warped_sign' | 'oak_hanging_sign' | 'spruce_hanging_sign' | 'birch_hanging_sign' | 'jungle_hanging_sign' | 'acacia_hanging_sign' | 'cherry_hanging_sign' | 'dark_oak_hanging_sign' | 'mangrove_hanging_sign' | 'bamboo_hanging_sign' | 'crimson_hanging_sign' | 'warped_hanging_sign' | 'bucket' | 'water_bucket' | 'lava_bucket' | 'powder_snow_bucket' | 'snowball' | 'leather' | 'milk_bucket' | 'pufferfish_bucket' | 'salmon_bucket' | 'cod_bucket' | 'tropical_fish_bucket' | 'axolotl_bucket' | 'tadpole_bucket' | 'brick' | 'clay_ball' | 'dried_kelp_block' | 'paper' | 'book' | 'slime_ball' | 'egg' | 'compass' | 'recovery_compass' | 'bundle' | 'fishing_rod' | 'clock' | 'spyglass' | 'glowstone_dust' | 'cod' | 'salmon' | 'tropical_fish' | 'pufferfish' | 'cooked_cod' | 'cooked_salmon' | 'ink_sac' | 'glow_ink_sac' | 'cocoa_beans' | 'white_dye' | 'orange_dye' | 'magenta_dye' | 'light_blue_dye' | 'yellow_dye' | 'lime_dye' | 'pink_dye' | 'gray_dye' | 'light_gray_dye' | 'cyan_dye' | 'purple_dye' | 'blue_dye' | 'brown_dye' | 'green_dye' | 'red_dye' | 'black_dye' | 'bone_meal' | 'bone' | 'sugar' | 'cake' | 'white_bed' | 'orange_bed' | 'magenta_bed' | 'light_blue_bed' | 'yellow_bed' | 'lime_bed' | 'pink_bed' | 'gray_bed' | 'light_gray_bed' | 'cyan_bed' | 'purple_bed' | 'blue_bed' | 'brown_bed' | 'green_bed' | 'red_bed' | 'black_bed' | 'cookie' | 'filled_map' | 'shears' | 'melon_slice' | 'dried_kelp' | 'pumpkin_seeds' | 'melon_seeds' | 'beef' | 'cooked_beef' | 'chicken' | 'cooked_chicken' | 'rotten_flesh' | 'ender_pearl' | 'blaze_rod' | 'ghast_tear' | 'gold_nugget' | 'nether_wart' | 'potion' | 'glass_bottle' | 'spider_eye' | 'fermented_spider_eye' | 'blaze_powder' | 'magma_cream' | 'brewing_stand' | 'cauldron' | 'ender_eye' | 'glistering_melon_slice' | 'allay_spawn_egg' | 'axolotl_spawn_egg' | 'bat_spawn_egg' | 'bee_spawn_egg' | 'blaze_spawn_egg' | 'cat_spawn_egg' | 'camel_spawn_egg' | 'cave_spider_spawn_egg' | 'chicken_spawn_egg' | 'cod_spawn_egg' | 'cow_spawn_egg' | 'creeper_spawn_egg' | 'dolphin_spawn_egg' | 'donkey_spawn_egg' | 'drowned_spawn_egg' | 'elder_guardian_spawn_egg' | 'ender_dragon_spawn_egg' | 'enderman_spawn_egg' | 'endermite_spawn_egg' | 'evoker_spawn_egg' | 'fox_spawn_egg' | 'frog_spawn_egg' | 'ghast_spawn_egg' | 'glow_squid_spawn_egg' | 'goat_spawn_egg' | 'guardian_spawn_egg' | 'hoglin_spawn_egg' | 'horse_spawn_egg' | 'husk_spawn_egg' | 'iron_golem_spawn_egg' | 'llama_spawn_egg' | 'magma_cube_spawn_egg' | 'mooshroom_spawn_egg' | 'mule_spawn_egg' | 'ocelot_spawn_egg' | 'panda_spawn_egg' | 'parrot_spawn_egg' | 'phantom_spawn_egg' | 'pig_spawn_egg' | 'piglin_spawn_egg' | 'piglin_brute_spawn_egg' | 'pillager_spawn_egg' | 'polar_bear_spawn_egg' | 'pufferfish_spawn_egg' | 'rabbit_spawn_egg' | 'ravager_spawn_egg' | 'salmon_spawn_egg' | 'sheep_spawn_egg' | 'shulker_spawn_egg' | 'silverfish_spawn_egg' | 'skeleton_spawn_egg' | 'skeleton_horse_spawn_egg' | 'slime_spawn_egg' | 'sniffer_spawn_egg' | 'snow_golem_spawn_egg' | 'spider_spawn_egg' | 'squid_spawn_egg' | 'stray_spawn_egg' | 'strider_spawn_egg' | 'tadpole_spawn_egg' | 'trader_llama_spawn_egg' | 'tropical_fish_spawn_egg' | 'turtle_spawn_egg' | 'vex_spawn_egg' | 'villager_spawn_egg' | 'vindicator_spawn_egg' | 'wandering_trader_spawn_egg' | 'warden_spawn_egg' | 'witch_spawn_egg' | 'wither_spawn_egg' | 'wither_skeleton_spawn_egg' | 'wolf_spawn_egg' | 'zoglin_spawn_egg' | 'zombie_spawn_egg' | 'zombie_horse_spawn_egg' | 'zombie_villager_spawn_egg' | 'zombified_piglin_spawn_egg' | 'experience_bottle' | 'fire_charge' | 'writable_book' | 'written_book' | 'item_frame' | 'glow_item_frame' | 'flower_pot' | 'carrot' | 'potato' | 'baked_potato' | 'poisonous_potato' | 'map' | 'golden_carrot' | 'skeleton_skull' | 'wither_skeleton_skull' | 'player_head' | 'zombie_head' | 'creeper_head' | 'dragon_head' | 'piglin_head' | 'nether_star' | 'pumpkin_pie' | 'firework_rocket' | 'firework_star' | 'enchanted_book' | 'nether_brick' | 'prismarine_shard' | 'prismarine_crystals' | 'rabbit' | 'cooked_rabbit' | 'rabbit_stew' | 'rabbit_foot' | 'rabbit_hide' | 'armor_stand' | 'iron_horse_armor' | 'golden_horse_armor' | 'diamond_horse_armor' | 'leather_horse_armor' | 'lead' | 'name_tag' | 'command_block_minecart' | 'mutton' | 'cooked_mutton' | 'white_banner' | 'orange_banner' | 'magenta_banner' | 'light_blue_banner' | 'yellow_banner' | 'lime_banner' | 'pink_banner' | 'gray_banner' | 'light_gray_banner' | 'cyan_banner' | 'purple_banner' | 'blue_banner' | 'brown_banner' | 'green_banner' | 'red_banner' | 'black_banner' | 'end_crystal' | 'chorus_fruit' | 'popped_chorus_fruit' | 'torchflower_seeds' | 'pitcher_pod' | 'beetroot' | 'beetroot_seeds' | 'beetroot_soup' | 'dragon_breath' | 'splash_potion' | 'spectral_arrow' | 'tipped_arrow' | 'lingering_potion' | 'shield' | 'totem_of_undying' | 'shulker_shell' | 'iron_nugget' | 'knowledge_book' | 'debug_stick' | 'music_disc_13' | 'music_disc_cat' | 'music_disc_blocks' | 'music_disc_chirp' | 'music_disc_far' | 'music_disc_mall' | 'music_disc_mellohi' | 'music_disc_stal' | 'music_disc_strad' | 'music_disc_ward' | 'music_disc_11' | 'music_disc_wait' | 'music_disc_otherside' | 'music_disc_relic' | 'music_disc_5' | 'music_disc_pigstep' | 'disc_fragment_5' | 'trident' | 'phantom_membrane' | 'nautilus_shell' | 'heart_of_the_sea' | 'crossbow' | 'suspicious_stew' | 'loom' | 'flower_banner_pattern' | 'creeper_banner_pattern' | 'skull_banner_pattern' | 'mojang_banner_pattern' | 'globe_banner_pattern' | 'piglin_banner_pattern' | 'goat_horn' | 'composter' | 'barrel' | 'smoker' | 'blast_furnace' | 'cartography_table' | 'fletching_table' | 'grindstone' | 'smithing_table' | 'stonecutter' | 'bell' | 'lantern' | 'soul_lantern' | 'sweet_berries' | 'glow_berries' | 'campfire' | 'soul_campfire' | 'shroomlight' | 'honeycomb' | 'bee_nest' | 'beehive' | 'honey_bottle' | 'honeycomb_block' | 'lodestone' | 'crying_obsidian' | 'blackstone' | 'blackstone_slab' | 'blackstone_stairs' | 'gilded_blackstone' | 'polished_blackstone' | 'polished_blackstone_slab' | 'polished_blackstone_stairs' | 'chiseled_polished_blackstone' | 'polished_blackstone_bricks' | 'polished_blackstone_brick_slab' | 'polished_blackstone_brick_stairs' | 'cracked_polished_blackstone_bricks' | 'respawn_anchor' | 'candle' | 'white_candle' | 'orange_candle' | 'magenta_candle' | 'light_blue_candle' | 'yellow_candle' | 'lime_candle' | 'pink_candle' | 'gray_candle' | 'light_gray_candle' | 'cyan_candle' | 'purple_candle' | 'blue_candle' | 'brown_candle' | 'green_candle' | 'red_candle' | 'black_candle' | 'small_amethyst_bud' | 'medium_amethyst_bud' | 'large_amethyst_bud' | 'amethyst_cluster' | 'pointed_dripstone' | 'ochre_froglight' | 'verdant_froglight' | 'pearlescent_froglight' | 'frogspawn' | 'echo_shard' | 'brush' | 'netherite_upgrade_smithing_template' | 'sentry_armor_trim_smithing_template' | 'dune_armor_trim_smithing_template' | 'coast_armor_trim_smithing_template' | 'wild_armor_trim_smithing_template' | 'ward_armor_trim_smithing_template' | 'eye_armor_trim_smithing_template' | 'vex_armor_trim_smithing_template' | 'tide_armor_trim_smithing_template' | 'snout_armor_trim_smithing_template' | 'rib_armor_trim_smithing_template' | 'spire_armor_trim_smithing_template' | 'wayfinder_armor_trim_smithing_template' | 'shaper_armor_trim_smithing_template' | 'silence_armor_trim_smithing_template' | 'raiser_armor_trim_smithing_template' | 'host_armor_trim_smithing_template' | 'angler_pottery_sherd' | 'archer_pottery_sherd' | 'arms_up_pottery_sherd' | 'blade_pottery_sherd' | 'brewer_pottery_sherd' | 'burn_pottery_sherd' | 'danger_pottery_sherd' | 'explorer_pottery_sherd' | 'friend_pottery_sherd' | 'heart_pottery_sherd' | 'heartbreak_pottery_sherd' | 'howl_pottery_sherd' | 'miner_pottery_sherd' | 'mourner_pottery_sherd' | 'plenty_pottery_sherd' | 'prize_pottery_sherd' | 'sheaf_pottery_sherd' | 'shelter_pottery_sherd' | 'skull_pottery_sherd' | 'snort_pottery_sherd' -export type EntityNames = 'allay' | 'area_effect_cloud' | 'armor_stand' | 'arrow' | 'axolotl' | 'bat' | 'bee' | 'blaze' | 'block_display' | 'boat' | 'camel' | 'cat' | 'cave_spider' | 'chest_boat' | 'chest_minecart' | 'chicken' | 'cod' | 'command_block_minecart' | 'cow' | 'creeper' | 'dolphin' | 'donkey' | 'dragon_fireball' | 'drowned' | 'egg' | 'elder_guardian' | 'end_crystal' | 'ender_dragon' | 'ender_pearl' | 'enderman' | 'endermite' | 'evoker' | 'evoker_fangs' | 'experience_bottle' | 'experience_orb' | 'eye_of_ender' | 'falling_block' | 'firework_rocket' | 'fox' | 'frog' | 'furnace_minecart' | 'ghast' | 'giant' | 'glow_item_frame' | 'glow_squid' | 'goat' | 'guardian' | 'hoglin' | 'hopper_minecart' | 'horse' | 'husk' | 'illusioner' | 'interaction' | 'iron_golem' | 'item' | 'item_display' | 'item_frame' | 'fireball' | 'leash_knot' | 'lightning_bolt' | 'llama' | 'llama_spit' | 'magma_cube' | 'marker' | 'minecart' | 'mooshroom' | 'mule' | 'ocelot' | 'painting' | 'panda' | 'parrot' | 'phantom' | 'pig' | 'piglin' | 'piglin_brute' | 'pillager' | 'polar_bear' | 'potion' | 'pufferfish' | 'rabbit' | 'ravager' | 'salmon' | 'sheep' | 'shulker' | 'shulker_bullet' | 'silverfish' | 'skeleton' | 'skeleton_horse' | 'slime' | 'small_fireball' | 'sniffer' | 'snow_golem' | 'snowball' | 'spawner_minecart' | 'spectral_arrow' | 'spider' | 'squid' | 'stray' | 'strider' | 'tadpole' | 'text_display' | 'tnt' | 'tnt_minecart' | 'trader_llama' | 'trident' | 'tropical_fish' | 'turtle' | 'vex' | 'villager' | 'vindicator' | 'wandering_trader' | 'warden' | 'witch' | 'wither' | 'wither_skeleton' | 'wither_skull' | 'wolf' | 'zoglin' | 'zombie' | 'zombie_horse' | 'zombie_villager' | 'zombified_piglin' | 'player' | 'fishing_bobber' -export type BiomesNames = 'badlands' | 'bamboo_jungle' | 'basalt_deltas' | 'beach' | 'birch_forest' | 'cherry_grove' | 'cold_ocean' | 'crimson_forest' | 'dark_forest' | 'deep_cold_ocean' | 'deep_dark' | 'deep_frozen_ocean' | 'deep_lukewarm_ocean' | 'deep_ocean' | 'desert' | 'dripstone_caves' | 'end_barrens' | 'end_highlands' | 'end_midlands' | 'eroded_badlands' | 'flower_forest' | 'forest' | 'frozen_ocean' | 'frozen_peaks' | 'frozen_river' | 'grove' | 'ice_spikes' | 'jagged_peaks' | 'jungle' | 'lukewarm_ocean' | 'lush_caves' | 'mangrove_swamp' | 'meadow' | 'mushroom_fields' | 'nether_wastes' | 'ocean' | 'old_growth_birch_forest' | 'old_growth_pine_taiga' | 'old_growth_spruce_taiga' | 'plains' | 'river' | 'savanna' | 'savanna_plateau' | 'small_end_islands' | 'snowy_beach' | 'snowy_plains' | 'snowy_slopes' | 'snowy_taiga' | 'soul_sand_valley' | 'sparse_jungle' | 'stony_peaks' | 'stony_shore' | 'sunflower_plains' | 'swamp' | 'taiga' | 'the_end' | 'the_void' | 'warm_ocean' | 'warped_forest' | 'windswept_forest' | 'windswept_gravelly_hills' | 'windswept_hills' | 'windswept_savanna' | 'wooded_badlands' -export type EnchantmentNames = 'protection' | 'fire_protection' | 'feather_falling' | 'blast_protection' | 'projectile_protection' | 'respiration' | 'aqua_affinity' | 'thorns' | 'depth_strider' | 'frost_walker' | 'binding_curse' | 'soul_speed' | 'swift_sneak' | 'sharpness' | 'smite' | 'bane_of_arthropods' | 'knockback' | 'fire_aspect' | 'looting' | 'sweeping' | 'efficiency' | 'silk_touch' | 'unbreaking' | 'fortune' | 'power' | 'punch' | 'flame' | 'infinity' | 'luck_of_the_sea' | 'lure' | 'loyalty' | 'impaling' | 'riptide' | 'channeling' | 'multishot' | 'quick_charge' | 'piercing' | 'mending' | 'vanishing_curse' +export type BlockNames = 'air' | 'stone' | 'granite' | 'polished_granite' | 'diorite' | 'polished_diorite' | 'andesite' | 'polished_andesite' | 'grass_block' | 'dirt' | 'coarse_dirt' | 'podzol' | 'cobblestone' | 'oak_planks' | 'spruce_planks' | 'birch_planks' | 'jungle_planks' | 'acacia_planks' | 'cherry_planks' | 'dark_oak_planks' | 'mangrove_planks' | 'bamboo_planks' | 'bamboo_mosaic' | 'oak_sapling' | 'spruce_sapling' | 'birch_sapling' | 'jungle_sapling' | 'acacia_sapling' | 'cherry_sapling' | 'dark_oak_sapling' | 'mangrove_propagule' | 'bedrock' | 'water' | 'lava' | 'sand' | 'suspicious_sand' | 'red_sand' | 'gravel' | 'suspicious_gravel' | 'gold_ore' | 'deepslate_gold_ore' | 'iron_ore' | 'deepslate_iron_ore' | 'coal_ore' | 'deepslate_coal_ore' | 'nether_gold_ore' | 'oak_log' | 'spruce_log' | 'birch_log' | 'jungle_log' | 'acacia_log' | 'cherry_log' | 'dark_oak_log' | 'mangrove_log' | 'mangrove_roots' | 'muddy_mangrove_roots' | 'bamboo_block' | 'stripped_spruce_log' | 'stripped_birch_log' | 'stripped_jungle_log' | 'stripped_acacia_log' | 'stripped_cherry_log' | 'stripped_dark_oak_log' | 'stripped_oak_log' | 'stripped_mangrove_log' | 'stripped_bamboo_block' | 'oak_wood' | 'spruce_wood' | 'birch_wood' | 'jungle_wood' | 'acacia_wood' | 'cherry_wood' | 'dark_oak_wood' | 'mangrove_wood' | 'stripped_oak_wood' | 'stripped_spruce_wood' | 'stripped_birch_wood' | 'stripped_jungle_wood' | 'stripped_acacia_wood' | 'stripped_cherry_wood' | 'stripped_dark_oak_wood' | 'stripped_mangrove_wood' | 'oak_leaves' | 'spruce_leaves' | 'birch_leaves' | 'jungle_leaves' | 'acacia_leaves' | 'cherry_leaves' | 'dark_oak_leaves' | 'mangrove_leaves' | 'azalea_leaves' | 'flowering_azalea_leaves' | 'sponge' | 'wet_sponge' | 'glass' | 'lapis_ore' | 'deepslate_lapis_ore' | 'lapis_block' | 'dispenser' | 'sandstone' | 'chiseled_sandstone' | 'cut_sandstone' | 'note_block' | 'white_bed' | 'orange_bed' | 'magenta_bed' | 'light_blue_bed' | 'yellow_bed' | 'lime_bed' | 'pink_bed' | 'gray_bed' | 'light_gray_bed' | 'cyan_bed' | 'purple_bed' | 'blue_bed' | 'brown_bed' | 'green_bed' | 'red_bed' | 'black_bed' | 'powered_rail' | 'detector_rail' | 'sticky_piston' | 'cobweb' | 'grass' | 'fern' | 'dead_bush' | 'seagrass' | 'tall_seagrass' | 'piston' | 'piston_head' | 'white_wool' | 'orange_wool' | 'magenta_wool' | 'light_blue_wool' | 'yellow_wool' | 'lime_wool' | 'pink_wool' | 'gray_wool' | 'light_gray_wool' | 'cyan_wool' | 'purple_wool' | 'blue_wool' | 'brown_wool' | 'green_wool' | 'red_wool' | 'black_wool' | 'moving_piston' | 'dandelion' | 'torchflower' | 'poppy' | 'blue_orchid' | 'allium' | 'azure_bluet' | 'red_tulip' | 'orange_tulip' | 'white_tulip' | 'pink_tulip' | 'oxeye_daisy' | 'cornflower' | 'wither_rose' | 'lily_of_the_valley' | 'brown_mushroom' | 'red_mushroom' | 'gold_block' | 'iron_block' | 'bricks' | 'tnt' | 'bookshelf' | 'chiseled_bookshelf' | 'mossy_cobblestone' | 'obsidian' | 'torch' | 'wall_torch' | 'fire' | 'soul_fire' | 'spawner' | 'oak_stairs' | 'chest' | 'redstone_wire' | 'diamond_ore' | 'deepslate_diamond_ore' | 'diamond_block' | 'crafting_table' | 'wheat' | 'farmland' | 'furnace' | 'oak_sign' | 'spruce_sign' | 'birch_sign' | 'acacia_sign' | 'cherry_sign' | 'jungle_sign' | 'dark_oak_sign' | 'mangrove_sign' | 'bamboo_sign' | 'oak_door' | 'ladder' | 'rail' | 'cobblestone_stairs' | 'oak_wall_sign' | 'spruce_wall_sign' | 'birch_wall_sign' | 'acacia_wall_sign' | 'cherry_wall_sign' | 'jungle_wall_sign' | 'dark_oak_wall_sign' | 'mangrove_wall_sign' | 'bamboo_wall_sign' | 'oak_hanging_sign' | 'spruce_hanging_sign' | 'birch_hanging_sign' | 'acacia_hanging_sign' | 'cherry_hanging_sign' | 'jungle_hanging_sign' | 'dark_oak_hanging_sign' | 'crimson_hanging_sign' | 'warped_hanging_sign' | 'mangrove_hanging_sign' | 'bamboo_hanging_sign' | 'oak_wall_hanging_sign' | 'spruce_wall_hanging_sign' | 'birch_wall_hanging_sign' | 'acacia_wall_hanging_sign' | 'cherry_wall_hanging_sign' | 'jungle_wall_hanging_sign' | 'dark_oak_wall_hanging_sign' | 'mangrove_wall_hanging_sign' | 'crimson_wall_hanging_sign' | 'warped_wall_hanging_sign' | 'bamboo_wall_hanging_sign' | 'lever' | 'stone_pressure_plate' | 'iron_door' | 'oak_pressure_plate' | 'spruce_pressure_plate' | 'birch_pressure_plate' | 'jungle_pressure_plate' | 'acacia_pressure_plate' | 'cherry_pressure_plate' | 'dark_oak_pressure_plate' | 'mangrove_pressure_plate' | 'bamboo_pressure_plate' | 'redstone_ore' | 'deepslate_redstone_ore' | 'redstone_torch' | 'redstone_wall_torch' | 'stone_button' | 'snow' | 'ice' | 'snow_block' | 'cactus' | 'clay' | 'sugar_cane' | 'jukebox' | 'oak_fence' | 'pumpkin' | 'netherrack' | 'soul_sand' | 'soul_soil' | 'basalt' | 'polished_basalt' | 'soul_torch' | 'soul_wall_torch' | 'glowstone' | 'nether_portal' | 'carved_pumpkin' | 'jack_o_lantern' | 'cake' | 'repeater' | 'white_stained_glass' | 'orange_stained_glass' | 'magenta_stained_glass' | 'light_blue_stained_glass' | 'yellow_stained_glass' | 'lime_stained_glass' | 'pink_stained_glass' | 'gray_stained_glass' | 'light_gray_stained_glass' | 'cyan_stained_glass' | 'purple_stained_glass' | 'blue_stained_glass' | 'brown_stained_glass' | 'green_stained_glass' | 'red_stained_glass' | 'black_stained_glass' | 'oak_trapdoor' | 'spruce_trapdoor' | 'birch_trapdoor' | 'jungle_trapdoor' | 'acacia_trapdoor' | 'cherry_trapdoor' | 'dark_oak_trapdoor' | 'mangrove_trapdoor' | 'bamboo_trapdoor' | 'stone_bricks' | 'mossy_stone_bricks' | 'cracked_stone_bricks' | 'chiseled_stone_bricks' | 'packed_mud' | 'mud_bricks' | 'infested_stone' | 'infested_cobblestone' | 'infested_stone_bricks' | 'infested_mossy_stone_bricks' | 'infested_cracked_stone_bricks' | 'infested_chiseled_stone_bricks' | 'brown_mushroom_block' | 'red_mushroom_block' | 'mushroom_stem' | 'iron_bars' | 'chain' | 'glass_pane' | 'melon' | 'attached_pumpkin_stem' | 'attached_melon_stem' | 'pumpkin_stem' | 'melon_stem' | 'vine' | 'glow_lichen' | 'oak_fence_gate' | 'brick_stairs' | 'stone_brick_stairs' | 'mud_brick_stairs' | 'mycelium' | 'lily_pad' | 'nether_bricks' | 'nether_brick_fence' | 'nether_brick_stairs' | 'nether_wart' | 'enchanting_table' | 'brewing_stand' | 'cauldron' | 'water_cauldron' | 'lava_cauldron' | 'powder_snow_cauldron' | 'end_portal' | 'end_portal_frame' | 'end_stone' | 'dragon_egg' | 'redstone_lamp' | 'cocoa' | 'sandstone_stairs' | 'emerald_ore' | 'deepslate_emerald_ore' | 'ender_chest' | 'tripwire_hook' | 'tripwire' | 'emerald_block' | 'spruce_stairs' | 'birch_stairs' | 'jungle_stairs' | 'command_block' | 'beacon' | 'cobblestone_wall' | 'mossy_cobblestone_wall' | 'flower_pot' | 'potted_torchflower' | 'potted_oak_sapling' | 'potted_spruce_sapling' | 'potted_birch_sapling' | 'potted_jungle_sapling' | 'potted_acacia_sapling' | 'potted_cherry_sapling' | 'potted_dark_oak_sapling' | 'potted_mangrove_propagule' | 'potted_fern' | 'potted_dandelion' | 'potted_poppy' | 'potted_blue_orchid' | 'potted_allium' | 'potted_azure_bluet' | 'potted_red_tulip' | 'potted_orange_tulip' | 'potted_white_tulip' | 'potted_pink_tulip' | 'potted_oxeye_daisy' | 'potted_cornflower' | 'potted_lily_of_the_valley' | 'potted_wither_rose' | 'potted_red_mushroom' | 'potted_brown_mushroom' | 'potted_dead_bush' | 'potted_cactus' | 'carrots' | 'potatoes' | 'oak_button' | 'spruce_button' | 'birch_button' | 'jungle_button' | 'acacia_button' | 'cherry_button' | 'dark_oak_button' | 'mangrove_button' | 'bamboo_button' | 'skeleton_skull' | 'skeleton_wall_skull' | 'wither_skeleton_skull' | 'wither_skeleton_wall_skull' | 'zombie_head' | 'zombie_wall_head' | 'player_head' | 'player_wall_head' | 'creeper_head' | 'creeper_wall_head' | 'dragon_head' | 'dragon_wall_head' | 'piglin_head' | 'piglin_wall_head' | 'anvil' | 'chipped_anvil' | 'damaged_anvil' | 'trapped_chest' | 'light_weighted_pressure_plate' | 'heavy_weighted_pressure_plate' | 'comparator' | 'daylight_detector' | 'redstone_block' | 'nether_quartz_ore' | 'hopper' | 'quartz_block' | 'chiseled_quartz_block' | 'quartz_pillar' | 'quartz_stairs' | 'activator_rail' | 'dropper' | 'white_terracotta' | 'orange_terracotta' | 'magenta_terracotta' | 'light_blue_terracotta' | 'yellow_terracotta' | 'lime_terracotta' | 'pink_terracotta' | 'gray_terracotta' | 'light_gray_terracotta' | 'cyan_terracotta' | 'purple_terracotta' | 'blue_terracotta' | 'brown_terracotta' | 'green_terracotta' | 'red_terracotta' | 'black_terracotta' | 'white_stained_glass_pane' | 'orange_stained_glass_pane' | 'magenta_stained_glass_pane' | 'light_blue_stained_glass_pane' | 'yellow_stained_glass_pane' | 'lime_stained_glass_pane' | 'pink_stained_glass_pane' | 'gray_stained_glass_pane' | 'light_gray_stained_glass_pane' | 'cyan_stained_glass_pane' | 'purple_stained_glass_pane' | 'blue_stained_glass_pane' | 'brown_stained_glass_pane' | 'green_stained_glass_pane' | 'red_stained_glass_pane' | 'black_stained_glass_pane' | 'acacia_stairs' | 'cherry_stairs' | 'dark_oak_stairs' | 'mangrove_stairs' | 'bamboo_stairs' | 'bamboo_mosaic_stairs' | 'slime_block' | 'barrier' | 'light' | 'iron_trapdoor' | 'prismarine' | 'prismarine_bricks' | 'dark_prismarine' | 'prismarine_stairs' | 'prismarine_brick_stairs' | 'dark_prismarine_stairs' | 'prismarine_slab' | 'prismarine_brick_slab' | 'dark_prismarine_slab' | 'sea_lantern' | 'hay_block' | 'white_carpet' | 'orange_carpet' | 'magenta_carpet' | 'light_blue_carpet' | 'yellow_carpet' | 'lime_carpet' | 'pink_carpet' | 'gray_carpet' | 'light_gray_carpet' | 'cyan_carpet' | 'purple_carpet' | 'blue_carpet' | 'brown_carpet' | 'green_carpet' | 'red_carpet' | 'black_carpet' | 'terracotta' | 'coal_block' | 'packed_ice' | 'sunflower' | 'lilac' | 'rose_bush' | 'peony' | 'tall_grass' | 'large_fern' | 'white_banner' | 'orange_banner' | 'magenta_banner' | 'light_blue_banner' | 'yellow_banner' | 'lime_banner' | 'pink_banner' | 'gray_banner' | 'light_gray_banner' | 'cyan_banner' | 'purple_banner' | 'blue_banner' | 'brown_banner' | 'green_banner' | 'red_banner' | 'black_banner' | 'white_wall_banner' | 'orange_wall_banner' | 'magenta_wall_banner' | 'light_blue_wall_banner' | 'yellow_wall_banner' | 'lime_wall_banner' | 'pink_wall_banner' | 'gray_wall_banner' | 'light_gray_wall_banner' | 'cyan_wall_banner' | 'purple_wall_banner' | 'blue_wall_banner' | 'brown_wall_banner' | 'green_wall_banner' | 'red_wall_banner' | 'black_wall_banner' | 'red_sandstone' | 'chiseled_red_sandstone' | 'cut_red_sandstone' | 'red_sandstone_stairs' | 'oak_slab' | 'spruce_slab' | 'birch_slab' | 'jungle_slab' | 'acacia_slab' | 'cherry_slab' | 'dark_oak_slab' | 'mangrove_slab' | 'bamboo_slab' | 'bamboo_mosaic_slab' | 'stone_slab' | 'smooth_stone_slab' | 'sandstone_slab' | 'cut_sandstone_slab' | 'petrified_oak_slab' | 'cobblestone_slab' | 'brick_slab' | 'stone_brick_slab' | 'mud_brick_slab' | 'nether_brick_slab' | 'quartz_slab' | 'red_sandstone_slab' | 'cut_red_sandstone_slab' | 'purpur_slab' | 'smooth_stone' | 'smooth_sandstone' | 'smooth_quartz' | 'smooth_red_sandstone' | 'spruce_fence_gate' | 'birch_fence_gate' | 'jungle_fence_gate' | 'acacia_fence_gate' | 'cherry_fence_gate' | 'dark_oak_fence_gate' | 'mangrove_fence_gate' | 'bamboo_fence_gate' | 'spruce_fence' | 'birch_fence' | 'jungle_fence' | 'acacia_fence' | 'cherry_fence' | 'dark_oak_fence' | 'mangrove_fence' | 'bamboo_fence' | 'spruce_door' | 'birch_door' | 'jungle_door' | 'acacia_door' | 'cherry_door' | 'dark_oak_door' | 'mangrove_door' | 'bamboo_door' | 'end_rod' | 'chorus_plant' | 'chorus_flower' | 'purpur_block' | 'purpur_pillar' | 'purpur_stairs' | 'end_stone_bricks' | 'torchflower_crop' | 'pitcher_crop' | 'pitcher_plant' | 'beetroots' | 'dirt_path' | 'end_gateway' | 'repeating_command_block' | 'chain_command_block' | 'frosted_ice' | 'magma_block' | 'nether_wart_block' | 'red_nether_bricks' | 'bone_block' | 'structure_void' | 'observer' | 'shulker_box' | 'white_shulker_box' | 'orange_shulker_box' | 'magenta_shulker_box' | 'light_blue_shulker_box' | 'yellow_shulker_box' | 'lime_shulker_box' | 'pink_shulker_box' | 'gray_shulker_box' | 'light_gray_shulker_box' | 'cyan_shulker_box' | 'purple_shulker_box' | 'blue_shulker_box' | 'brown_shulker_box' | 'green_shulker_box' | 'red_shulker_box' | 'black_shulker_box' | 'white_glazed_terracotta' | 'orange_glazed_terracotta' | 'magenta_glazed_terracotta' | 'light_blue_glazed_terracotta' | 'yellow_glazed_terracotta' | 'lime_glazed_terracotta' | 'pink_glazed_terracotta' | 'gray_glazed_terracotta' | 'light_gray_glazed_terracotta' | 'cyan_glazed_terracotta' | 'purple_glazed_terracotta' | 'blue_glazed_terracotta' | 'brown_glazed_terracotta' | 'green_glazed_terracotta' | 'red_glazed_terracotta' | 'black_glazed_terracotta' | 'white_concrete' | 'orange_concrete' | 'magenta_concrete' | 'light_blue_concrete' | 'yellow_concrete' | 'lime_concrete' | 'pink_concrete' | 'gray_concrete' | 'light_gray_concrete' | 'cyan_concrete' | 'purple_concrete' | 'blue_concrete' | 'brown_concrete' | 'green_concrete' | 'red_concrete' | 'black_concrete' | 'white_concrete_powder' | 'orange_concrete_powder' | 'magenta_concrete_powder' | 'light_blue_concrete_powder' | 'yellow_concrete_powder' | 'lime_concrete_powder' | 'pink_concrete_powder' | 'gray_concrete_powder' | 'light_gray_concrete_powder' | 'cyan_concrete_powder' | 'purple_concrete_powder' | 'blue_concrete_powder' | 'brown_concrete_powder' | 'green_concrete_powder' | 'red_concrete_powder' | 'black_concrete_powder' | 'kelp' | 'kelp_plant' | 'dried_kelp_block' | 'turtle_egg' | 'sniffer_egg' | 'dead_tube_coral_block' | 'dead_brain_coral_block' | 'dead_bubble_coral_block' | 'dead_fire_coral_block' | 'dead_horn_coral_block' | 'tube_coral_block' | 'brain_coral_block' | 'bubble_coral_block' | 'fire_coral_block' | 'horn_coral_block' | 'dead_tube_coral' | 'dead_brain_coral' | 'dead_bubble_coral' | 'dead_fire_coral' | 'dead_horn_coral' | 'tube_coral' | 'brain_coral' | 'bubble_coral' | 'fire_coral' | 'horn_coral' | 'dead_tube_coral_fan' | 'dead_brain_coral_fan' | 'dead_bubble_coral_fan' | 'dead_fire_coral_fan' | 'dead_horn_coral_fan' | 'tube_coral_fan' | 'brain_coral_fan' | 'bubble_coral_fan' | 'fire_coral_fan' | 'horn_coral_fan' | 'dead_tube_coral_wall_fan' | 'dead_brain_coral_wall_fan' | 'dead_bubble_coral_wall_fan' | 'dead_fire_coral_wall_fan' | 'dead_horn_coral_wall_fan' | 'tube_coral_wall_fan' | 'brain_coral_wall_fan' | 'bubble_coral_wall_fan' | 'fire_coral_wall_fan' | 'horn_coral_wall_fan' | 'sea_pickle' | 'blue_ice' | 'conduit' | 'bamboo_sapling' | 'bamboo' | 'potted_bamboo' | 'void_air' | 'cave_air' | 'bubble_column' | 'polished_granite_stairs' | 'smooth_red_sandstone_stairs' | 'mossy_stone_brick_stairs' | 'polished_diorite_stairs' | 'mossy_cobblestone_stairs' | 'end_stone_brick_stairs' | 'stone_stairs' | 'smooth_sandstone_stairs' | 'smooth_quartz_stairs' | 'granite_stairs' | 'andesite_stairs' | 'red_nether_brick_stairs' | 'polished_andesite_stairs' | 'diorite_stairs' | 'polished_granite_slab' | 'smooth_red_sandstone_slab' | 'mossy_stone_brick_slab' | 'polished_diorite_slab' | 'mossy_cobblestone_slab' | 'end_stone_brick_slab' | 'smooth_sandstone_slab' | 'smooth_quartz_slab' | 'granite_slab' | 'andesite_slab' | 'red_nether_brick_slab' | 'polished_andesite_slab' | 'diorite_slab' | 'brick_wall' | 'prismarine_wall' | 'red_sandstone_wall' | 'mossy_stone_brick_wall' | 'granite_wall' | 'stone_brick_wall' | 'mud_brick_wall' | 'nether_brick_wall' | 'andesite_wall' | 'red_nether_brick_wall' | 'sandstone_wall' | 'end_stone_brick_wall' | 'diorite_wall' | 'scaffolding' | 'loom' | 'barrel' | 'smoker' | 'blast_furnace' | 'cartography_table' | 'fletching_table' | 'grindstone' | 'lectern' | 'smithing_table' | 'stonecutter' | 'bell' | 'lantern' | 'soul_lantern' | 'campfire' | 'soul_campfire' | 'sweet_berry_bush' | 'warped_stem' | 'stripped_warped_stem' | 'warped_hyphae' | 'stripped_warped_hyphae' | 'warped_nylium' | 'warped_fungus' | 'warped_wart_block' | 'warped_roots' | 'nether_sprouts' | 'crimson_stem' | 'stripped_crimson_stem' | 'crimson_hyphae' | 'stripped_crimson_hyphae' | 'crimson_nylium' | 'crimson_fungus' | 'shroomlight' | 'weeping_vines' | 'weeping_vines_plant' | 'twisting_vines' | 'twisting_vines_plant' | 'crimson_roots' | 'crimson_planks' | 'warped_planks' | 'crimson_slab' | 'warped_slab' | 'crimson_pressure_plate' | 'warped_pressure_plate' | 'crimson_fence' | 'warped_fence' | 'crimson_trapdoor' | 'warped_trapdoor' | 'crimson_fence_gate' | 'warped_fence_gate' | 'crimson_stairs' | 'warped_stairs' | 'crimson_button' | 'warped_button' | 'crimson_door' | 'warped_door' | 'crimson_sign' | 'warped_sign' | 'crimson_wall_sign' | 'warped_wall_sign' | 'structure_block' | 'jigsaw' | 'composter' | 'target' | 'bee_nest' | 'beehive' | 'honey_block' | 'honeycomb_block' | 'netherite_block' | 'ancient_debris' | 'crying_obsidian' | 'respawn_anchor' | 'potted_crimson_fungus' | 'potted_warped_fungus' | 'potted_crimson_roots' | 'potted_warped_roots' | 'lodestone' | 'blackstone' | 'blackstone_stairs' | 'blackstone_wall' | 'blackstone_slab' | 'polished_blackstone' | 'polished_blackstone_bricks' | 'cracked_polished_blackstone_bricks' | 'chiseled_polished_blackstone' | 'polished_blackstone_brick_slab' | 'polished_blackstone_brick_stairs' | 'polished_blackstone_brick_wall' | 'gilded_blackstone' | 'polished_blackstone_stairs' | 'polished_blackstone_slab' | 'polished_blackstone_pressure_plate' | 'polished_blackstone_button' | 'polished_blackstone_wall' | 'chiseled_nether_bricks' | 'cracked_nether_bricks' | 'quartz_bricks' | 'candle' | 'white_candle' | 'orange_candle' | 'magenta_candle' | 'light_blue_candle' | 'yellow_candle' | 'lime_candle' | 'pink_candle' | 'gray_candle' | 'light_gray_candle' | 'cyan_candle' | 'purple_candle' | 'blue_candle' | 'brown_candle' | 'green_candle' | 'red_candle' | 'black_candle' | 'candle_cake' | 'white_candle_cake' | 'orange_candle_cake' | 'magenta_candle_cake' | 'light_blue_candle_cake' | 'yellow_candle_cake' | 'lime_candle_cake' | 'pink_candle_cake' | 'gray_candle_cake' | 'light_gray_candle_cake' | 'cyan_candle_cake' | 'purple_candle_cake' | 'blue_candle_cake' | 'brown_candle_cake' | 'green_candle_cake' | 'red_candle_cake' | 'black_candle_cake' | 'amethyst_block' | 'budding_amethyst' | 'amethyst_cluster' | 'large_amethyst_bud' | 'medium_amethyst_bud' | 'small_amethyst_bud' | 'tuff' | 'calcite' | 'tinted_glass' | 'powder_snow' | 'sculk_sensor' | 'calibrated_sculk_sensor' | 'sculk' | 'sculk_vein' | 'sculk_catalyst' | 'sculk_shrieker' | 'oxidized_copper' | 'weathered_copper' | 'exposed_copper' | 'copper_block' | 'copper_ore' | 'deepslate_copper_ore' | 'oxidized_cut_copper' | 'weathered_cut_copper' | 'exposed_cut_copper' | 'cut_copper' | 'oxidized_cut_copper_stairs' | 'weathered_cut_copper_stairs' | 'exposed_cut_copper_stairs' | 'cut_copper_stairs' | 'oxidized_cut_copper_slab' | 'weathered_cut_copper_slab' | 'exposed_cut_copper_slab' | 'cut_copper_slab' | 'waxed_copper_block' | 'waxed_weathered_copper' | 'waxed_exposed_copper' | 'waxed_oxidized_copper' | 'waxed_oxidized_cut_copper' | 'waxed_weathered_cut_copper' | 'waxed_exposed_cut_copper' | 'waxed_cut_copper' | 'waxed_oxidized_cut_copper_stairs' | 'waxed_weathered_cut_copper_stairs' | 'waxed_exposed_cut_copper_stairs' | 'waxed_cut_copper_stairs' | 'waxed_oxidized_cut_copper_slab' | 'waxed_weathered_cut_copper_slab' | 'waxed_exposed_cut_copper_slab' | 'waxed_cut_copper_slab' | 'lightning_rod' | 'pointed_dripstone' | 'dripstone_block' | 'cave_vines' | 'cave_vines_plant' | 'spore_blossom' | 'azalea' | 'flowering_azalea' | 'moss_carpet' | 'pink_petals' | 'moss_block' | 'big_dripleaf' | 'big_dripleaf_stem' | 'small_dripleaf' | 'hanging_roots' | 'rooted_dirt' | 'mud' | 'deepslate' | 'cobbled_deepslate' | 'cobbled_deepslate_stairs' | 'cobbled_deepslate_slab' | 'cobbled_deepslate_wall' | 'polished_deepslate' | 'polished_deepslate_stairs' | 'polished_deepslate_slab' | 'polished_deepslate_wall' | 'deepslate_tiles' | 'deepslate_tile_stairs' | 'deepslate_tile_slab' | 'deepslate_tile_wall' | 'deepslate_bricks' | 'deepslate_brick_stairs' | 'deepslate_brick_slab' | 'deepslate_brick_wall' | 'chiseled_deepslate' | 'cracked_deepslate_bricks' | 'cracked_deepslate_tiles' | 'infested_deepslate' | 'smooth_basalt' | 'raw_iron_block' | 'raw_copper_block' | 'raw_gold_block' | 'potted_azalea_bush' | 'potted_flowering_azalea_bush' | 'ochre_froglight' | 'verdant_froglight' | 'pearlescent_froglight' | 'frogspawn' | 'reinforced_deepslate' | 'decorated_pot'; +export type ItemNames = 'air' | 'stone' | 'granite' | 'polished_granite' | 'diorite' | 'polished_diorite' | 'andesite' | 'polished_andesite' | 'deepslate' | 'cobbled_deepslate' | 'polished_deepslate' | 'calcite' | 'tuff' | 'dripstone_block' | 'grass_block' | 'dirt' | 'coarse_dirt' | 'podzol' | 'rooted_dirt' | 'mud' | 'crimson_nylium' | 'warped_nylium' | 'cobblestone' | 'oak_planks' | 'spruce_planks' | 'birch_planks' | 'jungle_planks' | 'acacia_planks' | 'cherry_planks' | 'dark_oak_planks' | 'mangrove_planks' | 'bamboo_planks' | 'crimson_planks' | 'warped_planks' | 'bamboo_mosaic' | 'oak_sapling' | 'spruce_sapling' | 'birch_sapling' | 'jungle_sapling' | 'acacia_sapling' | 'cherry_sapling' | 'dark_oak_sapling' | 'mangrove_propagule' | 'bedrock' | 'sand' | 'suspicious_sand' | 'suspicious_gravel' | 'red_sand' | 'gravel' | 'coal_ore' | 'deepslate_coal_ore' | 'iron_ore' | 'deepslate_iron_ore' | 'copper_ore' | 'deepslate_copper_ore' | 'gold_ore' | 'deepslate_gold_ore' | 'redstone_ore' | 'deepslate_redstone_ore' | 'emerald_ore' | 'deepslate_emerald_ore' | 'lapis_ore' | 'deepslate_lapis_ore' | 'diamond_ore' | 'deepslate_diamond_ore' | 'nether_gold_ore' | 'nether_quartz_ore' | 'ancient_debris' | 'coal_block' | 'raw_iron_block' | 'raw_copper_block' | 'raw_gold_block' | 'amethyst_block' | 'budding_amethyst' | 'iron_block' | 'copper_block' | 'gold_block' | 'diamond_block' | 'netherite_block' | 'exposed_copper' | 'weathered_copper' | 'oxidized_copper' | 'cut_copper' | 'exposed_cut_copper' | 'weathered_cut_copper' | 'oxidized_cut_copper' | 'cut_copper_stairs' | 'exposed_cut_copper_stairs' | 'weathered_cut_copper_stairs' | 'oxidized_cut_copper_stairs' | 'cut_copper_slab' | 'exposed_cut_copper_slab' | 'weathered_cut_copper_slab' | 'oxidized_cut_copper_slab' | 'waxed_copper_block' | 'waxed_exposed_copper' | 'waxed_weathered_copper' | 'waxed_oxidized_copper' | 'waxed_cut_copper' | 'waxed_exposed_cut_copper' | 'waxed_weathered_cut_copper' | 'waxed_oxidized_cut_copper' | 'waxed_cut_copper_stairs' | 'waxed_exposed_cut_copper_stairs' | 'waxed_weathered_cut_copper_stairs' | 'waxed_oxidized_cut_copper_stairs' | 'waxed_cut_copper_slab' | 'waxed_exposed_cut_copper_slab' | 'waxed_weathered_cut_copper_slab' | 'waxed_oxidized_cut_copper_slab' | 'oak_log' | 'spruce_log' | 'birch_log' | 'jungle_log' | 'acacia_log' | 'cherry_log' | 'dark_oak_log' | 'mangrove_log' | 'mangrove_roots' | 'muddy_mangrove_roots' | 'crimson_stem' | 'warped_stem' | 'bamboo_block' | 'stripped_oak_log' | 'stripped_spruce_log' | 'stripped_birch_log' | 'stripped_jungle_log' | 'stripped_acacia_log' | 'stripped_cherry_log' | 'stripped_dark_oak_log' | 'stripped_mangrove_log' | 'stripped_crimson_stem' | 'stripped_warped_stem' | 'stripped_oak_wood' | 'stripped_spruce_wood' | 'stripped_birch_wood' | 'stripped_jungle_wood' | 'stripped_acacia_wood' | 'stripped_cherry_wood' | 'stripped_dark_oak_wood' | 'stripped_mangrove_wood' | 'stripped_crimson_hyphae' | 'stripped_warped_hyphae' | 'stripped_bamboo_block' | 'oak_wood' | 'spruce_wood' | 'birch_wood' | 'jungle_wood' | 'acacia_wood' | 'cherry_wood' | 'dark_oak_wood' | 'mangrove_wood' | 'crimson_hyphae' | 'warped_hyphae' | 'oak_leaves' | 'spruce_leaves' | 'birch_leaves' | 'jungle_leaves' | 'acacia_leaves' | 'cherry_leaves' | 'dark_oak_leaves' | 'mangrove_leaves' | 'azalea_leaves' | 'flowering_azalea_leaves' | 'sponge' | 'wet_sponge' | 'glass' | 'tinted_glass' | 'lapis_block' | 'sandstone' | 'chiseled_sandstone' | 'cut_sandstone' | 'cobweb' | 'grass' | 'fern' | 'azalea' | 'flowering_azalea' | 'dead_bush' | 'seagrass' | 'sea_pickle' | 'white_wool' | 'orange_wool' | 'magenta_wool' | 'light_blue_wool' | 'yellow_wool' | 'lime_wool' | 'pink_wool' | 'gray_wool' | 'light_gray_wool' | 'cyan_wool' | 'purple_wool' | 'blue_wool' | 'brown_wool' | 'green_wool' | 'red_wool' | 'black_wool' | 'dandelion' | 'poppy' | 'blue_orchid' | 'allium' | 'azure_bluet' | 'red_tulip' | 'orange_tulip' | 'white_tulip' | 'pink_tulip' | 'oxeye_daisy' | 'cornflower' | 'lily_of_the_valley' | 'wither_rose' | 'torchflower' | 'pitcher_plant' | 'spore_blossom' | 'brown_mushroom' | 'red_mushroom' | 'crimson_fungus' | 'warped_fungus' | 'crimson_roots' | 'warped_roots' | 'nether_sprouts' | 'weeping_vines' | 'twisting_vines' | 'sugar_cane' | 'kelp' | 'moss_carpet' | 'pink_petals' | 'moss_block' | 'hanging_roots' | 'big_dripleaf' | 'small_dripleaf' | 'bamboo' | 'oak_slab' | 'spruce_slab' | 'birch_slab' | 'jungle_slab' | 'acacia_slab' | 'cherry_slab' | 'dark_oak_slab' | 'mangrove_slab' | 'bamboo_slab' | 'bamboo_mosaic_slab' | 'crimson_slab' | 'warped_slab' | 'stone_slab' | 'smooth_stone_slab' | 'sandstone_slab' | 'cut_sandstone_slab' | 'petrified_oak_slab' | 'cobblestone_slab' | 'brick_slab' | 'stone_brick_slab' | 'mud_brick_slab' | 'nether_brick_slab' | 'quartz_slab' | 'red_sandstone_slab' | 'cut_red_sandstone_slab' | 'purpur_slab' | 'prismarine_slab' | 'prismarine_brick_slab' | 'dark_prismarine_slab' | 'smooth_quartz' | 'smooth_red_sandstone' | 'smooth_sandstone' | 'smooth_stone' | 'bricks' | 'bookshelf' | 'chiseled_bookshelf' | 'decorated_pot' | 'mossy_cobblestone' | 'obsidian' | 'torch' | 'end_rod' | 'chorus_plant' | 'chorus_flower' | 'purpur_block' | 'purpur_pillar' | 'purpur_stairs' | 'spawner' | 'chest' | 'crafting_table' | 'farmland' | 'furnace' | 'ladder' | 'cobblestone_stairs' | 'snow' | 'ice' | 'snow_block' | 'cactus' | 'clay' | 'jukebox' | 'oak_fence' | 'spruce_fence' | 'birch_fence' | 'jungle_fence' | 'acacia_fence' | 'cherry_fence' | 'dark_oak_fence' | 'mangrove_fence' | 'bamboo_fence' | 'crimson_fence' | 'warped_fence' | 'pumpkin' | 'carved_pumpkin' | 'jack_o_lantern' | 'netherrack' | 'soul_sand' | 'soul_soil' | 'basalt' | 'polished_basalt' | 'smooth_basalt' | 'soul_torch' | 'glowstone' | 'infested_stone' | 'infested_cobblestone' | 'infested_stone_bricks' | 'infested_mossy_stone_bricks' | 'infested_cracked_stone_bricks' | 'infested_chiseled_stone_bricks' | 'infested_deepslate' | 'stone_bricks' | 'mossy_stone_bricks' | 'cracked_stone_bricks' | 'chiseled_stone_bricks' | 'packed_mud' | 'mud_bricks' | 'deepslate_bricks' | 'cracked_deepslate_bricks' | 'deepslate_tiles' | 'cracked_deepslate_tiles' | 'chiseled_deepslate' | 'reinforced_deepslate' | 'brown_mushroom_block' | 'red_mushroom_block' | 'mushroom_stem' | 'iron_bars' | 'chain' | 'glass_pane' | 'melon' | 'vine' | 'glow_lichen' | 'brick_stairs' | 'stone_brick_stairs' | 'mud_brick_stairs' | 'mycelium' | 'lily_pad' | 'nether_bricks' | 'cracked_nether_bricks' | 'chiseled_nether_bricks' | 'nether_brick_fence' | 'nether_brick_stairs' | 'sculk' | 'sculk_vein' | 'sculk_catalyst' | 'sculk_shrieker' | 'enchanting_table' | 'end_portal_frame' | 'end_stone' | 'end_stone_bricks' | 'dragon_egg' | 'sandstone_stairs' | 'ender_chest' | 'emerald_block' | 'oak_stairs' | 'spruce_stairs' | 'birch_stairs' | 'jungle_stairs' | 'acacia_stairs' | 'cherry_stairs' | 'dark_oak_stairs' | 'mangrove_stairs' | 'bamboo_stairs' | 'bamboo_mosaic_stairs' | 'crimson_stairs' | 'warped_stairs' | 'command_block' | 'beacon' | 'cobblestone_wall' | 'mossy_cobblestone_wall' | 'brick_wall' | 'prismarine_wall' | 'red_sandstone_wall' | 'mossy_stone_brick_wall' | 'granite_wall' | 'stone_brick_wall' | 'mud_brick_wall' | 'nether_brick_wall' | 'andesite_wall' | 'red_nether_brick_wall' | 'sandstone_wall' | 'end_stone_brick_wall' | 'diorite_wall' | 'blackstone_wall' | 'polished_blackstone_wall' | 'polished_blackstone_brick_wall' | 'cobbled_deepslate_wall' | 'polished_deepslate_wall' | 'deepslate_brick_wall' | 'deepslate_tile_wall' | 'anvil' | 'chipped_anvil' | 'damaged_anvil' | 'chiseled_quartz_block' | 'quartz_block' | 'quartz_bricks' | 'quartz_pillar' | 'quartz_stairs' | 'white_terracotta' | 'orange_terracotta' | 'magenta_terracotta' | 'light_blue_terracotta' | 'yellow_terracotta' | 'lime_terracotta' | 'pink_terracotta' | 'gray_terracotta' | 'light_gray_terracotta' | 'cyan_terracotta' | 'purple_terracotta' | 'blue_terracotta' | 'brown_terracotta' | 'green_terracotta' | 'red_terracotta' | 'black_terracotta' | 'barrier' | 'light' | 'hay_block' | 'white_carpet' | 'orange_carpet' | 'magenta_carpet' | 'light_blue_carpet' | 'yellow_carpet' | 'lime_carpet' | 'pink_carpet' | 'gray_carpet' | 'light_gray_carpet' | 'cyan_carpet' | 'purple_carpet' | 'blue_carpet' | 'brown_carpet' | 'green_carpet' | 'red_carpet' | 'black_carpet' | 'terracotta' | 'packed_ice' | 'dirt_path' | 'sunflower' | 'lilac' | 'rose_bush' | 'peony' | 'tall_grass' | 'large_fern' | 'white_stained_glass' | 'orange_stained_glass' | 'magenta_stained_glass' | 'light_blue_stained_glass' | 'yellow_stained_glass' | 'lime_stained_glass' | 'pink_stained_glass' | 'gray_stained_glass' | 'light_gray_stained_glass' | 'cyan_stained_glass' | 'purple_stained_glass' | 'blue_stained_glass' | 'brown_stained_glass' | 'green_stained_glass' | 'red_stained_glass' | 'black_stained_glass' | 'white_stained_glass_pane' | 'orange_stained_glass_pane' | 'magenta_stained_glass_pane' | 'light_blue_stained_glass_pane' | 'yellow_stained_glass_pane' | 'lime_stained_glass_pane' | 'pink_stained_glass_pane' | 'gray_stained_glass_pane' | 'light_gray_stained_glass_pane' | 'cyan_stained_glass_pane' | 'purple_stained_glass_pane' | 'blue_stained_glass_pane' | 'brown_stained_glass_pane' | 'green_stained_glass_pane' | 'red_stained_glass_pane' | 'black_stained_glass_pane' | 'prismarine' | 'prismarine_bricks' | 'dark_prismarine' | 'prismarine_stairs' | 'prismarine_brick_stairs' | 'dark_prismarine_stairs' | 'sea_lantern' | 'red_sandstone' | 'chiseled_red_sandstone' | 'cut_red_sandstone' | 'red_sandstone_stairs' | 'repeating_command_block' | 'chain_command_block' | 'magma_block' | 'nether_wart_block' | 'warped_wart_block' | 'red_nether_bricks' | 'bone_block' | 'structure_void' | 'shulker_box' | 'white_shulker_box' | 'orange_shulker_box' | 'magenta_shulker_box' | 'light_blue_shulker_box' | 'yellow_shulker_box' | 'lime_shulker_box' | 'pink_shulker_box' | 'gray_shulker_box' | 'light_gray_shulker_box' | 'cyan_shulker_box' | 'purple_shulker_box' | 'blue_shulker_box' | 'brown_shulker_box' | 'green_shulker_box' | 'red_shulker_box' | 'black_shulker_box' | 'white_glazed_terracotta' | 'orange_glazed_terracotta' | 'magenta_glazed_terracotta' | 'light_blue_glazed_terracotta' | 'yellow_glazed_terracotta' | 'lime_glazed_terracotta' | 'pink_glazed_terracotta' | 'gray_glazed_terracotta' | 'light_gray_glazed_terracotta' | 'cyan_glazed_terracotta' | 'purple_glazed_terracotta' | 'blue_glazed_terracotta' | 'brown_glazed_terracotta' | 'green_glazed_terracotta' | 'red_glazed_terracotta' | 'black_glazed_terracotta' | 'white_concrete' | 'orange_concrete' | 'magenta_concrete' | 'light_blue_concrete' | 'yellow_concrete' | 'lime_concrete' | 'pink_concrete' | 'gray_concrete' | 'light_gray_concrete' | 'cyan_concrete' | 'purple_concrete' | 'blue_concrete' | 'brown_concrete' | 'green_concrete' | 'red_concrete' | 'black_concrete' | 'white_concrete_powder' | 'orange_concrete_powder' | 'magenta_concrete_powder' | 'light_blue_concrete_powder' | 'yellow_concrete_powder' | 'lime_concrete_powder' | 'pink_concrete_powder' | 'gray_concrete_powder' | 'light_gray_concrete_powder' | 'cyan_concrete_powder' | 'purple_concrete_powder' | 'blue_concrete_powder' | 'brown_concrete_powder' | 'green_concrete_powder' | 'red_concrete_powder' | 'black_concrete_powder' | 'turtle_egg' | 'sniffer_egg' | 'dead_tube_coral_block' | 'dead_brain_coral_block' | 'dead_bubble_coral_block' | 'dead_fire_coral_block' | 'dead_horn_coral_block' | 'tube_coral_block' | 'brain_coral_block' | 'bubble_coral_block' | 'fire_coral_block' | 'horn_coral_block' | 'tube_coral' | 'brain_coral' | 'bubble_coral' | 'fire_coral' | 'horn_coral' | 'dead_brain_coral' | 'dead_bubble_coral' | 'dead_fire_coral' | 'dead_horn_coral' | 'dead_tube_coral' | 'tube_coral_fan' | 'brain_coral_fan' | 'bubble_coral_fan' | 'fire_coral_fan' | 'horn_coral_fan' | 'dead_tube_coral_fan' | 'dead_brain_coral_fan' | 'dead_bubble_coral_fan' | 'dead_fire_coral_fan' | 'dead_horn_coral_fan' | 'blue_ice' | 'conduit' | 'polished_granite_stairs' | 'smooth_red_sandstone_stairs' | 'mossy_stone_brick_stairs' | 'polished_diorite_stairs' | 'mossy_cobblestone_stairs' | 'end_stone_brick_stairs' | 'stone_stairs' | 'smooth_sandstone_stairs' | 'smooth_quartz_stairs' | 'granite_stairs' | 'andesite_stairs' | 'red_nether_brick_stairs' | 'polished_andesite_stairs' | 'diorite_stairs' | 'cobbled_deepslate_stairs' | 'polished_deepslate_stairs' | 'deepslate_brick_stairs' | 'deepslate_tile_stairs' | 'polished_granite_slab' | 'smooth_red_sandstone_slab' | 'mossy_stone_brick_slab' | 'polished_diorite_slab' | 'mossy_cobblestone_slab' | 'end_stone_brick_slab' | 'smooth_sandstone_slab' | 'smooth_quartz_slab' | 'granite_slab' | 'andesite_slab' | 'red_nether_brick_slab' | 'polished_andesite_slab' | 'diorite_slab' | 'cobbled_deepslate_slab' | 'polished_deepslate_slab' | 'deepslate_brick_slab' | 'deepslate_tile_slab' | 'scaffolding' | 'redstone' | 'redstone_torch' | 'redstone_block' | 'repeater' | 'comparator' | 'piston' | 'sticky_piston' | 'slime_block' | 'honey_block' | 'observer' | 'hopper' | 'dispenser' | 'dropper' | 'lectern' | 'target' | 'lever' | 'lightning_rod' | 'daylight_detector' | 'sculk_sensor' | 'calibrated_sculk_sensor' | 'tripwire_hook' | 'trapped_chest' | 'tnt' | 'redstone_lamp' | 'note_block' | 'stone_button' | 'polished_blackstone_button' | 'oak_button' | 'spruce_button' | 'birch_button' | 'jungle_button' | 'acacia_button' | 'cherry_button' | 'dark_oak_button' | 'mangrove_button' | 'bamboo_button' | 'crimson_button' | 'warped_button' | 'stone_pressure_plate' | 'polished_blackstone_pressure_plate' | 'light_weighted_pressure_plate' | 'heavy_weighted_pressure_plate' | 'oak_pressure_plate' | 'spruce_pressure_plate' | 'birch_pressure_plate' | 'jungle_pressure_plate' | 'acacia_pressure_plate' | 'cherry_pressure_plate' | 'dark_oak_pressure_plate' | 'mangrove_pressure_plate' | 'bamboo_pressure_plate' | 'crimson_pressure_plate' | 'warped_pressure_plate' | 'iron_door' | 'oak_door' | 'spruce_door' | 'birch_door' | 'jungle_door' | 'acacia_door' | 'cherry_door' | 'dark_oak_door' | 'mangrove_door' | 'bamboo_door' | 'crimson_door' | 'warped_door' | 'iron_trapdoor' | 'oak_trapdoor' | 'spruce_trapdoor' | 'birch_trapdoor' | 'jungle_trapdoor' | 'acacia_trapdoor' | 'cherry_trapdoor' | 'dark_oak_trapdoor' | 'mangrove_trapdoor' | 'bamboo_trapdoor' | 'crimson_trapdoor' | 'warped_trapdoor' | 'oak_fence_gate' | 'spruce_fence_gate' | 'birch_fence_gate' | 'jungle_fence_gate' | 'acacia_fence_gate' | 'cherry_fence_gate' | 'dark_oak_fence_gate' | 'mangrove_fence_gate' | 'bamboo_fence_gate' | 'crimson_fence_gate' | 'warped_fence_gate' | 'powered_rail' | 'detector_rail' | 'rail' | 'activator_rail' | 'saddle' | 'minecart' | 'chest_minecart' | 'furnace_minecart' | 'tnt_minecart' | 'hopper_minecart' | 'carrot_on_a_stick' | 'warped_fungus_on_a_stick' | 'elytra' | 'oak_boat' | 'oak_chest_boat' | 'spruce_boat' | 'spruce_chest_boat' | 'birch_boat' | 'birch_chest_boat' | 'jungle_boat' | 'jungle_chest_boat' | 'acacia_boat' | 'acacia_chest_boat' | 'cherry_boat' | 'cherry_chest_boat' | 'dark_oak_boat' | 'dark_oak_chest_boat' | 'mangrove_boat' | 'mangrove_chest_boat' | 'bamboo_raft' | 'bamboo_chest_raft' | 'structure_block' | 'jigsaw' | 'turtle_helmet' | 'scute' | 'flint_and_steel' | 'apple' | 'bow' | 'arrow' | 'coal' | 'charcoal' | 'diamond' | 'emerald' | 'lapis_lazuli' | 'quartz' | 'amethyst_shard' | 'raw_iron' | 'iron_ingot' | 'raw_copper' | 'copper_ingot' | 'raw_gold' | 'gold_ingot' | 'netherite_ingot' | 'netherite_scrap' | 'wooden_sword' | 'wooden_shovel' | 'wooden_pickaxe' | 'wooden_axe' | 'wooden_hoe' | 'stone_sword' | 'stone_shovel' | 'stone_pickaxe' | 'stone_axe' | 'stone_hoe' | 'golden_sword' | 'golden_shovel' | 'golden_pickaxe' | 'golden_axe' | 'golden_hoe' | 'iron_sword' | 'iron_shovel' | 'iron_pickaxe' | 'iron_axe' | 'iron_hoe' | 'diamond_sword' | 'diamond_shovel' | 'diamond_pickaxe' | 'diamond_axe' | 'diamond_hoe' | 'netherite_sword' | 'netherite_shovel' | 'netherite_pickaxe' | 'netherite_axe' | 'netherite_hoe' | 'stick' | 'bowl' | 'mushroom_stew' | 'string' | 'feather' | 'gunpowder' | 'wheat_seeds' | 'wheat' | 'bread' | 'leather_helmet' | 'leather_chestplate' | 'leather_leggings' | 'leather_boots' | 'chainmail_helmet' | 'chainmail_chestplate' | 'chainmail_leggings' | 'chainmail_boots' | 'iron_helmet' | 'iron_chestplate' | 'iron_leggings' | 'iron_boots' | 'diamond_helmet' | 'diamond_chestplate' | 'diamond_leggings' | 'diamond_boots' | 'golden_helmet' | 'golden_chestplate' | 'golden_leggings' | 'golden_boots' | 'netherite_helmet' | 'netherite_chestplate' | 'netherite_leggings' | 'netherite_boots' | 'flint' | 'porkchop' | 'cooked_porkchop' | 'painting' | 'golden_apple' | 'enchanted_golden_apple' | 'oak_sign' | 'spruce_sign' | 'birch_sign' | 'jungle_sign' | 'acacia_sign' | 'cherry_sign' | 'dark_oak_sign' | 'mangrove_sign' | 'bamboo_sign' | 'crimson_sign' | 'warped_sign' | 'oak_hanging_sign' | 'spruce_hanging_sign' | 'birch_hanging_sign' | 'jungle_hanging_sign' | 'acacia_hanging_sign' | 'cherry_hanging_sign' | 'dark_oak_hanging_sign' | 'mangrove_hanging_sign' | 'bamboo_hanging_sign' | 'crimson_hanging_sign' | 'warped_hanging_sign' | 'bucket' | 'water_bucket' | 'lava_bucket' | 'powder_snow_bucket' | 'snowball' | 'leather' | 'milk_bucket' | 'pufferfish_bucket' | 'salmon_bucket' | 'cod_bucket' | 'tropical_fish_bucket' | 'axolotl_bucket' | 'tadpole_bucket' | 'brick' | 'clay_ball' | 'dried_kelp_block' | 'paper' | 'book' | 'slime_ball' | 'egg' | 'compass' | 'recovery_compass' | 'bundle' | 'fishing_rod' | 'clock' | 'spyglass' | 'glowstone_dust' | 'cod' | 'salmon' | 'tropical_fish' | 'pufferfish' | 'cooked_cod' | 'cooked_salmon' | 'ink_sac' | 'glow_ink_sac' | 'cocoa_beans' | 'white_dye' | 'orange_dye' | 'magenta_dye' | 'light_blue_dye' | 'yellow_dye' | 'lime_dye' | 'pink_dye' | 'gray_dye' | 'light_gray_dye' | 'cyan_dye' | 'purple_dye' | 'blue_dye' | 'brown_dye' | 'green_dye' | 'red_dye' | 'black_dye' | 'bone_meal' | 'bone' | 'sugar' | 'cake' | 'white_bed' | 'orange_bed' | 'magenta_bed' | 'light_blue_bed' | 'yellow_bed' | 'lime_bed' | 'pink_bed' | 'gray_bed' | 'light_gray_bed' | 'cyan_bed' | 'purple_bed' | 'blue_bed' | 'brown_bed' | 'green_bed' | 'red_bed' | 'black_bed' | 'cookie' | 'filled_map' | 'shears' | 'melon_slice' | 'dried_kelp' | 'pumpkin_seeds' | 'melon_seeds' | 'beef' | 'cooked_beef' | 'chicken' | 'cooked_chicken' | 'rotten_flesh' | 'ender_pearl' | 'blaze_rod' | 'ghast_tear' | 'gold_nugget' | 'nether_wart' | 'potion' | 'glass_bottle' | 'spider_eye' | 'fermented_spider_eye' | 'blaze_powder' | 'magma_cream' | 'brewing_stand' | 'cauldron' | 'ender_eye' | 'glistering_melon_slice' | 'allay_spawn_egg' | 'axolotl_spawn_egg' | 'bat_spawn_egg' | 'bee_spawn_egg' | 'blaze_spawn_egg' | 'cat_spawn_egg' | 'camel_spawn_egg' | 'cave_spider_spawn_egg' | 'chicken_spawn_egg' | 'cod_spawn_egg' | 'cow_spawn_egg' | 'creeper_spawn_egg' | 'dolphin_spawn_egg' | 'donkey_spawn_egg' | 'drowned_spawn_egg' | 'elder_guardian_spawn_egg' | 'ender_dragon_spawn_egg' | 'enderman_spawn_egg' | 'endermite_spawn_egg' | 'evoker_spawn_egg' | 'fox_spawn_egg' | 'frog_spawn_egg' | 'ghast_spawn_egg' | 'glow_squid_spawn_egg' | 'goat_spawn_egg' | 'guardian_spawn_egg' | 'hoglin_spawn_egg' | 'horse_spawn_egg' | 'husk_spawn_egg' | 'iron_golem_spawn_egg' | 'llama_spawn_egg' | 'magma_cube_spawn_egg' | 'mooshroom_spawn_egg' | 'mule_spawn_egg' | 'ocelot_spawn_egg' | 'panda_spawn_egg' | 'parrot_spawn_egg' | 'phantom_spawn_egg' | 'pig_spawn_egg' | 'piglin_spawn_egg' | 'piglin_brute_spawn_egg' | 'pillager_spawn_egg' | 'polar_bear_spawn_egg' | 'pufferfish_spawn_egg' | 'rabbit_spawn_egg' | 'ravager_spawn_egg' | 'salmon_spawn_egg' | 'sheep_spawn_egg' | 'shulker_spawn_egg' | 'silverfish_spawn_egg' | 'skeleton_spawn_egg' | 'skeleton_horse_spawn_egg' | 'slime_spawn_egg' | 'sniffer_spawn_egg' | 'snow_golem_spawn_egg' | 'spider_spawn_egg' | 'squid_spawn_egg' | 'stray_spawn_egg' | 'strider_spawn_egg' | 'tadpole_spawn_egg' | 'trader_llama_spawn_egg' | 'tropical_fish_spawn_egg' | 'turtle_spawn_egg' | 'vex_spawn_egg' | 'villager_spawn_egg' | 'vindicator_spawn_egg' | 'wandering_trader_spawn_egg' | 'warden_spawn_egg' | 'witch_spawn_egg' | 'wither_spawn_egg' | 'wither_skeleton_spawn_egg' | 'wolf_spawn_egg' | 'zoglin_spawn_egg' | 'zombie_spawn_egg' | 'zombie_horse_spawn_egg' | 'zombie_villager_spawn_egg' | 'zombified_piglin_spawn_egg' | 'experience_bottle' | 'fire_charge' | 'writable_book' | 'written_book' | 'item_frame' | 'glow_item_frame' | 'flower_pot' | 'carrot' | 'potato' | 'baked_potato' | 'poisonous_potato' | 'map' | 'golden_carrot' | 'skeleton_skull' | 'wither_skeleton_skull' | 'player_head' | 'zombie_head' | 'creeper_head' | 'dragon_head' | 'piglin_head' | 'nether_star' | 'pumpkin_pie' | 'firework_rocket' | 'firework_star' | 'enchanted_book' | 'nether_brick' | 'prismarine_shard' | 'prismarine_crystals' | 'rabbit' | 'cooked_rabbit' | 'rabbit_stew' | 'rabbit_foot' | 'rabbit_hide' | 'armor_stand' | 'iron_horse_armor' | 'golden_horse_armor' | 'diamond_horse_armor' | 'leather_horse_armor' | 'lead' | 'name_tag' | 'command_block_minecart' | 'mutton' | 'cooked_mutton' | 'white_banner' | 'orange_banner' | 'magenta_banner' | 'light_blue_banner' | 'yellow_banner' | 'lime_banner' | 'pink_banner' | 'gray_banner' | 'light_gray_banner' | 'cyan_banner' | 'purple_banner' | 'blue_banner' | 'brown_banner' | 'green_banner' | 'red_banner' | 'black_banner' | 'end_crystal' | 'chorus_fruit' | 'popped_chorus_fruit' | 'torchflower_seeds' | 'pitcher_pod' | 'beetroot' | 'beetroot_seeds' | 'beetroot_soup' | 'dragon_breath' | 'splash_potion' | 'spectral_arrow' | 'tipped_arrow' | 'lingering_potion' | 'shield' | 'totem_of_undying' | 'shulker_shell' | 'iron_nugget' | 'knowledge_book' | 'debug_stick' | 'music_disc_13' | 'music_disc_cat' | 'music_disc_blocks' | 'music_disc_chirp' | 'music_disc_far' | 'music_disc_mall' | 'music_disc_mellohi' | 'music_disc_stal' | 'music_disc_strad' | 'music_disc_ward' | 'music_disc_11' | 'music_disc_wait' | 'music_disc_otherside' | 'music_disc_relic' | 'music_disc_5' | 'music_disc_pigstep' | 'disc_fragment_5' | 'trident' | 'phantom_membrane' | 'nautilus_shell' | 'heart_of_the_sea' | 'crossbow' | 'suspicious_stew' | 'loom' | 'flower_banner_pattern' | 'creeper_banner_pattern' | 'skull_banner_pattern' | 'mojang_banner_pattern' | 'globe_banner_pattern' | 'piglin_banner_pattern' | 'goat_horn' | 'composter' | 'barrel' | 'smoker' | 'blast_furnace' | 'cartography_table' | 'fletching_table' | 'grindstone' | 'smithing_table' | 'stonecutter' | 'bell' | 'lantern' | 'soul_lantern' | 'sweet_berries' | 'glow_berries' | 'campfire' | 'soul_campfire' | 'shroomlight' | 'honeycomb' | 'bee_nest' | 'beehive' | 'honey_bottle' | 'honeycomb_block' | 'lodestone' | 'crying_obsidian' | 'blackstone' | 'blackstone_slab' | 'blackstone_stairs' | 'gilded_blackstone' | 'polished_blackstone' | 'polished_blackstone_slab' | 'polished_blackstone_stairs' | 'chiseled_polished_blackstone' | 'polished_blackstone_bricks' | 'polished_blackstone_brick_slab' | 'polished_blackstone_brick_stairs' | 'cracked_polished_blackstone_bricks' | 'respawn_anchor' | 'candle' | 'white_candle' | 'orange_candle' | 'magenta_candle' | 'light_blue_candle' | 'yellow_candle' | 'lime_candle' | 'pink_candle' | 'gray_candle' | 'light_gray_candle' | 'cyan_candle' | 'purple_candle' | 'blue_candle' | 'brown_candle' | 'green_candle' | 'red_candle' | 'black_candle' | 'small_amethyst_bud' | 'medium_amethyst_bud' | 'large_amethyst_bud' | 'amethyst_cluster' | 'pointed_dripstone' | 'ochre_froglight' | 'verdant_froglight' | 'pearlescent_froglight' | 'frogspawn' | 'echo_shard' | 'brush' | 'netherite_upgrade_smithing_template' | 'sentry_armor_trim_smithing_template' | 'dune_armor_trim_smithing_template' | 'coast_armor_trim_smithing_template' | 'wild_armor_trim_smithing_template' | 'ward_armor_trim_smithing_template' | 'eye_armor_trim_smithing_template' | 'vex_armor_trim_smithing_template' | 'tide_armor_trim_smithing_template' | 'snout_armor_trim_smithing_template' | 'rib_armor_trim_smithing_template' | 'spire_armor_trim_smithing_template' | 'wayfinder_armor_trim_smithing_template' | 'shaper_armor_trim_smithing_template' | 'silence_armor_trim_smithing_template' | 'raiser_armor_trim_smithing_template' | 'host_armor_trim_smithing_template' | 'angler_pottery_sherd' | 'archer_pottery_sherd' | 'arms_up_pottery_sherd' | 'blade_pottery_sherd' | 'brewer_pottery_sherd' | 'burn_pottery_sherd' | 'danger_pottery_sherd' | 'explorer_pottery_sherd' | 'friend_pottery_sherd' | 'heart_pottery_sherd' | 'heartbreak_pottery_sherd' | 'howl_pottery_sherd' | 'miner_pottery_sherd' | 'mourner_pottery_sherd' | 'plenty_pottery_sherd' | 'prize_pottery_sherd' | 'sheaf_pottery_sherd' | 'shelter_pottery_sherd' | 'skull_pottery_sherd' | 'snort_pottery_sherd'; +export type EntityNames = 'allay' | 'area_effect_cloud' | 'armor_stand' | 'arrow' | 'axolotl' | 'bat' | 'bee' | 'blaze' | 'block_display' | 'boat' | 'camel' | 'cat' | 'cave_spider' | 'chest_boat' | 'chest_minecart' | 'chicken' | 'cod' | 'command_block_minecart' | 'cow' | 'creeper' | 'dolphin' | 'donkey' | 'dragon_fireball' | 'drowned' | 'egg' | 'elder_guardian' | 'end_crystal' | 'ender_dragon' | 'ender_pearl' | 'enderman' | 'endermite' | 'evoker' | 'evoker_fangs' | 'experience_bottle' | 'experience_orb' | 'eye_of_ender' | 'falling_block' | 'firework_rocket' | 'fox' | 'frog' | 'furnace_minecart' | 'ghast' | 'giant' | 'glow_item_frame' | 'glow_squid' | 'goat' | 'guardian' | 'hoglin' | 'hopper_minecart' | 'horse' | 'husk' | 'illusioner' | 'interaction' | 'iron_golem' | 'item' | 'item_display' | 'item_frame' | 'fireball' | 'leash_knot' | 'lightning_bolt' | 'llama' | 'llama_spit' | 'magma_cube' | 'marker' | 'minecart' | 'mooshroom' | 'mule' | 'ocelot' | 'painting' | 'panda' | 'parrot' | 'phantom' | 'pig' | 'piglin' | 'piglin_brute' | 'pillager' | 'polar_bear' | 'potion' | 'pufferfish' | 'rabbit' | 'ravager' | 'salmon' | 'sheep' | 'shulker' | 'shulker_bullet' | 'silverfish' | 'skeleton' | 'skeleton_horse' | 'slime' | 'small_fireball' | 'sniffer' | 'snow_golem' | 'snowball' | 'spawner_minecart' | 'spectral_arrow' | 'spider' | 'squid' | 'stray' | 'strider' | 'tadpole' | 'text_display' | 'tnt' | 'tnt_minecart' | 'trader_llama' | 'trident' | 'tropical_fish' | 'turtle' | 'vex' | 'villager' | 'vindicator' | 'wandering_trader' | 'warden' | 'witch' | 'wither' | 'wither_skeleton' | 'wither_skull' | 'wolf' | 'zoglin' | 'zombie' | 'zombie_horse' | 'zombie_villager' | 'zombified_piglin' | 'player' | 'fishing_bobber'; +export type BiomesNames = 'badlands' | 'bamboo_jungle' | 'basalt_deltas' | 'beach' | 'birch_forest' | 'cherry_grove' | 'cold_ocean' | 'crimson_forest' | 'dark_forest' | 'deep_cold_ocean' | 'deep_dark' | 'deep_frozen_ocean' | 'deep_lukewarm_ocean' | 'deep_ocean' | 'desert' | 'dripstone_caves' | 'end_barrens' | 'end_highlands' | 'end_midlands' | 'eroded_badlands' | 'flower_forest' | 'forest' | 'frozen_ocean' | 'frozen_peaks' | 'frozen_river' | 'grove' | 'ice_spikes' | 'jagged_peaks' | 'jungle' | 'lukewarm_ocean' | 'lush_caves' | 'mangrove_swamp' | 'meadow' | 'mushroom_fields' | 'nether_wastes' | 'ocean' | 'old_growth_birch_forest' | 'old_growth_pine_taiga' | 'old_growth_spruce_taiga' | 'plains' | 'river' | 'savanna' | 'savanna_plateau' | 'small_end_islands' | 'snowy_beach' | 'snowy_plains' | 'snowy_slopes' | 'snowy_taiga' | 'soul_sand_valley' | 'sparse_jungle' | 'stony_peaks' | 'stony_shore' | 'sunflower_plains' | 'swamp' | 'taiga' | 'the_end' | 'the_void' | 'warm_ocean' | 'warped_forest' | 'windswept_forest' | 'windswept_gravelly_hills' | 'windswept_hills' | 'windswept_savanna' | 'wooded_badlands'; +export type EnchantmentNames = 'protection' | 'fire_protection' | 'feather_falling' | 'blast_protection' | 'projectile_protection' | 'respiration' | 'aqua_affinity' | 'thorns' | 'depth_strider' | 'frost_walker' | 'binding_curse' | 'soul_speed' | 'swift_sneak' | 'sharpness' | 'smite' | 'bane_of_arthropods' | 'knockback' | 'fire_aspect' | 'looting' | 'sweeping' | 'efficiency' | 'silk_touch' | 'unbreaking' | 'fortune' | 'power' | 'punch' | 'flame' | 'infinity' | 'luck_of_the_sea' | 'lure' | 'loyalty' | 'impaling' | 'riptide' | 'channeling' | 'multishot' | 'quick_charge' | 'piercing' | 'mending' | 'vanishing_curse'; + +export type EntityMetadataVersions = { +'Mob': {},'Monster': {},'Creeper': {},'Skeleton': {},'Spider': {},'Giant': {},'Zombie': {},'Slime': {},'Ghast': {},'PigZombie': {},'Enderman': {},'CaveSpider': {},'Silverfish': {},'Blaze': {},'LavaSlime': {},'EnderDragon': {},'WitherBoss': {},'Bat': {},'Witch': {},'Endermite': {},'Guardian': {},'Pig': {},'Sheep': {},'Cow': {},'Chicken': {},'Squid': {},'Wolf': {},'MushroomCow': {},'SnowMan': {},'Ozelot': {},'VillagerGolem': {},'EntityHorse': {},'Rabbit': {},'Villager': {},'Boat': {},'Item': {},'MinecartRideable': {},'PrimedTnt': {},'EnderCrystal': {},'Arrow': {},'Snowball': {},'ThrownEgg': {},'Fireball': {},'SmallFireball': {},'ThrownEnderpearl': {},'WitherSkull': {},'FallingSand': {},'ItemFrame': {},'EyeOfEnderSignal': {},'ThrownPotion': {},'ThrownExpBottle': {},'FireworksRocketEntity': {},'LeashKnot': {},'ArmorStand': {},'Fishing Float': {},'Shulker': {},'XPOrb': {},'Dragon Fireball': {},'item': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'item': string;},'xp_orb': {},'area_effect_cloud': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'radius': string; +/** 1.19.4+ (9) */ +'color': string; +/** 1.19.4+ (10) */ +'waiting': string; +/** 1.19.4+ (11) */ +'particle': string;},'elder_guardian': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'moving': string; +/** 1.19.4+ (17) */ +'attack_target': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'wither_skeleton': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'stray': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'egg': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'item_stack': string;},'leash_knot': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string;},'painting': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'painting_variant': string;},'arrow': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'flags': string; +/** 1.19.4+ (9) */ +'pierce_level': string; +/** 1.19.4+ (10) */ +'effect_color': string;},'snowball': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'item_stack': string;},'fireball': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'item_stack': string;},'small_fireball': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'item_stack': string;},'ender_pearl': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'item_stack': string;},'eye_of_ender_signal': {},'potion': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'item_stack': string;},'xp_bottle': {},'item_frame': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'item': string; +/** 1.19.4+ (9) */ +'rotation': string;},'wither_skull': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'dangerous': string;},'tnt': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'fuse': string; +/** 1.20.3+ (9) */ +'block_state': string;},'falling_block': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'start_pos': string;},'fireworks_rocket': {},'husk': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'special_type': string; +/** 1.19.4+ (18) */ +'drowned_conversion': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'spectral_arrow': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'flags': string; +/** 1.19.4+ (9) */ +'pierce_level': string;},'shulker_bullet': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string;},'dragon_fireball': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string;},'zombie_villager': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'special_type': string; +/** 1.19.4+ (18) */ +'drowned_conversion': string; +/** 1.19.4+ (19) */ +'converting': string; +/** 1.19.4+ (20) */ +'villager_data': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'skeleton_horse': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'zombie_horse': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'armor_stand': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'client_flags': string; +/** 1.19.4+ (16) */ +'head_pose': string; +/** 1.19.4+ (17) */ +'body_pose': string; +/** 1.19.4+ (18) */ +'left_arm_pose': string; +/** 1.19.4+ (19) */ +'right_arm_pose': string; +/** 1.19.4+ (20) */ +'left_leg_pose': string; +/** 1.19.4+ (21) */ +'right_leg_pose': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'donkey': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'flags': string; +/** 1.19.4+ (18) */ +'chest': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'mule': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'flags': string; +/** 1.19.4+ (18) */ +'chest': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'evocation_fangs': {},'evocation_illager': {},'vex': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'vindication_illager': {},'commandblock_minecart': {},'boat': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'hurt': string; +/** 1.19.4+ (9) */ +'hurtdir': string; +/** 1.19.4+ (10) */ +'damage': string; +/** 1.19.4+ (11) */ +'type': string; +/** 1.19.4+ (12) */ +'paddle_left': string; +/** 1.19.4+ (13) */ +'paddle_right': string; +/** 1.19.4+ (14) */ +'bubble_time': string;},'minecart': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'hurt': string; +/** 1.19.4+ (9) */ +'hurtdir': string; +/** 1.19.4+ (10) */ +'damage': string; +/** 1.19.4+ (11) */ +'display_block': string; +/** 1.19.4+ (12) */ +'display_offset': string; +/** 1.19.4+ (13) */ +'custom_display': string;},'chest_minecart': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'hurt': string; +/** 1.19.4+ (9) */ +'hurtdir': string; +/** 1.19.4+ (10) */ +'damage': string; +/** 1.19.4+ (11) */ +'display_block': string; +/** 1.19.4+ (12) */ +'display_offset': string; +/** 1.19.4+ (13) */ +'custom_display': string;},'furnace_minecart': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'hurt': string; +/** 1.19.4+ (9) */ +'hurtdir': string; +/** 1.19.4+ (10) */ +'damage': string; +/** 1.19.4+ (11) */ +'display_block': string; +/** 1.19.4+ (12) */ +'display_offset': string; +/** 1.19.4+ (13) */ +'custom_display': string; +/** 1.19.4+ (14) */ +'fuel': string;},'tnt_minecart': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'hurt': string; +/** 1.19.4+ (9) */ +'hurtdir': string; +/** 1.19.4+ (10) */ +'damage': string; +/** 1.19.4+ (11) */ +'display_block': string; +/** 1.19.4+ (12) */ +'display_offset': string; +/** 1.19.4+ (13) */ +'custom_display': string;},'hopper_minecart': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'hurt': string; +/** 1.19.4+ (9) */ +'hurtdir': string; +/** 1.19.4+ (10) */ +'damage': string; +/** 1.19.4+ (11) */ +'display_block': string; +/** 1.19.4+ (12) */ +'display_offset': string; +/** 1.19.4+ (13) */ +'custom_display': string;},'spawner_minecart': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'hurt': string; +/** 1.19.4+ (9) */ +'hurtdir': string; +/** 1.19.4+ (10) */ +'damage': string; +/** 1.19.4+ (11) */ +'display_block': string; +/** 1.19.4+ (12) */ +'display_offset': string; +/** 1.19.4+ (13) */ +'custom_display': string;},'creeper': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'swell_dir': string; +/** 1.19.4+ (17) */ +'is_powered': string; +/** 1.19.4+ (18) */ +'is_ignited': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'skeleton': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'stray_conversion': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'spider': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'giant': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'zombie': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'special_type': string; +/** 1.19.4+ (18) */ +'drowned_conversion': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'slime': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'size': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'ghast': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'is_charging': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'zombie_pigman': {},'enderman': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'carry_state': string; +/** 1.19.4+ (17) */ +'creepy': string; +/** 1.19.4+ (18) */ +'stared_at': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'cave_spider': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'silverfish': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'blaze': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'magma_cube': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'size': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'ender_dragon': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'phase': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'wither': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'target_a': string; +/** 1.19.4+ (17) */ +'target_b': string; +/** 1.19.4+ (18) */ +'target_c': string; +/** 1.19.4+ (19) */ +'inv': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'bat': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'witch': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'is_celebrating': string; +/** 1.19.4+ (17) */ +'using_item': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'endermite': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'guardian': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'moving': string; +/** 1.19.4+ (17) */ +'attack_target': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'shulker': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'attach_face': string; +/** 1.19.4+ (17) */ +'peek': string; +/** 1.19.4+ (18) */ +'color': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'pig': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'saddle': string; +/** 1.19.4+ (18) */ +'boost_time': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'sheep': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'wool': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'cow': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'chicken': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'squid': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'wolf': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'flags': string; +/** 1.19.4+ (18) */ +'owneruuid': string; +/** 1.19.4+ (19) */ +'interested': string; +/** 1.19.4+ (20) */ +'collar_color': string; +/** 1.19.4+ (21) */ +'remaining_anger_time': string; +/** 1.20.5+ (10) */ +'effect_particles': string; +/** 1.20.5+ (22) */ +'variant': string;},'mooshroom': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'type': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'snowman': {},'ocelot': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'trusting': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'villager_golem': {},'horse': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'flags': string; +/** 1.19.4+ (18) */ +'type_variant': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'rabbit': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'type': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'polar_bear': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'standing': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'llama': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'flags': string; +/** 1.19.4+ (18) */ +'chest': string; +/** 1.19.4+ (19) */ +'strength': string; +/** 1.19.4+ (20) */ +'swag': string; +/** 1.19.4+ (21) */ +'variant': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'llama_spit': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string;},'villager': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'unhappy_counter': string; +/** 1.19.4+ (18) */ +'villager_data': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'ender_crystal': {},'Fishing Hook': {},'illusion_illager': {},'parrot': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'flags': string; +/** 1.19.4+ (18) */ +'owneruuid': string; +/** 1.19.4+ (19) */ +'variant': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'cod': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'from_bucket': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'dolphin': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'treasure_pos': string; +/** 1.19.4+ (17) */ +'got_fish': string; +/** 1.19.4+ (18) */ +'moistness_level': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'drowned': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'special_type': string; +/** 1.19.4+ (18) */ +'drowned_conversion': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'end_crystal': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'beam_target': string; +/** 1.19.4+ (9) */ +'show_bottom': string;},'evoker_fangs': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string;},'evoker': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'is_celebrating': string; +/** 1.19.4+ (17) */ +'spell_casting': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'experience_orb': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string;},'eye_of_ender': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'item_stack': string;},'illusioner': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'is_celebrating': string; +/** 1.19.4+ (17) */ +'spell_casting': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'pufferfish': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'from_bucket': string; +/** 1.19.4+ (17) */ +'puff_state': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'salmon': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'from_bucket': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'snow_golem': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'pumpkin': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'tropical_fish': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'from_bucket': string; +/** 1.19.4+ (17) */ +'type_variant': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'turtle': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'home_pos': string; +/** 1.19.4+ (18) */ +'has_egg': string; +/** 1.19.4+ (19) */ +'laying_egg': string; +/** 1.19.4+ (20) */ +'travel_pos': string; +/** 1.19.4+ (21) */ +'going_home': string; +/** 1.19.4+ (22) */ +'travelling': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'experience_bottle': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'item_stack': string;},'iron_golem}': {},'vindicator': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'is_celebrating': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'phantom': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'size': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'lightning_bolt': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string;},'player': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'player_absorption': string; +/** 1.19.4+ (16) */ +'score': string; +/** 1.19.4+ (17) */ +'player_mode_customisation': string; +/** 1.19.4+ (18) */ +'player_main_hand': string; +/** 1.19.4+ (19) */ +'shoulder_left': string; +/** 1.19.4+ (20) */ +'shoulder_right': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'fishing_bobber': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'hooked_entity': string; +/** 1.19.4+ (9) */ +'biting': string;},'trident': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'flags': string; +/** 1.19.4+ (9) */ +'pierce_level': string; +/** 1.19.4+ (10) */ +'loyalty': string; +/** 1.19.4+ (11) */ +'foil': string;},'item_stack': {},'area_effect cloud': {},'activated_tnt': {},'endercrystal': {},'tipped_arrow': {},'firecharge': {},'thrown_enderpearl': {},'falling_objects': {},'item_frames': {},'eye_of ender': {},'thrown_potion': {},'thrown_exp bottle': {},'firework_rocket': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'fireworks_item': string; +/** 1.19.4+ (9) */ +'attached_to_target': string; +/** 1.19.4+ (10) */ +'shot_at_angle': string;},'armorstand': {},'fishing_hook': {},'cat': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'flags': string; +/** 1.19.4+ (18) */ +'owneruuid': string; +/** 1.19.4+ (19) */ +'variant': string; +/** 1.19.4+ (20) */ +'is_lying': string; +/** 1.19.4+ (21) */ +'relax_state_one': string; +/** 1.19.4+ (22) */ +'collar_color': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'fox': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'type': string; +/** 1.19.4+ (18) */ +'flags': string; +/** 1.19.4+ (19) */ +'trusted_0': string; +/** 1.19.4+ (20) */ +'trusted_1': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'command_block_minecart': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'hurt': string; +/** 1.19.4+ (9) */ +'hurtdir': string; +/** 1.19.4+ (10) */ +'damage': string; +/** 1.19.4+ (11) */ +'display_block': string; +/** 1.19.4+ (12) */ +'display_offset': string; +/** 1.19.4+ (13) */ +'custom_display': string; +/** 1.19.4+ (14) */ +'command_name': string; +/** 1.19.4+ (15) */ +'last_output': string;},'panda': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'unhappy_counter': string; +/** 1.19.4+ (18) */ +'sneeze_counter': string; +/** 1.19.4+ (19) */ +'eat_counter': string; +/** 1.19.4+ (20) */ +'main_gene': string; +/** 1.19.4+ (21) */ +'hidden_gene': string; +/** 1.19.4+ (22) */ +'flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'trader_llama': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'flags': string; +/** 1.19.4+ (18) */ +'chest': string; +/** 1.19.4+ (19) */ +'strength': string; +/** 1.19.4+ (20) */ +'swag': string; +/** 1.19.4+ (21) */ +'variant': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'iron_golem': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'pillager': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'is_celebrating': string; +/** 1.19.4+ (17) */ +'is_charging_crossbow': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'wandering_trader': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'unhappy_counter': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'ravager': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'is_celebrating': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'bee': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'flags': string; +/** 1.19.4+ (18) */ +'remaining_anger_time': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'hoglin': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'immune_to_zombification': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'piglin': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'immune_to_zombification': string; +/** 1.19.4+ (17) */ +'baby': string; +/** 1.19.4+ (18) */ +'is_charging_crossbow': string; +/** 1.19.4+ (19) */ +'is_dancing': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'strider': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'boost_time': string; +/** 1.19.4+ (18) */ +'suffocating': string; +/** 1.19.4+ (19) */ +'saddle': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'zoglin': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'zombified_piglin': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'special_type': string; +/** 1.19.4+ (18) */ +'drowned_conversion': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'piglin_brute': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'immune_to_zombification': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'axolotl': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'variant': string; +/** 1.19.4+ (18) */ +'playing_dead': string; +/** 1.19.4+ (19) */ +'from_bucket': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'glow_item_frame': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'item': string; +/** 1.19.4+ (9) */ +'rotation': string;},'glow_squid': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'dark_ticks_remaining': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'goat': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'is_screaming_goat': string; +/** 1.19.4+ (18) */ +'has_left_horn': string; +/** 1.19.4+ (19) */ +'has_right_horn': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'marker': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string;},'allay': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'dancing': string; +/** 1.19.4+ (17) */ +'can_duplicate': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'chest_boat': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'hurt': string; +/** 1.19.4+ (9) */ +'hurtdir': string; +/** 1.19.4+ (10) */ +'damage': string; +/** 1.19.4+ (11) */ +'type': string; +/** 1.19.4+ (12) */ +'paddle_left': string; +/** 1.19.4+ (13) */ +'paddle_right': string; +/** 1.19.4+ (14) */ +'bubble_time': string;},'frog': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'variant': string; +/** 1.19.4+ (18) */ +'tongue_target': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'tadpole': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'from_bucket': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'warden': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'client_anger_level': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'camel': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'flags': string; +/** 1.19.4+ (18) */ +'dash': string; +/** 1.19.4+ (19) */ +'last_pose_change_tick': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'block_display': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'interpolation_start_delta_ticks': string; +/** 1.19.4+ (9) */ +'interpolation_duration': string; +/** 1.19.4+ (10) */ +'translation': string; +/** 1.19.4+ (11) */ +'scale': string; +/** 1.19.4+ (12) */ +'left_rotation': string; +/** 1.19.4+ (13) */ +'right_rotation': string; +/** 1.19.4+ (14) */ +'billboard_render_constraints': string; +/** 1.19.4+ (15) */ +'brightness_override': string; +/** 1.19.4+ (16) */ +'view_range': string; +/** 1.19.4+ (17) */ +'shadow_radius': string; +/** 1.19.4+ (18) */ +'shadow_strength': string; +/** 1.19.4+ (19) */ +'width': string; +/** 1.19.4+ (20) */ +'height': string; +/** 1.19.4+ (21) */ +'glow_color_override': string; +/** 1.19.4+ (22) */ +'block_state': string; +/** 1.20.2+ (8) */ +'transformation_interpolation_start_delta_ticks': string; +/** 1.20.2+ (9) */ +'transformation_interpolation_duration': string; +/** 1.20.2+ (10) */ +'pos_rot_interpolation_duration': string;},'interaction': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'width': string; +/** 1.19.4+ (9) */ +'height': string; +/** 1.19.4+ (10) */ +'response': string;},'item_display': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'interpolation_start_delta_ticks': string; +/** 1.19.4+ (9) */ +'interpolation_duration': string; +/** 1.19.4+ (10) */ +'translation': string; +/** 1.19.4+ (11) */ +'scale': string; +/** 1.19.4+ (12) */ +'left_rotation': string; +/** 1.19.4+ (13) */ +'right_rotation': string; +/** 1.19.4+ (14) */ +'billboard_render_constraints': string; +/** 1.19.4+ (15) */ +'brightness_override': string; +/** 1.19.4+ (16) */ +'view_range': string; +/** 1.19.4+ (17) */ +'shadow_radius': string; +/** 1.19.4+ (18) */ +'shadow_strength': string; +/** 1.19.4+ (19) */ +'width': string; +/** 1.19.4+ (20) */ +'height': string; +/** 1.19.4+ (21) */ +'glow_color_override': string; +/** 1.19.4+ (22) */ +'item_stack': string; +/** 1.19.4+ (23) */ +'item_display': string; +/** 1.20.2+ (8) */ +'transformation_interpolation_start_delta_ticks': string; +/** 1.20.2+ (9) */ +'transformation_interpolation_duration': string; +/** 1.20.2+ (10) */ +'pos_rot_interpolation_duration': string;},'sniffer': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'living_entity_flags': string; +/** 1.19.4+ (9) */ +'health': string; +/** 1.19.4+ (10) */ +'effect_color': string; +/** 1.19.4+ (11) */ +'effect_ambience': string; +/** 1.19.4+ (12) */ +'arrow_count': string; +/** 1.19.4+ (13) */ +'stinger_count': string; +/** 1.19.4+ (14) */ +'sleeping_pos': string; +/** 1.19.4+ (15) */ +'mob_flags': string; +/** 1.19.4+ (16) */ +'baby': string; +/** 1.19.4+ (17) */ +'state': string; +/** 1.19.4+ (18) */ +'drop_seed_at_tick': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'text_display': { +/** 1.19.4+ (0) */ +'shared_flags': string; +/** 1.19.4+ (1) */ +'air_supply': string; +/** 1.19.4+ (2) */ +'custom_name': string; +/** 1.19.4+ (3) */ +'custom_name_visible': string; +/** 1.19.4+ (4) */ +'silent': string; +/** 1.19.4+ (5) */ +'no_gravity': string; +/** 1.19.4+ (6) */ +'pose': string; +/** 1.19.4+ (7) */ +'ticks_frozen': string; +/** 1.19.4+ (8) */ +'interpolation_start_delta_ticks': string; +/** 1.19.4+ (9) */ +'interpolation_duration': string; +/** 1.19.4+ (10) */ +'translation': string; +/** 1.19.4+ (11) */ +'scale': string; +/** 1.19.4+ (12) */ +'left_rotation': string; +/** 1.19.4+ (13) */ +'right_rotation': string; +/** 1.19.4+ (14) */ +'billboard_render_constraints': string; +/** 1.19.4+ (15) */ +'brightness_override': string; +/** 1.19.4+ (16) */ +'view_range': string; +/** 1.19.4+ (17) */ +'shadow_radius': string; +/** 1.19.4+ (18) */ +'shadow_strength': string; +/** 1.19.4+ (19) */ +'width': string; +/** 1.19.4+ (20) */ +'height': string; +/** 1.19.4+ (21) */ +'glow_color_override': string; +/** 1.19.4+ (22) */ +'text': string; +/** 1.19.4+ (23) */ +'line_width': string; +/** 1.19.4+ (24) */ +'background_color': string; +/** 1.19.4+ (25) */ +'text_opacity': string; +/** 1.19.4+ (26) */ +'style_flags': string; +/** 1.20.2+ (8) */ +'transformation_interpolation_start_delta_ticks': string; +/** 1.20.2+ (9) */ +'transformation_interpolation_duration': string; +/** 1.20.2+ (10) */ +'pos_rot_interpolation_duration': string;},'breeze': { +/** 1.20.3+ (0) */ +'shared_flags': string; +/** 1.20.3+ (1) */ +'air_supply': string; +/** 1.20.3+ (2) */ +'custom_name': string; +/** 1.20.3+ (3) */ +'custom_name_visible': string; +/** 1.20.3+ (4) */ +'silent': string; +/** 1.20.3+ (5) */ +'no_gravity': string; +/** 1.20.3+ (6) */ +'pose': string; +/** 1.20.3+ (7) */ +'ticks_frozen': string; +/** 1.20.3+ (8) */ +'living_entity_flags': string; +/** 1.20.3+ (9) */ +'health': string; +/** 1.20.3+ (10) */ +'effect_color': string; +/** 1.20.3+ (11) */ +'effect_ambience': string; +/** 1.20.3+ (12) */ +'arrow_count': string; +/** 1.20.3+ (13) */ +'stinger_count': string; +/** 1.20.3+ (14) */ +'sleeping_pos': string; +/** 1.20.3+ (15) */ +'mob_flags': string; +/** 1.20.5+ (10) */ +'effect_particles': string;},'wind_charge': { +/** 1.20.3+ (0) */ +'shared_flags': string; +/** 1.20.3+ (1) */ +'air_supply': string; +/** 1.20.3+ (2) */ +'custom_name': string; +/** 1.20.3+ (3) */ +'custom_name_visible': string; +/** 1.20.3+ (4) */ +'silent': string; +/** 1.20.3+ (5) */ +'no_gravity': string; +/** 1.20.3+ (6) */ +'pose': string; +/** 1.20.3+ (7) */ +'ticks_frozen': string;},'armadillo': { +/** 1.20.5+ (0) */ +'shared_flags': string; +/** 1.20.5+ (1) */ +'air_supply': string; +/** 1.20.5+ (2) */ +'custom_name': string; +/** 1.20.5+ (3) */ +'custom_name_visible': string; +/** 1.20.5+ (4) */ +'silent': string; +/** 1.20.5+ (5) */ +'no_gravity': string; +/** 1.20.5+ (6) */ +'pose': string; +/** 1.20.5+ (7) */ +'ticks_frozen': string; +/** 1.20.5+ (8) */ +'living_entity_flags': string; +/** 1.20.5+ (9) */ +'health': string; +/** 1.20.5+ (10) */ +'effect_particles': string; +/** 1.20.5+ (11) */ +'effect_ambience': string; +/** 1.20.5+ (12) */ +'arrow_count': string; +/** 1.20.5+ (13) */ +'stinger_count': string; +/** 1.20.5+ (14) */ +'sleeping_pos': string; +/** 1.20.5+ (15) */ +'mob_flags': string; +/** 1.20.5+ (16) */ +'baby': string; +/** 1.20.5+ (17) */ +'armadillo_state': string;},'bogged': { +/** 1.20.5+ (0) */ +'shared_flags': string; +/** 1.20.5+ (1) */ +'air_supply': string; +/** 1.20.5+ (2) */ +'custom_name': string; +/** 1.20.5+ (3) */ +'custom_name_visible': string; +/** 1.20.5+ (4) */ +'silent': string; +/** 1.20.5+ (5) */ +'no_gravity': string; +/** 1.20.5+ (6) */ +'pose': string; +/** 1.20.5+ (7) */ +'ticks_frozen': string; +/** 1.20.5+ (8) */ +'living_entity_flags': string; +/** 1.20.5+ (9) */ +'health': string; +/** 1.20.5+ (10) */ +'effect_particles': string; +/** 1.20.5+ (11) */ +'effect_ambience': string; +/** 1.20.5+ (12) */ +'arrow_count': string; +/** 1.20.5+ (13) */ +'stinger_count': string; +/** 1.20.5+ (14) */ +'sleeping_pos': string; +/** 1.20.5+ (15) */ +'mob_flags': string; +/** 1.20.5+ (16) */ +'sheared': string;},'breeze_wind_charge': { +/** 1.20.5+ (0) */ +'shared_flags': string; +/** 1.20.5+ (1) */ +'air_supply': string; +/** 1.20.5+ (2) */ +'custom_name': string; +/** 1.20.5+ (3) */ +'custom_name_visible': string; +/** 1.20.5+ (4) */ +'silent': string; +/** 1.20.5+ (5) */ +'no_gravity': string; +/** 1.20.5+ (6) */ +'pose': string; +/** 1.20.5+ (7) */ +'ticks_frozen': string;},'ominous_item_spawner': { +/** 1.20.5+ (0) */ +'shared_flags': string; +/** 1.20.5+ (1) */ +'air_supply': string; +/** 1.20.5+ (2) */ +'custom_name': string; +/** 1.20.5+ (3) */ +'custom_name_visible': string; +/** 1.20.5+ (4) */ +'silent': string; +/** 1.20.5+ (5) */ +'no_gravity': string; +/** 1.20.5+ (6) */ +'pose': string; +/** 1.20.5+ (7) */ +'ticks_frozen': string; +/** 1.20.5+ (8) */ +'item': string;}, +} \ No newline at end of file diff --git a/src/optionsGuiScheme.tsx b/src/optionsGuiScheme.tsx index 434ad4846..c6a979c16 100644 --- a/src/optionsGuiScheme.tsx +++ b/src/optionsGuiScheme.tsx @@ -89,7 +89,6 @@ export const guiOptionsScheme: { tooltip: 'Additional distance to keep the chunks loading before unloading them by marking them as too far', }, handDisplay: {}, - neighborChunkUpdates: {}, renderDebug: { values: [ 'advanced', @@ -250,6 +249,19 @@ export const guiOptionsScheme: { ], }, }, + { + custom () { + return Map + }, + showMinimap: { + text: 'Enable Minimap', + values: [ + 'always', + 'singleplayer', + 'never' + ], + }, + }, { custom () { return Experimental diff --git a/src/optionsStorage.ts b/src/optionsStorage.ts index 53deb927f..a242107c6 100644 --- a/src/optionsStorage.ts +++ b/src/optionsStorage.ts @@ -80,6 +80,7 @@ const defaultOptions = { autoParkour: false, vrSupport: true, // doesn't directly affect the VR mode, should only disable the button which is annoying to android users renderDebug: (isDev ? 'advanced' : 'basic') as 'none' | 'advanced' | 'basic', + autoVersionSelect: '1.20.4', // advanced bot options autoRespawn: false, @@ -88,6 +89,8 @@ const defaultOptions = { /** Wether to popup sign editor on server action */ autoSignEditor: true, wysiwygSignEditor: 'auto' as 'auto' | 'always' | 'never', + showMinimap: 'never' as 'always' | 'singleplayer' | 'never', + minimapOptimizations: true, displayBossBars: false, // boss bar overlay was removed for some reason, enable safely disabledUiParts: [] as string[], neighborChunkUpdates: true diff --git a/src/react/AppStatus.tsx b/src/react/AppStatus.tsx index f9e5217ed..2c24b1539 100644 --- a/src/react/AppStatus.tsx +++ b/src/react/AppStatus.tsx @@ -38,10 +38,10 @@ export default ({ return ( diff --git a/src/react/DebugOverlay.tsx b/src/react/DebugOverlay.tsx index 23f0d7db1..54d8cb404 100644 --- a/src/react/DebugOverlay.tsx +++ b/src/react/DebugOverlay.tsx @@ -1,8 +1,8 @@ import { useEffect, useRef, useMemo, useState } from 'react' import * as THREE from 'three' +import type { Block } from 'prismarine-block' import { getFixedFilesize } from '../downloadAndOpenFile' import { options } from '../optionsStorage' -import worldInteractions from '../worldInteractions' import styles from './DebugOverlay.module.css' export default () => { @@ -35,10 +35,10 @@ export default () => { const [day, setDay] = useState(0) const [entitiesCount, setEntitiesCount] = useState(0) const [dimension, setDimension] = useState('') - const [cursorBlock, setCursorBlock] = useState(null) - const [rendererDevice, setRendererDevice] = useState('') + const [cursorBlock, setCursorBlock] = useState(null) const minecraftYaw = useRef(0) const minecraftQuad = useRef(0) + const { rendererDevice } = viewer.world const quadsDescription = [ 'north (towards negative Z)', @@ -105,7 +105,7 @@ export default () => { setBiomeId(bot.world.getBiome(bot.entity.position)) setDimension(bot.game.dimension) setDay(bot.time.day) - setCursorBlock(worldInteractions.cursorBlock) + setCursorBlock(bot.blockAtCursor(5)) setEntitiesCount(Object.values(bot.entities).length) }, 100) @@ -118,13 +118,6 @@ export default () => { managePackets('sent', name, data) }) - try { - const gl = window.renderer.getContext() - setRendererDevice(gl.getParameter(gl.getExtension('WEBGL_debug_renderer_info')!.UNMASKED_RENDERER_WEBGL)) - } catch (err) { - console.warn(err) - } - return () => { document.removeEventListener('keydown', handleF3) clearInterval(packetsUpdateInterval) @@ -159,7 +152,7 @@ export default () => {
-

Renderer: {rendererDevice} powered by three.js r{THREE.REVISION}

+

Renderer: {rendererDevice}

{cursorBlock ? (<>

{cursorBlock.name}

diff --git a/src/react/FoodBar.tsx b/src/react/FoodBar.tsx index 5a131c073..dbed05023 100644 --- a/src/react/FoodBar.tsx +++ b/src/react/FoodBar.tsx @@ -25,7 +25,7 @@ export default ({ useEffect(() => { if (foodRef.current) { - foodRef.current.classList.toggle('creative', gameMode === 'creative') + foodRef.current.classList.toggle('creative', gameMode === 'creative' || gameMode === 'spectator') } }, [gameMode]) diff --git a/src/react/Fullmap.css b/src/react/Fullmap.css new file mode 100644 index 000000000..5b4b37ce8 --- /dev/null +++ b/src/react/Fullmap.css @@ -0,0 +1,13 @@ + +.map { + width: 70% !important; + height: 80% !important; + border: 1px solid black; +} + +@media (max-width: 500px) { + .map { + width: 100% !important; + height: 100% !important; + } +} diff --git a/src/react/Fullmap.tsx b/src/react/Fullmap.tsx new file mode 100644 index 000000000..69a2c5148 --- /dev/null +++ b/src/react/Fullmap.tsx @@ -0,0 +1,512 @@ +import { Vec3 } from 'vec3' +import { useRef, useEffect, useState, CSSProperties, Dispatch, SetStateAction } from 'react' +import { WorldWarp } from 'flying-squid/dist/lib/modules/warps' +import { TransformWrapper, TransformComponent, ReactZoomPanPinchRef } from 'react-zoom-pan-pinch' +import { MinimapDrawer, DrawerAdapter, ChunkInfo } from './MinimapDrawer' +import Button from './Button' +import Input from './Input' +import './Fullmap.css' + + +type FullmapProps = { + toggleFullMap: () => void, + adapter: DrawerAdapter, + drawer: MinimapDrawer | null, + canvasRef: any +} + +export default ({ toggleFullMap, adapter }: FullmapProps) => { + const [grid, setGrid] = useState(() => new Set()) + const zoomRef = useRef(null) + const redrawCell = useRef(false) + const [lastWarpPos, setLastWarpPos] = useState({ x: 0, y: 0, z: 0 }) + const stateRef = useRef({ scale: 1, positionX: 0, positionY: 0 }) + const cells = useRef({ columns: 0, rows: 0 }) + const [isWarpInfoOpened, setIsWarpInfoOpened] = useState(false) + const [initWarp, setInitWarp] = useState(undefined) + const [warpPreview, setWarpPreview] = useState<{ name: string, x: number, z: number, clientX: number, clientY: number } | undefined>(undefined) + + const updateGrid = () => { + const wrapperRect = zoomRef.current?.instance.wrapperComponent?.getBoundingClientRect() + if (!wrapperRect) return + const cellSize = 64 + const columns = Math.ceil(wrapperRect.width / (cellSize * stateRef.current.scale)) + const rows = Math.ceil(wrapperRect.height / (cellSize * stateRef.current.scale)) + cells.current.rows = rows + cells.current.columns = columns + const leftBorder = - Math.floor(stateRef.current.positionX / (stateRef.current.scale * cellSize)) * cellSize + const topBorder = - Math.floor(stateRef.current.positionY / (stateRef.current.scale * cellSize)) * cellSize + const newGrid = new Set() + for (let row = -1; row < rows; row += 1) { + for (let col = -1; col < columns; col += 1) { + const x = leftBorder + col * cellSize + const y = topBorder + row * cellSize + newGrid.add(`${x},${y}`) + } + } + setGrid(newGrid) + } + + useEffect(() => { + adapter.full = true + console.log('[fullmap] set full property to true') + updateGrid() + }, []) + + return
+ {window.screen.width > 500 ?
+ :
+} + + +const MapChunk = ( + { x, y, scale, adapter, worldX, worldZ, setIsWarpInfoOpened, setLastWarpPos, redraw, setInitWarp, setWarpPreview }: + { + x: number, + y: number, + scale: number, + adapter: DrawerAdapter, + worldX: number, + worldZ: number, + setIsWarpInfoOpened: (x: boolean) => void, + setLastWarpPos: (obj: { x: number, y: number, z: number }) => void, + redraw?: boolean + setInitWarp?: (warp: WorldWarp | undefined) => void + setWarpPreview?: (warpInfo) => void + } +) => { + const containerRef = useRef(null) + const drawerRef = useRef(null) + const touchTimer = useRef | null>(null) + const canvasRef = useRef(null) + const [isCanvas, setIsCanvas] = useState(false) + + const longPress = (e) => { + touchTimer.current = setTimeout(() => { + touchTimer.current = null + handleClick(e) + }, 500) + } + + const cancel = () => { + if (touchTimer.current) clearTimeout(touchTimer.current) + } + + const handleClick = (e: MouseEvent | TouchEvent) => { + // console.log('click:', e) + if (!drawerRef.current) return + let clientX: number + let clientY: number + if ('buttons' in e && e.button === 2) { + clientX = e.clientX + clientY = e.clientY + } else if ('changedTouches' in e) { + clientX = (e).changedTouches[0].clientX + clientY = (e).changedTouches[0].clientY + } else { return } + const [x, z] = getXZ(clientX, clientY) + const mapX = Math.floor(x + worldX) + const mapZ = Math.floor(z + worldZ) + const y = adapter.getHighestBlockY(mapX, mapZ) + drawerRef.current.setWarpPosOnClick(new Vec3(mapX, y, mapZ)) + setLastWarpPos(drawerRef.current.lastWarpPos) + const { lastWarpPos } = drawerRef.current + const initWarp = adapter.warps.find(warp => Math.hypot(lastWarpPos.x - warp.x, lastWarpPos.z - warp.z) < 2) + setInitWarp?.(initWarp) + setIsWarpInfoOpened(true) + } + + const getXZ = (clientX: number, clientY: number) => { + const rect = canvasRef.current!.getBoundingClientRect() + const factor = scale * (drawerRef.current?.mapPixel ?? 1) + const x = (clientX - rect.left) / factor + const y = (clientY - rect.top) / factor + return [x, y] + } + + const handleMouseMove = (e: MouseEvent) => { + const [x, z] = getXZ(e.clientX, e.clientY) + const warp = adapter.warps.find(w => Math.hypot(w.x - x - worldX, w.z - z - worldZ) < 2) + setWarpPreview?.( + warp ? { name: warp.name, x: warp.x, z: warp.z, clientX: e.clientX, clientY: e.clientY } : undefined + ) + } + + const handleRedraw = (key?: string, chunk?: ChunkInfo) => { + if (key !== `${worldX / 16},${worldZ / 16}`) return + adapter.mapDrawer.canvas = canvasRef.current! + adapter.mapDrawer.full = true + // console.log('handle redraw:', key) + // if (chunk) { + // drawerRef.current?.chunksStore.set(key, chunk) + // } + if (!adapter.chunksStore.has(key)) { + adapter.chunksStore.set(key, 'requested') + void adapter.loadChunk(key) + return + } + const timeout = setTimeout(() => { + const center = new Vec3(worldX + 8, 0, worldZ + 8) + drawerRef.current!.lastBotPos = center + drawerRef.current?.drawChunk(key) + // drawerRef.current?.drawWarps(center) + // drawerRef.current?.drawPlayerPos(center.x, center.z) + clearTimeout(timeout) + }, 100) + } + + useEffect(() => { + // if (canvasRef.current && !drawerRef.current) { + // drawerRef.current = adapter.mapDrawer + // } else if (canvasRef.current && drawerRef.current) { + // } + if (canvasRef.current) void adapter.drawChunkOnCanvas(`${worldX / 16},${worldZ / 16}`, canvasRef.current) + }, [canvasRef.current]) + + useEffect(() => { + canvasRef.current?.addEventListener('contextmenu', handleClick) + canvasRef.current?.addEventListener('touchstart', longPress) + canvasRef.current?.addEventListener('touchend', cancel) + canvasRef.current?.addEventListener('touchmove', cancel) + canvasRef.current?.addEventListener('mousemove', handleMouseMove) + + return () => { + canvasRef.current?.removeEventListener('contextmenu', handleClick) + canvasRef.current?.removeEventListener('touchstart', longPress) + canvasRef.current?.removeEventListener('touchend', cancel) + canvasRef.current?.removeEventListener('touchmove', cancel) + canvasRef.current?.removeEventListener('mousemove', handleMouseMove) + } + }, [canvasRef.current, scale]) + + useEffect(() => { + // handleRedraw() + }, [drawerRef.current, redraw]) + + useEffect(() => { + const intersectionObserver = new IntersectionObserver((entries) => { + for (const entry of entries) { + if (entry.isIntersecting) { + setIsCanvas(true) + } + } + }) + intersectionObserver.observe(containerRef.current!) + + // adapter.on('chunkReady', handleRedraw) + + return () => { + intersectionObserver.disconnect() + // adapter.off('chunkReady', handleRedraw) + } + }, []) + + return
+ +
+} + +const WarpInfo = ( + { adapter, warpPos, setIsWarpInfoOpened, afterWarpIsSet, initWarp, toggleFullMap }: + { + adapter: DrawerAdapter, + warpPos: { x: number, y: number, z: number }, + setIsWarpInfoOpened: Dispatch>, + afterWarpIsSet?: () => void + initWarp?: WorldWarp, + setInitWarp?: React.Dispatch>, + toggleFullMap?: ({ command }: { command: string }) => void + } +) => { + const [warp, setWarp] = useState(initWarp ?? { + name: '', + x: warpPos?.x ?? 100, + y: warpPos?.y ?? 100, + z: warpPos?.z ?? 100, + color: '', + disabled: false, + world: adapter.world + }) + + const posInputStyle: CSSProperties = { + flexGrow: '1', + } + const fieldCont: CSSProperties = { + display: 'flex', + alignItems: 'center', + gap: '5px' + } + + const updateChunk = () => { + for (let i = -1; i < 2; i += 1) { + for (let j = -1; j < 2; j += 1) { + adapter.emit( + 'chunkReady', + `${Math.floor(warp.x / 16) + j},${Math.floor(warp.z / 16) + i}` + ) + } + } + } + + const tpNow = () => { + adapter.off('updateChunk', tpNow) + } + + const quickTp = () => { + toggleFullMap?.({ command: 'ui.toggleMap' }) + adapter.quickTp?.(warp.x, warp.z) + } + + return
+
500 ? '100%' : '50%', + minWidth: '100px', + maxWidth: '300px', + padding: '20px', + backgroundColor: 'rgba(0, 0, 0, 0.5)', + border: '2px solid black' + }} + > +

Point on the map

+
+
+ Name: +
+ { + if (!e.target) return + setWarp(prev => { return { ...prev, name: e.target.value } }) + }} + autoFocus + /> +
+
+
+ X: +
+ { + if (!e.target) return + setWarp(prev => { return { ...prev, x: Number(e.target.value) } }) + }} + /> +
+ Z: +
+ { + if (!e.target) return + setWarp(prev => { return { ...prev, z: Number(e.target.value) } }) + }} + /> +
+
+
Color:
+ { + if (!e.target) return + setWarp(prev => { return { ...prev, color: e.target.value } }) + }} + rootStyles={{ width: '30px', }} + style={{ left: '0px' }} + /> +
+
+ + { + if (!e.target) return + setWarp(prev => { return { ...prev, disabled: e.target.checked } }) + }} + /> +
+ +
+ + + {initWarp && } +
+
+
+} diff --git a/src/react/HotbarRenderApp.tsx b/src/react/HotbarRenderApp.tsx index 5b65f890f..1c94905f4 100644 --- a/src/react/HotbarRenderApp.tsx +++ b/src/react/HotbarRenderApp.tsx @@ -73,7 +73,7 @@ const ItemName = ({ itemKey }: { itemKey: string }) => { } -export default () => { +const Inner = () => { const container = useRef(null!) const [itemKey, setItemKey] = useState('') const hasModals = useSnapshot(activeModalStack).length @@ -221,6 +221,17 @@ export default () => { } +export default () => { + const [gameMode, setGameMode] = useState(bot.game?.gameMode ?? 'creative') + useEffect(() => { + bot.on('game', () => { + setGameMode(bot.game.gameMode) + }) + }, []) + + return gameMode === 'spectator' ? null : +} + const Portal = ({ children, to = document.body }) => { return createPortal(children, to) } diff --git a/src/react/Input.tsx b/src/react/Input.tsx index 41dbc7ba8..1da36cc3f 100644 --- a/src/react/Input.tsx +++ b/src/react/Input.tsx @@ -9,10 +9,10 @@ interface Props extends React.ComponentProps<'input'> { validateInput?: (value: string) => CSSProperties | undefined } -export default ({ autoFocus, rootStyles, inputRef, validateInput, ...inputProps }: Props) => { +export default ({ autoFocus, rootStyles, inputRef, validateInput, defaultValue, ...inputProps }: Props) => { const ref = useRef(null!) const [validationStyle, setValidationStyle] = useState({}) - const [value, setValue] = useState(inputProps.value ?? '') + const [value, setValue] = useState(defaultValue ?? '') useEffect(() => { setValue(inputProps.value === '' || inputProps.value ? inputProps.value : value) diff --git a/src/react/MainMenuRenderApp.tsx b/src/react/MainMenuRenderApp.tsx index 7c6385dcb..f62cf1652 100644 --- a/src/react/MainMenuRenderApp.tsx +++ b/src/react/MainMenuRenderApp.tsx @@ -62,7 +62,7 @@ export default () => { return } const upStatus = () => { - setVersionStatus(`(${isLatest ? 'latest' : 'new version available'}${mainMenuState.serviceWorkerLoaded ? ' - Available Offline' : ''})`) + setVersionStatus(`(${isLatest ? 'latest' : 'new version available'}${mainMenuState.serviceWorkerLoaded ? ', Downloaded' : ''})`) } subscribe(mainMenuState, upStatus) upStatus() diff --git a/src/react/Minimap.stories.tsx b/src/react/Minimap.stories.tsx new file mode 100644 index 000000000..5b28a5b99 --- /dev/null +++ b/src/react/Minimap.stories.tsx @@ -0,0 +1,74 @@ +import { Vec3 } from 'vec3' +import type { Meta, StoryObj } from '@storybook/react' +import { WorldWarp } from 'flying-squid/dist/lib/modules/warps' +import { TypedEventEmitter } from 'contro-max/build/typedEventEmitter' +import { useEffect } from 'react' + +import Minimap from './Minimap' +import { DrawerAdapter, MapUpdates } from './MinimapDrawer' + +const meta: Meta = { + component: Minimap, + decorators: [ + (Story, context) => { + + useEffect(() => { + console.log('map updated') + adapter.emit('updateMap') + + }, [context.args['fullMap']]) + + return
+ } + ] +} + +export default meta +type Story = StoryObj + + +class DrawerAdapterImpl extends TypedEventEmitter { + playerPosition: Vec3 + yaw: number + warps: WorldWarp[] + chunksStore: any = {} + full: boolean + + constructor (pos?: Vec3, warps?: WorldWarp[]) { + super() + this.playerPosition = pos ?? new Vec3(0, 0, 0) + this.warps = warps ?? [] as WorldWarp[] + } + + async getHighestBlockColor (x: number, z: number) { + console.log('got color') + return 'green' + } + + getHighestBlockY (x: number, z: number) { + return 0 + } + + setWarp (warp: WorldWarp, remove?: boolean): void { + const index = this.warps.findIndex(w => w.name === warp.name) + if (index === -1) { + this.warps.push(warp) + } else { + this.warps[index] = warp + } + this.emit('updateWarps') + } + + clearChunksStore (x: number, z: number) { } + + async loadChunk (key: string) {} +} + +const adapter = new DrawerAdapterImpl() as any + +export const Primary: Story = { + args: { + adapter, + fullMap: false + }, +} diff --git a/src/react/Minimap.tsx b/src/react/Minimap.tsx new file mode 100644 index 000000000..1dae0344d --- /dev/null +++ b/src/react/Minimap.tsx @@ -0,0 +1,175 @@ +import { useRef, useEffect, useState } from 'react' +import { MinimapDrawer, DrawerAdapter, ChunkInfo } from './MinimapDrawer' +import Fullmap from './Fullmap' + + +export type DisplayMode = 'fullmapOnly' | 'minimapOnly' + +export default ( + { adapter, showMinimap, showFullmap, singleplayer, fullMap, toggleFullMap, displayMode }: + { + adapter: DrawerAdapter, + showMinimap: string, + showFullmap: string, + singleplayer: boolean, + fullMap?: boolean, + toggleFullMap?: ({ command }: { command: string }) => void + displayMode?: DisplayMode + } +) => { + const full = useRef(false) + const canvasTick = useRef(0) + const canvasRef = useRef(null) + const warpsAndPartsCanvasRef = useRef(null) + const playerPosCanvasRef = useRef(null) + const warpsDrawerRef = useRef(null) + const drawerRef = useRef(null) + const playerPosDrawerRef = useRef(null) + const [position, setPosition] = useState({ x: 0, y: 0, z: 0 }) + + const updateMap = () => { + setPosition({ x: adapter.playerPosition.x, y: adapter.playerPosition.y, z: adapter.playerPosition.z }) + if (drawerRef.current) { + if (!full.current) { + rotateMap() + drawerRef.current.draw(adapter.playerPosition) + drawerRef.current.drawPlayerPos() + drawerRef.current.drawWarps() + } + if (canvasTick.current % 300 === 0 && !fullMap) { + if ('requestIdleCallback' in window) { + requestIdleCallback(() => { + drawerRef.current?.clearChunksStore() + }) + } else { + drawerRef.current.clearChunksStore() + } + canvasTick.current = 0 + } + } + canvasTick.current += 1 + } + + const updateWarps = () => { } + + const rotateMap = () => { + if (!drawerRef.current) return + drawerRef.current.canvas.style.transform = `rotate(${adapter.yaw}rad)` + if (!warpsDrawerRef.current) return + warpsDrawerRef.current.canvas.style.transform = `rotate(${adapter.yaw}rad)` + } + + const updateChunkOnMap = (key: string, chunk: ChunkInfo) => { + adapter.chunksStore.set(key, chunk) + } + + useEffect(() => { + if (canvasRef.current && !drawerRef.current) { + drawerRef.current = adapter.mapDrawer + drawerRef.current.canvas = canvasRef.current + // drawerRef.current.adapter.on('chunkReady', updateChunkOnMap) + } else if (canvasRef.current && drawerRef.current) { + drawerRef.current.canvas = canvasRef.current + } + + }, [canvasRef.current]) + + // useEffect(() => { + // if (warpsAndPartsCanvasRef.current && !warpsDrawerRef.current) { + // warpsDrawerRef.current = new MinimapDrawer(warpsAndPartsCanvasRef.current, adapter) + // } else if (warpsAndPartsCanvasRef.current && warpsDrawerRef.current) { + // warpsDrawerRef.current.canvas = warpsAndPartsCanvasRef.current + // } + // }, [warpsAndPartsCanvasRef.current]) + + // useEffect(() => { + // if (playerPosCanvasRef.current && !playerPosDrawerRef.current) { + // playerPosDrawerRef.current = new MinimapDrawer(playerPosCanvasRef.current, adapter) + // } else if (playerPosCanvasRef.current && playerPosDrawerRef.current) { + // playerPosDrawerRef.current.canvas = playerPosCanvasRef.current + // } + // }, [playerPosCanvasRef.current]) + + useEffect(() => { + adapter.on('updateMap', updateMap) + adapter.on('updateWaprs', updateWarps) + + return () => { + adapter.off('updateMap', updateMap) + adapter.off('updateWaprs', updateWarps) + } + }, [adapter]) + + useEffect(() => { + return () => { + // if (drawerRef.current) drawerRef.current.adapter.off('chunkReady', updateChunkOnMap) + } + }, []) + + const displayFullmap = fullMap && displayMode !== 'minimapOnly' && (showFullmap === 'singleplayer' && singleplayer || showFullmap === 'always') + const displayMini = displayMode !== 'fullmapOnly' && (showMinimap === 'singleplayer' && singleplayer || showMinimap === 'always') + return displayFullmap + ? { + toggleFullMap?.({ command: 'ui.toggleMap' }) + }} + adapter={adapter} + drawer={drawerRef.current} + canvasRef={canvasRef} + /> + : displayMini + ?
{ + toggleFullMap?.({ command: 'ui.toggleMap' }) + }} + > + + + +
+ {position.x.toFixed(2)} {position.y.toFixed(2)} {position.z.toFixed(2)} +
+
: null +} diff --git a/src/react/MinimapDrawer.ts b/src/react/MinimapDrawer.ts new file mode 100644 index 000000000..935bdd4bb --- /dev/null +++ b/src/react/MinimapDrawer.ts @@ -0,0 +1,324 @@ +import { Vec3 } from 'vec3' +import { TypedEventEmitter } from 'contro-max/build/typedEventEmitter' +import { WorldWarp } from 'flying-squid/dist/lib/modules/warps' +import { Chunk } from 'prismarine-world/types/world' + +export type MapUpdates = { + updateBlockColor: (pos: Vec3) => void + updatePlayerPosition: () => void + updateWarps: () => void +} + +export interface DrawerAdapter extends TypedEventEmitter { + getHighestBlockY: (x: number, z: number, chunk?: Chunk) => number + clearChunksStore: (x: number, z: number) => void + chunksStore: Map + playerPosition: Vec3 + warps: WorldWarp[] + loadingChunksQueue: Set + mapDrawer: MinimapDrawer + yaw: number + full: boolean + world: string + setWarp: (warp: WorldWarp, remove?: boolean) => void + quickTp?: (x: number, z: number) => void + loadChunk: (key: string) => Promise + drawChunkOnCanvas: (key: string, canvas: HTMLCanvasElement) => Promise +} + +export type ChunkInfo = { + heightmap: Uint8Array, + colors: string[], +} + +export class MinimapDrawer { + canvasWidthCenterX: number + canvasWidthCenterY: number + _mapSize: number + radius: number + ctx: CanvasRenderingContext2D + _canvas: HTMLCanvasElement + chunksInView = new Set() + lastBotPos: Vec3 + lastWarpPos: Vec3 + mapPixel: number + yaw: number + chunksStore = new Map() + loadingChunksQueue: undefined | Set + warps: WorldWarp[] + loadChunk: undefined | ((key: string) => Promise) + _full = false + + setMapPixel () { + if (this.full) { + this.radius = Math.floor(Math.min(this.canvas.width, this.canvas.height) / 2) + this._mapSize = 16 + } else { + this.radius = Math.floor(Math.min(this.canvas.width, this.canvas.height) / 2.2) + this._mapSize = this.radius * 2 + } + this.mapPixel = Math.floor(this.radius * 2 / this.mapSize) + } + + get full () { + return this._full + } + + set full (full: boolean) { + this._full = full + this.setMapPixel() + } + + get canvas () { + return this._canvas + } + + set canvas (canvas: HTMLCanvasElement) { + this.ctx = canvas.getContext('2d', { willReadFrequently: true })! + this.ctx.imageSmoothingEnabled = false + this.canvasWidthCenterX = canvas.width / 2 + this.canvasWidthCenterY = canvas.height / 2 + this._canvas = canvas + this.setMapPixel() + } + + get mapSize () { + return this._mapSize + } + + set mapSize (mapSize: number) { + this._mapSize = mapSize + this.mapPixel = Math.floor(this.radius * 2 / this.mapSize) + this.draw(this.lastBotPos) + } + + draw (botPos: Vec3,) { + this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height) + + this.lastBotPos = botPos + this.updateChunksInView() + for (const key of this.chunksInView) { + if (!this.chunksStore.has(key) && !this.loadingChunksQueue?.has(key)) { + void this.loadChunk?.(key) + } + this.drawChunk(key) + } + if (!this.full) this.drawPartsOfWorld() + } + + updateChunksInView (viewX?: number, viewZ?: number) { + const worldCenterX = viewX ?? this.lastBotPos.x + const worldCenterZ = viewZ ?? this.lastBotPos.z + + const radius = this.mapSize / 2 + const leftViewBorder = Math.floor((worldCenterX - radius) / 16) - 1 + const rightViewBorder = Math.ceil((worldCenterX + radius) / 16) + const topViewBorder = Math.floor((worldCenterZ - radius) / 16) - 1 + const bottomViewBorder = Math.ceil((worldCenterZ + radius) / 16) + + this.chunksInView.clear() + for (let i = topViewBorder; i <= bottomViewBorder; i += 1) { + for (let j = leftViewBorder; j <= rightViewBorder; j += 1) { + this.chunksInView.add(`${j},${i}`) + } + } + } + + drawChunk (key: string, chunkInfo?: ChunkInfo | null) { + const [chunkX, chunkZ] = key.split(',').map(Number) + const chunkWorldX = chunkX * 16 + const chunkWorldZ = chunkZ * 16 + const chunkCanvasX = Math.floor((chunkWorldX - this.lastBotPos.x) * this.mapPixel + this.canvasWidthCenterX) + const chunkCanvasY = Math.floor((chunkWorldZ - this.lastBotPos.z) * this.mapPixel + this.canvasWidthCenterY) + const chunk = chunkInfo ?? this.chunksStore.get(key) + if (typeof chunk !== 'object') { + const chunkSize = this.mapPixel * 16 + this.ctx.fillStyle = chunk === 'requested' ? 'rgb(200, 200, 200)' : 'rgba(0, 0, 0, 0.5)' + this.ctx.fillRect(chunkCanvasX, chunkCanvasY, chunkSize, chunkSize) + return + } + for (let row = 0; row < 16; row += 1) { + for (let col = 0; col < 16; col += 1) { + const index = row * 16 + col + const color = chunk?.colors[index] ?? 'rgb(255, 0, 0)' + const pixelX = chunkCanvasX + this.mapPixel * col + const pixelY = chunkCanvasY + this.mapPixel * row + this.drawPixel(pixelX, pixelY, color) + } + } + } + + drawPixel (pixelX: number, pixelY: number, color: string) { + // if (!this.full && Math.hypot(pixelX - this.canvasWidthCenterX, pixelY - this.canvasWidthCenterY) > this.radius) { + // this.ctx.clearRect(pixelX, pixelY, this.mapPixel, this.mapPixel) + // return + // } + this.ctx.fillStyle = color + this.ctx.fillRect( + pixelX, + pixelY, + this.mapPixel, + this.mapPixel + ) + } + + clearChunksStore () { + for (const key of this.chunksStore.keys()) { + const [x, z] = key.split(',').map(x => Number(x) * 16) + if (Math.hypot((this.lastBotPos.x - x), (this.lastBotPos.z - z)) > this.radius * 5) { + this.chunksStore.delete(key) + } + } + } + + setWarpPosOnClick (mousePos: Vec3) { + this.lastWarpPos = new Vec3(mousePos.x, mousePos.y, mousePos.z) + } + + drawWarps (centerPos?: Vec3) { + for (const warp of this.warps) { + // if (!full) { + // const distance = this.getDistance( + // centerPos?.x ?? this.adapter.playerPosition.x, + // centerPos?.z ?? this.adapter.playerPosition.z, + // warp.x, + // warp.z + // ) + // if (distance > this.mapSize) continue + // } + const offset = this.full ? 0 : this.radius * 0.1 + const z = Math.floor( + (this.mapSize / 2 - (centerPos?.z ?? this.lastBotPos.z) + warp.z) * this.mapPixel + ) + offset + const x = Math.floor( + (this.mapSize / 2 - (centerPos?.x ?? this.lastBotPos.x) + warp.x) * this.mapPixel + ) + offset + const dz = z - this.canvasWidthCenterX + const dx = x - this.canvasWidthCenterY + const circleDist = Math.hypot(dx, dz) + + const angle = Math.atan2(dz, dx) + const circleZ = circleDist > this.mapSize / 2 && !this.full ? + this.canvasWidthCenterX + this.mapSize / 2 * Math.sin(angle) + : z + const circleX = circleDist > this.mapSize / 2 && !this.full ? + this.canvasWidthCenterY + this.mapSize / 2 * Math.cos(angle) + : x + this.ctx.beginPath() + this.ctx.arc( + circleX, + circleZ, + circleDist > this.mapSize / 2 && !this.full + ? this.mapPixel * 1.5 + : this.full ? this.mapPixel : this.mapPixel * 2, + 0, + Math.PI * 2, + false + ) + this.ctx.strokeStyle = 'black' + this.ctx.lineWidth = this.mapPixel + this.ctx.stroke() + this.ctx.fillStyle = warp.disabled ? 'rgba(255, 255, 255, 0.4)' : warp.color ?? '#d3d3d3' + this.ctx.fill() + this.ctx.closePath() + } + } + + drawPartsOfWorld () { + this.ctx.fillStyle = 'white' + this.ctx.shadowOffsetX = 1 + this.ctx.shadowOffsetY = 1 + this.ctx.shadowColor = 'black' + this.ctx.font = `${this.radius / 4}px serif` + this.ctx.textAlign = 'center' + this.ctx.textBaseline = 'middle' + this.ctx.strokeStyle = 'black' + this.ctx.lineWidth = 1 + + const angle = - Math.PI / 2 + const angleS = angle + Math.PI + const angleW = angle + Math.PI * 3 / 2 + const angleE = angle + Math.PI / 2 + + this.ctx.strokeText( + 'N', + this.canvasWidthCenterX + this.radius * Math.cos(angle), + this.canvasWidthCenterY + this.radius * Math.sin(angle) + ) + this.ctx.strokeText( + 'S', + this.canvasWidthCenterX + this.radius * Math.cos(angleS), + this.canvasWidthCenterY + this.radius * Math.sin(angleS) + ) + this.ctx.strokeText( + 'W', + this.canvasWidthCenterX + this.radius * Math.cos(angleW), + this.canvasWidthCenterY + this.radius * Math.sin(angleW) + ) + this.ctx.strokeText( + 'E', + this.canvasWidthCenterX + this.radius * Math.cos(angleE), + this.canvasWidthCenterY + this.radius * Math.sin(angleE) + ) + this.ctx.fillText( + 'N', + this.canvasWidthCenterX + this.radius * Math.cos(angle), + this.canvasWidthCenterY + this.radius * Math.sin(angle) + ) + this.ctx.fillText( + 'S', + this.canvasWidthCenterX + this.radius * Math.cos(angleS), + this.canvasWidthCenterY + this.radius * Math.sin(angleS) + ) + this.ctx.fillText( + 'W', + this.canvasWidthCenterX + this.radius * Math.cos(angleW), + this.canvasWidthCenterY + this.radius * Math.sin(angleW) + ) + this.ctx.fillText( + 'E', + this.canvasWidthCenterX + this.radius * Math.cos(angleE), + this.canvasWidthCenterY + this.radius * Math.sin(angleE) + ) + + this.ctx.shadowOffsetX = 0 + this.ctx.shadowOffsetY = 0 + } + + drawPlayerPos (canvasWorldCenterX?: number, canvasWorldCenterZ?: number, disableTurn?: boolean) { + this.ctx.setTransform(1, 0, 0, 1, 0, 0) + + const x = (this.lastBotPos.x - (canvasWorldCenterX ?? this.lastBotPos.x)) * this.mapPixel + const z = (this.lastBotPos.z - (canvasWorldCenterZ ?? this.lastBotPos.z)) * this.mapPixel + const center = this.mapSize / 2 * this.mapPixel + (this.full ? 0 : this.radius * 0.1) + this.ctx.translate(center + x, center + z) + if (!disableTurn) this.ctx.rotate(-this.yaw) + + const size = 3 + const factor = this.full ? 2 : 1 + const width = size * factor + const height = size * factor + + this.ctx.beginPath() + this.ctx.moveTo(0, -height) + this.ctx.lineTo(-width, height) + this.ctx.lineTo(width, height) + this.ctx.closePath() + + this.ctx.strokeStyle = '#000000' + this.ctx.lineWidth = this.full ? 2 : 1 + this.ctx.stroke() + this.ctx.fillStyle = '#FFFFFF' + this.ctx.fill() + + // Reset transformations + this.ctx.setTransform(1, 0, 0, 1, 0, 0) + } + + rotateMap (angle: number) { + this.ctx.setTransform(1, 0, 0, 1, 0, 0) + this.ctx.translate(this.canvasWidthCenterX, this.canvasWidthCenterY) + this.ctx.rotate(angle) + this.ctx.translate(-this.canvasWidthCenterX, -this.canvasWidthCenterY) + } +} diff --git a/src/react/MinimapProvider.tsx b/src/react/MinimapProvider.tsx new file mode 100644 index 000000000..4b877732b --- /dev/null +++ b/src/react/MinimapProvider.tsx @@ -0,0 +1,610 @@ +import { useEffect, useState } from 'react' +import { versions } from 'minecraft-data' +import { simplify } from 'prismarine-nbt' +import RegionFile from 'prismarine-provider-anvil/src/region' +import { Vec3 } from 'vec3' +import { versionToNumber } from 'prismarine-viewer/viewer/prepare/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 'prismarine-viewer/viewer/lib/mesher/worldConstants' +import { getRenamedData } from 'flying-squid/dist/blockRenames' +import { useSnapshot } from 'valtio' +import BlockData from '../../prismarine-viewer/viewer/lib/moreBlockDataGenerated.json' +import preflatMap from '../preflatMap.json' +import { contro } from '../controls' +import { gameAdditionalState, showModal, hideModal, miscUiState, loadedGameState, activeModalStack } from '../globalState' +import { options } from '../optionsStorage' +import Minimap, { DisplayMode } from './Minimap' +import { ChunkInfo, DrawerAdapter, MapUpdates, MinimapDrawer } from './MinimapDrawer' +import { useIsModalActive } from './utilsApp' + +const getBlockKey = (x: number, z: number) => { + return `${x},${z}` +} + +const findHeightMap = (obj: PCChunk): number[] | undefined => { + function search (obj: any): any | undefined { + for (const key in obj) { + if (['heightmap', 'heightmaps'].includes(key.toLowerCase())) { + return obj[key] + } else if (typeof obj[key] === 'object' && obj[key] !== null) { + const result = search(obj[key]) + return result + } + } + } + return search(obj) +} + +export class DrawerAdapterImpl extends TypedEventEmitter implements DrawerAdapter { + playerPosition: Vec3 + yaw: number + mapDrawer = new MinimapDrawer() + warps: WorldWarp[] + world: string + chunksStore = new Map() + loadingChunksQueue = new Set() + currChunk: PCChunk | undefined + currChunkPos: { x: number, z: number } = { x: 0, z: 0 } + isOldVersion: boolean + blockData: any + heightMap: Record = {} + regions = new Map() + chunksHeightmaps: Record = {} + loadChunk: (key: string) => Promise + loadChunkFullmap: ((key: string) => Promise) | undefined + _full: boolean + isBuiltinHeightmapAvailable = false + + constructor (pos?: Vec3) { + super() + this.full = false + this.playerPosition = pos ?? new Vec3(0, 0, 0) + this.warps = gameAdditionalState.warps + this.mapDrawer.warps = this.warps + this.mapDrawer.loadChunk = this.loadChunk + this.mapDrawer.loadingChunksQueue = this.loadingChunksQueue + this.mapDrawer.chunksStore = this.chunksStore + + // check if should use heightmap + if (localServer) { + const chunkX = Math.floor(this.playerPosition.x / 16) + const chunkZ = Math.floor(this.playerPosition.z / 16) + const regionX = Math.floor(chunkX / 32) + const regionZ = Math.floor(chunkZ / 32) + const regionKey = `${regionX},${regionZ}` + const worldFolder = this.getSingleplayerRootPath() + if (worldFolder && options.minimapOptimizations) { + const path = `${worldFolder}/region/r.${regionX}.${regionZ}.mca` + const region = new RegionFile(path) + void region.initialize() + this.regions.set(regionKey, region) + const readX = chunkX % 32 + const readZ = chunkZ % 32 + void this.regions.get(regionKey)!.read(readX, readZ).then((rawChunk) => { + const chunk = simplify(rawChunk as any) + const heightmap = findHeightMap(chunk) + if (heightmap) { + this.isBuiltinHeightmapAvailable = true + this.loadChunkFullmap = this.loadChunkFromRegion + console.log('using heightmap') + } else { + this.isBuiltinHeightmapAvailable = false + this.loadChunkFullmap = this.loadChunkNoRegion + console.log('[minimap] not using heightmap') + } + }).catch(err => { + console.error(err) + this.isBuiltinHeightmapAvailable = false + this.loadChunkFullmap = this.loadChunkFromViewer + }) + } else { + this.isBuiltinHeightmapAvailable = false + this.loadChunkFullmap = this.loadChunkFromViewer + } + } else { + this.isBuiltinHeightmapAvailable = false + this.loadChunkFullmap = this.loadChunkFromViewer + } + // if (localServer) { + // this.overwriteWarps(localServer.warps) + // this.on('cellReady', (key: string) => { + // if (this.loadingChunksQueue.size === 0) return + // const [x, z] = this.loadingChunksQueue.values().next().value.split(',').map(Number) + // this.loadChunk(x, z) + // this.loadingChunksQueue.delete(`${x},${z}`) + // }) + // } else { + // const storageWarps = localStorage.getItem(`warps: ${loadedGameState.username} ${loadedGameState.serverIp ?? ''}`) + // this.overwriteWarps(JSON.parse(storageWarps ?? '[]')) + // } + this.isOldVersion = versionToNumber(bot.version) < versionToNumber('1.13') + this.blockData = {} + for (const blockKey of Object.keys(BlockData.colors)) { + const renamedKey = getRenamedData('blocks', blockKey, '1.20.2', bot.version) + this.blockData[renamedKey as string] = BlockData.colors[blockKey] + } + + viewer.world?.renderUpdateEmitter.on('chunkFinished', (key) => { + if (!this.loadingChunksQueue.has(key)) return + void this.loadChunk(key) + this.loadingChunksQueue.delete(key) + }) + } + + get full () { + return this._full + } + + set full (full: boolean) { + console.log('this is minimap') + this.loadChunk = this.loadChunkMinimap + this.mapDrawer.loadChunk = this.loadChunk + this._full = full + } + + overwriteWarps (newWarps: WorldWarp[]) { + this.warps.splice(0, this.warps.length) + for (const warp of newWarps) { + this.warps.push({ ...warp }) + } + } + + setWarp (warp: WorldWarp, remove?: boolean): void { + this.world = bot.game.dimension + const index = this.warps.findIndex(w => w.name === warp.name) + if (index === -1) { + this.warps.push(warp) + } else if (remove && index !== -1) { + this.warps.splice(index, 1) + } else { + this.warps[index] = warp + } + if (localServer) { + // type suppressed until server is updated. It works fine + void (localServer as any).setWarp(warp, remove) + } else if (remove) { + localStorage.removeItem(`warps: ${loadedGameState.username} ${loadedGameState.serverIp}`) + } else { + localStorage.setItem(`warps: ${loadedGameState.username} ${loadedGameState.serverIp}`, JSON.stringify(this.warps)) + } + this.emit('updateWarps') + } + + getHighestBlockY (x: number, z: number, chunk?: Chunk) { + const chunkX = Math.floor(x / 16) * 16 + const chunkZ = Math.floor(z / 16) * 16 + if (this.chunksHeightmaps[`${chunkX},${chunkZ}`]) { + return this.chunksHeightmaps[`${chunkX},${chunkZ}`][x - chunkX + (z - chunkZ) * 16] - 1 + } + const source = chunk ?? bot.world + const { height, minY } = (bot.game as any) + for (let i = height; i > 0; i -= 1) { + const block = source.getBlock(new Vec3(x & 15, minY + i, z & 15)) + if (block && !INVISIBLE_BLOCKS.has(block.name)) { + return minY + i + } + } + return minY + } + + async getChunkSingleplayer (chunkX: number, chunkZ: number) { + // absolute coords + const region = (localServer!.overworld.storageProvider as any).getRegion(chunkX * 16, chunkZ * 16) + if (!region) return 'unavailable' + const chunk = await localServer!.players[0]!.world.getColumn(chunkX, chunkZ) + return chunk + } + + async loadChunkMinimap (key: string) { + const [chunkX, chunkZ] = key.split(',').map(Number) + const chunkWorldX = chunkX * 16 + const chunkWorldZ = chunkZ * 16 + if (viewer.world.finishedChunks[`${chunkWorldX},${chunkWorldZ}`]) { + const heightmap = new Uint8Array(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) { + const blockX = chunkWorldX + x + const blockZ = chunkWorldZ + z + const hBlock = viewer.world.highestBlocks.get(`${blockX},${blockZ}`) + const block = bot.world.getBlock(new Vec3(blockX, hBlock?.y ?? 0, blockZ)) + // const block = Block.fromStateId(hBlock?.stateId ?? -1, hBlock?.biomeId ?? -1) + const index = z * 16 + x + if (!block || !hBlock) { + console.warn(`[loadChunk] ${chunkX}, ${chunkZ}, ${chunkWorldX + x}, ${chunkWorldZ + z}`) + heightmap[index] = 0 + colors[index] = 'rgba(0, 0, 0, 0.5)' + continue + } + heightmap[index] = hBlock.y + let color: string + if (this.isOldVersion) { + color = BlockData.colors[preflatMap.blocks[`${block.type}:${block.metadata}`]?.replaceAll(/\[.*?]/g, '')] + ?? 'rgb(0, 0, 255)' + } else { + color = this.blockData[block.name] ?? 'rgb(0, 255, 0)' + } + colors[index] = color + } + } + const chunk = { heightmap, colors } + this.applyShadows(chunk) + this.chunksStore.set(key, chunk) + this.emit(`chunkReady`, `${chunkX},${chunkZ}`) + } else { + this.loadingChunksQueue.add(`${chunkX},${chunkZ}`) + this.chunksStore.set(key, 'requested') + } + } + + async loadChunkNoRegion (key: string) { + const [chunkX, chunkZ] = key.split(',').map(Number) + const chunkWorldX = chunkX * 16 + const chunkWorldZ = chunkZ * 16 + const chunkInfo = await this.getChunkSingleplayer(chunkX, chunkZ) + if (chunkInfo === 'unavailable') return null + const heightmap = new Uint8Array(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) { + const blockX = chunkWorldX + x + const blockZ = chunkWorldZ + z + const blockY = this.getHighestBlockY(blockX, blockZ, chunkInfo) + const block = chunkInfo.getBlock(new Vec3(blockX & 15, blockY, blockZ & 15)) + if (!block) { + console.warn(`[cannot get the block] ${chunkX}, ${chunkZ}, ${chunkWorldX + x}, ${chunkWorldZ + z}`) + return null + } + const index = z * 16 + x + heightmap[index] = blockY + const color = this.isOldVersion ? BlockData.colors[preflatMap.blocks[`${block.type}:${block.metadata}`]?.replaceAll(/\[.*?]/g, '')] ?? 'rgb(0, 0, 255)' : this.blockData[block.name] ?? 'rgb(0, 255, 0)' + colors[index] = color + } + } + const chunk: ChunkInfo = { heightmap, colors } + this.applyShadows(chunk) + return chunk + } + + async loadChunkFromRegion (key: string): Promise { + const [chunkX, chunkZ] = key.split(',').map(Number) + const chunkWorldX = chunkX * 16 + const chunkWorldZ = chunkZ * 16 + const heightmap = await this.getChunkHeightMapFromRegion(chunkX, chunkZ) as unknown as Uint8Array + if (!heightmap) return null + const chunkInfo = await this.getChunkSingleplayer(chunkX, chunkZ) + if (chunkInfo === 'unavailable') return null + 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) { + const blockX = chunkWorldX + x + const blockZ = chunkWorldZ + z + const index = z * 16 + x + heightmap[index] -= 1 + if (heightmap[index] < 0) heightmap[index] = 0 + const blockY = heightmap[index] + const block = chunkInfo.getBlock(new Vec3(blockX & 15, blockY, blockZ & 15)) + if (!block) { + console.warn(`[cannot get the block] ${chunkX}, ${chunkZ}, ${chunkWorldX + x}, ${chunkWorldZ + z}`) + return null + } + const color = this.isOldVersion ? BlockData.colors[preflatMap.blocks[`${block.type}:${block.metadata}`]?.replaceAll(/\[.*?]/g, '')] ?? 'rgb(0, 0, 255)' : this.blockData[block.name] ?? 'rgb(0, 255, 0)' + colors[index] = color + } + } + const chunk: ChunkInfo = { heightmap, colors } + this.applyShadows(chunk) + return chunk + } + + getSingleplayerRootPath (): string | undefined { + return localServer!.options.worldFolder + } + + async getChunkHeightMapFromRegion (chunkX: number, chunkZ: number, cb?: (hm: number[]) => void) { + const regionX = Math.floor(chunkX / 32) + const regionZ = Math.floor(chunkZ / 32) + const regionKey = `${regionX},${regionZ}` + if (!this.regions.has(regionKey)) { + const worldFolder = this.getSingleplayerRootPath() + if (!worldFolder) return + const path = `${worldFolder}/region/r.${regionX}.${regionZ}.mca` + const region = new RegionFile(path) + await region.initialize() + this.regions.set(regionKey, region) + } + const rawChunk = await this.regions.get(regionKey)!.read(chunkX % 32, chunkZ % 32) + const chunk = simplify(rawChunk as any) + console.log(`chunk ${chunkX}, ${chunkZ}:`, chunk) + const heightmap = findHeightMap(chunk) + console.log(`heightmap ${chunkX}, ${chunkZ}:`, heightmap) + cb?.(heightmap!) + return heightmap + // this.chunksHeightmaps[`${chunkX},${chunkZ}`] = heightmap + } + + async loadChunkFromViewer (key: string) { + const [chunkX, chunkZ] = key.split(',').map(Number) + const chunkWorldX = chunkX * 16 + const chunkWorldZ = chunkZ * 16 + if (viewer.world.finishedChunks[`${chunkWorldX},${chunkWorldZ}`]) { + const heightmap = new Uint8Array(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) { + const blockX = chunkWorldX + x + const blockZ = chunkWorldZ + z + const hBlock = viewer.world.highestBlocks.get(`${blockX},${blockZ}`) + const block = bot.world.getBlock(new Vec3(blockX, hBlock?.y ?? 0, blockZ)) + // const block = Block.fromStateId(hBlock?.stateId ?? -1, hBlock?.biomeId ?? -1) + const index = z * 16 + x + if (!block || !hBlock) { + console.warn(`[loadChunk] ${chunkX}, ${chunkZ}, ${chunkWorldX + x}, ${chunkWorldZ + z}`) + heightmap[index] = 0 + colors[index] = 'rgba(0, 0, 0, 0.5)' + continue + } + heightmap[index] = hBlock.y + const color = this.isOldVersion ? BlockData.colors[preflatMap.blocks[`${block.type}:${block.metadata}`]?.replaceAll(/\[.*?]/g, '')] ?? 'rgb(0, 0, 255)' : this.blockData[block.name] ?? 'rgb(0, 255, 0)' + colors[index] = color + } + } + const chunk = { heightmap, colors } + this.applyShadows(chunk) + return chunk + } else { + return null + } + } + + applyShadows (chunk: ChunkInfo) { + for (let j = 0; j < 16; j += 1) { + for (let i = 0; i < 16; i += 1) { + const index = j * 16 + i + const color = chunk.colors[index] + // if (i === 0 || j === 0 || i === 15 || j === 16) { + // const r = Math.floor(Math.random() * 2) + // chunk.colors[index] = r===0 ? this.makeDarker(color) : this.makeLighter(color) + // continue + // } + + const h = chunk.heightmap[index] + let isLighterOrDarker = 0 + + const r = chunk.heightmap[index + 1] ?? 0 + const u = chunk.heightmap[index - 16] ?? 0 + const ur = chunk.heightmap[index - 15] ?? 0 + if (r > h || u > h || ur > h) { + chunk.colors[index] = this.makeDarker(color) + isLighterOrDarker -= 1 + } + + const l = chunk.heightmap[index - 1] ?? 0 + const d = chunk.heightmap[index + 16] ?? 0 + const dl = chunk.heightmap[index + 15] ?? 0 + if (l > h || d > h || dl > h) { + chunk.colors[index] = this.makeLighter(color) + isLighterOrDarker += 1 + } + + let linkedIndex: number | undefined + if (i === 1) { + linkedIndex = index - 1 + } else if (i === 14) { + linkedIndex = index + 1 + } else if (j === 1) { + linkedIndex = index - 16 + } else if (j === 14) { + linkedIndex = index + 16 + } + if (linkedIndex !== undefined) { + const linkedColor = chunk.colors[linkedIndex] + switch (isLighterOrDarker) { + case 1: + chunk.colors[linkedIndex] = this.makeLighter(linkedColor) + break + case -1: + chunk.colors[linkedIndex] = this.makeDarker(linkedColor) + break + default: + break + } + } + } + } + } + + makeDarker (color: string) { + let rgbArray = color.match(/\d+/g)?.map(Number) ?? [] + if (rgbArray.length !== 3) return color + rgbArray = rgbArray.map(element => { + let newColor = element - 20 + if (newColor < 0) newColor = 0 + return newColor + }) + return `rgb(${rgbArray.join(',')})` + } + + makeLighter (color: string) { + let rgbArray = color.match(/\d+/g)?.map(Number) ?? [] + if (rgbArray.length !== 3) return color + rgbArray = rgbArray.map(element => { + let newColor = element + 20 + if (newColor > 255) newColor = 255 + return newColor + }) + return `rgb(${rgbArray.join(',')})` + } + + clearChunksStore (x: number, z: number) { + for (const key of Object.keys(this.chunksStore)) { + const [chunkX, chunkZ] = key.split(',').map(Number) + if (Math.hypot((chunkX - x), (chunkZ - z)) > 300) { + delete this.chunksStore[key] + delete this.chunksHeightmaps[key] + for (let i = 0; i < 16; i += 1) { + for (let j = 0; j < 16; j += 1) { + delete this.heightMap[`${chunkX + i},${chunkZ + j}`] + } + } + } + } + } + + quickTp (x: number, z: number) { + const y = this.getHighestBlockY(x, z) + bot.chat(`/tp ${x} ${y + 20} ${z}`) + const timeout = setTimeout(() => { + const y = this.getHighestBlockY(x, z) + bot.chat(`/tp ${x} ${y + 20} ${z}`) + clearTimeout(timeout) + }, 500) + } + + async drawChunkOnCanvas (key: string, canvas: HTMLCanvasElement) { + // console.log('chunk', key, 'on canvas') + if (!this.loadChunkFullmap) { + // wait for it to be available + await new Promise(resolve => { + const interval = setInterval(() => { + if (this.loadChunkFullmap) { + clearInterval(interval) + resolve(undefined) + } + }, 100) + setTimeout(() => { + clearInterval(interval) + resolve(undefined) + }, 10_000) + }) + if (!this.loadChunkFullmap) { + throw new Error('loadChunkFullmap not available') + } + } + const chunk = await this.loadChunkFullmap(key) + const [worldX, worldZ] = key.split(',').map(x => Number(x) * 16) + const center = new Vec3(worldX + 8, 0, worldZ + 8) + this.mapDrawer.lastBotPos = center + this.mapDrawer.canvas = canvas + this.mapDrawer.full = true + this.mapDrawer.drawChunk(key, chunk) + } +} + +const Inner = ( + { adapter, displayMode, toggleFullMap }: + { + adapter: DrawerAdapterImpl + displayMode?: DisplayMode, + toggleFullMap?: ({ command }: { command?: string }) => void + } +) => { + + const updateWarps = (newWarps: WorldWarp[] | Error) => { + if (newWarps instanceof Error) { + console.error('An error occurred:', newWarps.message) + return + } + + adapter.overwriteWarps(newWarps) + } + + const updateMap = () => { + if (!adapter) return + adapter.playerPosition = bot.entity.position + adapter.yaw = bot.entity.yaw + adapter.emit('updateMap') + } + + useEffect(() => { + bot.on('move', updateMap) + localServer?.on('warpsUpdated' as keyof ServerEvents, updateWarps) + + return () => { + bot?.off('move', updateMap) + localServer?.off('warpsUpdated' as keyof ServerEvents, updateWarps) + } + }, []) + + return
+ +
+} + +export default ({ displayMode }: { displayMode?: DisplayMode }) => { + const [adapter] = useState(() => new DrawerAdapterImpl(bot.entity.position)) + + const { showMinimap } = useSnapshot(options) + const fullMapOpened = useIsModalActive('full-map') + + + const readChunksHeightMaps = async () => { + const { worldFolder } = localServer!.options + const path = `${worldFolder}/region/r.0.0.mca` + const region = new RegionFile(path) + await region.initialize() + const chunks: Record = {} + console.log('Reading chunks...') + console.log(chunks) + let versionDetected = false + for (const [i, _] of Array.from({ length: 32 }).entries()) { + for (const [k, _] of Array.from({ length: 32 }).entries()) { + // todo, may use faster reading, but features is not commonly used + // eslint-disable-next-line no-await-in-loop + const nbt = await region.read(i, k) + chunks[`${i},${k}`] = nbt + if (nbt && !versionDetected) { + const simplified = simplify(nbt) + const version = versions.pc.find(x => x['dataVersion'] === simplified.DataVersion)?.minecraftVersion + console.log('Detected version', version ?? 'unknown') + versionDetected = true + } + } + } + Object.defineProperty(chunks, 'simplified', { + get () { + const mapped = {} + for (const [i, _] of Array.from({ length: 32 }).entries()) { + for (const [k, _] of Array.from({ length: 32 }).entries()) { + const key = `${i},${k}` + const chunk = chunks[key] + if (!chunk) continue + mapped[key] = simplify(chunk) + } + } + return mapped + }, + }) + console.log('Done!', chunks) + } + + if ( + displayMode === 'minimapOnly' + ? showMinimap === 'never' || (showMinimap === 'singleplayer' && !miscUiState.singleplayer) + : !fullMapOpened + ) { + return null + } + + const toggleFullMap = () => { + if (activeModalStack.at(-1)?.reactType === 'full-map') { + hideModal({ reactType: 'full-map' }) + } else { + showModal({ reactType: 'full-map' }) + } + } + + return +} diff --git a/src/react/Screen.tsx b/src/react/Screen.tsx index c80b880ac..6654e4ddf 100644 --- a/src/react/Screen.tsx +++ b/src/react/Screen.tsx @@ -4,15 +4,16 @@ interface Props { backdrop?: boolean | 'dirt' style?: React.CSSProperties className?: string + titleSelectable?: boolean } -export default ({ title, children, backdrop = true, style, className }: Props) => { +export default ({ title, children, backdrop = true, style, className, titleSelectable }: Props) => { return ( <> {backdrop === 'dirt' ?
: backdrop ?
: null}
-
{title}
+
{title}
{children}
diff --git a/src/react/ServersListProvider.tsx b/src/react/ServersListProvider.tsx index f42fb11bb..c5cff9f2f 100644 --- a/src/react/ServersListProvider.tsx +++ b/src/react/ServersListProvider.tsx @@ -9,6 +9,7 @@ import AddServerOrConnect, { BaseServerInfo } from './AddServerOrConnect' import { useDidUpdateEffect } from './utils' import { useIsModalActive } from './utilsApp' import { showOptionsModal } from './SelectOption' +import { useCopyKeybinding } from './simpleHooks' interface StoreServerItem extends BaseServerInfo { lastJoined?: number @@ -92,7 +93,11 @@ const getInitialServersList = () => { return servers } -const setNewServersList = (serversList: StoreServerItem[]) => { +const serversListQs = new URLSearchParams(window.location.search).get('serversList') +const proxyQs = new URLSearchParams(window.location.search).get('proxy') + +const setNewServersList = (serversList: StoreServerItem[], force = false) => { + if (serversListQs && !force) return localStorage['serversList'] = JSON.stringify(serversList) // cleanup legacy @@ -133,13 +138,14 @@ export const updateAuthenticatedAccountData = (callback: (data: AuthenticatedAcc // todo move to base const normalizeIp = (ip: string) => ip.replace(/https?:\/\//, '').replace(/\/(:|$)/, '') -const Inner = ({ hidden }: { hidden?: boolean }) => { +const Inner = ({ hidden, customServersList }: { hidden?: boolean, customServersList?: string[] }) => { const [proxies, setProxies] = useState(localStorage['proxies'] ? JSON.parse(localStorage['proxies']) : getInitialProxies()) - const [selectedProxy, setSelectedProxy] = useState(localStorage.getItem('selectedProxy') ?? proxies?.[0] ?? '') + const [selectedProxy, setSelectedProxy] = useState(proxyQs ?? localStorage.getItem('selectedProxy') ?? proxies?.[0] ?? '') const [serverEditScreen, setServerEditScreen] = useState(null) // true for add const [defaultUsername, _setDefaultUsername] = useState(localStorage['username'] ?? (`mcrafter${Math.floor(Math.random() * 1000)}`)) const [authenticatedAccounts, _setAuthenticatedAccounts] = useState(JSON.parse(localStorage['authenticatedAccounts'] || '[]')) const [quickConnectIp, setQuickConnectIp] = useState('') + const [selectedIndex, setSelectedIndex] = useState(-1) const setAuthenticatedAccounts = (newState: typeof authenticatedAccounts) => { _setAuthenticatedAccounts(newState) @@ -151,18 +157,35 @@ const Inner = ({ hidden }: { hidden?: boolean }) => { localStorage.setItem('username', newState) } + const saveNewProxy = () => { + if (!selectedProxy || proxyQs) return + localStorage.setItem('selectedProxy', selectedProxy) + } + useEffect(() => { if (proxies.length) { localStorage.setItem('proxies', JSON.stringify(proxies)) } - if (selectedProxy) { - localStorage.setItem('selectedProxy', selectedProxy) - } + saveNewProxy() }, [proxies]) - const [serversList, setServersList] = useState(() => getInitialServersList()) + const [serversList, setServersList] = useState(() => (customServersList ? [] : getInitialServersList())) const [additionalData, setAdditionalData] = useState>({}) + useEffect(() => { + if (customServersList) { + setServersList(customServersList.map(row => { + const [ip, name] = row.split(' ') + const [_ip, _port, version] = ip.split(':') + return { + ip, + versionOverride: version, + name, + } + })) + } + }, [customServersList]) + useDidUpdateEffect(() => { // save data only on user changes setNewServersList(serversList) @@ -218,6 +241,16 @@ const Inner = ({ hidden }: { hidden?: boolean }) => { } }, [isEditScreenModal]) + useCopyKeybinding(() => { + const item = serversList[selectedIndex] + if (!item) return + let str = `${item.ip}` + if (item.versionOverride) { + str += `:${item.versionOverride}` + } + return str + }) + const editModalJsx = isEditScreenModal ?
}
- {serversLayout ? : } - + {serversLayout ? : } + {serversLayout ? - : + : }
diff --git a/src/react/mainMenu.module.css b/src/react/mainMenu.module.css index db072ce1a..dcec47c3e 100644 --- a/src/react/mainMenu.module.css +++ b/src/react/mainMenu.module.css @@ -45,7 +45,7 @@ display: block; position: absolute; top: 37px; - left: calc(88px + 5px); + left: calc((512px / 2 - 176px / 2) / 2); background-image: url('../../assets/edition.png'); background-size: 128px; width: 88px; diff --git a/src/react/simpleHooks.ts b/src/react/simpleHooks.ts index 9202bfa2b..da8dd9e0e 100644 --- a/src/react/simpleHooks.ts +++ b/src/react/simpleHooks.ts @@ -1,6 +1,27 @@ +import { useUtilsEffect } from '@zardoy/react-util' import { useMedia } from 'react-use' const SMALL_SCREEN_MEDIA = '@media (max-width: 440px)' export const useIsSmallWidth = () => { return useMedia(SMALL_SCREEN_MEDIA.replace('@media ', '')) } + +export const useCopyKeybinding = (getCopyText: () => string | undefined) => { + useUtilsEffect(({ signal }) => { + addEventListener('keydown', (e) => { + if (e.code === 'KeyC' && (e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) { + const { activeElement } = document + if (activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement) { + return + } + if (window.getSelection()?.toString()) { + return + } + e.preventDefault() + const copyText = getCopyText() + if (!copyText) return + void navigator.clipboard.writeText(copyText) + } + }, { signal }) + }, [getCopyText]) +} diff --git a/src/react/useLongPress.ts b/src/react/useLongPress.ts index 3807221d0..49a1dec6a 100644 --- a/src/react/useLongPress.ts +++ b/src/react/useLongPress.ts @@ -31,9 +31,9 @@ const useLongPress = ( ) const clear = useCallback( - (event: React.MouseEvent | React.TouchEvent, shouldTriggerClick = true) => { + (event: React.MouseEvent | React.TouchEvent) => { if (timeout.current) clearTimeout(timeout.current) - if (shouldTriggerClick && !longPressTriggered) onClick() + if (!longPressTriggered) onClick() setLongPressTriggered(false) if (shouldPreventDefault && target.current) { target.current.removeEventListener('touchend', preventDefault) @@ -46,7 +46,7 @@ const useLongPress = ( onMouseDown: (e: React.MouseEvent) => start(e), onTouchStart: (e: React.TouchEvent) => start(e), onMouseUp: (e: React.MouseEvent) => clear(e), - onMouseLeave: (e: React.MouseEvent) => clear(e, false), + onMouseLeave: (e: React.MouseEvent) => clear(e), onTouchEnd: (e: React.TouchEvent) => clear(e) } } @@ -61,4 +61,3 @@ const preventDefault = (event: Event) => { } export default useLongPress - diff --git a/src/react/utilsApp.ts b/src/react/utilsApp.ts index 53df4cda0..445007ec7 100644 --- a/src/react/utilsApp.ts +++ b/src/react/utilsApp.ts @@ -6,7 +6,8 @@ import { activeModalStack, miscUiState } from '../globalState' export const watchedModalsFromHooks = new Set() // todo should not be there export const hardcodedKnownModals = [ - 'player_win:' + 'player_win:', + 'full-map' // todo ] export const useUsingTouch = () => { @@ -17,6 +18,7 @@ export const useIsModalActive = (modal: string, useIncludes = false) => { watchedModalsFromHooks.add(modal) }, []) useEffect(() => { + // watchedModalsFromHooks.add(modal) return () => { watchedModalsFromHooks.delete(modal) } diff --git a/src/reactUi.tsx b/src/reactUi.tsx index 2fb63c197..f0144d140 100644 --- a/src/reactUi.tsx +++ b/src/reactUi.tsx @@ -19,6 +19,7 @@ import ScoreboardProvider from './react/ScoreboardProvider' import SignEditorProvider from './react/SignEditorProvider' import IndicatorEffectsProvider from './react/IndicatorEffectsProvider' import PlayerListOverlayProvider from './react/PlayerListOverlayProvider' +import MinimapProvider from './react/MinimapProvider' import HudBarsProvider from './react/HudBarsProvider' import XPBarProvider from './react/XPBarProvider' import DebugOverlay from './react/DebugOverlay' @@ -27,7 +28,7 @@ import PauseScreen from './react/PauseScreen' import SoundMuffler from './react/SoundMuffler' import TouchControls from './react/TouchControls' import widgets from './react/widgets' -import { useIsWidgetActive } from './react/utilsApp' +import { useIsModalActive, useIsWidgetActive } from './react/utilsApp' import GlobalSearchInput from './react/GlobalSearchInput' import TouchAreasControlsProvider from './react/TouchAreasControlsProvider' import NotificationProvider, { showNotification } from './react/NotificationProvider' @@ -101,9 +102,13 @@ const InGameComponent = ({ children }) => { const InGameUi = () => { const { gameLoaded, showUI: showUIRaw } = useSnapshot(miscUiState) - const { disabledUiParts, displayBossBars } = useSnapshot(options) - const hasModals = useSnapshot(activeModalStack).length > 0 + const { disabledUiParts, displayBossBars, showMinimap } = useSnapshot(options) + const modalsSnapshot = useSnapshot(activeModalStack) + const hasModals = modalsSnapshot.length > 0 const showUI = showUIRaw || hasModals + const displayFullmap = modalsSnapshot.some(modal => modal.reactType === 'full-map') + // bot can't be used here + if (!gameLoaded || !bot || disabledUiParts.includes('*')) return return <> @@ -116,6 +121,7 @@ const InGameUi = () => { {!disabledUiParts.includes('players-list') && } {!disabledUiParts.includes('chat') && } + {showMinimap !== 'never' && } {!disabledUiParts.includes('title') && } {!disabledUiParts.includes('scoreboard') && } {!disabledUiParts.includes('effects-indicators') && } @@ -137,6 +143,7 @@ const InGameUi = () => { + {displayFullmap && } {/* because of z-index */} {showUI && } diff --git a/src/styles.css b/src/styles.css index 817fae8ca..2c645ae92 100644 --- a/src/styles.css +++ b/src/styles.css @@ -119,7 +119,7 @@ body { @font-face { font-family: mojangles; - src: url(../assets/mojangles.ttf); + src: url(../assets/mojangles.ttf?inline); } #ui-root { @@ -181,6 +181,10 @@ body::xr-overlay #viewer-canvas { color: #999; } +.text-select { + user-select: text; +} + @media screen and (min-width: 430px) { .span-2 { grid-column: span 2; diff --git a/src/topRightStats.ts b/src/topRightStats.ts index 4bcd7264e..fd717ef48 100644 --- a/src/topRightStats.ts +++ b/src/topRightStats.ts @@ -88,13 +88,40 @@ export const statsEnd = () => { // for advanced debugging, use with watch expression +window.statsPerSecAvg = {} +let currentStatsPerSec = {} as Record +const waitingStatsPerSec = {} +window.markStart = (label) => { + waitingStatsPerSec[label] ??= [] + waitingStatsPerSec[label][0] = performance.now() +} +window.markEnd = (label) => { + if (!waitingStatsPerSec[label]?.[0]) return + currentStatsPerSec[label] ??= [] + currentStatsPerSec[label].push(performance.now() - waitingStatsPerSec[label][0]) + delete waitingStatsPerSec[label] +} +const updateStatsPerSecAvg = () => { + window.statsPerSecAvg = Object.fromEntries(Object.entries(currentStatsPerSec).map(([key, value]) => { + return [key, { + avg: value.reduce((a, b) => a + b, 0) / value.length, + count: value.length + }] + })) + currentStatsPerSec = {} +} + + window.statsPerSec = {} -let statsPerSec = {} +let statsPerSecCurrent = {} window.addStatPerSec = (name) => { - statsPerSec[name] ??= 0 - statsPerSec[name]++ + statsPerSecCurrent[name] ??= 0 + statsPerSecCurrent[name]++ } +window.statsPerSecCurrent = statsPerSecCurrent setInterval(() => { - window.statsPerSec = statsPerSec - statsPerSec = {} + window.statsPerSec = statsPerSecCurrent + statsPerSecCurrent = {} + window.statsPerSecCurrent = statsPerSecCurrent + updateStatsPerSecAvg() }, 1000) diff --git a/src/watchOptions.ts b/src/watchOptions.ts index 4b69726c9..84092de27 100644 --- a/src/watchOptions.ts +++ b/src/watchOptions.ts @@ -96,6 +96,6 @@ export const watchOptionsAfterWorldViewInit = () => { watchValue(options, o => { if (!worldView) return worldView.keepChunksDistance = o.keepChunksDistance - worldView.handDisplay = o.handDisplay + viewer.world.config.displayHand = o.handDisplay }) } diff --git a/src/water.ts b/src/water.ts index 2d3be46fd..94875e33d 100644 --- a/src/water.ts +++ b/src/water.ts @@ -31,9 +31,6 @@ customEvents.on('gameLoaded', () => { let sceneBg = { r: 0, g: 0, b: 0 } export const updateBackground = (newSceneBg = sceneBg) => { sceneBg = newSceneBg - if (inWater) { - viewer.scene.background = new THREE.Color(0x00_00_ff) - } else { - viewer.scene.background = new THREE.Color(sceneBg.r, sceneBg.g, sceneBg.b) - } + const color: [number, number, number] = inWater ? [0, 0, 1] : [sceneBg.r, sceneBg.g, sceneBg.b] + viewer.world.changeBackgroundColor(color) } diff --git a/src/worldInteractions.ts b/src/worldInteractions.ts index dcd5dc3d0..1134d7f89 100644 --- a/src/worldInteractions.ts +++ b/src/worldInteractions.ts @@ -4,7 +4,7 @@ import * as THREE from 'three' // wouldn't better to create atlas instead? import { Vec3 } from 'vec3' -import { LineMaterial, Wireframe, LineSegmentsGeometry } from 'three-stdlib' +import { LineMaterial } from 'three-stdlib' import { Entity } from 'prismarine-entity' import destroyStage0 from '../assets/destroy_stage_0.png' import destroyStage1 from '../assets/destroy_stage_1.png' @@ -34,7 +34,6 @@ function getViewDirection (pitch, yaw) { class WorldInteraction { ready = false - interactionLines: null | { blockPos; mesh } = null prevBreakState currentDigTime prevOnGround @@ -44,11 +43,9 @@ class WorldInteraction { lastButtons = [false, false, false] breakStartTime: number | undefined = 0 lastDugBlock: Vec3 | null = null - cursorBlock: import('prismarine-block').Block | null = null blockBreakMesh: THREE.Mesh breakTextures: THREE.Texture[] lastDigged: number - lineMaterial: LineMaterial debugDigStatus: string oneTimeInit () { @@ -109,10 +106,10 @@ class WorldInteraction { }) beforeRenderFrame.push(() => { - if (this.lineMaterial) { + if (viewer.world.threejsCursorLineMaterial) { const { renderer } = viewer - this.lineMaterial.resolution.set(renderer.domElement.width, renderer.domElement.height) - this.lineMaterial.dashOffset = performance.now() / 750 + viewer.world.threejsCursorLineMaterial.resolution.set(renderer.domElement.width, renderer.domElement.height) + viewer.world.threejsCursorLineMaterial.dashOffset = performance.now() / 750 } }) } @@ -133,7 +130,7 @@ class WorldInteraction { this.debugDigStatus = 'done' }) bot.on('diggingAborted', (block) => { - if (!this.cursorBlock?.position.equals(block.position)) return + if (!viewer.world.cursorBlock?.equals(block.position)) return this.debugDigStatus = 'aborted' // if (this.lastDugBlock) this.breakStartTime = undefined @@ -151,7 +148,7 @@ class WorldInteraction { const upLineMaterial = () => { const inCreative = bot.game.gameMode === 'creative' const pixelRatio = viewer.renderer.getPixelRatio() - this.lineMaterial = new LineMaterial({ + viewer.world.threejsCursorLineMaterial = new LineMaterial({ color: inCreative ? 0x40_80_ff : 0x00_00_00, linewidth: Math.max(pixelRatio * 0.7, 1) * 2, // dashed: true, @@ -192,34 +189,6 @@ class WorldInteraction { } } - updateBlockInteractionLines (blockPos: Vec3 | null, shapePositions?: Array<{ position; width; height; depth }>) { - assertDefined(viewer) - if (blockPos && this.interactionLines && blockPos.equals(this.interactionLines.blockPos)) { - return - } - if (this.interactionLines !== null) { - viewer.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.lineMaterial) - const pos = blockPos.plus(position) - wireframe.position.set(pos.x, pos.y, pos.z) - wireframe.computeLineDistances() - group.add(wireframe) - } - viewer.scene.add(group) - this.interactionLines = { blockPos, mesh: group } - } - // todo this shouldnt be done in the render loop, migrate the code to dom events to avoid delays on lags update () { const inSpectator = bot.game.gameMode === 'spectator' @@ -232,10 +201,7 @@ class WorldInteraction { let cursorBlockDiggable = cursorBlock if (cursorBlock && !bot.canDigBlock(cursorBlock) && bot.game.gameMode !== 'creative') cursorBlockDiggable = null - let cursorChanged = !cursorBlock !== !this.cursorBlock - if (cursorBlock && this.cursorBlock) { - cursorChanged = !cursorBlock.position.equals(this.cursorBlock.position) - } + const cursorChanged = cursorBlock && viewer.world.cursorBlock ? !viewer.world.cursorBlock.equals(cursorBlock.position) : viewer.world.cursorBlock !== cursorBlock // Place / interact / activate if (this.buttons[2] && this.lastBlockPlaced >= 4) { @@ -291,8 +257,8 @@ class WorldInteraction { bot.lookAt = oldLookAt }).catch(console.warn) } - viewer.world.changeHandSwingingState(true) - viewer.world.changeHandSwingingState(false) + viewer.world.changeHandSwingingState(true, false) + viewer.world.changeHandSwingingState(false, false) } else if (!stop) { const offhand = activate ? false : activatableItems(bot.inventory.slots[45]?.name ?? '') bot.activateItem(offhand) // todo offhand @@ -351,42 +317,36 @@ class WorldInteraction { }) customEvents.emit('digStart') this.lastDigged = Date.now() - viewer.world.changeHandSwingingState(true) + viewer.world.changeHandSwingingState(true, false) } else if (performance.now() - this.lastSwing > 200) { bot.swingArm('right') this.lastSwing = performance.now() } } if (!this.buttons[0] && this.lastButtons[0]) { - viewer.world.changeHandSwingingState(false) + viewer.world.changeHandSwingingState(false, false) } this.prevOnGround = onGround // Show cursor + const allShapes = [...cursorBlock?.shapes ?? [], ...cursorBlock?.['interactionShapes'] ?? []] if (cursorBlock) { - const allShapes = [...cursorBlock.shapes, ...cursorBlock['interactionShapes'] ?? []] - this.updateBlockInteractionLines(cursorBlock.position, allShapes.map(shape => { - return getDataFromShape(shape) - })) - { - // union of all values - const breakShape = allShapes.reduce((acc, cur) => { - return [ - Math.min(acc[0], cur[0]), - Math.min(acc[1], cur[1]), - Math.min(acc[2], cur[2]), - Math.max(acc[3], cur[3]), - Math.max(acc[4], cur[4]), - Math.max(acc[5], cur[5]) - ] - }) - const { position, width, height, depth } = getDataFromShape(breakShape) - this.blockBreakMesh.scale.set(width * 1.001, height * 1.001, depth * 1.001) - position.add(cursorBlock.position) - this.blockBreakMesh.position.set(position.x, position.y, position.z) - } - } else { - this.updateBlockInteractionLines(null) + // BREAK MESH + // union of all values + const breakShape = allShapes.reduce((acc, cur) => { + return [ + Math.min(acc[0], cur[0]), + Math.min(acc[1], cur[1]), + Math.min(acc[2], cur[2]), + Math.max(acc[3], cur[3]), + Math.max(acc[4], cur[4]), + Math.max(acc[5], cur[5]) + ] + }) + const { position, width, height, depth } = getDataFromShape(breakShape) + this.blockBreakMesh.scale.set(width * 1.001, height * 1.001, depth * 1.001) + position.add(cursorBlock.position) + this.blockBreakMesh.position.set(position.x, position.y, position.z) } // Show break animation @@ -411,7 +371,11 @@ class WorldInteraction { } // Update state - this.cursorBlock = cursorBlock + if (cursorChanged) { + viewer.world.setHighlightCursorBlock(cursorBlock?.position ?? null, allShapes.map(shape => { + return getDataFromShape(shape) + })) + } this.lastButtons[0] = this.buttons[0] this.lastButtons[1] = this.buttons[1] this.lastButtons[2] = this.buttons[2] diff --git a/tsconfig.json b/tsconfig.json index 3c20075c1..addc64f19 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -29,6 +29,6 @@ "prismarine-viewer/examples" ], "exclude": [ - "node_modules", + "node_modules" ] }