diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index cef6a14..0000000 --- a/.dockerignore +++ /dev/null @@ -1,4 +0,0 @@ -* -!/Cargo.* -!/src -!/crates diff --git a/.github/workflows/MinedMap.yml b/.github/workflows/MinedMap.yml index a0e58cf..c2e9961 100644 --- a/.github/workflows/MinedMap.yml +++ b/.github/workflows/MinedMap.yml @@ -1,14 +1,5 @@ name: 'MinedMap' -on: - push: - branches: - - 'main' - tags: - - 'v*' - pull_request: - branches: - - 'main' - workflow_dispatch: {} +on: ['push', 'pull_request', 'workflow_dispatch'] env: RUSTFLAGS: -Dwarnings @@ -16,7 +7,7 @@ env: jobs: viewer: - runs-on: 'ubuntu-latest' + runs-on: 'ubuntu-20.04' steps: - name: 'Checkout' @@ -34,10 +25,9 @@ jobs: pkgdir='build/pkg/MinedMap-${{ steps.tag.outputs.tag }}-viewer' mkdir -p "$pkgdir" cp -r viewer/* "$pkgdir"/ - rm "$pkgdir"/Dockerfile - name: 'Archive' - uses: 'actions/upload-artifact@v4' + uses: 'actions/upload-artifact@v3' with: name: 'MinedMap-${{ steps.tag.outputs.tag }}-viewer' path: 'build/pkg' @@ -48,7 +38,7 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: - toolchain: '1.88' + toolchain: stable components: rustfmt - run: cargo fmt --all -- --check @@ -58,7 +48,7 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: - toolchain: '1.88' + toolchain: stable components: clippy - uses: swatinem/rust-cache@v2 - uses: actions-rs/clippy-check@v1 @@ -72,7 +62,7 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: - toolchain: '1.88' + toolchain: stable components: rust-docs - uses: swatinem/rust-cache@v2 - run: cargo doc --workspace --no-deps --document-private-items @@ -83,11 +73,12 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macOS-latest] + rust: [stable] steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: - toolchain: '1.88' + toolchain: ${{ matrix.rust }} - uses: swatinem/rust-cache@v2 - run: cargo test --workspace - run: cargo test --workspace --no-default-features @@ -110,7 +101,7 @@ jobs: - os: 'windows-2019' target: 'i686-pc-windows-msvc' ext: '.exe' - - os: 'ubuntu-22.04' + - os: 'ubuntu-20.04' target: 'x86_64-unknown-linux-gnu' steps: @@ -127,12 +118,10 @@ jobs: - uses: dtolnay/rust-toolchain@master with: - toolchain: '1.88' + toolchain: stable targets: '${{ matrix.target }}' - uses: swatinem/rust-cache@v2 - with: - key: '${{ matrix.target }}' - name: 'Build' shell: 'bash' @@ -145,94 +134,7 @@ jobs: cp target/${{ matrix.target }}/release/minedmap${{ matrix.ext }} "$pkgdir"/ - name: 'Archive' - uses: 'actions/upload-artifact@v4' + uses: 'actions/upload-artifact@v3' with: name: 'MinedMap-${{ steps.tag.outputs.tag }}-${{ matrix.target }}' path: 'target/pkg' - - build-container: - runs-on: ubuntu-latest - needs: - - test - steps: - - name: 'Checkout' - uses: 'actions/checkout@v4' - - - name: 'Get version' - id: 'tag' - run: | - set -o pipefail - git fetch --prune --unshallow --tags -f - echo "tag=$(git describe --abbrev=7 --match='v*' | sed 's/^v//')" >> $GITHUB_OUTPUT - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: | - ghcr.io/neocturne/minedmap/minedmap - tags: | - type=raw,value=latest,enable={{is_default_branch}} - type=ref,event=branch - type=ref,event=branch,suffix=-{{sha}} - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - - - name: Login to GHCR - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - uses: docker/setup-buildx-action@v3 - - - name: Build - uses: docker/build-push-action@v6 - with: - build-args: | - MINEDMAP_VERSION=${{ steps.tag.outputs.tag }} - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - viewer-container: - runs-on: ubuntu-latest - needs: - - test - steps: - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: | - ghcr.io/neocturne/minedmap/viewer - tags: | - type=raw,value=latest,enable={{is_default_branch}} - type=ref,event=branch - type=ref,event=branch,suffix=-{{sha}} - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - - - name: Login to GHCR - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - uses: docker/setup-buildx-action@v3 - - - name: Build - uses: docker/build-push-action@v6 - with: - context: "{{defaultContext}}:viewer" - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} diff --git a/CHANGELOG.md b/CHANGELOG.md index f1f0234..e75a75b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,81 +2,6 @@ ## [Unreleased] - ReleaseDate -## [2.6.0] - 2025-06-30 - -### Added - -- Added support for Minecraft 1.21.5 to 1.21.7 - - Added new block types and handling for changed sign text storage format. - -## [2.5.0] - 2025-03-16 - -### Added - -- Added experimental watch mode - - Passing `--watch` will cause MinedMap to run continuously instead of exiting - after map generation, regenerating tiles whenever they change. - - `--watch-delay` can be used to configure the delay between detecting a change - and runing the map generation, also limiting how often the regeneration - happens. This defaults to `30s`; significantly smaller values probably don't - make sense because Minecraft writes out changes in batches anyways. - - Finally, `--jobs-initial` can be used to configure the number of parallel - generation threads for the initial cycle separately from the value used for - subsequent cycles after a change is detected (`-j`/`--jobs`). Subsequent - cycles usually need to regenerate only a small number of tiles, so setting - `--jobs` to a smaller value than `--jobs-initial` may be advantageous. - -- Added jemalloc support to fix performace on musl targets - - The global allocator can be switched to jemalloc by enabling the `jemalloc` - cargo feature now. This is not the default because it is not always faster - than the default system allocator; in particular, the glibc allocator has - slightly better performance in multithreaded mode. In addition, jemalloc - uses a bit more memory. - - In addition, the `jemalloc-auto` feature has been introduced, which is enabled - by default and sets the global allocator to jemalloc on platforms where it is - clearly advantageous. For now, this is only done on musl-based targets, as - musl's default allocator is very slow in multithreaded operation (which was - making higher thread counts like `-j8` basically useless due to 7-8x - slowdowns). With the new default, performance on musl is basically identical - to glibc. - - Note that some platforms like `msvc` are unsupported by jemalloc, and trying - to enable the `jemalloc` feature on these platforms may break the MinedMap - build or cause issues at runtime. -- Docker images can be downloaded from the GitHub Container registry - - Two images are provided, one for the tile renderer and one with the viewer - and a web server. A `docker-compose.yml` example can be found in the - repository as a starting point. - -### Changed - -- Unknown biome types (from not yet supported or modded versions of Minecraft) - will now use plains biome colors as a fallback instead of resulting in water, - grass and foliage blocks to be rendered as transparent pixels -- Switched from zlib-ng to zlib-rs - - This should have no noticable effect on the usage of MinedMap, but avoids - an external build dependency on CMake. -- Small (1-block) seagrass is now visible on the map - - 1-block seagrass in 1-block deep water would previously result in the ground - to be shown instead of water, as MinedMap currently doesn't handle the - "waterlogged" block status. As 1-block seagrass is relatively big compared to - other "small" plants, just considering it opaque seems like a good enough - solution that avoids having to implement advanced block status flags. -- Use Bincode 2 for storage of intermediate data - - The update from Bincode 1 to 2 slightly reduces the size of the `processed` - directory used for intermediate data. At least Rust 1.85 is now required to - build MinedMap. - ## [2.4.0] - 2025-01-11 ### Added @@ -196,9 +121,7 @@ intermediate data. Full support for custom biomes datapacks might be added in a future release. -[Unreleased]: https://github.com/neocturne/MinedMap/compare/v2.6.0...HEAD -[2.6.0]: https://github.com/neocturne/MinedMap/compare/v2.5.0...v2.6.0 -[2.5.0]: https://github.com/neocturne/MinedMap/compare/v2.4.0...v2.5.0 +[Unreleased]: https://github.com/neocturne/MinedMap/compare/v2.4.0...HEAD [2.4.0]: https://github.com/neocturne/MinedMap/compare/v2.3.1...v2.4.0 [2.3.1]: https://github.com/neocturne/MinedMap/compare/v2.3.0...v2.3.1 [2.3.0]: https://github.com/neocturne/MinedMap/compare/v2.2.0...v2.3.0 diff --git a/Cargo.lock b/Cargo.lock index a000b9d..5b6de78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" @@ -34,9 +34,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "anstream" -version = "0.6.19" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -49,56 +49,55 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.3" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.59.0", + "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.9" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "once_cell_polyfill", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.75" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", "cfg-if", @@ -106,27 +105,16 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] name = "bincode" -version = "2.0.1" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ - "bincode_derive", "serde", - "unty", -] - -[[package]] -name = "bincode_derive" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" -dependencies = [ - "virtue", ] [[package]] @@ -137,15 +125,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" [[package]] name = "bytemuck" -version = "1.23.1" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "byteorder" @@ -161,9 +149,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "cc" -version = "1.2.27" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" +checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" dependencies = [ "jobserver", "libc", @@ -178,15 +166,15 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.40" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", "clap_derive", @@ -194,9 +182,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.40" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstream", "anstyle", @@ -207,9 +195,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.40" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck", "proc-macro2", @@ -219,15 +207,24 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "cmake" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" +dependencies = [ + "cc", +] [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "crc32fast" @@ -265,9 +262,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "either" -version = "1.15.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "enum-map" @@ -291,18 +288,19 @@ dependencies = [ [[package]] name = "enumflags2" -version = "0.7.12" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" dependencies = [ "enumflags2_derive", + "serde", ] [[package]] name = "enumflags2_derive" -version = "0.7.12" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", @@ -311,18 +309,28 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "erased-serde" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" +dependencies = [ + "serde", + "typeid", +] [[package]] name = "errno" -version = "0.3.13" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys", ] [[package]] @@ -337,12 +345,6 @@ dependencies = [ "serde_bytes", ] -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - [[package]] name = "fdeflate" version = "0.3.7" @@ -352,43 +354,22 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "filetime" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" -dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.59.0", -] - [[package]] name = "flate2" -version = "1.1.2" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", - "libz-rs-sys", + "libz-ng-sys", "miniz_oxide", ] [[package]] name = "foldhash" -version = "0.1.5" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" [[package]] name = "futures-core" @@ -427,18 +408,6 @@ dependencies = [ "slab", ] -[[package]] -name = "getrandom" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", -] - [[package]] name = "gimli" version = "0.31.1" @@ -467,15 +436,15 @@ dependencies = [ [[package]] name = "glam" -version = "0.30.4" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50a99dbe56b72736564cfa4b85bf9a33079f16ae8b74983ab06af3b1a3696b11" +checksum = "dc46dd3ec48fdd8e693a98d2b8bafae273a2d54c1de02a2a7e3d57d501f39677" [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", @@ -490,21 +459,15 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.5.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "humantime" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "image" -version = "0.25.6" +version = "0.25.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" +checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" dependencies = [ "bytemuck", "byteorder-lite", @@ -515,9 +478,9 @@ dependencies = [ [[package]] name = "image-webp" -version = "0.2.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6970fe7a5300b4b42e62c52efa0187540a5bef546c60edaf554ef595d2e6f0b" +checksum = "e031e8e3d94711a9ccb5d6ea357439ef3dcbed361798bd4071dc4d9793fbe22f" dependencies = [ "byteorder-lite", "quick-error", @@ -525,32 +488,13 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.10.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", -] - -[[package]] -name = "inotify" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" -dependencies = [ - "bitflags 2.9.1", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", + "serde", ] [[package]] @@ -570,37 +514,16 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ - "getrandom", - "libc", -] - -[[package]] -name = "kqueue" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" -dependencies = [ - "bitflags 1.3.2", "libc", ] @@ -612,41 +535,31 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.174" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] -name = "libredox" -version = "0.1.4" +name = "libz-ng-sys" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638" +checksum = "7cee1488e961a80d172564fd6fcda11d8a4ac6672c06fe008e9213fa60520c2b" dependencies = [ - "bitflags 2.9.1", + "cmake", "libc", - "redox_syscall", -] - -[[package]] -name = "libz-rs-sys" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172a788537a2221661b480fee8dc5f96c580eb34fa88764d3205dc356c7e4221" -dependencies = [ - "zlib-rs", ] [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -654,46 +567,45 @@ dependencies = [ [[package]] name = "log" -version = "0.4.27" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "3d6ea2a48c204030ee31a7d7fc72c93294c92fe87ecb1789881c9543516e1a0d" +dependencies = [ + "value-bag", +] [[package]] name = "lru" -version = "0.15.0" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0281c2e25e62316a5c9d98f2d2e9e95a37841afdaf4383c177dbb5c1dfab0568" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ "hashbrown", ] [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "minedmap" -version = "2.6.0" +version = "2.4.0" dependencies = [ "anyhow", "bincode", "clap", "enum-map", "fastnbt", - "flate2", "futures-util", "git-version", - "humantime", "image", "indexmap", "lru", - "minedmap-default-alloc", "minedmap-nbt", "minedmap-resource", "minedmap-types", - "notify", "num-integer", "num_cpus", "phf", @@ -708,16 +620,9 @@ dependencies = [ "zstd", ] -[[package]] -name = "minedmap-default-alloc" -version = "0.1.0" -dependencies = [ - "tikv-jemallocator", -] - [[package]] name = "minedmap-nbt" -version = "0.2.0" +version = "0.1.1" dependencies = [ "anyhow", "bytemuck", @@ -730,68 +635,31 @@ dependencies = [ [[package]] name = "minedmap-resource" -version = "0.8.0" +version = "0.6.0" dependencies = [ - "bincode", "enumflags2", "glam", + "serde", ] [[package]] name = "minedmap-types" -version = "0.2.0" +version = "0.1.4" dependencies = [ - "bincode", "itertools", + "serde", ] [[package]] name = "miniz_oxide" -version = "0.8.9" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ "adler2", "simd-adler32", ] -[[package]] -name = "mio" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" -dependencies = [ - "libc", - "log", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", -] - -[[package]] -name = "notify" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" -dependencies = [ - "bitflags 2.9.1", - "filetime", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "log", - "mio", - "notify-types", - "walkdir", - "windows-sys 0.59.0", -] - -[[package]] -name = "notify-types" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -822,9 +690,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.17.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", @@ -841,15 +709,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "once_cell_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "overload" @@ -859,9 +721,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -869,43 +731,42 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] name = "phf" -version = "0.12.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_macros", "phf_shared", - "serde", ] [[package]] name = "phf_generator" -version = "0.12.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cbb1126afed61dd6368748dae63b1ee7dc480191c6262a3b4ff1e29d86a6c5b" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "fastrand", "phf_shared", + "rand", ] [[package]] name = "phf_macros" -version = "0.12.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d713258393a82f091ead52047ca779d37e5766226d009de21696c4e667044368" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ "phf_generator", "phf_shared", @@ -916,9 +777,9 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.12.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] @@ -937,9 +798,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "png" @@ -956,9 +817,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -971,18 +832,27 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.40" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] -name = "r-efi" -version = "5.3.0" +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" [[package]] name = "rayon" @@ -1006,11 +876,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.13" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.7.0", ] [[package]] @@ -1044,43 +914,34 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustc-demangle" -version = "0.1.25" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustix" -version = "1.0.7" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.7.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "scopeguard" @@ -1090,27 +951,27 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.17" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -1118,10 +979,19 @@ dependencies = [ ] [[package]] -name = "serde_json" -version = "1.0.140" +name = "serde_fmt" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "e1d4ddca14104cd60529e8c7f7ba71a2c8acd8f7f5cfcdc2faf97eeb7c3010a4" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_json" +version = "1.0.135" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", "memchr", @@ -1158,15 +1028,18 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" -version = "0.4.10" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] [[package]] name = "smallvec" -version = "1.15.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "strsim" @@ -1175,10 +1048,88 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "syn" -version = "2.0.104" +name = "sval" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "f6dc0f9830c49db20e73273ffae9b5240f63c42e515af1da1fceefb69fceafd8" + +[[package]] +name = "sval_buffer" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "429922f7ad43c0ef8fd7309e14d750e38899e32eb7e8da656ea169dd28ee212f" +dependencies = [ + "sval", + "sval_ref", +] + +[[package]] +name = "sval_dynamic" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f16ff5d839396c11a30019b659b0976348f3803db0626f736764c473b50ff4" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_fmt" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c01c27a80b6151b0557f9ccbe89c11db571dc5f68113690c1e028d7e974bae94" +dependencies = [ + "itoa", + "ryu", + "sval", +] + +[[package]] +name = "sval_json" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0deef63c70da622b2a8069d8600cf4b05396459e665862e7bdb290fd6cf3f155" +dependencies = [ + "itoa", + "ryu", + "sval", +] + +[[package]] +name = "sval_nested" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a39ce5976ae1feb814c35d290cf7cf8cd4f045782fe1548d6bc32e21f6156e9f" +dependencies = [ + "sval", + "sval_buffer", + "sval_ref", +] + +[[package]] +name = "sval_ref" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7c6ee3751795a728bc9316a092023529ffea1783499afbc5c66f5fabebb1fa" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_serde" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a5572d0321b68109a343634e3a5d576bf131b82180c6c442dee06349dfc652a" +dependencies = [ + "serde", + "sval", + "sval_nested", +] + +[[package]] +name = "syn" +version = "2.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -1187,48 +1138,29 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" +checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" dependencies = [ "rustix", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] name = "thread_local" -version = "1.1.9" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", -] - -[[package]] -name = "tikv-jemalloc-sys" -version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "tikv-jemallocator" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cec5ff18518d81584f477e9bfdf957f5bb0979b0bac3af4ca30b5b3ae2d2865" -dependencies = [ - "libc", - "tikv-jemalloc-sys", + "once_cell", ] [[package]] name = "tokio" -version = "1.45.1" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "parking_lot", @@ -1248,9 +1180,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", @@ -1259,9 +1191,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -1293,16 +1225,16 @@ dependencies = [ ] [[package]] -name = "unicode-ident" -version = "1.0.18" +name = "typeid" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" [[package]] -name = "unty" -version = "0.0.4" +name = "unicode-ident" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "utf8parse" @@ -1312,39 +1244,44 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] -name = "virtue" -version = "0.0.18" +name = "value-bag" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" dependencies = [ - "same-file", - "winapi-util", + "value-bag-serde1", + "value-bag-sval2", ] [[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" +name = "value-bag-serde1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +checksum = "4bb773bd36fd59c7ca6e336c94454d9c66386416734817927ac93d81cb3c5b0b" +dependencies = [ + "erased-serde", + "serde", + "serde_fmt", +] [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "value-bag-sval2" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "53a916a702cac43a88694c97657d449775667bcd14b70419441d05b7fea4a83a" dependencies = [ - "wit-bindgen-rt", + "sval", + "sval_buffer", + "sval_dynamic", + "sval_fmt", + "sval_json", + "sval_ref", + "sval_serde", ] [[package]] @@ -1363,15 +1300,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1384,16 +1312,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.2", + "windows-targets", ] [[package]] @@ -1402,30 +1321,14 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -1434,134 +1337,71 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.1", -] - -[[package]] -name = "zlib-rs" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a" - [[package]] name = "zstd" -version = "0.13.3" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.2.4" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.15+zstd.1.5.7" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index f0c2bc0..2412edb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ members = ["crates/*"] [workspace.package] -edition = "2024" +edition = "2021" license = "MIT" readme = "README.md" repository = "https://github.com/neocturne/MinedMap" @@ -13,7 +13,7 @@ pre-release-commit-message = "{{crate_name}} {{version}}" [package] name = "minedmap" -version = "2.6.0" +version = "2.4.0" description = "Generate browsable maps from Minecraft save data" edition.workspace = true license.workspace = true @@ -38,29 +38,25 @@ pre-release-replacements = [ [dependencies] anyhow = "1.0.68" -bincode = "2.0.1" +bincode = "1.3.3" clap = { version = "4.1.4", features = ["derive", "wrap_help"] } enum-map = "2.7.3" fastnbt = "2.3.2" -flate2 = { version = "1.1.0", features = ["zlib-rs"] } futures-util = "0.3.28" git-version = "0.3.5" -humantime = "2.1.0" image = { version = "0.25.1", default-features = false, features = ["png", "webp"] } -indexmap = "2.0.0" -lru = "0.15.0" -minedmap-default-alloc = { version = "0.1.0", path = "crates/default-alloc", optional = true } -minedmap-nbt = { version = "0.2.0", path = "crates/nbt", default-features = false } -minedmap-resource = { version = "0.8.0", path = "crates/resource" } -minedmap-types = { version = "0.2.0", path = "crates/types" } -notify = "8.0.0" +indexmap = { version = "2.0.0", features = ["serde"] } +lru = "0.12.0" +minedmap-nbt = { version = "0.1.1", path = "crates/nbt", default-features = false } +minedmap-resource = { version = "0.6.0", path = "crates/resource" } +minedmap-types = { version = "0.1.4", path = "crates/types" } num-integer = "0.1.45" num_cpus = "1.16.0" -phf = { version = "0.12.1", features = ["macros"] } +phf = { version = "0.11.2", features = ["macros"] } rayon = "1.7.0" regex = "1.10.2" rustc-hash = "2.0.0" -serde = { version = "1.0.152", features = ["derive"] } +serde = { version = "1.0.152", features = ["rc", "derive"] } serde_json = "1.0.99" tokio = { version = "1.31.0", features = ["rt", "parking_lot", "sync"] } tracing = "0.1.37" @@ -68,6 +64,5 @@ tracing-subscriber = "0.3.17" zstd = "0.13.0" [features] -default = ["jemalloc-auto"] -jemalloc-auto = ["dep:minedmap-default-alloc"] -jemalloc = ["jemalloc-auto", "minedmap-default-alloc/jemalloc"] +default = ["zlib-ng"] +zlib-ng = ["minedmap-nbt/zlib-ng"] diff --git a/Dockerfile b/Dockerfile index 4b9de31..fa3627c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,17 +1,14 @@ -FROM docker.io/library/rust:1.88.0-alpine AS builder +FROM docker.io/library/rust:alpine AS BUILDER WORKDIR /build -RUN apk add --no-cache build-base tini-static +RUN apk update && apk add cmake build-base -ARG MINEDMAP_VERSION - -COPY . . +COPY src /build/src +COPY crates /build/crates +COPY Cargo.toml Cargo.lock /build RUN cargo build -r -RUN strip target/release/minedmap -FROM scratch +FROM scratch AS RUNNER -COPY --from=builder /sbin/tini-static /build/target/release/minedmap /bin/ -ENTRYPOINT [ "/bin/tini-static", "--", "/bin/minedmap" ] - -USER 1000:1000 +COPY --from=BUILDER /build/target/release/minedmap /minedmap +ENTRYPOINT [ "/minedmap" ] diff --git a/Dockerfile.viewer b/Dockerfile.viewer new file mode 100644 index 0000000..82d50bb --- /dev/null +++ b/Dockerfile.viewer @@ -0,0 +1,3 @@ +FROM docker.io/library/nginx:alpine +COPY viewer /usr/share/nginx/html +# datadir should be mounted to: /usr/share/nginx/html/data diff --git a/README.md b/README.md index cd30c8b..1ea4856 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ * Render beautiful maps of your [Minecraft](https://minecraft.net/) worlds! * Put them on a webserver and view them in your browser! -* Compatible with unmodified Minecraft Java Edition 1.8 up to 1.21.7 (no mod installation required!) +* Compatible with unmodified Minecraft Java Edition 1.8 up to 1.21.4 (no mod installation required!) * Illumination layer: the world at night * Fast: create a full map for a huge 3GB savegame in less than 5 minutes in single-threaded operation * Multi-threading support: pass `-j N` to the renderer to use `N` parallel threads for generation @@ -61,7 +61,7 @@ updates more quickly. ### Image formats MinedMap renders map tiles as PNG by default. Pass `--image-format webp` to select -WebP instead. For typical Minecraft worlds, using WebP reduces file sizes by 20-25% +WebP instead. For typical Minecraft worlds, using WebP reduces file sizes by 10-15% without increasing processing time. MinedMap always uses lossless compression for tile images, regardless of the @@ -117,11 +117,11 @@ or newer). The following command can be used to build the current development ve cargo install --git 'https://github.com/neocturne/MinedMap.git' ``` +In addition, CMake is needed to build the zlib-ng library. If you do not have +CMake installed, you can disable the zlib-ng feature by passing `--no-default-features` +to cargo. A pure-Rust zlib implementation will be used, which is more portable, +but slower than zlib-ng. + If you are looking for the older C++ implementation of the MinedMap tile renderer, see the [v1.19.1](https://github.com/neocturne/MinedMap/tree/v1.19.1) tag. -## See also - -Other projects using MinedMap: - -- [minecraft\_map\_marker](https://github.com/christopher-besch/minecraft_map_marker) diff --git a/crates/default-alloc/Cargo.toml b/crates/default-alloc/Cargo.toml deleted file mode 100644 index b03a871..0000000 --- a/crates/default-alloc/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "minedmap-default-alloc" -version = "0.1.0" -description = "Helper crate for target-specific selection of global allocator default" -edition.workspace = true -license.workspace = true -readme.workspace = true -repository.workspace = true - -[dependencies] -tikv-jemallocator = { version = "0.6.0", optional = true } - -[target.'cfg(target_env = "musl")'.dependencies] -tikv-jemallocator = "0.6.0" - -[features] -jemalloc = ["dep:tikv-jemallocator"] diff --git a/crates/default-alloc/src/lib.rs b/crates/default-alloc/src/lib.rs deleted file mode 100644 index 0797a5f..0000000 --- a/crates/default-alloc/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -#[cfg(any(target_env = "musl", feature = "jemalloc"))] -#[global_allocator] -static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; diff --git a/crates/nbt/Cargo.toml b/crates/nbt/Cargo.toml index 07a5fd7..9f815da 100644 --- a/crates/nbt/Cargo.toml +++ b/crates/nbt/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minedmap-nbt" -version = "0.2.0" +version = "0.1.1" description = "MinedMap's handling of Minecraft NBT data and region files" edition.workspace = true license.workspace = true @@ -11,10 +11,12 @@ repository.workspace = true anyhow = "1.0.75" bytemuck = "1.13.1" fastnbt = "2.4.4" -flate2 = "1.1.0" -minedmap-types = { version = "0.2.0", path = "../types" } +flate2 = "1.0.27" +minedmap-types = { version = "0.1.4", path = "../types" } serde = "1.0.183" +[features] +zlib-ng = ["flate2/zlib-ng"] + [dev-dependencies] clap = { version = "4.3.23", features = ["derive"] } -flate2 = { version = "1.1.0", features = ["zlib-rs"] } diff --git a/crates/nbt/examples/nbtdump.rs b/crates/nbt/examples/nbtdump.rs index 8b61693..66aaa2a 100644 --- a/crates/nbt/examples/nbtdump.rs +++ b/crates/nbt/examples/nbtdump.rs @@ -20,7 +20,7 @@ fn main() -> Result<()> { let args = Args::parse(); let value: fastnbt::Value = minedmap_nbt::data::from_file(args.file.as_path())?; - println!("{value:#x?}"); + println!("{:#x?}", value); Ok(()) } diff --git a/crates/nbt/examples/regiondump.rs b/crates/nbt/examples/regiondump.rs index 7cece8c..9315022 100644 --- a/crates/nbt/examples/regiondump.rs +++ b/crates/nbt/examples/regiondump.rs @@ -21,7 +21,7 @@ fn main() -> Result<()> { minedmap_nbt::region::from_file(args.file.as_path())?.foreach_chunk( |coords, value: fastnbt::Value| { - println!("Chunk {coords:?}: {value:#x?}"); + println!("Chunk {:?}: {:#x?}", coords, value); Ok(()) }, ) diff --git a/crates/nbt/src/region.rs b/crates/nbt/src/region.rs index 6a79a39..8a52b9d 100644 --- a/crates/nbt/src/region.rs +++ b/crates/nbt/src/region.rs @@ -2,11 +2,11 @@ use std::{ fs::File, - io::{SeekFrom, prelude::*}, + io::{prelude::*, SeekFrom}, path::Path, }; -use anyhow::{Context, Result, bail}; +use anyhow::{bail, Context, Result}; use flate2::read::ZlibDecoder; use serde::de::DeserializeOwned; @@ -124,7 +124,7 @@ impl Region { let mut len_buf = [0u8; 4]; reader .read_exact(&mut len_buf) - .with_context(|| format!("Failed to read length for chunk {coords:?}"))?; + .with_context(|| format!("Failed to read length for chunk {:?}", coords))?; let byte_len = u32::from_be_bytes(len_buf) as usize; if byte_len < 1 || byte_len > (len as usize) * BLOCKSIZE - 4 { bail!("Invalid length for chunk {:?}", coords); @@ -133,9 +133,9 @@ impl Region { let mut buffer = vec![0; byte_len]; reader .read_exact(&mut buffer) - .with_context(|| format!("Failed to read data for chunk {coords:?}"))?; + .with_context(|| format!("Failed to read data for chunk {:?}", coords))?; let chunk = decode_chunk(&buffer) - .with_context(|| format!("Failed to decode data for chunk {coords:?}"))?; + .with_context(|| format!("Failed to decode data for chunk {:?}", coords))?; f(coords, chunk)?; } diff --git a/crates/resource/Cargo.toml b/crates/resource/Cargo.toml index b59492c..4e0d512 100644 --- a/crates/resource/Cargo.toml +++ b/crates/resource/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minedmap-resource" -version = "0.8.0" +version = "0.6.0" description = "Data describing Minecraft biomes and block types" edition.workspace = true license.workspace = true @@ -8,6 +8,6 @@ readme.workspace = true repository.workspace = true [dependencies] -bincode = "2.0.1" -enumflags2 = "0.7.7" -glam = "0.30.0" +enumflags2 = { version = "0.7.7", features = ["serde"] } +glam = "0.29.2" +serde = { version = "1.0.183", features = ["derive"] } diff --git a/crates/resource/src/block_types.rs b/crates/resource/src/block_types.rs index 9419690..53abd54 100644 --- a/crates/resource/src/block_types.rs +++ b/crates/resource/src/block_types.rs @@ -1488,16 +1488,6 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), - ( - "bush", - ConstBlockType { - block_color: BlockColor { - flags: make_bitflags!(BlockFlag::{Opaque|Grass}), - color: Color([119, 120, 119]), - }, - sign_material: None, - }, - ), ( "cactus", ConstBlockType { @@ -1508,16 +1498,6 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), - ( - "cactus_flower", - ConstBlockType { - block_color: BlockColor { - flags: make_bitflags!(BlockFlag::{Opaque}), - color: Color([209, 120, 135]), - }, - sign_material: None, - }, - ), ( "cake", ConstBlockType { @@ -3508,16 +3488,6 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), - ( - "dried_ghast", - ConstBlockType { - block_color: BlockColor { - flags: make_bitflags!(BlockFlag::{Opaque}), - color: Color([179, 168, 168]), - }, - sign_material: None, - }, - ), ( "dried_kelp_block", ConstBlockType { @@ -3838,16 +3808,6 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), - ( - "firefly_bush", - ConstBlockType { - block_color: BlockColor { - flags: make_bitflags!(BlockFlag::{Opaque}), - color: Color([87, 83, 43]), - }, - sign_material: None, - }, - ), ( "fletching_table", ConstBlockType { @@ -4918,16 +4878,6 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), - ( - "leaf_litter", - ConstBlockType { - block_color: BlockColor { - flags: make_bitflags!(BlockFlag::{}), - color: Color([0, 0, 0]), - }, - sign_material: None, - }, - ), ( "lectern", ConstBlockType { @@ -8742,18 +8692,8 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ "seagrass", ConstBlockType { block_color: BlockColor { - flags: make_bitflags!(BlockFlag::{Opaque}), - color: Color([50, 126, 8]), - }, - sign_material: None, - }, - ), - ( - "short_dry_grass", - ConstBlockType { - block_color: BlockColor { - flags: make_bitflags!(BlockFlag::{Opaque}), - color: Color([187, 158, 108]), + flags: make_bitflags!(BlockFlag::{}), + color: Color([0, 0, 0]), }, sign_material: None, }, @@ -9698,16 +9638,6 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), - ( - "tall_dry_grass", - ConstBlockType { - block_color: BlockColor { - flags: make_bitflags!(BlockFlag::{Opaque}), - color: Color([196, 171, 122]), - }, - sign_material: None, - }, - ), ( "tall_grass", ConstBlockType { @@ -9748,26 +9678,6 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), - ( - "test_block", - ConstBlockType { - block_color: BlockColor { - flags: make_bitflags!(BlockFlag::{}), - color: Color([0, 0, 0]), - }, - sign_material: None, - }, - ), - ( - "test_instance_block", - ConstBlockType { - block_color: BlockColor { - flags: make_bitflags!(BlockFlag::{}), - color: Color([0, 0, 0]), - }, - sign_material: None, - }, - ), ( "tinted_glass", ConstBlockType { @@ -10918,16 +10828,6 @@ pub const BLOCK_TYPES: &[(&str, ConstBlockType)] = &[ sign_material: None, }, ), - ( - "wildflowers", - ConstBlockType { - block_color: BlockColor { - flags: make_bitflags!(BlockFlag::{}), - color: Color([0, 0, 0]), - }, - sign_material: None, - }, - ), ( "wither_rose", ConstBlockType { diff --git a/crates/resource/src/lib.rs b/crates/resource/src/lib.rs index 86cfb0f..fed9514 100644 --- a/crates/resource/src/lib.rs +++ b/crates/resource/src/lib.rs @@ -10,13 +10,13 @@ mod legacy_block_types; use std::collections::HashMap; -use bincode::{BorrowDecode, Decode, Encode}; -use enumflags2::{BitFlags, bitflags}; +use enumflags2::{bitflags, BitFlags}; +use serde::{Deserialize, Serialize}; /// Flags describing special properties of [BlockType]s #[bitflags] #[repr(u8)] -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] pub enum BlockFlag { /// The block type is opaque Opaque, @@ -38,14 +38,14 @@ pub enum BlockFlag { } /// An RGB color with u8 components -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] pub struct Color(pub [u8; 3]); /// An RGB color with f32 components pub type Colorf = glam::Vec3; /// A block type specification -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] pub struct BlockColor { /// Bit set of [BlockFlag]s describing special properties of the block type pub flags: BitFlags, @@ -61,43 +61,6 @@ impl BlockColor { } } -impl Encode for BlockColor { - fn encode( - &self, - encoder: &mut E, - ) -> Result<(), bincode::error::EncodeError> { - bincode::Encode::encode(&self.flags.bits(), encoder)?; - bincode::Encode::encode(&self.color, encoder)?; - Ok(()) - } -} - -impl Decode for BlockColor { - fn decode>( - decoder: &mut D, - ) -> Result { - Ok(BlockColor { - flags: BitFlags::from_bits(bincode::Decode::decode(decoder)?).or(Err( - bincode::error::DecodeError::Other("invalid block flags"), - ))?, - color: bincode::Decode::decode(decoder)?, - }) - } -} - -impl<'de, Context> BorrowDecode<'de, Context> for BlockColor { - fn borrow_decode>( - decoder: &mut D, - ) -> Result { - Ok(BlockColor { - flags: BitFlags::from_bits(bincode::BorrowDecode::borrow_decode(decoder)?).or(Err( - bincode::error::DecodeError::Other("invalid block flags"), - ))?, - color: bincode::BorrowDecode::borrow_decode(decoder)?, - }) - } -} - /// A block type specification (for use in constants) #[derive(Debug, Clone)] struct ConstBlockType { @@ -174,7 +137,7 @@ impl BlockTypes { pub use block_color::{block_color, needs_biome}; /// Grass color modifier used by a biome -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum BiomeGrassColorModifier { /// Grass color modifier used by the dark forest biome DarkForest, @@ -186,7 +149,7 @@ pub enum BiomeGrassColorModifier { /// /// A Biome contains all information about a biome necessary to compute a block /// color given a block type and depth -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Biome { /// Temperature value /// @@ -284,8 +247,6 @@ pub struct BiomeTypes { biome_map: HashMap, /// Array used to look up old numeric biome IDs legacy_biomes: Box<[&'static Biome; 256]>, - /// Fallback for unknown (new/modded) biomes - fallback_biome: &'static Biome, } impl Default for BiomeTypes { @@ -312,12 +273,9 @@ impl Default for BiomeTypes { .try_into() .unwrap(); - let fallback_biome = *biome_map.get("plains").expect("Plains biome undefined"); - Self { biome_map, legacy_biomes, - fallback_biome, } } } @@ -335,10 +293,4 @@ impl BiomeTypes { pub fn get_legacy(&self, id: u8) -> Option<&Biome> { Some(self.legacy_biomes[id as usize]) } - - /// Returns the fallback for unknown (new/modded) biomes - #[inline] - pub fn get_fallback(&self) -> &Biome { - self.fallback_biome - } } diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index 34caa1c..c5bd47e 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minedmap-types" -version = "0.2.0" +version = "0.1.4" description = "Common types used by several MinedMap crates" edition.workspace = true license.workspace = true @@ -8,5 +8,5 @@ readme.workspace = true repository.workspace = true [dependencies] -bincode = "2.0.1" itertools = "0.14.0" +serde = { version = "1.0.183", features = ["derive"] } diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index f2dc0e1..b4f12c2 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -8,8 +8,8 @@ use std::{ ops::{Index, IndexMut}, }; -use bincode::{Decode, Encode}; use itertools::iproduct; +use serde::{Deserialize, Serialize}; /// Const generic AXIS arguments for coordinate types pub mod axis { @@ -48,10 +48,10 @@ macro_rules! coord_type { /// Returns an iterator over all possible values of the type #[inline] pub fn iter() -> impl DoubleEndedIterator> - + ExactSizeIterator - + FusedIterator - + Clone - + Debug { + + ExactSizeIterator + + FusedIterator + + Clone + + Debug { (0..Self::MAX as u8).map($t) } } @@ -110,7 +110,7 @@ impl LayerBlockCoords { /// Generic array for data stored per block of a chunk layer /// /// Includes various convenient iteration functions. -#[derive(Debug, Clone, Copy, Default, Encode, Decode)] +#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)] pub struct LayerBlockArray(pub [[T; BLOCKS_PER_CHUNK]; BLOCKS_PER_CHUNK]); impl Index for LayerBlockArray { @@ -196,7 +196,7 @@ impl Debug for ChunkCoords { /// Generic array for data stored per chunk of a region /// /// Includes various convenient iteration functions. -#[derive(Debug, Clone, Copy, Default, Encode, Decode)] +#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)] pub struct ChunkArray(pub [[T; CHUNKS_PER_REGION]; CHUNKS_PER_REGION]); impl ChunkArray { diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index c725ae2..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,51 +0,0 @@ -# This is an example docker-compose configuration providing a Minecraft server, -# map generator and webserver. Visit http://localhost:8080 to view the map. -# -# See https://docker-minecraft-server.readthedocs.io/ for more information on -# the itzg/minecraft-server image and its configuration. - -services: - mc: - image: docker.io/itzg/minecraft-server - environment: - EULA: 'true' - ports: - - '25565:25565' - volumes: - - data:/data - stdin_open: true - tty: true - restart: unless-stopped - - minedmap: - image: ghcr.io/neocturne/minedmap/minedmap - command: - - '--jobs-initial=2' - - '--image-format=webp' - - '--sign-filter=\[Map\]' - - '--sign-transform=s/\[Map\]//' - - '--watch' - - '/input/world' - - '/output' - volumes: - - data:/input:ro - - output:/output - - processed:/output/processed - network_mode: 'none' - depends_on: - mc: - condition: service_healthy - restart: unless-stopped - - viewer: - image: ghcr.io/neocturne/minedmap/viewer - ports: - - '8080:80' - volumes: - - output:/usr/share/nginx/html/data:ro - restart: unless-stopped - -volumes: - data: {} - processed: {} - output: {} diff --git a/resource/blocks.json b/resource/blocks.json index 15dae2b..a88aa34 100644 --- a/resource/blocks.json +++ b/resource/blocks.json @@ -316,13 +316,9 @@ "bubble_coral_fan": null, "bubble_coral_wall_fan": null, "budding_amethyst": {}, - "bush": { - "grass": true - }, "cactus": { "texture": "cactus_top" }, - "cactus_flower": {}, "cake": { "texture": "cake_top" }, @@ -720,9 +716,6 @@ "dragon_egg": {}, "dragon_head": null, "dragon_wall_head": null, - "dried_ghast": { - "texture": "dried_ghast_hydration_1_top" - }, "dried_kelp_block": { "texture": "dried_kelp_top" }, @@ -785,7 +778,6 @@ "fire_coral_block": {}, "fire_coral_fan": null, "fire_coral_wall_fan": null, - "firefly_bush": {}, "fletching_table": { "texture": "fletching_table_top" }, @@ -995,7 +987,6 @@ "lava_cauldron": { "texture": "cauldron_top" }, - "leaf_litter": null, "lectern": { "texture": "lectern_top" }, @@ -1790,8 +1781,7 @@ "sculk_vein": {}, "sea_lantern": {}, "sea_pickle": {}, - "seagrass": {}, - "short_dry_grass": {}, + "seagrass": null, "short_grass": null, "shroomlight": {}, "shulker_box": {}, @@ -2023,7 +2013,6 @@ "sweet_berry_bush": { "texture": "sweet_berry_bush_stage3" }, - "tall_dry_grass": {}, "tall_grass": { "grass": true, "texture": "tall_grass_top" @@ -2035,8 +2024,6 @@ "texture": "target_top" }, "terracotta": {}, - "test_block": null, - "test_instance_block": null, "tinted_glass": {}, "tnt": { "texture": "tnt_top" @@ -2301,7 +2288,6 @@ "white_tulip": null, "white_wall_banner": null, "white_wool": {}, - "wildflowers": null, "wither_rose": null, "wither_skeleton_skull": null, "wither_skeleton_wall_skull": null, diff --git a/src/core/common.rs b/src/core/common.rs index 094d567..b933dcd 100644 --- a/src/core/common.rs +++ b/src/core/common.rs @@ -3,15 +3,14 @@ use std::{ collections::{BTreeMap, BTreeSet}, fmt::Debug, - hash::Hash, path::{Path, PathBuf}, }; use anyhow::{Context, Result}; -use bincode::{Decode, Encode}; use clap::ValueEnum; +use indexmap::IndexSet; use regex::{Regex, RegexSet}; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use crate::{ io::fs::FileMetaVersion, @@ -26,7 +25,7 @@ use crate::{ /// /// Increase when the generation of processed regions from region data changes /// (usually because of updated resource data) -pub const REGION_FILE_META_VERSION: FileMetaVersion = FileMetaVersion(8); +pub const REGION_FILE_META_VERSION: FileMetaVersion = FileMetaVersion(3); /// MinedMap map tile data version number /// @@ -38,7 +37,7 @@ pub const MAP_FILE_META_VERSION: FileMetaVersion = FileMetaVersion(0); /// /// Increase when the generation of lightmap tiles from region data changes /// (usually because of updated resource data) -pub const LIGHTMAP_FILE_META_VERSION: FileMetaVersion = FileMetaVersion(6); +pub const LIGHTMAP_FILE_META_VERSION: FileMetaVersion = FileMetaVersion(3); /// MinedMap mipmap data version number /// @@ -48,7 +47,7 @@ pub const MIPMAP_FILE_META_VERSION: FileMetaVersion = FileMetaVersion(0); /// MinedMap processed entity data version number /// /// Increase when entity collection changes bacause of code changes. -pub const ENTITIES_FILE_META_VERSION: FileMetaVersion = FileMetaVersion(3); +pub const ENTITIES_FILE_META_VERSION: FileMetaVersion = FileMetaVersion(1); /// Coordinate pair of a generated tile /// @@ -87,7 +86,7 @@ impl TileCoordMap { } /// Data structure for storing chunk data between processing and rendering steps -#[derive(Debug, Encode, Decode)] +#[derive(Debug, Serialize, Deserialize)] pub struct ProcessedChunk { /// Block type data pub blocks: Box, @@ -98,18 +97,18 @@ pub struct ProcessedChunk { } /// Data structure for storing region data between processing and rendering steps -#[derive(Debug, Default, Encode, Decode)] +#[derive(Debug, Default, Serialize, Deserialize)] pub struct ProcessedRegion { /// List of biomes used in the region /// /// Indexed by [ProcessedChunk] biome data - pub biome_list: Vec, + pub biome_list: IndexSet, /// Processed chunk data pub chunks: ChunkArray>>, } /// Data structure for storing entity data between processing and collection steps -#[derive(Debug, Default, Encode, Decode)] +#[derive(Debug, Default, Serialize, Deserialize)] pub struct ProcessedEntities { /// List of block entities pub block_entities: Vec, @@ -136,14 +135,10 @@ pub enum TileKind { pub struct Config { /// Number of threads for parallel processing pub num_threads: usize, - /// Number of threads for initial parallel processing - pub num_threads_initial: usize, /// Path of input region directory pub region_dir: PathBuf, /// Path of input `level.dat` file pub level_dat_path: PathBuf, - /// Path of input `level.dat_old` file - pub level_dat_old_path: PathBuf, /// Base path for storage of rendered tile data pub output_dir: PathBuf, /// Path for storage of intermediate processed data files @@ -172,13 +167,9 @@ impl Config { Some(threads) => threads, None => 1, }; - let num_threads_initial = args.jobs_initial.unwrap_or(num_threads); let region_dir = [&args.input_dir, Path::new("region")].iter().collect(); let level_dat_path = [&args.input_dir, Path::new("level.dat")].iter().collect(); - let level_dat_old_path = [&args.input_dir, Path::new("level.dat_old")] - .iter() - .collect(); let processed_dir: PathBuf = [&args.output_dir, Path::new("processed")].iter().collect(); let entities_dir: PathBuf = [&processed_dir, Path::new("entities")].iter().collect(); let entities_path_final = [&entities_dir, Path::new("entities.bin")].iter().collect(); @@ -193,10 +184,8 @@ impl Config { Ok(Config { num_threads, - num_threads_initial, region_dir, level_dat_path, - level_dat_old_path, output_dir: args.output_dir.clone(), processed_dir, entities_dir, @@ -237,7 +226,7 @@ impl Config { fn sign_transform(splitter: &Regex, transform: &str) -> Result<(Regex, String)> { let captures = splitter .captures(transform) - .with_context(|| format!("Invalid transform pattern '{transform}'"))?; + .with_context(|| format!("Invalid transform pattern '{}'", transform))?; let regexp = Regex::new(&captures[1])?; let replacement = captures[2].to_string(); Ok((regexp, replacement)) @@ -275,7 +264,7 @@ impl Config { TileKind::Map => "map", TileKind::Lightmap => "light", }; - let dir = format!("{prefix}/{level}"); + let dir = format!("{}/{}", prefix, level); [&self.output_dir, Path::new(&dir)].iter().collect() } diff --git a/src/core/entity_collector.rs b/src/core/entity_collector.rs index 0d18090..30b3a86 100644 --- a/src/core/entity_collector.rs +++ b/src/core/entity_collector.rs @@ -78,22 +78,23 @@ impl<'a> EntityCollector<'a> { let mut output = ProcessedEntities::default(); for source_path in sources { - let mut source: ProcessedEntities = match storage::read_file(source_path.as_ref()) { - Ok(source) => source, - Err(err) => { - warn!( - "Failed to read entity data file {}: {:?}", - source_path.as_ref().display(), - err, - ); - continue; - } - }; + let mut source: ProcessedEntities = + match storage::read_file(source_path.as_ref(), storage::Format::Json) { + Ok(source) => source, + Err(err) => { + warn!( + "Failed to read entity data file {}: {:?}", + source_path.as_ref().display(), + err, + ); + continue; + } + }; output.block_entities.append(&mut source.block_entities); } - storage::write(file, &output).context("Failed to write entity data") + storage::write(file, &output, storage::Format::Json).context("Failed to write entity data") } /// Runs the mipmap generation diff --git a/src/core/metadata_writer.rs b/src/core/metadata_writer.rs index 40c5796..92d8566 100644 --- a/src/core/metadata_writer.rs +++ b/src/core/metadata_writer.rs @@ -124,14 +124,7 @@ impl<'a> MetadataWriter<'a> { /// Reads and deserializes the `level.dat` of the Minecraft save data fn read_level_dat(&self) -> Result { - let res = crate::nbt::data::from_file(&self.config.level_dat_path); - if res.is_err() { - if let Ok(level_dat_old) = crate::nbt::data::from_file(&self.config.level_dat_old_path) - { - return Ok(level_dat_old); - } - } - res.context("Failed to read level.dat") + crate::nbt::data::from_file(&self.config.level_dat_path).context("Failed to read level.dat") } /// Generates [Spawn] data from a [de::LevelDat] @@ -179,8 +172,9 @@ impl<'a> MetadataWriter<'a> { /// Generates [Entities] data from collected entity lists fn entities(&self) -> Result { - let data: ProcessedEntities = storage::read_file(&self.config.entities_path_final) - .context("Failed to read entity data file")?; + let data: ProcessedEntities = + storage::read_file(&self.config.entities_path_final, storage::Format::Json) + .context("Failed to read entity data file")?; let ret = Entities { signs: data diff --git a/src/core/mod.rs b/src/core/mod.rs index fce2cb5..5832379 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -10,12 +10,7 @@ mod tile_merger; mod tile_mipmapper; mod tile_renderer; -use std::{ - path::PathBuf, - sync::mpsc::{self, Receiver}, - thread, - time::Duration, -}; +use std::path::PathBuf; use anyhow::{Context, Result}; use clap::Parser; @@ -23,33 +18,23 @@ use git_version::git_version; use common::{Config, ImageFormat}; use metadata_writer::MetadataWriter; -use notify::{RecommendedWatcher, RecursiveMode, Watcher as _}; -use rayon::ThreadPool; use region_processor::RegionProcessor; use tile_mipmapper::TileMipmapper; use tile_renderer::TileRenderer; -use tokio::runtime::Runtime; -use tracing::{info, warn}; use self::entity_collector::EntityCollector; -/// Returns the MinedMap version number -fn version() -> &'static str { - option_env!("MINEDMAP_VERSION").unwrap_or( - git_version!( - args = ["--abbrev=7", "--match=v*", "--dirty=-modified"], - cargo_prefix = "v", - ) - .strip_prefix("v") - .unwrap(), - ) -} +/// MinedMap version number +const VERSION: &str = git_version!( + args = ["--abbrev=7", "--match=v*", "--dirty=-modified"], + cargo_prefix = "v", +); /// Command line arguments for minedmap CLI #[derive(Debug, Parser)] #[command( about, - version = version(), + version = VERSION.strip_prefix("v").unwrap(), max_term_width = 100, )] pub struct Args { @@ -59,26 +44,9 @@ pub struct Args { /// use one thread per logical CPU core. #[arg(short, long)] pub jobs: Option, - /// Number of parallel threads to use for initial processing - /// - /// Passing this option only makes sense with --watch. The first run after - /// starting MinedMap will use as many parallel jobs as configured using - /// --job-initial, while subsequent regenerations of tiles will use the - /// the number configured using --jobs. - /// - /// If not given, the value from the --jobs option is used. - #[arg(long)] - pub jobs_initial: Option, /// Enable verbose messages #[arg(short, long)] pub verbose: bool, - /// Watch for file changes and regenerate tiles automatically instead of - /// exiting after generation - #[arg(long)] - pub watch: bool, - /// Minimum delay between map generation cycles in watch mode - #[arg(long, value_parser = humantime::parse_duration, default_value = "30s")] - pub watch_delay: Duration, /// Format of generated map tiles #[arg(long, value_enum, default_value_t)] pub image_format: ImageFormat, @@ -106,73 +74,14 @@ pub struct Args { pub output_dir: PathBuf, } -/// Configures a Rayon thread pool for parallel processing -fn setup_threads(num_threads: usize) -> Result { +/// Configures the Rayon thread pool for parallel processing +fn setup_threads(num_threads: usize) -> Result<()> { rayon::ThreadPoolBuilder::new() .num_threads(num_threads) - .build() + .build_global() .context("Failed to configure thread pool") } -/// Runs all MinedMap generation steps, updating all tiles as needed -fn generate(config: &Config, rt: &Runtime) -> Result<()> { - let regions = RegionProcessor::new(config).run()?; - TileRenderer::new(config, rt, ®ions).run()?; - let tiles = TileMipmapper::new(config, ®ions).run()?; - EntityCollector::new(config, ®ions).run()?; - MetadataWriter::new(config, &tiles).run() -} - -/// Creates a file watcher for the -fn create_watcher(args: &Args) -> Result<(RecommendedWatcher, Receiver<()>)> { - let (tx, rx) = mpsc::sync_channel::<()>(1); - let mut watcher = notify::recommended_watcher(move |res| { - // Ignore errors - we already have a watch trigger queued if try_send() fails - let event: notify::Event = match res { - Ok(event) => event, - Err(err) => { - warn!("Watch error: {err}"); - return; - } - }; - let notify::EventKind::Modify(modify_kind) = event.kind else { - return; - }; - if !matches!( - modify_kind, - notify::event::ModifyKind::Data(_) - | notify::event::ModifyKind::Name(notify::event::RenameMode::To) - ) { - return; - } - if !event - .paths - .iter() - .any(|path| path.ends_with("level.dat") || path.extension() == Some("mcu".as_ref())) - { - return; - } - let _ = tx.try_send(()); - })?; - watcher.watch(&args.input_dir, RecursiveMode::Recursive)?; - Ok((watcher, rx)) -} - -/// Watches the data directory for changes, returning when a change has happened -fn wait_watcher(args: &Args, watch_channel: &Receiver<()>) -> Result<()> { - info!("Watching for changes..."); - let () = watch_channel - .recv() - .context("Failed to read watch event channel")?; - info!("Change detected."); - - thread::sleep(args.watch_delay); - - let _ = watch_channel.try_recv(); - - Ok(()) -} - /// MinedMap CLI main function pub fn cli() -> Result<()> { let args = Args::parse(); @@ -187,28 +96,17 @@ pub fn cli() -> Result<()> { .with_target(false) .init(); - let mut pool = setup_threads(config.num_threads_initial)?; + setup_threads(config.num_threads)?; let rt = tokio::runtime::Builder::new_current_thread() .build() .unwrap(); - let watch = args.watch.then(|| create_watcher(&args)).transpose()?; + let regions = RegionProcessor::new(&config).run()?; + TileRenderer::new(&config, &rt, ®ions).run()?; + let tiles = TileMipmapper::new(&config, ®ions).run()?; + EntityCollector::new(&config, ®ions).run()?; + MetadataWriter::new(&config, &tiles).run()?; - pool.install(|| generate(&config, &rt))?; - - let Some((_watcher, watch_channel)) = watch else { - // watch mode disabled - return Ok(()); - }; - - if config.num_threads != config.num_threads_initial { - pool = setup_threads(config.num_threads)?; - } - pool.install(move || { - loop { - wait_watcher(&args, &watch_channel)?; - generate(&config, &rt)?; - } - }) + Ok(()) } diff --git a/src/core/region_processor.rs b/src/core/region_processor.rs index 74939bd..e448f5e 100644 --- a/src/core/region_processor.rs +++ b/src/core/region_processor.rs @@ -4,8 +4,6 @@ use std::{ffi::OsStr, path::PathBuf, sync::mpsc, time::SystemTime}; use anyhow::{Context, Result}; use enum_map::{Enum, EnumMap}; -use indexmap::IndexSet; -use minedmap_resource::Biome; use rayon::prelude::*; use tracing::{debug, info, warn}; @@ -45,37 +43,6 @@ enum RegionProcessorStatus { ErrorMissing, } -/// Data of a region being processed by a [SingleRegionProcessor] -#[derive(Debug)] -struct SingleRegionData { - /// [IndexSet] of biomes used by the processed region - biome_list: IndexSet, - /// Processed region chunk intermediate data - chunks: ChunkArray>>, - /// Lightmap intermediate data - lightmap: image::GrayAlphaImage, - /// Processed entity intermediate data - entities: ProcessedEntities, - /// True if any unknown block or biome types were encountered during processing - has_unknown: bool, -} - -impl Default for SingleRegionData { - fn default() -> Self { - /// Width/height of the region data - const N: u32 = (BLOCKS_PER_CHUNK * CHUNKS_PER_REGION) as u32; - - let lightmap = image::GrayAlphaImage::new(N, N); - Self { - biome_list: Default::default(), - chunks: Default::default(), - lightmap, - entities: Default::default(), - has_unknown: false, - } - } -} - /// Handles processing for a single region struct SingleRegionProcessor<'a> { /// Registry of known block types @@ -106,13 +73,24 @@ struct SingleRegionProcessor<'a> { lightmap_needed: bool, /// True if entity output file needs to be updated entities_needed: bool, + /// Processed region intermediate data + processed_region: ProcessedRegion, + /// Lightmap intermediate data + lightmap: image::GrayAlphaImage, + /// Processed entity intermediate data + entities: ProcessedEntities, /// Format of generated map tiles image_format: image::ImageFormat, + /// True if any unknown block or biome types were encountered during processing + has_unknown: bool, } impl<'a> SingleRegionProcessor<'a> { /// Initializes a [SingleRegionProcessor] fn new(processor: &'a RegionProcessor<'a>, coords: TileCoords) -> Result { + /// Width/height of the region data + const N: u32 = (BLOCKS_PER_CHUNK * CHUNKS_PER_REGION) as u32; + let input_path = processor.config.region_path(coords); let input_timestamp = fs::modified_timestamp(&input_path)?; @@ -129,6 +107,10 @@ impl<'a> SingleRegionProcessor<'a> { let lightmap_needed = Some(input_timestamp) > lightmap_timestamp; let entities_needed = Some(input_timestamp) > entities_timestamp; + let processed_region = ProcessedRegion::default(); + let lightmap = image::GrayAlphaImage::new(N, N); + let entities = ProcessedEntities::default(); + Ok(SingleRegionProcessor { block_types: &processor.block_types, biome_types: &processor.biome_types, @@ -144,7 +126,11 @@ impl<'a> SingleRegionProcessor<'a> { output_needed, lightmap_needed, entities_needed, + processed_region, + lightmap, + entities, image_format: processor.config.tile_image_format(), + has_unknown: false, }) } @@ -168,14 +154,15 @@ impl<'a> SingleRegionProcessor<'a> { /// Saves processed region data /// /// The timestamp is the time of the last modification of the input region data. - fn save_region(&self, processed_region: &ProcessedRegion) -> Result<()> { + fn save_region(&self) -> Result<()> { if !self.output_needed { return Ok(()); } storage::write_file( &self.output_path, - processed_region, + &self.processed_region, + storage::Format::Bincode, REGION_FILE_META_VERSION, self.input_timestamp, ) @@ -184,7 +171,7 @@ impl<'a> SingleRegionProcessor<'a> { /// Saves a lightmap tile /// /// The timestamp is the time of the last modification of the input region data. - fn save_lightmap(&self, lightmap: &image::GrayAlphaImage) -> Result<()> { + fn save_lightmap(&self) -> Result<()> { if !self.lightmap_needed { return Ok(()); } @@ -194,7 +181,7 @@ impl<'a> SingleRegionProcessor<'a> { LIGHTMAP_FILE_META_VERSION, self.input_timestamp, |file| { - lightmap + self.lightmap .write_to(file, self.image_format) .context("Failed to save image") }, @@ -204,32 +191,28 @@ impl<'a> SingleRegionProcessor<'a> { /// Saves processed entity data /// /// The timestamp is the time of the last modification of the input region data. - fn save_entities(&self, entities: &mut ProcessedEntities) -> Result<()> { + fn save_entities(&mut self) -> Result<()> { if !self.entities_needed { return Ok(()); } - entities.block_entities.sort_unstable(); + self.entities.block_entities.sort_unstable(); storage::write_file( &self.entities_path, - entities, + &self.entities, + storage::Format::Json, ENTITIES_FILE_META_VERSION, self.input_timestamp, ) } /// Processes a single chunk - fn process_chunk( - &self, - data: &mut SingleRegionData, - chunk_coords: ChunkCoords, - chunk_data: world::de::Chunk, - ) -> Result<()> { + fn process_chunk(&mut self, chunk_coords: ChunkCoords, data: world::de::Chunk) -> Result<()> { let (chunk, has_unknown) = - world::chunk::Chunk::new(&chunk_data, self.block_types, self.biome_types) - .with_context(|| format!("Failed to decode chunk {chunk_coords:?}"))?; - data.has_unknown |= has_unknown; + world::chunk::Chunk::new(&data, self.block_types, self.biome_types) + .with_context(|| format!("Failed to decode chunk {:?}", chunk_coords))?; + self.has_unknown |= has_unknown; if self.output_needed || self.lightmap_needed { if let Some(layer::LayerData { @@ -237,11 +220,11 @@ impl<'a> SingleRegionProcessor<'a> { biomes, block_light, depths, - }) = world::layer::top_layer(&mut data.biome_list, &chunk) - .with_context(|| format!("Failed to process chunk {chunk_coords:?}"))? + }) = world::layer::top_layer(&mut self.processed_region.biome_list, &chunk) + .with_context(|| format!("Failed to process chunk {:?}", chunk_coords))? { if self.output_needed { - data.chunks[chunk_coords] = Some(Box::new(ProcessedChunk { + self.processed_region.chunks[chunk_coords] = Some(Box::new(ProcessedChunk { blocks, biomes, depths, @@ -250,30 +233,32 @@ impl<'a> SingleRegionProcessor<'a> { if self.lightmap_needed { let chunk_lightmap = Self::render_chunk_lightmap(block_light); - overlay_chunk(&mut data.lightmap, &chunk_lightmap, chunk_coords); + overlay_chunk(&mut self.lightmap, &chunk_lightmap, chunk_coords); } } } if self.entities_needed { let mut block_entities = chunk.block_entities().with_context(|| { - format!("Failed to process block entities for chunk {chunk_coords:?}") + format!( + "Failed to process block entities for chunk {:?}", + chunk_coords, + ) })?; - data.entities.block_entities.append(&mut block_entities); + self.entities.block_entities.append(&mut block_entities); } Ok(()) } /// Processes the chunks of the region - fn process_chunks(&self, data: &mut SingleRegionData) -> Result<()> { - crate::nbt::region::from_file(&self.input_path)?.foreach_chunk( - |chunk_coords, chunk_data| self.process_chunk(data, chunk_coords, chunk_data), - ) + fn process_chunks(&mut self) -> Result<()> { + crate::nbt::region::from_file(&self.input_path)? + .foreach_chunk(|chunk_coords, data| self.process_chunk(chunk_coords, data)) } /// Processes the region - fn run(&self) -> Result { + fn run(mut self) -> Result { if !self.output_needed && !self.lightmap_needed && !self.entities_needed { debug!( "Skipping unchanged region r.{}.{}.mca", @@ -287,9 +272,7 @@ impl<'a> SingleRegionProcessor<'a> { self.coords.x, self.coords.z ); - let mut data = SingleRegionData::default(); - - if let Err(err) = self.process_chunks(&mut data) { + if let Err(err) = self.process_chunks() { if self.output_timestamp.is_some() && self.lightmap_timestamp.is_some() && self.entities_timestamp.is_some() @@ -308,16 +291,11 @@ impl<'a> SingleRegionProcessor<'a> { } } - let processed_region = ProcessedRegion { - biome_list: data.biome_list.into_iter().collect(), - chunks: data.chunks, - }; + self.save_region()?; + self.save_lightmap()?; + self.save_entities()?; - self.save_region(&processed_region)?; - self.save_lightmap(&data.lightmap)?; - self.save_entities(&mut data.entities)?; - - Ok(if data.has_unknown { + Ok(if self.has_unknown { RegionProcessorStatus::OkWithUnknown } else { RegionProcessorStatus::Ok @@ -404,7 +382,7 @@ impl<'a> RegionProcessor<'a> { self.collect_regions()?.par_iter().try_for_each(|&coords| { let ret = self .process_region(coords) - .with_context(|| format!("Failed to process region {coords:?}"))?; + .with_context(|| format!("Failed to process region {:?}", coords))?; if ret != Status::ErrorMissing { region_send.send(coords).unwrap(); diff --git a/src/core/tile_renderer.rs b/src/core/tile_renderer.rs index 0b534b8..a972b78 100644 --- a/src/core/tile_renderer.rs +++ b/src/core/tile_renderer.rs @@ -16,7 +16,7 @@ use tracing::{debug, info}; use super::{common::*, region_group::RegionGroup}; use crate::{ io::{fs, storage}, - resource::{Colorf, block_color, needs_biome}, + resource::{block_color, needs_biome, Colorf}, types::*, util::coord_offset, }; @@ -105,7 +105,8 @@ impl<'a> TileRenderer<'a> { region_loader .get_or_try_init(|| async { - storage::read_file(&processed_path).context("Failed to load processed region data") + storage::read_file(&processed_path, storage::Format::Bincode) + .context("Failed to load processed region data") }) .await .cloned() @@ -133,7 +134,7 @@ impl<'a> TileRenderer<'a> { /// Hashing the value as a single u32 is more efficient than hashing /// the tuple elements separately. fn biome_key((dx, dz, index): (i8, i8, u16)) -> u32 { - (dx as u8 as u32) | ((dz as u8 as u32) << 8) | ((index as u32) << 16) + (dx as u8 as u32) | (dz as u8 as u32) << 8 | (index as u32) << 16 } /// One quadrant of the kernel used to smooth biome edges @@ -186,7 +187,7 @@ impl<'a> TileRenderer<'a> { for ((region_x, region_z, index), w) in weights.into_values() { let region = region_group.get(region_x, region_z)?; - let biome = region.biome_list.get(usize::from(index))?; + let biome = region.biome_list.get_index(index.into())?; total += w; color += w * block_color(block, Some(biome), depth.0 as f32); @@ -249,7 +250,7 @@ impl<'a> TileRenderer<'a> { .filter(|entry| self.region_set.contains(entry)) }) .try_map(|entry| self.processed_source(entry)) - .with_context(|| format!("Region {coords:?} from previous step must exist"))?; + .with_context(|| format!("Region {:?} from previous step must exist", coords))?; let max_timestamp = *sources .iter() @@ -293,7 +294,7 @@ impl<'a> TileRenderer<'a> { let region_group = self .rt .block_on(self.load_region_group(processed_paths)) - .with_context(|| format!("Region {coords:?} from previous step must be loadable"))?; + .with_context(|| format!("Region {:?} from previous step must be loadable", coords))?; let mut image = image::RgbaImage::new(N, N); Self::render_region(&mut image, ®ion_group); @@ -325,7 +326,7 @@ impl<'a> TileRenderer<'a> { .map(|&coords| { anyhow::Ok(usize::from( self.render_tile(coords) - .with_context(|| format!("Failed to render tile {coords:?}"))?, + .with_context(|| format!("Failed to render tile {:?}", coords))?, )) }) .try_reduce(|| 0, |a, b| Ok(a + b))?; diff --git a/src/io/storage.rs b/src/io/storage.rs index ae311de..9296166 100644 --- a/src/io/storage.rs +++ b/src/io/storage.rs @@ -10,16 +10,28 @@ use std::{ }; use anyhow::{Context, Result}; -use bincode::{Decode, Encode}; +use serde::{de::DeserializeOwned, Serialize}; use super::fs; -/// Bincode configuration -const BINCODE_CONFIG: bincode::config::Configuration = bincode::config::standard(); +/// Storage format +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum Format { + /// Encode as Bincode + /// + /// Bincode is more efficient than JSON, but cannot handle many of + /// serde's features like flatten, conditional skipping, ... + Bincode, + /// Encode as JSON + Json, +} /// Serializes data and writes it to a writer -pub fn write(writer: &mut W, value: &T) -> Result<()> { - let data = bincode::encode_to_vec(value, BINCODE_CONFIG)?; +pub fn write(writer: &mut W, value: &T, format: Format) -> Result<()> { + let data = match format { + Format::Bincode => bincode::serialize(value)?, + Format::Json => serde_json::to_vec(value)?, + }; let len = u32::try_from(data.len())?; let compressed = zstd::bulk::compress(&data, 1)?; drop(data); @@ -33,21 +45,18 @@ pub fn write(writer: &mut W, value: &T) -> Result<()> { /// Serializes data and stores it in a file /// /// A timestamp is stored in an assiciated metadata file. -pub fn write_file( +pub fn write_file( path: &Path, value: &T, + format: Format, version: fs::FileMetaVersion, timestamp: SystemTime, ) -> Result<()> { - fs::create_with_timestamp(path, version, timestamp, |file| write(file, value)) + fs::create_with_timestamp(path, version, timestamp, |file| write(file, value, format)) } /// Reads data from a reader and deserializes it -pub fn read(reader: &mut R) -> Result -where - R: Read, - T: Decode<()>, -{ +pub fn read(reader: &mut R, format: Format) -> Result { let mut len_buf = [0u8; 4]; reader.read_exact(&mut len_buf)?; let len = usize::try_from(u32::from_be_bytes(len_buf))?; @@ -57,17 +66,18 @@ where let data = zstd::bulk::decompress(&compressed, len)?; drop(compressed); - Ok(bincode::decode_from_slice(&data, BINCODE_CONFIG)?.0) + let value = match format { + Format::Bincode => bincode::deserialize(&data)?, + Format::Json => serde_json::from_slice(&data)?, + }; + Ok(value) } /// Reads data from a file and deserializes it -pub fn read_file(path: &Path) -> Result -where - T: Decode<()>, -{ +pub fn read_file(path: &Path, format: Format) -> Result { (|| -> Result { let mut file = File::open(path)?; - read(&mut file) + read(&mut file, format) })() .with_context(|| format!("Failed to read file {}", path.display())) } diff --git a/src/main.rs b/src/main.rs index 1f19a41..31f2889 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,9 +2,6 @@ #![warn(missing_docs)] #![warn(clippy::missing_docs_in_private_items)] -#[cfg(feature = "jemalloc-auto")] -extern crate minedmap_default_alloc; - mod core; mod io; mod util; diff --git a/src/util.rs b/src/util.rs index ed07ba5..a128ef9 100644 --- a/src/util.rs +++ b/src/util.rs @@ -39,9 +39,7 @@ pub fn to_flat_coord( chunk: ChunkCoord, block: BlockCoord, ) -> i32 { - ((region as i32) << (BLOCK_BITS + CHUNK_BITS)) - | ((chunk.0 as i32) << BLOCK_BITS) - | (block.0 as i32) + (region as i32) << (BLOCK_BITS + CHUNK_BITS) | ((chunk.0 as i32) << BLOCK_BITS | block.0 as i32) } /// Splits a flat (linear) coordinate into region, chunk and block numbers diff --git a/src/world/block_entity.rs b/src/world/block_entity.rs index 589a53c..182ad50 100644 --- a/src/world/block_entity.rs +++ b/src/world/block_entity.rs @@ -1,8 +1,7 @@ //! Processing of block entity data -use bincode::{Decode, Encode}; use minedmap_resource::{BlockFlag, BlockType}; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use super::{ de, @@ -10,7 +9,7 @@ use super::{ }; /// Kind of sign block -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, Serialize)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] #[serde(rename_all = "snake_case")] pub enum SignKind { /// Standing sign @@ -24,7 +23,7 @@ pub enum SignKind { } /// Processed sign data -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, Serialize)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct Sign { /// The kind of the sign pub kind: SignKind, @@ -41,15 +40,10 @@ pub struct Sign { impl Sign { /// Processes a [de::BlockEntitySign] into a [Sign] - fn new( - sign: &de::BlockEntitySign, - kind: SignKind, - material: Option, - data_version: u32, - ) -> Sign { + fn new(sign: &de::BlockEntitySign, kind: SignKind, material: Option) -> Sign { let (front_text, back_text) = sign.text(); - let front_text = front_text.decode(data_version); - let back_text = back_text.decode(data_version); + let front_text = front_text.decode(); + let back_text = back_text.decode(); Sign { kind, material, @@ -60,7 +54,7 @@ impl Sign { } /// Data for different kinds of [BlockEntity] -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, Serialize)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] #[serde(tag = "type", rename_all = "snake_case")] pub enum BlockEntityData { /// A sign block @@ -68,7 +62,7 @@ pub enum BlockEntityData { } /// A processed block entity -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, Serialize)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct BlockEntity { /// Global X coordinate pub x: i32, @@ -83,11 +77,7 @@ pub struct BlockEntity { impl BlockEntity { /// Processes a [de::BlockEntity] into a [BlockEntity] - pub fn new( - entity: &de::BlockEntity, - block_type: Option<&BlockType>, - data_version: u32, - ) -> Option { + pub fn new(entity: &de::BlockEntity, block_type: Option<&BlockType>) -> Option { let wall_sign = block_type .map(|block_type| block_type.block_color.is(BlockFlag::WallSign)) .unwrap_or_default(); @@ -101,7 +91,7 @@ impl BlockEntity { let material = block_type .as_ref() .and_then(|block_type| block_type.sign_material.as_ref()); - let data = BlockEntityData::Sign(Sign::new(sign, kind, material.cloned(), data_version)); + let data = BlockEntityData::Sign(Sign::new(sign, kind, material.cloned())); Some(BlockEntity { x: entity.x, diff --git a/src/world/chunk.rs b/src/world/chunk.rs index aadf882..daee023 100644 --- a/src/world/chunk.rs +++ b/src/world/chunk.rs @@ -4,11 +4,11 @@ //! over different data versions as much as possible. use std::{ - collections::{BTreeMap, btree_map}, + collections::{btree_map, BTreeMap}, iter::{self, FusedIterator}, }; -use anyhow::{Context, Result, bail}; +use anyhow::{bail, Context, Result}; use super::{block_entity::BlockEntity, de, section::*}; use crate::{ @@ -58,8 +58,6 @@ pub struct Chunk<'a> { inner: ChunkInner<'a>, /// Unprocessed block entities block_entities: &'a Vec, - /// Chunk data version - data_version: u32, } impl<'a> Chunk<'a> { @@ -89,7 +87,6 @@ impl<'a> Chunk<'a> { Chunk { inner, block_entities, - data_version, }, has_unknown, )) @@ -295,11 +292,7 @@ impl<'a> Chunk<'a> { .iter() .map(|block_entity| { let block_type = self.block_type_at_block_entity(block_entity)?; - Ok(BlockEntity::new( - block_entity, - block_type, - self.data_version, - )) + Ok(BlockEntity::new(block_entity, block_type)) }) .collect::>()?; Ok(entities.into_iter().flatten().collect()) @@ -419,7 +412,7 @@ impl<'a> Iterator for SectionIter<'a> { } fn last(mut self) -> Option { - self.next_back() + self.with_iter(|iter| iter.last()) } } diff --git a/src/world/de.rs b/src/world/de.rs index 0a4b4b6..7ab8ba7 100644 --- a/src/world/de.rs +++ b/src/world/de.rs @@ -2,7 +2,7 @@ use serde::Deserialize; -use super::text_value::TextValue; +use super::json_text::JSONText; /// Element of the `palette` list of 1.18+ [block states](BlockStatesV1_18) #[derive(Debug, Deserialize)] @@ -110,7 +110,7 @@ pub enum BiomesV0 { #[derive(Debug, Deserialize)] pub struct BlockEntitySignV1_20Text { /// Lines of sign text - pub messages: Vec, + pub messages: Vec, /// Default text color pub color: Option, } @@ -125,13 +125,13 @@ pub enum BlockEntitySign { #[serde(rename_all = "PascalCase")] V0 { /// Line 1 of the sign text - text1: TextValue, + text1: JSONText, /// Line 2 of the sign text - text2: TextValue, + text2: JSONText, /// Line 3 of the sign text - text3: TextValue, + text3: JSONText, /// Line 4 of the sign text - text4: TextValue, + text4: JSONText, /// Default text color color: Option, }, diff --git a/src/world/text_value.rs b/src/world/json_text.rs similarity index 84% rename from src/world/text_value.rs rename to src/world/json_text.rs index 3de6593..fa18527 100644 --- a/src/world/text_value.rs +++ b/src/world/json_text.rs @@ -1,27 +1,24 @@ -//! Newtype and helper methods for handling Minecraft text values +//! Newtype and helper methods for handling Minecraft Raw JSON Text use std::{collections::VecDeque, fmt::Display}; -use bincode::{Decode, Encode}; use minedmap_resource::Color; use serde::{Deserialize, Serialize}; /// A span of formatted text /// -/// A [TextValue] consists of a tree of [FormattedText] nodes (canonically +/// A [JSONText] consists of a tree of [FormattedText] nodes (canonically /// represented as a [FormattedTextTree], but other kinds are possible with /// is handled by [DeserializedText]. /// /// Formatting that is not set in a node is inherited from the parent. -#[derive( - Debug, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Encode, Decode, -)] +#[derive(Debug, Serialize, Deserialize, Default, PartialEq, Eq, PartialOrd, Ord)] pub struct FormattedText { #[serde(default)] /// Text content pub text: String, /// Text color - #[serde(skip_serializing_if = "Option::is_none", with = "text_color")] + #[serde(skip_serializing_if = "Option::is_none", with = "json_color")] pub color: Option, /// Bold formatting #[serde(skip_serializing_if = "Option::is_none")] @@ -87,7 +84,7 @@ impl From for FormattedTextTree { } /// List of [FormattedText] -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Encode, Decode)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct FormattedTextList(pub Vec); impl FormattedTextList { @@ -107,9 +104,9 @@ impl Display for FormattedTextList { } } -/// Raw deserialized [TextValue] +/// Raw deserialized [JSONText] /// -/// A [TextValue] can contain various different types serialized as JSON or NBT. +/// A [JSONText] can contain various different JSON types. #[derive(Debug, Deserialize)] #[serde(untagged)] pub enum DeserializedText { @@ -169,41 +166,28 @@ impl Default for DeserializedText { } } -/// Minecraft raw text value +/// Minecraft Raw JSON Text #[derive(Debug, Deserialize)] -pub struct TextValue(pub fastnbt::Value); +pub struct JSONText(pub String); -impl TextValue { - /// Deserializes a [TextValue] into a [DeserializedText] - pub fn deserialize(&self, data_version: u32) -> DeserializedText { - // TODO: Improve error handling - // - // Unfortunately, there are a number of weird ways an empty sign coould - // be encoded (for example a compound with an "" key), so for now we - // simply interpret undecodable data as empty. - if data_version < 4290 { - let fastnbt::Value::String(json) = &self.0 else { - return DeserializedText::default(); - }; - - serde_json::from_str(json).unwrap_or_default() - } else { - fastnbt::from_value(&self.0).unwrap_or_default() - } +impl JSONText { + /// Deserializes a [JSONText] into a [DeserializedText] + pub fn deserialize(&self) -> DeserializedText { + serde_json::from_str(&self.0).unwrap_or_default() } } -mod text_color { +mod json_color { //! Helpers for serializing and deserializing [FormattedText](super::FormattedText) colors use minedmap_resource::Color; use serde::{ - Deserializer, Serializer, de::{self, Visitor}, ser::Error as _, + Deserializer, Serializer, }; - /// Named text colors + /// Named JSON text colors static COLORS: phf::Map<&'static str, Color> = phf::phf_map! { "black" => Color([0x00, 0x00, 0x00]), "dark_blue" => Color([0x00, 0x00, 0xAA]), diff --git a/src/world/layer.rs b/src/world/layer.rs index deb4b48..0764711 100644 --- a/src/world/layer.rs +++ b/src/world/layer.rs @@ -3,8 +3,8 @@ use std::num::NonZeroU16; use anyhow::{Context, Result}; -use bincode::{Decode, Encode}; use indexmap::IndexSet; +use serde::{Deserialize, Serialize}; use super::chunk::{Chunk, SectionIterItem}; use crate::{ @@ -13,7 +13,7 @@ use crate::{ }; /// Height (Y coordinate) of a block -#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub struct BlockHeight(pub i32); impl BlockHeight { @@ -97,14 +97,14 @@ impl LayerEntry<'_> { if self.is_empty() { *self.block = Some(block_type.block_color); - - let biome = section.biomes.biome_at(section.y, coords)?; - let (biome_index, _) = biome_list.insert_full(*biome); - *self.biome = NonZeroU16::new( - (biome_index + 1) - .try_into() - .expect("biome index not in range"), - ); + if let Some(biome) = section.biomes.biome_at(section.y, coords)? { + let (biome_index, _) = biome_list.insert_full(*biome); + *self.biome = NonZeroU16::new( + (biome_index + 1) + .try_into() + .expect("biome index not in range"), + ); + } } if block_type.block_color.is(BlockFlag::Water) { diff --git a/src/world/mod.rs b/src/world/mod.rs index 8a2e9be..6426c92 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -3,7 +3,7 @@ pub mod block_entity; pub mod chunk; pub mod de; +pub mod json_text; pub mod layer; pub mod section; pub mod sign; -pub mod text_value; diff --git a/src/world/section.rs b/src/world/section.rs index dc5c9a6..7988fd5 100644 --- a/src/world/section.rs +++ b/src/world/section.rs @@ -5,7 +5,7 @@ use std::fmt::Debug; -use anyhow::{Context, Result, bail}; +use anyhow::{bail, Context, Result}; use num_integer::div_rem; use tracing::debug; @@ -208,7 +208,7 @@ impl Section for SectionV0<'_> { /// Trait for common functions of [BiomesV1_18] and [BiomesV0] pub trait Biomes: Debug { /// Returns the [Biome] at a coordinate tuple inside the chunk - fn biome_at(&self, section: SectionY, coords: SectionBlockCoords) -> Result<&Biome>; + fn biome_at(&self, section: SectionY, coords: SectionBlockCoords) -> Result>; } /// Minecraft v1.18+ section biome data @@ -226,7 +226,7 @@ pub struct BiomesV1_18<'a> { /// to whole i64 values. biomes: Option<&'a [i64]>, /// Biome palette indexed by entries encoded in *biomes* - palette: Vec<&'a Biome>, + palette: Vec>, /// Number of bits used for each entry in *biomes* bits: u8, } @@ -253,11 +253,12 @@ impl<'a> BiomesV1_18<'a> { let palette_types = palette .iter() .map(|entry| { - biome_types.get(entry).unwrap_or_else(|| { + let biome_type = biome_types.get(entry); + if biome_type.is_none() { debug!("Unknown biome type: {}", entry); has_unknown = true; - biome_types.get_fallback() - }) + } + biome_type }) .collect(); @@ -294,7 +295,7 @@ impl<'a> BiomesV1_18<'a> { } impl Biomes for BiomesV1_18<'_> { - fn biome_at(&self, _section: SectionY, coords: SectionBlockCoords) -> Result<&Biome> { + fn biome_at(&self, _section: SectionY, coords: SectionBlockCoords) -> Result> { let index = self.palette_index_at(coords); Ok(*self .palette @@ -349,7 +350,7 @@ impl<'a> BiomesV0<'a> { } impl Biomes for BiomesV0<'_> { - fn biome_at(&self, section: SectionY, coords: SectionBlockCoords) -> Result<&Biome> { + fn biome_at(&self, section: SectionY, coords: SectionBlockCoords) -> Result> { let id = match self.data { BiomesV0Data::IntArrayV15(data) => { let LayerBlockCoords { x, z } = coords.xz; @@ -369,10 +370,7 @@ impl Biomes for BiomesV0<'_> { } BiomesV0Data::ByteArray(data) => data[coords.xz.offset()] as u8, }; - Ok(self - .biome_types - .get_legacy(id) - .unwrap_or(self.biome_types.get_fallback())) + Ok(self.biome_types.get_legacy(id)) } } @@ -400,6 +398,10 @@ impl<'a> BlockLight<'a> { let (offset, nibble) = div_rem(coords.offset(), 2); let byte = block_light[offset] as u8; - if nibble == 1 { byte >> 4 } else { byte & 0xf } + if nibble == 1 { + byte >> 4 + } else { + byte & 0xf + } } } diff --git a/src/world/sign.rs b/src/world/sign.rs index 8e4e670..eff319f 100644 --- a/src/world/sign.rs +++ b/src/world/sign.rs @@ -2,13 +2,12 @@ use std::fmt::Display; -use bincode::{Decode, Encode}; use minedmap_resource::Color; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use super::{ de, - text_value::{FormattedText, FormattedTextList, TextValue}, + json_text::{FormattedText, FormattedTextList, JSONText}, }; /// Version-independent reference to (front or back) sign text @@ -18,7 +17,7 @@ pub struct RawSignText<'a> { /// /// A regular sign always has 4 lines of text. The back of pre-1.20 /// signs is represented as a [SignText] without any `messages`. - pub messages: Vec<&'a TextValue>, + pub messages: Vec<&'a JSONText>, /// Sign color /// /// Defaults to "black". @@ -49,7 +48,7 @@ static DYE_COLORS: phf::Map<&'static str, Color> = phf::phf_map! { impl RawSignText<'_> { /// Decodes the [RawSignText] into a [SignText] - pub fn decode(&self, data_version: u32) -> SignText { + pub fn decode(&self) -> SignText { let color = self .color .map(|c| DYE_COLORS.get(c).copied().unwrap_or(DEFAULT_COLOR)); @@ -60,7 +59,7 @@ impl RawSignText<'_> { SignText( self.messages .iter() - .map(|message| message.deserialize(data_version).linearize(&parent)) + .map(|message| message.deserialize().linearize(&parent)) .collect(), ) } @@ -105,7 +104,7 @@ impl BlockEntitySignExt for de::BlockEntitySign { } } -#[derive(Debug, Default, Serialize, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)] +#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] /// Deserialized and linearized sign text pub struct SignText(pub Vec); diff --git a/viewer/.dockerignore b/viewer/.dockerignore deleted file mode 100644 index 3af0ccb..0000000 --- a/viewer/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -/data diff --git a/viewer/Dockerfile b/viewer/Dockerfile deleted file mode 100644 index 524fd4c..0000000 --- a/viewer/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM docker.io/library/nginx:alpine-slim -COPY . /usr/share/nginx/html -# datadir should be mounted to: /usr/share/nginx/html/data