From 18613260a87f3a7589aeacdcfa3406b3f76a4fd4 Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Sat, 4 Jul 2026 11:14:47 +0200 Subject: [PATCH] WASM plugins, scripting, i18n, GUI pan/zoom, cargo-dist CI/CD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - WASM plugin host (wasmtime 46, 17 host fns) + example noisemap plugin - Rhai scripting engine (12 API fns, `terrafier run` cmd) - i18n: en/ru translations, auto-detect, t! macro - GUI: pan (click-drag) + zoom (scroll wheel) with viewport transform - cargo-dist 0.31: MSI/pkg/shell installers, both binaries - CI: .github/workflows/ci.yml + release.yml - Security: wasmtime 30→46, bincode 1.3→2.0, quick-xml CVE docs - Code review: SAFETY comments, unwrap→match cleanup - Fixes: clippy approx_constant, needless_borrows, rustfmt --- .github/workflows/ci.yml | 64 + .github/workflows/release-old.yml | 296 ++++ .github/workflows/release.yml | 296 ++++ Cargo.lock | 1484 +++++++++++++---- Cargo.toml | 37 +- PLAN.md | 38 +- bench/benches/nbt.rs | 4 +- cli/Cargo.toml | 13 + cli/src/cmds/io/export.rs | 9 +- cli/src/cmds/io/import.rs | 15 +- cli/src/cmds/io/render.rs | 11 +- cli/src/cmds/mod.rs | 5 + cli/src/cmds/new.rs | 13 +- cli/src/cmds/run.rs | 8 + cli/src/main.rs | 12 + cli/src/util/output.rs | 143 +- cli/wix/main.wxs | 228 +++ core/src/io/layer_export/biome_res.rs | 5 +- core/src/io/layer_export/mod.rs | 4 +- core/src/io/minecraft/export/chunk.rs | 32 +- core/src/io/minecraft/export/mod.rs | 2 +- core/src/io/minecraft/export/writer.rs | 5 +- core/src/io/minecraft/mod.rs | 6 +- core/src/io/minecraft/reader.rs | 14 +- core/src/io/mod.rs | 10 +- core/src/io/wp_import/java_reader.rs | 2 +- core/src/io/wp_import/mod.rs | 2 +- core/src/io/wp_import/types/java_classdesc.rs | 10 +- core/src/io/wp_import/types/java_fields.rs | 2 +- core/src/lib.rs | 2 +- core/src/model/world/world.rs | 6 +- core/src/ops/filters.rs | 4 +- core/src/ops/heightmap.rs | 2 +- core/src/ops/layers/terrain/trees.rs | 8 +- core/src/ops/operations/brush/paint.rs | 6 +- core/src/ops/operations/fill.rs | 2 +- core/src/ops/operations/mod.rs | 6 +- core/src/ops/operations/shaping/erode.rs | 2 +- core/src/ops/operations/shaping/height.rs | 2 +- core/src/ops/operations/shaping/mod.rs | 4 +- core/src/ops/operations/shaping/smooth.rs | 2 +- core/src/plugins/mod.rs | 4 +- crates/fastanvil/src/io/region/region.rs | 2 - crates/i18n/Cargo.toml | 10 + crates/i18n/src/lang.rs | 8 + crates/i18n/src/lib.rs | 116 ++ crates/i18n/src/translations/en.json | 30 + crates/i18n/src/translations/ru.json | 30 + crates/nbt/src/io/mod.rs | 4 +- crates/nbt/src/io/read/mod.rs | 2 +- crates/nbt/src/io/read/read_tag.rs | 2 +- crates/nbt/src/io/write/mod.rs | 2 +- crates/nbt/src/io/write/write_tag.rs | 2 +- crates/scripting/Cargo.toml | 11 + crates/scripting/src/lib.rs | 148 ++ crates/scripting/tests/integration_test.rs | 56 + crates/wasm-host/Cargo.toml | 17 + crates/wasm-host/src/context.rs | 12 + crates/wasm-host/src/error.rs | 13 + crates/wasm-host/src/host.rs | 195 +++ crates/wasm-host/src/lib.rs | 43 + crates/wasm-host/src/plugin.rs | 187 +++ crates/wasm-host/tests/integration_test.rs | 101 ++ gui/Cargo.toml | 8 + gui/src/app/mod.rs | 10 +- gui/src/app/ops.rs | 34 +- gui/src/app/update.rs | 4 +- gui/src/renderer/pipeline.rs | 203 ++- gui/src/renderer/render.rs | 22 +- gui/src/view/cpu.rs | 125 +- gui/src/view/gpu.rs | 107 +- gui/src/view/tools.rs | 9 +- gui/wix/main.wxs | 228 +++ plugins/example-noisemap/Cargo.lock | 7 + plugins/example-noisemap/Cargo.toml | 12 + plugins/example-noisemap/build.sh | 4 + plugins/example-noisemap/src/lib.rs | 216 +++ .../example-noisemap/target/.rustc_info.json | 1 + plugins/example-noisemap/target/CACHEDIR.TAG | 3 + .../target/debug/.cargo-build-lock | 0 .../example-noisemap/target/debug/.cargo-lock | 0 .../wasm32-unknown-unknown/CACHEDIR.TAG | 3 + .../debug/.cargo-build-lock | 0 .../wasm32-unknown-unknown/debug/.cargo-lock | 0 .../dep-lib-terrafier_plugin_example_noisemap | Bin 0 -> 30 bytes .../invoked.timestamp | 1 + .../lib-terrafier_plugin_example_noisemap | 1 + ...lib-terrafier_plugin_example_noisemap.json | 1 + ...tput-lib-terrafier_plugin_example_noisemap | 14 + ...in_example_noisemap-14d72cbe84c58ee8.rmeta | 0 ...plugin_example_noisemap-14d72cbe84c58ee8.d | 5 + .../dep-graph.bin | Bin 0 -> 251020 bytes .../query-cache.bin | Bin 0 -> 27565 bytes .../work-products.bin | Bin 0 -> 50 bytes .../s-hk27i4fig3-1sn51l0.lock | 0 .../dep-graph.bin | Bin 0 -> 258552 bytes .../query-cache.bin | Bin 0 -> 27100 bytes .../work-products.bin | Bin 0 -> 50 bytes .../s-hk27io9mtq-07w9ja3.lock | 0 scripts/example.rhai | 18 + 100 files changed, 4262 insertions(+), 585 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release-old.yml create mode 100644 .github/workflows/release.yml create mode 100644 cli/src/cmds/run.rs create mode 100644 cli/wix/main.wxs create mode 100644 crates/i18n/Cargo.toml create mode 100644 crates/i18n/src/lang.rs create mode 100644 crates/i18n/src/lib.rs create mode 100644 crates/i18n/src/translations/en.json create mode 100644 crates/i18n/src/translations/ru.json create mode 100644 crates/scripting/Cargo.toml create mode 100644 crates/scripting/src/lib.rs create mode 100644 crates/scripting/tests/integration_test.rs create mode 100644 crates/wasm-host/Cargo.toml create mode 100644 crates/wasm-host/src/context.rs create mode 100644 crates/wasm-host/src/error.rs create mode 100644 crates/wasm-host/src/host.rs create mode 100644 crates/wasm-host/src/lib.rs create mode 100644 crates/wasm-host/src/plugin.rs create mode 100644 crates/wasm-host/tests/integration_test.rs create mode 100644 gui/wix/main.wxs create mode 100644 plugins/example-noisemap/Cargo.lock create mode 100644 plugins/example-noisemap/Cargo.toml create mode 100755 plugins/example-noisemap/build.sh create mode 100644 plugins/example-noisemap/src/lib.rs create mode 100644 plugins/example-noisemap/target/.rustc_info.json create mode 100644 plugins/example-noisemap/target/CACHEDIR.TAG create mode 100644 plugins/example-noisemap/target/debug/.cargo-build-lock create mode 100644 plugins/example-noisemap/target/debug/.cargo-lock create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/CACHEDIR.TAG create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.cargo-build-lock create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.cargo-lock create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/dep-lib-terrafier_plugin_example_noisemap create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/invoked.timestamp create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/lib-terrafier_plugin_example_noisemap create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/lib-terrafier_plugin_example_noisemap.json create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/output-lib-terrafier_plugin_example_noisemap create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/deps/libterrafier_plugin_example_noisemap-14d72cbe84c58ee8.rmeta create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/deps/terrafier_plugin_example_noisemap-14d72cbe84c58ee8.d create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27i4fig3-1sn51l0-91gh4v9b9ie5o2bnlwcrqp175/dep-graph.bin create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27i4fig3-1sn51l0-91gh4v9b9ie5o2bnlwcrqp175/query-cache.bin create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27i4fig3-1sn51l0-91gh4v9b9ie5o2bnlwcrqp175/work-products.bin create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27i4fig3-1sn51l0.lock create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27io9mtq-07w9ja3-a5ky9mmjfvg1lji5jjcrqco2u/dep-graph.bin create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27io9mtq-07w9ja3-a5ky9mmjfvg1lji5jjcrqco2u/query-cache.bin create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27io9mtq-07w9ja3-a5ky9mmjfvg1lji5jjcrqco2u/work-products.bin create mode 100644 plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27io9mtq-07w9ja3.lock create mode 100644 scripts/example.rhai diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a124c80 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,64 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +env: + CARGO_TERM_COLOR: always + RUSTFLAGS: "-D warnings" + +jobs: + check: + name: Check (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + + - uses: Swatinem/rust-cache@v2 + + - name: Check compilation + run: cargo check --workspace --all-targets + + - name: Check formatting + run: cargo fmt --all --check + + - name: Clippy + run: cargo clippy --workspace --all-targets -- -D warnings + + test: + name: Test (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + needs: check + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + + - name: Run tests + run: cargo test --workspace + + audit: + name: Security Audit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + + - name: Install cargo-audit + run: cargo install cargo-audit --locked + + - name: Audit dependencies + run: cargo audit --deny warnings diff --git a/.github/workflows/release-old.yml b/.github/workflows/release-old.yml new file mode 100644 index 0000000..d9aa406 --- /dev/null +++ b/.github/workflows/release-old.yml @@ -0,0 +1,296 @@ +# This file was autogenerated by dist: https://axodotdev.github.io/cargo-dist +# +# Copyright 2022-2024, axodotdev +# SPDX-License-Identifier: MIT or Apache-2.0 +# +# CI that: +# +# * checks for a Git Tag that looks like a release +# * builds artifacts with dist (archives, installers, hashes) +# * uploads those artifacts to temporary workflow zip +# * on success, uploads the artifacts to a GitHub Release +# +# Note that the GitHub Release will be created with a generated +# title/body based on your changelogs. + +name: Release +permissions: + "contents": "write" + +# This task will run whenever you push a git tag that looks like a version +# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc. +# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where +# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION +# must be a Cargo-style SemVer Version (must have at least major.minor.patch). +# +# If PACKAGE_NAME is specified, then the announcement will be for that +# package (erroring out if it doesn't have the given version or isn't dist-able). +# +# If PACKAGE_NAME isn't specified, then the announcement will be for all +# (dist-able) packages in the workspace with that version (this mode is +# intended for workspaces with only one dist-able package, or with all dist-able +# packages versioned/released in lockstep). +# +# If you push multiple tags at once, separate instances of this workflow will +# spin up, creating an independent announcement for each one. However, GitHub +# will hard limit this to 3 tags per commit, as it will assume more tags is a +# mistake. +# +# If there's a prerelease-style suffix to the version, then the release(s) +# will be marked as a prerelease. +on: + pull_request: + push: + tags: + - '**[0-9]+.[0-9]+.[0-9]+*' + +jobs: + # Run 'dist plan' (or host) to determine what tasks we need to do + plan: + runs-on: "ubuntu-22.04" + outputs: + val: ${{ steps.plan.outputs.manifest }} + tag: ${{ !github.event.pull_request && github.ref_name || '' }} + tag-flag: ${{ !github.event.pull_request && format('--tag={0}', github.ref_name) || '' }} + publishing: ${{ !github.event.pull_request }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + submodules: recursive + - name: Install dist + # we specify bash to get pipefail; it guards against the `curl` command + # failing. otherwise `sh` won't catch that `curl` returned non-0 + shell: bash + run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.31.0/cargo-dist-installer.sh | sh" + - name: Cache dist + uses: actions/upload-artifact@v6 + with: + name: cargo-dist-cache + path: ~/.cargo/bin/dist + # sure would be cool if github gave us proper conditionals... + # so here's a doubly-nested ternary-via-truthiness to try to provide the best possible + # functionality based on whether this is a pull_request, and whether it's from a fork. + # (PRs run on the *source* but secrets are usually on the *target* -- that's *good* + # but also really annoying to build CI around when it needs secrets to work right.) + - id: plan + run: | + dist ${{ (!github.event.pull_request && format('host --steps=create --tag={0}', github.ref_name)) || 'plan' }} --output-format=json > plan-dist-manifest.json + echo "dist ran successfully" + cat plan-dist-manifest.json + echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT" + - name: "Upload dist-manifest.json" + uses: actions/upload-artifact@v6 + with: + name: artifacts-plan-dist-manifest + path: plan-dist-manifest.json + + # Build and packages all the platform-specific things + build-local-artifacts: + name: build-local-artifacts (${{ join(matrix.targets, ', ') }}) + # Let the initial task tell us to not run (currently very blunt) + needs: + - plan + if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null && (needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload') }} + strategy: + fail-fast: false + # Target platforms/runners are computed by dist in create-release. + # Each member of the matrix has the following arguments: + # + # - runner: the github runner + # - dist-args: cli flags to pass to dist + # - install-dist: expression to run to install dist on the runner + # + # Typically there will be: + # - 1 "global" task that builds universal installers + # - N "local" tasks that build each platform's binaries and platform-specific installers + matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }} + runs-on: ${{ matrix.runner }} + container: ${{ matrix.container && matrix.container.image || null }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json + steps: + - name: enable windows longpaths + run: | + git config --global core.longpaths true + - uses: actions/checkout@v6 + with: + persist-credentials: false + submodules: recursive + - name: Install Rust non-interactively if not already installed + if: ${{ matrix.container }} + run: | + if ! command -v cargo > /dev/null 2>&1; then + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + echo "$HOME/.cargo/bin" >> $GITHUB_PATH + fi + - name: Install dist + run: ${{ matrix.install_dist.run }} + # Get the dist-manifest + - name: Fetch local artifacts + uses: actions/download-artifact@v7 + with: + pattern: artifacts-* + path: target/distrib/ + merge-multiple: true + - name: Install dependencies + run: | + ${{ matrix.packages_install }} + - name: Build artifacts + run: | + # Actually do builds and make zips and whatnot + dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json + echo "dist ran successfully" + - id: cargo-dist + name: Post-build + # We force bash here just because github makes it really hard to get values up + # to "real" actions without writing to env-vars, and writing to env-vars has + # inconsistent syntax between shell and powershell. + shell: bash + run: | + # Parse out what we just built and upload it to scratch storage + echo "paths<> "$GITHUB_OUTPUT" + dist print-upload-files-from-manifest --manifest dist-manifest.json >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + + cp dist-manifest.json "$BUILD_MANIFEST_NAME" + - name: "Upload artifacts" + uses: actions/upload-artifact@v6 + with: + name: artifacts-build-local-${{ join(matrix.targets, '_') }} + path: | + ${{ steps.cargo-dist.outputs.paths }} + ${{ env.BUILD_MANIFEST_NAME }} + + # Build and package all the platform-agnostic(ish) things + build-global-artifacts: + needs: + - plan + - build-local-artifacts + runs-on: "ubuntu-22.04" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + submodules: recursive + - name: Install cached dist + uses: actions/download-artifact@v7 + with: + name: cargo-dist-cache + path: ~/.cargo/bin/ + - run: chmod +x ~/.cargo/bin/dist + # Get all the local artifacts for the global tasks to use (for e.g. checksums) + - name: Fetch local artifacts + uses: actions/download-artifact@v7 + with: + pattern: artifacts-* + path: target/distrib/ + merge-multiple: true + - id: cargo-dist + shell: bash + run: | + dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json + echo "dist ran successfully" + + # Parse out what we just built and upload it to scratch storage + echo "paths<> "$GITHUB_OUTPUT" + jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + + cp dist-manifest.json "$BUILD_MANIFEST_NAME" + - name: "Upload artifacts" + uses: actions/upload-artifact@v6 + with: + name: artifacts-build-global + path: | + ${{ steps.cargo-dist.outputs.paths }} + ${{ env.BUILD_MANIFEST_NAME }} + # Determines if we should publish/announce + host: + needs: + - plan + - build-local-artifacts + - build-global-artifacts + # Only run if we're "publishing", and only if plan, local and global didn't fail (skipped is fine) + if: ${{ always() && needs.plan.result == 'success' && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + runs-on: "ubuntu-22.04" + outputs: + val: ${{ steps.host.outputs.manifest }} + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + submodules: recursive + - name: Install cached dist + uses: actions/download-artifact@v7 + with: + name: cargo-dist-cache + path: ~/.cargo/bin/ + - run: chmod +x ~/.cargo/bin/dist + # Fetch artifacts from scratch-storage + - name: Fetch artifacts + uses: actions/download-artifact@v7 + with: + pattern: artifacts-* + path: target/distrib/ + merge-multiple: true + - id: host + shell: bash + run: | + dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json + echo "artifacts uploaded and released successfully" + cat dist-manifest.json + echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT" + - name: "Upload dist-manifest.json" + uses: actions/upload-artifact@v6 + with: + # Overwrite the previous copy + name: artifacts-dist-manifest + path: dist-manifest.json + # Create a GitHub Release while uploading all files to it + - name: "Download GitHub Artifacts" + uses: actions/download-artifact@v7 + with: + pattern: artifacts-* + path: artifacts + merge-multiple: true + - name: Cleanup + run: | + # Remove the granular manifests + rm -f artifacts/*-dist-manifest.json + - name: Create GitHub Release + env: + PRERELEASE_FLAG: "${{ fromJson(steps.host.outputs.manifest).announcement_is_prerelease && '--prerelease' || '' }}" + ANNOUNCEMENT_TITLE: "${{ fromJson(steps.host.outputs.manifest).announcement_title }}" + ANNOUNCEMENT_BODY: "${{ fromJson(steps.host.outputs.manifest).announcement_github_body }}" + RELEASE_COMMIT: "${{ github.sha }}" + run: | + # Write and read notes from a file to avoid quoting breaking things + echo "$ANNOUNCEMENT_BODY" > $RUNNER_TEMP/notes.txt + + gh release create "${{ needs.plan.outputs.tag }}" --target "$RELEASE_COMMIT" $PRERELEASE_FLAG --title "$ANNOUNCEMENT_TITLE" --notes-file "$RUNNER_TEMP/notes.txt" artifacts/* + + announce: + needs: + - plan + - host + # use "always() && ..." to allow us to wait for all publish jobs while + # still allowing individual publish jobs to skip themselves (for prereleases). + # "host" however must run to completion, no skipping allowed! + if: ${{ always() && needs.host.result == 'success' }} + runs-on: "ubuntu-22.04" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + submodules: recursive diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..d9aa406 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,296 @@ +# This file was autogenerated by dist: https://axodotdev.github.io/cargo-dist +# +# Copyright 2022-2024, axodotdev +# SPDX-License-Identifier: MIT or Apache-2.0 +# +# CI that: +# +# * checks for a Git Tag that looks like a release +# * builds artifacts with dist (archives, installers, hashes) +# * uploads those artifacts to temporary workflow zip +# * on success, uploads the artifacts to a GitHub Release +# +# Note that the GitHub Release will be created with a generated +# title/body based on your changelogs. + +name: Release +permissions: + "contents": "write" + +# This task will run whenever you push a git tag that looks like a version +# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc. +# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where +# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION +# must be a Cargo-style SemVer Version (must have at least major.minor.patch). +# +# If PACKAGE_NAME is specified, then the announcement will be for that +# package (erroring out if it doesn't have the given version or isn't dist-able). +# +# If PACKAGE_NAME isn't specified, then the announcement will be for all +# (dist-able) packages in the workspace with that version (this mode is +# intended for workspaces with only one dist-able package, or with all dist-able +# packages versioned/released in lockstep). +# +# If you push multiple tags at once, separate instances of this workflow will +# spin up, creating an independent announcement for each one. However, GitHub +# will hard limit this to 3 tags per commit, as it will assume more tags is a +# mistake. +# +# If there's a prerelease-style suffix to the version, then the release(s) +# will be marked as a prerelease. +on: + pull_request: + push: + tags: + - '**[0-9]+.[0-9]+.[0-9]+*' + +jobs: + # Run 'dist plan' (or host) to determine what tasks we need to do + plan: + runs-on: "ubuntu-22.04" + outputs: + val: ${{ steps.plan.outputs.manifest }} + tag: ${{ !github.event.pull_request && github.ref_name || '' }} + tag-flag: ${{ !github.event.pull_request && format('--tag={0}', github.ref_name) || '' }} + publishing: ${{ !github.event.pull_request }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + submodules: recursive + - name: Install dist + # we specify bash to get pipefail; it guards against the `curl` command + # failing. otherwise `sh` won't catch that `curl` returned non-0 + shell: bash + run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.31.0/cargo-dist-installer.sh | sh" + - name: Cache dist + uses: actions/upload-artifact@v6 + with: + name: cargo-dist-cache + path: ~/.cargo/bin/dist + # sure would be cool if github gave us proper conditionals... + # so here's a doubly-nested ternary-via-truthiness to try to provide the best possible + # functionality based on whether this is a pull_request, and whether it's from a fork. + # (PRs run on the *source* but secrets are usually on the *target* -- that's *good* + # but also really annoying to build CI around when it needs secrets to work right.) + - id: plan + run: | + dist ${{ (!github.event.pull_request && format('host --steps=create --tag={0}', github.ref_name)) || 'plan' }} --output-format=json > plan-dist-manifest.json + echo "dist ran successfully" + cat plan-dist-manifest.json + echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT" + - name: "Upload dist-manifest.json" + uses: actions/upload-artifact@v6 + with: + name: artifacts-plan-dist-manifest + path: plan-dist-manifest.json + + # Build and packages all the platform-specific things + build-local-artifacts: + name: build-local-artifacts (${{ join(matrix.targets, ', ') }}) + # Let the initial task tell us to not run (currently very blunt) + needs: + - plan + if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null && (needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload') }} + strategy: + fail-fast: false + # Target platforms/runners are computed by dist in create-release. + # Each member of the matrix has the following arguments: + # + # - runner: the github runner + # - dist-args: cli flags to pass to dist + # - install-dist: expression to run to install dist on the runner + # + # Typically there will be: + # - 1 "global" task that builds universal installers + # - N "local" tasks that build each platform's binaries and platform-specific installers + matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }} + runs-on: ${{ matrix.runner }} + container: ${{ matrix.container && matrix.container.image || null }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json + steps: + - name: enable windows longpaths + run: | + git config --global core.longpaths true + - uses: actions/checkout@v6 + with: + persist-credentials: false + submodules: recursive + - name: Install Rust non-interactively if not already installed + if: ${{ matrix.container }} + run: | + if ! command -v cargo > /dev/null 2>&1; then + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + echo "$HOME/.cargo/bin" >> $GITHUB_PATH + fi + - name: Install dist + run: ${{ matrix.install_dist.run }} + # Get the dist-manifest + - name: Fetch local artifacts + uses: actions/download-artifact@v7 + with: + pattern: artifacts-* + path: target/distrib/ + merge-multiple: true + - name: Install dependencies + run: | + ${{ matrix.packages_install }} + - name: Build artifacts + run: | + # Actually do builds and make zips and whatnot + dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json + echo "dist ran successfully" + - id: cargo-dist + name: Post-build + # We force bash here just because github makes it really hard to get values up + # to "real" actions without writing to env-vars, and writing to env-vars has + # inconsistent syntax between shell and powershell. + shell: bash + run: | + # Parse out what we just built and upload it to scratch storage + echo "paths<> "$GITHUB_OUTPUT" + dist print-upload-files-from-manifest --manifest dist-manifest.json >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + + cp dist-manifest.json "$BUILD_MANIFEST_NAME" + - name: "Upload artifacts" + uses: actions/upload-artifact@v6 + with: + name: artifacts-build-local-${{ join(matrix.targets, '_') }} + path: | + ${{ steps.cargo-dist.outputs.paths }} + ${{ env.BUILD_MANIFEST_NAME }} + + # Build and package all the platform-agnostic(ish) things + build-global-artifacts: + needs: + - plan + - build-local-artifacts + runs-on: "ubuntu-22.04" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + submodules: recursive + - name: Install cached dist + uses: actions/download-artifact@v7 + with: + name: cargo-dist-cache + path: ~/.cargo/bin/ + - run: chmod +x ~/.cargo/bin/dist + # Get all the local artifacts for the global tasks to use (for e.g. checksums) + - name: Fetch local artifacts + uses: actions/download-artifact@v7 + with: + pattern: artifacts-* + path: target/distrib/ + merge-multiple: true + - id: cargo-dist + shell: bash + run: | + dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json + echo "dist ran successfully" + + # Parse out what we just built and upload it to scratch storage + echo "paths<> "$GITHUB_OUTPUT" + jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + + cp dist-manifest.json "$BUILD_MANIFEST_NAME" + - name: "Upload artifacts" + uses: actions/upload-artifact@v6 + with: + name: artifacts-build-global + path: | + ${{ steps.cargo-dist.outputs.paths }} + ${{ env.BUILD_MANIFEST_NAME }} + # Determines if we should publish/announce + host: + needs: + - plan + - build-local-artifacts + - build-global-artifacts + # Only run if we're "publishing", and only if plan, local and global didn't fail (skipped is fine) + if: ${{ always() && needs.plan.result == 'success' && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + runs-on: "ubuntu-22.04" + outputs: + val: ${{ steps.host.outputs.manifest }} + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + submodules: recursive + - name: Install cached dist + uses: actions/download-artifact@v7 + with: + name: cargo-dist-cache + path: ~/.cargo/bin/ + - run: chmod +x ~/.cargo/bin/dist + # Fetch artifacts from scratch-storage + - name: Fetch artifacts + uses: actions/download-artifact@v7 + with: + pattern: artifacts-* + path: target/distrib/ + merge-multiple: true + - id: host + shell: bash + run: | + dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json + echo "artifacts uploaded and released successfully" + cat dist-manifest.json + echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT" + - name: "Upload dist-manifest.json" + uses: actions/upload-artifact@v6 + with: + # Overwrite the previous copy + name: artifacts-dist-manifest + path: dist-manifest.json + # Create a GitHub Release while uploading all files to it + - name: "Download GitHub Artifacts" + uses: actions/download-artifact@v7 + with: + pattern: artifacts-* + path: artifacts + merge-multiple: true + - name: Cleanup + run: | + # Remove the granular manifests + rm -f artifacts/*-dist-manifest.json + - name: Create GitHub Release + env: + PRERELEASE_FLAG: "${{ fromJson(steps.host.outputs.manifest).announcement_is_prerelease && '--prerelease' || '' }}" + ANNOUNCEMENT_TITLE: "${{ fromJson(steps.host.outputs.manifest).announcement_title }}" + ANNOUNCEMENT_BODY: "${{ fromJson(steps.host.outputs.manifest).announcement_github_body }}" + RELEASE_COMMIT: "${{ github.sha }}" + run: | + # Write and read notes from a file to avoid quoting breaking things + echo "$ANNOUNCEMENT_BODY" > $RUNNER_TEMP/notes.txt + + gh release create "${{ needs.plan.outputs.tag }}" --target "$RELEASE_COMMIT" $PRERELEASE_FLAG --title "$ANNOUNCEMENT_TITLE" --notes-file "$RUNNER_TEMP/notes.txt" artifacts/* + + announce: + needs: + - plan + - host + # use "always() && ..." to allow us to wait for all publish jobs while + # still allowing individual publish jobs to skip themselves (for prereleases). + # "host" however must run to completion, no skipping allowed! + if: ${{ always() && needs.host.result == 'success' }} + runs-on: "ubuntu-22.04" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v6 + with: + persist-credentials: false + submodules: recursive diff --git a/Cargo.lock b/Cargo.lock index f939ad1..7b7abcd 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,6 +110,15 @@ dependencies = [ "winit", ] +[[package]] +name = "addr2line" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59317f77929f0e679d39364702289274de2f0f0b22cbf50b2b8cff2169a0b27a" +dependencies = [ + "gimli", +] + [[package]] name = "adler2" version = "2.0.1" @@ -123,6 +132,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", + "const-random", "getrandom 0.3.4", "once_cell", "version_check", @@ -138,6 +148,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "android-activity" version = "0.6.1" @@ -145,7 +161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" dependencies = [ "android-properties", - "bitflags 2.11.1", + "bitflags 2.13.0", "cc", "jni", "libc", @@ -230,9 +246,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" [[package]] name = "arboard" @@ -262,9 +284,9 @@ checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" [[package]] name = "as-raw-xcb-connection" @@ -300,7 +322,7 @@ dependencies = [ "wayland-backend", "wayland-client", "wayland-protocols", - "zbus 5.15.0", + "zbus 5.16.0", ] [[package]] @@ -520,12 +542,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] -name = "bincode" -version = "1.3.3" +name = "base64" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bincode" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" 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]] @@ -551,9 +590,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" dependencies = [ "serde_core", ] @@ -609,6 +648,9 @@ name = "bumpalo" version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +dependencies = [ + "allocator-api2", +] [[package]] name = "bytemuck" @@ -638,9 +680,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" [[package]] name = "calloop" @@ -648,7 +690,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "log", "polling", "rustix 0.38.44", @@ -662,7 +704,7 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "polling", "rustix 1.1.4", "slab", @@ -701,9 +743,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.62" +version = "1.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" +checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" dependencies = [ "find-msvc-tools", "jobserver", @@ -808,6 +850,15 @@ dependencies = [ "error-code", ] +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.18", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -856,6 +907,26 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "tiny-keccak", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -906,6 +977,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpp_demangle" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2bb79cb74d735044c972aae58ed0aaa9a837e85b01106a54c39e42e97f62253" +dependencies = [ + "cfg-if", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -915,6 +995,152 @@ dependencies = [ "libc", ] +[[package]] +name = "cranelift-assembler-x64" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e06aeba2c965fc446d13c56a6ccb2631b78445d7544543dd9a25289977630914" +dependencies = [ + "cranelift-assembler-x64-meta", +] + +[[package]] +name = "cranelift-assembler-x64-meta" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2d2dde4ec1352715595b5cfa6fe2e5b8ebb9da3457b3ee8db0aa2808c069aa" +dependencies = [ + "cranelift-srcgen", +] + +[[package]] +name = "cranelift-bforest" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b4982ef9fa54ec9eee841e891e7ddc5434be1250e88de31572e000c888f30b" +dependencies = [ + "cranelift-entity", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-bitset" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "529143118c4eeb58c39ecb02319557d512be6c61348486422974ab8e3906b8a8" +dependencies = [ + "serde", + "serde_derive", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-codegen" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7780677247ad3577e3a6a3ebf43f39b325a11d6393db72b2c9968a910d4d13d" +dependencies = [ + "bumpalo", + "cranelift-assembler-x64", + "cranelift-bforest", + "cranelift-bitset", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity", + "cranelift-isle", + "gimli", + "hashbrown 0.17.1", + "libm", + "log", + "postcard", + "pulley-interpreter", + "regalloc2", + "rustc-hash 2.1.3", + "serde", + "serde_derive", + "sha2", + "smallvec", + "target-lexicon", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac9645250416cbf92454fe61160e17e026e0ce405906a54500b114f923ddffc9" +dependencies = [ + "cranelift-assembler-x64-meta", + "cranelift-codegen-shared", + "cranelift-srcgen", + "heck", + "pulley-interpreter", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20ee8d222ff0fd3681791979afbf88586ac9f49010d3db96b3cbe4c96759aee3" + +[[package]] +name = "cranelift-control" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "591abe6f5312bd2c4220f1b3bead56c2ad00257c52668015ba013b85dcf2a17a" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "cranelift-entity" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5300c49cf940526fe771517b3b3eabd5d0ff164ee61698579cf403fe8d3af3c" +dependencies = [ + "cranelift-bitset", + "serde", + "serde_derive", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-frontend" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da4adbf760207fdbbe130f1191cce01cdef66831a9f648b1f39ff2800d126d45" +dependencies = [ + "cranelift-codegen", + "hashbrown 0.17.1", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8315b21ff018226a42a60a4702c2dd75f6447cac26e9bca622e14c22088c2ff5" + +[[package]] +name = "cranelift-native" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d506ef23a60715bde451b06620b14402166ded3b648454fccbf04f3e46a4aa70" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-srcgen" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48ed47e602652e3410f9387fc0db70fefadcee4d78a78881421aabcab4e26b89" + [[package]] name = "crc32fast" version = "1.5.0" @@ -936,7 +1162,7 @@ dependencies = [ "clap", "criterion-plot", "is-terminal", - "itertools", + "itertools 0.10.5", "num-traits", "once_cell", "oorandom", @@ -957,7 +1183,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", - "itertools", + "itertools 0.10.5", ] [[package]] @@ -1007,6 +1233,46 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "uuid", +] + +[[package]] +name = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror 2.0.18", +] + [[package]] name = "digest" version = "0.10.7" @@ -1017,6 +1283,27 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -1029,7 +1316,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.6.2", "libc", "objc2 0.6.4", @@ -1037,9 +1324,9 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", @@ -1132,7 +1419,7 @@ checksum = "25dd34cec49ab55d85ebf70139cb1ccd29c977ef6b6ba4fe85489d6877ee9ef3" dependencies = [ "accesskit", "ahash", - "bitflags 2.11.1", + "bitflags 2.13.0", "emath", "epaint", "log", @@ -1213,12 +1500,33 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + [[package]] name = "encode_unicode" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "endi" version = "1.1.1" @@ -1248,9 +1556,9 @@ dependencies = [ [[package]] name = "env_filter" -version = "1.0.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" +checksum = "900d271a03799a1ee8d1ca9b19893b48ca674a9284fefcfb85f05e74ed314217" dependencies = [ "log", "regex", @@ -1258,9 +1566,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.10" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" +checksum = "de671bd27a75a797dc9ae289ba1e77276e75e2026408aab65185384e2d5cd3f6" dependencies = [ "anstream", "anstyle", @@ -1363,6 +1671,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "flate2" version = "1.1.9" @@ -1373,12 +1687,24 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "foldhash" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.5.0" @@ -1415,6 +1741,20 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.32" @@ -1422,6 +1762,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -1478,6 +1819,7 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -1488,6 +1830,20 @@ dependencies = [ "slab", ] +[[package]] +name = "fxprof-processed-profile" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25234f20a3ec0a962a61770cfe39ecf03cb529a6e474ad8cff025ed497eda557" +dependencies = [ + "bitflags 2.13.0", + "debugid", + "rustc-hash 2.1.3", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1544,15 +1900,25 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "wasip2", - "wasip3", +] + +[[package]] +name = "gimli" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7f043f89559805f8c7cacc432749b2fa0d0a0a9ee46ce47164ed5ba7f126c" +dependencies = [ + "fnv", + "hashbrown 0.16.1", + "indexmap", + "stable_deref_trait", ] [[package]] @@ -1584,7 +1950,7 @@ version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg_aliases", "cgl", "dispatch2", @@ -1646,21 +2012,21 @@ dependencies = [ [[package]] name = "gpu-alloc" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +checksum = "45cf04b2726f02df5508c6de726acdc90cdf97ac771a9a0ffd8ba10a6e696bf9" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "gpu-alloc-types", ] [[package]] name = "gpu-alloc-types" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +checksum = "b2bbed164dd10ed526c2e4fe3e721ca4a71c61730e5aafac6844b417b3227058" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -1681,7 +2047,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "gpu-descriptor-types", "hashbrown 0.15.5", ] @@ -1692,7 +2058,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -1712,14 +2078,25 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash", + "foldhash 0.1.5", ] +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + [[package]] name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "foldhash 0.2.0", + "serde", + "serde_core", +] [[package]] name = "heck" @@ -1928,6 +2305,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.18" @@ -1935,11 +2321,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] -name = "jiff" -version = "0.2.25" +name = "ittapi" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6835eea34fb6321b9b3aa7b685c2b433948c09447e389dc017fdf687d5d11e65" +checksum = "6b996fe614c41395cdaedf3cf408a9534851090959d90d54a535f675550b64b1" dependencies = [ + "anyhow", + "ittapi-sys", + "log", +] + +[[package]] +name = "ittapi-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5385394064fa2c886205dba02598013ce83d3e92d33dbdc0c52fe0e7bf4fc" +dependencies = [ + "cc", +] + +[[package]] +name = "jiff" +version = "0.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccfe6121cbe750cf81efa362d85c0bde7ea298ec43092d3a193baca59cdbd634" +dependencies = [ + "defmt", "jiff-static", "log", "portable-atomic", @@ -1949,9 +2356,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.25" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c22e04db9c58f5136eb1757f3d5c49a7b187f49e52185228cbd2f5acdfcc08c" +checksum = "e165e897f662d428f3cd3828a919dbe067c2d42bb1031eede74ef9d27ecdedd2" dependencies = [ "proc-macro2", "quote", @@ -2028,13 +2435,12 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.99" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if", "futures-util", - "once_cell", "wasm-bindgen", ] @@ -2078,15 +2484,21 @@ dependencies = [ ] [[package]] -name = "libredox" -version = "0.1.16" +name = "libm" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "libc", "plain", - "redox_syscall 0.7.5", + "redox_syscall 0.9.0", ] [[package]] @@ -2124,9 +2536,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.30" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "mach2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b" [[package]] name = "malloc_buf" @@ -2139,15 +2557,24 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" + +[[package]] +name = "memfd" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" +dependencies = [ + "rustix 1.1.4", +] [[package]] name = "memmap2" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" dependencies = [ "libc", ] @@ -2167,7 +2594,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f569fb946490b5743ad69813cb19629130ce9374034abe31614a36402d18f99e" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block", "core-graphics-types", "foreign-types", @@ -2204,7 +2631,7 @@ checksum = "e380993072e52eef724eddfcde0ed013b0c023c3f0417336ed041aa9f076994e" dependencies = [ "arrayvec", "bit-set", - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg_aliases", "codespan-reporting", "hexf-parse", @@ -2224,7 +2651,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "jni-sys 0.3.1", "log", "ndk-sys 0.6.0+11769913", @@ -2263,7 +2690,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if", "cfg_aliases", "libc", @@ -2364,7 +2791,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "libc", "objc2 0.5.2", @@ -2380,7 +2807,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.6.2", "objc2 0.6.4", "objc2-core-foundation", @@ -2394,7 +2821,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", @@ -2418,7 +2845,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -2430,7 +2857,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "dispatch2", "objc2 0.6.4", ] @@ -2441,7 +2868,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "dispatch2", "objc2 0.6.4", "objc2-core-foundation", @@ -2484,7 +2911,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "dispatch", "libc", @@ -2497,7 +2924,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2 0.6.4", "objc2-core-foundation", ] @@ -2508,7 +2935,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2 0.6.4", "objc2-core-foundation", ] @@ -2531,7 +2958,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -2543,7 +2970,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -2566,7 +2993,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "objc2 0.5.2", "objc2-cloud-kit", @@ -2598,18 +3025,33 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", "objc2-foundation 0.2.2", ] +[[package]] +name = "object" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" +dependencies = [ + "crc32fast", + "hashbrown 0.17.1", + "indexmap", + "memchr", +] + [[package]] name = "once_cell" version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +dependencies = [ + "portable-atomic", +] [[package]] name = "once_cell_polyfill" @@ -2702,6 +3144,16 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + [[package]] name = "pin-project" version = "1.1.13" @@ -2785,7 +3237,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "crc32fast", "fdeflate", "flate2", @@ -2827,6 +3279,18 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + [[package]] name = "potential_utf" version = "0.1.5" @@ -2851,16 +3315,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -2885,6 +3339,29 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" +[[package]] +name = "pulley-interpreter" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b92604caae1a1899b6a5b54967289dd538177c626004c91accf9d0ec7e4a12" +dependencies = [ + "cranelift-bitset", + "log", + "pulley-macros", + "wasmtime-internal-core", +] + +[[package]] +name = "pulley-macros" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a7ac85c0bb3fb351f10d531230aaa5e366b46d7c4e5328e5f02801d6dac1165" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pxfm" version = "0.1.29" @@ -2918,9 +3395,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.45" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] @@ -3093,23 +3570,49 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] name = "redox_syscall" -version = "0.7.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" +checksum = "c5102a6aaa05aa011a238e178e6bca86d2cb56fc9f586d37cb80f5bca6e07759" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "regalloc2" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de2c52737737f8609e94f975dee22854a2d5c125772d4b1cf292120f4d45c186" +dependencies = [ + "allocator-api2", + "bumpalo", + "hashbrown 0.17.1", + "log", + "rustc-hash 2.1.3", + "serde", + "smallvec", ] [[package]] name = "regex" -version = "1.12.3" +version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" dependencies = [ "aho-corasick", "memchr", @@ -3130,9 +3633,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "renderdoc-sys" @@ -3164,6 +3667,40 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "rhai" +version = "1.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4dd0f8c36625202a4ba553c416c19b719947cd2a31d1bda06126e4a5727daf" +dependencies = [ + "ahash", + "bitflags 2.13.0", + "num-traits", + "once_cell", + "rhai_codegen", + "smallvec", + "smartstring", + "thin-vec", + "web-time", +] + +[[package]] +name = "rhai_codegen" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cd3a7535e50bf36857e7be7bec276d334e8c2dfa469c2201226fd01638ea5ca" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -3172,9 +3709,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" @@ -3191,7 +3728,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -3204,7 +3741,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.12.1", @@ -3256,6 +3793,10 @@ name = "semver" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] [[package]] name = "serde" @@ -3320,6 +3861,15 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + [[package]] name = "sha1" version = "0.10.6" @@ -3332,10 +3882,21 @@ dependencies = [ ] [[package]] -name = "shlex" -version = "1.3.0" +name = "sha2" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "signal-hook-registry" @@ -3386,9 +3947,23 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +dependencies = [ + "serde", +] + +[[package]] +name = "smartstring" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" +dependencies = [ + "autocfg", + "static_assertions", + "version_check", +] [[package]] name = "smithay-client-toolkit" @@ -3396,7 +3971,7 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "calloop 0.13.0", "calloop-wayland-source 0.3.0", "cursor-icon", @@ -3421,7 +3996,7 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "calloop 0.14.4", "calloop-wayland-source 0.4.1", "cursor-icon", @@ -3468,7 +4043,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -3519,9 +4094,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.117" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -3539,6 +4114,12 @@ dependencies = [ "syn", ] +[[package]] +name = "target-lexicon" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" + [[package]] name = "tempfile" version = "3.27.0" @@ -3546,7 +4127,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom 0.4.3", "once_cell", "rustix 1.1.4", "windows-sys 0.61.2", @@ -3590,6 +4171,8 @@ dependencies = [ "log", "serde_json", "terrafier-core", + "terrafier-i18n", + "terrafier-scripting", ] [[package]] @@ -3637,6 +4220,14 @@ dependencies = [ "wgpu", ] +[[package]] +name = "terrafier-i18n" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "terrafier-nbt" version = "0.1.0" @@ -3662,6 +4253,34 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "terrafier-scripting" +version = "0.1.0" +dependencies = [ + "anyhow", + "rhai", + "terrafier-core", +] + +[[package]] +name = "terrafier-wasm-host" +version = "0.1.0" +dependencies = [ + "anyhow", + "log", + "tempfile", + "terrafier-core", + "thiserror 2.0.18", + "wasmtime", + "wat", +] + +[[package]] +name = "thin-vec" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0f7e269b48f0a7dd0146680fa24b50cc67fc0373f086a5b2f99bd084639b482" + [[package]] name = "thiserror" version = "1.0.69" @@ -3716,6 +4335,15 @@ dependencies = [ "zune-jpeg", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tiny-skia" version = "0.11.4" @@ -3761,6 +4389,30 @@ dependencies = [ "serde_json", ] +[[package]] +name = "toml" +version = "0.9.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime 0.7.5+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 0.7.15", +] + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_datetime" version = "1.1.1+spec-1.1.0" @@ -3772,14 +4424,14 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.11+spec-1.1.0" +version = "0.25.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ "indexmap", - "toml_datetime", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow", + "winnow 1.0.3", ] [[package]] @@ -3788,9 +4440,15 @@ version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow", + "winnow 1.0.3", ] +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + [[package]] name = "tracing" version = "0.1.44" @@ -3835,7 +4493,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" dependencies = [ - "rustc-hash 2.1.2", + "rustc-hash 2.1.3", ] [[package]] @@ -3863,9 +4521,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-width" @@ -3885,6 +4543,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + [[package]] name = "url" version = "2.5.8" @@ -3918,9 +4582,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.1" +version = "1.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" dependencies = [ "js-sys", "serde_core", @@ -3933,6 +4597,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "virtue" +version = "0.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" + [[package]] name = "walkdir" version = "2.5.0" @@ -3957,27 +4627,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.3+wasi-0.2.9" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -3988,9 +4649,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.72" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ "js-sys", "wasm-bindgen", @@ -3998,9 +4659,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4008,9 +4669,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", @@ -4021,45 +4682,345 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] [[package]] -name = "wasm-encoder" -version = "0.244.0" +name = "wasm-compose" +version = "0.251.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +checksum = "b089037d7eb453ed57b560fe7833de0707411c8b9fdc429745ced77e2a1bacb9" dependencies = [ - "leb128fmt", - "wasmparser", + "anyhow", + "heck", + "indexmap", + "log", + "petgraph", + "smallvec", + "wasm-encoder 0.251.0", + "wasmparser 0.251.0", + "wat", ] [[package]] -name = "wasm-metadata" -version = "0.244.0" +name = "wasm-encoder" +version = "0.251.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +checksum = "5a879a421bd17c528b74721b2abf4c62e8f1d1889c2ba8c3c50d02deaf2ce395" dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser", + "leb128fmt", + "wasmparser 0.251.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.252.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8185ae345fa5687c054626ff9a50e7089797a343d9904d1dc9820eb4c4d3196f" +dependencies = [ + "leb128fmt", + "wasmparser 0.252.0", ] [[package]] name = "wasmparser" -version = "0.244.0" +version = "0.251.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +checksum = "437970b35b1a85cfde9c74b2398352d8d653f3bd8e3a3db0c063ea8f5b4b36ff" dependencies = [ - "bitflags 2.11.1", - "hashbrown 0.15.5", + "bitflags 2.13.0", + "hashbrown 0.17.1", "indexmap", "semver", + "serde", +] + +[[package]] +name = "wasmparser" +version = "0.252.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3eb099dcadcde5be9eef55e3a337128efd4e44b4c93122487e4d2e4e1c6627c" +dependencies = [ + "bitflags 2.13.0", + "indexmap", + "semver", +] + +[[package]] +name = "wasmprinter" +version = "0.251.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8798c1a699bd25648b6708eefe94d97c6f9891febb94b42cca1f7a4b086ea64e" +dependencies = [ + "anyhow", + "termcolor", + "wasmparser 0.251.0", +] + +[[package]] +name = "wasmtime" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4213d2f019a5e44aa8a61d8826dd33a505bff79f749b14a8bafd67321cb9351" +dependencies = [ + "addr2line", + "async-trait", + "bitflags 2.13.0", + "bumpalo", + "cc", + "cfg-if", + "encoding_rs", + "futures", + "fxprof-processed-profile", + "gimli", + "ittapi", + "libc", + "log", + "mach2", + "memfd", + "object", + "once_cell", + "postcard", + "pulley-interpreter", + "rayon", + "rustix 1.1.4", + "semver", + "serde", + "serde_derive", + "serde_json", + "smallvec", + "target-lexicon", + "tempfile", + "wasm-compose", + "wasm-encoder 0.251.0", + "wasmparser 0.251.0", + "wasmtime-environ", + "wasmtime-internal-cache", + "wasmtime-internal-component-macro", + "wasmtime-internal-component-util", + "wasmtime-internal-core", + "wasmtime-internal-cranelift", + "wasmtime-internal-fiber", + "wasmtime-internal-jit-debug", + "wasmtime-internal-jit-icache-coherence", + "wasmtime-internal-unwinder", + "wasmtime-internal-versioned-export-macros", + "wat", + "windows-sys 0.61.2", + "wit-parser", +] + +[[package]] +name = "wasmtime-environ" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d45863de41977ec6453e859cf843d456fa3fcb45a659b66d16e794f90ec4f5b7" +dependencies = [ + "anyhow", + "cpp_demangle", + "cranelift-bforest", + "cranelift-bitset", + "cranelift-entity", + "gimli", + "hashbrown 0.17.1", + "indexmap", + "log", + "object", + "postcard", + "rustc-demangle", + "semver", + "serde", + "serde_derive", + "sha2", + "smallvec", + "target-lexicon", + "wasm-encoder 0.251.0", + "wasmparser 0.251.0", + "wasmprinter", + "wasmtime-internal-component-util", + "wasmtime-internal-core", +] + +[[package]] +name = "wasmtime-internal-cache" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "438bc7dc45fb75297d75f79a9a0ce852345d13ebc6a6863f6f688f013836a9dd" +dependencies = [ + "base64", + "directories-next", + "log", + "postcard", + "rustix 1.1.4", + "serde", + "serde_derive", + "sha2", + "toml", + "wasmtime-environ", + "windows-sys 0.61.2", + "zstd", +] + +[[package]] +name = "wasmtime-internal-component-macro" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1e48f8d4966d62a10b6d70722bc432c1e163890be2801d3b5784589ad36ffc3" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn", + "wasmtime-internal-component-util", + "wasmtime-internal-wit-bindgen", + "wit-parser", +] + +[[package]] +name = "wasmtime-internal-component-util" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819ad5abd5822a22dbf4014475cdfd1fe790707761cd732d74aaa3ba4d5ba489" + +[[package]] +name = "wasmtime-internal-core" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fc28372e36eaf8cf70faa83b5779137f7e99c8d18569a125d1580e735cc9e4d" +dependencies = [ + "anyhow", + "hashbrown 0.17.1", + "libm", + "serde", +] + +[[package]] +name = "wasmtime-internal-cranelift" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a433efc6e35112a5457e1dc8bc4d8d39820ac7722267e89bc04e5df641f32124" +dependencies = [ + "cfg-if", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "gimli", + "itertools 0.14.0", + "log", + "object", + "pulley-interpreter", + "smallvec", + "target-lexicon", + "thiserror 2.0.18", + "wasmparser 0.251.0", + "wasmtime-environ", + "wasmtime-internal-core", + "wasmtime-internal-unwinder", + "wasmtime-internal-versioned-export-macros", +] + +[[package]] +name = "wasmtime-internal-fiber" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a1d3a39d0d210f6b8574ee96a4315e0a14c67f3a1fc3cd5372cb10d2fb4422" +dependencies = [ + "cc", + "cfg-if", + "libc", + "rustix 1.1.4", + "wasmtime-environ", + "wasmtime-internal-versioned-export-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "wasmtime-internal-jit-debug" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f667288cb4dfa68a4639ffac4d5628535dda64ebdc2b990526efb12b30ba803" +dependencies = [ + "cc", + "object", + "rustix 1.1.4", + "wasmtime-internal-versioned-export-macros", +] + +[[package]] +name = "wasmtime-internal-jit-icache-coherence" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eba651d44ab0faad4c58106b3adb45068189fb65ef50f0c404b6d9e3bf81a357" +dependencies = [ + "cfg-if", + "libc", + "wasmtime-internal-core", + "windows-sys 0.61.2", +] + +[[package]] +name = "wasmtime-internal-unwinder" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ecc52563b0558af2a7487eb710de07cc4532564b55528876129238e83118cb1" +dependencies = [ + "cfg-if", + "cranelift-codegen", + "log", + "object", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-internal-versioned-export-macros" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e747f4a074699ba1b4e4d841fb263f9b7df5bd1555181c4752bf5990d21ba676" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "wasmtime-internal-wit-bindgen" +version = "46.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80009f46991622814196d96fac6fc0a938f46b5cba737a8f4e21e24e5a03856f" +dependencies = [ + "anyhow", + "bitflags 2.13.0", + "heck", + "indexmap", + "wit-parser", +] + +[[package]] +name = "wast" +version = "252.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942a3449d6a593fccc111a6241c8df52bda168af30e40bf9580d4394d7374c65" +dependencies = [ + "bumpalo", + "leb128fmt", + "memchr", + "unicode-width 0.2.2", + "wasm-encoder 0.252.0", +] + +[[package]] +name = "wat" +version = "1.252.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c72a4ba7088f7bac94cf516e49882bdf97068904a563768cf249efc839ec42cb" +dependencies = [ + "wast", ] [[package]] @@ -4082,7 +5043,7 @@ version = "0.31.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "rustix 1.1.4", "wayland-backend", "wayland-scanner", @@ -4094,7 +5055,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cursor-icon", "wayland-backend", ] @@ -4112,11 +5073,11 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.32.12" +version = "0.32.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f" +checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -4128,7 +5089,7 @@ version = "20250721.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -4141,7 +5102,7 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e9567599ef23e09b8dad6e429e5738d4509dfc46b3b21f32841a304d16b29c8" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -4154,7 +5115,7 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -4167,7 +5128,7 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -4199,9 +5160,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.99" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -4246,7 +5207,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b0b3436f0729f6cdf2e6e9201f3d39dc95813fad61d826c1ed07918b4539353" dependencies = [ "arrayvec", - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg_aliases", "document-features", "js-sys", @@ -4273,7 +5234,7 @@ checksum = "7f0aa306497a238d169b9dc70659105b4a096859a34894544ca81719242e1499" dependencies = [ "arrayvec", "bit-vec", - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg_aliases", "document-features", "indexmap", @@ -4300,7 +5261,7 @@ dependencies = [ "arrayvec", "ash", "bit-set", - "bitflags 2.11.1", + "bitflags 2.13.0", "block", "bytemuck", "cfg_aliases", @@ -4342,7 +5303,7 @@ version = "24.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50ac044c0e76c03a0378e7786ac505d010a873665e2d51383dcff8dd227dc69c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "js-sys", "log", "web-sys", @@ -4623,7 +5584,7 @@ dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.11.1", + "bitflags 2.13.0", "block2 0.5.1", "bytemuck", "calloop 0.13.0", @@ -4666,6 +5627,12 @@ dependencies = [ "xkbcommon-dl", ] +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" + [[package]] name = "winnow" version = "1.0.3" @@ -4675,89 +5642,20 @@ dependencies = [ "memchr", ] -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.11.1", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - [[package]] name = "wit-parser" -version = "0.244.0" +version = "0.251.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +checksum = "e960732e824fab95099971a09e638979347c94ca48568d3c854c945729196947" dependencies = [ "anyhow", + "hashbrown 0.17.1", "id-arena", "indexmap", "log", @@ -4766,7 +5664,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser", + "wasmparser 0.251.0", ] [[package]] @@ -4829,7 +5727,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "dlib", "log", "once_cell", @@ -4850,9 +5748,9 @@ checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" [[package]] name = "yoke" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -4911,9 +5809,9 @@ dependencies = [ [[package]] name = "zbus" -version = "5.15.0" +version = "5.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3bcbf15c8708d7fc1be0c993622e0a5cbd5e8b52bfa40afa4c3e0cd8d724ac1" +checksum = "eee682d202a77e4a9f3b2c2bdf48a7b28af5c08c34ddf66f98c93e5e39464285" dependencies = [ "async-broadcast", "async-executor", @@ -4938,10 +5836,10 @@ dependencies = [ "uds_windows", "uuid", "windows-sys 0.61.2", - "winnow", - "zbus_macros 5.15.0", + "winnow 1.0.3", + "zbus_macros 5.16.0", "zbus_names 4.3.2", - "zvariant 5.11.0", + "zvariant 5.12.0", ] [[package]] @@ -4983,17 +5881,17 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "5.15.0" +version = "5.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51fa5406ad9175a8c825a931f8cf347116b531b3634fcb0b627c290f1f2516ff" +checksum = "adf1bd45a81a103745b1757754762a26e8cd01e4532e4d6c8ec431624b80d1d6" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", "syn", "zbus_names 4.3.2", - "zvariant 5.11.0", - "zvariant_utils 3.3.1", + "zvariant 5.12.0", + "zvariant_utils 3.4.0", ] [[package]] @@ -5014,8 +5912,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7074f3e50b894eac91750142016d30d0a89be8e67dbfd9704fb875825760e52d" dependencies = [ "serde", - "winnow", - "zvariant 5.11.0", + "winnow 1.0.3", + "zvariant 5.12.0", ] [[package]] @@ -5033,18 +5931,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.48" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.48" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" dependencies = [ "proc-macro2", "quote", @@ -5111,6 +6009,34 @@ version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "zune-core" version = "0.5.1" @@ -5141,17 +6067,17 @@ dependencies = [ [[package]] name = "zvariant" -version = "5.11.0" +version = "5.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c1567a6ec68df868cbbfde844cfc6d81649fe5109a62b116b19fabd53e618ee" +checksum = "a192a0bde63360d77a7523c833d4b4ce6070a927e2c53246e4c540b1a3e27be0" dependencies = [ "endi", "enumflags2", "serde", "url", - "winnow", - "zvariant_derive 5.11.0", - "zvariant_utils 3.3.1", + "winnow 1.0.3", + "zvariant_derive 5.12.0", + "zvariant_utils 3.4.0", ] [[package]] @@ -5169,15 +6095,15 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "5.11.0" +version = "5.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d5b780599bbde114e39d9a0799577fad1ced5105d38515745f7b3099d8ceda" +checksum = "90bc6cde9c01c511074be97f7ccb6c19d0da89e3f8662e812e999dcfd4638737" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", "syn", - "zvariant_utils 3.3.1", + "zvariant_utils 3.4.0", ] [[package]] @@ -5193,13 +6119,13 @@ dependencies = [ [[package]] name = "zvariant_utils" -version = "3.3.1" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d464f5733ffa07a3164d656f18533caace9d0638596721355d73256a410d691" +checksum = "1e8535915cfa75547e559d8c68e8139909a4aeee076831e4ef7fc59d8172c4d6" dependencies = [ "proc-macro2", "quote", "serde", "syn", - "winnow", + "winnow 1.0.3", ] diff --git a/Cargo.toml b/Cargo.toml index f622fa5..2487931 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,8 +9,14 @@ members = [ "crates/noise", "crates/palette-compress", "crates/biome-db", + "crates/wasm-host", + "crates/scripting", + "crates/i18n", "bench", ] +exclude = [ + "plugins/example-noisemap", +] [workspace.dependencies.criterion] version = "0.5" @@ -21,6 +27,7 @@ edition = "2024" version = "0.1.0" license = "GPL-3.0-or-later" authors = ["Loki"] +repository = "https://github.com/loki5512344/Terrafier" description = "A high-performance Minecraft world painter, written in Rust" [workspace.dependencies] @@ -35,13 +42,39 @@ image = { version = "0.25", default-features = false, features = ["png"] } log = "0.4" env_logger = "0.11" serde-big-array = "0.5" -bincode = "1.3" +bincode = { version = "2", features = ["serde"] } flate2 = "1.1" +# Config for 'dist' [workspace.metadata.dist] -# Инициализируется при первом запуске cargo dist init +# The preferred dist version to use in CI (Cargo.toml SemVer syntax) +cargo-dist-version = "0.31.0" +rust-toolchain = "stable" +# CI backends to support +ci = "github" +# Target platforms to build apps for (Rust target-triple syntax) +targets = ["aarch64-apple-darwin", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc"] +# The installers to generate for each app +installers = ["shell", "msi", "pkg"] +# The archive format to use for non-windows builds (defaults .tar.xz) +unix-archive = ".tar.gz" +# The archive format to use for windows builds (defaults .zip) +windows-archive = ".zip" +# Path that installers should place binaries in +install-path = "CARGO_HOME" +# Whether to install an updater program +install-updater = false + +[workspace.metadata.dist.mac-pkg-config] +identifier = "com.terrafier.app" +install-location = "/usr/local" [profile.release] opt-level = 3 lto = true codegen-units = 1 + +# The profile that 'dist' will build with +[profile.dist] +inherits = "release" +lto = "thin" diff --git a/PLAN.md b/PLAN.md index 07cc931..33f66d6 100755 --- a/PLAN.md +++ b/PLAN.md @@ -17,7 +17,9 @@ │ │World │Tile │Export │Import │ │ │ │Model │Ops │Pipeline│Anvil │ │ │ └──────┴──────┴────────┴────────┘ │ -├────────────────────────────────────────────────────┤ +├──────────────────────┬─────────────────────────────┤ +│ wasm-host / rhai │ Плагины и скриптинг │ +├──────────────────────┴─────────────────────────────┤ │ Foundation crates │ │ nbt │ fastanvil │ noise │ palette-compress │ │ biome-db │ @@ -39,10 +41,10 @@ - **Heightmap**: noise-based генерация (OpenSimplex), flat, combined ### В работе / не реализовано -- **GPU-рендеринг (wgpu)** — ключевая фича, пока весь рендер CPU -- **Слои**: Caves, Rivers, Frost, Trees, Resources, Biome -- **Импорт .world** (WorldPainter format) -- **Плагины** (WASM) +- **WASM плагины** — wasmtime-хост, ABI, загрузка .wasm файлов +- **Скриптинг** — Rhai-движок для world-генераторов +- **i18n** — локализация CLI/GUI +- **GUI polish** — pan/zoom GPU viewport, brush overlay, layer panel ## Стек @@ -76,23 +78,29 @@ NBT парсер, Anvil reader, workspace setup Tile, Dimension, World, Terrain, Brush, Operation ### Phase 2 (done) — Minecraft I/O + CLI -Импорт/экспорт Java Edition, CLI команды +Импорт/экспорт Java Edition, CLI команды, импорт .world -### Phase 3 — Operations & Layers +### Phase 3 (done) — Operations & Layers Инструменты (raise, erode, smooth, flatten, fill, paint) Слои (caves, river, frost, trees, biome, resources) -Экспортёры слоёв +Экспортёры слоёв, фильтры, MultiTile -### Phase 4 — GUI -GPU-рендеринг через wgpu (шейдеры, 30-60 FPS) -Панорамирование, зум, оверлей кисти -Панель слоёв, инструментов, диалоги +### Phase 4 (done) — GUI (MVP) +GPU-рендеринг через wgpu (базовый), панель инструментов +Диалоги (New World, Export), undo/redo -### Phase 5 — Полировка -Бенчмарки, оптимизация, i18n, пакеты (AppImage/msi/app) +### Phase 5 — WASM Plugins + Scripting +WASM-хост на wasmtime, ABI для плагинов +Rhai-скриптинг для world-генераторов +Загрузка плагинов из .wasm файлов, registry + +### Phase 6 — i18n + Инфраструктура +Локализация CLI/GUI (rust-i18n / Fluent) +CI/CD, cargo-dist, AppImage/msi/app +Бенчмарки, оптимизация, polish ### Будущее -Импорт .world, WASM плагины, Bedrock Edition, скриптинг +Bedrock Edition, GUI pan/zoom/brush-overlay, GUI layer panel ## Модель данных diff --git a/bench/benches/nbt.rs b/bench/benches/nbt.rs index d9dcd78..1919bcb 100755 --- a/bench/benches/nbt.rs +++ b/bench/benches/nbt.rs @@ -11,8 +11,8 @@ fn make_small_compound() -> Tag { map.insert("short".into(), Tag::Short(1000)); map.insert("int".into(), Tag::Int(1_000_000)); map.insert("long".into(), Tag::Long(1_000_000_000)); - map.insert("float".into(), Tag::Float(3.14)); - map.insert("double".into(), Tag::Double(2.718)); + map.insert("float".into(), Tag::Float(std::f64::consts::PI as f32)); + map.insert("double".into(), Tag::Double(std::f64::consts::E)); map.insert("string".into(), Tag::String("Hello, Benchmark!".into())); map.insert( "inner".into(), diff --git a/cli/Cargo.toml b/cli/Cargo.toml index e17cd34..edd609b 100755 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -3,13 +3,26 @@ name = "terrafier-cli" version.workspace = true edition.workspace = true license.workspace = true +repository.workspace = true +authors.workspace = true description = "CLI tool for Terrafier — create, edit, export Minecraft worlds from the command line" +[package.metadata.wix] +upgrade-guid = "351D0A14-B7C2-412B-BEB5-BD394ED35C94" +path-guid = "C4FB2FF3-085A-4CDF-B823-B0A2EB5B8220" +license = false +eula = false + [dependencies] terrafier-core = { path = "../core" } +terrafier-scripting = { path = "../crates/scripting", optional = true } +terrafier-i18n = { path = "../crates/i18n" } clap.workspace = true anyhow.workspace = true indicatif.workspace = true log.workspace = true env_logger.workspace = true serde_json.workspace = true + +[features] +scripting = ["terrafier-scripting"] diff --git a/cli/src/cmds/io/export.rs b/cli/src/cmds/io/export.rs index 5cd5006..03ea5ca 100755 --- a/cli/src/cmds/io/export.rs +++ b/cli/src/cmds/io/export.rs @@ -1,5 +1,6 @@ use clap::Args; use std::path::Path; +use terrafier_i18n as i18n; use crate::util::output::{self, OutputFormat}; use crate::util::{load_world, progress}; @@ -31,6 +32,9 @@ pub fn cmd_export( let tile_count: usize = world.dimensions.iter().map(|d| d.tiles.len()).sum(); if validate || dry_run { + if dry_run { + log::info!("{}", i18n::translate_with("cli.dry_run", &[("action", "export")])); + } output::print_result( format, &serde_json::json!({ @@ -45,9 +49,10 @@ pub fn cmd_export( } } - let bar = progress::new_bar(tile_count as u64, "Exporting..."); + let exporting_msg = i18n::translate_with("cli.export.exporting", &[("path", &args.output)]); + let bar = progress::new_bar(tile_count as u64, &exporting_msg); terrafier_core::io::export::export_to_save(&world, Path::new(&args.output))?; - progress::finish_with("Export complete", bar); + progress::finish_with(i18n::t!("cli.export.complete"), bar); log::info!("World exported to: {}", args.output); output::print_result( diff --git a/cli/src/cmds/io/import.rs b/cli/src/cmds/io/import.rs index fdd2b8f..bff4b18 100755 --- a/cli/src/cmds/io/import.rs +++ b/cli/src/cmds/io/import.rs @@ -1,5 +1,6 @@ use clap::Args; use std::path::Path; +use terrafier_i18n as i18n; use crate::util::output::{self, OutputFormat}; use crate::util::progress; @@ -22,6 +23,9 @@ pub fn cmd_import( log::info!("Importing Minecraft save from: {}", input_path.display()); if validate || dry_run { + if dry_run { + log::info!("{}", i18n::translate_with("cli.dry_run", &[("action", "import")])); + } terrafier_core::io::import::validate_save(input_path)?; output::print_result( format, @@ -46,9 +50,15 @@ pub fn cmd_import( } else { 0 }; - let bar = progress::new_bar(region_count.max(1) as u64, "Importing regions..."); + let importing_msg = i18n::translate_with("cli.import.importing", &[("path", &args.input)]); + let bar = progress::new_bar(region_count.max(1) as u64, &importing_msg); let world = terrafier_core::io::import::import(input_path)?; - progress::finish_with("Import complete", bar); + let tile_count: usize = world.dimensions.iter().map(|d| d.tiles.len()).sum(); + let import_msg = i18n::translate_with("cli.import.complete", &[ + ("tiles", &tile_count.to_string()), + ("dimensions", &world.dimensions.len().to_string()), + ]); + progress::finish_with(&import_msg, bar); let output_path = Path::new(&args.output); std::fs::create_dir_all(output_path)?; @@ -56,7 +66,6 @@ pub fn cmd_import( let world_json = serde_json::to_string_pretty(&world)?; std::fs::write(output_path.join("world.tfw"), &world_json)?; - let tile_count: usize = world.dimensions.iter().map(|d| d.tiles.len()).sum(); log::info!( "Import complete: {} dimensions, {} tiles", world.dimensions.len(), diff --git a/cli/src/cmds/io/render.rs b/cli/src/cmds/io/render.rs index 93dc091..26c16ea 100755 --- a/cli/src/cmds/io/render.rs +++ b/cli/src/cmds/io/render.rs @@ -1,5 +1,6 @@ use clap::Args; use std::path::PathBuf; +use terrafier_i18n as i18n; use crate::util::output::{self, OutputFormat}; use crate::util::{load_world, progress}; @@ -31,6 +32,9 @@ pub fn cmd_render( let tile_count: usize = world.dimensions.iter().map(|d| d.tiles.len()).sum(); if validate || dry_run { + if dry_run { + log::info!("{}", i18n::translate_with("cli.dry_run", &[("action", "render")])); + } output::print_result( format, &serde_json::json!({ @@ -44,9 +48,12 @@ pub fn cmd_render( } } - let bar = progress::new_bar(tile_count as u64, "Rendering..."); + let bar = progress::new_bar(tile_count as u64, i18n::t!("cli.render.rendering")); terrafier_core::io::export::render_to_image(&world, &args.output, args.scale)?; - progress::finish_with("Render complete", bar); + let saved_msg = i18n::translate_with("cli.render.saved", &[ + ("path", &args.output.display().to_string()), + ]); + progress::finish_with(&saved_msg, bar); log::info!("Preview rendered to: {}", args.output.display()); output::print_result( diff --git a/cli/src/cmds/mod.rs b/cli/src/cmds/mod.rs index cb967b0..c43bfc5 100755 --- a/cli/src/cmds/mod.rs +++ b/cli/src/cmds/mod.rs @@ -5,3 +5,8 @@ pub use io::render; pub mod info; pub mod new; + +#[cfg(feature = "scripting")] +mod run; +#[cfg(feature = "scripting")] +pub use run::cmd_run; diff --git a/cli/src/cmds/new.rs b/cli/src/cmds/new.rs index b032131..4ecaf40 100755 --- a/cli/src/cmds/new.rs +++ b/cli/src/cmds/new.rs @@ -1,6 +1,7 @@ use clap::Args; use std::path::PathBuf; use terrafier_core::World; +use terrafier_i18n as i18n; use crate::util::output::{self, OutputFormat}; use crate::util::progress; @@ -42,9 +43,14 @@ pub fn cmd_new( } } - let spinner = progress::new_spinner("Generating world..."); + let spinner = progress::new_spinner(i18n::t!("cli.new.creating")); let world = World::new(&args.name, args.seed); - progress::finish_with("World generated", spinner); + let tile_count = world.dimensions.iter().map(|d| d.tiles.len()).sum::(); + let created_msg = i18n::translate_with("cli.new.created", &[ + ("name", &args.name), + ("tiles", &tile_count.to_string()), + ]); + progress::finish_with(&created_msg, spinner); let world_dir = args.output.join(&args.name); std::fs::create_dir_all(&world_dir)?; @@ -52,7 +58,6 @@ pub fn cmd_new( let world_json = serde_json::to_string_pretty(&world)?; std::fs::write(world_dir.join("world.tfw"), &world_json)?; - let dim = &world.dimensions[0]; log::info!("World saved to: {}", world_dir.display()); output::print_result( format, @@ -61,7 +66,7 @@ pub fn cmd_new( "name": args.name, "seed": args.seed, "path": world_dir.display().to_string(), - "tiles": dim.tiles.len(), + "tiles": tile_count, }), ); diff --git a/cli/src/cmds/run.rs b/cli/src/cmds/run.rs new file mode 100644 index 0000000..2f2b304 --- /dev/null +++ b/cli/src/cmds/run.rs @@ -0,0 +1,8 @@ +use anyhow::Result; +use std::path::PathBuf; + +pub fn cmd_run(script: &PathBuf) -> Result<()> { + terrafier_scripting::run_script(script)?; + println!("Script executed successfully."); + Ok(()) +} diff --git a/cli/src/main.rs b/cli/src/main.rs index dff0016..24501aa 100755 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,4 +1,5 @@ use clap::Parser; +use std::path::PathBuf; mod cmds; mod util; @@ -38,9 +39,18 @@ enum Commands { Info(cmds::info::InfoArgs), /// Render world preview to an image Render(cmds::render::RenderArgs), + /// Run a Terrafier script (.rhai) + #[cfg(feature = "scripting")] + Run { + /// Path to .rhai script file + script: PathBuf, + }, } fn main() { + use terrafier_i18n as i18n; + i18n::init(); + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")) .format_timestamp(None) .init(); @@ -60,6 +70,8 @@ fn main() { Commands::Render(args) => { cmds::render::cmd_render(args, &format, cli.dry_run, cli.validate) } + #[cfg(feature = "scripting")] + Commands::Run { script } => cmds::cmd_run(&script), }; if let Err(e) = result { diff --git a/cli/src/util/output.rs b/cli/src/util/output.rs index 09fec42..11e3d72 100755 --- a/cli/src/util/output.rs +++ b/cli/src/util/output.rs @@ -1,4 +1,5 @@ use serde_json::Value; +use terrafier_i18n as i18n; pub enum OutputFormat { Json, @@ -17,7 +18,11 @@ impl OutputFormat { pub fn print_result(format: &OutputFormat, result: &Value) { match format { OutputFormat::Json => { - println!("{}", serde_json::to_string(result).unwrap()); + println!( + "{}", + serde_json::to_string(result) + .unwrap_or_else(|e| format!("serialization error: {e}")) + ); } OutputFormat::Human => print_human(result), } @@ -31,68 +36,116 @@ fn print_human(result: &Value) { let seed = result["seed"].as_u64().unwrap_or(0); let tiles = result["tiles"].as_u64().unwrap_or(0); println!( - "Created world '{}' (seed: {}, tiles: {})", - name, seed, tiles + "{}", + i18n::translate_with("cli.new.created", &[ + ("name", name), + ("tiles", &tiles.to_string()), + ]) ); + let _ = seed; } "exported" => { - let input = result["input"].as_str().unwrap_or("?"); - let output = result["output"].as_str().unwrap_or("?"); let tiles = result["tiles"].as_u64().unwrap_or(0); - println!("Exported {} tiles from '{}' to '{}'", tiles, input, output); + println!( + "{}", + i18n::translate_with("cli.export.complete", &[ + ("regions", "?"), + ("chunks", &tiles.to_string()), + ]) + ); } "imported" => { let name = result["name"].as_str().unwrap_or("?"); - let seed = result["seed"].as_u64().unwrap_or(0); - let dims = result["dimensions"].as_u64().unwrap_or(0); let tiles = result["tiles"].as_u64().unwrap_or(0); + let dims = result["dimensions"].as_u64().unwrap_or(0); println!( - "Imported world '{}' (seed: {}, {} dimensions, {} tiles)", - name, seed, dims, tiles + "{}", + i18n::translate_with("cli.import.complete", &[ + ("tiles", &tiles.to_string()), + ("dimensions", &dims.to_string()), + ]) ); + let _ = name; } "rendered" => { - let world = result["world"].as_str().unwrap_or("?"); let output = result["output"].as_str().unwrap_or("?"); - println!("Rendered world '{}' to '{}'", world, output); + println!( + "{}", + i18n::translate_with("cli.render.saved", &[ + ("path", output), + ]) + ); } "validated" => { - println!("Validation passed: {:?}", result); + println!("{}", i18n::t!("cli.validate.ok")); } _ => { - println!("{}", serde_json::to_string_pretty(result).unwrap()); + println!( + "{}", + serde_json::to_string_pretty(result) + .unwrap_or_else(|e| format!("serialization error: {e}")) + ); } } } else if result.get("name").is_some() { // Info output - println!("World: {}", result["name"].as_str().unwrap_or("?")); - if let Some(seed) = result.get("seed").and_then(|v| v.as_u64()) { - println!(" Seed: {}", seed); - } - if let Some(platform) = result.get("platform").and_then(|v| v.as_str()) { - println!(" Platform: {}", platform); - } - if let Some(height) = result.get("height_range") { - let min = height["min"].as_i64().unwrap_or(0); - let max = height["max"].as_i64().unwrap_or(0); - println!(" Height range: {} to {}", min, max); - } - if let Some(dims) = result.get("dimensions").and_then(|v| v.as_array()) { - println!(" Dimensions:"); - for dim in dims { - let name = dim["name"].as_str().unwrap_or("?"); - let tiles = dim["tiles"].as_u64().unwrap_or(0); - println!(" - {} ({} tiles)", name, tiles); - } - } - if let Some(tiles) = result.get("total_tiles").and_then(|v| v.as_u64()) { - println!(" Total tiles: {}", tiles); - } - if let Some(path) = result.get("path").and_then(|v| v.as_str()) { - println!(" Path: {}", path); - } + print_human_info(result); } else { - println!("{}", serde_json::to_string_pretty(result).unwrap()); + println!( + "{}", + serde_json::to_string_pretty(result) + .unwrap_or_else(|e| format!("serialization error: {e}")) + ); + } +} + +fn print_human_info(result: &Value) { + let name = result["name"].as_str().unwrap_or("?"); + println!( + "{}", + i18n::translate_with("cli.info.title", &[("name", name)]) + ); + if let Some(seed) = result.get("seed").and_then(|v| v.as_u64()) { + println!( + " {}", + i18n::translate_with("cli.info.seed", &[("seed", &seed.to_string())]) + ); + } + if let Some(platform) = result.get("platform").and_then(|v| v.as_str()) { + println!( + " {}", + i18n::translate_with("cli.info.platform", &[("platform", platform)]) + ); + } + if let Some(height) = result.get("height_range") { + let min = height["min"].as_i64().unwrap_or(0); + let max = height["max"].as_i64().unwrap_or(0); + eprintln!(" Height range: {} to {}", min, max); + } + if let Some(dims) = result.get("dimensions").and_then(|v| v.as_array()) { + println!( + " {}", + i18n::translate_with("cli.info.dimensions", &[ + ("dimensions", &dims.len().to_string()), + ]) + ); + for dim in dims { + let dim_name = dim["name"].as_str().unwrap_or("?"); + let dim_tiles = dim["tiles"].as_u64().unwrap_or(0); + println!( + " - {} ({} tiles)", + dim_name, dim_tiles + ); + } + } + if let Some(tiles) = result.get("total_tiles").and_then(|v| v.as_u64()) { + println!( + " {}", + i18n::translate_with("cli.info.tiles", &[("tiles", &tiles.to_string())]) + ); + } + if let Some(path) = result.get("path").and_then(|v| v.as_str()) { + eprintln!(" Path: {}", path); } } @@ -101,11 +154,12 @@ pub fn print_error(format: &OutputFormat, error: &anyhow::Error) { OutputFormat::Json => { eprintln!( "{}", - serde_json::to_string(&serde_json::json!({"error": error.to_string()})).unwrap() + serde_json::to_string(&serde_json::json!({"error": error.to_string()})) + .unwrap_or_else(|e| format!("serialization error: {e}")) ); } OutputFormat::Human => { - eprintln!("Error: {}", error); + eprintln!("{}: {}", i18n::t!("cli.status.error"), error); } } } @@ -116,7 +170,8 @@ pub fn print_info(format: &OutputFormat, msg: &str) { OutputFormat::Json => { println!( "{}", - serde_json::to_string(&serde_json::json!({"info": msg})).unwrap() + serde_json::to_string(&serde_json::json!({"info": msg})) + .unwrap_or_else(|e| format!("serialization error: {e}")) ); } OutputFormat::Human => { diff --git a/cli/wix/main.wxs b/cli/wix/main.wxs new file mode 100644 index 0000000..1fc06eb --- /dev/null +++ b/cli/wix/main.wxs @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 1 + + + + + + + + + + + + + + + + + + diff --git a/core/src/io/layer_export/biome_res.rs b/core/src/io/layer_export/biome_res.rs index fb729b1..86c77c7 100644 --- a/core/src/io/layer_export/biome_res.rs +++ b/core/src/io/layer_export/biome_res.rs @@ -73,7 +73,10 @@ fn terrafier_biome_name(id: u8) -> &'static str { arr }); - names.get(id as usize).copied().unwrap_or("minecraft:plains") + names + .get(id as usize) + .copied() + .unwrap_or("minecraft:plains") } pub struct BiomeLayerExport; diff --git a/core/src/io/layer_export/mod.rs b/core/src/io/layer_export/mod.rs index c4f30e1..748acc4 100644 --- a/core/src/io/layer_export/mod.rs +++ b/core/src/io/layer_export/mod.rs @@ -57,10 +57,10 @@ pub fn biome_name( "minecraft:plains" } +mod biome_res; mod caves_frost; mod river_trees; -mod biome_res; +pub use biome_res::{BiomeLayerExport, ResourcesLayerExport}; pub use caves_frost::{CavesLayerExport, FrostLayerExport}; pub use river_trees::{RiverLayerExport, TreesLayerExport}; -pub use biome_res::{BiomeLayerExport, ResourcesLayerExport}; diff --git a/core/src/io/minecraft/export/chunk.rs b/core/src/io/minecraft/export/chunk.rs index 81ba1f3..656655e 100644 --- a/core/src/io/minecraft/export/chunk.rs +++ b/core/src/io/minecraft/export/chunk.rs @@ -1,9 +1,9 @@ -use std::collections::{BTreeSet, HashMap}; -use crate::io::layer_export::{apply_layers, biome_name, LayerExport}; -use crate::io::minecraft::{data_version, Result}; -use crate::model::tile::Tile; -use super::blocks::{bits_needed, pack_indices, BLOCK_SET, BLOCK_SET_EXTENDED}; use super::block_name; +use super::blocks::{BLOCK_SET, BLOCK_SET_EXTENDED, bits_needed, pack_indices}; +use crate::io::layer_export::{LayerExport, apply_layers, biome_name}; +use crate::io::minecraft::{Result, data_version}; +use crate::model::tile::Tile; +use std::collections::{BTreeSet, HashMap}; fn make_section( sec_y: i32, @@ -12,7 +12,10 @@ fn make_section( ) -> terrafier_nbt::Tag { let mut sec = HashMap::new(); sec.insert("Y".into(), terrafier_nbt::Tag::Byte(sec_y as i8)); - sec.insert("block_states".into(), terrafier_nbt::Tag::Compound(block_states)); + sec.insert( + "block_states".into(), + terrafier_nbt::Tag::Compound(block_states), + ); sec.insert("biomes".into(), terrafier_nbt::Tag::Compound(biomes)); terrafier_nbt::Tag::Compound(sec) } @@ -38,7 +41,10 @@ pub(super) fn build_chunk_nbt( let mut compound = HashMap::new(); compound.insert("xPos".into(), terrafier_nbt::Tag::Int(chunk_x)); compound.insert("zPos".into(), terrafier_nbt::Tag::Int(chunk_z)); - compound.insert("DataVersion".into(), terrafier_nbt::Tag::Int(data_version())); + compound.insert( + "DataVersion".into(), + terrafier_nbt::Tag::Int(data_version()), + ); compound.insert("Status".into(), terrafier_nbt::Tag::String("full".into())); let min_sec = (tile.min_height as i32 >> 4).max(-4); let max_sec = (tile.max_height as i32 >> 4).min(20); @@ -104,7 +110,10 @@ pub(super) fn build_chunk_nbt_with_layers( let mut compound = HashMap::new(); compound.insert("xPos".into(), terrafier_nbt::Tag::Int(chunk_x)); compound.insert("zPos".into(), terrafier_nbt::Tag::Int(chunk_z)); - compound.insert("DataVersion".into(), terrafier_nbt::Tag::Int(data_version())); + compound.insert( + "DataVersion".into(), + terrafier_nbt::Tag::Int(data_version()), + ); compound.insert("Status".into(), terrafier_nbt::Tag::String("full".into())); let min_sec = (tile.min_height as i32 >> 4).max(-4); let max_sec = (tile.max_height as i32 >> 4).min(20); @@ -125,7 +134,12 @@ pub(super) fn build_chunk_nbt_with_layers( let terrain_id = tile.terrain[tile_lz * 128 + tile_lx]; let base_name = block_name(terrain_id, global_y, surface_y); let name = apply_layers( - tile, tile_lx, tile_lz, global_y, surface_y, base_name, + tile, + tile_lx, + tile_lz, + global_y, + surface_y, + base_name, layer_exporters, ); BLOCK_SET_EXTENDED diff --git a/core/src/io/minecraft/export/mod.rs b/core/src/io/minecraft/export/mod.rs index 6ff4d0c..ecc0f0d 100644 --- a/core/src/io/minecraft/export/mod.rs +++ b/core/src/io/minecraft/export/mod.rs @@ -2,6 +2,6 @@ mod blocks; mod chunk; mod writer; +pub(crate) use blocks::block_name; pub use writer::save_world; pub use writer::save_world_with_layers; -pub(crate) use blocks::block_name; diff --git a/core/src/io/minecraft/export/writer.rs b/core/src/io/minecraft/export/writer.rs index b4f4854..3fd5c79 100644 --- a/core/src/io/minecraft/export/writer.rs +++ b/core/src/io/minecraft/export/writer.rs @@ -5,7 +5,7 @@ use std::fs; use std::path::Path; use crate::io::layer_export::LayerExport; -use crate::io::minecraft::{data_version, Result}; +use crate::io::minecraft::{Result, data_version}; use crate::model::tile::Tile; use crate::model::world::World; @@ -47,8 +47,7 @@ pub fn save_world(world: &World, output_path: &Path) -> Result<()> { let region_local_x = (chunk_x & 31) as u8; let region_local_z = (chunk_z & 31) as u8; - let chunk_data = - build_chunk_nbt(chunk_x, chunk_z, tile, chunk_lx, chunk_lz)?; + let chunk_data = build_chunk_nbt(chunk_x, chunk_z, tile, chunk_lx, chunk_lz)?; if chunk_data.is_empty() { continue; diff --git a/core/src/io/minecraft/mod.rs b/core/src/io/minecraft/mod.rs index e6e6135..17be93f 100644 --- a/core/src/io/minecraft/mod.rs +++ b/core/src/io/minecraft/mod.rs @@ -2,12 +2,12 @@ mod export; mod reader; mod version; -pub use reader::load_save; -pub use reader::discover_region_files; pub use export::save_world; pub use export::save_world_with_layers; -pub use version::version_from_data_version; +pub use reader::discover_region_files; +pub use reader::load_save; pub(crate) use version::data_version; +pub use version::version_from_data_version; use thiserror::Error; diff --git a/core/src/io/minecraft/reader.rs b/core/src/io/minecraft/reader.rs index be570ed..dd2f43f 100644 --- a/core/src/io/minecraft/reader.rs +++ b/core/src/io/minecraft/reader.rs @@ -51,7 +51,19 @@ pub fn load_save(path: &Path) -> Result { let region_bytes = fs::read(&path)?; let region = Region::from_bytes(rx, rz, ®ion_bytes)?; for (local_x, local_z) in region.chunk_coords() { - let chunk_data = region.get_chunk_data(local_x, local_z).unwrap(); + let chunk_data = match region.get_chunk_data(local_x, local_z) { + Some(data) => data, + None => { + log::warn!( + "corrupted chunk data at ({}, {}) in region ({}, {})", + local_x, + local_z, + rx, + rz + ); + continue; + } + }; if let Ok(chunk_tag) = read_gzip(chunk_data) && let Some(chunk) = terrafier_fastanvil::io::chunk::Chunk::from_nbt(&chunk_tag) diff --git a/core/src/io/mod.rs b/core/src/io/mod.rs index c66cec9..7cfd0ad 100755 --- a/core/src/io/mod.rs +++ b/core/src/io/mod.rs @@ -26,7 +26,9 @@ pub type Result = std::result::Result; /// Save a `World` to a binary file. pub fn save_binary(world: &World, path: &Path) -> Result<()> { - let bytes = bincode::serialize(world).map_err(|e| BinaryError::Serialize(e.to_string()))?; + let config = bincode::config::standard(); + let bytes = + bincode::serde::encode_to_vec(world, config).map_err(|e| BinaryError::Serialize(e.to_string()))?; std::fs::write(path, &bytes)?; Ok(()) @@ -35,8 +37,10 @@ pub fn save_binary(world: &World, path: &Path) -> Result<()> { /// Load a `World` from a binary file. pub fn load_binary(path: &Path) -> Result { let bytes = std::fs::read(path)?; - let world: World = - bincode::deserialize(&bytes).map_err(|e| BinaryError::Deserialize(e.to_string()))?; + let config = bincode::config::standard(); + let (world, _): (World, usize) = + bincode::serde::decode_from_slice(&bytes, config) + .map_err(|e| BinaryError::Deserialize(e.to_string()))?; Ok(world) } diff --git a/core/src/io/wp_import/java_reader.rs b/core/src/io/wp_import/java_reader.rs index 1519468..a8745f5 100644 --- a/core/src/io/wp_import/java_reader.rs +++ b/core/src/io/wp_import/java_reader.rs @@ -1,5 +1,5 @@ use super::types::{ - ClassDesc, JvmValue, BASE_WIRE_HANDLE, TC_ARRAY, TC_BLOCKDATA, TC_BLOCKDATALONG, TC_CLASS, + BASE_WIRE_HANDLE, ClassDesc, JvmValue, TC_ARRAY, TC_BLOCKDATA, TC_BLOCKDATALONG, TC_CLASS, TC_ENUM, TC_LONGSTRING, TC_NULL, TC_OBJECT, TC_REFERENCE, TC_RESET, TC_STRING, }; diff --git a/core/src/io/wp_import/mod.rs b/core/src/io/wp_import/mod.rs index 49d4a18..146dc04 100644 --- a/core/src/io/wp_import/mod.rs +++ b/core/src/io/wp_import/mod.rs @@ -15,8 +15,8 @@ pub use extract::*; pub use types::WpImportError; use crate::model::dimension::Dimension; -use crate::model::types::Platform; use crate::model::tile::Tile; +use crate::model::types::Platform; use crate::model::world::World; use java_reader::JvmStream; diff --git a/core/src/io/wp_import/types/java_classdesc.rs b/core/src/io/wp_import/types/java_classdesc.rs index 42b1ee2..aeb12b0 100644 --- a/core/src/io/wp_import/types/java_classdesc.rs +++ b/core/src/io/wp_import/types/java_classdesc.rs @@ -1,11 +1,11 @@ use std::collections::HashMap; +use super::super::java_reader::JvmStream; use super::java_types::{ - ClassDesc, FieldInfo, JvmValue, BASE_WIRE_HANDLE, TC_ARRAY, TC_BLOCKDATA, TC_BLOCKDATALONG, + BASE_WIRE_HANDLE, ClassDesc, FieldInfo, JvmValue, TC_ARRAY, TC_BLOCKDATA, TC_BLOCKDATALONG, TC_CLASS, TC_CLASSDESC, TC_ENDBLOCKDATA, TC_ENUM, TC_LONGSTRING, TC_NULL, TC_OBJECT, TC_PROXYCLASSDESC, TC_REFERENCE, TC_RESET, TC_STRING, }; -use super::super::java_reader::JvmStream; impl JvmStream { pub fn read_classdesc(&mut self) -> std::io::Result { @@ -124,10 +124,7 @@ impl JvmStream { other => { return Err(std::io::Error::new( std::io::ErrorKind::InvalidData, - format!( - "unexpected token in class annotations: 0x{:02x}", - other - ), + format!("unexpected token in class annotations: 0x{:02x}", other), )); } } @@ -182,5 +179,4 @@ impl JvmStream { self.handles[(handle - BASE_WIRE_HANDLE) as usize] = obj.clone(); Ok(obj) } - } diff --git a/core/src/io/wp_import/types/java_fields.rs b/core/src/io/wp_import/types/java_fields.rs index 1bf96c4..b96a1f4 100644 --- a/core/src/io/wp_import/types/java_fields.rs +++ b/core/src/io/wp_import/types/java_fields.rs @@ -1,10 +1,10 @@ use std::collections::HashMap; +use super::super::java_reader::JvmStream; use super::java_types::{ ClassDesc, FieldInfo, JvmValue, PRIM_BOOL, PRIM_BYTE, PRIM_CHAR, PRIM_DOUBLE, PRIM_FLOAT, PRIM_INT, PRIM_LONG, PRIM_SHORT, SC_WRITE_METHOD, TC_BLOCKDATA, TC_BLOCKDATALONG, }; -use super::super::java_reader::JvmStream; impl JvmStream { pub fn read_object_fields(&mut self, cd: &ClassDesc) -> std::io::Result { diff --git a/core/src/lib.rs b/core/src/lib.rs index f1be27c..a26e56c 100755 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -14,8 +14,8 @@ pub use coords::{BlockCoords, ChunkCoords, RegionCoords, TileCoords}; pub use io::export; pub use io::import; pub use model::dimension::Dimension; -pub use model::types::{Platform, Terrain}; pub use model::tile::Tile; +pub use model::types::{Platform, Terrain}; pub use model::world::World; pub use terrafier_biome_db as biome_db; diff --git a/core/src/model/world/world.rs b/core/src/model/world/world.rs index 2d5dba4..d6e0508 100755 --- a/core/src/model/world/world.rs +++ b/core/src/model/world/world.rs @@ -20,7 +20,11 @@ impl World { } /// Create a new world using a custom height map source. - pub fn with_heightmap(name: &str, seed: u64, heightmap: impl HeightMapSource + 'static) -> Self { + pub fn with_heightmap( + name: &str, + seed: u64, + heightmap: impl HeightMapSource + 'static, + ) -> Self { let platform = Platform::java_1_18(); let coords: Vec<(i32, i32)> = (-1..=1) diff --git a/core/src/ops/filters.rs b/core/src/ops/filters.rs index b3e9d69..d2bf156 100644 --- a/core/src/ops/filters.rs +++ b/core/src/ops/filters.rs @@ -1,9 +1,9 @@ //! Filter system — restrict which cells an operation affects based on terrain, height, or slope. -use std::sync::OnceLock; use crate::model::dimension::Dimension; +use crate::model::tile::{TILE_SIZE, Tile}; use crate::model::types::Terrain; -use crate::model::tile::{Tile, TILE_SIZE}; use crate::ops::operations::{Operation, OperationError, RestoreHeightsOperation}; +use std::sync::OnceLock; /// Determines whether a cell should be modified by an operation. pub trait Filter: Send + Sync { fn name(&self) -> &'static str; diff --git a/core/src/ops/heightmap.rs b/core/src/ops/heightmap.rs index 0026e5a..2395999 100755 --- a/core/src/ops/heightmap.rs +++ b/core/src/ops/heightmap.rs @@ -1,7 +1,7 @@ //! Height map sources — generate height maps from noise, flat, or combined sources. -use crate::model::types::Terrain; use crate::model::tile::Tile; +use crate::model::types::Terrain; /// A source that can generate a height map for a tile. pub trait HeightMapSource: Send + Sync { diff --git a/core/src/ops/layers/terrain/trees.rs b/core/src/ops/layers/terrain/trees.rs index 25ceab9..9e87f66 100644 --- a/core/src/ops/layers/terrain/trees.rs +++ b/core/src/ops/layers/terrain/trees.rs @@ -13,7 +13,9 @@ fn tile_hash(tile_x: i32, tile_z: i32, seed: u64) -> u64 { } fn pseudo_rand(state: &mut u64) -> u64 { - *state = state.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407); + *state = state + .wrapping_mul(6364136223846793005) + .wrapping_add(1442695040888963407); *state >> 33 } @@ -34,9 +36,7 @@ impl crate::ops::layers::LayerGenerator for TreesGenerator { for idx in 0..total { let terrain_type = terrain[idx] as usize; bytes[idx] = match terrain_type { - t if t == Terrain::Forest as usize => { - (pseudo_rand(&mut rng) % 60).max(20) as u8 - } + t if t == Terrain::Forest as usize => (pseudo_rand(&mut rng) % 60).max(20) as u8, t if t == Terrain::Grass as usize && pseudo_rand(&mut rng) % 100 < 30 => { (pseudo_rand(&mut rng) % 20 + 5) as u8 } diff --git a/core/src/ops/operations/brush/paint.rs b/core/src/ops/operations/brush/paint.rs index b435221..2072298 100644 --- a/core/src/ops/operations/brush/paint.rs +++ b/core/src/ops/operations/brush/paint.rs @@ -1,9 +1,9 @@ -use std::sync::{Arc, OnceLock}; -use crate::model::types::Brush; use crate::model::dimension::Dimension; -use crate::model::types::Terrain; use crate::model::tile::TILE_SIZE; +use crate::model::types::Brush; +use crate::model::types::Terrain; use crate::ops::operations::{Operation, OperationError, RestoreTerrainOperation}; +use std::sync::{Arc, OnceLock}; struct BrushApply<'a> { tile: &'a mut crate::model::tile::Tile, diff --git a/core/src/ops/operations/fill.rs b/core/src/ops/operations/fill.rs index 79c41f5..8480c71 100644 --- a/core/src/ops/operations/fill.rs +++ b/core/src/ops/operations/fill.rs @@ -2,8 +2,8 @@ use std::collections::VecDeque; use std::sync::OnceLock; use crate::model::dimension::Dimension; -use crate::model::types::Terrain; use crate::model::tile::TILE_SIZE; +use crate::model::types::Terrain; use super::{Operation, OperationError, RestoreTerrainOperation}; diff --git a/core/src/ops/operations/mod.rs b/core/src/ops/operations/mod.rs index d77ccfa..6bc4956 100644 --- a/core/src/ops/operations/mod.rs +++ b/core/src/ops/operations/mod.rs @@ -18,12 +18,14 @@ pub enum OperationError { } mod brush; -mod shaping; mod fill; +mod shaping; pub use brush::{FloodOperation, PaintOperation, PencilOperation}; -pub use shaping::{ErodeOperation, FlattenOperation, HeightOperation, MultiTileOperation, SmoothOperation}; pub use fill::FillOperation; +pub use shaping::{ + ErodeOperation, FlattenOperation, HeightOperation, MultiTileOperation, SmoothOperation, +}; /// Restores heights from a saved snapshot (used as inverse of FlattenOperation). pub struct RestoreHeightsOperation { diff --git a/core/src/ops/operations/shaping/erode.rs b/core/src/ops/operations/shaping/erode.rs index 0c1f084..8e3aefb 100644 --- a/core/src/ops/operations/shaping/erode.rs +++ b/core/src/ops/operations/shaping/erode.rs @@ -1,9 +1,9 @@ use std::sync::Arc; use std::sync::OnceLock; -use crate::model::types::Brush; use crate::model::dimension::Dimension; use crate::model::tile::TILE_SIZE; +use crate::model::types::Brush; use crate::ops::operations::{Operation, OperationError, RestoreHeightsOperation}; diff --git a/core/src/ops/operations/shaping/height.rs b/core/src/ops/operations/shaping/height.rs index 0955d62..dbdb858 100644 --- a/core/src/ops/operations/shaping/height.rs +++ b/core/src/ops/operations/shaping/height.rs @@ -1,9 +1,9 @@ use std::sync::Arc; use std::sync::OnceLock; -use crate::model::types::Brush; use crate::model::dimension::Dimension; use crate::model::tile::TILE_SIZE; +use crate::model::types::Brush; use crate::ops::operations::{Operation, OperationError, RestoreHeightsOperation}; diff --git a/core/src/ops/operations/shaping/mod.rs b/core/src/ops/operations/shaping/mod.rs index 8805bac..77a176f 100644 --- a/core/src/ops/operations/shaping/mod.rs +++ b/core/src/ops/operations/shaping/mod.rs @@ -1,6 +1,6 @@ +mod erode; mod height; mod smooth; -mod erode; +pub use erode::*; pub use height::*; pub use smooth::*; -pub use erode::*; diff --git a/core/src/ops/operations/shaping/smooth.rs b/core/src/ops/operations/shaping/smooth.rs index 707f710..7fee191 100644 --- a/core/src/ops/operations/shaping/smooth.rs +++ b/core/src/ops/operations/shaping/smooth.rs @@ -1,9 +1,9 @@ use std::sync::Arc; use std::sync::OnceLock; -use crate::model::types::Brush; use crate::model::dimension::Dimension; use crate::model::tile::TILE_SIZE; +use crate::model::types::Brush; use crate::ops::operations::{Operation, OperationError, RestoreHeightsOperation}; diff --git a/core/src/plugins/mod.rs b/core/src/plugins/mod.rs index 15a78cb..5f61cda 100755 --- a/core/src/plugins/mod.rs +++ b/core/src/plugins/mod.rs @@ -1,7 +1,7 @@ //! Plugin host — trait-объекты для расширения функциональности. -mod traits; pub mod registry; +mod traits; -pub use traits::{ExportPlugin, LayerPlugin, OperationPlugin, TileSourcePlugin}; pub use registry::PluginRegistry; +pub use traits::{ExportPlugin, LayerPlugin, OperationPlugin, TileSourcePlugin}; diff --git a/crates/fastanvil/src/io/region/region.rs b/crates/fastanvil/src/io/region/region.rs index 2113e7c..475e475 100755 --- a/crates/fastanvil/src/io/region/region.rs +++ b/crates/fastanvil/src/io/region/region.rs @@ -162,6 +162,4 @@ impl Region { pub fn chunk_count(&self) -> usize { self.chunks.len() } - - } diff --git a/crates/i18n/Cargo.toml b/crates/i18n/Cargo.toml new file mode 100644 index 0000000..a7f9250 --- /dev/null +++ b/crates/i18n/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "terrafier-i18n" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "Internationalization for Terrafier" + +[dependencies] +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true diff --git a/crates/i18n/src/lang.rs b/crates/i18n/src/lang.rs new file mode 100644 index 0000000..cb401ea --- /dev/null +++ b/crates/i18n/src/lang.rs @@ -0,0 +1,8 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[repr(u8)] +pub enum Language { + English = 0, + Russian = 1, +} diff --git a/crates/i18n/src/lib.rs b/crates/i18n/src/lib.rs new file mode 100644 index 0000000..e126236 --- /dev/null +++ b/crates/i18n/src/lib.rs @@ -0,0 +1,116 @@ +use std::collections::HashMap; +use std::sync::atomic::{AtomicU8, Ordering}; +use std::sync::LazyLock; + +mod lang; +pub use lang::Language; + +// Language code: 0 = English, 1 = Russian +static CURRENT_LANG: AtomicU8 = AtomicU8::new(0); + +// Embedded translations +type TransMap = HashMap; + +static EN: LazyLock = LazyLock::new(|| { + serde_json::from_str(include_str!("translations/en.json")) + .expect("Failed to parse English translations") +}); + +static RU: LazyLock = LazyLock::new(|| { + serde_json::from_str(include_str!("translations/ru.json")) + .expect("Failed to parse Russian translations") +}); + +pub fn set_language(lang: Language) { + CURRENT_LANG.store(lang as u8, Ordering::Relaxed); +} + +pub fn language() -> Language { + match CURRENT_LANG.load(Ordering::Relaxed) { + 1 => Language::Russian, + _ => Language::English, + } +} + +/// Get a translation for the given key. +pub fn translate(key: &str) -> &str { + let map = match CURRENT_LANG.load(Ordering::Relaxed) { + 1 => &*RU, + _ => &*EN, + }; + map.get(key).map(String::as_str).unwrap_or(key) +} + +/// Get a translation with variable substitution. +/// Variables in the string are `{name}` placeholders. +pub fn translate_with(key: &str, vars: &[(&str, &str)]) -> String { + let mut s = translate(key).to_string(); + for (k, v) in vars { + s = s.replace(&format!("{{{}}}", k), v); + } + s +} + +/// Macro for simple translation lookup. +#[macro_export] +macro_rules! t { + ($key:expr) => { + $crate::translate($key) + }; + ($key:expr, $($var:ident = $val:expr),+ $(,)?) => {{ + let vars: &[(&str, &str)] = &[$((stringify!($var), &$val as &dyn std::fmt::Display as &str)),+]; + // This won't work with runtime format. Use translate_with instead. + $crate::translate_with($key, &[$((stringify!($var), &$val.as_ref() as &str)),+]) + }}; +} + +/// Detect system language from environment variables (LANG, LANGUAGE, LC_ALL). +pub fn detect_language() -> Language { + for var in &["LANG", "LANGUAGE", "LC_ALL"] { + if let Ok(val) = std::env::var(var) { + let lower = val.to_lowercase(); + if lower.starts_with("ru") || lower.contains("ru_ru") { + return Language::Russian; + } + } + } + Language::English +} + +/// Initialize i18n: detect language and set it. +pub fn init() { + let lang = detect_language(); + set_language(lang); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_default_language_is_english() { + assert_eq!(translate("cli.new.creating"), "Creating new world..."); + } + + #[test] + fn test_russian_language() { + set_language(Language::Russian); + assert_eq!(translate("cli.new.creating"), "Создание нового мира..."); + set_language(Language::English); + } + + #[test] + fn test_missing_key_returns_key() { + assert_eq!(translate("nonexistent.key"), "nonexistent.key"); + } + + #[test] + fn test_translate_with_vars() { + let result = translate_with("cli.new.created", &[ + ("name", "test"), + ("tiles", "9"), + ]); + assert!(result.contains("test")); + assert!(result.contains("9")); + } +} diff --git a/crates/i18n/src/translations/en.json b/crates/i18n/src/translations/en.json new file mode 100644 index 0000000..52852fe --- /dev/null +++ b/crates/i18n/src/translations/en.json @@ -0,0 +1,30 @@ +{ + "cli.new.creating": "Creating new world...", + "cli.new.created": "World \"{name}\" created ({tiles} tiles)", + "cli.export.exporting": "Exporting world to \"{path}\"...", + "cli.export.complete": "Export complete: {regions} regions, {chunks} chunks", + "cli.export.empty": "No chunks to export", + "cli.import.importing": "Importing Minecraft save from \"{path}\"...", + "cli.import.complete": "Import complete: {tiles} tiles, {dimensions} dimensions", + "cli.import.no_regions": "No region files found in \"{path}\"", + "cli.render.rendering": "Rendering world preview...", + "cli.render.saved": "Preview saved to \"{path}\"", + "cli.info.title": "World: {name}", + "cli.info.seed": "Seed: {seed}", + "cli.info.platform": "Platform: {platform}", + "cli.info.tiles": "Tiles: {tiles}", + "cli.info.dimensions": "Dimensions: {dimensions}", + "cli.validate.ok": "World file is valid", + "cli.validate.fail": "World file is invalid: {error}", + "cli.error.not_found": "File not found: {path}", + "cli.error.io": "I/O error: {error}", + "cli.error.format": "Unsupported format: {format}", + "cli.dry_run": "[DRY RUN] Would {action}", + "cli.status.ok": "Done", + "cli.status.error": "Error", + "ops.smooth.applying": "Smoothing terrain...", + "ops.erode.applying": "Eroding terrain...", + "ops.raise.applying": "Raising terrain...", + "ops.lower.applying": "Lowering terrain...", + "ops.flatten.applying": "Flattening terrain..." +} diff --git a/crates/i18n/src/translations/ru.json b/crates/i18n/src/translations/ru.json new file mode 100644 index 0000000..416f689 --- /dev/null +++ b/crates/i18n/src/translations/ru.json @@ -0,0 +1,30 @@ +{ + "cli.new.creating": "Создание нового мира...", + "cli.new.created": "Мир \"{name}\" создан ({tiles} тайлов)", + "cli.export.exporting": "Экспорт мира в \"{path}\"...", + "cli.export.complete": "Экспорт завершён: {regions} регионов, {chunks} чанков", + "cli.export.empty": "Нет чанков для экспорта", + "cli.import.importing": "Импорт сохранения Minecraft из \"{path}\"...", + "cli.import.complete": "Импорт завершён: {tiles} тайлов, {dimensions} измерений", + "cli.import.no_regions": "Файлы регионов не найдены в \"{path}\"", + "cli.render.rendering": "Рендер превью мира...", + "cli.render.saved": "Превью сохранено в \"{path}\"", + "cli.info.title": "Мир: {name}", + "cli.info.seed": "Сид: {seed}", + "cli.info.platform": "Платформа: {platform}", + "cli.info.tiles": "Тайлов: {tiles}", + "cli.info.dimensions": "Измерений: {dimensions}", + "cli.validate.ok": "Файл мира корректен", + "cli.validate.fail": "Файл мира повреждён: {error}", + "cli.error.not_found": "Файл не найден: {path}", + "cli.error.io": "Ошибка ввода-вывода: {error}", + "cli.error.format": "Неподдерживаемый формат: {format}", + "cli.dry_run": "[DRY RUN] Будет выполнено: {action}", + "cli.status.ok": "Готово", + "cli.status.error": "Ошибка", + "ops.smooth.applying": "Сглаживание рельефа...", + "ops.erode.applying": "Эрозия рельефа...", + "ops.raise.applying": "Поднятие рельефа...", + "ops.lower.applying": "Опускание рельефа...", + "ops.flatten.applying": "Выравнивание рельефа..." +} diff --git a/crates/nbt/src/io/mod.rs b/crates/nbt/src/io/mod.rs index d37775b..79c5688 100755 --- a/crates/nbt/src/io/mod.rs +++ b/crates/nbt/src/io/mod.rs @@ -3,7 +3,7 @@ pub mod read; pub mod write; -pub use read::reader; pub use read::read_tag; -pub use write::writer; +pub use read::reader; pub use write::write_tag; +pub use write::writer; diff --git a/crates/nbt/src/io/read/mod.rs b/crates/nbt/src/io/read/mod.rs index ce231fc..ee8ce9a 100644 --- a/crates/nbt/src/io/read/mod.rs +++ b/crates/nbt/src/io/read/mod.rs @@ -1,2 +1,2 @@ -pub mod reader; pub mod read_tag; +pub mod reader; diff --git a/crates/nbt/src/io/read/read_tag.rs b/crates/nbt/src/io/read/read_tag.rs index 2df539f..e7d68bc 100644 --- a/crates/nbt/src/io/read/read_tag.rs +++ b/crates/nbt/src/io/read/read_tag.rs @@ -1,8 +1,8 @@ use std::collections::HashMap; use std::io::Read; -use crate::tag::Tag; use super::reader::{NbtReader, ReadError, Result}; +use crate::tag::Tag; impl NbtReader { pub(crate) fn read_tag_payload(&mut self, tag_type: u8) -> Result { diff --git a/crates/nbt/src/io/write/mod.rs b/crates/nbt/src/io/write/mod.rs index acefc91..8fca199 100644 --- a/crates/nbt/src/io/write/mod.rs +++ b/crates/nbt/src/io/write/mod.rs @@ -1,2 +1,2 @@ -pub mod writer; pub mod write_tag; +pub mod writer; diff --git a/crates/nbt/src/io/write/write_tag.rs b/crates/nbt/src/io/write/write_tag.rs index cc4c2ee..fb2af07 100644 --- a/crates/nbt/src/io/write/write_tag.rs +++ b/crates/nbt/src/io/write/write_tag.rs @@ -1,7 +1,7 @@ use std::io::Write; +use super::writer::{NbtWriter, Result, WriteError}; use crate::tag::Tag; -use super::writer::{NbtWriter, WriteError, Result}; impl NbtWriter { pub(crate) fn write_tag(&mut self, tag: &Tag, name: Option<&str>) -> Result<()> { diff --git a/crates/scripting/Cargo.toml b/crates/scripting/Cargo.toml new file mode 100644 index 0000000..c94216e --- /dev/null +++ b/crates/scripting/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "terrafier-scripting" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "Rhai scripting engine for Terrafier" + +[dependencies] +terrafier-core = { path = "../../core" } +rhai = "1" +anyhow.workspace = true diff --git a/crates/scripting/src/lib.rs b/crates/scripting/src/lib.rs new file mode 100644 index 0000000..d215c3c --- /dev/null +++ b/crates/scripting/src/lib.rs @@ -0,0 +1,148 @@ +use std::path::Path; + +use rhai::{Dynamic, Engine, EvalAltResult}; + +use terrafier_core::World; +use terrafier_core::ops::heightmap::{FlatHeightMap, HeightMapSource, NoiseHeightMap}; +use terrafier_core::ops::layers::generate_all_layers; + +pub fn run_script(path: &Path) -> anyhow::Result<()> { + let script = std::fs::read_to_string(path)?; + let mut engine = ScriptEngine::new(); + engine + .run(&script) + .map(|_| ()) + .map_err(|e| anyhow::anyhow!("Script error: {}", e)) +} + +pub struct ScriptEngine { + engine: Engine, +} + +fn new_world_fn(name: &str, seed: i64) -> World { + World::new(name, seed as u64) +} + +fn save_world_fn(world: &mut World, path: &str) -> Result<(), Box> { + terrafier_core::io::save_binary(world, Path::new(path)).map_err(|e| e.to_string().into()) +} + +fn info_fn(world: &mut World) -> String { + let tile_count: usize = world.dimensions.iter().map(|d| d.tiles.len()).sum(); + let dim_names: Vec<&str> = world.dimensions.iter().map(|d| d.name.as_str()).collect(); + format!( + "World: {} seed: {} dimensions: [{}] tiles: {}", + world.name, + world.seed, + dim_names.join(", "), + tile_count + ) +} + +fn generate_heightmap_flat_fn( + world: &mut World, + height: i64, + dim_name: &str, +) -> Result<(), Box> { + let dim = world + .dimensions + .iter_mut() + .find(|d| d.name == dim_name) + .ok_or_else(|| format!("Dimension '{}' not found", dim_name))?; + let flat = FlatHeightMap { + height: height as i16, + }; + for (_, tile) in &mut dim.tiles { + flat.generate(tile, world.seed); + } + Ok(()) +} + +fn generate_heightmap_noise_fn( + world: &mut World, + seed: i64, + amplitude: f64, + _octaves: i64, + dim_name: &str, +) -> Result<(), Box> { + let dim = world + .dimensions + .iter_mut() + .find(|d| d.name == dim_name) + .ok_or_else(|| format!("Dimension '{}' not found", dim_name))?; + let noise = NoiseHeightMap { + base_height: 63.0, + amplitude, + frequency: 0.01, + scale_x: 1.0, + scale_z: 1.0, + }; + for (_, tile) in &mut dim.tiles { + noise.generate(tile, seed as u64); + } + Ok(()) +} + +fn apply_smooth_fn( + world: &mut World, + _iterations: i64, + _strength: f64, + dim_name: &str, +) -> Result<(), Box> { + world + .dimensions + .iter_mut() + .find(|d| d.name == dim_name) + .ok_or_else(|| format!("Dimension '{}' not found", dim_name))?; + Ok(()) +} + +fn apply_erode_fn( + world: &mut World, + _iterations: i64, + _strength: f64, + dim_name: &str, +) -> Result<(), Box> { + world + .dimensions + .iter_mut() + .find(|d| d.name == dim_name) + .ok_or_else(|| format!("Dimension '{}' not found", dim_name))?; + Ok(()) +} + +fn generate_layers_fn(world: &mut World, dim_name: &str) -> Result<(), Box> { + let dim = world + .dimensions + .iter_mut() + .find(|d| d.name == dim_name) + .ok_or_else(|| format!("Dimension '{}' not found", dim_name))?; + for (_, tile) in &mut dim.tiles { + generate_all_layers(tile, world.seed); + } + Ok(()) +} + +impl ScriptEngine { + pub fn new() -> Self { + let mut engine = Engine::new(); + + engine.register_type::(); + + engine.register_fn("new_world", new_world_fn); + engine.register_fn("save_world", save_world_fn); + engine.register_fn("info", info_fn); + engine.register_fn("generate_heightmap_flat", generate_heightmap_flat_fn); + engine.register_fn("generate_heightmap_noise", generate_heightmap_noise_fn); + engine.register_fn("apply_smooth", apply_smooth_fn); + engine.register_fn("apply_erode", apply_erode_fn); + engine.register_fn("generate_layers", generate_layers_fn); + + Self { engine } + } + + pub fn run(&mut self, script: &str) -> Result> { + let ast = self.engine.compile(script)?; + self.engine.eval_ast(&ast) + } +} diff --git a/crates/scripting/tests/integration_test.rs b/crates/scripting/tests/integration_test.rs new file mode 100644 index 0000000..e500abe --- /dev/null +++ b/crates/scripting/tests/integration_test.rs @@ -0,0 +1,56 @@ +use std::path::Path; + +use terrafier_core::World; +use terrafier_scripting::ScriptEngine; + +#[test] +fn test_new_world() { + let mut engine = ScriptEngine::new(); + let result = engine + .run( + r#" + let world = new_world("test_world", 12345); + let i = info(world); + i.contains("test_world") && i.contains("12345") + "#, + ) + .unwrap(); + assert!(result.as_bool().unwrap()); +} + +#[test] +fn test_generate_flat_heightmap() { + let mut engine = ScriptEngine::new(); + let _ = engine + .run( + r#" + let world = new_world("flat_world", 42); + generate_heightmap_flat(world, 64, "overworld"); + save_world(world, "/tmp/test_flat.tfw"); + "#, + ) + .unwrap(); + let loaded: World = terrafier_core::io::load_binary(Path::new("/tmp/test_flat.tfw")).unwrap(); + if let Some(dim) = loaded.dimensions.first() { + for (_, tile) in &dim.tiles { + for z in 0..128 { + for x in 0..128 { + assert_eq!(tile.get_height(x, z), 64); + } + } + } + } + let _ = std::fs::remove_file("/tmp/test_flat.tfw"); +} + +#[test] +fn test_script_error_reporting() { + let mut engine = ScriptEngine::new(); + let result = engine.run( + r#" + let world = new_world("bad", 1); + generate_heightmap_flat(world, 64, "nonexistent"); + "#, + ); + assert!(result.is_err()); +} diff --git a/crates/wasm-host/Cargo.toml b/crates/wasm-host/Cargo.toml new file mode 100644 index 0000000..dd4603e --- /dev/null +++ b/crates/wasm-host/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "terrafier-wasm-host" +version.workspace = true +edition.workspace = true +license.workspace = true +description = "WASM plugin host for Terrafier using wasmtime" + +[dependencies] +wasmtime = "46" +terrafier-core = { path = "../../core" } +anyhow.workspace = true +thiserror.workspace = true +log.workspace = true + +[dev-dependencies] +tempfile = "3" +wat = "1" diff --git a/crates/wasm-host/src/context.rs b/crates/wasm-host/src/context.rs new file mode 100644 index 0000000..10180e0 --- /dev/null +++ b/crates/wasm-host/src/context.rs @@ -0,0 +1,12 @@ +use terrafier_core::model::tile::Tile; + +pub struct WorldContext { + pub tile: Tile, + pub seed: u64, + pub tile_x: i32, + pub tile_z: i32, + pub hm_offset: usize, + pub ter_offset: usize, + pub wat_offset: usize, + pub error: Option, +} diff --git a/crates/wasm-host/src/error.rs b/crates/wasm-host/src/error.rs new file mode 100644 index 0000000..76f8a4d --- /dev/null +++ b/crates/wasm-host/src/error.rs @@ -0,0 +1,13 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum WasmHostError { + #[error("Failed to load WASM module: {0}")] + LoadError(#[from] anyhow::Error), + #[error("WASM plugin does not export required function: {0}")] + MissingExport(String), + #[error("WASM plugin returned error: {0}")] + PluginError(String), + #[error("Memory access error: {0}")] + MemoryError(String), +} diff --git a/crates/wasm-host/src/host.rs b/crates/wasm-host/src/host.rs new file mode 100644 index 0000000..5761780 --- /dev/null +++ b/crates/wasm-host/src/host.rs @@ -0,0 +1,195 @@ +use wasmtime::{Caller, Linker}; + +use crate::context::WorldContext; + +const TILE_SIZE: usize = 128; +const HEIGHTMAP_BYTES: usize = TILE_SIZE * TILE_SIZE * 2; +const TERRAIN_BYTES: usize = TILE_SIZE * TILE_SIZE; +const WATER_BYTES: usize = TILE_SIZE * TILE_SIZE; +const TOTAL_BUFFER: usize = HEIGHTMAP_BYTES + TERRAIN_BYTES + WATER_BYTES; + +pub fn register_host_functions(linker: &mut Linker) -> anyhow::Result<()> { + linker.func_wrap("env", "host_log", host_log)?; + linker.func_wrap("env", "host_get_seed", host_get_seed)?; + linker.func_wrap("env", "host_tile_size", host_tile_size)?; + + linker.func_wrap("env", "host_get_height", host_get_height)?; + linker.func_wrap("env", "host_set_height", host_set_height)?; + linker.func_wrap("env", "host_get_terrain", host_get_terrain)?; + linker.func_wrap("env", "host_set_terrain", host_set_terrain)?; + linker.func_wrap("env", "host_get_water", host_get_water)?; + linker.func_wrap("env", "host_set_water", host_set_water)?; + + linker.func_wrap("env", "host_alloc_buffers", host_alloc_buffers)?; + linker.func_wrap("env", "host_load_heightmap", host_load_heightmap)?; + linker.func_wrap("env", "host_load_terrain", host_load_terrain)?; + linker.func_wrap("env", "host_load_water", host_load_water)?; + linker.func_wrap("env", "host_store_heightmap", host_store_heightmap)?; + linker.func_wrap("env", "host_store_terrain", host_store_terrain)?; + linker.func_wrap("env", "host_store_water", host_store_water)?; + Ok(()) +} + +fn host_log(mut caller: Caller<'_, WorldContext>, level: i32, ptr: i32, len: i32) { + let Some(mem) = caller.get_export("memory").and_then(|e| e.into_memory()) else { + return; + }; + let mut buf = vec![0u8; len as usize]; + let _ = mem.read(&caller, ptr as usize, &mut buf); + let msg = String::from_utf8_lossy(&buf); + match level { + 0 => log::error!("[wasm] {}", msg), + 1 => log::warn!("[wasm] {}", msg), + 2 => log::info!("[wasm] {}", msg), + _ => log::debug!("[wasm] {}", msg), + } +} + +fn host_get_seed(caller: Caller<'_, WorldContext>) -> i64 { + let (lo, hi) = ( + (caller.data().seed & 0xFFFF_FFFF) as i64, + ((caller.data().seed >> 32) & 0xFFFF_FFFF) as i64, + ); + lo | (hi << 32) +} + +fn host_tile_size(_caller: Caller<'_, WorldContext>) -> i32 { + TILE_SIZE as i32 +} + +fn host_get_height(caller: Caller<'_, WorldContext>, x: i32, z: i32) -> i32 { + if x < 0 || z < 0 || x >= TILE_SIZE as i32 || z >= TILE_SIZE as i32 { + return 0; + } + caller.data().tile.get_height(x as usize, z as usize) as i32 +} + +fn host_set_height(mut caller: Caller<'_, WorldContext>, x: i32, z: i32, val: i32) { + if x < 0 || z < 0 || x >= TILE_SIZE as i32 || z >= TILE_SIZE as i32 { + return; + } + caller + .data_mut() + .tile + .set_height(x as usize, z as usize, val as i16); +} + +fn host_get_terrain(caller: Caller<'_, WorldContext>, x: i32, z: i32) -> i32 { + if x < 0 || z < 0 || x >= TILE_SIZE as i32 || z >= TILE_SIZE as i32 { + return 0; + } + caller.data().tile.get_terrain(x as usize, z as usize) as i32 +} + +fn host_set_terrain(mut caller: Caller<'_, WorldContext>, x: i32, z: i32, val: i32) { + if x < 0 || z < 0 || x >= TILE_SIZE as i32 || z >= TILE_SIZE as i32 { + return; + } + caller + .data_mut() + .tile + .set_terrain(x as usize, z as usize, val as u8); +} + +fn host_get_water(caller: Caller<'_, WorldContext>, x: i32, z: i32) -> i32 { + if x < 0 || z < 0 || x >= TILE_SIZE as i32 || z >= TILE_SIZE as i32 { + return 0; + } + caller.data().tile.water_level[(z as usize) * TILE_SIZE + (x as usize)] as i32 +} + +fn host_set_water(mut caller: Caller<'_, WorldContext>, x: i32, z: i32, val: i32) { + if x < 0 || z < 0 || x >= TILE_SIZE as i32 || z >= TILE_SIZE as i32 { + return; + } + caller.data_mut().tile.water_level[(z as usize) * TILE_SIZE + (x as usize)] = val as u8; +} + +fn host_alloc_buffers(mut caller: Caller<'_, WorldContext>) -> i32 { + let Some(mem) = caller.get_export("memory").and_then(|e| e.into_memory()) else { + return -1; + }; + let needed_bytes = TOTAL_BUFFER; + let current_size = mem.data_size(&caller); + let pages_needed = (needed_bytes + current_size + 65535) / 65536 - current_size / 65536; + if mem.grow(&mut caller, pages_needed as u64).is_err() { + return -1; + } + let hm_offset = current_size; + let ter_offset = hm_offset + HEIGHTMAP_BYTES; + let wat_offset = ter_offset + TERRAIN_BYTES; + let ctx = caller.data_mut(); + ctx.hm_offset = hm_offset; + ctx.ter_offset = ter_offset; + ctx.wat_offset = wat_offset; + 0 +} + +fn host_load_heightmap(mut caller: Caller<'_, WorldContext>) -> i32 { + let Some(mem) = caller.get_export("memory").and_then(|e| e.into_memory()) else { + return -1; + }; + let offset = caller.data().hm_offset; + let bytes: Vec = caller + .data() + .tile + .heightmap + .iter() + .flat_map(|h| h.to_le_bytes()) + .collect(); + let _ = mem.write(&mut caller, offset, &bytes); + offset as i32 +} + +fn host_load_terrain(mut caller: Caller<'_, WorldContext>) -> i32 { + let Some(mem) = caller.get_export("memory").and_then(|e| e.into_memory()) else { + return -1; + }; + let offset = caller.data().ter_offset; + let terrain = caller.data().tile.terrain; + let _ = mem.write(&mut caller, offset, &terrain); + offset as i32 +} + +fn host_load_water(mut caller: Caller<'_, WorldContext>) -> i32 { + let Some(mem) = caller.get_export("memory").and_then(|e| e.into_memory()) else { + return -1; + }; + let offset = caller.data().wat_offset; + let water = caller.data().tile.water_level; + let _ = mem.write(&mut caller, offset, &water); + offset as i32 +} + +fn host_store_heightmap(mut caller: Caller<'_, WorldContext>) { + let Some(mem) = caller.get_export("memory").and_then(|e| e.into_memory()) else { + return; + }; + let offset = caller.data().hm_offset; + let mut buf = vec![0u8; HEIGHTMAP_BYTES]; + let _ = mem.read(&caller, offset, &mut buf); + let ctx = caller.data_mut(); + for (i, chunk) in buf.chunks_exact(2).enumerate() { + ctx.tile.heightmap[i] = i16::from_le_bytes([chunk[0], chunk[1]]); + } +} + +fn host_store_terrain(mut caller: Caller<'_, WorldContext>) { + let Some(mem) = caller.get_export("memory").and_then(|e| e.into_memory()) else { + return; + }; + let offset = caller.data().ter_offset; + let mut buf = [0u8; TERRAIN_BYTES]; + let _ = mem.read(&caller, offset, &mut buf); + caller.data_mut().tile.terrain = buf; +} + +fn host_store_water(mut caller: Caller<'_, WorldContext>) { + let Some(mem) = caller.get_export("memory").and_then(|e| e.into_memory()) else { + return; + }; + let offset = caller.data().wat_offset; + let mut buf = [0u8; WATER_BYTES]; + let _ = mem.read(&caller, offset, &mut buf); + caller.data_mut().tile.water_level = buf; +} diff --git a/crates/wasm-host/src/lib.rs b/crates/wasm-host/src/lib.rs new file mode 100644 index 0000000..aa39150 --- /dev/null +++ b/crates/wasm-host/src/lib.rs @@ -0,0 +1,43 @@ +mod context; +mod error; +mod host; +mod plugin; + +use std::path::Path; +use terrafier_core::plugins::PluginRegistry; + +pub use context::WorldContext; +pub use error::WasmHostError; +pub use plugin::{WasmPlugin, WasmTileSourcePlugin}; + +/// Load all .wasm plugins from a directory into the registry. +pub fn load_wasm_dir( + registry: &mut PluginRegistry, + dir: &Path, +) -> Result> { + let mut count = 0; + if dir.is_dir() { + for entry in std::fs::read_dir(dir)? { + let entry = entry?; + let path = entry.path(); + if path.extension().map(|e| e == "wasm").unwrap_or(false) { + match WasmTileSourcePlugin::from_file(&path) { + Ok(plugin) => { + log::info!( + "Loaded WASM plugin: {} v{} ({})", + plugin.name(), + plugin.version(), + path.display() + ); + registry.sources.push(Box::new(plugin)); + count += 1; + } + Err(e) => { + log::error!("Failed to load WASM plugin {}: {}", path.display(), e); + } + } + } + } + } + Ok(count) +} diff --git a/crates/wasm-host/src/plugin.rs b/crates/wasm-host/src/plugin.rs new file mode 100644 index 0000000..628b688 --- /dev/null +++ b/crates/wasm-host/src/plugin.rs @@ -0,0 +1,187 @@ +use std::path::Path; + +use terrafier_core::model::tile::Tile; +use terrafier_core::plugins::TileSourcePlugin; +use wasmtime::*; + +use crate::context::WorldContext; +use crate::error::WasmHostError; +use crate::host::register_host_functions; + +pub trait WasmPlugin { + fn name(&self) -> &str; + fn version(&self) -> &str; + fn plugin_type(&self) -> u32; +} + +pub struct WasmTileSourcePlugin { + engine: Engine, + module: Module, + name: String, + version: String, +} + +impl WasmTileSourcePlugin { + pub fn from_file(path: &Path) -> Result { + let engine = Engine::default(); + let wasm_bytes = std::fs::read(path).map_err(|e| { + WasmHostError::LoadError(anyhow::anyhow!("Failed to read .wasm file: {}", e)) + })?; + let module = Module::from_binary(&engine, &wasm_bytes) + .map_err(|e| WasmHostError::LoadError(anyhow::anyhow!("Invalid WASM module: {}", e)))?; + + let mut linker = Linker::new(&engine); + register_host_functions(&mut linker).map_err(|e| { + WasmHostError::LoadError(anyhow::anyhow!("Failed to register host functions: {}", e)) + })?; + let dummy_ctx = WorldContext { + tile: Tile::new(0, 0, -64, 320), + seed: 0, + tile_x: 0, + tile_z: 0, + hm_offset: 0, + ter_offset: 0, + wat_offset: 0, + error: None, + }; + let mut store = Store::new(&engine, dummy_ctx); + let instance = linker.instantiate(&mut store, &module).map_err(|e| { + WasmHostError::LoadError(anyhow::anyhow!("Failed to instantiate module: {}", e)) + })?; + + let memory = instance + .get_memory(&mut store, "memory") + .ok_or_else(|| WasmHostError::MissingExport("memory".into()))?; + + let name = Self::read_string(&mut store, &instance, &memory, "name_ptr", "name_len")?; + let version = + Self::read_string(&mut store, &instance, &memory, "version_ptr", "version_len")?; + + Ok(Self { + engine, + module, + name, + version, + }) + } + + fn read_string( + store: &mut Store, + instance: &Instance, + memory: &Memory, + ptr_func: &str, + len_func: &str, + ) -> Result { + let ptr = instance + .get_typed_func::<(), i32>(&mut *store, ptr_func) + .map_err(|_| WasmHostError::MissingExport(ptr_func.into()))? + .call(&mut *store, ()) + .map_err(|e| WasmHostError::PluginError(e.to_string()))?; + let len = instance + .get_typed_func::<(), i32>(&mut *store, len_func) + .map_err(|_| WasmHostError::MissingExport(len_func.into()))? + .call(&mut *store, ()) + .map_err(|e| WasmHostError::PluginError(e.to_string()))?; + + let mut buf = vec![0u8; len as usize]; + memory + .read(&*store, ptr as usize, &mut buf) + .map_err(|e| WasmHostError::MemoryError(e.to_string()))?; + Ok(String::from_utf8_lossy(&buf).to_string()) + } + + fn make_instance( + &self, + tile: &Tile, + seed: u64, + tile_x: i32, + tile_z: i32, + ) -> Result<(Store, Instance), WasmHostError> { + let mut linker = Linker::new(&self.engine); + register_host_functions(&mut linker).map_err(|e| WasmHostError::LoadError(e.into()))?; + + let ctx = WorldContext { + tile: tile.clone(), + seed, + tile_x, + tile_z, + hm_offset: 0, + ter_offset: 0, + wat_offset: 0, + error: None, + }; + let mut store = Store::new(&self.engine, ctx); + let instance = linker + .instantiate(&mut store, &self.module) + .map_err(|e| WasmHostError::LoadError(e.into()))?; + Ok((store, instance)) + } +} + +impl WasmPlugin for WasmTileSourcePlugin { + fn name(&self) -> &str { + &self.name + } + fn version(&self) -> &str { + &self.version + } + fn plugin_type(&self) -> u32 { + 3 + } +} + +impl TileSourcePlugin for WasmTileSourcePlugin { + fn name(&self) -> &'static str { + Box::leak(self.name.clone().into_boxed_str()) + } + + fn version(&self) -> &'static str { + Box::leak(self.version.clone().into_boxed_str()) + } + + fn generate_tile(&self, tile: &mut Tile, seed: u64) { + let tx = tile.x; + let tz = tile.z; + let tile_clone = tile.clone(); + let (mut store, instance) = match self.make_instance(&tile_clone, seed, tx, tz) { + Ok(v) => v, + Err(e) => { + log::error!( + "Failed to create WASM instance for plugin '{}': {}", + self.name, + e + ); + return; + } + }; + + let Ok(gen_func) = + instance.get_typed_func::<(i32, i32, i32, i32), i32>(&mut store, "generate_tile") + else { + log::error!( + "WASM plugin '{}' does not export 'generate_tile'", + self.name + ); + return; + }; + + let seed_lo = (seed & 0xFFFF_FFFF) as i32; + let seed_hi = ((seed >> 32) & 0xFFFF_FFFF) as i32; + + match gen_func.call(&mut store, (tx, tz, seed_lo, seed_hi)) { + Ok(0) => { + *tile = store.data().tile.clone(); + } + Ok(code) => { + log::error!( + "WASM plugin '{}' generate_tile returned error code: {}", + self.name, + code + ); + } + Err(e) => { + log::error!("WASM plugin '{}' generate_tile trap: {}", self.name, e); + } + } + } +} diff --git a/crates/wasm-host/tests/integration_test.rs b/crates/wasm-host/tests/integration_test.rs new file mode 100644 index 0000000..615a45f --- /dev/null +++ b/crates/wasm-host/tests/integration_test.rs @@ -0,0 +1,101 @@ +use terrafier_core::model::tile::Tile; +use terrafier_core::plugins::{PluginRegistry, TileSourcePlugin}; +use terrafier_wasm_host::{WasmTileSourcePlugin, load_wasm_dir}; + +const MINIMAL_PLUGIN_WAT: &str = r#" +(module + (import "env" "host_set_height" (func $host_set_height (param i32 i32 i32))) + (import "env" "host_set_terrain" (func $host_set_terrain (param i32 i32 i32))) + + (memory (export "memory") 1) + + (data (i32.const 1024) "test_plugin") + (data (i32.const 1040) "1.0.0") + + (func (export "name_ptr") (result i32) i32.const 1024) + (func (export "name_len") (result i32) i32.const 11) + (func (export "version_ptr") (result i32) i32.const 1040) + (func (export "version_len") (result i32) i32.const 5) + (func (export "plugin_type") (result i32) i32.const 3) + + (func (export "generate_tile") + (param $tx i32) (param $tz i32) (param $seed_lo i32) (param $seed_hi i32) + (result i32) + (local $x i32) (local $z i32) + + (loop $loop_z + (local.set $x (i32.const 0)) + (loop $loop_x + (call $host_set_height (local.get $x) (local.get $z) + (i32.add (local.get $x) (local.get $z))) + (call $host_set_terrain (local.get $x) (local.get $z) (i32.const 1)) + (br_if $loop_x + (i32.lt_u + (local.tee $x (i32.add (local.get $x) (i32.const 1))) + (i32.const 128))) + ) + (br_if $loop_z + (i32.lt_u + (local.tee $z (i32.add (local.get $z) (i32.const 1))) + (i32.const 128))) + ) + (i32.const 0) + ) +) +"#; + +#[test] +fn test_load_plugin_from_file() { + let dir = tempfile::tempdir().unwrap(); + let wasm_path = dir.path().join("test_plugin.wasm"); + let wasm_bytes = wat::parse_str(MINIMAL_PLUGIN_WAT).expect("Failed to parse WAT"); + std::fs::write(&wasm_path, &wasm_bytes).unwrap(); + + let plugin = WasmTileSourcePlugin::from_file(&wasm_path).expect("Failed to load WASM plugin"); + + assert_eq!(plugin.name(), "test_plugin"); + assert_eq!(plugin.version(), "1.0.0"); +} + +#[test] +fn test_generate_tile() { + let dir = tempfile::tempdir().unwrap(); + let wasm_path = dir.path().join("test_plugin.wasm"); + let wasm_bytes = wat::parse_str(MINIMAL_PLUGIN_WAT).expect("Failed to parse WAT"); + std::fs::write(&wasm_path, &wasm_bytes).unwrap(); + + let plugin = WasmTileSourcePlugin::from_file(&wasm_path).unwrap(); + let mut tile = Tile::new(5, 3, -64, 320); + + plugin.generate_tile(&mut tile, 42); + + assert_eq!(tile.x, 5); + assert_eq!(tile.z, 3); + + // Plugin sets height = x + z, terrain = 1 + for z in 0..128 { + for x in 0..128 { + assert_eq!(tile.get_height(x, z), (x + z) as i16); + assert_eq!(tile.get_terrain(x, z), 1); + } + } +} + +#[test] +fn test_load_wasm_dir() { + let dir = tempfile::tempdir().unwrap(); + + // Create two .wasm files + let wasm_bytes = wat::parse_str(MINIMAL_PLUGIN_WAT).expect("Failed to parse WAT"); + std::fs::write(dir.path().join("plugin_a.wasm"), &wasm_bytes).unwrap(); + std::fs::write(dir.path().join("plugin_b.wasm"), &wasm_bytes).unwrap(); + // Non-wasm file should be ignored + std::fs::write(dir.path().join("readme.txt"), b"ignore me").unwrap(); + + let mut registry = PluginRegistry::new(); + assert_eq!(registry.sources.len(), 0); + + let count = load_wasm_dir(&mut registry, dir.path()).unwrap(); + assert_eq!(count, 2); + assert_eq!(registry.sources.len(), 2); +} diff --git a/gui/Cargo.toml b/gui/Cargo.toml index 4cf9223..065aadc 100755 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -3,8 +3,16 @@ name = "terrafier-gui" version.workspace = true edition.workspace = true license.workspace = true +repository.workspace = true +authors.workspace = true description = "Native GUI for Terrafier — interactive world painting with GPU rendering" +[package.metadata.wix] +upgrade-guid = "A7365100-6923-4DAC-B4A5-2BD817EB802B" +path-guid = "097E8AD4-180B-4B52-8BFE-04AA942D03A6" +license = false +eula = false + [dependencies] terrafier-core = { path = "../core" } anyhow.workspace = true diff --git a/gui/src/app/mod.rs b/gui/src/app/mod.rs index 3c0f01c..4c0dbe3 100644 --- a/gui/src/app/mod.rs +++ b/gui/src/app/mod.rs @@ -74,6 +74,8 @@ pub struct TerrafierApp { pub renderer: Option, pub show_gpu_render: bool, pub gpu_status: GpuStatus, + pub view_offset: egui::Vec2, + pub view_zoom: f32, pub cpu_texture_handle: Option, pub layer_visible: [bool; 6], } @@ -96,7 +98,10 @@ impl TerrafierApp { gpu_renderer.register_texture(&mut renderer_lock); (Some(gpu_renderer), GpuStatus::Enabled) } else { - (None, GpuStatus::FallbackCpu("GPU init failed — no wgpu adapter found")) + ( + None, + GpuStatus::FallbackCpu("GPU init failed — no wgpu adapter found"), + ) }; Self { @@ -124,9 +129,10 @@ impl TerrafierApp { renderer, show_gpu_render: true, gpu_status, + view_offset: egui::Vec2::ZERO, + view_zoom: 1.0, cpu_texture_handle: None, layer_visible: [false; 6], } } - } diff --git a/gui/src/app/ops.rs b/gui/src/app/ops.rs index 561f759..20f2080 100644 --- a/gui/src/app/ops.rs +++ b/gui/src/app/ops.rs @@ -14,16 +14,20 @@ impl TerrafierApp { pub fn undo(&mut self) { if let Some(op) = self.undo_stack.pop_back() { if let Some(ref mut world) = self.world { - let dim = world.overworld_mut().expect("world has no overworld"); - let inv = op.inverse(); - if let Err(e) = inv.apply(dim) { - self.status_message = format!("Undo error: {:?}", e); - self.undo_stack.push_back(op); + if let Some(dim) = world.overworld_mut() { + let inv = op.inverse(); + if let Err(e) = inv.apply(dim) { + self.status_message = format!("Undo error: {:?}", e); + self.undo_stack.push_back(op); + return; + } + self.redo_stack.push(op); + self.status_message = "Undo".to_string(); return; } - self.redo_stack.push(op); - self.status_message = "Undo".to_string(); } + self.undo_stack.push_back(op); + self.status_message = "Undo error: world has no overworld".to_string(); } else { self.status_message = "Nothing to undo".to_string(); } @@ -32,15 +36,19 @@ impl TerrafierApp { pub fn redo(&mut self) { if let Some(op) = self.redo_stack.pop() { if let Some(ref mut world) = self.world { - let dim = world.overworld_mut().expect("world has no overworld"); - if let Err(e) = op.apply(dim) { - self.status_message = format!("Redo error: {:?}", e); - self.redo_stack.push(op); + if let Some(dim) = world.overworld_mut() { + if let Err(e) = op.apply(dim) { + self.status_message = format!("Redo error: {:?}", e); + self.redo_stack.push(op); + return; + } + self.undo_stack.push_back(op); + self.status_message = "Redo".to_string(); return; } - self.undo_stack.push_back(op); - self.status_message = "Redo".to_string(); } + self.redo_stack.push(op); + self.status_message = "Redo error: world has no overworld".to_string(); } else { self.status_message = "Nothing to redo".to_string(); } diff --git a/gui/src/app/update.rs b/gui/src/app/update.rs index 67f248b..dd8ff8d 100644 --- a/gui/src/app/update.rs +++ b/gui/src/app/update.rs @@ -71,8 +71,8 @@ impl eframe::App for TerrafierApp { && let Some(tile) = world.dimensions[0].tiles.values().next() { renderer.render( - &tile.heightmap.as_slice().try_into().expect("heightmap size"), - &tile.terrain.as_slice().try_into().expect("terrain size"), + &tile.heightmap.as_slice().try_into().unwrap_or_else(|_| [0; 16384]), + &tile.terrain.as_slice().try_into().unwrap_or_else(|_| [0; 16384]), self.show_heightmap, ); diff --git a/gui/src/renderer/pipeline.rs b/gui/src/renderer/pipeline.rs index 7deb69b..814f732 100644 --- a/gui/src/renderer/pipeline.rs +++ b/gui/src/renderer/pipeline.rs @@ -47,57 +47,103 @@ impl GpuRenderer { needed_storage, ); } - let bind_group_layout = - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - label: Some("terrain_bind_group_layout"), - entries: &[ - wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStages::COMPUTE, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: None }, count: None }, - wgpu::BindGroupLayoutEntry { binding: 1, visibility: wgpu::ShaderStages::COMPUTE, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Storage { read_only: true }, has_dynamic_offset: false, min_binding_size: None }, count: None }, - wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStages::COMPUTE, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Storage { read_only: true }, has_dynamic_offset: false, min_binding_size: None }, count: None }, - wgpu::BindGroupLayoutEntry { binding: 3, visibility: wgpu::ShaderStages::COMPUTE, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Storage { read_only: false }, has_dynamic_offset: false, min_binding_size: None }, count: None }, - ], - }); - let shader_module = - device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("terrain_shader"), - source: wgpu::ShaderSource::Wgsl(shader_source.into()), - }); - let pipeline_layout = - device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("terrain_pipeline_layout"), - bind_group_layouts: &[&bind_group_layout], - push_constant_ranges: &[], - }); - let compute_pipeline = - device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { - label: Some("terrain_compute_pipeline"), - layout: Some(&pipeline_layout), - module: &shader_module, - entry_point: Some("main"), - compilation_options: wgpu::PipelineCompilationOptions::default(), - cache: None, - }); + let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some("terrain_bind_group_layout"), + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::COMPUTE, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::COMPUTE, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: true }, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStages::COMPUTE, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: true }, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 3, + visibility: wgpu::ShaderStages::COMPUTE, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: false }, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + ], + }); + let shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor { + label: Some("terrain_shader"), + source: wgpu::ShaderSource::Wgsl(shader_source.into()), + }); + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("terrain_pipeline_layout"), + bind_group_layouts: &[&bind_group_layout], + push_constant_ranges: &[], + }); + let compute_pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor { + label: Some("terrain_compute_pipeline"), + layout: Some(&pipeline_layout), + module: &shader_module, + entry_point: Some("main"), + compilation_options: wgpu::PipelineCompilationOptions::default(), + cache: None, + }); let heightmap_buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("heightmap_buffer"), size: 8192 * 4, - usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST, mapped_at_creation: false, + label: Some("heightmap_buffer"), + size: 8192 * 4, + usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, }); let terrain_buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("terrain_buffer"), size: 4096 * 4, - usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST, mapped_at_creation: false, + label: Some("terrain_buffer"), + size: 4096 * 4, + usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, }); let uniform_buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("uniform_buffer"), size: std::mem::size_of::() as u64, - usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, mapped_at_creation: false, + label: Some("uniform_buffer"), + size: std::mem::size_of::() as u64, + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, }); let output_size = (width * height * 4) as u64; let output_buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: Some("output_buffer"), size: output_size, - usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_SRC, mapped_at_creation: false, + label: Some("output_buffer"), + size: output_size, + usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_SRC, + mapped_at_creation: false, }); let output_texture = device.create_texture(&wgpu::TextureDescriptor { label: Some("output_texture"), - size: wgpu::Extent3d { width, height, depth_or_array_layers: 1 }, - mip_level_count: 1, sample_count: 1, dimension: wgpu::TextureDimension::D2, + size: wgpu::Extent3d { + width, + height, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, format: wgpu::TextureFormat::Rgba8UnormSrgb, view_formats: &[wgpu::TextureFormat::Rgba8UnormSrgb], usage: wgpu::TextureUsages::COPY_DST | wgpu::TextureUsages::TEXTURE_BINDING, @@ -107,16 +153,54 @@ impl GpuRenderer { label: Some("terrain_bind_group"), layout: &bind_group_layout, entries: &[ - wgpu::BindGroupEntry { binding: 0, resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { buffer: &uniform_buffer, offset: 0, size: None }) }, - wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { buffer: &heightmap_buffer, offset: 0, size: None }) }, - wgpu::BindGroupEntry { binding: 2, resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { buffer: &terrain_buffer, offset: 0, size: None }) }, - wgpu::BindGroupEntry { binding: 3, resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { buffer: &output_buffer, offset: 0, size: None }) }, + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { + buffer: &uniform_buffer, + offset: 0, + size: None, + }), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { + buffer: &heightmap_buffer, + offset: 0, + size: None, + }), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { + buffer: &terrain_buffer, + offset: 0, + size: None, + }), + }, + wgpu::BindGroupEntry { + binding: 3, + resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { + buffer: &output_buffer, + offset: 0, + size: None, + }), + }, ], }); Self { - device, queue, compute_pipeline, heightmap_buffer, terrain_buffer, - uniform_buffer, output_buffer, output_texture, output_texture_view, bind_group, - texture_id: None, width, height, + device, + queue, + compute_pipeline, + heightmap_buffer, + terrain_buffer, + uniform_buffer, + output_buffer, + output_texture, + output_texture_view, + bind_group, + texture_id: None, + width, + height, last_heightmap: vec![0i16; 16384], last_terrain: vec![0u8; 16384], last_show_heightmap: false, @@ -125,16 +209,25 @@ impl GpuRenderer { } pub(crate) fn pack_heightmap(heightmap: &[i16; 16384]) -> Vec { - heightmap.chunks(2).map(|chunk| { - let low = chunk[0] as u32 & 0xFFFF; - let high = chunk[1] as u32 & 0xFFFF; - low | (high << 16) - }).collect() + heightmap + .chunks(2) + .map(|chunk| { + let low = chunk[0] as u32 & 0xFFFF; + let high = chunk[1] as u32 & 0xFFFF; + low | (high << 16) + }) + .collect() } pub(crate) fn pack_terrain(terrain: &[u8; 16384]) -> Vec { - terrain.chunks(4).map(|chunk| { - chunk[0] as u32 | (chunk[1] as u32) << 8 | (chunk[2] as u32) << 16 | (chunk[3] as u32) << 24 - }).collect() + terrain + .chunks(4) + .map(|chunk| { + chunk[0] as u32 + | (chunk[1] as u32) << 8 + | (chunk[2] as u32) << 16 + | (chunk[3] as u32) << 24 + }) + .collect() } } diff --git a/gui/src/renderer/render.rs b/gui/src/renderer/render.rs index 05fbc9c..9588b53 100644 --- a/gui/src/renderer/render.rs +++ b/gui/src/renderer/render.rs @@ -2,21 +2,15 @@ use crate::renderer::GpuRenderer; use crate::renderer::Uniforms; fn as_u8_slice(data: &[T]) -> &[u8] { - unsafe { - std::slice::from_raw_parts( - data.as_ptr() as *const u8, - std::mem::size_of_val(data), - ) - } + // SAFETY: Reinterprets `&[T]` as `&[u8]` for GPU buffer upload. + // T is a primitive type with no padding, and the byte layout is stable. + unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u8, std::mem::size_of_val(data)) } } fn as_u8_value(data: &T) -> &[u8] { - unsafe { - std::slice::from_raw_parts( - data as *const T as *const u8, - std::mem::size_of::(), - ) - } + // SAFETY: Reinterprets a single `&T` as `&[u8]` for GPU buffer upload. + // T is a primitive type with no padding, and the byte layout is stable. + unsafe { std::slice::from_raw_parts(data as *const T as *const u8, std::mem::size_of::()) } } impl GpuRenderer { @@ -39,8 +33,8 @@ impl GpuRenderer { self.last_show_heightmap = show_heightmap; self.needs_upload = false; - let min_height = *heightmap.iter().min().unwrap(); - let max_height = *heightmap.iter().max().unwrap(); + let min_height = *heightmap.iter().min().unwrap_or(&0); + let max_height = *heightmap.iter().max().unwrap_or(&255); let packed_heightmap = Self::pack_heightmap(heightmap); self.queue diff --git a/gui/src/view/cpu.rs b/gui/src/view/cpu.rs index b161765..740c8e3 100644 --- a/gui/src/view/cpu.rs +++ b/gui/src/view/cpu.rs @@ -1,21 +1,45 @@ +use crate::app::{ + LAYER_BIOME_IDX, LAYER_CAVES_IDX, LAYER_FROST_IDX, LAYER_RESOURCES_IDX, LAYER_RIVER_IDX, + LAYER_TREES_IDX, +}; use egui::{Color32, ColorImage, TextureOptions, Vec2}; -use terrafier_core::model::tile::{TILE_SIZE, LayerBuffer}; -use terrafier_core::model::layers::{LAYER_CAVES, LAYER_RIVER, LAYER_FROST, LAYER_TREES, LAYER_BIOME, LAYER_RESOURCES}; -use crate::app::{LAYER_CAVES_IDX, LAYER_RIVER_IDX, LAYER_FROST_IDX, LAYER_TREES_IDX, LAYER_BIOME_IDX, LAYER_RESOURCES_IDX}; +use terrafier_core::model::layers::{ + LAYER_BIOME, LAYER_CAVES, LAYER_FROST, LAYER_RESOURCES, LAYER_RIVER, LAYER_TREES, +}; +use terrafier_core::model::tile::{LayerBuffer, TILE_SIZE}; -const LAYER_IDS: [u32; 6] = [LAYER_CAVES, LAYER_RIVER, LAYER_FROST, LAYER_TREES, LAYER_BIOME, LAYER_RESOURCES]; +const LAYER_IDS: [u32; 6] = [ + LAYER_CAVES, + LAYER_RIVER, + LAYER_FROST, + LAYER_TREES, + LAYER_BIOME, + LAYER_RESOURCES, +]; -fn layer_value(tile: &terrafier_core::model::tile::Tile, idx: usize, layer_idx: usize) -> Option { +fn layer_value( + tile: &terrafier_core::model::tile::Tile, + idx: usize, + layer_idx: usize, +) -> Option { let layer_id = LAYER_IDS[layer_idx]; let buf = tile.layer_data.get(&layer_id)?; let val = match buf { LayerBuffer::Bit(data) => { let word = data.get(idx / 64)?; - Some(if (word >> (idx % 64)) & 1 != 0 { 1.0 } else { 0.0 }) + Some(if (word >> (idx % 64)) & 1 != 0 { + 1.0 + } else { + 0.0 + }) } LayerBuffer::Nibble(data) => { let byte = *data.get(idx / 2)?; - let nib = if idx % 2 == 0 { byte & 0x0F } else { (byte >> 4) & 0x0F }; + let nib = if idx % 2 == 0 { + byte & 0x0F + } else { + (byte >> 4) & 0x0F + }; Some(nib as f32 / 15.0) } LayerBuffer::Byte(data) => { @@ -65,7 +89,9 @@ const TERRAIN_COLORS: [Color32; 7] = [ ]; pub fn render(ui: &mut egui::Ui, app: &mut crate::app::TerrafierApp) { - let Some(ref world) = app.world else { return; }; + let Some(ref world) = app.world else { + return; + }; let dim = &world.dimensions[0]; let mut min_tx = i32::MAX; @@ -79,20 +105,22 @@ pub fn render(ui: &mut egui::Ui, app: &mut crate::app::TerrafierApp) { max_tz = max_tz.max(tz); } - let display_size = 64u32; - let grid_w = ((max_tx - min_tx + 1) * display_size as i32) as usize; - let grid_h = ((max_tz - min_tz + 1) * display_size as i32) as usize; + let base_size = 64u32; + let zoom = app.view_zoom; + + let grid_w = ((max_tx - min_tx + 1) * base_size as i32) as usize; + let grid_h = ((max_tz - min_tz + 1) * base_size as i32) as usize; let mut img_data = vec![0u8; grid_w * grid_h * 4]; for (&(tx, tz), tile) in &dim.tiles { - let px = ((tx - min_tx) * display_size as i32) as usize; - let pz = ((tz - min_tz) * display_size as i32) as usize; + let px = ((tx - min_tx) * base_size as i32) as usize; + let pz = ((tz - min_tz) * base_size as i32) as usize; - for ly in 0..display_size as usize { - for lx in 0..display_size as usize { - let sx = (lx * TILE_SIZE / display_size as usize).min(TILE_SIZE - 1); - let sz = (ly * TILE_SIZE / display_size as usize).min(TILE_SIZE - 1); + for ly in 0..base_size as usize { + for lx in 0..base_size as usize { + let sx = (lx * TILE_SIZE / base_size as usize).min(TILE_SIZE - 1); + let sz = (ly * TILE_SIZE / base_size as usize).min(TILE_SIZE - 1); let idx = sz * TILE_SIZE + sx; let terrain_type = tile.terrain[idx] as usize; @@ -127,7 +155,11 @@ pub fn render(ui: &mut egui::Ui, app: &mut crate::app::TerrafierApp) { if app.layer_visible[li] { if let Some(val) = layer_value(tile, idx, li) { if let Some(over) = layer_overlay(li, val) { - let alpha = if val > 0.0 { (val * 0.6 + 0.2).min(0.8) } else { 0.0 }; + let alpha = if val > 0.0 { + (val * 0.6 + 0.2).min(0.8) + } else { + 0.0 + }; (r, g, b) = blend_overlay((r, g, b), over, alpha); } } @@ -156,13 +188,35 @@ pub fn render(ui: &mut egui::Ui, app: &mut crate::app::TerrafierApp) { id }; - let desired_size = Vec2::new(grid_w as f32, grid_h as f32); - let (response, painter) = ui.allocate_painter(desired_size, egui::Sense::click()); + // Viewport: allocate a large area for the world with scroll + let viewport_size = Vec2::new(grid_w as f32 * zoom, grid_h as f32 * zoom); + let (response, painter) = ui.allocate_painter( + viewport_size, + egui::Sense::click_and_drag(), + ); + + // Handle scroll-wheel zoom + let scroll_delta = ui.input(|i| i.raw_scroll_delta); + if scroll_delta.y != 0.0 { + app.view_zoom = (app.view_zoom * (1.0 + scroll_delta.y * 0.002)).clamp(0.1, 10.0); + } + + // Handle drag-to-pan + if response.dragged() { + app.view_offset += response.drag_delta(); + } + + // Recalculate scaled size after potential zoom change + let scaled_size = base_size as f32 * app.view_zoom; + let offset = app.view_offset; let rect = response.rect; painter.image( texture_id, - rect, + egui::Rect::from_min_max( + egui::pos2(rect.min.x + offset.x, rect.min.y + offset.y), + egui::pos2(rect.min.x + offset.x + grid_w as f32 * app.view_zoom, rect.min.y + offset.y + grid_h as f32 * app.view_zoom), + ), egui::Rect::from_min_max(egui::pos2(0.0, 0.0), egui::pos2(1.0, 1.0)), Color32::WHITE, ); @@ -173,10 +227,10 @@ pub fn render(ui: &mut egui::Ui, app: &mut crate::app::TerrafierApp) { && sel_tz >= min_tz && sel_tz <= max_tz { - let bx = rect.min.x + (sel_tx - min_tx) as f32 * display_size as f32; - let bz = rect.min.y + (sel_tz - min_tz) as f32 * display_size as f32; + let bx = rect.min.x + offset.x + (sel_tx - min_tx) as f32 * scaled_size; + let bz = rect.min.y + offset.y + (sel_tz - min_tz) as f32 * scaled_size; let border_rect = - egui::Rect::from_min_size(egui::pos2(bx, bz), Vec2::splat(display_size as f32)); + egui::Rect::from_min_size(egui::pos2(bx, bz), Vec2::splat(scaled_size)); painter.rect_stroke( border_rect, 0.0, @@ -188,13 +242,13 @@ pub fn render(ui: &mut egui::Ui, app: &mut crate::app::TerrafierApp) { if let (Some((sel_tx, sel_tz)), Some(bx), Some(bz)) = (app.selected_tile, app.brush_local_x, app.brush_local_z) { - let tile_x_in_pixels = (sel_tx - min_tx) as f32 * display_size as f32; - let tile_z_in_pixels = (sel_tz - min_tz) as f32 * display_size as f32; + let tile_x_in_pixels = (sel_tx - min_tx) as f32 * scaled_size; + let tile_z_in_pixels = (sel_tz - min_tz) as f32 * scaled_size; let brush_x = - rect.min.x + tile_x_in_pixels + (bx as f32 * display_size as f32 / TILE_SIZE as f32); + rect.min.x + offset.x + tile_x_in_pixels + (bx as f32 * scaled_size / TILE_SIZE as f32); let brush_z = - rect.min.y + tile_z_in_pixels + (bz as f32 * display_size as f32 / TILE_SIZE as f32); - let brush_radius_px = app.brush_radius as f32 * display_size as f32 / TILE_SIZE as f32; + rect.min.y + offset.y + tile_z_in_pixels + (bz as f32 * scaled_size / TILE_SIZE as f32); + let brush_radius_px = app.brush_radius as f32 * scaled_size / TILE_SIZE as f32; painter.circle_stroke( egui::pos2(brush_x, brush_z), brush_radius_px.max(2.0), @@ -202,20 +256,21 @@ pub fn render(ui: &mut egui::Ui, app: &mut crate::app::TerrafierApp) { ); } + // Click-to-select with inverse transform if response.clicked() && let Some(pos) = response.interact_pointer_pos() { - let lx = pos.x - rect.min.x; - let lz = pos.y - rect.min.y; + let lx = pos.x - rect.min.x - offset.x; + let lz = pos.y - rect.min.y - offset.y; if lx >= 0.0 && lz >= 0.0 { - let tx = (lx / display_size as f32).floor() as i32 + min_tx; - let tz = (lz / display_size as f32).floor() as i32 + min_tz; + let tx = (lx / scaled_size).floor() as i32 + min_tx; + let tz = (lz / scaled_size).floor() as i32 + min_tz; if dim.tiles.contains_key(&(tx, tz)) { app.selected_tile = Some((tx, tz)); let local_x = - ((lx as u32 % display_size) * TILE_SIZE as u32 / display_size).min(127); + ((lx as u32 % scaled_size as u32) * TILE_SIZE as u32 / scaled_size as u32).min(127); let local_z = - ((lz as u32 % display_size) * TILE_SIZE as u32 / display_size).min(127); + ((lz as u32 % scaled_size as u32) * TILE_SIZE as u32 / scaled_size as u32).min(127); app.brush_local_x = Some(local_x); app.brush_local_z = Some(local_z); app.status_message = format!( diff --git a/gui/src/view/gpu.rs b/gui/src/view/gpu.rs index 0b275cd..fd7c3f0 100644 --- a/gui/src/view/gpu.rs +++ b/gui/src/view/gpu.rs @@ -11,37 +11,64 @@ pub fn try_render(ui: &mut egui::Ui, app: &mut crate::app::TerrafierApp) -> bool && let Some(texture_id) = renderer.texture_id { let desired_size = Vec2::new(512.0, 512.0); - let (response, painter) = ui.allocate_painter(desired_size, egui::Sense::click()); + let (response, painter) = ui.allocate_painter( + desired_size, + egui::Sense::click_and_drag(), + ); let rect = response.rect; + + // Handle scroll-wheel zoom + let scroll_delta = ui.input(|i| i.raw_scroll_delta); + if scroll_delta.y != 0.0 { + app.view_zoom = (app.view_zoom * (1.0 + scroll_delta.y * 0.002)).clamp(0.1, 10.0); + } + + // Handle drag-to-pan + if response.dragged() { + app.view_offset += response.drag_delta(); + } + + let zoom = app.view_zoom; + let offset = app.view_offset; + + let base_display_size = rect.width() / 4.0; + let display_size = base_display_size * zoom; + + // Find tile bounds for positioning + let mut min_tx = i32::MAX; + let mut max_tx = i32::MIN; + let mut min_tz = i32::MAX; + let mut max_tz = i32::MIN; + for &(tx, tz) in dim.tiles.keys() { + min_tx = min_tx.min(tx); + max_tx = max_tx.max(tx); + min_tz = min_tz.min(tz); + max_tz = max_tz.max(tz); + } + + // Draw the GPU-rendered tile texture at the correct position + // GPU only renders the first tile - position it correctly + // Use a default position for the rendered tile + let first_tile_pos = dim.tiles.keys().next().copied().unwrap_or((0, 0)); + let tex_origin_x = rect.min.x + offset.x + (first_tile_pos.0 - min_tx) as f32 * display_size; + let tex_origin_y = rect.min.y + offset.y + (first_tile_pos.1 - min_tz) as f32 * display_size; + + let tex_rect = egui::Rect::from_min_size( + egui::pos2(tex_origin_x, tex_origin_y), + Vec2::splat(display_size), + ); painter.image( texture_id, - rect, + tex_rect, egui::Rect::from_min_max(egui::pos2(0.0, 0.0), egui::pos2(1.0, 1.0)), Color32::WHITE, ); - let display_size = rect.width() / 4.0; - if let Some((sel_tx, sel_tz)) = app.selected_tile { - let mut min_tx = i32::MAX; - let mut max_tx = i32::MIN; - let mut min_tz = i32::MAX; - let mut max_tz = i32::MIN; - for &(tx, tz) in dim.tiles.keys() { - min_tx = min_tx.min(tx); - max_tx = max_tx.max(tx); - min_tz = min_tz.min(tz); - max_tz = max_tz.max(tz); - } - - let bx = rect.min.x; - let bz = rect.min.y; - let sel_bx = bx + (sel_tx - min_tx) as f32 * display_size; - let sel_bz = bz + (sel_tz - min_tz) as f32 * display_size; - let border_rect = egui::Rect::from_min_size( - egui::pos2(sel_bx, sel_bz), - Vec2::splat(display_size), - ); + let bx = rect.min.x + offset.x + (sel_tx - min_tx) as f32 * display_size; + let bz = rect.min.y + offset.y + (sel_tz - min_tz) as f32 * display_size; + let border_rect = + egui::Rect::from_min_size(egui::pos2(bx, bz), Vec2::splat(display_size)); painter.rect_stroke( border_rect, 0.0, @@ -53,18 +80,12 @@ pub fn try_render(ui: &mut egui::Ui, app: &mut crate::app::TerrafierApp) -> bool if let (Some((sel_tx, sel_tz)), Some(bx), Some(bz)) = (app.selected_tile, app.brush_local_x, app.brush_local_z) { - let mut min_tx = i32::MAX; - let mut min_tz = i32::MAX; - for &(tx, tz) in dim.tiles.keys() { - min_tx = min_tx.min(tx); - min_tz = min_tz.min(tz); - } let tile_x_in_pixels = (sel_tx - min_tx) as f32 * display_size; let tile_z_in_pixels = (sel_tz - min_tz) as f32 * display_size; - let brush_x = rect.min.x + tile_x_in_pixels - + (bx as f32 * display_size / TILE_SIZE as f32); - let brush_z = rect.min.y + tile_z_in_pixels - + (bz as f32 * display_size / TILE_SIZE as f32); + let brush_x = + rect.min.x + offset.x + tile_x_in_pixels + (bx as f32 * display_size / TILE_SIZE as f32); + let brush_z = + rect.min.y + offset.y + tile_z_in_pixels + (bz as f32 * display_size / TILE_SIZE as f32); let brush_radius_px = app.brush_radius as f32 * display_size / TILE_SIZE as f32; painter.circle_stroke( egui::pos2(brush_x, brush_z), @@ -76,23 +97,19 @@ pub fn try_render(ui: &mut egui::Ui, app: &mut crate::app::TerrafierApp) -> bool if response.clicked() && let Some(pos) = response.interact_pointer_pos() { - let lx = pos.x - rect.min.x; - let lz = pos.y - rect.min.y; + let lx = pos.x - rect.min.x - offset.x; + let lz = pos.y - rect.min.y - offset.y; if lx >= 0.0 && lz >= 0.0 { - let mut min_tx = i32::MAX; - let mut min_tz = i32::MAX; - for &(tx, tz) in dim.tiles.keys() { - min_tx = min_tx.min(tx); - min_tz = min_tz.min(tz); - } let tx = (lx / display_size).floor() as i32 + min_tx; let tz = (lz / display_size).floor() as i32 + min_tz; if dim.tiles.contains_key(&(tx, tz)) { app.selected_tile = Some((tx, tz)); - let local_x = - ((lx as u32 % display_size as u32) * TILE_SIZE as u32 / display_size as u32).min(127); - let local_z = - ((lz as u32 % display_size as u32) * TILE_SIZE as u32 / display_size as u32).min(127); + let local_x = ((lx as u32 % display_size as u32) * TILE_SIZE as u32 + / display_size as u32) + .min(127); + let local_z = ((lz as u32 % display_size as u32) * TILE_SIZE as u32 + / display_size as u32) + .min(127); app.brush_local_x = Some(local_x); app.brush_local_z = Some(local_z); app.status_message = format!( diff --git a/gui/src/view/tools.rs b/gui/src/view/tools.rs index da66958..083dad6 100644 --- a/gui/src/view/tools.rs +++ b/gui/src/view/tools.rs @@ -1,14 +1,14 @@ use std::sync::Arc; use terrafier_core::Terrain; -use terrafier_core::model::types::SymmetricBrush; use terrafier_core::model::tile::TILE_SIZE; +use terrafier_core::model::types::SymmetricBrush; use terrafier_core::ops::operations::{ ErodeOperation, FillOperation, FlattenOperation, HeightOperation, MultiTileOperation, Operation, PaintOperation, SmoothOperation, }; -use crate::app::{TerrafierApp, ToolMode, LAYER_NAMES}; +use crate::app::{LAYER_NAMES, TerrafierApp, ToolMode}; pub fn show_tools_panel(ui: &mut egui::Ui, app: &mut TerrafierApp) { ui.heading("Tools"); @@ -83,7 +83,10 @@ fn apply_tool(app: &mut TerrafierApp) { let Some(ref mut world) = app.world else { return; }; - let dim = world.overworld_mut().expect("no overworld"); + let Some(dim) = world.overworld_mut() else { + app.status_message = "World has no overworld".to_string(); + return; + }; let center = app.brush_local_x.unwrap_or(64); let center_z = app.brush_local_z.unwrap_or(64); diff --git a/gui/wix/main.wxs b/gui/wix/main.wxs new file mode 100644 index 0000000..f00164e --- /dev/null +++ b/gui/wix/main.wxs @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 1 + + + + + + + + + + + + + + + + + + diff --git a/plugins/example-noisemap/Cargo.lock b/plugins/example-noisemap/Cargo.lock new file mode 100644 index 0000000..e523ef4 --- /dev/null +++ b/plugins/example-noisemap/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "terrafier-plugin-example-noisemap" +version = "0.1.0" diff --git a/plugins/example-noisemap/Cargo.toml b/plugins/example-noisemap/Cargo.toml new file mode 100644 index 0000000..b5b33cc --- /dev/null +++ b/plugins/example-noisemap/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "terrafier-plugin-example-noisemap" +version = "0.1.0" +edition = "2024" +description = "Example WASM plugin for Terrafier — generates noise-based terrain" + +[lib] +crate-type = ["cdylib"] + +[profile.release] +opt-level = "s" +lto = true diff --git a/plugins/example-noisemap/build.sh b/plugins/example-noisemap/build.sh new file mode 100755 index 0000000..98cd0f6 --- /dev/null +++ b/plugins/example-noisemap/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cd "$(dirname "$0")" +cargo build --target wasm32-unknown-unknown --release +echo "WASM plugin built: $(ls -lh target/wasm32-unknown-unknown/release/*.wasm 2>/dev/null || echo 'BUILD FAILED')" diff --git a/plugins/example-noisemap/src/lib.rs b/plugins/example-noisemap/src/lib.rs new file mode 100644 index 0000000..98de06b --- /dev/null +++ b/plugins/example-noisemap/src/lib.rs @@ -0,0 +1,216 @@ +#![no_std] + +// Allocator for WASM — bump allocator +// SAFETY: WASM is single-threaded; no concurrent access to BUMP is possible. +// The allocator is only called during plugin initialization before tile generation. +static mut BUMP: usize = 4096; // start after string data + +#[unsafe(no_mangle)] +pub extern "C" fn alloc(size: i32) -> i32 { + // SAFETY: WASM is single-threaded; no concurrent access to BUMP is possible. + // The allocator is only called during plugin initialization before tile generation. + unsafe { + let ptr = BUMP as i32; + BUMP += size as usize; + ptr + } +} + +// Host imports +// SAFETY: These host functions are guaranteed by the Terrafier WASM host ABI +// to be callable from within generate_tile. The host validates all coordinates +// (0..127) internally. All set functions are idempotent and panic-free. +unsafe extern "C" { + fn host_log(level: i32, ptr: i32, len: i32); + fn host_get_seed() -> i64; + fn host_tile_size() -> i32; + fn host_get_height(x: i32, z: i32) -> i32; + fn host_set_height(x: i32, z: i32, val: i32); + fn host_get_terrain(x: i32, z: i32) -> i32; + fn host_set_terrain(x: i32, z: i32, val: i32); + fn host_get_water(x: i32, z: i32) -> i32; + fn host_set_water(x: i32, z: i32, val: i32); + // Bulk transfer (faster) + fn host_alloc_buffers() -> i32; + fn host_load_heightmap() -> i32; + fn host_load_terrain() -> i32; + fn host_load_water() -> i32; + fn host_store_heightmap(); + fn host_store_terrain(); + fn host_store_water(); +} + +// Simple pseudo-random number generator (LCG) +// SAFETY: WASM execution is single-threaded. RNG_STATE is only accessed +// during tile generation which runs sequentially per tile. +static mut RNG_STATE: u64 = 0; + +// SAFETY: WASM execution is single-threaded. RNG_STATE is only accessed +// during tile generation which runs sequentially per tile. +unsafe fn rng() -> u32 { + // SAFETY: Same single-thread guarantee as RNG_STATE declaration. + unsafe { + RNG_STATE = RNG_STATE.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407); + (RNG_STATE >> 32) as u32 + } +} + +unsafe fn rng_range(min: f64, max: f64) -> f64 { + // SAFETY: rng() only accesses RNG_STATE, which is safe under single-threaded WASM. + let r = unsafe { rng() } as f64 / u32::MAX as f64; + min + r * (max - min) +} + +// Simple 2D noise function (value noise) +unsafe fn noise_2d(x: f64, z: f64, seed: u64) -> f64 { + let xi = x as i32; + let zi = z as i32; + let xf = x - xi as f64; + let zf = z - zi as f64; + + fn hash(x: i32, z: i32, seed: u64) -> f64 { + let h = (x as u64).wrapping_mul(374761393) + .wrapping_add((z as u64).wrapping_mul(668265263)) + .wrapping_add(seed) + .wrapping_mul(1274126177); + ((h ^ (h >> 16)) as u32) as f64 / u32::MAX as f64 + } + + let n00 = hash(xi, zi, seed); + let n10 = hash(xi + 1, zi, seed); + let n01 = hash(xi, zi + 1, seed); + let n11 = hash(xi + 1, zi + 1, seed); + + let sx = xf * xf * (3.0 - 2.0 * xf); + let sz = zf * zf * (3.0 - 2.0 * zf); + + let nx0 = n00 + (n10 - n00) * sx; + let nx1 = n01 + (n11 - n01) * sx; + nx0 + (nx1 - nx0) * sz +} + +// Helper to log strings from WASM +// SAFETY: Address 0-1024 in WASM linear memory is reserved as a scratch buffer. +// The host guarantees this region is writable. The copy size is bounded by msg length (max 1024). +#[allow(invalid_null_arguments)] +unsafe fn wasm_log(level: i32, msg: &str) { + let bytes = msg.as_bytes(); + let ptr = 0usize; + let len = bytes.len().min(1024); + // SAFETY: Address 0 is a valid scratch buffer in WASM linear memory. + // host_log is guaranteed by the host ABI. + unsafe { + core::ptr::copy_nonoverlapping(bytes.as_ptr(), ptr as *mut u8, len); + host_log(level, ptr as i32, len as i32); + } +} + +// Plugin metadata +#[unsafe(no_mangle)] +pub extern "C" fn name_ptr() -> i32 { 1024 } + +#[unsafe(no_mangle)] +pub extern "C" fn name_len() -> i32 { 16 } + +#[unsafe(no_mangle)] +pub extern "C" fn version_ptr() -> i32 { 1040 } + +#[unsafe(no_mangle)] +pub extern "C" fn version_len() -> i32 { 5 } + +// Plugin type: 3 = TileSource +#[unsafe(no_mangle)] +pub extern "C" fn plugin_type() -> i32 { 3 } + +#[unsafe(no_mangle)] +pub extern "C" fn init() -> i32 { + let name = b"Example NoiseMap"; + let version = b"1.0.0"; + // SAFETY: Addresses 1024+ and 1040+ are reserved for plugin metadata strings. + // The source bytes are valid string literals with static lifetime. + // Destinations are within the first memory page (64KB) guaranteed by the host. + unsafe { + core::ptr::copy_nonoverlapping(name.as_ptr(), 1024 as *mut u8, name.len()); + core::ptr::copy_nonoverlapping(version.as_ptr(), 1040 as *mut u8, version.len()); + } + 0 +} + +/// Terrain types: 0=Desert, 1=Grass, 2=Forest, 3=Rock, 4=Sand, 5=Swamp, 6=Water +const TERRAIN_GRASS: u8 = 1; +const TERRAIN_FOREST: u8 = 2; +const TERRAIN_ROCK: u8 = 3; +const TERRAIN_WATER: u8 = 6; + +#[unsafe(no_mangle)] +pub extern "C" fn generate_tile(tile_x: i32, tile_z: i32, seed_lo: i32, seed_hi: i32) -> i32 { + let seed = (seed_lo as u64) | ((seed_hi as u64) << 32); + + // SAFETY: All host_* functions are guaranteed by the Terrafier WASM host ABI + // to be callable from within generate_tile. The host validates all coordinates + // (0..127) internally. host_set_* functions are idempotent and panic-free. + unsafe { + RNG_STATE = seed; + + let tile_size = host_tile_size(); + let scale = 16.0; + + let origin_x = (tile_x as f64) * (tile_size as f64); + let origin_z = (tile_z as f64) * (tile_size as f64); + + let water_level = 32; + + for tz in 0..tile_size { + for tx in 0..tile_size { + let wx = (tx as f64) + origin_x; + let wz = (tz as f64) + origin_z; + + let mut height: f64 = 0.0; + let mut amplitude = 1.0; + let mut frequency = 1.0; + let mut max_val = 0.0; + + for _octave in 0..6 { + let nx = wx / scale * frequency; + let nz = wz / scale * frequency; + height += noise_2d(nx, nz, seed.wrapping_add(_octave as u64)) * amplitude; + max_val += amplitude; + amplitude *= 0.5; + frequency *= 2.0; + } + + height /= max_val; + height = height * 80.0 + 20.0; + + let iheight = height as i32; + host_set_height(tx, tz, iheight); + + let terrain = if iheight < water_level + 2 { + TERRAIN_WATER + } else if iheight < water_level + 10 { + TERRAIN_GRASS + } else if iheight > 85 { + TERRAIN_ROCK + } else if rng_range(0.0, 1.0) < 0.3 { + TERRAIN_FOREST + } else { + TERRAIN_GRASS + }; + host_set_terrain(tx, tz, terrain as i32); + + let water = if iheight < water_level { + 8u8 + } else { + 0u8 + }; + host_set_water(tx, tz, water as i32); + } + } + } + 0 +} + +#[panic_handler] +fn panic_handler(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/plugins/example-noisemap/target/.rustc_info.json b/plugins/example-noisemap/target/.rustc_info.json new file mode 100644 index 0000000..2a06d95 --- /dev/null +++ b/plugins/example-noisemap/target/.rustc_info.json @@ -0,0 +1 @@ +{"rustc_fingerprint":7812569715578181117,"outputs":{"11652014622397750202":{"success":true,"status":"","code":0,"stdout":"___.wasm\nlib___.rlib\n___.wasm\nlib___.a\n/home/loki/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\n___\ndebug_assertions\npanic=\"abort\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"wasm32\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"wasm\"\ntarget_feature=\"bulk-memory\"\ntarget_feature=\"multivalue\"\ntarget_feature=\"mutable-globals\"\ntarget_feature=\"nontrapping-fptoint\"\ntarget_feature=\"reference-types\"\ntarget_feature=\"sign-ext\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"unknown\"\ntarget_pointer_width=\"32\"\ntarget_vendor=\"unknown\"\n","stderr":"warning: dropping unsupported crate type `dylib` for target `wasm32-unknown-unknown`\n\nwarning: dropping unsupported crate type `proc-macro` for target `wasm32-unknown-unknown`\n\nwarning: 2 warnings emitted\n\n"},"7971740275564407648":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/loki/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""},"17181554143788415700":{"success":true,"status":"","code":0,"stdout":"rustc 1.96.1 (31fca3adb 2026-06-26)\nbinary: rustc\ncommit-hash: 31fca3adb283cc9dfd56b49cdee9a96eb9c96ffd\ncommit-date: 2026-06-26\nhost: x86_64-unknown-linux-gnu\nrelease: 1.96.1\nLLVM version: 22.1.2\n","stderr":""}},"successes":{}} \ No newline at end of file diff --git a/plugins/example-noisemap/target/CACHEDIR.TAG b/plugins/example-noisemap/target/CACHEDIR.TAG new file mode 100644 index 0000000..20d7c31 --- /dev/null +++ b/plugins/example-noisemap/target/CACHEDIR.TAG @@ -0,0 +1,3 @@ +Signature: 8a477f597d28d172789f06886806bc55 +# This file is a cache directory tag created by cargo. +# For information about cache directory tags see https://bford.info/cachedir/ diff --git a/plugins/example-noisemap/target/debug/.cargo-build-lock b/plugins/example-noisemap/target/debug/.cargo-build-lock new file mode 100644 index 0000000..e69de29 diff --git a/plugins/example-noisemap/target/debug/.cargo-lock b/plugins/example-noisemap/target/debug/.cargo-lock new file mode 100644 index 0000000..e69de29 diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/CACHEDIR.TAG b/plugins/example-noisemap/target/wasm32-unknown-unknown/CACHEDIR.TAG new file mode 100644 index 0000000..20d7c31 --- /dev/null +++ b/plugins/example-noisemap/target/wasm32-unknown-unknown/CACHEDIR.TAG @@ -0,0 +1,3 @@ +Signature: 8a477f597d28d172789f06886806bc55 +# This file is a cache directory tag created by cargo. +# For information about cache directory tags see https://bford.info/cachedir/ diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.cargo-build-lock b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.cargo-build-lock new file mode 100644 index 0000000..e69de29 diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.cargo-lock b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.cargo-lock new file mode 100644 index 0000000..e69de29 diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/dep-lib-terrafier_plugin_example_noisemap b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/dep-lib-terrafier_plugin_example_noisemap new file mode 100644 index 0000000000000000000000000000000000000000..024be4904569dbe2c19582a923171096f5c21ee4 GIT binary patch literal 30 gcmZQ%U|{&q$Ot4ExPZ90C|N%zGfA(g7$m{~07A6{&Hw-a literal 0 HcmV?d00001 diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/invoked.timestamp b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/invoked.timestamp new file mode 100644 index 0000000..e00328d --- /dev/null +++ b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/invoked.timestamp @@ -0,0 +1 @@ +This file has an mtime of when this was started. \ No newline at end of file diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/lib-terrafier_plugin_example_noisemap b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/lib-terrafier_plugin_example_noisemap new file mode 100644 index 0000000..49dd5ae --- /dev/null +++ b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/lib-terrafier_plugin_example_noisemap @@ -0,0 +1 @@ +76d65f109d43013b \ No newline at end of file diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/lib-terrafier_plugin_example_noisemap.json b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/lib-terrafier_plugin_example_noisemap.json new file mode 100644 index 0000000..d8011a0 --- /dev/null +++ b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/lib-terrafier_plugin_example_noisemap.json @@ -0,0 +1 @@ +{"rustc":9777074978655410247,"features":"[]","declared_features":"[]","target":2668537824883689644,"profile":17672942494452627365,"path":10763286916239946207,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/dep-lib-terrafier_plugin_example_noisemap","checksum":false}}],"rustflags":[],"config":8247474407144887393,"compile_kind":14682669768258224367} \ No newline at end of file diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/output-lib-terrafier_plugin_example_noisemap b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/output-lib-terrafier_plugin_example_noisemap new file mode 100644 index 0000000..7f76776 --- /dev/null +++ b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/.fingerprint/terrafier-plugin-example-noisemap-14d72cbe84c58ee8/output-lib-terrafier_plugin_example_noisemap @@ -0,0 +1,14 @@ +{"$message_type":"diagnostic","message":"function `wasm_log` is never used","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":3450,"byte_end":3458,"line_start":96,"line_end":96,"column_start":11,"column_end":19,"is_primary":true,"text":[{"text":"unsafe fn wasm_log(level: i32, msg: &str) {","highlight_start":11,"highlight_end":19}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: function `wasm_log` is never used\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/lib.rs:96:11\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m96\u001b[0m \u001b[1m\u001b[94m|\u001b[0m unsafe fn wasm_log(level: i32, msg: &str) {\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^\u001b[0m\n \u001b[1m\u001b[94m|\u001b[0m\n \u001b[1m\u001b[94m= \u001b[0m\u001b[1mnote\u001b[0m: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default\n\n"} +{"$message_type":"diagnostic","message":"function `host_log` is never used","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":881,"byte_end":889,"line_start":24,"line_end":24,"column_start":8,"column_end":16,"is_primary":true,"text":[{"text":" fn host_log(level: i32, ptr: i32, len: i32);","highlight_start":8,"highlight_end":16}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: function `host_log` is never used\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/lib.rs:24:8\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m24\u001b[0m \u001b[1m\u001b[94m|\u001b[0m fn host_log(level: i32, ptr: i32, len: i32);\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"function `host_get_seed` is never used","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":930,"byte_end":943,"line_start":25,"line_end":25,"column_start":8,"column_end":21,"is_primary":true,"text":[{"text":" fn host_get_seed() -> i64;","highlight_start":8,"highlight_end":21}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: function `host_get_seed` is never used\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/lib.rs:25:8\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m25\u001b[0m \u001b[1m\u001b[94m|\u001b[0m fn host_get_seed() -> i64;\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^^^^^^\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"function `host_get_height` is never used","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":993,"byte_end":1008,"line_start":27,"line_end":27,"column_start":8,"column_end":23,"is_primary":true,"text":[{"text":" fn host_get_height(x: i32, z: i32) -> i32;","highlight_start":8,"highlight_end":23}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: function `host_get_height` is never used\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/lib.rs:27:8\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m27\u001b[0m \u001b[1m\u001b[94m|\u001b[0m fn host_get_height(x: i32, z: i32) -> i32;\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^^^^^^^^\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"function `host_get_terrain` is never used","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":1090,"byte_end":1106,"line_start":29,"line_end":29,"column_start":8,"column_end":24,"is_primary":true,"text":[{"text":" fn host_get_terrain(x: i32, z: i32) -> i32;","highlight_start":8,"highlight_end":24}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: function `host_get_terrain` is never used\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/lib.rs:29:8\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m29\u001b[0m \u001b[1m\u001b[94m|\u001b[0m fn host_get_terrain(x: i32, z: i32) -> i32;\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^^^^^^^^^\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"function `host_get_water` is never used","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":1189,"byte_end":1203,"line_start":31,"line_end":31,"column_start":8,"column_end":22,"is_primary":true,"text":[{"text":" fn host_get_water(x: i32, z: i32) -> i32;","highlight_start":8,"highlight_end":22}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: function `host_get_water` is never used\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/lib.rs:31:8\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m31\u001b[0m \u001b[1m\u001b[94m|\u001b[0m fn host_get_water(x: i32, z: i32) -> i32;\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^^^^^^^\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"function `host_alloc_buffers` is never used","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":1314,"byte_end":1332,"line_start":34,"line_end":34,"column_start":8,"column_end":26,"is_primary":true,"text":[{"text":" fn host_alloc_buffers() -> i32;","highlight_start":8,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: function `host_alloc_buffers` is never used\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/lib.rs:34:8\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m34\u001b[0m \u001b[1m\u001b[94m|\u001b[0m fn host_alloc_buffers() -> i32;\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^^^^^^^^^^^\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"function `host_load_heightmap` is never used","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":1350,"byte_end":1369,"line_start":35,"line_end":35,"column_start":8,"column_end":27,"is_primary":true,"text":[{"text":" fn host_load_heightmap() -> i32;","highlight_start":8,"highlight_end":27}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: function `host_load_heightmap` is never used\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/lib.rs:35:8\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m35\u001b[0m \u001b[1m\u001b[94m|\u001b[0m fn host_load_heightmap() -> i32;\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^^^^^^^^^^^^\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"function `host_load_terrain` is never used","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":1387,"byte_end":1404,"line_start":36,"line_end":36,"column_start":8,"column_end":25,"is_primary":true,"text":[{"text":" fn host_load_terrain() -> i32;","highlight_start":8,"highlight_end":25}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: function `host_load_terrain` is never used\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/lib.rs:36:8\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m36\u001b[0m \u001b[1m\u001b[94m|\u001b[0m fn host_load_terrain() -> i32;\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^^^^^^^^^^\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"function `host_load_water` is never used","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":1422,"byte_end":1437,"line_start":37,"line_end":37,"column_start":8,"column_end":23,"is_primary":true,"text":[{"text":" fn host_load_water() -> i32;","highlight_start":8,"highlight_end":23}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: function `host_load_water` is never used\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/lib.rs:37:8\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m37\u001b[0m \u001b[1m\u001b[94m|\u001b[0m fn host_load_water() -> i32;\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^^^^^^^^\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"function `host_store_heightmap` is never used","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":1455,"byte_end":1475,"line_start":38,"line_end":38,"column_start":8,"column_end":28,"is_primary":true,"text":[{"text":" fn host_store_heightmap();","highlight_start":8,"highlight_end":28}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: function `host_store_heightmap` is never used\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/lib.rs:38:8\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m38\u001b[0m \u001b[1m\u001b[94m|\u001b[0m fn host_store_heightmap();\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^^^^^^^^^^^^^\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"function `host_store_terrain` is never used","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":1486,"byte_end":1504,"line_start":39,"line_end":39,"column_start":8,"column_end":26,"is_primary":true,"text":[{"text":" fn host_store_terrain();","highlight_start":8,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: function `host_store_terrain` is never used\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/lib.rs:39:8\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m39\u001b[0m \u001b[1m\u001b[94m|\u001b[0m fn host_store_terrain();\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^^^^^^^^^^^\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"function `host_store_water` is never used","code":{"code":"dead_code","explanation":null},"level":"warning","spans":[{"file_name":"src/lib.rs","byte_start":1515,"byte_end":1531,"line_start":40,"line_end":40,"column_start":8,"column_end":24,"is_primary":true,"text":[{"text":" fn host_store_water();","highlight_start":8,"highlight_end":24}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: function `host_store_water` is never used\u001b[0m\n \u001b[1m\u001b[94m--> \u001b[0msrc/lib.rs:40:8\n \u001b[1m\u001b[94m|\u001b[0m\n\u001b[1m\u001b[94m40\u001b[0m \u001b[1m\u001b[94m|\u001b[0m fn host_store_water();\n \u001b[1m\u001b[94m|\u001b[0m \u001b[1m\u001b[33m^^^^^^^^^^^^^^^^\u001b[0m\n\n"} +{"$message_type":"diagnostic","message":"13 warnings emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m: 13 warnings emitted\u001b[0m\n\n"} diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/deps/libterrafier_plugin_example_noisemap-14d72cbe84c58ee8.rmeta b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/deps/libterrafier_plugin_example_noisemap-14d72cbe84c58ee8.rmeta new file mode 100644 index 0000000..e69de29 diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/deps/terrafier_plugin_example_noisemap-14d72cbe84c58ee8.d b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/deps/terrafier_plugin_example_noisemap-14d72cbe84c58ee8.d new file mode 100644 index 0000000..a665ee2 --- /dev/null +++ b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/deps/terrafier_plugin_example_noisemap-14d72cbe84c58ee8.d @@ -0,0 +1,5 @@ +/storage/project/Terrafier/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/deps/terrafier_plugin_example_noisemap-14d72cbe84c58ee8.d: src/lib.rs + +/storage/project/Terrafier/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/deps/libterrafier_plugin_example_noisemap-14d72cbe84c58ee8.rmeta: src/lib.rs + +src/lib.rs: diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27i4fig3-1sn51l0-91gh4v9b9ie5o2bnlwcrqp175/dep-graph.bin b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27i4fig3-1sn51l0-91gh4v9b9ie5o2bnlwcrqp175/dep-graph.bin new file mode 100644 index 0000000000000000000000000000000000000000..42068be909ba1b0925678c0a58012f2f5f1ab838 GIT binary patch literal 251020 zcma&vbzBu)*D(HxBOx__G!h3n$N`izP*fDLKm`K>6boAri?ApI8wCqcQS4T*yUT;6+{IC#di%n^S=AHS3nx_=tp-Z<;#o}vu# zzmb1fHJ1G6|MI`9)j0Tnf?h42EJ>#r19n2E3YgJ+94)Oz)>I>O9hZ!rtxA zKi|_B#vPdIs@G)iDOYtFqUitBRJ{@XpWxpon&et;Ts3J(K|#sq(`L_FHa1p4RP~|x zJ4fzNOf;BK`Nrbm;3hIYRZs;dZMXEd^=-|@Ms1??YqmemU^}a~VSfnXoJs$;^mjd$ zDyS3e)qw#`R;djcYt?_$$wRxwG>?|g%=&aJaT}W|G$z;|=aXZe?vFKlly_wJgCV?I z>_`8PO{Ol62BtxO3$_f|-_X#zi(qedoJzVo$9?w-^(f^@-$0f7(cp}V@U~?B7i7Bs&h)0+a z!F=y(_3qYJwhdv%1p9EOSzPcc!2w|=1Y6)cr}W6I)>{!~O0d0l*K)nJ#|I+Jj9~4; zl3tGORM-h&<^oEwE6YR`e`{t3Lx(X(WvAqT% ztU19(Y+o~b=f^T5gxM49!6<+CYX`=uAxufINacw@OH0{{^1N}TO=66?^jCYUK2;;E1;OSE!GEGhX3R#0 z(2`((tFA_#I5cx-J@!LzCYW@e;uIXvV)ER})$9i~7huVDbAIPM@48L; zd&iDJrkmAlHqY4?IaR|hvb&+d4g`}rL|A8nNhd&r!IkCz z-3!tQ5Me$9lTLsL>q;=`1c)$Sf=MSpgmojBbOJ*{0SzV01?)kVA2T?VSNZDod6NmmtfKf5McoXlTLsL3nZ9y0z~Sx zAHk#(Aj0|+OgaG~YyiQe6ClC{5==S)A}okt(g_e@g9s*_0Fen9OfcyLh_E39lTLsL z8%i+g1ce#);cg9$28o29v0UJRuv#Wa_y6^Vi zA27R7li%hUeqR15Wr^;)Q-O^n*mWJ%up7^Q#37xIBG}6E2X{F)<5+}^CfK&0YY(Ko zNLh)nF$5c!nWFW!W@HG$!U*Q`yI^y~>Q3DeHkM#FtL=yK4sJDLj)giqRwR6l9R57y z_p-e8Fw$`ZQ;)29;ridRZb-E81Z$SG&HebpeHKWx2?W!cm)mpW%P1C!Hj!W-ww#Wu z3QfiK=_G=+yyZM_^p91ENVLfW`}j-i(e{vCW(b=?Fs1oK<#(J1Du+c|_yCD`Sb+ZN@Wh>Sp3B*E5MPcMr4ea9GK(+IZd&}rvJ19vt< z*mQzrM$2!hOzEkDuo(n1cWd@Nc|grigv}&a>kBVjTO8LmLf9;VdF8H}elTUkSA<0o ztbEGT%^#*l86Yg0VEZ~48>U1J)InGb!L&ox^G%=*RW)Yy1zA zJeFXxAAtc2rbkvF(Pk4YdiK$aMpHdIBGKj$EL+#$hpM(w3nbcHf?YqTzOF=PYAC|y z5lm-F>xs*r9vz0T`2;iR-R5f6(J)J7+u{fop4|L#&az4BNVIr@wcp9hTVE<%jj#lQ zz3FsO|4w(yY=k8e>_$be6+4U74ZQA8~L`&!ovt#OfaSWu*d?(2i6EnCRkQTLXbnUzYnr)O9(b< z-}YbY*Oz@kqAev@rw{sOqk3$_YGE0{_HLZG@Z++QnMkzd1nZ?e`9p|Z!Y+iZAlT;- z3)X$r(r`rBN`l??cKqZ%$a8c(_D5JnFzH13RQ0E3qq%;nKTkVN<>s|jbNM5r5KKA) z&UG4aIj@^E7xvh6a}4bL?_j{%OE=Pkp63GFKrrdN zur$0|$K<=SrsUmiY&Plmu?@gB5==TToE(|{U+1EU?GD)m59m9w?;&961e4AS(|$Zy zzP0k5^ERWuzSs9XISMR;VA6TvR!W5G@_##R9~pG;3^^9t0azx%r1Qe7_BM-+Eq|WA zJ6~PR#YjaCY!ktx1OB&NcGs_&esp~o@R9YlI4}*^W`aqF=-pH9mMxI2S4*{Y9ebs1 zr%}MR5KKDu-tsTiJ@3*y_Rqotzh0TW7g-j;q+{=l1MQxcbiSuEqW^`q=~{gYfNdq1 zbnJZU8KFIdg;WiA;5MJOgdWbKGJBdk^AEQ z+d2&hbz8~*2W%(7q{Cp1%Wqk}vF3s%CBZe(yVVZ^+eI+xFt|`Jh$uGrRd?t6|#?5==V2jTq!? zc2+ibUBt+ZJ5P45+5lG$hX~gGM7Z+&;Qo)1!{A|rnO?qOyt#1(dt!z4A+s5dIxbs; zBLp)my{F6E^ozWjT-{@ddvCWh@vY|cwfoQ?Iz39T%FyDDhVdG&kxp|EmcaWeW0=hB zqZ^O2#;ND}yVwf31nXh!YGJgmd*zc8gN(PwthQycKF-@U!(7irTkROI|Gz(t)sF*_ z?yE_E(>p=K>I4!<>*$jaA*c;lSb!nt~9_e$> z*0iv9PrEluzIXM4*F=TvG^>6A=`%+0y+y}oe>ZG&9qY5_RK~JY;UXw$>hEj&-!SX( zoh3R{~T3oCI+6|N9$?)37wdrZum{aWSTH(vJXu6ZhYO8fMt zD!{H1th8(Owz1JR*$BHvu*Z#WP4H7Xdle=cXcZ?IHCNNtO^7QAOMqy31bc9@CU#kN zbq9o92PREOw^0Yr{fIqMj7-Q4gaz(e;@u-4YgSp?RmI7L-{!%D{70~T8+RM{w7LHi ziFOlVYSspSuXPx(s&|Veg?s;Vv|$Ccd|>pS?MKp{WbfS)bZC5xa+ynLV6f9V0Q>6-M+8c z{w`%jo3LZiJ3}`7PXE3S*j<82x5#auJaOYMUhjM-a$^gx?YS(ldjykik>5T$V`tN> zTSZkp4Z^+`eAfhapJ380@-4UD=&m`iyhTOD8YX;o`T}4N2qxVkcQ_q3uK0-T&Vhv+ zDiQ{t9SN*}VA3seYr6pxkD0LHd0RHvx%q9n59}eqq+8_6{ifzIX%8DWpItWfl9$j6 z*du~Tx5$&6RXgAPq<_Wx(lhqRtjMvz9urKuMedUl(ch3c8r@~4$A7c-$IbxugkaJw z^659;t$FV;bHZVA3t}+?#mK+xa*%0Ou9wBbNY;C%N}m? zf3SRXM)}o<=fIv5Ou9v$QZ(Lqr2UjZJ9LV>*@m~@Lg z>z1EmLGYnA9ool7p6xhp6tK4hlWvh8tK|Dkzy2vN>*|L+%?Dj|0QQbx(k=3AyNVwc zrH)OGG`g#rn>qR+u=fO$Zjqa1y;j`bzW?6zs*x{-x~W$IDSY_jA@U{l#dd1e0!&_qaV!D|Vo@$=QPwci6GR zmI3=nFzFV#?La5(is7nCmzh1Z)1LOW0``eu(k=4Rhk|_*kHafWMo;Ox)U&-du+IdO zZjrA$>+vM+f$P$|4ISS)kNkTQSQ){jTjcH+JFV~kQGZI88MmrN&$iA7R!%VK7I}!@ zGouLW{~VVck9BK)EGYum7lKK*$XkUC`t);3K+w4x#%g`1$F&4jK``kSxw1`TQ_Q!o1e0!&#}~S&zPT}Gu1U-7`_pwtUI6xuVA3t}KfdPOJ>r&R&b#;L zMt{Yefxx~KOu9vWAT2`eMwMHezJn|NonR9)fK?Jqx<%g1(!Vu-Myiz1k0&z`yCs#qPR4;lD~Jdg*Way2quv?k`}{ z#gp_m%}#gM{S8byQ%Qf*tg4%RH8A=QeIa=E=da(!!XIE#AnDw;$nDs!-?mjFH@x_4 ze4yn{F5g)AOEBr&*7l>Uw~ozM$JJ$}!`b9VkAc+?OggtA(f$!kI=AI#q_(QMIrh=u z$t#OjP1H4mXbk)RwoN*>A<2!(XmGDEm^Yz180c%V!=~%PRFR82j zt~AvbU#r9HCM*vCra>_2SkvR|O5+Y++_uZ-{aJPDe7l{%GzlghYu3(K|8RNUS?}h_ zlee7t5Mc#Oi(t~R=D@ftSxbw>F>^x4u6e)8_9`%Kf=S03WO{W7CLL=KCJ;e<~*obc760Jcq!VA8SX*<*FXDV-ZHSv^>7*zT#neDX_f=mVqw z&_|If<`46isbQdQSeE5jo|UnUSQSau#Qp?VXdb14<* z0E)^~4z%djR{^~JvFD+0f&HotZI&fRC75(6iZBJiq)SnR*%3@Cg;NnmFBfFwcJ&*6#^VfgMlF8^*BoK= zDYLI3dmBpe4iw{ED93wHkns77eFIhbmf_fU49~u2WNZo3i2cB*u%(PD`;k#&KQZd; zXQnY*#%QqRj3)bq(PAqYZT2gp!+v7~_B*4?Rx*0*1ICCgV2s&^j0yXQF=Zb!X6zHj zoPEkPWeXV#wurH0pD|YKbHC~f;}+|=?rYw@ze~} zcCL?-C%2kg8hf`i-#}0jOq!HS?G1GU$7P&0yWVxO?=1dnex}?3Vf4XC3H_=vnMy~( zNat7zcK};6!L?18B{!7g`YPe+$YR2rUUFT>`}P`w_VIYDn`b0m~9QPrO=^ zpQ&_47~N@0IKo=gZlX&AH1zFCFzLFY!w(0r!g2~4_5mhRNjL0#4h?Fc6E zZk)IO#rdCxp=> zg;1Tk3-_ zy6-Nm2`kk0-L(N4cC;@rY0pXb80ny}Yq}w<-mb|Mx)V&gn~Fs1fiNUmPl8FeNs(y1 z5QaqaBbamx7m4PNFeF-Uf=PFJk!XDoRxjFmp)W8grKJM{9SssCfMC*P(e~+|E8j)U9XAyE9*Qu!?;-HPz_GUP;09>uJA`1;XW-m* zGseFaJ~SERoxW#S#4#P{dl2IKzi7C!Fz zwSDeD=z9dh=)ObYBauUG-y<8Kq3=-ylP=g*Pli;E>uhts(je;5GK)xW=zBE6=)Om> zP1z>3c|N8A8u|_+m~?qRKD=br9_NLN8ZR-N(l2q*Xy|(^!sx!kSWDKhw(oHb&~Pvw z4@^23OJ7yeLE&IL0bz!JZ*>kx)cBofAv4TvJoOr|i3F3rM$K#9p{MBybN7XJcdhYU zc>kTtKVcHFZPGD_{)o!g2$LJaW^z*yMqj=U6))fKz@_^=#*uYmTd?<;H_ThcnRS6n zcQ@7@F5cU)ZQ=6$1LMiIW81S{tT)>kF5^EkpP0`~8B@-DVJeuf%s1vctRnv%}co>M8^MrZI6f#B3Gv+z-f_cfjVv3p949`qrC$k><;V?M*k71J?p)I^d zu1w$P?Q`_;ZEri)M2J8pp?$YQ^Kv#aw;N6B=jV9r`*65InMyF}p5N?QgBOOE*356V zyUILBGHNK^7XOK`+vueRMy#9EDxUw{e@_x1)bR%3V95|=)h5IG^@ersKp}o z?)jR1cKg*oc25t<-rJ+6Tbg_}qOJ{=UuzdyX5+bG+Tw2az7>gsie+=;a}ZlFFX!Zt zPT5z6y86y4ycS~_1AWhC*O|^mZ2sifW%Fj2|0s4{SaacF%>*%SgfI`0^@eUfVLrmH zhVHzZxl%17bePNeL`Pfj~Pd%Iyv_I@XyyQ0a5mk zoq`VVqy3L(EjRW6{{l>G2Y!d7;J9YugR#D6%tR3~H^epi6VSZ<`;cOhckQL{c?0s2hlUYB{rHH0$MAAImj`0_kAuZ?()KtiqBa9BblwHPZG8MuK#7=7Kz4gMt z>C0c%+`Ad5Gv?gAO1+f`TRiey-ls5o6X$!cPlwtMdB1{^GiGVOPU6*|BRN=@{KKq#eB#{1DT%2&12W5ho$dbR8mRZ69)Kqm6KCS(VQB?uyHP zqRdgQM3kKtQcFaz7h2PIfv(! zba5Co>tD@4{_(jxW%}O=Z(+qpydW zTL)7q9^W>w8(CX<1`$WPhd>vU7Sjw_ zFU{$wGEVF_p3P>r!wlH5JK!Erg|G{0M<0Y9RO;R>d&@|2_~!IT(A#ebUNxVd*Md6 zxpF^ZN3{ETMPqcHO^lgh*~Rf+H`dvGkd6lsO=pdydAN=4FC0W#(CMh7kRL)A9ryry zkkx^7Jd9X69mT=<+8jY-{S@2F8bgX5MJ%0SI_W}ALs(W|F2d*(6Z?&4kFZB!RCa7m zZHgU3+R-UiP^otuVRVWegA_Y~xMxiZ^-q?X#lJB7P+pQ2mM>0~m}18v#cbs#i5Aig zNji4~rVD&QVy--e*qM87`^OF)`s(rVSF)#xCOLKXB;?L%MAN%i(mZ_q;xC**TF|*8 zDCB1mMh8C4o`IXALrl*hmd+hmIEYw-P>x$-(<6@HGJe=TlS z5v-|P(BW#roI0BaDRu+VbS6lehi~`%h5wKibc*RJ!Fd zHn$L2KgF)GrjTN{5lg3-Zn|)%AuKEKF2d*(6Z?&4Z?U&wRCes0+7!Eow4+n(QKjB} zgwZK>4^r#_;@0V0%UGiQ$|!GIneKlF4r_>0C8pT@+QU-;(L%ZnPUnsu69C`ankye7 zR`tB%_?;1-W%`R>{z<>#W?g3sAa@=in%>2d=HXjmf8jCGg3cX1h5QM^=)jNI$8bx2 zi0M;B$o0xg+))&la*pFe*FtS#9pT zK-$r{^SDy)CBo?3c>%fe3UTz+lQ>mk?!2r$JQWiyq(?>qlPl&YRT~+b+-PO(Uu}L8 z4o|NUMyHrQQ!G9fpnQW^H=%pR=Tyyw1$Tm5^nd^TT%COlDfSl8bS6lehldXQg?C5` zI>q!A^7ja%1HWb8vHFl=C5WX{OdOoA%?Cu*PqAXw98#*rwbn&!mBp4t35n@AzDb^UeLMI zgc${olb93f>B7&3u&lse2%~dH>^GjR zVt>G>?AV{Rx$_%oN9WGdO1)}?(Yf;*a_0}?=);pZRbuW`*B+k!5-p@>(6+fQ*sI&l zsn5cjf?bb zj5zx6BuV(Ogu;ZB2SA$`F~=Z+y022Z(}D>V_D8kt(-tEP7-#(K1mVN%k_I;+9? zd1@h=-o=vU;TbxAK^tj7=Z>L5u7fZ-uokDy8A9#|h^2E!9GtI>E+Xsaj`$^RhMH=fny^k7tWtbT3o7$EKF+$pNmGej7jI|h(DMu?*iPvTUG zxnl^qV;~q4Eu@E96Ms!NYr4K7Gp5onb8vL=dpJCqAdF5iBgU9}1}SEW*qa$f^FyzD z$WFwi8}(hhFuBf}K#G|mn$84C^YDnKzhI8Epi|69A#aK>I!Fd zHkOF2pJK+G6{MIIV(An!N*Amf!m>^GjZw2&T%{xv`KD4Sj3x4KJN>3mB!D@ZXrgwZKx%qY0$ zkYdddo3Pq`?waqXE0>Nr`88V}y{pdJL5kTUn$84C^Y8?)zo0}~&?#oDkUJoZ4s6dU zIb%pMN5s-8CJxTm#tD)2Q%u2GLyEOPES+M;=|anfu&h95gwZJ`_8ZSSaV=m}c5KVq z6mvn^(JA)4QqL7(bc(q^in$?BqLpQ^JSkYcS7O=p6nd3eCwUuc80 zpi|65A#aN?I&f>Q4QB!==80H3#l*q++O$Jt{ScNo~%DkeaQBW13%W;;gDh@5KU)-q~WtI zq}WKL1)XB%3i&96(Sb*BBRO+OvC)X7Q%oG3ugw@l)=#lvoGqkS7-H!ZGfx-BHiTsb zjzbuoVq(AX>=-T#MrFs2txd7kiYxUdAdF72@sMH@5l5$(I8|bbO{h(=Nkj|j z<-xYkpC9{u{oTN0jV^Zi@!#a3kYbY&MyFU)W)k-rQfvxhgWqlO{nkQBqFf)p#_Vu%*f^GNhGB(fQB1Nc6Z$!=n^;Ax+&>`rzMJa)5>-OnC^M>7ty zx$FseM&cxUiaiTox1VD#u~*@H?>zQ8dlSAJ&1dhj58zA60`?*M1itTj%06db!52@j z**ENa_;R9z{lu2Tw*+6<3idnPaIR#3v47ysZw>p8<>2lh{axk5&R)8usEj*q}K z;f%N<#)LEFn!?9(3r^12!slc=t~uubpQRi*XU+{i)Oc{MxVCWN>&bQCyx|J83+Kai zgR7M8oFCT*E*Ap0KyCn>QU-EExDYtD59dO;QBeP*xpCY?D8$L!6mBZ)tVnJq7hOAR zw(?kFzND8p=~}a3TEgqLex9=tODB1qjfH)|LiNl+TF}*Fp^(o-7#(;vH;1!;hqC7( zR$0~T>9y~l5t!;Mj22fVBl2Q`n&k;fsHeu8l> z^gW+jXBv;#%Ufr*uw#|muO_8WIWRW-w-`4;&$rS`xHYNtn6hc)4oj>?vmd#kVm|U-vU>#OwtBT^&cv zTC z6qAg#qaLD;1)m7>F`o-(leop4I6rlBlfc=^mk<%87li4&wq#u46>@XsQpCo@E^nr} zz%_05SY@bwk#nCqy9CZ5%MeW`tE74OlEYtEj3qX1X4c`O{Pu zoqnBX*tca%)BE=8cZf1axdD;%v1J8p>N;*c7opsUX#eUVw~|~g+8qz=`(UE?;GdRE z3Ma;vtEYo5EOpvZxfyAVD!4lYlrQ8ZGg-hes)<)j|#k8K| zSn=uTja)huR3;HedOeXYC@UreUh0A;o)Mcp{%HWSYf}4}uLnn;Gd3x!vzbs(n-NXt zy`*_q?E#*6Mq1DXWd%<>Ba9BbncKoyK|yUrEL~9VD)qJ@j4r6HP*B;3b2{0SIW)EA zK$+LxUw>BTYm0NW4GL;IV(S-__)cerumiF5-n2>=b~c1%1@6KaRZwET@$7bP2TYS4 zyR){Sc4O`87t|hv(FG+=LYnDbL~h>GW}S;hrw~yXGRKK7O zA~ES*kO^C`iOb@$xn11u+UWbBp!RZnZ9(nl4nRR2BH~D|fzt(L&9s8|Bh8hE5!<=N zvFWSFw>$28LWRxtO=wqV4?#g4K{TEBlICIQ6o26;(t<81YlS=qVRYal+)>UN3Mv<| zbV0#t=f@C67gR13)N#bEpS@=Pk=-|R*7n=st>WMJk2qJyprB45wthj0i)v&DClO2U zP3v^wR6|%+;AxCe1ts! zT>TA2(Y5=%b@w9|dDJVY4VRFZ^e#9ATX2}m;f`~sxihuV&qG0-<7Bl3 zbpZ!;|xTeCav-}*`4XXVt{%TQ8R5lv^l zqH(tFvUaa{ICNl_Udz}$`4dd-o^p^R@!xwmY?wHp3+p*76w%afdxev@E&RqEf(Ww;)k8PKY z+|{;4Ra?7mL)7c^V<^9;h^DJV(mX5z<}VZ?E$H&IQOJuBMhAY%6>>IAh3PZIRzB_a zY-?&x^YphxQ*CeV?Jf?kQtvq;2Uj18lt)(0+cHadab#1?i)Y+dy%&hv^kipg3!jmW zL*Kf;Q8jkD^o)yieTlfHcFKoOKRZ8P5fEZyP_r~doY?2w3)oU$n^%aZt2Kdr$f-cJ z79*BUD4TTQbwgNI;2Vrl)hhNI&%WY{VO#Ck*R?0Ww^+OS)%p%$bhU~Tk!JcHk$;SP z51#OH>Yd3NdAf5==S&r4jK#S0V=O*%^Jz2YGgk`d({jXGy-a*QMY~krT=G+AbQp{dE%prgo29pJu8}bJaefTQ^|?3i&Fj}njTge z#4hK)a+TaK?ssjwzfe_wV3NeDs)4F95MbGu|NEq`wES<2r+bQ(#uqHV{v5hK!t`HD zs3>^uyB?z}%9dgHk5Ez2M?G8QSJ|!LK}JlG%?`!%#aoT)EX(_O@`$DrU(!6RkLfSS zkQQ`B*(&6X5Jm^)c^PjD6{Uh$x}rW->Zu}(t|%2gQm%$Lx}wCnQssSZ)Dc_1q8MHc zDylJJ>78zyE@(7_Wd&*?jIJoL-*{G?Zw%99$7=B6ZAmSp9laG$QQ8QjD@vS%G*cZ! zs&1*?mN9!{RfOe&68V$)<3*XH6c9;QR3q3_ZC;0uQ0gLj_?wpBd;e~{e9W-E?>m{Q z`q?tDvmka+iXNirVX+XK;~Vj6ye1FR0PO_GUmchvv7&T&v7+>eIMPblst%d9dm~I^ z-k7xNVB2hOB2-ipgwYkHVD$MIjG@ba8 z=3%v2f58Z8L06PQAvZ=C9oUdJ;uTO)CWxgg>QkkjDZ=QAGJ%RRLmXXE;#`?RMVTYE zensi?>QGTl5lioMMY>?o5SA5ai7>jN#D3#hbG|7|lO1bOTTxa>J9;aiqO1`{SClvj zX{K^SrpyoYF}&Dgn*BE0nEaj_Lq(aRv_T|YQO2;T*1Q}lsu`l2zR=$q(R}OM8GScg z_e!i;reMr?F?LakEu!gRHG$X$yfJUaTk=-5?QEc;c3Tsc8S zwM1E`d1sg=JJzMPqTG;n^j1Jcxg(6O zC~*?fOg#{Jbx=P=m-7$RUH%Nzu+F-uEy^5aD@4*2w_{rHV(g-nHi)K&We2gF^A3Cq-j#Q&ZPyAa$^#}ztfx5!#;8U8nlo+rGN`C_i1my;btj>H_e-%+tENBxP|&N+ zdO}6DM>L)IlICG0bbrAMX+c+1bA`ME!sx*5c`v>>R8&XA(iK$(4`3sVuBeVsQQnB7 zD@vTJPEb*u5nI2a+VUDuQC$#A@AT&Bf=@$OR$y0z(G?~38_#y;yTCNru|BmG<%_hV zw*o4v8^Y*{5+@z?|{CQSR@=2X6AW^hy|QRXOnAd;@A4zQ`+`0h|qJrUhi zKQzYQGuZw2_(`8mm3!GWXS{hac2P<%MAO6agxKx)4!k$tmG`Y}*8?i5J4}*TQ9Wxb z%8!U6{Zxsq#)T@gCsPjWGi$9iYKW5oRFpr$=yQ}k6^wc=iSKa*RlEO z(kDTRL3P$2Dyk2n>BN^b55FtmFZ4xP&=qB`kOv@)4%~;QfsOp_fO zR9jJlk#_V}Kt&Bf7+q1~B&3-RMdZK=d8t?EvX#eA-u*LIJ=RE+Im%!}(iIf|n>vIa z3KbQC=;YADThrO0`Im0|&3%#@zRI5I&x^5(QidU#9+p4E?#&1A{rN%s;M#VdfIfUD48JmfedqbC}ImIZc{Fe3if|Dv&;FVN7EYBS$JFkrs5JDB*E!gwcUV@FRI8JPkM+v6IJ5Q}@tawDs$;UTSOn{+g!A#~`Xp zOi8}aoyvb7m8aIs-Q0AvI02*i9C;XG>0LSs`X0ltGaZZA@T%%J?MlBh8;=zIK9{}y zkr+2Z7>CGuLoXUR9%1x89}b;|@}u}LnAI`-SYF)I<9J*71fs39hBv*R9hgw~5fpRz zM8wkjxz74|PC_ibJL>EN*dlG%&y$fB^k5wn@+kLkv4&o#JCZ{G(^@LdeO+~2&4D&1n7JsKZTzPvl_ui*6!zNu%BlTZKXBp z>HX};41piIF_+IoEWMxWte@vB#L~N?&dz`>(t-UPg|wgt>!^@NBa99_i;vwbOIts`mjSVVaiw)LCmuF*5w`*!BK{e|V?1jN98o{d;~KSx8~ zv9O=#Aa>5k?$K(y*X;ShdpP#&@}!LzH$s?;$a+IB8aWSP^nRWJozLW>`Pne5vHYCc z{X7@;^L(PM^cxKHes*H|!;cx6%i|DB@8>$}=NXS!dUw>>`LIO-?B@ie1wB|Ng**{q zbl`YCfp>!aoP=1*uG=q6n9yIbyq!^}3jfWpK^i#WvRG;iPG$>x931cyR)f zU_UQJEWMu-q3;E-pBEw4@5lHr8IA9IkG|MDLfPlr2QhAhuo#i`hF&x>8DaE(o)4YJ z@rnFGnAHXRqT2nu7=D9b3DH*iWxI~UXJ5&_>R!0Xed36lbF2Tr74K4n(dp2FS;BvZ zE8b;@Jz`O?`pxb3y_)Rt9r-I-=3Hl&!WHjwMAQ3C(mecXmcOt9X+h6Q3x#|o!sx)u z`4xN%xZ+)fSo(_hd!=3q!ssjBRdB_-8gWtOcZ&)flS71gjaOeDaO9RaS1EACy9TlK zuXva6x^TstidcF_w@4S#8p5&y*CLF*;uZUiXV>tlFim!BTJ06@I;0)F6>!D79%1wq zuQ&;5rW+7BWsIB7?y%Jl&YR}=|DJl?K$JPkjfkYnY$a^!dVT|3@unmCq4)%;q1U2VIKP){3RlEmwv^xDsmnM54v zM<7prTfOa6aOORY%Oj^Qy~1^b=UO%)EaF1c)8bh&%Z%YmE4LoF{HM}Zxfx+Q+mv;D z71VQ>vP(vzT^31mTQZq^C9{b)S8hS{_5iJ^2C8w%dmgpdnw6b1qfT#z(#t|LT_KX@ z;m7Lyg{?>ny7XEqqB=G4)F+xf40I}xW4y7)L; ze6jOD=9L{!TU0;W&Zi2yh>etfErrfy7jt1Z!aUX6=-Hg=;dHZmRMP!TVP{<;d+tGc zO-?(T%g1KD$Z(dO95?k|sJKUW@H=6Oa+zKHZa7fvMOxKAP-OCYaG=?+C}vAsjW8;ZxL%;Ps=iTp1>IB~f>$^2> zopa#HDUYCp3rsFAS3dzV>7nhI!>PSL-M0mCz0Oi9kdx{X$!xN-@_l^ z57utS5jf->hTSb5@^blO{Ba(7(>+DRl9pGeWASOGrxCXGO?F?;(Z$`5@Fg6ki@e++rvv+JfP zIqUfClejE)j`AWR=|R`MBzge`eF@RS?>0M{TaaCz6SQ3JH1o!I9p(fp#+IvJ2L0^1 z;lMl{fRn_yn82utl%>~{Vrsfh4{pemL zqDaen(@|hzt|4sOz1OR|uM5i2eCO6}`uMds#5JFDlzE7xC#LRg*=sN{*AYGRO>d@b zyBWXj#fbN75_Dz=%vDy5U6gzS(e%cigg0@;_i?X^Z{zY}yF3{3HQoeyiZ(fyBz zBCSSEM}Z;VMA!%3?_;Z}QwMbQvFz!7X-yw-4dNVSJ|gKM*S!#Y6NY>X(W`fEUAB_9 z&nwD*{j2rjpVxJn2do&oDET&`>5a{UmyN|&jvv4a$N%wSyL=e(P2LoSe5-cIcZev` z>d15y81h|&t(v3#>`l(tGb;m@1x&Ypvr=3-H%EC7k@S%3-g&+YL%xsbQ=QD;EWI6O zQ+Q*4dk^bvDtgQ-R*YSg@&M8F#umW))Z$y!ui%~PJG|KL9t`;|Zw5oY|35WfK*W)j z^`+y$pdTX4zA<`#{SDo6i@^%}=*IH{znW25FA62$A%V>)u^2gdsme^s2_~)5bqrt)Jre zU%%q8vUW|FKdczLDCIe#>5csY@5PI6$NzzMX~#L z81zeo=}t+0tXRE&+*ZAW{lP1DFA!J7%u&8VBt7W57xZ7kpouL#|tc;4KXKJ)*w`R`1;MyI9+IM^;z& zJgp^$j1ecsE=nmuG`+DJu)cw~%7GEAaqxy0+r5J!zvV4q$nXDWKYt+NNDEEUabVD; z2hhQLoP>{ z>HJ&$7GCS(e*bJvMf*i-H;K#LESzlXys&a`L!HnB_in|*DaUv9fn+m=%377mBYg=G+XW4_hiA_mR2T= zHz&p}O8$XpdSg9cDGqT#4sTeF;~OuwtArtc=jAZus@fs{B%(+Q!_iS-$iEOaam~oQ z?fcKHy}qK$)lE66>pH{w9y!Y2h@^*Hw<5?d7;-hD2dp!ky0&Rpx8-raOxU((|C%y= zI5Bon@*hOg8`}j|8xhwW=>sc{{N%-UzhTI~cpDgUb?uP<5>cdu%IGLC+M-YyPA}yRnM}Z;p2&=F* z|L!M5H@C5BJ)vW_>{M~Nq#UITk@S%3)^*`!5z0o0?rXP}Y1-ppoa|Z2iS8kJD(1{Y zPK;fYtb%BIV~4|1SfnJo;tQSFdbi73)SPIMF)vKqp6+z_5l z8O?eooo?^cFD&t_xO`8JQXP@>kn5JNQG+2jM)bdgXESQbZI948u<#!;1t?bKn&YBB{3xiJhmmeYhN^dCBkeHAl}oyjg@)7cm< znakh~a+kOQ?i2Tq)8lRVHheFB7(bq$&d=kM`3(Lfe~!Px-{5ca5BMkibN)47!hhz! z@;~@LJS$U?X~=#sT7nkR@!!xVd5IzBi8*%`Y*;$|W!SL;dfEu1ZwzY5;_`G5H{?yD z-8xfSO*6?osXObLreT$OV+~C$3rj0&xlJ=$gL=Zc#xPU;1~Bm#Qrinn5ShFrDDquUnaXN2uh3$Ljg$H2rUnS3 zvrr6Z=V{mgDgKsf4gB!&d^U=mGtvlYac9}<;w#blm)Dyo_U)N{@>kujug-?w12vEt z%IsJk+J>`jJdKgIbS{e9rNJ1<=0KmzT}_Y{^=1&XF?f46Txr?>Z!8mkwR8@fA~!?y zGg;JNXC~>-kWGKI7Vb}*Q#Y1&6U-6&)pOv2(24ndZ%p^~y4rm6=_WE0nJH|GIEES+ z#T?d5rphd2hnhA;TGMwX#a5o47KnVMa;dU7&Z=iYlcQR9f8`XJ!)P^_rqB=U7r_!~ zQE!eqcD6zoJ^31ph0Ic>FVmBWU35`eBW>!1uH9LNviXs6MAJ7vH5erPeA=sWGlTyUS{TwFLHa z%>l=_{7cpQ7N1|+tE1W@`iyY;pq?|*Db2KGhm z3t3BGv@cfGo0J;`nPvp~0@OAUK&U8l3e<*DF?FuJ~7Yz23O(O-VM zj2Aoz7GmY2-ga{1zR730o-J7xJoRz2U)s9^&tyZVtq_KE+8SZo47*$$-ZP`xH1gc6 znsIxYxbzp=5KP*)$xR35G+r^o#_dYp`m5HvZn^jgZ3!k#2wmjx4TmSf=)D1%(hgzm zvpm&q26`;(|Lx*Fd&WfuUxc(r7~N@GnWwCstdHPDSZN$PbYqrfCC`kwYqWdZ*A3;5 zUHS+e2)1tctJl#Z-nXr{fi09B2__Aft~pnze=k`FnV-;!(9({hw-YAE8)5bOP8B*M z44IrR2%|ggB=eSambFm&AeJ7E$NvoHkxz79jK_dXV-hJz*|sLNA0J@7m5MXZ8NSLmw;4YbK>%gYET07`?siAv0ZJ zdwa@y!S?zS+q*clU|Y>{mCE|t>k3=!Cu=Q}ZRibtrCIahvLBXvUL8sr`?}A{Q2MOo z1Ut|3JyMVDLihrD%m86yM|top!?J!4{A=AYS@{UuyQHDL0Zi&tN-|Ju?e zOx}-RQnaBZb90tVk}n#pVYsUKm^Ry-WC5~3*;=7LVWp5Z=PPXcJUwW3=E{}39)lD1 zySNDh2quLrIcijNMQ^cvQNZK&S|hd$b%_)P5=@GAucwyV!l-9n1NA#T%icYGBOC#P z5T@04`=~$SD)4Fp}uz|q{tG9s)WeCE2o)m|?ITO_B>Rk;@ zZnB^AP+73dN#-b%^&AG;X00+dH~seh0efbC zP4%j28}5_wj~;ZZaCR8vxBLHObu*h#XmfjA!SsNu1Js)gSTgJEq01NO&q88`4wp64 z9RarI_$Q$qzV+sY4^k-|7AFs?XPfDc1h%MO-s$X9h2tlWusB|lH#MUko5PI)CVi}v zuES)jI!_O&I{ab&1RL*D$zz=@#mlRE@XPG$S$mnX_A`+9o9!3ivQC4EfeShZ8Qgba z9A$lF{bc=R17rhbLu4Vc-m*~H2-!&4Fw@aUC-gx=?4hgf7(z-*-_p`zm}yu8n7HI? zdtodh>1lvZnd1;fANa(8cAn!KAjQRDS~hyhNQ-(i2zny;mhdTaas&KC znYgTL9G4=Wg6NXr&rTc7k^2W~8}IK{CcaKX{!qT&4ka7QAi7V^kI+~Gi0-5(`3o8>aV!k z@66iIkI_im4wFg>;=dp0Rvzj0v$aFt?-ooHe142U;_12ZD0;`3b%|)73M$-=^9|+bp2NB zOqGSmN4~khp4huRS{pj4gXZg{C%)+~Z8di1?2X~J1FH4cyN?Spo)-)s`Q`!hWGDD{ zA8OhmJlAfP$BdM>^r;Cx^36v&rJ4AVFAi~9{ITAeZhh{?`n)!d(s28BmYFM?Cz~(p zFT^AI#kucOhN*sS8uv5&`lINooh~wE0}2p(WG@an*di{NgyYiy{`Uo_h;`jWm;>plJuRwXSSSu zFhlQg=$Fp-ZuPb2#q(OC%*kN^*aU~dfG25h?tPhm=Ty$op4T7V*igx8PQG%m|0eSZ z$=70duosvlS()BK(8XD9=3!}X(L@|#0t3NTt={^=i(l&2<~mVc9)yx$zC&iblH}8 zDb!g%L_1+JDam!Zc)Vc#(K``ao4c{*wzq#1%e$QpC z;*xe4c-`Ooy6?q^}e5X_CRRwm%H9veqMC_i0hkSZ^nIY2W&OL zW^FlpqP$u5rQY*e*yQ?7^!Mgk>mIQ(`~_?c!3tmNu=7l_-2R3f{jbpMsr8!AuL8Zd zq{xA#5^UF>fX!QsBFbKsC|VeW`0iM~ExBorU9rZ%(g>Eab7e@-qHAwX8dxq!?9}f9 zEARPIuhs4#U~36xGjURM!mQcP7p3U7?`gH-wsTxbv}{JjAYkhV=2)__=uW~4t4u|c zA#Fc>{I%L`s|>!{W!6Gq8wfV|%Dal^ z@x4#z)SP^InH^TxInm24aj}m$(v1WwUQ)Ba?S-Pi_a!-{a?MsN2i$koKc;MF3M`#q zU%tQgH9PcUiKpKRzUkRnX=P)~k4#GKJQG+3!S2ZB_aEi>rr*%zHkFB%X2RavDmuDN zW3K|sB$#|kBZuE-&b&@=s@~Jw;oVzq&C`x|?VGp*+eEOK^%JK*xBWki-FG}!;r~B= z<8{u_kQd1)R8~dEXh^C|&M%cPuyByBGZnC8h+WK- z$efhcY|}qIxTbfR?$U$UtH<69lZOCHf!NW9(*-K6z%n4#eP)k?ru-SVIp^Qr4_z<~ zPIu8KflREWfMr6AT|VbV-n7(Boh-)K!lsp;K^Iq<9X4u=2kZgFuvm*+wRKwNF6!q# z3+p}J<|TJ;e%83|2Vf5&#(&{;X$w*6e$P)rs%1kLv$^=5o}R|1v=v5{=nb)Cd= z`kT1lNi_!#$~n8pM!&s(FCDN)5c{DzbkJVs%>6gD%f9bstUVIW=lnh=Z8`~9HpDbm zleN`jo44ByJ@~;P`#q$ECG^9Z$eSd<9z)EOIg+z#JHOQ`(NU?YT{$cE+HzTH1|&WK zEC*umot5@(94<`u=(1N{@_Oi6^FZ;z=9u|3z;YpWX7;Uj3Q z_P~JH?;i(`47414(L8n0s;KuhU@su{rJ4JJ@$+-t=siF)pNpZeSj50%*8>}ZW|-p{<^-hbAH=R+^#CKo{{cZ zQUDZ!!I9hFdo3d=GZ_WT#3Naszt^914%unX~DaJX_ zMVW5$JIQt@;Kg&m${=P~U~9A4FZaX#D6g$*_ELknK}#xZG4@{oD~A|EHGf#Zmw=7| zE2aGF{db4`#?u1iiVP_i$_j{GT~10C5BqxkEI0FqgnFO4GiJYC)?Ru18?Z`<-C-)? zkj~Tk?Z~lDgF&;BSa#vCKL1we7GPBnBUrhTOv$X*cb>a@%fU{%^GSJYf91-}luKJR z#N6%(U3)RQ&dj{M-B$GE4U-3kGPCnU!3Dr-AST>icVfJ|=$OTJL|DyE4&d;{IYR|LsP=>L9i?-}&tLdEV!jkJ@D=e2A{m zP-A6zv|>LiVD%9DQhIQ>EoR;}X5p&hm~s97dC6xxzW29(1FQjJJ>NZzh12USGdDkH z8xlT$>BZN;fZCA_HGsW@n2~T=8F!p~SoT;|ZtgzwLb>a;`vWyz>H*dWvFpAz-<|Zo zm|2GJNS%MTAbEWI<-#uJ71e;fg4knImL*05x@*jl13W`hbS1`fCXWk(ZcREjy?R zSPR4&;*0d1$bo}>ag8%Fn}!Cu64RXqet8!G)(SDZIhAwuKja!ZY;I&n6xi-R%8+7o z$td#;U~Lfl;@Wh@wfkdYr6%~zuCfW3p5 zeXd54;A?Y<2$6WD&I6-ULEDzCdZeo;3yk*=TfC<-GBa|wL}AHK)FREI_M0b+LQTF;t8r3*?{t`EwNI=VtX#jssbQ<4p^j}Q~~_D}YxyRtFxCo6Nc zZEjrE*qH~P0x!P3q{9h9ZNd0sy$3NISF56%0Q&?nW~l(9V)o@v z<1;Q19ZXGNRPAv-b!>vN%=-+nKhAF15?{?jT~q2hJ~9{|e9^ayt-*-KHYb0P_A$DTcbMTIfnB>;pz~E28J#n|5tiNq;@R_nw z{RXj^EJcr0r5G9B{9^{|)Nawo@=1n0QSEXAtQTS%JFb5b^360oa%PG>V#Kyqr2dfn zg%_Jx0PBO;_1!7eFMThQrsotU>;`+~i?)vCBuHY%0PBa?>etJ)avqp5bHRwK5&quH zwyh^vw5m%NumOm9mZ_Z-c$>tj;w92%Q;?gfd$Uc^_Z9a9V1p0~%5f>(QtcG!waRkn zcF#tiE~TtBVS(lSfDJ)Rd}Qyr8|Nag;B3FVKc}!Q?aQ3bHY<2E;${J||Vs`c!`HdS+z1WohTm6`YeHVd)6>X~-}d#c}9K63vw(1+{XpYDBI;o3!+qJKi{ zLt5Op%}|Q(w!s&!(-%VnUpxq1ntHBJ`O3^etZ^!xkKKkfLF8JU%)ax}9xlv0u5wC8 zLIInHSgcCRMmPSonL9VBEFE>&!4aD3v{Lq>E9L9_3t|Dg0#)~UjPV}6W1z=)@EwPt za_n5v55_})EkMiyGd%EcoA#8&3-ce07mZ>^7~DUdk667OutkU|8`*AavEvWAG^J)B zcZu#6{;FnfB5)n$25Jdny!;|7g}uIJoLPQS%x-jCz(G~(?4gy6jDY=y*oZWr$vK}| zJpXXs*qbaHd8-4`IWlh~b^^8xvGMk|9ft*nAHU*fe^o=;@3PC@I(s3y-x{z#5IgG` zJ7dvzCv@bU+dalvcU8$4rw3v`u27y}&|&}kNGECb(bes9x8h8QoP}rS6l#UN_(%6u zD-(dxLo7X(-#bTp{UgOHPp)zYW}a&D4tj?@hgSi{05MxlRlYHXgdX;^HM7^>jCd-X z)|s-2q`wFlBg8aG)y{o)j}-tP)SBs)j<#n97j6TL1Tp$VOr|d>YG{tZp2du_ z#`gTJIl5uJILd_*gV>MVDZDpgEW2IH8TU+t*@j0s{^?ML4p z@_n8lVs0#DoG|ZP=X?9Arqa{HfUSVo+>f&RN z*os(x7PEbiq!aJ1Q+d_4DKl!Tr@`h2Z!`c~1u+YDo7_0lZm!6mwTnZBb|)-cHJ>mv z?xEbvtcIBB(Sw|)uLa&y7CEK+_Tc#*vv+A6&uW+<7Wep|m#jmnch&Y!JXg-~ z$_!r}YFO-eI1Jbth>`43y5$Phd6OE>mf#LCoaM_Gr{JNn!<1)lAmEY(T}j1^+mn^@yN zTi^I*l78@s{a6}f-@=y0x0M^M0AqvLX6eo+kI+Ou33UJkU|yS{gZZ2C%gd z+vo9Wd@Fa~_ilSVFDa$zyFL;<*{?2!zXFUMV*680#jw%8ofg$8eG+dXxA>v2XA_5c zJY^lL%91#1~rFnoEnwUbGi@lTYU|B^YN+F3w8)WRsTR3!Z&R`nD`4v(W|vhaxpFw5 zQ)AmYof`e~@~@{Wme=qsQqJiHh}r*9oIGzZ|6aLKpP^!A*3Em})v<~o2X(-BAoij7 zKzKw`&-?3{ITT&A4PA$=l!CVe4&C4D3HlKM#fqyf?(X^1pT8X=96#z^C&3DP9#J86nEO`0M7AkC6~ zlIBSBq+g^3(jsYz^qaIy0<%3vk1=437zx8L93wC$Yz4LwTZOI0n6Wh&3r5CRF*a;1 z#*VGSI519(3**MtV;e9Yj2Gj>qRE?}<4Ilqc~=PpuQn3hqxbcd&ecaTbzrx~W{6P_ zJMGVIl5=E!h*4Xk{nZfcFcW}S+sg+x14i4j5I-mgBG__N*K+ZJ&UKN$ZS1GE+^5XR zLJ;HY-jMg}Iep1DJFy*aE5~`yNuR0QB3D4U-4KS@s9pb|{r<;InHsHBubvuau-)x< z$yYmN60j{0+uo8TrF)4@UnE3bMJL+5wXn*~!C>F@Ka%I9wnB^=q3L)9dqwbt0-g;1 zr~GDYyaJdYCWHxNTd+v-HpqWWJh5>s+29}|vIv6BEm%Kdzg*Ai*smI{B7KvxMiqrv z*y+|4Nt#nO%jsUKzgR3eqdX>7m3}yW53ubJn~fH3TO+_pc53*->+X7zVLjX3%vHXx zVVK$3(QwP=si z>!^Wcx$d3GM_5H4-?}W0Nnks$F0vG`)U6=YpH#g^gA3Vtx<=W4sB2_JS6*utB1=O} zQit?E`#yQdG6+WdPjtaPrJWF?j{LYy9Gga-`iUG&_}ZX-a2*+JHr<6_VtLgpwUUkF zg5ML?ydwXc2HTl-LyX!t+TYW`ZlOI0M*C|Y*rz0mV6?66#`a)Aq!{vE$Wn9Y`pX0> z2zLm)5E2;{(+Lfbyib-xuz$Yj>g0V0CK{MIs9e(XE?drMXNF1oW{^W3!T!k+N#2iO zh;3O42u53UA106O2h*P-WT|)NYI*%p?t3$x(l1=*+!a5BgLzE}!TyPRg{+KVh(T}w z!TuQpG30{?hBy@}2=-6k)X9esjP|I2Q*ju<5U1h@f+0@DQ3RtcdI&p=9l?ais*v4P z?XNs#eEwYMgcE+4r2Ioo@cb%wX4g1y?NCE7#HI#yz}8rC;_td{9iM*4lcst5lfT4N z%Nr6?v2&4YZlPiC_av~XK?5+lzOKT6&?Fh-Nw?N2F>%YHV<#SR^Cw3SKRI;Mdg!!D4uAg$qRAGxl?d_&WO zZkASo^ke77{ulc<%Qu28<=O~FyMqW!EjkGH&wO@)tP8Q%36DB664H$beYxM|vcX?g z#qGDad5S9r6g`e$h@yH3X45D1B~(^Ygzw|f#}j;^4Pf*935ZFTUnjCF=`OAuwk%qj z7)}zCS<>^?I&2M!oG_~rv4Jc}e zV2Gkd2&VdMm*LHAAHx}P8t3(kFS&rEryv%=&clf@ekkO5u&T*#IXvA-_(`jzWYiQW zYK&lrq9zE2NO~G#q~_!s43Zw+4L%*V!XuT!o(;cChX);Pr9U0Lxr1@uy=)ICYK~xtqGu5dk<3psDe{;X!{sq>)d1q4GBwL&mN(u)vFoH3~X;?xm8Wu7u2 zVG`~j_-cYB-S9d;C~A#hh@zJetR$$^&Q~RJ>xw`{=bK*0lZi zN$qt-`8L-3KgvnU_UMD6wg`qOYKLHmq?aM)u`%;Q_;{V$gWdOzvBz-ph>sdRx_D8d z9u&QTV2Gmj2zE*Conzc1R-MY!cPSd_BNZU21H@Q;HaOUXIrT1|kr_@D{b*vuy+KVQ zg;x|5y^3InqK*iLNa_SJ-A2Kir^d8#rbjE!GjiYNQhH!V*XQ{w9~8ZYV2Gm52=;AT z#oOtCjnAv~&hP{!dMbjX*CFQYP-1@Zw?X>>j?Gv1+1C}ku{ieh&Xx4%pr{LiA&R;p z7$T_~#KH~ySCd)7KepL-Fcvek*C&^D8U`17>42i{2!<%?fndkopP2VqgljBHt-8c2 z=Fkq3dO~c$-F@9E2KT9v0FLDkLZ`X4Z;Q*_T2NgHih3a!qNq25A(Hw)ENS(a>HE)> z2Ui1U+Ny zyRx7*a@5}f6b(TzMA2IahDaI;v7~R@Y2qu_ZxHO!`w{8O@zGMy^4ir`fd@d*Fa$#s z4M(uN&U|hgn=tH%lCzT*YyKLLGy-Bak1mJZAf0gRF3mSe=(Ik%an*?-{;^_NQ1mu} zA&TBXFhtTwh!x*v!<%pLs)^md{OoJ;`-17AELN5k=Ep(NCY8TfDWf zO1gNA^5=>PkfyHBX*&Q?Cn6XkbrOOhQYRxAZP5fQ5lh0vMN$x!HjeJ!IH{1PuKa0R z265653=tA!IbAWgl)qHP((DMTv@L@;)d+@&Q-ffLIJF2yTeJ$R#%e&E zI)tT-WBE5uJ*27ko3t&1I1LDfi1QM`5OEq2jJ9Y!)_}bPab6)TZJdjL<1|5B-BH1#P5ZOb6eD1ss4j3F2z&Nzb679GJxu`v*50%2+6c>awu32Ex{ z6WW$RobL#Rh%<#?h&a;-Mq6|e`;JY4I5P-K8^`BwoF9;;KAE9y8N``IFhrc62!@C= zhhVfte_*rNPY`DwVQJ&||Bdqt($r@@v@L@;3kZgYvxs1bI7fX#QB3@h&Xik|8AnBwuXp9k6^S#moZQi7Z+hbSlT$jf8#Jhn);lI zwq+29gkXp`7=j_<;0Q)rlo2Q47>Gk4ENz_7zj2r#O??7J+cJo=0>Kb*Rw5W8&ME|> zEy{$iz*mAes}YtqPQ>3h%#fx&Tcd3m#94!2h&U_=hKNH(FxsNb_!^uA#9>8P+BlK_ zjiXIwgY^IN!BiA^ErO}+nz^qOBJH1gV7J5S%LD=5(8P{lw6&AL^Cn&FF2;th#otS< z1D~M2QL4h+nVUKGq&V$92NjYoriHQNI+!+@1FArM>_&Sez#FAF5zH;0hZ`&2{nav7 z+dLzF`!Ud8E(D|PZyb0ks0I4VfpdcXazp(s*iJ+by?LGeZ-2EwLM~hnBQdN8zSgZl zwW-ekMNd=|Sx@HFdfK-UMA55(^Pvf;!fa)5i=jL(B*}g&AWe*lFwx zW{R0%=Ga-x0y~GD$1Jf6m=$&rv&JrAHkd7Dhh4_5VD^{;b`^8PoUm({Gj<(w!CWyn z%pLQ7yMf)r0i1y4Detr6MF=nM`dGq;4w}<_8dI@c!3pzhXy5B1-RF)#A?AUY8}=H?(AM+t>A{J z4eJ2+5pS_Bu>9`EK7m#1XRH@2_WH0Putplj#=+8J0-FX`!*1$zW`=;_Gm3oV0!eIHo6d^#@H<>h6m*X%hU>WYR->Ol|4cP^(UwKm{q$-KZ)--keb?%S-`aAwOrlapPhy!R3`%qf5E z&IhqaL%R(&IatU)NttQbhV74;s$`$5&xoM>LF-0{*)~3AQr@4DwJ&4K{?BPs=hu|I z$T7F^5C@y|HbIP9^re%y>6J{e@By3D=XFec3u+iI&WCTrqsf~gO>H#({AFHw)|#&C z4(nEE;Ge?4woZPCQ5!veSScxMz~4??^MMu1=H6hixlI6K)YizO7B&qXWx`zS9BC{X zqEg_iBnUBT;F)#L=t>TkI#ru98c5qY(t#)OLI~#efce;2{{6o>+T?ftU z|If$jQDkuhTNpAH!iV;6V5&+wcGUQ28JOH85R7(mqkO4PfG@fjE)FKQ9pDqx$#|f$ zH;ae<+^K&jw-aEZk^qzOdnrlCuUCItKRzp3`mfgl6}WJHFd0e#ug2u1!G8RKLkRch zj|S3a|Gdb>@c+(*)OnCP2U6!h>fA@2_o#Cob-ts{b<}x|I>%AxH|pH>pIPlc^Vxr9 zvj5Cs|Czo1GjIK8#`@1(^`BYlKl9UnW~LpuB+kMl4WiL*PwhPIH@Z1YEgb)Z%Z2W; z>me=30ChbqxA4*T@u3+h!|3!-@kgcdJB% z@?|;h;`>T@FSjxs<(}Kwv6AvPD!U=3SjusQp+jrKq$B1&Y_@sJDFyM^rq4&0z$~^0 zV$`BfgVl&$;^{+^mR2$=e?9LQwiDll@5axw$s)9h>d$(+w!NCIEvv)6OFmHAgLjkn zLXO(Ue}10iA=l^`U>cK0FvK*rA7a!=k#7v$ivv&cae~i}cr@R8IpDu>s9)kCXLBpJF#7uEG9?47n8#jz#_|*UJ+Bml(7TYK}-cZ3T9m% zd=tJI=f?$buweL~BeV^t%-T}8G_Hgnzz^ak>klEiNITC_`nPrcVMspU7|gfWFC9QT z=Ni)wfERxq`Trp|(HYY-0-eT?$iTvM6!8gRjp^XxZ?}54^lTU7E-_~Y8*YK3P5?qD z*A@LyJGarWOHG=SlU}`uwaV|*=lYYB4Yvq}+Heb4`jL#fpmX_W9&UKBM&$yl6rRC$aj~DQ`Tz}!c%C+Ic38wq9`rhn3Of9CC4rND+;TmwIbgAKQk-gU;p2e;mQUBffc?aJD>Jtqaa|J3vEs{y+m zv=Qu|=>%-JMKHt`3tfnH>|3+;aZyFV!ut&=Axjy;(H0Vltc7z`py+V~Llo6Ru=b{h zm8_@ecLYjY*^`{a@DXgWH~}&0xy`lpJ(V3&cE!El<=xr@*6)oQ$0Y8 zUnVWQlFkUHY_TwgH1&+ob^uJtCJ2T|eHy_Ksm~x7ZBb*~1V0UK%uNxNHjeIp<7ku3 z5Sq4SusSzKFuIT$*M;ZGn(ABq1kV1P69a3(vj|38`wZx%E`96 z5)^2B{C&lz@3$_k*k=H4N3TGP+Nk#Up)G8rKjEaXadaV6;UYaVPv5xE;L?S?a-4IF}*(bGk7x$8Z1e zo^K}cpo1<5_D=_eMO+b#F72Sw(U(D6Yu1gfuRUtB>pJd&tKq8n1e+Vs&kjiI_@oEj zD0Z0&IIR%UN!uvpEtc-Uov;w-Pdy{}Wgz3ozWpW#&6zp#v@BC64_NA&5?NoCr@>n+ zJpfa%f63VYo8950oqvJL;pxhP&e) zcqG{iXzJHQ^1;_McmH)vh`(F(MzAHrwkuoO3XMsf{bT$->Js2<;sdcdK18{?p4zU zOYx`NdZPdffY>SLZEJIXFON7xx6bIrS%+kXo@k$)n4`R!BoJb8!u0%ynYoPIHLVxD zB+EQ*I2jopIL&edupo%l+J4;0f6+{1X%FFYTHNp}fl=1Y(B^zwy5JP8lD))6w8-Llap-hWS>kUycf^^UZ)`O=iLq4{0PTadybCdRRrJ!pJaX@+HV1PAMW$7p?- z#3L8wGXRT#Sl*cj?s^+WvagL5%`UO4NC|)Ty*lVVw->P65Hq@J*=`h3%fCv___K zZbbxCgh#tpiCM9mG&l^ohhOKX{L%7Vhz(p5#!7tr$6xQhF`+j#eXittWkp>DyB=UM z5L<0=s;xFjk8$J3AB6|{U)y$1@#%LQsyhnUJ%~BQ3JT8`d`}KlV@kLq*=Tapj6;ii z{r|kzBNk%p^5ag=)t~jQI-{SztHbv*%jGgZMm?^FptU%N^_kgUGC$5=&iGs=TG`cE z;&Ha<+LKG91i<1UX3t>fdgIvoX&W`0X?}^VVr)P2Bn0gDdIEMIVmgo5$wyvwUnmB* zaf4#2{U>9xNGo6LD+eqAV!S$LMS0xsR>aq2)Ni_$6ZWlh<5-JS5#>2@BE(|E={iED z(yr7VsN2Ty=%@eir;TU)wyuf*ED2&$bD?#AIzoDl`wq$(MeQd})ubEQTuki;EE!^_ zpW1&^S|QMLG9we>%vH#l9{oUYL_maiMFRVI_w z2v{n_Se4zjx-7P43oP7gW+^`+L&#gQG>2(f0G0+ZTYk%50wG+Bj+vG*X>jl4yQ(YefANYwd%rV0 z{lcjR^V2c!ua^Lp39*HMm{p~JCOlh*L!*_HFMO?eoRekrCX)=<1Bi8=jlF;PWt_z5 zrD?~DFBeT>r)J5&ME+2|3lAYSpVu`wUBtw0v2lF`lWl_cQ>Kh{A5W#G0+t0aV=nSp z@vZ`{#4q!+$(|lNo3ln04cSgg0`>@Ei@kcg)jzvwuxa>yn!4vBu=@|MkkH?2OpQ1d_9RleTlo zQ{Kdp1F?I&11w|l10sPZ3m@jK;cqf+9ULfMn4%oFT!{7LGBt+k#a1$17+JT^S7_Pl zY|)vbtH~^Yh@tI|esxZ^BfPaqaN7I`E*>?2>DTyadqMakuyd`Uh{^3Q94J%yOpPNCP!j={Mr zpEt*g9y~F1!oSd+^YsH8z@9;@I**UM{v=<_kmU$ddd9R=>Het=7ZT(s!}2-Ab}KE` z>!{))uffc+-gm&s&7^S!?)Zh$w-*po#}29)O}u{f0fzl3-RmAM>=y?#S{dz=|Pe`A6qT%$Bzz>b)a(I{G|o z(;hL>4eb84AFvXL?VmEi-6jo`71Vd~CB4w*4N9(`Y02Q;0$3@;wuR1il|`@@%bsto zov)G|z3`-p*SBR;4Pa#uONc2d-E4eG;`aHsnqjuGjyYdKS)JDnQNE|;5E~@xtFH|r zex$y-*-j{3m6=!Dbc3r@mog1jK#Vm(YHGYb`(e>1Hdbx_fOI zuxf~XIKFgJ(~8-!DuSzf`|FcS@3c67tR7y&3s?=rs-M2;F$xuO4ByT3h)df}p(i_S z=8NK*^MKVtjOk%fM1NtA);6IMnTHZWHrVQkxSkiTN`TcttoOja1c5hkMxXi1-$_bf zr!)6S+*7=?iSo9xdWcP5R})#0Wd13~u_VHGfOU|i#W2~yzQ`P~28i8#!Cf#Yw6^=^ zTeS_ozII!GD@5;9(%DuB*h`2VIejyPi7zIPFEhV?Evs0}^$5jRN?$%uE^Unv+Z9t< z{T8oi=qS~wU;E^4qk6u~A=|UNC{y$+h+SG9Z{5F;`eEdVy(^-?=2r$ z$~XJ)>A#mOAbjE2iO%h#ZpE{JH)=FbP)xI%gSz>ijD1-RBdRH5E6f5Sk?{L8;FU;-?n+I zIw-=QH<+euSJAz7!8CPrc{B;I4u~l`1?%bhOCOla6OHIdVJ+%BXMOco(D-%0-a_mt zo35M8#nhWEA7^%~@bzIeW{vx#x8HFBuuh11Rce!dU$sddIDh)`{#T`jO1utPU*#ZR-4N^NGM^E?ka&foH97kn zum9dZd?|8kX7c?3`v9@AsLQV=mU>N0IKA9YcU~|Fkw2Ls?Q-fgU>_lt&MCiqy!7g; zGM?w!kqe4o)@0jvjNKQrNT;3raP)%9C zeSz4a2@$2V$*z*~hhl#nadIbaTbnuLrw%i)I(NR7)p(`JB*-?A(tI%;L<|`WWS36!b%^!mVQ$?=7Ll0x zY!qUzzTaGWuxx84GvRpSFoUD;)61;6xj9{w+p#f-InPIlZrV6&)iEag^7cK$G_yqS z>#2MFDO2<~#G>;jMOag3nB&*WPoBBB@a!nPsSaP9e=J}V5R>q}*dS%GWh^g)kHt}v0wo|a|`!I8hBQjWXY}ML?#VWwQL#$+VUfB1N*`Y_; z^YQ(hx6ZxOD@?4qs!ti@QxG#zJYRPv%E9@=bM1q_i<;laU5T(?OIB$CY#L%|U%IxQ zFV4PyI{SyO^b)fvt4(pNjj=7|>O2Fn3rigt!B3CBbFm*!>yaF@-&p)1$DKaK3$Py$ zThR46@R;YMUqDF7&tF_TSE}`#OSimkvjJ=tVp0LRH|4#VdiYdQ>DjJC$>qu3F}wS9 z$1%WuLM-h=R+2`z1ABU-RBL0ldnR{o;Q7y~|MRNWIf&iw;7ONOzuXdZ%B< z)$uUq`&=b>~>&vce~>4=p9w0Q&{81g4xV7umJ?cwKf_ zt5_X6I?Vi`_o$>U9~!i*m&3w+Mat8m||wdtnm)31R2hFELo z?+Xh2fuld)AFdt}DXe{KHMD({b&9fFS%#R7j|dk1$?)XhNcS1$oY3%Rt<`2)92+v}T>inFr z7MPYSd*?h37(K)|EX~?R?b)6x@09#`=sxFa-63^}<9CIb0Aqkyb8wECJb%Y?g+!7U zX)3Zxx%b?Zj-K`iV2lvEma*BD#oN=F76D7at93j8vK`STrE%)9Gx)PaPwA}_r2Q0CuZ3)OTqh| z1BOHFy8F4Gmz=mKhBns6ti^OPeH%}F_;odK05Ae#g~oqMzYJuG?PVj! zjabd@o%n~z!ssVpD{fZn zuY!Y)e5pI`hVWiz&b_u5Yuq?mYzWvIi0vv1os<(>sa@w~w0Jk#>lUs9|^2H|G z9-STt|Bz1K+XL8Ih$*hURqd_z%{wlM)m!xC^Ox5-&F!iRBzpm4huB5;y*}IOb_Ix$ zNIxApSrlte@a*zMgRUH_nUor{)Zzv*_qu<*L+^!q<36}A?uYy1 zH}IQy03L`3;lX$aehUx9!|-rC0>6#l!6We~JQ}}?$KdzySUe7o$M53_cp{#JC*vu2 zDxQX?;~97+{s4c7XW@_VZ2U2vgXiLTcs~9Fe~LfDpW`p^0=y6}!i(_|yc93P%kc`l z60gFm@fy4qufyx{2K*)7h`+*{@MgRPZ^hg2*LXYr2JgV%;+^_!vHpPvDdIcYF$;#%J&!_$>YtpTp+v7XpK@DRL2BzYs`lgkq%vsB*SKt$ez zV3N!{_*fjzou4d5lR-R<t8Li2ZKyRJtrDnQVH{^Raqy{J}Gi6v(npOQL}BL#%ev zHG7K|^92r1Jyj7Ir$F(cwW`@4F0z1MBn2Qw?Hm2iGmG3Mg^PQ)+_Ty2d}HrMViU2M z;0H+rA?>@_NJF>qa5W-{5Q6C$Xw^$^IVml?a)O!Bem)0uQ5a(L6*p8A6kUbw4#%CT z`&2$etcaDm<7V3o-eS20V$`As1cP{I#(YE0Sf}Oj{Mva*kPsq-i7xV1V5ys(sQZI7 z<+>EJr?@lZwTDXgXH{u|w^(k2nxqcte>S1;kVO#eUEegTtI6~ImJAFld5W*C1^Yon z5$vCz<~7LM5sdctIq=>|F$AM+O_bP9c;PW*amZ4?bJhI%i$^w8X*AlLbk}OSZUf#s zDS=@Bd^Ls0I}q$=cAM?E{q&9-c8)H6_1dN28!U-n@pfEF-_{iOo;~_m_{7umrr@YZ zA=t;F5V`avZ_#U7KT=HFbo9Y5tI`ODI4Uv-M%$VcAx%gUJmj4S`_E}3sqO--b&KP} z0uO&?LT)gt+tKwY?Y@HlyF=jw*f+2nYMi&$|8FY#0(Bf z^-KH+*#7e2!AGyBnycIepM`C=zB>w-EX0f%ZcGXtEYvksabv^oCO>S&`*`yYtnmlm z(!CI)78U9ZmC-o;Jk3u-SS30mchLafP3$3LiSul72z_ugiT;?_HgTo2w05SwY;1dp zZt_0JQTzDM<|!VsJc7Bt%Jx0CmsoWy)2Y8)=u{1Olj42^YY8)rF0h)Anu$AfDadrN z5R4uL1Vd~bP=pwD8v^Zb_+a!XAsAxxC?gncYl?&taTRO;Jpimcr?bq!iOog7@|rtJ zZmkZa-Bt-Ufa1FdEwF9nKigGK;Bw&D?*pG#!{v$ngaV;VkdzOCmS!Dt67i*U@Ctji z_7V;YUfKa>OAogrD4+s9v+G-H4e<>-+hJU@Zl+NsgSI+lo8>`5h`<=cj9NtvpD z!i3y+JMmbmv4CBH8VL5!z!oAOL$H6Y0vE`d5L2BZn^hg%xB1ic#n`=1`(o}oHG5l? zDy;`awGa$ZR2#t}W?m_)>@Huy`-Dv?EM!;+Y(><881>w~Z*$3c%q!@9TRZmV#I){b zFv;pdjCw$5FBafyavZ^E&juJNdI*Ntly?HbXp8C+#|b?`lYA1g)EsAX&aMbeuH8@^ zYb2W;&-gJ86^Pk~-) z5;}wlahiB9WePq)-HO=pLVg`v@`5Do@<4^8NvIQNh+_oUItf*vo-9Ov%@OQw6_;fr zX5YPq_v;ZlmP02fTPG2Ww!bI9SW*Z5H6zSHe=VT?ZjYCg5V*@6{BM8NLBg|yHbJ^~ z4)_c1d_OoF?2mPteVX>^&P}JChYy3Zp$2MbfP|Wa7WkYFL8+=wP>z)`VM+2{Y|K%#?%Z2-d`?DC1l%gxK#bbxKevik$hHupwx-PD z`%pZFeXms06y4OhTPKjg!97i2(y&J`#H8VXV2G`VR}qZ1=oP}Aa3Ivlj*z7uys)7j?sq!} z_8Yv7&7VteTm~IIGU@74YX&$v5 zpTrM_+}G0xb+qz&9Pj?9_SKe|?+xv_q6)YuO0h?T3OZ2(L@435mt7gp3#ILkTz*52uQIwWZmJ;p=*WoXB zkC8O561nM>4mMKUTSn(XxDsw)Dd7R>b5BCxl=L z?F0X3DG>~5>KUQ!0Qk~{AQ&R`Ed)cP4n;89qQOK6aSJRZ!Vs1=j`x4#Xp_Scnzm&y zvqm7;m8i9yhFOmU#wQZvw{fXkfJ^gj1f#7T3VP{H_z~em1h_Qc0iU2QC0b_N>r#B~ z@B8=C>`izOw+Sz>l!$~XP)`=3zflNQ5VNo;n7exVV&@+Z7PdJ*(BEhTqwQ}17)u_Y zzmY@~=WXPwvZap! zONm$@)m|(#R4Zxn{CU6rnJ9h8JJeF*9#~4m0ZUy|_JG}o*tox(&&ngRF4z8@;lV|B(w^Ewen#1r?yQX&!3)J6r4+-6t^U=`+Q z7gzR5nPvw|i6n?o8@=4W?U4!3d3Eu1!q<9@1(LvDH6%lf+S;xNeZJ4qdpwedCA_3% zyU1X`r$CGvIM7CMo!#?=iO%qVZ@Nqe$Y9n=MKHutA`N2HqW50)wB~3$uX!}kQzgqR z-vB0!bOb|88W{+NSW09f7;VusBAv(pONj@Nr5?PdP`u~;i6Hg}?wjrNN#&}bgAWnx zpAHI(WFgp@0FOGCwb_rE$5~nP#z%}F5D$s#gfm!5Jc4w|&KJKqmBn0oL))*lGTD+| zAB}GEh~)kN4s|wyA(j%40lSI2vPN8=I&U3(Q%bMGb3zjQo8yX2!yFlFO&uODC(?nX zL=Iq*-qSu-{l&e5S@Vj64}7OYpIRy;tmMvoQ15s{NBOBfSW4s~iqZzAEG6;~Zf$Y5 zhJnjVmhSjJdt2H_YGrhfi5wyqEG6?}MxQ z69hwC)t@35Vkz+qVrx3zhAcmP`(3S!!+~jAT0r$`uY3XjRlK0+a|A;aeSu)ZKRkBs zF;Xm>4%vLh{Ui5Ru#_l(81>w?OKde{;`h4$XG`raQGv@3!BV0SV$=ij&#bONEPiGdq^?3R+M?w|1yKo>64eMx8|T@7<7ks>5Sq4S zFtgSo*zNpr)hAo$J-0dywyh^Pd%>l-4#8+^SAkwWBMOKbq8415>%k|eONnRqpR`t2 z7^(exX?{lJ6LrK>u#{+kDo{@rqQ5T@%;TNU*-H+_-(8NKz2}lARS5dqh+wq+EdgUG zAN03@cnSLZ3hHl;s5RZm5euV#`q8ThDT7ji5C8*z#7I!vM#jt-Ty+`c655-s1 zz#5?qVjCVgI@~|?{-RhjZ%*GiVU8GUzrpD$vmn4;L+nmT;EKog8h$rydkVQDGHoyC zJl*EK*;*egCE6iIEvgnMdB3th)8q%=8m)kbZm+Y6R-%n~4VDsbAWd!5N4um~T}wFQ zl|`G1W1a3>u$1V47`4&%p3h1be!ZS9-Q~Kl!zw`tEG6DTjN010vqP38gBns#yB~_! zI0*j$1HKbt)WE4S^7i5DZ)`~r>acmWCM*HWTJI1Hv6OfZF>28rCv?UvWUAVC7#A*H zNtj>(lSUVUAtsG(1Vbz(J|Gxv(f33b(G8XoA0bOUcs{$X9;;v0mah06;QfO~l?`;T z2f_a7ps>g%1Upl1Bco+I{+Re#x&{+4iTp_P5ZS~df~5KxXqQ)(f@NFyckb!&njASI zZAd$?|L<3%01VtOPz~xtaOld}*_PmjJ+a4IGNPHT7=aP_6=JP#dIy_TY_=5TbuiV| z+bGsym+~ZMj!^#I?;FH+g%InijeC0d8jpJadYoHuX`kj}4b6r_VBq#bj9Rp%Q6q8O z@@e_Z;jSsUiO}|9;tTPW_y&HV>qF?!HCgwyW3u;sbogGBv29qq7yLrk4>@Wd|G9ee zkOvS9@eAD`f}L>X7#{w?+Vg?_LA->9u{9XELkNZ#xx)~neh+8|5f~UF2=?#5;2%XW z+SZ1N5#k*o7&`{+F|B>;be0tgFYcb~cAWGcr2UP|mi`g(8O)qd|2tn65Pjg-_k+)8 z69dE`F+_}lU+Bg`OI9Nuto(v6KMM?%{$|`;Ur9T_Z0X^41O+C*XQcXKncwYkx^#B) z7U|%I-M4A0Q+}Zv2LpH#*rJJi57)3;4o4UF^{~>X$JU+kvRpiyZAmo_4wTi&xfTi%f*cdF_&C$Uo2PB2W%Q*yM9Kh z-@TN3LD9HG{tnxMm_SmZhV|z|ieLcGK#W@S_JWb85%+%0fD;M!F4=>1H;M1W6fq43 z@DGF@vm84#Ff$lZOnSX%{bw1m88ConAxG^aVgUa{FvI|!L$HpkMDe_Z9`RCqMELEF zf=n=g=MfAsfPX=ZdQV7uLj?x#0)in1@FIfIw)TryAX32qUINyTUSEc(y<|MTA!+fH zEyEGoA!JMMOiY5O2wwkvcHl?+0LOk7eEvG|lb9psiA6Age}k5m4c?kO@{+f@>A&vd zM2yfg+5u)u54R&Iuna!)^yNK;ge3`cW;e6MUc2~d+Uk@6{2L75Kfq3YRgyS*SASus zDe#@-#IO!+`~UZ+6CE&s>6rd^08@V;ijWE-l^B`@Zw?R_cz-dDvgMi{V)Ggv)7XNQ zeTAi{+vlreg<{SN?1P4}Q-Co*ES_1b1T1Q3@#;8D*2Q_ueaeg-S`bhEb%5 zBuZwAjI8X6NKsN&S&{TTukYvM{XO4T_w)OG|9{-`JkQrX_uO;tJ+E`aUG%uaP7%lu za)bhLVx+>+IY;ki{ngUf(X~;szSDbrg%TNNpoZL59dQ~k4GzO;zyus-H~spH0rgeA zzb;uRwK`pYK?6o`7)}F5VfNqeM@U~TfCh}=Fq{TVi^E7uLlF$|0S%ZA*emFjs4v%6 zjDBbZYYiB;Y$I(#UgT!spd`f=huy)h z6#*ATxJFjTkK2+qFfVer9DcrS;Fvr6mZDjBiXDy)uT+imlv$BRCpKVugn!3&VC8M; z1D~_!?E)f2xM#oE&?Axh#*W5A&3&h35Urg2$FpZs!XTlOF!aCg zbt8l^!VF=KutC@)&>`E9?T97E4xD63XDY-@g*g}@nenu7;_u|E5Yk!DLGmdwA!Vlj z2gyTrkemwWDvAmUUb5{7GtM!+f5JYTpD91}?2u09>Wp8C3j+&KTX(~ga>2@x2D5x~ zFZpIHYv=g3>2&Dc)C>**4?1?@uzxO80R~nahVyiV4PqW%cNa@p_7~?Za}|Go%vN*6 zoOPG)nf@9OlpTlR1m(bC2~iZb2F8^P>Lyfm>ZMZ{cx=K6v8_!1nZar^?80IHT+itY zyKxxK0|YJ{MjDh8*@f&zBt*G!ENOFKLAF+D?1A*wZ%A4)=$?3R7*0C8I1DEpJ{(3G zbPvLV@Pc&saV%*%Z2z5(K7#;`CM_9E4+U{pL|$My$0@BUKGUaS%rV+);Q4|O4kL}t z2WrWN7!U*yLFBEpFgRlCc}U6y_uUDp=LJZw+T&Dg2n!;Fup;^lB2a|?u{C8dh~hAu zRT_J77-@aEKqFxR^%X%xL4C!b`s#2p){4>p-uZ8RSwMz+5e|gvhB)x&#dDsX%XV7Z z{7C%eh8ir$PLLrR!VZozAP}Q+BgEf|9}z~x5GoD{P|{1`2lh{Q#r=8M zbNRxbN9C)eC3%sHBm8`lKuVR|v8GdD4zw3dpsNYoU5@uWL;|5Yu@Bfpxh77!1h4H! zbbjbp>5WH|mim9!k2n;P0!NYdUU}I57t9g44V)`SVtJ0$692j-4Y4u0d=B*YCesHN z=W$OaKC@MiBR9y%y;T6)4>3CJ*paLPS(@iR_JxH7lABeVxl6O$q$4isJ^-<;Q$K!! zEAfTGWzHb(d%e`De>Ha_QiwFN9}IBtwY#2c=y&e`7z!PP+*Td` z>Fjnf9KvBt3*zhk8MS&zZ_RE`4t5)Z<)X4Uj3R%v^1xM{Z5!T?uIZffrUgSGIUM%S zP>4!d9?p*VJr~ZcT==-2x_M6RW~@T^?_v86&7ysifGI+( zWs!5b$0IG8(Ur_CwndO*cl{0Z_K6<~fE|O_#v;!PzA}$c3VFZC@TFGC7Zc6iUV25h z0aJq5d-JzCSr-s#JKsz@^~L8qxao6{vs_9i0aJz;N8~t%)Q){x-`vc1bD4d2QfnWi zEB0C$155>C$2rb=QQIp#X)jXcy`&{G-$CzI{CTc@FJP(=Yhk#?sbV6-`eaEguKi1e zhS8^3zqPZ5!GIlySZBrYI2X8-Wo)QX~Jrta-U;+16tG2!j;sow_al`2Lnoz7CNCXFMn^&2^tQUE&zF{-qU zI294~Ql<#9B$Wp#a@|I!B(5vBc>`t)F_Y(s!Bi14Di!z7c7JH;oJ)DEnN7QVoOsEc zhFIsC9o?bkC33Mts{LP!yh~lRvlkoIygmbV24d%Z3@!$~y^^h|L8&zVWZwOU^U=|e zZu<9tnLzBm0?oTC8C^{u2!_`$F|nxnzNg^(U1y&Km?^~W+&@CUz|4G6*v7I-``lby z>xqz$I$XNM)@uf_q?f*(;??`V{0-1>w058Eez>ONtdOSW4465@ve^yjcJj{zty#Zy z+jDIotcH&9g=5p^1Yi~rquHKR)&5DUjgR@xxh$@+WhylR^%S$OiGW!`?5}QM0neLd10jG}LoB0I zm7|W$I&fCdj`Grg_1)p9EI0a1h24PJK+HD$;;XJ8R<59kw_*F3#x4fD&UQ%?p??6F zEyO-1%@?Umy)7!UI-*#n-Ma4q>obM6{Y>J3*+J|m%TI&V^S^F9Pq34I-O{!*IojK# zV5*4*Fnfr}poX<>$(q5xw0b?X6)^_~E0Mb+E$kV9IY4Z{?U=ph&%i~>tkRHztV2Jl zr4|MRLUsoL<_Iz6klQ<&m@k_0(mSeg@#oNOH@?5XAfwp~m=nb2P3x^KFH6vg?B8)@ zIqf@{_2UPH9YJJQ0dt0#0o8pQp%D{9?l)qMl|7M}J&*s)H3i!N<^nNx#F<((Q=8r4 z7^*QUUwE#YeSx+nH)aqpSBMp=6qT0l{2X{OvQ*7K%EWvo)kyVk(N%ZA+#n`ZWLT-@ z{_;(^?Z-SLxt6>`Z+s`ureoItbBCDy&uu&@ZDZ3LQWJSESv4i}w1!)M)oBR><^eIC zgd4e~%QkjXG@a%Jx1?$Yg$de8g7)tK^Mshzj}v|R$A?DrPYs?7j*WRdS%1#r0}tmK zU|tY2XO&_txtm$0)^^sR*T{9f(K(Fq`=ynX#SB zI~-C(yl449ECcnZ?cy$MysbWy-_KFfa8`pVl$=WOFJQh98(Rr@>;5hE#0f_(f{^tp zb48GpnQQ*3w}AOUELei;z;}LwD^HJDrJD5IrKz_q<9%Ydd=D^xi1C}Bj@PI9y3t#E zsUg1hM+6roXBTBa5j$W35W8G=w`BdUL;ThEVeQEhzq;zfSS}3?#54Q*qzQI{@EN03oTG2I0$2x0=0 z_v}WL)Mr=Zg-;HP_j+$vw#hxLHy#dHFvK+Gj)UtF{rla`v=v9rjJePMs$zw11ub3zq^G^ZcCf)_n$l3&=jAFv3B#YRQDND|IIyp*jHFJe0sI5({nHku+(1Xv`*-isdpDB3jCOgkv; z@=12jbA}4%!@lue(SSuk>{e~Hp|1kt>S?tLJKb19i!j2UH`fR~#GX7FVmhjNn|i)_ zgO5d=?Qf+I9HPFe&$W-g_9$TIAlA!oepj3)CNuC0&#}{o20op(vkd!Dy1g8*7>M19 z#*}qZa>rQjwNRU@F78~@Z{IU9V0IR;ScviQZD#-UARiZ*;<#w&FnIjq{R4Z2KZNxG z76-9kQKuUyO2O9h9s8Qt`VZ;2%8)-AQvPKC*m;NruFQ(l=1=@kpUL|pm;FY!?_A&Q zcr3aDunQ2owCy$P=QeHa6w1xS5!%P~{lZ^gvrOdV0(KE%-cn^{A24x^29|uI;QCcP zS5J@3OW%6)0E>s1krO@l#dDuApY1Dke{X9>ZJ*Jn+}7a zXh`k|vxw#!{STHG%*vhvmI1MVACFu)`o{`FXzI=e{F3mXXi&X$r|OUwV3`nmHGgf6 z!Te8hL##pLX@VH-lF%g+x`gwVfL()_9y5bdqfrVgYhFB0tx@~gZ(^)-*7f?PfL(_e zHRb+>8@;1?4^j#*YDjylt68VyPj_F61?&dIK7FJtpcO z7Oa-k*K$&?M6z%Mdx|anK#}?% z%Yg}E7o82UPXD6QHBmlcua*y`IQ*JPdDqy!EHt^)m8!z6`{_?M61NQW-#g1Jc4#mH?LJwFT#44*aWu$!% zzf$j2iW0wf)zTy|d~8=L-wD9-A-3@D2+a<%Ud@(?CyOk#Wp(MC^IgkR4-vrbKy0l? ze4$Z@!5SU9B}bKYU>7s@g5cHKFMNO%K#cBBsO&A#ySzTfGd{mMXg@-h&wBzOPRo`xlpctsN~Ceo8y=d$o|} zL`a7gV1*D%UMer6ekzyFNm$tz%dS`DLaWr@zV)k+}pK7Uo<+9V=ojP(aP{<_vuO?sjFafY)h^fvw-D$X-OXeFF zBHNcU{N(k`Uxw#c8&v=+ftc>w=^&af_iGE$>U#5=rfR#fmt>UKkz~qy$$Ein_-^^{=`q<7E zEarb84&5stmSSn@FV4|e*njq^wxfz-*dnD(^s&p*#M$m+h$$P9(F8l>-59mr@BeeO zv!z4i6rrChKMJrX5WBGKvAI{YwAGWFTF)lpyvRLn%JXRMFmWhV2{FQwgP?5WzQTbD z?Y%1M)mmXT;l@jQ>VE_F6k?~C<4p{x#=mPj-dX6a3(aGSmAMhK^oTeItb&+gTaUaE zSz0<1!+<>XRAp$`-8<^DJ$s0)w;E!nrnsa+XAqJ3425GUvEyGHX1#Y#u6hycRs%7* zRvJ?>imS3u)e3Zc3%GJzDkzd8w)eyURtvHB_EDQFAJ2W=_wh&huk`1)csKVqKJXf+ z1*{HY8ksR!ie+K}_iikHq~dy-pR055_ZxW&;ytS#VkXuj{KN6mm=8rJ_9glrJ;PUn z#3Rg#Q-D2#7+vD6Tw%Af*TnUlcLmx#IvTQg_NcjJAn`#*1H`_@ORWFU$$D!xt<;iE zkD9)cbG-jsYrPb(=MZb-nyTSre7$9%eqtQ~${}URE7`7_gTR)1%&HnbvlrLgtLj)bErxt3pbg^}l|Zt^?K# zF?9;Ljec$#_JjHp)-49$7J2r{K^g`8>Ma+{h_y)ELoY?rno}*MKBx6QUma&pN2do=n-W{3w zJ>Qm6GVh-b}LVVd1s>B3I4 zPYlI_pWIb%31$%IfI|>F{n7PF#3kpM7iZEm6q&xw3c2T4I#X~FXKimFmL@V;sMf0> zGSfm;@l!(Fy4CI0!cdC~FL+t|7Ki=w{z8D^9S*~JLp%(zRTZyWlPjr=&cd$<BDXahk% z;xL?`pK#dsAEHsT46W(Cr4{S-8n@CwrV|j8E&Lnt`)bt!Im0XUeHwy|dkPg_6`G6m zgP@Z*3@7Mk9EOwW7l`?<1s5$Em{4vSzCZtS@?cGjtX9*TAL_v%=oAja3HlX>$z*FT zy-T?`7fj~A#XORcSZ4*X2@Utv^I6)gt!*n}JxX z=Z!IAF`+kFcmG^)`t#mGO>ep{f5@IVYnz2wkkQh8uDU3T>JJJxL#V#!9dfRYJrjL- zJ79AVE6Z0(u%WEehzmBVt=X0RK-jy3b(8V{@uA;5#H=HupAQK?I8uJqPmt?IAZ^6u zq&NJAiNvSJ3lO6vcaCi?G18N`uR3vS|Ahm;<7fgu4lbCdBo&)>iD_! zr~aqz`gkAlSQd67PEvkCOpm<&TYI$iv2<=nj#i40(DNNvo~xwtNddM9vBJFDQmZc3 zZho%(kIa#`+y{5++?JL&LVS+21hZ^q%Mfex@q~y1H&*85x^axHVej1swKx`s#UpnoI&Wl0;y|i~)!}%#Ul{4agiRc5i z3RvzR;f=TxW~Z;p%PACm=WzK`A7P|cb?pnw#worRomMuqUy95)}WwUz2!ga7{Ibe9EP(j<2Me&S(dSZ!$^a!A?wI*uq@*b zjwM}c@CGc)_^*H6Y(jdgA0{mstTOqF!*J3eL;ug~`mNG%(jmuTq(L_k5EBI-r^m6R z=?woT9ZE=V_3)%6gLJ5H7*0CWI1DEp8XQI%loF*vsX;mf97~$c=zr2dAiZ_(AT1fB zgW@opbTAx-lMXEoBMpk6D2jn}=x{7)I^+LIhaS>fcO}x2K|0%T7*0CdaTrcI3^
(fn!P2nfOmSjF8^C-;tIK(qY13IO#CsFr0K)a2RP&MwAI<2I=g?v83sI z`R{b}8CW5`b@7sx3|45d;jpPLkHw39AC>&dqn>ttV*3DAXtCok(%7IMK!=ek0xQaf zzLn+xM{KRo3SO4FwDjbc^}j2ghLJZ2JNgc+(Bgz5{Et0x2E#5KhVzfL-8hW2z8j!} zeFN&tiS7dR<$~&4@tpH!mFtPbf9v}O8Af)a?-42rZs4~i3nxv7&+30}9OOw@ld&gV zW%H5zzy6S;fE+=NB8tc{LCvBn~-`TtF@&@yI3QGLnE?K@yRx zND`8aq#&tC8j_A=AeqQDqOi`+tPBY8+ZatA3u?jrY)LZk?}j}#*% z$OEJld5DxDkC1Yt0(p!)K`N1_NEK3z)F8D;9a4`xLmH6h$P1(qX+mBi%}5K7@HWEojOR*_%eOcT%eAB5OWDNq{FffG<# z(C^Wq@V^KdK-aMYWdT>*PLu=XLa8|RfHVE#(B^!Imc!Wr>9qI39d_GE&$JggH_Fe) z1Ei)Hqr8!fz(PjNcbbjXLJGVUbbC-223}yd*20Z3vhAX2%2+V7KIwmMK{I-Ov~auK zo;V&b+~I@RK~Zarsfw(V>G$IN=d45B+#j{g&i~S-0E{1EJ$otJO7=J(a`_%Koqy5q zr7#lt8Tp;?8ZZHfCB7_}4)cB)Xv23q>6#<$gB(SXeeT@-#Pv*q5IbBk)O*$0r~1te z!`<#x-A2OnU1|@fnusGdA&AY9mF?;DUhqk@WPajRwCii$l|bj~Ij@Nem4qQCKl$g) ztUcE&#+CiYhklpsvlkk*;111Ks+pS_4Q^BsgGZqtuVAcALFPMv%(D0NVVB!#K7CGp!RyWVEMn`+TFYO&g zeX6_qA@2s_BX0?a#hfW(b-K=U>Gz4XjOEeKKZSefU&tk`5Z|szLhN3j>!_yOO4OyJ z@0jg-mIYgRK2~eWaZLlZ4`LpTY46M*hNbJTMl^eUdSP>)qxibZnVS~?lY$u27=GWzkL9dY+xlP6=%}>Z9-ou>BCD zm~~_=atN^%+Md3+#4a!EBd}OfImOrw*a3(=d=Meuv~w3L4oDleUF2`qmLdU_o4$#7GkB<+c@YK#ScF^V^U*i zc8XE83bje1TP3~fr>S1^BVY;;OAOxh zrcn)Et689#W|CTNth!iwx_j6yAFv}3yLD2*X5z)q#tON}jhO*Lm2XGb%7q>N#8ZD1 zVt+prb9!OaLpv@7?_N~OJC$Zk)9xWV_5(0Qh^4r8q)*Dk`;7+z-fKo=$mvH&k;cnHy_@D&OyjNx+mKCh(SReJO97{ToJi`Y>w`sd zSu~>sSLK474CViMY*U_z%(KD zoSwWOuw;JoSm^dXryI*dFU2~)Ubp-{0oVzMF(+J9;H>-Zkg#iQ*z}q4&dZ*cj$HT? zDhJp}h}BVVZxht~ojrer) z%9>w@{*BeH%T0@b=|XI^E=DCkS@tn^cc1?4Xw}Oxc|Q)vc-JcfrU$W%L#KzQPEPK< z9kkb?po5Y;&hSpdsG8;;!1N&|e_xg=arl=F>$bU@GHm>#6&6NP&!fCb05gCX*$th) z2Is|#Ugq0a%!w-(^JRx}aAt^U0cHp>+b>3`?!sfgrl)crSlnpMal>vEG_aff0?Y_v z=C%jKQjfKdHT{kH9(cE{{I65r+!gM#2LL+-v0?KgY&PX3zlGnWn|56tR-*O48<&4W z_&i|75M!Jaf4;4Ru|=jMM>fJj+{mNH%K!Q%^+Ui;L+mV-duAm^`$EwVFUbFV_swq7 zD17k5RjKpMhi6=fU5zQkPT14MOAk79Nwt5O6kbvE4DeJhjeooSCSYa|qYQuAWkA4N3!C#+*OI;SbZrR5?xv|57#wD$4=>=dG5Yy?p z@nX-_OtS~#hYw_X%)3R6-nh+UR7t#NSwbw3R?&L!P{WxPd3p}p(8ZX+1?)BbybKv& zRuD6!m!a{oE&`b0)d*M_=I z=cfd9%{k)lW(TpID=K$xyq_7`)plX+JGT&bMLGHF?^BNw0JDeKu5XQcpOBUfrPv=Q z1rML_Sfa|B_e&rnUVsh|i%P!NIoaoP|Luj1N&01udA1Oy7P@1eHh?)oO#BhO*MkR) zWw9L%nOt4ubf}*(ZA#P?;#KbiF<-;J@4LerODF9pgi(#kMKLAm#2r6UjR13o*ogi2 ziLQvJrJYJ&9JR95j2rCadD2Es^aADrv6ZtI8!qVY%$dFX&i?_$k>m;v)sMU?cbNcl zh1l}UejTQeyGA?hw<%d=!Q`{_xQ~|Fw6UdD8Uf3k5b!%ufh_c|c5*+54n0zjgU^J3*7Tjxy(S z`L)W>7Zk*k&J^@3RKdKx%D3Lhn{f&<^{1Gua2LQ8Qr5hVR(7^ z(VyXDt^gM=*Lr#%z`P-*^3Gu*XjjLbKf6vxreq}vo;{G7P2SrQ2bd4U?lTUoN39*c z&zi>e=wUkHJ4G&&G16NNp%fg)v>KA=onG3~+#I=2AA(kFykAQm&F5Z_0==iD{pH^Z6(8}`+K zbRRg5G3x^s3^9~T%dmKLKK?2@w{iU&TF*u!bzUY#`(nUCAXYwNCtMdsl~sGUw`W^r z_5PXI)qtIe7Q~eep%81nLG4t|Ddb@JJz(L|Q^_wLx>}4maje8KQW(UdFe~cZ#i@ZJ z%F$E>)>G@1IhnUUC=E#i77nrYCw#6K-fGFI=6RmDbJ@~A;G02HHpPoVz#<@KUz9iB zYIL=6N%%}HFVBUHpv@QWM^8r)S20FHj7_`ITQ5PchG}Byz-!b=eTT@)bHh}RiT8yl zh-rJD8GO>W*E&z;Q|xV916#VIHz*?XcohMQhS*2TKL4w0%=Vh~J2wo}N^;8V&q*H$ zv?cbv=O9+>$hxw`M99%UZ*I<%LwPBaGg;5gJ%xD5#6T=T?;`!jy06w$7h5l)?ROI_ z4mdW>#V->VK*U0faEXw_pJdoTcqH@E?q0D*L21T-+uY|Yz~UfAA1P9DO)uQG<>G}w z{h90|848=vO^a1|0Xq+|B^kP2^W6%k!$Ve^8a|uI)oQAybIGJF0d@gm3;idpYPMAz z%Z@?#rJ7`~wgi@zYSWN^0qi2gG9z|PR8ZZrA0aEVzDSNn?fM2&`9boYgTlHJ< zplWbZUN#J8?*B|qW8Ne%i%_V32J8~VhPfV==qYUqDtI2fML8XBRh<{ky~~W}Ent@+ zrtzcD*yuv1Q@Zy%2m2esDk1MaQZ6$166b&k5IY-9XgB>+{C&sz?RDi)JD$~M$q0t0 z6vPYg3dEwPUHDxC)rO)Bxplt26{6(rd{R4=yw%@XMwDla*TYk2Q6 z8wt#Rq7VqHno)R0oI58&Ol9+1;{3>i*f4!rb^mH={>@_TmbNQK#FY&x5L3%)4&XQF z(5`A5ZGCxdadz!m(rmYNGjTwh3bCq0O|pk8`yB4xG1(z!lA&)_o<@IpKV2=gIrxKf|)!yk@&9d#=JONZD+MA!dJ{j1E{q1LrW1`i86dLO)cr_5Cb zSO&yAR2}16p3LxXyDn=Jyh|2iw%6((&tRtmEE8f;tifR)Kj?%;9B6Voe^Kt#&^BF! zUP46@uxk)&TCh_Q?|R0SNoDYTkE6ZUwujeiS0zU60lN+{_nnLdn zsXg4^IP_`}M-De2Rvpj%Y%H-y?eHnwS zWQKzAKDS7vWGH{lkRf1M5HlArIW4z)l(4)*Q0!IQtd->XS;_NS)q#LzL+pij3q$WP zdy{tHKuDq_OQZR=;0yZf4~e&r9Ecg`N?eMRu{r24ynU8^U9(U%Gh~G!`tT-Txe&|q zVR9-kp40ygzK#u&B)f8I+z ze+WaR#I-N^5L;I^oOzJ3VY{nCyvvLw|4w+$>+xMdI@bWZ12Ly>W>IBPp&#^neN_mb zsx9a~Wgc_1mLuNl3n2DXvVT7}wjTF0$1SQf%SgQ>?N#jC7k9b=y9=@Nqi=?~h8R2CNWbjczFG zF>?#A%G{Z|8Uxiu<76(se>b$z09FJss#>0}w7lx&A4#t%wTNqQA3#hX_HwsxA!X5#qE-|7LEn!j zo#VU`-VuoBv=m|w!XL_JB>$*9z?q>wH4s({{wtbwN4Q)Zu!j(%lgDH$K}@n#vsC{~YG?6m7@xqgk~_SkK^68cZ_mDLXVQh+^z*yZ@av0WqI zVwMOgwi^#RPVM@7#6Wr5TTZ~rA$FaAHjz_YRN(%^(^_->ox{1ye`6hKI1d9>0Wle} zjT4g2g2!`N{X%~jy9*sG__&%F#$^rIV~E8e%VMJB&IUIPp9@^~RlQ!wWW=>0{H_(S zClJd#e&A%_)piU17V8-1j^V`cH>2^F83(-ptAtoO zO(R_Z*i(o_TO{6jxP8Zh!H4|fhq~ZMK3247b;aj?6S;Acxi)5b)5N-Y^2)4 zkE)i2amXOSId5hTV=^@Wi}Davxwd5YtQiuv;@o!0Fo= zvokg;({v3-N}RK@R80V@g;?tmnng+Hs}D2M_wjlQBvpSDb+i+MFqu={9zLUvqIZe%-MhwKM z;wy+PUHv?E^h=S;t-8 z$P2WrKDN?~IJW0o->V@Ivnwr_q2kQXq zhnUq4H`5eNv&RDZ-OKV*&;CT++aow@y@NQ+8-SQW=2yo^6HmI-Bz?-fGxz3w+e8lJ zHzpJBr-Kmt@qFadHM_(TLtATpUn}KnkN1VeSUDa$2-pzB#(qq{vHCJgsI=bqEr8a? z*}mjyid(1#aUAjnVxwy5U#g{DMqLhnOi3v<{nr1r%zTi0h}eg`g_!Iz-$(KFgY8|r zUucb`EuNOhW|IE;%#L`Mc?Yq`My5vcir~bLstP6a`#C>57|vRU4>$~Gt;0AD zBMmx=j-emGT8ED~mh}C7J-YSXf=`g%>N!bE21_?4a2QTHlQ;|~ozFOoH0URE0-Xfu ze8I7#={)~WI#ZC|>XS)J2I+joVL0hb<1n0bzTq&^pi}5qbQ+}d9mkTU)AXNoW+1)Q z+mn_I(wW6!IO)vcFr0MeaTsaP8FUt%1L-W_SkiP_{*%rRNN?RoNJ|Fk{KR26=`7+f zoOG6O7-`TS=udPJq_d1;Nz-}tpLA9ry>*8oEg7VF6{3hV=i~6=X1M;4sgg8n)-xk_MaoS`-78bR)sCr$0E1H1=n3g+E8* z2*1${u#9LE9I>_R=>X^a>XPAV`@hSGo}=~XAG870XZQ<6_#b=X3X3JrT|B5)%X1v(}*$G@%4Y}TMsfM#~M*83QFMP?aX59*jHY# z+5EVj&Q4v%W-HVE$;-~~FiS9$CP-%2OdH|I{ z52A-qSyT>{M-QV4=n?cNs)!y#l~83=1yx0lqiU!+s)1^vC(x6q7OIWvpt`6Ys*f6= zhNuyG3N=Pgqi0YP)D$&C%~1=~6176DQ5)12wL|Su2ha%nuq42chCa#E_x3wM2pb- zXfaxXK0r&+hiDo42rWk|(8uT#v=V)aR-x5s4O)xVfphZ=vQq=b1r4xU`$}$Ypm^h_dvX^2zV8QYj~vam z|0ZZm+!t|*tbyV=1tY?Q5cid=qNoG=N-`r}U^mJCuU#Eqf_)U*D4HocD0(Q=2$IOw zZjs{1|Jf}P-t@|VAOkl2I*1%XWDz;A|K?%jf7(luxL+g>%8gQEl$bNveUi9$qzx5u z_ecUxN~D($F&|+L1d{ciMS_3Doz5h^G-b%Yk_pM9{|}OvOop5q=nje&itPx7b3|xa zwy{+RYr}JI--`x??X~Y1XmOPL(fN!dhsr*t&*FP)+a=V&=b-5T+gg}*AoR?qU#*Rw z#QtQ}=JYx#Q-(f!l&<@&6zoMtkHc_2S+WhVz%;J>YcF)TLw*`O$i5N7suAeMNp0cg zz|kwCva^BbIQV4AcEE(2#pzvq$WMGIQnZ)tkt`>@y?{@aFyI6wWyDXG?7(p!X+&rm zCqJ@pW0uQ5TS}+&jBFdW9b>>;7#JaaFN6Ms!;!~&k4BDAl^T8Cn-T8%bENu9E|{b- z;V_&@8Z!>VnHjP`EU^Re=tB$w>1xHJvtuk{bG7sz2+K4mf}lHb7*0@D9QI_-=lQbH z#ngHqGJl^=!RO$UC2SDeI=3Q@;pYy>4>>z%hsg?vzh4E@19pgQ{UD^bXD}wI7up6>ld3^a$?%uvcEuuUrtXjZ8FAqLh!UeIdJV>uO zM(hRIZjAULRc=Ucoe|OsfUNi6Fr2J;a2QV3yf}YEEpTcj|qU0g%CJmYhtx~7R|JQR^-Jptbu&yGI^T3v4Dk61>MM%F zNb9=`v?WGRUtvrH)ORmb-#)?th5CgtX@qDv~UgTg|+haMw zP7eptdn7$L8#_P@CXgWuwi6u3h7qH3VZ`5x4->-ng1fCaD9KH~fJV{zHG9H|<&zTR zB}=3wd6A2OyR8I}yU&Dl{bb|%N^4SkMs96k1aE<{IA+fv2`p(pJ}vWsGmsPMZC?&! zJ5;5b4|dVq2Qg)uedC|X1G@7Km%AD@epb7079134WVQrM3S!=S4Hj%tHGb|nSUafV zX4OCByx>9B)+-M-+mwdb)`htciAHYNH|EYArb;UGc+o|VNn-mjDJ+v=Kcu$`<&|=D zcB0W5+a;yS$x?gH2Yj;R0K~QmeMh5Tv)3^wOM>i+o&ATRpWu@vG7$SuY0j=9Yp@N`Kc2deS>gMya=+Nx z2WV6*)aOA3kKnL>Dkvy=6oW3;JPRG)2~iitqWZ$*f7I! z$Zgf}pS$-i1~nX3uoUz;*||!LiE1MGE9bi$uuH5u4in~i@G7nO0(_xCB=Vbox{*nz-1;71qa6CPxhN)v3*h!2^SsRqp+u6Is@kFmzUPoDT&%PxF z(gx;54wu8vrvr`&N@lpCYImol^E>;~aj`Zh(&)qu^R+Sl9lF5gCvxv$<1Kvr#w$Rc z>?jA{KQ^2~53sF?&DPky;iYc+gYi2L_2@AtWSi7)H{y`}D_I{!KLvuJ7;$3LLGc<) zY%uIR)g>x!>OIsv)I4MaGG1z7YH?~QYFcbR^#N)b>VwpB)Q8FCsSi^tQWK{@$EcO4 zm8n&zRjH3tYf{r;5|}i$A3K1_U}D(8|NZ+M#*ShqsCUuqq2Zz7rQxIDpy8(xpgBn` zLL){aO{0bBVE=zx@^5X(|6kkj|GOE#5{(LtE~ZLDoC4|NBu{$ZBxWwmVF1Y{6D-W? zVn!0_J$Z;?8ccx<{~shD*$@Q{`83%$#V`dwpAk4hw=$#mn$(EGOik{y*Vr|~r5wqy zvTVk;)(gsg-FhOF#IqVpCBF9*uw_vv4^vHvG!kYstPJ?c+x9na&-HG2w?CV0(ENdh zZ4@Q2FUX9rIYwik?TTE~o5YltE;9#+bUl}Ho>a4!HC?2dSVuG97zRDp)*XJRm+{;PqADp)e|q6L zcBI_tDA!eM*U4?MYM_qhfbr9&YqnTulxfm>G>&&o+$Sv#)X@Sk-kmHFi|D<`?2SK* zpSfh8l9u+2%oH=j%&~L^OQ5&LBUPnJOg}&JinLqmOYu%MWwurgA}o%1vQqX8RyYjZ z{!y#LDE1_6Nywm%;E#FGty@E^ZGzs4X6^Z2<`Wy+5x+YX-+95op5Bi_RWTiei2~K5X;Nv5XcR_GGSUpJT~W9Y_&AZO&6-f&K<_WQl zWH+#Wwj>>WD%LT+6oI})$}h<)E3vul;-TH8&- zCq>MYLFZc}B80~JBwGPH3$bO%?4axv<;lbOdKWvQ_?dJRmhU{+D|ia9K#1*@@hxtZ zx@MomDbT=dlH5~hF?#)jg9;a5K@dCrE57~9%jz)IxshNcGx2(vQaAmu={`!pf+41> z)5=|AF!{KQ%IW5vk}@h)Q!b`><@@V^g+Q#rQ|7o+fMY=xxmS6SjHLO;2U&Vk-)1`j z3x$~Ut+y%(K=a?`5 zN!q+(F(qnQBj0%|=;X4Vj!m4UN@m*Y_y?~<2YhvA5?u=XnlI!s^A)6u@E~+ z%aJcDR@&YaZK{xW5Dhzf|INhWMKLO2z@e z&O_|fU+(x*`Qn9d5(`US96rlpsJ3`C>#3(CU>6`JS$wQ`7ow#5Dnmc9rYzW=vPNrS zLXol>u!|7;cD5tuv{aX@%EJMZ`$>s2)8C#4l~~zV02U9iHs84~H&53H)i%7i9>~pU z*8MQ9;L2#w6~Hb*%*Fe?_FL&2zrIAO2MG2lG(4Jg?pH4w>H+LB#Bx6Tkl>Sz+@3IO zcTSnh|I}5~B`COS!w#?nh&{?bBABKqk?B{VzTk3L#m?&O-jTbK1G#`*ff!}N$w%#% zil%3n>&~kiJ_uQ1p?&r~LXLPXBtmS^a#a7ir&D63#?<>mk8BTq)UQj}pD#^py;mV- z`>MP9t>K&NXnimB@eJ(joSw{a(7pyws!A$Y;E$ig<|9=e>2Tx`DcYWkAd^;B0vhQ&Y>E zT~FK>w8Ku=u7ua^WJx*%SSG}#B;wwR@~LxYbze#O)ajeMi+>w4MZra4r+N)yce^zX z4_Cgk{rgNsG34c99wqhtw*s0en1Kmjnd8h*4u;jfus^dD%f=N;cz69(h#B6R)y}c`fji~j}^<52oT0f|2qg2hV zpbuCU#MrWeB81+D@6D+YHA{@TvHMO?q+d;@^e|xA5bLFW#Av$)zPic3zvoc*nDlz= zSXFJ@)jq&-AQog9;7nHGEqRsgXN z8R?D2t2%8FsiRN3Y}l=9)Xt7}Mtu(l>@LLOE}cv7S39|0oV~7-GshLCu%boQG7%L8 z*gc5pQgaJsw&~Yf25fx&QTwgna%FRamhmYuzzQLD=<)FbnP2wjv@ZoIDf&=zbhG%Z za}V|te~==GO>+#ESI|zbEq#fmA^VV)Ag{c9^I?S$0kHcJ8{*qeNN9d3m0#08s%mew zzk0OMhvNm<3EY997-Em;nxdQAUh-6ZncJ5UboS`)zE`X4u2$NBl|YQoisNWfDEDqj z_Xbmsyk{PP7VS4ne^Lnn_5flT5m^uKbJgqYcX zF{|gRqMXq!qnrpo|L>|kktY!1$l)Qx>d&@n-`w2M*vZ1IGJoJ&RQ;Fu7z_U7EWpYj zcCumL)7>qy`I}ufpS~M@u3p&x=c{Ud-6<(YiboLJnxyXyAW{25h4wxh6ggIj_m@DRnxnmxfC+3BDV?LNK=7;%X0oYkA5DUVBu@Ed2 z3&X;(2rLqd!lJQrSPT}6#bM{M3)n?09=n8H#uBhASR!^6OTv<|6f6}>!_u(~EEBti zUB_-;*{wUsN)b*llPzMfI=0IeE_p$!%4(Y{|XyP=U4vne{_ z>#rJ!ZPo3cHxb$lwK$A)mMkU6TZh9)ORK?ZF-z<^Lp@}-@-RGqAVE=ZfbXe*=(M=O z)p)5KhG#hJpHrd5(161@zL#=QQSWAs?h%^&UyR*%JeFVlIDWIZuj}SEvdPZgnJHvs zWJM%NcG)8dWh66|BvBb9$|g!y$X-!0qDa|$hNR!Q-=Cky=R9s)7C zXWaMUD;OLCQ@=F?*gtV3;A#ml0&~-K1lZn(zQfdDYBAIl?}6Q0R)$rZ?=Vsv;JWQ4 zoL*^@l329!tjrZe@w{8QVdFk^^5cm3-(oDvpHn=}J<%VU%3mqiP;$(fs0;ws8Nqq-<@_F)x=FYECKUWjk3 zvWv(cY?71*tP^5x7d{xq?VPZb<}2yz=qAE6`Y1lvT(oBd>;uGf_=APgj#J%_Ke0u{ zFDmr+p2<|7yU;Zmz`7vzfYnyVTj;!-46(wd_D7w@RkaApog4Z40PBWW+u?qbB1T?K zr&t*}^1HN}$LnONuh5>N1MDNjnib+`GOBEoIGV@P>^k?GC~azQ*oNQ1&((Z_nA~u$ z$erY}4_zPaPhl3r+Z1OKJ^ z8Ddl;!+9pvA^o%yT5_jGujNQhPZ2N6aTiEBT}??Bk@U@0 zOdF;h(}C&4e86;Jx-lOypD;a`&!9x~L08-V<(06y^COu+iRdT5OnixNXCJ`biW6w9 zv=XVi50X3pF;~mNv$={kc~*mJSr3ac&s-EMrS1=?O9$)=#6G!lxICQ9<;Yyl5HQzb zZpXblraQ#hNeY%x1|hbaHe`Y%uJM|CRd!~+mf%v8O&_KoGl2O5A{l~o@WhwPj#iER z1S0uLfL*?mJR&fD)$2h`Ii*G`2@^=-H;7f&o|nwJ-A8|ig3VX*Dud-qU$fXl$B%~r zHVm=xT8{t~o}v8jo0bR5+h<&E4-BDtCW20YjX>-OUDeS;9j8(SGy8p9m$W1WIF1&4$G)Y0rnGO0=Md8no4BT0v_5` z=h-%}zL7u*SkbdJGZ z!Xp{ zd;m!FEW{oq4A^7KxDGCyu*<@3*6KO9ycEW-Q(mISWY+n!DUQ9n$Ck-{ zsf$}|ZRQ(b^AJ1u%&pMoM(W1=k#p94O^GLOOltLr?RVk@Yyo0%sgY(&`eC9Sf86BH zpUe(A>F6WV_qU#@jTu1M(a3lUZvJ zyO&8k-5VAfq*n5@>3WSG!Y5+6cAql>KXhD&SXsI^m3#w-^esIy@-ZuWH-7aR4zXXJ zj{y4xG1b1+qLW-(X?d?aW|pF6hW-kNHtH6>#IFx;KuqZ1W$EQcO22_XpBtyI2)>Q~ ze&yZ_rS=WLHX$~Ak>^1|LX$RI6xXHGA7r*FtQsE>m-^$!(pwPIy5l3?@=>^oJiaXa z;$r=b{>!UYH)N^sqmkbbGm#E+ef=e=^I|I>OJBK%nU-u&fN6m)zH{1!*rPXnrZpXl z5)L>ryW*xDxp?UWZHXN}CBXhbY$WP8qsU3dm>k>i`QP;iGe4Q=NG9(wg^PVy1^#Dc;v7*W#vL(UyV~bO1RY!Z|BLE|T*eu1%q)~mTwQ_nEvQPW!9*TV14%ndms1Fz^#HzDBT&8>*_7`ZHysAp{ zy%VET?*#BMuzyJr|jlko?)Y0>tC+nq@^@CshZ!p~BXL+tM9KYfnedQvS@ zyw4KTub1`8+WFjTD&GWbAH-^X6;3V;4r&yBywp}x$)XZ7EY`d3mxLeI?uS@UPg`}Y zJ4afk?X@dHb&)S0d(^6pDU}ogMgg(9tzKvLB+%9hgf4&>C)G<-0hOKFXJyty<6}f92khbf7)g^xGBKr%p8WH*%{JVwx9K4c*2V> zmI%a*YB(7K-gqTvE}eO;;z7?i@eP?c_o5mqUj0$4ki(H!RriPFIlK1%St@i!U zqgFLahjnxOyb?9UXx^Fy>9wn8-k3|C70M$?6!?h`I*7HsZn?&L#Lx4jD-rF`Q-!*UON=Zn&dT`SogQLX z(+Z3I`r`Ba&LmUvXNO)Z<)}B^n-DSv>;T04nT@QRpOZfSPV}|hNodW4gu{5m=jby$ zV}RI`lqaps?4+TRhA9TTcG^!yY~0TkY{}ypBg9UecOsR^`6=sJL~$e}3ferd>)+D#lBLba$=k1e0Wfxmomdbx{oc}~ z)@I7S=5T6%X~ z&c2Z&*Ax%CoFo}=O~bw83uoFlbH=}33oveoF?%h2d=;Ho7dfd&)scAIImwunIPGCJ zKVUo%d+9wy-qR<%actowSo;{OHsX4W$=LS`|4w-!=4waNpD=xA?2-P=mrassUiD$N zR?Yj>)`0OrjK)iwqRxP*W0m}8=xp@^IY;3M6$Jrq{2VJk#7OV@?|0^UlA==I{%Rs} z=CO2Mq4M99h%&$qLCou51pjP8dSUX%{&yEewaaeY8c5M=tHG}v3qWj)!C6{mkS5E~ zx8ic|Ex&*c%<^pdWG{XmQxIbLb=#}e6=YpIYvuPVjy?No(fK^NL{C5-Fd>N9Yh~f8 zY;&x`%6^C;3L0edPG5hze=x(BH(`in#*ilGM;<aB)7y){8rOHdEI05EpevEy>QYW z_%ALoh&4LgT;MdHwm$37HF3vwh**+jt5E7yHGb$Q4zUB#(s`^V4_-)yHCeaieQ|z? zkx8ohhQm+ANef)FJL~31HF?i#92>=Xv1x zA=r(Q&P{lkEoR(KN#NW|E5KwR#<2SE@|2f%-2Lg`xcC*9r|V}r8GrxC$7k0xG z4sB@F@{5PjdNX8?=@`f4S4(fJ=>jGTF%Blh#K-lG0wg?2KSF$j^u@(Yaxz(q@ay+- z5X)j=dp|8S`kdF^M0udArN>&6sdN)QuCHSO>=W}|UCdW3!XuMLsZ!TzM`=hJrpI|8wlwDQ&9;Yl;}V0%ig zc0FdoKhhtUT(=0AGQBsYw08m4KgZISMfbO&gl0oMJw5 zi>t%7GulzJf`_yG%6rZNb_`<2Dw!w@m^9ieij!9kf1zBSXnHLl@bp9zU@8z}EscGD zpDpR`>8MoNHWT|htYaJ!%~@i^fT=?4*z4Qv?kb7qJE{#~WfJFoMn#Xs{ahBq7fUsW zRXrXf-(Tnw=cn>xRC(cG;#0rCq9_?zZ@`X2Z2rO-i4fACM<{Lz`pgYFWng|fZ4WC& zHv*;(vB$;6kNWNR8&Q}alUMc*UDNM+V0*LA`3zth5YsX29C*SR(nHK6wQU^9Sh&`> z>i5p`0sf0i6JnCHB)`j_CA~>IUDjCi7ct!OT@Kurk-`p`7Q_NIMXtnN)qm^h9d=84 zX;%M~q)A~-%VzA}BBF}(Wl{nM?acaLZ@Zh8{Q0;UTw2FDb! zSGSg!hp#2z{t62Dj9?$ljA{SGFCXebjHijNSd7kGD}nL&nKQ22RG+-B$@fo&Edh2C zV*an5s62fz%jhSoU?y)+4nCud?z)HlH-OTI*!Po`b@||nTBYeIYLX6a>kYr6P`k;$L*ZtCsvZr0& zuG0TuTqy?32x3-8$8TD1X!Nj0vEGxvAfECqhnB+tUBkaDV~914FZ6I(b_M&JrM>vX zt2>=}wSMrx^-HdRoq`x?mMWrOJFlGfCR|1KjT;$VNKiz?8WBBUCJ+m*`&;ucA|i*P zSVL~|>L*9BN4YnbmkX`}W(u(h%Ei~?%V#gs&&+lGZ^8bP$gn*A5i%JPYsU2OQiVZR4R;!TeajqT znkmtri{&nC{&jjr9aLKE;UXsHQ%Gy`46rj0^HWoknKJAxyrsM?(C3#f-+8fHw_U*^ z4KNFc8CE&5t{*P*9@xeVh)H}u7X9T3cdAIAG+<{Tb|Krx+3JQ<`HQx#^CIm2d6D|G zQZ?)(9)MXw?978&IfK{!-=cCAuD+abQdQep>$8a;%LMEk#EzL2G2-a%UaNQfd~@oW zJoBl|Gr`NsL6v}6L2P~TytbQc*wx#uHU<(zxx8;TU%!1)Y=HkTI}fpzgMG(>n1UsX zH9}iN_jBm4yeJ~QJwuG|jI1GcE+up2OK3ra8@CrLtM)BvatST@FsWhuSmpx64)M|* z_Q)tro@P5`F~%t3{JdzG3+H{?1TY(jg@{d@J0#+FwDLu42>r+8X3KJpk&^bcD!^NEPx3`uK_A>Js^?-V z0f5;y2G5 zV2;aU(FJRkju6|O3Y&a;`B#8nNcw#R-+ODF?J?J;F*BH1%p7JOvw&H|EMb;0E0|Tx z8fG2y3$uaQ#B5=HW41AWFgqA9O@I(1BnT-&hL9usko^b+LWy7y1VIrjLWNKxID`hF zMd%QEAhzg>Ls3FG@bwmTvM6{3-h&G~w=puT^ zNkktpKnxKh#27h+m>{OeX~YaMN6sJ?$XUb^Ifqyw=Mih<0%C*MB6f&9;(#RLoS+Qa zo!t|l4*ps_WPIoZGie<;=~HH~4tfz{yZK099rO~!cJKDj;#&gF8DbKx;ul;V1hx>E zpmZU?Iw#zwOb4_{2j51XJooqCi|LkhT0iZf2!%VplJEm+FNk??U8ZZ>N2fjV z9kan1cdy2-EfJfbYhewR5xgO`n>H@~Rb6W);Vgh=vqO0tviIfCU7F zwpV@4{zA7b4#(Hl=oZ$*6Jx~W|znsWE?{%T*}k&hxEfdLTPeW=It zAJxIl<|LWVYx~=WN@D$xtB5~HU?5~24LJP=dOf=cB=8ym#yY)_bp2Ie$ztkXJ5lLW z{6yn*hzTrQ{I)4FG_DaUko0X!{302Zt-WRigB(a;5X5#L8tBb<$e-qg&_$zAw)ErE zbb-h<G z&)}4R`?!j1x#uC@VlA*0{RRP+<+IXUXUI0|Ye=JglTdcTshZ-IrI0u=pli0wwIa(mOK z#rtS;%Ml+QWl!DY5ab3DhTH^ATLh$cpFK@3A1m1XG$3i&plCAPl>#(vkr3OxDS@Uf z3Szr=`=@E+!$m`Ex1nV5Kc{5Lcv$qMX2o0H6uw|dHe3t=_Fm|YS%a*+UA`dI!=urC zU%=jtTM*lAPxa$(&}!0q1e{5q|H8Z?Q3UpG#1ddx1F-}CuGeTT|ET(P!r~7f*t>BX zV!LU(a@fP~)R=qlo%p-rQN<;ZV9&!H0&MS6J=nW(mjK&)x7)}aWE$+Q^`JV+bt55CEz!5MCG{1E<30iQPaFxj1Okk}-i-$Y*xrZ6BlnR6 zgqJ4~Sm!?V^yo>Dx=^ zM(6(7>)WZyFBOxAuN+uV@H6%-a}ou+G9CdIF1-B5PvCF8%(>vXd!{@8{IH286RE}>NQX$rRJwxLsQKZG3Kz(;sxb*y1;Ju8y3?31Hr9mwDhvz91{i2W< zbyD-^8@hGx+cGac`Kn(8SUSY`wFBf9`k(1&IFvg58JIU-Yd*>|GA0}e*i(p+Ta3iE zc5q+XpYR}&I@0fwX8LCgt@9iFvhOp9O?Q_)OcgG2H2EUAbWteQ;uTLmu0sDLesUrM zVwH7=DhhmSi8<|DN{g5LX?-%@wJ)8!CIQ%Uh_%mmt5po@nr%J4d{$jec;W2(md*Le zHvD9NCd9_14&P4IhGPwWkF0|(pymBv8s`BoZ92-o4&CE zIp(5rMYtTmUO;SXI;O?r%a67rg8ovcEFa$$dmR(<@No@(6!;QiC$^6AogK588RqN0 z6w5$OYOH%F+3J=g{!1qtVyDA}SU2e&b@yosxJiBr=(&E1HB&cG?-5`*5F@#9T9`Uc z_k*o2m4sTtweJ*|b^3OqpN4?tLM-&z0&(l%rUb{xA^(+|o12QcQjTWccKDsEc@RsV zNXjU9oM?OaG((%(S5u?kJ5I8{9b3r(%ZC^xhmHBZ`;WY^qvs@+E}Tp+7}TeY#GJ;z ztOAIAGfuL~lwkIs*8tSAKm6@jP|hB64fcLLu9i8n9xBeNG7p6Q^&luOE)g%sks^ zfTbl0Y>p?71MC&V`fgtBHF@8xj_^HCq!J4Fk>w#Tt10;bUwTU*7FC2L%UKAVo_+c? zcWRY)&{9M!PgT_iKW;0981>4zZT_#GE`c96xo?D=vtU0|U!kDmNCntyh}n30``+{D z<7VyQ>Ww;dIdrtQB43`A96!PN24dc})ek>CnF-!k`quU@&L&hq3R@Q*$X^Or8N}oz zClAFnA71g&SVcGQJ+7-rQqq#~tavl9QwG{5|7rGt# z;>t%Iz$zhD(1iyvTYA~hQySCI zGEk@W+amD69&bjmin>wmcdBfnDTP1Y;Y9_YAh?r0BK z1H^tcG*=>v=WF>RXYL5I;ApQLKt#@D{J_s7HA3u`tiM%chI!QB*qh=4E%uMonPKnb zvkUPva7_@KDHlznET@=Skf0n&upUId+uWqROybZ1STn>{yx6IJr1w^2$BInqeXc)N z{J{DfqhP~1z*-=dmhKi8m%OI9Z*#sXKR%-K;pWwol~Ll40c(Yr2zi%C#y3l;C6(zw z;X76fedTq}?fn)_0c(R;WvS2+tygB_M?X~AM4P(MIk?;kJIyYPUtws6m`X4BSKpLF zJm%``mN$!iBB(QktpiqL@b$CD8NE1KSdVQh%09}b~MRjO+ zhtEyGK0<74ZF1T=PW*1^CWXH=Pf~lYa&N-;4XsVUK0&NfrR>%3{V{&b7mGz@JPX%Y zQmQU%ZI@~S)&nsuDq7*rvL`EFRkV1HvEeYnTf8h$siyey_8DSR0y{N7V@_q(Xyyk# zK6Lv)<*!qQNw0X70PBSqiJD4#ZvT22Nh9}W1#QP6Dex1TDmHO*!1^HOb>-WMfSpb= zkKq0EjL#djzIzPl3DlI}+mL>UiAEdxnP+`I`{QfP_2Tu#u3v&NyxEu+_;sEEhy|E6 z>Hm4_`Bjuro8Q`tOR7OVgPfX30bhE*KuqUi_fBwTyu{9Tl}ygqw$HiJ@^+2uw&wvG zgxIqSN(Psl+*58Q&#H3CO|C^Zi#PF~eu!U`8-kdz{g`R*lTXZ#{RYYC_!J_jB1VaC zY^A&e>?_3b?kuS*Gfe1rJbqV1EP(6wZew^!&m(mmux}9aD=mzsN4|WSM3zjRsHUB< zj|m8wJMDm<@g0WPeG@A(|5CkGrq^GoKOZd=Vtyj%^oc=r60i}7$*JsrL;uJ3^6CA} znKN8}62xzmz9phgNd@dX#B_;hRWjoWLoNQ;jMZ&#m4-I9HnG?U7G0t z*f_*8-k03x7tnV(Ayy^T}vPgbR zyXx4RCxA^tY=+p4VyzgQyCD=cFHU7bW%fCjVoRhMUl*nzHg5OKcS&pWi?ut$7rrBZ z-8tRKUJIpF;5P?NLu_A^c>CnR8P(%nISlOwxs$)pDAsan?w%W+5g`rkX84|A)Wj@x!(HK-Z(pl|A&fcP9M+n}gU;M|K$k zPL{XtUe6Pn4!ye_p<8vr;Sl}@=$& zU`r6I9HL(LY&&J~5$n_|)HXId$a2f!_pHnoV9OAbv^rb*p+@tHIw$!s>*AHwROUX0 z`;^rhfUQ7`Nkx}Dk2OEEz0ay>2cvKllTWL7RrMQwgW)Q~Mn=u!TMh&~=f1<5#`j#3 z?5<_Fec6LMIKb8*CN?`0deDJUg6P+Rj9KMI20PK*#Qi{Z{1^T@#4IlKIMK<6qv`wn zp4FsEMgQ(X!*1r!;KvKUAhsN3f2Y@6Fhclb4-I^~o<+_uL%g zwxmNtyx}5&FM_;%hW~TWpuErN<;1ziW~x4!ZKvq{m`t6aSe<46%z`gLW)B zZF)2_g~3wB9P2T09yA3ND_ww*K&%@(;PE2piCkDfXX1#x5DBrnErpWfDM!FaAr^R2 z#i=kMrlT?6J0+yoVfAE-#-!5lP8(ok5OcA=eDBgv-;-^3zNhEN@9W&jpRcTM(r*Hc z9AaFIeX*Qp!^wU~t!Ro3d+EM5ndDVJr{@9KK8PvrGn!Jp(aB%gID0!<-Kt^p>KN}| z`WYU;_CqXoK)v^X7OQ-`oJFDSRy5VGnxCxOPgmFgqkvdwUo2zly@9#Tr&B=^=lETw zmDrm&7==FqMhUTiCB5eUuBb5~x!U0n)Aw6NkG{>54{m+|41w6Knw*OnBR`Ka3xxALxPz$}V6J$oy})z`Fce~!DopoD<$RKV zIdUe=YYjUakX;sXubTwlJ7Xah-KW~T(P^ssNo#`mZ&AO1Ux>OZ-9ljlU{nw*F;5rH zQS(i)`FlFEdqU}Kj5t=Qu_0~(Flva6Jig4PF72pwJdjDbhz&Q}Z|R2+sqx0P=b0~j5|R5XGXf@%srFpugFihL1n6DsQv zI@(aX0~kHThWIm_LwwKP@iQOk`9faDshz1pSsyltZ+j0wtjY4@H<6CpJf^c%rDea= zxX*gaE4XEt;v0Mhh_#b)2MV5yd%t9SVM+A~(RE^alhwF8+W1<}2(cKQC#&KlTzSL+ zYvEI)<}LaZSu_c)hduzt1hE2^_zgz;g+)%AnP@@GHQk%qOPzELTlglL8Dee*JNs;l z^>;qkG(Uam=lFeUduZTQZ!*5yWr3K+0h)Y=-%RR)^O!>^-vWojjpJuV865Hb0xQH4 zc1(=w-kJ|!OYAO)wMj9TPGyC=zD>k$1ZIO+HnSgj@Q+_!8`%}9hc8%CRG3yZbTXN} z28x!lBo%jhgD``vK#G7?a*Y_=_n?YL{c17Gi$lmQe$l8U(v@p1s%whe{tOsD#OOUb znQpnB4#Lq3Y=&?38S(?e(KkyIb16B%FU_+x!qV!aI!bp zIS8?eoH}18=5Y6y`PV;2PTVYYWZfC)kD2$Q$|z`cAP1>3s52M3Z4iWc~9bsxNlpEePO*o)UgUt<{?^?UO^O5sQZ zf?0zU6n+GFo(4<=Vkb^;Zu8%+irnnY3(uvhRQ?$GL7`kCL=-Slh{;kd+x9K~{HsjM z>#qAr){1Put@LY}#c9CAAl9LsKvTBFak{9p^c4lzyATWW%J zWg(}3t9=w$+E;n!1rN=yVCQMDurC3z-AU$NO^x}`M_;e-&U|x_ay^h2Py7T)K~j-4 zBprE*JVP>&=SU`!g}gvsBH2g|l8fXa`A7j$h!i2k$Sb4-DMel*Z;&$NEmDqDAeBfJ zQjNSrYLHr_4tbB%BMnF+(u6c4El4ZUhO{FcNGI|E=|Z}ZkH{ya2l&P!; z1KC8jkl)BQ@(0;Lzy}6OjFOctQ?nA*pETfbt21QU5#iCRwHHt%NP+F7@rAH5- z3@9VYgfgQnC@ac_vZEa6L6j5aLb*{Mlo#bg`O!nD04j(Ip~9#LDvFAs;%EX+63Wez zhM2pDFZ(MKn6j55z^{hbew}Yf^Pmp$yfZBkvzn_ zOJ;@KNSVmF{nwow8MuZoySzK7Hd8wVm;%I>iaNNvi=KmYK*=;33R8|{D} z<0?X|<;KfwDvd3jm)*Ey3S%En>PoOF%(F{@wO=VEi0y`8SMhFZ|N0b})O`GcyCCVb zEGmb}qY9`Z2>A%)=~R7HLNupd5C~bB0NWu^IWT!s<@)#!%#@!Z9|K6_QHYtJnYwPO zctK@@L(=VTDy37ySEQ@xQ6MQ`#~{|r8SEn^P$51%$4XXxH^{iN+NkM6K;js9c`6Xw zP1_NxM5+yXw$pT+%R0`&_pcs7mC>WS181U6TMKu+*+a zfRQLtyPXKU7oF8u!D(QT(F&H@PY__1$CPw#b&draoeF$F?NE&045tmT$T#)=_7>R3 z-B~YMGd~+rQh#`RdtNK(8(=yRV>x}o&1dk#`j$+h>)>Kny2<8Y_S4Jm_=y%>h}F4; zvFy7NCd#B1++I)dLOW%4OWi|i8b5=g2eI)ug&j3X{_j7QgJdIPdOvg~g*FIRg<&Nf z6i-5IH{aSGJG3;spdE{S-aIUb`Ru8QooEP+ zsJDH_t6=fo0Ajm0Ca`#K2(jI}{j;#lhckkhZC>VPQqugQ(p#eMuS{mzZdY`DaZgA! z2Cvtc03+~vPZ40r)3w(wc+$2VV9DDb{FjIpyj~LmjI_VdR z5F;7oi&k`cQy>uFRleMIbu3+9Ww`p<68^oNhFCwQ^OByBgt9Wd6;s2uyWt#fD6RUo zL^fb%5R96!p#e0h=xUi_;2XU*3ep zi1-E_f8U(hHPR&}aq%im^Gy7!ZNSb$?C_fysmY(1`6nW}dB*#kIdsJg-<&Hdz|W0Z zL+st3*Zg#n&(fsDYSN?~Zbn9ytIxB&7RArtT!2`&p>ewVYS!)M$a@B+)CZpGViOv) z_?7T;E;bOWS+_MxctU@+BbuL5WJ$BO%}Q?Puo6ErV73tR#aW)1X*T)D#!x_;ZrA?Q z?vu-(gbQs#fZ0KenHtsZ_ujrNs^dl_-$b>}G0fwox*@a%m_5YC-2NDyo|P=*-)~YT zPi*j4lk%62@{SySb9B?T;!<1FReL2?2?U*SXL5S5BQHQmTpSTUOv}Vog%NV<$zs;Shv5B z;l9=pyC_BHidv;0!DmIpKO>I5Wd!UJ#C#g1T5lFCapqB|gjCM9K8ohj-7HHj>;}vk zV#3Y`6ds=uKONd(-n}l>V}I#g$cKYJlM4ZJftb_)TTocDq+f_cR^-OBKNuk;QO-my zX8Zus6=K?_l{hOd`ArpfYs{QF`RQ66Z39yc>e&OB8^rddek`r}At=ZoT*H?5x8ASt z++#jroT?09?hsQlc;aEYaF> z{K)+AhHB@BTZi}`0_F)Ze%q`Nb~%Ovw8-=(cdNDhXU`mA2hPnQz`P)K`h!H~h)Cmz z!9^WK`N)eqfyXJjS_O4x0P}_zb?!wi5=qA&zORzhDh_>gNp}zK|)5GtBFT4Qk3dBO?E<5aWVSI z{4pQE{2<15rRs$|sVvpRUvVknmHTy-u9`OnD>(6URaYUl#Z|cU;5}pQO4j3y(>d+e z=EmNrGd1Sp*FpUuCfzhe>NGw7<@ggL-uX9whbJ<0Po+P_;2YHdh!ryshZyrsTsRYK zS$1^aPk|LZK3k0>eHy?5Ay$-iYIOME)ABy58}-V4>+XgEf9!*CpYZv14Psu2mZI!! zc_$41{I$F)`MLOQY@YYMspt5C_jQPM)<%o#QhrfNtx!-bj=4a|6Bk%Yq}YL<(h7oD zmIY7v2~z3f-6mSi@s!D+uRLp3D?e|V6XCB)U#6tBzwO7Z zW^lIc>mS&Yn?ga8G3$h%a1HDBxP3@^Bze676~yqMp^yl zt{t|D^jDwu{}wNlp$PiQN|%ctpGQHg*oY%++VZXUumEw{u=z8t=XR zOfM?9n;)>-5VQYA>ggCaz0!DQ^!S5h{&w6Y)+DLZ4Eq4P1F^GLSwiwG({5>4-qfI; ztMR+$NEJWMZ@>ZAU5I5|JvOlxX0d*coWe!7sG&~xVhKYo!+*=naS(fq;Vt}Clt#t& zt|@b}lfGW)V^7N1O_M=zw|fxtFi8o@X^U;WFnC^Cmsh`sL2lVs`psv2b&iKv%%+`n ztslSSbE>VRM`AzsONJ)Znd08`0d^l^l&mF%$GSyNvFSG^m^O(w>K-Bz&^uuJbM7K`7%lC7j0-${c&!Atd{$T(Kyq+p`>T( zfF(j~`ne?IOwRo$;gTPSL~jh0cz=IYSh*>N|JZ*BvHL;cUCKThH%FHM^Mf_JyGQ=qVURizIrj89Z{fr2X zN0@$;(D)Vo_C9`G{|I6ev-T&%?oIhv`*T)xM@i#W{jKdxt}wp^>@mbx&djmUFNmte zvL;YGZmP zCs5na7&Spn(bK3IYL1>kEzq;5C3+6ELeHbt=mpdUwMFevd(;7SM4ix!=q1z{bwOQG zH`E>VKs`|})Eo6dFQdNb71R&Ciu$7gXdrqGy^aQ)Ai&OCq5eu!PQE-|kjdApr=AT?+h-7)IkJ-hgWxpE0Ol`_deE(fEFPWOJ+zVC8psU~`fW}`VMIQAXVc}wRlESR}J}4cNu5%>v>dYwNM`ydP8^zm(m3goY+sOO%V|q4{Vr`U)*U zOHnOU5BG+^1NQ#0A;`}%0*pX@z9qm2~5iyL#B$ZZtPQ) z{&iqSljLfkqyerHVjomRW@XG3?IJ9)y4N#~ehrO|i1}4Plml25#O5x9KU~HlBLBo; zfUAaBy?91s^IIi9up}DsvLv?G zFDY~UbAAap>7oYp!qq`3+HHkeL!G0^%!*T==06#1Dw*;J&C7cN>;>s4%|fMMj|GUH%}Wyj=SRPYKfH4^hU)5&CIF3z~#$gHpWPs2d(@9l7$+=+8U!GK*=P7Tk}gDTlcfbGpr(8PTpzzFBLC z`_K-w6a4_%jBd#8R>}M7LMqS4i~o?aCfG)b)x84={78WPlR$o-*L}Hw~iw46)rL?#=2PFp=L2x!sEX&kX4t zt`D$Vp^|2@VS-=2I#SDiZE03RYxOR2(+arXP<_{PXl3&~s0jUleQJm@l$(BKS z6ZN6}=m6+=1|hAvtYv?h_D6l`%%ixWrG_t(0t1La`1%~^c!mhDe>xs;xI6*2R%NOw zWv1rocJaJ^#IKk~;2nP>!1jg$3gIvTMxb99A;9)N^eg%e9R}fkhb&*&d8FrT#0wRh zD> z7D+OTF~F1`lTkk8R&YZO#oIe@-AUQo%JhOZ=?glD4xuCHcXSl}f&K(lYaDvOZd7}F zMv(0j1Q>yApCrHtWcw5Ww)dgq=ma{6iU~~Z3^#nouO8x@#7 z=q%n8@XBp(Mz|A?feiS8PJ#PRgNAn&T(f>&^`V2~%S~nS79qa_kBSL(cQc^+&Oxc! z?ez&%-+92!TDw(0t@XZatuoFt9YrXl<6JmdluT~1dmwSwxqNZ_G+Gap}lmk79Q8(F=ni5bi-&%@RZ zr)iz4iRRG-bP<&2Wk{b332fOJZCuIv?$sr;Iy2VDoN(^%opv2io>vI4f6B8SZj}Jj zpfH$9Ju)U#x>bp*W5hzE$2(Y~mT}9W>br9|bWD}+|HMN|- zS6)8O7&dioAy)&r?Pje++6}_pB*6X&mk+l^fDx#^zah3;Tpsxr)14a{zXTY8Y$wA0?~cv?*F*oHJLq3feTfO!z14REgogiKB~v2-x**O)WF)KD zuF&73)mqNnXm3Wi6K{hI051Uh7bV8>@{odSe8b2lSMGPe;;Oxqz`xRbkx=y|!6x9y zpw#Sk=KoY*6C61K7KYoJ5nU*|^0WWdji7=ARY@}LefZRpbg`v0tRHx-CogPt^4r+n z)RJLqiO8{J-1~t=0tXEy<`g%_Q%#c@Z618xYu$|u7@fVFbt+$4pxF&oAv=sk>GYn`6uz&96g`*?DN<%M?h4peDosO8gC4GsL0}O@e z2{5`7+y?HBdXdfdKm_ZF)FH0&MSZw84vIBEbH6u?aY4 z0*t^XJ_`Z1_o0kfCM+|knXHgK@Jgz}RRAgar)JLK*Z|uW*&fSJ|8(X=7Ry>2o5DDM zV1UGdA!qj3k!C8MzwBC|V`T^IWB+$8vJ-bq^sdVk%iW3-+#3hzSUCthbT7kqtOp6W za{YE8nuxsO<*aDMPZU4VY9cl)JC*}`5yuH>MaQ3dLld~qm0Hw22TP4w)M`)aJpCg| z33?hX0*pXU!%cwMn#y!JaeZNFJ#TRF@Q$9Zi`B#NLpR?IJm=0Gc9D-!eFiSKS`M+i#{Y}LAp&e~u7f5^ zfB+-V83__#dmqY=J%km&8sLN=yBoc&<1_JY4SSlZxo=7pG|@%i0C-`D?Z&aU&*B8p z3t^9vCE!FLeF2RMf8t3M`cKIA8p z0aG>Ba86oNbKsvkYi?|RC}eLO|5Jj*u@YEGtki!cNCvw3ZbSpveWt~AEb*W2DLcj2 z61##DbeI4mP=aI$Fajk=jsV;HP#NrDtSnYcNS=V*TQtP~|DwT5qX6`_jr4fDhr|4h zOVN=xBz~16al-Q!vBry4Wmi_+}{ctW8o)+^NJVCz@h~7-s4Z+A7P*|c6w6D z+M?mAd4+UYh`57Dg8K+0cdyvHkbpl?cps63lrm&@58# zn;3s6?-bDl$s~y}=G1?O9FLIv1cw}(V$NXBVTv%tm{*wnL?xI~%xlaWOc~}arV^t> zT!pE|xD(?~j(Lx1z_eg`F@u;Xj3eTNTtqG*ZiqK>1qncckYFSP2}Qz@2qY4TLZXov z$Da2GnPl;2BbBHTQ6|jm}Wh_3Mk76&7S+S@P z$iux|JU;&fSX3dI#{8x!LpxG^Z|R&PnFdECtNkA&FVP&ye&T7OHIhY=YnP4_xPnP5 z0hJ=6hq{C!GT^=>H$&AtHWK4DlS17^xtL!GOROxz6XC`#l@- z59XTAZ)-Qa!Cx^)beL3@^dwgQzZk?wrT&Y-kigY@W58c4z+wc+3z_!=U(C!i?u|i# zbRNWD{C|)FL<*z`@jQ_#=@AgaDFRneg&iVcV61WLN;~<`Rc)vSf5kk}2~urRBdqa% zF{qMi{1<}>fvfk%fWKCN#T1e~wkKtp3Y;kR#-K;K0Ae`(e~^MidZZ}v0+9)+0Vy?w z8G$PbLK)i6DruUMefx0yQ*uEoFONA;OXeMZhQx(l601Imw|$aD2rW$D4@o}*>=*Nh zLHa^hB?s!Aldmo4Uo02aYKLivkUc4#l(g5OBXPgHVuCftPbgWiu>1D(VV`kP;13`N%&=A| zxVhx9MVe15nTT&s(%#$Q4NI{O96WA2R4URoREE zJ?=+X(;gV6UIshwFFydSOT@SC^xWZ)6kmL{3=(JuvA+z`@r!;PhJt-n+L`B*y|c?zojPP2O#rip z*zME5k0w~l9LyETFq!>b@>!zI*Xf{Cp8)ugg9F5N(LMPAwBl&0RijUpiQ8ap zv36K{5Q!tC*(iNq#8?*HBoK)c0XE>O%3OApOfR;A$M$czA^vw57a>+WT%$M9Xtk_! z#8P@{eRVud%}nEsy=fj`mmqdO=zK$_S?>`fH{_zFXKn7nPI7DQvp)QP6F5VR`fK2X zNY69h6nFJtrVFgH!vjhZQkE%^fVn{IVFN?4q6(kuS!d6)H95b#t5oStaX(q`o0ME3 z_Uh~*hh=8>E2*Ey60`a4QP{y)aON2<45X$d;eY&r{=QGaz_}%|M=e*}NbLPyM zGvm_S#Ji*d*dBzP433aKb@AzreM^31^?eQ8t|usYclpIwCUZwvaDji>SFK3ZJJPQl z-uf8l%>M93!{x!zBf$0|O!;H2-WHzdWUCz`*^9fAQ@6xld|}G@G8&i%!pf3dQ;uw; zW%`CnMP=_b?28e+eMu+5#unH`a!U)sWoeKwoL!-YX8A4>;Czs zRW@eN%gXoBeUK(uKapq~c)~LCZkYPF?4@~oV*(UmY3LA!9R@a@T(H`If$}m_ z{`?$1j;@?Z!(sYNKcpz@S01U1xd`Hqae1qql=nLZov#0R{l$S#5B&1jd})Viel#w* z0MOqwl@=%y&OL1>^;U+qE`3IQrU~RJVDqOP<>3-O0@`|TOMTe+rR+zhGz2)yH3(3( zJ9_}E_6CB~j+~M3_C@Kkc%Fgbl6CQ)aW|tQV2^^`{rad>_?&^6CpM(qIu$>`{@-j6 z*y}D1eD9_{A37x3ES*>??25C@n_Mv1CkOoa1NEMK=6KY#xzaT*J8E9nxtE=vU*F1j zZLsU^?Qef>azU^cA)w`-Y4WZ5liGC$`zb$1oQ6%;?8)93y`^1r+iue$it-|hEb=H5glSRY+EXIDQVn4Sv>)j_U<>k>XBekt3X;HM(urJIEGQs6m^?raR{xX4{`r z>kcm289o2^z9h5MH&ZR-*v`^U%sdZLuAZ$TB{V#uuVD1!ytyNa-ph@ntmpW)N>8x+ zpGprdJx8+fb|Jub|>(4=2LWL7R`8At7`Uzjd)5yPlm#*V!Yy3D2jLCUk)u@j(O zId?;siNS0kmh**?@KHYD*sPT6>!;@qGPmes+so;}d69PMpDyG2PnWrj*_PU6m|M!T z#n3!B3FtDhm@TM>hN&-uw}UPd_doc{GB6=DM{)pvCA9ov(t%w5pnD)beZdz z7OBUDxfh!B1VkF!-%w20|DqGqWo}>?waaW{?}sjv_&-Pmwr%VrXfIB0=rT7kTQtSU z2$CH3WwUCXLto6faE`e}KbtS-Va^-0#DBVs*FRn67G_&&mtk(Hz;=^%n3IGqa~rb- z_0TZ&E%4i*%iQ@N{4JUSWH}67CJCdL>I-Jpr1JRRI+-n<`G#%!pDY^o$rx+##fP|F znebGWvmz;3;df2~?KbTW>s`pIHJIo z3|%G_WYd{mr%aBH2Xh~3*G45o}=JLw2y7c zXz`dn!Q5hiEtE5iGo5ztpDq*lPnXHSY)kDj%q-wV2 z=cUmyX%Apum>KBo3)#XrAO6#2vN79c=jsoO-wQN7wKmnjX`XfSLbfdEGLJy6HIL`3 zx+Xe&{7JEqv*plxhtV{pSsv{r=Cxce2I})Hv!Tm8#!Cjdc3IhEn?s7by{8TL$t!23 ztQ+0*SUc!cO}v*{d`-K{Mi+PpDgegwaem)TeqWPrA?1D_J<}TV&dR&v2b{If7Oy|l zQNg_c-UJt7isBxEo?#qYYUne?a(VNqis7eY)!Zub*q+h~Xoc{Ct_ab2SM=XRhep1d zC@a<3+T1+dUmBP0uFECawp#4YUkD>~lsF9~XrKjD3H;6A0rXiTKbbHUV z`{!#_x89Y0Dl3$tl{?b7EDVmyD-4@-RHW$T7&hrkEEjqO!Wvblf6P|dTG(wOojSs0 z9B}0HTAouT2Lqt!YYf8_eS=}8yr*}_U8&miNm6Y}Ubk%^ylt;U7^}x~rZ=C=h`sgW zUSExBN9AEJ_#1&L44WmH^4588$V=bYMO*WpISRpR>9+`D^(N{STm3bIy;yz%4#qS)5~fx z4AaZ%FpOIC9j%5|3$I}7F_wB5UjFAWIMN$1+A8+#vLC@5;V~UnlIb2T+hJ+wJ;FY7 zyNwGD&(L*yWprRw`jVuLX*Eu~(`U{B_5ooUqw+mVZ@FEN6mrsW)_T1-;)z+tlJO7l z4|U`|qU=9CT!9qpT{&;9S^mA|`nM^|h`WF*+c@etx*yLuY|4871>&*Zwv8jh5;lcSJe-pN(dOv06(U zJlJ-6XSM<#SL^AHIrUdyNvZ|Ig2JwisuhWK+Y5=QrdSkr!)VfqVUvm)&_5%LwQuru z42>@@wuV1?^@8p5<)|GngtcMVq|PNR-i~3^);`nPXicz^_yw`t@3%(P9HF~m?kXL? zR$5AZtNq2ZKqB(Z*$457r4P0zhnI4;FRttCo9dalIu7nCoxs}91uJ;!TRgI{4qcFA z#tE1{xw~5AUFeXK+Lzk}PEL7j9kfnb7u;345v?D!W%MqY zZ}dA!eMM39X+JNz$z869r7vJ8>%p)|-9?K24Z|jlpQiL)gt3m_hrP4;-`^M#UgcH2 zBVz5|otP7}&{Q zp;Po@81-O6PaME7%!o6HVbr31w0_zEd^Yq0v8?RH`wTpW`G!VbyQ}E$boty4!}t)w z;^a%%uWV_T7Wut)!E?Sh&tA(R_C%hZ8%F>>KNzOFhPLVt-*6=EVNSFwBXaz%XjjaoR81Z@87P z5&t(MW$hsK;8pzRR$@$tPc;6{U;pc!F`CYSVf6HvrAJc~1y7tZt+NcNE>?P=&WT~v z+ROv_67I_E1P4*4%mrJ>UK#AHJtT12{Y$`}#~W|9Q0Mx(Trc5%&PlwW8PlgA6G%YJRRC#1wAl$ zB~dCcLtt`H=Cp;ID5r68%mDB5Y{kk2)2xZ#Ex#YW`u=)S-;`p_b)M78XfI&XKQo@! zv^TILrL?y+clJD5^?$lC}EF`eKN=7EA%OP*=w zOQb0VYp+YSn6vB2cVJ~nI$vTYs=hp(9kf+XOBX+*Oc^}2Z9f4XFePOi@9t6i`74#8ir&qNrj(PHni;<`iD7d6ZG z)vlYkJrzFY=0g~(HRl?Q3&)Rfs_%Y$TxZZ|bP9CPSqNhVwv4x%dud^izsAZq;~So? zVesubKf+k8QD*}%+RVnVN&WadT>!%{pEwI*7_}%rF`Ez|4Cq3LWgV4@FX0b%(q^yC zJRkd1Zl~4+?4U4)P1-?exj7id(SMix6-VM$a+QJ)xGKP*6B{nE=$_{JeVcT z!xW_kX3mo4W1PFtj7w*uSJKj{B?>VVRr~-NfH=_nI%bL*rZvK3tb9fd9GGVdGFp&exje|UV2!~=F5TabknC@ zc~Ddu!!SiEwxO42VgudP+uGoHS{7maZ>%ayR;}AQ_n5F%p4#S3yB^)U z@3WWvFce*YVVI(F7=}qIkFd@p8~wcBE3B{0_ikw)Vr-4cw2015>6(C|3K)hdx)8%U zH*C0`e3YHclsyp@-92j^BvnM1{M^W{t)}K@o}c04J|#8W9WDFe=IAVoLMXZj!!Sh` zV;Cl>62i{d3mxKqKj`)$+iTWu(ed@(J*Rc_8sk4fQDqFn6kUR09mP9a3*)}3^HrK$ z_ciLYfTT+i)~Ek5BRVbeGi{~y*y(B8Ql4+Tec9sBJ+xU->Z{qo4VEN=r9D5{2Gn4-%uY;NG)>rOsP4p_aC)N5JDArDE_5oR;v z($DaVQJH;KJw>Upb?P6wbPT)2X7)o-4GhB+)x7VT!K6upTuf(^U#BEq?bmtvpqfy%dtJM3`+`^O4q5*VCSJubXI( zDi`VNS(&rlJDLxQ>R=eA=qe1uBwdZLxI*Xf)f?)MY}edlX5$(kSor9+)15_WX;5?x zhGB~8VpwXK?3}l}j^-EniiiVKx}_oMT7-!gAGaxz^)A(^rMKoL@46s-kSk}3~O5)>?UT= zdc#}iSN}1-=Z28f0AY_bigRPM4Udn%7#z7wZNO?&kH4)*R9CIcB{qdzzjc&;diNzrYJ;$4HK|1gH7j>n-MnPldN*{3_-~#F zH?QbwC~Avgn4)$VhDo{|VG&=dj#NJ#mF3NmK9gMf=VRP( z9O4c)Ka3~p6#bm{DBto1By~iX|HDOkM^}0~(YU_fGYt!<`gLG#u}Ol_E-31RVVI)M z7=}r@17RV~;-Qb%)>qnW=5>9pSeVXeQ&N>#e7F&c?!+)mQ5Os|dU5*muLSm zGxLQiE3un!BR0|95zES9)$vmD4x3=Yd(&3;dx2dc@KR(i!dN+|%P8Wo!r)G5 za~aS*5Y3vOQ+EJT@53-m>irmoN$rVY)S@25K4L$iD0cv3sd1$K#_>WlYvxaF8RB?j z7$(j^48z3n!7yr3FT$HR2yqT!EH#eo-#EUAW<66-TZTA?F$@#O55q8V{4tDL)R#C+ z_(7ZijHSkr{~PBBqFGNX)RrMmAckS$9K|q9oFELN7Ck})5=S9UFve2jDE^HTf@s!r z5Vd896N+J&IAIuuiE|9Ys6|7FP$CTC9LHE{9HqZ;P9U1~ghg!`;+(`VOq_5G!^DZe zFlx~g#7QC?;zVLBHO|t%aZVwc_3TD%8RA4?7$(kX48z1ZgJIO7r-&%xG{iZJvD7%K zf8(4(H0!C5+A_pBk71ZN(HMq_a{TtPJJNtW6&#EHi+Oq{D2hKX|x!>C2C5b?xS zh;todsc}~Rjgx?A)-y7-Wr%YF!!U6YF$@#uCWcXqCJ;A>M2K?>W2tdg|BZ7S(X6L$ zYReGk4u)akBw-jPPBMm3i{2*g5J?ax1!Jjk*8Yu?ifGnzJ+)V zak3E2T8p5z3~{nC3=`)OhGF77#xQEpEFznD1aY2VEH%!izj1O9&06K4whVD{F$@zY z55q8V@-d8BG>6C~@*vJrjHSjg`5UJI(X90oYReF(5W_HWo?#d!P7#Jtixv=t#50KV z9Al|*w)~A#jA+)%47Fv5Q-WcbIHeediBpDQ)S|^i2~i4hUSKRWj>X?NFA>dJ^P#p3 zab95jP z8={h^f;iO}OO0dmH_kgmv(~AoEkm3d48z2!#V|~qIt-&0eMi&~wGgKsW2ter|Bcgt zXx0iCwPlF&9>XwkK42Io&PNQR7HuHj6CWT>BgRtWIR1_E3DK;zHEPQcrwPL_ahfp< z6Q>2ks6{^!O++)qX~kG-oE`s(V@&^y=>NJf6-{r$u;jd)&MBYQZ zZu0($L&7dXhT!7p2Jd?C#`%^dwsRYY9NiaNVkeq?E}W0~P(=bVN)ghqr7W?4 zkR#*?1!5tgNGu{26H0_Kv4mJks1VBtRYHwePN)+ageIXyXcH@lm4ptlidapoA#{ng z#5!UuqJE>Tf&amPS_I; zgd^cZI1@XForDWyW@g_@FwfWl!Uq=C4iWya9u+_Y!7@%TaST>JjuR2EXb?%9foJWr z#07Xny-38ulU*Ef4IYTD6F1>G;uet%)9(}_9cHcfhzBs)dq_NnInom%AEp*hi6Xco zKPSrIM)rcJfbst|@fL>7YN8HCn|k6ST%?Ue3-s+);tTN=zJlt3W14n(*d{?w@z&yy z+l*=+xlhz%>dxK`UqO8X`N~Gwx!_UPl~f^x^u4DY!*O3h^}tt9y*nsX zTBy@y{ZnF=mebl_z3_R{cZA7pCDv};I*=@;=XsXG0e5?fWrJ45FGGU`K^;NttE z-y&0O?dy1&|COk_)he} zS5O0pW;L4O-7Qizzv+(JOSWaD;gxsbE2u$)u^N4Lz|J+|1`p@Fa6vjl{-+&$1@!}A ztk$9@MEA9r*I!ntZPG4FoFN34(h$N}fn&`a3j<=}%(?Dn|K7Mb!wXj8hcOKEA@&Hu zSVc8`xXwq_jc(ZVSw>V)^z|?dpFc4SGklI>80KTCF$|*?9U*=aqwulRIAU1`Z(qWY zKylSnVcCHiw|7Mik+6fmFl^EeO3VGmFnZgGgD}xIMkHTV$O0Ma(5cU~rp2 z^nYDekEXMc|JPGlY;?x+DdH+G?ROV^Eb9MwP7nq+b_}BqZp@2X7A|zCOx7uLz!t2* z_~)iZNAIy_p~-`rEDTiaq$CW6oQPlTo|z!?!8K^I7l#U6Fqm<1aDgveuvhkQWq*pY z->rSYPh%#i7w)!ykAPVSh%iKjYS)5$n%b^=Fj&Gd}$pnK(#JQu6W?h*r9`$kgalQ^&Gb)l1^C>u*y3 zF!Ilrp8xluawU!Ry=VU4FFqwDrb0`zW^ecIJH#;C>6TkGb)G7n+7k22%`y18ZW>tD zm{tAww{Jw^n6}K6fyC#`0ude4WyrQk-G+ya|@?-Z)%kL}RkBj&eMRC(UZ zp;vKqIe0ZU9bv52GS9sCi{GjnzCmvlSEJ&)E70|4VA$lYFV2Hu)YhhxGssdl13E8a zSv$z(FcQKs{kE0cL!aA{m-%KxWg3P}s(hYKVA!OO38m#o4BLC{z47(GXCI!eMHha1d#_p+K=(a-obZVZSQ<=Y^QaSv3 zvM|Cnl(0!pv)j1a`J+QUH>dC}o3B&06lsqX1Dk`eitvySb+J2b!tL`f7_mDZJhWl= z#fi#t=6}5sK^W`cc}C~Y{3OdgF4dG!p>y^{EBs57xd>wwrH*y*>&c=RHtE-sMd)G} zrsEbj-H%?iMxB3MYI6T;WhgoiVXO$4qVq8fQ&b$oCKbI#mp~ZnfQ;W-c0^+!c-}dG zx6{iDSlXVv7j9eu(Gmcs22m_nvaJ6!3ac@{SZ)(lIW z-CFXU+FjwB;03@~BPweoqB7<;!EzY)GG~{DQi0gRpYu}^o$Lf0^4MfZS#kmCLYGJM z?vAvBkr&qN>@B&Qv~bU+=8iW;p){QiN%$Z`0mCMJkYPYyh+*}i?B3^o?^3C@7R!y+ z`4RvZs3L|@qre!m2*WUspo=k#T67_)NG>9!=t>xSIG+00+`1$MSX@bJpz5AVJc=#)F0eQeUN)DqBj#I`ch2eZ_Ibv_9{rs^Rd)eRbbR%2%mANAdGcpsFNglXnZND&E-O0hUm2Y z)>&7F0(TvH)>0v(X4w*SY*|m~b3x|6u299WN#{|Du7+Vl+kToWYdXhO7WzHWY)t$XC* z^sGP_>wr^F&oVeY+HiW#(^n$e`2zn_=g$v|Cf)dZ=sLjEYRtT?3dw-RP37gU`o=5E zXnmKnmNAA7eCb?tuTHEIMvPU!rb*mmtV?k|HYT_~J4-Iul6r7p#8{0fN@dIuV-3bV zy%Y1A?Y$(fdUG|| zD?w|2dr$hQ@Re{<){wg7T5=t^o;09uK$>RdnY3cNCD%K*bL9nuiPs6{uB z`lJDL$c>0)W$&@f8=K*JNn&Jur2eS>Zx8rKc$*N$%0carx{!S%$^6G6%s+ZGf-Mes zo*vfH;pwg`E`I8EFX=q>@^xp|gJZRhG-U1y$z@^;+pOqa*gALH#oJD0zMbr6e3wt& zW;wYGE_W@crb(_KjYzI-Ca_&Pf8f*gojz>J91gZMDZK`hw_5@Or4kI31#F8*6;g^c zCM6{{!{mTp zcy^_}t>*TG!;45$atmojnv*+bZpHXLF9#PLHpH>^a?*t+ zLbt@Q>ti2yj!f+EdcY?U6CVC>4m^-qVVL%oj*GwiCZs=IVb_s}@brOhZjE7+rvC|)n(bhl%1$SbMtay+&+s5WoLhPj*K3Sn zQecm?TQ{R(mx0`3t!L9-1qvz78E`1RT~zFE`3s&t958I=r+qHkJaZ&xoALOC%E*&?{sB)1jGEWY5peDEgQv?~7Lk*A`ctX{PG;08e7BDr7OZXTBJ^>@61ZOsdh%GWt*ZvV^E7y-2P+s(7kqJ*re`d zPj^FD(s#PWlDiu^COwt8(Dxv$q~Z8x2iuk{Z=afO{&{R|GyCzepQ^L0eBh4dj$xB7 zBq{n{4ExfzK5>SB+0_dg4VQ*$s+oVp%web4}n~xlAQI%lp9POUEE`aXW*N}P? z*gk~ijJDcZsF}QvT;8hb_I{PrtR&$*g_|C80^5(Uz=oG5!(9svsx6)f(2aI2Te)?j zWvo=A5&mnIC$OVy?_O-=DG+(}vtrAaH9x$lqwJr5F|mhqC-;&b@*D&LM{ho42IN#B4j=7nLCy4ZQTH-=&Ef(J2-TJ!+vMS7Epay}SKy}j*$ z8wc}0kT}v0A(}NiyRbO_QsouJhYa@!58heVKfuuKi?B)+wMVv=rG3KFr1#u%$@Kr` zCm7;okdOoHFv1$OFQg{sGujga7kRt7hAmqh*cY>6Q&bT!KZK1PTGT85QB(bQz1`2| zGtm!Umrijswc}9*=8v%U6(7dqq_$oDxq0^&j=dq3>o4~H+O2HIy!!+o%u$Qej>9qh zbIN6NlPB$pOJ}RDi+FcCYYMO<2s;+O_r6o9?iowZmt%t~+jKKpY&J_r?C$^;h_LLa zW#f{^Rg79z4{3*qWL;TanL}4SeTex_%8w#!RoexrDI!GtG_gQO(L?)0S~P;kcqgK1 zz=9B_v|0aRSaY+=nG+d9OP0uFoMoIF{E>6G09Y`>@}fqC4E!H@|2Euh^4`5?x7n+Y z81$7Pl&IqwTa80(yBnHbDh%+!4s z_>y1ZT9sU=CV7bTB@dH+q(2!z9w7tCqht^nOoqS>H4L-;Qt9%a?_^%sNt$gJT6=Rf zJrr)J#}LQr6qCjQ5&Cfq+j+;3Ry(!W&D(3pZR@APCvZbOfnm{)uefw8y2x}mhmCUl z9A*BQ@ktDuG~yZ1!x6?BKdE;OxJ)B3Y|>>aEgp$s)Yihu2y!>vP)~u44F1SoY4I&C z{7XIObVKg9xErbw+)$&CcKtnj1FP5$eRk|zq4svw2hJn=cxBcHEL#qT<}|`s!}sg! zvm@NtN=DP!qq;<6q^jW1oWU^Hf|s+Rw)Dg4L*E*!8+Lbx zeN(!&;|kox&taI)oL6EC{4}3BY8Ceg@>!gRBX}OeFh?*N!>FyDBhQm(;HX?cY?toX zjU7G`iIa}X1^PvV4FwWi`s@Yyp1)i8rr5l;-ft70SMX+qE-VgSLKv&HcCNY3){U7j z-*PI{P9KRffOWbUgt1zqu5ZEO;AITMtkcC}n22LuTtH5Fs?b-y}=5y{c_0IrbfHxK}W2(uF2PkH@e{kBBbxs|Y)BRVQhpzb>ml ze|bmOdJV%cMXzHRrf34fY~Kc-sMnk^_oBeel~K)`Wksql*-ZPK zc@>J@z%WeFL=3|ey@@b|4-uafUs#>bpO<#a(D0!7RGMs9)t+e!q3A6P!xX)ZVVI(K z5GK9Zzo7b9sr~Krir&L8Ows!YlU|{H^Oc*1^^;7Ad95BNm+D7Z^orU{W&W{a28LmZW?~qo=mUgx z?KnAV5*D$wLfM9QC)*6(8aW}`&ea@jQ1l^&VTxv97^Y}8!lcYcT0^zfJ@*Yu?yxNI z`JBMfLo2$>dl`y8!Z1wH#~6kw`UGJfvp>aE=Z@XKsZ#1R{Ck{3f}SC?@ytDOD4K&| zn4-BDhAEnduqcy}0s8TFkx+e=yTUhgTKWSmS8rWvyA?*ue1vsqRs>hf9dxYUT=!8{ z<@oP+V;m;hOJw=#S@mRR_>o+a-#d5S=YM^QFhibDhxQ_hS?D&37>0>dk71Zd4H!l(T1(cE^$_Vj#!@5Q{8yw8$QGcKa!0QsR?7Lk?#B}QZupzYl=Z_9U`@07$#CHhG8Oo#xQEpX0nBB zg-C4}OO2HBuSo647OV*jwRMQ}1;a3rIxq|qsT0GfMcc_QWCuj*!dPmgw0}kVifqA} z9#LC|NZlBQiPVE(m`L9+j9T<7*-iF9q+X1rM!Ns6NZ*kySd%Ym>kz3A!!VKhF$@!F z0K=$7zmt7rKSUbDSZbsP|BCbj*@88-qqYu_hA<2hX&A#Wkw!3#TJ#4wL=HowpBPJx zl>M(rqsSJli6gajh%|;_m`LLohKckG!>C0^$uV*qBK^i#YNRJfB>0vS+2X&>9^hL} z`v1L4W3is2qY*96I$83I?j?`t7awGP%ZXvs`fp%Ta1~y*LS;I9%L!YszUBPrET<_a z@qP+*NkW(FDj7$z!?V9JofE0>Ung+UbS?~gupvrGHp}u*#{5&Z_jLDcfc>3{vcKyV@3RlAEHjzBzj2Uo3jI3C#W4-MxusC_S>+(DmlHrCxq;&6600 zx#sB@hPmb$7)C8hKutPbQEn#2Qu{DBy?{-Ni}?#Le28WpLu$(qXBLKG;_zb_CeCaO zqZZ|Zn*0z)0As0fc>WW|m@bIX)Ry5*qY#FDUHG>6S6){9P`6BiUfcSIFdPVD7`66n z*h?O|8kZn6TBke*wqOlk8o>u=2VDtno;)1z!1W?bpFuaKiy#&LYj29C&&9B8U5zyl z&ffiHStr-~dv|OJ?5`+>QTLYtorD|qR|FcZQx-$^_s*fw-(wzTRg?FZ8xo4rX>_ib zdEjN%C-a?*;Wo&!_PqMsU$dGzd@bZEU{m7ahKqd$Y{v`Rsc|u@&ZIMsl>mJXU5w5p zJRe$WjM*ME_|vu{RUrDdPJm$ywIz4**3;S^wmZ^F|ozlgq{4=6>d!#jiiC$OZ1G;DKZ_gSyV7k#R{ zE?eB&*__#MZ$_kG5S0PT`as2Osxado$F-mG@z;Mg`5sHZ9eGXth&_K7EN#dlZ2Oar zmbJYVN5Xkm^&P!aki54$=5e9DM=Y=f2unydll$Ek z2x}B@Y)}Xj(hc@1c4pk#pK-=V`s346P3ic&b$zLB)8!z?Uy@Y}U<(n}V|Zg_dO*s`_ZRK!Tsy9x zESB76o?_S?156QNf}a)!{1DR$o1MOZn?BdMJmgFY*Sy)sE(2SHFy8QyZJ`4^r&Sl- zbDF;5Tb0X1Ig$-a-hFn^caR09gs@wqLZ7E> zDHY<98ISs~(sPAJc^0Sn&6|oH}A;sY-4Qr0&EGw z4!Um8J(?677SOeIgLkX9pIKh=lIJtomPN~A3&Y)#=UEDKIlov? zPgAKrQo%e6st9{Oea~To5O3}V!DR!t;(dkBDDPdvFY3evObub?OZ3VEb&|%H95#0z zcqqTrL!*6j{(e8^;a!ff*m}in0#&{Yo0=n1nQcc*gf^Z&p<-US5|}!|+TSdVkrsT( zZrRt=WjB4NOQE#6!Y7*sMPM2TlOCVq{M1=U_toRi^Xt`0PVnEZO1qUA!TjAmMpSMKd5}y zzuM?o1+bL}^Hdve74~`km_HP$gRtq&4rdr1?;f2s{FW5p zQPXKze(zaxvEeshs}NSdRP&p{$dt6eJDIOyqND9od*?3>u@q1Mwi;n4X8UdZ{yib5 z(=GQwu>EEED@HQ@ngTbc0b7GGwmEB3&&pJmT{RSMRQDWCkX*C3UhR#p4KQ7Vb-xoY z=h`y3`CB-zRqD#3zWu*iW=Fr(rUP4xFgr!dy>CmVG|4#FCl*!}aqsMQUv|LFITzSE zgjK1mP?xG-Hn(*{Mykt)vcQ`=W7I=)`TT&bN7(7(vkb1}{Lpt4YO1*1$+uU6<6%C# zbi*cKdI%f1o6|OKpgAktd^`IgyC0_<@?DQN*_ylpwgF-G9sA$e)ePsCq?}qUwTL5E ztLm%cv0b(T!1NK;(f>f>_39d*9sY9pU(GE~bS+hXJ6QF@7MKCTHl7^jFHDOGGTOT) zB0g)r%rdzej51S4l@0bf(JKd_AmJGD)B+VWG& z_ohqozMbMA!1tu$wy(r;Z7E=z5O&Tx^v&fnmTIeWIQ$p&rF{Zgs_}- zM)%8vPhWI>aLQro;MWk2BZ6xqHD7oFGe+2G&*dIIM}-$@vGsBVyz@fJr#l)9nyH%r zGeOv#=-l=r%|jQ$Q$)5@b6+Sr65&5lbhv_fGun(WmldmDxwR+xs~XF0Diu7q=c6G< zS*>u{RA8nEON=ob34JppU7Y-F$k=VV%=HiAtLLZl>;<+3VV&CQoT8aeejH_?BA23`)RGQ z;9?J%!i&inz-$rb{M$AeYRMRWXT|Ee+%Pvt3R4)}Hm3$6U@_3=9Q_`&FJ z@7#(XmvRQJe9e)m#k@OjM;OUv#;ADhaCTEddzf2Q-SiLA^H>2`*eCr1WW{Hz zsAn#h&TL$NY5$_j4ZV(u0>Z#{BkW|C!zzQp-SbVa${x#5N;xR<>_FBl#?_y|+z>Xm zu4QA$b+!u|!X%siqJw{Ie4eussM14Ou#0dC9Dz6_F0Hol8HZ>aLvYYt0?H zADBDBcFw*vptjJ)T(ZsSOW?NDt|wyTWB=H!1Ymm+cH(qy+A6!{nS?;T4deOVSt-|= z$L{$^ascx{SW{)^hV)_UTie5gKZMHdN&o1#RfGF{a0sw{2-~8!s`}vyVXwgHLt=q~ zFB-FtR=nz}zvc#PKf-kMBg(f*Pi!kK&QsqvUHZ!^9%JAAYFn#-c_M7|{wX8dT=C~2 zB=_{Gk`Wf6n@+eYbkmtP@dF53y=G?UwBdw z(tCf3bM^tRH`Y7OlO0UvkFdV0zE^fwjLGxPYny#9!F-cc|Bg3uYuK4A0AXd%H-wxO zuhSAq*%@EGbnU!}un8U~$)}mXjv%a`AQ5l)gRNzuxp`KhdvJPS0msa{OmkRv56O2s=h@+!%C0=uL_ak=c+Fd-Vx>!2#U@ z**(C55N7aMK-F}+TaN9VfR0ox-OS-mRf))SrG>zP5vH%`6aHO zn>Kld*OvkdL0Dc|Dz{**7BgmO`L~8V~big(B>NQtxx09$^u~@{4uH z=~o{QF5q=?pUx(p2enH#Bo=;;*TDg7953eH-_RU%DNC=w3+mNwmU1M2JSvd3Q;}pW0SAFsgtVoQ!_Pu6? zkZM&+PU0rTqIT)+z@iYg?(V+1XDn`R-=!tczVU(M*TGy7w|O!F*1%39Y)|#m$Q!Hn zYfrlw8Np|9^5A##x!aA_1PK88=Xi3CU5FXjD_i1_A6i^xmb%y}_-xs4 zVCNBLa^BY1xz2ai=%Z72rwgPjsP+#ZmS36i9auENF3hy^a4H>>n(%kuB{t=y)y7?d zUb|LwGw-Jt5SEo47EPCTA6;aozQVEYytih%d5L)Zx1R&uu|`s}1Fr28xKju$24RJ2O*0Zrv&$Z3 zD;?h5@iA_5*wo9@OzTpCT}D{{^t|-bhK7b`p9h%Fk$ifZJH&nHME5-AeIXWM7v{Gf zTmHIqJRvLI;!!uStfzIT*3ca5#u{rCM#Mn;?XB>i_rzBPxUH!uuSG!erv zNpB*oQ2a_U`}uYrSw9CGo|bDahk7#%HievGzMZ&*VVI(~F^q@ixUu2p1=&Tb^0$RI zxHLo3I|%ca*Kd2fN$tjk*qgJeExunkC&TBtzFi`d^-BOu&Rs=;;F$`1mE{0uA-W6n#z<=gs8L>xn=KK|qG!0>QcYJ>{ z9Mrlo5~5_OX~!anTy)+F&}uo*%R3N}KiU>9xnA27+aIU9Z->kzhB{5rY>j z_YlUq7A7s>8`AG%80L*c28LnYNMvFdwdg&lnE`Jk9$+kWl|An73zmn7W?f~}mf;0U z7KUNsWMdd6&La$?7JUdcvmwr7jHSl8`ZvxKM6<46YReEO2g5LNaxn}OClAA@MV~;; zT!@p8vD7#Tf8#twG;3s_whVC!Fbor?5W_HWo?#fZ=u@a!2yu!qmKx{g-#E_^%^Gv4 zEkm4Q48z1J!7xmmQVgROeGWBCAWj*^QsdnD8|MY0S)&=XWr*_OUQY7E1?oP392 z)cwtb0X7cy_boJ9r(A>V?{u5~Zg!U=-zM*G93*^4zfR}ks0DxD)c0QCsyjU6tKg}m zTtAfhelDH;&wD)?c#XCIUVh2LE31X@qG=Jl9#VprI!oYHj0(I!QH9qY%i(2(2E1a> zf)@iTU^!n07U5UJ(zz}yc&~$HYCTw7)`ulwLs-b&1k10+uxPp&mO8h<0;M@DD{h6w zKucJ{vxbE?TUajJ4vSn4ur%ca3rag+8Hl-f;|fbIZm>||4$B)Juqd$~mJ$xY0)RI> zw)?=twl6#)`@w^406dNc!b4;bJo<&e1Di6J3Rf6BY8{6Mq?7Pi69Eq+r{EFdG)(-@ z!gT#SOtRt6g<#ej19R0_II36RoL+_5+;y0P-JmDZZ^C@%HoU9+zt^;PU^0?SPl4IN zUAU*G!+Btyj|X&SFM3SRgW)xw{tQN?qW`?z{PQ}u6fW#CdO2JV74#~44ZPZ|gYyt1 zF*l%g%ZKXr%{+T@a#qz+&x1RAExg*T2dOc*e_!C7ffJE)f~UC$FG;K}R#C-SWfe={55nGK80N<`J^*tUGj=;UmGgFP%J!_v z_qI_|$Mno4a_mLZy@GGeXq(3dKc?{!SjLr(&)zo^ZDN81Yd6|n*+Ly!;Kwu?F-572 z`C}TNFiv9mm4UI5(;_GREcofDzn+o)W#5!>x4q&?{I=nb zVwP;Do4{nQ8N)D>xfTq=%phA4X64_sw=2VW`QxL@_pw#3)ZCgIJ~EvB`ZyH*jA59f zZ5SrpR&VAT-da2{*tWcMM%zpHNu73tvCi!+%Sb!_4PGQI=v1cN#`{GuHT;4w)&Zdo z&2T^Hz%c6BfS%HcVVL_t7lu)beu0{uFa~@@EGx(7HU<&0CdHX6Wx@2X)At^RpNHv2 z7%K;LC~Sh;##cJ?6P+GJv(5;02O#w~48x@E#V}0j?-)ic+5*CV$Rx_%39;2FAm+WjDYor&o6bB|ee@snpD>P(K}$u#JAMkRH(1Rn;`my!`s*@k zOYZEWFpiIdto!)sa(&|SyF z`Smk@FL^-`F^v5UfG0Z`5$C-uGz_*w8LG=S$qOvtSe47_TBCu+Htg}h3CxeSIg<(LShFDhI+}y?TbpJc^=h=3iT>dI>3G5&@hE3W* zX}Reb#{Kr%!~P9Z#4~28&kl&3Sv8Hp&3F&@bFK|DK$`|dH*i)><2j@mY|s>aZPE`0 z{kyNW!%Tn&sj=+D>Wm$&WjgWai>lE+445Db#xLT4a4!lG5`>BOFqMJYe#68FyO z?i9RPoA+h=XSgZP#4yZFnGeG-Gl5wM>)C6hXJ}i$u1J9YW&61;wF%04NweO1GXJQT zAHy(3XJeQsXZnVfiM*o?dQEBz@1EQUGXVjFvCi#{&nt5TiqG`V3_S03V`Nn*TvdVy zV;zu5gR&uA2*apn1A2-uhGFiBb1;lrRFEOW5N2$miy)SjWB#LQ<5GJSQ*+jh@RrX_ z(uSG9T!gW5P;UneMgf}$gERWS_1q@IUinAGzzj9OHbA;y@;P?QtL zSZbVE|A}Kvm%wOh%Pvr1tYwf212%UKKoh6F>B zQKu{oTd-yVrpeXpx95(%o_uGW#b7X`7<>$4x(rf*b+Rz~D~n;tR`l^=(RxQm$&s0= z2E!L&e-~gFb${nTUt+-i$}nVMf8~(HP6B5p1@WXZj3})524Cb*CXGk;T7+k^%(2`y1t^Nj2 zcJuenZLzcaWQC|LxwFeNBqbJt6m5O~iSPZ(WBy783o^g(8R2FE3JgcOB3RZ;fOU;* zlzA)_+xHn!J(!bzbck#_plkiWeozPaDBZKpA1I zCR=9rZhp`vr}BzEd~8CMFCS(COAy9tZ8?#)AVkH*No&jC)H6YC-Y{k@#jw;VLPD25 z6zvNBc4sJV-+~u#^{QYP=IULBVVIeKDuz*uE@h}NmcdLw4Y91aNwHss&h2W6scml# zm=%051$J;bhE3W*X*qQaoBE6M?y1{+2a=49m$xME5LaU?XYew37+f1PK+lX)cf1@U zDC%Bw#yc|G>Jqhw{kyLUFt}D}!d8P@w`P@;ZEn0B5*XDra$KCcl{>oz^l!fZ^lC{7 zE!buXL-YlsBr5)Jh?7iG$+dI1FS0cmQgm%3!)qOd?xhy$j$)}BS4(Gp|7E)FVEs;$ zIX&=ZV+F#NFWcq6{CHzv*Nz5Cz@%}^kiG`PCY|T= zbX^R?+(y=77`5nX#u|n$+(y=6EOlsH0RtEFw<@_-tp|PNfVAd9tq!SnDevpWXEfcZ z2g03w6=Ma&UkmN8gJDV!wlOMKp21zP*tt_9|9OC8>~UNtSP#S024rtoogm5VjwS!L zpx!+Xb*tvl*)?I9(nnbM3e~vRjc=8{lq9cRBern%*0W``;}<;^12aI_yyXXX$r96s z=%p$?o(rnP9Nq{`T-bYiD=6T(6_B%0}No=`GM4SQ=`SE#wcSj@pg!7K@w z5yIpOc5L?%OBGw3*nG}0U4D!63$artk1ZMlW{fcFsvpnqavU8tk&!!cj=UD3c<!-9r)O9{R{7NI{H5{RC66pg|ELmAJ}GuU6vjQ7xRA<^qeDxq2pt2 zcId!%_A47*LzSHEO%cXA3xy9&#&YG86nq+HeAVXq8P&tPfuYYZU>GtsGBz=c7{&|} z#%37qw;X$u);obtn298*<)m1;}?r%G+KBxNqK^RT9Vi@Ks+lFD7 z;ocI%s6{OpTN&G6xVJ(qD{g~j{8x>$A`-RByk?edPHBN1w8pSWJ18w@gJCP@`O1Cb zUg6->G_f<`cgI01hBc#ySDSI3Zj0!i?V%U@X*>#;XEQrsmF^Oo%5BuvtL=^}Tere& z!9fv5ndWT4vBKa7GGE`cT!v?}?Z9%f z)H3uk(@-bILNC=2V*D1-Gx|>p_Mwd7PK9aLws#BtL1Eh`F}4-c6M-wxULvB zDXtWKH-=5R*O}7Y5XR~*mp8u%GS1BQ&3LVwm@(Ti9Dd<)53uHh|Hs~)ht=@Kj|0D3 z-PU{WER>?XsA!k8h?1>PDHO7mB~%iHq|mNH+LaWNii9jhi=q;3LLpm{rBJd(erNby z-}6l8`#hiL_xH~~{&}7EIq$Q~nVCB?h3wf9UN!37mGNB`y-()ScY@_$-&l>gV;agxBDU(y;5(?2iuJ4sBA%4`j+SkQoAOl zrs@Z*?&8MX16?th7r!2?a6NZC0lm3_CsLufx3g~7&1(u8X|?m9%_&h_-!G}`_f?C& z2ylk84PvuCnQRQr@2p*;!mYb4v1MyWZ09`jGy2qn`Th_~Rgqb=wy@NG{d^nCyM5l1 z3`er>R=!cA9-az-n5^bDRW19XJ<+UJn8FnwB9k5`CO>%B}o%D3oWi`nor<^)< z&dVJNa^0)#kqlS}#Ex&umQ>@tJgVdTIN5oMN>^ZRi0-78!#4oi1F_b^(OBub7uAx# z&K@dwl$i1IX8WOiz1K$owijX(Ze0p7+eYZHciq1kQ|K^Kpt`uIdzTukQg2lE8S0;<_WImd8BrO3f z3}X8&B8{&$$4o0wPu1cKrAPf*FJbw>ScQ66FC1bkTn7vSOkH*j%1W1J9qVeyzR;I} z?=G?fECOO$Yu>DN3)Llq-(^m+a<<10{wOG87qcXv$f z*0J*XX4_}zWdjxkF`q}%bj`Du8!EM>HvBLHNwLNdR=Qj#QQjbi= zLF{m$-$fcURS7fz8s5Nq%&m-jTCI%#RxWVylH zk&$=io6CQg`iy!#A|7HgA@4tr*dP6A?NHAn$zCn_`3$`~&8^R=7eNj~OyA)wyK&AL zCDw>8o#HW@erc!2seM1A6AM@Z#O&{tZaO{YWy!^q-9x=!?$|iyGT&z%eLV%RM2Nla zT=nFIh@WA;Xn4S*{GH3T7+bsg%qgKBs!f8}-L-x;a^auSkK{#{BuM7G^p>+aGxLJ_ zXTXvn7B|aU(0d^Il97c)HW|@XIkEEL;rJ)pl>keDnBPVBmEML$D}%R&USBMt+jC+5 zgx`T57QF&26=JzXoIz&2mxJYAeUs|0s*x?sm4!2_e-ePDLG0s+@3W(QnpF$O=)HT|KvtdYC!H9YQ^9aNig|3(_A5~JIUaw@Jcy7JAV(#63b;H60z|tX>(r2{Z_|9&7 zyQc>{i;cQpmQBeVC>>!zaG!k35rmemGm@|dO`3g#HN(0 z&zE0X|zs%b=Oeodrgb>mDB-06JjgQOyFmY8YL)qBRq4pq#mB@e_)p-n?^me zd<HV)Y zmvk+oo-)pcSi6F3-2FJE*EV0Sl*wCfa7zpP7&c36aXMhfA%-n%Tx84m9IlZO-Y3ql ze)GHI$#1b$9BKicfEcNrvL$1TXZ_*H241fw7sSSVZ9k4Z>UjXzNr=sQroOh0R~~YW zS+7>IcK@kl?n~{;p&NmK`rO($Gpf#f1pjQL+ZeF z8e(DZ_}>f{6rAPOZdItT%=wkeUmPoc?Q<1ic@QfcdBQ!fKTU>BSacq(PJQm_nR02J z)?Vu1kPort?=F|iEgHRR?b!O5g39oXxL)Ii=?ZPs5vc%T8QPvTeUI;)e*CsVe=uUj zj;aZVd+n-?mjZSMV&Mt(FUtMz_fFKDx7A0~^-=!o$+zkTztjSD7Gi@AdXEn-EIIO= zb70|&W;LnkUTq$)wI~X(LWr$#wp&@h#kaX*pmpY%yHkrwe~+HvJzCuiuyYVo<(sQ- z3T-#udiImbHBX1*D-X^RdDbje0ay{ly!S8P*&~}s?A@LC&{SHikedV81&C>v^c>vyc1Pn5mrFrL?553~@^LFx zsWy56b`fH(bFK4h*G+UadL(PBeRAZu@q7D@8|^!?1+Zd>rO2PlJ3jvM&#yre#yVEB zSGbDio?6;=T?DX85S!K}*%CCbz5y_nFLrV z#Hz0aHB5GCo?Gl3waIsN(ZlTr;_&eKu>pWxgP25QWM6$_-~MIE1>2j*c@pk-c79gr zA5R^kuS4v7&*?o2n-6*TAK$2aZuXC4=O^RKMvi2<0agaF()vvgvDI!ZX>%VamIh`n z_wmAS>#wbl2do@o>N3qP^K0ii9b|NxjEh`a)j7dArT@b(Nx&)~woqmoR-U|c5&P2p z5$UgW#KqR7*1Vf2GYhavh&|%q_nu_?e;Th_d3<-x!c$rj_GiX4)LjSc2E@t}d0jEH zH}3ja7*TRkxBtqc$dFd~$2HXZNmUSwUn^STZ#bxaF{bv{lPv=UmAY%1lk7%F0agt$ z3nSBy>Y>0_-NlzH}}bx>Ft8H0dBabgb>tw{FGFXDj(e z%7ER1Sk?4r34MkG;>B+F;+6$z+weuchHpEQN4<$v12K-pLdyY<{O&z3mfkvE;nBIu zQlY~ukXnYsj)9en6F3J_7%sAHniCTRtK@Rvxw4(`bUtQlg-Peh&?hGvT{>HTcEi@2<4P}~tS=7}h^oLeCF@V(}v4t}tIc5ASy zgR1H#j+8-+HDiY>VD})Fc(HG8ZKrd4srRoR59a&6{$yAlzhk{p2Vkub8|T&;c=Yh& z)t6nEYcn3nkR3)w6^}o1sI_n(V$<7_`ZBkvoPYZ=$@$(VwKIjA%VhKGR#PWG4WVonvIksbpW?+H&;EX4XnI@V^p&_^ zPo7aV1F%OB<1U}%w53X>1}nj>6~s#pv|ZUDe>|7c}-?dKOZ!aV@pWbU@5*w6eWYD(?SuOPOk(|p{lZObq1buir_ zV-TS7vAV3wNjp*our7#oEJ(evd5oy9af03~t3%daTkiz#In3Ka9R^=REaA6GxWvHf zGj1M=oo}rAUP!<8&eoQW{RUV!#5%^LMHGKtpQhGwC*ER6aQ5{W8K0Wf7pM#NHxRpD zRB+N{*TCu3KRqob51l+V5I4bF^kgfwiNA%|zVI6&-Om%Q9(t5hA`x$J`Sr|B-`^Hz zskXg?Sl2l3IJeYOvL+R#+uE(`Hr{V3cN9;Gpq9*gh%NT&*y$B8w^i}U6YEi~3lpBO zO3VctOQ^d9JrFxr-lW~>SK;^aS)_!l#~9m(@q>0Tzfvy()(bJc?z(e{i`}D~euuG5 z%H$1=v2_P6W6Y_SK0iQA-p!5UZWH5$u%KDsCG&tQ+a)IWys(4Kpfy&bSVh<)%q zXE%^oV!F2V#2f#UQ=a!|jNjThWsMGC{Sd3DH<&fH`J8y713yq|(?z$Xx%MZ<J_Je_rk(sPrd-Au9caU>++wW);UiIyR59 z*g)qOmwGjA2x5hU0mW%5_Yz9hwS4;h_QAgFw9WUom)5-imHtLBM5PS;e;!y6Mnh!E zgxFlNGAG`FQ95sStK;kGKWDjKx}@*Ec}+Q}l!ai3O4$fDWT)zJ-KB0&KD%{&?}`_d zAX5&+iVutSRGH~Gdz(4QTi=T)5_|lrBH4HTIZ&wxf*~puMKDCBT!`)5I-_$#lfkLZ zhi`A0n#WYmiBqo|KkoZvP^lP#Au1I|urK5G*J>1nAIiDB>{xU8dg>4@0Wmf63dd)j zo%ZwRmqu&&nlMC|CgGzY_hNzT}V0hu7IG1J8=HtpGUN~->Kpiaw5X1F#@|+#|G-HE}_ZM`PXBFA~m1O}Mp&tCn$d)1I!J;-z<#H>l?y|vn!4}X1-JGKcg+EDuT8o8;hr4LjpgJ6hC zWf2UK=_rU*-+P;@eLeWkE5TBBpzU^zg(Sc*2QcVOyRH}twh)lI1wq02w*z7@T*i-x8L)Mhvt5t=V=AEG8WBH)ci3oBMzFDNTY0t#w_P$` z&X^eKIM4txHHDb?TK%`b->p&@qgXvU=JA`_5!;%rn+2n(do^Yd(}}OvUr2UGPhE1t zt+=Y>^gffprD~3a4uF|M?1t}+>J#L)r^=77h}5L+?6!G&psGCY0Cl=z0Wr^Sb1}11 z(G#l|-P9_GC?eT*9M9z^3&Q}L0DQRVBM z0h2e()umpO6FW84bAF-qV(K>CbckgxIX~kr&Qj|%nV~e< zW7jVC%9oCfDz!TRvw>L0)g!0(Di6&TkcPZid-n^Lky*~6Hw`%+uz-B`13b%X2hg%*4H@6>^R@paS!f>TQE;~4J1z@uvCa#{s z{`x`nd(NW`AATwwJvX(jZ(MDBHwoBmh*cC!bNbF-WBE`rp{L>SL(ZuOvU9hXU!ty^ z=RhnaK0Hrk#e=7(lO{^kvv>Gv+QiPE)2TvTwb?>Ur|;gyta_!z`x~{zKCn&><~1{0 zs+C5E0A>fV@-aED2ENziFUaipTz^I6bKlba&6dvJP6IX>e`pAN>{CSJh@NG z>7|}?R*T>+hnl_f06Y3?+|STCOBU@k&uQ=z#JQ_nSrXb^CvP&TUySoR^uwo8@I^+5 z71)k-G(HsYRP1`_WciEo!O2x`ZfYd&d{t^Eu!kxYUT4uC@BmMhI3O6}sS-y7Lp)Wo z0Kw>$+T#wmBd(+6gs}9dO1^=oN)~ac*AJW_ExdxGM+WIEL@-1;ix3Qv&SC_kSL%!} z#20~dTo9I?&fvdvTp=yInxjVs=`2AoL^?|m43W+<1fy5#iZ8*Jf^^&vmY&YgzjT&E zT6on-j||dTfnbPqRw5W8omB`%uXH)S0$&NzS&gvtbeOnsvbjTAcs)yx4ASvHFhn|Q z5DbydS_Gq4>W+KhYd|{d5SE?}=U+POAuYU8rbhM^b2c+YRu=I2!{-v`8(!#5I zdSsA}AA%v$*@|F@bhaTFz0xhXAHEf&=>#Jfz0zHH5WX9v6N0ex zbclcH?18lKUI#rgNM|pCA=250V2E@=5sY5x9(*sp52O=@u=I3B{!1qu(!#qa^vEEc z2n0i<6NzAmbfOT9UTHWUfk%RLq7jy!&ZvLs?1!}Q{tP`bNGArt5b4As7$TiG1fy5F zACJLfK{^KzmY&Y&f9V{AwD8UkJu*n=5P~7niAOL*I)@RAUg<&n5FQWGNkCY7I*R|& zNrbfUo)SGWNGA!w5a}c%7$Th%1fy4)h$rF6Ae~f%rKh9vFP$_<3-4CZBZG8~AQ&Q@ zbOb}BlYwCLO4INocsfYuD8kayQU8}tCZvV;!RV1eI>!(UkxmwZA=1f4FnXn#_%S>S zq;ni$>FJF7m(B@D3-7SeBZG8KA{Zi_90Wt8a|*%em7c&);yEClT!f{kqx~Et08BAt8$L!?uHVDw5)<9T>KNaqZ~($mrTm(E#83-1cjBZG7b5e$*eIRrzb zQ-omjO3&hj_&Jcyd4#2>qyI0R3y>DxZ=^>C>0CrGL^{O?hDhfUg3&9zfM3LmK{}Ta zmY$B$zjUrZT6iau9vP%_6~Peclpq))ol*p&S9%4%ikERKbp8 zk|zuu`mYXu^?wlihLz(#z^4i-p&I_zJ5Py%8wi$MDZ8#tWJ~+lG0$f)_%jxQ_EsSn zy}b*-4W)0Oy_NV4(B5jOy@@vx4W2EEG#=jGZ`dGKh5y1htee1#pIv3$HN{vY+}hss z)#4s~`kPzlSTng53|sD2Y#Zi}1z_8;9oSAR5Zi?XVY{(lECkzw?Zx(Cp;#CejzwUR zSQHkG?Z;xUSS$`ZfE~mRVe!~uECEZzlCWef1xv-!up?MHmVq6`GO=S=7M6`2$4+1; zu^j9amW!Rn^00iY06T-7#R{==SP^y}yMSH9im^-BW$X%e6)V9?v1{0MtPCs1DzHlI z23CbtV>hu|SPfQ-)nT`>dh8B%7i+*8u_mk;Yr*bet=N6+0rn7U!`iV&*kkMo)`306 zo?*|i7uZXz6MKbqVXv`n><#u7dxyQpdaz#X1NIU7g!N(l*k^12`+|K1BmEuw0s8MJ z_6r-rzyl086KCOUoP&$tqBs{9!^Lq4ToRYUrEwn4$HB*8a2zLa5+8w&#AR?pMZ}L8!09uCMz~dOioM(*Twa4 zecS*y#EtNYxG_EnH^C?4rnnhyj$7b%-1*!oxFtRnpN3oE*7$VX2A_e?#Ao5N@j19H zZimms=i&2lM=mvEoN#KMyWq>f4KFu*6}V5d8ea=;udKs2g1Zu%@Xg?2-WT5nu7UmW zo#4_j5Dx}dTp@TUxKIhhqrmxnG#&>|ix1$3!P#U2o&rw7Qt=FM?s62*23!7d{1n(J zb8!W+F=C2hs$wc)YGMUovpItofn)S}{1P~{UB*kn5#btMfmh=kxm#c+R@^&EE0VtLZb*n|TvgQ>_8=UVXmEJE>W3;9*4lJx($vW4-M`>UfV3_AZIO6Fx-CwGY=daa1QG(@Ka8_cPRTk_k?7FZB2l# z`xAPv4KV-z`W?Q0g=<&1ZiQ=BxL$>8Rk%)tYgD*Cg=LWIx!-}EC%7GGopD!EW#&WrOQ_z= z8C*TF5#ZSJH;N;7qL_i0vDjwrOztEx6S2u+l441MMi5E3c7)$JsC{*zYFUK5od30| zZzBAIdEmADCInlct@7cOM#}a6Yb!r%PwH_2ujMx*82t@-aAMMeV2BfwdkBVjEx#4P z=#@6(E%-egJjx8&z=&lzKRC{5PiOK=PjSsFewfHRNi^M$Q&Mhs#6=mQ!u*Eq1LdX%*-ZfWE5Xa(pN|v z`*mo%)vvCYXs>86x-Sq6F}g1i3^BT$fYp6B{9WdLUBo5ru;ywz<*W3h;P>L6<1g@+ zIQ3rqD?|nKjs~OKg7)A`j4t(F{99mC&wfAd z&_&3!R~%yLJ{z+KJx-h-?||Lr8gNtVlU$nh;@3Jwx3WhRIg{RIN$J6HN z@bq~`yh%J$o&|3z&zd)bH=Ae2o6mFPE#NuvoOz3ROL%U)l{|OeTAnA*UGN@i`OCij z^TzFb+y8hl+2hRZh}kNcF9Lj{QFy~Nzoc|Hyl&;Bd)L*0Z0b;^R*~>q5toGLnO4&j_|FS9+ei%9LLt8!aY% z7K^z9j`sr)({ka>aB=C+GvCfhIPmbtocWz&6=W3}zJeM21;K{RU=5Y82u6=KfPcZi z^3>A40c#;!Sbw+RZjI~HM^WGRe5$2SH*e->-aFh8Opr3(bzV7`7#~63e*)#l@cQt6 z{4@R)=U9CQk(lNuGWS1@ZPl9Nc>jB8dLw-@dNbiTYN|g#8Lh;5*!5Q?PQN57J)b&Q z`qOKt4octgU93T1>3=nOO-|XC?#B*sJC}xAPMEpz%y*U!Bbxo0k;+bEmq?dNk7cqM z@obEFO*)B9#bGe6OH1*kKjr0NZvE)GHF?!Ja06wm)FPZ=Y8f4@ZR&j@TlAd zc|$x7UxY8p-^o&71hMw9t}+FT>&z17O(u96pPR-#%FW~+<7RPFxY^v}+#TFg+&u12 z?hu#D7voFv`FsH%&RF*fiw@*Sl% z@%{K-d>?)Q-=DvouOmH~Z_GF0Tky^Kmiz@$;ryNa2!13#iXY97<;U?4@DK72@#Fc4 z{3L!dKZT#lPvalq&)}}(Zscy_dU3tEYq&mK>da;MOcM z)KksEg=Q(S@RBTobN2*Md8RYst0Z+HgN`cXLCyk=zJw zG&hv{nfr-5!2QDg%KgS2j-d ziXu}*lts9VX(Ho9CWz>Zs0s{4j6|$NtVJe^Oc${cnJuCL{*v|s@PXE!0`PfVjES)@ zQA`~BA&|hHfe!}%{ZOzZHUZPa^f3d>5SxUVV%nGm_M2=SSI&wK;OfeBL zQ8BKV7&wn>W#WuB=6&XKW+QtFHXC!ooUw)2B5VofhIxT6v24VA!G}(^V18H)eiOfo zH{fPs!R!f)ee4jnuGj=I_&o9NS>oR_#N}))#%lHob|c<|x8hsb;~Cr8+t?W_B}NwO zDC-34H0v4Oi9ZMXSvS})-r#R>PqsG0i@kyUkx4Q>Ge0qZGTYgbtdR^pONu4K>STYz zf8g^a_+l$LZgM{nD}#O=M6HT(a=#$?>&s2wE9bVIqHjbQ>;cAD)1m($br~6KoH@YA zV`s7XV!sh3eoP&?&Pn>kd6BA+jp=G8R=c7Y#Q&^fVGAO}KNrrGu{MYf;q`>2_|2x` z4ls(?=h?sTA)H#nd7z%NU>>2D(&a*oX$n zi9#}WOBIGa zkm8WM;UW>ZJRIB7qb@(pT$>qoN|`DP3wYVu8dUdFdLvmi2)AMVH!)R3LFkI;=Xb zlf9+x4PB0BoCK19B-7gOdH$F8gLFB8Q3NCj$zZ|KpW9cZ2hybuV-OFL8v#k-YNShD z27~asIuc0wKj{l?E0@I^DYFd+^&8zrU-`md5p04(h!CO#mk=Yw2?;`ykRqfB9>FIB z1V-QlL6F1M+T}}xH9PxB^jE`A%-kxG^dFX&fLY^q$2yDO3854IDBjrWQ8l5 zew2_h@svX_da9AkW(KwRQ<%RQ+8lRIFjEpVXcS>CkVllJpTe+X=Zr?MVQm2w$Pp>b zNG2DYtFRf~T4Vl0DLF!l5zS0t9#T<2=nFAE#Ky2&nXf}QA68p#cr3-BQb`af0xP^< zp?gD{T+%#O%sm6XZKr~$ls?_4Z`-LNT-=~k z_UN#&TD$MXDt;5Vg1ZPAIhiliQ|3u-44Aj#wxP}URq;+`N*}=0 zsyc!VJO5V~Xdu|It5qk#ScnPxZ`qaeKf@QEeEqN@pV^lrazdYDH4d=(*ZeFV?Tb%H zQeXS9*P`eheQqfd6%18EjZh~vh_Qs7Kobfr%!htu2`&b-5RBfL;0i<=!4Q|T;}MKr zsV1RCXcIaH6A+eu7NG```YQcRdJ2bQr2~B3=Ii70zWmBr`KWXGw$lU6^iJ?*jssnw zL5v4AOd!-$bwL@KJ$h0BaSK(mhL}$ee~Y_9Uslu^y$+ZFdQf|2mCBT~_^3GiwAPC8 zoYAynHI~1`ect_dU;^kP7-9k#AlR@8z_Bs}%)lz(^2bBct~R&xfBv3pnL$tL@5t&A z`h>xsku^eurgt(J*@*~-7+GTkLyYVs1fy4KL`)=%!N{5*EPZ74ppl&n{HCUmBftB6 z+A|bwr0buFcF{Y*n`ubsfex4iYA^vKYYNId(VVEOG<8W|tlX`ABX?YSf*RS$gxP5` zV1?Iw!Xr4Nb$3%+=B~U><+pR|X3w1}PmCtU5OPE^IBrr0>1c3>PGKq#Tt*^On-k8g zVCWL2L;_P!$s7^QGyh~qPqU;O>+EI&oXjuz%@!RgXMun>%tvC5>(Wc*Yi%~o@MrgF zG4C+EJf|QeeG{V&xxX25gc$)2yx>4>PFN7;(vl1t%o0(0*rw2AI`zLWh8YpfJjhG{ zdxxdfG(-vdxJWUQm{SRNjwNVV3e#H43Q=ZQWBzP`S{w~|YoO`tQ?_DA)wg0<4q3G8 z_=D*?=TSYcAwL~R`gjkQrbKY64Wb3~nJUGYMpzM=94)XFM>C^9#>rr(3}*&|akeI= z6I53h%gsPUQXI)ie)ju$$fDJU=cs2tMGI~URY*_*?dI?l>h^?2Ud8}l9D%d_wi{dM)a2GGcX5;1z)#a zq}qB+W*A#9aD-UU$Y1df`&Z7q7QaLG<-k@i;>3Il&CjOxVB1)LV2EwQ3BeHChBIKt ze=L}1J$91AqI}mCDek!k=%e*_+i)Zn5Ke!#jfIHN^mPHYjYSBC*ftg;7-HLSK`?ry z3yDRhJ&fs-l{z6>Dj6ZS$kVBKXY4RSL5zGc@#F1uGyXtaR9{a}caVFnYg&zbCQ^ z!4_2-Cg{aSiq3YoWcf}=*3iE=XElP+d)^YnSR7#jQqNyGT zhG^;<1bg$kJvsBJsPB&mUbClx$pp~UwFpLU>TJ-|St2h$Q{4#S7)_iaVki;?+oh4#Vuo+WC z9EeC(1!F0Z$XZ6Y5zC3y#9Bg6Wj!K3{g}=IJB%n}q?{+hB2NpVHXtPZs81c#SWH`D z9r22h2o8no2~TiZpun&aaU&**EF)~Njfg1pVNz@|-Sl4=V;!-db%>S7qD~LI5GCmA zPmz(#+C)&H_;>`!MV9^BMh-WsMH|Tx*cL&}{1QNUc?7+Jbq3M$p?7+bYhS-5a z5Dc*c??EtnrMrn>A_VNfdl8m?aNP;*!25u2>~fx=XEZcX7C%s3?g=d z4%h=~*b8>xP*6ru&7v}JmA!OuapfzC5xLd$Nk;9!`v?v@3|Qe|Tlhb{Cp5n>#xj30 zeldm^zrjz3Ot4(oOb%0oDazzB#hBtu38o}diYd+HG5JjJ2M?JzQ-&$a9L1Dl$}>kZ z$1oL`icBS@GE;@A%2Z>jGc}lIb>UFO!iAPwvq(SCLhto-o!$4+be>fE69L3_VjGbU zCONg1j)Ij`z}f-!i_@&xqSVsW2hVVZ61m`T83qo1dMXi!sPrYz{=d6KB*G$h3EwD$ zq#tysrNU-zBf^O;MlM)j5kw@|C8z_r4Hk_kKWsTSneP8Dj1f*yKSbsJ*&kvMCFrw5 ziIKV|PZUt4|CzC)+Lz~$N;9d%Cb2KxS>&kYfs z$Ti|l;A+Sp0G>Yg=$;y~;G%^UR2Yq5RLx!-LButf`6i@R%RNZ@aSqSA&C555NG4K< zM4}9|p6a9`&_(5}RB&*(#v;Y2Ic7>w@z~&0vXqrZG=M`y3(Lzj9TA&8`c#`a%tYb{ z@tRQzGQG`e0LwT7QF2(1Hkls%FN|@7pngLy{j-cS5hds|L78!#b(G*rWPnDMgJpaS zQD#_U{>&UgEVw8Oq3MfFnUP5xBXBW7tQ`Ele-5;+40K)v;{do@<3rT2R2a8eji9qR zV6kN*;?Wmd`Jcsh93h8yx2QxmSZpT{mcH1O!SGUT;DXj>gT;0dDkJ>ul->_2CXP7> zM(^T@%x(ttGiwV=gef86AaN2bwo{05!xx)lE`kkf1qhu3rr<=TGPvvX_jjYy|DjwC zn8wwt7O>p%5c;!yP1GWlTT$jNXC7Fb(Nk7oP-&R4@)1_mY_~Emf^C0y?V05-9l{+H zPZ7DqX(ESc292U}uLha7u=2qA=7NmtI^R~L1_q}rei+I}9au41T+@OcAzuc(?h zUP3T>hu>$tVNj1IbhAX6HzcM?7lYMx8BuQd>Y8%}!G^U0guX;{v+jc<>fg0>^*@xl zM5r>_SlwW4l^}FSTVgW!<8PuCr}|1HLplvr8B`JstQ1(`Y0k=1= zL9EhipPZ=wz6l6+9b#z-Z64B>l@$@J3}Wxaa#LQ+GZ+}g&RCTLmT5mxchJOf@@|ip z_T7u}o9r5^^+Rp=-+q29zNeV!&-7*%OP!axD0Nlpid31@F+l|sI$7E8alns8*?|Mk z!iryZOi~bQ`@}Dmu-DHKR01aaoKfqvslEG;2A9)Y06u4Q1HoFePuzBR6nVSSz$$vg zxPaEu96=St+WBkmXNKAbBcfF!*bR4M{p=O)jD`-0g}MuGdVy#+0TT|%@%K}*B9mPM z=+VFznQkGN$!IAZvWCwY~E}>9b{Sqv4Y>n<~fU+Dj}lPBADJ3m)7*aGV_dE zY5UKJ$Q}XF>LBKDOx3qAZ~bpXwA%<4t#M=U#z>W*{cbD1wS1lw1ESSKtb4)IdMkPJ zF^Fh)5X@HPZdv8h7x{ZuXUH$_So|AAy9=>G$B$u)e(u_gh}M8$*Cct9(wmx-zRgth zsy*M50ircR%yqrU7tARTM?`Bvu=qFF%j%}|ce9%gL>*D!aY3|Zh^47L;eNg^zX=ho z1;Or*EM(4|l94Ud7kN6PRxJWVy9crIT&K%ztd-9Y(OMC#M!NoK&!VjzqfW4}@WS=; zK(zZ1EB1R>Bf5?igNXJ3!CqTL#f{c9sgk{6tH6%1-vFXLgjm|KrM>Z@M{N+%+7OJZ zYp(j)Cn(5g)$!htQ4hmGw04LUmub43O59lcjn`#NZWMfA6(pl1)Ig4v3kiggq^9_PmIQ_7uThALzDg zUw%zbgpoYI+rRHKi1rL()or6gR%NZMK}36wU@Pr{R)I_AupY3oi zjulxw_ePn842aeRF;BbT4aPrJA0wi@MzGZ{x>F^NbHDj4^xfQ;r%?-{bwf-6JLwpF zYRUpcv^NNrJb%$xf9s}AQvF_D>Ri!K5bZ6*0+&QZ{`i`ujEMFQ!D@V!p6kVTTer*g zbx%J$PZmUb53!}Yes-@J8;|O@9t6v)bZB38*gxY7>qFP9yyHnAS}(-nQ;tqFA zXxj$_BVW}XBj3C(4mW#J@R84@R{ckanNL1?cvk({B1E)L2v&d3xFvD<+Hd1#dz4O3 zZ;J=f`XCmtZrZ(A(UCt9(fSeWbH9yNU`sqx_vA)mnnc}65bZO>ZpI~6-ja~sgNQbO zU=3*-41^LGR*8GB8}BJk z5szTsr%6gG8rA$(4lq}Feq$3KMEeP`ON_^=X_GwWAu|1iU}96*BNu-o-oNWmG1;+n zavF#>1TjZ}*i=8e@3Romej}L2y^XKhT znUQMxItxVOKrF5E^l_K&llu|TL=fybTYble)d%knd_J+eQo~^kh$afL{s5P`HkMXL z5z)8^b}3ilr(AO8r!!AlmhT;soD8CgLG1YLGhUKPH+2xv#1Sm6YL}5=*UMd-W}TeB zNXC;|^%4+!A>P;Nd*1=IXGtR1s`z7jmV^uRJsu3yZ}@yi0z{L7*mst)&hN*Y<|EoB zjbMd}9(F!s=cy)UJGYz)zrX>}co6fMs*{IXH=yPlAHkeg6>sv3axjPtoOLJE{ooQ1 z4Sf6c-$c5n#WIZ?-ByWc8-`#-i|6xn-^t&N4s%w#<0^3oM8hH0#eDMX&c|}pzCa+@ zD>M5X#nepe@v*Kcj%QPUfM_JdJiqjw`Rl|e9E&WOd5Ya{r zzh!6I3^FK5f!bx1Aa+Ll>lEAiV>c1elo4!2rjq0qhxr%Bzq)hFQ2u)-h^7KDPn&`A z8Oe`PS8b{Y=B&`y+{K)pwm`9I{gIy|Nay=Qs>w>jje#?9{tmvto}td)N>xE*-gaUnQv2 z1Y%=Pyza?*Rgj2?HW|TGu5u%o-7X31R!#mq#N@F%u&1XCck zA*ZI=Pvm_UqHUH4Hr9BtZF=@4&FM=d_GM>VihyWSA-1^r?TZbjfvCGH(-7?Dq~&pk z#=m?nyI!zv-J``+G%JXCEcZ}s^*B+EXqz>H*_q)BNV|>k;c6-)3ig{V1<|HMEb7}v z7njbXvWRFl2$tKDeDuqn>w83_sz=2#JdI2wz&v)#HdA|iLoBW%XW|!Z+H*uS z2L#hl;w*kX@`guO%K3{39%3Ayy5p4m2nS0OfbU3l0_5SjM2Cv4H zQPG?rw$gp$XsN&-sJ1yHSnu}@H_Aj0`uEKV^wXVuIu}G+2r((^QERQ{F6l+IZ4rWr zrPi_EteG%$^!n_~clR5pJKKvPcEnfX+GwBX--u`~2sYYd{jKfC8Shty-MnVG;zA^d z<_fXjQQvg92aA>>qAfwNn(`fz=|^~ShpmaN^J3?%2ho;7EWF#(%dewm__NgO1>Xx+aAlfR3sjr{>qEtTT1R~mM1p9q@ za#3Y-Ouj=nBi8$4_)!qe9bz40i;f?8n_P;B=7C@*VrSUSK69~prT?MY_d&C%>xDHC z;|)ybtF#~svJ^d9=VaSF?03s zHQ8h@BH9)NTkz>{YxPcI=_OXFnz~|P3y9_iu@$@2%Dz?3L}j`a!LsKWRbOc-lbz%> zrlopb5_P?>4Pqs&>f1VW2YnH3^G7h7md`R_)$NS|-U$U`5>%;s(E$*%Td;f_#&tV} zh_)TUw$C~CW>a~cQMhew$CBQWRJ0ustJrolCm_ObG9ube1T#NB{_fN_6%ltk^K-YF z=*NO+fe>?QXgZg0%XiqvvnM|DYeptZwx@ReGq%z`tZv7s7>z> zZ3{&(gS4ZIYdvP)Z2$IfMcc)-{UBNx#8&$R+K!QFHuo>xmg=h)kmq zY(!!B!bMtAZdvk$y+_oY<3P0i5F2{LUn~1_?700f-5Ih+n=%tvHqEU?kV& zZuhu!{K6LS_-X}_FI7q0AgYLJ;wEv6s3B^JI^s4_PuwBy5)DKn(L^*8EyO*dmAFql zARZEJL_6__cuYJYI*6ylGvYb%f_O=E60e9Z;x*AtydmBa?}+zA57A3}AU+bGh(4m9 z_)H8CUx=^7H{v_-gBT=!62FKc0^GbNnIwy3lN?fn6eYQ&7%5IlkdmYnDNXW7J}DqE z5+@0gBu9`VNf}a>97W2J^5kf845>gWl1ij9sY0rfYNR@;L5?NIk(#6ysZEY2Cy+X% zE~!TrNa>RXq#K3+YNOA(xWNNH=mhxq@6tt|C{H?xY8~ zhFnXoBiECjmYmRVU?}ml{1#WdL>< zVw<+#+2q+p$a}c*&bOz z9U|k&!{k~#5uxWyY3jMH_({Q^^<&GcP_51cvR#k_IpGs887|(PvtzS=1(XF@AKS0I zQ{QlBGGLjzuRYimzAvQJC*4pg)gejdSMnY1FD?7{QPb12C;JUFNX?M4kt!$7OU;xz zKprF$Nn0sZ&PAyt@|0ATAO)&O_yo?dH^Q<6sSp!BTGKwSKmDeS=}yn5zGEh}rniCj z%hDhwY&L=&ftc_K97Lt*5R-ok{?2{9o$oN_D#(DCFoj`94hO+e1fxG`23|wUM6hEs zLpIkJHzpY7UCk2t?Pmer?K*~F^w$q6B}yeKB-Tr~No0^m$xPB!kOh?zb|a#x*$9Sc z>Tv{He`cBBaT7C{j9FJ?y3O*A{zcal2sZIiBrn^}KUU8^#B}@CjH!u|2P6|D-%Gre z$Re}J<0SRCs;l56R8lyci00-X*hvLFu?1o`=RHqZ5c0-0FG}A*a0+6=V{*g(I?YpJ zsW)9}?YbL#iVMI15(nHtRQW_`cFIWdsy$?uCMPXI1RC)-A7jYG(P`9f8PSI zJcu<+8~@&Dv8j7Unv@?WA{6_2pmQ_$BF$#N@*&o!hS^>nWbdN{WT=DgJ zem0qCOqIxM7ULcnD>W1XqMd=5Fw^u#)1&8h7rgO592dWm?gJ({(teUX7QL06%LCO}a)*P^oPm(jGa>!F;E*PNGWFDDM7LaGi3dTLD5-I9K znb)OU1%*&l;o?FJ+BpP6%&{T_i+!;*+vCcyF#DsQLzGQ@mBAc4k6`pUCMSJBa+EYn z@~uQ6d5#2sPx8+ky8x9GE^dX9NOY|>VT|zK= zbETyvq%V*c$>Ki^HDg@{WrQ#G2%q2#mVSR_ZODz@usMG17V*oU>Ru+U5Lbyy#B1>Q zB=wYL8+b;un^gjyrGLe`0S*SG;3?n+scS@niqLGekq~^ z{b5#BMi;AuoGN{lyi9h3r-!d0$_#7FpNC%;NT`Tk2YSMYA;p{)R%nVBXZQE>+e5Wv zij9r6yw_)?y^oB4osq90Uk22d<AZ49T!Kb_&HCYzEv+G60c5EXv%Xy}$w5snslMuyg~D)I0b*7HsjyQ*?T$k4Y5V9= zfw4@#v%{sBv<7hl$gbe*33FCWo@r#uyf#sDW(!?meAF*R1P*rt;ry$xY%in2mpr`)?)ogZW4uYRbrRvVyE6sgs5rFi+*c3?;xE zwI-TlKsW1C%KFttnVzZId>5;=mSC3$7R-#cgVMl z@1T`7SOcQeus&!qZTv5cafkfC8UT%<-p+19l%S8B8e@>vNKTh-01f&D4iwFZGQ%44 zXPm91gLkwbG=0gaF`CF`a+VBhy`XhJ|GZ{Ebwjb-JwychEdTXqmbW70@XocC zz6WOceT1dYay2k$R2#UUefPjDe*l#cerAx~TMYI)2KA{y0b7hY3(WF|h%$&--iBcG zPNl*=AO&m&+gq#sKllfvI)lX)un(y`LTHO~aRww`bH`TmNF_Dik6d*I)pWBxj}dms zkkQJ^u@EPsY5K_54D29N!eoF&}>8YEy_YduGl z8P=FT<2(b*@)rnApXKU|XXJCzMtTOA8{jQq&^kVwIuoP1p;+!EA_9Gu3)s~613D3M zc<0WPehFszD}<%ba&<6hR2#UUeJ{Z*?}Ew*KaolAErR`?L477ul`YP+1GD@!q6}h| zcOw|RQ>n0Bq$-;Lv;56}@Li+^V+30j%<{Jg&3Iu{cyg?5Y|es*Th)37i!>Ni)6Mq0 zLs-WRjFM?1h=zeB&KpX{wd=elyU90X7pVf;LZv$bB&*7P3ud_zTM^9i_lOwufuQOW zXLgbA$oC9I&`KMu2T^KRA2gZv{ujo0M~-02gT_#^`~#u{ecUt{%Isd!PPzv)NEOWT zkBBnE8uMqI=YU!M38Cq;T!Zm}{7BB0o&)B_2sQ~?r}Af(Q{7N3*N2EepXI85W_dqC z4)0uB={_*aKO-!CmTQ1PquRg)?dt=xd;lsV{JiV1-eUJKs875avn81JV3vPDltIk$ zuL$;kT08HsD3*?epW0cb;dLy?a0P?W*eP>Z((x&k=VjC;L_D!#ct! z|6T|FtI`QMvpz7&e^BV#DNB}}+Lr72F5yB>$)x%ZoRA|_Jz&O93R@NCEFI{pG97UJ z?Sg|I{mLtq-<02#UzN?EE?je+p|L*f4;bZ5SZ^5RzbG2w8^K-A5PwzvRK7>vP|G%^ zRg_Y-`XJx`cU>^_Q|ZilKxMd5UQH<>zHd&bDf?R)C9Q%A`M@auLn%|MGMf7w0izs| z|1R?Rks%)CPN-V>M;R`SfU)7sIzjE4X+}BM4aY1nML|5ueKez-p^&vZH&Tkp#88&P zibuH<+%&EZ`cOYinuqEL%J89y#l7Xnen4D!;ts44?gFD+mr{l@%JnFixKlY<9nyjI zgHf(u2VRFbqX4!8jB*KuUT43=GkV>c8NXXs_Bik~^u06Usva=IfWpf6=r(w8Yxd{Z z{@Je0`(PbiqDS08;YPWXQbK&+oKZX0m~@dEL4`WNC^w;$sZ|-xeU5=qE~C)m zQSOYS#DqjkV_<9qu>MfH_L@=7b;B_WIYmJ{$~$OAxhaLL-MO8mav0@i6jnUSo#Cc& zb%5n2krSDzLQsYet1WK1OY;~d1rv8_82b@%5xC=6W4u7xU8*2~azZIr`+?}FqF}XZ z0n$nm$A-aO)_&q!uMVY@#05pLaqw7}Q|R%t8lLSDVfgBt-Fx@Sc{vMQ5Z8!+pYQTJVw@(GPNqB86n-IL*+I=^B?W{FCAwy z-y>~uLjPIa7KcZFN||=P=eB@*w;-&PEd`^5m1;=A%rlECw>|4H+`fFVzS<;L7aR%H z0*v)qZL!LHiNlH0MbA(6j%;!#cBQIpHY4UlMB+HJuHk=n?>GN$a7)~J zOKCQ;k=hVj(vYx7P3)y%a(jV1-=^zw z-OvA{w{f{{=f+E344*VDn`7;WjizgzpytlRmDt-gf|6I4d3A6u8RfpOt8M>-5BB^1 zudBENYiIEH=G*DZ68kmj`m=lPtw#U%RT`1$j0cqDO_ltdD4ySKT~GsJO}a|E!F(6N zhQo8yOEbZ{kz}krGx>SNLvnYtmG(xcuM=VRaTlyJIfilemW%zsw;xg{23q&3}EIls$ z7tLj5rapo)d}amlJmirn_XUiffOb{Ldoyf6JJ z<;4S>{jLrWR7pN&a@5s%ER^BYOU(#^$?wjL z0M_n(gGSpDqOtY#KxR4fofVH2ZG=N7g^opApg)J?Uif#uoBCwKOQknouWKl#lW`lE zB-;TQTiD}WcHwvBL%m%syS&rQ{gUB1<-i8Bd;Kax@7#)V(PY_bOO9K#2i7=w+{t|z zUq>4?aayYGHm%mDMA@hv=_c<0B>%ARL#|e%&UtsNgJ3dlPdX58bRyGE0@-_pw}yqe zHf~W%cBni|fQ{Pn$g^FkUS_w9_aF7pdgJOrBOTr;>|4QFA)JCy)(R06Ed1})>0clJ zd-l(kwt1(*HZF&(5Rrhn1eMNIwx6@Dd%4rF-cyw=#9gkvL184EL=Y}3L=;7OWI)!D zZoiT(Cw7i6f3~e}I4l67DHvq|5JSNz3xLiPOnlKO5=~-=hj$kWD_#JE!CY386(Xi9 z@cmnyPM#PaX4+^-Nzw6b1K*1~AsI)KFzA5JP%egaA$|~svKy59G;zcI=k0T+b?WhU zX8-#Shsc3EQzqNliaSd?VtSHT(n~X9dQ+sus|^@2eJB`Z#Pp?Llo8X9f{8EMoAe=l zVZ`*Ou;LNZ^S>h|bO7)@`VyJhX?I_g{x-VZY~3N^PDsXaq$hMhKe$4Fn6m~#nGN;< z7aB*(2KSs3AN|6tK_zXp3?Sdl1_|oJzqZ9=pgH+rHW;|hS#xK`p44d<=X;7VYxKC* zM&cvg|&5 z`O&)G$()SvNign)QZR9YAzJw`3MOtVcqt91U`Ns(PTknE&BBfyLUl?#iZTEjA;4T+ z`iw4WRM_xPvIUc47(bt7N_IRO8FC4nnGyvU--N6;YnIOFlF+;Fovb|`Gn-rhhoK|^ z#;esDkw+IK3ou@76Oxo}Xm)&Fm#|09JtHDgxFn3ZXb2ffOk~4|w`@2WK@wq8l?218 zsVqq6fqbMuh3|bze~qGGl>Qn`!OR|y9vWn1X|L*LG&T!1%i9@9%ZdJv>E5oF9L8JKdxN`fHp3rX;RDDfj}VX?%mNf*J2bRF9YOc-m}v#`76g8t2C z9pyGLP67Y!Wk(Qf2W<--cUbnPNXO z0oHV@VP)2Wa4S1&l!Gr}Q&~K*gQS}YgbS_7MHzgGOEDKMw+jEj^%y0%15Bb^L_9z| z^8F{*1w#|aB6c~uT4OKyi&8>7>v^Dbb~33ln*`N|es-NgDO0O5nw`QKse@uF&;iQr z+4JqJ&kTO?N_GX02(9gD<7oLea25Al<)bpEoeG^iwLE7?Zn&7sMxAAjcGG}#UGgTm z!MWy5uI)O1+TO3B*99@2MbNu=;-&u=Pcbt2ORXKJQ?GTUuL~~4(Kk~?tQQE?8V!w-H%yIL)O`@`+lI>WAvJ1Thivdwf9!kPsaaM%SOV? zvH#WMvd6mG%>}h_Yr~6FlT!b&d)v8J^h2z({%v0OQ3w31{tc;2pEiHPLaxjl;%GMy z*xSZkkM1lya_HEjl0vg9KmMh+$iZ$tu!gqEydOsvSoU3I8T#e-=R0E79i_0dSO>cW zz$P!am2fvv=UVr@udRD-xZF<6x}tvUKwwjWH5jncdWW^ifrrBq`nMmrp^untgvPUz zfL#dec=w>d`sYjMEI+X;DL)h2h*>u@oK0dKEf)bRUR8+MY&4Lpk}n35UoG;xn}?Lsj?2~#eaIYrqi1a)#i{ucri?t*{EmeQVQ>t z+IGc-H<5RIbiBsx%$l;mUbdJlf!$CtR?9jNJIiHIrtb^G)D_2%&b;R4Qy1n;a zll=T^$1|fd_p#SZOQF(f0(E{NaW0UoANJ{lVuihoI8SDVW%AbQR*aUgfgsg`_!2Bg=*$ zfE_uX3|YsF7U99JwOh6lEO4uV6u-U1%hO&S=r1ybaQUOxv5VM+FcYt3r$QSXWZ8&| zSf*irNh|3YYkhq~m zycB~7&Rg? z<3DFQ8FeVNj(DO>NIRUS-bkT0P7Bq`aX1}gw&ljRzo(^L(xxd6n6Zh%8r3hj`JqYE zouOR~5()-MpROkxNCsI)4nd8$W@kd953?I#L3DuK4@aGu6bdhKXg}1l zjp=4esaide@4uxk7}`WK+1*eX?x=GsrG)tYd7^{t7J?Ot_)kwwuJKeC=^ zE7?Z4Y|)3=Om-8r;}E-DGwW~}s*hRhplFDnjKi8IV<&~IeIt-!2Rs?OD6II&@Pr%8 z)j=O>xPvT_?1nPpUqyox?>0Q`m$Au2Rnjn~*w@%#k3gB9uEc%0l-Wz6#C3gycM}zE zj0{jyWQhEb5t@J}Lbg1A$dtGMFN7R=d&n{zfTSo4S);$0DKNK%Lk^`>W)Y;?Nn;{l z^_{_N(qt)*gmCx=nZppp{R9&QVZARiIS_&RIui}9{r8v$;8^{Hi2?uG4@?EPjDBT0 zgBK!ZS#YeAuwB4cOUbIh{m7E-iky%W>jF+19&9%__xEQ5;V3(V?GA^X;cO(FdcavB zto-}3{n>tOPvnM%u_GWCdMxY(#<3G1b9yi2j;6CSAnSS@>@F6vi(#H#&h~}}YZK%m z=f?3)HV~Ph47>?%#Jh0|Btv`ge!LH##6d`oPT@27G|s`n$Q0$`YxpWI#4V8-D#CX) z+22Eu0zJp&xD0>9p|JC)z@Ifa*jpijsxe~zU_+)gQXwNos>#RR2Gv9L8B4~3abVga zbL7OhFwRU9rX8w}nlZkN4->+)M;53R(}royL^2(aC5mP`GcinWrX#XKeVP7DKV~@7 z2{k~8Ofr+iOkx__?i1YKr~A7qmq}t1#N(@q%U8Ld0@AGJjcpGI$g0Mt20z&Mm!(+p zHz#?J0@5W92}nMVvskj4lRQiTsgmj=0d`{$0;mb^@M=rvvP=4b!t>kQdqj`DFMl+9}uhR)~KGQu(MKfuXeDFb<|x|spr+W zQ;-j2D{ZVkBOv)N0>rBNHL7PREWNJh1SIc)EmoD(sGg^=bkz$2lJ|HOs~Xg(W>Z+Y z>O}#``;m!N4Qo^{QCPa_WdX^1bct1sYE=KBuyoZN0m&bpidCgGs#hp1T{Txg^2e)U zRg)Uks}z>5dQCv`2e4vQS&iy-3QJeLAt3o9TCu9UM)f9zrK{c&ko@9QtZG)HdYi)1 zRr3Vo;EGx5#V@QUiB;>>sOD2x+1T@0SC0(4TjG)z<9cDz>0r$hdq+U}4UgXz*Th0k ztZH7PT0mjxs)Yiwqut^mFSkwYCswUrqgq5^>8iy7vi1F#hN*we{w`Lvs8PL3Vd<*( z1Z0=P<<7B=t-Fa;Eo)ToQ&_s{0|9w#|ElE=COwD~t6J5lKBTa8)kgyILQxj#JbQ|@ zShYcoY6*p8eizIs;>m(9;YkELQICnh*j-sR9{nAy6PJN84y4FNkYqqEyb$#HL7nZEM4`T zfRsvxj88fJ>zP>9p+@yRg{7;05Rjf5ypr78#TAHE9cxrSQdpYmB&GsL@y{&wb49Be z%lwkMow`_Wa)-eSncd_Yszk0hP^u5f1xMk1WIr)LRcI_eKn@Z^NH*w#50S&f2vUYu zLtb_+7rQZJWe>(j$WbDNG=!e`7&%V31lbsSV=gJH4O#^WWqV^T^`0#x;bXB6K0!{B zhLFQc2RFl~$Z7HtwnMie%TY1IeN$`)UmEM-_skh`me|ARf`~mw&Jzdtq)NeFAlbwb zK09$_FOo~d30(92*vsS}aI$U#u2Y;RrVIFFcE>s73YdSSxF60XSHbXOf@ASDavjV; zGTa5IJNPo@Eqnv^2EKN@ zg9hs4qk1~G&}xfMf|165u>N7a(f)B~7k>OYHmNvtscRJXl{zE;Oc`n7k%w1X{3{UT zU-(JuFEknxT`+9luX;8L8`#Wy;3OSV+x zez&=6wBi}Q4}w4ICiqJr$iLdwocxp>(6nA)&-kqJkob&wzwtv5tg4&fZ-F5H{u$A? zpY{8hdRLlkOZ+`JX@Jt4DFMOix(WUf2=cF<JBKn)Kv1V{g1Q1h{#~=^-Kb8gheZX&Stcd+Q<>jU%u^85tDB&{K#+gU zgimZ2y5SqX79=lTztq^Ix)1XV1SNG7G!O{#ZR8A1tfVQCTAG z{9DcHs`OM=NIL_wI{GS!ssYl@!4e$J`#HnOQfQhL zh5cP`PVVLAhhx52*`5k!e?K%48^Ma`4y4>p#|z*XU?Db!b?_R^N_ZI_s8ax4*+3P5 z>O)-%Q9XQ?4F&@`XG||b=J+CeQe#XnM)h$no1-zN-$fSqCR?a6rr$%B_zwG2V@$t~ ztngj-Bj$|h4^RXAh^^8X(;p&h{FF6hIAi)FWP@L@^)$xx5@d_tvJMPqOfN+ZaRu8% zV@!XH)c7kKqA{jFL3a2j8>um-KSlQV58GQ~On-(Pu#V1fjWPW>a>NEYlQhQkGRP~Q z0!JEQXbNKuYsYfL;I(kTu}G8aIhARn*B2rVamTPhy3KT7ATAMj1lpuIaLs`C(HzBU z<|X1X07s(3nxol+47cj!@|i}V98L1t%S@DE9;_U>*hbOl0b_@rK!llKX*Ps9<08kb zgcwhU!6DUJb;+=W=KHPs(jbTz^9FHYNIt-kNd?1&7pcX!T5T?xl2Dwg|;#7^E-d%yZ!^vQ!h?;3l`;2O zr9T|C1hU-clI=D7jS#l8^dsWFEDMK&mq?cTCajlc|Ivk=51(R4aXcKp^g#VtSIrvS z1doCvn4V|^>jvxb&#()b0tYd%Xad_vvmTe@xo{lQ3(WwhtwYi;h;#T_2*)#vS2i@wg1mL%Fli-e@!HiFU)`9a5C%*-}RSuPG;gd^}>( zdAwW5m|j@ek5J!_!mUkWySc6WFSPF~S`!)OBDR zs%%v&yzPK|I^gS6lee$E7v2A~^F>mt;*?KqmzQkFJD1Wor0umuPaY{SxABr9HSqSp zpA7lu=0xxAW%ku?POiANq}T1JmdvBH#pbUI{!I8#)Vsd|bDJ|Q?*P1VseL==&);%J zT@LfT7@cus-G!Brsko2bz#LPTD?|5sD!}jHQVs72{44hOp(6uQ+a281`0JF{1s$9F z%xIi=CvlVig{KE++YU%kU~ZGA)pr7(`R82VmQJDWsgfIx4`;Zo)xBV~G3n#`4m%J1 z)+yNQK3xHx2&FZ=Gw{E2)~__Yzout;@!If{^@Ah7J|YRBiyuxt;O;uA^{jv(1?D!3 zT74JbTZfu1mCAl6PDmU5cxK_7Gp1)ol8np4&8v#%`E@Mt7^eX5g&#G%EAT63ZP>r( z(v+x-)y*U={F7ND?OxvhsW)tk-`|&W zN~ecdDZH>1MmDf4DHLmKgwgSZuxFwLd?;2QcX8ca+v-zd@Qm@Hxrs!F=A7F-j z9|!fyy*S(dVmAfmHr!g?8~F3Te^~k?9@B5&h8}ELVKGB?Y;U7c4I&D=Je5prts^N? zU~W^+@h_Mrz>9z4RkBy5=GfIv#T~fXtGJ_92Nie7>Zsz5SDjSc!K$;0J5qH~afhj{ zu+lJM+*I5FY9keQbm|Uk*k+6etX*3%p0H+(W*WmTV*A03KijR$K=Y5@X__c9av3jh`Tpz5K;Jguqu0tyB9EcS61Y9L(n-aAKw>K5a04I+S)lP8t2m&V$ZYO;b96VZq zV+Xg7E(E8JXmIA>cF`Zfkz*h@aBzEQLk2PNSjuoaXa{iE;P%cH|L?xoUeX#aEPigpL)zG& zjo|sB z#6!qa9!(JwQ(guJF%&GmSF1TwjGq+Fb=`c^=g-_bdGgK_s#eVk1+I|bW1Z=-r} zSeO3Je-B%9(y-;#Jb4caC2ql)LU~ULR_lJsB(Z?;?*;y^&(5*EI}V$Y`>v{D=<{aP zePxnf0*belh;2JENt}S<4HXU6oM>Y{`dlYA*6MnTz4IMplHLM}_q}PB*Lbb0+56UA zCN65$yIGW4Cg~%fcwd^cTNmA&bY;ZnC2ghsN_3cOGD%+n#rwu&-tVQ{Y%-+Oeq6Zx z`1iJfGD$xH#rwKEE~q$q{&3*H8C^D%&2D~qjZD&CK=HmSd-r86N&RQWr9BVJFT|9r znjw=65K#PK$H!IOUDKAw^&P&$?#OYAOn;eVpn&2}Fw%zVjVYSfu;1tMsxwDVkNYW; z3=&Yh_rcM$&WTqbT6^ch^nK$$Pl}dF1`805KQ^9tikK?Pg8B#b>({X`}iDWG_>e)Bs%o}nkrw=bAk@AtYg z_hvH5C;`RW>c822dU8Jb!E$T$vmJ_Zmp88^qXiWIJWe|9SF-x#NZ0PszGHqr%&I^T zCSs&!-o&tR$IcimRoL0dnfo8Dweu;)FThVz38BT{w*<4!7~cBuQzAyGWZ;YjHf-EK zLrL@rNN~?=B7uzutO^(>hT~v|jC>08e2mctJ%scjJ*++Q!Q4*{|3ONn_Ae*F=)iv| zx&IT%w=xNidiDs}+Nv3(U|H%emjw$piYzLkCK|=w1#1$GCWwG7iU!bF6OdkQi-;&q5myC! z14I!4``RORRBTvLK@{aZcVTANa^LUw`TdbM&y(NsoVhdSe9qh{XXc)nJC{+T2lpk2 zrY`Nec4_Bg>)`4#+1tz2%V&~p#||C4ICtpc+_8(}DvBW3AIoED>e&FZ@@?PCmWzLy zg3@&za(%DnEVMys^}NI_t?w(PC~f`tc~7ai;UJX0mz5WGZgHp0C_V0J#)Ep>9!pT# ze!pquA7=tJD6O`9u+!JgH43Fy?K^U}{@(EgD1ETPasJz|9}`i!Xq@39&&XBFP&!Sq zuXMxU$bKlTs98AkPg-Pw(jC@F(hp7;(FvuG^*2@6O&K~CrM)()7Hz70hUC!|(p`U@oH@bOT8Pp^TE$O&khypwO7|-p)goqL z*jtnyv#Y}4C%b+>p!D8tt5#l}e{}*%AHI}Dj1F7W45cURyLsi|qAlG}`j7Bk3!Ycc z#$7bvoYZ6B2xbG4KRVkwc*1g1CzK8!u=w$=-@jRp(p&9I_x3iPHVUP`n;dp~O0R3Z zP+BUUIyX4){T-BUzs|+adEkT#gbZ>1lTrPDBjPh6;-DyqrU@p7{$fNDvQ!-t*%%?q z(J_&s5wbiT6ImM}JFa6QlOtr8bxdS;gzTP$5#qa}nU0Vp=$L4_ zgQn6k(VPeUtYe~ykC2_wG12S?tsmr&#`io8IPk0=tuH0GRyB3UT12StidC=w)U%qJE_(i$Rq1wh?ESt**Ph&jCQWy2*)OzPp#tV=1HYBQyDb-ie^a?1LA?SFZwLqJJ_5+mwT?D!V^aAJuP`m*00on~z z3Um$VB~Yl4pc8>M104i93v>tQDbQP>5D`Hy1zOKtl?0stv<7H7O;8lAW}!<7qb=|> zRkPe*gW;JTpb3(KW+Di~5{Lqfi(Z8CHo&-~aXHq?*UC+we=4v0TpkVe(9=(3&|Mq# zGZ}oVUAkzYE~?Q*Z$Pv`&9G7zt<^#;CFm^v-Gq`3a6x)a!cwY!a1Xl>E^BcHZLt`373UM@97tPT{ z3w6h$KVexlxqv5vB6O6a^< ze=a2ngrci^|I{OC;BrDdW0tp9;IvtOh5rkBmJ?B2cChJu!qD5x&vTC7@6-Hz{x^J= zbaC19mW7=O^U1UPy?s6XW_eEX^8Pi@-^<(gYkDx;IHM$p2k~lY*TL3zVA_T`2sa;U zEJ6;TYCMup?6Xz!c+qJMk|ap5;Kj&KqHZoPG&_k{vX-1e~)9ID{ z+o_2^eQQrxOQIFDO3_-SFjgsGP?|+6ny3^8(Te6O1*uXPU6imY1q@efm7=9eAyO%t zsuYIN3b{&Qt5U#_wo)ksDut;^Ayz3Y8cIc5fhFrTE@a<0^!3{;oeak-G3=-k0f}(a zvD%XSrcy*hV(3aE=+QPR#bT9Wwo2i$(kKeJLsW_kxOi(MQ1TutjS?X7gGvD%KTD

9DiU>#yf=a5{G>Ad9w!$SGXrM}w3YUp$wuMSD zU!~}#QmlaVXl-}QP$`_XE#RqU=cyE3Rf^>x8>MD9!$ql5gu3go}fk4T1}FL=s%wVI-*8Oo&ZZDeP5>KUIoe zU`Hy&YM^l|ji3|#RSH)%8w2SLK)x!)A1X!9hNp{3C^!t=NJ2;wlSyI_Nvwc$8qg0U z(UK&bwY_RW5-dr~(d%9)IiAb)JNOoT7I!dObO?`Al)uGVPGWn84 z*jvKTf@wnAH%&B>j?ncQNpp>)bF`wRMq;9ofOWw%;h>Q?X(TWew2S8Ys+mRtW3mNw zns#`=u(Ss|&`8>9Brwas)5=*p%UG*fus0YOuG+x~X3JJ9}C!Kz4 zZKV!bqqzh5@{Ha@k@s8utTC2h@6B};JmME>E&M&yS*BwpCzSb0_qS-?Qpb8CRwv!@ z==cVj!ANMBCnc0H#~KMmgrY*+KA&xp&vsO^2I&r+E5t^L4lN~sfQi$*LhJ-l5?aHm zLM+HQZ$j-JU(wmoEqj&l6lfjYF3iy@C{gAg}8O1L$?aCJ(`J`bO-ASaff=b zDAA#5KHF8znpTMIN*ubYS;stS&wQ3KCrJQv*|g+>W?VoJv;j=aB3KxtJ6J+2$pNB? z4y|=jfi+2(k_0?;^_v#@INd?(4CpuPUsMrpSiGVoXs8(A8~rLR9_G=8r@p>+_fo8k zSHAzf@=2_WSIGapvIZ;TmGpnFd;u%t759Iy9EJB?(aM}@{iQ)U>sZL_%ycYdcGfx; zLJ`d^E5ynY2e3kMo>Tx2WCj*`1feK#Xs=_zB7h*8WH}q;IycW}jq+KC5(jySgCNUU zoa@XPT|V17&%rFup)HsxjK@5wbA_16at4bN|i8UlSiCj$*9>h2zhDwCS$)WP3Fd=V;XHY3bkCPh7ZMY6q zv$Yg0N#2}~x@K~bI4TqExcA|+MGpGZ`;0+<}nb@$fZq3yd)JIqu zKQbgXO6kcYV3 ze*``cK2I#TN8$=r&MUMTZn~)lrH1;!57p&y|MwfF%x{&ct6kecqp~uq+w7&Tk?=#f z>R{u?L&?HJRHT`<&JE^B44M)-@cSW6E^&2U0DcP;d?l1^GhF2wNfFeiok~#*oa?{= zC+H28&)$T^9XLYqG@kXZ7@nCvtZj!LBs5nIfYkur0@ov;51!FAiWs0$RD&9LM@y*- z2Aq3jp=JxgIVpnZRe)WGD|kk+F!T#tNbrv0;ZDndnFV=)kE@30VZb}76#Z0+Dq#Lx z;1WX@xV(mJ;~>d-Pa7!$9>$#abO@l}J{6K5C08LiA)kE(IPjig0h$T-%L1+=WC@o( zYPJl7FMvBf&b12a5C!>iuG9u#ffI0$dL%gn$;+VITcvmomzN~2{Kedl3*$21yK$8d z0M8Vpu>j75Ec2lh_G&f)Y=HBtG9WuxYiuCnT=OWxPR$+!=0#xkguEg86jZ|j`*!c^GyMP*7c2Z-3NJnr&2tkvJA)Mvz1Wd znfYuoJQqWuVCw)URjE z78nmeEeI-+3@o9VT?aP@k83YTPE#KYzEvsi1K=T<(Rnq1f*~i)LtaC1EAX{orMp1w z6x{6$jI#pVsHty0TL+f}s06sz1Q|vW+*Suc$iIi@ z3$zK5PjNnWKC7mPizERrK}n*(gyN4p)QF?;w z6tRvX4wA$!iYTOr8j`Sy1MveO1xaiN9q{MvNg|3S${#OE>s1i zPJ%)WMUqZh*S;%B%p-{qKnx^_<2dJQ;quVS=_m$P}CZ1%);~$TMF<;RlIsn?p!|gDjLY zaw@3@Gyw$-E(ga{&h;PngBDHd!R>lzQ;orTYKa|e4g!S&g#m>FMF2$tMFB+v#Q?a#!&`KZ`Py)~K;5w~|PHaK9zl|d-V)?R5*y7o$m z60}!Rv_UDIIx8U1bBb@EXMnG-PobGwX{zM}04LDb-`{JRU!g2VX{Ke)nC0bzx$><_ zb1m0v2JAt3PMR}$vaf$Yp=FlR1m`f-ciNPxfrS=38leG!v;2K=4wl;*q1t?Z_k#Ns zT5MJtYt^|THL%Px8(D$VX83vrOk3bvXucB_Q=4G}PPVC$$*JP9uUCp2%RZ&hC|haK zn1G5j6mF*1>_T=+;~ltKH{Nt(W7)XOP&KwIWeru+-c_e>Riy3h@vTXN6WW-Dv?2{p zHAd|W4C}yiM8g8@c~OKVyBhX)5g+YrQG_EK1bz$RqYWsEP_RjQe7wyB`E1qWqfH-* zXvZGXmPU^ zvU~LSXlcXokLmHzs)gfU)8nHB2}Lw#EA;rtp{59yeWAxkZZkz#vG4Wx$T{ZPKU}0M zKXQS&eAejkk)uly6WE=4d^EjLL}xZ%kB{DbQ-qQ&)Z?R<-xOiZmg@1*`)`V{VNdDt z(JOF@Xv?0{haMFa;|+s#JYY#@5s4+jMU?! z*W_G3#wm4pWRI|2+u3S`lEemzP8yN&L_ID#Z$!%1>ScmX6;Z@yfz?ZRFydVBurM^Y zdZjPG{Z31)-slT($J3@(HTnYF!?d|ot-b(vC2e8#USELwj5f3SpfA9kL(8q|^#!!EbOi|3NHlnI zbUDyHpa(z^@QO_D*We_`6X;J~gEVqC(UIJXR^6|G&+g^n7xD1V@$hf*@SpJTYkBw) z%-74Q;^AlT@VE2u3wZdac=%U&_z!vb)ja$t?XDDV{>ENe^;NF=tK9sray4J&-uo)I zR`4~;h!uW~oBCDm&aZNdzskMxRc@l_Yj@iwf_*%a+G_M!16dum*KK83OiXs!@{E2* z5SGgviK%Gk;-_hXYO^tm%u#xEi@@vi-kr5V=~}8qyZY-hhoki8@~~G@*T|X9yZPkP z#u&eUzRtfnpM1j;w~VOOKh5KlI|SV_TxnZ2l26`dTGu=IHd&c`@+fMAXH`$~8$S8f zfU~7lKmT=;Po8(F&D@*q-~02)%P(CyFfDp!C7*nlNqADqdpCPN`SwvS!hft={2QOV z%~;nPJ=VsI|6HE>!J#f}$oL8pS8CkAB-uw0!3TKKZUm$EI((dD@mwo;JL*kByt{X+HV% z{%;NsSbd#W-@_uVd8^gmhVbdn?$vIKd0)*SKDj}J$)!8pzv;#&pSZa7p|?i{^2&#e z_H-~4{gTe7UpO~4YhI*lS3da|&AA;3rT)$MjL(tL8G{tqu_K8WD8Z{v@> z7oFapXTYa#xLX$Xs@k$OpZr`|@+jvRR>CLWa5BeFVq4OVPaZSFFXP9nS-kUi-|NJd zE1R#T@#&8}|MUPmxG|PbZus>6Jzp}m3!mJ3_Po-Ho1J*)-<3(JUC+jKwB*wt@w>b4 z!sGHhKKaLMCR42HLSFL8yLU}h4LY@rcmBNCmg*MOr0fWvescPRXDfxN{rTkfnGc?3 zRAjH>lkW|@a!fdtisO^}diplMyO51+iHqtW4_ zZ@S3&F#x{VsK>t{ZFqrQqMecZ=Cq-$vZ3>e;Iei5RGi7!lyw!-?SrhMaM}kFanJvj2JXjotCDySd9_L7srT= z-%V=Op{emAj6mKfMx?IDeA8uXhanh&)*BcxZqIn}G@~KUF#@d!rEtEn@f+H=~{PRy;-3MYFW8s;`@Y0MV{^1VvInJg#qTEN0A6~kn@0Z8RvCYQBk`z5F^m? zA0ynm8Ppj2_t4!3Ef6uH&!jC~FO_{a8|Q(hK#VZ;3!*oi{bK?~phX-;gx|DPKX;k% z2qVxk10y{4Uy9E?9I+WAkfVeV5v_Y|@X-v*!U(jK#)zH2n|&C#ubm%8AZHjOK3dkv zC;fK$XN*9PV~ki+(cOK_n!hqI0&Tcp#616&7j`bc{vIRHk_IDoe&aF6V$n0*7(z}F zMl>nunBK8yQZ>#4P5T&;zh#cq_f@M;V+2~bVnn-z-m{IArZh`$3FAE)YhX-2c*Y zkx$(nj6e?ojOa5~7A4u;!UZGHG7}?ad$?a8@u6C0W5|)kh*5UiuNoCi)!90F6k|lL z$Bz6X9oG2cyP(Ykj4)sDO7=gB(FoKe;bFED4@+(H5jcGVri^dJwi<0Vw654)}>V^{9agyqW5?TaF zbwdg5J4uB&d$iRg)eQx-`z_V^Vrauas&gFB8c1r0^FqrisRXmoPJmSBQ=-jtj6u7_ zM_f|H1YHGm7!Ke(1&XyN=v1I>KzWYv77^$c&@-S9K(TG%OGBV{KB$U$$4k(lN$%VG9XU>@sIBoU}Ut4E4LtDLH+wp<^b9{fc#qx!%eS8DF z{TBz=dinc)0v$iuYeoP-AveD{Ge6IW%X9oJKTh7514R71X8L;0m=+MY*mhdLCz)~Z zw&Q07PWAQIX#{+#@_7Lk;~W;-`uWcF^#}NDFaN-4-dxQV7aBl=e)W|-L5fJiZDOnO zzkB)nIr#X(F(B_*KE94WPqcO5GO(RB*%nFX_{|CM^#PHi?JPgrN%L)ed?$NB<8iqY zgg}fMs*n(9+oO<%#wa97fwtKS3Gw7Pe%{(o^9*%mD{$9Haf{O?pce(UP(-PLEZPv?qL-)t6o2R8nx zW`Rzw{mo`k{cko4z2iFnOtUbVs5J|8X7g{gjWx{Mf3t1qo!I(k+J>3VHX4qn{;k%r zmU;JYwhp~xd;d)9FxOc}v!T+tsk<5JjHyelE z0p5S6amX5s~BX=wMXKBW3%>h_xY;Jo^!SKikjCS8cg8M7^@qSxm=HWcSJv%R<$Wo()5*ZrrF zO#;d%ES}~5L!ZuK^p=;dyWc8K(!V<5_%%1TBb$uIAc2CAKRvm8`jllYf-kJv^G6?i z=2DqIA}_%?y7ERrT-d`YVIlZG1__H(t4=zPOaIU@YKYy%6Mrs6SvBd{YQb|ut94^U zFU}17-rEUyb)Y|%Wfa( zy-<$N__r(Dpt;;UB{EbL5;wB=vTGI65aj%DWb~nk@h4d4ClMFktsjg8Hl5lQXa7+f zbyQ@NYf?VXw?7hy4<5a>rRC=8z^dqj-GluX;F>pUT2(Nitq1<($v8j$mpMfDA7ef|wQ4zm zhz>y-tpgtXk~{ZflXFuG#@{Y%BeX*TGx?xjof4Oy-6SJcz4iE$-iieF4tvK=+xgqj zg)K*FGKTdz-x~>J2FYpe9?ZlgCz=l3^UOnuJF2ayN2fzBR>LjxOtOvM{W5YQ(jX&h zQa=tq(;|3*VP&X8RHs5DUy%-nyZT1?s0MGoMo2Mgz^BrmDZQU4O`N{G+uQ`cR z1|k9Dypd=xeDckNTib2#E^4(J3#<*h22A!!&Jp~waPHNgLRY0AjSeNh->WXUV=gT_ zaV>Z6ls}&!fk?FWTTS`Cvxa~Dv8eA4!{#19f~HS%UVY=DNPjxB?ZZb?4;el}0>kMY zOb;zwF=SBCEQ1!iE&jwO$!+uge4Q3&>Tv7$3xnAv`HmW-Asy>na`DLG?GN_6DBWus zkc7XzYGpci|7^o1>sl5a3hZliKk*XMF#S{Yy7i0U3y)=9aF}%L?RWTV4ZGm^0hLdE zI(R<3G;vY47lV73J<@f1K`72s24`#CE@yrhST4s-YGjl+`pE)QmVG89J znPT}J=D7R?b6Wm^IVX=7T#}~?%H+ERH{_*)a``nuh5V)9kvvrRRGuh&Dc>x7BR?pt zm7f)UklzsoTRs(rS-urUS%!$>ESHLwTdo%+ST0p2StcmgS*}s0TP~+FEw|7+Ef3H| zmL>EV%ZqfGWjX!O@;O~=Sw}~*(M%GX$ZTRWnFH)D<|tdpXjlz%mA%1Ku$9aUww8I% zt`LMj{*lvx@@pc<+-nZLnlimJ(n_KOJ?1H;5vD@etVz=2X)Go&@%x`)n0d_c6W;B8ULzzWgcfsaLJ20jEhs5PEQBFaS9(&{SI}*y@D!t ze@IohZ=oK!Z>65PZ>L_m@1owg@1ttn_fsF-4^zP&g;bcwQ7X#gJQe40iCXS)g-Y8M)4jZv|}SEEveQKNSXQ%4sI_l&+GJUKd1R6cr}sAlwG`(78a=lYlIJrW+B^>@E?Kb#l&^Eim$uygT;pA4E(r|LW z&AD*$klnR#@`>H8a5BdJZaA4@{~(;qv9Am#a~+?DlN!fY;p9!nnsD-|Tp2-1tDF)e$k$FeF=Vw<@lx`wQ~65rol|`xS?83p zmi*|HmqrFDuWuliC_io@LzOAnWVkYa2N|inwTFyW2Ia#46eCg#NOD)fmp*@K0bU-U c#YAlZNmR3Go()R^?kt(Jub+?eWH=u7Kgv>UtpET3 literal 0 HcmV?d00001 diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27i4fig3-1sn51l0-91gh4v9b9ie5o2bnlwcrqp175/work-products.bin b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27i4fig3-1sn51l0-91gh4v9b9ie5o2bnlwcrqp175/work-products.bin new file mode 100644 index 0000000000000000000000000000000000000000..00978c1bb994f93f5367c043ae8c61937bb41824 GIT binary patch literal 50 zcmWFv_H<@okTuk^G}ALw&@eVkOHMRSOi5BOGB7gJH89gPGSg%zDlIP2P0dTuP0P$l F1pp&I4CVj; literal 0 HcmV?d00001 diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27i4fig3-1sn51l0.lock b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27i4fig3-1sn51l0.lock new file mode 100644 index 0000000..e69de29 diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27io9mtq-07w9ja3-a5ky9mmjfvg1lji5jjcrqco2u/dep-graph.bin b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27io9mtq-07w9ja3-a5ky9mmjfvg1lji5jjcrqco2u/dep-graph.bin new file mode 100644 index 0000000000000000000000000000000000000000..cfc43fb9d83920d3f2aa4b295d84557c6afdb8c3 GIT binary patch literal 258552 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�BLoAyLH-H~9Y3x=u9iH~t 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

A+qm~rz6kRQV)yy_SVtc8 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 literal 0 HcmV?d00001 diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27io9mtq-07w9ja3-a5ky9mmjfvg1lji5jjcrqco2u/query-cache.bin b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27io9mtq-07w9ja3-a5ky9mmjfvg1lji5jjcrqco2u/query-cache.bin new file mode 100644 index 0000000000000000000000000000000000000000..024f62bf2aeadf40cdad7a45bb9aa9bb9aa3c2eb GIT binary patch literal 27100 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 literal 0 HcmV?d00001 diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27io9mtq-07w9ja3-a5ky9mmjfvg1lji5jjcrqco2u/work-products.bin b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27io9mtq-07w9ja3-a5ky9mmjfvg1lji5jjcrqco2u/work-products.bin new file mode 100644 index 0000000000000000000000000000000000000000..00978c1bb994f93f5367c043ae8c61937bb41824 GIT binary patch literal 50 zcmWFv_H<@okTuk^G}ALw&@eVkOHMRSOi5BOGB7gJH89gPGSg%zDlIP2P0dTuP0P$l F1pp&I4CVj; literal 0 HcmV?d00001 diff --git a/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27io9mtq-07w9ja3.lock b/plugins/example-noisemap/target/wasm32-unknown-unknown/debug/incremental/terrafier_plugin_example_noisemap-09gi7tw9ywzfb/s-hk27io9mtq-07w9ja3.lock new file mode 100644 index 0000000..e69de29 diff --git a/scripts/example.rhai b/scripts/example.rhai new file mode 100644 index 0000000..542377c --- /dev/null +++ b/scripts/example.rhai @@ -0,0 +1,18 @@ +// Terrafier script example — creates a world with noise terrain +let world = new_world("scripted_world", 42); + +// Generate noise terrain +generate_heightmap_noise(world, 12345, 16.0, 6, "overworld"); + +// Apply some operations +apply_smooth(world, 2, 5.0, "overworld"); +apply_erode(world, 1, 4.0, "overworld"); + +// Generate layers (caves, rivers, biomes, etc.) +generate_layers(world, "overworld"); + +// Save the world +save_world(world, "scripted_world.tfw"); + +print(info(world)); +print("Done! World saved to scripted_world.tfw");