diff --git a/assets/generic_91.png b/assets/generic_91.png deleted file mode 100644 index 99e4d04ae..000000000 Binary files a/assets/generic_91.png and /dev/null differ diff --git a/assets/generic_92.png b/assets/generic_92.png deleted file mode 100644 index 299e081b3..000000000 Binary files a/assets/generic_92.png and /dev/null differ diff --git a/assets/generic_93.png b/assets/generic_93.png deleted file mode 100644 index 1b35f671d..000000000 Binary files a/assets/generic_93.png and /dev/null differ diff --git a/assets/generic_94.png b/assets/generic_94.png deleted file mode 100644 index 19dc788d5..000000000 Binary files a/assets/generic_94.png and /dev/null differ diff --git a/assets/generic_95.png b/assets/generic_95.png deleted file mode 100644 index 2286dbfc8..000000000 Binary files a/assets/generic_95.png and /dev/null differ diff --git a/package.json b/package.json index 1b71541f5..fc0d9330f 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,8 @@ "jszip": "^3.10.1", "lodash-es": "^4.17.21", "mcraft-fun-mineflayer": "^0.1.23", - "minecraft-data": "3.106.0", + "minecraft-data": "0.0.0", + "minecraft-inventory": "^0.1.37", "minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master", "mineflayer-item-map-downloader": "github:zardoy/mineflayer-item-map-downloader", "mojangson": "^2.0.4", @@ -155,9 +156,8 @@ "http-server": "^14.1.1", "https-browserify": "^1.0.0", "mc-assets": "^0.2.72", - "minecraft-inventory-gui": "github:zardoy/minecraft-inventory-gui#next", - "mineflayer": "github:zardoy/mineflayer#gen-the-master", - "mineflayer-mouse": "^0.1.26", + "mineflayer": "0.0.0", + "mineflayer-mouse": "0.1.28", "npm-run-all": "^4.1.5", "os-browserify": "^0.3.0", "path-browserify": "^1.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c3ff57345..4989a5950 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -122,7 +122,7 @@ importers: version: 10.1.6 flying-squid: specifier: npm:@zardoy/flying-squid@^0.0.119 - version: '@zardoy/flying-squid@0.0.119(encoding@0.1.13)(prismarine-registry@1.11.0)' + version: '@zardoy/flying-squid@0.0.119(encoding@0.1.13)' framer-motion: specifier: ^12.9.2 version: 12.9.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -140,10 +140,13 @@ importers: version: 4.17.21 mcraft-fun-mineflayer: specifier: ^0.1.23 - version: 0.1.23(encoding@0.1.13)(mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/6dd654c3f7f6cd0cf3260fa963a96a113e32fcb9(encoding@0.1.13)) + version: 0.1.23(encoding@0.1.13)(mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/afebaa007ac86a02eba8e38bb2bdfb85487d9b8b(encoding@0.1.13)) minecraft-data: specifier: 3.106.0 version: 3.106.0 + minecraft-inventory: + specifier: ^0.1.37 + version: 0.1.39(@xmcl/text-component@2.1.3)(mc-assets@0.2.72)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) minecraft-protocol: specifier: github:PrismarineJS/node-minecraft-protocol#master version: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/3fabf16c61995b7a2c6d4d2902f7af99d0fe0a77(patch_hash=a0fc92234601e93b1e536d8d7cc9bf80a9df670d821e1d12746f261d15954fae)(encoding@0.1.13) @@ -170,7 +173,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/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.106.0) + version: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/c4c47c0ffcc6cebcc85a414d73b1795cbfa2c6b9(minecraft-data@3.106.0) prosemirror-example-setup: specifier: ^1.2.2 version: 1.2.3 @@ -340,15 +343,12 @@ importers: mc-assets: specifier: ^0.2.72 version: 0.2.72 - minecraft-inventory-gui: - specifier: github:zardoy/minecraft-inventory-gui#next - version: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/ae382e30ad66c3ca40f51ff3376605e8c67413db(@types/react@18.3.18)(react@18.3.1) mineflayer: specifier: github:zardoy/mineflayer#gen-the-master - version: https://codeload.github.com/zardoy/mineflayer/tar.gz/6dd654c3f7f6cd0cf3260fa963a96a113e32fcb9(encoding@0.1.13) + version: https://codeload.github.com/zardoy/mineflayer/tar.gz/afebaa007ac86a02eba8e38bb2bdfb85487d9b8b(encoding@0.1.13) mineflayer-mouse: - specifier: ^0.1.26 - version: 0.1.26 + specifier: 0.1.28 + version: 0.1.28 npm-run-all: specifier: ^4.1.5 version: 4.1.5 @@ -433,13 +433,13 @@ importers: version: 1.3.9 prismarine-block: specifier: github:zardoy/prismarine-block#next-era - version: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) + version: https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad prismarine-chunk: specifier: github:zardoy/prismarine-chunk#master - version: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/ec44d01fbe2e3a310c605761688a85119f056332(minecraft-data@3.106.0) + version: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/1eb3a5d85dffe18b7b504c6e5871c4b36681df1a(minecraft-data@3.106.0) prismarine-schematic: specifier: ^1.2.0 - version: 1.2.3(prismarine-registry@1.11.0) + version: 1.2.3 process: specifier: ^0.11.10 version: 0.11.10 @@ -4432,15 +4432,6 @@ packages: supports-color: optional: true - debug@4.4.1: - resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -6708,9 +6699,17 @@ packages: minecraft-folder-path@1.2.0: resolution: {integrity: sha512-qaUSbKWoOsH9brn0JQuBhxNAzTDMwrOXorwuRxdJKKKDYvZhtml+6GVCUrY5HRiEsieBEjCUnhVpDuQiKsiFaw==} - minecraft-inventory-gui@https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/ae382e30ad66c3ca40f51ff3376605e8c67413db: - resolution: {tarball: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/ae382e30ad66c3ca40f51ff3376605e8c67413db} - version: 1.0.1 + minecraft-inventory@0.1.39: + resolution: {integrity: sha512-m92NGCKsfqnTkNZ1J0s2PC5JSo+sHpT6nVHrkY16yOnLWauBu5mPR7v2MjVm7Hc9OL23XVKwAG8tMGy60ChtZw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + '@xmcl/text-component': '*' + mc-assets: '*' + react: ^18.2.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + mc-assets: + optional: true minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/3fabf16c61995b7a2c6d4d2902f7af99d0fe0a77: resolution: {tarball: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/3fabf16c61995b7a2c6d4d2902f7af99d0fe0a77} @@ -6728,12 +6727,12 @@ packages: resolution: {tarball: https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824} version: 1.2.0 - mineflayer-mouse@0.1.26: - resolution: {integrity: sha512-fTHGUx+xy/43mA3of0cUQCSoXTQF6jvV7t8ALAIKKnvYCW5Y9Zcth0mZS5nUFszkJyYj47r7G44SjCHAS1sxvA==} + mineflayer-mouse@0.1.28: + resolution: {integrity: sha512-31r73CqU7eiv8cQSVA+NMR0WfA8Qs+p6of+Bd7ApWzR4a56W6fgfY3MExNmxxbb1/w9IbxTcMhDbcoKmE/5+nw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/6dd654c3f7f6cd0cf3260fa963a96a113e32fcb9: - resolution: {tarball: https://codeload.github.com/zardoy/mineflayer/tar.gz/6dd654c3f7f6cd0cf3260fa963a96a113e32fcb9} + mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/afebaa007ac86a02eba8e38bb2bdfb85487d9b8b: + resolution: {tarball: https://codeload.github.com/zardoy/mineflayer/tar.gz/afebaa007ac86a02eba8e38bb2bdfb85487d9b8b} version: 8.0.0 engines: {node: '>=22'} @@ -7434,16 +7433,16 @@ packages: minecraft-data: 3.106.0 prismarine-registry: ^1.1.0 - prismarine-block@https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9: - resolution: {tarball: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9} - version: 1.21.0 + prismarine-block@https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad: + resolution: {tarball: https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad} + version: 1.23.0 prismarine-chat@1.11.0: resolution: {integrity: sha512-VJT/MWYB3qoiznUhrgvSQh76YFpzpCZpY85kJKxHLbd3UVoM0wsfs43Eg8dOltiZG92wc5/DTMLlT07TEeoa9w==} - prismarine-chunk@https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/ec44d01fbe2e3a310c605761688a85119f056332: - resolution: {tarball: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/ec44d01fbe2e3a310c605761688a85119f056332} - version: 1.39.0 + prismarine-chunk@https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/1eb3a5d85dffe18b7b504c6e5871c4b36681df1a: + resolution: {tarball: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/1eb3a5d85dffe18b7b504c6e5871c4b36681df1a} + version: 1.40.0 engines: {node: '>=14'} prismarine-entity@2.5.0: @@ -7459,15 +7458,15 @@ packages: resolution: {tarball: https://codeload.github.com/zardoy/prismarine-physics/tar.gz/353e25b800149393f40539ec381218be44cbb03b} version: 1.9.0 - prismarine-provider-anvil@https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7: - resolution: {tarball: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7} - version: 2.8.0 + prismarine-provider-anvil@https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/c4c47c0ffcc6cebcc85a414d73b1795cbfa2c6b9: + resolution: {tarball: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/c4c47c0ffcc6cebcc85a414d73b1795cbfa2c6b9} + version: 2.13.0 prismarine-realms@1.3.2: resolution: {integrity: sha512-5apl9Ru8veTj5q2OozRc4GZOuSIcs3yY4UEtALiLKHstBe8bRw8vNlaz4Zla3jsQ8yP/ul1b1IJINTRbocuA6g==} - prismarine-recipe@1.3.1: - resolution: {integrity: sha512-xfa9E9ACoaDi+YzNQ+nk8kWSIqt5vSZOOCHIT+dTXscf/dng2HaJ/59uwe1D/jvOkAd2OvM6RRJM6fFe0q/LDA==} + prismarine-recipe@1.5.0: + resolution: {integrity: sha512-GRZHbsyBIUgVNF10vFRv2YWZj86vokCT5EWX6iK6gfx6h4FapgZT29V2DNkjv5+hmdzBCLZvfx1/RYr8VPeoGQ==} peerDependencies: prismarine-registry: ^1.4.0 @@ -10356,7 +10355,7 @@ snapshots: '@babel/parser': 7.26.9 '@babel/template': 7.26.9 '@babel/types': 7.26.9 - debug: 4.4.1 + debug: 4.4.3 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -11390,8 +11389,8 @@ snapshots: dependencies: '@nxg-org/mineflayer-util-plugin': 1.8.4 minecraft-data: 3.106.0 - mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/6dd654c3f7f6cd0cf3260fa963a96a113e32fcb9(encoding@0.1.13) - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) + mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/afebaa007ac86a02eba8e38bb2bdfb85487d9b8b(encoding@0.1.13) + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad prismarine-item: 1.18.0 prismarine-physics: https://codeload.github.com/zardoy/prismarine-physics/tar.gz/353e25b800149393f40539ec381218be44cbb03b vec3: 0.1.10 @@ -12937,7 +12936,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 6.1.0(typescript@5.5.4) '@typescript-eslint/utils': 6.1.0(eslint@8.57.1)(typescript@5.5.4) - debug: 4.4.1 + debug: 4.4.3 eslint: 8.57.1 ts-api-utils: 1.4.3(typescript@5.5.4) optionalDependencies: @@ -12969,7 +12968,7 @@ snapshots: dependencies: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.4.1 + debug: 4.4.3 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -12984,7 +12983,7 @@ snapshots: dependencies: '@typescript-eslint/types': 8.26.0 '@typescript-eslint/visitor-keys': 8.26.0 - debug: 4.4.1 + debug: 4.4.3 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 @@ -13140,7 +13139,7 @@ snapshots: '@types/emscripten': 1.40.0 tslib: 1.14.1 - '@zardoy/flying-squid@0.0.119(encoding@0.1.13)(prismarine-registry@1.11.0)': + '@zardoy/flying-squid@0.0.119(encoding@0.1.13)': dependencies: '@tootallnate/once': 2.0.0 chalk: 5.4.1 @@ -13155,12 +13154,12 @@ snapshots: mkdirp: 2.1.6 node-gzip: 1.1.2 node-rsa: 1.1.1 - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/ec44d01fbe2e3a310c605761688a85119f056332(minecraft-data@3.106.0) + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/1eb3a5d85dffe18b7b504c6e5871c4b36681df1a(minecraft-data@3.106.0) prismarine-entity: 2.5.0 prismarine-item: 1.18.0 prismarine-nbt: 2.7.0 - prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.106.0) + prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/c4c47c0ffcc6cebcc85a414d73b1795cbfa2c6b9(minecraft-data@3.106.0) prismarine-windows: 2.9.0 prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c rambda: 9.4.2 @@ -13175,7 +13174,6 @@ snapshots: yargs: 17.7.2 transitivePeerDependencies: - encoding - - prismarine-registry - supports-color '@zardoy/flying-squid@0.0.49(encoding@0.1.13)': @@ -13193,11 +13191,11 @@ snapshots: 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/ec44d01fbe2e3a310c605761688a85119f056332(minecraft-data@3.106.0) + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/1eb3a5d85dffe18b7b504c6e5871c4b36681df1a(minecraft-data@3.106.0) prismarine-entity: 2.5.0 prismarine-item: 1.18.0 prismarine-nbt: 2.7.0 - prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.106.0) + prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/c4c47c0ffcc6cebcc85a414d73b1795cbfa2c6b9(minecraft-data@3.106.0) prismarine-windows: 2.9.0 prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c rambda: 9.4.2 @@ -14447,10 +14445,6 @@ snapshots: optionalDependencies: supports-color: 8.1.1 - debug@4.4.1: - dependencies: - ms: 2.1.3 - debug@4.4.3: dependencies: ms: 2.1.3 @@ -14598,7 +14592,7 @@ snapshots: diamond-square@https://codeload.github.com/zardoy/diamond-square/tar.gz/cfaad2d1d5909fdfa63c8cc7bc05fb5e87782d71: dependencies: minecraft-data: 3.106.0 - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/ec44d01fbe2e3a310c605761688a85119f056332(minecraft-data@3.106.0) + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/1eb3a5d85dffe18b7b504c6e5871c4b36681df1a(minecraft-data@3.106.0) prismarine-registry: 1.11.0 random-seed: 0.3.0 vec3: 0.1.10 @@ -15017,7 +15011,7 @@ snapshots: esbuild-register@3.6.0(esbuild@0.18.20): dependencies: - debug: 4.4.1 + debug: 4.4.3 esbuild: 0.18.20 transitivePeerDependencies: - supports-color @@ -17053,12 +17047,12 @@ snapshots: dependencies: minecraft-data: 3.106.0 - mcraft-fun-mineflayer@0.1.23(encoding@0.1.13)(mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/6dd654c3f7f6cd0cf3260fa963a96a113e32fcb9(encoding@0.1.13)): + mcraft-fun-mineflayer@0.1.23(encoding@0.1.13)(mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/afebaa007ac86a02eba8e38bb2bdfb85487d9b8b(encoding@0.1.13)): dependencies: '@zardoy/flying-squid': 0.0.49(encoding@0.1.13) exit-hook: 2.2.1 minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/3fabf16c61995b7a2c6d4d2902f7af99d0fe0a77(patch_hash=a0fc92234601e93b1e536d8d7cc9bf80a9df670d821e1d12746f261d15954fae)(encoding@0.1.13) - mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/6dd654c3f7f6cd0cf3260fa963a96a113e32fcb9(encoding@0.1.13) + mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/afebaa007ac86a02eba8e38bb2bdfb85487d9b8b(encoding@0.1.13) prismarine-item: 1.18.0 ws: 8.18.1 transitivePeerDependencies: @@ -17369,12 +17363,13 @@ snapshots: minecraft-folder-path@1.2.0: {} - minecraft-inventory-gui@https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/ae382e30ad66c3ca40f51ff3376605e8c67413db(@types/react@18.3.18)(react@18.3.1): + minecraft-inventory@0.1.39(@xmcl/text-component@2.1.3)(mc-assets@0.2.72)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - valtio: 1.13.2(@types/react@18.3.18)(react@18.3.1) - transitivePeerDependencies: - - '@types/react' - - react + '@xmcl/text-component': 2.1.3 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + mc-assets: 0.2.72 minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/3fabf16c61995b7a2c6d4d2902f7af99d0fe0a77(patch_hash=a0fc92234601e93b1e536d8d7cc9bf80a9df670d821e1d12746f261d15954fae)(encoding@0.1.13): dependencies: @@ -17428,13 +17423,13 @@ snapshots: mineflayer-item-map-downloader@https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824(patch_hash=a731ebbace2d8790c973ab3a5ba33494a6e9658533a9710dd8ba36f86db061ad)(encoding@0.1.13): dependencies: - mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/6dd654c3f7f6cd0cf3260fa963a96a113e32fcb9(encoding@0.1.13) + mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/afebaa007ac86a02eba8e38bb2bdfb85487d9b8b(encoding@0.1.13) sharp: 0.30.7 transitivePeerDependencies: - encoding - supports-color - mineflayer-mouse@0.1.26: + mineflayer-mouse@0.1.28: dependencies: change-case: 5.4.4 debug: 4.4.3 @@ -17443,20 +17438,21 @@ snapshots: transitivePeerDependencies: - supports-color - mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/6dd654c3f7f6cd0cf3260fa963a96a113e32fcb9(encoding@0.1.13): + mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/afebaa007ac86a02eba8e38bb2bdfb85487d9b8b(encoding@0.1.13): dependencies: '@nxg-org/mineflayer-physics-util': 1.8.19 minecraft-data: 3.106.0 minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/3fabf16c61995b7a2c6d4d2902f7af99d0fe0a77(patch_hash=a0fc92234601e93b1e536d8d7cc9bf80a9df670d821e1d12746f261d15954fae)(encoding@0.1.13) + mojangson: 2.0.4 prismarine-biome: 1.3.0(minecraft-data@3.106.0)(prismarine-registry@1.11.0) - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad prismarine-chat: 1.11.0 - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/ec44d01fbe2e3a310c605761688a85119f056332(minecraft-data@3.106.0) + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/1eb3a5d85dffe18b7b504c6e5871c4b36681df1a(minecraft-data@3.106.0) prismarine-entity: 2.5.0 prismarine-item: 1.18.0 prismarine-nbt: 2.7.0 prismarine-physics: https://codeload.github.com/zardoy/prismarine-physics/tar.gz/353e25b800149393f40539ec381218be44cbb03b - prismarine-recipe: 1.3.1(prismarine-registry@1.11.0) + prismarine-recipe: 1.5.0(prismarine-registry@1.11.0) prismarine-registry: 1.11.0 prismarine-windows: 2.9.0 prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c @@ -18243,7 +18239,7 @@ snapshots: minecraft-data: 3.106.0 prismarine-registry: 1.11.0 - prismarine-block@https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0): + prismarine-block@https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad: dependencies: minecraft-data: 3.106.0 prismarine-biome: 1.3.0(minecraft-data@3.106.0)(prismarine-registry@1.11.0) @@ -18251,8 +18247,6 @@ snapshots: prismarine-item: 1.18.0 prismarine-nbt: 2.7.0 prismarine-registry: 1.11.0 - transitivePeerDependencies: - - prismarine-registry prismarine-chat@1.11.0: dependencies: @@ -18260,10 +18254,10 @@ snapshots: prismarine-nbt: 2.7.0 prismarine-registry: 1.11.0 - prismarine-chunk@https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/ec44d01fbe2e3a310c605761688a85119f056332(minecraft-data@3.106.0): + prismarine-chunk@https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/1eb3a5d85dffe18b7b504c6e5871c4b36681df1a(minecraft-data@3.106.0): dependencies: prismarine-biome: 1.3.0(minecraft-data@3.106.0)(prismarine-registry@1.11.0) - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad prismarine-nbt: 2.7.0 prismarine-registry: 1.11.0 smart-buffer: 4.2.0 @@ -18295,12 +18289,11 @@ snapshots: prismarine-nbt: 2.7.0 vec3: 0.1.10 - prismarine-provider-anvil@https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.106.0): + prismarine-provider-anvil@https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/c4c47c0ffcc6cebcc85a414d73b1795cbfa2c6b9(minecraft-data@3.106.0): dependencies: - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/ec44d01fbe2e3a310c605761688a85119f056332(minecraft-data@3.106.0) + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/1eb3a5d85dffe18b7b504c6e5871c4b36681df1a(minecraft-data@3.106.0) prismarine-nbt: 2.7.0 - prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c uint4: 0.1.2 vec3: 0.1.10 transitivePeerDependencies: @@ -18314,25 +18307,23 @@ snapshots: - encoding - supports-color - prismarine-recipe@1.3.1(prismarine-registry@1.11.0): + prismarine-recipe@1.5.0(prismarine-registry@1.11.0): dependencies: prismarine-registry: 1.11.0 prismarine-registry@1.11.0: dependencies: minecraft-data: 3.106.0 - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad prismarine-nbt: 2.7.0 - prismarine-schematic@1.2.3(prismarine-registry@1.11.0): + prismarine-schematic@1.2.3: dependencies: minecraft-data: 3.106.0 - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/401a296892fbde312ade34685fdc2db3d31668ad prismarine-nbt: 2.7.0 prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c vec3: 0.1.10 - transitivePeerDependencies: - - prismarine-registry prismarine-windows@2.9.0: dependencies: @@ -18527,7 +18518,7 @@ snapshots: puppeteer-core@2.1.1: dependencies: '@types/mime-types': 2.1.4 - debug: 4.4.1 + debug: 4.4.3 extract-zip: 1.7.0 https-proxy-agent: 4.0.0 mime: 2.6.0 diff --git a/src/defaultOptions.ts b/src/defaultOptions.ts index 990973f77..000d7df49 100644 --- a/src/defaultOptions.ts +++ b/src/defaultOptions.ts @@ -58,7 +58,10 @@ export const defaultOptions = { preciseMouseInput: false, // todo ui setting, maybe enable by default? waitForChunksRender: false as 'sp-only' | boolean, - jeiEnabled: true as boolean | Array<'creative' | 'survival' | 'adventure' | 'spectator'>, + inventoryJei: true as boolean | Array<'creative' | 'survival' | 'adventure' | 'spectator'>, + inventoryNotes: true as boolean, + inventoryPlaceholders: false, + inventoryPlayerModel: true, modsSupport: false, modsAutoUpdate: 'check' as 'check' | 'never' | 'always', modsUpdatePeriodCheck: 24, // hours diff --git a/src/inventoryWindows.ts b/src/inventoryWindows.ts index 51db10ec2..e54bf11bc 100644 --- a/src/inventoryWindows.ts +++ b/src/inventoryWindows.ts @@ -1,126 +1,80 @@ import { proxy, subscribe } from 'valtio' -import { showInventory } from 'minecraft-inventory-gui/web/ext.mjs' -// import Dirt from 'mc-assets/dist/other-textures/latest/blocks/dirt.png' import { RecipeItem } from 'minecraft-data' -import { flat, fromFormattedString } from '@xmcl/text-component' +import { flat } from '@xmcl/text-component' import { splitEvery, equals } from 'rambda' import PItem, { Item } from 'prismarine-item' import { versionToNumber } from 'renderer/viewer/common/utils' -import { getRenamedData } from 'flying-squid/dist/blockRenames' -import PrismarineChatLoader from 'prismarine-chat' -import * as nbt from 'prismarine-nbt' -import { BlockModel } from 'mc-assets' +import { getInventoryType } from 'minecraft-inventory/src/registry' +import type { RecipeGuide, ItemStack as InventoryItemStack } from 'minecraft-inventory/src/types' +import type { JEIItem } from 'minecraft-inventory/src/components/JEI/JEI' import { renderSlot } from 'renderer/viewer/three/renderSlot' -import { loadSkinFromUsername } from 'renderer/viewer/lib/utils/skins' -import Generic95 from '../assets/generic_95.png' -import { appReplacableResources } from './generated/resources' import { activeModalStack, hideCurrentModal, hideModal, miscUiState, showModal } from './globalState' import { options } from './optionsStorage' -import { assertDefined, inGameError } from './utils' import { displayClientChat } from './botUtils' -import { currentScaling } from './scaleInterface' import { getItemDescription } from './itemsDescriptions' import { MessageFormatPart } from './chatUtils' -import { GeneralInputItem, getItemMetadata, getItemModelName, getItemNameRaw, RenderItem } from './mineflayer/items' -import { playerState } from './mineflayer/playerState' -import { modelViewerState } from './react/OverlayModelViewer' - -const loadedImagesCache = new Map() -const cleanLoadedImagesCache = () => { - loadedImagesCache.delete('blocks') - loadedImagesCache.delete('items') -} +import { getItemModelName, getItemNameRaw, RenderItem } from './mineflayer/items' +import { clearInventoryCaches } from './react/inventory/Inventory' +import { buildBlockTexture, extractSpriteDataUrl } from './react/inventory/sharedConnectorSetup' -let lastWindow: ReturnType -let lastWindowType: string | null | undefined // null is inventory -/** bot version */ -let version: string let PrismarineItem: typeof Item export const jeiCustomCategories = proxy({ value: [] as Array<{ id: string, categoryTitle: string, items: any[] }> }) -let remotePlayerSkin: string | undefined | Promise - -export const showInventoryPlayer = () => { - modelViewerState.model = { - positioning: { - windowWidth: 176, - windowHeight: 166, - x: 25, - y: 8, - width: 50, - height: 70, - scaled: true, - onlyInitialScale: true, - }, - followCursor: true, - followCursorCenter: { - x: 51, - y: 27, - }, - // models: ['https://bucket.mcraft.fun/sitarbuckss.glb'], - // debug: true, - steveModelSkin: appViewer.playerState.reactive.playerSkin ?? (typeof remotePlayerSkin === 'string' ? remotePlayerSkin : ''), - } - if (remotePlayerSkin === undefined && !appViewer.playerState.reactive.playerSkin) { - remotePlayerSkin = loadSkinFromUsername(bot.username, 'skin').then(a => { - setTimeout(() => { - // Check if player inventory is still open before updating - if (lastWindowType === null) { - showInventoryPlayer() - } - }, 0) // todo patch instead and make reactive - remotePlayerSkin = a ?? '' - return remotePlayerSkin - }) - } -} +// ----- JEI items cache ----- +let jeiItemsCache: JEIItem[] | null = null +const clearJeiItemsCache = () => { jeiItemsCache = null } +subscribe(jeiCustomCategories, clearJeiItemsCache) export const onGameLoad = () => { - version = bot.version + PrismarineItem = PItem(bot.version) - PrismarineItem = PItem(version) - - const mapWindowType = (type: string, inventoryStart: number) => { + /** Maps mineflayer window type + inventoryStart to an exact key in the new library's registry */ + const mapWindowType = (type: string, inventoryStart: number): string => { + // minecraft:container size is determined by inventoryStart if (type === 'minecraft:container') { - if (inventoryStart === 45 - 9 * 4) return 'minecraft:generic_9x1' - if (inventoryStart === 45 - 9 * 3) return 'minecraft:generic_9x2' - if (inventoryStart === 45 - 9 * 2) return 'minecraft:generic_9x3' - if (inventoryStart === 45 - 9) return 'minecraft:generic_9x4' - if (inventoryStart === 45) return 'minecraft:generic_9x5' - if (inventoryStart === 45 + 9) return 'minecraft:generic_9x6' + if (inventoryStart === 45 - 9 * 4) return 'generic_9x1' + if (inventoryStart === 45 - 9 * 3) return 'generic_9x2' + if (inventoryStart === 45 - 9 * 2) return 'generic_9x3' + if (inventoryStart === 45 - 9) return 'generic_9x4' + if (inventoryStart === 45) return 'generic_9x5' + if (inventoryStart === 45 + 9) return 'generic_9x6' } - return type - } - - const maybeParseNbtJson = (data: any) => { - if (typeof data === 'string') { - try { - data = JSON.parse(data) - } catch (err) { - // ignore - } + // Version-specific smithing table layout + if (type === 'minecraft:smithing') { + return versionToNumber(bot.version) < versionToNumber('1.20') ? 'smithing_table_legacy' : 'smithing_table' } - return nbt.simplify(data) ?? data + // Strip minecraft: prefix then handle remaining aliases + const stripped = type.startsWith('minecraft:') ? type.slice(10) : type + const remap: Record = { + generic_5x1: 'hopper', + generic_3x3: 'dispenser', + crafting: 'crafting_table', + crafting3x3: 'crafting_table', + } + return remap[stripped] ?? stripped } bot.on('windowOpen', (win) => { - const implementedWindow = implementedContainersGuiMap[mapWindowType(win.type as string, win.inventoryStart)] - if (implementedWindow) { - openWindow(implementedWindow, maybeParseNbtJson(win.title)) - } else if (options.unimplementedContainers) { - openWindow('ChestWin', maybeParseNbtJson(win.title)) + const mappedType = mapWindowType(win.type as string, win.inventoryStart) + const isImplemented = !!getInventoryType(mappedType) + + if (isImplemented || options.unimplementedContainers) { + if (activeModalStack.length && !miscUiState.disconnectedCleanup) { + hideCurrentModal() + } + showModal({ reactType: `player_win:${isImplemented ? mappedType : 'chest'}` }) } else { - // todo format - displayClientChat(`[client error] cannot open unimplemented window ${win.id} (${win.type}). Slots: ${win.slots.map(item => getItemName(item)).filter(Boolean).join(', ')}`) + displayClientChat(`[client error] cannot open unimplemented window ${(win as any).id} (${win.type}). Slots: ${win.slots.map(item => getItemName(item as any)).filter(Boolean).join(', ')}`) + displayClientChat('You can help us fix it! Open a pull request adding support for it on https://github.com/zardoy/minecraft-inventory') bot.currentWindow?.['close']() } }) - // workaround: singleplayer player inventory crafting + // Workaround: singleplayer player-inventory crafting let skipUpdate = false bot.inventory.on('updateSlot', ((_oldSlot, oldItem, newItem) => { const currentSlot = _oldSlot as number @@ -149,441 +103,43 @@ export const onGameLoad = () => { }) } catch (err) { console.error(err) - // todo resolve the error! and why would we ever get here on every update? } }) as any) bot.on('windowClose', () => { - // todo hide up to the window itself! - if (lastWindow) { - hideCurrentModal() + const modal = activeModalStack.at(-1) + if (modal?.reactType?.startsWith('player_win:')) { + hideModal(undefined, undefined, { force: true }) } }) - bot.on('respawn', () => { // todo validate logic against native client (maybe login) - if (lastWindow) { - hideCurrentModal() + bot.on('respawn', () => { + const modal = activeModalStack.at(-1) + if (modal?.reactType?.startsWith('player_win:')) { + hideModal(undefined, undefined, { force: true }) } }) - customEvents.on('search', (q) => { - if (!lastWindow) return - upJei(q) - }) - if (!appViewer.resourcesManager['_inventoryChangeTracked']) { appViewer.resourcesManager['_inventoryChangeTracked'] = true - const texturesChanged = () => { - cleanLoadedImagesCache() - if (!lastWindow) return - upWindowItemsLocal() - upJei(lastJeiSearch) - } - appViewer.resourcesManager.on('assetsInventoryReady', () => texturesChanged()) - appViewer.resourcesManager.on('assetsTexturesUpdated', () => texturesChanged()) + appViewer.resourcesManager.on('assetsInventoryReady', () => { clearJeiItemsCache(); clearInventoryCaches() }) + appViewer.resourcesManager.on('assetsTexturesUpdated', () => { clearJeiItemsCache(); clearInventoryCaches() }) } } -const getImageSrc = (path): string | HTMLImageElement | ImageBitmap => { - switch (path) { - case 'gui/container/inventory': return appReplacableResources.latest_gui_container_inventory.content - case 'blocks': return appViewer.resourcesManager.blocksAtlasParser.latestImage - case 'items': return appViewer.resourcesManager.itemsAtlasParser.latestImage - case 'gui': return appViewer.resourcesManager.currentResources!.guiAtlas!.image - case 'gui/container/dispenser': return appReplacableResources.latest_gui_container_dispenser.content - case 'gui/container/furnace': return appReplacableResources.furnace_gui_texture.content - case 'gui/container/crafting_table': return appReplacableResources.latest_gui_container_crafting_table.content - case 'gui/container/shulker_box': return appReplacableResources.latest_gui_container_shulker_box.content - case 'gui/container/generic_54': return appReplacableResources.latest_gui_container_generic_54.content - case 'gui/container/generic_95': return Generic95 - case 'gui/container/hopper': return appReplacableResources.latest_gui_container_hopper.content - case 'gui/container/horse': return appReplacableResources.latest_gui_container_horse.content - case 'gui/container/villager2': return appReplacableResources.latest_gui_container_villager2.content - case 'gui/container/enchanting_table': return appReplacableResources.latest_gui_container_enchanting_table.content - case 'gui/container/anvil': return appReplacableResources.latest_gui_container_anvil.content - case 'gui/container/beacon': return appReplacableResources.latest_gui_container_beacon.content - case 'gui/container/smithing': - return versionToNumber(bot.version) < versionToNumber('1.20') - ? appReplacableResources._1_19_4_gui_container_smithing.content - : appReplacableResources.latest_gui_container_smithing.content - case 'gui/widgets': return appReplacableResources.other_textures_latest_gui_widgets.content - } - // empty texture - return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=' -} - -const getImage = ({ path = undefined as string | undefined, texture = undefined as string | undefined, blockData = undefined as any, image = undefined as HTMLImageElement | undefined }, onLoad = () => { }) => { - if (image) { - return image - } - if (!path && !texture) { - throw new Error('Either pass path or texture') - } - const loadPath = (blockData ? 'blocks' : path ?? texture)! - if (loadedImagesCache.has(loadPath)) { - onLoad() - } else { - const imageSrc = getImageSrc(loadPath) - if (imageSrc instanceof ImageBitmap) { - onLoad() - loadedImagesCache.set(loadPath, imageSrc) - return imageSrc - } - - let image: HTMLImageElement - if (imageSrc instanceof Image) { - image = imageSrc - } else { - image = new Image() - image.src = imageSrc - } - image.onload = onLoad - loadedImagesCache.set(loadPath, image) - } - return loadedImagesCache.get(loadPath) -} - const getItemName = (slot: Item | RenderItem | null) => { const parsed = getItemNameRaw(slot, appViewer.resourcesManager) if (!parsed) return - // todo display full text renderer from sign renderer const text = flat(parsed as MessageFormatPart).map(x => (typeof x === 'string' ? x : x.text)) return text.join('') } -let lastMappedSlots = [] as any[] -const itemToVisualKey = (slot: RenderItem | Item | null) => { - if (!slot) return '' - const keys = [ - slot.name, - slot.durabilityUsed, - slot.maxDurability, - slot['count'], - slot['metadata'], - slot.nbt ? JSON.stringify(slot.nbt) : '', - slot['components'] ? JSON.stringify(slot['components']) : '', - appViewer.resourcesManager.currentResources!.guiAtlasVersion, - ].join('|') - return keys -} -const validateSlot = (slot: any, index: number) => { - if (!slot.texture) { - throw new Error(`Slot has no texture: ${index} ${slot.name}`) - } -} -const mapSlots = (slots: Array, isJei = false) => { - const newSlots = slots.map((slot, i) => { - if (!slot) return null - - if (!isJei) { - const oldKey = lastMappedSlots[i]?.cacheKey - const newKey = itemToVisualKey(slot) - slot['cacheKey'] = i + '|' + newKey - if (oldKey && oldKey === newKey) { - validateSlot(lastMappedSlots[i], i) - return lastMappedSlots[i] - } - } - - try { - if (slot.durabilityUsed && slot.maxDurability) slot.durabilityUsed = Math.min(slot.durabilityUsed, slot.maxDurability) - const debugIsQuickbar = !isJei && i === bot.inventory.hotbarStart + bot.quickBarSlot - const modelName = getItemModelName(slot, { 'minecraft:display_context': 'gui', }, appViewer.resourcesManager, appViewer.playerState.reactive) - const slotCustomProps = renderSlot({ modelName, originalItemName: slot.name }, appViewer.resourcesManager, debugIsQuickbar) - const itemCustomName = getItemName(slot) - Object.assign(slot, { ...slotCustomProps, displayName: itemCustomName ?? slot.displayName }) - //@ts-expect-error - slot.toJSON = () => { - // Allow to serialize slot to JSON as minecraft-inventory-gui creates icon property as cache (recursively) - //@ts-expect-error - const { icon, ...rest } = slot - return rest - } - validateSlot(slot, i) - } catch (err) { - inGameError(err) - } - return slot - }) - lastMappedSlots = JSON.parse(JSON.stringify(newSlots)) - return newSlots -} - -export const upInventoryItems = (isInventory: boolean, invWindow = lastWindow) => { - // inv.pwindow.inv.slots[2].displayName = 'test' - // inv.pwindow.inv.slots[2].blockData = getBlockData('dirt') - const customSlots = mapSlots((isInventory ? bot.inventory : bot.currentWindow)!.slots) - invWindow.pwindow.setSlots(customSlots) - return customSlots -} - -export const onModalClose = (callback: () => any) => { - const modal = activeModalStack.at(-1) - const unsubscribe = subscribe(activeModalStack, () => { - const newModal = activeModalStack.at(-1) - if (modal?.reactType !== newModal?.reactType) { - callback() - unsubscribe() - } - }, true) -} - -const implementedContainersGuiMap = { - // todo allow arbitrary size instead! - 'minecraft:generic_9x1': 'ChestWin', - 'minecraft:generic_9x2': 'ChestWin', - 'minecraft:generic_9x3': 'ChestWin', - 'minecraft:generic_9x4': 'Generic95Win', - 'minecraft:generic_9x5': 'Generic95Win', - // hopper - 'minecraft:hopper': 'HopperWin', - 'minecraft:generic_5x1': 'HopperWin', - 'minecraft:generic_9x6': 'LargeChestWin', - 'minecraft:generic_3x3': 'DropDispenseWin', - 'minecraft:furnace': 'FurnaceWin', - 'minecraft:smoker': 'FurnaceWin', - 'minecraft:blast_furnace': 'FurnaceWin', - 'minecraft:shulker_box': 'ChestWin', - 'minecraft:crafting': 'CraftingWin', - 'minecraft:smithing': 'will_be_patched_in_openWindow', - 'minecraft:crafting3x3': 'CraftingWin', // todo different result slot - 'minecraft:anvil': 'AnvilWin', - // enchant - 'minecraft:enchanting_table': 'EnchantingWin', - // horse - 'minecraft:horse': 'HorseWin', - // villager - 'minecraft:villager': 'VillagerWin', -} - -let lastJeiSearch = '' -const upJei = (search: string) => { - lastJeiSearch = search - search = search.toLowerCase() - // todo fix pre flat - const itemsArray = [ - ...jeiCustomCategories.value.flatMap(x => x.items).filter(x => x !== null), - ...loadedData.itemsArray.filter(x => x.displayName.toLowerCase().includes(search)).map(item => new PrismarineItem(item.id, 1)).filter(x => x !== null) - ] - const matchedSlots = itemsArray.map(x => { - x.displayName = getItemName(x) ?? x.displayName - if (!x.displayName.toLowerCase().includes(search)) return null - return x - }).filter(a => a !== null) - lastWindow.pwindow.win.jeiSlotsPage = 0 - lastWindow.pwindow.win.jeiSlots = mapSlots(matchedSlots, true) -} - -export const openItemsCanvas = (type, _bot = bot as typeof bot | null) => { - const inv = showInventory(type, getImage, {}, _bot); - (inv.canvasManager.children[0].callbacks as any).getItemRecipes = (item) => { - const allRecipes = getAllItemRecipes(item.name) - inv.canvasManager.children[0].messageDisplay = '' - const itemDescription = getItemDescription(item) - if (!allRecipes?.length && !itemDescription) { - inv.canvasManager.children[0].messageDisplay = `No recipes found for ${item.displayName}` - } - return [...allRecipes ?? [], ...itemDescription ? [ - [ - 'GenericDescription', - mapSlots([item], true)[0], - [], - itemDescription - ] - ] : []] - } - (inv.canvasManager.children[0].callbacks as any).getItemUsages = (item) => { - const allItemUsages = getAllItemUsages(item.name) - inv.canvasManager.children[0].messageDisplay = '' - if (!allItemUsages?.length) { - inv.canvasManager.children[0].messageDisplay = `No usages found for ${item.displayName}` - } - return allItemUsages - } - return inv -} - -const upWindowItemsLocal = () => { - void Promise.resolve().then(() => { - if (!lastWindow && bot.currentWindow) { - // edge case: might happen due to high ping, inventory should be closed soon! - // openWindow(implementedContainersGuiMap[bot.currentWindow.type]) - return - } - upInventoryItems(lastWindowType === null) - }) -} - -let skipClosePacketSending = false -const openWindow = (type: string | undefined, title: string | any = undefined) => { - // patch implementedContainersGuiMap - implementedContainersGuiMap['minecraft:smithing'] = versionToNumber(bot.version) < versionToNumber('1.20') ? 'SmithingTableLegacyWin' : 'SmithingTableWin' - - // if (activeModalStack.some(x => x.reactType?.includes?.('player_win:'))) { - if (activeModalStack.length && !miscUiState.disconnectedCleanup) { // game is not in foreground, don't close current modal - if (type) { - skipClosePacketSending = true - hideCurrentModal() - } else { - bot.currentWindow?.['close']() - return - } - } - lastWindowType = type ?? null - showModal({ - reactType: `player_win:${type}`, - }) - if (type === undefined) { - showInventoryPlayer() - } - cleanLoadedImagesCache() - const inv = openItemsCanvas(type) - inv.canvasManager.children[0].mobileHelpers = miscUiState.currentTouch - window.inventory = inv - const PrismarineChat = PrismarineChatLoader(bot.version) - try { - inv.canvasManager.children[0].customTitleText = title ? - typeof title === 'string' ? - fromFormattedString(title).text : - new PrismarineChat(title).toString() : - undefined - } catch (err) { - reportError?.(err) - inv.canvasManager.children[0].customTitleText = undefined - } - // todo - inv.canvasManager.setScale(currentScaling.scale === 1 ? 1.5 : currentScaling.scale) - inv.canvas.style.zIndex = '10' - inv.canvas.style.position = 'fixed' - inv.canvas.style.inset = '0' - - inv.canvasManager.onClose = async () => { - await new Promise(resolve => { - setTimeout(resolve, 0) - }) - if (activeModalStack.at(-1)?.reactType?.includes('player_win:')) { - hideModal(undefined, undefined, { force: true }) - } - inv.canvasManager.destroy() - } - - lastWindow = inv - - onModalClose(() => { - // might be already closed (event fired) - if (type !== undefined && bot.currentWindow && !skipClosePacketSending) bot.currentWindow['close']() - lastWindow.destroy() - lastWindow = null as any - lastWindowType = undefined - window.inventory = null - miscUiState.displaySearchInput = false - destroyFn() - skipClosePacketSending = false - - modelViewerState.model = undefined - }) - - upWindowItemsLocal() - - lastWindow.pwindow.touch = miscUiState.currentTouch ?? false - const oldOnInventoryEvent = lastWindow.pwindow.onInventoryEvent.bind(lastWindow.pwindow) - lastWindow.pwindow.onInventoryEvent = (type, containing, windowIndex, inventoryIndex, item) => { - if (inv.canvasManager.children[0].currentGuide) { - const isRightClick = type === 'rightclick' - const isLeftClick = type === 'leftclick' - if (isLeftClick || isRightClick) { - modelViewerState.model = undefined - inv.canvasManager.children[0].showRecipesOrUsages(isLeftClick, item) - } - } else { - oldOnInventoryEvent(type, containing, windowIndex, inventoryIndex, item) - } - } - lastWindow.pwindow.onJeiClick = (slotItem, _index, isRightclick) => { - if (!slotItem) { - console.warn('onJeiClick called with undefined slotItem') - return - } - if (versionToNumber(bot.version) < versionToNumber('1.13')) { - alert('Item give is broken on 1.12.2 and below, we are working on it!') - return - } - // slotItem is the slot from mapSlots - const itemId = loadedData.itemsByName[slotItem.name]?.id - if (!itemId) { - inGameError(`Item for block ${slotItem.name} not found`) - return - } - const item = PrismarineItem.fromNotch({ - ...slotItem, - itemId, - itemCount: isRightclick ? 64 : 1, - components: slotItem.components ?? [], - removeComponents: slotItem.removedComponents ?? [], - itemDamage: slotItem.metadata ?? 0, - nbt: slotItem.nbt, - }) - if (bot.game.gameMode === 'creative') { - const freeSlot = bot.inventory.firstEmptyInventorySlot() - if (freeSlot === null) { - console.warn('[JEI] no free inventory slot available') - return - } - bot._client.write('set_creative_slot', { - slot: freeSlot, - item: PrismarineItem.toNotch(item) - }) - //@ts-expect-error - bot._setSlot(freeSlot, item) - } else { - modelViewerState.model = undefined - inv.canvasManager.children[0].showRecipesOrUsages(!isRightclick, mapSlots([item], true)[0]) - } - } - - const isJeiEnabled = () => { - if (typeof options.jeiEnabled === 'boolean') return options.jeiEnabled - if (Array.isArray(options.jeiEnabled)) { - return options.jeiEnabled.includes(bot.game?.gameMode as any) - } - return false - } - - if (isJeiEnabled()) { - lastWindow.pwindow.win.jeiSlotsPage = 0 - // todo workaround so inventory opens immediately (though it still lags) - setTimeout(() => { - upJei('') - }) - miscUiState.displaySearchInput = true - } else { - lastWindow.pwindow.win.jeiSlots = [] - miscUiState.displaySearchInput = false - } - - if (type === undefined) { - // player inventory - bot.inventory.on('updateSlot', upWindowItemsLocal) - destroyFn = () => { - bot.inventory.off('updateSlot', upWindowItemsLocal) - } - } else { - //@ts-expect-error - bot.currentWindow.on('updateSlot', () => { - upWindowItemsLocal() - }) - } -} - -let destroyFn = () => { } - export const openPlayerInventory = () => { - openWindow(undefined) + showModal({ reactType: 'player_win:player' }) } const getResultingRecipe = (slots: Array, gridRows: number) => { const inputSlotsItems = slots.map(blockSlot => blockSlot?.type) let currentShape = splitEvery(gridRows, inputSlotsItems as Array) - // todo rewrite with candidates search if (currentShape.length > 1) { // eslint-disable-next-line @typescript-eslint/no-for-in-array for (const slotX in currentShape[0]) { @@ -598,7 +154,6 @@ const getResultingRecipe = (slots: Array, gridRows: number) => { } currentShape = currentShape.map(arr => arr.filter(x => x !== undefined)).filter(x => x.length !== 0) - // todo rewrite // eslint-disable-next-line @typescript-eslint/require-array-sort-compare const slotsIngredients = [...inputSlotsItems].sort().filter(item => item !== undefined) type Result = RecipeItem | undefined @@ -618,82 +173,242 @@ const getResultingRecipe = (slots: Array, gridRows: number) => { } const result = shapeResult ?? shapelessResult if (!result) return - const id = typeof result === 'number' ? result : Array.isArray(result) ? result[0] : result.id + const id = typeof result === 'number' ? result : Array.isArray(result) ? result[0] : (result as any).id if (!id) return - const count = (typeof result === 'number' ? undefined : Array.isArray(result) ? result[1] : result.count) ?? 1 - const metadata = typeof result === 'object' && !Array.isArray(result) ? result.metadata : undefined - const item = new PrismarineItem(id, count, metadata) + const count = (typeof result === 'number' ? undefined : Array.isArray(result) ? result[1] : (result as any).count) ?? 1 + const metadata = typeof result === 'object' && !Array.isArray(result) ? (result as any).metadata : undefined + const item = new PrismarineItem(id as number, count, metadata) return item } const ingredientToItem = (recipeItem) => (recipeItem === null ? null : new PrismarineItem(recipeItem, 1)) -const getAllItemRecipes = (itemName: string) => { +// Legacy format used by openItemsCanvas / HotbarRenderApp +// const getAllItemRecipesLegacy = (itemName: string) => { +// const item = loadedData.itemsByName[itemName] +// if (!item) return +// const itemId = item.id +// const recipes = loadedData.recipes?.[itemId] +// if (!recipes) return +// const results = [] as Array<{ +// result: Item, +// ingredients: Array, +// description?: string +// }> + +// for (const recipe of recipes) { +// const { result } = recipe +// if (!result) continue +// const resultId = typeof result === 'number' ? result : Array.isArray(result) ? result[0]! : (result as any).id +// const resultCount = (typeof result === 'number' ? undefined : Array.isArray(result) ? result[1] : (result as any).count) ?? 1 +// const resultMetadata = typeof result === 'object' && !Array.isArray(result) ? (result as any).metadata : undefined +// const resultItem = new PrismarineItem(resultId as number, resultCount, resultMetadata) +// if ('inShape' in recipe) { +// const ingredients = recipe.inShape +// if (!ingredients) continue +// const ingredientsItems = ingredients.flatMap(items => items.map(item => ingredientToItem(item))) +// results.push({ result: resultItem, ingredients: ingredientsItems }) +// } +// if ('ingredients' in recipe) { +// const { ingredients } = recipe +// if (!ingredients) continue +// const ingredientsItems = ingredients.map(item => ingredientToItem(item)) +// results.push({ result: resultItem, ingredients: ingredientsItems, description: 'Shapeless' }) +// } +// } +// return results.map(({ result, ingredients, description }) => { +// return [ +// 'CraftingTableGuide', +// mapSlots([result], true)[0], +// mapSlots(ingredients, true), +// description +// ] +// }) +// } + +// const getAllItemUsagesLegacy = (itemName: string) => { +// const item = loadedData.itemsByName[itemName] +// if (!item) return +// const foundRecipeIds = [] as string[] + +// for (const [id, recipes] of Object.entries(loadedData.recipes ?? {})) { +// for (const recipe of recipes) { +// if ('inShape' in recipe) { +// if (recipe.inShape.some(row => row.includes(item.id))) { +// foundRecipeIds.push(id) +// } +// } +// if ('ingredients' in recipe) { +// if (recipe.ingredients.includes(item.id)) { +// foundRecipeIds.push(id) +// } +// } +// } +// } + +// return foundRecipeIds.flatMap(id => { +// return getAllItemRecipesLegacy(loadedData.items[id].name) +// }) +// } + +// ----- New React inventory exports ----- + +/** Enrich a single item with texture data from the rendering pipeline (same as JEI enrichment) */ +const enrichItemTexture = (item: InventoryItemStack): void => { + if (!appViewer?.resourcesManager?.currentResources) return + const playerState = appViewer.playerState?.reactive + if (!playerState) return + try { + const modelName = getItemModelName( + { name: item.name ?? '', nbt: null }, + { 'minecraft:display_context': 'gui' }, + appViewer.resourcesManager, + playerState + ) + const slotProps = renderSlot({ modelName, originalItemName: item.name ?? '' }, appViewer.resourcesManager) + if (slotProps.blockData) { + item.blockTexture = buildBlockTexture(slotProps.blockData as Record) + } else if (slotProps.slice) { + item.texture = extractSpriteDataUrl(slotProps.texture, slotProps.slice) + } + } catch { /* skip items that fail enrichment */ } +} + +/** Helper: convert a minecraft-data item ID to a minimal ItemStack for recipe guides */ +const idToItemStack = (id: number | null | undefined): InventoryItemStack | null => { + if (!id) return null + const data = loadedData.items[id] + if (!data) return null + const stack: InventoryItemStack = { type: id, count: 1, name: data.name, displayName: data.displayName } + enrichItemTexture(stack) + return stack +} + +/** + * Returns recipes for the given item name in the new library's RecipeGuide format. + * Used by Inventory.tsx for JEI recipe lookup. + */ +export const getItemRecipes = (itemName: string): RecipeGuide[] => { + if (!PrismarineItem) return [] const item = loadedData.itemsByName[itemName] - if (!item) return - const itemId = item.id - const recipes = loadedData.recipes?.[itemId] - if (!recipes) return - const results = [] as Array<{ - result: Item, - ingredients: Array, - description?: string - }> - - // get recipes here + if (!item) return [] + const recipes = loadedData.recipes?.[item.id] + if (!recipes) { + const description = getItemDescription(item as any) + if (description) return [{ type: 'custom', title: item.displayName, description }] + return [] + } + + const guides: RecipeGuide[] = [] + for (const recipe of recipes) { const { result } = recipe if (!result) continue - const resultId = typeof result === 'number' ? result : Array.isArray(result) ? result[0]! : result.id - const resultCount = (typeof result === 'number' ? undefined : Array.isArray(result) ? result[1] : result.count) ?? 1 - const resultMetadata = typeof result === 'object' && !Array.isArray(result) ? result.metadata : undefined - const resultItem = new PrismarineItem(resultId!, resultCount, resultMetadata) - if ('inShape' in recipe) { - const ingredients = recipe.inShape - if (!ingredients) continue - - const ingredientsItems = ingredients.flatMap(items => items.map(item => ingredientToItem(item))) - results.push({ result: resultItem, ingredients: ingredientsItems }) + const resultId = typeof result === 'number' ? result : Array.isArray(result) ? result[0]! : (result as any).id + const resultCount = (typeof result === 'number' ? undefined : Array.isArray(result) ? result[1] : (result as any).count) ?? 1 + const resultData = resultId ? loadedData.items[resultId as number] : undefined + if (!resultData) continue + const resultStack: InventoryItemStack = { type: resultId, count: resultCount, name: resultData.name, displayName: resultData.displayName } + enrichItemTexture(resultStack) + + if ('inShape' in recipe && recipe.inShape) { + // Expand shaped recipe into a 9-element 3x3 grid (top-left aligned) + const grid: Array = Array.from({ length: 9 }, () => null) + for (const [rowIdx, row] of recipe.inShape.entries()) { + if (rowIdx >= 3) continue + for (const [colIdx, id] of row.entries()) { + if (colIdx >= 3) continue + grid[rowIdx * 3 + colIdx] = idToItemStack(id as number | null | undefined) + } + } + guides.push({ type: 'crafting', title: resultData.displayName, ingredients: grid, result: resultStack }) } - if ('ingredients' in recipe) { - const { ingredients } = recipe - if (!ingredients) continue - const ingredientsItems = ingredients.map(item => ingredientToItem(item)) - results.push({ result: resultItem, ingredients: ingredientsItems, description: 'Shapeless' }) + + if ('ingredients' in recipe && recipe.ingredients) { + const grid: Array = Array.from({ length: 9 }, () => null) + for (const [i, id] of recipe.ingredients.slice(0, 9).entries()) { grid[i] = idToItemStack(id as number | null | undefined) } + guides.push({ type: 'crafting', title: resultData.displayName, description: 'Shapeless', ingredients: grid, result: resultStack }) } } - return results.map(({ result, ingredients, description }) => { - return [ - 'CraftingTableGuide', - mapSlots([result], true)[0], - mapSlots(ingredients, true), - description - ] - }) + + const description = getItemDescription(item as any) + if (description) guides.push({ type: 'custom', title: item.displayName, description }) + + return guides } -const getAllItemUsages = (itemName: string) => { +/** + * Returns usages (recipes where this item is an ingredient) in RecipeGuide format. + * Used by Inventory.tsx for JEI usage lookup. + */ +export const getItemUsages = (itemName: string): RecipeGuide[] => { const item = loadedData.itemsByName[itemName] - if (!item) return - const foundRecipeIds = [] as string[] + if (!item) return [] + const foundItemIds = new Set() for (const [id, recipes] of Object.entries(loadedData.recipes ?? {})) { for (const recipe of recipes) { - if ('inShape' in recipe) { - if (recipe.inShape.some(row => row.includes(item.id))) { - foundRecipeIds.push(id) - } + if ('inShape' in recipe && recipe.inShape.some(row => row.includes(item.id))) { + foundItemIds.add(id) } - if ('ingredients' in recipe) { - if (recipe.ingredients.includes(item.id)) { - foundRecipeIds.push(id) - } + if ('ingredients' in recipe && recipe.ingredients.includes(item.id)) { + foundItemIds.add(id) } } } - return foundRecipeIds.flatMap(id => { - // todo should use exact match, not include all recipes! - return getAllItemRecipes(loadedData.items[id].name) - }) + return [...foundItemIds].flatMap(id => getItemRecipes(loadedData.items[id].name)) +} + +/** + * Returns all JEI items (custom categories + vanilla items) for the new inventory UI. + * Items are enriched with texture/blockTexture data from the rendering pipeline. + */ +export const getJeiItems = (): JEIItem[] => { + if (jeiItemsCache) return jeiItemsCache + if (!PrismarineItem) return [] + + const customItems: JEIItem[] = jeiCustomCategories.value.flatMap(cat => (cat.items).filter(Boolean).map(item => ({ + type: item.type ?? item.id ?? 0, + name: item.name ?? '', + displayName: getItemName(item) ?? item.displayName ?? item.name ?? '', + }))) + + const vanillaItems: JEIItem[] = loadedData.itemsArray.map(item => ({ + type: item.id, + name: item.name, + displayName: item.displayName, + })) + + const allItems = [...customItems, ...vanillaItems] + + // Enrich items with texture data if the rendering pipeline is available + if (!appViewer?.resourcesManager?.currentResources) return allItems + + const { resourcesManager } = appViewer + const playerState = appViewer.playerState?.reactive + if (!playerState) return allItems + + for (const item of allItems) { + try { + const modelName = getItemModelName( + { name: item.name, nbt: null }, + { 'minecraft:display_context': 'gui' }, + resourcesManager, + playerState + ) + const slotProps = renderSlot({ modelName, originalItemName: item.name }, resourcesManager) + + if (slotProps.blockData) { + item.blockTexture = buildBlockTexture(slotProps.blockData as Record) + } else if (slotProps.slice) { + item.texture = extractSpriteDataUrl(slotProps.texture, slotProps.slice) + } + } catch { + // Skip texture enrichment for items that fail — they'll fall back to CDN sprites + } + } + + jeiItemsCache = allItems + return allItems } diff --git a/src/mineflayer/plugins/mouse.ts b/src/mineflayer/plugins/mouse.ts index 14e193455..1ca73ceb2 100644 --- a/src/mineflayer/plugins/mouse.ts +++ b/src/mineflayer/plugins/mouse.ts @@ -45,7 +45,9 @@ function cursorBlockDisplay (bot: Bot) { } export default (bot: Bot) => { - bot.loadPlugin(createMouse({})) + bot.loadPlugin(createMouse({ + useMineflayerInteractMethods: false, + })) domListeners(bot) cursorBlockDisplay(bot) diff --git a/src/optionsGuiScheme.tsx b/src/optionsGuiScheme.tsx index 2bc0fb660..d86c2e447 100644 --- a/src/optionsGuiScheme.tsx +++ b/src/optionsGuiScheme.tsx @@ -197,16 +197,16 @@ export const guiOptionsScheme: { return } if (choice === 'Uninstall') { - // todo make hidable + // todo make hidable setLoadingScreenStatus('Uninstalling texturepack') await uninstallResourcePack() setLoadingScreenStatus(undefined) } } else { - // if (!fsState.inMemorySave && isGameActive(false)) { - // alert('Unable to install resource pack in loaded save for now') - // return - // } + // if (!fsState.inMemorySave && isGameActive(false)) { + // alert('Unable to install resource pack in loaded save for now') + // return + // } openFilePicker('resourcepack') } }} @@ -258,6 +258,13 @@ export const guiOptionsScheme: { unit: '', delayApply: true, }, + }, + { + custom () { + return