diff --git a/.cursor/rules/vars-usage.mdc b/.cursor/rules/vars-usage.mdc new file mode 100644 index 00000000..233e0aba --- /dev/null +++ b/.cursor/rules/vars-usage.mdc @@ -0,0 +1,18 @@ +--- +description: Restricts usage of the global Mineflayer `bot` variable to only src/ files; prohibits usage in renderer/. Specifies correct usage of player state and appViewer globals. +globs: src/**/*.ts,renderer/**/*.ts +alwaysApply: false +--- +Ask AI + +- The global variable `bot` refers to the Mineflayer bot instance. +- You may use `bot` directly in any file under the `src/` directory (e.g., `src/mineflayer/playerState.ts`). +- Do **not** use `bot` directly in any file under the `renderer/` directory or its subfolders (e.g., `renderer/viewer/three/worldrendererThree.ts`). +- In renderer code, all bot/player state and events must be accessed via explicit interfaces, state managers, or passed-in objects, never by referencing `bot` directly. +- In renderer code (such as in `WorldRendererThree`), use the `playerState` property (e.g., `worldRenderer.playerState.gameMode`) to access player state. The implementation for `playerState` lives in `src/mineflayer/playerState.ts`. +- In `src/` code, you may use the global variable `appViewer` from `src/appViewer.ts` directly. Do **not** import `appViewer` or use `window.appViewer`; use the global `appViewer` variable as-is. +- Some other global variables that can be used without window prefixes are listed in src/globals.d.ts + +Rationale: This ensures a clean separation between the Mineflayer logic (server-side/game logic) and the renderer (client-side/view logic), making the renderer portable and testable, and maintains proper usage of global state. + +For more general project contributing guides see CONTRIBUTING.md on like how to setup the project. Use pnpm tsc if needed to validate result with typechecking the whole project. diff --git a/.eslintrc.json b/.eslintrc.json index 8b2225b5..63f6749a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -23,6 +23,7 @@ // ], "@stylistic/arrow-spacing": "error", "@stylistic/block-spacing": "error", + "@typescript-eslint/no-this-alias": "off", "@stylistic/brace-style": [ "error", "1tbs", @@ -102,6 +103,7 @@ // "@stylistic/multiline-ternary": "error", // not needed // "@stylistic/newline-per-chained-call": "error", // not sure if needed "@stylistic/new-parens": "error", + "@typescript-eslint/class-literal-property-style": "off", "@stylistic/no-confusing-arrow": "error", "@stylistic/wrap-iife": "error", "@stylistic/space-before-blocks": "error", diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 00000000..e80b7100 --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,59 @@ +name: Benchmark +on: + issue_comment: + types: [created] + push: + branches: + - perf-test +jobs: + deploy: + runs-on: ubuntu-latest + if: >- + (github.event_name == 'push' && github.ref == 'refs/heads/perf-test') || + ( + github.event_name == 'issue_comment' && + github.event.issue.pull_request != '' && + (startsWith(github.event.comment.body, '/benchmark')) + ) + permissions: + pull-requests: write + steps: + - run: lscpu + + - name: Checkout + uses: actions/checkout@v2 + - name: Setup pnpm + uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: "pnpm" + - name: Move Cypress to dependencies + run: | + jq '.dependencies.cypress = .optionalDependencies.cypress | del(.optionalDependencies.cypress)' package.json > package.json.tmp + mv package.json.tmp package.json + - run: pnpm install --no-frozen-lockfile + + - run: pnpm build + - run: nohup pnpm prod-start & + + - run: pnpm test:benchmark + id: benchmark + continue-on-error: true + # read benchmark results from stdout + - run: | + if [ -f benchmark.txt ]; then + # Format the benchmark results for GitHub comment + BENCHMARK_RESULT=$(cat benchmark.txt | sed 's/^/- /') + echo "BENCHMARK_RESULT<> $GITHUB_ENV + echo "$BENCHMARK_RESULT" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + else + echo "BENCHMARK_RESULT=Benchmark failed to run or produce results" >> $GITHUB_ENV + fi + + - uses: mshick/add-pr-comment@v2 + with: + allow-repeats: true + message: | + Benchmark result: ${{ env.BENCHMARK_RESULT }} diff --git a/.github/workflows/build-single-file.yml b/.github/workflows/build-single-file.yml index 93b1b77f..5f9800db 100644 --- a/.github/workflows/build-single-file.yml +++ b/.github/workflows/build-single-file.yml @@ -23,6 +23,8 @@ jobs: - name: Build single-file version - minecraft.html run: pnpm build-single-file && mv dist/single/index.html minecraft.html + env: + LOCAL_CONFIG_FILE: config.mcraft-only.json - name: Upload artifact uses: actions/upload-artifact@v4 diff --git a/.github/workflows/build-zip.yml b/.github/workflows/build-zip.yml index cc472476..76ca65ca 100644 --- a/.github/workflows/build-zip.yml +++ b/.github/workflows/build-zip.yml @@ -23,6 +23,8 @@ jobs: - name: Build project run: pnpm build + env: + LOCAL_CONFIG_FILE: config.mcraft-only.json - name: Bundle server.js run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 92b7e7f3..8fc56ea9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,11 +20,56 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@v4 - run: pnpm install + - run: pnpm build-single-file + - name: Store minecraft.html size + run: | + SIZE_BYTES=$(du -s dist/single/minecraft.html 2>/dev/null | cut -f1) + echo "SIZE_BYTES=$SIZE_BYTES" >> $GITHUB_ENV - run: pnpm check-build + - name: Create zip package for size comparison + run: | + mkdir -p package + cp -r dist package/ + cd package + zip -r ../self-host.zip . - run: pnpm build-playground - - run: pnpm build-storybook + # - run: pnpm build-storybook - run: pnpm test-unit - run: pnpm lint + + - name: Parse Bundle Stats + run: | + GZIP_BYTES=$(du -s self-host.zip 2>/dev/null | cut -f1) + SIZE=$(echo "scale=2; $SIZE_BYTES/1024/1024" | bc) + GZIP_SIZE=$(echo "scale=2; $GZIP_BYTES/1024/1024" | bc) + echo "{\"total\": ${SIZE}, \"gzipped\": ${GZIP_SIZE}}" > /tmp/bundle-stats.json + + # - name: Compare Bundle Stats + # id: compare + # uses: actions/github-script@v6 + # env: + # GITHUB_TOKEN: ${{ secrets.GIST_TOKEN }} + # with: + # script: | + # const gistId = '${{ secrets.BUNDLE_STATS_GIST_ID }}'; + + # async function getGistContent() { + # const { data } = await github.rest.gists.get({ + # gist_id: gistId, + # headers: { + # authorization: `token ${process.env.GITHUB_TOKEN}` + # } + # }); + # return JSON.parse(data.files['bundle-stats.json'].content || '{}'); + # } + + # const content = await getGistContent(); + # const baseStats = content['${{ github.event.pull_request.base.ref }}']; + # const newStats = require('/tmp/bundle-stats.json'); + + # const comparison = `minecraft.html (normal build gzip)\n${baseStats.total}MB (${baseStats.gzipped}MB compressed) -> ${newStats.total}MB (${newStats.gzipped}MB compressed)`; + # core.setOutput('stats', comparison); + # - run: pnpm tsx scripts/buildNpmReact.ts - run: nohup pnpm prod-start & - run: nohup pnpm test-mc-server & @@ -40,6 +85,74 @@ jobs: # if: ${{ github.event.pull_request.base.ref == 'release' }} # env: # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # - name: Store Bundle Stats + # if: github.event.pull_request.base.ref == 'next' + # uses: actions/github-script@v6 + # env: + # GITHUB_TOKEN: ${{ secrets.GIST_TOKEN }} + # with: + # script: | + # const gistId = '${{ secrets.BUNDLE_STATS_GIST_ID }}'; + + # async function getGistContent() { + # const { data } = await github.rest.gists.get({ + # gist_id: gistId, + # headers: { + # authorization: `token ${process.env.GITHUB_TOKEN}` + # } + # }); + # return JSON.parse(data.files['bundle-stats.json'].content || '{}'); + # } + + # async function updateGistContent(content) { + # await github.rest.gists.update({ + # gist_id: gistId, + # headers: { + # authorization: `token ${process.env.GITHUB_TOKEN}` + # }, + # files: { + # 'bundle-stats.json': { + # content: JSON.stringify(content, null, 2) + # } + # } + # }); + # } + + # const stats = require('/tmp/bundle-stats.json'); + # const content = await getGistContent(); + # content['${{ github.event.pull_request.base.ref }}'] = stats; + # await updateGistContent(content); + + # - name: Update PR Description + # uses: actions/github-script@v6 + # with: + # script: | + # const { data: pr } = await github.rest.pulls.get({ + # owner: context.repo.owner, + # repo: context.repo.repo, + # pull_number: context.issue.number + # }); + + # let body = pr.body || ''; + # const statsMarker = '### Bundle Size'; + # const comparison = '${{ steps.compare.outputs.stats }}'; + + # if (body.includes(statsMarker)) { + # body = body.replace( + # new RegExp(`${statsMarker}[^\n]*\n[^\n]*`), + # `${statsMarker}\n${comparison}` + # ); + # } else { + # body += `\n\n${statsMarker}\n${comparison}`; + # } + + # await github.rest.pulls.update({ + # owner: context.repo.owner, + # repo: context.repo.repo, + # pull_number: context.issue.number, + # body + # }); # dedupe-check: # runs-on: ubuntu-latest # if: github.event.pull_request.head.ref == 'next' diff --git a/.github/workflows/next-deploy.yml b/.github/workflows/next-deploy.yml index 042302a4..75b39f6c 100644 --- a/.github/workflows/next-deploy.yml +++ b/.github/workflows/next-deploy.yml @@ -30,18 +30,18 @@ jobs: - name: Write Release Info run: | echo "{\"latestTag\": \"$(git rev-parse --short $GITHUB_SHA)\", \"isCommit\": true}" > assets/release.json + - name: Download Generated Sounds map + run: node scripts/downloadSoundsMap.mjs - name: Build Project Artifacts run: vercel build --token=${{ secrets.VERCEL_TOKEN }} env: CONFIG_JSON_SOURCE: BUNDLED - - run: pnpm build-storybook + LOCAL_CONFIG_FILE: config.mcraft-only.json - name: Copy playground files run: | mkdir -p .vercel/output/static/playground pnpm build-playground cp -r renderer/dist/* .vercel/output/static/playground/ - - name: Download Generated Sounds map - run: node scripts/downloadSoundsMap.mjs - name: Deploy Project Artifacts to Vercel uses: mathiasvr/command-output@v2.0.0 with: diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 6408c86a..89fd6698 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -1,4 +1,4 @@ -name: Vercel Deploy Preview +name: Vercel PR Deploy (Preview) env: VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} @@ -52,6 +52,19 @@ jobs: with: node-version: 22 cache: "pnpm" + - name: Update deployAlwaysUpdate packages + run: | + if [ -f package.json ]; then + PACKAGES=$(node -e "const pkg = require('./package.json'); if (pkg.deployAlwaysUpdate) console.log(pkg.deployAlwaysUpdate.join(' '))") + if [ ! -z "$PACKAGES" ]; then + echo "Updating packages: $PACKAGES" + pnpm up -L $PACKAGES + else + echo "No deployAlwaysUpdate packages found in package.json" + fi + else + echo "package.json not found" + fi - name: Install Global Dependencies run: pnpm add -g vercel - name: Pull Vercel Environment Information @@ -59,11 +72,13 @@ jobs: - name: Write Release Info run: | echo "{\"latestTag\": \"$(git rev-parse --short ${{ github.event.pull_request.head.sha }})\", \"isCommit\": true}" > assets/release.json + - name: Download Generated Sounds map + run: node scripts/downloadSoundsMap.mjs - name: Build Project Artifacts run: vercel build --token=${{ secrets.VERCEL_TOKEN }} env: CONFIG_JSON_SOURCE: BUNDLED - - run: pnpm build-storybook + LOCAL_CONFIG_FILE: config.mcraft-only.json - name: Copy playground files run: | mkdir -p .vercel/output/static/playground @@ -77,8 +92,6 @@ jobs: run: | mkdir -p .vercel/output/static/commit echo "" > .vercel/output/static/commit/index.html - - name: Download Generated Sounds map - run: node scripts/downloadSoundsMap.mjs - name: Deploy Project Artifacts to Vercel uses: mathiasvr/command-output@v2.0.0 with: diff --git a/.github/workflows/publish.yml b/.github/workflows/release.yml similarity index 66% rename from .github/workflows/publish.yml rename to .github/workflows/release.yml index 986bf6cc..3e8c4136 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/release.yml @@ -29,22 +29,18 @@ jobs: run: pnpx zardoy-release empty --skip-github --output-file assets/release.json env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Download Generated Sounds map + run: node scripts/downloadSoundsMap.mjs - run: vercel build --token=${{ secrets.VERCEL_TOKEN }} --prod env: CONFIG_JSON_SOURCE: BUNDLED - - run: pnpm build-storybook + LOCAL_CONFIG_FILE: config.mcraft-only.json - name: Copy playground files run: | mkdir -p .vercel/output/static/playground pnpm build-playground cp -r renderer/dist/* .vercel/output/static/playground/ - - name: Download Generated Sounds map - run: node scripts/downloadSoundsMap.mjs - - name: Deploy Project to Vercel - uses: mathiasvr/command-output@v2.0.0 - with: - run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} --prod - id: deploy + # publish to github - run: cp vercel.json .vercel/output/static/vercel.json - uses: peaceiris/actions-gh-pages@v3 @@ -53,6 +49,39 @@ jobs: publish_dir: .vercel/output/static force_orphan: true + # Create CNAME file for custom domain + - name: Create CNAME file + run: echo "github.mcraft.fun" > .vercel/output/static/CNAME + + - name: Deploy to mwc-mcraft-pages repository + uses: peaceiris/actions-gh-pages@v3 + with: + personal_token: ${{ secrets.MCW_MCRAFT_PAGE_DEPLOY_TOKEN }} + external_repository: ${{ github.repository_owner }}/mwc-mcraft-pages + publish_dir: .vercel/output/static + publish_branch: main + destination_dir: docs + force_orphan: true + + - name: Change index.html title + run: | + # change Minecraft Web Client to Minecraft Web Client — Free Online Browser Version + sed -i 's/Minecraft Web Client<\/title>/<title>Minecraft Web Client — Free Online Browser Version<\/title>/' .vercel/output/static/index.html + + - name: Deploy Project to Vercel + uses: mathiasvr/command-output@v2.0.0 + with: + run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} --prod + id: deploy + - name: Get releasing alias + run: node scripts/githubActions.mjs getReleasingAlias + id: alias + - name: Set deployment alias + run: | + for alias in $(echo ${{ steps.alias.outputs.alias }} | tr "," "\n"); do + vercel alias set ${{ steps.deploy.outputs.stdout }} $alias --token=${{ secrets.VERCEL_TOKEN }} --scope=zaro + done + - name: Build single-file version - minecraft.html run: pnpm build-single-file && mv dist/single/index.html minecraft.html - name: Build self-host version @@ -70,7 +99,7 @@ jobs: zip -r ../self-host.zip . - run: | - pnpx zardoy-release node --footer "This release URL: ${{ steps.deploy.outputs.stdout }}" + pnpx zardoy-release node --footer "This release URL: https://$(echo ${{ steps.alias.outputs.alias }} | cut -d',' -f1) (Vercel URL: ${{ steps.deploy.outputs.stdout }})" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # has possible output: tag diff --git a/.gitignore b/.gitignore index bd774315..33734572 100644 --- a/.gitignore +++ b/.gitignore @@ -19,5 +19,6 @@ generated storybook-static server-jar config.local.json +logs/ src/react/npmReactComponents.ts diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fb0ae55e..a5a3482d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,8 +9,10 @@ After forking the repository, run the following commands to get started: 4. Let us know if you are working on something and be sure to open a PR if you got any changes. Happy coding! *(1): If you are getting `Cannot find matching keyid` update corepack to the latest version with `npm i -g corepack`. + *(2): If still something doesn't work ensure you have the right nodejs version with `node -v` (tested on 22.x) -*(3): For GitHub codespaces (cloud ide): Run `pnpm i @rsbuild/core@1.2.4 @rsbuild/plugin-node-polyfill@1.3.0 @rsbuild/plugin-react@1.1.0 @rsbuild/plugin-typed-css-modules@1.0.2` command to avoid crashes because of limited ram + +<!-- *(3): For GitHub codespaces (cloud ide): Run `pnpm i @rsbuild/core@1.2.4 @rsbuild/plugin-node-polyfill@1.3.0 @rsbuild/plugin-react@1.1.0 @rsbuild/plugin-typed-css-modules@1.0.2` command to avoid crashes because of limited ram --> ## Project Structure @@ -175,8 +177,13 @@ New React components, improve UI (including mobile support). ## Updating Dependencies -1. Ensure mineflayer fork is up to date with the latest version of mineflayer original repo +1. Use `pnpm update-git-deps` to check and update git dependencies (like mineflayer fork, prismarine packages etc). The script will: + - Show which git dependencies have updates available + - Ask if you want to update them + - Skip dependencies listed in `pnpm.updateConfig.ignoreDependencies` + 2. Update PrismarineJS dependencies to the latest version: `minecraft-data` (be sure to replace the version twice in the package.json), `mineflayer`, `minecraft-protocol`, `prismarine-block`, `prismarine-chunk`, `prismarine-item`, ... + 3. If `minecraft-protocol` patch fails, do this: 1. Remove the patch from `patchedDependencies` in `package.json` 2. Run `pnpm patch minecraft-protocol`, open patch directory diff --git a/Dockerfile b/Dockerfile index 34641353..22bcfac6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,8 @@ FROM node:18-alpine AS build RUN apk add git WORKDIR /app COPY . /app -# install pnpm -RUN npm i -g pnpm@9.0.4 +# install pnpm with corepack +RUN corepack enable # Build arguments ARG DOWNLOAD_SOUNDS=false ARG DISABLE_SERVICE_WORKER=false @@ -35,7 +35,7 @@ WORKDIR /app COPY --from=build /app/dist /app/dist COPY server.js /app/server.js # Install express -RUN npm i -g pnpm@9.0.4 +RUN npm i -g pnpm@10.8.0 RUN npm init -yp RUN pnpm i express github:zardoy/prismarinejs-net-browserify compression cors EXPOSE 8080 diff --git a/README.MD b/README.MD index 67e46333..018784e3 100644 --- a/README.MD +++ b/README.MD @@ -6,12 +6,17 @@ Minecraft **clone** rewritten in TypeScript using the best modern web technologi You can try this out at [mcraft.fun](https://mcraft.fun/), [pcm.gg](https://pcm.gg) (short link), [mcon.vercel.app](https://mcon.vercel.app/) or the GitHub pages deploy. Every commit from the default (`develop`) branch is deployed to [s.mcraft.fun](https://s.mcraft.fun/) and [s.pcm.gg](https://s.pcm.gg/) - so it's usually newer, but might be less stable. -Don't confuse with [Eaglercraft](https://git.eaglercraft.rip/eaglercraft/eaglercraft-1.8) which is a REAL vanilla Minecraft Java edition port to the web (but with its own limitations). Eaglercraft is a fully playable solution, but this project is more in position of a "technical demo" to show how it's possible to build games for web at scale entirely with the JS ecosystem. Have fun! +> For Turkey/Russia use [ru.mcraft.fun](https://ru.mcraft.fun/) (since Cloudflare is blocked) -For building the project yourself / contributing, see [Development, Debugging & Contributing](#development-debugging--contributing). For reference at what and how web technologies / frameworks are used, see [TECH.md](./TECH.md). +Don't confuse with [Eaglercraft](https://git.eaglercraft.rip/eaglercraft/eaglercraft-1.8) which is a REAL vanilla Minecraft Java edition port to the web (but with its own limitations). Eaglercraft is a fully playable solution, meanwhile this project is aimed for *device-compatiiblity* and better performance so it feels portable, flexible and lightweight. It's also a very strong example on how to build true HTML games for the web at scale entirely with the JS ecosystem. Have fun! + +For building the project yourself / contributing, see [Development, Debugging & Contributing](#development-debugging--contributing). For reference at what and how web technologies / frameworks are used, see [TECH.md](./TECH.md) (also for comparison with Eaglercraft). + +> **Note**: You can deploy it on your own server in less than a minute using a one-liner script from [Minecraft Everywhere repo](https://github.com/zardoy/minecraft-everywhere) ### Big Features +- Official Mineflayer [plugin integration](https://github.com/zardoy/mcraft-fun-mineflayer-plugin)! View / Control your bot remotely. - Open any zip world file or even folder in read-write mode! - Connect to Java servers running in both offline (cracked) and online mode* (it's possible because of proxy servers, see below) - Integrated JS server clone capable of opening Java world saves in any way (folders, zip, web chunks streaming, etc) @@ -27,22 +32,36 @@ For building the project yourself / contributing, see [Development, Debugging & - Support for custom rendering 3D engines. Modular architecture. - even even more! -All components that are in [Storybook](https://mcraft.fun/storybook) are published as npm module and can be used in other projects: [`minecraft-react`](https://npmjs.com/minecraft-react) +All components that are in [Storybook](https://minimap.mcraft.fun/storybook/) are published as npm module and can be used in other projects: [`minecraft-react`](https://npmjs.com/minecraft-react) ### Recommended Settings - Controls -> **Touch Controls Type** -> **Joystick** - Controls -> **Auto Full Screen** -> **On** - To avoid ctrl+w issue +- Interface -> **Enable Minimap** -> **Always** - To enable useful minimap (why not?) - Controls -> **Raw Input** -> **On** - This will make the controls more precise (UPD: already enabled by default) - Interface -> **Chat Select** -> **On** - To select chat messages (UPD: already enabled by default) ### Browser Notes -These browsers have issues with capturing pointer: +This project is tested with BrowserStack. Special thanks to [BrowserStack](https://www.browserstack.com/) for providing testing infrastructure! + +Howerver, it's known that these browsers have issues: **Opera Mini**: Disable *mouse gestures* in browsre settings to avoid opening new tab on right click hold + **Vivaldi**: Disable Controls -> *Raw Input* in game settings if experiencing issues +### Versions Support + +Server versions 1.8 - 1.21.5 are supported. +First class versions (most of the features are tested on these versions): + +- 1.19.4 +- 1.21.4 + +Versions below 1.13 are not tested currently and may not work correctly. + ### World Loading Zip files and folders are supported. Just drag and drop them into the browser window. You can open folders in readonly and read-write mode. New chunks may be generated incorrectly for now. @@ -59,6 +78,8 @@ There is a builtin proxy, but you can also host your one! Just clone the repo, r [![Deploy to Koyeb](https://www.koyeb.com/static/images/deploy/button.svg)](https://app.koyeb.com/deploy?name=minecraft-web-client&type=git&repository=zardoy%2Fminecraft-web-client&branch=next&builder=dockerfile&env%5B%5D=&ports=8080%3Bhttp%3B%2F) +> **Note**: If you want to make **your own** Minecraft server accessible to web clients (without our proxies), you can use [mwc-proxy](https://github.com/zardoy/mwc-proxy) - a lightweight JS WebSocket proxy that runs on the same server as your Minecraft server, allowing players to connect directly via `wss://play.example.com`. `?client_mcraft` is added to the URL, so the proxy will know that it's this client. + Proxy servers are used to connect to Minecraft servers which use TCP protocol. When you connect connect to a server with a proxy, websocket connection is created between you (browser client) and the proxy server located in Europe, then the proxy connects to the Minecraft server and sends the data to the client (you) without any packet deserialization to avoid any additional delays. That said all the Minecraft protocol packets are processed by the client, right in your browser. ```mermaid @@ -106,12 +127,12 @@ There is world renderer playground ([link](https://mcon.vercel.app/playground/)) However, there are many things that can be done in online production version (like debugging actual source code). Also you can access some global variables in the console and there are a few useful examples: -- `localStorage.debug = '*'` - Enables all debug messages! Warning: this will start all packets spam. +- If you type `debugToggle`, press enter in console - It will enables all debug messages! Warning: this will start all packets spam. Instead I recommend setting `options.debugLogNotFrequentPackets`. Also you can use `debugTopPackets` (with JSON.stringify) to see what packets were received/sent by name - `bot` - Mineflayer bot instance. See Mineflayer documentation for more. -- `viewer` - Three.js viewer instance, basically does all the rendering. -- `viewer.world.sectionObjects` - Object with all active chunk sections (geometries) in the world. Each chunk section is a Three.js mesh or group. +- `world` - Three.js world instance, basically does all the rendering (part of renderer backend). +- `world.sectionObjects` - Object with all active chunk sections (geometries) in the world. Each chunk section is a Three.js mesh or group. - `debugSceneChunks` - The same as above, but relative to current bot position (e.g. 0,0 is the current chunk). - `debugChangedOptions` - See what options are changed. Don't change options here. - `localServer`/`server` - Only for singleplayer mode/host. Flying Squid server instance, see it's documentation for more. @@ -120,7 +141,7 @@ Instead I recommend setting `options.debugLogNotFrequentPackets`. Also you can u - `nbt.simplify(someNbt)` - Simplifies nbt data, so it's easier to read. -The most useful thing in devtools is the watch expression. You can add any expression there and it will be re-evaluated in real time. For example, you can add `viewer.camera.position` to see the camera position and so on. +The most useful thing in devtools is the watch expression. You can add any expression there and it will be re-evaluated in real time. For example, you can add `world.getCameraPosition()` to see the camera position and so on. <img src="./docs-assets/watch-expr.png" alt="Watch expression" width="480"/> @@ -157,6 +178,7 @@ Server specific: - `?lockConnect=true` - Only works then `ip` parameter is set. Disables cancel/save buttons and all inputs in the connect screen already set as parameters. Useful for integrates iframes. - `?autoConnect=true` - Only works then `ip` and `version` parameters are set and `allowAutoConnect` is `true` in config.json! Directly connects to the specified server. Useful for integrates iframes. - `?serversList=<list_or_url>` - `<list_or_url>` can be a list of servers in the format `ip:version,ip` or a url to a json file with the same format (array) or a txt file with line-delimited list of server IPs. +- `?addPing=<ping>` - Add a latency to both sides of the connection. Useful for testing ping issues. For example `?addPing=100` will add 200ms to your ping. Single player specific: @@ -213,3 +235,4 @@ Only during development: - [https://github.com/ClassiCube/ClassiCube](ClassiCube - Better C# Rewrite) [DEMO](https://www.classicube.net/server/play/?warned=true) - [https://m.eaglercraft.com/](EaglerCraft) - Eaglercraft runnable on mobile (real Minecraft in the browser) +- [js-minecraft](https://github.com/LabyStudio/js-minecraft) - An insanely well done clone from the graphical side that inspired many features here diff --git a/TECH.md b/TECH.md index c7f4ef4e..2d15993a 100644 --- a/TECH.md +++ b/TECH.md @@ -10,26 +10,27 @@ This client generally has better performance but some features reproduction migh | Gamepad Support | ✅ | ❌ | | | A11Y | ✅ | ❌ | We have DOM for almost all UI so your extensions and other browser features will work natively like on any other web page (but maybe it's not needed) | | Game Features | | | | -| Servers Support (quality) | ❌ | ✅ | Eaglercraft is vanilla Minecraft, while this project tries to emulate original game behavior at protocol level (Mineflayer is used) | +| Servers Support (quality) | ❌(+) | ✅ | Eaglercraft is vanilla Minecraft, while this project tries to emulate original game behavior at protocol level (Mineflayer is used) | | Servers Support (any version, ip) | ✅ | ❌ | We support almost all Minecraft versions, only important if you connect to a server where you need new content like blocks or if you play with friends. And you can connect to almost any server using proxy servers! | +| Servers Support (online mode) | ✅ | ❌ | Join to online servers like Hypixel using your Microsoft account without additional proxies | | Singleplayer Survival Features | ❌ | ✅ | Just like Eaglercraft this project can generate and save worlds, but generator is simple and only a few survival features are supported (look here for [supported features list](https://github.com/zardoy/space-squid)) | | Singleplayer Maps | ✅ | ✅ | We support any version, but adventure maps won't work, but simple parkour and build maps might be interesting to explore... | | Singleplayer Maps World Streaming | ✅ | ❌ | Thanks to Browserfs, saves can be loaded to local singleplayer server using multiple ways: from local folder, server directory (not zip), dropbox or other cloud *backend* etc... | | P2P Multiplayer | ✅ | ✅ | A way to connect to other browser running the project. But it's almost useless here since many survival features are not implemented. Maybe only to build / explore maps together... | -| Voice Chat | ❌ | ✅ | Eaglercraft has custom WebRTC voice chat implementation, though it could also be easily implemented there | +| Voice Chat | ❌(+) | ✅ | Eaglercraft has custom WebRTC voice chat implementation, though it could also be easily implemented there | | Online Servers | ✅ | ❌ | We have custom implementation (including integration on proxy side) for joining to servers | | Plugin Features | ✅ | ❌ | We have Mineflayer plugins support, like Auto Jump & Auto Parkour was added here that way | | Direct Connection | ✅ | ✅ | We have DOM for almost all UI so your extensions and other browser features will work natively like on any other web page | -| Moding | ❌(roadmap, client-side) | ❌ | This project will support mods for singleplayer. In theory its possible to implement support for modded servers on protocol level (including all needed mods) | -| Video Recording | ❌ | ✅ | Don't feel needed | -| Metaverse Features | ❌(roadmap) | ❌ | Iframes, video streams inside of game world (custom protocol channel) | +| Moding | ✅(own js mods) | ❌ | This project will support mods for singleplayer. In theory its possible to implement support for modded servers on protocol level (including all needed mods) | +| Video Recording | ❌ | ✅ | Doesn't feel needed | +| Metaverse Features | ✅(50%) | ❌ | We have videos / images support inside world, but not iframes (custom protocol channel) | | Sounds | ✅ | ✅ | | | Resource Packs | ✅(+extras) | ✅ | This project has very limited support for them (only textures images are loadable for now) | | Assets Compressing & Splitting | ✅ | ❌ | We have advanced Minecraft data processing and good code chunk splitting so the web app will open much faster and use less memory | | Graphics | | | | | Fancy Graphics | ❌ | ✅ | While Eaglercraft has top-level shaders we don't even support lighting | | Fast & Efficient Graphics | ❌(+) | ❌ | Feels like no one needs to have 64 rendering distance work smoothly | -| VR | ✅ | ❌ | Feels like not needed feature. UI is missing in this project since DOM can't be rendered in VR so Eaglercraft could be better in that aspect | +| VR | ✅(-) | ❌ | Feels like not needed feature. UI is missing in this project since DOM can't be rendered in VR so Eaglercraft could be better in that aspect | | AR | ❌ | ❌ | Would be the most useless feature | | Minimap & Waypoints | ✅(-) | ❌ | We have buggy minimap, which can be enabled in settings and full map is opened by pressing `M` key | diff --git a/assets/config.html b/assets/config.html new file mode 100644 index 00000000..9bd2dd8e --- /dev/null +++ b/assets/config.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Configure client + + + +
+ + + + + +
+ + + diff --git a/assets/customTextures/readme.md b/assets/customTextures/readme.md new file mode 100644 index 00000000..e2a78c20 --- /dev/null +++ b/assets/customTextures/readme.md @@ -0,0 +1,2 @@ +here you can place custom textures for bundled files (blocks/items) e.g. blocks/stone.png +get file names from here (blocks/items) https://zardoy.github.io/mc-assets/ diff --git a/assets/debug-inputs.html b/assets/debug-inputs.html new file mode 100644 index 00000000..584fe4d7 --- /dev/null +++ b/assets/debug-inputs.html @@ -0,0 +1,237 @@ + + + + + + Web Input Debugger + + + +
+ +
+ +
+
W
+
A
+
S
+
D
+
+ +
+
Ctrl
+
+ +
+
Space
+
+ + + + diff --git a/config.json b/config.json index 532ed9c7..2bfa9cfe 100644 --- a/config.json +++ b/config.json @@ -3,25 +3,36 @@ "defaultHost": "", "defaultProxy": "https://proxy.mcraft.fun", "mapsProvider": "https://maps.mcraft.fun/", + "skinTexturesProxy": "", "peerJsServer": "", "peerJsServerFallback": "https://p2p.mcraft.fun", "promoteServers": [ - { - "ip": "wss://mcraft.ryzyn.xyz", - "version": "1.19.4" - }, { "ip": "wss://play.mcraft.fun" }, + { + "ip": "wss://play.webmc.fun", + "name": "WebMC" + }, + { + "ip": "wss://ws.fuchsmc.net" + }, { "ip": "wss://play2.mcraft.fun" }, + { + "ip": "wss://play-creative.mcraft.fun", + "description": "Might be available soon, stay tuned!" + }, { "ip": "kaboom.pw", "version": "1.20.3", "description": "Very nice a polite server. Must try for everyone!" } ], + "rightSideText": "A Minecraft client clone in the browser!", + "splashText": "The sunset is coming!", + "splashTextFallback": "Welcome!", "pauseLinks": [ [ { @@ -31,5 +42,39 @@ "type": "discord" } ] + ], + "defaultUsername": "mcrafter{0-9999}", + "mobileButtons": [ + { + "action": "general.drop", + "actionHold": "general.dropStack", + "label": "Q" + }, + { + "action": "general.selectItem", + "actionHold": "", + "label": "S" + }, + { + "action": "general.debugOverlay", + "actionHold": "general.debugOverlayHelpMenu", + "label": "F3" + }, + { + "action": "general.playersList", + "actionHold": "", + "icon": "pixelarticons:users", + "label": "TAB" + }, + { + "action": "general.chat", + "actionHold": "", + "label": "" + }, + { + "action": "ui.pauseMenu", + "actionHold": "", + "label": "" + } ] } diff --git a/config.mcraft-only.json b/config.mcraft-only.json new file mode 100644 index 00000000..52a3aa2c --- /dev/null +++ b/config.mcraft-only.json @@ -0,0 +1,5 @@ +{ + "alwaysReconnectButton": true, + "reportBugButtonWithReconnect": true, + "allowAutoConnect": true +} diff --git a/cypress.config.ts b/cypress.config.ts index 861931e3..3bf2c720 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -1,5 +1,7 @@ import { defineConfig } from 'cypress' +const isPerformanceTest = process.env.PERFORMANCE_TEST === 'true' + export default defineConfig({ video: false, chromeWebSecurity: false, @@ -32,7 +34,7 @@ export default defineConfig({ return require('./cypress/plugins/index.js')(on, config) }, baseUrl: 'http://localhost:8080', - specPattern: 'cypress/e2e/**/*.spec.ts', + specPattern: !isPerformanceTest ? 'cypress/e2e/smoke.spec.ts' : 'cypress/e2e/rendering_performance.spec.ts', excludeSpecPattern: ['**/__snapshots__/*', '**/__image_snapshots__/*'], }, }) diff --git a/cypress/e2e/rendering_performance.spec.ts b/cypress/e2e/rendering_performance.spec.ts new file mode 100644 index 00000000..2ca85329 --- /dev/null +++ b/cypress/e2e/rendering_performance.spec.ts @@ -0,0 +1,32 @@ +/// +import { BenchmarkAdapterInfo, getAllInfoLines } from '../../src/benchmarkAdapter' +import { cleanVisit } from './shared' + +it('Benchmark rendering performance', () => { + cleanVisit('/?openBenchmark=true&renderDistance=5') + // wait for render end event + return cy.document().then({ timeout: 180_000 }, doc => { + return new Cypress.Promise(resolve => { + cy.log('Waiting for world to load') + doc.addEventListener('cypress-world-ready', resolve) + }).then(() => { + cy.log('World loaded') + }) + }).then(() => { + cy.window().then(win => { + const adapter = win.benchmarkAdapter as BenchmarkAdapterInfo + + const messages = getAllInfoLines(adapter) + // wait for 10 seconds + cy.wait(10_000) + const messages2 = getAllInfoLines(adapter, true) + for (const message of messages) { + cy.log(message) + } + for (const message of messages2) { + cy.log(message) + } + cy.writeFile('benchmark.txt', [...messages, ...messages2].join('\n')) + }) + }) +}) diff --git a/experiments/three-item.html b/experiments/three-item.html new file mode 100644 index 00000000..70155c50 --- /dev/null +++ b/experiments/three-item.html @@ -0,0 +1,13 @@ + + + + Minecraft Item Viewer + + + + + + diff --git a/experiments/three-item.ts b/experiments/three-item.ts new file mode 100644 index 00000000..b9d492fe --- /dev/null +++ b/experiments/three-item.ts @@ -0,0 +1,108 @@ +import * as THREE from 'three' +import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' +import itemsAtlas from 'mc-assets/dist/itemsAtlasLegacy.png' +import { createItemMeshFromCanvas, createItemMesh } from '../renderer/viewer/three/itemMesh' + +// Create scene, camera and renderer +const scene = new THREE.Scene() +const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000) +const renderer = new THREE.WebGLRenderer({ antialias: true }) +renderer.setSize(window.innerWidth, window.innerHeight) +document.body.appendChild(renderer.domElement) + +// Setup camera and controls +camera.position.set(0, 0, 3) +const controls = new OrbitControls(camera, renderer.domElement) +controls.enableDamping = true + +// Background and lights +scene.background = new THREE.Color(0x333333) +const ambientLight = new THREE.AmbientLight(0xffffff, 0.7) +scene.add(ambientLight) + +// Animation loop +function animate () { + requestAnimationFrame(animate) + controls.update() + renderer.render(scene, camera) +} + +async function setupItemMesh () { + try { + const loader = new THREE.TextureLoader() + const atlasTexture = await loader.loadAsync(itemsAtlas) + + // Pixel-art configuration + atlasTexture.magFilter = THREE.NearestFilter + atlasTexture.minFilter = THREE.NearestFilter + atlasTexture.generateMipmaps = false + atlasTexture.wrapS = atlasTexture.wrapT = THREE.ClampToEdgeWrapping + + // Extract the tile at x=2, y=0 (16x16) + const tileSize = 16 + const tileX = 2 + const tileY = 0 + + const canvas = document.createElement('canvas') + canvas.width = tileSize + canvas.height = tileSize + const ctx = canvas.getContext('2d')! + + ctx.imageSmoothingEnabled = false + ctx.drawImage( + atlasTexture.image, + tileX * tileSize, + tileY * tileSize, + tileSize, + tileSize, + 0, + 0, + tileSize, + tileSize + ) + + // Test both approaches - working manual extraction: + const meshOld = createItemMeshFromCanvas(canvas, { depth: 0.1 }) + meshOld.position.x = -1 + meshOld.rotation.x = -Math.PI / 12 + meshOld.rotation.y = Math.PI / 12 + scene.add(meshOld) + + // And new unified function: + const atlasWidth = atlasTexture.image.width + const atlasHeight = atlasTexture.image.height + const u = (tileX * tileSize) / atlasWidth + const v = (tileY * tileSize) / atlasHeight + const sizeX = tileSize / atlasWidth + const sizeY = tileSize / atlasHeight + + console.log('Debug texture coords:', {u, v, sizeX, sizeY, atlasWidth, atlasHeight}) + + const resultNew = createItemMesh(atlasTexture, { + u, v, sizeX, sizeY + }, { + faceCamera: false, + use3D: true, + depth: 0.1 + }) + + resultNew.mesh.position.x = 1 + resultNew.mesh.rotation.x = -Math.PI / 12 + resultNew.mesh.rotation.y = Math.PI / 12 + scene.add(resultNew.mesh) + + animate() + } catch (err) { + console.error('Failed to create item mesh:', err) + } +} + +// Handle window resize +window.addEventListener('resize', () => { + camera.aspect = window.innerWidth / window.innerHeight + camera.updateProjectionMatrix() + renderer.setSize(window.innerWidth, window.innerHeight) +}) + +// Start +setupItemMesh() diff --git a/experiments/three-labels.html b/experiments/three-labels.html new file mode 100644 index 00000000..2b25bc23 --- /dev/null +++ b/experiments/three-labels.html @@ -0,0 +1,5 @@ + + diff --git a/experiments/three-labels.ts b/experiments/three-labels.ts new file mode 100644 index 00000000..b69dc95b --- /dev/null +++ b/experiments/three-labels.ts @@ -0,0 +1,67 @@ +import * as THREE from 'three' +import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js' +import { createWaypointSprite, WAYPOINT_CONFIG } from '../renderer/viewer/three/waypointSprite' + +// Create scene, camera and renderer +const scene = new THREE.Scene() +const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000) +const renderer = new THREE.WebGLRenderer({ antialias: true }) +renderer.setSize(window.innerWidth, window.innerHeight) +document.body.appendChild(renderer.domElement) + +// Add FirstPersonControls +const controls = new FirstPersonControls(camera, renderer.domElement) +controls.lookSpeed = 0.1 +controls.movementSpeed = 10 +controls.lookVertical = true +controls.constrainVertical = true +controls.verticalMin = 0.1 +controls.verticalMax = Math.PI - 0.1 + +// Position camera +camera.position.y = 1.6 // Typical eye height +camera.lookAt(0, 1.6, -1) + +// Create a helper grid and axes +const grid = new THREE.GridHelper(20, 20) +scene.add(grid) +const axes = new THREE.AxesHelper(5) +scene.add(axes) + +// Create waypoint sprite via utility +const waypoint = createWaypointSprite({ + position: new THREE.Vector3(0, 0, -5), + color: 0xff0000, + label: 'Target', +}) +scene.add(waypoint.group) + +// Use built-in offscreen arrow from utils +waypoint.enableOffscreenArrow(true) +waypoint.setArrowParent(scene) + +// Animation loop +function animate() { + requestAnimationFrame(animate) + + const delta = Math.min(clock.getDelta(), 0.1) + controls.update(delta) + + // Unified camera update (size, distance text, arrow, visibility) + const sizeVec = renderer.getSize(new THREE.Vector2()) + waypoint.updateForCamera(camera.position, camera, sizeVec.width, sizeVec.height) + + renderer.render(scene, camera) +} + +// Handle window resize +window.addEventListener('resize', () => { + camera.aspect = window.innerWidth / window.innerHeight + camera.updateProjectionMatrix() + renderer.setSize(window.innerWidth, window.innerHeight) +}) + +// Add clock for controls +const clock = new THREE.Clock() + +animate() diff --git a/experiments/three.ts b/experiments/three.ts index 7a629a13..21142b5f 100644 --- a/experiments/three.ts +++ b/experiments/three.ts @@ -1,101 +1,60 @@ import * as THREE from 'three' -import * as tweenJs from '@tweenjs/tween.js' -import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' -import * as THREE from 'three'; -import Jimp from 'jimp'; +// Create scene, camera and renderer const scene = new THREE.Scene() const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000) -camera.position.set(0, 0, 5) const renderer = new THREE.WebGLRenderer() renderer.setSize(window.innerWidth, window.innerHeight) document.body.appendChild(renderer.domElement) -const controls = new OrbitControls(camera, renderer.domElement) +// Position camera +camera.position.z = 5 -const geometry = new THREE.BoxGeometry(1, 1, 1) -const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }) -const cube = new THREE.Mesh(geometry, material) -cube.position.set(0.5, 0.5, 0.5); -const group = new THREE.Group() -group.add(cube) -group.position.set(-0.5, -0.5, -0.5); -const outerGroup = new THREE.Group() -outerGroup.add(group) -outerGroup.scale.set(0.2, 0.2, 0.2) -outerGroup.position.set(1, 1, 0) -scene.add(outerGroup) +// Create a canvas with some content +const canvas = document.createElement('canvas') +canvas.width = 256 +canvas.height = 256 +const ctx = canvas.getContext('2d') -// const mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({ color: 0x00_00_ff, transparent: true, opacity: 0.5 })) -// mesh.position.set(0.5, 1, 0.5) -// const group = new THREE.Group() -// group.add(mesh) -// group.position.set(-0.5, -1, -0.5) -// const outerGroup = new THREE.Group() -// outerGroup.add(group) -// // outerGroup.position.set(this.camera.position.x, this.camera.position.y, this.camera.position.z) -// scene.add(outerGroup) +scene.background = new THREE.Color(0x444444) - new tweenJs.Tween(group.rotation).to({ z: THREE.MathUtils.degToRad(90) }, 1000).yoyo(true).repeat(Infinity).start() +// Draw something on the canvas +ctx.fillStyle = '#444444' +// ctx.fillRect(0, 0, 256, 256) +ctx.fillStyle = 'red' +ctx.font = '48px Arial' +ctx.textAlign = 'center' +ctx.textBaseline = 'middle' +ctx.fillText('Hello!', 128, 128) -const tweenGroup = new tweenJs.Group() -function animate () { - tweenGroup.update() - requestAnimationFrame(animate) -// cube.rotation.x += 0.01 -// cube.rotation.y += 0.01 - renderer.render(scene, camera) +// Create bitmap and texture +async function createTexturedBox() { + const canvas2 = new OffscreenCanvas(256, 256) + const ctx2 = canvas2.getContext('2d')! + ctx2.drawImage(canvas, 0, 0) + const texture = new THREE.Texture(canvas2) + texture.magFilter = THREE.NearestFilter + texture.minFilter = THREE.NearestFilter + texture.needsUpdate = true + texture.flipY = false + + // Create box with texture + const geometry = new THREE.BoxGeometry(2, 2, 2) + const material = new THREE.MeshBasicMaterial({ + map: texture, + side: THREE.DoubleSide, + premultipliedAlpha: false, + }) + const cube = new THREE.Mesh(geometry, material) + scene.add(cube) +} + +// Create the textured box +createTexturedBox() + +// Animation loop +function animate() { + requestAnimationFrame(animate) + renderer.render(scene, camera) } animate() - -// let animation - -window.animate = () => { - // new Tween.Tween(group.position).to({ y: group.position.y - 1}, 1000 * 0.35/2).yoyo(true).repeat(1).start() - new tweenJs.Tween(group.rotation, tweenGroup).to({ z: THREE.MathUtils.degToRad(90) }, 1000 * 0.35 / 2).yoyo(true).repeat(Infinity).start().onRepeat(() => { - console.log('done') - }) -} - -window.stop = () => { - tweenGroup.removeAll() -} - - -function createGeometryFromImage() { - return new Promise((resolve, reject) => { - const img = new Image(); - img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAABEElEQVQ4jWNkIAPw2Zv9J0cfXPOSvx/+L/n74T+HqsJ/JlI1T9u3i6H91B7ybdY+vgZuO1majV+fppFmPnuz/+ihy2dv9t/49Wm8mlECkV1FHh5FfPZm/1XXTGX4cechA4eKPMNVq1CGH7cfMBJ0rlxX+X8OVYX/xq9P/5frKifoZ0Z0AwS8HRkYGBgYvt+8xyDXUUbQZgwJPnuz/+wq8gw/7zxk+PXsFUFno0h6mon+l5fgZFhwnYmBTUqMgYGBgaAhLMiaHQyFGOZvf8Lw49FXRgYGhv8MDAwwg/7jMoQFFury/C8Y5m9/wnADohnZVryJhoWBARJ9Cw69gtmMAgiFAcuvZ68Yfj17hU8NXgAATdKfkzbQhBEAAAAASUVORK5CYII=' - console.log('img.complete', img.complete) - img.onload = () => { - const canvas = document.createElement('canvas'); - canvas.width = img.width; - canvas.height = img.height; - const context = canvas.getContext('2d'); - context.drawImage(img, 0, 0, img.width, img.height); - const imgData = context.getImageData(0, 0, img.width, img.height); - - const shape = new THREE.Shape(); - for (let y = 0; y < img.height; y++) { - for (let x = 0; x < img.width; x++) { - const index = (y * img.width + x) * 4; - const alpha = imgData.data[index + 3]; - if (alpha !== 0) { - shape.lineTo(x, y); - } - } - } - - const geometry = new THREE.ShapeGeometry(shape); - resolve(geometry); - }; - img.onerror = reject; - }); -} - -// Usage: -const shapeGeomtry = createGeometryFromImage().then(geometry => { - const material = new THREE.MeshBasicMaterial({ color: 0xffffff }); - const mesh = new THREE.Mesh(geometry, material); - scene.add(mesh); -}) diff --git a/index.html b/index.html index 891aeff3..b2fa3dbd 100644 --- a/index.html +++ b/index.html @@ -27,6 +27,7 @@
A true Minecraft client in your browser!
+ ` @@ -36,6 +37,13 @@ if (!window.pageLoaded) { document.documentElement.appendChild(loadingDivElem) } + + // iOS version detection + const getIOSVersion = () => { + const match = navigator.userAgent.match(/OS (\d+)_(\d+)_?(\d+)?/); + return match ? parseInt(match[1], 10) : null; + } + // load error handling const onError = (errorOrMessage, log = false) => { let message = errorOrMessage instanceof Error ? (errorOrMessage.stack ?? errorOrMessage.message) : errorOrMessage @@ -46,12 +54,23 @@ const [errorMessage, ...errorStack] = message.split('\n') document.querySelector('.initial-loader').querySelector('.subtitle').textContent = errorMessage document.querySelector('.initial-loader').querySelector('.advanced-info').textContent = errorStack.join('\n') + + // Show iOS warning if applicable + const iosVersion = getIOSVersion(); + if (iosVersion !== null && iosVersion < 15) { + document.querySelector('.initial-loader').querySelector('.ios-warning').style.display = 'block'; + } + if (window.navigator.maxTouchPoints > 1) window.location.hash = '#dev' // show eruda // unregister all sw - if (window.navigator.serviceWorker) { + if (window.navigator.serviceWorker && document.querySelector('.initial-loader').style.opacity !== 0) { + console.log('got worker') window.navigator.serviceWorker.getRegistrations().then(registrations => { registrations.forEach(registration => { - registration.unregister() + console.log('got registration') + registration.unregister().then(() => { + console.log('worker unregistered') + }) }) }) } @@ -130,7 +149,7 @@ --> Minecraft Web Client - + diff --git a/package.json b/package.json index d9d0b69e..ff673726 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,14 @@ "dev-proxy": "node server.js", "start": "run-p dev-proxy dev-rsbuild watch-mesher", "start2": "run-p dev-rsbuild watch-mesher", + "start-metrics": "ENABLE_METRICS=true rsbuild dev", "build": "pnpm build-other-workers && rsbuild build", "build-analyze": "BUNDLE_ANALYZE=true rsbuild build && pnpm build-other-workers", "build-single-file": "SINGLE_FILE_BUILD=true rsbuild build", "prepare-project": "tsx scripts/genShims.ts && tsx scripts/makeOptimizedMcData.mjs && tsx scripts/genLargeDataAliases.ts", "check-build": "pnpm prepare-project && tsc && pnpm build", "test:cypress": "cypress run", + "test:benchmark": "PERFORMANCE_TEST=true cypress run", "test:cypress:open": "cypress open", "test-unit": "vitest", "test:e2e": "start-test http-get://localhost:8080 test:cypress", @@ -30,7 +32,9 @@ "run-playground": "run-p watch-mesher watch-other-workers watch-playground", "run-all": "run-p start run-playground", "build-playground": "rsbuild build --config renderer/rsbuild.config.ts", - "watch-playground": "rsbuild dev --config renderer/rsbuild.config.ts" + "watch-playground": "rsbuild dev --config renderer/rsbuild.config.ts", + "update-git-deps": "tsx scripts/updateGitDeps.ts", + "request-data": "tsx scripts/requestData.ts" }, "keywords": [ "prismarine", @@ -50,8 +54,9 @@ "dependencies": { "@dimaka/interface": "0.0.3-alpha.0", "@floating-ui/react": "^0.26.1", - "@nxg-org/mineflayer-auto-jump": "^0.7.12", - "@nxg-org/mineflayer-tracker": "1.2.1", + "@monaco-editor/react": "^4.7.0", + "@nxg-org/mineflayer-auto-jump": "^0.7.18", + "@nxg-org/mineflayer-tracker": "1.3.0", "@react-oauth/google": "^0.12.1", "@stylistic/eslint-plugin": "^2.6.1", "@types/gapi": "^0.0.47", @@ -75,18 +80,19 @@ "esbuild-plugin-polyfill-node": "^0.3.0", "express": "^4.18.2", "filesize": "^10.0.12", - "flying-squid": "npm:@zardoy/flying-squid@^0.0.51", + "flying-squid": "npm:@zardoy/flying-squid@^0.0.104", + "framer-motion": "^12.9.2", "fs-extra": "^11.1.1", "google-drive-browserfs": "github:zardoy/browserfs#google-drive", "jszip": "^3.10.1", "lodash-es": "^4.17.21", - "minecraft-data": "3.83.1", + "mcraft-fun-mineflayer": "^0.1.23", + "minecraft-data": "3.98.0", "minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master", "mineflayer-item-map-downloader": "github:zardoy/mineflayer-item-map-downloader", "mojangson": "^2.0.4", "net-browserify": "github:zardoy/prismarinejs-net-browserify", "node-gzip": "^1.1.2", - "mcraft-fun-mineflayer": "^0.1.14", "peerjs": "^1.5.0", "pixelarticons": "^1.8.1", "pretty-bytes": "^6.1.1", @@ -100,7 +106,6 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-select": "^5.8.0", - "react-transition-group": "^4.4.5", "react-zoom-pan-pinch": "3.4.4", "remark": "^15.0.1", "sanitize-filename": "^1.6.3", @@ -118,11 +123,11 @@ "workbox-build": "^7.0.0" }, "devDependencies": { - "@rsbuild/core": "^1.0.1-beta.9", - "@rsbuild/plugin-node-polyfill": "^1.0.3", - "@rsbuild/plugin-react": "^1.0.1-beta.9", - "@rsbuild/plugin-type-check": "^1.0.1-beta.9", - "@rsbuild/plugin-typed-css-modules": "^1.0.1", + "@rsbuild/core": "1.3.5", + "@rsbuild/plugin-node-polyfill": "1.3.0", + "@rsbuild/plugin-react": "1.2.0", + "@rsbuild/plugin-type-check": "1.2.1", + "@rsbuild/plugin-typed-css-modules": "1.0.2", "@storybook/addon-essentials": "^7.4.6", "@storybook/addon-links": "^7.4.6", "@storybook/blocks": "^7.4.6", @@ -130,7 +135,6 @@ "@storybook/react-vite": "^7.4.6", "@types/diff-match-patch": "^1.0.36", "@types/lodash-es": "^4.17.9", - "@types/react-transition-group": "^4.4.7", "@types/stats.js": "^0.17.1", "@types/three": "0.154.0", "@types/ua-parser-js": "^0.7.39", @@ -140,7 +144,7 @@ "browserify-zlib": "^0.2.0", "buffer": "^6.0.3", "constants-browserify": "^1.0.0", - "contro-max": "^0.1.8", + "contro-max": "^0.1.9", "crypto-browserify": "^3.12.0", "cypress-esbuild-preprocessor": "^1.0.2", "eslint": "^8.50.0", @@ -150,17 +154,16 @@ "http-browserify": "^1.7.0", "http-server": "^14.1.1", "https-browserify": "^1.0.0", - "mc-assets": "^0.2.45", - "mineflayer-mouse": "^0.1.7", + "mc-assets": "^0.2.62", "minecraft-inventory-gui": "github:zardoy/minecraft-inventory-gui#next", - "mineflayer": "github:zardoy/mineflayer", - "mineflayer-pathfinder": "^2.4.4", + "mineflayer": "github:zardoy/mineflayer#gen-the-master", + "mineflayer-mouse": "^0.1.21", "npm-run-all": "^4.1.5", "os-browserify": "^0.3.0", "path-browserify": "^1.0.1", "path-exists-cli": "^2.0.0", - "renderer": "link:renderer", "process": "github:PrismarineJS/node-process", + "renderer": "link:renderer", "rimraf": "^5.0.1", "storybook": "^7.4.6", "stream-browserify": "^3.0.0", @@ -194,14 +197,15 @@ }, "pnpm": { "overrides": { + "mineflayer": "github:zardoy/mineflayer#gen-the-master", + "@nxg-org/mineflayer-physics-util": "1.8.10", "buffer": "^6.0.3", "vec3": "0.1.10", - "@nxg-org/mineflayer-physics-util": "1.5.8", "three": "0.154.0", "diamond-square": "github:zardoy/diamond-square", "prismarine-block": "github:zardoy/prismarine-block#next-era", "prismarine-world": "github:zardoy/prismarine-world#next-era", - "minecraft-data": "3.83.1", + "minecraft-data": "3.98.0", "prismarine-provider-anvil": "github:zardoy/prismarine-provider-anvil#everything", "prismarine-physics": "github:zardoy/prismarine-physics", "minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master", @@ -210,14 +214,29 @@ "prismarine-item": "latest" }, "updateConfig": { - "ignoreDependencies": [] + "ignoreDependencies": [ + "browserfs", + "google-drive-browserfs" + ] }, "patchedDependencies": { - "three@0.154.0": "patches/three@0.154.0.patch", "pixelarticons@1.8.1": "patches/pixelarticons@1.8.1.patch", "mineflayer-item-map-downloader@1.2.0": "patches/mineflayer-item-map-downloader@1.2.0.patch", - "minecraft-protocol@1.54.0": "patches/minecraft-protocol@1.54.0.patch" - } + "minecraft-protocol": "patches/minecraft-protocol.patch" + }, + "ignoredBuiltDependencies": [ + "canvas", + "core-js", + "gl" + ], + "onlyBuiltDependencies": [ + "sharp", + "cypress", + "esbuild", + "fsevents" + ], + "ignorePatchFailures": false, + "allowUnusedPatches": false }, - "packageManager": "pnpm@9.0.4" + "packageManager": "pnpm@10.8.0+sha512.0e82714d1b5b43c74610193cb20734897c1d00de89d0e18420aebc5977fa13d780a9cb05734624e81ebd81cc876cd464794850641c48b9544326b5622ca29971" } diff --git a/patches/minecraft-protocol@1.54.0.patch b/patches/minecraft-protocol.patch similarity index 54% rename from patches/minecraft-protocol@1.54.0.patch rename to patches/minecraft-protocol.patch index 29111f69..e29f87d9 100644 --- a/patches/minecraft-protocol@1.54.0.patch +++ b/patches/minecraft-protocol.patch @@ -1,26 +1,26 @@ diff --git a/src/client/chat.js b/src/client/chat.js -index f14269bea055d4329cd729271e7406ec4b344de7..00f5482eb6e3c911381ca9a728b1b4aae0d1d337 100644 +index 0021870994fc59a82f0ac8aba0a65a8be43ef2f4..a53fceb843105ea2a1d88722b3fc7c3b43cb102a 100644 --- a/src/client/chat.js +++ b/src/client/chat.js -@@ -111,7 +111,7 @@ module.exports = function (client, options) { - for (const player of packet.data) { - if (!player.chatSession) continue - client._players[player.UUID] = { -- publicKey: crypto.createPublicKey({ key: player.chatSession.publicKey.keyBytes, format: 'der', type: 'spki' }), -+ // publicKey: crypto.createPublicKey({ key: player.chatSession.publicKey.keyBytes, format: 'der', type: 'spki' }), - publicKeyDER: player.chatSession.publicKey.keyBytes, - sessionUuid: player.chatSession.uuid - } -@@ -127,7 +127,7 @@ module.exports = function (client, options) { - for (const player of packet.data) { - if (player.crypto) { - client._players[player.UUID] = { -- publicKey: crypto.createPublicKey({ key: player.crypto.publicKey, format: 'der', type: 'spki' }), -+ // publicKey: crypto.createPublicKey({ key: player.crypto.publicKey, format: 'der', type: 'spki' }), - publicKeyDER: player.crypto.publicKey, - signature: player.crypto.signature, - displayName: player.displayName || player.name -@@ -198,7 +198,7 @@ module.exports = function (client, options) { +@@ -116,7 +116,7 @@ module.exports = function (client, options) { + for (const player of packet.data) { + if (player.chatSession) { + client._players[player.uuid] = { +- publicKey: crypto.createPublicKey({ key: player.chatSession.publicKey.keyBytes, format: 'der', type: 'spki' }), ++ // publicKey: crypto.createPublicKey({ key: player.chatSession.publicKey.keyBytes, format: 'der', type: 'spki' }), + publicKeyDER: player.chatSession.publicKey.keyBytes, + sessionUuid: player.chatSession.uuid + } +@@ -126,7 +126,7 @@ module.exports = function (client, options) { + + if (player.crypto) { + client._players[player.uuid] = { +- publicKey: crypto.createPublicKey({ key: player.crypto.publicKey, format: 'der', type: 'spki' }), ++ // publicKey: crypto.createPublicKey({ key: player.crypto.publicKey, format: 'der', type: 'spki' }), + publicKeyDER: player.crypto.publicKey, + signature: player.crypto.signature, + displayName: player.displayName || player.name +@@ -196,7 +196,7 @@ module.exports = function (client, options) { if (mcData.supportFeature('useChatSessions')) { const tsDelta = BigInt(Date.now()) - packet.timestamp const expired = !packet.timestamp || tsDelta > messageExpireTime || tsDelta < 0 @@ -28,8 +28,8 @@ index f14269bea055d4329cd729271e7406ec4b344de7..00f5482eb6e3c911381ca9a728b1b4aa + const verified = false && !packet.unsignedChatContent && updateAndValidateSession(packet.senderUuid, packet.plainMessage, packet.signature, packet.index, packet.previousMessages, packet.salt, packet.timestamp) && !expired if (verified) client._signatureCache.push(packet.signature) client.emit('playerChat', { - plainMessage: packet.plainMessage, -@@ -363,7 +363,7 @@ module.exports = function (client, options) { + globalIndex: packet.globalIndex, +@@ -362,7 +362,7 @@ module.exports = function (client, options) { } } @@ -38,16 +38,16 @@ index f14269bea055d4329cd729271e7406ec4b344de7..00f5482eb6e3c911381ca9a728b1b4aa options.timestamp = options.timestamp || BigInt(Date.now()) options.salt = options.salt || 1n -@@ -405,7 +405,7 @@ module.exports = function (client, options) { +@@ -407,7 +407,7 @@ module.exports = function (client, options) { message, timestamp: options.timestamp, salt: options.salt, - signature: (client.profileKeys && client._session) ? client.signMessage(message, options.timestamp, options.salt, undefined, acknowledgements) : undefined, + signature: (client.profileKeys && client._session) ? await client.signMessage(message, options.timestamp, options.salt, undefined, acknowledgements) : undefined, offset: client._lastSeenMessages.pending, + checksum: computeChatChecksum(client._lastSeenMessages), // 1.21.5+ acknowledged - }) -@@ -419,7 +419,7 @@ module.exports = function (client, options) { +@@ -422,7 +422,7 @@ module.exports = function (client, options) { message, timestamp: options.timestamp, salt: options.salt, @@ -57,7 +57,7 @@ index f14269bea055d4329cd729271e7406ec4b344de7..00f5482eb6e3c911381ca9a728b1b4aa previousMessages: client._lastSeenMessages.map((e) => ({ messageSender: e.sender, diff --git a/src/client/encrypt.js b/src/client/encrypt.js -index b9d21bab9faccd5dbf1975fc423fc55c73e906c5..99ffd76527b410e3a393181beb260108f4c63536 100644 +index 63cc2bd9615100bd2fd63dfe14c094aa6b8cd1c9..36df57d1196af9761d920fa285ac48f85410eaef 100644 --- a/src/client/encrypt.js +++ b/src/client/encrypt.js @@ -25,7 +25,11 @@ module.exports = function (client, options) { @@ -73,28 +73,24 @@ index b9d21bab9faccd5dbf1975fc423fc55c73e906c5..99ffd76527b410e3a393181beb260108 } function onJoinServerResponse (err) { +diff --git a/src/client/pluginChannels.js b/src/client/pluginChannels.js +index 671eb452f31e6b5fcd57d715f1009d010160c65f..7f69f511c8fb97d431ec5125c851b49be8e2ab76 100644 +--- a/src/client/pluginChannels.js ++++ b/src/client/pluginChannels.js +@@ -57,7 +57,7 @@ module.exports = function (client, options) { + try { + packet.data = proto.parsePacketBuffer(channel, packet.data).data + } catch (error) { +- client.emit('error', error) ++ client.emit('error', error, { customPayload: packet }) + return + } + } diff --git a/src/client.js b/src/client.js -index 74749698f8cee05b5dc749c271544f78d06645b0..e77e0a3f41c1ee780c3abbd54b0801d248c2a07c 100644 +index e369e77d055ba919e8f9da7b8e8b5dc879c74cf4..54bb9e6644388e9b6bd42b3012951875989cdf0c 100644 --- a/src/client.js +++ b/src/client.js -@@ -89,10 +89,12 @@ class Client extends EventEmitter { - parsed.metadata.name = parsed.data.name - parsed.data = parsed.data.params - parsed.metadata.state = state -- debug('read packet ' + state + '.' + parsed.metadata.name) -- if (debug.enabled) { -- const s = JSON.stringify(parsed.data, null, 2) -- debug(s && s.length > 10000 ? parsed.data : s) -+ if (!globalThis.excludeCommunicationDebugEvents?.includes(parsed.metadata.name)) { -+ debug('read packet ' + state + '.' + parsed.metadata.name) -+ if (debug.enabled) { -+ const s = JSON.stringify(parsed.data, null, 2) -+ debug(s && s.length > 10000 ? parsed.data : s) -+ } - } - if (this._hasBundlePacket && parsed.metadata.name === 'bundle_delimiter') { - if (this._mcBundle.length) { // End bundle -@@ -110,7 +112,13 @@ class Client extends EventEmitter { +@@ -111,7 +111,13 @@ class Client extends EventEmitter { this._hasBundlePacket = false } } else { @@ -109,7 +105,7 @@ index 74749698f8cee05b5dc749c271544f78d06645b0..e77e0a3f41c1ee780c3abbd54b0801d2 } }) } -@@ -168,7 +176,10 @@ class Client extends EventEmitter { +@@ -169,7 +175,10 @@ class Client extends EventEmitter { } const onFatalError = (err) => { @@ -121,25 +117,21 @@ index 74749698f8cee05b5dc749c271544f78d06645b0..e77e0a3f41c1ee780c3abbd54b0801d2 endSocket() } -@@ -197,6 +208,8 @@ class Client extends EventEmitter { +@@ -198,6 +207,10 @@ class Client extends EventEmitter { serializer -> framer -> socket -> splitter -> deserializer */ if (this.serializer) { this.serializer.end() -+ this.socket?.end() -+ this.socket?.emit('end') ++ setTimeout(() => { ++ this.socket?.end() ++ this.socket?.emit('end') ++ }, 2000) // allow the serializer to finish writing } else { if (this.socket) this.socket.end() } -@@ -238,8 +251,11 @@ class Client extends EventEmitter { - - write (name, params) { - if (!this.serializer.writable) { return } -- debug('writing packet ' + this.state + '.' + name) -- debug(params) -+ if (!globalThis.excludeCommunicationDebugEvents?.includes(name)) { -+ debug(`[${this.state}] from ${this.isServer ? 'server' : 'client'}: ` + name) -+ debug(params) -+ } +@@ -243,6 +256,7 @@ class Client extends EventEmitter { + debug('writing packet ' + this.state + '.' + name) + debug(params) + } + this.emit('writePacket', name, params) this.serializer.write({ name, params }) } diff --git a/patches/pixelarticons@1.8.1.patch b/patches/pixelarticons@1.8.1.patch index 10044536..b65b6f2b 100644 --- a/patches/pixelarticons@1.8.1.patch +++ b/patches/pixelarticons@1.8.1.patch @@ -1,5 +1,5 @@ diff --git a/fonts/pixelart-icons-font.css b/fonts/pixelart-icons-font.css -index 3b2ebe839370d96bf93ef5ca94a827f07e49378d..103ab4d6b9f3b5c9f41d1407e3cbf4ac392fbf41 100644 +index 3b2ebe839370d96bf93ef5ca94a827f07e49378d..4f8d76be2ca6e4ddc43c68d0a6f0f69979165ab4 100644 --- a/fonts/pixelart-icons-font.css +++ b/fonts/pixelart-icons-font.css @@ -1,16 +1,13 @@ @@ -10,10 +10,11 @@ index 3b2ebe839370d96bf93ef5ca94a827f07e49378d..103ab4d6b9f3b5c9f41d1407e3cbf4ac + src: url("pixelart-icons-font.woff2?t=1711815892278") format("woff2"), url("pixelart-icons-font.woff?t=1711815892278") format("woff"), - url('pixelart-icons-font.ttf?t=1711815892278') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ +- url('pixelart-icons-font.ttf?t=1711815892278') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ - url('pixelart-icons-font.svg?t=1711815892278#pixelart-icons-font') format('svg'); /* iOS 4.1- */ ++ url('pixelart-icons-font.ttf?t=1711815892278') format('truetype'); /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ } - + [class^="pixelart-icons-font-"], [class*=" pixelart-icons-font-"] { font-family: 'pixelart-icons-font' !important; - font-size:24px; diff --git a/patches/three@0.154.0.patch b/patches/three@0.154.0.patch deleted file mode 100644 index e612415c..00000000 --- a/patches/three@0.154.0.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/examples/jsm/webxr/VRButton.js b/examples/jsm/webxr/VRButton.js -index 6856a21b17aa45d7922bbf776fd2d7e63c7a9b4e..0925b706f7629bd52f0bb5af469536af8f5fce2c 100644 ---- a/examples/jsm/webxr/VRButton.js -+++ b/examples/jsm/webxr/VRButton.js -@@ -62,7 +62,10 @@ class VRButton { - // ('local' is always available for immersive sessions and doesn't need to - // be requested separately.) - -- const sessionInit = { optionalFeatures: [ 'local-floor', 'bounded-floor', 'hand-tracking', 'layers' ] }; -+ const sessionInit = { -+ optionalFeatures: ['local-floor', 'bounded-floor', 'layers'], -+ domOverlay: { root: document.body }, -+ }; - navigator.xr.requestSession( 'immersive-vr', sessionInit ).then( onSessionStarted ); - - } else { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 537a391e..5bcd74a0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,14 +5,15 @@ settings: excludeLinksFromLockfile: false overrides: + mineflayer: github:zardoy/mineflayer#gen-the-master + '@nxg-org/mineflayer-physics-util': 1.8.10 buffer: ^6.0.3 vec3: 0.1.10 - '@nxg-org/mineflayer-physics-util': 1.5.8 three: 0.154.0 diamond-square: github:zardoy/diamond-square prismarine-block: github:zardoy/prismarine-block#next-era prismarine-world: github:zardoy/prismarine-world#next-era - minecraft-data: 3.83.1 + minecraft-data: 3.98.0 prismarine-provider-anvil: github:zardoy/prismarine-provider-anvil#everything prismarine-physics: github:zardoy/prismarine-physics minecraft-protocol: github:PrismarineJS/node-minecraft-protocol#master @@ -21,18 +22,15 @@ overrides: prismarine-item: latest patchedDependencies: - minecraft-protocol@1.54.0: - hash: dkeyukcqlupmk563gwxsmjr3yu - path: patches/minecraft-protocol@1.54.0.patch + minecraft-protocol: + hash: 4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b + path: patches/minecraft-protocol.patch mineflayer-item-map-downloader@1.2.0: - hash: bck55yjvd4wrgz46x7o4vfur5q + hash: a731ebbace2d8790c973ab3a5ba33494a6e9658533a9710dd8ba36f86db061ad path: patches/mineflayer-item-map-downloader@1.2.0.patch pixelarticons@1.8.1: - hash: cclg2qo6d4yjs4evj64nr2mbwa + hash: 533230072bc402f425c86abd3d0356fe087b14cab2a254d93f419b083f2d8dfa path: patches/pixelarticons@1.8.1.patch - three@0.154.0: - hash: sj7ocb4p23jym6bkfgueanti2e - path: patches/three@0.154.0.patch importers: @@ -40,58 +38,61 @@ importers: dependencies: '@dimaka/interface': specifier: 0.0.3-alpha.0 - version: 0.0.3-alpha.0(@babel/core@7.22.11)(@popperjs/core@2.11.8)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 0.0.3-alpha.0(@babel/core@7.26.9)(@popperjs/core@2.11.8)(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@floating-ui/react': specifier: ^0.26.1 - version: 0.26.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 0.26.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@monaco-editor/react': + specifier: ^4.7.0 + version: 4.7.0(monaco-editor@0.52.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@nxg-org/mineflayer-auto-jump': - specifier: ^0.7.12 - version: 0.7.12 + specifier: ^0.7.18 + version: 0.7.18 '@nxg-org/mineflayer-tracker': - specifier: 1.2.1 - version: 1.2.1 + specifier: 1.3.0 + version: 1.3.0(encoding@0.1.13) '@react-oauth/google': specifier: ^0.12.1 - version: 0.12.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 0.12.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@stylistic/eslint-plugin': specifier: ^2.6.1 - version: 2.6.1(eslint@8.50.0)(typescript@5.5.4) + version: 2.13.0(eslint@8.57.1)(typescript@5.5.4) '@types/gapi': specifier: ^0.0.47 version: 0.0.47 '@types/react': specifier: ^18.2.20 - version: 18.2.20 + version: 18.3.18 '@types/react-dom': specifier: ^18.2.7 - version: 18.2.7 + version: 18.3.5(@types/react@18.3.18) '@types/wicg-file-system-access': specifier: ^2023.10.2 - version: 2023.10.2 + version: 2023.10.5 '@xmcl/text-component': specifier: ^2.1.3 version: 2.1.3 '@zardoy/react-util': specifier: ^0.2.4 - version: 0.2.4(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 0.2.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@zardoy/utils': specifier: ^0.0.11 version: 0.0.11 adm-zip: specifier: ^0.5.12 - version: 0.5.12 + version: 0.5.16 browserfs: specifier: github:zardoy/browserfs#build version: https://codeload.github.com/zardoy/browserfs/tar.gz/e60ca69e74888e057a96a468afe1d62347d3f56f change-case: specifier: ^5.1.2 - version: 5.1.2 + version: 5.4.4 classnames: specifier: ^2.5.1 version: 2.5.1 compression: specifier: ^1.7.4 - version: 1.7.4 + version: 1.8.0 cors: specifier: ^2.8.5 version: 2.8.5 @@ -106,25 +107,28 @@ importers: version: 1.0.5 eruda: specifier: ^3.0.1 - version: 3.0.1 + version: 3.4.1 esbuild: specifier: ^0.19.3 - version: 0.19.11 + version: 0.19.12 esbuild-plugin-polyfill-node: specifier: ^0.3.0 - version: 0.3.0(esbuild@0.19.11) + version: 0.3.0(esbuild@0.19.12) express: specifier: ^4.18.2 - version: 4.18.2 + version: 4.21.2 filesize: specifier: ^10.0.12 - version: 10.0.12 + version: 10.1.6 flying-squid: - specifier: npm:@zardoy/flying-squid@^0.0.51 - version: '@zardoy/flying-squid@0.0.51(encoding@0.1.13)' + specifier: npm:@zardoy/flying-squid@^0.0.104 + version: '@zardoy/flying-squid@0.0.104(encoding@0.1.13)' + framer-motion: + specifier: ^12.9.2 + version: 12.9.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) fs-extra: specifier: ^11.1.1 - version: 11.1.1 + version: 11.3.0 google-drive-browserfs: specifier: github:zardoy/browserfs#google-drive version: browserfs@https://codeload.github.com/zardoy/browserfs/tar.gz/ab58ae8ef00e3a31db01909e365e6cb5188436e0 @@ -135,44 +139,44 @@ importers: specifier: ^4.17.21 version: 4.17.21 mcraft-fun-mineflayer: - specifier: ^0.1.14 - version: 0.1.14(encoding@0.1.13)(mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/06e3050ddf4d9aa655fea6e2bed182937a81705d(encoding@0.1.13)) + specifier: ^0.1.23 + version: 0.1.23(encoding@0.1.13)(mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13)) minecraft-data: - specifier: 3.83.1 - version: 3.83.1 + specifier: 3.98.0 + version: 3.98.0 minecraft-protocol: specifier: github:PrismarineJS/node-minecraft-protocol#master - version: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/5ec3dd4b367fcc039fbcb3edd214fe3cf8178a6d(patch_hash=dkeyukcqlupmk563gwxsmjr3yu)(encoding@0.1.13) + version: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13) mineflayer-item-map-downloader: specifier: github:zardoy/mineflayer-item-map-downloader - version: https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824(patch_hash=bck55yjvd4wrgz46x7o4vfur5q)(encoding@0.1.13) + version: https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824(patch_hash=a731ebbace2d8790c973ab3a5ba33494a6e9658533a9710dd8ba36f86db061ad)(encoding@0.1.13) mojangson: specifier: ^2.0.4 version: 2.0.4 net-browserify: specifier: github:zardoy/prismarinejs-net-browserify - version: https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/624cc67c16f5e8b23b772e7eaabae16ba84b8590 + version: https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/e754999ffdea67853bc9b10553b5e9908b40f618 node-gzip: specifier: ^1.1.2 version: 1.1.2 peerjs: specifier: ^1.5.0 - version: 1.5.0 + version: 1.5.4 pixelarticons: specifier: ^1.8.1 - version: 1.8.1(patch_hash=cclg2qo6d4yjs4evj64nr2mbwa) + version: 1.8.1(patch_hash=533230072bc402f425c86abd3d0356fe087b14cab2a254d93f419b083f2d8dfa) pretty-bytes: specifier: ^6.1.1 version: 6.1.1 prismarine-provider-anvil: specifier: github:zardoy/prismarine-provider-anvil#everything - version: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.83.1) + version: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.98.0) prosemirror-example-setup: specifier: ^1.2.2 - version: 1.2.2 + version: 1.2.3 prosemirror-markdown: specifier: ^1.12.0 - version: 1.12.0 + version: 1.13.1 prosemirror-menu: specifier: ^1.2.4 version: 1.2.4 @@ -181,25 +185,22 @@ importers: version: 1.4.3 prosemirror-view: specifier: ^1.33.1 - version: 1.33.1 + version: 1.38.1 qrcode.react: specifier: ^3.1.0 - version: 3.1.0(react@18.2.0) + version: 3.2.0(react@18.3.1) react: specifier: ^18.2.0 - version: 18.2.0 + version: 18.3.1 react-dom: specifier: ^18.2.0 - version: 18.2.0(react@18.2.0) + version: 18.3.1(react@18.3.1) react-select: specifier: ^5.8.0 - version: 5.8.0(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react-transition-group: - specifier: ^4.4.5 - version: 4.4.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.10.1(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-zoom-pan-pinch: specifier: 3.4.4 - version: 3.4.4(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 3.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) remark: specifier: ^15.0.1 version: 15.0.1 @@ -208,13 +209,13 @@ importers: version: 1.6.3 skinview3d: specifier: ^3.0.1 - version: 3.0.1 + version: 3.1.0 source-map-js: specifier: ^1.0.2 version: 1.2.1 stats-gl: specifier: ^1.0.5 - version: 1.0.5 + version: 1.0.7 stats.js: specifier: ^0.17.0 version: 0.17.0 @@ -226,13 +227,13 @@ importers: version: 3.0.3 ua-parser-js: specifier: ^1.0.37 - version: 1.0.37 + version: 1.0.40 use-typed-event-listener: specifier: ^4.0.2 - version: 4.0.2(react@18.2.0)(typescript@5.5.4) + version: 4.0.2(react@18.3.1)(typescript@5.5.4) valtio: specifier: ^1.11.1 - version: 1.11.2(@types/react@18.2.20)(react@18.2.0) + version: 1.13.2(@types/react@18.3.18)(react@18.3.1) vec3: specifier: 0.1.10 version: 0.1.10 @@ -241,63 +242,47 @@ importers: version: 7.2.0(debug@4.4.0) workbox-build: specifier: ^7.0.0 - version: 7.0.0(@types/babel__core@7.20.2) - optionalDependencies: - cypress: - specifier: ^10.11.0 - version: 10.11.0 - cypress-plugin-snapshots: - specifier: ^1.4.4 - version: 1.4.4(cypress@10.11.0) - sharp: - specifier: ^0.33.5 - version: 0.33.5 - systeminformation: - specifier: ^5.21.22 - version: 5.22.7 + version: 7.3.0(@types/babel__core@7.20.5) devDependencies: '@rsbuild/core': - specifier: ^1.0.1-beta.9 - version: 1.0.1-beta.9 + specifier: 1.3.5 + version: 1.3.5 '@rsbuild/plugin-node-polyfill': - specifier: ^1.0.3 - version: 1.0.3(@rsbuild/core@1.0.1-beta.9) + specifier: 1.3.0 + version: 1.3.0(@rsbuild/core@1.3.5) '@rsbuild/plugin-react': - specifier: ^1.0.1-beta.9 - version: 1.0.1-beta.9(@rsbuild/core@1.0.1-beta.9) + specifier: 1.2.0 + version: 1.2.0(@rsbuild/core@1.3.5) '@rsbuild/plugin-type-check': - specifier: ^1.0.1-beta.9 - version: 1.0.1-beta.9(@rsbuild/core@1.0.1-beta.9)(esbuild@0.19.11)(typescript@5.5.4) + specifier: 1.2.1 + version: 1.2.1(@rsbuild/core@1.3.5)(@rspack/core@1.3.3(@swc/helpers@0.5.15))(typescript@5.5.4) '@rsbuild/plugin-typed-css-modules': - specifier: ^1.0.1 - version: 1.0.1(@rsbuild/core@1.0.1-beta.9) + specifier: 1.0.2 + version: 1.0.2(@rsbuild/core@1.3.5) '@storybook/addon-essentials': specifier: ^7.4.6 - version: 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 7.6.20(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/addon-links': specifier: ^7.4.6 - version: 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 7.6.20(react@18.3.1) '@storybook/blocks': specifier: ^7.4.6 - version: 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 7.6.20(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/react': specifier: ^7.4.6 - version: 7.4.6(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4) + version: 7.6.20(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@storybook/react-vite': specifier: ^7.4.6 - version: 7.4.6(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(rollup@2.79.1)(typescript@5.5.4)(vite@6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1)) + version: 7.6.20(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@2.79.2)(typescript@5.5.4)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0)) '@types/diff-match-patch': specifier: ^1.0.36 version: 1.0.36 '@types/lodash-es': specifier: ^4.17.9 - version: 4.17.9 - '@types/react-transition-group': - specifier: ^4.4.7 - version: 4.4.7 + version: 4.17.12 '@types/stats.js': specifier: ^0.17.1 - version: 0.17.1 + version: 0.17.3 '@types/three': specifier: 0.154.0 version: 0.154.0 @@ -309,7 +294,7 @@ importers: version: 5.3.4 '@xmcl/installer': specifier: ^5.1.0 - version: 5.1.0 + version: 5.4.0 assert: specifier: ^2.0.0 version: 2.1.0 @@ -323,20 +308,20 @@ importers: specifier: ^1.0.0 version: 1.0.0 contro-max: - specifier: ^0.1.8 - version: 0.1.8(typescript@5.5.4) + specifier: ^0.1.9 + version: 0.1.9(typescript@5.5.4) crypto-browserify: specifier: ^3.12.0 - version: 3.12.0 + version: 3.12.1 cypress-esbuild-preprocessor: specifier: ^1.0.2 version: 1.0.2 eslint: specifier: ^8.50.0 - version: 8.50.0 + version: 8.57.1 eslint-config-zardoy: specifier: ^0.2.17 - version: 0.2.17(eslint-plugin-react-hooks@4.6.0(eslint@8.50.0))(eslint-plugin-react@7.34.1(eslint@8.50.0))(eslint@8.50.0)(typescript@5.5.4) + version: 0.2.17(eslint-plugin-react-hooks@5.2.0(eslint@8.57.1))(eslint-plugin-react@7.37.4(eslint@8.57.1))(eslint@8.57.1)(typescript@5.5.4) events: specifier: ^3.3.0 version: 3.3.0 @@ -353,20 +338,17 @@ importers: specifier: ^1.0.0 version: 1.0.0 mc-assets: - specifier: ^0.2.45 - version: 0.2.45 + specifier: ^0.2.62 + version: 0.2.62 minecraft-inventory-gui: specifier: github:zardoy/minecraft-inventory-gui#next - version: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/75e940a4cd50d89e0ba03db3733d5d704917a3c8(@types/react@18.2.20)(react@18.2.0) + version: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/89c33d396f3fde4804c71f4be3c203ade1833b41(@types/react@18.3.18)(react@18.3.1) mineflayer: - specifier: github:zardoy/mineflayer - version: https://codeload.github.com/zardoy/mineflayer/tar.gz/06e3050ddf4d9aa655fea6e2bed182937a81705d(encoding@0.1.13) + specifier: github:zardoy/mineflayer#gen-the-master + version: https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13) mineflayer-mouse: - specifier: ^0.1.7 - version: 0.1.7(@types/debug@4.1.12)(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1) - mineflayer-pathfinder: - specifier: ^2.4.4 - version: 2.4.4 + specifier: ^0.1.21 + version: 0.1.21 npm-run-all: specifier: ^4.1.5 version: 4.1.5 @@ -387,16 +369,16 @@ importers: version: link:renderer rimraf: specifier: ^5.0.1 - version: 5.0.1 + version: 5.0.10 storybook: specifier: ^7.4.6 - version: 7.4.6(encoding@0.1.13) + version: 7.6.20(encoding@0.1.13) stream-browserify: specifier: ^3.0.0 version: 3.0.0 three: specifier: 0.154.0 - version: 0.154.0(patch_hash=sj7ocb4p23jym6bkfgueanti2e) + version: 0.154.0 timers-browserify: specifier: ^2.0.12 version: 2.0.12 @@ -405,10 +387,23 @@ importers: version: 5.5.4 vitest: specifier: ^0.34.6 - version: 0.34.6(terser@5.31.3) + version: 0.34.6(terser@5.39.0) yaml: specifier: ^2.3.2 - version: 2.4.1 + version: 2.7.0 + optionalDependencies: + cypress: + specifier: ^10.11.0 + version: 10.11.0 + cypress-plugin-snapshots: + specifier: ^1.4.4 + version: 1.4.4(cypress@10.11.0)(debug@4.4.0) + sharp: + specifier: ^0.33.5 + version: 0.33.5 + systeminformation: + specifier: ^5.21.22 + version: 5.25.11 renderer: dependencies: @@ -423,25 +418,25 @@ importers: version: 6.0.3 filesize: specifier: ^10.0.12 - version: 10.0.12 + version: 10.1.6 fs-extra: specifier: ^11.0.0 - version: 11.1.1 + version: 11.3.0 lil-gui: specifier: ^0.18.2 version: 0.18.2 minecraft-wrap: specifier: ^1.3.0 - version: 1.5.1(encoding@0.1.13) + version: 1.6.0(encoding@0.1.13) minecrafthawkeye: specifier: ^1.3.6 - version: 1.3.6 + version: 1.3.9 prismarine-block: specifier: github:zardoy/prismarine-block#next-era - version: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) + version: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9 prismarine-chunk: specifier: github:zardoy/prismarine-chunk#master - version: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/e68e9a423b5b1907535878fb636f12c28a1a9374(minecraft-data@3.83.1) + version: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0) prismarine-schematic: specifier: ^1.2.0 version: 1.2.3 @@ -453,22 +448,26 @@ importers: version: 'link:' socket.io: specifier: ^4.0.0 - version: 4.7.2 + version: 4.8.1 socket.io-client: specifier: ^4.0.0 - version: 4.7.2 + version: 4.8.1 three-stdlib: specifier: ^2.26.11 - version: 2.28.5(three@0.154.0(patch_hash=sj7ocb4p23jym6bkfgueanti2e)) + version: 2.35.14(three@0.154.0) three.meshline: specifier: ^1.3.0 version: 1.4.0 tsx: specifier: ^4.7.0 - version: 4.7.0 + version: 4.19.3 vec3: specifier: 0.1.10 version: 0.1.10 + devDependencies: + live-server: + specifier: ^1.2.2 + version: 1.2.2 optionalDependencies: canvas: specifier: ^2.11.2 @@ -476,25 +475,17 @@ importers: node-canvas-webgl: specifier: ^0.3.0 version: 0.3.0(encoding@0.1.13) - devDependencies: - live-server: - specifier: ^1.2.2 - version: 1.2.2 renderer/viewer/sign-renderer: dependencies: vite: specifier: ^4.4.9 - version: 4.5.3(@types/node@22.8.1)(terser@5.31.3) + version: 4.5.9(@types/node@22.13.9)(terser@5.39.0) packages: - '@aashutoshrathi/word-wrap@1.2.6': - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - - '@ampproject/remapping@2.2.1': - resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} '@apideck/better-ajv-errors@0.3.6': @@ -507,178 +498,147 @@ packages: resolution: {integrity: sha512-Xk1sIhyNC/esHGGVjL/niHLowM0csl/kFO5uawBy4IrWwy0o1G8LGt3jP6nmWGz+USxeeqbihAmp/oVZju6wug==} hasBin: true - '@azure/msal-common@14.9.0': - resolution: {integrity: sha512-yzBPRlWPnTBeixxLNI3BBIgF5/bHpbhoRVuuDBnYjCyWRavaPUsKAHUDYLqpGkBLDciA6TCc6GOxN4/S3WiSxg==} + '@azure/msal-common@14.16.0': + resolution: {integrity: sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA==} engines: {node: '>=0.8.0'} - '@azure/msal-node@2.7.0': - resolution: {integrity: sha512-wXD8LkUvHICeSWZydqg6o8Yvv+grlBEcmLGu+QEI4FcwFendbTEZrlSygnAXXSOCVaGAirWLchca35qrgpO6Jw==} + '@azure/msal-node@2.16.2': + resolution: {integrity: sha512-An7l1hEr0w1HMMh1LU+rtDtqL7/jw74ORlc9Wnh06v7TU/xpG39/Zdr1ZJu3QpjUfKJ+E0/OXMW8DRSWTlh7qQ==} engines: {node: '>=16'} - '@babel/code-frame@7.22.13': - resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.22.9': - resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==} + '@babel/compat-data@7.26.8': + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} engines: {node: '>=6.9.0'} - '@babel/core@7.22.11': - resolution: {integrity: sha512-lh7RJrtPdhibbxndr6/xx0w8+CVlY5FJZiaSz908Fpy+G0xkBFTvwLcKJFF4PJxVfGhVWNebikpWGnOoC71juQ==} + '@babel/core@7.26.9': + resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} engines: {node: '>=6.9.0'} - '@babel/generator@7.22.10': - resolution: {integrity: sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==} + '@babel/generator@7.26.9': + resolution: {integrity: sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==} engines: {node: '>=6.9.0'} - '@babel/helper-annotate-as-pure@7.22.5': - resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + '@babel/helper-annotate-as-pure@7.25.9': + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} engines: {node: '>=6.9.0'} - '@babel/helper-builder-binary-assignment-operator-visitor@7.22.10': - resolution: {integrity: sha512-Av0qubwDQxC56DoUReVDeLfMEjYYSN1nZrTUrWkXd7hpU73ymRANkbuDm3yni9npkn+RXy9nNbEJZEzXr7xrfQ==} + '@babel/helper-compilation-targets@7.26.5': + resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.22.10': - resolution: {integrity: sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==} - engines: {node: '>=6.9.0'} - - '@babel/helper-create-class-features-plugin@7.22.15': - resolution: {integrity: sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==} + '@babel/helper-create-class-features-plugin@7.26.9': + resolution: {integrity: sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-create-regexp-features-plugin@7.22.9': - resolution: {integrity: sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==} + '@babel/helper-create-regexp-features-plugin@7.26.3': + resolution: {integrity: sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-define-polyfill-provider@0.4.2': - resolution: {integrity: sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==} + '@babel/helper-define-polyfill-provider@0.6.3': + resolution: {integrity: sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - '@babel/helper-environment-visitor@7.22.20': - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + '@babel/helper-member-expression-to-functions@7.25.9': + resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} engines: {node: '>=6.9.0'} - '@babel/helper-function-name@7.22.5': - resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==} + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} engines: {node: '>=6.9.0'} - '@babel/helper-hoist-variables@7.22.5': - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-member-expression-to-functions@7.23.0': - resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.22.15': - resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.23.0': - resolution: {integrity: sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==} + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-optimise-call-expression@7.22.5': - resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} + '@babel/helper-optimise-call-expression@7.25.9': + resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.22.5': - resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} + '@babel/helper-plugin-utils@7.26.5': + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} engines: {node: '>=6.9.0'} - '@babel/helper-remap-async-to-generator@7.22.9': - resolution: {integrity: sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==} + '@babel/helper-remap-async-to-generator@7.25.9': + resolution: {integrity: sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-replace-supers@7.22.9': - resolution: {integrity: sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==} + '@babel/helper-replace-supers@7.26.5': + resolution: {integrity: sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-simple-access@7.22.5': - resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': + resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} engines: {node: '>=6.9.0'} - '@babel/helper-skip-transparent-expression-wrappers@7.22.5': - resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} - '@babel/helper-split-export-declaration@7.22.6': - resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.22.5': - resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.22.20': - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + '@babel/helper-wrap-function@7.25.9': + resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.22.15': - resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==} + '@babel/helpers@7.26.9': + resolution: {integrity: sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==} engines: {node: '>=6.9.0'} - '@babel/helper-wrap-function@7.22.10': - resolution: {integrity: sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.22.11': - resolution: {integrity: sha512-vyOXC8PBWaGc5h7GMsNx68OH33cypkEDJCHvYVVgVbbxJDROYVtexSk0gK5iCF1xNjRIN2s8ai7hwkWDq5szWg==} - engines: {node: '>=6.9.0'} - - '@babel/highlight@7.22.13': - resolution: {integrity: sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.22.13': - resolution: {integrity: sha512-3l6+4YOvc9wx7VlCSw4yQfcBo01ECA8TicQfbnCPuCEpRQrf+gTUyGdxNw+pyTUyywp6JRD1w0YQs9TpBXYlkw==} + '@babel/parser@7.26.9': + resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.22.5': - resolution: {integrity: sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==} + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9': + resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.22.5': - resolution: {integrity: sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==} + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9': + resolution: {integrity: sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9': + resolution: {integrity: sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9': + resolution: {integrity: sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 - '@babel/plugin-proposal-class-properties@7.18.6': - resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9': + resolution: {integrity: sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==} engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead. peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6': - resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-proposal-optional-chaining@7.21.0': - resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead. - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/core': ^7.0.0 '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} @@ -686,110 +646,32 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-async-generators@7.8.4': - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-properties@7.12.13': - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-static-block@7.14.5': - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + '@babel/plugin-syntax-flow@7.26.0': + resolution: {integrity: sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-dynamic-import@7.8.3': - resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-export-namespace-from@7.8.3': - resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-flow@7.22.5': - resolution: {integrity: sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==} + '@babel/plugin-syntax-import-assertions@7.26.0': + resolution: {integrity: sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-assertions@7.22.5': - resolution: {integrity: sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==} + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-attributes@7.22.5': - resolution: {integrity: sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==} + '@babel/plugin-syntax-jsx@7.25.9': + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-meta@7.10.4': - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-json-strings@7.8.3': - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-jsx@7.22.5': - resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4': - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-numeric-separator@7.10.4': - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-object-rest-spread@7.8.3': - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3': - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-chaining@7.8.3': - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-private-property-in-object@7.14.5': - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-top-level-await@7.14.5': - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-typescript@7.22.5': - resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==} + '@babel/plugin-syntax-typescript@7.25.9': + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -800,326 +682,338 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-arrow-functions@7.22.5': - resolution: {integrity: sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==} + '@babel/plugin-transform-arrow-functions@7.25.9': + resolution: {integrity: sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-generator-functions@7.22.11': - resolution: {integrity: sha512-0pAlmeRJn6wU84zzZsEOx1JV1Jf8fqO9ok7wofIJwUnplYo247dcd24P+cMJht7ts9xkzdtB0EPHmOb7F+KzXw==} + '@babel/plugin-transform-async-generator-functions@7.26.8': + resolution: {integrity: sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-to-generator@7.22.5': - resolution: {integrity: sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==} + '@babel/plugin-transform-async-to-generator@7.25.9': + resolution: {integrity: sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoped-functions@7.22.5': - resolution: {integrity: sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==} + '@babel/plugin-transform-block-scoped-functions@7.26.5': + resolution: {integrity: sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.22.10': - resolution: {integrity: sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg==} + '@babel/plugin-transform-block-scoping@7.25.9': + resolution: {integrity: sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-properties@7.22.5': - resolution: {integrity: sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==} + '@babel/plugin-transform-class-properties@7.25.9': + resolution: {integrity: sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-static-block@7.22.11': - resolution: {integrity: sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==} + '@babel/plugin-transform-class-static-block@7.26.0': + resolution: {integrity: sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 - '@babel/plugin-transform-classes@7.22.6': - resolution: {integrity: sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==} + '@babel/plugin-transform-classes@7.25.9': + resolution: {integrity: sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-computed-properties@7.22.5': - resolution: {integrity: sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==} + '@babel/plugin-transform-computed-properties@7.25.9': + resolution: {integrity: sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-destructuring@7.22.10': - resolution: {integrity: sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw==} + '@babel/plugin-transform-destructuring@7.25.9': + resolution: {integrity: sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-dotall-regex@7.22.5': - resolution: {integrity: sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==} + '@babel/plugin-transform-dotall-regex@7.25.9': + resolution: {integrity: sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-duplicate-keys@7.22.5': - resolution: {integrity: sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==} + '@babel/plugin-transform-duplicate-keys@7.25.9': + resolution: {integrity: sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-dynamic-import@7.22.11': - resolution: {integrity: sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-exponentiation-operator@7.22.5': - resolution: {integrity: sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-export-namespace-from@7.22.11': - resolution: {integrity: sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-flow-strip-types@7.22.5': - resolution: {integrity: sha512-tujNbZdxdG0/54g/oua8ISToaXTFBf8EnSb5PgQSciIXWOWKX3S4+JR7ZE9ol8FZwf9kxitzkGQ+QWeov/mCiA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-for-of@7.22.5': - resolution: {integrity: sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-function-name@7.22.5': - resolution: {integrity: sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-json-strings@7.22.11': - resolution: {integrity: sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-literals@7.22.5': - resolution: {integrity: sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-logical-assignment-operators@7.22.11': - resolution: {integrity: sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-member-expression-literals@7.22.5': - resolution: {integrity: sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-modules-amd@7.22.5': - resolution: {integrity: sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-modules-commonjs@7.23.0': - resolution: {integrity: sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-modules-systemjs@7.22.11': - resolution: {integrity: sha512-rIqHmHoMEOhI3VkVf5jQ15l539KrwhzqcBO6wdCNWPWc/JWt9ILNYNUssbRpeq0qWns8svuw8LnMNCvWBIJ8wA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-modules-umd@7.22.5': - resolution: {integrity: sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-named-capturing-groups-regex@7.22.5': - resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9': + resolution: {integrity: sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-new-target@7.22.5': - resolution: {integrity: sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==} + '@babel/plugin-transform-dynamic-import@7.25.9': + resolution: {integrity: sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-nullish-coalescing-operator@7.22.11': - resolution: {integrity: sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==} + '@babel/plugin-transform-exponentiation-operator@7.26.3': + resolution: {integrity: sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-numeric-separator@7.22.11': - resolution: {integrity: sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==} + '@babel/plugin-transform-export-namespace-from@7.25.9': + resolution: {integrity: sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-rest-spread@7.22.11': - resolution: {integrity: sha512-nX8cPFa6+UmbepISvlf5jhQyaC7ASs/7UxHmMkuJ/k5xSHvDPPaibMo+v3TXwU/Pjqhep/nFNpd3zn4YR59pnw==} + '@babel/plugin-transform-flow-strip-types@7.26.5': + resolution: {integrity: sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-super@7.22.5': - resolution: {integrity: sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==} + '@babel/plugin-transform-for-of@7.26.9': + resolution: {integrity: sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-catch-binding@7.22.11': - resolution: {integrity: sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==} + '@babel/plugin-transform-function-name@7.25.9': + resolution: {integrity: sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-chaining@7.22.12': - resolution: {integrity: sha512-7XXCVqZtyFWqjDsYDY4T45w4mlx1rf7aOgkc/Ww76xkgBiOlmjPkx36PBLHa1k1rwWvVgYMPsbuVnIamx2ZQJw==} + '@babel/plugin-transform-json-strings@7.25.9': + resolution: {integrity: sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-parameters@7.22.5': - resolution: {integrity: sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==} + '@babel/plugin-transform-literals@7.25.9': + resolution: {integrity: sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-methods@7.22.5': - resolution: {integrity: sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==} + '@babel/plugin-transform-logical-assignment-operators@7.25.9': + resolution: {integrity: sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-property-in-object@7.22.11': - resolution: {integrity: sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==} + '@babel/plugin-transform-member-expression-literals@7.25.9': + resolution: {integrity: sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-property-literals@7.22.5': - resolution: {integrity: sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==} + '@babel/plugin-transform-modules-amd@7.25.9': + resolution: {integrity: sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-self@7.22.5': - resolution: {integrity: sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==} + '@babel/plugin-transform-modules-commonjs@7.26.3': + resolution: {integrity: sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-source@7.22.5': - resolution: {integrity: sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w==} + '@babel/plugin-transform-modules-systemjs@7.25.9': + resolution: {integrity: sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regenerator@7.22.10': - resolution: {integrity: sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==} + '@babel/plugin-transform-modules-umd@7.25.9': + resolution: {integrity: sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-reserved-words@7.22.5': - resolution: {integrity: sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-shorthand-properties@7.22.5': - resolution: {integrity: sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-spread@7.22.5': - resolution: {integrity: sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-sticky-regex@7.22.5': - resolution: {integrity: sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-template-literals@7.22.5': - resolution: {integrity: sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-typeof-symbol@7.22.5': - resolution: {integrity: sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-typescript@7.22.15': - resolution: {integrity: sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-unicode-escapes@7.22.10': - resolution: {integrity: sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-unicode-property-regex@7.22.5': - resolution: {integrity: sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-unicode-regex@7.22.5': - resolution: {integrity: sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-unicode-sets-regex@7.22.5': - resolution: {integrity: sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==} + '@babel/plugin-transform-named-capturing-groups-regex@7.25.9': + resolution: {integrity: sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/preset-env@7.22.10': - resolution: {integrity: sha512-riHpLb1drNkpLlocmSyEg4oYJIQFeXAK/d7rI6mbD0XsvoTOOweXDmQPG/ErxsEhWk3rl3Q/3F6RFQlVFS8m0A==} + '@babel/plugin-transform-new-target@7.25.9': + resolution: {integrity: sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/preset-flow@7.22.15': - resolution: {integrity: sha512-dB5aIMqpkgbTfN5vDdTRPzjqtWiZcRESNR88QYnoPR+bmdYoluOzMX9tQerTv0XzSgZYctPfO1oc0N5zdog1ew==} + '@babel/plugin-transform-nullish-coalescing-operator@7.26.6': + resolution: {integrity: sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-numeric-separator@7.25.9': + resolution: {integrity: sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.25.9': + resolution: {integrity: sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-super@7.25.9': + resolution: {integrity: sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.25.9': + resolution: {integrity: sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.25.9': + resolution: {integrity: sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.25.9': + resolution: {integrity: sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.25.9': + resolution: {integrity: sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.25.9': + resolution: {integrity: sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-property-literals@7.25.9': + resolution: {integrity: sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-self@7.25.9': + resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.25.9': + resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.25.9': + resolution: {integrity: sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regexp-modifiers@7.26.0': + resolution: {integrity: sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.25.9': + resolution: {integrity: sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.25.9': + resolution: {integrity: sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-spread@7.25.9': + resolution: {integrity: sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-sticky-regex@7.25.9': + resolution: {integrity: sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.26.8': + resolution: {integrity: sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typeof-symbol@7.26.7': + resolution: {integrity: sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.26.8': + resolution: {integrity: sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-escapes@7.25.9': + resolution: {integrity: sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-property-regex@7.25.9': + resolution: {integrity: sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.25.9': + resolution: {integrity: sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-sets-regex@7.25.9': + resolution: {integrity: sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/preset-env@7.26.9': + resolution: {integrity: sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-flow@7.25.9': + resolution: {integrity: sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1129,73 +1023,37 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - '@babel/preset-typescript@7.23.0': - resolution: {integrity: sha512-6P6VVa/NM/VlAYj5s2Aq/gdVg8FSENCg3wlZ6Qau9AcPaoF5LbN1nyGlR9DTRIw9PpxI94e+ReydsJHcjwAweg==} + '@babel/preset-typescript@7.26.0': + resolution: {integrity: sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/register@7.22.15': - resolution: {integrity: sha512-V3Q3EqoQdn65RCgTLwauZaTfd1ShhwPmbBv+1dkZV/HpCGMKVyn6oFcRlI7RaKqiDQjX2Qd3AuoEguBgdjIKlg==} + '@babel/register@7.25.9': + resolution: {integrity: sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/regjsgen@0.8.0': - resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - - '@babel/runtime@7.24.5': - resolution: {integrity: sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==} + '@babel/runtime@7.26.9': + resolution: {integrity: sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==} engines: {node: '>=6.9.0'} - '@babel/template@7.22.5': - resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} + '@babel/template@7.26.9': + resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.22.11': - resolution: {integrity: sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==} + '@babel/traverse@7.26.9': + resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==} engines: {node: '>=6.9.0'} - '@babel/types@7.23.0': - resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} + '@babel/types@7.26.9': + resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} engines: {node: '>=6.9.0'} '@base2/pretty-print-object@1.0.1': resolution: {integrity: sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==} - '@bcoe/v8-coverage@0.2.3': - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - - '@cbor-extract/cbor-extract-darwin-arm64@2.2.0': - resolution: {integrity: sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==} - cpu: [arm64] - os: [darwin] - - '@cbor-extract/cbor-extract-darwin-x64@2.2.0': - resolution: {integrity: sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==} - cpu: [x64] - os: [darwin] - - '@cbor-extract/cbor-extract-linux-arm64@2.2.0': - resolution: {integrity: sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==} - cpu: [arm64] - os: [linux] - - '@cbor-extract/cbor-extract-linux-arm@2.2.0': - resolution: {integrity: sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==} - cpu: [arm] - os: [linux] - - '@cbor-extract/cbor-extract-linux-x64@2.2.0': - resolution: {integrity: sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==} - cpu: [x64] - os: [linux] - - '@cbor-extract/cbor-extract-win32-x64@2.2.0': - resolution: {integrity: sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==} - cpu: [x64] - os: [win32] - '@colors/colors@1.5.0': resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} @@ -1219,11 +1077,11 @@ packages: '@emnapi/runtime@1.3.1': resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} - '@emotion/babel-plugin@11.12.0': - resolution: {integrity: sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==} + '@emotion/babel-plugin@11.13.5': + resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} - '@emotion/cache@11.13.1': - resolution: {integrity: sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==} + '@emotion/cache@11.14.0': + resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==} '@emotion/css@11.5.0': resolution: {integrity: sha512-mqjz/3aqR9rp40M+pvwdKYWxlQK4Nj3cnNjo3Tx6SM14dSsEn7q/4W2/I7PlgG+mb27iITHugXuBIHH/QwUBVQ==} @@ -1239,8 +1097,8 @@ packages: '@emotion/memoize@0.9.0': resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} - '@emotion/react@11.13.0': - resolution: {integrity: sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ==} + '@emotion/react@11.14.0': + resolution: {integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==} peerDependencies: '@types/react': '*' react: ^18.2.0 @@ -1248,28 +1106,28 @@ packages: '@types/react': optional: true - '@emotion/serialize@1.3.0': - resolution: {integrity: sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==} + '@emotion/serialize@1.3.3': + resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==} '@emotion/sheet@1.4.0': resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} - '@emotion/unitless@0.9.0': - resolution: {integrity: sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==} + '@emotion/unitless@0.10.0': + resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} - '@emotion/use-insertion-effect-with-fallbacks@1.1.0': - resolution: {integrity: sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==} + '@emotion/use-insertion-effect-with-fallbacks@1.2.0': + resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} peerDependencies: react: ^18.2.0 - '@emotion/utils@1.4.0': - resolution: {integrity: sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==} + '@emotion/utils@1.4.2': + resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==} '@emotion/weak-memoize@0.4.0': resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - '@esbuild/aix-ppc64@0.19.11': - resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==} + '@esbuild/aix-ppc64@0.19.12': + resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} engines: {node: '>=12'} cpu: [ppc64] os: [aix] @@ -1286,8 +1144,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.19.11': - resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==} + '@esbuild/android-arm64@0.19.12': + resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} engines: {node: '>=12'} cpu: [arm64] os: [android] @@ -1304,8 +1162,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.19.11': - resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==} + '@esbuild/android-arm@0.19.12': + resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} engines: {node: '>=12'} cpu: [arm] os: [android] @@ -1322,8 +1180,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.19.11': - resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==} + '@esbuild/android-x64@0.19.12': + resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} engines: {node: '>=12'} cpu: [x64] os: [android] @@ -1340,8 +1198,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.19.11': - resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==} + '@esbuild/darwin-arm64@0.19.12': + resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] @@ -1358,8 +1216,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.19.11': - resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==} + '@esbuild/darwin-x64@0.19.12': + resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} engines: {node: '>=12'} cpu: [x64] os: [darwin] @@ -1376,8 +1234,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.19.11': - resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==} + '@esbuild/freebsd-arm64@0.19.12': + resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] @@ -1394,8 +1252,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.19.11': - resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==} + '@esbuild/freebsd-x64@0.19.12': + resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] @@ -1412,8 +1270,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.19.11': - resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==} + '@esbuild/linux-arm64@0.19.12': + resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} engines: {node: '>=12'} cpu: [arm64] os: [linux] @@ -1430,8 +1288,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.19.11': - resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==} + '@esbuild/linux-arm@0.19.12': + resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} engines: {node: '>=12'} cpu: [arm] os: [linux] @@ -1448,8 +1306,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.19.11': - resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==} + '@esbuild/linux-ia32@0.19.12': + resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} engines: {node: '>=12'} cpu: [ia32] os: [linux] @@ -1466,8 +1324,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.19.11': - resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==} + '@esbuild/linux-loong64@0.19.12': + resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} engines: {node: '>=12'} cpu: [loong64] os: [linux] @@ -1484,8 +1342,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.19.11': - resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==} + '@esbuild/linux-mips64el@0.19.12': + resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] @@ -1502,8 +1360,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.19.11': - resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==} + '@esbuild/linux-ppc64@0.19.12': + resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] @@ -1520,8 +1378,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.19.11': - resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==} + '@esbuild/linux-riscv64@0.19.12': + resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] @@ -1538,8 +1396,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.19.11': - resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==} + '@esbuild/linux-s390x@0.19.12': + resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} engines: {node: '>=12'} cpu: [s390x] os: [linux] @@ -1556,8 +1414,8 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.19.11': - resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==} + '@esbuild/linux-x64@0.19.12': + resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} engines: {node: '>=12'} cpu: [x64] os: [linux] @@ -1580,8 +1438,8 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.19.11': - resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==} + '@esbuild/netbsd-x64@0.19.12': + resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] @@ -1604,8 +1462,8 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.19.11': - resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==} + '@esbuild/openbsd-x64@0.19.12': + resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] @@ -1622,8 +1480,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.19.11': - resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==} + '@esbuild/sunos-x64@0.19.12': + resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} engines: {node: '>=12'} cpu: [x64] os: [sunos] @@ -1640,8 +1498,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.19.11': - resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==} + '@esbuild/win32-arm64@0.19.12': + resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] @@ -1658,8 +1516,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.19.11': - resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==} + '@esbuild/win32-ia32@0.19.12': + resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} engines: {node: '>=12'} cpu: [ia32] os: [win32] @@ -1676,8 +1534,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.19.11': - resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==} + '@esbuild/win32-x64@0.19.12': + resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} engines: {node: '>=12'} cpu: [x64] os: [win32] @@ -1688,51 +1546,51 @@ packages: cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.4.0': - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + '@eslint-community/eslint-utils@4.4.1': + resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.8.0': - resolution: {integrity: sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==} + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/eslintrc@2.1.2': - resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==} + '@eslint/eslintrc@2.1.4': + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/js@8.50.0': - resolution: {integrity: sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==} + '@eslint/js@8.57.1': + resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} '@fal-works/esbuild-plugin-global-externals@2.1.2': resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==} - '@fastify/busboy@2.0.0': - resolution: {integrity: sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==} + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@floating-ui/core@1.5.0': - resolution: {integrity: sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==} + '@floating-ui/core@1.6.9': + resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==} - '@floating-ui/dom@1.5.3': - resolution: {integrity: sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==} + '@floating-ui/dom@1.6.13': + resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==} - '@floating-ui/react-dom@2.0.9': - resolution: {integrity: sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ==} + '@floating-ui/react-dom@2.1.2': + resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==} peerDependencies: react: ^18.2.0 react-dom: '>=16.8.0' - '@floating-ui/react@0.26.1': - resolution: {integrity: sha512-5gyJIJ2tZOPMgmZ/vEcVhdmQiy75b7LPO71sYIiDsxGcZ4hxLuygQWCuT0YXHqppt//Eese+L6t5KnX/gZ3tVA==} + '@floating-ui/react@0.26.28': + resolution: {integrity: sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==} peerDependencies: react: ^18.2.0 react-dom: '>=16.8.0' - '@floating-ui/utils@0.1.6': - resolution: {integrity: sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==} + '@floating-ui/utils@0.2.9': + resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} '@gar/promisify@1.1.3': resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} @@ -1743,8 +1601,8 @@ packages: '@hapi/topo@5.1.0': resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} - '@humanwhocodes/config-array@0.11.11': - resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==} + '@humanwhocodes/config-array@0.13.0': + resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} deprecated: Use @eslint/config-array instead @@ -1752,8 +1610,8 @@ packages: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/object-schema@1.2.1': - resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + '@humanwhocodes/object-schema@2.0.3': + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead '@img/sharp-darwin-arm64@0.33.5': @@ -2050,32 +1908,29 @@ packages: '@jimp/utils@0.10.3': resolution: {integrity: sha512-VcSlQhkil4ReYmg1KkN+WqHyYfZ2XfZxDsKAHSfST1GEz/RQHxKZbX+KhFKtKflnL0F4e6DlNQj3vznMNXCR2w==} - '@joshwooding/vite-plugin-react-docgen-typescript@0.2.1': - resolution: {integrity: sha512-ou4ZJSXMMWHqGS4g8uNRbC5TiTWxAgQZiVucoUrOCWuPrTbkpJbmVyIi9jU72SBry7gQtuMEDp4YR8EEXAg7VQ==} + '@joshwooding/vite-plugin-react-docgen-typescript@0.3.0': + resolution: {integrity: sha512-2D6y7fNvFmsLmRt6UCOFJPvFoPMJGT0Uh1Wg0RaigUp7kdQPs6yYn8Dmx6GZkOH/NW0yMTwRz/p0SRMMRo50vA==} peerDependencies: typescript: '>= 4.3.x' - vite: ^3.0.0 || ^4.0.0 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 peerDependenciesMeta: typescript: optional: true - '@jridgewell/gen-mapping@0.3.3': - resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} - '@jridgewell/resolve-uri@3.1.1': - resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/set-array@1.1.2': - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - '@jridgewell/source-map@0.3.5': - resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} - - '@jridgewell/sourcemap-codec@1.4.15': - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + '@jridgewell/source-map@0.3.6': + resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} @@ -2083,12 +1938,33 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@jspm/core@2.0.1': - resolution: {integrity: sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw==} + '@jsonjoy.com/base64@1.1.2': + resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@1.2.0': + resolution: {integrity: sha512-io1zEbbYcElht3tdlqEOFxZ0dMTYrHz9iMf0gqn1pPjZFTCgM5R4R5IMA20Chb2UPYYsxjzs8CgZ7Nb5n2K2rA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@1.5.0': + resolution: {integrity: sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jspm/core@2.1.0': + resolution: {integrity: sha512-3sRl+pkyFY/kLmHl0cgHiFp2xEqErA8N3ECjMs7serSUBmoJ70lBa0PG5t0IM6WJgdZNyyI0R8YFfi5wM8+mzg==} '@juggle/resize-observer@3.3.1': resolution: {integrity: sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw==} + '@juggle/resize-observer@3.4.0': + resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==} + '@mapbox/node-pre-gyp@1.0.11': resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} hasBin: true @@ -2098,17 +1974,33 @@ packages: peerDependencies: react: ^18.2.0 - '@module-federation/runtime-tools@0.2.3': - resolution: {integrity: sha512-capN8CVTCEqNAjnl102girrkevczoQfnQYyiYC4WuyKsg7+LUqfirIe1Eiyv6VSE2UgvOTZDnqvervA6rBOlmg==} + '@module-federation/error-codes@0.11.2': + resolution: {integrity: sha512-ik1Qnn0I+WyEdprTck9WGlH41vGsVdUg8cfO+ZM02qOb2cZm5Vu3SlxGAobj6g7uAj0g8yINnd7h7Dci40BxQA==} - '@module-federation/runtime@0.2.3': - resolution: {integrity: sha512-N+ZxBUb1mkmfO9XT1BwgYQgShtUTlijHbukqQ4afFka5lRAT+ayC7RKfHJLz0HbuexKPCmPBDfdmCnErR5WyTQ==} + '@module-federation/runtime-core@0.11.2': + resolution: {integrity: sha512-dia5kKybi6MFU0s5PgglJwN27k7n9Sf69Cy5xZ4BWaP0qlaXTsxHKO0PECHNt2Pt8jDdyU29sQ4DwAQfxpnXJQ==} - '@module-federation/sdk@0.2.3': - resolution: {integrity: sha512-W9zrPchLocyCBc/B8CW21akcfJXLl++9xBe1L1EtgxZGfj/xwHt0GcBWE/y+QGvYTL2a1iZjwscbftbUhxgxXg==} + '@module-federation/runtime-tools@0.11.2': + resolution: {integrity: sha512-4MJTGAxVq6vxQRkTtTlH7Mm9AVqgn0X9kdu+7RsL7T/qU+jeYsbrntN2CWG3GVVA8r5JddXyTI1iJ0VXQZLV1w==} - '@module-federation/webpack-bundler-runtime@0.2.3': - resolution: {integrity: sha512-L/jt2uJ+8dwYiyn9GxryzDR6tr/Wk8rpgvelM2EBeLIhu7YxCHSmSjQYhw3BTux9zZIr47d1K9fGjBFsVRd/SQ==} + '@module-federation/runtime@0.11.2': + resolution: {integrity: sha512-Ya9u/L6z2LvhgpqxuKCB7LcigIIRf1BbaxAZIH7mzbq/A7rZtTP7v+73E433jvgiAlbAfPSZkeoYGele6hfRwA==} + + '@module-federation/sdk@0.11.2': + resolution: {integrity: sha512-SBFe5xOamluT900J4AGBx+2/kCH/JbfqXoUwPSAC6PRzb8Y7LB0posnOGzmqYsLZXT37vp3d6AmJDsVoajDqxw==} + + '@module-federation/webpack-bundler-runtime@0.11.2': + resolution: {integrity: sha512-WdwIE6QF+MKs/PdVu0cKPETF743JB9PZ62/qf7Uo3gU4fjsUMc37RnbJZ/qB60EaHHfjwp1v6NnhZw1r4eVsnw==} + + '@monaco-editor/loader@1.5.0': + resolution: {integrity: sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==} + + '@monaco-editor/react@4.7.0': + resolution: {integrity: sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==} + peerDependencies: + monaco-editor: '>= 0.25.0 < 1' + react: ^18.2.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 '@msgpack/msgpack@2.8.0': resolution: {integrity: sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ==} @@ -2138,20 +2030,20 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} deprecated: This functionality has been moved to @npmcli/fs - '@nxg-org/mineflayer-auto-jump@0.7.12': - resolution: {integrity: sha512-F5vX/lerlWx/5HVlkDNbvrtQ19PL6iG8i4ItPTIRtjGiFzusDefP7DI226zSFR8Wlaw45qHv0jn814p/4/qVdQ==} + '@nxg-org/mineflayer-auto-jump@0.7.18': + resolution: {integrity: sha512-O/nRCyWrRwFpcCXXSJhmt844c4a8KhkK4OJPAOKSc63tExIIQU/sipHgjgpy0B+gVDjSmLMPYXe71CN0W327Wg==} - '@nxg-org/mineflayer-physics-util@1.5.8': - resolution: {integrity: sha512-KmCkAqpUo8BbuRdIBs6+V2hWHehz++PRz3lRwIsb47CuG0u4sgLYh37RY3ifAznC6uWvmPK+q3B4ZXwJzPy1MQ==} + '@nxg-org/mineflayer-physics-util@1.8.10': + resolution: {integrity: sha512-JGIJEPauVmqoBFQ0I8ZtbaYo3mKn2N00srnDrWkCEt1qozyZWie4sYR0khjjwYubFCljMoWtoEA0+DLsHZLNFg==} - '@nxg-org/mineflayer-tracker@1.2.1': - resolution: {integrity: sha512-SI1ffF8zvg3/ZNE021Ja2W0FZPN+WbQDZf8yFqOcXtPRXAtM9W6HvoACdzXep8BZid7WYgYLIgjKpB+9RqvCNQ==} + '@nxg-org/mineflayer-tracker@1.3.0': + resolution: {integrity: sha512-HINrv51l2aZ/lDrcL77gSWDvf3Z3trd6kdiifXitCMDNdBT0FpWnXq9bi5Fr7yPpFGQ3fqGUIq5DQYYY84E9IA==} - '@nxg-org/mineflayer-trajectories@1.1.1': - resolution: {integrity: sha512-X103KXlX8+L3uMeK4jQxMUdTizv01sQRSfBizAF/iOAdfQZehRLXr3CYKeJzfwPYGLN0X0JCl++cMEcZVn4vbg==} + '@nxg-org/mineflayer-trajectories@1.2.0': + resolution: {integrity: sha512-yTDHn96fyWLKwdHdOGIrnt8nss4SJmxXwJn101o7aNI4sgdnUmwaX4FoNbmrEa9eZn6IwxaXIxDf+fJmKj9RIw==} - '@nxg-org/mineflayer-util-plugin@1.8.3': - resolution: {integrity: sha512-YlIbzCDs9822xuvmYlD0vXZz0iye9buqp9NK4nNn15gYybdqBtC/YxK6BLqXtwNohZCKoZdKgei7Xd5Bt2/rUg==} + '@nxg-org/mineflayer-util-plugin@1.8.4': + resolution: {integrity: sha512-hPaCZxU0Aq+gUSi/l6x7n32hUG6bnDugAMoQXD2dFE/gyNkmRSpmgH5+Y6G41w3H8P3Nl++upGCOlaxvZ7RuoA==} '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} @@ -2166,6 +2058,9 @@ packages: '@radix-ui/primitive@1.0.1': resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==} + '@radix-ui/primitive@1.1.1': + resolution: {integrity: sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==} + '@radix-ui/react-arrow@1.0.3': resolution: {integrity: sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==} peerDependencies: @@ -2192,6 +2087,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-collection@1.1.2': + resolution: {integrity: sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^18.2.0 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-compose-refs@1.0.1': resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} peerDependencies: @@ -2201,6 +2109,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-compose-refs@1.1.1': + resolution: {integrity: sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==} + peerDependencies: + '@types/react': '*' + react: ^18.2.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-context@1.0.1': resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==} peerDependencies: @@ -2210,6 +2127,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-context@1.1.1': + resolution: {integrity: sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==} + peerDependencies: + '@types/react': '*' + react: ^18.2.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-direction@1.0.1': resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==} peerDependencies: @@ -2219,6 +2145,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-direction@1.1.0': + resolution: {integrity: sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==} + peerDependencies: + '@types/react': '*' + react: ^18.2.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-dismissable-layer@1.0.4': resolution: {integrity: sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==} peerDependencies: @@ -2263,6 +2198,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-id@1.1.0': + resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==} + peerDependencies: + '@types/react': '*' + react: ^18.2.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-popper@1.1.2': resolution: {integrity: sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg==} peerDependencies: @@ -2302,13 +2246,26 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-roving-focus@1.0.4': - resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==} + '@radix-ui/react-primitive@2.0.2': + resolution: {integrity: sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' react: ^18.2.0 - react-dom: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-roving-focus@1.1.2': + resolution: {integrity: sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^18.2.0 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true @@ -2328,13 +2285,13 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-separator@1.0.3': - resolution: {integrity: sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==} + '@radix-ui/react-separator@1.1.2': + resolution: {integrity: sha512-oZfHcaAp2Y6KFBX6I5P1u7CQoy4lheCGiYj+pGFrHy8E/VNRb5E39TkTr3JrV520csPBTZjkuKFdEsjS5EUNKQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' react: ^18.2.0 - react-dom: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true @@ -2350,39 +2307,48 @@ packages: '@types/react': optional: true - '@radix-ui/react-toggle-group@1.0.4': - resolution: {integrity: sha512-Uaj/M/cMyiyT9Bx6fOZO0SAG4Cls0GptBWiBmBxofmDbNVnYYoyRWj/2M/6VCi/7qcXFWnHhRUfdfZFvvkuu8A==} + '@radix-ui/react-slot@1.1.2': + resolution: {integrity: sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==} + peerDependencies: + '@types/react': '*' + react: ^18.2.0 + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-toggle-group@1.1.2': + resolution: {integrity: sha512-JBm6s6aVG/nwuY5eadhU2zDi/IwYS0sDM5ZWb4nymv/hn3hZdkw+gENn0LP4iY1yCd7+bgJaCwueMYJIU3vk4A==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' react: ^18.2.0 - react-dom: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true '@types/react-dom': optional: true - '@radix-ui/react-toggle@1.0.3': - resolution: {integrity: sha512-Pkqg3+Bc98ftZGsl60CLANXQBBQ4W3mTFS9EJvNxKMZ7magklKV69/id1mlAlOFDDfHvlCms0fx8fA4CMKDJHg==} + '@radix-ui/react-toggle@1.1.2': + resolution: {integrity: sha512-lntKchNWx3aCHuWKiDY+8WudiegQvBpDRAYL8dKLRvKEH8VOpl0XX6SSU/bUBqIRJbcTy4+MW06Wv8vgp10rzQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' react: ^18.2.0 - react-dom: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true '@types/react-dom': optional: true - '@radix-ui/react-toolbar@1.0.4': - resolution: {integrity: sha512-tBgmM/O7a07xbaEkYJWYTXkIdU/1pW4/KZORR43toC/4XWyBCURK0ei9kMUdp+gTPPKBgYLxXmRSH1EVcIDp8Q==} + '@radix-ui/react-toolbar@1.1.2': + resolution: {integrity: sha512-wT20eQ7ScFk+kBMDmHp+lMk18cgxhu35b2Bn5deUcPxiVwfn5vuZgi7NGcHu8ocdkinahmp4FaSZysKDyRVPWQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' react: ^18.2.0 - react-dom: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true @@ -2398,6 +2364,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-callback-ref@1.1.0': + resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==} + peerDependencies: + '@types/react': '*' + react: ^18.2.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-controllable-state@1.0.1': resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==} peerDependencies: @@ -2407,6 +2382,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-controllable-state@1.1.0': + resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==} + peerDependencies: + '@types/react': '*' + react: ^18.2.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-escape-keydown@1.0.3': resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==} peerDependencies: @@ -2425,6 +2409,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-layout-effect@1.1.0': + resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==} + peerDependencies: + '@types/react': '*' + react: ^18.2.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-previous@1.0.1': resolution: {integrity: sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==} peerDependencies: @@ -2485,25 +2478,37 @@ packages: '@types/babel__core': optional: true - '@rollup/plugin-node-resolve@11.2.1': - resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==} - engines: {node: '>= 10.0.0'} + '@rollup/plugin-node-resolve@15.3.1': + resolution: {integrity: sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==} + engines: {node: '>=14.0.0'} peerDependencies: - rollup: ^1.20.0||^2.0.0 + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true '@rollup/plugin-replace@2.4.2': resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==} peerDependencies: rollup: ^1.20.0 || ^2.0.0 + '@rollup/plugin-terser@0.4.4': + resolution: {integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/pluginutils@3.1.0': resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} engines: {node: '>= 8.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0 - '@rollup/pluginutils@5.0.5': - resolution: {integrity: sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q==} + '@rollup/pluginutils@5.1.4': + resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 @@ -2511,203 +2516,210 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.34.8': - resolution: {integrity: sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==} + '@rollup/rollup-android-arm-eabi@4.34.9': + resolution: {integrity: sha512-qZdlImWXur0CFakn2BJ2znJOdqYZKiedEPEVNTBrpfPjc/YuTGcaYZcdmNFTkUj3DU0ZM/AElcM8Ybww3xVLzA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.34.8': - resolution: {integrity: sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==} + '@rollup/rollup-android-arm64@4.34.9': + resolution: {integrity: sha512-4KW7P53h6HtJf5Y608T1ISKvNIYLWRKMvfnG0c44M6In4DQVU58HZFEVhWINDZKp7FZps98G3gxwC1sb0wXUUg==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.34.8': - resolution: {integrity: sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==} + '@rollup/rollup-darwin-arm64@4.34.9': + resolution: {integrity: sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.34.8': - resolution: {integrity: sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==} + '@rollup/rollup-darwin-x64@4.34.9': + resolution: {integrity: sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.34.8': - resolution: {integrity: sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==} + '@rollup/rollup-freebsd-arm64@4.34.9': + resolution: {integrity: sha512-2lzjQPJbN5UnHm7bHIUKFMulGTQwdvOkouJDpPysJS+QFBGDJqcfh+CxxtG23Ik/9tEvnebQiylYoazFMAgrYw==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.34.8': - resolution: {integrity: sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==} + '@rollup/rollup-freebsd-x64@4.34.9': + resolution: {integrity: sha512-SLl0hi2Ah2H7xQYd6Qaiu01kFPzQ+hqvdYSoOtHYg/zCIFs6t8sV95kaoqjzjFwuYQLtOI0RZre/Ke0nPaQV+g==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.34.8': - resolution: {integrity: sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==} + '@rollup/rollup-linux-arm-gnueabihf@4.34.9': + resolution: {integrity: sha512-88I+D3TeKItrw+Y/2ud4Tw0+3CxQ2kLgu3QvrogZ0OfkmX/DEppehus7L3TS2Q4lpB+hYyxhkQiYPJ6Mf5/dPg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.34.8': - resolution: {integrity: sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==} + '@rollup/rollup-linux-arm-musleabihf@4.34.9': + resolution: {integrity: sha512-3qyfWljSFHi9zH0KgtEPG4cBXHDFhwD8kwg6xLfHQ0IWuH9crp005GfoUUh/6w9/FWGBwEHg3lxK1iHRN1MFlA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.34.8': - resolution: {integrity: sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==} + '@rollup/rollup-linux-arm64-gnu@4.34.9': + resolution: {integrity: sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.34.8': - resolution: {integrity: sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==} + '@rollup/rollup-linux-arm64-musl@4.34.9': + resolution: {integrity: sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.34.8': - resolution: {integrity: sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==} + '@rollup/rollup-linux-loongarch64-gnu@4.34.9': + resolution: {integrity: sha512-dRAgTfDsn0TE0HI6cmo13hemKpVHOEyeciGtvlBTkpx/F65kTvShtY/EVyZEIfxFkV5JJTuQ9tP5HGBS0hfxIg==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': - resolution: {integrity: sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==} + '@rollup/rollup-linux-powerpc64le-gnu@4.34.9': + resolution: {integrity: sha512-PHcNOAEhkoMSQtMf+rJofwisZqaU8iQ8EaSps58f5HYll9EAY5BSErCZ8qBDMVbq88h4UxaNPlbrKqfWP8RfJA==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.34.8': - resolution: {integrity: sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==} + '@rollup/rollup-linux-riscv64-gnu@4.34.9': + resolution: {integrity: sha512-Z2i0Uy5G96KBYKjeQFKbbsB54xFOL5/y1P5wNBsbXB8yE+At3oh0DVMjQVzCJRJSfReiB2tX8T6HUFZ2k8iaKg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.34.8': - resolution: {integrity: sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==} + '@rollup/rollup-linux-s390x-gnu@4.34.9': + resolution: {integrity: sha512-U+5SwTMoeYXoDzJX5dhDTxRltSrIax8KWwfaaYcynuJw8mT33W7oOgz0a+AaXtGuvhzTr2tVKh5UO8GVANTxyQ==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.34.8': - resolution: {integrity: sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==} + '@rollup/rollup-linux-x64-gnu@4.34.9': + resolution: {integrity: sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.34.8': - resolution: {integrity: sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==} + '@rollup/rollup-linux-x64-musl@4.34.9': + resolution: {integrity: sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.34.8': - resolution: {integrity: sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==} + '@rollup/rollup-win32-arm64-msvc@4.34.9': + resolution: {integrity: sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.34.8': - resolution: {integrity: sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==} + '@rollup/rollup-win32-ia32-msvc@4.34.9': + resolution: {integrity: sha512-KB48mPtaoHy1AwDNkAJfHXvHp24H0ryZog28spEs0V48l3H1fr4i37tiyHsgKZJnCmvxsbATdZGBpbmxTE3a9w==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.34.8': - resolution: {integrity: sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==} + '@rollup/rollup-win32-x64-msvc@4.34.9': + resolution: {integrity: sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==} cpu: [x64] os: [win32] - '@rsbuild/core@1.0.1-beta.9': - resolution: {integrity: sha512-F9npL47TFmNVhPBqoE6jBvKGxXEKNszBA7skhbi3opskmX7Ako9vfXvtgi2W2jQjq837/WUL8gG/ua9zRqKFEQ==} + '@rsbuild/core@1.3.5': + resolution: {integrity: sha512-Fn6nJ4YvLO2UtFcoSPxgJoiUdS0Iix7X1BsyZ+DCj3SGpVCxp3Td9x58F5uhcRraMZFPB91wvcS/OabYwT3N2w==} engines: {node: '>=16.7.0'} hasBin: true - '@rsbuild/plugin-node-polyfill@1.0.3': - resolution: {integrity: sha512-AoPIOV1pyInIz08K1ECwUjFemLLSa5OUq8sfJN1ShXrGR2qc14b1wzwZKwF4vgKnBromqfMLagVbk6KT/nLIvQ==} + '@rsbuild/plugin-node-polyfill@1.3.0': + resolution: {integrity: sha512-KvckyUg9wq3F1Iv/y4+mlcnO/E7vDklvMY7kF6CxnUYImroQVw/EDS0zDezkPvcm7aKTH5b0Jaa0iIcTNFzhVw==} peerDependencies: '@rsbuild/core': 1.x peerDependenciesMeta: '@rsbuild/core': optional: true - '@rsbuild/plugin-react@1.0.1-beta.9': - resolution: {integrity: sha512-MX5bWSEW5Nr8jhNAVxWlNVnraJxtOYTEZna5znaypLv7m4V8w0go1Nzb210ueRSbFCEYvP+zJZzkq33m+3TWXQ==} + '@rsbuild/plugin-react@1.2.0': + resolution: {integrity: sha512-TXd0cvcLPF7OrO215vlGSyRXD6Fc3KQWhFuXFKOtRYp+C1Vc9oeW0GopUIStv2pI2/xtv2XX8GOAdJsnsc6lkA==} peerDependencies: - '@rsbuild/core': ^1.0.1-beta.9 + '@rsbuild/core': 1.x - '@rsbuild/plugin-type-check@1.0.1-beta.9': - resolution: {integrity: sha512-nvH1zoxeWE1S+pg4UQ7PNsBjfa+cOYyApn+2qcmVzgTMbglfyqalPtaUSa8zRFmToooJNK3Ko//6w1zvSbOi8w==} - peerDependencies: - '@rsbuild/core': ^1.0.1-beta.9 - - '@rsbuild/plugin-typed-css-modules@1.0.1': - resolution: {integrity: sha512-biCSm7+vOgqrqXdAjxnjGNA7KPUfBadfndCeINJ2HApWfuQ2TLWuI5R+MzGvslis13SCKQ55K7NMAkvRhXyi8w==} + '@rsbuild/plugin-type-check@1.2.1': + resolution: {integrity: sha512-PtbjeMqDQy8IiPDTuaj8ZmvR42b0AsRq6RUF6wxa8dDsOzD0Dl1GcvemVGCto+/Dh8frLUmnlWF+T8riBw5rtA==} peerDependencies: '@rsbuild/core': 1.x peerDependenciesMeta: '@rsbuild/core': optional: true - '@rspack/binding-darwin-arm64@1.0.0-beta.1': - resolution: {integrity: sha512-KyC+xEMy9Y5JivO2e5rlKFGT74uwDhbwJjSCR5KOLQtZjDWeLwhf7aZhkoSQJUEsK5tAuuUoTP02RJFzK5llpA==} + '@rsbuild/plugin-typed-css-modules@1.0.2': + resolution: {integrity: sha512-QX376pBXWeBrZBvYLP2HGGrHiWA5O0SDHwRoBNto5BqYDXhi6y+Eol2Hb/cY+h2ARKZVanMfUiJRABULOJ/FCQ==} + peerDependencies: + '@rsbuild/core': 1.x || ^1.0.1-beta.0 + peerDependenciesMeta: + '@rsbuild/core': + optional: true + + '@rspack/binding-darwin-arm64@1.3.3': + resolution: {integrity: sha512-vbzEdpRCZl5+HXWsVjzSDqB9ZVIlqldV+udHp4YDD8qiwdQznVaBZke0eMzZ7kaInqRPsZ+UHQuVk6JaH/JkMQ==} cpu: [arm64] os: [darwin] - '@rspack/binding-darwin-x64@1.0.0-beta.1': - resolution: {integrity: sha512-Onc35+qQ7YwE6+aB66l/ZnRFXfhA1hXH5aNnNJmIFEAmqzkvOGREkWy3CdfsklF/l/xt33iUM7ccnNgdpk7yKw==} + '@rspack/binding-darwin-x64@1.3.3': + resolution: {integrity: sha512-OXtY2s4nlYtUXkeJt8TQKKNIcN7PI8yDq0nqI75OfJoS4u1ZmRXJ8IMeSALLo8I+xD2RAF79tf7yhM/Y/AaiKQ==} cpu: [x64] os: [darwin] - '@rspack/binding-linux-arm64-gnu@1.0.0-beta.1': - resolution: {integrity: sha512-NlXtRlKcoBzB6EQEiXegW0nMToEPXD+hExaev0j1+uzsFrMJ0uIY49k6+DapwWZ8A2jUdvH7xdWT+eAXD3l/EA==} + '@rspack/binding-linux-arm64-gnu@1.3.3': + resolution: {integrity: sha512-Lluq3RLYzyCMdXr/HyALKEPGsr+196x8Ccuy5AmIRosOdWuwtSiomSRH1Ka8REUFNHfYy5y9SzfmIZo/E0QEmg==} cpu: [arm64] os: [linux] - '@rspack/binding-linux-arm64-musl@1.0.0-beta.1': - resolution: {integrity: sha512-fPS8ukoPgmBSUX4dt74flObcbYzO3uaP1bk4k/98Gr3Bw0ACDZ6h5nqlxoXoeVzhNcNMBcfv45un8H3i411AyA==} + '@rspack/binding-linux-arm64-musl@1.3.3': + resolution: {integrity: sha512-PIsicXWjOqzmoOutUqxpMNkCoKo+8/wxDyKxHFeu+5WIAxVFphe2d3H5qvEjc2MasWSdRmAVn9XiuIj2LIXFzA==} cpu: [arm64] os: [linux] - '@rspack/binding-linux-x64-gnu@1.0.0-beta.1': - resolution: {integrity: sha512-9U78G7BtevPZ9GEJ2AhGHt03n+GEhKVvEZ/tgu+flFV0tYGjq75QQX345x4m+uercTqzRBTyuWITweIzppeWuQ==} + '@rspack/binding-linux-x64-gnu@1.3.3': + resolution: {integrity: sha512-BtksK73ZFdny2T/wU1x0kxBF4ruYUUArZDyeGfpO+vd/1nNYqzzdhGvOksKmtdvsO38ETr2gZ9+XZyr1vpy9uQ==} cpu: [x64] os: [linux] - '@rspack/binding-linux-x64-musl@1.0.0-beta.1': - resolution: {integrity: sha512-qqNPseWAOKmV33YL7tihY0N9xwY+N1G9na6lT7iqZnsrzPkIZmESI9Z24fXVJqLC/UhfxAth4RKhVBeKTsPk1w==} + '@rspack/binding-linux-x64-musl@1.3.3': + resolution: {integrity: sha512-jx86CxkTmyBz/eHDqZp1mCqBwY+UTEtaPlPoWFyGkJUR5ey6nQnxS+fhG34Rqz63chW+q/afwpGNGyALYdgc8g==} cpu: [x64] os: [linux] - '@rspack/binding-win32-arm64-msvc@1.0.0-beta.1': - resolution: {integrity: sha512-VeBGYItHWqImYt23rBChXrk1o7fQxwTv6BEhtMpTnMJV10O6+Db9NckPEplcKLmNKAAA5anxH40GcpPc4nff8A==} + '@rspack/binding-win32-arm64-msvc@1.3.3': + resolution: {integrity: sha512-uXAdDzajFToVrH3fCNVDP/uKQ9i5FQjJc2aYxsnhS9Su/CZB+UQsOecbq6MnIN2s0B9GBKBG8QdQEtS3RtC6Hg==} cpu: [arm64] os: [win32] - '@rspack/binding-win32-ia32-msvc@1.0.0-beta.1': - resolution: {integrity: sha512-ZxLQ1zOpyCKefsKvDYGGIHM019avNPfesJKdw7wYqeC+EIvWZfs86lnhlSL5PlZzV5AfFZQyQJFRjAv4JPpe4Q==} + '@rspack/binding-win32-ia32-msvc@1.3.3': + resolution: {integrity: sha512-VBE6XsJ3IiAlozAywAIxAZ1Aqc2QVnEwBo0gP9998KkwL7wxB6Bg/OJnPbH3Q0ZaNWAQViC99rPC+5hSIdeSxw==} cpu: [ia32] os: [win32] - '@rspack/binding-win32-x64-msvc@1.0.0-beta.1': - resolution: {integrity: sha512-tMrjEA/2SGMVLbh/zOQoZrr1Xx+oI6RZnkXH6l95ON4yZiD+8wM84w8Ernj1N8KwclTuvBzxM0r3DLHTNZcDhw==} + '@rspack/binding-win32-x64-msvc@1.3.3': + resolution: {integrity: sha512-rOsNz4/DFgSENjEh0t9kFn89feuXK14/9wbmmFlT8VMpYOCcj4tKcAHjWg+Nzzj4FL+NSOC/81SrUF9J+C2R7w==} cpu: [x64] os: [win32] - '@rspack/binding@1.0.0-beta.1': - resolution: {integrity: sha512-p7XBvk1+fAmvrlmdeRr5J9wdXx5idVZjHFJu/3qPHWf5mHKRw2/tQVbqzExj+B1nwR6HXFgxCiiddaWauMS/YQ==} + '@rspack/binding@1.3.3': + resolution: {integrity: sha512-zdwJ801tyC8k+Gu5RjNoc7bEtX0MgJzzVv9qpaMwcAUfUfwZgCzXPTqcGMDoNI+Z47Fw59/2fKCmgZhZn60AgA==} - '@rspack/core@1.0.0-beta.1': - resolution: {integrity: sha512-aUWR/FUUw7x0L/qEZ0qrXC+7YYOL0Ezwd95TqDIDIYkSODJ6ZPt3a8poPwWc7IBdONgb8sGDPTzAXXEjcsBMwQ==} + '@rspack/core@1.3.3': + resolution: {integrity: sha512-+mXVlFcYr0tWezZfJ/gR0fj8njRc7pzEMtTFa2NO5cfsNAKPF/SXm4rb55kfa63r0b3U3N7f2nKrJG9wyG7zMQ==} engines: {node: '>=16.0.0'} peerDependencies: + '@rspack/tracing': ^1.x '@swc/helpers': '>=0.5.1' peerDependenciesMeta: + '@rspack/tracing': + optional: true '@swc/helpers': optional: true - '@rspack/lite-tapable@1.0.0-beta.1': - resolution: {integrity: sha512-r4xtbJp6QhW6A1twkgTP0UQkPC9cOT3sFjjjlx22j/q669HJRz+CVTlVcNxPomK7Q3Kg6dVsyv16MjGRl/fl5g==} + '@rspack/lite-tapable@1.0.1': + resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==} engines: {node: '>=16.0.0'} - '@rspack/plugin-react-refresh@1.0.0-beta.1': - resolution: {integrity: sha512-TLv3aB0NJtGPY38cMktnEkJ64RGLCed7MxQhc7f6V5FzOc3cZldTYSMThTZw1R/APc7GIHC4A26Ny5IogYlzvw==} + '@rspack/plugin-react-refresh@1.2.0': + resolution: {integrity: sha512-DTsbtggCfsiXE5QQtYMS8rKfEF8GIjwPDbgIT6Kg8BlAjpJY4jT5IisyhfIi7YOT3d5RIvu60iFB6Kr9sSMsnA==} peerDependencies: react-refresh: '>=0.10.0 <1.0.0' + webpack-hot-middleware: 2.x peerDependenciesMeta: - react-refresh: + webpack-hot-middleware: optional: true - '@rushstack/eslint-patch@1.4.0': - resolution: {integrity: sha512-cEjvTPU32OM9lUFegJagO0mRnIn+rbqrG89vV8/xLnLFX0DoR0r1oy5IlTga71Q7uT3Qus7qm7wgeiMT/+Irlg==} + '@rushstack/eslint-patch@1.10.5': + resolution: {integrity: sha512-kkKUDVlII2DQiKy7UstOR1ErJP8kUKAQ4oa+SQtM0K+lPdmmjj0YnnxBgtTVYH7mUKtbsxeFC9y0AmK7Yb78/A==} '@sideway/address@4.1.5': resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} @@ -2721,127 +2733,68 @@ packages: '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - '@socket.io/component-emitter@3.1.0': - resolution: {integrity: sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==} + '@socket.io/component-emitter@3.1.2': + resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} - '@storybook/addon-actions@7.4.6': - resolution: {integrity: sha512-SsqZr3js5NinKPnC8AeNI7Ij+Q6fIl9tRdRmSulEgjksjOg7E5S1/Wsn5Bb2CCgj7MaX6VxGyC7s3XskQtDiIQ==} + '@storybook/addon-actions@7.6.20': + resolution: {integrity: sha512-c/GkEQ2U9BC/Ew/IMdh+zvsh4N6y6n7Zsn2GIhJgcu9YEAa5aF2a9/pNgEGBMOABH959XE8DAOMERw/5qiLR8g==} + + '@storybook/addon-backgrounds@7.6.20': + resolution: {integrity: sha512-a7ukoaXT42vpKsMxkseIeO3GqL0Zst2IxpCTq5dSlXiADrcemSF/8/oNpNW9C4L6F1Zdt+WDtECXslEm017FvQ==} + + '@storybook/addon-controls@7.6.20': + resolution: {integrity: sha512-06ZT5Ce1sZW52B0s6XuokwjkKO9GqHlTUHvuflvd8wifxKlCmRvNUxjBvwh+ccGJ49ZS73LbMSLFgtmBEkCxbg==} + + '@storybook/addon-docs@7.6.20': + resolution: {integrity: sha512-XNfYRhbxH5JP7B9Lh4W06PtMefNXkfpV39Gaoih5HuqngV3eoSL4RikZYOMkvxRGQ738xc6axySU3+JKcP1OZg==} peerDependencies: react: ^18.2.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + + '@storybook/addon-essentials@7.6.20': + resolution: {integrity: sha512-hCupSOiJDeOxJKZSgH0x5Mb2Xqii6mps21g5hpxac1XjhQtmGflShxi/xOHhK3sNqrbgTSbScfpUP3hUlZO/2Q==} + peerDependencies: + react: ^18.2.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + + '@storybook/addon-highlight@7.6.20': + resolution: {integrity: sha512-7/x7xFdFyqCki5Dm3uBePldUs9l98/WxJ7rTHQuYqlX7kASwyN5iXPzuhmMRUhlMm/6G6xXtLabIpzwf1sFurA==} + + '@storybook/addon-links@7.6.20': + resolution: {integrity: sha512-iomSnBD90CA4MinesYiJkFX2kb3P1Psd/a1Y0ghlFEsHD4uMId9iT6sx2s16DYMja0SlPkrbWYnGukqaCjZpRw==} + peerDependencies: + react: ^18.2.0 peerDependenciesMeta: react: optional: true - react-dom: - optional: true - '@storybook/addon-backgrounds@7.4.6': - resolution: {integrity: sha512-+LHTZB/ZYMAzkyD5ZxSriBsqmsrvIaW/Nnd/BeuXGbkrVKKqM0qAKiFZAfjc2WchA1piVNy0/1Rsf+kuYCEiJw==} - peerDependencies: - react: ^18.2.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true + '@storybook/addon-measure@7.6.20': + resolution: {integrity: sha512-i2Iq08bGfI7gZbG6Lb8uF/L287tnaGUR+2KFEmdBjH6+kgjWLiwfpanoPQpy4drm23ar0gUjX+L3Ri03VI5/Xg==} - '@storybook/addon-controls@7.4.6': - resolution: {integrity: sha512-4lq3sycEUIsK8SUWDYc60QgF4vV9FZZ3lDr6M7j2W9bOnvGw49d2fbdlnq+bX1ZprZZ9VgglQpBAorQB3BXZRw==} - peerDependencies: - react: ^18.2.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true + '@storybook/addon-outline@7.6.20': + resolution: {integrity: sha512-TdsIQZf/TcDsGoZ1XpO+9nBc4OKqcMIzY4SrI8Wj9dzyFLQ37s08gnZr9POci8AEv62NTUOVavsxcafllkzqDQ==} - '@storybook/addon-docs@7.4.6': - resolution: {integrity: sha512-dLaub+XWFq4hChw+xfuF9yYg0Txp77FUawKoAigccfjWXx+OOhRV3XTuAcknpXkYq94GWynHgUFXosXT9kbDNA==} + '@storybook/addon-toolbars@7.6.20': + resolution: {integrity: sha512-5Btg4i8ffWTDHsU72cqxC8nIv9N3E3ObJAc6k0llrmPBG/ybh3jxmRfs8fNm44LlEXaZ5qrK/petsXX3UbpIFg==} + + '@storybook/addon-viewport@7.6.20': + resolution: {integrity: sha512-i8mIw8BjLWAVHEQsOTE6UPuEGQvJDpsu1XZnOCkpfTfPMz73m+3td/PmLG7mMT2wPnLu9IZncKLCKTAZRbt/YQ==} + + '@storybook/blocks@7.6.20': + resolution: {integrity: sha512-xADKGEOJWkG0UD5jbY4mBXRlmj2C+CIupDL0/hpzvLvwobxBMFPKZIkcZIMvGvVnI/Ui+tJxQxLSuJ5QsPthUw==} peerDependencies: react: ^18.2.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@storybook/addon-essentials@7.4.6': - resolution: {integrity: sha512-dWodufrt71TK7ELkeIvVae/x4PzECUlbOm57Iqqt4yQCyR291CgvI4PjeB8un2HbpcXCGZ+N/Oj3YkytvzBi4A==} - peerDependencies: - react: ^18.2.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + '@storybook/builder-manager@7.6.20': + resolution: {integrity: sha512-e2GzpjLaw6CM/XSmc4qJRzBF8GOoOyotyu3JrSPTYOt4RD8kjUsK4QlismQM1DQRu8i39aIexxmRbiJyD74xzQ==} - '@storybook/addon-highlight@7.4.6': - resolution: {integrity: sha512-zCufxxD2KS5VwczxfkcBxe1oR/juTTn2H1Qm8kYvWCJQx3UxzX0+G9cwafbpV7eivqaufLweEwROkH+0KjAtkQ==} - - '@storybook/addon-links@7.4.6': - resolution: {integrity: sha512-BPygElZKX+CPI9Se6GJNk1dYc5oxuhA+vHigO1tBqhiM6VkHyFP3cvezJNQvpNYhkUnu3cxnZXb3UJnlRbPY3g==} - peerDependencies: - react: ^18.2.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - - '@storybook/addon-measure@7.4.6': - resolution: {integrity: sha512-nCymMLaHnxv8TE3yEM1A9Tulb1NuRXRNmtsdHTkjv7P1aWCxZo8A/GZaottKe/GLT8jSRjZ+dnpYWrbAhw6wTQ==} - peerDependencies: - react: ^18.2.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - - '@storybook/addon-outline@7.4.6': - resolution: {integrity: sha512-errNUblRVDLpuEaHQPr/nsrnsUkD2ARmXawkRvizgDWLIDMDJYjTON3MUCaVx3x+hlZ3I6X//G5TVcma8tCc8A==} - peerDependencies: - react: ^18.2.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - - '@storybook/addon-toolbars@7.4.6': - resolution: {integrity: sha512-L9m2FBcKeteGq7qIYsMJr0LEfiH7Wdrv5IDcldZTn68eZUJTh1p4GdJZcOmzX1P5IFRr76hpu03iWsNlWQjpbQ==} - peerDependencies: - react: ^18.2.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - - '@storybook/addon-viewport@7.4.6': - resolution: {integrity: sha512-INDtk54j7bi7NgxMfd2ATmbA0J7nAd6X8itMkLIyPuPJtx8bYHPDORyemDOd0AojgmAdTOAyUtDYdI/PFeo4Cw==} - peerDependencies: - react: ^18.2.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - - '@storybook/blocks@7.4.6': - resolution: {integrity: sha512-HxBSAeOiTZW2jbHQlo1upRWFgoMsaAyKijUFf5MwwMNIesXCuuTGZDJ3xTABwAVLK2qC9Ektfbo0CZCiPVuDRQ==} - peerDependencies: - react: ^18.2.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - - '@storybook/builder-manager@7.4.6': - resolution: {integrity: sha512-zylZCD2rmyLOOFBFmUgtJg6UNUKmRNgXiig1XApzS2TkIbTZP827DsVEUl0ey/lskCe0uArkrEBR6ICba8p/Rw==} - - '@storybook/builder-vite@7.4.6': - resolution: {integrity: sha512-xV9STYK+TkqWWTf2ydm6jx+7P70fjD2UPd1XTUw08uKszIjhuuxk+bG/OF5R1E25mPunAKXm6kBFh351AKejBg==} + '@storybook/builder-vite@7.6.20': + resolution: {integrity: sha512-q3vf8heE7EaVYTWlm768ewaJ9lh6v/KfoPPeHxXxzSstg4ByP9kg4E1mrfAo/l6broE9E9zo3/Q4gsM/G/rw8Q==} peerDependencies: '@preact/preset-vite': '*' typescript: '>= 4.3.x' - vite: ^3.0.0 || ^4.0.0 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 vite-plugin-glimmerx: '*' peerDependenciesMeta: '@preact/preset-vite': @@ -2851,95 +2804,92 @@ packages: vite-plugin-glimmerx: optional: true - '@storybook/channels@7.4.6': - resolution: {integrity: sha512-yPv/sfo2c18fM3fvG0i1xse63vG8l33Al/OU0k/dtovltPu001/HVa1QgBgsb/QrEfZtvGjGhmtdVeYb39fv3A==} + '@storybook/channels@7.6.20': + resolution: {integrity: sha512-4hkgPSH6bJclB2OvLnkZOGZW1WptJs09mhQ6j6qLjgBZzL/ZdD6priWSd7iXrmPiN5TzUobkG4P4Dp7FjkiO7A==} - '@storybook/cli@7.4.6': - resolution: {integrity: sha512-rRwaH8pOL+FHz/pJMEkNpMH2xvZvWsrl7obBYw26NQiHmiVSAkfHJicndSN1mwc+p5w+9iXthrgzbLtSAOSvkA==} + '@storybook/cli@7.6.20': + resolution: {integrity: sha512-ZlP+BJyqg7HlnXf7ypjG2CKMI/KVOn03jFIiClItE/jQfgR6kRFgtjRU7uajh427HHfjv9DRiur8nBzuO7vapA==} hasBin: true - '@storybook/client-logger@7.4.6': - resolution: {integrity: sha512-XDw31ZziU//86PKuMRnmc+L/G0VopaGKENQOGEpvAXCU9IZASwGKlKAtcyosjrpi+ZiUXlMgUXCpXM7x3b1Ehw==} + '@storybook/client-logger@7.6.20': + resolution: {integrity: sha512-NwG0VIJQCmKrSaN5GBDFyQgTAHLNishUPLW1NrzqTDNAhfZUoef64rPQlinbopa0H4OXmlB+QxbQIb3ubeXmSQ==} - '@storybook/codemod@7.4.6': - resolution: {integrity: sha512-lxmwEpwksCaAq96APN2YlooSDfKjJ1vKzN5Ni2EqQzf2TEXl7XQjLacHd7OOaII1kfsy+D5gNG4N5wBo7Ub30g==} + '@storybook/codemod@7.6.20': + resolution: {integrity: sha512-8vmSsksO4XukNw0TmqylPmk7PxnfNfE21YsxFa7mnEBmEKQcZCQsNil4ZgWfG0IzdhTfhglAN4r++Ew0WE+PYA==} - '@storybook/components@7.4.6': - resolution: {integrity: sha512-nIRBhewAgrJJVafyCzuaLx1l+YOfvvD5dOZ0JxZsxJsefOdw1jFpUqUZ5fIpQ2moyvrR0mAUFw378rBfMdHz5Q==} + '@storybook/components@7.6.20': + resolution: {integrity: sha512-0d8u4m558R+W5V+rseF/+e9JnMciADLXTpsILrG+TBhwECk0MctIWW18bkqkujdCm8kDZr5U2iM/5kS1Noy7Ug==} peerDependencies: react: ^18.2.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@storybook/core-client@7.4.6': - resolution: {integrity: sha512-tfgxAHeCvMcs6DsVgtb4hQSDaCHeAPJOsoyhb47eDQfk4OmxzriM0qWucJV5DePSMi+KutX/rN2u0JxfOuN68g==} + '@storybook/core-client@7.6.20': + resolution: {integrity: sha512-upQuQQinLmlOPKcT8yqXNtwIucZ4E4qegYZXH5HXRWoLAL6GQtW7sUVSIuFogdki8OXRncr/dz8OA+5yQyYS4w==} - '@storybook/core-common@7.4.6': - resolution: {integrity: sha512-05MJFmOM86qvTLtgDskokIFz9txe0Lbhq4L3by1FtF0GwgH+p+W6I94KI7c6ANER+kVZkXQZhiRzwBFnVTW+Cg==} + '@storybook/core-common@7.6.20': + resolution: {integrity: sha512-8H1zPWPjcmeD4HbDm4FDD0WLsfAKGVr566IZ4hG+h3iWVW57II9JW9MLBtiR2LPSd8u7o0kw64lwRGmtCO1qAw==} - '@storybook/core-events@7.4.6': - resolution: {integrity: sha512-r5vrE+32lwrJh1NGFr1a0mWjvxo7q8FXYShylcwRWpacmL5NTtLkrXOoJSeGvJ4yKNYkvxQFtOPId4lzDxa32w==} + '@storybook/core-events@7.6.20': + resolution: {integrity: sha512-tlVDuVbDiNkvPDFAu+0ou3xBBYbx9zUURQz4G9fAq0ScgBOs/bpzcRrFb4mLpemUViBAd47tfZKdH4MAX45KVQ==} - '@storybook/core-server@7.4.6': - resolution: {integrity: sha512-jqmRTGCJ1W0WReImivkisPVaLFT5sjtLnFoAk0feHp6QS5j7EYOPN7CYzliyQmARWTLUEXOVaFf3VD6nJZQhJQ==} + '@storybook/core-server@7.6.20': + resolution: {integrity: sha512-qC5BdbqqwMLTdCwMKZ1Hbc3+3AaxHYWLiJaXL9e8s8nJw89xV8c8l30QpbJOGvcDmsgY6UTtXYaJ96OsTr7MrA==} - '@storybook/csf-plugin@7.4.6': - resolution: {integrity: sha512-yi7Qa4NSqKOyiJTWCxlB0ih2ijXq6oY5qZKW6MuMMBP14xJNRGLbH5KabpfXgN2T7YECcOWG1uWaGj2veJb1KA==} + '@storybook/csf-plugin@7.6.20': + resolution: {integrity: sha512-dzBzq0dN+8WLDp6NxYS4G7BCe8+vDeDRBRjHmM0xb0uJ6xgQViL8SDplYVSGnk3bXE/1WmtvyRzQyTffBnaj9Q==} - '@storybook/csf-tools@7.4.6': - resolution: {integrity: sha512-ocKpcIUtTBy6hlLY34RUFQyX403cWpB2gGfqvkHbpGe2BQj7EyV0zpWnjsfVxvw+M9OWlCdxHWDOPUgXM33ELw==} + '@storybook/csf-tools@7.6.20': + resolution: {integrity: sha512-rwcwzCsAYh/m/WYcxBiEtLpIW5OH1ingxNdF/rK9mtGWhJxXRDV8acPkFrF8rtFWIVKoOCXu5USJYmc3f2gdYQ==} - '@storybook/csf@0.1.1': - resolution: {integrity: sha512-4hE3AlNVxR60Wc5KSC68ASYzUobjPqtSKyhV6G+ge0FIXU55N5nTY7dXGRZHQGDBPq+XqchMkIdlkHPRs8nTHg==} + '@storybook/csf@0.1.13': + resolution: {integrity: sha512-7xOOwCLGB3ebM87eemep89MYRFTko+D8qE7EdAAq74lgdqRR5cOUtYWJLjO2dLtP94nqoOdHJo6MdLLKzg412Q==} '@storybook/docs-mdx@0.1.0': resolution: {integrity: sha512-JDaBR9lwVY4eSH5W8EGHrhODjygPd6QImRbwjAuJNEnY0Vw4ie3bPkeGfnacB3OBW6u/agqPv2aRlR46JcAQLg==} - '@storybook/docs-tools@7.4.6': - resolution: {integrity: sha512-nZj1L/8WwKWWJ41FW4MaKGajZUtrhnr9UwflRCkQJaWhAKmDfOb5M5TqI93uCOULpFPOm5wpoMBz2IHInQ2Lrg==} + '@storybook/docs-tools@7.6.20': + resolution: {integrity: sha512-Bw2CcCKQ5xGLQgtexQsI1EGT6y5epoFzOINi0FSTGJ9Wm738nRp5LH3dLk1GZLlywIXcYwOEThb2pM+pZeRQxQ==} '@storybook/global@5.0.0': resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} - '@storybook/manager-api@7.4.6': - resolution: {integrity: sha512-inrm3DIbCp8wjXSN/wK6e6i2ysQ/IEmtC7IN0OJ7vdrp+USCooPT448SQTUmVctUGCFmOU3fxXByq8g77oIi7w==} - peerDependencies: - react: ^18.2.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + '@storybook/manager-api@7.6.20': + resolution: {integrity: sha512-gOB3m8hO3gBs9cBoN57T7jU0wNKDh+hi06gLcyd2awARQlAlywnLnr3s1WH5knih6Aq+OpvGBRVKkGLOkaouCQ==} - '@storybook/manager@7.4.6': - resolution: {integrity: sha512-kA1hUDxpn1i2SO9OinvLvVXDeL4xgJkModp+pbE8IXv4NJWReNq1ecMeQCzPLS3Sil2gnrullQ9uYXsnZ9bxxA==} + '@storybook/manager@7.6.20': + resolution: {integrity: sha512-0Cf6WN0t7yEG2DR29tN5j+i7H/TH5EfPppg9h9/KiQSoFHk+6KLoy2p5do94acFU+Ro4+zzxvdCGbcYGKuArpg==} '@storybook/mdx2-csf@1.1.0': resolution: {integrity: sha512-TXJJd5RAKakWx4BtpwvSNdgTDkKM6RkXU8GK34S/LhidQ5Pjz3wcnqb0TxEkfhK/ztbP8nKHqXFwLfa2CYkvQw==} - '@storybook/node-logger@7.4.6': - resolution: {integrity: sha512-djZb310Q27GviDug1XBv0jOEDLCiwr4hhDE0aifCEKZpfNCi/EaP31nbWimFzZwxu4hE/YAPWExzScruR1zw9Q==} + '@storybook/node-logger@7.6.20': + resolution: {integrity: sha512-l2i4qF1bscJkOplNffcRTsgQWYR7J51ewmizj5YrTM8BK6rslWT1RntgVJWB1RgPqvx6VsCz1gyP3yW1oKxvYw==} - '@storybook/postinstall@7.4.6': - resolution: {integrity: sha512-TqI5BucPAGRWrkh55BYiG2/gHLFtC0In4cuu0GsUzB/1jc4i51npLRorCwhmT7r7YliGl5F7JaP0Bni/qHN3Lg==} + '@storybook/postinstall@7.6.20': + resolution: {integrity: sha512-AN4WPeNma2xC2/K/wP3I/GMbBUyeSGD3+86ZFFJFO1QmE/Zea6E+1aVlTd1iKHQUcNkZ9bZTrqkhPGVYx10pIw==} - '@storybook/preview-api@7.4.6': - resolution: {integrity: sha512-byUS/Opt3ytWD4cWz3sNEKw5Yks8MkQgRN+GDSyIomaEAQkLAM0rchPC0MYjwCeUSecV7IIQweNX5RbV4a34BA==} + '@storybook/preview-api@7.6.20': + resolution: {integrity: sha512-3ic2m9LDZEPwZk02wIhNc3n3rNvbi7VDKn52hDXfAxnL5EYm7yDICAkaWcVaTfblru2zn0EDJt7ROpthscTW5w==} - '@storybook/preview@7.4.6': - resolution: {integrity: sha512-2RPXusJ4CTDrIipIKKvbotD7fP0+8VzoFjImunflIrzN9rni+2rq5eMjqlXAaB+77w064zIR4uDUzI9fxsMDeQ==} + '@storybook/preview@7.6.20': + resolution: {integrity: sha512-cxYlZ5uKbCYMHoFpgleZqqGWEnqHrk5m5fT8bYSsDsdQ+X5wPcwI/V+v8dxYAdQcMphZVIlTjo6Dno9WG8qmVA==} - '@storybook/react-dom-shim@7.4.6': - resolution: {integrity: sha512-DSq8l9FDocUF1ooVI+TF83pddj1LynE/Hv0/y8XZhc3IgJ/HkuOQuUmfz29ezgfAi9gFYUR8raTIBi3/xdoRmw==} + '@storybook/react-dom-shim@7.6.20': + resolution: {integrity: sha512-SRvPDr9VWcS24ByQOVmbfZ655y5LvjXRlsF1I6Pr9YZybLfYbu3L5IicfEHT4A8lMdghzgbPFVQaJez46DTrkg==} peerDependencies: react: ^18.2.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@storybook/react-vite@7.4.6': - resolution: {integrity: sha512-jkjnrf3FxzR5wcmebXRPflrsM4WIDjWyW/NVFJwxi5PeIOk7fE7/QAPrm4NFRUu2Q7DeuH3oLKsw8bigvUI9RA==} + '@storybook/react-vite@7.6.20': + resolution: {integrity: sha512-uKuBFyGPZxpfR8vpDU/2OE9v7iTaxwL7ldd7k1swYd1rTSAPacTnEHSMl1R5AjUhkdI7gRmGN9q7qiVfK2XJCA==} engines: {node: '>=16'} peerDependencies: react: ^18.2.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - vite: ^3.0.0 || ^4.0.0 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 - '@storybook/react@7.4.6': - resolution: {integrity: sha512-w0dVo64baFFPTGpUOWFqkKsu6pQincoymegSNgqaBd5DxEyMDRiRoTWSJHMKE9BwgE8SyWhRkP1ak1mkccSOhQ==} + '@storybook/react@7.6.20': + resolution: {integrity: sha512-i5tKNgUbTNwlqBWGwPveDhh9ktlS0wGtd97A1ZgKZc3vckLizunlAFc7PRC1O/CMq5PTyxbuUb4RvRD2jWKwDA==} engines: {node: '>=16.0.0'} peerDependencies: react: ^18.2.0 @@ -2949,49 +2899,23 @@ packages: typescript: optional: true - '@storybook/router@7.4.6': - resolution: {integrity: sha512-Vl1esrHkcHxDKqc+HY7+6JQpBPW3zYvGk0cQ2rxVMhWdLZTAz1hss9DqzN9tFnPyfn0a1Q77EpMySkUrvWKKNQ==} + '@storybook/router@7.6.20': + resolution: {integrity: sha512-mCzsWe6GrH47Xb1++foL98Zdek7uM5GhaSlrI7blWVohGa0qIUYbfJngqR4ZsrXmJeeEvqowobh+jlxg3IJh+w==} + + '@storybook/telemetry@7.6.20': + resolution: {integrity: sha512-dmAOCWmOscYN6aMbhCMmszQjoycg7tUPRVy2kTaWg6qX10wtMrvEtBV29W4eMvqdsoRj5kcvoNbzRdYcWBUOHQ==} + + '@storybook/theming@7.6.20': + resolution: {integrity: sha512-iT1pXHkSkd35JsCte6Qbanmprx5flkqtSHC6Gi6Umqoxlg9IjiLPmpHbaIXzoC06DSW93hPj5Zbi1lPlTvRC7Q==} peerDependencies: react: ^18.2.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@storybook/telemetry@7.4.6': - resolution: {integrity: sha512-c8p/C1NIH8EMBviZkBCx8MMDk6rrITJ+b29DEp5MaWSRlklIVyhGiC4RPIRv6sxJwlD41PnqWVFtfu2j2eXLdQ==} + '@storybook/types@7.6.20': + resolution: {integrity: sha512-GncdY3x0LpbhmUAAJwXYtJDUQEwfF175gsjH0/fxPkxPoV7Sef9TM41jQLJW/5+6TnZoCZP/+aJZTJtq3ni23Q==} - '@storybook/theming@7.4.6': - resolution: {integrity: sha512-HW77iJ9ptCMqhoBOYFjRQw7VBap+38fkJGHP5KylEJCyYCgIAm2dEcQmtWpMVYFssSGcb6djfbtAMhYU4TL4Iw==} - peerDependencies: - react: ^18.2.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - - '@storybook/types@7.4.6': - resolution: {integrity: sha512-6QLXtMVsFZFpzPkdGWsu/iuc8na9dnS67AMOBKm5qCLPwtUJOYkwhMdFRSSeJthLRpzV7JLAL8Kwvl7MFP3QSw==} - - '@stylistic/eslint-plugin-js@2.6.1': - resolution: {integrity: sha512-iLOiVzcvqzDGD9U0EuVOX680v+XOPiPAjkxWj+Q6iV2GLOM5NB27tKVOpJY7AzBhidwpRbaLTgg3T4UzYx09jw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: '>=8.40.0' - - '@stylistic/eslint-plugin-jsx@2.6.1': - resolution: {integrity: sha512-5qHLXqxfY6jubAQfDqrifv41fx7gaqA9svDaChxMI6JiHpEBfh+PXxmm3g+B8gJCYVBTC62Rjl0Ny5QabK58bw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: '>=8.40.0' - - '@stylistic/eslint-plugin-plus@2.6.1': - resolution: {integrity: sha512-z/IYu/q8ipApzNam5utSU+BrXg4pK/Gv9xNbr4eWv/bZppvTWJU62xCO4nw/6r2dHNPnqc7uCHEC7GMlBnPY0A==} - peerDependencies: - eslint: '*' - - '@stylistic/eslint-plugin-ts@2.6.1': - resolution: {integrity: sha512-Mxl1VMorEG1Hc6oBYPD0+KIJOWkjEF1R0liL7wWgKfwpqOkgmnh5lVdZBrYyfRKOE4RlGcwEFTNai1IW6orgVg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: '>=8.40.0' - - '@stylistic/eslint-plugin@2.6.1': - resolution: {integrity: sha512-UT0f4t+3sQ/GKW7875NiIIjZJ1Bh4gd7JNfoIkwIQyWqO7wGd0Pqzu0Ho30Ka8MNF5lm++SkVeqAk26vGxoUpg==} + '@stylistic/eslint-plugin@2.13.0': + resolution: {integrity: sha512-RnO1SaiCFHn666wNz2QfZEFxvmiNRqhzaMXHXxXXKt+MEP7aajlPxUSMIQpKAaJfverpovEYqjBOXDq6dDcaOQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=8.40.0' @@ -2999,8 +2923,8 @@ packages: '@surma/rollup-plugin-off-main-thread@2.2.3': resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} - '@swc/helpers@0.5.11': - resolution: {integrity: sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==} + '@swc/helpers@0.5.15': + resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} '@tootallnate/once@2.0.0': resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} @@ -3012,44 +2936,43 @@ packages: '@tweenjs/tween.js@20.0.3': resolution: {integrity: sha512-SYUe1UgY5HM05EB4+0B4arq2IPjvyzKXoklXKxSYrc2IFxGm1cBrqg5XbiB5uwbs0xY5j+rj986NAJMM0KZaUw==} - '@types/babel__core@7.20.2': - resolution: {integrity: sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==} + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - '@types/babel__generator@7.6.5': - resolution: {integrity: sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==} + '@types/babel__generator@7.6.8': + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} - '@types/babel__template@7.4.2': - resolution: {integrity: sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==} + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - '@types/babel__traverse@7.20.2': - resolution: {integrity: sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==} + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} - '@types/body-parser@1.19.3': - resolution: {integrity: sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==} + '@types/body-parser@1.19.5': + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} - '@types/chai-subset@1.3.3': - resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} + '@types/chai-subset@1.3.6': + resolution: {integrity: sha512-m8lERkkQj+uek18hXOZuec3W/fCRTrU4hrnXjH3qhHy96ytuPaPiWGgu7sJb7tZxZonO75vYAjCvpe/e4VUwRw==} + peerDependencies: + '@types/chai': <5.2.0 - '@types/chai@4.3.6': - resolution: {integrity: sha512-VOVRLM1mBxIRxydiViqPcKn6MIxZytrbMpd6RJLIWKxUNr3zux8no0Oc7kJx0WAPIitgZ0gkrDS+btlqQpubpw==} + '@types/chai@4.3.20': + resolution: {integrity: sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==} - '@types/connect@3.4.36': - resolution: {integrity: sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==} + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - '@types/cookie@0.4.1': - resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} + '@types/cors@2.8.17': + resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} - '@types/cors@2.8.15': - resolution: {integrity: sha512-n91JxbNLD8eQIuXDIChAN1tCKNWCEgpceU9b7ZMbFA+P+Q4yIeh80jizFLEvolRPc1ES0VdwFlGv+kJTSirogw==} - - '@types/cross-spawn@6.0.3': - resolution: {integrity: sha512-BDAkU7WHHRHnvBf5z89lcvACsvkz/n7Tv+HyD/uW76O29HoH1Tk/W6iQrepaZVbisvlEek4ygwT8IW7ow9XLAA==} + '@types/cross-spawn@6.0.6': + resolution: {integrity: sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==} '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} - '@types/detect-port@1.3.3': - resolution: {integrity: sha512-bV/jQlAJ/nPY3XqSatkGpu+nGzou+uSwrH1cROhn+jBFg47yaNH+blW4C7p9KhopC7QxCv/6M86s37k8dMk0Yg==} + '@types/detect-port@1.3.5': + resolution: {integrity: sha512-Rf3/lB9WkDfIL9eEKaSYKc+1L/rNVYBjThk22JTqQw0YozXarX8YljFAz+HCoC6h4B4KwCMsBPZHaFezwT4BNA==} '@types/diff-match-patch@1.0.36': resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==} @@ -3057,41 +2980,35 @@ packages: '@types/doctrine@0.0.3': resolution: {integrity: sha512-w5jZ0ee+HaPOaX25X2/2oGR/7rgAQSYII7X7pp0m9KgBfMP7uKfMfTvcpl5Dj+eDBbpxKGiqE+flqDr6XTd2RA==} - '@types/draco3d@1.4.7': - resolution: {integrity: sha512-sjx6hQ8UArRZf+2ZhpPkjJW8iCkyxar69/IElc9NHuGE40n0U9SuvxX59CHvF4xUH7qfJDQ2lIbANZ0HHJg+BQ==} + '@types/doctrine@0.0.9': + resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==} - '@types/ejs@3.1.3': - resolution: {integrity: sha512-mv5T/JI/bu+pbfz1o+TLl1NF0NIBbjS0Vl6Ppz1YY9DkXfzZT0lelXpfS5i3ZS3U/p90it7uERQpBvLYoK8e4A==} + '@types/draco3d@1.4.10': + resolution: {integrity: sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw==} - '@types/emscripten@1.39.8': - resolution: {integrity: sha512-Rk0HKcMXFUuqT32k1kXHZWgxiMvsyYsmlnjp0rLKa0MMoqXLE3T9dogDBTRfuc3SAsXu97KD3k4SKR1lHqd57w==} + '@types/ejs@3.1.5': + resolution: {integrity: sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==} + + '@types/emscripten@1.40.0': + resolution: {integrity: sha512-MD2JJ25S4tnjnhjWyalMS6K6p0h+zQV6+Ylm+aGbiS8tSn/aHLSGNzBgduj6FB4zH0ax2GRMGYi/8G1uOxhXWA==} '@types/escodegen@0.0.6': resolution: {integrity: sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==} - '@types/eslint-scope@3.7.7': - resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - - '@types/eslint@9.6.0': - resolution: {integrity: sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==} - '@types/estree@0.0.39': resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} '@types/estree@0.0.51': resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==} - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - '@types/express-serve-static-core@4.17.37': - resolution: {integrity: sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==} + '@types/express-serve-static-core@4.19.6': + resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} - '@types/express@4.17.18': - resolution: {integrity: sha512-Sxv8BSLLgsBYmcnGdGjjEjqET2U+AKAdCRODmMiq02FgjwuV75Ut85DRpvFjyw/Mk0vgUOliGRU0UUmuuZHByQ==} + '@types/express@4.17.21': + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} '@types/find-cache-dir@3.2.1': resolution: {integrity: sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==} @@ -3102,140 +3019,150 @@ packages: '@types/glob@7.2.0': resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} - '@types/graceful-fs@4.1.7': - resolution: {integrity: sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==} + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} - '@types/http-cache-semantics@4.0.2': - resolution: {integrity: sha512-FD+nQWA2zJjh4L9+pFXqWOi0Hs1ryBCfI+985NjluQ1p8EYtoLvjLOKidXBtZ4/IcxDX4o8/E8qDS3540tNliw==} + '@types/http-cache-semantics@4.0.4': + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} - '@types/http-errors@2.0.2': - resolution: {integrity: sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==} + '@types/http-errors@2.0.4': + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - '@types/istanbul-lib-coverage@2.0.4': - resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} - '@types/istanbul-lib-report@3.0.1': - resolution: {integrity: sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ==} + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} - '@types/istanbul-reports@3.0.2': - resolution: {integrity: sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A==} + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} '@types/js-cookie@2.2.7': resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} - '@types/json-schema@7.0.12': - resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/lodash-es@4.17.9': - resolution: {integrity: sha512-ZTcmhiI3NNU7dEvWLZJkzG6ao49zOIjEgIE0RgV7wbPxU0f2xT3VSAHw2gmst8swH6V0YkLRGp4qPlX/6I90MQ==} + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} - '@types/lodash@4.14.199': - resolution: {integrity: sha512-Vrjz5N5Ia4SEzWWgIVwnHNEnb1UE1XMkvY5DGXrAeOGE9imk0hgTHh5GyDjLDJi9OTCn9oo9dXH1uToK1VRfrg==} + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} - '@types/mdast@4.0.3': - resolution: {integrity: sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==} + '@types/lodash@4.17.16': + resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==} - '@types/mdx@2.0.8': - resolution: {integrity: sha512-r7/zWe+f9x+zjXqGxf821qz++ld8tp6Z4jUS6qmPZUXH6tfh4riXOhAqb12tWGWAevCFtMt1goLWkQMqIJKpsA==} + '@types/markdown-it@14.1.2': + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} - '@types/mime-types@2.1.2': - resolution: {integrity: sha512-q9QGHMGCiBJCHEvd4ZLdasdqXv570agPsUW0CeIm/B8DzhxsYMerD0l3IlI+EQ1A2RWHY2mmM9x1YIuuWxisCg==} + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - '@types/mime@1.3.3': - resolution: {integrity: sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==} + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} - '@types/mime@3.0.2': - resolution: {integrity: sha512-Wj+fqpTLtTbG7c0tH47dkahefpLKEbB+xAZuLq7b4/IDHPl/n6VoXcyUQ2bypFlbSwvCr0y+bD4euTTqTJsPxQ==} + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + + '@types/mime-types@2.1.4': + resolution: {integrity: sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==} + + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - '@types/minimist@1.2.3': - resolution: {integrity: sha512-ZYFzrvyWUNhaPomn80dsMNgMeXxNWZBdkuG/hWlUvXvbdUH8ZERNBGXnU87McuGcWDsyzX2aChCv/SVN348k3A==} + '@types/minimist@1.2.5': + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} - '@types/ms@0.7.34': - resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node-fetch@2.6.6': - resolution: {integrity: sha512-95X8guJYhfqiuVVhRFxVQcf4hW/2bCuoPwDasMf/531STFoNoWTT7YDnWdXHEZKqAGUigmpG31r2FE70LwnzJw==} + '@types/node-fetch@2.6.12': + resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==} '@types/node-rsa@1.1.4': resolution: {integrity: sha512-dB0ECel6JpMnq5ULvpUTunx3yNm8e/dIkv8Zu9p2c8me70xIRUUG3q+qXRwcSf9rN3oqamv4116iHy90dJGRpA==} - '@types/node@14.18.56': - resolution: {integrity: sha512-+k+57NVS9opgrEn5l9c0gvD1r6C+PtyhVE4BTnMMRwiEA8ZO8uFcs6Yy2sXIy0eC95ZurBtRSvhZiHXBysbl6w==} + '@types/node@14.18.63': + resolution: {integrity: sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==} - '@types/node@16.18.58': - resolution: {integrity: sha512-YGncyA25/MaVtQkjWW9r0EFBukZ+JulsLcVZBlGUfIb96OBMjkoRWwQo5IEWJ8Fj06Go3GHw+bjYDitv6BaGsA==} + '@types/node@18.19.79': + resolution: {integrity: sha512-90K8Oayimbctc5zTPHPfZloc/lGVs7f3phUAAMcTgEPtg8kKquGZDERC8K4vkBYkQQh48msiYUslYtxTWvqcAg==} - '@types/node@22.8.1': - resolution: {integrity: sha512-k6Gi8Yyo8EtrNtkHXutUu2corfDf9su95VYVP10aGYMMROM6SAItZi0w1XszA6RtWTHSVp5OeFof37w0IEqCQg==} + '@types/node@22.13.9': + resolution: {integrity: sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==} - '@types/normalize-package-data@2.4.2': - resolution: {integrity: sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==} + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - '@types/offscreencanvas@2019.7.2': - resolution: {integrity: sha512-ujCjOxeA07IbEBQYAkoOI+XFw5sT3nhWJ/xZfPR6reJppDG7iPQPZacQiLTtWH1b3a2NYXWlxvYqa40y/LAixQ==} + '@types/offscreencanvas@2019.7.3': + resolution: {integrity: sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==} - '@types/parse-json@4.0.0': - resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} + '@types/parse-json@4.0.2': + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - '@types/pretty-hrtime@1.0.1': - resolution: {integrity: sha512-VjID5MJb1eGKthz2qUerWT8+R4b9N+CHvGCzg9fn4kWZgaF9AhdYikQio3R7wV8YY1NsQKPaCwKz1Yff+aHNUQ==} + '@types/pretty-hrtime@1.0.3': + resolution: {integrity: sha512-nj39q0wAIdhwn7DGUyT9irmsKK1tV0bd5WFEhgpqNTMFZ8cE+jieuTphCW0tfdm47S2zVT5mr09B28b1chmQMA==} - '@types/prop-types@15.7.12': - resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} + '@types/prop-types@15.7.14': + resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} - '@types/qs@6.9.8': - resolution: {integrity: sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==} + '@types/qs@6.9.18': + resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==} - '@types/range-parser@1.2.5': - resolution: {integrity: sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==} + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - '@types/rbush@3.0.1': - resolution: {integrity: sha512-0LecKcQjuJ/PclmThftzePIKXaKt7OMjoZZ3Xf17Ebd28ZU6OFUu1mObbvV74YXS1W3APdZO5GRHyD/ezGK4Vg==} + '@types/rbush@3.0.4': + resolution: {integrity: sha512-knSt9cCW8jj1ZSFcFeBZaX++OucmfPxxHiRwTahZfJlnQsek7O0bazTJHWD2RVj9LEoejUYF2de3/stf+QXcXw==} - '@types/react-dom@18.2.7': - resolution: {integrity: sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==} + '@types/react-dom@18.3.5': + resolution: {integrity: sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==} + peerDependencies: + '@types/react': ^18.0.0 - '@types/react-transition-group@4.4.7': - resolution: {integrity: sha512-ICCyBl5mvyqYp8Qeq9B5G/fyBSRC0zx3XM3sCC6KkcMsNeAHqXBKkmat4GqdJET5jtYUpZXrxI5flve5qhi2Eg==} + '@types/react-transition-group@4.4.12': + resolution: {integrity: sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==} + peerDependencies: + '@types/react': '*' - '@types/react@18.2.20': - resolution: {integrity: sha512-WKNtmsLWJM/3D5mG4U84cysVY31ivmyw85dE84fOCk5Hx78wezB/XEjVPWl2JTZ5FkEeaTJf+VgUAUn3PE7Isw==} + '@types/react@18.3.18': + resolution: {integrity: sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==} - '@types/readable-stream@4.0.12': - resolution: {integrity: sha512-SCaw+bs9o/HCX1eTa3glTcQgW1oPxof49mqP2Qikik3xzTimNv2M4p43BQHhBuf7CwOJdQW0s1SrWU3MZxz6lw==} + '@types/readable-stream@4.0.18': + resolution: {integrity: sha512-21jK/1j+Wg+7jVw1xnSwy/2Q1VgVjWuFssbYGTREPUBeZ+rqVFl2udq0IkxzPC0ZhOzVceUbyIACFZKLqKEBlA==} - '@types/resolve@1.17.1': - resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + + '@types/resolve@1.20.6': + resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} '@types/sat@0.0.31': resolution: {integrity: sha512-P4SVw79XheP1p92useDVpLYYOUQ6lpw2L7IdQz4dD23DZ8DiC1STgPOh72hjR5IZJBPQbzlICAbmjCKbwyYuxg==} - '@types/scheduler@0.16.3': - resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} + '@types/semver@7.5.8': + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - '@types/semver@7.5.3': - resolution: {integrity: sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==} + '@types/send@0.17.4': + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} - '@types/send@0.17.2': - resolution: {integrity: sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==} - - '@types/serve-static@1.15.3': - resolution: {integrity: sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==} + '@types/serve-static@1.15.7': + resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} '@types/sinonjs__fake-timers@8.1.1': resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==} - '@types/sizzle@2.3.3': - resolution: {integrity: sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==} + '@types/sizzle@2.3.9': + resolution: {integrity: sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==} - '@types/stats.js@0.17.1': - resolution: {integrity: sha512-OgfYE1x2w1jRUXzzKABX+kOdwz2y9PE0uSwnZabkWfJTWOzm7Pvfm4JI2xqRE0q2nwUe2jZLWcrcnhd9lQU63w==} + '@types/stats.js@0.17.3': + resolution: {integrity: sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==} '@types/three@0.154.0': resolution: {integrity: sha512-IioqpGhch6FdLDh4zazRn3rXHj6Vn2nVOziJdXVbJFi9CaI65LtP9qqUtpzbsHK2Ezlox8NtsLNHSw3AQzucjA==} @@ -3243,32 +3170,35 @@ packages: '@types/three@0.156.0': resolution: {integrity: sha512-733bXDSRdlrxqOmQuOmfC1UBRuJ2pREPk8sWnx9MtIJEVDQMx8U0NQO5MVVaOrjzDPyLI+cFPim2X/ss9v0+LQ==} - '@types/trusted-types@2.0.3': - resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} '@types/ua-parser-js@0.7.39': resolution: {integrity: sha512-P/oDfpofrdtF5xw433SPALpdSchtJmY7nsJItf8h3KXqOslkbySh8zq4dSWXH2oTjRvJ5PczVEoCZPow6GicLg==} - '@types/unist@2.0.8': - resolution: {integrity: sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw==} + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} - '@types/unist@3.0.2': - resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/uuid@9.0.8': + resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} '@types/wait-on@5.3.4': resolution: {integrity: sha512-EBsPjFMrFlMbbUFf9D1Fp+PAB2TwmUn7a3YtHyD9RLuTIk1jDd8SxXVAoez2Ciy+8Jsceo2MYEYZzJ/DvorOKw==} - '@types/webxr@0.5.7': - resolution: {integrity: sha512-Rcgs5c2eNFnHp53YOjgtKfl/zWX1Y+uFGUwlSXrWcZWu3yhANRezmph4MninmqybUYT6g9ZE0aQ9QIdPkLR3Kg==} + '@types/webxr@0.5.21': + resolution: {integrity: sha512-geZIAtLzjGmgY2JUi6VxXdCrTb99A7yP49lxLr2Nm/uIK0PkkxcEi4OGhoGDO4pxCf3JwGz2GiJL2Ej4K2bKaA==} - '@types/wicg-file-system-access@2023.10.2': - resolution: {integrity: sha512-nSiK8qt0O7sQmDcW3HYfvya7GDoD6ipgdcUFzk3QN+UBIqXeNg38Nh6VnKv7EIPfkVETRiquyMskCbpxUzgX1Q==} + '@types/wicg-file-system-access@2023.10.5': + resolution: {integrity: sha512-e9kZO9kCdLqT2h9Tw38oGv9UNzBBWaR1MzuAavxPcsV/7FJ3tWbU6RI3uB+yKIDPGLkGVbplS52ub0AcRLvrhA==} - '@types/yargs-parser@21.0.1': - resolution: {integrity: sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==} + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - '@types/yargs@17.0.28': - resolution: {integrity: sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw==} + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} @@ -3284,8 +3214,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@6.7.3': - resolution: {integrity: sha512-TlutE+iep2o7R8Lf+yoer3zU6/0EAUc8QIBB3GYBc1KGz4c4TRm83xwXUZVPlZ6YCLss4r77jbu6j3sendJoiQ==} + '@typescript-eslint/parser@6.21.0': + resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -3298,12 +3228,12 @@ packages: resolution: {integrity: sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==} engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/scope-manager@6.7.3': - resolution: {integrity: sha512-wOlo0QnEou9cHO2TdkJmzF7DFGvAKEnB82PuPNHpT8ZKKaZu6Bm63ugOTn9fXNJtvuDPanBc78lGUGGytJoVzQ==} + '@typescript-eslint/scope-manager@6.21.0': + resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/scope-manager@8.0.0': - resolution: {integrity: sha512-V0aa9Csx/ZWWv2IPgTfY7T4agYwJyILESu/PVqFtTFz9RIS823mAze+NbnBI8xiwdX3iqeQbcTYlvB04G9wyQw==} + '@typescript-eslint/scope-manager@8.26.0': + resolution: {integrity: sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript-eslint/type-utils@6.1.0': @@ -3320,12 +3250,12 @@ packages: resolution: {integrity: sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==} engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/types@6.7.3': - resolution: {integrity: sha512-4g+de6roB2NFcfkZb439tigpAMnvEIg3rIjWQ+EM7IBaYt/CdJt6em9BJ4h4UpdgaBWdmx2iWsafHTrqmgIPNw==} + '@typescript-eslint/types@6.21.0': + resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/types@8.0.0': - resolution: {integrity: sha512-wgdSGs9BTMWQ7ooeHtu5quddKKs5Z5dS+fHLbrQI+ID0XWJLODGMHRfhwImiHoeO2S5Wir2yXuadJN6/l4JRxw==} + '@typescript-eslint/types@8.26.0': + resolution: {integrity: sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript-eslint/typescript-estree@6.1.0': @@ -3337,8 +3267,8 @@ packages: typescript: optional: true - '@typescript-eslint/typescript-estree@6.7.3': - resolution: {integrity: sha512-YLQ3tJoS4VxLFYHTw21oe1/vIZPRqAO91z6Uv0Ss2BKm/Ag7/RVQBcXTGcXhgJMdA4U+HrKuY5gWlJlvoaKZ5g==} + '@typescript-eslint/typescript-estree@6.21.0': + resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -3346,14 +3276,11 @@ packages: typescript: optional: true - '@typescript-eslint/typescript-estree@8.0.0': - resolution: {integrity: sha512-5b97WpKMX+Y43YKi4zVcCVLtK5F98dFls3Oxui8LbnmRsseKenbbDinmvxrWegKDMmlkIq/XHuyy0UGLtpCDKg==} + '@typescript-eslint/typescript-estree@8.26.0': + resolution: {integrity: sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <5.9.0' '@typescript-eslint/utils@6.1.0': resolution: {integrity: sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==} @@ -3361,24 +3288,28 @@ packages: peerDependencies: eslint: ^7.0.0 || ^8.0.0 - '@typescript-eslint/utils@8.0.0': - resolution: {integrity: sha512-k/oS/A/3QeGLRvOWCg6/9rATJL5rec7/5s1YmdS0ZU6LHveJyGFwBvLhSRBv6i9xaj7etmosp+l+ViN1I9Aj/Q==} + '@typescript-eslint/utils@8.26.0': + resolution: {integrity: sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' '@typescript-eslint/visitor-keys@6.1.0': resolution: {integrity: sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==} engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/visitor-keys@6.7.3': - resolution: {integrity: sha512-HEVXkU9IB+nk9o63CeICMHxFWbHWr3E1mpilIQBe9+7L/lH97rleFLVtYsfnWB+JVMaiFnEaxvknvmIzX+CqVg==} + '@typescript-eslint/visitor-keys@6.21.0': + resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/visitor-keys@8.0.0': - resolution: {integrity: sha512-oN0K4nkHuOyF3PVMyETbpP5zp6wfyOvm7tWhTMfoqxSSsPmJIh6JNASuZDlODE8eE+0EB9uar+6+vxr9DBTYOA==} + '@typescript-eslint/visitor-keys@8.26.0': + resolution: {integrity: sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + '@vitejs/plugin-react@3.1.0': resolution: {integrity: sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g==} engines: {node: ^14.18.0 || >=16.0.0} @@ -3388,92 +3319,18 @@ packages: '@vitest/expect@0.34.6': resolution: {integrity: sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==} - '@vitest/expect@3.0.7': - resolution: {integrity: sha512-QP25f+YJhzPfHrHfYHtvRn+uvkCFCqFtW9CktfBxmB+25QqWsx7VB2As6f4GmwllHLDhXNHvqedwhvMmSnNmjw==} - - '@vitest/mocker@3.0.7': - resolution: {integrity: sha512-qui+3BLz9Eonx4EAuR/i+QlCX6AUZ35taDQgwGkK/Tw6/WgwodSrjN1X2xf69IA/643ZX5zNKIn2svvtZDrs4w==} - peerDependencies: - msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true - - '@vitest/pretty-format@3.0.7': - resolution: {integrity: sha512-CiRY0BViD/V8uwuEzz9Yapyao+M9M008/9oMOSQydwbwb+CMokEq3XVaF3XK/VWaOK0Jm9z7ENhybg70Gtxsmg==} - '@vitest/runner@0.34.6': resolution: {integrity: sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==} - '@vitest/runner@3.0.7': - resolution: {integrity: sha512-WeEl38Z0S2ZcuRTeyYqaZtm4e26tq6ZFqh5y8YD9YxfWuu0OFiGFUbnxNynwLjNRHPsXyee2M9tV7YxOTPZl2g==} - '@vitest/snapshot@0.34.6': resolution: {integrity: sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==} - '@vitest/snapshot@3.0.7': - resolution: {integrity: sha512-eqTUryJWQN0Rtf5yqCGTQWsCFOQe4eNz5Twsu21xYEcnFJtMU5XvmG0vgebhdLlrHQTSq5p8vWHJIeJQV8ovsA==} - '@vitest/spy@0.34.6': resolution: {integrity: sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==} - '@vitest/spy@3.0.7': - resolution: {integrity: sha512-4T4WcsibB0B6hrKdAZTM37ekuyFZt2cGbEGd2+L0P8ov15J1/HUsUaqkXEQPNAWr4BtPPe1gI+FYfMHhEKfR8w==} - '@vitest/utils@0.34.6': resolution: {integrity: sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==} - '@vitest/utils@3.0.7': - resolution: {integrity: sha512-xePVpCRfooFX3rANQjwoditoXgWb1MaFbzmGuPP59MK6i13mrnDw/yEIyJudLeW6/38mCNcwCiJIGmpDPibAIg==} - - '@webassemblyjs/ast@1.12.1': - resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} - - '@webassemblyjs/floating-point-hex-parser@1.11.6': - resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} - - '@webassemblyjs/helper-api-error@1.11.6': - resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} - - '@webassemblyjs/helper-buffer@1.12.1': - resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==} - - '@webassemblyjs/helper-numbers@1.11.6': - resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} - - '@webassemblyjs/helper-wasm-bytecode@1.11.6': - resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} - - '@webassemblyjs/helper-wasm-section@1.12.1': - resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==} - - '@webassemblyjs/ieee754@1.11.6': - resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} - - '@webassemblyjs/leb128@1.11.6': - resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} - - '@webassemblyjs/utf8@1.11.6': - resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} - - '@webassemblyjs/wasm-edit@1.12.1': - resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==} - - '@webassemblyjs/wasm-gen@1.12.1': - resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==} - - '@webassemblyjs/wasm-opt@1.12.1': - resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==} - - '@webassemblyjs/wasm-parser@1.12.1': - resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==} - - '@webassemblyjs/wast-printer@1.12.1': - resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==} - '@xboxreplay/errors@0.1.0': resolution: {integrity: sha512-Tgz1d/OIPDWPeyOvuL5+aai5VCcqObhPnlI3skQuf80GVF3k1I0lPCnGC+8Cm5PV9aLBT5m8qPcJoIUQ2U4y9g==} @@ -3484,24 +3341,24 @@ packages: resolution: {integrity: sha512-7vCVgm1E1IZ2cujiitFk9550Vgu2XAOn1ff90di638fMmTK0XkFMXKsSR/nGZmYKt+XiTMI/0B3TvreqbVjOug==} engines: {node: '>=16'} - '@xmcl/core@2.12.0': - resolution: {integrity: sha512-rcxy29i2fjGFpe6sEvaJxYHFGlfYMcJwElbk6TIUCrKNOiMhyLZeBtCJSk38hvaYF0kiROA3c4EJeWNGHf2zVw==} + '@xmcl/core@2.13.0': + resolution: {integrity: sha512-1BslEWUr234zZZTq9Q3QDm8APReYx7phy6PY5fodiztwblYbgipsd89vfx+Qvjc1xWpGtjei0AvxubUDeMFTgA==} engines: {node: '>=16.0'} - '@xmcl/file-transfer@1.0.3': - resolution: {integrity: sha512-p5JsUQpNShqW4VpqaKXcQzYSO9o/9UGjXZfb5aNt/24Ty+j9qepQyPo4P1CFwfzgFuf9GGhH5cPUi6nShlKS+g==} + '@xmcl/file-transfer@1.0.6': + resolution: {integrity: sha512-WVnCTyHTqUUIMsqgGnkmQqov9/qxKWWBj+wjn6pMotpCJHu3gKkLqVoD76IQeTgUBIoh5sGgGbYMZmpRlqCGzw==} engines: {node: '>=16.0'} '@xmcl/forge-site-parser@2.0.9': resolution: {integrity: sha512-OHKG2KYE+F6TSeOQmymuGoqEifxbJb3w3X/hmxMNeqtewiYukJldPmKO559ZFnZnOuMQEnr+X0dMbTQwWs5dFg==} engines: {node: '>=16'} - '@xmcl/installer@5.1.0': - resolution: {integrity: sha512-KpoxpfYdUWH4U4Yat7RifS1JZajArOdfgsJ/LdU90y6Fc3hKhHSJsiRudk1VxASTyMXKCM0lWVxH5JzywRHBDw==} + '@xmcl/installer@5.4.0': + resolution: {integrity: sha512-Y4UK6WWogDdgvcAUQnUPoJidlkuVQP5dSV5QueJhKeEJAA3lmGklwV8Dp8z0/92ITQ45OBsB7g08qV3eec4G6w==} engines: {node: '>=16.0'} - '@xmcl/task@4.0.6': - resolution: {integrity: sha512-h0AR7DQm6xxBgROPnRi0EY8DlaDQwuGzPA5lFRMD4EsnpHJ/3fPdzwbMLb81ZxKJlLSCn3hVR2yI0mSKIm5Heg==} + '@xmcl/task@4.1.0': + resolution: {integrity: sha512-5Gqo/gltcenXTvRUz3H1Q2tNw9wWbOjeOVd9TeRNtBAOaKmdTD7iMhOIbdei71BSZ9FkVEhcUjO+PL+y+WNHoQ==} '@xmcl/text-component@2.1.3': resolution: {integrity: sha512-LdUZgC5+8F23J2ZkZi7aZb87QBNfxwJqhUyts8YBQYwxQPwei20TOBm2hr69euoAeDo7NDfbLXssD4mUvsAS0Q==} @@ -3516,12 +3373,6 @@ packages: '@xobotyi/scrollbar-width@1.9.5': resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==} - '@xtuc/ieee754@1.2.0': - resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} - - '@xtuc/long@4.2.2': - resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - '@yarnpkg/esbuild-plugin-pnp@3.0.0-rc.15': resolution: {integrity: sha512-kYzDJO5CA9sy+on/s2aIW0411AklfCi8Ck/4QDivOqsMKpStZA2SsR+X27VTggGwpStWaLrjJcDcdDMowtG8MA==} engines: {node: '>=14.15.0'} @@ -3536,22 +3387,29 @@ packages: resolution: {integrity: sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==} engines: {node: '>=12 <14 || 14.2 - 14.9 || >14.10.0'} + '@zardoy/flying-squid@0.0.104': + resolution: {integrity: sha512-jGhQ7fn7o8UN+mUwZbt9674D37YLuBi+Au4TwKcopCA6huIQdHTFNl2e+0ZSTI5mnhN+NpyVoR3vmtH6L58vHQ==} + engines: {node: '>=8'} + hasBin: true + '@zardoy/flying-squid@0.0.49': resolution: {integrity: sha512-Kt4wr5/R+44tcLU9gjuNG2an9weWeKEpIoKXfsgJN2GGQqdnbd5nBpxfGDdgZ9aMdFugsVW8BsyPZNhj9vbMXA==} engines: {node: '>=8'} hasBin: true - '@zardoy/flying-squid@0.0.51': - resolution: {integrity: sha512-HHZ79H9NkS44lL9vk6gVEuJDJqj88gpiBt9Ihh5p4rHXTVbRid95riiNK5dD0kHI94P5/DXdtNalvmJDPU86oQ==} - engines: {node: '>=8'} - hasBin: true + '@zardoy/maxrects-packer@2.7.4': + resolution: {integrity: sha512-ZIDcSdtSg6EhKFxGYWCcTnA/0YVbpixBL+psUS6ncw4IvdDF5hWauMU3XeCfYwrT/88QFgAq/Pafxt+P9OJyoQ==} - '@zardoy/react-util@0.2.4': - resolution: {integrity: sha512-YRBbXi54QOgWGDSn3NLEMMGrWbfL/gn2khxO31HT0WPFB6IW2rSnB4hcy+S/nc+2D6PRNq4kQxGs4vTAe4a7Xg==} + '@zardoy/react-util@0.2.7': + resolution: {integrity: sha512-LJOml3y8wa5OxvNgDKMceP7kaFHkw2nX9y/RQGMv2sijTEnc4gCd3yNtc4fibu1PFWZlupb6UvsNe45o7UwElg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} peerDependencies: + '@nextui-org/react': ^2.4.6 react: ^18.2.0 react-dom: '>=18.0.0' + peerDependenciesMeta: + '@nextui-org/react': + optional: true '@zardoy/utils@0.0.11': resolution: {integrity: sha512-d6xBnSFCOa98HcL52xSBflJKjKpxfRhtr1eVexy89YujeCHSQhUMmSz9h07xyrulfW60k9tSeYH5reuqoh4l4w==} @@ -3571,11 +3429,6 @@ packages: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} - acorn-import-attributes@1.9.5: - resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} - peerDependencies: - acorn: ^8 - acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -3585,8 +3438,8 @@ packages: resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} engines: {node: '>=0.4.0'} - acorn-walk@8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} engines: {node: '>=0.4.0'} acorn@7.4.1: @@ -3594,8 +3447,8 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - acorn@8.12.1: - resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} engines: {node: '>=0.4.0'} hasBin: true @@ -3603,9 +3456,9 @@ packages: resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} engines: {node: '>= 10.0.0'} - adm-zip@0.5.12: - resolution: {integrity: sha512-6TVU49mK6KZb4qG6xWaaM4C7sA/sgUMLy/JYMOzkcp3BvVLpW0fXDFQiIzAuxFCt/2+xD7fNIiPFAoLZPhVNLQ==} - engines: {node: '>=6.0'} + adm-zip@0.5.16: + resolution: {integrity: sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==} + engines: {node: '>=12.0'} aes-js@3.1.2: resolution: {integrity: sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==} @@ -3621,28 +3474,19 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} - agent-base@7.1.0: - resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} - engines: {node: '>= 14'} - - agentkeepalive@4.5.0: - resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} engines: {node: '>= 8.0.0'} aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} - ajv-keywords@3.5.2: - resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} - peerDependencies: - ajv: ^6.9.1 - ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} animejs@3.2.1: resolution: {integrity: sha512-sWno3ugFryK5nhiDm/2BKeFCpZv7vzerWUcUPyAZLDhMek3+S/p418ldZJbJXo5ZUOpfm2kP2XRO4NJcULMy9A==} @@ -3659,8 +3503,8 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} engines: {node: '>=12'} ansi-styles@3.2.1: @@ -3725,8 +3569,8 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - aria-hidden@1.2.3: - resolution: {integrity: sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==} + aria-hidden@1.2.4: + resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==} engines: {node: '>=10'} arr-diff@4.0.0: @@ -3752,6 +3596,10 @@ packages: resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} engines: {node: '>= 0.4'} + array-includes@3.1.9: + resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} + engines: {node: '>= 0.4'} + array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -3772,9 +3620,6 @@ packages: resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} engines: {node: '>= 0.4'} - array.prototype.toreversed@1.1.2: - resolution: {integrity: sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==} - array.prototype.tosorted@1.1.4: resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} engines: {node: '>= 0.4'} @@ -3790,8 +3635,8 @@ packages: resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} engines: {node: '>=0.10.0'} - asn1.js@5.4.1: - resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} + asn1.js@4.10.1: + resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} asn1@0.2.3: resolution: {integrity: sha512-6i37w/+EhlWlGUJff3T/Q8u1RGmP5wgbiwYnOnbOqvtrPxT63/sYFyP9RcpxtxGymtfA075IvmOnL7ycNOWl3w==} @@ -3809,22 +3654,10 @@ packages: assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - assertion-error@2.0.1: - resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} - engines: {node: '>=12'} - assign-symbols@1.0.0: resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} engines: {node: '>=0.10.0'} - ast-types@0.14.2: - resolution: {integrity: sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==} - engines: {node: '>=4'} - - ast-types@0.15.2: - resolution: {integrity: sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==} - engines: {node: '>=4'} - ast-types@0.16.1: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} @@ -3846,8 +3679,8 @@ packages: async@2.6.4: resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} - async@3.2.5: - resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -3868,14 +3701,14 @@ packages: aws-sign2@0.7.0: resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} - aws4@1.12.0: - resolution: {integrity: sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==} + aws4@1.13.2: + resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} axios@0.21.4: resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} - axios@1.7.2: - resolution: {integrity: sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==} + axios@1.8.2: + resolution: {integrity: sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==} babel-core@7.0.0-bridge.0: resolution: {integrity: sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==} @@ -3890,18 +3723,18 @@ packages: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} - babel-plugin-polyfill-corejs2@0.4.5: - resolution: {integrity: sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==} + babel-plugin-polyfill-corejs2@0.4.12: + resolution: {integrity: sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-corejs3@0.8.3: - resolution: {integrity: sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==} + babel-plugin-polyfill-corejs3@0.11.1: + resolution: {integrity: sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-regenerator@0.5.2: - resolution: {integrity: sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==} + babel-plugin-polyfill-regenerator@0.6.3: + resolution: {integrity: sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -3946,16 +3779,16 @@ packages: resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} engines: {node: '>=12.0.0'} - big-integer@1.6.51: - resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==} + big-integer@1.6.52: + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} engines: {node: '>=0.6'} binary-extensions@1.13.1: resolution: {integrity: sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==} engines: {node: '>=0.10.0'} - binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} bindings@1.5.0: @@ -3979,18 +3812,14 @@ packages: bmp-js@0.1.0: resolution: {integrity: sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==} - bn.js@4.12.0: - resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + bn.js@4.12.1: + resolution: {integrity: sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==} bn.js@5.2.1: resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} - body-parser@1.20.1: - resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - - body-parser@1.20.2: - resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} boolbase@1.0.0: @@ -4010,8 +3839,8 @@ packages: resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} engines: {node: '>=0.10.0'} - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} brorand@1.1.0: @@ -4038,11 +3867,13 @@ packages: browserify-des@1.0.2: resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} - browserify-rsa@4.1.0: - resolution: {integrity: sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==} + browserify-rsa@4.1.1: + resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==} + engines: {node: '>= 0.10'} - browserify-sign@4.2.1: - resolution: {integrity: sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==} + browserify-sign@4.2.3: + resolution: {integrity: sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==} + engines: {node: '>= 0.12'} browserify-zlib@0.1.4: resolution: {integrity: sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==} @@ -4050,8 +3881,8 @@ packages: browserify-zlib@0.2.0: resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} - browserslist@4.23.2: - resolution: {integrity: sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==} + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -4088,19 +3919,10 @@ packages: builtin-status-codes@3.0.0: resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} - bytes@3.0.0: - resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} - engines: {node: '>= 0.8'} - bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} - c8@7.14.0: - resolution: {integrity: sha512-i04rtkkcNcCf7zsQcSv/T9EbUn4RXQ6mropeMcjFOsQXQ0iGLAr/xT6TImQg4+U9hmNpN9XdvPkjUL1IzbgxJw==} - engines: {node: '>=10.12.0'} - hasBin: true - cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -4125,10 +3947,6 @@ packages: resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} engines: {node: '>= 0.4'} - call-bound@1.0.3: - resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} - engines: {node: '>= 0.4'} - call-bound@1.0.4: resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} engines: {node: '>= 0.4'} @@ -4152,8 +3970,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001646: - resolution: {integrity: sha512-dRg00gudiBDDTmUhClSdv3hqRfpbOnU28IpI1T6PBTLWa+kOj0681C8uML3PifYfREuBrVjDGhL3adYpBT6spw==} + caniuse-lite@1.0.30001713: + resolution: {integrity: sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q==} canvas@2.11.2: resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} @@ -4165,21 +3983,13 @@ packages: caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - cbor-extract@2.2.0: - resolution: {integrity: sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==} - hasBin: true + centra@2.7.0: + resolution: {integrity: sha512-PbFMgMSrmgx6uxCdm57RUos9Tc3fclMvhLSATYN39XsDV29B89zZ3KA89jmY0vwSGazyU+uerqwa6t+KaodPcg==} - cbor-x@1.5.4: - resolution: {integrity: sha512-PVKILDn+Rf6MRhhcyzGXi5eizn1i0i3F8Fe6UMMxXBnWkalq9+C5+VTmlIjAYM4iF2IYF2N+zToqAfYOp+3rfw==} - - chai@4.3.10: - resolution: {integrity: sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==} + chai@4.5.0: + resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} engines: {node: '>=4'} - chai@5.2.0: - resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} - engines: {node: '>=12'} - chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -4188,16 +3998,13 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} change-case@4.1.2: resolution: {integrity: sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==} - change-case@5.1.2: - resolution: {integrity: sha512-CAtbGEDulyjzs05RXy3uKcwqeztz/dMEuAc1Xu9NQBsbrhuGMneL0u9Dj5SoutLKBFYun8txxYIwhjtLNfUmCA==} - change-case@5.4.4: resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} @@ -4210,10 +4017,6 @@ packages: check-error@1.0.3: resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - check-error@2.1.1: - resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} - engines: {node: '>= 16'} - check-more-types@2.24.0: resolution: {integrity: sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==} engines: {node: '>= 0.8.0'} @@ -4221,8 +4024,8 @@ packages: chokidar@2.1.8: resolution: {integrity: sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==} - chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} chownr@1.1.4: @@ -4232,16 +4035,16 @@ packages: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} - chrome-trace-event@1.0.4: - resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} - engines: {node: '>=6.0'} - - ci-info@3.8.0: - resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} - cipher-base@1.0.4: - resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==} + cipher-base@1.0.6: + resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==} + engines: {node: '>= 0.10'} + + citty@0.1.6: + resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} class-utils@0.3.6: resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} @@ -4262,21 +4065,18 @@ packages: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} - cli-spinners@2.9.1: - resolution: {integrity: sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==} + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} - cli-table3@0.6.3: - resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} + cli-table3@0.6.5: + resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} engines: {node: 10.* || >= 12.*} cli-truncate@2.1.0: resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} engines: {node: '>=8'} - cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -4356,8 +4156,8 @@ packages: component-emitter@1.2.1: resolution: {integrity: sha512-jPatnhd33viNplKjqXKRkGU345p263OIWzDL2wH3LGIGp5Kojo+uXizHmOADRvhGFFTnJqX3jBAKP6vvmSDKcA==} - component-emitter@1.3.0: - resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} + component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} component-inherit@0.0.3: resolution: {integrity: sha512-w+LhYREhatpVqTESyGFg3NlP6Iu0kEKUHETY9GoZP/pQyW4mHFZuFWRUCIqVPZ36ueVLtoOEZaAqbCF2RDndaA==} @@ -4366,8 +4166,8 @@ packages: resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} engines: {node: '>= 0.6'} - compression@1.7.4: - resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} + compression@1.8.0: + resolution: {integrity: sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==} engines: {node: '>= 0.8.0'} concat-map@0.0.1: @@ -4377,6 +4177,9 @@ packages: resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} engines: {'0': node >= 0.8} + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + confusing-browser-globals@1.0.11: resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} @@ -4384,6 +4187,10 @@ packages: resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} engines: {node: '>= 0.10.0'} + consola@3.4.0: + resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==} + engines: {node: ^14.18.0 || >=16.10.0} + console-browserify@1.2.0: resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} @@ -4404,8 +4211,8 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} - contro-max@0.1.8: - resolution: {integrity: sha512-5SoeudO8Zzfj/gbFTDrMRFJny02+MY1lBtb2NyCNiBLtHAfvhWZxZs/Z3yJvKL2rY/qKUZs9gTQOIDygBcBrdw==} + contro-max@0.1.9: + resolution: {integrity: sha512-zH9FB60EzhHKublD92d11QuarYRTdYci5rvDgwDr5XXwUqae5mr6IgzXGcr78T2odnO/Aeqmrf32RDwJIl5GfQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} convert-source-map@1.9.0: @@ -4421,8 +4228,12 @@ packages: resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} engines: {node: '>= 0.6'} - cookie@0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} + engines: {node: '>= 0.6'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} copy-descriptor@0.1.1: @@ -4432,11 +4243,11 @@ packages: copy-to-clipboard@3.3.3: resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} - core-js-compat@3.32.1: - resolution: {integrity: sha512-GSvKDv4wE0bPnQtjklV101juQ85g6H3rm5PDP20mqlS5j0kXF3pP97YvAu5hl+uFHqMictp3b2VxOHljWMAtuA==} + core-js-compat@3.41.0: + resolution: {integrity: sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==} - core-js@3.37.1: - resolution: {integrity: sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw==} + core-js@3.41.0: + resolution: {integrity: sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==} core-util-is@1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} @@ -4456,15 +4267,6 @@ packages: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} - cosmiconfig@8.3.6: - resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=4.9.5' - peerDependenciesMeta: - typescript: - optional: true - create-ecdh@4.0.4: resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} @@ -4477,19 +4279,20 @@ packages: crelt@1.0.6: resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} - cross-spawn@6.0.5: - resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} + cross-spawn@6.0.6: + resolution: {integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==} engines: {node: '>=4.8'} - cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} crypt@0.0.2: resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} - crypto-browserify@3.12.0: - resolution: {integrity: sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==} + crypto-browserify@3.12.1: + resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==} + engines: {node: '>= 0.10'} crypto-random-string@2.0.0: resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} @@ -4509,8 +4312,8 @@ packages: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} - csstype@3.1.2: - resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} cypress-esbuild-preprocessor@1.0.2: resolution: {integrity: sha512-JsFnm6fBQt/OEzstknJ1KLMTuUERUaG0ZB9fk0KdNUlZqxaVEoQ9/pFvKmqRfzUe2y00cWD++ptccQA4tNAAlQ==} @@ -4542,8 +4345,8 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} - dayjs@1.11.9: - resolution: {integrity: sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==} + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} debounce@1.2.1: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} @@ -4599,6 +4402,15 @@ packages: supports-color: optional: true + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decamelize-keys@1.1.1: resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} engines: {node: '>=0.10.0'} @@ -4611,8 +4423,8 @@ packages: resolution: {integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==} engines: {node: '>=10'} - decode-named-character-reference@1.0.2: - resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + decode-named-character-reference@1.1.0: + resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==} decode-uri-component@0.2.2: resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} @@ -4626,12 +4438,8 @@ packages: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} - deep-eql@4.1.3: - resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} - engines: {node: '>=6'} - - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + deep-eql@4.1.4: + resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} engines: {node: '>=6'} deep-extend@0.6.0: @@ -4679,8 +4487,8 @@ packages: resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} engines: {node: '>=0.10.0'} - defu@6.1.2: - resolution: {integrity: sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==} + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} del@6.1.1: resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} @@ -4701,14 +4509,15 @@ packages: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} - dequal@1.0.0: - resolution: {integrity: sha512-/Nd1EQbQbI9UbSHrMiKZjFLrXSnU328iQdZKPQf78XQI6C+gutkFUeoHpG5J08Ioa6HeRbRNFpSIclh1xyG0mw==} - engines: {node: '>=6'} - dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + derive-valtio@0.1.0: + resolution: {integrity: sha512-OCg2UsLbXK7GmmpzMXhYkdO64vhJ1ROUUGaTFyHjVwEdMEcTTRj7W1TxLbSBxdY8QLBPCcp66MTyaSy0RpO17A==} + peerDependencies: + valtio: '*' + des.js@1.1.0: resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} @@ -4723,10 +4532,6 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} - detect-libc@2.0.2: - resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} - engines: {node: '>=8'} - detect-libc@2.0.3: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} @@ -4738,8 +4543,9 @@ packages: resolution: {integrity: sha512-j/lJHyoLlWi6G1LDdLgvUtz60Zo5GEj+sVYtTVXnYLDPuzgC3llMxonXym9zIwhhUII8vjdw0LXxavpLqTbl1A==} engines: {node: '>=12'} - detect-port@1.5.1: - resolution: {integrity: sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==} + detect-port@1.6.1: + resolution: {integrity: sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==} + engines: {node: '>= 4.0.0'} hasBin: true devlop@1.1.0: @@ -4806,8 +4612,8 @@ packages: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} - domutils@3.1.0: - resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} @@ -4816,12 +4622,12 @@ packages: resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} engines: {node: '>=12'} - dotenv@16.3.1: - resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} engines: {node: '>=12'} - draco3d@1.5.6: - resolution: {integrity: sha512-+3NaRjWktb5r61ZFoDejlykPEFKT5N/LkbXsaddlw6xNSXBanUYpFc2AXXpbJDilPHazcSreU/DpQIaxfX0NfQ==} + draco3d@1.5.7: + resolution: {integrity: sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==} dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} @@ -4845,16 +4651,16 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - ejs@3.1.9: - resolution: {integrity: sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==} + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} engines: {node: '>=0.10.0'} hasBin: true - electron-to-chromium@1.5.0: - resolution: {integrity: sha512-Vb3xHHYnLseK8vlMJQKJYXJ++t4u1/qJ3vykuVrVjvdiOEhYyT1AuP4x03G8EnPmYvYOhe9T+dADTmthjRQMkA==} + electron-to-chromium@1.5.113: + resolution: {integrity: sha512-wjT2O4hX+wdWPJ76gWSkMhcHAV2PTMX+QetUCPYEdCIe+cxmgzzSSiGRCKW8nuh4mwKZlpv0xvoW7OF2X+wmHg==} - elliptic@6.5.4: - resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} + elliptic@6.6.1: + resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} emit-then@2.0.0: resolution: {integrity: sha512-y5JHnrygHnCndtqVHHDhCr0ZzzWHK5RBTczWRlGSIR5UnGHBXuxpoaE0UB5E82qym8ma2dI799wDSSJN2e4VSg==} @@ -4883,31 +4689,27 @@ packages: endian-toggle@0.0.0: resolution: {integrity: sha512-ShfqhXeHRE4TmggSlHXG8CMGIcsOsqDw/GcoPcosToE59Rm9e4aXaMhEQf2kPBsBRrKem1bbOAv5gOKnkliMFQ==} - engine.io-client@3.5.3: - resolution: {integrity: sha512-qsgyc/CEhJ6cgMUwxRRtOndGVhIu5hpL5tR4umSpmX/MvkFoIxUTM7oFMDQumHNzlNLwSVy6qhstFPoWTf7dOw==} + engine.io-client@3.5.4: + resolution: {integrity: sha512-ydc8uuMMDxC5KCKNJN3zZKYJk2sgyTuTZQ7Aj1DJSsLKAcizA/PzWivw8fZMIjJVBo2CJOYzntv4FSjY/Lr//g==} - engine.io-client@6.5.2: - resolution: {integrity: sha512-CQZqbrpEYnrpGqC07a9dJDz4gePZUgTPMU3NKJPSeQOyw27Tst4Pl3FemKoFGAlHzgZmKjoRmiJvbWfhCXUlIg==} + engine.io-client@6.6.3: + resolution: {integrity: sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==} engine.io-parser@2.2.1: resolution: {integrity: sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==} - engine.io-parser@5.2.1: - resolution: {integrity: sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==} + engine.io-parser@5.2.3: + resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} engines: {node: '>=10.0.0'} - engine.io@3.6.1: - resolution: {integrity: sha512-dfs8EVg/i7QjFsXxn7cCRQ+Wai1G1TlEvHhdYEi80fxn5R1vZ2K661O6v/rezj1FP234SZ14r9CmJke99iYDGg==} + engine.io@3.6.2: + resolution: {integrity: sha512-C4JjGQZLY3kWlIDx0BQNKizbrfpb7NahxDztGdN5jrPK2ghmXiNDN+E/t0JzDeNRZxPVaszxEng42Pmj27X/0w==} engines: {node: '>=8.0.0'} - engine.io@6.5.3: - resolution: {integrity: sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==} + engine.io@6.6.4: + resolution: {integrity: sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==} engines: {node: '>=10.2.0'} - enhanced-resolve@5.17.1: - resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} - engines: {node: '>=10.13.0'} - enquirer@2.4.1: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} @@ -4920,8 +4722,8 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} - envinfo@7.10.0: - resolution: {integrity: sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==} + envinfo@7.14.0: + resolution: {integrity: sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==} engines: {node: '>=4'} hasBin: true @@ -4934,13 +4736,17 @@ packages: error-stack-parser@2.1.4: resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} - eruda@3.0.1: - resolution: {integrity: sha512-6q1Xdwga4JTr1mKSW4mzuWSSbmXgqpm/8Wa1QGFGfCWRjC0bCQjbS4u06M1te1moucIS3hBLlbSTPWYH2W0qbQ==} + eruda@3.4.1: + resolution: {integrity: sha512-RmaO5yD97URY/9Q0lye3cmmNPoXNKreeePIw7c/zllbscR92CjGFZFuQ70+0fLIvLcKW3Xha8DS8NFhmeNbEBQ==} es-abstract@1.23.9: resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} engines: {node: '>= 0.4'} + es-abstract@1.24.0: + resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} + engines: {node: '>= 0.4'} + es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -4956,12 +4762,6 @@ packages: es-module-lexer@0.9.3: resolution: {integrity: sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==} - es-module-lexer@1.5.4: - resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} - - es-module-lexer@1.6.0: - resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} - es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} @@ -4992,8 +4792,8 @@ packages: peerDependencies: esbuild: '*' - esbuild-register@3.5.0: - resolution: {integrity: sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==} + esbuild-register@3.6.0: + resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} peerDependencies: esbuild: '>=0.12 <1' @@ -5002,8 +4802,8 @@ packages: engines: {node: '>=12'} hasBin: true - esbuild@0.19.11: - resolution: {integrity: sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==} + esbuild@0.19.12: + resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} engines: {node: '>=12'} hasBin: true @@ -5012,8 +4812,8 @@ packages: engines: {node: '>=18'} hasBin: true - escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} escape-html@1.0.3: @@ -5078,8 +4878,8 @@ packages: eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - eslint-module-utils@2.8.0: - resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + eslint-module-utils@2.12.0: + resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -5127,17 +4927,17 @@ packages: peerDependencies: eslint: '>=5.16.0' - eslint-plugin-react-hooks@4.6.0: - resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} + eslint-plugin-react-hooks@5.2.0: + resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==} engines: {node: '>=10'} peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - eslint-plugin-react@7.34.1: - resolution: {integrity: sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==} + eslint-plugin-react@7.37.4: + resolution: {integrity: sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==} engines: {node: '>=4'} peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 eslint-plugin-sonarjs@0.19.0: resolution: {integrity: sha512-6+s5oNk5TFtVlbRxqZN7FIGmjdPCYQKaTzFPmqieCmsU1kBYDzndTeQav0xtQNwZJWu5awWfTGe8Srq9xFOGnw==} @@ -5151,10 +4951,6 @@ packages: peerDependencies: eslint: '>=8.44.0' - eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - eslint-scope@7.2.2: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5171,18 +4967,18 @@ packages: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-visitor-keys@4.0.0: - resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@8.50.0: - resolution: {integrity: sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==} + eslint@8.57.1: + resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true - espree@10.1.0: - resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} espree@9.6.1: @@ -5194,35 +4990,24 @@ packages: engines: {node: '>=4'} hasBin: true - esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} - estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - estree-to-babel@3.2.1: - resolution: {integrity: sha512-YNF+mZ/Wu2FU/gvmzuWtYc8rloubL7wfXCTgouFrnjGVXPA/EeYYA7pupXWrb3Iv1cTBeSSxxJIbK23l4MRNqg==} - engines: {node: '>=8.3.0'} - estree-walker@1.0.1: resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -5278,12 +5063,8 @@ packages: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} - expect-type@1.1.0: - resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==} - engines: {node: '>=12.0.0'} - - exponential-backoff@3.1.1: - resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} + exponential-backoff@3.1.2: + resolution: {integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==} express-ws@4.0.0: resolution: {integrity: sha512-KEyUw8AwRET2iFjFsI1EJQrJ/fHeGiJtgpYgEWG3yDv4l/To/m3a2GaYfeGyB3lsWdvbesjF5XCMx+SVBgAAYw==} @@ -5291,8 +5072,8 @@ packages: peerDependencies: express: ^4.0.0 || ^5.0.0-alpha.1 - express@4.18.2: - resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} + express@4.21.2: + resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} extend-shallow@2.0.1: @@ -5326,8 +5107,8 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-glob@3.3.1: - resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} fast-json-stable-stringify@2.1.0: @@ -5336,17 +5117,17 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-loops@1.1.3: - resolution: {integrity: sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g==} - fast-shallow-equal@1.0.0: resolution: {integrity: sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==} + fast-uri@3.0.6: + resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + fastest-stable-stringify@2.0.2: resolution: {integrity: sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==} - fastq@1.15.0: - resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} faye-websocket@0.11.4: resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} @@ -5385,24 +5166,24 @@ packages: filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - filesize@10.0.12: - resolution: {integrity: sha512-6RS9gDchbn+qWmtV2uSjo5vmKizgfCQeb5jKmqx8HyzA3MoLqqyQxN+QcjkGBJt7FjJ9qFce67Auyya5rRRbpw==} + filesize@10.1.6: + resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} engines: {node: '>= 10.4.0'} fill-range@4.0.0: resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} engines: {node: '>=0.10.0'} - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} finalhandler@1.1.2: resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} engines: {node: '>= 0.8'} - finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} find-cache-dir@2.1.0: @@ -5428,22 +5209,22 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - flat-cache@3.1.0: - resolution: {integrity: sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==} - engines: {node: '>=12.0.0'} + flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} flatmap@0.0.3: resolution: {integrity: sha512-OuR+o7kHVe+x9RtIujPay7Uw3bvDZBZFSBXClEphZuSDLmZTqMdclasf4vFSsogC8baDz0eaC2NdO/2dlXHBKQ==} - flatted@3.2.7: - resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} - flow-parser@0.218.0: - resolution: {integrity: sha512-mk4e7UK4P/W3tjrJyto6oxPuCjwvRMyzBh72hTl8T0dOcTzkP0M2JJHpncgyhKphMFi9pnjwHfc8e0oe4Uk3LA==} + flow-parser@0.263.0: + resolution: {integrity: sha512-F0Tr7SUvZ4BQYglFOkr8rCTO5FPjCwMhm/6i57h40F80Oz/hzzkqte4lGO0vGJ7THQonuXcTyYqCdKkAwt5d2w==} engines: {node: '>=0.4.0'} - follow-redirects@1.15.6: - resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} peerDependencies: debug: '*' @@ -5451,38 +5232,27 @@ packages: debug: optional: true - for-each@0.3.4: - resolution: {integrity: sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw==} + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} for-in@1.0.2: resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} engines: {node: '>=0.10.0'} - foreground-child@2.0.0: - resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} - engines: {node: '>=8.0.0'} - - foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} forever-agent@0.6.1: resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} - fork-ts-checker-webpack-plugin@9.0.2: - resolution: {integrity: sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==} - engines: {node: '>=12.13.0', yarn: '>=1.0.0'} - peerDependencies: - typescript: '>3.6.0' - webpack: ^5.11.0 - form-data@2.3.3: resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} engines: {node: '>= 0.12'} - form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} engines: {node: '>= 6'} forwarded@0.2.0: @@ -5493,24 +5263,42 @@ packages: resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} engines: {node: '>=0.10.0'} + framer-motion@12.9.2: + resolution: {integrity: sha512-R0O3Jdqbfwywpm45obP+8sTgafmdEcUoShQTAV+rB5pi+Y1Px/FYL5qLLRe5tPtBdN1J4jos7M+xN2VV2oEAbQ==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.2.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + from@0.1.7: resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - fs-extra@11.1.1: resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} engines: {node: '>=14.14'} + fs-extra@11.3.0: + resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} + engines: {node: '>=14.14'} + fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} @@ -5523,9 +5311,6 @@ packages: resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} engines: {node: '>= 8'} - fs-monkey@1.0.6: - resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==} - fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -5579,8 +5364,8 @@ packages: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} engines: {node: '>=6'} - get-npm-tarball-url@2.0.3: - resolution: {integrity: sha512-R/PW6RqyaBQNWYaSyfrh54/qtcnOp22FHCCiRhSSZj0FP3KQWCsxxt0DzIdVTbwTqe9CtQfvl/FPD4UIPt4pqw==} + get-npm-tarball-url@2.1.0: + resolution: {integrity: sha512-ro+DiMu5DXgRBabqXupW38h7WPZ9+Ad8UjwhvsmmN8w1sU7ab0nzAXvVZ4kqYg57OrqomRtJvepX5/xvFKNtjA==} engines: {node: '>=12.17'} get-own-enumerable-property-symbols@3.0.2: @@ -5610,8 +5395,8 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - get-tsconfig@4.7.2: - resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} + get-tsconfig@4.10.0: + resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} get-value@2.0.6: resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} @@ -5623,8 +5408,8 @@ packages: getpass@0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} - giget@1.1.3: - resolution: {integrity: sha512-zHuCeqtfgqgDwvXlR84UNgnJDuUHQcNI5OqWqFxxuk2BshuKbYhJWdxBsEo4PvKqoGh23lUAIvBNpChMLv7/9Q==} + giget@1.2.5: + resolution: {integrity: sha512-r1ekGw/Bgpi3HLV3h1MRBIlSAdHoIMklpaQ3OQLFcRw9PwAj2rqigvIbg+dBUI51OxVI2jsEtDywDBjSiuf7Ug==} hasBin: true github-from-package@0.0.0: @@ -5660,9 +5445,8 @@ packages: glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - glob@10.3.3: - resolution: {integrity: sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==} - engines: {node: '>=16 || 14 >=14.17'} + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true glob@7.2.3: @@ -5685,8 +5469,8 @@ packages: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - globals@13.21.0: - resolution: {integrity: sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==} + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} globalthis@1.0.4: @@ -5779,13 +5563,13 @@ packages: resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} engines: {node: '>=0.10.0'} - has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + has@1.0.4: + resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} engines: {node: '>= 0.4.0'} - hash-base@3.1.0: - resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} - engines: {node: '>=4'} + hash-base@3.0.5: + resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==} + engines: {node: '>= 0.10'} hash.js@1.1.7: resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} @@ -5822,11 +5606,8 @@ packages: resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} engines: {node: '>=12'} - html-entities@2.5.2: - resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} - - html-escaper@2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html-entities@2.6.0: + resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} html-tags@3.3.1: resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} @@ -5850,8 +5631,8 @@ packages: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} - http-parser-js@0.5.8: - resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} + http-parser-js@0.5.9: + resolution: {integrity: sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==} http-proxy-agent@5.0.0: resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} @@ -5881,10 +5662,6 @@ packages: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} - https-proxy-agent@7.0.2: - resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} - engines: {node: '>= 14'} - human-signals@1.1.1: resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} engines: {node: '>=8.12.0'} @@ -5896,8 +5673,12 @@ packages: humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - hyphenate-style-name@1.0.4: - resolution: {integrity: sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==} + hyperdyperid@1.2.0: + resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} + engines: {node: '>=10.18'} + + hyphenate-style-name@1.1.0: + resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==} iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} @@ -5913,8 +5694,8 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - ignore@5.2.4: - resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} image-size@0.7.5: @@ -5925,12 +5706,12 @@ packages: immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} - import-meta-resolve@3.0.0: - resolution: {integrity: sha512-4IwhLhNNA8yy445rPjD/lWh++7hMDOml2eHtd58eG7h+qK3EryMuuRbsHGPikCoAgIkkDnckKfWSk2iDla/ejg==} + import-meta-resolve@3.1.1: + resolution: {integrity: sha512-qeywsE/KC3w9Fd2ORrRDUw6nS/nLwZpXgfrOc2IILvZYnCaEMd+D56Vfg9k4G29gIeVi3XKql1RQatME8iYsiw==} imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} @@ -5967,18 +5748,16 @@ packages: resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} engines: {node: '>=10'} - inline-style-prefixer@6.0.4: - resolution: {integrity: sha512-FwXmZC2zbeeS7NzGjJ6pAiqRhXR0ugUShSNb6GApMl6da0/XGc4MOJsoWAywia52EEWbXNSy0pzkwz/+Y+swSg==} + inline-style-prefixer@7.0.1: + resolution: {integrity: sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==} internal-slot@1.1.0: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - invariant@2.2.4: - resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} - - ip@2.0.0: - resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} + ip-address@9.0.5: + resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + engines: {node: '>= 12'} ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} @@ -5992,8 +5771,8 @@ packages: resolution: {integrity: sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==} engines: {node: '>= 0.10'} - is-arguments@1.1.1: - resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} engines: {node: '>= 0.4'} is-array-buffer@3.0.5: @@ -6022,8 +5801,8 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} - is-boolean-object@1.2.1: - resolution: {integrity: sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==} + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} is-buffer@1.1.6: @@ -6134,6 +5913,10 @@ packages: resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} engines: {node: '>= 0.4'} + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + is-number-object@1.1.1: resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} @@ -6217,8 +6000,8 @@ packages: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} - is-weakref@1.1.0: - resolution: {integrity: sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==} + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} engines: {node: '>= 0.4'} is-weakset@2.0.4: @@ -6263,32 +6046,23 @@ packages: isstream@0.1.2: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} - istanbul-lib-coverage@3.2.0: - resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} istanbul-lib-instrument@5.2.1: resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} engines: {node: '>=8'} - istanbul-lib-report@3.0.1: - resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} - engines: {node: '>=10'} - - istanbul-reports@3.1.6: - resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} - engines: {node: '>=8'} - iterator.prototype@1.1.5: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} - jackspeak@2.3.0: - resolution: {integrity: sha512-uKmsITSsF4rUWQHzqaRUuyAir3fZfW3f202Ee34lz/gZCi970CPZwyQXLGNgWJvvZbvFyzeyGq0+4fcG/mBKZg==} - engines: {node: '>=14'} + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - jake@10.8.7: - resolution: {integrity: sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==} + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} engines: {node: '>=10'} hasBin: true @@ -6304,14 +6078,6 @@ packages: resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - jest-worker@26.6.2: - resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} - engines: {node: '>= 10.13.0'} - - jest-worker@27.5.1: - resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} - engines: {node: '>= 10.13.0'} - jest-worker@29.7.0: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6319,11 +6085,12 @@ packages: jimp@0.10.3: resolution: {integrity: sha512-meVWmDMtyUG5uYjFkmzu0zBgnCvvxwWNi27c4cg55vWNVC9ES4Lcwb+ogx+uBBQE3Q+dLKjXaLl0JVW+nUNwbQ==} - joi@17.13.1: - resolution: {integrity: sha512-vaBlIKCyo4FCUtCm7Eu4QZd/q02bWcxfUO6YSXAZOWF6gzcLBeba8kwotUdYJjDLW8Cz8RywsSOqiNJZW0mNvg==} + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true - jose@4.15.5: - resolution: {integrity: sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==} + joi@17.13.3: + resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} jpeg-js@0.3.7: resolution: {integrity: sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==} @@ -6348,26 +6115,32 @@ packages: jsbn@0.1.1: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} - jscodeshift@0.14.0: - resolution: {integrity: sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==} + jsbn@1.1.0: + resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + + jscodeshift@0.15.2: + resolution: {integrity: sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==} hasBin: true peerDependencies: '@babel/preset-env': ^7.1.6 + peerDependenciesMeta: + '@babel/preset-env': + optional: true jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true - jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - jsesc@3.0.2: resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} engines: {node: '>=6'} hasBin: true + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -6401,9 +6174,6 @@ packages: engines: {node: '>=6'} hasBin: true - jsonc-parser@3.2.0: - resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} @@ -6435,8 +6205,8 @@ packages: jws@3.2.2: resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} - keyv@4.5.3: - resolution: {integrity: sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==} + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} kind-of@3.2.2: resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} @@ -6499,17 +6269,13 @@ packages: engines: {node: '>=0.10.0'} hasBin: true - load-bmfont@1.4.1: - resolution: {integrity: sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==} + load-bmfont@1.4.2: + resolution: {integrity: sha512-qElWkmjW9Oq1F9EI5Gt7aD9zcdHb9spJCW1L/dmPf7KzCCEJxq8nhHz5eCgI9aMf7vrG/wyaCqdsI+Iy9ZTlog==} load-json-file@4.0.0: resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} engines: {node: '>=4'} - loader-runner@4.3.0: - resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} - engines: {node: '>=6.11.5'} - local-pkg@0.4.3: resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} engines: {node: '>=14'} @@ -6580,8 +6346,8 @@ packages: resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} engines: {node: '>=10'} - long@5.2.3: - resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + long@5.3.1: + resolution: {integrity: sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==} longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -6590,19 +6356,14 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - loupe@2.3.6: - resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} - deprecated: Please upgrade to 2.3.7 which fixes GHSA-4q6p-r6v2-jvc5 - - loupe@3.1.3: - resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} - lru-cache@10.0.1: - resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==} - engines: {node: 14 || >=16.14} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -6628,10 +6389,6 @@ packages: magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} - magic-string@0.30.4: - resolution: {integrity: sha512-Q/TKtsC5BPm0kGqgBIF9oXAs/xEf2vRKiIB4wCRQTJOQIByZ1d+NnUOotvJOvNpi5RNIgVOMC3pOuaP1ZTDlVg==} - engines: {node: '>=12'} - make-dir@2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} engines: {node: '>=6'} @@ -6640,10 +6397,6 @@ packages: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} - make-dir@4.0.0: - resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} - engines: {node: '>=10'} - make-fetch-happen@10.2.1: resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -6673,12 +6426,12 @@ packages: resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} engines: {node: '>=0.10.0'} - markdown-it@14.0.0: - resolution: {integrity: sha512-seFjF0FIcPt4P9U39Bq1JYblX0KZCjDLFFQPHpL5AzHpqPEKtosxmdq/LTVZnjfH7tjt9BxStm+wXcDBNuYmzw==} + markdown-it@14.1.0: + resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} hasBin: true - markdown-to-jsx@7.3.2: - resolution: {integrity: sha512-B+28F5ucp83aQm+OxNrPkS8z0tMKaeHiy0lHJs3LqCyDQFtWuenaIrkaVTgAm1pf1AU85LXltva86hlaT17i8Q==} + markdown-to-jsx@7.7.4: + resolution: {integrity: sha512-1bSfXyBKi+EYS3YY+e0Csuxf8oZ3decdfhOav/Z7Wrk89tjudyL5FOmwZQUoy0/qVXGUl+6Q3s2SWtpDEWITfQ==} engines: {node: '>= 10'} peerDependencies: react: ^18.2.0 @@ -6687,16 +6440,19 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - maxrects-packer@2.7.3: - resolution: {integrity: sha512-bG6qXujJ1QgttZVIH4WDanhoJtvbud/xP/XPyf6A69C9RdA61BM4TomFALCq2nrTa+tARRIBB4LuIFsnUQU2wA==} - - mc-assets@0.2.45: - resolution: {integrity: sha512-M1qnX73h/fW+mj9+A+jGtPaWDlq449DzPziZJxeLxmS1nSh/TSydKkLkWX967LaevVA1YtxNpA/SJ1N4jaW48w==} + mc-assets@0.2.62: + resolution: {integrity: sha512-RYZeD1+joNlPuUpi+tIWkbP0ieVJr+R6IFkI6/8juhSxx9zE4osoSmteybrfspGm8A6u+YbbY1epqRKEMwVR6Q==} engines: {node: '>=18.0.0'} - mcraft-fun-mineflayer@0.1.14: - resolution: {integrity: sha512-q/qXQaNbkGJIvXjRvudUT7/k0EsJgphFcvYjrSRWYyGDJeb61MKRVqq1hhMjqx7UK7FMfBKvjfPSxq/QlAP7WQ==} - version: 0.1.14 + mc-bridge@0.1.3: + resolution: {integrity: sha512-H9jPt2xEU77itC27dSz3qazHYqN9qVsv4HgMPozg7RqQ1uwgXmEa+ojKIlDtXf/TLJsG6Kv4EbzGa8a1Wh72uA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + minecraft-data: 3.98.0 + + mcraft-fun-mineflayer@0.1.23: + resolution: {integrity: sha512-qmI1rQQ0Ro5zJdi99rClWLF+mS9JZffgNX2vyWWesS3Hsk3Xblp/8swYTJKHSaFpNgzkVfXV92fEIrBqeH6iKA==} + version: 0.1.23 engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} peerDependencies: '@roamhq/wrtc': '*' @@ -6719,14 +6475,14 @@ packages: mdast-util-definitions@4.0.0: resolution: {integrity: sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==} - mdast-util-from-markdown@2.0.0: - resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} + mdast-util-from-markdown@2.0.2: + resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==} mdast-util-phrasing@4.1.0: resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} - mdast-util-to-markdown@2.1.0: - resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} + mdast-util-to-markdown@2.1.2: + resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} mdast-util-to-string@1.1.0: resolution: {integrity: sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==} @@ -6744,8 +6500,8 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - memfs@3.5.3: - resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} + memfs@4.17.0: + resolution: {integrity: sha512-4eirfZ7thblFmqFjywlTmuWVSvccHAJbn1r8qQLzmTO11qcqpohOjmY2mFce6x7x7WtskzRqApPD0hv+Oa74jg==} engines: {node: '>= 4.0.0'} memoize-one@6.0.0: @@ -6762,8 +6518,8 @@ packages: resolution: {integrity: sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - merge-descriptors@1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -6782,75 +6538,75 @@ packages: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} - micromark-core-commonmark@2.0.0: - resolution: {integrity: sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==} + micromark-core-commonmark@2.0.3: + resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} - micromark-factory-destination@2.0.0: - resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} - micromark-factory-label@2.0.0: - resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} - micromark-factory-space@2.0.0: - resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} + micromark-factory-space@2.0.1: + resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} - micromark-factory-title@2.0.0: - resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==} + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} - micromark-factory-whitespace@2.0.0: - resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} - micromark-util-character@2.1.0: - resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} - micromark-util-chunked@2.0.0: - resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} - micromark-util-classify-character@2.0.0: - resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==} + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} - micromark-util-combine-extensions@2.0.0: - resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==} + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} - micromark-util-decode-numeric-character-reference@2.0.1: - resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==} + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} - micromark-util-decode-string@2.0.0: - resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==} + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} - micromark-util-encode@2.0.0: - resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} - micromark-util-html-tag-name@2.0.0: - resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} - micromark-util-normalize-identifier@2.0.0: - resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==} + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} - micromark-util-resolve-all@2.0.0: - resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==} + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} - micromark-util-sanitize-uri@2.0.0: - resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} - micromark-util-subtokenize@2.0.0: - resolution: {integrity: sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==} + micromark-util-subtokenize@2.1.0: + resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} - micromark-util-symbol@2.0.0: - resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} - micromark-util-types@2.0.0: - resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} - micromark@4.0.0: - resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} + micromark@4.0.2: + resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} micromatch@3.1.10: resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} engines: {node: '>=0.10.0'} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} miller-rabin@4.0.1: @@ -6861,10 +6617,18 @@ packages: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime-types@3.0.1: + resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} + engines: {node: '>= 0.6'} + mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} @@ -6894,52 +6658,40 @@ packages: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} - minecraft-data@3.83.1: - resolution: {integrity: sha512-5K26za9k5WV1OnfkGexA77lBhfGZeFw3rT3NM7/rbFXRZC65prCx7Tk2BQvC9UfzgxxvmxHfxM5y8G1U+Oxgfg==} + minecraft-data@3.98.0: + resolution: {integrity: sha512-JAPqJ/TZoxMUlAPPdWUh1v5wdqvYGFSZ4rW9bUtmaKBkGpomDSjw4V02ocBqbxKJvcTtmc5nM/LfN9/0DDqHrQ==} minecraft-folder-path@1.2.0: resolution: {integrity: sha512-qaUSbKWoOsH9brn0JQuBhxNAzTDMwrOXorwuRxdJKKKDYvZhtml+6GVCUrY5HRiEsieBEjCUnhVpDuQiKsiFaw==} - minecraft-inventory-gui@https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/75e940a4cd50d89e0ba03db3733d5d704917a3c8: - resolution: {tarball: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/75e940a4cd50d89e0ba03db3733d5d704917a3c8} + minecraft-inventory-gui@https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/89c33d396f3fde4804c71f4be3c203ade1833b41: + resolution: {tarball: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/89c33d396f3fde4804c71f4be3c203ade1833b41} version: 1.0.1 - minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/3bd4dc1b2002cd7badfa5b9cf8dda35cd6cc9ac1: - resolution: {tarball: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/3bd4dc1b2002cd7badfa5b9cf8dda35cd6cc9ac1} - version: 1.54.0 + minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9: + resolution: {tarball: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9} + version: 1.62.0 engines: {node: '>=22'} - minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/5ec3dd4b367fcc039fbcb3edd214fe3cf8178a6d: - resolution: {tarball: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/5ec3dd4b367fcc039fbcb3edd214fe3cf8178a6d} - version: 1.54.0 - engines: {node: '>=22'} - - minecraft-wrap@1.5.1: - resolution: {integrity: sha512-7DZ2WhrcRD3fUMau84l9Va0KWzV92SHNdB7mnNdNhgXID2aW6pjWuYPZi8MepEBemA4XKKdnDx7HmhTbkoiR8A==} + minecraft-wrap@1.6.0: + resolution: {integrity: sha512-A1GjIR72x9H9cEaxAQsXZe5uhw7CPgq1pGwYkdbPe6mQraePinmj/jRIuntXYWEKrYamwQFT3igIafA+PEG11w==} hasBin: true - minecrafthawkeye@1.3.6: - resolution: {integrity: sha512-SlRlorxQs6nNzMiiIQ5z47wzbAI27UaCdbRB82CE8jqj4C8m3Gqk5TlgN+PSThxx8EDPXySzd8Vk+/wNigAd5A==} + minecrafthawkeye@1.3.9: + resolution: {integrity: sha512-YIDHTvljQjsJH4cEcbF02/ehNRUrbzEiL/quQmdEU8ruv69R4bwHqmBB8O9FyhpQgNppmNTs3pK8h4J0/MYGpQ==} mineflayer-item-map-downloader@https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824: resolution: {tarball: https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824} version: 1.2.0 - mineflayer-mouse@0.1.7: - resolution: {integrity: sha512-sUX77P8Z94N6N/KEvplZdXLwtuCHLx3lmU4Y1FB8189+jFCl3jH/+bdzwtksObmrXWW+evJ5nAPpzmOOxqcfag==} + mineflayer-mouse@0.1.21: + resolution: {integrity: sha512-1XTVuw3twIrEcqQ1QRSB8NcStIUEZ+tbxiAG6rOrN/9M4thhtlS5PTJzFdmdrcYgWEBLvuOdJszaKE5zFfiXhg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - mineflayer-pathfinder@2.4.4: - resolution: {integrity: sha512-HAXakZrJRb1UC+5dv8EaDrqjW3ZnBnBk3nkb6x/YWyhHCUKn/E7VU0FO+UN9whuqPlkSaVumEdXJdydE6lSYxQ==} - - mineflayer@4.25.0: - resolution: {integrity: sha512-q7cmpZFaSI6sodcMJxc2GkV8IO84HbsUP+xNipGKfGg+FMISKabzdJ838Axb60qRtZrp6ny7LluQE7lesHvvxQ==} - engines: {node: '>=18'} - - mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/06e3050ddf4d9aa655fea6e2bed182937a81705d: - resolution: {tarball: https://codeload.github.com/zardoy/mineflayer/tar.gz/06e3050ddf4d9aa655fea6e2bed182937a81705d} - version: 4.25.0 - engines: {node: '>=18'} + mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659: + resolution: {tarball: https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659} + version: 8.0.0 + engines: {node: '>=22'} minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} @@ -6954,6 +6706,10 @@ packages: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} + minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -6993,8 +6749,8 @@ packages: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} - minipass@7.0.3: - resolution: {integrity: sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} minizlib@2.1.2: @@ -7026,12 +6782,15 @@ packages: engines: {node: '>=10'} hasBin: true - mlly@1.4.2: - resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==} + mlly@1.7.4: + resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} mojangson@2.0.4: resolution: {integrity: sha512-HYmhgDjr1gzF7trGgvcC/huIg2L8FsVbi/KacRe6r1AswbboGVZDS47SOZlomPuMWvZLas8m9vuHHucdZMwTmQ==} + monaco-editor@0.52.2: + resolution: {integrity: sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==} + moo@0.5.2: resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==} @@ -7039,9 +6798,11 @@ packages: resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==} engines: {node: '>= 0.8.0'} - mri@1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} + motion-dom@12.9.1: + resolution: {integrity: sha512-xqXEwRLDYDTzOgXobSoWtytRtGlf7zdkRfFbrrdP7eojaGQZ5Go4OOKtgnx7uF8sAkfr1ZjMvbCJSCIT2h6fkQ==} + + motion-utils@12.8.3: + resolution: {integrity: sha512-GYVauZEbca8/zOhEiYOY9/uJeedYQld6co/GJFKOy//0c/4lDqk0zB549sBYqqV2iMuX+uHrY1E5zd8A2L+1Lw==} ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -7052,22 +6813,17 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nan@2.18.0: - resolution: {integrity: sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==} + nan@2.22.2: + resolution: {integrity: sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==} - nano-css@5.3.5: - resolution: {integrity: sha512-vSB9X12bbNu4ALBu7nigJgRViZ6ja3OU7CeuiV1zMIbXOdmkLahgtPmh3GBOlDxbKY0CitqlPdOReGlBLSp+yg==} + nano-css@5.6.2: + resolution: {integrity: sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==} peerDependencies: react: ^18.2.0 react-dom: '*' - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} + nanoid@3.3.9: + resolution: {integrity: sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -7075,8 +6831,8 @@ packages: resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} engines: {node: '>=0.10.0'} - napi-build-utils@1.0.2: - resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + napi-build-utils@2.0.0: + resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} natural-compare-lite@1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} @@ -7092,11 +6848,15 @@ packages: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - net-browserify@https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/624cc67c16f5e8b23b772e7eaabae16ba84b8590: - resolution: {tarball: https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/624cc67c16f5e8b23b772e7eaabae16ba84b8590} + net-browserify@https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/e754999ffdea67853bc9b10553b5e9908b40f618: + resolution: {tarball: https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/e754999ffdea67853bc9b10553b5e9908b40f618} version: 0.2.4 nice-try@1.0.5: @@ -7105,13 +6865,10 @@ packages: no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} - node-abi@3.47.0: - resolution: {integrity: sha512-2s6B2CWZM//kPgwnuI0KrYwNjfdByE25zvAaEpq9IH4zcNsarH8Ihu/UuX6XMPEogDAxkuUFeZn60pXNHAqn3A==} + node-abi@3.74.0: + resolution: {integrity: sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==} engines: {node: '>=10'} - node-abort-controller@3.1.1: - resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} - node-addon-api@5.1.0: resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} @@ -7122,8 +6879,8 @@ packages: resolution: {integrity: sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==} engines: {node: '>= 0.10.5'} - node-fetch-native@1.4.0: - resolution: {integrity: sha512-F5kfEj95kX8tkDhUCYdV8dg3/8Olx/94zB8+ZNthFs6Bz31UpUi8Xh40TN3thLwXgrwXry1pEg9lJ++tLWTcqA==} + node-fetch-native@1.6.6: + resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==} node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} @@ -7134,10 +6891,6 @@ packages: encoding: optional: true - node-gyp-build-optional-packages@5.1.1: - resolution: {integrity: sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==} - hasBin: true - node-gyp@9.4.1: resolution: {integrity: sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==} engines: {node: ^12.13 || ^14.13 || >=16} @@ -7146,14 +6899,14 @@ packages: node-gzip@1.1.2: resolution: {integrity: sha512-ZB6zWpfZHGtxZnPMrJSKHVPrRjURoUzaDbLFj3VO70mpLTW5np96vXyHwft4Id0o+PYIzgDkBUjIzaNHhQ8srw==} - node-html-parser@6.1.10: - resolution: {integrity: sha512-6/uWdWxjQWQ7tMcFK2wWlrflsQUzh1HsEzlIf2j5+TtzfhT2yUvg3DwZYAmjEHeR3uX74ko7exjHW69J0tOzIg==} + node-html-parser@6.1.13: + resolution: {integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==} node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - node-releases@2.0.18: - resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} node-rsa@0.4.2: resolution: {integrity: sha512-Bvso6Zi9LY4otIZefYrscsUpo2mUpiAVIEmSZV2q41sP8tHZoert3Yu6zv4f/RXJqMNZQKCtnhDugIuCma23YA==} @@ -7211,6 +6964,11 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + nypm@0.5.4: + resolution: {integrity: sha512-X0SNNrZiGU8/e/zAB7sCTtdxWTMSIO73q+xuKgglm2Yvzwlo8UoC5FNySQFCvl84uPaeADkqHUZUkWy4aH4xOA==} + engines: {node: ^14.16.0 || >=16.10.0} + hasBin: true + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -7219,12 +6977,12 @@ packages: resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} engines: {node: '>=0.10.0'} - object-inspect@1.13.3: - resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} - object-is@1.1.5: - resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} engines: {node: '>= 0.4'} object-keys@1.1.1: @@ -7239,18 +6997,14 @@ packages: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} - object.entries@1.1.8: - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} + object.entries@1.1.9: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} engines: {node: '>= 0.4'} object.fromentries@2.0.8: resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} engines: {node: '>= 0.4'} - object.hasown@1.1.4: - resolution: {integrity: sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==} - engines: {node: '>= 0.4'} - object.pick@1.3.0: resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} engines: {node: '>=0.10.0'} @@ -7294,8 +7048,8 @@ packages: engines: {node: '>=8'} deprecated: The package has been renamed to `open` - optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} ora@5.4.1: @@ -7347,6 +7101,9 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + pako@0.2.9: resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} @@ -7363,8 +7120,9 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} - parse-asn1@5.1.6: - resolution: {integrity: sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==} + parse-asn1@5.1.7: + resolution: {integrity: sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==} + engines: {node: '>= 0.10'} parse-bmfont-ascii@1.0.6: resolution: {integrity: sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==} @@ -7372,8 +7130,8 @@ packages: parse-bmfont-binary@1.0.6: resolution: {integrity: sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==} - parse-bmfont-xml@1.1.4: - resolution: {integrity: sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==} + parse-bmfont-xml@1.1.6: + resolution: {integrity: sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==} parse-headers@2.0.5: resolution: {integrity: sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==} @@ -7444,12 +7202,12 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@1.10.1: - resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} - engines: {node: '>=16 || 14 >=14.17'} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} - path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} path-type@3.0.0: resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} @@ -7459,8 +7217,8 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - pathe@1.1.1: - resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -7468,10 +7226,6 @@ packages: pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - pathval@2.0.0: - resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} - engines: {node: '>= 14.16'} - pause-stream@0.0.11: resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} @@ -7482,12 +7236,12 @@ packages: peek-stream@1.1.3: resolution: {integrity: sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==} - peerjs-js-binarypack@2.0.0: - resolution: {integrity: sha512-wu+L0Qeg4IH2DXm3B6xKP5ODeCIovwEEO/Fu3MVqApPQeVLzSdZpFzQzPobh+sdhUWMQGEO7YxHeiwpPngLjqQ==} + peerjs-js-binarypack@2.1.0: + resolution: {integrity: sha512-YIwCC+pTzp3Bi8jPI9UFKO0t0SLo6xALnHkiNt/iUFmUUZG0fEEmEyFKvjsDKweiFitzHRyhuh6NvyJZ4nNxMg==} engines: {node: '>= 14.0.0'} - peerjs@1.5.0: - resolution: {integrity: sha512-NLZ73jRNE4aLq2pmVTiSkWmwf6cvt9cH72qJHnzaLH+I2CtoWVvY42U9/O0/tYE6UYwRYJ1ktKRs2DdZ1Jrgcg==} + peerjs@1.5.4: + resolution: {integrity: sha512-yFsoLMnurJKlQbx6kVSBpOp+AlNldY1JQS2BrSsHLKCZnq6t7saHleuHM5svuLNbQkUJXHLF3sKOJB1K0xulOw==} engines: {node: '>= 14'} pend@1.2.0: @@ -7500,6 +7254,10 @@ packages: resolution: {integrity: sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==} deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + phin@3.7.1: + resolution: {integrity: sha512-GEazpTWwTZaEQ9RhL7Nyz0WwqilbqgLahDM3D0hxWwmVDI52nXEybHqiN6/elwpkJBhcuj+WbBu+QfT0uhPGfQ==} + engines: {node: '>= 8'} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -7551,8 +7309,8 @@ packages: resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==} engines: {node: '>=10'} - pkg-types@1.0.3: - resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} pluralize@8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} @@ -7562,29 +7320,25 @@ packages: resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==} engines: {node: '>=4.0.0'} - polished@4.2.2: - resolution: {integrity: sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==} + polished@4.3.1: + resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==} engines: {node: '>=10'} poly-decomp@0.3.0: resolution: {integrity: sha512-hWeBxGzPYiybmI4548Fca7Up/0k1qS5+79cVHI9+H33dKya5YNb9hxl0ZnDaDgvrZSuYFBhkCK/HOnqN7gefkQ==} - portfinder@1.0.32: - resolution: {integrity: sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==} + portfinder@1.0.33: + resolution: {integrity: sha512-+2jndHT63cL5MdQOwDm9OT2dIe11zVpjV+0GGRXdtO1wpPxv260NfVqoEXtYAi/shanmm3W4+yLduIe55ektTw==} engines: {node: '>= 0.12.0'} posix-character-classes@0.1.1: resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} engines: {node: '>=0.10.0'} - possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} - postcss@8.4.47: - resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.5.3: resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} @@ -7592,8 +7346,8 @@ packages: potpack@1.0.2: resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==} - prebuild-install@7.1.1: - resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} + prebuild-install@7.1.3: + resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} engines: {node: '>=10'} hasBin: true @@ -7627,35 +7381,35 @@ packages: resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==} engines: {node: '>= 0.8'} - prismarine-auth@2.4.2: - resolution: {integrity: sha512-Cq4woGobnFYYfMBDh1WITW+Vs98toN91qAFBvBitwV7IwJaiSAh2Nl+WPUEGeg5eLBoSPpSyCVT8P2oi7Cav8g==} + prismarine-auth@2.7.0: + resolution: {integrity: sha512-L8wTF6sdtnN6hViPNy+Nx39a8iQBwR5iO92AWCiym5cSXp/92pmnuwnTdcmNDWyqq6zY4hbibVGYhgLA1Ox8sQ==} prismarine-biome@1.3.0: resolution: {integrity: sha512-GY6nZxq93mTErT7jD7jt8YS1aPrOakbJHh39seYsJFXvueIOdHAmW16kYQVrTVMW5MlWLQVxV/EquRwOgr4MnQ==} peerDependencies: - minecraft-data: 3.83.1 + minecraft-data: 3.98.0 prismarine-registry: ^1.1.0 prismarine-block@https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9: resolution: {tarball: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9} version: 1.21.0 - prismarine-chat@1.10.1: - resolution: {integrity: sha512-XukYcuueuhDxzEXG7r8BZyt6jOObrPPB4JESCgb+/XenB9nExoSHF8eTQWWj8faKPLqm1dRQaYwFJlNBlJZJUw==} + prismarine-chat@1.11.0: + resolution: {integrity: sha512-VJT/MWYB3qoiznUhrgvSQh76YFpzpCZpY85kJKxHLbd3UVoM0wsfs43Eg8dOltiZG92wc5/DTMLlT07TEeoa9w==} - prismarine-chunk@https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/e68e9a423b5b1907535878fb636f12c28a1a9374: - resolution: {tarball: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/e68e9a423b5b1907535878fb636f12c28a1a9374} + prismarine-chunk@https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f: + resolution: {tarball: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f} version: 1.38.1 engines: {node: '>=14'} - prismarine-entity@2.3.1: - resolution: {integrity: sha512-HOv8l7IetHNf4hwZ7V/W4vM3GNl+e6VCtKDkH9h02TRq7jWngsggKtJV+VanCce/sNwtJUhJDjORGs728ep4MA==} + prismarine-entity@2.5.0: + resolution: {integrity: sha512-nRPCawUwf9r3iKqi4I7mZRlir1Ix+DffWYdWq6p/KNnmiXve+xHE5zv8XCdhZlUmOshugHv5ONl9o6ORAkCNIA==} - prismarine-item@1.16.0: - resolution: {integrity: sha512-88Tz+/6HquYIsDuseae5G3IbqLeMews2L+ba2gX+p6K6soU9nuFhCfbwN56QuB7d/jZFcWrCYAPE5+UhwWh67w==} + prismarine-item@1.17.0: + resolution: {integrity: sha512-wN1OjP+f+Uvtjo3KzeCkVSy96CqZ8yG7cvuvlGwcYupQ6ct7LtNkubHp0AHuLMJ0vbbfAC0oZ2bWOgI1DYp8WA==} - prismarine-nbt@2.5.0: - resolution: {integrity: sha512-F0/8UAa9SDDnAGrBYqZc4nG8h2zj5cE2eAJU5xlDR/IsQQ3moVxkOjE3h3nMv6SbvZrvAcgX7waA/nd9LLHYdA==} + prismarine-nbt@2.7.0: + resolution: {integrity: sha512-Du9OLQAcCj3y29YtewOJbbV4ARaSUEJiTguw0PPQbPBy83f+eCyDRkyBpnXTi/KPyEpgYCzsjGzElevLpFoYGQ==} prismarine-physics@https://codeload.github.com/zardoy/prismarine-physics/tar.gz/353e25b800149393f40539ec381218be44cbb03b: resolution: {tarball: https://codeload.github.com/zardoy/prismarine-physics/tar.gz/353e25b800149393f40539ec381218be44cbb03b} @@ -7726,20 +7480,20 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - prosemirror-commands@1.5.2: - resolution: {integrity: sha512-hgLcPaakxH8tu6YvVAaILV2tXYsW3rAdDR8WNkeKGcgeMVQg3/TMhPdVoh7iAmfgVjZGtcOSjKiQaoeKjzd2mQ==} + prosemirror-commands@1.7.0: + resolution: {integrity: sha512-6toodS4R/Aah5pdsrIwnTYPEjW70SlO5a66oo5Kk+CIrgJz3ukOoS+FYDGqvQlAX5PxoGWDX1oD++tn5X3pyRA==} prosemirror-dropcursor@1.8.1: resolution: {integrity: sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==} - prosemirror-example-setup@1.2.2: - resolution: {integrity: sha512-pHJc656IgYm249RNp0eQaWNmnyWGk6OrzysWfYI4+NwE14HQ7YNYOlRBLErUS6uCAHIYJLNXf0/XCmf1OCtNbQ==} + prosemirror-example-setup@1.2.3: + resolution: {integrity: sha512-+hXZi8+xbFvYM465zZH3rdZ9w7EguVKmUYwYLZjIJIjPK+I0nPTwn8j0ByW2avchVczRwZmOJGNvehblyIerSQ==} prosemirror-gapcursor@1.3.2: resolution: {integrity: sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==} - prosemirror-history@1.3.2: - resolution: {integrity: sha512-/zm0XoU/N/+u7i5zepjmZAEnpvjDtzoPWW6VmKptcAnPadN/SStsBjMImdCEbb3seiNTpveziPTIrXQbHLtU1g==} + prosemirror-history@1.4.1: + resolution: {integrity: sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==} prosemirror-inputrules@1.4.0: resolution: {integrity: sha512-6ygpPRuTJ2lcOXs9JkefieMst63wVJBgHZGl5QOytN7oSZs3Co/BYbc3Yx9zm9H37Bxw8kVzCnDsihsVsL4yEg==} @@ -7747,29 +7501,29 @@ packages: prosemirror-keymap@1.2.2: resolution: {integrity: sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==} - prosemirror-markdown@1.12.0: - resolution: {integrity: sha512-6F5HS8Z0HDYiS2VQDZzfZP6A0s/I0gbkJy8NCzzDMtcsz3qrfqyroMMeoSjAmOhDITyon11NbXSzztfKi+frSQ==} + prosemirror-markdown@1.13.1: + resolution: {integrity: sha512-Sl+oMfMtAjWtlcZoj/5L/Q39MpEnVZ840Xo330WJWUvgyhNmLBLN7MsHn07s53nG/KImevWHSE6fEj4q/GihHw==} prosemirror-menu@1.2.4: resolution: {integrity: sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==} - prosemirror-model@1.19.4: - resolution: {integrity: sha512-RPmVXxUfOhyFdayHawjuZCxiROsm9L4FCUA6pWI+l7n2yCBsWy9VpdE1hpDHUS8Vad661YLY9AzqfjLhAKQ4iQ==} + prosemirror-model@1.24.1: + resolution: {integrity: sha512-YM053N+vTThzlWJ/AtPtF1j0ebO36nvbmDy4U7qA2XQB8JVaQp1FmB9Jhrps8s+z+uxhhVTny4m20ptUvhk0Mg==} - prosemirror-schema-list@1.3.0: - resolution: {integrity: sha512-Hz/7gM4skaaYfRPNgr421CU4GSwotmEwBVvJh5ltGiffUJwm7C8GfN/Bc6DR1EKEp5pDKhODmdXXyi9uIsZl5A==} + prosemirror-schema-list@1.5.1: + resolution: {integrity: sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==} prosemirror-state@1.4.3: resolution: {integrity: sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==} - prosemirror-transform@1.8.0: - resolution: {integrity: sha512-BaSBsIMv52F1BVVMvOmp1yzD3u65uC3HTzCBQV1WDPqJRQ2LuHKcyfn0jwqodo8sR9vVzMzZyI+Dal5W9E6a9A==} + prosemirror-transform@1.10.3: + resolution: {integrity: sha512-Nhh/+1kZGRINbEHmVu39oynhcap4hWTs/BlU7NnxWj3+l0qi8I1mu67v6mMdEe/ltD8hHvU4FV6PHiCw2VSpMw==} - prosemirror-view@1.33.1: - resolution: {integrity: sha512-62qkYgSJIkwIMMCpuGuPzc52DiK1Iod6TWoIMxP4ja6BTD4yO8kCUL64PZ/WhH/dJ9fW0CDO39FhH1EMyhUFEg==} + prosemirror-view@1.38.1: + resolution: {integrity: sha512-4FH/uM1A4PNyrxXbD+RAbAsf0d/mM0D/wAKSVVWK7o0A9Q/oOXJBrw786mBf2Vnrs/Edly6dH6Z2gsb7zWwaUw==} - protodef-validator@1.3.1: - resolution: {integrity: sha512-lZ5FWKZYR9xOjpMw1+EfZRfCjzNRQWPq+Dk+jki47Sikl2EeWEPnTfnJERwnU/EwFq6us+0zqHHzSsmLeYX+Lg==} + protodef-validator@1.4.0: + resolution: {integrity: sha512-2y2coBolqCEuk5Kc3QwO7ThR+/7TZiOit4FrpAgl+vFMvq8w76nDhh09z08e2NQOdrgPLsN2yzXsvRvtADgUZQ==} hasBin: true protodef@1.18.0: @@ -7783,6 +7537,9 @@ packages: proxy-compare@2.5.1: resolution: {integrity: sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA==} + proxy-compare@2.6.0: + resolution: {integrity: sha512-8xuCeM3l8yqdmbPoYeLbrAXCBWu19XEYc5/F28f5qOaoAIMyfmBUkl5axiK+x9olUvRlcekvnm98AP9RDngOIw==} + proxy-from-env@1.0.0: resolution: {integrity: sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==} @@ -7793,8 +7550,8 @@ packages: resolution: {integrity: sha512-EGCG8SeoIRVMhsqHQUdDigB2i7qU7fCsWASwn54+nPutYO8n4q6EiwMzyfWlC+dzRFExP+kvcnDFdBDHoZBU7Q==} engines: {node: '>=0.8.0'} - psl@1.9.0: - resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} public-encrypt@4.0.3: resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} @@ -7802,8 +7559,8 @@ packages: pump@2.0.1: resolution: {integrity: sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==} - pump@3.0.0: - resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} pumpify@1.5.1: resolution: {integrity: sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==} @@ -7823,8 +7580,8 @@ packages: resolution: {integrity: sha512-n13AWriBMPYxnpbb6bnaY5YoY6rGj8vPLrz6CZF3o0qJNEwlcfJVxBzYZ0NJsQ21UbdJoijPCDrM++SUVEz7+w==} engines: {node: '>=8.16.0'} - qrcode.react@3.1.0: - resolution: {integrity: sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==} + qrcode.react@3.2.0: + resolution: {integrity: sha512-YietHHltOHA4+l5na1srdaMx4sVSOjV9tamHs+mwiLWAMr6QVACRUw1Neax5CptFILcNoITctJY0Ipyn5enQ8g==} peerDependencies: react: ^18.2.0 @@ -7832,12 +7589,12 @@ packages: resolution: {integrity: sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==} engines: {node: '>=0.6'} - qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} engines: {node: '>=0.6'} - qs@6.11.2: - resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} querystring-es3@0.2.1: @@ -7863,8 +7620,8 @@ packages: rambda@6.9.0: resolution: {integrity: sha512-yosVdGg1hNGkXPzqGiOYNEpXKjEOxzUCg2rB0l+NKdyCaSf4z+i5ojbN0IqDSezMMf71YEglI+ZUTgTffn5afw==} - rambda@9.2.0: - resolution: {integrity: sha512-RjM8TBNPR+iSvWLqbBpFveDfEf2RPRKHuwBHjQdXsYFDwn3MIvgmJiqVVC1CIQKnOwzeDQd44zqDFgSKQ7RT1Q==} + rambda@9.4.2: + resolution: {integrity: sha512-++euMfxnl7OgaEKwXh9QqThOjMeta2HH001N1v4mYQzBjJBnmXBh2BCK6dZAbICFVXOFUVD3xFG0R3ZPU0mxXw==} ramda@0.29.0: resolution: {integrity: sha512-BBea6L67bYLtdbOqfp8f58fPMqEwx0doL+pAi8TZyp2YWz8R9G8z9x75CZI8W+ftqhFHCpEX2cRnUUXK130iKA==} @@ -7892,10 +7649,6 @@ packages: engines: {node: '>=0.8'} deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. - raw-body@2.5.1: - resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} - engines: {node: '>= 0.8'} - raw-body@2.5.2: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} @@ -7918,13 +7671,12 @@ packages: peerDependencies: typescript: '>= 4.3.x' - react-docgen@6.0.0-alpha.3: - resolution: {integrity: sha512-DDLvB5EV9As1/zoUsct6Iz2Cupw9FObEGD3DMcIs3EDFIoSKyz8FZtoWj3Wj+oodrU4/NfidN0BL5yrapIcTSA==} - engines: {node: '>=12.0.0'} - hasBin: true + react-docgen@7.1.1: + resolution: {integrity: sha512-hlSJDQ2synMPKFZOsKo9Hi8WWZTC7POR8EmWvTSjow+VDgKzkmjQvFm2fk0tmRw+f0vTOIYKlarR0iL4996pdg==} + engines: {node: '>=16.14.0'} - react-dom@18.2.0: - resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: react: ^18.2.0 @@ -7937,14 +7689,9 @@ packages: react-fast-compare@3.2.2: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} - react-hook-form@7.52.0: - resolution: {integrity: sha512-mJX506Xc6mirzLsmXUJyqlAI3Kj9Ph2RhplYhUVffeOQSnubK2uVqBFOBJmvKikvbFV91pxVXmDiR+QMF19x6A==} - engines: {node: '>=12.22.0'} - peerDependencies: - react: ^18.2.0 - - react-inspector@6.0.2: - resolution: {integrity: sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==} + react-hook-form@7.54.2: + resolution: {integrity: sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==} + engines: {node: '>=18.0.0'} peerDependencies: react: ^18.2.0 @@ -7954,8 +7701,8 @@ packages: react-is@18.1.0: resolution: {integrity: sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==} - react-is@18.2.0: - resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} react-popper@2.3.0: resolution: {integrity: sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==} @@ -7974,11 +7721,15 @@ packages: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} - react-remove-scroll-bar@2.3.4: - resolution: {integrity: sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==} + react-refresh@0.17.0: + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} + engines: {node: '>=0.10.0'} + + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + '@types/react': '*' react: ^18.2.0 peerDependenciesMeta: '@types/react': @@ -7994,17 +7745,17 @@ packages: '@types/react': optional: true - react-select@5.8.0: - resolution: {integrity: sha512-TfjLDo58XrhP6VG5M/Mi56Us0Yt8X7xD6cDybC7yoRMUNm7BGO7qk8J0TLQOua/prb8vUOtsfnXZwfm30HGsAA==} + react-select@5.10.1: + resolution: {integrity: sha512-roPEZUL4aRZDx6DcsD+ZNreVl+fM8VsKn0Wtex1v4IazH60ILp5xhdlp464IsEAlJdXeD+BhDAFsBVMfvLQueA==} peerDependencies: react: ^18.2.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-style-singleton@2.2.1: - resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + '@types/react': '*' react: ^18.2.0 peerDependenciesMeta: '@types/react': @@ -8041,8 +7792,8 @@ packages: react: ^18.2.0 react-dom: '*' - react@18.2.0: - resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} read-pkg-up@7.0.1: @@ -8075,8 +7826,8 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} - readable-stream@4.5.2: - resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} readdirp@2.2.1: @@ -8090,27 +7841,23 @@ packages: readline@1.3.0: resolution: {integrity: sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==} - recast@0.21.5: - resolution: {integrity: sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==} - engines: {node: '>= 4'} - - recast@0.23.4: - resolution: {integrity: sha512-qtEDqIZGVcSZCHniWwZWbRy79Dc6Wp3kT/UmDA2RJKBPg7+7k51aQBZirHmUGn5uvHf2rg8DkjizrN26k61ATw==} + recast@0.23.11: + resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} engines: {node: '>= 4'} redent@4.0.0: resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==} engines: {node: '>=12'} - reduce-configs@1.0.0: - resolution: {integrity: sha512-/JCYSgL/QeXXsq0Lv/7kOZfqvof7vyzHWfyNQPt3c6vc73mU4WRyT8RJ6ZH5Ci08vUOqXwk7jkZy6BycHTDD9w==} + reduce-configs@1.1.0: + resolution: {integrity: sha512-DQxy6liNadHfrLahZR7lMdc227NYVaQZhY5FMsxLEjX8X0SCuH+ESHSLCoz2yDZFq1/CLMDOAHdsEHwOEXKtvg==} reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} - regenerate-unicode-properties@10.1.0: - resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==} + regenerate-unicode-properties@10.2.0: + resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} engines: {node: '>=4'} regenerate@1.4.2: @@ -8119,8 +7866,8 @@ packages: regenerator-runtime@0.13.11: resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} - regenerator-runtime@0.14.0: - resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} regenerator-transform@0.15.2: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} @@ -8141,16 +7888,19 @@ packages: resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} engines: {node: '>=8'} - regexpu-core@5.3.2: - resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} + regexpu-core@6.2.0: + resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} engines: {node: '>=4'} + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + regjsparser@0.10.0: resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} hasBin: true - regjsparser@0.9.1: - resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} + regjsparser@0.12.0: + resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} hasBin: true remark-external-links@8.0.0: @@ -8211,8 +7961,9 @@ packages: resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} deprecated: https://github.com/lydell/resolve-url#deprecated - resolve@1.22.4: - resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} hasBin: true resolve@2.0.0-next.5: @@ -8231,12 +7982,12 @@ packages: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rfdc@1.3.0: - resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} rimraf@2.6.3: resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} @@ -8253,32 +8004,25 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - rimraf@5.0.1: - resolution: {integrity: sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==} - engines: {node: '>=14'} + rimraf@5.0.10: + resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} hasBin: true ripemd160@2.0.2: resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} - rollup-plugin-terser@7.0.2: - resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} - deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser - peerDependencies: - rollup: ^2.0.0 - - rollup@2.79.1: - resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} + rollup@2.79.2: + resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} engines: {node: '>=10.0.0'} hasBin: true - rollup@3.29.4: - resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} + rollup@3.29.5: + resolution: {integrity: sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true - rollup@4.34.8: - resolution: {integrity: sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==} + rollup@4.34.9: + resolution: {integrity: sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -8291,8 +8035,8 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} safe-array-concat@1.1.3: resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} @@ -8324,15 +8068,11 @@ packages: sat@0.9.0: resolution: {integrity: sha512-mxdv5RZJO4tdMnUURGU3gAMcnDUEwcNJwE+lPO0/V+rBeDvFLH3wEZEOR0fH7cTN0zQaNxBEbHnyQL9DzupwQQ==} - sax@1.3.0: - resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} + sax@1.4.1: + resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} - scheduler@0.23.0: - resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} - - schema-utils@3.3.0: - resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} - engines: {node: '>= 10.13.0'} + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} screenfull@5.2.0: resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} @@ -8352,30 +8092,22 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} - engines: {node: '>=10'} - hasBin: true - semver@7.7.1: resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} engines: {node: '>=10'} hasBin: true - send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} - send@1.1.0: - resolution: {integrity: sha512-v67WcEouB5GxbTWL/4NeToqcZiAWEq90N888fczVArY8A79J0L4FD7vj5hm3eUMua5EpoQ59wa/oovY6TLvRUA==} + send@1.2.0: + resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} engines: {node: '>= 18'} sentence-case@3.0.4: resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==} - serialize-javascript@4.0.0: - resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} - serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} @@ -8383,8 +8115,8 @@ packages: resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} engines: {node: '>= 0.8.0'} - serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} set-blocking@2.0.0: @@ -8451,8 +8183,9 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shell-quote@1.8.1: - resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} + shell-quote@1.8.2: + resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==} + engines: {node: '>= 0.4'} side-channel-list@1.0.0: resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} @@ -8492,18 +8225,14 @@ packages: simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - simple-update-notifier@2.0.0: - resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} - engines: {node: '>=10'} - sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} skinview-utils@0.7.1: resolution: {integrity: sha512-4eLrMqR526ehlZbsd8SuZ/CHpS9GiH0xUMoV+PYlJVi95ZFz5HJu7Spt5XYa72DRS7wgt5qquvHZf0XZJgmu9Q==} - skinview3d@3.0.1: - resolution: {integrity: sha512-2LUSkzGxlZrTQelGT10jcW4TLiFTg5aZqXMEuqAFoWtk3qtaNu0qRFtwK5dN8zEXyKUJ3xlxah5eGtKY/NifQg==} + skinview3d@3.1.0: + resolution: {integrity: sha512-L+HXXAP4qYjLcY3YHasXKie9KXQpv/mPTMxgLOEd+hVQRdQkPs5xdWaKuOmlZY8UnyZzecQM7yrWRzgT/e7HZw==} slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} @@ -8521,6 +8250,9 @@ packages: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + smob@1.5.0: + resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} + snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} @@ -8539,18 +8271,18 @@ packages: socket.io-adapter@1.1.2: resolution: {integrity: sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==} - socket.io-adapter@2.5.2: - resolution: {integrity: sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==} + socket.io-adapter@2.5.5: + resolution: {integrity: sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==} socket.io-client@2.5.0: resolution: {integrity: sha512-lOO9clmdgssDykiOmVQQitwBAF3I6mYcQAo7hQ7AM6Ny5X7fp8hIJ3HcQs3Rjz4SoggoxA1OgrQyY8EgTbcPYw==} - socket.io-client@4.7.2: - resolution: {integrity: sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==} + socket.io-client@4.8.1: + resolution: {integrity: sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==} engines: {node: '>=10.0.0'} - socket.io-parser@3.3.3: - resolution: {integrity: sha512-qOg87q1PMWWTeO01768Yh9ogn7chB9zkKtQnya41Y355S0UmpXgpcrFwAgjYJxu9BdKug5r5e9YtVSeWhKBUZg==} + socket.io-parser@3.3.4: + resolution: {integrity: sha512-z/pFQB3x+EZldRRzORYW1vwVO8m/3ILkswtnpoeU6Ve3cbMWkmHEWDAVJn4QJtchiiFTo5j7UG2QvwxvaA9vow==} socket.io-parser@3.4.3: resolution: {integrity: sha512-1rE4dZN3kCI/E5wixd393hmbqa78vVpkKmnEJhLeWoS/C5hbFYAbcSfnWoaVH43u9ToUVtzKjguxEZq+1XZfCQ==} @@ -8560,20 +8292,20 @@ packages: resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} engines: {node: '>=10.0.0'} - socket.io@2.5.0: - resolution: {integrity: sha512-gGunfS0od3VpwDBpGwVkzSZx6Aqo9uOcf1afJj2cKnKFAoyl16fvhpsUhmUFd4Ldbvl5JvRQed6eQw6oQp6n8w==} + socket.io@2.5.1: + resolution: {integrity: sha512-eaTE4tBKRD6RFoetquMbxgvcpvoDtRyIlkIMI/SMK2bsKvbENTsDeeu4GJ/z9c90yOWxB7b/eC+yKLPbHnH6bA==} - socket.io@4.7.2: - resolution: {integrity: sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==} + socket.io@4.8.1: + resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==} engines: {node: '>=10.2.0'} socks-proxy-agent@7.0.0: resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} engines: {node: '>= 10'} - socks@2.7.1: - resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} - engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} + socks@2.8.4: + resolution: {integrity: sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} @@ -8605,6 +8337,7 @@ packages: source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions sourcemap-codec@1.4.8: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} @@ -8616,14 +8349,14 @@ packages: spdx-correct@3.2.0: resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - spdx-exceptions@2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - spdx-license-ids@3.0.13: - resolution: {integrity: sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==} + spdx-license-ids@3.0.21: + resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} split-string@3.1.0: resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} @@ -8635,8 +8368,11 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - sshpk@1.17.0: - resolution: {integrity: sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==} + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + sshpk@1.18.0: + resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} engines: {node: '>=0.10.0'} hasBin: true @@ -8659,12 +8395,15 @@ packages: stacktrace-js@2.0.2: resolution: {integrity: sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==} + state-local@1.0.7: + resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} + static-extend@0.1.2: resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} engines: {node: '>=0.10.0'} - stats-gl@1.0.5: - resolution: {integrity: sha512-XimMxvwnf1Qf5KwebhcoA34kcX+fWEkIl0QjNkCbu4IpoyDMMsOajExn7FIq5w569k45+LhmsuRlGSrsvmGdNw==} + stats-gl@1.0.7: + resolution: {integrity: sha512-vZI82CjefSxLC1bjw36z28v0+QE9rJKymGlXtfWu+ipW70ZEAwa4EbO4LxluAfLfpqiaAS04NzpYBRLDeAwYWQ==} stats.js@0.17.0: resolution: {integrity: sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==} @@ -8677,17 +8416,22 @@ packages: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} - std-env@3.4.3: - resolution: {integrity: sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q==} + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} - std-env@3.8.0: - resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} + std-env@3.8.1: + resolution: {integrity: sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==} - store2@2.14.2: - resolution: {integrity: sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w==} + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} - storybook@7.4.6: - resolution: {integrity: sha512-YkFSpnR47j5zz7yElA+2axLjXN7K7TxDGJRHHlqXmG5iQ0PXzmjrj2RxMDKFz4Ybp/QjEUoJ4rx//ESEY0Nb5A==} + store2@2.14.4: + resolution: {integrity: sha512-srTItn1GOvyvOycgxjAnPA63FZNwy0PTyUBFMHRM+hVFltAeoh0LmNBz9SZqUS9mMqGk8rfyWyXn3GH5ReJ8Zw==} + + storybook@7.6.20: + resolution: {integrity: sha512-Wt04pPTO71pwmRmsgkyZhNo4Bvdb/1pBAMsIFb9nQLykEdzzpXjvingxFFvdOG4nIowzwgxD+CLlyRqVJqnATw==} hasBin: true stream-browserify@3.0.0: @@ -8699,8 +8443,8 @@ packages: stream-http@3.2.0: resolution: {integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==} - stream-shift@1.0.1: - resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==} + stream-shift@1.0.3: + resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} strict-event-emitter-types@2.0.0: resolution: {integrity: sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==} @@ -8717,10 +8461,13 @@ packages: resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} engines: {node: '>= 0.4'} - string.prototype.padend@3.1.4: - resolution: {integrity: sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==} + string.prototype.padend@3.1.6: + resolution: {integrity: sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==} engines: {node: '>= 0.4'} + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + string.prototype.trim@1.2.10: resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} @@ -8788,6 +8535,9 @@ packages: stylis@4.2.0: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + stylis@4.3.6: + resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -8807,8 +8557,8 @@ packages: synchronous-promise@2.0.17: resolution: {integrity: sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==} - systeminformation@5.22.7: - resolution: {integrity: sha512-AWxlP05KeHbpGdgvZkcudJpsmChc2Y5Eo/GvxG/iUA/Aws5LZKHAMSeAo+V+nD+nxWZaxrwpWcnx4SH3oxNL3A==} + systeminformation@5.25.11: + resolution: {integrity: sha512-jI01fn/t47rrLTQB0FTlMCC+5dYx8o0RRF+R4BPiUNsvg5OdY0s9DKMFmJGrx5SwMZQ4cag0Gl6v8oycso9b/g==} engines: {node: '>=8.0.0'} os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android] hasBin: true @@ -8816,19 +8566,15 @@ packages: tabbable@6.2.0: resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} - tapable@2.2.1: - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} - engines: {node: '>=6'} - - tar-fs@2.1.1: - resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + tar-fs@2.1.2: + resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==} tar-stream@2.2.0: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} - tar@6.2.0: - resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} telejson@7.2.0: @@ -8850,24 +8596,8 @@ packages: resolution: {integrity: sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==} engines: {node: '>=10'} - terser-webpack-plugin@5.3.10: - resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@swc/core': '*' - esbuild: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@swc/core': - optional: true - esbuild: - optional: true - uglify-js: - optional: true - - terser@5.31.3: - resolution: {integrity: sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==} + terser@5.39.0: + resolution: {integrity: sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==} engines: {node: '>=10'} hasBin: true @@ -8885,8 +8615,14 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - three-stdlib@2.28.5: - resolution: {integrity: sha512-JdLMhkpT+1ZWeQPyKQNW1zqUwISI2hsUljS6u3vB9lp5EvwsayaAzGnbVeR35895udOF+zxcTiQY3psk+qqlxg==} + thingies@1.21.0: + resolution: {integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==} + engines: {node: '>=10.18'} + peerDependencies: + tslib: ^2 + + three-stdlib@2.35.14: + resolution: {integrity: sha512-kpCaEg59M9usFTgHC+YZNKvx7nMoLI2zQxZBV8pjoNW6vNZmGyXpaLBL09A2oLCsS3KepgMFkOuk6lRoebTNvA==} peerDependencies: three: 0.154.0 @@ -8900,8 +8636,8 @@ packages: resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} engines: {node: '>=10'} - throttleit@1.0.0: - resolution: {integrity: sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==} + throttleit@1.0.1: + resolution: {integrity: sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==} through2@0.6.5: resolution: {integrity: sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==} @@ -8919,11 +8655,8 @@ packages: timm@1.7.1: resolution: {integrity: sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==} - tiny-invariant@1.3.1: - resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} - - tinybench@2.5.1: - resolution: {integrity: sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==} + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -8938,28 +8671,16 @@ packages: resolution: {integrity: sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==} engines: {node: '>=14.0.0'} - tinypool@1.0.2: - resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} - engines: {node: ^18.0.0 || >=20.0.0} - - tinyrainbow@2.0.0: - resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} - engines: {node: '>=14.0.0'} - - tinyspy@2.2.0: - resolution: {integrity: sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==} - engines: {node: '>=14.0.0'} - - tinyspy@3.0.2: - resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + tinyspy@2.2.1: + resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} engines: {node: '>=14.0.0'} title-case@3.0.3: resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==} - tmp@0.2.1: - resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==} - engines: {node: '>=8.17.0'} + tmp@0.2.3: + resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} + engines: {node: '>=14.14'} tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} @@ -8967,10 +8688,6 @@ packages: to-array@0.1.4: resolution: {integrity: sha512-LhVdShQD/4Mk4zXNroIQZJC+Ap3zgLcDuwEdcmLv9CCO73NWockQDwyUnW/m8VX/EElfL6FcYx7EeutN4HJA6A==} - to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - to-object-path@0.3.0: resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} engines: {node: '>=0.10.0'} @@ -8987,8 +8704,8 @@ packages: resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} engines: {node: '>=0.10.0'} - tocbot@4.21.2: - resolution: {integrity: sha512-R5Muhi/TUu4i4snWVrMgNoXyJm2f8sJfdgIkQvqb+cuIXQEIMAiWGWgCgYXHqX4+XiS/Bnm7IYZ9Zy6NVe6lhw==} + tocbot@4.35.0: + resolution: {integrity: sha512-i8FoSaP3u60D94e/dtzCk23PIEBnc/l8XqvlK4g8gUCa9XFY4RmyMLYP6X+yN+ljcEijFbmCtNHtBoeTsQkCPg==} toggle-selection@1.0.6: resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} @@ -8997,8 +8714,8 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - tough-cookie@4.1.3: - resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} engines: {node: '>=6'} tr46@0.0.3: @@ -9007,6 +8724,12 @@ packages: tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + tree-dump@1.0.2: + resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + trim-newlines@4.1.1: resolution: {integrity: sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==} engines: {node: '>=12'} @@ -9017,12 +8740,28 @@ packages: truncate-utf8-bytes@1.0.2: resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==} - ts-api-utils@1.3.0: - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + ts-api-utils@1.4.3: + resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} engines: {node: '>=16'} peerDependencies: typescript: '>=4.2.0' + ts-api-utils@2.0.1: + resolution: {integrity: sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + ts-checker-rspack-plugin@1.1.1: + resolution: {integrity: sha512-BlpPqnfAmV0TcDg58H+1qV8Zb57ilv0x+ajjnxrVQ6BWgC8HzAdc+TycqDOJ4sZZYIV+hywQGozZFGklzbCR6A==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@rspack/core': ^1.0.0 + typescript: '>=3.8.0' + peerDependenciesMeta: + '@rspack/core': + optional: true + ts-dedent@2.2.0: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} @@ -9030,17 +8769,17 @@ packages: ts-easing@0.2.0: resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==} - tsconfig-paths@3.14.2: - resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.7.0: - resolution: {integrity: sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg==} + tsx@4.19.3: + resolution: {integrity: sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==} engines: {node: '>=18.0.0'} hasBin: true @@ -9057,8 +8796,8 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + type-detect@4.1.0: + resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} engines: {node: '>=4'} type-fest@0.16.0: @@ -9123,17 +8862,18 @@ packages: engines: {node: '>=14.17'} hasBin: true - ua-parser-js@1.0.37: - resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==} + ua-parser-js@1.0.40: + resolution: {integrity: sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==} + hasBin: true uc.micro@2.1.0: resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} - ufo@1.3.1: - resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==} + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} - uglify-js@3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} engines: {node: '>=0.8.0'} hasBin: true @@ -9144,23 +8884,26 @@ packages: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} - undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - undici@5.25.4: - resolution: {integrity: sha512-450yJxT29qKMf3aoudzFpIciqpx6Pji3hEWaXqXmanbXF58LTAGCKxcJjxMXWu3iG+Mudgo3ZUfDB6YDFd/dAw==} - engines: {node: '>=14.0'} + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} - unicode-canonical-property-names-ecmascript@2.0.0: - resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} + undici@6.0.1: + resolution: {integrity: sha512-eZFYQLeS9BiXpsU0cuFhCwfeda2MnC48EVmmOz/eCjsTgmyTdaHdVsPSC/kwC2GtW2e0uH0HIPbadf3/bRWSxw==} + engines: {node: '>=18.0'} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} engines: {node: '>=4'} unicode-match-property-ecmascript@2.0.0: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} engines: {node: '>=4'} - unicode-match-property-value-ecmascript@2.1.0: - resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} + unicode-match-property-value-ecmascript@2.2.0: + resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} engines: {node: '>=4'} unicode-property-aliases-ecmascript@2.1.0: @@ -9170,8 +8913,8 @@ packages: unidiff@1.0.2: resolution: {integrity: sha512-2sbEzki5fBmjgAqoafwxRenfMcumMlmVAoJDwYJa3CI4ZVugkdR6qjTw5sVsl29/4JfBBXhWEAd5ars8nRdqXg==} - unified@11.0.4: - resolution: {integrity: sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==} + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} union-value@1.0.1: resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} @@ -9222,8 +8965,8 @@ packages: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} - universalify@2.0.0: - resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} unix-crypt-td-js@1.1.4: @@ -9233,8 +8976,9 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - unplugin@1.5.0: - resolution: {integrity: sha512-9ZdRwbh/4gcm1JTOkp9lAkIDrtOyOxgHmY7cjuwI8L/2RTikMcVG25GsZwNAgRuap3iDw2jeq7eoqtAsz5rW3A==} + unplugin@1.16.1: + resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} + engines: {node: '>=14.0.0'} unset-value@1.0.0: resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} @@ -9248,8 +8992,8 @@ packages: resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} engines: {node: '>=4'} - update-browserslist-db@1.1.0: - resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -9273,26 +9017,27 @@ packages: url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} - url@0.11.3: - resolution: {integrity: sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==} + url@0.11.4: + resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} + engines: {node: '>= 0.4'} - use-callback-ref@1.3.0: - resolution: {integrity: sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==} + use-callback-ref@1.3.3: + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + '@types/react': '*' react: ^18.2.0 peerDependenciesMeta: '@types/react': optional: true - use-deep-compare@1.1.0: - resolution: {integrity: sha512-6yY3zmKNCJ1jjIivfZMZMReZjr8e6iC6Uqtp701jvWJ6ejC/usXD+JjmslZDPJQgX8P4B1Oi5XSLHkOLeYSJsA==} + use-deep-compare@1.3.0: + resolution: {integrity: sha512-94iG+dEdEP/Sl3WWde+w9StIunlV8Dgj+vkt5wTwMoFQLaijiEZSXXy8KtcStpmEDtIptRJiNeD4ACTtVvnIKA==} peerDependencies: react: ^18.2.0 - use-isomorphic-layout-effect@1.1.2: - resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} + use-isomorphic-layout-effect@1.2.0: + resolution: {integrity: sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==} peerDependencies: '@types/react': '*' react: ^18.2.0 @@ -9306,11 +9051,11 @@ packages: react: ^18.2.0 react-dom: 16.8.0 - 18 - use-sidecar@1.1.2: - resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} engines: {node: '>=10'} peerDependencies: - '@types/react': ^16.9.0 || ^17.0.0 || ^18.0.0 + '@types/react': '*' react: ^18.2.0 peerDependenciesMeta: '@types/react': @@ -9335,8 +9080,8 @@ packages: resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} engines: {node: '>=0.10.0'} - utf8-byte-length@1.0.4: - resolution: {integrity: sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==} + utf8-byte-length@1.0.5: + resolution: {integrity: sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==} utif@2.0.1: resolution: {integrity: sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==} @@ -9367,10 +9112,6 @@ packages: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true - v8-to-istanbul@9.1.3: - resolution: {integrity: sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==} - engines: {node: '>=10.12.0'} - validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -9386,6 +9127,18 @@ packages: react: optional: true + valtio@1.13.2: + resolution: {integrity: sha512-Qik0o+DSy741TmkqmRfjq+0xpZBXi/Y6+fXZLn0xNF1z/waFMbE3rkivv5Zcf9RrMUp6zswf2J7sbh2KBlba5A==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=16.8' + react: ^18.2.0 + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -9400,21 +9153,16 @@ packages: vfile-message@4.0.2: resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} - vfile@6.0.1: - resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} vite-node@0.34.6: resolution: {integrity: sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==} engines: {node: '>=v14.18.0'} hasBin: true - vite-node@3.0.7: - resolution: {integrity: sha512-2fX0QwX4GkkkpULXdT1Pf4q0tC1i1lFOyseKoonavXUNlQ77KpW2XqBGGNIm/J4Ows4KxgGJzDguYVPKwG/n5A==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - - vite@4.5.3: - resolution: {integrity: sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==} + vite@4.5.9: + resolution: {integrity: sha512-qK9W4xjgD3gXbC0NmdNFFnVFLMWSNiR3swj957yutwzzN16xF/E7nmtAyp1rT9hviDroQANjE4HK3H4WqWdFtw==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true peerDependencies: @@ -9441,8 +9189,8 @@ packages: terser: optional: true - vite@6.2.0: - resolution: {integrity: sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==} + vite@6.2.1: + resolution: {integrity: sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -9512,34 +9260,6 @@ packages: webdriverio: optional: true - vitest@3.0.7: - resolution: {integrity: sha512-IP7gPK3LS3Fvn44x30X1dM9vtawm0aesAa2yBIZ9vQf+qB69NXC5776+Qmcr7ohUXIQuLhk7xQR0aSUIDPqavg==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@types/debug': ^4.1.12 - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.0.7 - '@vitest/ui': 3.0.7 - happy-dom: '*' - jsdom: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@types/debug': - optional: true - '@types/node': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - vm-browserify@1.1.2: resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} @@ -9557,8 +9277,8 @@ packages: warning@4.0.3: resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} - watchpack@2.4.1: - resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} + watchpack@2.4.2: + resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} engines: {node: '>=10.13.0'} wcwidth@1.0.1: @@ -9570,25 +9290,11 @@ packages: webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} - webpack-sources@3.2.3: - resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} - engines: {node: '>=10.13.0'} + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} - webpack-virtual-modules@0.5.0: - resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} - - webpack@5.93.0: - resolution: {integrity: sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==} - engines: {node: '>=10.13.0'} - hasBin: true - peerDependencies: - webpack-cli: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - - webrtc-adapter@8.2.3: - resolution: {integrity: sha512-gnmRz++suzmvxtp3ehQts6s2JtAGPuDPjA1F3a9ckNpG1kYdYuHWYpazoAnL9FS5/B21tKlhkorbdCXat0+4xQ==} + webrtc-adapter@9.0.1: + resolution: {integrity: sha512-1AQO+d4ElfVSXyzNVTOewgGT/tAomwwztX/6e3totvyyzXPvXIIuUUjAmyZGbKBKbZOXauuJooZm3g6IuFuiNQ==} engines: {node: '>=6.0.0', npm: '>=3.10.0'} websocket-driver@0.7.4: @@ -9603,8 +9309,8 @@ packages: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} engines: {node: '>=12'} - whatwg-fetch@3.6.18: - resolution: {integrity: sha512-ltN7j66EneWn5TFDO4L9inYC1D+Czsxlrw2SalgjMmEMkLfA5SIZxEFdE6QtHFiiM6Q7WL32c7AkI3w6yxM84Q==} + whatwg-fetch@3.6.20: + resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -9628,6 +9334,10 @@ packages: resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==} engines: {node: '>= 0.4'} + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} + engines: {node: '>= 0.4'} + which@1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} hasBin: true @@ -9637,11 +9347,6 @@ packages: engines: {node: '>= 8'} hasBin: true - why-is-node-running@2.2.2: - resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} - engines: {node: '>=8'} - hasBin: true - why-is-node-running@2.3.0: resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} engines: {node: '>=8'} @@ -9650,58 +9355,61 @@ packages: wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - workbox-background-sync@7.0.0: - resolution: {integrity: sha512-S+m1+84gjdueM+jIKZ+I0Lx0BDHkk5Nu6a3kTVxP4fdj3gKouRNmhO8H290ybnJTOPfBDtTMXSQA/QLTvr7PeA==} + workbox-background-sync@7.3.0: + resolution: {integrity: sha512-PCSk3eK7Mxeuyatb22pcSx9dlgWNv3+M8PqPaYDokks8Y5/FX4soaOqj3yhAZr5k6Q5JWTOMYgaJBpbw11G9Eg==} - workbox-broadcast-update@7.0.0: - resolution: {integrity: sha512-oUuh4jzZrLySOo0tC0WoKiSg90bVAcnE98uW7F8GFiSOXnhogfNDGZelPJa+6KpGBO5+Qelv04Hqx2UD+BJqNQ==} + workbox-broadcast-update@7.3.0: + resolution: {integrity: sha512-T9/F5VEdJVhwmrIAE+E/kq5at2OY6+OXXgOWQevnubal6sO92Gjo24v6dCVwQiclAF5NS3hlmsifRrpQzZCdUA==} - workbox-build@7.0.0: - resolution: {integrity: sha512-CttE7WCYW9sZC+nUYhQg3WzzGPr4IHmrPnjKiu3AMXsiNQKx+l4hHl63WTrnicLmKEKHScWDH8xsGBdrYgtBzg==} + workbox-build@7.3.0: + resolution: {integrity: sha512-JGL6vZTPlxnlqZRhR/K/msqg3wKP+m0wfEUVosK7gsYzSgeIxvZLi1ViJJzVL7CEeI8r7rGFV973RiEqkP3lWQ==} engines: {node: '>=16.0.0'} - workbox-cacheable-response@7.0.0: - resolution: {integrity: sha512-0lrtyGHn/LH8kKAJVOQfSu3/80WDc9Ma8ng0p2i/5HuUndGttH+mGMSvOskjOdFImLs2XZIimErp7tSOPmu/6g==} + workbox-cacheable-response@7.3.0: + resolution: {integrity: sha512-eAFERIg6J2LuyELhLlmeRcJFa5e16Mj8kL2yCDbhWE+HUun9skRQrGIFVUagqWj4DMaaPSMWfAolM7XZZxNmxA==} - workbox-core@7.0.0: - resolution: {integrity: sha512-81JkAAZtfVP8darBpfRTovHg8DGAVrKFgHpOArZbdFd78VqHr5Iw65f2guwjE2NlCFbPFDoez3D3/6ZvhI/rwQ==} + workbox-core@7.3.0: + resolution: {integrity: sha512-Z+mYrErfh4t3zi7NVTvOuACB0A/jA3bgxUN3PwtAVHvfEsZxV9Iju580VEETug3zYJRc0Dmii/aixI/Uxj8fmw==} - workbox-expiration@7.0.0: - resolution: {integrity: sha512-MLK+fogW+pC3IWU9SFE+FRStvDVutwJMR5if1g7oBJx3qwmO69BNoJQVaMXq41R0gg3MzxVfwOGKx3i9P6sOLQ==} + workbox-expiration@7.3.0: + resolution: {integrity: sha512-lpnSSLp2BM+K6bgFCWc5bS1LR5pAwDWbcKt1iL87/eTSJRdLdAwGQznZE+1czLgn/X05YChsrEegTNxjM067vQ==} - workbox-google-analytics@7.0.0: - resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==} - deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained + workbox-google-analytics@7.3.0: + resolution: {integrity: sha512-ii/tSfFdhjLHZ2BrYgFNTrb/yk04pw2hasgbM70jpZfLk0vdJAXgaiMAWsoE+wfJDNWoZmBYY0hMVI0v5wWDbg==} - workbox-navigation-preload@7.0.0: - resolution: {integrity: sha512-juWCSrxo/fiMz3RsvDspeSLGmbgC0U9tKqcUPZBCf35s64wlaLXyn2KdHHXVQrb2cqF7I0Hc9siQalainmnXJA==} + workbox-navigation-preload@7.3.0: + resolution: {integrity: sha512-fTJzogmFaTv4bShZ6aA7Bfj4Cewaq5rp30qcxl2iYM45YD79rKIhvzNHiFj1P+u5ZZldroqhASXwwoyusnr2cg==} - workbox-precaching@7.0.0: - resolution: {integrity: sha512-EC0vol623LJqTJo1mkhD9DZmMP604vHqni3EohhQVwhJlTgyKyOkMrZNy5/QHfOby+39xqC01gv4LjOm4HSfnA==} + workbox-precaching@7.3.0: + resolution: {integrity: sha512-ckp/3t0msgXclVAYaNndAGeAoWQUv7Rwc4fdhWL69CCAb2UHo3Cef0KIUctqfQj1p8h6aGyz3w8Cy3Ihq9OmIw==} - workbox-range-requests@7.0.0: - resolution: {integrity: sha512-SxAzoVl9j/zRU9OT5+IQs7pbJBOUOlriB8Gn9YMvi38BNZRbM+RvkujHMo8FOe9IWrqqwYgDFBfv6sk76I1yaQ==} + workbox-range-requests@7.3.0: + resolution: {integrity: sha512-EyFmM1KpDzzAouNF3+EWa15yDEenwxoeXu9bgxOEYnFfCxns7eAxA9WSSaVd8kujFFt3eIbShNqa4hLQNFvmVQ==} - workbox-recipes@7.0.0: - resolution: {integrity: sha512-DntcK9wuG3rYQOONWC0PejxYYIDHyWWZB/ueTbOUDQgefaeIj1kJ7pdP3LZV2lfrj8XXXBWt+JDRSw1lLLOnww==} + workbox-recipes@7.3.0: + resolution: {integrity: sha512-BJro/MpuW35I/zjZQBcoxsctgeB+kyb2JAP5EB3EYzePg8wDGoQuUdyYQS+CheTb+GhqJeWmVs3QxLI8EBP1sg==} - workbox-routing@7.0.0: - resolution: {integrity: sha512-8YxLr3xvqidnbVeGyRGkaV4YdlKkn5qZ1LfEePW3dq+ydE73hUUJJuLmGEykW3fMX8x8mNdL0XrWgotcuZjIvA==} + workbox-routing@7.3.0: + resolution: {integrity: sha512-ZUlysUVn5ZUzMOmQN3bqu+gK98vNfgX/gSTZ127izJg/pMMy4LryAthnYtjuqcjkN4HEAx1mdgxNiKJMZQM76A==} - workbox-strategies@7.0.0: - resolution: {integrity: sha512-dg3qJU7tR/Gcd/XXOOo7x9QoCI9nk74JopaJaYAQ+ugLi57gPsXycVdBnYbayVj34m6Y8ppPwIuecrzkpBVwbA==} + workbox-strategies@7.3.0: + resolution: {integrity: sha512-tmZydug+qzDFATwX7QiEL5Hdf7FrkhjaF9db1CbB39sDmEZJg3l9ayDvPxy8Y18C3Y66Nrr9kkN1f/RlkDgllg==} - workbox-streams@7.0.0: - resolution: {integrity: sha512-moVsh+5to//l6IERWceYKGiftc+prNnqOp2sgALJJFbnNVpTXzKISlTIsrWY+ogMqt+x1oMazIdHj25kBSq/HQ==} + workbox-streams@7.3.0: + resolution: {integrity: sha512-SZnXucyg8x2Y61VGtDjKPO5EgPUG5NDn/v86WYHX+9ZqvAsGOytP0Jxp1bl663YUuMoXSAtsGLL+byHzEuMRpw==} - workbox-sw@7.0.0: - resolution: {integrity: sha512-SWfEouQfjRiZ7GNABzHUKUyj8pCoe+RwjfOIajcx6J5mtgKkN+t8UToHnpaJL5UVVOf5YhJh+OHhbVNIHe+LVA==} + workbox-sw@7.3.0: + resolution: {integrity: sha512-aCUyoAZU9IZtH05mn0ACUpyHzPs0lMeJimAYkQkBsOWiqaJLgusfDCR+yllkPkFRxWpZKF8vSvgHYeG7LwhlmA==} - workbox-window@7.0.0: - resolution: {integrity: sha512-j7P/bsAWE/a7sxqTzXo3P2ALb1reTfZdvVp6OJ/uLr/C2kZAMvjeWGm8V4htQhor7DOvYg0sSbFN2+flT5U0qA==} + workbox-window@7.3.0: + resolution: {integrity: sha512-qW8PDy16OV1UBaUNGlTVcepzrlzyzNW/ZJvFQQs2j2TzGsg6IKjcpZC1RSquqQnTOafl5pCj5bGfAHlCjOOjdA==} wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} @@ -9725,8 +9433,8 @@ packages: resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - ws@5.2.3: - resolution: {integrity: sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==} + ws@5.2.4: + resolution: {integrity: sha512-fFCejsuC8f9kOSu9FYaOw8CdO68O3h5v0lg4p74o8JqWpwTf9tniOD+nOB78aWoVSS6WptVUmDrp/KPsMVBWFQ==} peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ^5.0.2 @@ -9736,8 +9444,8 @@ packages: utf-8-validate: optional: true - ws@6.2.2: - resolution: {integrity: sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==} + ws@6.2.3: + resolution: {integrity: sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==} peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ^5.0.2 @@ -9747,8 +9455,8 @@ packages: utf-8-validate: optional: true - ws@7.4.6: - resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} engines: {node: '>=8.3.0'} peerDependencies: bufferutil: ^4.0.1 @@ -9759,20 +9467,20 @@ packages: utf-8-validate: optional: true - ws@8.11.0: - resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==} + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 + utf-8-validate: '>=5.0.2' peerDependenciesMeta: bufferutil: optional: true utf-8-validate: optional: true - ws@8.18.0: - resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + ws@8.18.1: + resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -9789,8 +9497,8 @@ packages: xml-parse-from-string@1.0.1: resolution: {integrity: sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==} - xml2js@0.4.23: - resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==} + xml2js@0.5.0: + resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} engines: {node: '>=4.0.0'} xmlbuilder@11.0.1: @@ -9801,8 +9509,8 @@ packages: resolution: {integrity: sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==} engines: {node: '>=0.4.0'} - xmlhttprequest-ssl@2.0.0: - resolution: {integrity: sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==} + xmlhttprequest-ssl@2.1.2: + resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==} engines: {node: '>=0.4.0'} xtend@4.0.2: @@ -9826,8 +9534,8 @@ packages: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} - yaml@2.4.1: - resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} + yaml@2.7.0: + resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} engines: {node: '>= 14'} hasBin: true @@ -9839,10 +9547,6 @@ packages: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} @@ -9850,6 +9554,9 @@ packages: yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + yazl@2.5.1: + resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} + yeast@0.1.2: resolution: {integrity: sha512-8HFIh676uyGYP6wP13R/j6OJ/1HwJ46snpvzE7aHAN3Ryqh2yX6Xox2B4CUmTwwOIzlG3Bs7ocsP5dZH/R1Qbg==} @@ -9860,12 +9567,12 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - yocto-queue@1.0.0: - resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + yocto-queue@1.2.0: + resolution: {integrity: sha512-KHBC7z61OJeaMGnF3wqNZj+GGNXOyypZviiKpQeiHirG5Ib1ImwcLBH70rbMSkKfSmUNBsdf2PwaEJtKvgmkNw==} engines: {node: '>=12.20'} - zod@3.24.1: - resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} + zod@3.24.2: + resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} zustand@3.6.5: resolution: {integrity: sha512-/WfLJuXiEJimt61KGMHebrFBwckkCHGhAgVXTgPQHl6IMzjqm6MREb1OnDSnCRiSmRdhgdFCctceg6tSm79hiw==} @@ -9881,16 +9588,14 @@ packages: snapshots: - '@aashutoshrathi/word-wrap@1.2.6': {} - - '@ampproject/remapping@2.2.1': + '@ampproject/remapping@2.3.0': dependencies: - '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - '@apideck/better-ajv-errors@0.3.6(ajv@8.12.0)': + '@apideck/better-ajv-errors@0.3.6(ajv@8.17.1)': dependencies: - ajv: 8.12.0 + ajv: 8.17.1 json-schema: 0.4.0 jsonpointer: 5.0.1 leven: 3.1.0 @@ -9899,34 +9604,35 @@ snapshots: dependencies: default-browser-id: 3.0.0 - '@azure/msal-common@14.9.0': {} + '@azure/msal-common@14.16.0': {} - '@azure/msal-node@2.7.0': + '@azure/msal-node@2.16.2': dependencies: - '@azure/msal-common': 14.9.0 + '@azure/msal-common': 14.16.0 jsonwebtoken: 9.0.2 uuid: 8.3.2 - '@babel/code-frame@7.22.13': + '@babel/code-frame@7.26.2': dependencies: - '@babel/highlight': 7.22.13 - chalk: 2.4.2 + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 - '@babel/compat-data@7.22.9': {} + '@babel/compat-data@7.26.8': {} - '@babel/core@7.22.11': + '@babel/core@7.26.9': dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.22.13 - '@babel/generator': 7.22.10 - '@babel/helper-compilation-targets': 7.22.10 - '@babel/helper-module-transforms': 7.23.0(@babel/core@7.22.11) - '@babel/helpers': 7.22.11 - '@babel/parser': 7.22.13 - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.11 - '@babel/types': 7.23.0 - convert-source-map: 1.9.0 + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helpers': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + convert-source-map: 2.0.0 debug: 4.4.0(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 @@ -9934,787 +9640,695 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.22.10': + '@babel/generator@7.26.9': dependencies: - '@babel/types': 7.23.0 - '@jridgewell/gen-mapping': 0.3.3 + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 + jsesc: 3.1.0 - '@babel/helper-annotate-as-pure@7.22.5': + '@babel/helper-annotate-as-pure@7.25.9': dependencies: - '@babel/types': 7.23.0 + '@babel/types': 7.26.9 - '@babel/helper-builder-binary-assignment-operator-visitor@7.22.10': + '@babel/helper-compilation-targets@7.26.5': dependencies: - '@babel/types': 7.23.0 - - '@babel/helper-compilation-targets@7.22.10': - dependencies: - '@babel/compat-data': 7.22.9 - '@babel/helper-validator-option': 7.22.15 - browserslist: 4.23.2 + '@babel/compat-data': 7.26.8 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.4 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.22.15(@babel/core@7.22.11)': + '@babel/helper-create-class-features-plugin@7.26.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.22.5 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.11) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.9) + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/traverse': 7.26.9 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.26.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + regexpu-core: 6.2.0 semver: 6.3.1 - '@babel/helper-create-regexp-features-plugin@7.22.9(@babel/core@7.22.11)': + '@babel/helper-define-polyfill-provider@0.6.3(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-annotate-as-pure': 7.22.5 - regexpu-core: 5.3.2 - semver: 6.3.1 - - '@babel/helper-define-polyfill-provider@0.4.2(@babel/core@7.22.11)': - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-compilation-targets': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - debug: 4.4.0(supports-color@8.1.1) + '@babel/core': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + debug: 4.4.1 lodash.debounce: 4.0.8 - resolve: 1.22.4 + resolve: 1.22.10 transitivePeerDependencies: - supports-color - '@babel/helper-environment-visitor@7.22.20': {} - - '@babel/helper-function-name@7.22.5': + '@babel/helper-member-expression-to-functions@7.25.9': dependencies: - '@babel/template': 7.22.5 - '@babel/types': 7.23.0 - - '@babel/helper-hoist-variables@7.22.5': - dependencies: - '@babel/types': 7.23.0 - - '@babel/helper-member-expression-to-functions@7.23.0': - dependencies: - '@babel/types': 7.23.0 - - '@babel/helper-module-imports@7.22.15': - dependencies: - '@babel/types': 7.23.0 - - '@babel/helper-module-transforms@7.23.0(@babel/core@7.22.11)': - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 - - '@babel/helper-optimise-call-expression@7.22.5': - dependencies: - '@babel/types': 7.23.0 - - '@babel/helper-plugin-utils@7.22.5': {} - - '@babel/helper-remap-async-to-generator@7.22.9(@babel/core@7.22.11)': - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-wrap-function': 7.22.10 - - '@babel/helper-replace-supers@7.22.9(@babel/core@7.22.11)': - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - - '@babel/helper-simple-access@7.22.5': - dependencies: - '@babel/types': 7.23.0 - - '@babel/helper-skip-transparent-expression-wrappers@7.22.5': - dependencies: - '@babel/types': 7.23.0 - - '@babel/helper-split-export-declaration@7.22.6': - dependencies: - '@babel/types': 7.23.0 - - '@babel/helper-string-parser@7.22.5': {} - - '@babel/helper-validator-identifier@7.22.20': {} - - '@babel/helper-validator-option@7.22.15': {} - - '@babel/helper-wrap-function@7.22.10': - dependencies: - '@babel/helper-function-name': 7.22.5 - '@babel/template': 7.22.5 - '@babel/types': 7.23.0 - - '@babel/helpers@7.22.11': - dependencies: - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.11 - '@babel/types': 7.23.0 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 transitivePeerDependencies: - supports-color - '@babel/highlight@7.22.13': + '@babel/helper-module-imports@7.25.9': dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color - '@babel/parser@7.22.13': + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.9)': dependencies: - '@babel/types': 7.23.0 + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.22.5(@babel/core@7.22.11)': + '@babel/helper-optimise-call-expression@7.25.9': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/types': 7.26.9 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.22.5(@babel/core@7.22.11)': - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.22.12(@babel/core@7.22.11) + '@babel/helper-plugin-utils@7.26.5': {} - '@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.22.11)': + '@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-wrap-function': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.22.11)': + '@babel/helper-replace-supers@7.26.5(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.22.11)': + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.11) + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.22.11)': - dependencies: - '@babel/core': 7.22.11 + '@babel/helper-string-parser@7.25.9': {} - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.22.11)': - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-identifier@7.25.9': {} - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.22.11)': - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option@7.25.9': {} - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.22.11)': + '@babel/helper-wrap-function@7.25.9': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.22.11)': + '@babel/helpers@7.26.9': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 - '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.22.11)': + '@babel/parser@7.26.9': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/types': 7.26.9 - '@babel/plugin-syntax-flow@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-import-assertions@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-import-attributes@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.22.11)': + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.22.11)': + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.22.11)': + '@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.22.11)': + '@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.22.11)': + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.22.11)': + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.22.11)': + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.22.11)': + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.22.11)': + '@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.22.11)': + '@babel/plugin-transform-async-generator-functions@7.26.8(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.9) + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.22.11)': + '@babel/plugin-transform-block-scoped-functions@7.26.5(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-create-regexp-features-plugin': 7.22.9(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-arrow-functions@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-block-scoping@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-async-generator-functions@7.22.11(@babel/core@7.22.11)': + '@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-remap-async-to-generator': 7.22.9(@babel/core@7.22.11) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-async-to-generator@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-class-static-block@7.26.0(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-remap-async-to-generator': 7.22.9(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-block-scoped-functions@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-classes@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - - '@babel/plugin-transform-block-scoping@7.22.10(@babel/core@7.22.11)': - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - - '@babel/plugin-transform-class-properties@7.22.5(@babel/core@7.22.11)': - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 - - '@babel/plugin-transform-class-static-block@7.22.11(@babel/core@7.22.11)': - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.11) - - '@babel/plugin-transform-classes@7.22.6(@babel/core@7.22.11)': - dependencies: - '@babel/core': 7.22.11 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-compilation-targets': 7.22.10 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.22.5 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.11) - '@babel/helper-split-export-declaration': 7.22.6 + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.9) + '@babel/traverse': 7.26.9 globals: 11.12.0 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-computed-properties@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-computed-properties@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/template': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/template': 7.26.9 - '@babel/plugin-transform-destructuring@7.22.10(@babel/core@7.22.11)': + '@babel/plugin-transform-destructuring@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-dotall-regex@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-create-regexp-features-plugin': 7.22.9(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-duplicate-keys@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-dynamic-import@7.22.11(@babel/core@7.22.11)': + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-exponentiation-operator@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-export-namespace-from@7.22.11(@babel/core@7.22.11)': + '@babel/plugin-transform-exponentiation-operator@7.26.3(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-flow-strip-types@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-export-namespace-from@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-flow': 7.22.5(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-for-of@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-flow-strip-types@7.26.5(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.26.9) - '@babel/plugin-transform-function-name@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-for-of@7.26.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-compilation-targets': 7.22.10 - '@babel/helper-function-name': 7.22.5 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-json-strings@7.22.11(@babel/core@7.22.11)': + '@babel/plugin-transform-function-name@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-literals@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-json-strings@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-logical-assignment-operators@7.22.11(@babel/core@7.22.11)': + '@babel/plugin-transform-literals@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-member-expression-literals@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-logical-assignment-operators@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-modules-amd@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-member-expression-literals@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-module-transforms': 7.23.0(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-modules-commonjs@7.23.0(@babel/core@7.22.11)': + '@babel/plugin-transform-modules-amd@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-module-transforms': 7.23.0(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-simple-access': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-modules-systemjs@7.22.11(@babel/core@7.22.11)': + '@babel/plugin-transform-modules-commonjs@7.26.3(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-module-transforms': 7.23.0(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-identifier': 7.22.20 + '@babel/core': 7.26.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-modules-umd@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-modules-systemjs@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-module-transforms': 7.23.0(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-modules-umd@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-create-regexp-features-plugin': 7.22.9(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-new-target@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-named-capturing-groups-regex@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-nullish-coalescing-operator@7.22.11(@babel/core@7.22.11)': + '@babel/plugin-transform-new-target@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-numeric-separator@7.22.11(@babel/core@7.22.11)': + '@babel/plugin-transform-nullish-coalescing-operator@7.26.6(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-object-rest-spread@7.22.11(@babel/core@7.22.11)': + '@babel/plugin-transform-numeric-separator@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/compat-data': 7.22.9 - '@babel/core': 7.22.11 - '@babel/helper-compilation-targets': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.11) - '@babel/plugin-transform-parameters': 7.22.5(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-object-super@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.9) - '@babel/plugin-transform-optional-catch-binding@7.22.11(@babel/core@7.22.11)': + '@babel/plugin-transform-object-super@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-optional-chaining@7.22.12(@babel/core@7.22.11)': + '@babel/plugin-transform-optional-catch-binding@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-parameters@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-optional-chaining@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-private-methods@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-parameters@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-private-property-in-object@7.22.11(@babel/core@7.22.11)': + '@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-property-literals@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-private-property-in-object@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-react-jsx-self@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-property-literals@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-react-jsx-source@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-regenerator@7.22.10(@babel/core@7.22.11)': + '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-regenerator@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 regenerator-transform: 0.15.2 - '@babel/plugin-transform-reserved-words@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-regexp-modifiers@7.26.0(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-shorthand-properties@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-spread@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-sticky-regex@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-spread@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-template-literals@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-sticky-regex@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-typeof-symbol@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-template-literals@7.26.8(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-typescript@7.22.15(@babel/core@7.22.11)': + '@babel/plugin-transform-typeof-symbol@7.26.7(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-unicode-escapes@7.22.10(@babel/core@7.22.11)': + '@babel/plugin-transform-typescript@7.26.8(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-unicode-property-regex@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-create-regexp-features-plugin': 7.22.9(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-unicode-regex@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-create-regexp-features-plugin': 7.22.9(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-unicode-sets-regex@7.22.5(@babel/core@7.22.11)': + '@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-create-regexp-features-plugin': 7.22.9(@babel/core@7.22.11) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 - '@babel/preset-env@7.22.10(@babel/core@7.22.11)': + '@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/compat-data': 7.22.9 - '@babel/core': 7.22.11 - '@babel/helper-compilation-targets': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.22.15 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.22.11) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.11) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.22.11) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.11) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.11) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.11) - '@babel/plugin-syntax-import-assertions': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-syntax-import-attributes': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.22.11) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.11) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.11) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.11) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.11) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.11) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.11) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.11) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.22.11) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.22.11) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.22.11) - '@babel/plugin-transform-arrow-functions': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-async-generator-functions': 7.22.11(@babel/core@7.22.11) - '@babel/plugin-transform-async-to-generator': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-block-scoped-functions': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-block-scoping': 7.22.10(@babel/core@7.22.11) - '@babel/plugin-transform-class-properties': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-class-static-block': 7.22.11(@babel/core@7.22.11) - '@babel/plugin-transform-classes': 7.22.6(@babel/core@7.22.11) - '@babel/plugin-transform-computed-properties': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-destructuring': 7.22.10(@babel/core@7.22.11) - '@babel/plugin-transform-dotall-regex': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-duplicate-keys': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-dynamic-import': 7.22.11(@babel/core@7.22.11) - '@babel/plugin-transform-exponentiation-operator': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-export-namespace-from': 7.22.11(@babel/core@7.22.11) - '@babel/plugin-transform-for-of': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-function-name': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-json-strings': 7.22.11(@babel/core@7.22.11) - '@babel/plugin-transform-literals': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-logical-assignment-operators': 7.22.11(@babel/core@7.22.11) - '@babel/plugin-transform-member-expression-literals': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-modules-amd': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-modules-commonjs': 7.23.0(@babel/core@7.22.11) - '@babel/plugin-transform-modules-systemjs': 7.22.11(@babel/core@7.22.11) - '@babel/plugin-transform-modules-umd': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-new-target': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-nullish-coalescing-operator': 7.22.11(@babel/core@7.22.11) - '@babel/plugin-transform-numeric-separator': 7.22.11(@babel/core@7.22.11) - '@babel/plugin-transform-object-rest-spread': 7.22.11(@babel/core@7.22.11) - '@babel/plugin-transform-object-super': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-optional-catch-binding': 7.22.11(@babel/core@7.22.11) - '@babel/plugin-transform-optional-chaining': 7.22.12(@babel/core@7.22.11) - '@babel/plugin-transform-parameters': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-private-methods': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-private-property-in-object': 7.22.11(@babel/core@7.22.11) - '@babel/plugin-transform-property-literals': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-regenerator': 7.22.10(@babel/core@7.22.11) - '@babel/plugin-transform-reserved-words': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-shorthand-properties': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-spread': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-sticky-regex': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-template-literals': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-typeof-symbol': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-unicode-escapes': 7.22.10(@babel/core@7.22.11) - '@babel/plugin-transform-unicode-property-regex': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-unicode-regex': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-unicode-sets-regex': 7.22.5(@babel/core@7.22.11) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.22.11) - '@babel/types': 7.23.0 - babel-plugin-polyfill-corejs2: 0.4.5(@babel/core@7.22.11) - babel-plugin-polyfill-corejs3: 0.8.3(@babel/core@7.22.11) - babel-plugin-polyfill-regenerator: 0.5.2(@babel/core@7.22.11) - core-js-compat: 3.32.1 + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/preset-env@7.26.9(@babel/core@7.26.9)': + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/core': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.9) + '@babel/plugin-syntax-import-assertions': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.9) + '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-async-generator-functions': 7.26.8(@babel/core@7.26.9) + '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-block-scoped-functions': 7.26.5(@babel/core@7.26.9) + '@babel/plugin-transform-block-scoping': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-class-static-block': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-transform-classes': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-computed-properties': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-destructuring': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-dotall-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-duplicate-keys': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-dynamic-import': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-exponentiation-operator': 7.26.3(@babel/core@7.26.9) + '@babel/plugin-transform-export-namespace-from': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-for-of': 7.26.9(@babel/core@7.26.9) + '@babel/plugin-transform-function-name': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-json-strings': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-literals': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-logical-assignment-operators': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-member-expression-literals': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-modules-amd': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-modules-commonjs': 7.26.3(@babel/core@7.26.9) + '@babel/plugin-transform-modules-systemjs': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-modules-umd': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-new-target': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-nullish-coalescing-operator': 7.26.6(@babel/core@7.26.9) + '@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-object-super': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-optional-catch-binding': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-private-property-in-object': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-property-literals': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-regenerator': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-regexp-modifiers': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-transform-reserved-words': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-shorthand-properties': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-spread': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-sticky-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-template-literals': 7.26.8(@babel/core@7.26.9) + '@babel/plugin-transform-typeof-symbol': 7.26.7(@babel/core@7.26.9) + '@babel/plugin-transform-unicode-escapes': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-unicode-property-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-unicode-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-unicode-sets-regex': 7.25.9(@babel/core@7.26.9) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.9) + babel-plugin-polyfill-corejs2: 0.4.12(@babel/core@7.26.9) + babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.9) + babel-plugin-polyfill-regenerator: 0.6.3(@babel/core@7.26.9) + core-js-compat: 3.41.0 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/preset-flow@7.22.15(@babel/core@7.22.11)': + '@babel/preset-flow@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.22.15 - '@babel/plugin-transform-flow-strip-types': 7.22.5(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-transform-flow-strip-types': 7.26.5(@babel/core@7.26.9) - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.22.11)': + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/types': 7.23.0 + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/types': 7.26.9 esutils: 2.0.3 - '@babel/preset-typescript@7.23.0(@babel/core@7.22.11)': + '@babel/preset-typescript@7.26.0(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.22.15 - '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-modules-commonjs': 7.23.0(@babel/core@7.22.11) - '@babel/plugin-transform-typescript': 7.22.15(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-modules-commonjs': 7.26.3(@babel/core@7.26.9) + '@babel/plugin-transform-typescript': 7.26.8(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color - '@babel/register@7.22.15(@babel/core@7.22.11)': + '@babel/register@7.25.9(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.26.9 clone-deep: 4.0.1 find-cache-dir: 2.1.0 make-dir: 2.1.0 pirates: 4.0.6 source-map-support: 0.5.21 - '@babel/regjsgen@0.8.0': {} - - '@babel/runtime@7.24.5': + '@babel/runtime@7.26.9': dependencies: - regenerator-runtime: 0.14.0 + regenerator-runtime: 0.14.1 - '@babel/template@7.22.5': + '@babel/template@7.26.9': dependencies: - '@babel/code-frame': 7.22.13 - '@babel/parser': 7.22.13 - '@babel/types': 7.23.0 + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 - '@babel/traverse@7.22.11': + '@babel/traverse@7.26.9': dependencies: - '@babel/code-frame': 7.22.13 - '@babel/generator': 7.22.10 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.22.5 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.22.13 - '@babel/types': 7.23.0 - debug: 4.4.0(supports-color@8.1.1) + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 + debug: 4.4.1 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.23.0': + '@babel/types@7.26.9': dependencies: - '@babel/helper-string-parser': 7.22.5 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 '@base2/pretty-print-object@1.0.1': {} - '@bcoe/v8-coverage@0.2.3': {} - - '@cbor-extract/cbor-extract-darwin-arm64@2.2.0': - optional: true - - '@cbor-extract/cbor-extract-darwin-x64@2.2.0': - optional: true - - '@cbor-extract/cbor-extract-linux-arm64@2.2.0': - optional: true - - '@cbor-extract/cbor-extract-linux-arm@2.2.0': - optional: true - - '@cbor-extract/cbor-extract-linux-x64@2.2.0': - optional: true - - '@cbor-extract/cbor-extract-win32-x64@2.2.0': - optional: true - '@colors/colors@1.5.0': optional: true '@cypress/request@2.88.12': dependencies: aws-sign2: 0.7.0 - aws4: 1.12.0 + aws4: 1.13.2 caseless: 0.12.0 combined-stream: 1.0.8 extend: 3.0.2 @@ -10728,7 +10342,7 @@ snapshots: performance-now: 2.1.0 qs: 6.10.4 safe-buffer: 5.2.1 - tough-cookie: 4.1.3 + tough-cookie: 4.1.4 tunnel-agent: 0.6.0 uuid: 8.3.2 optional: true @@ -10741,103 +10355,110 @@ snapshots: - supports-color optional: true - '@dimaka/interface@0.0.3-alpha.0(@babel/core@7.22.11)(@popperjs/core@2.11.8)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@dimaka/interface@0.0.3-alpha.0(@babel/core@7.26.9)(@popperjs/core@2.11.8)(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@emotion/css': 11.5.0(@babel/core@7.22.11) + '@emotion/css': 11.5.0(@babel/core@7.26.9) '@juggle/resize-observer': 3.3.1 animejs: 3.2.1 clsx: 1.1.1 - react: 18.2.0 - react-popper: 2.3.0(@popperjs/core@2.11.8)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react-portal: 4.2.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react-use: 17.3.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react-use-measure: 2.1.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - valtio: 1.11.2(@types/react@18.2.20)(react@18.2.0) - zustand: 3.6.5(react@18.2.0) + react: 18.3.1 + react-popper: 2.3.0(@popperjs/core@2.11.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-portal: 4.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-use: 17.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-use-measure: 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + valtio: 1.11.2(@types/react@18.3.18)(react@18.3.1) + zustand: 3.6.5(react@18.3.1) transitivePeerDependencies: - '@babel/core' - '@popperjs/core' - '@types/react' - react-dom + - supports-color '@discoveryjs/json-ext@0.5.7': {} '@emnapi/runtime@1.3.1': dependencies: - tslib: 2.6.2 + tslib: 2.8.1 optional: true - '@emotion/babel-plugin@11.12.0': + '@emotion/babel-plugin@11.13.5': dependencies: - '@babel/helper-module-imports': 7.22.15 - '@babel/runtime': 7.24.5 + '@babel/helper-module-imports': 7.25.9 + '@babel/runtime': 7.26.9 '@emotion/hash': 0.9.2 '@emotion/memoize': 0.9.0 - '@emotion/serialize': 1.3.0 + '@emotion/serialize': 1.3.3 babel-plugin-macros: 3.1.0 convert-source-map: 1.9.0 escape-string-regexp: 4.0.0 find-root: 1.1.0 source-map: 0.5.7 stylis: 4.2.0 + transitivePeerDependencies: + - supports-color - '@emotion/cache@11.13.1': + '@emotion/cache@11.14.0': dependencies: '@emotion/memoize': 0.9.0 '@emotion/sheet': 1.4.0 - '@emotion/utils': 1.4.0 + '@emotion/utils': 1.4.2 '@emotion/weak-memoize': 0.4.0 stylis: 4.2.0 - '@emotion/css@11.5.0(@babel/core@7.22.11)': + '@emotion/css@11.5.0(@babel/core@7.26.9)': dependencies: - '@emotion/babel-plugin': 11.12.0 - '@emotion/cache': 11.13.1 - '@emotion/serialize': 1.3.0 + '@emotion/babel-plugin': 11.13.5 + '@emotion/cache': 11.14.0 + '@emotion/serialize': 1.3.3 '@emotion/sheet': 1.4.0 - '@emotion/utils': 1.4.0 + '@emotion/utils': 1.4.2 optionalDependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.26.9 + transitivePeerDependencies: + - supports-color '@emotion/hash@0.9.2': {} '@emotion/memoize@0.9.0': {} - '@emotion/react@11.13.0(@types/react@18.2.20)(react@18.2.0)': + '@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@emotion/babel-plugin': 11.12.0 - '@emotion/cache': 11.13.1 - '@emotion/serialize': 1.3.0 - '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.2.0) - '@emotion/utils': 1.4.0 + '@babel/runtime': 7.26.9 + '@emotion/babel-plugin': 11.13.5 + '@emotion/cache': 11.14.0 + '@emotion/serialize': 1.3.3 + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1) + '@emotion/utils': 1.4.2 '@emotion/weak-memoize': 0.4.0 hoist-non-react-statics: 3.3.2 - react: 18.2.0 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 + transitivePeerDependencies: + - supports-color - '@emotion/serialize@1.3.0': + '@emotion/serialize@1.3.3': dependencies: '@emotion/hash': 0.9.2 '@emotion/memoize': 0.9.0 - '@emotion/unitless': 0.9.0 - '@emotion/utils': 1.4.0 - csstype: 3.1.2 + '@emotion/unitless': 0.10.0 + '@emotion/utils': 1.4.2 + csstype: 3.1.3 '@emotion/sheet@1.4.0': {} - '@emotion/unitless@0.9.0': {} + '@emotion/unitless@0.10.0': {} - '@emotion/use-insertion-effect-with-fallbacks@1.1.0(react@18.2.0)': + '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@18.3.1)': dependencies: - react: 18.2.0 + react: 18.3.1 - '@emotion/utils@1.4.0': {} + '@emotion/utils@1.4.2': {} '@emotion/weak-memoize@0.4.0': {} - '@esbuild/aix-ppc64@0.19.11': + '@esbuild/aix-ppc64@0.19.12': optional: true '@esbuild/aix-ppc64@0.25.0': @@ -10846,7 +10467,7 @@ snapshots: '@esbuild/android-arm64@0.18.20': optional: true - '@esbuild/android-arm64@0.19.11': + '@esbuild/android-arm64@0.19.12': optional: true '@esbuild/android-arm64@0.25.0': @@ -10855,7 +10476,7 @@ snapshots: '@esbuild/android-arm@0.18.20': optional: true - '@esbuild/android-arm@0.19.11': + '@esbuild/android-arm@0.19.12': optional: true '@esbuild/android-arm@0.25.0': @@ -10864,7 +10485,7 @@ snapshots: '@esbuild/android-x64@0.18.20': optional: true - '@esbuild/android-x64@0.19.11': + '@esbuild/android-x64@0.19.12': optional: true '@esbuild/android-x64@0.25.0': @@ -10873,7 +10494,7 @@ snapshots: '@esbuild/darwin-arm64@0.18.20': optional: true - '@esbuild/darwin-arm64@0.19.11': + '@esbuild/darwin-arm64@0.19.12': optional: true '@esbuild/darwin-arm64@0.25.0': @@ -10882,7 +10503,7 @@ snapshots: '@esbuild/darwin-x64@0.18.20': optional: true - '@esbuild/darwin-x64@0.19.11': + '@esbuild/darwin-x64@0.19.12': optional: true '@esbuild/darwin-x64@0.25.0': @@ -10891,7 +10512,7 @@ snapshots: '@esbuild/freebsd-arm64@0.18.20': optional: true - '@esbuild/freebsd-arm64@0.19.11': + '@esbuild/freebsd-arm64@0.19.12': optional: true '@esbuild/freebsd-arm64@0.25.0': @@ -10900,7 +10521,7 @@ snapshots: '@esbuild/freebsd-x64@0.18.20': optional: true - '@esbuild/freebsd-x64@0.19.11': + '@esbuild/freebsd-x64@0.19.12': optional: true '@esbuild/freebsd-x64@0.25.0': @@ -10909,7 +10530,7 @@ snapshots: '@esbuild/linux-arm64@0.18.20': optional: true - '@esbuild/linux-arm64@0.19.11': + '@esbuild/linux-arm64@0.19.12': optional: true '@esbuild/linux-arm64@0.25.0': @@ -10918,7 +10539,7 @@ snapshots: '@esbuild/linux-arm@0.18.20': optional: true - '@esbuild/linux-arm@0.19.11': + '@esbuild/linux-arm@0.19.12': optional: true '@esbuild/linux-arm@0.25.0': @@ -10927,7 +10548,7 @@ snapshots: '@esbuild/linux-ia32@0.18.20': optional: true - '@esbuild/linux-ia32@0.19.11': + '@esbuild/linux-ia32@0.19.12': optional: true '@esbuild/linux-ia32@0.25.0': @@ -10936,7 +10557,7 @@ snapshots: '@esbuild/linux-loong64@0.18.20': optional: true - '@esbuild/linux-loong64@0.19.11': + '@esbuild/linux-loong64@0.19.12': optional: true '@esbuild/linux-loong64@0.25.0': @@ -10945,7 +10566,7 @@ snapshots: '@esbuild/linux-mips64el@0.18.20': optional: true - '@esbuild/linux-mips64el@0.19.11': + '@esbuild/linux-mips64el@0.19.12': optional: true '@esbuild/linux-mips64el@0.25.0': @@ -10954,7 +10575,7 @@ snapshots: '@esbuild/linux-ppc64@0.18.20': optional: true - '@esbuild/linux-ppc64@0.19.11': + '@esbuild/linux-ppc64@0.19.12': optional: true '@esbuild/linux-ppc64@0.25.0': @@ -10963,7 +10584,7 @@ snapshots: '@esbuild/linux-riscv64@0.18.20': optional: true - '@esbuild/linux-riscv64@0.19.11': + '@esbuild/linux-riscv64@0.19.12': optional: true '@esbuild/linux-riscv64@0.25.0': @@ -10972,7 +10593,7 @@ snapshots: '@esbuild/linux-s390x@0.18.20': optional: true - '@esbuild/linux-s390x@0.19.11': + '@esbuild/linux-s390x@0.19.12': optional: true '@esbuild/linux-s390x@0.25.0': @@ -10981,7 +10602,7 @@ snapshots: '@esbuild/linux-x64@0.18.20': optional: true - '@esbuild/linux-x64@0.19.11': + '@esbuild/linux-x64@0.19.12': optional: true '@esbuild/linux-x64@0.25.0': @@ -10993,7 +10614,7 @@ snapshots: '@esbuild/netbsd-x64@0.18.20': optional: true - '@esbuild/netbsd-x64@0.19.11': + '@esbuild/netbsd-x64@0.19.12': optional: true '@esbuild/netbsd-x64@0.25.0': @@ -11005,7 +10626,7 @@ snapshots: '@esbuild/openbsd-x64@0.18.20': optional: true - '@esbuild/openbsd-x64@0.19.11': + '@esbuild/openbsd-x64@0.19.12': optional: true '@esbuild/openbsd-x64@0.25.0': @@ -11014,7 +10635,7 @@ snapshots: '@esbuild/sunos-x64@0.18.20': optional: true - '@esbuild/sunos-x64@0.19.11': + '@esbuild/sunos-x64@0.19.12': optional: true '@esbuild/sunos-x64@0.25.0': @@ -11023,7 +10644,7 @@ snapshots: '@esbuild/win32-arm64@0.18.20': optional: true - '@esbuild/win32-arm64@0.19.11': + '@esbuild/win32-arm64@0.19.12': optional: true '@esbuild/win32-arm64@0.25.0': @@ -11032,7 +10653,7 @@ snapshots: '@esbuild/win32-ia32@0.18.20': optional: true - '@esbuild/win32-ia32@0.19.11': + '@esbuild/win32-ia32@0.19.12': optional: true '@esbuild/win32-ia32@0.25.0': @@ -11041,63 +10662,63 @@ snapshots: '@esbuild/win32-x64@0.18.20': optional: true - '@esbuild/win32-x64@0.19.11': + '@esbuild/win32-x64@0.19.12': optional: true '@esbuild/win32-x64@0.25.0': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@8.50.0)': + '@eslint-community/eslint-utils@4.4.1(eslint@8.57.1)': dependencies: - eslint: 8.50.0 + eslint: 8.57.1 eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.8.0': {} + '@eslint-community/regexpp@4.12.1': {} - '@eslint/eslintrc@2.1.2': + '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 debug: 4.4.0(supports-color@8.1.1) espree: 9.6.1 - globals: 13.21.0 - ignore: 5.2.4 - import-fresh: 3.3.0 + globals: 13.24.0 + ignore: 5.3.2 + import-fresh: 3.3.1 js-yaml: 4.1.0 minimatch: 3.1.2 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - '@eslint/js@8.50.0': {} + '@eslint/js@8.57.1': {} '@fal-works/esbuild-plugin-global-externals@2.1.2': {} - '@fastify/busboy@2.0.0': {} + '@fastify/busboy@2.1.1': {} - '@floating-ui/core@1.5.0': + '@floating-ui/core@1.6.9': dependencies: - '@floating-ui/utils': 0.1.6 + '@floating-ui/utils': 0.2.9 - '@floating-ui/dom@1.5.3': + '@floating-ui/dom@1.6.13': dependencies: - '@floating-ui/core': 1.5.0 - '@floating-ui/utils': 0.1.6 + '@floating-ui/core': 1.6.9 + '@floating-ui/utils': 0.2.9 - '@floating-ui/react-dom@2.0.9(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@floating-ui/react-dom@2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@floating-ui/dom': 1.5.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@floating-ui/dom': 1.6.13 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - '@floating-ui/react@0.26.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@floating-ui/react@0.26.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@floating-ui/react-dom': 2.0.9(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@floating-ui/utils': 0.1.6 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@floating-ui/utils': 0.2.9 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) tabbable: 6.2.0 - '@floating-ui/utils@0.1.6': {} + '@floating-ui/utils@0.2.9': {} '@gar/promisify@1.1.3': optional: true @@ -11108,9 +10729,9 @@ snapshots: dependencies: '@hapi/hoek': 9.3.0 - '@humanwhocodes/config-array@0.11.11': + '@humanwhocodes/config-array@0.13.0': dependencies: - '@humanwhocodes/object-schema': 1.2.1 + '@humanwhocodes/object-schema': 2.0.3 debug: 4.4.0(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: @@ -11118,7 +10739,7 @@ snapshots: '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/object-schema@1.2.1': {} + '@humanwhocodes/object-schema@2.0.3': {} '@img/sharp-darwin-arm64@0.33.5': optionalDependencies: @@ -11220,7 +10841,7 @@ snapshots: '@jest/transform@29.7.0': dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.26.9 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 babel-plugin-istanbul: 6.1.1 @@ -11231,7 +10852,7 @@ snapshots: jest-haste-map: 29.7.0 jest-regex-util: 29.6.3 jest-util: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.8 pirates: 4.0.6 slash: 3.0.0 write-file-atomic: 4.0.2 @@ -11241,397 +10862,441 @@ snapshots: '@jest/types@29.6.3': dependencies: '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.4 - '@types/istanbul-reports': 3.0.2 - '@types/node': 22.8.1 - '@types/yargs': 17.0.28 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.13.9 + '@types/yargs': 17.0.33 chalk: 4.1.2 - '@jimp/bmp@0.10.3(@jimp/custom@0.10.3)': + '@jimp/bmp@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 bmp-js: 0.1.0 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/core@0.10.3': + '@jimp/core@0.10.3(debug@4.4.0)': dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.26.9 '@jimp/utils': 0.10.3 any-base: 1.1.0 buffer: 6.0.3 - core-js: 3.37.1 + core-js: 3.41.0 exif-parser: 0.1.12 file-type: 9.0.0 - load-bmfont: 1.4.1 + load-bmfont: 1.4.2(debug@4.4.0) mkdirp: 0.5.6 phin: 2.9.3 pixelmatch: 4.0.2 tinycolor2: 1.6.0 + transitivePeerDependencies: + - debug optional: true - '@jimp/custom@0.10.3': + '@jimp/custom@0.10.3(debug@4.4.0)': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/core': 0.10.3 - core-js: 3.37.1 + '@babel/runtime': 7.26.9 + '@jimp/core': 0.10.3(debug@4.4.0) + core-js: 3.41.0 + transitivePeerDependencies: + - debug optional: true - '@jimp/gif@0.10.3(@jimp/custom@0.10.3)': + '@jimp/gif@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 omggif: 1.0.10 optional: true - '@jimp/jpeg@0.10.3(@jimp/custom@0.10.3)': + '@jimp/jpeg@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 jpeg-js: 0.3.7 optional: true - '@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-blur@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugin-blur@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-circle@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugin-circle@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-color@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugin-color@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 tinycolor2: 1.6.0 optional: true - '@jimp/plugin-contain@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-scale@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3)))': + '@jimp/plugin-contain@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-scale@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 - '@jimp/plugin-blit': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-scale': 0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3)) + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) + '@jimp/plugin-blit': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-scale': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-cover@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-scale@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3)))': + '@jimp/plugin-cover@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-scale@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 - '@jimp/plugin-crop': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-scale': 0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3)) + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) + '@jimp/plugin-crop': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-scale': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-displace@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugin-displace@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-dither@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugin-dither@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-fisheye@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugin-fisheye@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-flip@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-rotate@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3)))': + '@jimp/plugin-flip@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-rotate@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 - '@jimp/plugin-rotate': 0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3)) + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) + '@jimp/plugin-rotate': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-gaussian@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugin-gaussian@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-invert@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugin-invert@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-mask@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugin-mask@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-normalize@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugin-normalize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-print@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3))': + '@jimp/plugin-print@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(debug@4.4.0)': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 - '@jimp/plugin-blit': 0.10.3(@jimp/custom@0.10.3) + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) + '@jimp/plugin-blit': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) '@jimp/utils': 0.10.3 - core-js: 3.37.1 - load-bmfont: 1.4.1 + core-js: 3.41.0 + load-bmfont: 1.4.2(debug@4.4.0) + transitivePeerDependencies: + - debug optional: true - '@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-rotate@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3))': + '@jimp/plugin-rotate@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 - '@jimp/plugin-blit': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-crop': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3) + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) + '@jimp/plugin-blit': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-crop': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-scale@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3))': + '@jimp/plugin-scale@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 - '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3) + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) + '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-shadow@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-blur@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3))': + '@jimp/plugin-shadow@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-blur@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 - '@jimp/plugin-blur': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3) + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) + '@jimp/plugin-blur': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugin-threshold@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-color@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3))': + '@jimp/plugin-threshold@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-color@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 - '@jimp/plugin-color': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3) + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) + '@jimp/plugin-color': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 optional: true - '@jimp/plugins@0.10.3(@jimp/custom@0.10.3)': + '@jimp/plugins@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(debug@4.4.0)': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 - '@jimp/plugin-blit': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-blur': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-circle': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-color': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-contain': 0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-scale@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3))) - '@jimp/plugin-cover': 0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-scale@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3))) - '@jimp/plugin-crop': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-displace': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-dither': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-fisheye': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-flip': 0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-rotate@0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3))) - '@jimp/plugin-gaussian': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-invert': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-mask': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-normalize': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-print': 0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3)) - '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3) - '@jimp/plugin-rotate': 0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3)) - '@jimp/plugin-scale': 0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3)) - '@jimp/plugin-shadow': 0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-blur@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3)) - '@jimp/plugin-threshold': 0.10.3(@jimp/custom@0.10.3)(@jimp/plugin-color@0.10.3(@jimp/custom@0.10.3))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3)) - core-js: 3.37.1 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) + '@jimp/plugin-blit': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-blur': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-circle': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-color': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-contain': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-scale@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))) + '@jimp/plugin-cover': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-scale@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))) + '@jimp/plugin-crop': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-displace': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-dither': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-fisheye': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-flip': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-rotate@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))) + '@jimp/plugin-gaussian': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-invert': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-mask': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-normalize': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-print': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(debug@4.4.0) + '@jimp/plugin-resize': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/plugin-rotate': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-blit@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-crop@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))) + '@jimp/plugin-scale': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))) + '@jimp/plugin-shadow': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-blur@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))) + '@jimp/plugin-threshold': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(@jimp/plugin-color@0.10.3(@jimp/custom@0.10.3(debug@4.4.0)))(@jimp/plugin-resize@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))) + core-js: 3.41.0 timm: 1.7.1 + transitivePeerDependencies: + - debug optional: true - '@jimp/png@0.10.3(@jimp/custom@0.10.3)': + '@jimp/png@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) '@jimp/utils': 0.10.3 - core-js: 3.37.1 + core-js: 3.41.0 pngjs: 3.4.0 optional: true - '@jimp/tiff@0.10.3(@jimp/custom@0.10.3)': + '@jimp/tiff@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 - core-js: 3.37.1 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) + core-js: 3.41.0 utif: 2.0.1 optional: true - '@jimp/types@0.10.3(@jimp/custom@0.10.3)': + '@jimp/types@0.10.3(@jimp/custom@0.10.3(debug@4.4.0))': dependencies: - '@babel/runtime': 7.24.5 - '@jimp/bmp': 0.10.3(@jimp/custom@0.10.3) - '@jimp/custom': 0.10.3 - '@jimp/gif': 0.10.3(@jimp/custom@0.10.3) - '@jimp/jpeg': 0.10.3(@jimp/custom@0.10.3) - '@jimp/png': 0.10.3(@jimp/custom@0.10.3) - '@jimp/tiff': 0.10.3(@jimp/custom@0.10.3) - core-js: 3.37.1 + '@babel/runtime': 7.26.9 + '@jimp/bmp': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/custom': 0.10.3(debug@4.4.0) + '@jimp/gif': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/jpeg': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/png': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + '@jimp/tiff': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + core-js: 3.41.0 timm: 1.7.1 optional: true '@jimp/utils@0.10.3': dependencies: - '@babel/runtime': 7.24.5 - core-js: 3.37.1 + '@babel/runtime': 7.26.9 + core-js: 3.41.0 regenerator-runtime: 0.13.11 optional: true - '@joshwooding/vite-plugin-react-docgen-typescript@0.2.1(typescript@5.5.4)(vite@6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1))': + '@joshwooding/vite-plugin-react-docgen-typescript@0.3.0(typescript@5.5.4)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))': dependencies: glob: 7.2.3 glob-promise: 4.2.2(glob@7.2.3) magic-string: 0.27.0 react-docgen-typescript: 2.2.2(typescript@5.5.4) - vite: 6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1) + vite: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) optionalDependencies: typescript: 5.5.4 - '@jridgewell/gen-mapping@0.3.3': + '@jridgewell/gen-mapping@0.3.8': dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 - '@jridgewell/resolve-uri@3.1.1': {} + '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/set-array@1.1.2': {} + '@jridgewell/set-array@1.2.1': {} - '@jridgewell/source-map@0.3.5': + '@jridgewell/source-map@0.3.6': dependencies: - '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - '@jridgewell/sourcemap-codec@1.4.15': {} - '@jridgewell/sourcemap-codec@1.5.0': {} '@jridgewell/trace-mapping@0.3.25': dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 - '@jspm/core@2.0.1': {} + '@jsonjoy.com/base64@1.1.2(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@1.2.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) + '@jsonjoy.com/util': 1.5.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 1.21.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@1.5.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jspm/core@2.1.0': {} '@juggle/resize-observer@3.3.1': {} + '@juggle/resize-observer@3.4.0': {} + '@mapbox/node-pre-gyp@1.0.11(encoding@0.1.13)': dependencies: - detect-libc: 2.0.2 + detect-libc: 2.0.3 https-proxy-agent: 5.0.1 make-dir: 3.1.0 node-fetch: 2.7.0(encoding@0.1.13) nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 - semver: 7.6.0 - tar: 6.2.0 + semver: 7.7.1 + tar: 6.2.1 transitivePeerDependencies: - encoding - supports-color optional: true - '@mdx-js/react@2.3.0(react@18.2.0)': + '@mdx-js/react@2.3.0(react@18.3.1)': dependencies: - '@types/mdx': 2.0.8 - '@types/react': 18.2.20 - react: 18.2.0 + '@types/mdx': 2.0.13 + '@types/react': 18.3.18 + react: 18.3.1 - '@module-federation/runtime-tools@0.2.3': + '@module-federation/error-codes@0.11.2': {} + + '@module-federation/runtime-core@0.11.2': dependencies: - '@module-federation/runtime': 0.2.3 - '@module-federation/webpack-bundler-runtime': 0.2.3 + '@module-federation/error-codes': 0.11.2 + '@module-federation/sdk': 0.11.2 - '@module-federation/runtime@0.2.3': + '@module-federation/runtime-tools@0.11.2': dependencies: - '@module-federation/sdk': 0.2.3 + '@module-federation/runtime': 0.11.2 + '@module-federation/webpack-bundler-runtime': 0.11.2 - '@module-federation/sdk@0.2.3': {} - - '@module-federation/webpack-bundler-runtime@0.2.3': + '@module-federation/runtime@0.11.2': dependencies: - '@module-federation/runtime': 0.2.3 - '@module-federation/sdk': 0.2.3 + '@module-federation/error-codes': 0.11.2 + '@module-federation/runtime-core': 0.11.2 + '@module-federation/sdk': 0.11.2 + + '@module-federation/sdk@0.11.2': {} + + '@module-federation/webpack-bundler-runtime@0.11.2': + dependencies: + '@module-federation/runtime': 0.11.2 + '@module-federation/sdk': 0.11.2 + + '@monaco-editor/loader@1.5.0': + dependencies: + state-local: 1.0.7 + + '@monaco-editor/react@4.7.0(monaco-editor@0.52.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@monaco-editor/loader': 1.5.0 + monaco-editor: 0.52.2 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) '@msgpack/msgpack@2.8.0': {} '@ndelangen/get-tarball@3.0.9': dependencies: gunzip-maybe: 1.4.2 - pump: 3.0.0 - tar-fs: 2.1.1 + pump: 3.0.2 + tar-fs: 2.1.2 '@nodelib/fs.scandir@2.1.5': dependencies: @@ -11643,12 +11308,12 @@ snapshots: '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.15.0 + fastq: 1.19.1 '@npmcli/fs@2.1.2': dependencies: '@gar/promisify': 1.1.3 - semver: 7.6.0 + semver: 7.7.1 optional: true '@npmcli/move-file@2.0.1': @@ -11657,25 +11322,38 @@ snapshots: rimraf: 3.0.2 optional: true - '@nxg-org/mineflayer-auto-jump@0.7.12': + '@nxg-org/mineflayer-auto-jump@0.7.18': dependencies: - '@nxg-org/mineflayer-physics-util': 1.5.8 + '@nxg-org/mineflayer-physics-util': 1.8.10 strict-event-emitter-types: 2.0.0 - '@nxg-org/mineflayer-physics-util@1.5.8': + '@nxg-org/mineflayer-physics-util@1.8.10': dependencies: - '@nxg-org/mineflayer-util-plugin': 1.8.3 + '@nxg-org/mineflayer-util-plugin': 1.8.4 - '@nxg-org/mineflayer-tracker@1.2.1': + '@nxg-org/mineflayer-tracker@1.3.0(encoding@0.1.13)': dependencies: - '@nxg-org/mineflayer-trajectories': 1.1.1 - '@nxg-org/mineflayer-util-plugin': 1.8.3 + '@nxg-org/mineflayer-physics-util': 1.8.10 + '@nxg-org/mineflayer-trajectories': 1.2.0(encoding@0.1.13) + '@nxg-org/mineflayer-util-plugin': 1.8.4 + transitivePeerDependencies: + - encoding + - supports-color - '@nxg-org/mineflayer-trajectories@1.1.1': + '@nxg-org/mineflayer-trajectories@1.2.0(encoding@0.1.13)': dependencies: - '@nxg-org/mineflayer-util-plugin': 1.8.3 + '@nxg-org/mineflayer-util-plugin': 1.8.4 + minecraft-data: 3.98.0 + mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13) + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9 + prismarine-item: 1.17.0 + prismarine-physics: https://codeload.github.com/zardoy/prismarine-physics/tar.gz/353e25b800149393f40539ec381218be44cbb03b + vec3: 0.1.10 + transitivePeerDependencies: + - encoding + - supports-color - '@nxg-org/mineflayer-util-plugin@1.8.3': {} + '@nxg-org/mineflayer-util-plugin@1.8.4': {} '@pkgjs/parseargs@0.11.0': optional: true @@ -11684,433 +11362,512 @@ snapshots: '@radix-ui/number@1.0.1': dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.26.9 '@radix-ui/primitive@1.0.1': dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.26.9 - '@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/primitive@1.1.1': {} + + '@radix-ui/react-arrow@1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@babel/runtime': 7.26.9 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-collection@1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.20)(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@babel/runtime': 7.26.9 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.20)(react@18.2.0)': + '@radix-ui/react-collection@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - react: 18.2.0 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.2(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-context@1.0.1(@types/react@18.2.20)(react@18.2.0)': + '@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - react: 18.2.0 + '@babel/runtime': 7.26.9 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - '@radix-ui/react-direction@1.0.1(@types/react@18.2.20)(react@18.2.0)': + '@radix-ui/react-compose-refs@1.1.1(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - react: 18.2.0 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - '@radix-ui/react-dismissable-layer@1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-context@1.0.1(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.26.9 + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 + + '@radix-ui/react-context@1.1.1(@types/react@18.3.18)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 + + '@radix-ui/react-direction@1.0.1(@types/react@18.3.18)(react@18.3.1)': + dependencies: + '@babel/runtime': 7.26.9 + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 + + '@radix-ui/react-direction@1.1.0(@types/react@18.3.18)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 + + '@radix-ui/react-dismissable-layer@1.0.4(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@babel/runtime': 7.26.9 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.20)(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.20)(react@18.2.0)': + '@radix-ui/react-focus-guards@1.0.1(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - react: 18.2.0 + '@babel/runtime': 7.26.9 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - '@radix-ui/react-focus-scope@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-focus-scope@1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.20)(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@babel/runtime': 7.26.9 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-id@1.0.1(@types/react@18.2.20)(react@18.2.0)': + '@radix-ui/react-id@1.0.1(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.20)(react@18.2.0) - react: 18.2.0 + '@babel/runtime': 7.26.9 + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - '@radix-ui/react-popper@1.1.2(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-id@1.1.0(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@floating-ui/react-dom': 2.0.9(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.20)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 + + '@radix-ui/react-popper@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@babel/runtime': 7.26.9 + '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-use-rect': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.3.18)(react@18.3.1) '@radix-ui/rect': 1.0.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-portal@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-portal@1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@babel/runtime': 7.26.9 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.20)(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@babel/runtime': 7.26.9 + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-primitive@2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-direction': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.20)(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@radix-ui/react-slot': 1.1.2(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-select@1.2.2(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-roving-focus@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-collection': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) + + '@radix-ui/react-select@1.2.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@babel/runtime': 7.26.9 '@radix-ui/number': 1.0.1 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-direction': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-dismissable-layer': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-focus-scope': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-popper': 1.1.2(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-portal': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - aria-hidden: 1.2.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-remove-scroll: 2.5.5(@types/react@18.2.20)(react@18.2.0) + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-direction': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.0.4(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-popper': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-use-previous': 1.0.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + aria-hidden: 1.2.4 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-remove-scroll: 2.5.5(@types/react@18.3.18)(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-separator@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-separator@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-slot@1.0.2(@types/react@18.2.20)(react@18.2.0)': + '@radix-ui/react-slot@1.0.2(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.20)(react@18.2.0) - react: 18.2.0 + '@babel/runtime': 7.26.9 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - '@radix-ui/react-toggle-group@1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-slot@1.1.2(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-context': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-direction': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-toggle': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.20)(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 - '@radix-ui/react-toggle@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-toggle-group@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.20)(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-toggle': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-toolbar@1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-toggle@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-context': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-direction': 1.0.1(@types/react@18.2.20)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-separator': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-toggle-group': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.20)(react@18.2.0)': + '@radix-ui/react-toolbar@1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - react: 18.2.0 + '@radix-ui/primitive': 1.1.1 + '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.18)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-separator': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-toggle-group': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) - '@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.20)(react@18.2.0)': + '@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.20)(react@18.2.0) - react: 18.2.0 + '@babel/runtime': 7.26.9 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.20)(react@18.2.0)': + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.20)(react@18.2.0) - react: 18.2.0 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - '@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.20)(react@18.2.0)': + '@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - react: 18.2.0 + '@babel/runtime': 7.26.9 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - '@radix-ui/react-use-previous@1.0.1(@types/react@18.2.20)(react@18.2.0)': + '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - react: 18.2.0 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - '@radix-ui/react-use-rect@1.0.1(@types/react@18.2.20)(react@18.2.0)': + '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.26.9 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 + + '@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.3.18)(react@18.3.1)': + dependencies: + '@babel/runtime': 7.26.9 + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 + + '@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.3.18)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 + + '@radix-ui/react-use-previous@1.0.1(@types/react@18.3.18)(react@18.3.1)': + dependencies: + '@babel/runtime': 7.26.9 + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.18 + + '@radix-ui/react-use-rect@1.0.1(@types/react@18.3.18)(react@18.3.1)': + dependencies: + '@babel/runtime': 7.26.9 '@radix-ui/rect': 1.0.1 - react: 18.2.0 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - '@radix-ui/react-use-size@1.0.1(@types/react@18.2.20)(react@18.2.0)': + '@radix-ui/react-use-size@1.0.1(@types/react@18.3.18)(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.20)(react@18.2.0) - react: 18.2.0 + '@babel/runtime': 7.26.9 + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.18)(react@18.3.1) + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - '@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.24.5 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@babel/runtime': 7.26.9 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - '@types/react-dom': 18.2.7 + '@types/react': 18.3.18 + '@types/react-dom': 18.3.5(@types/react@18.3.18) '@radix-ui/rect@1.0.1': dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.26.9 - '@react-oauth/google@0.12.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@react-oauth/google@0.12.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - '@rollup/plugin-babel@5.3.1(@babel/core@7.22.11)(@types/babel__core@7.20.2)(rollup@2.79.1)': + '@rollup/plugin-babel@5.3.1(@babel/core@7.26.9)(@types/babel__core@7.20.5)(rollup@2.79.2)': dependencies: - '@babel/core': 7.22.11 - '@babel/helper-module-imports': 7.22.15 - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) - rollup: 2.79.1 + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + rollup: 2.79.2 optionalDependencies: - '@types/babel__core': 7.20.2 + '@types/babel__core': 7.20.5 + transitivePeerDependencies: + - supports-color - '@rollup/plugin-node-resolve@11.2.1(rollup@2.79.1)': + '@rollup/plugin-node-resolve@15.3.1(rollup@2.79.2)': dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) - '@types/resolve': 1.17.1 - builtin-modules: 3.3.0 + '@rollup/pluginutils': 5.1.4(rollup@2.79.2) + '@types/resolve': 1.20.2 deepmerge: 4.3.1 is-module: 1.0.0 - resolve: 1.22.4 - rollup: 2.79.1 + resolve: 1.22.10 + optionalDependencies: + rollup: 2.79.2 - '@rollup/plugin-replace@2.4.2(rollup@2.79.1)': + '@rollup/plugin-replace@2.4.2(rollup@2.79.2)': dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) magic-string: 0.25.9 - rollup: 2.79.1 + rollup: 2.79.2 - '@rollup/pluginutils@3.1.0(rollup@2.79.1)': + '@rollup/plugin-terser@0.4.4(rollup@2.79.2)': + dependencies: + serialize-javascript: 6.0.2 + smob: 1.5.0 + terser: 5.39.0 + optionalDependencies: + rollup: 2.79.2 + + '@rollup/pluginutils@3.1.0(rollup@2.79.2)': dependencies: '@types/estree': 0.0.39 estree-walker: 1.0.1 picomatch: 2.3.1 - rollup: 2.79.1 + rollup: 2.79.2 - '@rollup/pluginutils@5.0.5(rollup@2.79.1)': + '@rollup/pluginutils@5.1.4(rollup@2.79.2)': dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 estree-walker: 2.0.2 - picomatch: 2.3.1 + picomatch: 4.0.2 optionalDependencies: - rollup: 2.79.1 + rollup: 2.79.2 - '@rollup/rollup-android-arm-eabi@4.34.8': + '@rollup/rollup-android-arm-eabi@4.34.9': optional: true - '@rollup/rollup-android-arm64@4.34.8': + '@rollup/rollup-android-arm64@4.34.9': optional: true - '@rollup/rollup-darwin-arm64@4.34.8': + '@rollup/rollup-darwin-arm64@4.34.9': optional: true - '@rollup/rollup-darwin-x64@4.34.8': + '@rollup/rollup-darwin-x64@4.34.9': optional: true - '@rollup/rollup-freebsd-arm64@4.34.8': + '@rollup/rollup-freebsd-arm64@4.34.9': optional: true - '@rollup/rollup-freebsd-x64@4.34.8': + '@rollup/rollup-freebsd-x64@4.34.9': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.34.8': + '@rollup/rollup-linux-arm-gnueabihf@4.34.9': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.34.8': + '@rollup/rollup-linux-arm-musleabihf@4.34.9': optional: true - '@rollup/rollup-linux-arm64-gnu@4.34.8': + '@rollup/rollup-linux-arm64-gnu@4.34.9': optional: true - '@rollup/rollup-linux-arm64-musl@4.34.8': + '@rollup/rollup-linux-arm64-musl@4.34.9': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.34.8': + '@rollup/rollup-linux-loongarch64-gnu@4.34.9': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': + '@rollup/rollup-linux-powerpc64le-gnu@4.34.9': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.34.8': + '@rollup/rollup-linux-riscv64-gnu@4.34.9': optional: true - '@rollup/rollup-linux-s390x-gnu@4.34.8': + '@rollup/rollup-linux-s390x-gnu@4.34.9': optional: true - '@rollup/rollup-linux-x64-gnu@4.34.8': + '@rollup/rollup-linux-x64-gnu@4.34.9': optional: true - '@rollup/rollup-linux-x64-musl@4.34.8': + '@rollup/rollup-linux-x64-musl@4.34.9': optional: true - '@rollup/rollup-win32-arm64-msvc@4.34.8': + '@rollup/rollup-win32-arm64-msvc@4.34.9': optional: true - '@rollup/rollup-win32-ia32-msvc@4.34.8': + '@rollup/rollup-win32-ia32-msvc@4.34.9': optional: true - '@rollup/rollup-win32-x64-msvc@4.34.8': + '@rollup/rollup-win32-x64-msvc@4.34.9': optional: true - '@rsbuild/core@1.0.1-beta.9': + '@rsbuild/core@1.3.5': dependencies: - '@rspack/core': 1.0.0-beta.1(@swc/helpers@0.5.11) - '@rspack/lite-tapable': 1.0.0-beta.1 - '@swc/helpers': 0.5.11 - caniuse-lite: 1.0.30001646 - core-js: 3.37.1 - optionalDependencies: - fsevents: 2.3.3 + '@rspack/core': 1.3.3(@swc/helpers@0.5.15) + '@rspack/lite-tapable': 1.0.1 + '@swc/helpers': 0.5.15 + core-js: 3.41.0 + jiti: 2.4.2 + transitivePeerDependencies: + - '@rspack/tracing' - '@rsbuild/plugin-node-polyfill@1.0.3(@rsbuild/core@1.0.1-beta.9)': + '@rsbuild/plugin-node-polyfill@1.3.0(@rsbuild/core@1.3.5)': dependencies: assert: 2.1.0 browserify-zlib: 0.2.0 buffer: 6.0.3 console-browserify: 1.2.0 constants-browserify: 1.0.0 - crypto-browserify: 3.12.0 + crypto-browserify: 3.12.1 domain-browser: 5.7.0 events: 3.3.0 https-browserify: 1.0.0 @@ -12119,101 +11876,99 @@ snapshots: process: 0.11.10 punycode: 2.3.1 querystring-es3: 0.2.1 - readable-stream: 4.5.2 + readable-stream: 4.7.0 stream-browserify: 3.0.0 stream-http: 3.2.0 string_decoder: 1.3.0 timers-browserify: 2.0.12 tty-browserify: 0.0.1 - url: 0.11.3 + url: 0.11.4 util: 0.12.5 vm-browserify: 1.1.2 optionalDependencies: - '@rsbuild/core': 1.0.1-beta.9 + '@rsbuild/core': 1.3.5 - '@rsbuild/plugin-react@1.0.1-beta.9(@rsbuild/core@1.0.1-beta.9)': + '@rsbuild/plugin-react@1.2.0(@rsbuild/core@1.3.5)': dependencies: - '@rsbuild/core': 1.0.1-beta.9 - '@rspack/plugin-react-refresh': 1.0.0-beta.1(react-refresh@0.14.2) - react-refresh: 0.14.2 - - '@rsbuild/plugin-type-check@1.0.1-beta.9(@rsbuild/core@1.0.1-beta.9)(esbuild@0.19.11)(typescript@5.5.4)': - dependencies: - '@rsbuild/core': 1.0.1-beta.9 - deepmerge: 4.3.1 - fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.5.4)(webpack@5.93.0(esbuild@0.19.11)) - json5: 2.2.3 - reduce-configs: 1.0.0 - webpack: 5.93.0(esbuild@0.19.11) + '@rsbuild/core': 1.3.5 + '@rspack/plugin-react-refresh': 1.2.0(react-refresh@0.17.0) + react-refresh: 0.17.0 transitivePeerDependencies: - - '@swc/core' - - esbuild - - typescript - - uglify-js - - webpack-cli + - webpack-hot-middleware - '@rsbuild/plugin-typed-css-modules@1.0.1(@rsbuild/core@1.0.1-beta.9)': - optionalDependencies: - '@rsbuild/core': 1.0.1-beta.9 - - '@rspack/binding-darwin-arm64@1.0.0-beta.1': - optional: true - - '@rspack/binding-darwin-x64@1.0.0-beta.1': - optional: true - - '@rspack/binding-linux-arm64-gnu@1.0.0-beta.1': - optional: true - - '@rspack/binding-linux-arm64-musl@1.0.0-beta.1': - optional: true - - '@rspack/binding-linux-x64-gnu@1.0.0-beta.1': - optional: true - - '@rspack/binding-linux-x64-musl@1.0.0-beta.1': - optional: true - - '@rspack/binding-win32-arm64-msvc@1.0.0-beta.1': - optional: true - - '@rspack/binding-win32-ia32-msvc@1.0.0-beta.1': - optional: true - - '@rspack/binding-win32-x64-msvc@1.0.0-beta.1': - optional: true - - '@rspack/binding@1.0.0-beta.1': - optionalDependencies: - '@rspack/binding-darwin-arm64': 1.0.0-beta.1 - '@rspack/binding-darwin-x64': 1.0.0-beta.1 - '@rspack/binding-linux-arm64-gnu': 1.0.0-beta.1 - '@rspack/binding-linux-arm64-musl': 1.0.0-beta.1 - '@rspack/binding-linux-x64-gnu': 1.0.0-beta.1 - '@rspack/binding-linux-x64-musl': 1.0.0-beta.1 - '@rspack/binding-win32-arm64-msvc': 1.0.0-beta.1 - '@rspack/binding-win32-ia32-msvc': 1.0.0-beta.1 - '@rspack/binding-win32-x64-msvc': 1.0.0-beta.1 - - '@rspack/core@1.0.0-beta.1(@swc/helpers@0.5.11)': + '@rsbuild/plugin-type-check@1.2.1(@rsbuild/core@1.3.5)(@rspack/core@1.3.3(@swc/helpers@0.5.15))(typescript@5.5.4)': dependencies: - '@module-federation/runtime-tools': 0.2.3 - '@rspack/binding': 1.0.0-beta.1 - '@rspack/lite-tapable': 1.0.0-beta.1 - caniuse-lite: 1.0.30001646 + deepmerge: 4.3.1 + json5: 2.2.3 + reduce-configs: 1.1.0 + ts-checker-rspack-plugin: 1.1.1(@rspack/core@1.3.3(@swc/helpers@0.5.15))(typescript@5.5.4) optionalDependencies: - '@swc/helpers': 0.5.11 + '@rsbuild/core': 1.3.5 + transitivePeerDependencies: + - '@rspack/core' + - typescript - '@rspack/lite-tapable@1.0.0-beta.1': {} + '@rsbuild/plugin-typed-css-modules@1.0.2(@rsbuild/core@1.3.5)': + optionalDependencies: + '@rsbuild/core': 1.3.5 - '@rspack/plugin-react-refresh@1.0.0-beta.1(react-refresh@0.14.2)': + '@rspack/binding-darwin-arm64@1.3.3': + optional: true + + '@rspack/binding-darwin-x64@1.3.3': + optional: true + + '@rspack/binding-linux-arm64-gnu@1.3.3': + optional: true + + '@rspack/binding-linux-arm64-musl@1.3.3': + optional: true + + '@rspack/binding-linux-x64-gnu@1.3.3': + optional: true + + '@rspack/binding-linux-x64-musl@1.3.3': + optional: true + + '@rspack/binding-win32-arm64-msvc@1.3.3': + optional: true + + '@rspack/binding-win32-ia32-msvc@1.3.3': + optional: true + + '@rspack/binding-win32-x64-msvc@1.3.3': + optional: true + + '@rspack/binding@1.3.3': + optionalDependencies: + '@rspack/binding-darwin-arm64': 1.3.3 + '@rspack/binding-darwin-x64': 1.3.3 + '@rspack/binding-linux-arm64-gnu': 1.3.3 + '@rspack/binding-linux-arm64-musl': 1.3.3 + '@rspack/binding-linux-x64-gnu': 1.3.3 + '@rspack/binding-linux-x64-musl': 1.3.3 + '@rspack/binding-win32-arm64-msvc': 1.3.3 + '@rspack/binding-win32-ia32-msvc': 1.3.3 + '@rspack/binding-win32-x64-msvc': 1.3.3 + + '@rspack/core@1.3.3(@swc/helpers@0.5.15)': + dependencies: + '@module-federation/runtime-tools': 0.11.2 + '@rspack/binding': 1.3.3 + '@rspack/lite-tapable': 1.0.1 + caniuse-lite: 1.0.30001713 + optionalDependencies: + '@swc/helpers': 0.5.15 + + '@rspack/lite-tapable@1.0.1': {} + + '@rspack/plugin-react-refresh@1.2.0(react-refresh@0.17.0)': dependencies: error-stack-parser: 2.1.4 - html-entities: 2.5.2 - optionalDependencies: - react-refresh: 0.14.2 + html-entities: 2.6.0 + react-refresh: 0.17.0 - '@rushstack/eslint-patch@1.4.0': {} + '@rushstack/eslint-patch@1.10.5': {} '@sideway/address@4.1.5': dependencies: @@ -12225,95 +11980,56 @@ snapshots: '@sinclair/typebox@0.27.8': {} - '@socket.io/component-emitter@3.1.0': {} + '@socket.io/component-emitter@3.1.2': {} - '@storybook/addon-actions@7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/addon-actions@7.6.20': dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/core-events': 7.4.6 + '@storybook/core-events': 7.6.20 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/types': 7.4.6 + '@types/uuid': 9.0.8 dequal: 2.0.3 - lodash: 4.17.21 - polished: 4.2.2 - prop-types: 15.8.1 - react-inspector: 6.0.2(react@18.2.0) - telejson: 7.2.0 - ts-dedent: 2.2.0 + polished: 4.3.1 uuid: 9.0.1 - optionalDependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - '@storybook/addon-backgrounds@7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/addon-backgrounds@7.6.20': dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/core-events': 7.4.6 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/types': 7.4.6 memoizerific: 1.11.3 ts-dedent: 2.2.0 - optionalDependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - '@storybook/addon-controls@7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/addon-controls@7.6.20(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@storybook/blocks': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/core-common': 7.4.6(encoding@0.1.13) - '@storybook/core-events': 7.4.6 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/node-logger': 7.4.6 - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/blocks': 7.6.20(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) lodash: 4.17.21 ts-dedent: 2.2.0 - optionalDependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) transitivePeerDependencies: - '@types/react' - '@types/react-dom' - encoding + - react + - react-dom - supports-color - '@storybook/addon-docs@7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/addon-docs@7.6.20(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@jest/transform': 29.7.0 - '@mdx-js/react': 2.3.0(react@18.2.0) - '@storybook/blocks': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/csf-plugin': 7.4.6 - '@storybook/csf-tools': 7.4.6 + '@mdx-js/react': 2.3.0(react@18.3.1) + '@storybook/blocks': 7.6.20(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/client-logger': 7.6.20 + '@storybook/components': 7.6.20(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/csf-plugin': 7.6.20 + '@storybook/csf-tools': 7.6.20 '@storybook/global': 5.0.0 '@storybook/mdx2-csf': 1.1.0 - '@storybook/node-logger': 7.4.6 - '@storybook/postinstall': 7.4.6 - '@storybook/preview-api': 7.4.6 - '@storybook/react-dom-shim': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/theming': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/types': 7.4.6 - fs-extra: 11.1.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@storybook/node-logger': 7.6.20 + '@storybook/postinstall': 7.6.20 + '@storybook/preview-api': 7.6.20 + '@storybook/react-dom-shim': 7.6.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/theming': 7.6.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/types': 7.6.20 + fs-extra: 11.3.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) remark-external-links: 8.0.0 remark-slug: 6.1.0 ts-dedent: 2.2.0 @@ -12323,23 +12039,23 @@ snapshots: - encoding - supports-color - '@storybook/addon-essentials@7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/addon-essentials@7.6.20(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@storybook/addon-actions': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/addon-backgrounds': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/addon-controls': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/addon-docs': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/addon-highlight': 7.4.6 - '@storybook/addon-measure': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/addon-outline': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/addon-toolbars': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/addon-viewport': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/core-common': 7.4.6(encoding@0.1.13) - '@storybook/manager-api': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/node-logger': 7.4.6 - '@storybook/preview-api': 7.4.6 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@storybook/addon-actions': 7.6.20 + '@storybook/addon-backgrounds': 7.6.20 + '@storybook/addon-controls': 7.6.20(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/addon-docs': 7.6.20(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/addon-highlight': 7.6.20 + '@storybook/addon-measure': 7.6.20 + '@storybook/addon-outline': 7.6.20 + '@storybook/addon-toolbars': 7.6.20 + '@storybook/addon-viewport': 7.6.20 + '@storybook/core-common': 7.6.20(encoding@0.1.13) + '@storybook/manager-api': 7.6.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/node-logger': 7.6.20 + '@storybook/preview-api': 7.6.20 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) ts-dedent: 2.2.0 transitivePeerDependencies: - '@types/react' @@ -12347,119 +12063,59 @@ snapshots: - encoding - supports-color - '@storybook/addon-highlight@7.4.6': + '@storybook/addon-highlight@7.6.20': dependencies: - '@storybook/core-events': 7.4.6 '@storybook/global': 5.0.0 - '@storybook/preview-api': 7.4.6 - '@storybook/addon-links@7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/addon-links@7.6.20(react@18.3.1)': dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/core-events': 7.4.6 - '@storybook/csf': 0.1.1 + '@storybook/csf': 0.1.13 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/router': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/types': 7.4.6 - prop-types: 15.8.1 ts-dedent: 2.2.0 optionalDependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 - '@storybook/addon-measure@7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/addon-measure@7.6.20': dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/core-events': 7.4.6 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/types': 7.4.6 - tiny-invariant: 1.3.1 - optionalDependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' + tiny-invariant: 1.3.3 - '@storybook/addon-outline@7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/addon-outline@7.6.20': dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/core-events': 7.4.6 '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/types': 7.4.6 ts-dedent: 2.2.0 - optionalDependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - '@storybook/addon-toolbars@7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': - dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/manager-api': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - optionalDependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' + '@storybook/addon-toolbars@7.6.20': {} - '@storybook/addon-viewport@7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/addon-viewport@7.6.20': dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/core-events': 7.4.6 - '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) memoizerific: 1.11.3 - prop-types: 15.8.1 - optionalDependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - '@storybook/blocks@7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/blocks@7.6.20(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@storybook/channels': 7.4.6 - '@storybook/client-logger': 7.4.6 - '@storybook/components': 7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/core-events': 7.4.6 - '@storybook/csf': 0.1.1 - '@storybook/docs-tools': 7.4.6(encoding@0.1.13) + '@storybook/channels': 7.6.20 + '@storybook/client-logger': 7.6.20 + '@storybook/components': 7.6.20(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/core-events': 7.6.20 + '@storybook/csf': 0.1.13 + '@storybook/docs-tools': 7.6.20(encoding@0.1.13) '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/preview-api': 7.4.6 - '@storybook/theming': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/types': 7.4.6 - '@types/lodash': 4.14.199 + '@storybook/manager-api': 7.6.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/preview-api': 7.6.20 + '@storybook/theming': 7.6.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/types': 7.6.20 + '@types/lodash': 4.17.16 color-convert: 2.0.1 dequal: 2.0.3 lodash: 4.17.21 - markdown-to-jsx: 7.3.2(react@18.2.0) + markdown-to-jsx: 7.7.4(react@18.3.1) memoizerific: 1.11.3 - polished: 4.2.2 - react: 18.2.0 - react-colorful: 5.6.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react-dom: 18.2.0(react@18.2.0) + polished: 4.3.1 + react: 18.3.1 + react-colorful: 5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-dom: 18.3.1(react@18.3.1) telejson: 7.2.0 - tocbot: 4.21.2 + tocbot: 4.35.0 ts-dedent: 2.2.0 util-deprecate: 1.0.2 transitivePeerDependencies: @@ -12468,104 +12124,100 @@ snapshots: - encoding - supports-color - '@storybook/builder-manager@7.4.6(encoding@0.1.13)': + '@storybook/builder-manager@7.6.20(encoding@0.1.13)': dependencies: '@fal-works/esbuild-plugin-global-externals': 2.1.2 - '@storybook/core-common': 7.4.6(encoding@0.1.13) - '@storybook/manager': 7.4.6 - '@storybook/node-logger': 7.4.6 - '@types/ejs': 3.1.3 + '@storybook/core-common': 7.6.20(encoding@0.1.13) + '@storybook/manager': 7.6.20 + '@storybook/node-logger': 7.6.20 + '@types/ejs': 3.1.5 '@types/find-cache-dir': 3.2.1 '@yarnpkg/esbuild-plugin-pnp': 3.0.0-rc.15(esbuild@0.18.20) browser-assert: 1.2.1 - ejs: 3.1.9 + ejs: 3.1.10 esbuild: 0.18.20 esbuild-plugin-alias: 0.2.1 - express: 4.18.2 + express: 4.21.2 find-cache-dir: 3.3.2 - fs-extra: 11.1.1 + fs-extra: 11.3.0 process: 0.11.10 util: 0.12.5 transitivePeerDependencies: - encoding - supports-color - '@storybook/builder-vite@7.4.6(encoding@0.1.13)(typescript@5.5.4)(vite@6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1))': + '@storybook/builder-vite@7.6.20(encoding@0.1.13)(typescript@5.5.4)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))': dependencies: - '@storybook/channels': 7.4.6 - '@storybook/client-logger': 7.4.6 - '@storybook/core-common': 7.4.6(encoding@0.1.13) - '@storybook/csf-plugin': 7.4.6 - '@storybook/mdx2-csf': 1.1.0 - '@storybook/node-logger': 7.4.6 - '@storybook/preview': 7.4.6 - '@storybook/preview-api': 7.4.6 - '@storybook/types': 7.4.6 + '@storybook/channels': 7.6.20 + '@storybook/client-logger': 7.6.20 + '@storybook/core-common': 7.6.20(encoding@0.1.13) + '@storybook/csf-plugin': 7.6.20 + '@storybook/node-logger': 7.6.20 + '@storybook/preview': 7.6.20 + '@storybook/preview-api': 7.6.20 + '@storybook/types': 7.6.20 '@types/find-cache-dir': 3.2.1 browser-assert: 1.2.1 es-module-lexer: 0.9.3 - express: 4.18.2 + express: 4.21.2 find-cache-dir: 3.3.2 - fs-extra: 11.1.1 - magic-string: 0.30.4 - remark-external-links: 8.0.0 - remark-slug: 6.1.0 - rollup: 3.29.4 - vite: 6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1) + fs-extra: 11.3.0 + magic-string: 0.30.17 + rollup: 3.29.5 + vite: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: - encoding - supports-color - '@storybook/channels@7.4.6': + '@storybook/channels@7.6.20': dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/core-events': 7.4.6 + '@storybook/client-logger': 7.6.20 + '@storybook/core-events': 7.6.20 '@storybook/global': 5.0.0 - qs: 6.11.2 + qs: 6.14.0 telejson: 7.2.0 - tiny-invariant: 1.3.1 + tiny-invariant: 1.3.3 - '@storybook/cli@7.4.6(encoding@0.1.13)': + '@storybook/cli@7.6.20(encoding@0.1.13)': dependencies: - '@babel/core': 7.22.11 - '@babel/preset-env': 7.22.10(@babel/core@7.22.11) - '@babel/types': 7.23.0 + '@babel/core': 7.26.9 + '@babel/preset-env': 7.26.9(@babel/core@7.26.9) + '@babel/types': 7.26.9 '@ndelangen/get-tarball': 3.0.9 - '@storybook/codemod': 7.4.6 - '@storybook/core-common': 7.4.6(encoding@0.1.13) - '@storybook/core-events': 7.4.6 - '@storybook/core-server': 7.4.6(encoding@0.1.13) - '@storybook/csf-tools': 7.4.6 - '@storybook/node-logger': 7.4.6 - '@storybook/telemetry': 7.4.6(encoding@0.1.13) - '@storybook/types': 7.4.6 - '@types/semver': 7.5.3 + '@storybook/codemod': 7.6.20 + '@storybook/core-common': 7.6.20(encoding@0.1.13) + '@storybook/core-events': 7.6.20 + '@storybook/core-server': 7.6.20(encoding@0.1.13) + '@storybook/csf-tools': 7.6.20 + '@storybook/node-logger': 7.6.20 + '@storybook/telemetry': 7.6.20(encoding@0.1.13) + '@storybook/types': 7.6.20 + '@types/semver': 7.5.8 '@yarnpkg/fslib': 2.10.3 '@yarnpkg/libzip': 2.3.0 chalk: 4.1.2 commander: 6.2.1 - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 detect-indent: 6.1.0 - envinfo: 7.10.0 + envinfo: 7.14.0 execa: 5.1.1 - express: 4.18.2 + express: 4.21.2 find-up: 5.0.0 - fs-extra: 11.1.1 - get-npm-tarball-url: 2.0.3 + fs-extra: 11.3.0 + get-npm-tarball-url: 2.1.0 get-port: 5.1.1 - giget: 1.1.3 + giget: 1.2.5 globby: 11.1.0 - jscodeshift: 0.14.0(@babel/preset-env@7.22.10(@babel/core@7.22.11)) + jscodeshift: 0.15.2(@babel/preset-env@7.26.9(@babel/core@7.26.9)) leven: 3.1.0 ora: 5.4.1 prettier: 2.8.8 prompts: 2.4.2 puppeteer-core: 2.1.1 read-pkg-up: 7.0.1 - semver: 7.6.0 - simple-update-notifier: 2.0.0 + semver: 7.7.1 strip-json-comments: 3.1.1 tempy: 1.0.1 ts-dedent: 2.2.0 @@ -12576,69 +12228,69 @@ snapshots: - supports-color - utf-8-validate - '@storybook/client-logger@7.4.6': + '@storybook/client-logger@7.6.20': dependencies: '@storybook/global': 5.0.0 - '@storybook/codemod@7.4.6': + '@storybook/codemod@7.6.20': dependencies: - '@babel/core': 7.22.11 - '@babel/preset-env': 7.22.10(@babel/core@7.22.11) - '@babel/types': 7.23.0 - '@storybook/csf': 0.1.1 - '@storybook/csf-tools': 7.4.6 - '@storybook/node-logger': 7.4.6 - '@storybook/types': 7.4.6 - '@types/cross-spawn': 6.0.3 - cross-spawn: 7.0.3 + '@babel/core': 7.26.9 + '@babel/preset-env': 7.26.9(@babel/core@7.26.9) + '@babel/types': 7.26.9 + '@storybook/csf': 0.1.13 + '@storybook/csf-tools': 7.6.20 + '@storybook/node-logger': 7.6.20 + '@storybook/types': 7.6.20 + '@types/cross-spawn': 6.0.6 + cross-spawn: 7.0.6 globby: 11.1.0 - jscodeshift: 0.14.0(@babel/preset-env@7.22.10(@babel/core@7.22.11)) + jscodeshift: 0.15.2(@babel/preset-env@7.26.9(@babel/core@7.26.9)) lodash: 4.17.21 prettier: 2.8.8 - recast: 0.23.4 + recast: 0.23.11 transitivePeerDependencies: - supports-color - '@storybook/components@7.4.6(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/components@7.6.20(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-select': 1.2.2(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-toolbar': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/client-logger': 7.4.6 - '@storybook/csf': 0.1.1 + '@radix-ui/react-select': 1.2.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-toolbar': 1.1.2(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/client-logger': 7.6.20 + '@storybook/csf': 0.1.13 '@storybook/global': 5.0.0 - '@storybook/theming': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/theming': 7.6.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/types': 7.6.20 memoizerific: 1.11.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - use-resize-observer: 9.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + use-resize-observer: 9.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) util-deprecate: 1.0.2 transitivePeerDependencies: - '@types/react' - '@types/react-dom' - '@storybook/core-client@7.4.6': + '@storybook/core-client@7.6.20': dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/preview-api': 7.4.6 + '@storybook/client-logger': 7.6.20 + '@storybook/preview-api': 7.6.20 - '@storybook/core-common@7.4.6(encoding@0.1.13)': + '@storybook/core-common@7.6.20(encoding@0.1.13)': dependencies: - '@storybook/core-events': 7.4.6 - '@storybook/node-logger': 7.4.6 - '@storybook/types': 7.4.6 + '@storybook/core-events': 7.6.20 + '@storybook/node-logger': 7.6.20 + '@storybook/types': 7.6.20 '@types/find-cache-dir': 3.2.1 - '@types/node': 16.18.58 - '@types/node-fetch': 2.6.6 - '@types/pretty-hrtime': 1.0.1 + '@types/node': 18.19.79 + '@types/node-fetch': 2.6.12 + '@types/pretty-hrtime': 1.0.3 chalk: 4.1.2 esbuild: 0.18.20 - esbuild-register: 3.5.0(esbuild@0.18.20) + esbuild-register: 3.6.0(esbuild@0.18.20) file-system-cache: 2.3.0 find-cache-dir: 3.3.2 find-up: 5.0.0 - fs-extra: 11.1.1 - glob: 10.3.3 + fs-extra: 11.3.0 + glob: 10.4.5 handlebars: 4.7.8 lazy-universal-dotenv: 4.0.0 node-fetch: 2.7.0(encoding@0.1.13) @@ -12651,92 +12303,92 @@ snapshots: - encoding - supports-color - '@storybook/core-events@7.4.6': + '@storybook/core-events@7.6.20': dependencies: ts-dedent: 2.2.0 - '@storybook/core-server@7.4.6(encoding@0.1.13)': + '@storybook/core-server@7.6.20(encoding@0.1.13)': dependencies: '@aw-web-design/x-default-browser': 1.4.126 '@discoveryjs/json-ext': 0.5.7 - '@storybook/builder-manager': 7.4.6(encoding@0.1.13) - '@storybook/channels': 7.4.6 - '@storybook/core-common': 7.4.6(encoding@0.1.13) - '@storybook/core-events': 7.4.6 - '@storybook/csf': 0.1.1 - '@storybook/csf-tools': 7.4.6 + '@storybook/builder-manager': 7.6.20(encoding@0.1.13) + '@storybook/channels': 7.6.20 + '@storybook/core-common': 7.6.20(encoding@0.1.13) + '@storybook/core-events': 7.6.20 + '@storybook/csf': 0.1.13 + '@storybook/csf-tools': 7.6.20 '@storybook/docs-mdx': 0.1.0 '@storybook/global': 5.0.0 - '@storybook/manager': 7.4.6 - '@storybook/node-logger': 7.4.6 - '@storybook/preview-api': 7.4.6 - '@storybook/telemetry': 7.4.6(encoding@0.1.13) - '@storybook/types': 7.4.6 - '@types/detect-port': 1.3.3 - '@types/node': 16.18.58 - '@types/pretty-hrtime': 1.0.1 - '@types/semver': 7.5.3 + '@storybook/manager': 7.6.20 + '@storybook/node-logger': 7.6.20 + '@storybook/preview-api': 7.6.20 + '@storybook/telemetry': 7.6.20(encoding@0.1.13) + '@storybook/types': 7.6.20 + '@types/detect-port': 1.3.5 + '@types/node': 18.19.79 + '@types/pretty-hrtime': 1.0.3 + '@types/semver': 7.5.8 better-opn: 3.0.2 chalk: 4.1.2 - cli-table3: 0.6.3 - compression: 1.7.4 - detect-port: 1.5.1 - express: 4.18.2 - fs-extra: 11.1.1 + cli-table3: 0.6.5 + compression: 1.8.0 + detect-port: 1.6.1 + express: 4.21.2 + fs-extra: 11.3.0 globby: 11.1.0 - ip: 2.0.0 lodash: 4.17.21 open: 8.4.2 pretty-hrtime: 1.0.3 prompts: 2.4.2 read-pkg-up: 7.0.1 - semver: 7.6.0 + semver: 7.7.1 telejson: 7.2.0 - tiny-invariant: 1.3.1 + tiny-invariant: 1.3.3 ts-dedent: 2.2.0 util: 0.12.5 util-deprecate: 1.0.2 - watchpack: 2.4.1 - ws: 8.18.0 + watchpack: 2.4.2 + ws: 8.18.1 transitivePeerDependencies: - bufferutil - encoding - supports-color - utf-8-validate - '@storybook/csf-plugin@7.4.6': + '@storybook/csf-plugin@7.6.20': dependencies: - '@storybook/csf-tools': 7.4.6 - unplugin: 1.5.0 + '@storybook/csf-tools': 7.6.20 + unplugin: 1.16.1 transitivePeerDependencies: - supports-color - '@storybook/csf-tools@7.4.6': + '@storybook/csf-tools@7.6.20': dependencies: - '@babel/generator': 7.22.10 - '@babel/parser': 7.22.13 - '@babel/traverse': 7.22.11 - '@babel/types': 7.23.0 - '@storybook/csf': 0.1.1 - '@storybook/types': 7.4.6 - fs-extra: 11.1.1 - recast: 0.23.4 + '@babel/generator': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + '@storybook/csf': 0.1.13 + '@storybook/types': 7.6.20 + fs-extra: 11.3.0 + recast: 0.23.11 ts-dedent: 2.2.0 transitivePeerDependencies: - supports-color - '@storybook/csf@0.1.1': + '@storybook/csf@0.1.13': dependencies: type-fest: 2.19.0 '@storybook/docs-mdx@0.1.0': {} - '@storybook/docs-tools@7.4.6(encoding@0.1.13)': + '@storybook/docs-tools@7.6.20(encoding@0.1.13)': dependencies: - '@storybook/core-common': 7.4.6(encoding@0.1.13) - '@storybook/preview-api': 7.4.6 - '@storybook/types': 7.4.6 + '@storybook/core-common': 7.6.20(encoding@0.1.13) + '@storybook/preview-api': 7.6.20 + '@storybook/types': 7.6.20 '@types/doctrine': 0.0.3 + assert: 2.1.0 doctrine: 3.0.0 lodash: 4.17.21 transitivePeerDependencies: @@ -12745,71 +12397,70 @@ snapshots: '@storybook/global@5.0.0': {} - '@storybook/manager-api@7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/manager-api@7.6.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@storybook/channels': 7.4.6 - '@storybook/client-logger': 7.4.6 - '@storybook/core-events': 7.4.6 - '@storybook/csf': 0.1.1 + '@storybook/channels': 7.6.20 + '@storybook/client-logger': 7.6.20 + '@storybook/core-events': 7.6.20 + '@storybook/csf': 0.1.13 '@storybook/global': 5.0.0 - '@storybook/router': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/theming': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/router': 7.6.20 + '@storybook/theming': 7.6.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/types': 7.6.20 dequal: 2.0.3 lodash: 4.17.21 memoizerific: 1.11.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - semver: 7.6.0 - store2: 2.14.2 + store2: 2.14.4 telejson: 7.2.0 ts-dedent: 2.2.0 + transitivePeerDependencies: + - react + - react-dom - '@storybook/manager@7.4.6': {} + '@storybook/manager@7.6.20': {} '@storybook/mdx2-csf@1.1.0': {} - '@storybook/node-logger@7.4.6': {} + '@storybook/node-logger@7.6.20': {} - '@storybook/postinstall@7.4.6': {} + '@storybook/postinstall@7.6.20': {} - '@storybook/preview-api@7.4.6': + '@storybook/preview-api@7.6.20': dependencies: - '@storybook/channels': 7.4.6 - '@storybook/client-logger': 7.4.6 - '@storybook/core-events': 7.4.6 - '@storybook/csf': 0.1.1 + '@storybook/channels': 7.6.20 + '@storybook/client-logger': 7.6.20 + '@storybook/core-events': 7.6.20 + '@storybook/csf': 0.1.13 '@storybook/global': 5.0.0 - '@storybook/types': 7.4.6 - '@types/qs': 6.9.8 + '@storybook/types': 7.6.20 + '@types/qs': 6.9.18 dequal: 2.0.3 lodash: 4.17.21 memoizerific: 1.11.3 - qs: 6.11.2 + qs: 6.14.0 synchronous-promise: 2.0.17 ts-dedent: 2.2.0 util-deprecate: 1.0.2 - '@storybook/preview@7.4.6': {} + '@storybook/preview@7.6.20': {} - '@storybook/react-dom-shim@7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/react-dom-shim@7.6.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - '@storybook/react-vite@7.4.6(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(rollup@2.79.1)(typescript@5.5.4)(vite@6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1))': + '@storybook/react-vite@7.6.20(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@2.79.2)(typescript@5.5.4)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))': dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.2.1(typescript@5.5.4)(vite@6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1)) - '@rollup/pluginutils': 5.0.5(rollup@2.79.1) - '@storybook/builder-vite': 7.4.6(encoding@0.1.13)(typescript@5.5.4)(vite@6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1)) - '@storybook/react': 7.4.6(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4) - '@vitejs/plugin-react': 3.1.0(vite@6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1)) - ast-types: 0.14.2 - magic-string: 0.30.4 - react: 18.2.0 - react-docgen: 6.0.0-alpha.3 - react-dom: 18.2.0(react@18.2.0) - vite: 6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.0(typescript@5.5.4)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0)) + '@rollup/pluginutils': 5.1.4(rollup@2.79.2) + '@storybook/builder-vite': 7.6.20(encoding@0.1.13)(typescript@5.5.4)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0)) + '@storybook/react': 7.6.20(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@vitejs/plugin-react': 3.1.0(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0)) + magic-string: 0.30.17 + react: 18.3.1 + react-docgen: 7.1.1 + react-dom: 18.3.1(react@18.3.1) + vite: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) transitivePeerDependencies: - '@preact/preset-vite' - encoding @@ -12818,18 +12469,18 @@ snapshots: - typescript - vite-plugin-glimmerx - '@storybook/react@7.4.6(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.5.4)': + '@storybook/react@7.6.20(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/core-client': 7.4.6 - '@storybook/docs-tools': 7.4.6(encoding@0.1.13) + '@storybook/client-logger': 7.6.20 + '@storybook/core-client': 7.6.20 + '@storybook/docs-tools': 7.6.20(encoding@0.1.13) '@storybook/global': 5.0.0 - '@storybook/preview-api': 7.4.6 - '@storybook/react-dom-shim': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@storybook/types': 7.4.6 + '@storybook/preview-api': 7.6.20 + '@storybook/react-dom-shim': 7.6.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/types': 7.6.20 '@types/escodegen': 0.0.6 '@types/estree': 0.0.51 - '@types/node': 16.18.58 + '@types/node': 18.19.79 acorn: 7.4.1 acorn-jsx: 5.3.2(acorn@7.4.1) acorn-walk: 7.2.0 @@ -12837,9 +12488,9 @@ snapshots: html-tags: 3.3.1 lodash: 4.17.21 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-element-to-jsx-string: 15.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-element-to-jsx-string: 15.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) ts-dedent: 2.2.0 type-fest: 2.19.0 util-deprecate: 1.0.2 @@ -12849,101 +12500,64 @@ snapshots: - encoding - supports-color - '@storybook/router@7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/router@7.6.20': dependencies: - '@storybook/client-logger': 7.4.6 + '@storybook/client-logger': 7.6.20 memoizerific: 1.11.3 - qs: 6.11.2 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + qs: 6.14.0 - '@storybook/telemetry@7.4.6(encoding@0.1.13)': + '@storybook/telemetry@7.6.20(encoding@0.1.13)': dependencies: - '@storybook/client-logger': 7.4.6 - '@storybook/core-common': 7.4.6(encoding@0.1.13) - '@storybook/csf-tools': 7.4.6 + '@storybook/client-logger': 7.6.20 + '@storybook/core-common': 7.6.20(encoding@0.1.13) + '@storybook/csf-tools': 7.6.20 chalk: 4.1.2 detect-package-manager: 2.0.1 fetch-retry: 5.0.6 - fs-extra: 11.1.1 + fs-extra: 11.3.0 read-pkg-up: 7.0.1 transitivePeerDependencies: - encoding - supports-color - '@storybook/theming@7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@storybook/theming@7.6.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.2.0) - '@storybook/client-logger': 7.4.6 + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1) + '@storybook/client-logger': 7.6.20 '@storybook/global': 5.0.0 memoizerific: 1.11.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - '@storybook/types@7.4.6': + '@storybook/types@7.6.20': dependencies: - '@storybook/channels': 7.4.6 - '@types/babel__core': 7.20.2 - '@types/express': 4.17.18 + '@storybook/channels': 7.6.20 + '@types/babel__core': 7.20.5 + '@types/express': 4.17.21 file-system-cache: 2.3.0 - '@stylistic/eslint-plugin-js@2.6.1(eslint@8.50.0)': + '@stylistic/eslint-plugin@2.13.0(eslint@8.57.1)(typescript@5.5.4)': dependencies: - '@types/eslint': 9.6.0 - acorn: 8.12.1 - eslint: 8.50.0 - eslint-visitor-keys: 4.0.0 - espree: 10.1.0 - - '@stylistic/eslint-plugin-jsx@2.6.1(eslint@8.50.0)': - dependencies: - '@stylistic/eslint-plugin-js': 2.6.1(eslint@8.50.0) - '@types/eslint': 9.6.0 - eslint: 8.50.0 + '@typescript-eslint/utils': 8.26.0(eslint@8.57.1)(typescript@5.5.4) + eslint: 8.57.1 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 estraverse: 5.3.0 picomatch: 4.0.2 - - '@stylistic/eslint-plugin-plus@2.6.1(eslint@8.50.0)(typescript@5.5.4)': - dependencies: - '@types/eslint': 9.6.0 - '@typescript-eslint/utils': 8.0.0(eslint@8.50.0)(typescript@5.5.4) - eslint: 8.50.0 - transitivePeerDependencies: - - supports-color - - typescript - - '@stylistic/eslint-plugin-ts@2.6.1(eslint@8.50.0)(typescript@5.5.4)': - dependencies: - '@stylistic/eslint-plugin-js': 2.6.1(eslint@8.50.0) - '@types/eslint': 9.6.0 - '@typescript-eslint/utils': 8.0.0(eslint@8.50.0)(typescript@5.5.4) - eslint: 8.50.0 - transitivePeerDependencies: - - supports-color - - typescript - - '@stylistic/eslint-plugin@2.6.1(eslint@8.50.0)(typescript@5.5.4)': - dependencies: - '@stylistic/eslint-plugin-js': 2.6.1(eslint@8.50.0) - '@stylistic/eslint-plugin-jsx': 2.6.1(eslint@8.50.0) - '@stylistic/eslint-plugin-plus': 2.6.1(eslint@8.50.0)(typescript@5.5.4) - '@stylistic/eslint-plugin-ts': 2.6.1(eslint@8.50.0)(typescript@5.5.4) - '@types/eslint': 9.6.0 - eslint: 8.50.0 transitivePeerDependencies: - supports-color - typescript '@surma/rollup-plugin-off-main-thread@2.2.3': dependencies: - ejs: 3.1.9 + ejs: 3.1.10 json5: 2.2.3 magic-string: 0.25.9 string.prototype.matchall: 4.0.12 - '@swc/helpers@0.5.11': + '@swc/helpers@0.5.15': dependencies: - tslib: 2.6.2 + tslib: 2.8.1 '@tootallnate/once@2.0.0': {} @@ -12951,101 +12565,89 @@ snapshots: '@tweenjs/tween.js@20.0.3': {} - '@types/babel__core@7.20.2': + '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.22.13 - '@babel/types': 7.23.0 - '@types/babel__generator': 7.6.5 - '@types/babel__template': 7.4.2 - '@types/babel__traverse': 7.20.2 + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 - '@types/babel__generator@7.6.5': + '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.23.0 + '@babel/types': 7.26.9 - '@types/babel__template@7.4.2': + '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.22.13 - '@babel/types': 7.23.0 + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 - '@types/babel__traverse@7.20.2': + '@types/babel__traverse@7.20.6': dependencies: - '@babel/types': 7.23.0 + '@babel/types': 7.26.9 - '@types/body-parser@1.19.3': + '@types/body-parser@1.19.5': dependencies: - '@types/connect': 3.4.36 - '@types/node': 22.8.1 + '@types/connect': 3.4.38 + '@types/node': 22.13.9 - '@types/chai-subset@1.3.3': + '@types/chai-subset@1.3.6(@types/chai@4.3.20)': dependencies: - '@types/chai': 4.3.6 + '@types/chai': 4.3.20 - '@types/chai@4.3.6': {} + '@types/chai@4.3.20': {} - '@types/connect@3.4.36': + '@types/connect@3.4.38': dependencies: - '@types/node': 22.8.1 + '@types/node': 22.13.9 - '@types/cookie@0.4.1': {} - - '@types/cors@2.8.15': + '@types/cors@2.8.17': dependencies: - '@types/node': 22.8.1 + '@types/node': 22.13.9 - '@types/cross-spawn@6.0.3': + '@types/cross-spawn@6.0.6': dependencies: - '@types/node': 22.8.1 + '@types/node': 22.13.9 '@types/debug@4.1.12': dependencies: - '@types/ms': 0.7.34 + '@types/ms': 2.1.0 - '@types/detect-port@1.3.3': {} + '@types/detect-port@1.3.5': {} '@types/diff-match-patch@1.0.36': {} '@types/doctrine@0.0.3': {} - '@types/draco3d@1.4.7': {} + '@types/doctrine@0.0.9': {} - '@types/ejs@3.1.3': {} + '@types/draco3d@1.4.10': {} - '@types/emscripten@1.39.8': {} + '@types/ejs@3.1.5': {} + + '@types/emscripten@1.40.0': {} '@types/escodegen@0.0.6': {} - '@types/eslint-scope@3.7.7': - dependencies: - '@types/eslint': 9.6.0 - '@types/estree': 1.0.5 - - '@types/eslint@9.6.0': - dependencies: - '@types/estree': 1.0.5 - '@types/json-schema': 7.0.12 - '@types/estree@0.0.39': {} '@types/estree@0.0.51': {} - '@types/estree@1.0.5': {} - '@types/estree@1.0.6': {} - '@types/express-serve-static-core@4.17.37': + '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 22.8.1 - '@types/qs': 6.9.8 - '@types/range-parser': 1.2.5 - '@types/send': 0.17.2 + '@types/node': 22.13.9 + '@types/qs': 6.9.18 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 - '@types/express@4.17.18': + '@types/express@4.17.21': dependencies: - '@types/body-parser': 1.19.3 - '@types/express-serve-static-core': 4.17.37 - '@types/qs': 6.9.8 - '@types/serve-static': 1.15.3 + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.19.6 + '@types/qs': 6.9.18 + '@types/serve-static': 1.15.7 '@types/find-cache-dir@3.2.1': {} @@ -13054,209 +12656,217 @@ snapshots: '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.8.1 + '@types/node': 22.13.9 - '@types/graceful-fs@4.1.7': + '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 22.8.1 + '@types/node': 22.13.9 - '@types/http-cache-semantics@4.0.2': {} + '@types/http-cache-semantics@4.0.4': {} - '@types/http-errors@2.0.2': {} + '@types/http-errors@2.0.4': {} - '@types/istanbul-lib-coverage@2.0.4': {} + '@types/istanbul-lib-coverage@2.0.6': {} - '@types/istanbul-lib-report@3.0.1': + '@types/istanbul-lib-report@3.0.3': dependencies: - '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports@3.0.2': + '@types/istanbul-reports@3.0.4': dependencies: - '@types/istanbul-lib-report': 3.0.1 + '@types/istanbul-lib-report': 3.0.3 '@types/js-cookie@2.2.7': {} - '@types/json-schema@7.0.12': {} + '@types/json-schema@7.0.15': {} '@types/json5@0.0.29': {} - '@types/lodash-es@4.17.9': + '@types/linkify-it@5.0.0': {} + + '@types/lodash-es@4.17.12': dependencies: - '@types/lodash': 4.14.199 + '@types/lodash': 4.17.16 - '@types/lodash@4.14.199': {} + '@types/lodash@4.17.16': {} - '@types/mdast@4.0.3': + '@types/markdown-it@14.1.2': dependencies: - '@types/unist': 3.0.2 + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 - '@types/mdx@2.0.8': {} + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 - '@types/mime-types@2.1.2': {} + '@types/mdurl@2.0.0': {} - '@types/mime@1.3.3': {} + '@types/mdx@2.0.13': {} - '@types/mime@3.0.2': {} + '@types/mime-types@2.1.4': {} + + '@types/mime@1.3.5': {} '@types/minimatch@5.1.2': {} - '@types/minimist@1.2.3': {} + '@types/minimist@1.2.5': {} - '@types/ms@0.7.34': {} + '@types/ms@2.1.0': {} - '@types/node-fetch@2.6.6': + '@types/node-fetch@2.6.12': dependencies: - '@types/node': 22.8.1 - form-data: 4.0.0 + '@types/node': 22.13.9 + form-data: 4.0.2 '@types/node-rsa@1.1.4': dependencies: - '@types/node': 22.8.1 + '@types/node': 22.13.9 - '@types/node@14.18.56': + '@types/node@14.18.63': optional: true - '@types/node@16.18.58': {} - - '@types/node@22.8.1': + '@types/node@18.19.79': dependencies: - undici-types: 6.19.8 + undici-types: 5.26.5 - '@types/normalize-package-data@2.4.2': {} - - '@types/offscreencanvas@2019.7.2': {} - - '@types/parse-json@4.0.0': {} - - '@types/pretty-hrtime@1.0.1': {} - - '@types/prop-types@15.7.12': {} - - '@types/qs@6.9.8': {} - - '@types/range-parser@1.2.5': {} - - '@types/rbush@3.0.1': {} - - '@types/react-dom@18.2.7': + '@types/node@22.13.9': dependencies: - '@types/react': 18.2.20 + undici-types: 6.20.0 - '@types/react-transition-group@4.4.7': - dependencies: - '@types/react': 18.2.20 + '@types/normalize-package-data@2.4.4': {} - '@types/react@18.2.20': - dependencies: - '@types/prop-types': 15.7.12 - '@types/scheduler': 0.16.3 - csstype: 3.1.2 + '@types/offscreencanvas@2019.7.3': {} - '@types/readable-stream@4.0.12': + '@types/parse-json@4.0.2': {} + + '@types/pretty-hrtime@1.0.3': {} + + '@types/prop-types@15.7.14': {} + + '@types/qs@6.9.18': {} + + '@types/range-parser@1.2.7': {} + + '@types/rbush@3.0.4': {} + + '@types/react-dom@18.3.5(@types/react@18.3.18)': dependencies: - '@types/node': 22.8.1 + '@types/react': 18.3.18 + + '@types/react-transition-group@4.4.12(@types/react@18.3.18)': + dependencies: + '@types/react': 18.3.18 + + '@types/react@18.3.18': + dependencies: + '@types/prop-types': 15.7.14 + csstype: 3.1.3 + + '@types/readable-stream@4.0.18': + dependencies: + '@types/node': 22.13.9 safe-buffer: 5.1.2 - '@types/resolve@1.17.1': - dependencies: - '@types/node': 22.8.1 + '@types/resolve@1.20.2': {} + + '@types/resolve@1.20.6': {} '@types/sat@0.0.31': {} - '@types/scheduler@0.16.3': {} + '@types/semver@7.5.8': {} - '@types/semver@7.5.3': {} - - '@types/send@0.17.2': + '@types/send@0.17.4': dependencies: - '@types/mime': 1.3.3 - '@types/node': 22.8.1 + '@types/mime': 1.3.5 + '@types/node': 22.13.9 - '@types/serve-static@1.15.3': + '@types/serve-static@1.15.7': dependencies: - '@types/http-errors': 2.0.2 - '@types/mime': 3.0.2 - '@types/node': 22.8.1 + '@types/http-errors': 2.0.4 + '@types/node': 22.13.9 + '@types/send': 0.17.4 '@types/sinonjs__fake-timers@8.1.1': optional: true - '@types/sizzle@2.3.3': + '@types/sizzle@2.3.9': optional: true - '@types/stats.js@0.17.1': {} + '@types/stats.js@0.17.3': {} '@types/three@0.154.0': dependencies: '@tweenjs/tween.js': 18.6.4 - '@types/stats.js': 0.17.1 - '@types/webxr': 0.5.7 + '@types/stats.js': 0.17.3 + '@types/webxr': 0.5.21 fflate: 0.6.10 lil-gui: 0.17.0 meshoptimizer: 0.18.1 '@types/three@0.156.0': dependencies: - '@types/stats.js': 0.17.1 - '@types/webxr': 0.5.7 + '@types/stats.js': 0.17.3 + '@types/webxr': 0.5.21 fflate: 0.6.10 meshoptimizer: 0.18.1 - '@types/trusted-types@2.0.3': {} + '@types/trusted-types@2.0.7': {} '@types/ua-parser-js@0.7.39': {} - '@types/unist@2.0.8': {} + '@types/unist@2.0.11': {} - '@types/unist@3.0.2': {} + '@types/unist@3.0.3': {} + + '@types/uuid@9.0.8': {} '@types/wait-on@5.3.4': dependencies: - '@types/node': 22.8.1 + '@types/node': 22.13.9 - '@types/webxr@0.5.7': {} + '@types/webxr@0.5.21': {} - '@types/wicg-file-system-access@2023.10.2': {} + '@types/wicg-file-system-access@2023.10.5': {} - '@types/yargs-parser@21.0.1': {} + '@types/yargs-parser@21.0.3': {} - '@types/yargs@17.0.28': + '@types/yargs@17.0.33': dependencies: - '@types/yargs-parser': 21.0.1 + '@types/yargs-parser': 21.0.3 '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.8.1 + '@types/node': 22.13.9 - '@typescript-eslint/eslint-plugin@6.1.0(@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.5.4))(eslint@8.50.0)(typescript@5.5.4)': + '@typescript-eslint/eslint-plugin@6.1.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.5.4))(eslint@8.57.1)(typescript@5.5.4)': dependencies: - '@eslint-community/regexpp': 4.8.0 - '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.5.4) + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.5.4) '@typescript-eslint/scope-manager': 6.1.0 - '@typescript-eslint/type-utils': 6.1.0(eslint@8.50.0)(typescript@5.5.4) - '@typescript-eslint/utils': 6.1.0(eslint@8.50.0)(typescript@5.5.4) + '@typescript-eslint/type-utils': 6.1.0(eslint@8.57.1)(typescript@5.5.4) + '@typescript-eslint/utils': 6.1.0(eslint@8.57.1)(typescript@5.5.4) '@typescript-eslint/visitor-keys': 6.1.0 debug: 4.4.0(supports-color@8.1.1) - eslint: 8.50.0 + eslint: 8.57.1 graphemer: 1.4.0 - ignore: 5.2.4 + ignore: 5.3.2 natural-compare: 1.4.0 natural-compare-lite: 1.4.0 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.5.4) + semver: 7.7.1 + ts-api-utils: 1.4.3(typescript@5.5.4) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.5.4)': + '@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.5.4)': dependencies: - '@typescript-eslint/scope-manager': 6.7.3 - '@typescript-eslint/types': 6.7.3 - '@typescript-eslint/typescript-estree': 6.7.3(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 6.7.3 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) + '@typescript-eslint/visitor-keys': 6.21.0 debug: 4.4.0(supports-color@8.1.1) - eslint: 8.50.0 + eslint: 8.57.1 optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: @@ -13267,23 +12877,23 @@ snapshots: '@typescript-eslint/types': 6.1.0 '@typescript-eslint/visitor-keys': 6.1.0 - '@typescript-eslint/scope-manager@6.7.3': + '@typescript-eslint/scope-manager@6.21.0': dependencies: - '@typescript-eslint/types': 6.7.3 - '@typescript-eslint/visitor-keys': 6.7.3 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 - '@typescript-eslint/scope-manager@8.0.0': + '@typescript-eslint/scope-manager@8.26.0': dependencies: - '@typescript-eslint/types': 8.0.0 - '@typescript-eslint/visitor-keys': 8.0.0 + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/visitor-keys': 8.26.0 - '@typescript-eslint/type-utils@6.1.0(eslint@8.50.0)(typescript@5.5.4)': + '@typescript-eslint/type-utils@6.1.0(eslint@8.57.1)(typescript@5.5.4)': dependencies: '@typescript-eslint/typescript-estree': 6.1.0(typescript@5.5.4) - '@typescript-eslint/utils': 6.1.0(eslint@8.50.0)(typescript@5.5.4) - debug: 4.4.0(supports-color@8.1.1) - eslint: 8.50.0 - ts-api-utils: 1.3.0(typescript@5.5.4) + '@typescript-eslint/utils': 6.1.0(eslint@8.57.1)(typescript@5.5.4) + debug: 4.4.1 + eslint: 8.57.1 + ts-api-utils: 1.4.3(typescript@5.5.4) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: @@ -13291,101 +12901,103 @@ snapshots: '@typescript-eslint/types@6.1.0': {} - '@typescript-eslint/types@6.7.3': {} + '@typescript-eslint/types@6.21.0': {} - '@typescript-eslint/types@8.0.0': {} + '@typescript-eslint/types@8.26.0': {} '@typescript-eslint/typescript-estree@6.1.0(typescript@5.5.4)': dependencies: '@typescript-eslint/types': 6.1.0 '@typescript-eslint/visitor-keys': 6.1.0 - debug: 4.4.0(supports-color@8.1.1) + debug: 4.4.1 globby: 11.1.0 is-glob: 4.0.3 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.5.4) + semver: 7.7.1 + ts-api-utils: 1.4.3(typescript@5.5.4) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@6.7.3(typescript@5.5.4)': + '@typescript-eslint/typescript-estree@6.21.0(typescript@5.5.4)': dependencies: - '@typescript-eslint/types': 6.7.3 - '@typescript-eslint/visitor-keys': 6.7.3 - debug: 4.4.0(supports-color@8.1.1) + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.4.1 globby: 11.1.0 is-glob: 4.0.3 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.5.4) + minimatch: 9.0.3 + semver: 7.7.1 + ts-api-utils: 1.4.3(typescript@5.5.4) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.0.0(typescript@5.5.4)': + '@typescript-eslint/typescript-estree@8.26.0(typescript@5.5.4)': dependencies: - '@typescript-eslint/types': 8.0.0 - '@typescript-eslint/visitor-keys': 8.0.0 - debug: 4.4.0(supports-color@8.1.1) - globby: 11.1.0 + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/visitor-keys': 8.26.0 + debug: 4.4.1 + fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - optionalDependencies: + semver: 7.7.1 + ts-api-utils: 2.0.1(typescript@5.5.4) typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@6.1.0(eslint@8.50.0)(typescript@5.5.4)': + '@typescript-eslint/utils@6.1.0(eslint@8.57.1)(typescript@5.5.4)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.50.0) - '@types/json-schema': 7.0.12 - '@types/semver': 7.5.3 + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 6.1.0 '@typescript-eslint/types': 6.1.0 '@typescript-eslint/typescript-estree': 6.1.0(typescript@5.5.4) - eslint: 8.50.0 - semver: 7.6.0 + eslint: 8.57.1 + semver: 7.7.1 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/utils@8.0.0(eslint@8.50.0)(typescript@5.5.4)': + '@typescript-eslint/utils@8.26.0(eslint@8.57.1)(typescript@5.5.4)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.50.0) - '@typescript-eslint/scope-manager': 8.0.0 - '@typescript-eslint/types': 8.0.0 - '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4) - eslint: 8.50.0 + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@typescript-eslint/scope-manager': 8.26.0 + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.5.4) + eslint: 8.57.1 + typescript: 5.5.4 transitivePeerDependencies: - supports-color - - typescript '@typescript-eslint/visitor-keys@6.1.0': dependencies: '@typescript-eslint/types': 6.1.0 eslint-visitor-keys: 3.4.3 - '@typescript-eslint/visitor-keys@6.7.3': + '@typescript-eslint/visitor-keys@6.21.0': dependencies: - '@typescript-eslint/types': 6.7.3 + '@typescript-eslint/types': 6.21.0 eslint-visitor-keys: 3.4.3 - '@typescript-eslint/visitor-keys@8.0.0': + '@typescript-eslint/visitor-keys@8.26.0': dependencies: - '@typescript-eslint/types': 8.0.0 - eslint-visitor-keys: 3.4.3 + '@typescript-eslint/types': 8.26.0 + eslint-visitor-keys: 4.2.0 - '@vitejs/plugin-react@3.1.0(vite@6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1))': + '@ungap/structured-clone@1.3.0': {} + + '@vitejs/plugin-react@3.1.0(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))': dependencies: - '@babel/core': 7.22.11 - '@babel/plugin-transform-react-jsx-self': 7.22.5(@babel/core@7.22.11) - '@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.9) magic-string: 0.27.0 react-refresh: 0.14.2 - vite: 6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1) + vite: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) transitivePeerDependencies: - supports-color @@ -13393,146 +13005,30 @@ snapshots: dependencies: '@vitest/spy': 0.34.6 '@vitest/utils': 0.34.6 - chai: 4.3.10 - - '@vitest/expect@3.0.7': - dependencies: - '@vitest/spy': 3.0.7 - '@vitest/utils': 3.0.7 - chai: 5.2.0 - tinyrainbow: 2.0.0 - - '@vitest/mocker@3.0.7(vite@6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1))': - dependencies: - '@vitest/spy': 3.0.7 - estree-walker: 3.0.3 - magic-string: 0.30.17 - optionalDependencies: - vite: 6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1) - - '@vitest/pretty-format@3.0.7': - dependencies: - tinyrainbow: 2.0.0 + chai: 4.5.0 '@vitest/runner@0.34.6': dependencies: '@vitest/utils': 0.34.6 p-limit: 4.0.0 - pathe: 1.1.1 - - '@vitest/runner@3.0.7': - dependencies: - '@vitest/utils': 3.0.7 - pathe: 2.0.3 + pathe: 1.1.2 '@vitest/snapshot@0.34.6': dependencies: - magic-string: 0.30.4 - pathe: 1.1.1 - pretty-format: 29.7.0 - - '@vitest/snapshot@3.0.7': - dependencies: - '@vitest/pretty-format': 3.0.7 magic-string: 0.30.17 - pathe: 2.0.3 + pathe: 1.1.2 + pretty-format: 29.7.0 '@vitest/spy@0.34.6': dependencies: - tinyspy: 2.2.0 - - '@vitest/spy@3.0.7': - dependencies: - tinyspy: 3.0.2 + tinyspy: 2.2.1 '@vitest/utils@0.34.6': dependencies: diff-sequences: 29.6.3 - loupe: 2.3.6 + loupe: 2.3.7 pretty-format: 29.7.0 - '@vitest/utils@3.0.7': - dependencies: - '@vitest/pretty-format': 3.0.7 - loupe: 3.1.3 - tinyrainbow: 2.0.0 - - '@webassemblyjs/ast@1.12.1': - dependencies: - '@webassemblyjs/helper-numbers': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - - '@webassemblyjs/floating-point-hex-parser@1.11.6': {} - - '@webassemblyjs/helper-api-error@1.11.6': {} - - '@webassemblyjs/helper-buffer@1.12.1': {} - - '@webassemblyjs/helper-numbers@1.11.6': - dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.11.6 - '@webassemblyjs/helper-api-error': 1.11.6 - '@xtuc/long': 4.2.2 - - '@webassemblyjs/helper-wasm-bytecode@1.11.6': {} - - '@webassemblyjs/helper-wasm-section@1.12.1': - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/wasm-gen': 1.12.1 - - '@webassemblyjs/ieee754@1.11.6': - dependencies: - '@xtuc/ieee754': 1.2.0 - - '@webassemblyjs/leb128@1.11.6': - dependencies: - '@xtuc/long': 4.2.2 - - '@webassemblyjs/utf8@1.11.6': {} - - '@webassemblyjs/wasm-edit@1.12.1': - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/helper-wasm-section': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-opt': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - '@webassemblyjs/wast-printer': 1.12.1 - - '@webassemblyjs/wasm-gen@1.12.1': - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 - - '@webassemblyjs/wasm-opt@1.12.1': - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - - '@webassemblyjs/wasm-parser@1.12.1': - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-api-error': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 - - '@webassemblyjs/wast-printer@1.12.1': - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@xtuc/long': 4.2.2 - '@xboxreplay/errors@0.1.0': {} '@xboxreplay/xboxlive-auth@3.3.3(debug@4.4.0)': @@ -13544,34 +13040,35 @@ snapshots: '@xmcl/asm@1.0.1': {} - '@xmcl/core@2.12.0(yauzl@2.10.0)': + '@xmcl/core@2.13.0(yauzl@2.10.0)': dependencies: '@xmcl/unzip': 2.1.2(yauzl@2.10.0) transitivePeerDependencies: - yauzl - '@xmcl/file-transfer@1.0.3': + '@xmcl/file-transfer@1.0.6': dependencies: - '@types/http-cache-semantics': 4.0.2 + '@types/http-cache-semantics': 4.0.4 http-cache-semantics: 4.1.1 - undici: 5.25.4 + undici: 6.0.1 '@xmcl/forge-site-parser@2.0.9': dependencies: - node-html-parser: 6.1.10 + node-html-parser: 6.1.13 - '@xmcl/installer@5.1.0': + '@xmcl/installer@5.4.0': dependencies: '@xmcl/asm': 1.0.1 - '@xmcl/core': 2.12.0(yauzl@2.10.0) - '@xmcl/file-transfer': 1.0.3 + '@xmcl/core': 2.13.0(yauzl@2.10.0) + '@xmcl/file-transfer': 1.0.6 '@xmcl/forge-site-parser': 2.0.9 - '@xmcl/task': 4.0.6 + '@xmcl/task': 4.1.0 '@xmcl/unzip': 2.1.2(yauzl@2.10.0) - undici: 5.25.4 + undici: 6.0.1 yauzl: 2.10.0 + yazl: 2.5.1 - '@xmcl/task@4.0.6': {} + '@xmcl/task@4.1.0': {} '@xmcl/text-component@2.1.3': {} @@ -13582,14 +13079,10 @@ snapshots: '@xobotyi/scrollbar-width@1.9.5': {} - '@xtuc/ieee754@1.2.0': {} - - '@xtuc/long@4.2.2': {} - '@yarnpkg/esbuild-plugin-pnp@3.0.0-rc.15(esbuild@0.18.20)': dependencies: esbuild: 0.18.20 - tslib: 2.6.2 + tslib: 2.8.1 '@yarnpkg/fslib@2.10.3': dependencies: @@ -13598,32 +13091,70 @@ snapshots: '@yarnpkg/libzip@2.3.0': dependencies: - '@types/emscripten': 1.39.8 + '@types/emscripten': 1.40.0 tslib: 1.14.1 + '@zardoy/flying-squid@0.0.104(encoding@0.1.13)': + dependencies: + '@tootallnate/once': 2.0.0 + chalk: 5.4.1 + change-case: 4.1.2 + diamond-square: https://codeload.github.com/zardoy/diamond-square/tar.gz/cfaad2d1d5909fdfa63c8cc7bc05fb5e87782d71 + emit-then: 2.0.0 + exit-hook: 2.2.1 + flatmap: 0.0.3 + long: 5.3.1 + mc-bridge: 0.1.3(minecraft-data@3.98.0) + minecraft-data: 3.98.0 + minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13) + mkdirp: 2.1.6 + node-gzip: 1.1.2 + node-rsa: 1.1.1 + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9 + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0) + prismarine-entity: 2.5.0 + prismarine-item: 1.17.0 + prismarine-nbt: 2.7.0 + prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.98.0) + prismarine-windows: 2.9.0 + prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c + rambda: 9.4.2 + random-seed: 0.3.0 + range: 0.0.3 + readline: 1.3.0 + sanitize-filename: 1.6.3 + typed-emitter: 1.4.0 + uuid-1345: 1.0.2 + vec3: 0.1.10 + yaml: 2.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - encoding + - supports-color + '@zardoy/flying-squid@0.0.49(encoding@0.1.13)': dependencies: '@tootallnate/once': 2.0.0 - chalk: 5.3.0 + chalk: 5.4.1 change-case: 4.1.2 diamond-square: https://codeload.github.com/zardoy/diamond-square/tar.gz/cfaad2d1d5909fdfa63c8cc7bc05fb5e87782d71 emit-then: 2.0.0 exit-hook: 2.2.1 flatmap: 0.0.3 - long: 5.2.3 - minecraft-data: 3.83.1 - minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/3bd4dc1b2002cd7badfa5b9cf8dda35cd6cc9ac1(patch_hash=dkeyukcqlupmk563gwxsmjr3yu)(encoding@0.1.13) + long: 5.3.1 + minecraft-data: 3.98.0 + minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13) mkdirp: 2.1.6 node-gzip: 1.1.2 node-rsa: 1.1.1 - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/e68e9a423b5b1907535878fb636f12c28a1a9374(minecraft-data@3.83.1) - prismarine-entity: 2.3.1 - prismarine-item: 1.16.0 - prismarine-nbt: 2.5.0 - prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.83.1) + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0) + prismarine-entity: 2.5.0 + prismarine-item: 1.17.0 + prismarine-nbt: 2.7.0 + prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.98.0) prismarine-windows: 2.9.0 prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c - rambda: 9.2.0 + rambda: 9.4.2 random-seed: 0.3.0 range: 0.0.3 readline: 1.3.0 @@ -13631,54 +13162,20 @@ snapshots: typed-emitter: 1.4.0 uuid-1345: 1.0.2 vec3: 0.1.10 - yaml: 2.4.1 + yaml: 2.7.0 yargs: 17.7.2 transitivePeerDependencies: - encoding - supports-color - '@zardoy/flying-squid@0.0.51(encoding@0.1.13)': - dependencies: - '@tootallnate/once': 2.0.0 - chalk: 5.3.0 - change-case: 4.1.2 - diamond-square: https://codeload.github.com/zardoy/diamond-square/tar.gz/cfaad2d1d5909fdfa63c8cc7bc05fb5e87782d71 - emit-then: 2.0.0 - exit-hook: 2.2.1 - flatmap: 0.0.3 - long: 5.2.3 - minecraft-data: 3.83.1 - minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/5ec3dd4b367fcc039fbcb3edd214fe3cf8178a6d(patch_hash=dkeyukcqlupmk563gwxsmjr3yu)(encoding@0.1.13) - mkdirp: 2.1.6 - node-gzip: 1.1.2 - node-rsa: 1.1.1 - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/e68e9a423b5b1907535878fb636f12c28a1a9374(minecraft-data@3.83.1) - prismarine-entity: 2.3.1 - prismarine-item: 1.16.0 - prismarine-nbt: 2.5.0 - prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.83.1) - prismarine-windows: 2.9.0 - prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c - rambda: 9.2.0 - random-seed: 0.3.0 - range: 0.0.3 - readline: 1.3.0 - sanitize-filename: 1.6.3 - typed-emitter: 1.4.0 - uuid-1345: 1.0.2 - vec3: 0.1.10 - yaml: 2.4.1 - yargs: 17.7.2 - transitivePeerDependencies: - - encoding - - supports-color + '@zardoy/maxrects-packer@2.7.4': {} - '@zardoy/react-util@0.2.4(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@zardoy/react-util@0.2.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: classnames: 2.5.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-hook-form: 7.52.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-hook-form: 7.54.2(react@18.3.1) '@zardoy/utils@0.0.11': dependencies: @@ -13701,29 +13198,27 @@ snapshots: mime-types: 2.1.35 negotiator: 0.6.3 - acorn-import-attributes@1.9.5(acorn@8.12.1): - dependencies: - acorn: 8.12.1 - acorn-jsx@5.3.2(acorn@7.4.1): dependencies: acorn: 7.4.1 - acorn-jsx@5.3.2(acorn@8.12.1): + acorn-jsx@5.3.2(acorn@8.14.1): dependencies: - acorn: 8.12.1 + acorn: 8.14.1 acorn-walk@7.2.0: {} - acorn-walk@8.2.0: {} + acorn-walk@8.3.4: + dependencies: + acorn: 8.14.1 acorn@7.4.1: {} - acorn@8.12.1: {} + acorn@8.14.1: {} address@1.2.2: {} - adm-zip@0.5.12: {} + adm-zip@0.5.16: {} aes-js@3.1.2: {} @@ -13734,18 +13229,12 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.4.0(supports-color@8.1.1) + debug: 4.4.1 transitivePeerDependencies: - supports-color optional: true - agent-base@7.1.0: - dependencies: - debug: 4.4.0(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - - agentkeepalive@4.5.0: + agentkeepalive@4.6.0: dependencies: humanize-ms: 1.2.1 optional: true @@ -13755,10 +13244,6 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ajv-keywords@3.5.2(ajv@6.12.6): - dependencies: - ajv: 6.12.6 - ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -13766,12 +13251,12 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.12.0: + ajv@8.17.1: dependencies: fast-deep-equal: 3.1.3 + fast-uri: 3.0.6 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - uri-js: 4.4.1 animejs@3.2.1: {} @@ -13785,7 +13270,7 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.0.1: {} + ansi-regex@6.1.0: {} ansi-styles@3.2.1: dependencies: @@ -13848,9 +13333,9 @@ snapshots: argparse@2.0.1: {} - aria-hidden@1.2.3: + aria-hidden@1.2.4: dependencies: - tslib: 2.6.2 + tslib: 2.8.1 arr-diff@4.0.0: {} @@ -13860,7 +13345,7 @@ snapshots: array-buffer-byte-length@1.0.2: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 is-array-buffer: 3.0.5 array-flatten@1.1.1: {} @@ -13874,6 +13359,17 @@ snapshots: get-intrinsic: 1.3.0 is-string: 1.1.1 + array-includes@3.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + math-intrinsics: 1.1.0 + array-union@2.1.0: {} array-unique@0.3.2: {} @@ -13882,7 +13378,7 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-errors: 1.3.0 es-object-atoms: 1.1.1 es-shim-unscopables: 1.1.0 @@ -13901,18 +13397,11 @@ snapshots: es-abstract: 1.23.9 es-shim-unscopables: 1.1.0 - array.prototype.toreversed@1.1.2: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.23.9 - es-shim-unscopables: 1.1.0 - array.prototype.tosorted@1.1.4: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-errors: 1.3.0 es-shim-unscopables: 1.1.0 @@ -13931,12 +13420,11 @@ snapshots: arrify@1.0.1: {} - asn1.js@5.4.1: + asn1.js@4.10.1: dependencies: - bn.js: 4.12.0 + bn.js: 4.12.1 inherits: 2.0.4 minimalistic-assert: 1.0.1 - safer-buffer: 2.1.2 asn1@0.2.3: {} @@ -13951,27 +13439,17 @@ snapshots: dependencies: call-bind: 1.0.8 is-nan: 1.3.2 - object-is: 1.1.5 + object-is: 1.1.6 object.assign: 4.1.7 util: 0.12.5 assertion-error@1.1.0: {} - assertion-error@2.0.1: {} - assign-symbols@1.0.0: {} - ast-types@0.14.2: - dependencies: - tslib: 2.6.2 - - ast-types@0.15.2: - dependencies: - tslib: 2.6.2 - ast-types@0.16.1: dependencies: - tslib: 2.6.2 + tslib: 2.8.1 astral-regex@2.0.0: optional: true @@ -13986,7 +13464,7 @@ snapshots: dependencies: lodash: 4.17.21 - async@3.2.5: {} + async@3.2.6: {} asynckit@0.4.0: {} @@ -13996,35 +13474,35 @@ snapshots: available-typed-arrays@1.0.7: dependencies: - possible-typed-array-names: 1.0.0 + possible-typed-array-names: 1.1.0 aws-sign2@0.7.0: optional: true - aws4@1.12.0: + aws4@1.13.2: optional: true axios@0.21.4(debug@4.4.0): dependencies: - follow-redirects: 1.15.6(debug@4.4.0) + follow-redirects: 1.15.9(debug@4.4.0) transitivePeerDependencies: - debug - axios@1.7.2(debug@4.4.0): + axios@1.8.2(debug@4.4.0): dependencies: - follow-redirects: 1.15.6(debug@4.4.0) - form-data: 4.0.0 + follow-redirects: 1.15.9(debug@4.4.0) + form-data: 4.0.2 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug - babel-core@7.0.0-bridge.0(@babel/core@7.22.11): + babel-core@7.0.0-bridge.0(@babel/core@7.26.9): dependencies: - '@babel/core': 7.22.11 + '@babel/core': 7.26.9 babel-plugin-istanbul@6.1.1: dependencies: - '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-plugin-utils': 7.26.5 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 5.2.1 @@ -14034,31 +13512,31 @@ snapshots: babel-plugin-macros@3.1.0: dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.26.9 cosmiconfig: 7.1.0 - resolve: 1.22.4 + resolve: 1.22.10 - babel-plugin-polyfill-corejs2@0.4.5(@babel/core@7.22.11): + babel-plugin-polyfill-corejs2@0.4.12(@babel/core@7.26.9): dependencies: - '@babel/compat-data': 7.22.9 - '@babel/core': 7.22.11 - '@babel/helper-define-polyfill-provider': 0.4.2(@babel/core@7.22.11) + '@babel/compat-data': 7.26.8 + '@babel/core': 7.26.9 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.9) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.8.3(@babel/core@7.22.11): + babel-plugin-polyfill-corejs3@0.11.1(@babel/core@7.26.9): dependencies: - '@babel/core': 7.22.11 - '@babel/helper-define-polyfill-provider': 0.4.2(@babel/core@7.22.11) - core-js-compat: 3.32.1 + '@babel/core': 7.26.9 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.9) + core-js-compat: 3.41.0 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.5.2(@babel/core@7.22.11): + babel-plugin-polyfill-regenerator@0.6.3(@babel/core@7.26.9): dependencies: - '@babel/core': 7.22.11 - '@babel/helper-define-polyfill-provider': 0.4.2(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.9) transitivePeerDependencies: - supports-color @@ -14080,7 +13558,7 @@ snapshots: dependencies: cache-base: 1.0.1 class-utils: 0.3.6 - component-emitter: 1.3.0 + component-emitter: 1.3.1 define-property: 1.0.0 isobject: 3.0.1 mixin-deep: 1.3.2 @@ -14103,11 +13581,11 @@ snapshots: dependencies: open: 8.4.2 - big-integer@1.6.51: {} + big-integer@1.6.52: {} binary-extensions@1.13.1: {} - binary-extensions@2.2.0: {} + binary-extensions@2.3.0: {} bindings@1.5.0: dependencies: @@ -14135,11 +13613,11 @@ snapshots: bmp-js@0.1.0: optional: true - bn.js@4.12.0: {} + bn.js@4.12.1: {} bn.js@5.2.1: {} - body-parser@1.20.1: + body-parser@1.20.3: dependencies: bytes: 3.1.2 content-type: 1.0.5 @@ -14149,24 +13627,7 @@ snapshots: http-errors: 2.0.0 iconv-lite: 0.4.24 on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.1 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - - body-parser@1.20.2: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 + qs: 6.13.0 raw-body: 2.5.2 type-is: 1.6.18 unpipe: 1.0.0 @@ -14177,7 +13638,7 @@ snapshots: bplist-parser@0.2.0: dependencies: - big-integer: 1.6.51 + big-integer: 1.6.52 brace-expansion@1.1.11: dependencies: @@ -14203,9 +13664,9 @@ snapshots: transitivePeerDependencies: - supports-color - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 brorand@1.1.0: {} @@ -14220,7 +13681,7 @@ snapshots: browserify-aes@1.2.0: dependencies: buffer-xor: 1.0.3 - cipher-base: 1.0.4 + cipher-base: 1.0.6 create-hash: 1.2.0 evp_bytestokey: 1.0.3 inherits: 2.0.4 @@ -14234,26 +13695,28 @@ snapshots: browserify-des@1.0.2: dependencies: - cipher-base: 1.0.4 + cipher-base: 1.0.6 des.js: 1.1.0 inherits: 2.0.4 safe-buffer: 5.2.1 - browserify-rsa@4.1.0: + browserify-rsa@4.1.1: dependencies: bn.js: 5.2.1 randombytes: 2.1.0 + safe-buffer: 5.2.1 - browserify-sign@4.2.1: + browserify-sign@4.2.3: dependencies: bn.js: 5.2.1 - browserify-rsa: 4.1.0 + browserify-rsa: 4.1.1 create-hash: 1.2.0 create-hmac: 1.1.7 - elliptic: 6.5.4 + elliptic: 6.6.1 + hash-base: 3.0.5 inherits: 2.0.4 - parse-asn1: 5.1.6 - readable-stream: 3.6.2 + parse-asn1: 5.1.7 + readable-stream: 2.3.8 safe-buffer: 5.2.1 browserify-zlib@0.1.4: @@ -14264,12 +13727,12 @@ snapshots: dependencies: pako: 1.0.11 - browserslist@4.23.2: + browserslist@4.24.4: dependencies: - caniuse-lite: 1.0.30001646 - electron-to-chromium: 1.5.0 - node-releases: 2.0.18 - update-browserslist-db: 1.1.0(browserslist@4.23.2) + caniuse-lite: 1.0.30001713 + electron-to-chromium: 1.5.113 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.4) bser@2.1.1: dependencies: @@ -14297,25 +13760,8 @@ snapshots: builtin-status-codes@3.0.0: {} - bytes@3.0.0: {} - bytes@3.1.2: {} - c8@7.14.0: - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@istanbuljs/schema': 0.1.3 - find-up: 5.0.0 - foreground-child: 2.0.0 - istanbul-lib-coverage: 3.2.0 - istanbul-lib-report: 3.0.1 - istanbul-reports: 3.1.6 - rimraf: 3.0.2 - test-exclude: 6.0.0 - v8-to-istanbul: 9.1.3 - yargs: 16.2.0 - yargs-parser: 20.2.9 - cac@6.7.14: {} cacache@16.1.3: @@ -14336,7 +13782,7 @@ snapshots: promise-inflight: 1.0.1 rimraf: 3.0.2 ssri: 9.0.1 - tar: 6.2.0 + tar: 6.2.1 unique-filename: 2.0.1 transitivePeerDependencies: - bluebird @@ -14345,7 +13791,7 @@ snapshots: cache-base@1.0.1: dependencies: collection-visit: 1.0.0 - component-emitter: 1.3.0 + component-emitter: 1.3.1 get-value: 2.0.6 has-value: 1.0.0 isobject: 3.0.1 @@ -14369,11 +13815,6 @@ snapshots: get-intrinsic: 1.3.0 set-function-length: 1.2.2 - call-bound@1.0.3: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 - call-bound@1.0.4: dependencies: call-bind-apply-helpers: 1.0.2 @@ -14384,7 +13825,7 @@ snapshots: camel-case@4.1.2: dependencies: pascal-case: 3.1.2 - tslib: 2.6.2 + tslib: 2.8.1 camelcase-keys@7.0.2: dependencies: @@ -14397,12 +13838,12 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001646: {} + caniuse-lite@1.0.30001713: {} canvas@2.11.2(encoding@0.1.13): dependencies: '@mapbox/node-pre-gyp': 1.0.11(encoding@0.1.13) - nan: 2.18.0 + nan: 2.22.2 simple-get: 3.1.1 transitivePeerDependencies: - encoding @@ -14412,45 +13853,28 @@ snapshots: capital-case@1.0.4: dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.8.1 upper-case-first: 2.0.2 caseless@0.12.0: optional: true - cbor-extract@2.2.0: + centra@2.7.0(debug@4.4.0): dependencies: - node-gyp-build-optional-packages: 5.1.1 - optionalDependencies: - '@cbor-extract/cbor-extract-darwin-arm64': 2.2.0 - '@cbor-extract/cbor-extract-darwin-x64': 2.2.0 - '@cbor-extract/cbor-extract-linux-arm': 2.2.0 - '@cbor-extract/cbor-extract-linux-arm64': 2.2.0 - '@cbor-extract/cbor-extract-linux-x64': 2.2.0 - '@cbor-extract/cbor-extract-win32-x64': 2.2.0 + follow-redirects: 1.15.9(debug@4.4.0) + transitivePeerDependencies: + - debug optional: true - cbor-x@1.5.4: - optionalDependencies: - cbor-extract: 2.2.0 - - chai@4.3.10: + chai@4.5.0: dependencies: assertion-error: 1.1.0 check-error: 1.0.3 - deep-eql: 4.1.3 + deep-eql: 4.1.4 get-func-name: 2.0.2 - loupe: 2.3.6 + loupe: 2.3.7 pathval: 1.1.1 - type-detect: 4.0.8 - - chai@5.2.0: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.1 - deep-eql: 5.0.2 - loupe: 3.1.3 - pathval: 2.0.0 + type-detect: 4.1.0 chalk@2.4.2: dependencies: @@ -14463,7 +13887,7 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - chalk@5.3.0: {} + chalk@5.4.1: {} change-case@4.1.2: dependencies: @@ -14478,9 +13902,7 @@ snapshots: path-case: 3.0.4 sentence-case: 3.0.4 snake-case: 3.0.4 - tslib: 2.6.2 - - change-case@5.1.2: {} + tslib: 2.8.1 change-case@5.4.4: {} @@ -14492,8 +13914,6 @@ snapshots: dependencies: get-func-name: 2.0.2 - check-error@2.1.1: {} - check-more-types@2.24.0: optional: true @@ -14515,10 +13935,10 @@ snapshots: transitivePeerDependencies: - supports-color - chokidar@3.5.3: + chokidar@3.6.0: dependencies: anymatch: 3.1.3 - braces: 3.0.2 + braces: 3.0.3 glob-parent: 5.1.2 is-binary-path: 2.1.0 is-glob: 4.0.3 @@ -14531,15 +13951,17 @@ snapshots: chownr@2.0.0: {} - chrome-trace-event@1.0.4: {} + ci-info@3.9.0: {} - ci-info@3.8.0: {} - - cipher-base@1.0.4: + cipher-base@1.0.6: dependencies: inherits: 2.0.4 safe-buffer: 5.2.1 + citty@0.1.6: + dependencies: + consola: 3.4.0 + class-utils@0.3.6: dependencies: arr-union: 3.1.0 @@ -14559,9 +13981,9 @@ snapshots: dependencies: restore-cursor: 3.1.0 - cli-spinners@2.9.1: {} + cli-spinners@2.9.2: {} - cli-table3@0.6.3: + cli-table3@0.6.5: dependencies: string-width: 4.2.3 optionalDependencies: @@ -14573,12 +13995,6 @@ snapshots: string-width: 4.2.3 optional: true - cliui@7.0.4: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -14625,7 +14041,8 @@ snapshots: color-convert: 2.0.1 color-string: 1.9.1 - colorette@2.0.20: {} + colorette@2.0.20: + optional: true colors@1.4.0: {} @@ -14650,23 +14067,23 @@ snapshots: component-emitter@1.2.1: optional: true - component-emitter@1.3.0: {} + component-emitter@1.3.1: {} component-inherit@0.0.3: optional: true compressible@2.0.18: dependencies: - mime-db: 1.52.0 + mime-db: 1.54.0 - compression@1.7.4: + compression@1.8.0: dependencies: - accepts: 1.3.8 - bytes: 3.0.0 + bytes: 3.1.2 compressible: 2.0.18 debug: 2.6.9 + negotiator: 0.6.4 on-headers: 1.0.2 - safe-buffer: 5.1.2 + safe-buffer: 5.2.1 vary: 1.1.2 transitivePeerDependencies: - supports-color @@ -14680,6 +14097,8 @@ snapshots: readable-stream: 2.3.8 typedarray: 0.0.6 + confbox@0.1.8: {} + confusing-browser-globals@1.0.11: {} connect@3.7.0: @@ -14691,6 +14110,8 @@ snapshots: transitivePeerDependencies: - supports-color + consola@3.4.0: {} + console-browserify@1.2.0: {} console-control-strings@1.1.0: @@ -14699,7 +14120,7 @@ snapshots: constant-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.8.1 upper-case: 2.0.2 constants-browserify@1.0.0: {} @@ -14710,14 +14131,14 @@ snapshots: content-type@1.0.5: {} - contro-max@0.1.8(typescript@5.5.4): + contro-max@0.1.9(typescript@5.5.4): dependencies: events: 3.3.0 lodash-es: 4.17.21 typed-emitter: 2.1.0 optionalDependencies: - react: 18.2.0 - use-typed-event-listener: 4.0.2(react@18.2.0)(typescript@5.5.4) + react: 18.3.1 + use-typed-event-listener: 4.0.2(react@18.3.1)(typescript@5.5.4) transitivePeerDependencies: - typescript @@ -14727,9 +14148,12 @@ snapshots: cookie-signature@1.0.6: {} - cookie@0.4.2: {} + cookie@0.4.2: + optional: true - cookie@0.5.0: {} + cookie@0.7.1: {} + + cookie@0.7.2: {} copy-descriptor@0.1.1: {} @@ -14737,11 +14161,11 @@ snapshots: dependencies: toggle-selection: 1.0.6 - core-js-compat@3.32.1: + core-js-compat@3.41.0: dependencies: - browserslist: 4.23.2 + browserslist: 4.24.4 - core-js@3.37.1: {} + core-js@3.41.0: {} core-util-is@1.0.2: optional: true @@ -14757,29 +14181,20 @@ snapshots: cosmiconfig@7.1.0: dependencies: - '@types/parse-json': 4.0.0 - import-fresh: 3.3.0 + '@types/parse-json': 4.0.2 + import-fresh: 3.3.1 parse-json: 5.2.0 path-type: 4.0.0 yaml: 1.10.2 - cosmiconfig@8.3.6(typescript@5.5.4): - dependencies: - import-fresh: 3.3.0 - js-yaml: 4.1.0 - parse-json: 5.2.0 - path-type: 4.0.0 - optionalDependencies: - typescript: 5.5.4 - create-ecdh@4.0.4: dependencies: - bn.js: 4.12.0 - elliptic: 6.5.4 + bn.js: 4.12.1 + elliptic: 6.6.1 create-hash@1.2.0: dependencies: - cipher-base: 1.0.4 + cipher-base: 1.0.6 inherits: 2.0.4 md5.js: 1.3.5 ripemd160: 2.0.2 @@ -14787,7 +14202,7 @@ snapshots: create-hmac@1.1.7: dependencies: - cipher-base: 1.0.4 + cipher-base: 1.0.6 create-hash: 1.2.0 inherits: 2.0.4 ripemd160: 2.0.2 @@ -14796,7 +14211,7 @@ snapshots: crelt@1.0.6: {} - cross-spawn@6.0.5: + cross-spawn@6.0.6: dependencies: nice-try: 1.0.5 path-key: 2.0.1 @@ -14804,7 +14219,7 @@ snapshots: shebang-command: 1.2.0 which: 1.3.1 - cross-spawn@7.0.3: + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 @@ -14812,14 +14227,15 @@ snapshots: crypt@0.0.2: {} - crypto-browserify@3.12.0: + crypto-browserify@3.12.1: dependencies: browserify-cipher: 1.0.1 - browserify-sign: 4.2.1 + browserify-sign: 4.2.3 create-ecdh: 4.0.4 create-hash: 1.2.0 create-hmac: 1.1.7 diffie-hellman: 5.0.3 + hash-base: 3.0.5 inherits: 2.0.4 pbkdf2: 3.1.2 public-encrypt: 4.0.3 @@ -14830,14 +14246,14 @@ snapshots: css-in-js-utils@3.1.0: dependencies: - hyphenate-style-name: 1.0.4 + hyphenate-style-name: 1.1.0 css-select@5.1.0: dependencies: boolbase: 1.0.0 css-what: 6.1.0 domhandler: 5.0.3 - domutils: 3.1.0 + domutils: 3.2.2 nth-check: 2.1.1 css-tree@1.1.3: @@ -14847,17 +14263,17 @@ snapshots: css-what@6.1.0: {} - csstype@3.1.2: {} + csstype@3.1.3: {} cypress-esbuild-preprocessor@1.0.2: {} - cypress-plugin-snapshots@1.4.4(cypress@10.11.0): + cypress-plugin-snapshots@1.4.4(cypress@10.11.0)(debug@4.4.0): dependencies: cypress: 10.11.0 diff2html: 2.12.2 fs-extra: 7.0.1 image-size: 0.7.5 - jimp: 0.10.3 + jimp: 0.10.3(debug@4.4.0) js-base64: 2.6.4 lodash: 4.17.21 pixelmatch: 4.0.2 @@ -14865,12 +14281,13 @@ snapshots: prettier: 1.19.1 rimraf: 2.7.1 sanitize-filename: 1.6.3 - socket.io: 2.5.0 + socket.io: 2.5.1 socket.io-client: 2.5.0 source-map-support: 0.5.21 unidiff: 1.0.2 transitivePeerDependencies: - bufferutil + - debug - supports-color - utf-8-validate optional: true @@ -14879,9 +14296,9 @@ snapshots: dependencies: '@cypress/request': 2.88.12 '@cypress/xvfb': 1.2.4(supports-color@8.1.1) - '@types/node': 14.18.56 + '@types/node': 14.18.63 '@types/sinonjs__fake-timers': 8.1.1 - '@types/sizzle': 2.3.3 + '@types/sizzle': 2.3.9 arch: 2.2.0 blob-util: 2.0.2 bluebird: 3.7.2 @@ -14890,10 +14307,10 @@ snapshots: chalk: 4.1.2 check-more-types: 2.24.0 cli-cursor: 3.1.0 - cli-table3: 0.6.3 + cli-table3: 0.6.5 commander: 5.1.0 common-tags: 1.8.2 - dayjs: 1.11.9 + dayjs: 1.11.13 debug: 4.4.0(supports-color@8.1.1) enquirer: 2.4.1 eventemitter2: 6.4.7 @@ -14914,9 +14331,9 @@ snapshots: pretty-bytes: 5.6.0 proxy-from-env: 1.0.0 request-progress: 3.0.0 - semver: 7.6.0 + semver: 7.7.1 supports-color: 8.1.1 - tmp: 0.2.1 + tmp: 0.2.3 untildify: 4.0.0 yauzl: 2.10.0 optional: true @@ -14928,23 +14345,23 @@ snapshots: data-view-buffer@1.0.2: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 es-errors: 1.3.0 is-data-view: 1.0.2 data-view-byte-length@1.0.2: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 es-errors: 1.3.0 is-data-view: 1.0.2 data-view-byte-offset@1.0.1: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 es-errors: 1.3.0 is-data-view: 1.0.2 - dayjs@1.11.9: + dayjs@1.11.13: optional: true debounce@1.2.1: {} @@ -14979,6 +14396,10 @@ snapshots: optionalDependencies: supports-color: 8.1.1 + debug@4.4.1: + dependencies: + ms: 2.1.3 + decamelize-keys@1.1.1: dependencies: decamelize: 1.2.0 @@ -14988,7 +14409,7 @@ snapshots: decamelize@5.0.1: {} - decode-named-character-reference@1.0.2: + decode-named-character-reference@1.1.0: dependencies: character-entities: 2.0.2 @@ -15003,11 +14424,9 @@ snapshots: dependencies: mimic-response: 3.1.0 - deep-eql@4.1.3: + deep-eql@4.1.4: dependencies: - type-detect: 4.0.8 - - deep-eql@5.0.2: {} + type-detect: 4.1.0 deep-extend@0.6.0: {} @@ -15057,7 +14476,7 @@ snapshots: is-descriptor: 1.0.3 isobject: 3.0.1 - defu@6.1.2: {} + defu@6.1.4: {} del@6.1.1: dependencies: @@ -15079,10 +14498,12 @@ snapshots: depd@2.0.0: {} - dequal@1.0.0: {} - dequal@2.0.3: {} + derive-valtio@0.1.0(valtio@1.13.2(@types/react@18.3.18)(react@18.3.1)): + dependencies: + valtio: 1.13.2(@types/react@18.3.18)(react@18.3.1) + des.js@1.1.0: dependencies: inherits: 2.0.4 @@ -15092,7 +14513,7 @@ snapshots: detect-collisions@7.0.5: dependencies: - '@types/rbush': 3.0.1 + '@types/rbush': 3.0.4 '@types/sat': 0.0.31 poly-decomp: 0.3.0 rbush: 3.0.1 @@ -15100,10 +14521,7 @@ snapshots: detect-indent@6.1.0: {} - detect-libc@2.0.2: {} - - detect-libc@2.0.3: - optional: true + detect-libc@2.0.3: {} detect-node-es@1.1.0: {} @@ -15111,10 +14529,10 @@ snapshots: dependencies: execa: 5.1.1 - detect-port@1.5.1: + detect-port@1.6.1: dependencies: address: 1.2.2 - debug: 4.4.0(supports-color@8.1.1) + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -15124,8 +14542,8 @@ snapshots: diamond-square@https://codeload.github.com/zardoy/diamond-square/tar.gz/cfaad2d1d5909fdfa63c8cc7bc05fb5e87782d71: dependencies: - minecraft-data: 3.83.1 - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/e68e9a423b5b1907535878fb636f12c28a1a9374(minecraft-data@3.83.1) + minecraft-data: 3.98.0 + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0) prismarine-registry: 1.11.0 random-seed: 0.3.0 vec3: 0.1.10 @@ -15139,7 +14557,7 @@ snapshots: diff: 4.0.2 hogan.js: 3.0.2 merge: 1.2.1 - whatwg-fetch: 3.6.18 + whatwg-fetch: 3.6.20 optional: true diff@2.2.3: @@ -15150,7 +14568,7 @@ snapshots: diffie-hellman@5.0.3: dependencies: - bn.js: 4.12.0 + bn.js: 4.12.1 miller-rabin: 4.0.1 randombytes: 2.1.0 @@ -15170,8 +14588,8 @@ snapshots: dom-helpers@5.2.1: dependencies: - '@babel/runtime': 7.24.5 - csstype: 3.1.2 + '@babel/runtime': 7.26.9 + csstype: 3.1.3 dom-serializer@2.0.0: dependencies: @@ -15190,7 +14608,7 @@ snapshots: dependencies: domelementtype: 2.3.0 - domutils@3.1.0: + domutils@3.2.2: dependencies: dom-serializer: 2.0.0 domelementtype: 2.3.0 @@ -15199,13 +14617,13 @@ snapshots: dot-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.8.1 dotenv-expand@10.0.0: {} - dotenv@16.3.1: {} + dotenv@16.4.7: {} - draco3d@1.5.6: {} + draco3d@1.5.7: {} dunder-proto@1.0.1: dependencies: @@ -15220,7 +14638,7 @@ snapshots: end-of-stream: 1.4.4 inherits: 2.0.4 readable-stream: 2.3.8 - stream-shift: 1.0.1 + stream-shift: 1.0.3 eastasianwidth@0.2.0: {} @@ -15236,15 +14654,15 @@ snapshots: ee-first@1.1.1: {} - ejs@3.1.9: + ejs@3.1.10: dependencies: - jake: 10.8.7 + jake: 10.9.2 - electron-to-chromium@1.5.0: {} + electron-to-chromium@1.5.113: {} - elliptic@6.5.4: + elliptic@6.6.1: dependencies: - bn.js: 4.12.0 + bn.js: 4.12.1 brorand: 1.1.0 hash.js: 1.1.7 hmac-drbg: 1.0.1 @@ -15273,9 +14691,9 @@ snapshots: endian-toggle@0.0.0: {} - engine.io-client@3.5.3: + engine.io-client@3.5.4: dependencies: - component-emitter: 1.3.0 + component-emitter: 1.3.1 component-inherit: 0.0.3 debug: 3.1.0 engine.io-parser: 2.2.1 @@ -15283,7 +14701,7 @@ snapshots: indexof: 0.0.1 parseqs: 0.0.6 parseuri: 0.0.6 - ws: 7.4.6 + ws: 7.5.10 xmlhttprequest-ssl: 1.6.3 yeast: 0.1.2 transitivePeerDependencies: @@ -15292,13 +14710,13 @@ snapshots: - utf-8-validate optional: true - engine.io-client@6.5.2: + engine.io-client@6.6.3: dependencies: - '@socket.io/component-emitter': 3.1.0 + '@socket.io/component-emitter': 3.1.2 debug: 4.3.7 - engine.io-parser: 5.2.1 - ws: 8.11.0 - xmlhttprequest-ssl: 2.0.0 + engine.io-parser: 5.2.3 + ws: 8.17.1 + xmlhttprequest-ssl: 2.1.2 transitivePeerDependencies: - bufferutil - supports-color @@ -15313,44 +14731,38 @@ snapshots: has-binary2: 1.0.3 optional: true - engine.io-parser@5.2.1: {} + engine.io-parser@5.2.3: {} - engine.io@3.6.1: + engine.io@3.6.2: dependencies: accepts: 1.3.8 base64id: 2.0.0 cookie: 0.4.2 debug: 4.1.1 engine.io-parser: 2.2.1 - ws: 7.4.6 + ws: 7.5.10 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate optional: true - engine.io@6.5.3: + engine.io@6.6.4: dependencies: - '@types/cookie': 0.4.1 - '@types/cors': 2.8.15 - '@types/node': 22.8.1 + '@types/cors': 2.8.17 + '@types/node': 22.13.9 accepts: 1.3.8 base64id: 2.0.0 - cookie: 0.4.2 + cookie: 0.7.2 cors: 2.8.5 debug: 4.3.7 - engine.io-parser: 5.2.1 - ws: 8.11.0 + engine.io-parser: 5.2.3 + ws: 8.17.1 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - enhanced-resolve@5.17.1: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - enquirer@2.4.1: dependencies: ansi-colors: 4.1.3 @@ -15362,7 +14774,7 @@ snapshots: env-paths@2.2.1: optional: true - envinfo@7.10.0: {} + envinfo@7.14.0: {} err-code@2.0.3: optional: true @@ -15375,7 +14787,7 @@ snapshots: dependencies: stackframe: 1.3.4 - eruda@3.0.1: {} + eruda@3.4.1: {} es-abstract@1.23.9: dependencies: @@ -15383,7 +14795,7 @@ snapshots: arraybuffer.prototype.slice: 1.0.4 available-typed-arrays: 1.0.7 call-bind: 1.0.8 - call-bound: 1.0.3 + call-bound: 1.0.4 data-view-buffer: 1.0.2 data-view-byte-length: 1.0.2 data-view-byte-offset: 1.0.1 @@ -15410,9 +14822,9 @@ snapshots: is-shared-array-buffer: 1.0.4 is-string: 1.1.1 is-typed-array: 1.1.15 - is-weakref: 1.1.0 + is-weakref: 1.1.1 math-intrinsics: 1.1.0 - object-inspect: 1.13.3 + object-inspect: 1.13.4 object-keys: 1.1.1 object.assign: 4.1.7 own-keys: 1.0.1 @@ -15431,6 +14843,63 @@ snapshots: unbox-primitive: 1.1.0 which-typed-array: 1.1.18 + es-abstract@1.24.0: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.19 + es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -15440,7 +14909,7 @@ snapshots: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-errors: 1.3.0 es-set-tostringtag: 2.1.0 function-bind: 1.1.2 @@ -15456,10 +14925,6 @@ snapshots: es-module-lexer@0.9.3: {} - es-module-lexer@1.5.4: {} - - es-module-lexer@1.6.0: {} - es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -15489,13 +14954,13 @@ snapshots: esbuild-plugin-alias@0.2.1: {} - esbuild-plugin-polyfill-node@0.3.0(esbuild@0.19.11): + esbuild-plugin-polyfill-node@0.3.0(esbuild@0.19.12): dependencies: - '@jspm/core': 2.0.1 - esbuild: 0.19.11 - import-meta-resolve: 3.0.0 + '@jspm/core': 2.1.0 + esbuild: 0.19.12 + import-meta-resolve: 3.1.1 - esbuild-register@3.5.0(esbuild@0.18.20): + esbuild-register@3.6.0(esbuild@0.18.20): dependencies: debug: 4.4.0(supports-color@8.1.1) esbuild: 0.18.20 @@ -15527,31 +14992,31 @@ snapshots: '@esbuild/win32-ia32': 0.18.20 '@esbuild/win32-x64': 0.18.20 - esbuild@0.19.11: + esbuild@0.19.12: optionalDependencies: - '@esbuild/aix-ppc64': 0.19.11 - '@esbuild/android-arm': 0.19.11 - '@esbuild/android-arm64': 0.19.11 - '@esbuild/android-x64': 0.19.11 - '@esbuild/darwin-arm64': 0.19.11 - '@esbuild/darwin-x64': 0.19.11 - '@esbuild/freebsd-arm64': 0.19.11 - '@esbuild/freebsd-x64': 0.19.11 - '@esbuild/linux-arm': 0.19.11 - '@esbuild/linux-arm64': 0.19.11 - '@esbuild/linux-ia32': 0.19.11 - '@esbuild/linux-loong64': 0.19.11 - '@esbuild/linux-mips64el': 0.19.11 - '@esbuild/linux-ppc64': 0.19.11 - '@esbuild/linux-riscv64': 0.19.11 - '@esbuild/linux-s390x': 0.19.11 - '@esbuild/linux-x64': 0.19.11 - '@esbuild/netbsd-x64': 0.19.11 - '@esbuild/openbsd-x64': 0.19.11 - '@esbuild/sunos-x64': 0.19.11 - '@esbuild/win32-arm64': 0.19.11 - '@esbuild/win32-ia32': 0.19.11 - '@esbuild/win32-x64': 0.19.11 + '@esbuild/aix-ppc64': 0.19.12 + '@esbuild/android-arm': 0.19.12 + '@esbuild/android-arm64': 0.19.12 + '@esbuild/android-x64': 0.19.12 + '@esbuild/darwin-arm64': 0.19.12 + '@esbuild/darwin-x64': 0.19.12 + '@esbuild/freebsd-arm64': 0.19.12 + '@esbuild/freebsd-x64': 0.19.12 + '@esbuild/linux-arm': 0.19.12 + '@esbuild/linux-arm64': 0.19.12 + '@esbuild/linux-ia32': 0.19.12 + '@esbuild/linux-loong64': 0.19.12 + '@esbuild/linux-mips64el': 0.19.12 + '@esbuild/linux-ppc64': 0.19.12 + '@esbuild/linux-riscv64': 0.19.12 + '@esbuild/linux-s390x': 0.19.12 + '@esbuild/linux-x64': 0.19.12 + '@esbuild/netbsd-x64': 0.19.12 + '@esbuild/openbsd-x64': 0.19.12 + '@esbuild/sunos-x64': 0.19.12 + '@esbuild/win32-arm64': 0.19.12 + '@esbuild/win32-ia32': 0.19.12 + '@esbuild/win32-x64': 0.19.12 esbuild@0.25.0: optionalDependencies: @@ -15581,7 +15046,7 @@ snapshots: '@esbuild/win32-ia32': 0.25.0 '@esbuild/win32-x64': 0.25.0 - escalade@3.1.2: {} + escalade@3.2.0: {} escape-html@1.0.3: {} @@ -15597,43 +15062,43 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-prettier@8.10.0(eslint@8.50.0): + eslint-config-prettier@8.10.0(eslint@8.57.1): dependencies: - eslint: 8.50.0 + eslint: 8.57.1 - eslint-config-xo-react@0.27.0(eslint-plugin-react-hooks@4.6.0(eslint@8.50.0))(eslint-plugin-react@7.34.1(eslint@8.50.0))(eslint@8.50.0): + eslint-config-xo-react@0.27.0(eslint-plugin-react-hooks@5.2.0(eslint@8.57.1))(eslint-plugin-react@7.37.4(eslint@8.57.1))(eslint@8.57.1): dependencies: - eslint: 8.50.0 - eslint-plugin-react: 7.34.1(eslint@8.50.0) - eslint-plugin-react-hooks: 4.6.0(eslint@8.50.0) + eslint: 8.57.1 + eslint-plugin-react: 7.37.4(eslint@8.57.1) + eslint-plugin-react-hooks: 5.2.0(eslint@8.57.1) - eslint-config-xo-typescript@1.0.1(@typescript-eslint/eslint-plugin@6.1.0(@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.5.4))(eslint@8.50.0)(typescript@5.5.4))(@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.5.4))(eslint@8.50.0)(typescript@5.5.4): + eslint-config-xo-typescript@1.0.1(@typescript-eslint/eslint-plugin@6.1.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.5.4))(eslint@8.57.1)(typescript@5.5.4))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.5.4))(eslint@8.57.1)(typescript@5.5.4): dependencies: - '@typescript-eslint/eslint-plugin': 6.1.0(@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.5.4))(eslint@8.50.0)(typescript@5.5.4) - '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.5.4) - eslint: 8.50.0 + '@typescript-eslint/eslint-plugin': 6.1.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.5.4))(eslint@8.57.1)(typescript@5.5.4) + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.5.4) + eslint: 8.57.1 typescript: 5.5.4 - eslint-config-xo@0.43.1(eslint@8.50.0): + eslint-config-xo@0.43.1(eslint@8.57.1): dependencies: confusing-browser-globals: 1.0.11 - eslint: 8.50.0 + eslint: 8.57.1 - eslint-config-zardoy@0.2.17(eslint-plugin-react-hooks@4.6.0(eslint@8.50.0))(eslint-plugin-react@7.34.1(eslint@8.50.0))(eslint@8.50.0)(typescript@5.5.4): + eslint-config-zardoy@0.2.17(eslint-plugin-react-hooks@5.2.0(eslint@8.57.1))(eslint-plugin-react@7.37.4(eslint@8.57.1))(eslint@8.57.1)(typescript@5.5.4): dependencies: - '@rushstack/eslint-patch': 1.4.0 - '@typescript-eslint/eslint-plugin': 6.1.0(@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.5.4))(eslint@8.50.0)(typescript@5.5.4) - '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.5.4) - eslint: 8.50.0 - eslint-config-prettier: 8.10.0(eslint@8.50.0) - eslint-config-xo: 0.43.1(eslint@8.50.0) - eslint-config-xo-react: 0.27.0(eslint-plugin-react-hooks@4.6.0(eslint@8.50.0))(eslint-plugin-react@7.34.1(eslint@8.50.0))(eslint@8.50.0) - eslint-config-xo-typescript: 1.0.1(@typescript-eslint/eslint-plugin@6.1.0(@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.5.4))(eslint@8.50.0)(typescript@5.5.4))(@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.5.4))(eslint@8.50.0)(typescript@5.5.4) - eslint-plugin-eslint-comments: 3.2.0(eslint@8.50.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.5.4))(eslint@8.50.0) - eslint-plugin-node: 11.1.0(eslint@8.50.0) - eslint-plugin-sonarjs: 0.19.0(eslint@8.50.0) - eslint-plugin-unicorn: 48.0.0(eslint@8.50.0) + '@rushstack/eslint-patch': 1.10.5 + '@typescript-eslint/eslint-plugin': 6.1.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.5.4))(eslint@8.57.1)(typescript@5.5.4) + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.5.4) + eslint: 8.57.1 + eslint-config-prettier: 8.10.0(eslint@8.57.1) + eslint-config-xo: 0.43.1(eslint@8.57.1) + eslint-config-xo-react: 0.27.0(eslint-plugin-react-hooks@5.2.0(eslint@8.57.1))(eslint-plugin-react@7.37.4(eslint@8.57.1))(eslint@8.57.1) + eslint-config-xo-typescript: 1.0.1(@typescript-eslint/eslint-plugin@6.1.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.5.4))(eslint@8.57.1)(typescript@5.5.4))(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.5.4))(eslint@8.57.1)(typescript@5.5.4) + eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.1) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.5.4))(eslint@8.57.1) + eslint-plugin-node: 11.1.0(eslint@8.57.1) + eslint-plugin-sonarjs: 0.19.0(eslint@8.57.1) + eslint-plugin-unicorn: 48.0.0(eslint@8.57.1) typescript: 5.5.4 transitivePeerDependencies: - eslint-import-resolver-typescript @@ -15646,121 +15111,116 @@ snapshots: dependencies: debug: 3.2.7(supports-color@8.1.1) is-core-module: 2.16.1 - resolve: 1.22.4 + resolve: 1.22.10 transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@8.50.0): + eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1): dependencies: debug: 3.2.7(supports-color@8.1.1) optionalDependencies: - '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.5.4) - eslint: 8.50.0 + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.5.4) + eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-es@3.0.1(eslint@8.50.0): + eslint-plugin-es@3.0.1(eslint@8.57.1): dependencies: - eslint: 8.50.0 + eslint: 8.57.1 eslint-utils: 2.1.0 regexpp: 3.2.0 - eslint-plugin-eslint-comments@3.2.0(eslint@8.50.0): + eslint-plugin-eslint-comments@3.2.0(eslint@8.57.1): dependencies: escape-string-regexp: 1.0.5 - eslint: 8.50.0 - ignore: 5.2.4 + eslint: 8.57.1 + ignore: 5.3.2 - eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.5.4))(eslint@8.50.0): + eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.5.4))(eslint@8.57.1): dependencies: array-includes: 3.1.8 array.prototype.flat: 1.3.3 array.prototype.flatmap: 1.3.3 debug: 3.2.7(supports-color@8.1.1) doctrine: 2.1.0 - eslint: 8.50.0 + eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@8.50.0) - has: 1.0.3 + eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) + has: 1.0.4 is-core-module: 2.16.1 is-glob: 4.0.3 minimatch: 3.1.2 object.values: 1.2.1 - resolve: 1.22.4 + resolve: 1.22.10 semver: 6.3.1 - tsconfig-paths: 3.14.2 + tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.5.4) + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.5.4) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-node@11.1.0(eslint@8.50.0): + eslint-plugin-node@11.1.0(eslint@8.57.1): dependencies: - eslint: 8.50.0 - eslint-plugin-es: 3.0.1(eslint@8.50.0) + eslint: 8.57.1 + eslint-plugin-es: 3.0.1(eslint@8.57.1) eslint-utils: 2.1.0 - ignore: 5.2.4 + ignore: 5.3.2 minimatch: 3.1.2 - resolve: 1.22.4 + resolve: 1.22.10 semver: 6.3.1 - eslint-plugin-react-hooks@4.6.0(eslint@8.50.0): + eslint-plugin-react-hooks@5.2.0(eslint@8.57.1): dependencies: - eslint: 8.50.0 + eslint: 8.57.1 - eslint-plugin-react@7.34.1(eslint@8.50.0): + eslint-plugin-react@7.37.4(eslint@8.57.1): dependencies: - array-includes: 3.1.8 + array-includes: 3.1.9 array.prototype.findlast: 1.2.5 array.prototype.flatmap: 1.3.3 - array.prototype.toreversed: 1.1.2 array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 8.50.0 + eslint: 8.57.1 estraverse: 5.3.0 + hasown: 2.0.2 jsx-ast-utils: 3.3.5 minimatch: 3.1.2 - object.entries: 1.1.8 + object.entries: 1.1.9 object.fromentries: 2.0.8 - object.hasown: 1.1.4 object.values: 1.2.1 prop-types: 15.8.1 resolve: 2.0.0-next.5 semver: 6.3.1 string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 - eslint-plugin-sonarjs@0.19.0(eslint@8.50.0): + eslint-plugin-sonarjs@0.19.0(eslint@8.57.1): dependencies: - eslint: 8.50.0 + eslint: 8.57.1 - eslint-plugin-unicorn@48.0.0(eslint@8.50.0): + eslint-plugin-unicorn@48.0.0(eslint@8.57.1): dependencies: - '@babel/helper-validator-identifier': 7.22.20 - '@eslint-community/eslint-utils': 4.4.0(eslint@8.50.0) - ci-info: 3.8.0 + '@babel/helper-validator-identifier': 7.25.9 + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + ci-info: 3.9.0 clean-regexp: 1.0.0 - eslint: 8.50.0 - esquery: 1.5.0 + eslint: 8.57.1 + esquery: 1.6.0 indent-string: 4.0.0 is-builtin-module: 3.2.1 - jsesc: 3.0.2 + jsesc: 3.1.0 lodash: 4.17.21 pluralize: 8.0.0 read-pkg-up: 7.0.1 regexp-tree: 0.1.27 regjsparser: 0.10.0 - semver: 7.6.0 + semver: 7.7.1 strip-indent: 3.0.0 - eslint-scope@5.1.1: - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - eslint-scope@7.2.2: dependencies: esrecurse: 4.3.0 @@ -15774,35 +15234,36 @@ snapshots: eslint-visitor-keys@3.4.3: {} - eslint-visitor-keys@4.0.0: {} + eslint-visitor-keys@4.2.0: {} - eslint@8.50.0: + eslint@8.57.1: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.50.0) - '@eslint-community/regexpp': 4.8.0 - '@eslint/eslintrc': 2.1.2 - '@eslint/js': 8.50.0 - '@humanwhocodes/config-array': 0.11.11 + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@eslint-community/regexpp': 4.12.1 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.1 + '@humanwhocodes/config-array': 0.13.0 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.3.0 ajv: 6.12.6 chalk: 4.1.2 - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 debug: 4.4.0(supports-color@8.1.1) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 espree: 9.6.1 - esquery: 1.5.0 + esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 6.0.1 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.21.0 + globals: 13.24.0 graphemer: 1.4.0 - ignore: 5.2.4 + ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 @@ -15812,27 +15273,27 @@ snapshots: lodash.merge: 4.6.2 minimatch: 3.1.2 natural-compare: 1.4.0 - optionator: 0.9.3 + optionator: 0.9.4 strip-ansi: 6.0.1 text-table: 0.2.0 transitivePeerDependencies: - supports-color - espree@10.1.0: + espree@10.3.0: dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) - eslint-visitor-keys: 4.0.0 + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + eslint-visitor-keys: 4.2.0 espree@9.6.1: dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} - esquery@1.5.0: + esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -15840,26 +15301,12 @@ snapshots: dependencies: estraverse: 5.3.0 - estraverse@4.3.0: {} - estraverse@5.3.0: {} - estree-to-babel@3.2.1: - dependencies: - '@babel/traverse': 7.22.11 - '@babel/types': 7.23.0 - c8: 7.14.0 - transitivePeerDependencies: - - supports-color - estree-walker@1.0.1: {} estree-walker@2.0.2: {} - estree-walker@3.0.3: - dependencies: - '@types/estree': 1.0.6 - esutils@2.0.3: {} etag@1.8.1: {} @@ -15890,7 +15337,7 @@ snapshots: execa@4.1.0: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 get-stream: 5.2.0 human-signals: 1.1.1 is-stream: 2.0.1 @@ -15903,7 +15350,7 @@ snapshots: execa@5.1.1: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 get-stream: 6.0.1 human-signals: 2.1.0 is-stream: 2.0.1 @@ -15937,47 +15384,45 @@ snapshots: expand-template@2.0.3: {} - expect-type@1.1.0: {} - - exponential-backoff@3.1.1: + exponential-backoff@3.1.2: optional: true - express-ws@4.0.0(express@4.18.2): + express-ws@4.0.0(express@4.21.2): dependencies: - express: 4.18.2 - ws: 5.2.3 + express: 4.21.2 + ws: 5.2.4 transitivePeerDependencies: - bufferutil - utf-8-validate - express@4.18.2: + express@4.21.2: dependencies: accepts: 1.3.8 array-flatten: 1.1.1 - body-parser: 1.20.1 + body-parser: 1.20.3 content-disposition: 0.5.4 content-type: 1.0.5 - cookie: 0.5.0 + cookie: 0.7.1 cookie-signature: 1.0.6 debug: 2.6.9 depd: 2.0.0 - encodeurl: 1.0.2 + encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 - finalhandler: 1.2.0 + finalhandler: 1.3.1 fresh: 0.5.2 http-errors: 2.0.0 - merge-descriptors: 1.0.1 + merge-descriptors: 1.0.3 methods: 1.1.2 on-finished: 2.4.1 parseurl: 1.3.3 - path-to-regexp: 0.1.7 + path-to-regexp: 0.1.12 proxy-addr: 2.0.7 - qs: 6.11.0 + qs: 6.13.0 range-parser: 1.2.1 safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 + send: 0.19.0 + serve-static: 1.16.2 setprototypeof: 1.2.0 statuses: 2.0.1 type-is: 1.6.18 @@ -16034,27 +15479,27 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-glob@3.3.1: + fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.8 fast-json-stable-stringify@2.1.0: {} fast-levenshtein@2.0.6: {} - fast-loops@1.1.3: {} - fast-shallow-equal@1.0.0: {} + fast-uri@3.0.6: {} + fastest-stable-stringify@2.0.2: {} - fastq@1.15.0: + fastq@1.19.1: dependencies: - reusify: 1.0.4 + reusify: 1.1.0 faye-websocket@0.11.4: dependencies: @@ -16079,7 +15524,7 @@ snapshots: file-entry-cache@6.0.1: dependencies: - flat-cache: 3.1.0 + flat-cache: 3.2.0 file-system-cache@2.3.0: dependencies: @@ -16096,7 +15541,7 @@ snapshots: dependencies: minimatch: 5.1.6 - filesize@10.0.12: {} + filesize@10.1.6: {} fill-range@4.0.0: dependencies: @@ -16105,7 +15550,7 @@ snapshots: repeat-string: 1.6.1 to-regex-range: 2.1.1 - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -16121,10 +15566,10 @@ snapshots: transitivePeerDependencies: - supports-color - finalhandler@1.2.0: + finalhandler@1.3.1: dependencies: debug: 2.6.9 - encodeurl: 1.0.2 + encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 parseurl: 1.3.3 @@ -16161,58 +15606,36 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - flat-cache@3.1.0: + flat-cache@3.2.0: dependencies: - flatted: 3.2.7 - keyv: 4.5.3 + flatted: 3.3.3 + keyv: 4.5.4 rimraf: 3.0.2 flatmap@0.0.3: {} - flatted@3.2.7: {} + flatted@3.3.3: {} - flow-parser@0.218.0: {} + flow-parser@0.263.0: {} - follow-redirects@1.15.6(debug@4.4.0): + follow-redirects@1.15.9(debug@4.4.0): optionalDependencies: debug: 4.4.0(supports-color@8.1.1) - for-each@0.3.4: + for-each@0.3.5: dependencies: is-callable: 1.2.7 for-in@1.0.2: {} - foreground-child@2.0.0: + foreground-child@3.3.1: dependencies: - cross-spawn: 7.0.3 - signal-exit: 3.0.7 - - foreground-child@3.1.1: - dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 signal-exit: 4.1.0 forever-agent@0.6.1: optional: true - fork-ts-checker-webpack-plugin@9.0.2(typescript@5.5.4)(webpack@5.93.0(esbuild@0.19.11)): - dependencies: - '@babel/code-frame': 7.22.13 - chalk: 4.1.2 - chokidar: 3.5.3 - cosmiconfig: 8.3.6(typescript@5.5.4) - deepmerge: 4.3.1 - fs-extra: 10.1.0 - memfs: 3.5.3 - minimatch: 3.1.2 - node-abort-controller: 3.1.1 - schema-utils: 3.3.0 - semver: 7.6.0 - tapable: 2.2.1 - typescript: 5.5.4 - webpack: 5.93.0(esbuild@0.19.11) - form-data@2.3.3: dependencies: asynckit: 0.4.0 @@ -16220,10 +15643,11 @@ snapshots: mime-types: 2.1.35 optional: true - form-data@4.0.0: + form-data@4.0.2: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 mime-types: 2.1.35 forwarded@0.2.0: {} @@ -16232,23 +15656,34 @@ snapshots: dependencies: map-cache: 0.2.2 + framer-motion@12.9.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + motion-dom: 12.9.1 + motion-utils: 12.8.3 + tslib: 2.8.1 + optionalDependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + fresh@0.5.2: {} + fresh@2.0.0: {} + from@0.1.7: {} fs-constants@1.0.0: {} - fs-extra@10.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.0 - fs-extra@11.1.1: dependencies: graceful-fs: 4.2.11 jsonfile: 6.1.0 - universalify: 2.0.0 + universalify: 2.0.1 + + fs-extra@11.3.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 fs-extra@7.0.1: dependencies: @@ -16262,20 +15697,18 @@ snapshots: at-least-node: 1.0.0 graceful-fs: 4.2.11 jsonfile: 6.1.0 - universalify: 2.0.0 + universalify: 2.0.1 fs-minipass@2.1.0: dependencies: minipass: 3.3.6 - fs-monkey@1.0.6: {} - fs.realpath@1.0.0: {} fsevents@1.2.13: dependencies: bindings: 1.5.0 - nan: 2.18.0 + nan: 2.22.2 optional: true fsevents@2.3.3: @@ -16286,7 +15719,7 @@ snapshots: function.prototype.name@1.1.8: dependencies: call-bind: 1.0.8 - call-bound: 1.0.3 + call-bound: 1.0.4 define-properties: 1.2.1 functions-have-names: 1.2.3 hasown: 2.0.2 @@ -16340,7 +15773,7 @@ snapshots: get-nonce@1.0.1: {} - get-npm-tarball-url@2.0.3: {} + get-npm-tarball-url@2.1.0: {} get-own-enumerable-property-symbols@3.0.2: {} @@ -16355,17 +15788,17 @@ snapshots: get-stream@5.2.0: dependencies: - pump: 3.0.0 + pump: 3.0.2 get-stream@6.0.1: {} get-symbol-description@1.1.0: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 es-errors: 1.3.0 get-intrinsic: 1.3.0 - get-tsconfig@4.7.2: + get-tsconfig@4.10.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -16373,7 +15806,7 @@ snapshots: getos@3.2.1: dependencies: - async: 3.2.5 + async: 3.2.6 optional: true getpass@0.1.7: @@ -16381,17 +15814,15 @@ snapshots: assert-plus: 1.0.0 optional: true - giget@1.1.3: + giget@1.2.5: dependencies: - colorette: 2.0.20 - defu: 6.1.2 - https-proxy-agent: 7.0.2 - mri: 1.2.0 - node-fetch-native: 1.4.0 - pathe: 1.1.1 - tar: 6.2.0 - transitivePeerDependencies: - - supports-color + citty: 0.1.6 + consola: 3.4.0 + defu: 6.1.4 + node-fetch-native: 1.6.6 + nypm: 0.5.4 + pathe: 2.0.3 + tar: 6.2.1 github-from-package@0.0.0: {} @@ -16404,10 +15835,10 @@ snapshots: bindings: 1.5.0 bit-twiddle: 1.0.2 glsl-tokenizer: 2.1.5 - nan: 2.18.0 - node-abi: 3.47.0 + nan: 2.22.2 + node-abi: 3.74.0 node-gyp: 9.4.1 - prebuild-install: 7.1.1 + prebuild-install: 7.1.3 transitivePeerDependencies: - bluebird - supports-color @@ -16433,13 +15864,14 @@ snapshots: glob-to-regexp@0.4.1: {} - glob@10.3.3: + glob@10.4.5: dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.0 + foreground-child: 3.3.1 + jackspeak: 3.4.3 minimatch: 9.0.5 - minipass: 7.0.3 - path-scurry: 1.10.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 glob@7.2.3: dependencies: @@ -16472,7 +15904,7 @@ snapshots: globals@11.12.0: {} - globals@13.21.0: + globals@13.24.0: dependencies: type-fest: 0.20.2 @@ -16485,8 +15917,8 @@ snapshots: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 - fast-glob: 3.3.1 - ignore: 5.2.4 + fast-glob: 3.3.3 + ignore: 5.3.2 merge2: 1.4.1 slash: 3.0.0 @@ -16521,7 +15953,7 @@ snapshots: source-map: 0.6.1 wordwrap: 1.0.0 optionalDependencies: - uglify-js: 3.17.4 + uglify-js: 3.19.3 hard-rejection@2.1.0: {} @@ -16575,14 +16007,11 @@ snapshots: is-number: 3.0.0 kind-of: 4.0.0 - has@1.0.3: - dependencies: - function-bind: 1.1.2 + has@1.0.4: {} - hash-base@3.1.0: + hash-base@3.0.5: dependencies: inherits: 2.0.4 - readable-stream: 3.6.2 safe-buffer: 5.2.1 hash.js@1.1.7: @@ -16599,7 +16028,7 @@ snapshots: header-case@2.0.4: dependencies: capital-case: 1.0.4 - tslib: 2.6.2 + tslib: 2.8.1 hmac-drbg@1.0.1: dependencies: @@ -16627,9 +16056,7 @@ snapshots: dependencies: whatwg-encoding: 2.0.0 - html-entities@2.5.2: {} - - html-escaper@2.0.2: {} + html-entities@2.6.0: {} html-tags@3.3.1: {} @@ -16662,13 +16089,13 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 - http-parser-js@0.5.8: {} + http-parser-js@0.5.9: {} http-proxy-agent@5.0.0: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.4.0(supports-color@8.1.1) + debug: 4.4.1 transitivePeerDependencies: - supports-color optional: true @@ -16676,7 +16103,7 @@ snapshots: http-proxy@1.18.1(debug@4.4.0): dependencies: eventemitter3: 4.0.7 - follow-redirects: 1.15.6(debug@4.4.0) + follow-redirects: 1.15.9(debug@4.4.0) requires-port: 1.0.0 transitivePeerDependencies: - debug @@ -16692,7 +16119,7 @@ snapshots: mime: 1.6.0 minimist: 1.2.8 opener: 1.5.2 - portfinder: 1.0.32 + portfinder: 1.0.33 secure-compare: 3.0.1 union: 0.5.0 url-join: 4.0.1 @@ -16704,7 +16131,7 @@ snapshots: dependencies: assert-plus: 1.0.0 jsprim: 2.0.2 - sshpk: 1.17.0 + sshpk: 1.18.0 optional: true https-browserify@1.0.0: {} @@ -16712,25 +16139,18 @@ snapshots: https-proxy-agent@4.0.0: dependencies: agent-base: 5.1.1 - debug: 4.4.0(supports-color@8.1.1) + debug: 4.4.1 transitivePeerDependencies: - supports-color https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.4.0(supports-color@8.1.1) + debug: 4.4.1 transitivePeerDependencies: - supports-color optional: true - https-proxy-agent@7.0.2: - dependencies: - agent-base: 7.1.0 - debug: 4.4.0(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - human-signals@1.1.1: optional: true @@ -16741,7 +16161,9 @@ snapshots: ms: 2.1.3 optional: true - hyphenate-style-name@1.0.4: {} + hyperdyperid@1.2.0: {} + + hyphenate-style-name@1.1.0: {} iconv-lite@0.4.24: dependencies: @@ -16755,19 +16177,19 @@ snapshots: ieee754@1.2.1: {} - ignore@5.2.4: {} + ignore@5.3.2: {} image-size@0.7.5: optional: true immediate@3.0.6: {} - import-fresh@3.3.0: + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - import-meta-resolve@3.0.0: {} + import-meta-resolve@3.1.1: {} imurmurhash@0.1.4: {} @@ -16795,10 +16217,9 @@ snapshots: ini@2.0.0: optional: true - inline-style-prefixer@6.0.4: + inline-style-prefixer@7.0.1: dependencies: css-in-js-utils: 3.1.0 - fast-loops: 1.1.3 internal-slot@1.1.0: dependencies: @@ -16806,11 +16227,11 @@ snapshots: hasown: 2.0.2 side-channel: 1.1.0 - invariant@2.2.4: + ip-address@9.0.5: dependencies: - loose-envify: 1.4.0 - - ip@2.0.0: {} + jsbn: 1.1.0 + sprintf-js: 1.1.3 + optional: true ipaddr.js@1.9.1: {} @@ -16820,15 +16241,15 @@ snapshots: dependencies: hasown: 2.0.2 - is-arguments@1.1.1: + is-arguments@1.2.0: dependencies: - call-bind: 1.0.8 + call-bound: 1.0.4 has-tostringtag: 1.0.2 is-array-buffer@3.0.5: dependencies: call-bind: 1.0.8 - call-bound: 1.0.3 + call-bound: 1.0.4 get-intrinsic: 1.3.0 is-arrayish@0.2.1: {} @@ -16838,7 +16259,7 @@ snapshots: is-async-function@2.1.1: dependencies: async-function: 1.0.0 - call-bound: 1.0.3 + call-bound: 1.0.4 get-proto: 1.0.1 has-tostringtag: 1.0.2 safe-regex-test: 1.1.0 @@ -16853,11 +16274,11 @@ snapshots: is-binary-path@2.1.0: dependencies: - binary-extensions: 2.2.0 + binary-extensions: 2.3.0 - is-boolean-object@1.2.1: + is-boolean-object@1.2.2: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 has-tostringtag: 1.0.2 is-buffer@1.1.6: {} @@ -16870,7 +16291,7 @@ snapshots: is-ci@3.0.1: dependencies: - ci-info: 3.8.0 + ci-info: 3.9.0 optional: true is-core-module@2.16.1: @@ -16883,13 +16304,13 @@ snapshots: is-data-view@1.0.2: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 get-intrinsic: 1.3.0 is-typed-array: 1.1.15 is-date-object@1.1.0: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 has-tostringtag: 1.0.2 is-deflate@1.0.0: {} @@ -16916,7 +16337,7 @@ snapshots: is-finalizationregistry@1.1.1: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 is-fullwidth-code-point@3.0.0: {} @@ -16925,7 +16346,7 @@ snapshots: is-generator-function@1.1.0: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 get-proto: 1.0.1 has-tostringtag: 1.0.2 safe-regex-test: 1.1.0 @@ -16960,9 +16381,11 @@ snapshots: call-bind: 1.0.8 define-properties: 1.2.1 + is-negative-zero@2.0.3: {} + is-number-object@1.1.1: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 has-tostringtag: 1.0.2 is-number@3.0.0: @@ -16989,7 +16412,7 @@ snapshots: is-regex@1.2.1: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 gopd: 1.2.0 has-tostringtag: 1.0.2 hasown: 2.0.2 @@ -17000,18 +16423,18 @@ snapshots: is-shared-array-buffer@1.0.4: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 is-stream@2.0.1: {} is-string@1.1.1: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 has-tostringtag: 1.0.2 is-symbol@1.1.1: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 has-symbols: 1.1.0 safe-regex-test: 1.1.0 @@ -17026,13 +16449,13 @@ snapshots: is-weakmap@2.0.2: {} - is-weakref@1.1.0: + is-weakref@1.1.1: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 is-weakset@2.0.4: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 get-intrinsic: 1.3.0 is-windows@1.0.2: {} @@ -17064,29 +16487,18 @@ snapshots: isstream@0.1.2: optional: true - istanbul-lib-coverage@3.2.0: {} + istanbul-lib-coverage@3.2.2: {} istanbul-lib-instrument@5.2.1: dependencies: - '@babel/core': 7.22.11 - '@babel/parser': 7.22.13 + '@babel/core': 7.26.9 + '@babel/parser': 7.26.9 '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.0 + istanbul-lib-coverage: 3.2.2 semver: 6.3.1 transitivePeerDependencies: - supports-color - istanbul-lib-report@3.0.1: - dependencies: - istanbul-lib-coverage: 3.2.0 - make-dir: 4.0.0 - supports-color: 7.2.0 - - istanbul-reports@3.1.6: - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.1 - iterator.prototype@1.1.5: dependencies: define-data-property: 1.1.4 @@ -17096,15 +16508,15 @@ snapshots: has-symbols: 1.1.0 set-function-name: 2.0.2 - jackspeak@2.3.0: + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 - jake@10.8.7: + jake@10.9.2: dependencies: - async: 3.2.5 + async: 3.2.6 chalk: 4.1.2 filelist: 1.0.4 minimatch: 3.1.2 @@ -17112,15 +16524,15 @@ snapshots: jest-haste-map@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.7 - '@types/node': 22.8.1 + '@types/graceful-fs': 4.1.9 + '@types/node': 22.13.9 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 jest-regex-util: 29.6.3 jest-util: 29.7.0 jest-worker: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.8 walker: 1.0.8 optionalDependencies: fsevents: 2.3.3 @@ -17130,42 +16542,34 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.8.1 + '@types/node': 22.13.9 chalk: 4.1.2 - ci-info: 3.8.0 + ci-info: 3.9.0 graceful-fs: 4.2.11 picomatch: 2.3.1 - jest-worker@26.6.2: - dependencies: - '@types/node': 22.8.1 - merge-stream: 2.0.0 - supports-color: 7.2.0 - - jest-worker@27.5.1: - dependencies: - '@types/node': 22.8.1 - merge-stream: 2.0.0 - supports-color: 8.1.1 - jest-worker@29.7.0: dependencies: - '@types/node': 22.8.1 + '@types/node': 22.13.9 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jimp@0.10.3: + jimp@0.10.3(debug@4.4.0): dependencies: - '@babel/runtime': 7.24.5 - '@jimp/custom': 0.10.3 - '@jimp/plugins': 0.10.3(@jimp/custom@0.10.3) - '@jimp/types': 0.10.3(@jimp/custom@0.10.3) - core-js: 3.37.1 + '@babel/runtime': 7.26.9 + '@jimp/custom': 0.10.3(debug@4.4.0) + '@jimp/plugins': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0))(debug@4.4.0) + '@jimp/types': 0.10.3(@jimp/custom@0.10.3(debug@4.4.0)) + core-js: 3.41.0 regenerator-runtime: 0.13.11 + transitivePeerDependencies: + - debug optional: true - joi@17.13.1: + jiti@2.4.2: {} + + joi@17.13.3: dependencies: '@hapi/hoek': 9.3.0 '@hapi/topo': 5.1.0 @@ -17173,8 +16577,6 @@ snapshots: '@sideway/formula': 3.0.1 '@sideway/pinpoint': 2.0.0 - jose@4.15.5: {} - jpeg-js@0.3.7: optional: true @@ -17197,37 +16599,42 @@ snapshots: jsbn@0.1.1: optional: true - jscodeshift@0.14.0(@babel/preset-env@7.22.10(@babel/core@7.22.11)): + jsbn@1.1.0: + optional: true + + jscodeshift@0.15.2(@babel/preset-env@7.26.9(@babel/core@7.26.9)): dependencies: - '@babel/core': 7.22.11 - '@babel/parser': 7.22.13 - '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.11) - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.22.11) - '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.22.11) - '@babel/plugin-transform-modules-commonjs': 7.23.0(@babel/core@7.22.11) - '@babel/preset-env': 7.22.10(@babel/core@7.22.11) - '@babel/preset-flow': 7.22.15(@babel/core@7.22.11) - '@babel/preset-typescript': 7.23.0(@babel/core@7.22.11) - '@babel/register': 7.22.15(@babel/core@7.22.11) - babel-core: 7.0.0-bridge.0(@babel/core@7.22.11) + '@babel/core': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-modules-commonjs': 7.26.3(@babel/core@7.26.9) + '@babel/plugin-transform-nullish-coalescing-operator': 7.26.6(@babel/core@7.26.9) + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.9) + '@babel/preset-flow': 7.25.9(@babel/core@7.26.9) + '@babel/preset-typescript': 7.26.0(@babel/core@7.26.9) + '@babel/register': 7.25.9(@babel/core@7.26.9) + babel-core: 7.0.0-bridge.0(@babel/core@7.26.9) chalk: 4.1.2 - flow-parser: 0.218.0 + flow-parser: 0.263.0 graceful-fs: 4.2.11 - micromatch: 4.0.5 + micromatch: 4.0.8 neo-async: 2.6.2 node-dir: 0.1.17 - recast: 0.21.5 + recast: 0.23.11 temp: 0.8.4 write-file-atomic: 2.4.3 + optionalDependencies: + '@babel/preset-env': 7.26.9(@babel/core@7.26.9) transitivePeerDependencies: - supports-color jsesc@0.5.0: {} - jsesc@2.5.2: {} - jsesc@3.0.2: {} + jsesc@3.1.0: {} + json-buffer@3.0.1: {} json-parse-better-errors@1.0.2: {} @@ -17250,8 +16657,6 @@ snapshots: json5@2.2.3: {} - jsonc-parser@3.2.0: {} - jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.11 @@ -17259,7 +16664,7 @@ snapshots: jsonfile@6.1.0: dependencies: - universalify: 2.0.0 + universalify: 2.0.1 optionalDependencies: graceful-fs: 4.2.11 @@ -17276,7 +16681,7 @@ snapshots: lodash.isstring: 4.0.1 lodash.once: 4.1.1 ms: 2.1.3 - semver: 7.6.0 + semver: 7.7.1 jsprim@2.0.2: dependencies: @@ -17288,7 +16693,7 @@ snapshots: jsx-ast-utils@3.3.5: dependencies: - array-includes: 3.1.8 + array-includes: 3.1.9 array.prototype.flat: 1.3.3 object.assign: 4.1.7 object.values: 1.2.1 @@ -17311,7 +16716,7 @@ snapshots: jwa: 1.4.1 safe-buffer: 5.2.1 - keyv@4.5.3: + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -17333,7 +16738,7 @@ snapshots: lazy-universal-dotenv@4.0.0: dependencies: app-root-dir: 1.0.2 - dotenv: 16.3.1 + dotenv: 16.4.7 dotenv-expand: 10.0.0 leven@3.1.0: {} @@ -17363,8 +16768,8 @@ snapshots: colorette: 2.0.20 log-update: 4.0.0 p-map: 4.0.0 - rfdc: 1.3.0 - rxjs: 7.8.1 + rfdc: 1.4.1 + rxjs: 7.8.2 through: 2.3.8 wrap-ansi: 7.0.0 optionalDependencies: @@ -17384,21 +16789,23 @@ snapshots: object-assign: 4.1.1 opn: 6.0.0 proxy-middleware: 0.15.0 - send: 1.1.0 + send: 1.2.0 serve-index: 1.9.1 transitivePeerDependencies: - supports-color - load-bmfont@1.4.1: + load-bmfont@1.4.2(debug@4.4.0): dependencies: buffer-equal: 0.0.1 mime: 1.6.0 parse-bmfont-ascii: 1.0.6 parse-bmfont-binary: 1.0.6 - parse-bmfont-xml: 1.1.4 - phin: 2.9.3 + parse-bmfont-xml: 1.1.6 + phin: 3.7.1(debug@4.4.0) xhr: 2.6.0 xtend: 4.0.2 + transitivePeerDependencies: + - debug optional: true load-json-file@4.0.0: @@ -17408,8 +16815,6 @@ snapshots: pify: 3.0.0 strip-bom: 3.0.0 - loader-runner@4.3.0: {} - local-pkg@0.4.3: {} locate-path@3.0.0: @@ -17468,7 +16873,7 @@ snapshots: wrap-ansi: 6.2.0 optional: true - long@5.2.3: {} + long@5.3.1: {} longest-streak@3.1.0: {} @@ -17476,17 +16881,15 @@ snapshots: dependencies: js-tokens: 4.0.0 - loupe@2.3.6: + loupe@2.3.7: dependencies: get-func-name: 2.0.2 - loupe@3.1.3: {} - lower-case@2.0.2: dependencies: - tslib: 2.6.2 + tslib: 2.8.1 - lru-cache@10.0.1: {} + lru-cache@10.4.3: {} lru-cache@5.1.1: dependencies: @@ -17507,16 +16910,12 @@ snapshots: magic-string@0.27.0: dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 magic-string@0.30.17: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 - magic-string@0.30.4: - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - make-dir@2.1.0: dependencies: pify: 4.0.1 @@ -17526,13 +16925,9 @@ snapshots: dependencies: semver: 6.3.1 - make-dir@4.0.0: - dependencies: - semver: 7.6.0 - make-fetch-happen@10.2.1: dependencies: - agentkeepalive: 4.5.0 + agentkeepalive: 4.6.0 cacache: 16.1.3 http-cache-semantics: 4.1.1 http-proxy-agent: 5.0.0 @@ -17544,7 +16939,7 @@ snapshots: minipass-fetch: 2.1.2 minipass-flush: 1.0.5 minipass-pipeline: 1.2.4 - negotiator: 0.6.3 + negotiator: 0.6.4 promise-retry: 2.0.1 socks-proxy-agent: 7.0.0 ssri: 9.0.1 @@ -17571,7 +16966,7 @@ snapshots: dependencies: object-visit: 1.0.1 - markdown-it@14.0.0: + markdown-it@14.1.0: dependencies: argparse: 2.0.1 entities: 4.5.0 @@ -17580,27 +16975,29 @@ snapshots: punycode.js: 2.3.1 uc.micro: 2.1.0 - markdown-to-jsx@7.3.2(react@18.2.0): + markdown-to-jsx@7.7.4(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 math-intrinsics@1.1.0: {} - maxrects-packer@2.7.3: {} - - mc-assets@0.2.45: + mc-assets@0.2.62: dependencies: - maxrects-packer: 2.7.3 - zod: 3.24.1 + maxrects-packer: '@zardoy/maxrects-packer@2.7.4' + zod: 3.24.2 - mcraft-fun-mineflayer@0.1.14(encoding@0.1.13)(mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/06e3050ddf4d9aa655fea6e2bed182937a81705d(encoding@0.1.13)): + mc-bridge@0.1.3(minecraft-data@3.98.0): + dependencies: + minecraft-data: 3.98.0 + + mcraft-fun-mineflayer@0.1.23(encoding@0.1.13)(mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13)): dependencies: '@zardoy/flying-squid': 0.0.49(encoding@0.1.13) exit-hook: 2.2.1 - minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/3bd4dc1b2002cd7badfa5b9cf8dda35cd6cc9ac1(patch_hash=dkeyukcqlupmk563gwxsmjr3yu)(encoding@0.1.13) - mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/06e3050ddf4d9aa655fea6e2bed182937a81705d(encoding@0.1.13) - prismarine-item: 1.16.0 - ws: 8.18.0 + minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13) + mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13) + prismarine-item: 1.17.0 + ws: 8.18.1 transitivePeerDependencies: - bufferutil - encoding @@ -17611,7 +17008,7 @@ snapshots: md5.js@1.3.5: dependencies: - hash-base: 3.1.0 + hash-base: 3.0.5 inherits: 2.0.4 safe-buffer: 5.2.1 @@ -17625,36 +17022,37 @@ snapshots: dependencies: unist-util-visit: 2.0.3 - mdast-util-from-markdown@2.0.0: + mdast-util-from-markdown@2.0.2: dependencies: - '@types/mdast': 4.0.3 - '@types/unist': 3.0.2 - decode-named-character-reference: 1.0.2 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.1.0 devlop: 1.1.0 mdast-util-to-string: 4.0.0 - micromark: 4.0.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-decode-string: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark: 4.0.2 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 unist-util-stringify-position: 4.0.0 transitivePeerDependencies: - supports-color mdast-util-phrasing@4.1.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 unist-util-is: 6.0.0 - mdast-util-to-markdown@2.1.0: + mdast-util-to-markdown@2.1.2: dependencies: - '@types/mdast': 4.0.3 - '@types/unist': 3.0.2 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 longest-streak: 3.1.0 mdast-util-phrasing: 4.1.0 mdast-util-to-string: 4.0.0 - micromark-util-decode-string: 2.0.0 + micromark-util-classify-character: 2.0.1 + micromark-util-decode-string: 2.0.1 unist-util-visit: 5.0.0 zwitch: 2.0.4 @@ -17662,7 +17060,7 @@ snapshots: mdast-util-to-string@4.0.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 mdn-data@2.0.14: {} @@ -17670,9 +17068,12 @@ snapshots: media-typer@0.3.0: {} - memfs@3.5.3: + memfs@4.17.0: dependencies: - fs-monkey: 1.0.6 + '@jsonjoy.com/json-pack': 1.2.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.5.0(tslib@2.8.1) + tree-dump: 1.0.2(tslib@2.8.1) + tslib: 2.8.1 memoize-one@6.0.0: {} @@ -17684,7 +17085,7 @@ snapshots: meow@10.1.5: dependencies: - '@types/minimist': 1.2.3 + '@types/minimist': 1.2.5 camelcase-keys: 7.0.2 decamelize: 5.0.1 decamelize-keys: 1.1.1 @@ -17697,7 +17098,7 @@ snapshots: type-fest: 1.4.0 yargs-parser: 20.2.9 - merge-descriptors@1.0.1: {} + merge-descriptors@1.0.3: {} merge-stream@2.0.0: {} @@ -17710,136 +17111,136 @@ snapshots: methods@1.1.2: {} - micromark-core-commonmark@2.0.0: + micromark-core-commonmark@2.0.3: dependencies: - decode-named-character-reference: 1.0.2 + decode-named-character-reference: 1.1.0 devlop: 1.1.0 - micromark-factory-destination: 2.0.0 - micromark-factory-label: 2.0.0 - micromark-factory-space: 2.0.0 - micromark-factory-title: 2.0.0 - micromark-factory-whitespace: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-classify-character: 2.0.0 - micromark-util-html-tag-name: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-resolve-all: 2.0.0 - micromark-util-subtokenize: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-factory-destination@2.0.0: + micromark-factory-destination@2.0.1: dependencies: - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-factory-label@2.0.0: + micromark-factory-label@2.0.1: dependencies: devlop: 1.1.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-factory-space@2.0.0: + micromark-factory-space@2.0.1: dependencies: - micromark-util-character: 2.1.0 - micromark-util-types: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.2 - micromark-factory-title@2.0.0: + micromark-factory-title@2.0.1: dependencies: - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-factory-whitespace@2.0.0: + micromark-factory-whitespace@2.0.1: dependencies: - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-util-character@2.1.0: + micromark-util-character@2.1.1: dependencies: - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-util-chunked@2.0.0: + micromark-util-chunked@2.0.1: dependencies: - micromark-util-symbol: 2.0.0 + micromark-util-symbol: 2.0.1 - micromark-util-classify-character@2.0.0: + micromark-util-classify-character@2.0.1: dependencies: - micromark-util-character: 2.1.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-util-combine-extensions@2.0.0: + micromark-util-combine-extensions@2.0.1: dependencies: - micromark-util-chunked: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.2 - micromark-util-decode-numeric-character-reference@2.0.1: + micromark-util-decode-numeric-character-reference@2.0.2: dependencies: - micromark-util-symbol: 2.0.0 + micromark-util-symbol: 2.0.1 - micromark-util-decode-string@2.0.0: + micromark-util-decode-string@2.0.1: dependencies: - decode-named-character-reference: 1.0.2 - micromark-util-character: 2.1.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-symbol: 2.0.0 + decode-named-character-reference: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 - micromark-util-encode@2.0.0: {} + micromark-util-encode@2.0.1: {} - micromark-util-html-tag-name@2.0.0: {} + micromark-util-html-tag-name@2.0.1: {} - micromark-util-normalize-identifier@2.0.0: + micromark-util-normalize-identifier@2.0.1: dependencies: - micromark-util-symbol: 2.0.0 + micromark-util-symbol: 2.0.1 - micromark-util-resolve-all@2.0.0: + micromark-util-resolve-all@2.0.1: dependencies: - micromark-util-types: 2.0.0 + micromark-util-types: 2.0.2 - micromark-util-sanitize-uri@2.0.0: + micromark-util-sanitize-uri@2.0.1: dependencies: - micromark-util-character: 2.1.0 - micromark-util-encode: 2.0.0 - micromark-util-symbol: 2.0.0 + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 - micromark-util-subtokenize@2.0.0: + micromark-util-subtokenize@2.1.0: dependencies: devlop: 1.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 - micromark-util-symbol@2.0.0: {} + micromark-util-symbol@2.0.1: {} - micromark-util-types@2.0.0: {} + micromark-util-types@2.0.2: {} - micromark@4.0.0: + micromark@4.0.2: dependencies: '@types/debug': 4.1.12 - debug: 4.4.0(supports-color@8.1.1) - decode-named-character-reference: 1.0.2 + debug: 4.4.1 + decode-named-character-reference: 1.1.0 devlop: 1.1.0 - micromark-core-commonmark: 2.0.0 - micromark-factory-space: 2.0.0 - micromark-util-character: 2.1.0 - micromark-util-chunked: 2.0.0 - micromark-util-combine-extensions: 2.0.0 - micromark-util-decode-numeric-character-reference: 2.0.1 - micromark-util-encode: 2.0.0 - micromark-util-normalize-identifier: 2.0.0 - micromark-util-resolve-all: 2.0.0 - micromark-util-sanitize-uri: 2.0.0 - micromark-util-subtokenize: 2.0.0 - micromark-util-symbol: 2.0.0 - micromark-util-types: 2.0.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 transitivePeerDependencies: - supports-color @@ -17861,22 +17262,28 @@ snapshots: transitivePeerDependencies: - supports-color - micromatch@4.0.5: + micromatch@4.0.8: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 miller-rabin@4.0.1: dependencies: - bn.js: 4.12.0 + bn.js: 4.12.1 brorand: 1.1.0 mime-db@1.52.0: {} + mime-db@1.54.0: {} + mime-types@2.1.35: dependencies: mime-db: 1.52.0 + mime-types@3.0.1: + dependencies: + mime-db: 1.54.0 + mime@1.6.0: {} mime@2.6.0: {} @@ -17895,71 +17302,45 @@ snapshots: min-indent@1.0.1: {} - minecraft-data@3.83.1: {} + minecraft-data@3.98.0: {} minecraft-folder-path@1.2.0: {} - minecraft-inventory-gui@https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/75e940a4cd50d89e0ba03db3733d5d704917a3c8(@types/react@18.2.20)(react@18.2.0): + minecraft-inventory-gui@https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/89c33d396f3fde4804c71f4be3c203ade1833b41(@types/react@18.3.18)(react@18.3.1): dependencies: - valtio: 1.11.2(@types/react@18.2.20)(react@18.2.0) + valtio: 1.13.2(@types/react@18.3.18)(react@18.3.1) transitivePeerDependencies: - '@types/react' - react - minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/3bd4dc1b2002cd7badfa5b9cf8dda35cd6cc9ac1(patch_hash=dkeyukcqlupmk563gwxsmjr3yu)(encoding@0.1.13): + minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13): dependencies: '@types/node-rsa': 1.1.4 - '@types/readable-stream': 4.0.12 + '@types/readable-stream': 4.0.18 aes-js: 3.1.2 buffer-equal: 1.0.1 debug: 4.4.0(supports-color@8.1.1) endian-toggle: 0.0.0 - lodash.get: 4.4.2 lodash.merge: 4.6.2 - minecraft-data: 3.83.1 + minecraft-data: 3.98.0 minecraft-folder-path: 1.2.0 node-fetch: 2.7.0(encoding@0.1.13) node-rsa: 0.4.2 - prismarine-auth: 2.4.2(encoding@0.1.13) - prismarine-chat: 1.10.1 - prismarine-nbt: 2.5.0 + prismarine-auth: 2.7.0 + prismarine-chat: 1.11.0 + prismarine-nbt: 2.7.0 prismarine-realms: 1.3.2(encoding@0.1.13) protodef: 1.18.0 - readable-stream: 4.5.2 + readable-stream: 4.7.0 uuid-1345: 1.0.2 yggdrasil: 1.7.0(encoding@0.1.13) transitivePeerDependencies: - encoding - supports-color - minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/5ec3dd4b367fcc039fbcb3edd214fe3cf8178a6d(patch_hash=dkeyukcqlupmk563gwxsmjr3yu)(encoding@0.1.13): - dependencies: - '@types/node-rsa': 1.1.4 - '@types/readable-stream': 4.0.12 - aes-js: 3.1.2 - buffer-equal: 1.0.1 - debug: 4.4.0(supports-color@8.1.1) - endian-toggle: 0.0.0 - lodash.get: 4.4.2 - lodash.merge: 4.6.2 - minecraft-data: 3.83.1 - minecraft-folder-path: 1.2.0 - node-fetch: 2.7.0(encoding@0.1.13) - node-rsa: 0.4.2 - prismarine-auth: 2.4.2(encoding@0.1.13) - prismarine-chat: 1.10.1 - prismarine-nbt: 2.5.0 - prismarine-realms: 1.3.2(encoding@0.1.13) - protodef: 1.18.0 - readable-stream: 4.5.2 - uuid-1345: 1.0.2 - yggdrasil: 1.7.0(encoding@0.1.13) - transitivePeerDependencies: - - encoding - - supports-color - - minecraft-wrap@1.5.1(encoding@0.1.13): + minecraft-wrap@1.6.0(encoding@0.1.13): dependencies: + adm-zip: 0.5.16 debug: 4.4.0(supports-color@8.1.1) es6-promisify: 5.0.0 extract-zip: 2.0.1(supports-color@8.1.1) @@ -17976,91 +17357,41 @@ snapshots: - encoding - supports-color - minecrafthawkeye@1.3.6: + minecrafthawkeye@1.3.9: dependencies: detect-collisions: 7.0.5 + uuid: 9.0.1 vec3: 0.1.10 - mineflayer-item-map-downloader@https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824(patch_hash=bck55yjvd4wrgz46x7o4vfur5q)(encoding@0.1.13): + mineflayer-item-map-downloader@https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824(patch_hash=a731ebbace2d8790c973ab3a5ba33494a6e9658533a9710dd8ba36f86db061ad)(encoding@0.1.13): dependencies: - mineflayer: 4.25.0(encoding@0.1.13) + mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13) sharp: 0.30.7 transitivePeerDependencies: - encoding - supports-color - mineflayer-mouse@0.1.7(@types/debug@4.1.12)(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1): + mineflayer-mouse@0.1.21: dependencies: change-case: 5.4.4 - debug: 4.4.0(supports-color@8.1.1) - prismarine-item: 1.16.0 + debug: 4.4.1 + prismarine-item: 1.17.0 prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c - vitest: 3.0.7(@types/debug@4.1.12)(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1) transitivePeerDependencies: - - '@edge-runtime/vm' - - '@types/debug' - - '@types/node' - - '@vitest/browser' - - '@vitest/ui' - - happy-dom - - jiti - - jsdom - - less - - lightningcss - - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - mineflayer-pathfinder@2.4.4: - dependencies: - minecraft-data: 3.83.1 - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) - prismarine-entity: 2.3.1 - prismarine-item: 1.16.0 - prismarine-nbt: 2.5.0 - prismarine-physics: https://codeload.github.com/zardoy/prismarine-physics/tar.gz/353e25b800149393f40539ec381218be44cbb03b - vec3: 0.1.10 - - mineflayer@4.25.0(encoding@0.1.13): - dependencies: - minecraft-data: 3.83.1 - minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/5ec3dd4b367fcc039fbcb3edd214fe3cf8178a6d(patch_hash=dkeyukcqlupmk563gwxsmjr3yu)(encoding@0.1.13) - prismarine-biome: 1.3.0(minecraft-data@3.83.1)(prismarine-registry@1.11.0) - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) - prismarine-chat: 1.10.1 - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/e68e9a423b5b1907535878fb636f12c28a1a9374(minecraft-data@3.83.1) - prismarine-entity: 2.3.1 - prismarine-item: 1.16.0 - prismarine-nbt: 2.5.0 - prismarine-physics: https://codeload.github.com/zardoy/prismarine-physics/tar.gz/353e25b800149393f40539ec381218be44cbb03b - prismarine-recipe: 1.3.1(prismarine-registry@1.11.0) - prismarine-registry: 1.11.0 - prismarine-windows: 2.9.0 - prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c - protodef: 1.18.0 - typed-emitter: 1.4.0 - vec3: 0.1.10 - transitivePeerDependencies: - - encoding - supports-color - mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/06e3050ddf4d9aa655fea6e2bed182937a81705d(encoding@0.1.13): + mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13): dependencies: - minecraft-data: 3.83.1 - minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/5ec3dd4b367fcc039fbcb3edd214fe3cf8178a6d(patch_hash=dkeyukcqlupmk563gwxsmjr3yu)(encoding@0.1.13) - prismarine-biome: 1.3.0(minecraft-data@3.83.1)(prismarine-registry@1.11.0) - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) - prismarine-chat: 1.10.1 - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/e68e9a423b5b1907535878fb636f12c28a1a9374(minecraft-data@3.83.1) - prismarine-entity: 2.3.1 - prismarine-item: 1.16.0 - prismarine-nbt: 2.5.0 + '@nxg-org/mineflayer-physics-util': 1.8.10 + minecraft-data: 3.98.0 + minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13) + prismarine-biome: 1.3.0(minecraft-data@3.98.0)(prismarine-registry@1.11.0) + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9 + prismarine-chat: 1.11.0 + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0) + prismarine-entity: 2.5.0 + prismarine-item: 1.17.0 + prismarine-nbt: 2.7.0 prismarine-physics: https://codeload.github.com/zardoy/prismarine-physics/tar.gz/353e25b800149393f40539ec381218be44cbb03b prismarine-recipe: 1.3.1(prismarine-registry@1.11.0) prismarine-registry: 1.11.0 @@ -18085,6 +17416,10 @@ snapshots: dependencies: brace-expansion: 2.0.1 + minimatch@9.0.3: + dependencies: + brace-expansion: 2.0.1 + minimatch@9.0.5: dependencies: brace-expansion: 2.0.1 @@ -18132,7 +17467,7 @@ snapshots: minipass@5.0.0: {} - minipass@7.0.3: {} + minipass@7.1.2: {} minizlib@2.1.2: dependencies: @@ -18157,17 +17492,19 @@ snapshots: mkdirp@2.1.6: {} - mlly@1.4.2: + mlly@1.7.4: dependencies: - acorn: 8.12.1 - pathe: 1.1.1 - pkg-types: 1.0.3 - ufo: 1.3.1 + acorn: 8.14.1 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.5.4 mojangson@2.0.4: dependencies: nearley: 2.20.1 + monaco-editor@0.52.2: {} + moo@0.5.2: {} morgan@1.10.0: @@ -18180,7 +17517,11 @@ snapshots: transitivePeerDependencies: - supports-color - mri@1.2.0: {} + motion-dom@12.9.1: + dependencies: + motion-utils: 12.8.3 + + motion-utils@12.8.3: {} ms@2.0.0: {} @@ -18192,25 +17533,23 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nan@2.18.0: + nan@2.22.2: optional: true - nano-css@5.3.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + nano-css@5.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 css-tree: 1.1.3 - csstype: 3.1.2 + csstype: 3.1.3 fastest-stable-stringify: 2.0.2 - inline-style-prefixer: 6.0.4 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + inline-style-prefixer: 7.0.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) rtl-css-js: 1.16.1 - sourcemap-codec: 1.4.8 stacktrace-js: 2.0.2 - stylis: 4.2.0 + stylis: 4.3.6 - nanoid@3.3.7: {} - - nanoid@3.3.8: {} + nanoid@3.3.9: {} nanomatch@1.2.13: dependencies: @@ -18228,7 +17567,7 @@ snapshots: transitivePeerDependencies: - supports-color - napi-build-utils@1.0.2: {} + napi-build-utils@2.0.0: {} natural-compare-lite@1.4.0: {} @@ -18243,13 +17582,15 @@ snapshots: negotiator@0.6.3: {} + negotiator@0.6.4: {} + neo-async@2.6.2: {} - net-browserify@https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/624cc67c16f5e8b23b772e7eaabae16ba84b8590: + net-browserify@https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/e754999ffdea67853bc9b10553b5e9908b40f618: dependencies: - body-parser: 1.20.2 - express: 4.18.2 - express-ws: 4.0.0(express@4.18.2) + body-parser: 1.20.3 + express: 4.21.2 + express-ws: 4.0.0(express@4.21.2) transitivePeerDependencies: - bufferutil - supports-color @@ -18260,13 +17601,11 @@ snapshots: no-case@3.0.4: dependencies: lower-case: 2.0.2 - tslib: 2.6.2 + tslib: 2.8.1 - node-abi@3.47.0: + node-abi@3.74.0: dependencies: - semver: 7.6.0 - - node-abort-controller@3.1.1: {} + semver: 7.7.1 node-addon-api@5.1.0: {} @@ -18284,7 +17623,7 @@ snapshots: dependencies: minimatch: 3.1.2 - node-fetch-native@1.4.0: {} + node-fetch-native@1.6.6: {} node-fetch@2.7.0(encoding@0.1.13): dependencies: @@ -18292,23 +17631,18 @@ snapshots: optionalDependencies: encoding: 0.1.13 - node-gyp-build-optional-packages@5.1.1: - dependencies: - detect-libc: 2.0.2 - optional: true - node-gyp@9.4.1: dependencies: env-paths: 2.2.1 - exponential-backoff: 3.1.1 + exponential-backoff: 3.1.2 glob: 7.2.3 graceful-fs: 4.2.11 make-fetch-happen: 10.2.1 nopt: 6.0.0 npmlog: 6.0.2 rimraf: 3.0.2 - semver: 7.6.0 - tar: 6.2.0 + semver: 7.7.1 + tar: 6.2.1 which: 2.0.2 transitivePeerDependencies: - bluebird @@ -18317,14 +17651,14 @@ snapshots: node-gzip@1.1.2: {} - node-html-parser@6.1.10: + node-html-parser@6.1.13: dependencies: css-select: 5.1.0 he: 1.2.0 node-int64@0.4.0: {} - node-releases@2.0.18: {} + node-releases@2.0.19: {} node-rsa@0.4.2: dependencies: @@ -18352,7 +17686,7 @@ snapshots: normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 - resolve: 1.22.4 + resolve: 1.22.10 semver: 5.7.2 validate-npm-package-license: 3.0.4 @@ -18360,7 +17694,7 @@ snapshots: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.16.1 - semver: 7.6.0 + semver: 7.7.1 validate-npm-package-license: 3.0.4 normalize-path@2.1.1: @@ -18373,13 +17707,13 @@ snapshots: dependencies: ansi-styles: 3.2.1 chalk: 2.4.2 - cross-spawn: 6.0.5 + cross-spawn: 6.0.6 memorystream: 0.3.1 minimatch: 3.1.2 pidtree: 0.3.1 read-pkg: 3.0.0 - shell-quote: 1.8.1 - string.prototype.padend: 3.1.4 + shell-quote: 1.8.2 + string.prototype.padend: 3.1.6 npm-run-path@4.0.1: dependencies: @@ -18405,6 +17739,15 @@ snapshots: dependencies: boolbase: 1.0.0 + nypm@0.5.4: + dependencies: + citty: 0.1.6 + consola: 3.4.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + tinyexec: 0.3.2 + ufo: 1.5.4 + object-assign@4.1.1: {} object-copy@0.1.0: @@ -18413,9 +17756,9 @@ snapshots: define-property: 0.2.5 kind-of: 3.2.2 - object-inspect@1.13.3: {} + object-inspect@1.13.4: {} - object-is@1.1.5: + object-is@1.1.6: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 @@ -18429,15 +17772,16 @@ snapshots: object.assign@4.1.7: dependencies: call-bind: 1.0.8 - call-bound: 1.0.3 + call-bound: 1.0.4 define-properties: 1.2.1 es-object-atoms: 1.1.1 has-symbols: 1.1.0 object-keys: 1.1.1 - object.entries@1.1.8: + object.entries@1.1.9: dependencies: call-bind: 1.0.8 + call-bound: 1.0.4 define-properties: 1.2.1 es-object-atoms: 1.1.1 @@ -18445,13 +17789,7 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.9 - es-object-atoms: 1.1.1 - - object.hasown@1.1.4: - dependencies: - define-properties: 1.2.1 - es-abstract: 1.23.9 + es-abstract: 1.24.0 es-object-atoms: 1.1.1 object.pick@1.3.0: @@ -18461,7 +17799,7 @@ snapshots: object.values@1.2.1: dependencies: call-bind: 1.0.8 - call-bound: 1.0.3 + call-bound: 1.0.4 define-properties: 1.2.1 es-object-atoms: 1.1.1 @@ -18498,21 +17836,21 @@ snapshots: dependencies: is-wsl: 1.1.0 - optionator@0.9.3: + optionator@0.9.4: dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 deep-is: 0.1.4 fast-levenshtein: 2.0.6 levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 + word-wrap: 1.2.5 ora@5.4.1: dependencies: bl: 4.1.0 chalk: 4.1.2 cli-cursor: 3.1.0 - cli-spinners: 2.9.1 + cli-spinners: 2.9.2 is-interactive: 1.0.0 is-unicode-supported: 0.1.0 log-symbols: 4.1.0 @@ -18542,7 +17880,7 @@ snapshots: p-limit@4.0.0: dependencies: - yocto-queue: 1.0.0 + yocto-queue: 1.2.0 p-locate@3.0.0: dependencies: @@ -18562,6 +17900,8 @@ snapshots: p-try@2.2.0: {} + package-json-from-dist@1.0.1: {} + pako@0.2.9: {} pako@1.0.11: {} @@ -18571,17 +17911,18 @@ snapshots: param-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.8.1 parent-module@1.0.1: dependencies: callsites: 3.1.0 - parse-asn1@5.1.6: + parse-asn1@5.1.7: dependencies: - asn1.js: 5.4.1 + asn1.js: 4.10.1 browserify-aes: 1.2.0 evp_bytestokey: 1.0.3 + hash-base: 3.0.5 pbkdf2: 3.1.2 safe-buffer: 5.2.1 @@ -18591,10 +17932,10 @@ snapshots: parse-bmfont-binary@1.0.6: optional: true - parse-bmfont-xml@1.1.4: + parse-bmfont-xml@1.1.6: dependencies: xml-parse-from-string: 1.0.1 - xml2js: 0.4.23 + xml2js: 0.5.0 optional: true parse-headers@2.0.5: @@ -18607,7 +17948,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.22.13 + '@babel/code-frame': 7.26.2 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -18623,7 +17964,7 @@ snapshots: pascal-case@3.1.2: dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.8.1 pascalcase@0.1.1: {} @@ -18632,7 +17973,7 @@ snapshots: path-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.8.1 path-dirname@1.0.2: {} @@ -18655,12 +17996,12 @@ snapshots: path-parse@1.0.7: {} - path-scurry@1.10.1: + path-scurry@1.11.1: dependencies: - lru-cache: 10.0.1 - minipass: 7.0.3 + lru-cache: 10.4.3 + minipass: 7.1.2 - path-to-regexp@0.1.7: {} + path-to-regexp@0.1.12: {} path-type@3.0.0: dependencies: @@ -18668,14 +18009,12 @@ snapshots: path-type@4.0.0: {} - pathe@1.1.1: {} + pathe@1.1.2: {} pathe@2.0.3: {} pathval@1.1.1: {} - pathval@2.0.0: {} - pause-stream@0.0.11: dependencies: through: 2.3.8 @@ -18694,15 +18033,14 @@ snapshots: duplexify: 3.7.1 through2: 2.0.5 - peerjs-js-binarypack@2.0.0: {} + peerjs-js-binarypack@2.1.0: {} - peerjs@1.5.0: + peerjs@1.5.4: dependencies: '@msgpack/msgpack': 2.8.0 - cbor-x: 1.5.4 eventemitter3: 4.0.7 - peerjs-js-binarypack: 2.0.0 - webrtc-adapter: 8.2.3 + peerjs-js-binarypack: 2.1.0 + webrtc-adapter: 9.0.1 pend@1.2.0: {} @@ -18712,6 +18050,13 @@ snapshots: phin@2.9.3: optional: true + phin@3.7.1(debug@4.4.0): + dependencies: + centra: 2.7.0(debug@4.4.0) + transitivePeerDependencies: + - debug + optional: true + picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -18729,7 +18074,7 @@ snapshots: pirates@4.0.6: {} - pixelarticons@1.8.1(patch_hash=cclg2qo6d4yjs4evj64nr2mbwa): {} + pixelarticons@1.8.1(patch_hash=533230072bc402f425c86abd3d0356fe087b14cab2a254d93f419b083f2d8dfa): {} pixelmatch@4.0.2: dependencies: @@ -18748,24 +18093,24 @@ snapshots: dependencies: find-up: 5.0.0 - pkg-types@1.0.3: + pkg-types@1.3.1: dependencies: - jsonc-parser: 3.2.0 - mlly: 1.4.2 - pathe: 1.1.1 + confbox: 0.1.8 + mlly: 1.7.4 + pathe: 2.0.3 pluralize@8.0.0: {} pngjs@3.4.0: optional: true - polished@4.2.2: + polished@4.3.1: dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.26.9 poly-decomp@0.3.0: {} - portfinder@1.0.32: + portfinder@1.0.33: dependencies: async: 2.6.4 debug: 3.2.7(supports-color@8.1.1) @@ -18775,35 +18120,29 @@ snapshots: posix-character-classes@0.1.1: {} - possible-typed-array-names@1.0.0: {} - - postcss@8.4.47: - dependencies: - nanoid: 3.3.7 - picocolors: 1.1.1 - source-map-js: 1.2.1 + possible-typed-array-names@1.1.0: {} postcss@8.5.3: dependencies: - nanoid: 3.3.8 + nanoid: 3.3.9 picocolors: 1.1.1 source-map-js: 1.2.1 potpack@1.0.2: {} - prebuild-install@7.1.1: + prebuild-install@7.1.3: dependencies: - detect-libc: 2.0.2 + detect-libc: 2.0.3 expand-template: 2.0.3 github-from-package: 0.0.0 minimist: 1.2.8 mkdirp-classic: 0.5.3 - napi-build-utils: 1.0.2 - node-abi: 3.47.0 - pump: 3.0.0 + napi-build-utils: 2.0.0 + node-abi: 3.74.0 + pump: 3.0.2 rc: 1.2.8 simple-get: 4.0.1 - tar-fs: 2.1.1 + tar-fs: 2.1.2 tunnel-agent: 0.6.0 prelude-ls@1.2.1: {} @@ -18821,50 +18160,45 @@ snapshots: dependencies: '@jest/schemas': 29.6.3 ansi-styles: 5.2.0 - react-is: 18.2.0 + react-is: 18.3.1 pretty-hrtime@1.0.3: {} - prismarine-auth@2.4.2(encoding@0.1.13): + prismarine-auth@2.7.0: dependencies: - '@azure/msal-node': 2.7.0 + '@azure/msal-node': 2.16.2 '@xboxreplay/xboxlive-auth': 3.3.3(debug@4.4.0) debug: 4.4.0(supports-color@8.1.1) - jose: 4.15.5 - node-fetch: 2.7.0(encoding@0.1.13) smart-buffer: 4.2.0 uuid-1345: 1.0.2 transitivePeerDependencies: - - encoding - supports-color - prismarine-biome@1.3.0(minecraft-data@3.83.1)(prismarine-registry@1.11.0): + prismarine-biome@1.3.0(minecraft-data@3.98.0)(prismarine-registry@1.11.0): dependencies: - minecraft-data: 3.83.1 + minecraft-data: 3.98.0 prismarine-registry: 1.11.0 - prismarine-block@https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0): + prismarine-block@https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9: dependencies: - minecraft-data: 3.83.1 - prismarine-biome: 1.3.0(minecraft-data@3.83.1)(prismarine-registry@1.11.0) - prismarine-chat: 1.10.1 - prismarine-item: 1.16.0 - prismarine-nbt: 2.5.0 + minecraft-data: 3.98.0 + prismarine-biome: 1.3.0(minecraft-data@3.98.0)(prismarine-registry@1.11.0) + prismarine-chat: 1.11.0 + prismarine-item: 1.17.0 + prismarine-nbt: 2.7.0 prismarine-registry: 1.11.0 - transitivePeerDependencies: - - prismarine-registry - prismarine-chat@1.10.1: + prismarine-chat@1.11.0: dependencies: mojangson: 2.0.4 - prismarine-nbt: 2.5.0 + prismarine-nbt: 2.7.0 prismarine-registry: 1.11.0 - prismarine-chunk@https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/e68e9a423b5b1907535878fb636f12c28a1a9374(minecraft-data@3.83.1): + prismarine-chunk@https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0): dependencies: - prismarine-biome: 1.3.0(minecraft-data@3.83.1)(prismarine-registry@1.11.0) - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) - prismarine-nbt: 2.5.0 + prismarine-biome: 1.3.0(minecraft-data@3.98.0)(prismarine-registry@1.11.0) + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9 + prismarine-nbt: 2.7.0 prismarine-registry: 1.11.0 smart-buffer: 4.2.0 uint4: 0.1.2 @@ -18873,33 +18207,33 @@ snapshots: transitivePeerDependencies: - minecraft-data - prismarine-entity@2.3.1: + prismarine-entity@2.5.0: dependencies: - prismarine-chat: 1.10.1 - prismarine-item: 1.16.0 + prismarine-chat: 1.11.0 + prismarine-item: 1.17.0 prismarine-registry: 1.11.0 vec3: 0.1.10 - prismarine-item@1.16.0: + prismarine-item@1.17.0: dependencies: - prismarine-nbt: 2.5.0 + prismarine-nbt: 2.7.0 prismarine-registry: 1.11.0 - prismarine-nbt@2.5.0: + prismarine-nbt@2.7.0: dependencies: protodef: 1.18.0 prismarine-physics@https://codeload.github.com/zardoy/prismarine-physics/tar.gz/353e25b800149393f40539ec381218be44cbb03b: dependencies: - minecraft-data: 3.83.1 - prismarine-nbt: 2.5.0 + minecraft-data: 3.98.0 + prismarine-nbt: 2.7.0 vec3: 0.1.10 - prismarine-provider-anvil@https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.83.1): + prismarine-provider-anvil@https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.98.0): dependencies: - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) - prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/e68e9a423b5b1907535878fb636f12c28a1a9374(minecraft-data@3.83.1) - prismarine-nbt: 2.5.0 + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9 + prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0) + prismarine-nbt: 2.7.0 prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c uint4: 0.1.2 vec3: 0.1.10 @@ -18920,21 +18254,21 @@ snapshots: prismarine-registry@1.11.0: dependencies: - minecraft-data: 3.83.1 - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) - prismarine-nbt: 2.5.0 + minecraft-data: 3.98.0 + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9 + prismarine-nbt: 2.7.0 prismarine-schematic@1.2.3: dependencies: - minecraft-data: 3.83.1 - prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9(prismarine-registry@1.11.0) - prismarine-nbt: 2.5.0 + minecraft-data: 3.98.0 + prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9 + prismarine-nbt: 2.7.0 prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c vec3: 0.1.10 prismarine-windows@2.9.0: dependencies: - prismarine-item: 1.16.0 + prismarine-item: 1.17.0 prismarine-registry: 1.11.0 typed-emitter: 2.1.0 @@ -18972,93 +18306,94 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 - prosemirror-commands@1.5.2: + prosemirror-commands@1.7.0: dependencies: - prosemirror-model: 1.19.4 + prosemirror-model: 1.24.1 prosemirror-state: 1.4.3 - prosemirror-transform: 1.8.0 + prosemirror-transform: 1.10.3 prosemirror-dropcursor@1.8.1: dependencies: prosemirror-state: 1.4.3 - prosemirror-transform: 1.8.0 - prosemirror-view: 1.33.1 + prosemirror-transform: 1.10.3 + prosemirror-view: 1.38.1 - prosemirror-example-setup@1.2.2: + prosemirror-example-setup@1.2.3: dependencies: - prosemirror-commands: 1.5.2 + prosemirror-commands: 1.7.0 prosemirror-dropcursor: 1.8.1 prosemirror-gapcursor: 1.3.2 - prosemirror-history: 1.3.2 + prosemirror-history: 1.4.1 prosemirror-inputrules: 1.4.0 prosemirror-keymap: 1.2.2 prosemirror-menu: 1.2.4 - prosemirror-schema-list: 1.3.0 + prosemirror-schema-list: 1.5.1 prosemirror-state: 1.4.3 prosemirror-gapcursor@1.3.2: dependencies: prosemirror-keymap: 1.2.2 - prosemirror-model: 1.19.4 + prosemirror-model: 1.24.1 prosemirror-state: 1.4.3 - prosemirror-view: 1.33.1 + prosemirror-view: 1.38.1 - prosemirror-history@1.3.2: + prosemirror-history@1.4.1: dependencies: prosemirror-state: 1.4.3 - prosemirror-transform: 1.8.0 - prosemirror-view: 1.33.1 + prosemirror-transform: 1.10.3 + prosemirror-view: 1.38.1 rope-sequence: 1.3.4 prosemirror-inputrules@1.4.0: dependencies: prosemirror-state: 1.4.3 - prosemirror-transform: 1.8.0 + prosemirror-transform: 1.10.3 prosemirror-keymap@1.2.2: dependencies: prosemirror-state: 1.4.3 w3c-keyname: 2.2.8 - prosemirror-markdown@1.12.0: + prosemirror-markdown@1.13.1: dependencies: - markdown-it: 14.0.0 - prosemirror-model: 1.19.4 + '@types/markdown-it': 14.1.2 + markdown-it: 14.1.0 + prosemirror-model: 1.24.1 prosemirror-menu@1.2.4: dependencies: crelt: 1.0.6 - prosemirror-commands: 1.5.2 - prosemirror-history: 1.3.2 + prosemirror-commands: 1.7.0 + prosemirror-history: 1.4.1 prosemirror-state: 1.4.3 - prosemirror-model@1.19.4: + prosemirror-model@1.24.1: dependencies: orderedmap: 2.1.1 - prosemirror-schema-list@1.3.0: + prosemirror-schema-list@1.5.1: dependencies: - prosemirror-model: 1.19.4 + prosemirror-model: 1.24.1 prosemirror-state: 1.4.3 - prosemirror-transform: 1.8.0 + prosemirror-transform: 1.10.3 prosemirror-state@1.4.3: dependencies: - prosemirror-model: 1.19.4 - prosemirror-transform: 1.8.0 - prosemirror-view: 1.33.1 + prosemirror-model: 1.24.1 + prosemirror-transform: 1.10.3 + prosemirror-view: 1.38.1 - prosemirror-transform@1.8.0: + prosemirror-transform@1.10.3: dependencies: - prosemirror-model: 1.19.4 + prosemirror-model: 1.24.1 - prosemirror-view@1.33.1: + prosemirror-view@1.38.1: dependencies: - prosemirror-model: 1.19.4 + prosemirror-model: 1.24.1 prosemirror-state: 1.4.3 - prosemirror-transform: 1.8.0 + prosemirror-transform: 1.10.3 - protodef-validator@1.3.1: + protodef-validator@1.4.0: dependencies: ajv: 6.12.6 @@ -19066,8 +18401,8 @@ snapshots: dependencies: lodash.get: 4.4.2 lodash.reduce: 4.6.0 - protodef-validator: 1.3.1 - readable-stream: 4.5.2 + protodef-validator: 1.4.0 + readable-stream: 4.7.0 proxy-addr@2.0.7: dependencies: @@ -19076,6 +18411,8 @@ snapshots: proxy-compare@2.5.1: {} + proxy-compare@2.6.0: {} + proxy-from-env@1.0.0: optional: true @@ -19083,15 +18420,17 @@ snapshots: proxy-middleware@0.15.0: {} - psl@1.9.0: + psl@1.15.0: + dependencies: + punycode: 2.3.1 optional: true public-encrypt@4.0.3: dependencies: - bn.js: 4.12.0 - browserify-rsa: 4.1.0 + bn.js: 4.12.1 + browserify-rsa: 4.1.1 create-hash: 1.2.0 - parse-asn1: 5.1.6 + parse-asn1: 5.1.7 randombytes: 2.1.0 safe-buffer: 5.2.1 @@ -19100,7 +18439,7 @@ snapshots: end-of-stream: 1.4.4 once: 1.4.0 - pump@3.0.0: + pump@3.0.2: dependencies: end-of-stream: 1.4.4 once: 1.4.0 @@ -19119,8 +18458,8 @@ snapshots: puppeteer-core@2.1.1: dependencies: - '@types/mime-types': 2.1.2 - debug: 4.4.0(supports-color@8.1.1) + '@types/mime-types': 2.1.4 + debug: 4.4.1 extract-zip: 1.7.0 https-proxy-agent: 4.0.0 mime: 2.6.0 @@ -19128,26 +18467,26 @@ snapshots: progress: 2.0.3 proxy-from-env: 1.1.0 rimraf: 2.7.1 - ws: 6.2.2 + ws: 6.2.3 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - qrcode.react@3.1.0(react@18.2.0): + qrcode.react@3.2.0(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 qs@6.10.4: dependencies: side-channel: 1.1.0 optional: true - qs@6.11.0: + qs@6.13.0: dependencies: side-channel: 1.1.0 - qs@6.11.2: + qs@6.14.0: dependencies: side-channel: 1.1.0 @@ -19166,7 +18505,7 @@ snapshots: rambda@6.9.0: {} - rambda@9.2.0: {} + rambda@9.4.2: {} ramda@0.29.0: {} @@ -19192,13 +18531,6 @@ snapshots: range@0.0.3: {} - raw-body@2.5.1: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - raw-body@2.5.2: dependencies: bytes: 3.1.2 @@ -19217,141 +18549,139 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - react-colorful@5.6.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-colorful@5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) react-docgen-typescript@2.2.2(typescript@5.5.4): dependencies: typescript: 5.5.4 - react-docgen@6.0.0-alpha.3: + react-docgen@7.1.1: dependencies: - '@babel/core': 7.22.11 - '@babel/generator': 7.22.10 - ast-types: 0.14.2 - commander: 2.20.3 + '@babel/core': 7.26.9 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.6 + '@types/doctrine': 0.0.9 + '@types/resolve': 1.20.6 doctrine: 3.0.0 - estree-to-babel: 3.2.1 - neo-async: 2.6.2 - node-dir: 0.1.17 - resolve: 1.22.4 - strip-indent: 3.0.0 + resolve: 1.22.10 + strip-indent: 4.0.0 transitivePeerDependencies: - supports-color - react-dom@18.2.0(react@18.2.0): + react-dom@18.3.1(react@18.3.1): dependencies: loose-envify: 1.4.0 - react: 18.2.0 - scheduler: 0.23.0 + react: 18.3.1 + scheduler: 0.23.2 - react-element-to-jsx-string@15.0.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-element-to-jsx-string@15.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@base2/pretty-print-object': 1.0.1 is-plain-object: 5.0.0 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) react-is: 18.1.0 react-fast-compare@3.2.2: {} - react-hook-form@7.52.0(react@18.2.0): + react-hook-form@7.54.2(react@18.3.1): dependencies: - react: 18.2.0 - - react-inspector@6.0.2(react@18.2.0): - dependencies: - react: 18.2.0 + react: 18.3.1 react-is@16.13.1: {} react-is@18.1.0: {} - react-is@18.2.0: {} + react-is@18.3.1: {} - react-popper@2.3.0(@popperjs/core@2.11.8)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-popper@2.3.0(@popperjs/core@2.11.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@popperjs/core': 2.11.8 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) react-fast-compare: 3.2.2 warning: 4.0.3 - react-portal@4.2.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-portal@4.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) react-refresh@0.14.2: {} - react-remove-scroll-bar@2.3.4(@types/react@18.2.20)(react@18.2.0): - dependencies: - react: 18.2.0 - react-style-singleton: 2.2.1(@types/react@18.2.20)(react@18.2.0) - tslib: 2.6.2 - optionalDependencies: - '@types/react': 18.2.20 + react-refresh@0.17.0: {} - react-remove-scroll@2.5.5(@types/react@18.2.20)(react@18.2.0): + react-remove-scroll-bar@2.3.8(@types/react@18.3.18)(react@18.3.1): dependencies: - react: 18.2.0 - react-remove-scroll-bar: 2.3.4(@types/react@18.2.20)(react@18.2.0) - react-style-singleton: 2.2.1(@types/react@18.2.20)(react@18.2.0) - tslib: 2.6.2 - use-callback-ref: 1.3.0(@types/react@18.2.20)(react@18.2.0) - use-sidecar: 1.1.2(@types/react@18.2.20)(react@18.2.0) + react: 18.3.1 + react-style-singleton: 2.2.3(@types/react@18.3.18)(react@18.3.1) + tslib: 2.8.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - react-select@5.8.0(@types/react@18.2.20)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-remove-scroll@2.5.5(@types/react@18.3.18)(react@18.3.1): dependencies: - '@babel/runtime': 7.24.5 - '@emotion/cache': 11.13.1 - '@emotion/react': 11.13.0(@types/react@18.2.20)(react@18.2.0) - '@floating-ui/dom': 1.5.3 - '@types/react-transition-group': 4.4.7 + react: 18.3.1 + react-remove-scroll-bar: 2.3.8(@types/react@18.3.18)(react@18.3.1) + react-style-singleton: 2.2.3(@types/react@18.3.18)(react@18.3.1) + tslib: 2.8.1 + use-callback-ref: 1.3.3(@types/react@18.3.18)(react@18.3.1) + use-sidecar: 1.1.3(@types/react@18.3.18)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + + react-select@5.10.1(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@babel/runtime': 7.26.9 + '@emotion/cache': 11.14.0 + '@emotion/react': 11.14.0(@types/react@18.3.18)(react@18.3.1) + '@floating-ui/dom': 1.6.13 + '@types/react-transition-group': 4.4.12(@types/react@18.3.18) memoize-one: 6.0.0 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-transition-group: 4.4.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - use-isomorphic-layout-effect: 1.1.2(@types/react@18.2.20)(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + use-isomorphic-layout-effect: 1.2.0(@types/react@18.3.18)(react@18.3.1) transitivePeerDependencies: - '@types/react' + - supports-color - react-style-singleton@2.2.1(@types/react@18.2.20)(react@18.2.0): + react-style-singleton@2.2.3(@types/react@18.3.18)(react@18.3.1): dependencies: get-nonce: 1.0.1 - invariant: 2.2.4 - react: 18.2.0 - tslib: 2.6.2 + react: 18.3.1 + tslib: 2.8.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - react-transition-group@4.4.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.26.9 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-universal-interface@0.6.2(react@18.2.0)(tslib@2.6.2): + react-universal-interface@0.6.2(react@18.3.1)(tslib@2.8.1): dependencies: - react: 18.2.0 - tslib: 2.6.2 + react: 18.3.1 + tslib: 2.8.1 - react-use-measure@2.1.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-use-measure@2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: debounce: 1.2.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-use@17.3.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-use@17.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@types/js-cookie': 2.2.7 '@xobotyi/scrollbar-width': 1.9.5 @@ -19359,23 +18689,23 @@ snapshots: fast-deep-equal: 3.1.3 fast-shallow-equal: 1.0.0 js-cookie: 2.2.1 - nano-css: 5.3.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-universal-interface: 0.6.2(react@18.2.0)(tslib@2.6.2) + nano-css: 5.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-universal-interface: 0.6.2(react@18.3.1)(tslib@2.8.1) resize-observer-polyfill: 1.5.1 screenfull: 5.2.0 set-harmonic-interval: 1.0.1 throttle-debounce: 3.0.1 ts-easing: 0.2.0 - tslib: 2.6.2 + tslib: 2.8.1 - react-zoom-pan-pinch@3.4.4(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-zoom-pan-pinch@3.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react@18.2.0: + react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -19399,14 +18729,14 @@ snapshots: read-pkg@5.2.0: dependencies: - '@types/normalize-package-data': 2.4.2 + '@types/normalize-package-data': 2.4.4 normalize-package-data: 2.5.0 parse-json: 5.2.0 type-fest: 0.6.0 read-pkg@6.0.0: dependencies: - '@types/normalize-package-data': 2.4.2 + '@types/normalize-package-data': 2.4.4 normalize-package-data: 3.0.3 parse-json: 5.2.0 type-fest: 1.4.0 @@ -19435,7 +18765,7 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 - readable-stream@4.5.2: + readable-stream@4.7.0: dependencies: abort-controller: 3.0.0 buffer: 6.0.3 @@ -19457,29 +18787,20 @@ snapshots: readline@1.3.0: {} - recast@0.21.5: + recast@0.23.11: dependencies: - ast-types: 0.15.2 - esprima: 4.0.1 - source-map: 0.6.1 - tslib: 2.6.2 - - recast@0.23.4: - dependencies: - assert: 2.1.0 ast-types: 0.16.1 esprima: 4.0.1 source-map: 0.6.1 - tslib: 2.6.2 + tiny-invariant: 1.3.3 + tslib: 2.8.1 redent@4.0.0: dependencies: indent-string: 5.0.0 strip-indent: 4.0.0 - reduce-configs@1.0.0: - dependencies: - browserslist: 4.23.2 + reduce-configs@1.1.0: {} reflect.getprototypeof@1.0.10: dependencies: @@ -19492,7 +18813,7 @@ snapshots: get-proto: 1.0.1 which-builtin-type: 1.2.1 - regenerate-unicode-properties@10.1.0: + regenerate-unicode-properties@10.2.0: dependencies: regenerate: 1.4.2 @@ -19501,11 +18822,11 @@ snapshots: regenerator-runtime@0.13.11: optional: true - regenerator-runtime@0.14.0: {} + regenerator-runtime@0.14.1: {} regenerator-transform@0.15.2: dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.26.9 regex-not@1.0.2: dependencies: @@ -19525,22 +18846,24 @@ snapshots: regexpp@3.2.0: {} - regexpu-core@5.3.2: + regexpu-core@6.2.0: dependencies: - '@babel/regjsgen': 0.8.0 regenerate: 1.4.2 - regenerate-unicode-properties: 10.1.0 - regjsparser: 0.9.1 + regenerate-unicode-properties: 10.2.0 + regjsgen: 0.8.0 + regjsparser: 0.12.0 unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.1.0 + unicode-match-property-value-ecmascript: 2.2.0 + + regjsgen@0.8.0: {} regjsparser@0.10.0: dependencies: jsesc: 0.5.0 - regjsparser@0.9.1: + regjsparser@0.12.0: dependencies: - jsesc: 0.5.0 + jsesc: 3.0.2 remark-external-links@8.0.0: dependencies: @@ -19552,10 +18875,10 @@ snapshots: remark-parse@11.0.0: dependencies: - '@types/mdast': 4.0.3 - mdast-util-from-markdown: 2.0.0 - micromark-util-types: 2.0.0 - unified: 11.0.4 + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.2 + micromark-util-types: 2.0.2 + unified: 11.0.5 transitivePeerDependencies: - supports-color @@ -19567,16 +18890,16 @@ snapshots: remark-stringify@11.0.0: dependencies: - '@types/mdast': 4.0.3 - mdast-util-to-markdown: 2.1.0 - unified: 11.0.4 + '@types/mdast': 4.0.4 + mdast-util-to-markdown: 2.1.2 + unified: 11.0.5 remark@15.0.1: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 remark-parse: 11.0.0 remark-stringify: 11.0.0 - unified: 11.0.4 + unified: 11.0.5 transitivePeerDependencies: - supports-color @@ -19588,7 +18911,7 @@ snapshots: request-progress@3.0.0: dependencies: - throttleit: 1.0.0 + throttleit: 1.0.1 optional: true require-directory@2.1.1: {} @@ -19607,7 +18930,7 @@ snapshots: resolve-url@0.2.1: {} - resolve@1.22.4: + resolve@1.22.10: dependencies: is-core-module: 2.16.1 path-parse: 1.0.7 @@ -19629,9 +18952,9 @@ snapshots: retry@0.12.0: optional: true - reusify@1.0.4: {} + reusify@1.1.0: {} - rfdc@1.3.0: + rfdc@1.4.1: optional: true rimraf@2.6.3: @@ -19646,74 +18969,66 @@ snapshots: dependencies: glob: 7.2.3 - rimraf@5.0.1: + rimraf@5.0.10: dependencies: - glob: 10.3.3 + glob: 10.4.5 ripemd160@2.0.2: dependencies: - hash-base: 3.1.0 + hash-base: 3.0.5 inherits: 2.0.4 - rollup-plugin-terser@7.0.2(rollup@2.79.1): - dependencies: - '@babel/code-frame': 7.22.13 - jest-worker: 26.6.2 - rollup: 2.79.1 - serialize-javascript: 4.0.0 - terser: 5.31.3 - - rollup@2.79.1: + rollup@2.79.2: optionalDependencies: fsevents: 2.3.3 - rollup@3.29.4: + rollup@3.29.5: optionalDependencies: fsevents: 2.3.3 - rollup@4.34.8: + rollup@4.34.9: dependencies: '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.34.8 - '@rollup/rollup-android-arm64': 4.34.8 - '@rollup/rollup-darwin-arm64': 4.34.8 - '@rollup/rollup-darwin-x64': 4.34.8 - '@rollup/rollup-freebsd-arm64': 4.34.8 - '@rollup/rollup-freebsd-x64': 4.34.8 - '@rollup/rollup-linux-arm-gnueabihf': 4.34.8 - '@rollup/rollup-linux-arm-musleabihf': 4.34.8 - '@rollup/rollup-linux-arm64-gnu': 4.34.8 - '@rollup/rollup-linux-arm64-musl': 4.34.8 - '@rollup/rollup-linux-loongarch64-gnu': 4.34.8 - '@rollup/rollup-linux-powerpc64le-gnu': 4.34.8 - '@rollup/rollup-linux-riscv64-gnu': 4.34.8 - '@rollup/rollup-linux-s390x-gnu': 4.34.8 - '@rollup/rollup-linux-x64-gnu': 4.34.8 - '@rollup/rollup-linux-x64-musl': 4.34.8 - '@rollup/rollup-win32-arm64-msvc': 4.34.8 - '@rollup/rollup-win32-ia32-msvc': 4.34.8 - '@rollup/rollup-win32-x64-msvc': 4.34.8 + '@rollup/rollup-android-arm-eabi': 4.34.9 + '@rollup/rollup-android-arm64': 4.34.9 + '@rollup/rollup-darwin-arm64': 4.34.9 + '@rollup/rollup-darwin-x64': 4.34.9 + '@rollup/rollup-freebsd-arm64': 4.34.9 + '@rollup/rollup-freebsd-x64': 4.34.9 + '@rollup/rollup-linux-arm-gnueabihf': 4.34.9 + '@rollup/rollup-linux-arm-musleabihf': 4.34.9 + '@rollup/rollup-linux-arm64-gnu': 4.34.9 + '@rollup/rollup-linux-arm64-musl': 4.34.9 + '@rollup/rollup-linux-loongarch64-gnu': 4.34.9 + '@rollup/rollup-linux-powerpc64le-gnu': 4.34.9 + '@rollup/rollup-linux-riscv64-gnu': 4.34.9 + '@rollup/rollup-linux-s390x-gnu': 4.34.9 + '@rollup/rollup-linux-x64-gnu': 4.34.9 + '@rollup/rollup-linux-x64-musl': 4.34.9 + '@rollup/rollup-win32-arm64-msvc': 4.34.9 + '@rollup/rollup-win32-ia32-msvc': 4.34.9 + '@rollup/rollup-win32-x64-msvc': 4.34.9 fsevents: 2.3.3 rope-sequence@1.3.4: {} rtl-css-js@1.16.1: dependencies: - '@babel/runtime': 7.24.5 + '@babel/runtime': 7.26.9 run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 - rxjs@7.8.1: + rxjs@7.8.2: dependencies: - tslib: 2.6.2 + tslib: 2.8.1 safe-array-concat@1.1.3: dependencies: call-bind: 1.0.8 - call-bound: 1.0.3 + call-bound: 1.0.4 get-intrinsic: 1.3.0 has-symbols: 1.1.0 isarray: 2.0.5 @@ -19729,7 +19044,7 @@ snapshots: safe-regex-test@1.1.0: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 es-errors: 1.3.0 is-regex: 1.2.1 @@ -19745,19 +19060,13 @@ snapshots: sat@0.9.0: {} - sax@1.3.0: + sax@1.4.1: optional: true - scheduler@0.23.0: + scheduler@0.23.2: dependencies: loose-envify: 1.4.0 - schema-utils@3.3.0: - dependencies: - '@types/json-schema': 7.0.12 - ajv: 6.12.6 - ajv-keywords: 3.5.2(ajv@6.12.6) - screenfull@5.2.0: {} sdp@3.2.0: {} @@ -19768,14 +19077,9 @@ snapshots: semver@6.3.1: {} - semver@7.6.0: - dependencies: - lru-cache: 6.0.0 + semver@7.7.1: {} - semver@7.7.1: - optional: true - - send@0.18.0: + send@0.19.0: dependencies: debug: 2.6.9 depd: 2.0.0 @@ -19793,33 +19097,28 @@ snapshots: transitivePeerDependencies: - supports-color - send@1.1.0: + send@1.2.0: dependencies: - debug: 4.4.0(supports-color@8.1.1) - destroy: 1.2.0 + debug: 4.4.1 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 - fresh: 0.5.2 + fresh: 2.0.0 http-errors: 2.0.0 - mime-types: 2.1.35 + mime-types: 3.0.1 ms: 2.1.3 on-finished: 2.4.1 range-parser: 1.2.1 - statuses: 2.0.1 + statuses: 2.0.2 transitivePeerDependencies: - supports-color sentence-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.8.1 upper-case-first: 2.0.2 - serialize-javascript@4.0.0: - dependencies: - randombytes: 2.1.0 - serialize-javascript@6.0.2: dependencies: randombytes: 2.1.0 @@ -19836,12 +19135,12 @@ snapshots: transitivePeerDependencies: - supports-color - serve-static@1.15.0: + serve-static@1.16.2: dependencies: - encodeurl: 1.0.2 + encodeurl: 2.0.0 escape-html: 1.0.3 parseurl: 1.3.3 - send: 0.18.0 + send: 0.19.0 transitivePeerDependencies: - supports-color @@ -19897,12 +19196,12 @@ snapshots: sharp@0.30.7: dependencies: color: 4.2.3 - detect-libc: 2.0.2 + detect-libc: 2.0.3 node-addon-api: 5.1.0 - prebuild-install: 7.1.1 - semver: 7.6.0 + prebuild-install: 7.1.3 + semver: 7.7.1 simple-get: 4.0.1 - tar-fs: 2.1.1 + tar-fs: 2.1.2 tunnel-agent: 0.6.0 sharp@0.33.5: @@ -19944,32 +19243,32 @@ snapshots: shebang-regex@3.0.0: {} - shell-quote@1.8.1: {} + shell-quote@1.8.2: {} side-channel-list@1.0.0: dependencies: es-errors: 1.3.0 - object-inspect: 1.13.3 + object-inspect: 1.13.4 side-channel-map@1.0.1: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 es-errors: 1.3.0 get-intrinsic: 1.3.0 - object-inspect: 1.13.3 + object-inspect: 1.13.4 side-channel-weakmap@1.0.2: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 es-errors: 1.3.0 get-intrinsic: 1.3.0 - object-inspect: 1.13.3 + object-inspect: 1.13.4 side-channel-map: 1.0.1 side-channel@1.1.0: dependencies: es-errors: 1.3.0 - object-inspect: 1.13.3 + object-inspect: 1.13.4 side-channel-list: 1.0.0 side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 @@ -19999,19 +19298,15 @@ snapshots: dependencies: is-arrayish: 0.3.2 - simple-update-notifier@2.0.0: - dependencies: - semver: 7.6.0 - sisteransi@1.0.5: {} skinview-utils@0.7.1: {} - skinview3d@3.0.1: + skinview3d@3.1.0: dependencies: '@types/three': 0.156.0 skinview-utils: 0.7.1 - three: 0.154.0(patch_hash=sj7ocb4p23jym6bkfgueanti2e) + three: 0.154.0 slash@3.0.0: {} @@ -20031,10 +19326,12 @@ snapshots: smart-buffer@4.2.0: {} + smob@1.5.0: {} + snake-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.8.1 snapdragon-node@2.1.1: dependencies: @@ -20062,25 +19359,27 @@ snapshots: socket.io-adapter@1.1.2: optional: true - socket.io-adapter@2.5.2: + socket.io-adapter@2.5.5: dependencies: - ws: 8.11.0 + debug: 4.3.7 + ws: 8.17.1 transitivePeerDependencies: - bufferutil + - supports-color - utf-8-validate socket.io-client@2.5.0: dependencies: backo2: 1.0.2 component-bind: 1.0.0 - component-emitter: 1.3.0 + component-emitter: 1.3.1 debug: 3.1.0 - engine.io-client: 3.5.3 + engine.io-client: 3.5.4 has-binary2: 1.0.3 indexof: 0.0.1 parseqs: 0.0.6 parseuri: 0.0.6 - socket.io-parser: 3.3.3 + socket.io-parser: 3.3.4 to-array: 0.1.4 transitivePeerDependencies: - bufferutil @@ -20088,20 +19387,20 @@ snapshots: - utf-8-validate optional: true - socket.io-client@4.7.2: + socket.io-client@4.8.1: dependencies: - '@socket.io/component-emitter': 3.1.0 + '@socket.io/component-emitter': 3.1.2 debug: 4.3.7 - engine.io-client: 6.5.2 + engine.io-client: 6.6.3 socket.io-parser: 4.2.4 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - socket.io-parser@3.3.3: + socket.io-parser@3.3.4: dependencies: - component-emitter: 1.3.0 + component-emitter: 1.3.1 debug: 3.1.0 isarray: 2.0.1 transitivePeerDependencies: @@ -20119,15 +19418,15 @@ snapshots: socket.io-parser@4.2.4: dependencies: - '@socket.io/component-emitter': 3.1.0 + '@socket.io/component-emitter': 3.1.2 debug: 4.3.7 transitivePeerDependencies: - supports-color - socket.io@2.5.0: + socket.io@2.5.1: dependencies: debug: 4.1.1 - engine.io: 3.6.1 + engine.io: 3.6.2 has-binary2: 1.0.3 socket.io-adapter: 1.1.2 socket.io-client: 2.5.0 @@ -20138,14 +19437,14 @@ snapshots: - utf-8-validate optional: true - socket.io@4.7.2: + socket.io@4.8.1: dependencies: accepts: 1.3.8 base64id: 2.0.0 cors: 2.8.5 debug: 4.3.7 - engine.io: 6.5.3 - socket.io-adapter: 2.5.2 + engine.io: 6.6.4 + socket.io-adapter: 2.5.5 socket.io-parser: 4.2.4 transitivePeerDependencies: - bufferutil @@ -20155,15 +19454,15 @@ snapshots: socks-proxy-agent@7.0.0: dependencies: agent-base: 6.0.2 - debug: 4.4.0(supports-color@8.1.1) - socks: 2.7.1 + debug: 4.4.1 + socks: 2.8.4 transitivePeerDependencies: - supports-color optional: true - socks@2.7.1: + socks@2.8.4: dependencies: - ip: 2.0.0 + ip-address: 9.0.5 smart-buffer: 4.2.0 optional: true @@ -20201,16 +19500,16 @@ snapshots: spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.13 + spdx-license-ids: 3.0.21 - spdx-exceptions@2.3.0: {} + spdx-exceptions@2.5.0: {} spdx-expression-parse@3.0.1: dependencies: - spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.13 + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.21 - spdx-license-ids@3.0.13: {} + spdx-license-ids@3.0.21: {} split-string@3.1.0: dependencies: @@ -20222,7 +19521,10 @@ snapshots: sprintf-js@1.0.3: {} - sshpk@1.17.0: + sprintf-js@1.1.3: + optional: true + + sshpk@1.18.0: dependencies: asn1: 0.2.6 assert-plus: 1.0.0 @@ -20259,12 +19561,14 @@ snapshots: stack-generator: 2.0.10 stacktrace-gps: 3.1.2 + state-local@1.0.7: {} + static-extend@0.1.2: dependencies: define-property: 0.2.5 object-copy: 0.1.0 - stats-gl@1.0.5: {} + stats-gl@1.0.7: {} stats.js@0.17.0: {} @@ -20272,15 +19576,20 @@ snapshots: statuses@2.0.1: {} - std-env@3.4.3: {} + statuses@2.0.2: {} - std-env@3.8.0: {} + std-env@3.8.1: {} - store2@2.14.2: {} - - storybook@7.4.6(encoding@0.1.13): + stop-iteration-iterator@1.1.0: dependencies: - '@storybook/cli': 7.4.6(encoding@0.1.13) + es-errors: 1.3.0 + internal-slot: 1.1.0 + + store2@2.14.4: {} + + storybook@7.6.20(encoding@0.1.13): + dependencies: + '@storybook/cli': 7.6.20(encoding@0.1.13) transitivePeerDependencies: - bufferutil - encoding @@ -20303,7 +19612,7 @@ snapshots: readable-stream: 3.6.2 xtend: 4.0.2 - stream-shift@1.0.1: {} + stream-shift@1.0.3: {} strict-event-emitter-types@2.0.0: {} @@ -20322,7 +19631,7 @@ snapshots: string.prototype.matchall@4.0.12: dependencies: call-bind: 1.0.8 - call-bound: 1.0.3 + call-bound: 1.0.4 define-properties: 1.2.1 es-abstract: 1.23.9 es-errors: 1.3.0 @@ -20335,16 +19644,22 @@ snapshots: set-function-name: 2.0.2 side-channel: 1.1.0 - string.prototype.padend@3.1.4: + string.prototype.padend@3.1.6: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.24.0 string.prototype.trim@1.2.10: dependencies: call-bind: 1.0.8 - call-bound: 1.0.3 + call-bound: 1.0.4 define-data-property: 1.1.4 define-properties: 1.2.1 es-abstract: 1.23.9 @@ -20354,7 +19669,7 @@ snapshots: string.prototype.trimend@1.0.9: dependencies: call-bind: 1.0.8 - call-bound: 1.0.3 + call-bound: 1.0.4 define-properties: 1.2.1 es-object-atoms: 1.1.1 @@ -20387,7 +19702,7 @@ snapshots: strip-ansi@7.1.0: dependencies: - ansi-regex: 6.0.1 + ansi-regex: 6.1.0 strip-bom@3.0.0: {} @@ -20409,10 +19724,12 @@ snapshots: strip-literal@1.3.0: dependencies: - acorn: 8.12.1 + acorn: 8.14.1 stylis@4.2.0: {} + stylis@4.3.6: {} + supports-color@5.5.0: dependencies: has-flag: 3.0.0 @@ -20429,18 +19746,16 @@ snapshots: synchronous-promise@2.0.17: {} - systeminformation@5.22.7: + systeminformation@5.25.11: optional: true tabbable@6.2.0: {} - tapable@2.2.1: {} - - tar-fs@2.1.1: + tar-fs@2.1.2: dependencies: chownr: 1.1.4 mkdirp-classic: 0.5.3 - pump: 3.0.0 + pump: 3.0.2 tar-stream: 2.2.0 tar-stream@2.2.0: @@ -20451,7 +19766,7 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - tar@6.2.0: + tar@6.2.1: dependencies: chownr: 2.0.0 fs-minipass: 2.1.0 @@ -20485,21 +19800,10 @@ snapshots: type-fest: 0.16.0 unique-string: 2.0.0 - terser-webpack-plugin@5.3.10(esbuild@0.19.11)(webpack@5.93.0(esbuild@0.19.11)): + terser@5.39.0: dependencies: - '@jridgewell/trace-mapping': 0.3.25 - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.2 - terser: 5.31.3 - webpack: 5.93.0(esbuild@0.19.11) - optionalDependencies: - esbuild: 0.19.11 - - terser@5.31.3: - dependencies: - '@jridgewell/source-map': 0.3.5 - acorn: 8.12.1 + '@jridgewell/source-map': 0.3.6 + acorn: 8.14.1 commander: 2.20.3 source-map-support: 0.5.21 @@ -20519,23 +19823,27 @@ snapshots: dependencies: any-promise: 1.3.0 - three-stdlib@2.28.5(three@0.154.0(patch_hash=sj7ocb4p23jym6bkfgueanti2e)): + thingies@1.21.0(tslib@2.8.1): dependencies: - '@types/draco3d': 1.4.7 - '@types/offscreencanvas': 2019.7.2 - '@types/webxr': 0.5.7 - draco3d: 1.5.6 + tslib: 2.8.1 + + three-stdlib@2.35.14(three@0.154.0): + dependencies: + '@types/draco3d': 1.4.10 + '@types/offscreencanvas': 2019.7.3 + '@types/webxr': 0.5.21 + draco3d: 1.5.7 fflate: 0.6.10 potpack: 1.0.2 - three: 0.154.0(patch_hash=sj7ocb4p23jym6bkfgueanti2e) + three: 0.154.0 three.meshline@1.4.0: {} - three@0.154.0(patch_hash=sj7ocb4p23jym6bkfgueanti2e): {} + three@0.154.0: {} throttle-debounce@3.0.1: {} - throttleit@1.0.0: + throttleit@1.0.1: optional: true through2@0.6.5: @@ -20558,9 +19866,7 @@ snapshots: timm@1.7.1: optional: true - tiny-invariant@1.3.1: {} - - tinybench@2.5.1: {} + tiny-invariant@1.3.3: {} tinybench@2.9.0: {} @@ -20571,21 +19877,13 @@ snapshots: tinypool@0.7.0: {} - tinypool@1.0.2: {} - - tinyrainbow@2.0.0: {} - - tinyspy@2.2.0: {} - - tinyspy@3.0.2: {} + tinyspy@2.2.1: {} title-case@3.0.3: dependencies: - tslib: 2.6.2 + tslib: 2.8.1 - tmp@0.2.1: - dependencies: - rimraf: 3.0.2 + tmp@0.2.3: optional: true tmpl@1.0.5: {} @@ -20593,8 +19891,6 @@ snapshots: to-array@0.1.4: optional: true - to-fast-properties@2.0.0: {} - to-object-path@0.3.0: dependencies: kind-of: 3.2.2 @@ -20615,15 +19911,15 @@ snapshots: regex-not: 1.0.2 safe-regex: 1.1.0 - tocbot@4.21.2: {} + tocbot@4.35.0: {} toggle-selection@1.0.6: {} toidentifier@1.0.1: {} - tough-cookie@4.1.3: + tough-cookie@4.1.4: dependencies: - psl: 1.9.0 + psl: 1.15.0 punycode: 2.3.1 universalify: 0.2.0 url-parse: 1.5.10 @@ -20635,23 +19931,43 @@ snapshots: dependencies: punycode: 2.3.1 + tree-dump@1.0.2(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + trim-newlines@4.1.1: {} trough@2.2.0: {} truncate-utf8-bytes@1.0.2: dependencies: - utf8-byte-length: 1.0.4 + utf8-byte-length: 1.0.5 - ts-api-utils@1.3.0(typescript@5.5.4): + ts-api-utils@1.4.3(typescript@5.5.4): dependencies: typescript: 5.5.4 + ts-api-utils@2.0.1(typescript@5.5.4): + dependencies: + typescript: 5.5.4 + + ts-checker-rspack-plugin@1.1.1(@rspack/core@1.3.3(@swc/helpers@0.5.15))(typescript@5.5.4): + dependencies: + '@babel/code-frame': 7.26.2 + '@rspack/lite-tapable': 1.0.1 + chokidar: 3.6.0 + memfs: 4.17.0 + minimatch: 9.0.5 + picocolors: 1.1.1 + typescript: 5.5.4 + optionalDependencies: + '@rspack/core': 1.3.3(@swc/helpers@0.5.15) + ts-dedent@2.2.0: {} ts-easing@0.2.0: {} - tsconfig-paths@3.14.2: + tsconfig-paths@3.15.0: dependencies: '@types/json5': 0.0.29 json5: 1.0.2 @@ -20660,12 +19976,12 @@ snapshots: tslib@1.14.1: {} - tslib@2.6.2: {} + tslib@2.8.1: {} - tsx@4.7.0: + tsx@4.19.3: dependencies: - esbuild: 0.19.11 - get-tsconfig: 4.7.2 + esbuild: 0.25.0 + get-tsconfig: 4.10.0 optionalDependencies: fsevents: 2.3.3 @@ -20682,7 +19998,7 @@ snapshots: dependencies: prelude-ls: 1.2.1 - type-detect@4.0.8: {} + type-detect@4.1.0: {} type-fest@0.16.0: {} @@ -20706,14 +20022,14 @@ snapshots: typed-array-buffer@1.0.3: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 es-errors: 1.3.0 is-typed-array: 1.1.15 typed-array-byte-length@1.0.3: dependencies: call-bind: 1.0.8 - for-each: 0.3.4 + for-each: 0.3.5 gopd: 1.2.0 has-proto: 1.2.0 is-typed-array: 1.1.15 @@ -20722,7 +20038,7 @@ snapshots: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.8 - for-each: 0.3.4 + for-each: 0.3.5 gopd: 1.2.0 has-proto: 1.2.0 is-typed-array: 1.1.15 @@ -20731,54 +20047,56 @@ snapshots: typed-array-length@1.0.7: dependencies: call-bind: 1.0.8 - for-each: 0.3.4 + for-each: 0.3.5 gopd: 1.2.0 is-typed-array: 1.1.15 - possible-typed-array-names: 1.0.0 + possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 typed-emitter@1.4.0: {} typed-emitter@2.1.0: optionalDependencies: - rxjs: 7.8.1 + rxjs: 7.8.2 typedarray@0.0.6: {} typescript@5.5.4: {} - ua-parser-js@1.0.37: {} + ua-parser-js@1.0.40: {} uc.micro@2.1.0: {} - ufo@1.3.1: {} + ufo@1.5.4: {} - uglify-js@3.17.4: + uglify-js@3.19.3: optional: true uint4@0.1.2: {} unbox-primitive@1.1.0: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 has-bigints: 1.1.0 has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 - undici-types@6.19.8: {} + undici-types@5.26.5: {} - undici@5.25.4: + undici-types@6.20.0: {} + + undici@6.0.1: dependencies: - '@fastify/busboy': 2.0.0 + '@fastify/busboy': 2.1.1 - unicode-canonical-property-names-ecmascript@2.0.0: {} + unicode-canonical-property-names-ecmascript@2.0.1: {} unicode-match-property-ecmascript@2.0.0: dependencies: - unicode-canonical-property-names-ecmascript: 2.0.0 + unicode-canonical-property-names-ecmascript: 2.0.1 unicode-property-aliases-ecmascript: 2.1.0 - unicode-match-property-value-ecmascript@2.1.0: {} + unicode-match-property-value-ecmascript@2.2.0: {} unicode-property-aliases-ecmascript@2.1.0: {} @@ -20787,15 +20105,15 @@ snapshots: diff: 2.2.3 optional: true - unified@11.0.4: + unified@11.0.5: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 bail: 2.0.2 devlop: 1.1.0 extend: 3.0.2 is-plain-obj: 4.1.0 trough: 2.2.0 - vfile: 6.0.1 + vfile: 6.0.3 union-value@1.0.1: dependencies: @@ -20806,7 +20124,7 @@ snapshots: union@0.5.0: dependencies: - qs: 6.11.2 + qs: 6.14.0 unique-filename@2.0.1: dependencies: @@ -20826,31 +20144,31 @@ snapshots: unist-util-is@6.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-stringify-position@4.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-visit-parents@3.1.1: dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.11 unist-util-is: 4.1.0 unist-util-visit-parents@6.0.1: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-is: 6.0.0 unist-util-visit@2.0.3: dependencies: - '@types/unist': 2.0.8 + '@types/unist': 2.0.11 unist-util-is: 4.1.0 unist-util-visit-parents: 3.1.1 unist-util-visit@5.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 @@ -20860,18 +20178,16 @@ snapshots: universalify@0.2.0: optional: true - universalify@2.0.0: {} + universalify@2.0.1: {} unix-crypt-td-js@1.1.4: {} unpipe@1.0.0: {} - unplugin@1.5.0: + unplugin@1.16.1: dependencies: - acorn: 8.12.1 - chokidar: 3.5.3 - webpack-sources: 3.2.3 - webpack-virtual-modules: 0.5.0 + acorn: 8.14.1 + webpack-virtual-modules: 0.6.2 unset-value@1.0.0: dependencies: @@ -20882,19 +20198,19 @@ snapshots: upath@1.2.0: {} - update-browserslist-db@1.1.0(browserslist@4.23.2): + update-browserslist-db@1.1.3(browserslist@4.24.4): dependencies: - browserslist: 4.23.2 - escalade: 3.1.2 + browserslist: 4.24.4 + escalade: 3.2.0 picocolors: 1.1.1 upper-case-first@2.0.2: dependencies: - tslib: 2.6.2 + tslib: 2.8.1 upper-case@2.0.2: dependencies: - tslib: 2.6.2 + tslib: 2.8.1 uri-js@4.4.1: dependencies: @@ -20910,58 +20226,58 @@ snapshots: requires-port: 1.0.0 optional: true - url@0.11.3: + url@0.11.4: dependencies: punycode: 1.4.1 - qs: 6.11.2 + qs: 6.14.0 - use-callback-ref@1.3.0(@types/react@18.2.20)(react@18.2.0): + use-callback-ref@1.3.3(@types/react@18.3.18)(react@18.3.1): dependencies: - react: 18.2.0 - tslib: 2.6.2 + react: 18.3.1 + tslib: 2.8.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - use-deep-compare@1.1.0(react@18.2.0): + use-deep-compare@1.3.0(react@18.3.1): dependencies: - dequal: 1.0.0 - react: 18.2.0 + dequal: 2.0.3 + react: 18.3.1 - use-isomorphic-layout-effect@1.1.2(@types/react@18.2.20)(react@18.2.0): + use-isomorphic-layout-effect@1.2.0(@types/react@18.3.18)(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - use-resize-observer@9.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + use-resize-observer@9.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@juggle/resize-observer': 3.3.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@juggle/resize-observer': 3.4.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - use-sidecar@1.1.2(@types/react@18.2.20)(react@18.2.0): + use-sidecar@1.1.3(@types/react@18.3.18)(react@18.3.1): dependencies: detect-node-es: 1.1.0 - react: 18.2.0 - tslib: 2.6.2 + react: 18.3.1 + tslib: 2.8.1 optionalDependencies: - '@types/react': 18.2.20 + '@types/react': 18.3.18 - use-sync-external-store@1.2.0(react@18.2.0): + use-sync-external-store@1.2.0(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 - use-typed-event-listener@4.0.2(react@18.2.0)(typescript@5.5.4): + use-typed-event-listener@4.0.2(react@18.3.1)(typescript@5.5.4): dependencies: - '@babel/runtime': 7.24.5 - react: 18.2.0 - use-deep-compare: 1.1.0(react@18.2.0) + '@babel/runtime': 7.26.9 + react: 18.3.1 + use-deep-compare: 1.3.0(react@18.3.1) optionalDependencies: typescript: 5.5.4 use@3.1.1: {} - utf8-byte-length@1.0.4: {} + utf8-byte-length@1.0.5: {} utif@2.0.1: dependencies: @@ -20973,7 +20289,7 @@ snapshots: util@0.12.5: dependencies: inherits: 2.0.4 - is-arguments: 1.1.1 + is-arguments: 1.2.0 is-generator-function: 1.1.0 is-typed-array: 1.1.15 which-typed-array: 1.1.18 @@ -20990,24 +20306,27 @@ snapshots: uuid@9.0.1: {} - v8-to-istanbul@9.1.3: - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - '@types/istanbul-lib-coverage': 2.0.4 - convert-source-map: 2.0.0 - validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - valtio@1.11.2(@types/react@18.2.20)(react@18.2.0): + valtio@1.11.2(@types/react@18.3.18)(react@18.3.1): dependencies: proxy-compare: 2.5.1 - use-sync-external-store: 1.2.0(react@18.2.0) + use-sync-external-store: 1.2.0(react@18.3.1) optionalDependencies: - '@types/react': 18.2.20 - react: 18.2.0 + '@types/react': 18.3.18 + react: 18.3.1 + + valtio@1.13.2(@types/react@18.3.18)(react@18.3.1): + dependencies: + derive-valtio: 0.1.0(valtio@1.13.2(@types/react@18.3.18)(react@18.3.1)) + proxy-compare: 2.6.0 + use-sync-external-store: 1.2.0(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.18 + react: 18.3.1 vary@1.1.2: {} @@ -21022,23 +20341,22 @@ snapshots: vfile-message@4.0.2: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-stringify-position: 4.0.0 - vfile@6.0.1: + vfile@6.0.3: dependencies: - '@types/unist': 3.0.2 - unist-util-stringify-position: 4.0.0 + '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite-node@0.34.6(@types/node@22.8.1)(terser@5.31.3): + vite-node@0.34.6(@types/node@22.13.9)(terser@5.39.0): dependencies: cac: 6.7.14 debug: 4.4.0(supports-color@8.1.1) - mlly: 1.4.2 - pathe: 1.1.1 + mlly: 1.7.4 + pathe: 1.1.2 picocolors: 1.1.1 - vite: 4.5.3(@types/node@22.8.1)(terser@5.31.3) + vite: 4.5.9(@types/node@22.13.9)(terser@5.39.0) transitivePeerDependencies: - '@types/node' - less @@ -21049,122 +20367,63 @@ snapshots: - supports-color - terser - vite-node@3.0.7(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1): - dependencies: - cac: 6.7.14 - debug: 4.4.0(supports-color@8.1.1) - es-module-lexer: 1.6.0 - pathe: 2.0.3 - vite: 6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1) - transitivePeerDependencies: - - '@types/node' - - jiti - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - vite@4.5.3(@types/node@22.8.1)(terser@5.31.3): + vite@4.5.9(@types/node@22.13.9)(terser@5.39.0): dependencies: esbuild: 0.18.20 - postcss: 8.4.47 - rollup: 3.29.4 + postcss: 8.5.3 + rollup: 3.29.5 optionalDependencies: - '@types/node': 22.8.1 + '@types/node': 22.13.9 fsevents: 2.3.3 - terser: 5.31.3 + terser: 5.39.0 - vite@6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1): + vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0): dependencies: esbuild: 0.25.0 postcss: 8.5.3 - rollup: 4.34.8 + rollup: 4.34.9 optionalDependencies: - '@types/node': 22.8.1 + '@types/node': 22.13.9 fsevents: 2.3.3 - terser: 5.31.3 - tsx: 4.7.0 - yaml: 2.4.1 + jiti: 2.4.2 + terser: 5.39.0 + tsx: 4.19.3 + yaml: 2.7.0 - vitest@0.34.6(terser@5.31.3): + vitest@0.34.6(terser@5.39.0): dependencies: - '@types/chai': 4.3.6 - '@types/chai-subset': 1.3.3 - '@types/node': 22.8.1 + '@types/chai': 4.3.20 + '@types/chai-subset': 1.3.6(@types/chai@4.3.20) + '@types/node': 22.13.9 '@vitest/expect': 0.34.6 '@vitest/runner': 0.34.6 '@vitest/snapshot': 0.34.6 '@vitest/spy': 0.34.6 '@vitest/utils': 0.34.6 - acorn: 8.12.1 - acorn-walk: 8.2.0 + acorn: 8.14.1 + acorn-walk: 8.3.4 cac: 6.7.14 - chai: 4.3.10 + chai: 4.5.0 debug: 4.4.0(supports-color@8.1.1) local-pkg: 0.4.3 - magic-string: 0.30.4 - pathe: 1.1.1 - picocolors: 1.1.1 - std-env: 3.4.3 - strip-literal: 1.3.0 - tinybench: 2.5.1 - tinypool: 0.7.0 - vite: 4.5.3(@types/node@22.8.1)(terser@5.31.3) - vite-node: 0.34.6(@types/node@22.8.1)(terser@5.31.3) - why-is-node-running: 2.2.2 - transitivePeerDependencies: - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - - vitest@3.0.7(@types/debug@4.1.12)(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1): - dependencies: - '@vitest/expect': 3.0.7 - '@vitest/mocker': 3.0.7(vite@6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1)) - '@vitest/pretty-format': 3.0.7 - '@vitest/runner': 3.0.7 - '@vitest/snapshot': 3.0.7 - '@vitest/spy': 3.0.7 - '@vitest/utils': 3.0.7 - chai: 5.2.0 - debug: 4.4.0(supports-color@8.1.1) - expect-type: 1.1.0 magic-string: 0.30.17 - pathe: 2.0.3 - std-env: 3.8.0 + pathe: 1.1.2 + picocolors: 1.1.1 + std-env: 3.8.1 + strip-literal: 1.3.0 tinybench: 2.9.0 - tinyexec: 0.3.2 - tinypool: 1.0.2 - tinyrainbow: 2.0.0 - vite: 6.2.0(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1) - vite-node: 3.0.7(@types/node@22.8.1)(terser@5.31.3)(tsx@4.7.0)(yaml@2.4.1) + tinypool: 0.7.0 + vite: 4.5.9(@types/node@22.13.9)(terser@5.39.0) + vite-node: 0.34.6(@types/node@22.13.9)(terser@5.39.0) why-is-node-running: 2.3.0 - optionalDependencies: - '@types/debug': 4.1.12 - '@types/node': 22.8.1 transitivePeerDependencies: - - jiti - less - lightningcss - - msw - sass - - sass-embedded - stylus - sugarss - supports-color - terser - - tsx - - yaml vm-browserify@1.1.2: {} @@ -21172,11 +20431,11 @@ snapshots: wait-on@7.2.0(debug@4.4.0): dependencies: - axios: 1.7.2(debug@4.4.0) - joi: 17.13.1 + axios: 1.8.2(debug@4.4.0) + joi: 17.13.3 lodash: 4.17.21 minimist: 1.2.8 - rxjs: 7.8.1 + rxjs: 7.8.2 transitivePeerDependencies: - debug @@ -21188,7 +20447,7 @@ snapshots: dependencies: loose-envify: 1.4.0 - watchpack@2.4.1: + watchpack@2.4.2: dependencies: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 @@ -21201,48 +20460,15 @@ snapshots: webidl-conversions@4.0.2: {} - webpack-sources@3.2.3: {} + webpack-virtual-modules@0.6.2: {} - webpack-virtual-modules@0.5.0: {} - - webpack@5.93.0(esbuild@0.19.11): - dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.5 - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/wasm-edit': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.12.1 - acorn-import-attributes: 1.9.5(acorn@8.12.1) - browserslist: 4.23.2 - chrome-trace-event: 1.0.4 - enhanced-resolve: 5.17.1 - es-module-lexer: 1.5.4 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 3.3.0 - tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(esbuild@0.19.11)(webpack@5.93.0(esbuild@0.19.11)) - watchpack: 2.4.1 - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - - webrtc-adapter@8.2.3: + webrtc-adapter@9.0.1: dependencies: sdp: 3.2.0 websocket-driver@0.7.4: dependencies: - http-parser-js: 0.5.8 + http-parser-js: 0.5.9 safe-buffer: 5.2.1 websocket-extensions: 0.1.4 @@ -21252,7 +20478,7 @@ snapshots: dependencies: iconv-lite: 0.6.3 - whatwg-fetch@3.6.18: + whatwg-fetch@3.6.20: optional: true whatwg-url@5.0.0: @@ -21269,14 +20495,14 @@ snapshots: which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 - is-boolean-object: 1.2.1 + is-boolean-object: 1.2.2 is-number-object: 1.1.1 is-string: 1.1.1 is-symbol: 1.1.1 which-builtin-type@1.2.1: dependencies: - call-bound: 1.0.3 + call-bound: 1.0.4 function.prototype.name: 1.1.8 has-tostringtag: 1.0.2 is-async-function: 2.1.1 @@ -21284,7 +20510,7 @@ snapshots: is-finalizationregistry: 1.1.1 is-generator-function: 1.1.0 is-regex: 1.2.1 - is-weakref: 1.1.0 + is-weakref: 1.1.1 isarray: 2.0.5 which-boxed-primitive: 1.1.1 which-collection: 1.0.2 @@ -21301,8 +20527,18 @@ snapshots: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.8 - call-bound: 1.0.3 - for-each: 0.3.4 + call-bound: 1.0.4 + for-each: 0.3.5 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which-typed-array@1.1.19: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 gopd: 1.2.0 has-tostringtag: 1.0.2 @@ -21314,11 +20550,6 @@ snapshots: dependencies: isexe: 2.0.0 - why-is-node-running@2.2.2: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 - why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 @@ -21329,120 +20560,122 @@ snapshots: string-width: 4.2.3 optional: true + word-wrap@1.2.5: {} + wordwrap@1.0.0: {} - workbox-background-sync@7.0.0: + workbox-background-sync@7.3.0: dependencies: idb: 7.1.1 - workbox-core: 7.0.0 + workbox-core: 7.3.0 - workbox-broadcast-update@7.0.0: + workbox-broadcast-update@7.3.0: dependencies: - workbox-core: 7.0.0 + workbox-core: 7.3.0 - workbox-build@7.0.0(@types/babel__core@7.20.2): + workbox-build@7.3.0(@types/babel__core@7.20.5): dependencies: - '@apideck/better-ajv-errors': 0.3.6(ajv@8.12.0) - '@babel/core': 7.22.11 - '@babel/preset-env': 7.22.10(@babel/core@7.22.11) - '@babel/runtime': 7.24.5 - '@rollup/plugin-babel': 5.3.1(@babel/core@7.22.11)(@types/babel__core@7.20.2)(rollup@2.79.1) - '@rollup/plugin-node-resolve': 11.2.1(rollup@2.79.1) - '@rollup/plugin-replace': 2.4.2(rollup@2.79.1) + '@apideck/better-ajv-errors': 0.3.6(ajv@8.17.1) + '@babel/core': 7.26.9 + '@babel/preset-env': 7.26.9(@babel/core@7.26.9) + '@babel/runtime': 7.26.9 + '@rollup/plugin-babel': 5.3.1(@babel/core@7.26.9)(@types/babel__core@7.20.5)(rollup@2.79.2) + '@rollup/plugin-node-resolve': 15.3.1(rollup@2.79.2) + '@rollup/plugin-replace': 2.4.2(rollup@2.79.2) + '@rollup/plugin-terser': 0.4.4(rollup@2.79.2) '@surma/rollup-plugin-off-main-thread': 2.2.3 - ajv: 8.12.0 + ajv: 8.17.1 common-tags: 1.8.2 fast-json-stable-stringify: 2.1.0 fs-extra: 9.1.0 glob: 7.2.3 lodash: 4.17.21 pretty-bytes: 5.6.0 - rollup: 2.79.1 - rollup-plugin-terser: 7.0.2(rollup@2.79.1) + rollup: 2.79.2 source-map: 0.8.0-beta.0 stringify-object: 3.3.0 strip-comments: 2.0.1 tempy: 0.6.0 upath: 1.2.0 - workbox-background-sync: 7.0.0 - workbox-broadcast-update: 7.0.0 - workbox-cacheable-response: 7.0.0 - workbox-core: 7.0.0 - workbox-expiration: 7.0.0 - workbox-google-analytics: 7.0.0 - workbox-navigation-preload: 7.0.0 - workbox-precaching: 7.0.0 - workbox-range-requests: 7.0.0 - workbox-recipes: 7.0.0 - workbox-routing: 7.0.0 - workbox-strategies: 7.0.0 - workbox-streams: 7.0.0 - workbox-sw: 7.0.0 - workbox-window: 7.0.0 + workbox-background-sync: 7.3.0 + workbox-broadcast-update: 7.3.0 + workbox-cacheable-response: 7.3.0 + workbox-core: 7.3.0 + workbox-expiration: 7.3.0 + workbox-google-analytics: 7.3.0 + workbox-navigation-preload: 7.3.0 + workbox-precaching: 7.3.0 + workbox-range-requests: 7.3.0 + workbox-recipes: 7.3.0 + workbox-routing: 7.3.0 + workbox-strategies: 7.3.0 + workbox-streams: 7.3.0 + workbox-sw: 7.3.0 + workbox-window: 7.3.0 transitivePeerDependencies: - '@types/babel__core' - supports-color - workbox-cacheable-response@7.0.0: + workbox-cacheable-response@7.3.0: dependencies: - workbox-core: 7.0.0 + workbox-core: 7.3.0 - workbox-core@7.0.0: {} + workbox-core@7.3.0: {} - workbox-expiration@7.0.0: + workbox-expiration@7.3.0: dependencies: idb: 7.1.1 - workbox-core: 7.0.0 + workbox-core: 7.3.0 - workbox-google-analytics@7.0.0: + workbox-google-analytics@7.3.0: dependencies: - workbox-background-sync: 7.0.0 - workbox-core: 7.0.0 - workbox-routing: 7.0.0 - workbox-strategies: 7.0.0 + workbox-background-sync: 7.3.0 + workbox-core: 7.3.0 + workbox-routing: 7.3.0 + workbox-strategies: 7.3.0 - workbox-navigation-preload@7.0.0: + workbox-navigation-preload@7.3.0: dependencies: - workbox-core: 7.0.0 + workbox-core: 7.3.0 - workbox-precaching@7.0.0: + workbox-precaching@7.3.0: dependencies: - workbox-core: 7.0.0 - workbox-routing: 7.0.0 - workbox-strategies: 7.0.0 + workbox-core: 7.3.0 + workbox-routing: 7.3.0 + workbox-strategies: 7.3.0 - workbox-range-requests@7.0.0: + workbox-range-requests@7.3.0: dependencies: - workbox-core: 7.0.0 + workbox-core: 7.3.0 - workbox-recipes@7.0.0: + workbox-recipes@7.3.0: dependencies: - workbox-cacheable-response: 7.0.0 - workbox-core: 7.0.0 - workbox-expiration: 7.0.0 - workbox-precaching: 7.0.0 - workbox-routing: 7.0.0 - workbox-strategies: 7.0.0 + workbox-cacheable-response: 7.3.0 + workbox-core: 7.3.0 + workbox-expiration: 7.3.0 + workbox-precaching: 7.3.0 + workbox-routing: 7.3.0 + workbox-strategies: 7.3.0 - workbox-routing@7.0.0: + workbox-routing@7.3.0: dependencies: - workbox-core: 7.0.0 + workbox-core: 7.3.0 - workbox-strategies@7.0.0: + workbox-strategies@7.3.0: dependencies: - workbox-core: 7.0.0 + workbox-core: 7.3.0 - workbox-streams@7.0.0: + workbox-streams@7.3.0: dependencies: - workbox-core: 7.0.0 - workbox-routing: 7.0.0 + workbox-core: 7.3.0 + workbox-routing: 7.3.0 - workbox-sw@7.0.0: {} + workbox-sw@7.3.0: {} - workbox-window@7.0.0: + workbox-window@7.3.0: dependencies: - '@types/trusted-types': 2.0.3 - workbox-core: 7.0.0 + '@types/trusted-types': 2.0.7 + workbox-core: 7.3.0 wrap-ansi@6.2.0: dependencies: @@ -21476,20 +20709,20 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 3.0.7 - ws@5.2.3: + ws@5.2.4: dependencies: async-limiter: 1.0.1 - ws@6.2.2: + ws@6.2.3: dependencies: async-limiter: 1.0.1 - ws@7.4.6: + ws@7.5.10: optional: true - ws@8.11.0: {} + ws@8.17.1: {} - ws@8.18.0: {} + ws@8.18.1: {} xhr@2.6.0: dependencies: @@ -21502,9 +20735,9 @@ snapshots: xml-parse-from-string@1.0.1: optional: true - xml2js@0.4.23: + xml2js@0.5.0: dependencies: - sax: 1.3.0 + sax: 1.4.1 xmlbuilder: 11.0.1 optional: true @@ -21514,7 +20747,7 @@ snapshots: xmlhttprequest-ssl@1.6.3: optional: true - xmlhttprequest-ssl@2.0.0: {} + xmlhttprequest-ssl@2.1.2: {} xtend@4.0.2: {} @@ -21528,26 +20761,16 @@ snapshots: yaml@1.10.2: {} - yaml@2.4.1: {} + yaml@2.7.0: {} yargs-parser@20.2.9: {} yargs-parser@21.1.1: {} - yargs@16.2.0: - dependencies: - cliui: 7.0.4 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - yargs@17.7.2: dependencies: cliui: 8.0.1 - escalade: 3.1.2 + escalade: 3.2.0 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 @@ -21559,6 +20782,10 @@ snapshots: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 + yazl@2.5.1: + dependencies: + buffer-crc32: 0.2.13 + yeast@0.1.2: optional: true @@ -21571,12 +20798,12 @@ snapshots: yocto-queue@0.1.0: {} - yocto-queue@1.0.0: {} + yocto-queue@1.2.0: {} - zod@3.24.1: {} + zod@3.24.2: {} - zustand@3.6.5(react@18.2.0): + zustand@3.6.5(react@18.3.1): optionalDependencies: - react: 18.2.0 + react: 18.3.1 zwitch@2.0.4: {} diff --git a/renderer/buildMesherWorker.mjs b/renderer/buildMesherWorker.mjs index 2f9a4a02..d88297a5 100644 --- a/renderer/buildMesherWorker.mjs +++ b/renderer/buildMesherWorker.mjs @@ -22,7 +22,7 @@ const buildOptions = { }, platform: 'browser', entryPoints: [path.join(__dirname, './viewer/lib/mesher/mesher.ts')], - minify: true, + minify: !watch, logLevel: 'info', drop: !watch ? [ 'debugger' @@ -35,11 +35,15 @@ const buildOptions = { define: { 'process.env.BROWSER': '"true"', }, + loader: { + '.png': 'dataurl', + '.obj': 'text' + }, plugins: [ ...mesherSharedPlugins, { name: 'external-json', - setup (build) { + setup(build) { build.onResolve({ filter: /\.json$/ }, args => { const fileName = args.path.split('/').pop().replace('.json', '') if (args.resolveDir.includes('minecraft-data')) { diff --git a/renderer/playground.html b/renderer/playground.html index ec4c0f33..258426fe 100644 --- a/renderer/playground.html +++ b/renderer/playground.html @@ -11,11 +11,17 @@ html, body { height: 100%; + touch-action: none; margin: 0; padding: 0; } + * { + user-select: none; + -webkit-user-select: none; + } + canvas { height: 100%; width: 100%; diff --git a/renderer/playground/allEntitiesDebug.ts b/renderer/playground/allEntitiesDebug.ts new file mode 100644 index 00000000..5bc56ca6 --- /dev/null +++ b/renderer/playground/allEntitiesDebug.ts @@ -0,0 +1,170 @@ +import { EntityMesh, rendererSpecialHandled, EntityDebugFlags } from '../viewer/three/entity/EntityMesh' + +export const displayEntitiesDebugList = (version: string) => { + // Create results container + const container = document.createElement('div') + container.style.cssText = ` + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + max-height: 90vh; + overflow-y: auto; + background: rgba(0,0,0,0.8); + color: white; + padding: 20px; + border-radius: 8px; + font-family: monospace; + min-width: 400px; + z-index: 1000; + ` + document.body.appendChild(container) + + // Add title + const title = document.createElement('h2') + title.textContent = 'Minecraft Entity Support' + title.style.cssText = 'margin-top: 0; text-align: center;' + container.appendChild(title) + + // Test entities + const results: Array<{ + entity: string; + supported: boolean; + type?: 'obj' | 'bedrock' | 'special'; + mappedFrom?: string; + textureMap?: boolean; + errors?: string[]; + }> = [] + const { mcData } = window + const entityNames = Object.keys(mcData.entitiesArray.reduce((acc, entity) => { + acc[entity.name] = true + return acc + }, {})) + + // Add loading indicator + const loading = document.createElement('div') + loading.textContent = 'Testing entities...' + loading.style.textAlign = 'center' + container.appendChild(loading) + + for (const entity of entityNames) { + const debugFlags: EntityDebugFlags = {} + + if (rendererSpecialHandled.includes(entity)) { + results.push({ + entity, + supported: true, + type: 'special', + }) + continue + } + + try { + + const { mesh: entityMesh } = new EntityMesh(version, entity, undefined, {}, debugFlags) + // find the most distant pos child + window.objects ??= {} + window.objects[entity] = entityMesh + + results.push({ + entity, + supported: !!debugFlags.type || rendererSpecialHandled.includes(entity), + type: debugFlags.type, + mappedFrom: debugFlags.tempMap, + textureMap: debugFlags.textureMap, + errors: debugFlags.errors + }) + } catch (e) { + console.error(e) + results.push({ + entity, + supported: false, + mappedFrom: debugFlags.tempMap + }) + } + } + + // Remove loading indicator + loading.remove() + + const createSection = (title: string, items: any[], filter: (item: any) => boolean) => { + const section = document.createElement('div') + section.style.marginBottom = '20px' + + const sectionTitle = document.createElement('h3') + sectionTitle.textContent = title + sectionTitle.style.textAlign = 'center' + section.appendChild(sectionTitle) + + const list = document.createElement('ul') + list.style.cssText = 'padding-left: 20px; list-style-type: none; margin: 0;' + + const filteredItems = items.filter(filter) + for (const item of filteredItems) { + const listItem = document.createElement('li') + listItem.style.cssText = 'line-height: 1.4; margin: 8px 0;' + + const entityName = document.createElement('strong') + entityName.style.cssText = 'user-select: text;-webkit-user-select: text;' + entityName.textContent = item.entity + listItem.appendChild(entityName) + + let text = '' + if (item.mappedFrom) { + text += ` -> ${item.mappedFrom}` + } + if (item.type) { + text += ` - ${item.type}` + } + if (item.textureMap) { + text += ' ⚠️' + } + if (item.errors) { + text += ' ❌' + } + + listItem.appendChild(document.createTextNode(text)) + list.appendChild(listItem) + } + + section.appendChild(list) + return { section, count: filteredItems.length } + } + + // Sort results - bedrock first + results.sort((a, b) => { + if (a.type === 'bedrock' && b.type !== 'bedrock') return -1 + if (a.type !== 'bedrock' && b.type === 'bedrock') return 1 + return a.entity.localeCompare(b.entity) + }) + + // Add sections + const sections = [ + { + title: '❌ Unsupported Entities', + filter: (r: any) => !r.supported && !r.mappedFrom + }, + { + title: '⚠️ Partially Supported Entities', + filter: (r: any) => r.mappedFrom + }, + { + title: '✅ Supported Entities', + filter: (r: any) => r.supported && !r.mappedFrom + } + ] + + for (const { title, filter } of sections) { + const { section, count } = createSection(title, results, filter) + if (count > 0) { + container.appendChild(section) + } + } + + // log object with errors per entity + const errors = results.filter(r => r.errors).map(r => ({ + entity: r.entity, + errors: r.errors + })) + console.log(errors) +} diff --git a/renderer/playground/scenes/allEntities.ts b/renderer/playground/scenes/allEntities.ts index 68714cf8..281af807 100644 --- a/renderer/playground/scenes/allEntities.ts +++ b/renderer/playground/scenes/allEntities.ts @@ -1,6 +1,6 @@ -//@ts-nocheck import { BasePlaygroundScene } from '../baseScene' import { EntityDebugFlags, EntityMesh, rendererSpecialHandled } from '../../viewer/three/entity/EntityMesh' +import { displayEntitiesDebugList } from '../allEntitiesDebug' export default class AllEntities extends BasePlaygroundScene { continuousRender = false @@ -8,159 +8,6 @@ export default class AllEntities extends BasePlaygroundScene { async initData () { await super.initData() - - // Create results container - const container = document.createElement('div') - container.style.cssText = ` - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - max-height: 90vh; - overflow-y: auto; - background: rgba(0,0,0,0.8); - color: white; - padding: 20px; - border-radius: 8px; - font-family: monospace; - min-width: 400px; - ` - document.body.appendChild(container) - - // Add title - const title = document.createElement('h2') - title.textContent = 'Minecraft Entity Support' - title.style.cssText = 'margin-top: 0; text-align: center;' - container.appendChild(title) - - // Test entities - const results: Array<{ - entity: string; - supported: boolean; - type?: 'obj' | 'bedrock'; - mappedFrom?: string; - textureMap?: boolean; - errors?: string[]; - }> = [] - const { mcData } = window - const entityNames = Object.keys(mcData.entitiesArray.reduce((acc, entity) => { - acc[entity.name] = true - return acc - }, {})) - - // Add loading indicator - const loading = document.createElement('div') - loading.textContent = 'Testing entities...' - loading.style.textAlign = 'center' - container.appendChild(loading) - - for (const entity of entityNames) { - const debugFlags: EntityDebugFlags = {} - - try { - // eslint-disable-next-line no-new - new EntityMesh(this.version, entity, viewer.world, {}, debugFlags) - - results.push({ - entity, - supported: !!debugFlags.type || rendererSpecialHandled.includes(entity), - type: debugFlags.type, - mappedFrom: debugFlags.tempMap, - textureMap: debugFlags.textureMap, - errors: debugFlags.errors - }) - } catch (e) { - console.error(e) - results.push({ - entity, - supported: false, - mappedFrom: debugFlags.tempMap - }) - } - } - - // Remove loading indicator - loading.remove() - - const createSection = (title: string, items: any[], filter: (item: any) => boolean) => { - const section = document.createElement('div') - section.style.marginBottom = '20px' - - const sectionTitle = document.createElement('h3') - sectionTitle.textContent = title - sectionTitle.style.textAlign = 'center' - section.appendChild(sectionTitle) - - const list = document.createElement('ul') - list.style.cssText = 'padding-left: 20px; list-style-type: none; margin: 0;' - - const filteredItems = items.filter(filter) - for (const item of filteredItems) { - const listItem = document.createElement('li') - listItem.style.cssText = 'line-height: 1.4; margin: 8px 0;' - - const entityName = document.createElement('strong') - entityName.style.cssText = 'user-select: text;-webkit-user-select: text;' - entityName.textContent = item.entity - listItem.appendChild(entityName) - - let text = '' - if (item.mappedFrom) { - text += ` -> ${item.mappedFrom}` - } - if (item.type) { - text += ` - ${item.type}` - } - if (item.textureMap) { - text += ' ⚠️' - } - if (item.errors) { - text += ' ❌' - } - - listItem.appendChild(document.createTextNode(text)) - list.appendChild(listItem) - } - - section.appendChild(list) - return { section, count: filteredItems.length } - } - - // Sort results - bedrock first - results.sort((a, b) => { - if (a.type === 'bedrock' && b.type !== 'bedrock') return -1 - if (a.type !== 'bedrock' && b.type === 'bedrock') return 1 - return a.entity.localeCompare(b.entity) - }) - - // Add sections - const sections = [ - { - title: '❌ Unsupported Entities', - filter: (r: any) => !r.supported && !r.mappedFrom - }, - { - title: '⚠️ Partially Supported Entities', - filter: (r: any) => r.mappedFrom - }, - { - title: '✅ Supported Entities', - filter: (r: any) => r.supported && !r.mappedFrom - } - ] - - for (const { title, filter } of sections) { - const { section, count } = createSection(title, results, filter) - if (count > 0) { - container.appendChild(section) - } - } - - // log object with errors per entity - const errors = results.filter(r => r.errors).map(r => ({ - entity: r.entity, - errors: r.errors - })) - console.log(errors) + displayEntitiesDebugList(this.version) } } diff --git a/renderer/playground/shared.ts b/renderer/playground/shared.ts index ba58a57f..9d12fae9 100644 --- a/renderer/playground/shared.ts +++ b/renderer/playground/shared.ts @@ -65,7 +65,7 @@ function getAllMethods (obj) { return [...methods] as string[] } -export const delayedIterator = async (arr: T[], delay: number, exec: (item: T, index: number) => void, chunkSize = 1) => { +export const delayedIterator = async (arr: T[], delay: number, exec: (item: T, index: number) => Promise, chunkSize = 1) => { // if delay is 0 then don't use setTimeout for (let i = 0; i < arr.length; i += chunkSize) { if (delay) { @@ -74,6 +74,6 @@ export const delayedIterator = async (arr: T[], delay: number, exec: (item: setTimeout(resolve, delay) }) } - exec(arr[i], i) + await exec(arr[i], i) } } diff --git a/renderer/rsbuildSharedConfig.ts b/renderer/rsbuildSharedConfig.ts index c39c4454..45da30b1 100644 --- a/renderer/rsbuildSharedConfig.ts +++ b/renderer/rsbuildSharedConfig.ts @@ -2,6 +2,7 @@ import { defineConfig, ModifyRspackConfigUtils } from '@rsbuild/core'; import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill'; import { pluginReact } from '@rsbuild/plugin-react'; import path from 'path' +import fs from 'fs' export const appAndRendererSharedConfig = () => defineConfig({ dev: { @@ -60,18 +61,24 @@ export const appAndRendererSharedConfig = () => defineConfig({ ], tools: { rspack (config, helpers) { + const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf8')) + const hasFileProtocol = Object.values(packageJson.pnpm.overrides).some((dep) => (dep as string).startsWith('file:')) + if (hasFileProtocol) { + // enable node_modules watching + config.watchOptions.ignored = /\.git/ + } rspackViewerConfig(config, helpers) } }, }) export const rspackViewerConfig = (config, { appendPlugins, addRules, rspack }: ModifyRspackConfigUtils) => { - appendPlugins(new rspack.NormalModuleReplacementPlugin(/data/, (resource) => { + appendPlugins(new rspack.NormalModuleReplacementPlugin(/data|prismarine-physics/, (resource) => { let absolute: string const request = resource.request.replaceAll('\\', '/') absolute = path.join(resource.context, request).replaceAll('\\', '/') - if (request.includes('minecraft-data/data/pc/1.')) { - console.log('Error: incompatible resource', request, resource.contextInfo.issuer) + if (request.includes('minecraft-data/data/pc/1.') || request.includes('prismarine-physics')) { + console.log('Error: incompatible resource', request, 'from', resource.contextInfo.issuer) process.exit(1) // throw new Error(`${resource.request} was requested by ${resource.contextInfo.issuer}`) } @@ -101,6 +108,10 @@ export const rspackViewerConfig = (config, { appendPlugins, addRules, rspack }: { test: /\.txt$/, type: 'asset/source', + }, + { + test: /\.log$/, + type: 'asset/source', } ]) config.ignoreWarnings = [ diff --git a/renderer/viewer/baseGraphicsBackend.ts b/renderer/viewer/baseGraphicsBackend.ts index 79607695..486c930f 100644 --- a/renderer/viewer/baseGraphicsBackend.ts +++ b/renderer/viewer/baseGraphicsBackend.ts @@ -1,15 +1,27 @@ -import { RendererReactiveState } from '../../src/appViewer' +import { proxy } from 'valtio' +import { NonReactiveState, RendererReactiveState } from '../../src/appViewer' -export const getDefaultRendererState = (): RendererReactiveState => { +export const getDefaultRendererState = (): { + reactive: RendererReactiveState + nonReactive: NonReactiveState +} => { return { - world: { - chunksLoaded: [], - chunksTotalNumber: 0, - allChunksLoaded: true, - mesherWork: false, - intersectMedia: null - }, - renderer: '', - preventEscapeMenu: false + reactive: proxy({ + world: { + chunksLoaded: new Set(), + heightmaps: new Map(), + allChunksLoaded: true, + mesherWork: false, + intersectMedia: null + }, + renderer: '', + preventEscapeMenu: false + }), + nonReactive: { + world: { + chunksLoaded: new Set(), + chunksTotalNumber: 0, + } + } } } diff --git a/renderer/viewer/lib/basePlayerState.ts b/renderer/viewer/lib/basePlayerState.ts index 3384f0b4..9cf1350a 100644 --- a/renderer/viewer/lib/basePlayerState.ts +++ b/renderer/viewer/lib/basePlayerState.ts @@ -1,103 +1,87 @@ -import { EventEmitter } from 'events' -import { Vec3 } from 'vec3' -import TypedEmitter from 'typed-emitter' import { ItemSelector } from 'mc-assets/dist/itemDefinitions' +import { GameMode, Team } from 'mineflayer' import { proxy } from 'valtio' -import { GameMode } from 'mineflayer' -import { HandItemBlock } from '../three/holdingBlock' +import type { HandItemBlock } from '../three/holdingBlock' export type MovementState = 'NOT_MOVING' | 'WALKING' | 'SPRINTING' | 'SNEAKING' export type ItemSpecificContextProperties = Partial> +export type CameraPerspective = 'first_person' | 'third_person_back' | 'third_person_front' +export type BlockShape = { position: any; width: any; height: any; depth: any; } +export type BlocksShapes = BlockShape[] -export type PlayerStateEvents = { - heldItemChanged: (item: HandItemBlock | undefined, isLeftHand: boolean) => void -} +// edit src/mineflayer/playerState.ts for implementation of player state from mineflayer +export const getInitialPlayerState = () => proxy({ + playerSkin: undefined as string | undefined, + inWater: false, + waterBreathing: false, + backgroundColor: [0, 0, 0] as [number, number, number], + ambientLight: 0, + directionalLight: 0, + eyeHeight: 0, + gameMode: undefined as GameMode | undefined, + lookingAtBlock: undefined as { + x: number + y: number + z: number + face?: number + shapes: BlocksShapes + } | undefined, + diggingBlock: undefined as { + x: number + y: number + z: number + stage: number + face?: number + mergedShape: BlockShape | undefined + } | undefined, + movementState: 'NOT_MOVING' as MovementState, + onGround: true, + sneaking: false, + flying: false, + sprinting: false, + itemUsageTicks: 0, + username: '', + onlineMode: false, + lightingDisabled: false, + shouldHideHand: false, + heldItemMain: undefined as HandItemBlock | undefined, + heldItemOff: undefined as HandItemBlock | undefined, + perspective: 'first_person' as CameraPerspective, + onFire: false, -export interface IPlayerState { - getEyeHeight(): number - getMovementState(): MovementState - getVelocity(): Vec3 - isOnGround(): boolean - isSneaking(): boolean - isFlying(): boolean - isSprinting (): boolean - getItemUsageTicks?(): number - getPosition(): Vec3 - // isUsingItem?(): boolean - getHeldItem?(isLeftHand: boolean): HandItemBlock | undefined - username?: string - onlineMode?: boolean + cameraSpectatingEntity: undefined as number | undefined, - events: TypedEmitter + team: undefined as Team | undefined, +}) - reactive: { - playerSkin: string | undefined - inWater: boolean - backgroundColor: [number, number, number] - ambientLight: number - directionalLight: number - gameMode?: GameMode - } -} - -export class BasePlayerState implements IPlayerState { - reactive = proxy({ - playerSkin: undefined as string | undefined, - inWater: false, - backgroundColor: [0, 0, 0] as [number, number, number], - ambientLight: 0, - directionalLight: 0, - }) - protected movementState: MovementState = 'NOT_MOVING' - protected velocity = new Vec3(0, 0, 0) - protected onGround = true - protected sneaking = false - protected flying = false - protected sprinting = false - readonly events = new EventEmitter() as TypedEmitter - - getEyeHeight (): number { - return 1.62 - } - - getMovementState (): MovementState { - return this.movementState - } - - getVelocity (): Vec3 { - return this.velocity - } - - isOnGround (): boolean { - return this.onGround - } - - isSneaking (): boolean { - return this.sneaking - } - - isFlying (): boolean { - return this.flying - } - - isSprinting (): boolean { - return this.sprinting - } - - getPosition (): Vec3 { - return new Vec3(0, 0, 0) - } - - // For testing purposes - setState (state: Partial<{ - movementState: MovementState - velocity: Vec3 - onGround: boolean - sneaking: boolean - flying: boolean - sprinting: boolean - }>) { - Object.assign(this, state) +export const getPlayerStateUtils = (reactive: PlayerStateReactive) => ({ + isSpectator () { + return reactive.gameMode === 'spectator' + }, + isSpectatingEntity () { + return reactive.cameraSpectatingEntity !== undefined && reactive.gameMode === 'spectator' + }, + isThirdPerson () { + if ((this as PlayerStateUtils).isSpectatingEntity()) return false + return reactive.perspective === 'third_person_back' || reactive.perspective === 'third_person_front' + } +}) + +export const getInitialPlayerStateRenderer = () => ({ + reactive: getInitialPlayerState() +}) + +export type PlayerStateReactive = ReturnType +export type PlayerStateUtils = ReturnType + +export type PlayerStateRenderer = PlayerStateReactive + +export const getItemSelector = (playerState: PlayerStateRenderer, specificProperties: ItemSpecificContextProperties, item?: import('prismarine-item').Item) => { + return { + ...specificProperties, + 'minecraft:date': new Date(), + // "minecraft:context_dimension": bot.entityp, + // 'minecraft:time': bot.time.timeOfDay / 24_000, } } diff --git a/renderer/viewer/lib/createPlayerObject.ts b/renderer/viewer/lib/createPlayerObject.ts new file mode 100644 index 00000000..836c8062 --- /dev/null +++ b/renderer/viewer/lib/createPlayerObject.ts @@ -0,0 +1,55 @@ +import { PlayerObject, PlayerAnimation } from 'skinview3d' +import * as THREE from 'three' +import { WalkingGeneralSwing } from '../three/entity/animations' +import { loadSkinImage, stevePngUrl } from './utils/skins' + +export type PlayerObjectType = PlayerObject & { + animation?: PlayerAnimation + realPlayerUuid: string + realUsername: string +} + +export function createPlayerObject (options: { + username?: string + uuid?: string + scale?: number +}): { + playerObject: PlayerObjectType + wrapper: THREE.Group + } { + const wrapper = new THREE.Group() + const playerObject = new PlayerObject() as PlayerObjectType + + playerObject.realPlayerUuid = options.uuid ?? '' + playerObject.realUsername = options.username ?? '' + playerObject.position.set(0, 16, 0) + + // fix issues with starfield + playerObject.traverse((obj) => { + if (obj instanceof THREE.Mesh && obj.material instanceof THREE.MeshStandardMaterial) { + obj.material.transparent = true + } + }) + + wrapper.add(playerObject as any) + const scale = options.scale ?? (1 / 16) + wrapper.scale.set(scale, scale, scale) + wrapper.rotation.set(0, Math.PI, 0) + + // Set up animation + playerObject.animation = new WalkingGeneralSwing() + ;(playerObject.animation as WalkingGeneralSwing).isMoving = false + playerObject.animation.update(playerObject, 0) + + return { playerObject, wrapper } +} + +export const applySkinToPlayerObject = async (playerObject: PlayerObjectType, skinUrl: string) => { + return loadSkinImage(skinUrl || stevePngUrl).then(({ canvas }) => { + const skinTexture = new THREE.CanvasTexture(canvas) + skinTexture.magFilter = THREE.NearestFilter + skinTexture.minFilter = THREE.NearestFilter + skinTexture.needsUpdate = true + playerObject.skin.map = skinTexture as any + }).catch(console.error) +} diff --git a/renderer/viewer/lib/guiRenderer.ts b/renderer/viewer/lib/guiRenderer.ts index 2360e104..709941dc 100644 --- a/renderer/viewer/lib/guiRenderer.ts +++ b/renderer/viewer/lib/guiRenderer.ts @@ -9,10 +9,6 @@ import { makeTextureAtlas } from 'mc-assets/dist/atlasCreator' import { proxy, ref } from 'valtio' import { getItemDefinition } from 'mc-assets/dist/itemDefinitions' -export const activeGuiAtlas = proxy({ - atlas: null as null | { json, image }, -}) - export const getNonFullBlocksModels = () => { let version = appViewer.resourcesManager.currentResources!.version ?? 'latest' if (versionToNumber(version) < versionToNumber('1.13')) version = '1.13' @@ -47,6 +43,8 @@ export const getNonFullBlocksModels = () => { if (!model?.elements?.length) return const isFullBlock = model.elements.length === 1 && arrEqual(model.elements[0].from, [0, 0, 0]) && arrEqual(model.elements[0].to, [16, 16, 16]) if (isFullBlock) return + const hasBetterPrerender = assetsParser.blockModelsStore.data.latest[`item/${name}`]?.textures?.['layer0']?.startsWith('invsprite_') + if (hasBetterPrerender) return model['display'] ??= {} model['display']['gui'] ??= standardGuiDisplay blockModelsResolved[name] = model @@ -66,7 +64,6 @@ export const getNonFullBlocksModels = () => { handledItemsWithDefinitions.add(name) } if (resolvedModel?.elements) { - let hasStandardDisplay = true if (resolvedModel['display']?.gui) { hasStandardDisplay = @@ -120,18 +117,18 @@ const RENDER_SIZE = 64 const generateItemsGui = async (models: Record, isItems = false) => { const { currentResources } = appViewer.resourcesManager - const img = await getLoadedImage(isItems ? currentResources!.itemsAtlasParser.latestImage : currentResources!.blocksAtlasParser.latestImage) + const imgBitmap = isItems ? currentResources!.itemsAtlasImage : currentResources!.blocksAtlasImage const canvasTemp = document.createElement('canvas') - canvasTemp.width = img.width - canvasTemp.height = img.height + canvasTemp.width = imgBitmap.width + canvasTemp.height = imgBitmap.height canvasTemp.style.imageRendering = 'pixelated' const ctx = canvasTemp.getContext('2d')! ctx.imageSmoothingEnabled = false - ctx.drawImage(img, 0, 0) + ctx.drawImage(imgBitmap, 0, 0) - const atlasParser = isItems ? currentResources!.itemsAtlasParser : currentResources!.blocksAtlasParser + const atlasParser = isItems ? appViewer.resourcesManager.itemsAtlasParser : appViewer.resourcesManager.blocksAtlasParser const textureAtlas = new TextureAtlas( - ctx.getImageData(0, 0, img.width, img.height), + ctx.getImageData(0, 0, imgBitmap.width, imgBitmap.height), Object.fromEntries(Object.entries(atlasParser.atlas.latest.textures).map(([key, value]) => { return [key, [ value.u, @@ -145,6 +142,7 @@ const generateItemsGui = async (models: Record, isIt const PREVIEW_ID = Identifier.parse('preview:preview') const PREVIEW_DEFINITION = new BlockDefinition({ '': { model: PREVIEW_ID.toString() } }, undefined) + let textureWasRequested = false let modelData: any let currentModelName: string | undefined const resources: ItemRendererResources = { @@ -155,6 +153,7 @@ const generateItemsGui = async (models: Record, isIt return null }, getTextureUV (texture) { + textureWasRequested = true return textureAtlas.getTextureUV(texture.toString().replace('minecraft:', '').replace('block/', '').replace('item/', '').replace('blocks/', '').replace('items/', '') as any) }, getTextureAtlas () { @@ -203,6 +202,7 @@ const generateItemsGui = async (models: Record, isIt const renderer = new ItemRenderer(gl, item, resources, { display_context: 'gui' }) const missingTextures = new Set() for (const [modelName, model] of Object.entries(models)) { + textureWasRequested = false if (includeOnly.length && !includeOnly.includes(modelName)) continue const patchMissingTextures = () => { @@ -224,6 +224,7 @@ const generateItemsGui = async (models: Record, isIt if (!modelData) continue renderer.setItem(item, { display_context: 'gui' }) renderer.drawItem() + if (!textureWasRequested) continue const url = canvas.toDataURL() // eslint-disable-next-line no-await-in-loop const img = await getLoadedImage(url) @@ -237,6 +238,9 @@ const generateItemsGui = async (models: Record, isIt return images } +/** + * @mainThread + */ const generateAtlas = async (images: Record) => { const atlas = makeTextureAtlas({ input: Object.keys(images), @@ -254,9 +258,9 @@ const generateAtlas = async (images: Record) => { // a.download = 'blocks_atlas.png' // a.click() - activeGuiAtlas.atlas = { + appViewer.resourcesManager.currentResources!.guiAtlas = { json: atlas.json, - image: ref(await getLoadedImage(atlas.canvas.toDataURL())), + image: await createImageBitmap(atlas.canvas), } return atlas @@ -273,5 +277,6 @@ export const generateGuiAtlas = async () => { const itemImages = await generateItemsGui(itemsModelsResolved, true) console.timeEnd('generate items gui atlas') await generateAtlas({ ...blockImages, ...itemImages }) + appViewer.resourcesManager.currentResources!.guiAtlasVersion++ // await generateAtlas(blockImages) } diff --git a/renderer/viewer/lib/mesher/mesher.ts b/renderer/viewer/lib/mesher/mesher.ts index 42432a6d..a063d77f 100644 --- a/renderer/viewer/lib/mesher/mesher.ts +++ b/renderer/viewer/lib/mesher/mesher.ts @@ -2,6 +2,7 @@ import { Vec3 } from 'vec3' import { World } from './world' import { getSectionGeometry, setBlockStatesData as setMesherData } from './models' import { BlockStateModelInfo } from './shared' +import { INVISIBLE_BLOCKS } from './worldConstants' globalThis.structuredClone ??= (value) => JSON.parse(JSON.stringify(value)) @@ -53,7 +54,7 @@ function setSectionDirty (pos, value = true) { const key = sectionKey(x, y, z) if (!value) { dirtySections.delete(key) - postMessage({ type: 'sectionFinished', key }) + postMessage({ type: 'sectionFinished', key, workerIndex }) return } @@ -61,7 +62,7 @@ function setSectionDirty (pos, value = true) { if (chunk?.getSection(pos)) { dirtySections.set(key, (dirtySections.get(key) || 0) + 1) } else { - postMessage({ type: 'sectionFinished', key }) + postMessage({ type: 'sectionFinished', key, workerIndex }) } } @@ -76,6 +77,7 @@ const handleMessage = data => { if (data.type === 'mcData') { globalVar.mcData = data.mcData + globalVar.loadedData = data.mcData } if (data.config) { @@ -122,12 +124,12 @@ const handleMessage = data => { case 'blockUpdate': { const loc = new Vec3(data.pos.x, data.pos.y, data.pos.z).floored() if (data.stateId !== undefined && data.stateId !== null) { - world.setBlockStateId(loc, data.stateId) + world?.setBlockStateId(loc, data.stateId) } const chunkKey = `${Math.floor(loc.x / 16) * 16},${Math.floor(loc.z / 16) * 16}` if (data.customBlockModels) { - world.customBlockModels.set(chunkKey, data.customBlockModels) + world?.customBlockModels.set(chunkKey, data.customBlockModels) } break } @@ -137,8 +139,40 @@ const handleMessage = data => { dirtySections = new Map() // todo also remove cached globalVar.mcData = null + globalVar.loadedData = null allDataReady = false + break + } + case 'getCustomBlockModel': { + const pos = new Vec3(data.pos.x, data.pos.y, data.pos.z) + const chunkKey = `${Math.floor(pos.x / 16) * 16},${Math.floor(pos.z / 16) * 16}` + const customBlockModel = world.customBlockModels.get(chunkKey)?.[`${pos.x},${pos.y},${pos.z}`] + global.postMessage({ type: 'customBlockModel', chunkKey, customBlockModel }) + break + } + case 'getHeightmap': { + const heightmap = new Uint8Array(256) + + const blockPos = new Vec3(0, 0, 0) + for (let z = 0; z < 16; z++) { + for (let x = 0; x < 16; x++) { + const blockX = x + data.x + const blockZ = z + data.z + blockPos.x = blockX + blockPos.z = blockZ + blockPos.y = world.config.worldMaxY + let block = world.getBlock(blockPos) + while (block && INVISIBLE_BLOCKS.has(block.name) && blockPos.y > world.config.worldMinY) { + blockPos.y -= 1 + block = world.getBlock(blockPos) + } + const index = z * 16 + x + heightmap[index] = block ? blockPos.y : 0 + } + } + postMessage({ type: 'heightmap', key: `${Math.floor(data.x / 16)},${Math.floor(data.z / 16)}`, heightmap }) + break } // No default diff --git a/renderer/viewer/lib/mesher/models.ts b/renderer/viewer/lib/mesher/models.ts index dd2952fb..aca47e15 100644 --- a/renderer/viewer/lib/mesher/models.ts +++ b/renderer/viewer/lib/mesher/models.ts @@ -2,7 +2,7 @@ import { Vec3 } from 'vec3' import worldBlockProvider, { WorldBlockProvider } from 'mc-assets/dist/worldBlockProvider' import legacyJson from '../../../../src/preflatMap.json' import { BlockType } from '../../../playground/shared' -import { World, BlockModelPartsResolved, WorldBlock as Block } from './world' +import { World, BlockModelPartsResolved, WorldBlock as Block, WorldBlock } from './world' import { BlockElement, buildRotationMatrix, elemFaces, matmul3, matmulmat3, vecadd3, vecsub3 } from './modelsGeometryCommon' import { INVISIBLE_BLOCKS } from './worldConstants' import { MesherGeometryOutput, HighestBlockInfo } from './shared' @@ -103,7 +103,8 @@ function tintToGl (tint) { return [r / 255, g / 255, b / 255] } -function getLiquidRenderHeight (world, block, type, pos) { +function getLiquidRenderHeight (world: World, block: WorldBlock | null, type: number, pos: Vec3, isWater: boolean, isRealWater: boolean) { + if ((isWater && !isRealWater) || (block && isBlockWaterlogged(block))) return 8 / 9 if (!block || block.type !== type) return 1 / 9 if (block.metadata === 0) { // source block const blockAbove = world.getBlock(pos.offset(0, 1, 0)) @@ -124,12 +125,19 @@ const isCube = (block: Block) => { })) } -function renderLiquid (world: World, cursor: Vec3, texture: any | undefined, type: number, biome: string, water: boolean, attr: Record) { +const getVec = (v: Vec3, dir: Vec3) => { + for (const coord of ['x', 'y', 'z']) { + if (Math.abs(dir[coord]) > 0) v[coord] = 0 + } + return v.plus(dir) +} + +function renderLiquid (world: World, cursor: Vec3, texture: any | undefined, type: number, biome: string, water: boolean, attr: MesherGeometryOutput, isRealWater: boolean) { const heights: number[] = [] for (let z = -1; z <= 1; z++) { for (let x = -1; x <= 1; x++) { const pos = cursor.offset(x, 0, z) - heights.push(getLiquidRenderHeight(world, world.getBlock(pos), type, pos)) + heights.push(getLiquidRenderHeight(world, world.getBlock(pos), type, pos, water, isRealWater)) } } const cornerHeights = [ @@ -141,15 +149,14 @@ function renderLiquid (world: World, cursor: Vec3, texture: any | undefined, typ // eslint-disable-next-line guard-for-in for (const face in elemFaces) { - const { dir, corners } = elemFaces[face] + const { dir, corners, mask1, mask2 } = elemFaces[face] const isUp = dir[1] === 1 const neighborPos = cursor.offset(...dir as [number, number, number]) const neighbor = world.getBlock(neighborPos) if (!neighbor) continue - if (neighbor.type === type) continue - const isGlass = neighbor.name.includes('glass') - if ((isCube(neighbor) && !isUp) || neighbor.material === 'plant' || neighbor.getProperties().waterlogged) continue + if (neighbor.type === type || (water && (neighbor.name === 'water' || isBlockWaterlogged(neighbor)))) continue + if (isCube(neighbor) && !isUp) continue let tint = [1, 1, 1] if (water) { @@ -180,16 +187,44 @@ function renderLiquid (world: World, cursor: Vec3, texture: any | undefined, typ const { su } = texture const { sv } = texture + // Get base light value for the face + const baseLight = world.getLight(neighborPos, undefined, undefined, water ? 'water' : 'lava') / 15 + for (const pos of corners) { const height = cornerHeights[pos[2] * 2 + pos[0]] - attr.t_positions.push( - (pos[0] ? 0.999 : 0.001) + (cursor.x & 15) - 8, - (pos[1] ? height - 0.001 : 0.001) + (cursor.y & 15) - 8, - (pos[2] ? 0.999 : 0.001) + (cursor.z & 15) - 8 + const OFFSET = 0.0001 + attr.t_positions!.push( + (pos[0] ? 1 - OFFSET : OFFSET) + (cursor.x & 15) - 8, + (pos[1] ? height - OFFSET : OFFSET) + (cursor.y & 15) - 8, + (pos[2] ? 1 - OFFSET : OFFSET) + (cursor.z & 15) - 8 ) - attr.t_normals.push(...dir) - attr.t_uvs.push(pos[3] * su + u, pos[4] * sv * (pos[1] ? 1 : height) + v) - attr.t_colors.push(tint[0], tint[1], tint[2]) + attr.t_normals!.push(...dir) + attr.t_uvs!.push(pos[3] * su + u, pos[4] * sv * (pos[1] ? 1 : height) + v) + + let cornerLightResult = baseLight + if (world.config.smoothLighting) { + const dx = pos[0] * 2 - 1 + const dy = pos[1] * 2 - 1 + const dz = pos[2] * 2 - 1 + const cornerDir: [number, number, number] = [dx, dy, dz] + const side1Dir: [number, number, number] = [dx * mask1[0], dy * mask1[1], dz * mask1[2]] + const side2Dir: [number, number, number] = [dx * mask2[0], dy * mask2[1], dz * mask2[2]] + + const dirVec = new Vec3(...dir as [number, number, number]) + + const side1LightDir = getVec(new Vec3(...side1Dir), dirVec) + const side1Light = world.getLight(cursor.plus(side1LightDir)) / 15 + const side2DirLight = getVec(new Vec3(...side2Dir), dirVec) + const side2Light = world.getLight(cursor.plus(side2DirLight)) / 15 + const cornerLightDir = getVec(new Vec3(...cornerDir), dirVec) + const cornerLight = world.getLight(cursor.plus(cornerLightDir)) / 15 + // interpolate + const lights = [side1Light, side2Light, cornerLight, baseLight] + cornerLightResult = lights.reduce((acc, cur) => acc + cur, 0) / lights.length + } + + // Apply light value to tint + attr.t_colors!.push(tint[0] * cornerLightResult, tint[1] * cornerLightResult, tint[2] * cornerLightResult) } } } @@ -253,7 +288,7 @@ function renderElement (world: World, cursor: Vec3, element: BlockElement, doAO: if (!neighbor.transparent && (isCube(neighbor) || identicalCull(element, neighbor, new Vec3(...dir)))) continue } else { needSectionRecomputeOnChange = true - continue + // continue } } @@ -301,7 +336,7 @@ function renderElement (world: World, cursor: Vec3, element: BlockElement, doAO: let localShift = null as any if (element.rotation && !needTiles) { - // todo do we support rescale? + // Rescale support for block model rotations localMatrix = buildRotationMatrix( element.rotation.axis, element.rotation.angle @@ -314,6 +349,37 @@ function renderElement (world: World, cursor: Vec3, element: BlockElement, doAO: element.rotation.origin ) ) + + // Apply rescale if specified + if (element.rotation.rescale) { + const FIT_TO_BLOCK_SCALE_MULTIPLIER = 2 - Math.sqrt(2) + const angleRad = element.rotation.angle * Math.PI / 180 + const scale = Math.abs(Math.sin(angleRad)) * FIT_TO_BLOCK_SCALE_MULTIPLIER + + // Get axis vector components (1 for the rotation axis, 0 for others) + const axisX = element.rotation.axis === 'x' ? 1 : 0 + const axisY = element.rotation.axis === 'y' ? 1 : 0 + const axisZ = element.rotation.axis === 'z' ? 1 : 0 + + // Create scale matrix: scale = (1 - axisComponent) * scaleFactor + 1 + const scaleMatrix = [ + [(1 - axisX) * scale + 1, 0, 0], + [0, (1 - axisY) * scale + 1, 0], + [0, 0, (1 - axisZ) * scale + 1] + ] + + // Apply scaling to the transformation matrix + localMatrix = matmulmat3(localMatrix, scaleMatrix) + + // Recalculate shift with the new matrix + localShift = vecsub3( + element.rotation.origin, + matmul3( + localMatrix, + element.rotation.origin + ) + ) + } } const aos: number[] = [] @@ -423,13 +489,19 @@ function renderElement (world: World, cursor: Vec3, element: BlockElement, doAO: if (!needTiles) { if (doAO && aos[0] + aos[3] >= aos[1] + aos[2]) { - attr.indices.push( - ndx, ndx + 3, ndx + 2, ndx, ndx + 1, ndx + 3 - ) + attr.indices[attr.indicesCount++] = ndx + attr.indices[attr.indicesCount++] = ndx + 3 + attr.indices[attr.indicesCount++] = ndx + 2 + attr.indices[attr.indicesCount++] = ndx + attr.indices[attr.indicesCount++] = ndx + 1 + attr.indices[attr.indicesCount++] = ndx + 3 } else { - attr.indices.push( - ndx, ndx + 1, ndx + 2, ndx + 2, ndx + 1, ndx + 3 - ) + attr.indices[attr.indicesCount++] = ndx + attr.indices[attr.indicesCount++] = ndx + 1 + attr.indices[attr.indicesCount++] = ndx + 2 + attr.indices[attr.indicesCount++] = ndx + 2 + attr.indices[attr.indicesCount++] = ndx + 1 + attr.indices[attr.indicesCount++] = ndx + 3 } } } @@ -447,7 +519,7 @@ const isBlockWaterlogged = (block: Block) => { } let unknownBlockModel: BlockModelPartsResolved -export function getSectionGeometry (sx, sy, sz, world: World) { +export function getSectionGeometry (sx: number, sy: number, sz: number, world: World) { let delayedRender = [] as Array<() => void> const attr: MesherGeometryOutput = { @@ -463,12 +535,13 @@ export function getSectionGeometry (sx, sy, sz, world: World) { t_colors: [], t_uvs: [], indices: [], + indicesCount: 0, // Track current index position + using32Array: true, tiles: {}, // todo this can be removed here heads: {}, signs: {}, // isFull: true, - highestBlocks: new Map([]), hadErrors: false, blocksCount: 0 } @@ -478,12 +551,6 @@ export function getSectionGeometry (sx, sy, sz, world: World) { for (cursor.z = sz; cursor.z < sz + 16; cursor.z++) { for (cursor.x = sx; cursor.x < sx + 16; cursor.x++) { let block = world.getBlock(cursor, blockProvider, attr)! - if (!INVISIBLE_BLOCKS.has(block.name)) { - const highest = attr.highestBlocks.get(`${cursor.x},${cursor.z}`) - if (!highest || highest.y < cursor.y) { - attr.highestBlocks.set(`${cursor.x},${cursor.z}`, { y: cursor.y, stateId: block.stateId, biomeId: block.biome.id }) - } - } if (INVISIBLE_BLOCKS.has(block.name)) continue if ((block.name.includes('_sign') || block.name === 'sign') && !world.config.disableSignsMapsSupport) { const key = `${cursor.x},${cursor.y},${cursor.z}` @@ -539,11 +606,11 @@ export function getSectionGeometry (sx, sy, sz, world: World) { const pos = cursor.clone() // eslint-disable-next-line @typescript-eslint/no-loop-func delayedRender.push(() => { - renderLiquid(world, pos, blockProvider.getTextureInfo('water_still'), block.type, biome, true, attr) + renderLiquid(world, pos, blockProvider.getTextureInfo('water_still'), block.type, biome, true, attr, !isWaterlogged) }) attr.blocksCount++ } else if (block.name === 'lava') { - renderLiquid(world, cursor, blockProvider.getTextureInfo('lava_still'), block.type, biome, false, attr) + renderLiquid(world, cursor, blockProvider.getTextureInfo('lava_still'), block.type, biome, false, attr, false) attr.blocksCount++ } if (block.name !== 'water' && block.name !== 'lava' && !INVISIBLE_BLOCKS.has(block.name)) { @@ -605,12 +672,19 @@ export function getSectionGeometry (sx, sy, sz, world: World) { let ndx = attr.positions.length / 3 for (let i = 0; i < attr.t_positions!.length / 12; i++) { - attr.indices.push( - ndx, ndx + 1, ndx + 2, ndx + 2, ndx + 1, ndx + 3, - // eslint-disable-next-line @stylistic/function-call-argument-newline - // back face - ndx, ndx + 2, ndx + 1, ndx + 2, ndx + 3, ndx + 1 - ) + attr.indices[attr.indicesCount++] = ndx + attr.indices[attr.indicesCount++] = ndx + 1 + attr.indices[attr.indicesCount++] = ndx + 2 + attr.indices[attr.indicesCount++] = ndx + 2 + attr.indices[attr.indicesCount++] = ndx + 1 + attr.indices[attr.indicesCount++] = ndx + 3 + // back face + attr.indices[attr.indicesCount++] = ndx + attr.indices[attr.indicesCount++] = ndx + 2 + attr.indices[attr.indicesCount++] = ndx + 1 + attr.indices[attr.indicesCount++] = ndx + 2 + attr.indices[attr.indicesCount++] = ndx + 3 + attr.indices[attr.indicesCount++] = ndx + 1 ndx += 4 } @@ -628,6 +702,12 @@ export function getSectionGeometry (sx, sy, sz, world: World) { attr.normals = new Float32Array(attr.normals) as any attr.colors = new Float32Array(attr.colors) as any attr.uvs = new Float32Array(attr.uvs) as any + attr.using32Array = arrayNeedsUint32(attr.indices) + if (attr.using32Array) { + attr.indices = new Uint32Array(attr.indices) + } else { + attr.indices = new Uint16Array(attr.indices) + } if (needTiles) { delete attr.positions @@ -639,6 +719,21 @@ export function getSectionGeometry (sx, sy, sz, world: World) { return attr } +// copied from three.js +function arrayNeedsUint32 (array) { + + // assumes larger values usually on last + + for (let i = array.length - 1; i >= 0; -- i) { + + if (array[i] >= 65_535) return true // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 + + } + + return false + +} + export const setBlockStatesData = (blockstatesModels, blocksAtlas: any, _needTiles = false, useUnknownBlockModel = true, version = 'latest') => { blockProvider = worldBlockProvider(blockstatesModels, blocksAtlas, version) globalThis.blockProvider = blockProvider diff --git a/renderer/viewer/lib/mesher/modelsGeometryCommon.ts b/renderer/viewer/lib/mesher/modelsGeometryCommon.ts index 2aec00e2..3df20556 100644 --- a/renderer/viewer/lib/mesher/modelsGeometryCommon.ts +++ b/renderer/viewer/lib/mesher/modelsGeometryCommon.ts @@ -122,10 +122,10 @@ export const elemFaces = { mask1: [1, 0, 1], mask2: [0, 1, 1], corners: [ - [1, 0, 0, 0, 1], - [0, 0, 0, 1, 1], - [1, 1, 0, 0, 0], - [0, 1, 0, 1, 0] + [1, 0, 0, 1, 1], + [0, 0, 0, 0, 1], + [1, 1, 0, 1, 0], + [0, 1, 0, 0, 0] ] }, south: { diff --git a/renderer/viewer/lib/mesher/shared.ts b/renderer/viewer/lib/mesher/shared.ts index d8d89042..230db6b9 100644 --- a/renderer/viewer/lib/mesher/shared.ts +++ b/renderer/viewer/lib/mesher/shared.ts @@ -3,11 +3,13 @@ import { BlockType } from '../../../playground/shared' // only here for easier testing export const defaultMesherConfig = { version: '', + worldMaxY: 256, + worldMinY: 0, enableLighting: true, skyLight: 15, smoothLighting: true, outputFormat: 'threeJs' as 'threeJs' | 'webgpu', - textureSize: 1024, // for testing + // textureSize: 1024, // for testing debugModelVariant: undefined as undefined | number[], clipWorldBelowY: undefined as undefined | number, disableSignsMapsSupport: false @@ -33,17 +35,27 @@ export type MesherGeometryOutput = { t_colors?: number[], t_uvs?: number[], - indices: number[], + indices: Uint32Array | Uint16Array | number[], + indicesCount: number, + using32Array: boolean, tiles: Record, heads: Record, signs: Record, // isFull: boolean - highestBlocks: Map hadErrors: boolean blocksCount: number customBlockModels?: CustomBlockModels } +export interface MesherMainEvents { + geometry: { type: 'geometry'; key: string; geometry: MesherGeometryOutput; workerIndex: number }; + sectionFinished: { type: 'sectionFinished'; key: string; workerIndex: number; processTime?: number }; + blockStateModelInfo: { type: 'blockStateModelInfo'; info: Record }; + heightmap: { type: 'heightmap'; key: string; heightmap: Uint8Array }; +} + +export type MesherMainEvent = MesherMainEvents[keyof MesherMainEvents] + export type HighestBlockInfo = { y: number, stateId: number | undefined, biomeId: number | undefined } export type BlockStateModelInfo = { diff --git a/renderer/viewer/lib/mesher/test/tests.test.ts b/renderer/viewer/lib/mesher/test/tests.test.ts index 7959f573..2c3dc6a5 100644 --- a/renderer/viewer/lib/mesher/test/tests.test.ts +++ b/renderer/viewer/lib/mesher/test/tests.test.ts @@ -49,9 +49,6 @@ test('Known blocks are not rendered', () => { // TODO resolve creaking_heart issue (1.21.3) expect(missingBlocks).toMatchInlineSnapshot(` { - "creaking_heart": true, - "end_gateway": true, - "end_portal": true, "structure_void": true, } `) diff --git a/renderer/viewer/lib/mesherlogReader.ts b/renderer/viewer/lib/mesherlogReader.ts new file mode 100644 index 00000000..0f1e74c0 --- /dev/null +++ b/renderer/viewer/lib/mesherlogReader.ts @@ -0,0 +1,131 @@ +/* eslint-disable no-await-in-loop */ +import { Vec3 } from 'vec3' + +// import log from '../../../../../Downloads/mesher (2).log' +import { WorldRendererCommon } from './worldrendererCommon' +const log = '' + + +export class MesherLogReader { + chunksToReceive: Array<{ + x: number + z: number + chunkLength: number + }> = [] + messagesQueue: Array<{ + fromWorker: boolean + workerIndex: number + message: any + }> = [] + + sectionFinishedToReceive = null as { + messagesLeft: string[] + resolve: () => void + } | null + replayStarted = false + + constructor (private readonly worldRenderer: WorldRendererCommon) { + this.parseMesherLog() + } + + chunkReceived (x: number, z: number, chunkLength: number) { + // remove existing chunks with same x and z + const existingChunkIndex = this.chunksToReceive.findIndex(chunk => chunk.x === x && chunk.z === z) + if (existingChunkIndex === -1) { + // console.error('Chunk not found', x, z) + } else { + // warn if chunkLength is different + if (this.chunksToReceive[existingChunkIndex].chunkLength !== chunkLength) { + // console.warn('Chunk length mismatch', x, z, this.chunksToReceive[existingChunkIndex].chunkLength, chunkLength) + } + // remove chunk + this.chunksToReceive = this.chunksToReceive.filter((chunk, index) => chunk.x !== x || chunk.z !== z) + } + this.maybeStartReplay() + } + + async maybeStartReplay () { + if (this.chunksToReceive.length !== 0 || this.replayStarted) return + const lines = log.split('\n') + console.log('starting replay') + this.replayStarted = true + const waitForWorkersMessages = async () => { + if (!this.sectionFinishedToReceive) return + await new Promise(resolve => { + this.sectionFinishedToReceive!.resolve = resolve + }) + } + + for (const line of lines) { + if (line.includes('dispatchMessages dirty')) { + await waitForWorkersMessages() + this.worldRenderer.stopMesherMessagesProcessing = true + const message = JSON.parse(line.slice(line.indexOf('{'), line.lastIndexOf('}') + 1)) + if (!message.value) continue + const index = line.split(' ')[1] + const type = line.split(' ')[3] + // console.log('sending message', message.x, message.y, message.z) + this.worldRenderer.forceCallFromMesherReplayer = true + this.worldRenderer.setSectionDirty(new Vec3(message.x, message.y, message.z), message.value) + this.worldRenderer.forceCallFromMesherReplayer = false + } + if (line.includes('-> blockUpdate')) { + await waitForWorkersMessages() + this.worldRenderer.stopMesherMessagesProcessing = true + const message = JSON.parse(line.slice(line.indexOf('{'), line.lastIndexOf('}') + 1)) + this.worldRenderer.forceCallFromMesherReplayer = true + this.worldRenderer.setBlockStateIdInner(new Vec3(message.pos.x, message.pos.y, message.pos.z), message.stateId) + this.worldRenderer.forceCallFromMesherReplayer = false + } + + if (line.includes(' sectionFinished ')) { + if (!this.sectionFinishedToReceive) { + console.log('starting worker message processing validating') + this.worldRenderer.stopMesherMessagesProcessing = false + this.sectionFinishedToReceive = { + messagesLeft: [], + resolve: () => { + this.sectionFinishedToReceive = null + } + } + } + const parts = line.split(' ') + const coordsPart = parts.find(part => part.split(',').length === 3) + if (!coordsPart) throw new Error(`no coords part found ${line}`) + const [x, y, z] = coordsPart.split(',').map(Number) + this.sectionFinishedToReceive.messagesLeft.push(`${x},${y},${z}`) + } + } + } + + workerMessageReceived (type: string, message: any) { + if (type === 'sectionFinished') { + const { key } = message + if (!this.sectionFinishedToReceive) { + console.warn(`received sectionFinished message but no sectionFinishedToReceive ${key}`) + return + } + + const idx = this.sectionFinishedToReceive.messagesLeft.indexOf(key) + if (idx === -1) { + console.warn(`received sectionFinished message for non-outstanding section ${key}`) + return + } + this.sectionFinishedToReceive.messagesLeft.splice(idx, 1) + if (this.sectionFinishedToReceive.messagesLeft.length === 0) { + this.sectionFinishedToReceive.resolve() + } + } + } + + parseMesherLog () { + const lines = log.split('\n') + for (const line of lines) { + if (line.startsWith('-> chunk')) { + const chunk = JSON.parse(line.slice('-> chunk'.length)) + this.chunksToReceive.push(chunk) + continue + } + } + } +} diff --git a/renderer/viewer/lib/renderUtils.js b/renderer/viewer/lib/renderUtils.js deleted file mode 100644 index 14176561..00000000 --- a/renderer/viewer/lib/renderUtils.js +++ /dev/null @@ -1,11 +0,0 @@ -import { fromFormattedString } from '@xmcl/text-component' - -export const formattedStringToSimpleString = (str) => { - const result = fromFormattedString(str) - str = result.text - // todo recursive - for (const extra of result.extra) { - str += extra.text - } - return str -} diff --git a/renderer/viewer/lib/ui/newStats.ts b/renderer/viewer/lib/ui/newStats.ts index 6c84ef69..4a1b0a0f 100644 --- a/renderer/viewer/lib/ui/newStats.ts +++ b/renderer/viewer/lib/ui/newStats.ts @@ -7,7 +7,7 @@ let lastY = 40 export const addNewStat = (id: string, width = 80, x = rightOffset, y = lastY) => { const pane = document.createElement('div') pane.style.position = 'fixed' - pane.style.top = `${y}px` + pane.style.top = `${y ?? lastY}px` pane.style.right = `${x}px` // gray bg pane.style.backgroundColor = 'rgba(0, 0, 0, 0.7)' @@ -19,7 +19,7 @@ export const addNewStat = (id: string, width = 80, x = rightOffset, y = lastY) = pane.style.pointerEvents = 'none' document.body.appendChild(pane) stats[id] = pane - if (y === 0) { // otherwise it's a custom position + if (y === undefined && x === rightOffset) { // otherwise it's a custom position // rightOffset += width lastY += 20 } @@ -35,11 +35,62 @@ export const addNewStat = (id: string, width = 80, x = rightOffset, y = lastY) = } } +export const addNewStat2 = (id: string, { top, bottom, right, left, displayOnlyWhenWider }: { top?: number, bottom?: number, right?: number, left?: number, displayOnlyWhenWider?: number }) => { + if (top === undefined && bottom === undefined) top = 0 + const pane = document.createElement('div') + pane.style.position = 'fixed' + if (top !== undefined) { + pane.style.top = `${top}px` + } + if (bottom !== undefined) { + pane.style.bottom = `${bottom}px` + } + if (left !== undefined) { + pane.style.left = `${left}px` + } + if (right !== undefined) { + pane.style.right = `${right}px` + } + // gray bg + pane.style.backgroundColor = 'rgba(0, 0, 0, 0.7)' + pane.style.color = 'white' + pane.style.padding = '2px' + pane.style.fontFamily = 'monospace' + pane.style.fontSize = '12px' + pane.style.zIndex = '10000' + pane.style.pointerEvents = 'none' + document.body.appendChild(pane) + stats[id] = pane + + const resizeCheck = () => { + if (!displayOnlyWhenWider) return + pane.style.display = window.innerWidth > displayOnlyWhenWider ? 'block' : 'none' + } + window.addEventListener('resize', resizeCheck) + resizeCheck() + + return { + updateText (text: string) { + pane.innerText = text + }, + setVisibility (visible: boolean) { + pane.style.display = visible ? 'block' : 'none' + } + } +} + export const updateStatText = (id, text) => { if (!stats[id]) return stats[id].innerText = text } +export const updatePanesVisibility = (visible: boolean) => { + // eslint-disable-next-line guard-for-in + for (const id in stats) { + stats[id].style.display = visible ? 'block' : 'none' + } +} + export const removeAllStats = () => { // eslint-disable-next-line guard-for-in for (const id in stats) { diff --git a/renderer/viewer/lib/utils.ts b/renderer/viewer/lib/utils.ts index 240dfa7f..f471aa9d 100644 --- a/renderer/viewer/lib/utils.ts +++ b/renderer/viewer/lib/utils.ts @@ -1,28 +1,4 @@ -import * as THREE from 'three' - -let textureCache: Record = {} -let imagesPromises: Record> = {} - -export async function loadTexture (texture: string, cb: (texture: THREE.Texture) => void, onLoad?: () => void): Promise { - const cached = textureCache[texture] - if (!cached) { - const { promise, resolve } = Promise.withResolvers() - textureCache[texture] = new THREE.TextureLoader().load(texture, resolve) - imagesPromises[texture] = promise - } - - cb(textureCache[texture]) - void imagesPromises[texture].then(() => { - onLoad?.() - }) -} - -export const clearTextureCache = () => { - textureCache = {} - imagesPromises = {} -} - -export const loadScript = async function (scriptSrc: string): Promise { +export const loadScript = async function (scriptSrc: string, highPriority = true): Promise { const existingScript = document.querySelector(`script[src="${scriptSrc}"]`) if (existingScript) { return existingScript @@ -31,6 +7,10 @@ export const loadScript = async function (scriptSrc: string): Promise { const scriptElement = document.createElement('script') scriptElement.src = scriptSrc + + if (highPriority) { + scriptElement.fetchPriority = 'high' + } scriptElement.async = true scriptElement.addEventListener('load', () => { @@ -45,3 +25,33 @@ export const loadScript = async function (scriptSrc: string): Promise { + if (typeof OffscreenCanvas === 'undefined') return false + try { + const canvas = new OffscreenCanvas(1, 1) + // Try to get a WebGL context - this will fail on iOS where only 2D is supported (iOS 16) + const gl = canvas.getContext('webgl2') || canvas.getContext('webgl') + return gl !== null + } catch (e) { + return false + } +} + +const hasFullOffscreenCanvasSupport = detectFullOffscreenCanvasSupport() + +export const createCanvas = (width: number, height: number): OffscreenCanvas => { + if (hasFullOffscreenCanvasSupport) { + return new OffscreenCanvas(width, height) + } + const canvas = document.createElement('canvas') + canvas.width = width + canvas.height = height + return canvas as unknown as OffscreenCanvas // todo-low +} + +export async function loadImageFromUrl (imageUrl: string): Promise { + const response = await fetch(imageUrl) + const blob = await response.blob() + return createImageBitmap(blob) +} diff --git a/renderer/viewer/lib/utils/skins.ts b/renderer/viewer/lib/utils/skins.ts index 385c16c1..3163702c 100644 --- a/renderer/viewer/lib/utils/skins.ts +++ b/renderer/viewer/lib/utils/skins.ts @@ -1,27 +1,59 @@ import { loadSkinToCanvas } from 'skinview-utils' -import * as THREE from 'three' -import stevePng from 'mc-assets/dist/other-textures/latest/entity/player/wide/steve.png' +import { createCanvas, loadImageFromUrl } from '../utils' -// eslint-disable-next-line unicorn/prefer-export-from -export const stevePngUrl = stevePng -export const steveTexture = new THREE.TextureLoader().loadAsync(stevePng) +export { default as stevePngUrl } from 'mc-assets/dist/other-textures/latest/entity/player/wide/steve.png' -export async function loadImageFromUrl (imageUrl: string): Promise { - const img = new Image() - img.src = imageUrl - await new Promise(resolve => { - img.onload = () => resolve() - }) - return img +const config = { + apiEnabled: true, } -export function getLookupUrl (username: string, type: 'skin' | 'cape'): string { - return `https://mulv.tycrek.dev/api/lookup?username=${username}&type=${type}` +export const setSkinsConfig = (newConfig: Partial) => { + Object.assign(config, newConfig) } -export async function loadSkinImage (skinUrl: string): Promise<{ canvas: HTMLCanvasElement, image: HTMLImageElement }> { +export async function loadSkinFromUsername (username: string, type: 'skin' | 'cape'): Promise { + if (!config.apiEnabled) return + + if (type === 'cape') return + const url = `https://playerdb.co/api/player/minecraft/${username}` + const response = await fetch(url) + if (!response.ok) return + + const data: { + data: { + player: { + skin_texture: string + } + } + } = await response.json() + return data.data.player.skin_texture +} + +export const parseSkinTexturesValue = (value: string) => { + const decodedData: { + textures: { + SKIN: { + url: string + } + } + } = JSON.parse(Buffer.from(value, 'base64').toString()) + return decodedData.textures?.SKIN?.url +} + +export async function loadSkinImage (skinUrl: string): Promise<{ canvas: OffscreenCanvas, image: ImageBitmap }> { + if (!skinUrl.startsWith('data:')) { + skinUrl = await fetchAndConvertBase64Skin(skinUrl.replace('http://', 'https://')) + } + const image = await loadImageFromUrl(skinUrl) - const skinCanvas = document.createElement('canvas') + const skinCanvas = createCanvas(64, 64) loadSkinToCanvas(skinCanvas, image) return { canvas: skinCanvas, image } } + +const fetchAndConvertBase64Skin = async (skinUrl: string) => { + const response = await fetch(skinUrl, { }) + const arrayBuffer = await response.arrayBuffer() + const base64 = Buffer.from(arrayBuffer).toString('base64') + return `data:image/png;base64,${base64}` +} diff --git a/renderer/viewer/lib/workerProxy.ts b/renderer/viewer/lib/workerProxy.ts index a27c817d..2b38dca9 100644 --- a/renderer/viewer/lib/workerProxy.ts +++ b/renderer/viewer/lib/workerProxy.ts @@ -1,8 +1,20 @@ -export function createWorkerProxy void>> (handlers: T): { __workerProxy: T } { - addEventListener('message', (event) => { - const { type, args } = event.data +import { proxy, getVersion, subscribe } from 'valtio' + +export function createWorkerProxy void | Promise>> (handlers: T, channel?: MessagePort): { __workerProxy: T } { + const target = channel ?? globalThis + target.addEventListener('message', (event: any) => { + const { type, args, msgId } = event.data if (handlers[type]) { - handlers[type](...args) + const result = handlers[type](...args) + if (result instanceof Promise) { + void result.then((result) => { + target.postMessage({ + type: 'result', + msgId, + args: [result] + }) + }) + } } }) return null as any @@ -19,9 +31,10 @@ export function createWorkerProxy v * const workerChannel = useWorkerProxy(worker) * ``` */ -export const useWorkerProxy = void> }> (worker: Worker, autoTransfer = true): T['__workerProxy'] & { +export const useWorkerProxy = void> }> (worker: Worker | MessagePort, autoTransfer = true): T['__workerProxy'] & { transfer: (...args: Transferable[]) => T['__workerProxy'] } => { + let messageId = 0 // in main thread return new Proxy({} as any, { get (target, prop) { @@ -40,11 +53,30 @@ export const useWorkerProxy = { - const transfer = autoTransfer ? args.filter(arg => arg instanceof ArrayBuffer || arg instanceof MessagePort || arg instanceof ImageBitmap || arg instanceof OffscreenCanvas) : [] + const msgId = messageId++ + const transfer = autoTransfer ? args.filter(arg => { + return arg instanceof ArrayBuffer || arg instanceof MessagePort + || (typeof ImageBitmap !== 'undefined' && arg instanceof ImageBitmap) + || (typeof OffscreenCanvas !== 'undefined' && arg instanceof OffscreenCanvas) + || (typeof ImageData !== 'undefined' && arg instanceof ImageData) + }) : [] worker.postMessage({ type: prop, + msgId, args, }, transfer) + return { + // eslint-disable-next-line unicorn/no-thenable + then (onfulfilled: (value: any) => void) { + const handler = ({ data }: MessageEvent): void => { + if (data.type === 'result' && data.msgId === msgId) { + onfulfilled(data.args[0]) + worker.removeEventListener('message', handler as EventListener) + } + } + worker.addEventListener('message', handler as EventListener) + } + } } } }) diff --git a/renderer/viewer/lib/worldDataEmitter.ts b/renderer/viewer/lib/worldDataEmitter.ts index eb491748..dfbdb35c 100644 --- a/renderer/viewer/lib/worldDataEmitter.ts +++ b/renderer/viewer/lib/worldDataEmitter.ts @@ -7,46 +7,64 @@ import { Vec3 } from 'vec3' import { BotEvents } from 'mineflayer' import { proxy } from 'valtio' import TypedEmitter from 'typed-emitter' -import { getItemFromBlock } from '../../../src/chatUtils' +import { Biome } from 'minecraft-data' import { delayedIterator } from '../../playground/shared' -import { playerState } from '../../../src/mineflayer/playerState' import { chunkPos } from './simpleUtils' -export type ChunkPosKey = string -type ChunkPos = { x: number, z: number } +export type ChunkPosKey = string // like '16,16' +type ChunkPos = { x: number, z: number } // like { x: 16, z: 16 } export type WorldDataEmitterEvents = { chunkPosUpdate: (data: { pos: Vec3 }) => void blockUpdate: (data: { pos: Vec3, stateId: number }) => void entity: (data: any) => void entityMoved: (data: any) => void + playerEntity: (data: any) => void time: (data: number) => void renderDistance: (viewDistance: number) => void blockEntities: (data: Record | { blockEntities: Record }) => void - listening: () => void markAsLoaded: (data: { x: number, z: number }) => void unloadChunk: (data: { x: number, z: number }) => void - loadChunk: (data: { x: number, z: number, chunk: any, blockEntities: any, worldConfig: any, isLightUpdate: boolean }) => void + loadChunk: (data: { x: number, z: number, chunk: string, blockEntities: any, worldConfig: any, isLightUpdate: boolean }) => void updateLight: (data: { pos: Vec3 }) => void + onWorldSwitch: () => void + end: () => void + biomeUpdate: (data: { biome: Biome }) => void + biomeReset: () => void +} + +export class WorldDataEmitterWorker extends (EventEmitter as new () => TypedEmitter) { + static readonly restorerName = 'WorldDataEmitterWorker' } -/** - * Usually connects to mineflayer bot and emits world data (chunks, entities) - * It's up to the consumer to serialize the data if needed - */ export class WorldDataEmitter extends (EventEmitter as new () => TypedEmitter) { - private loadedChunks: Record - private readonly lastPos: Vec3 + spiralNumber = 0 + gotPanicLastTime = false + panicChunksReload = () => {} + loadedChunks: Record + private inLoading = false + private chunkReceiveTimes: number[] = [] + private lastChunkReceiveTime = 0 + public lastChunkReceiveTimeAvg = 0 + private panicTimeout?: NodeJS.Timeout + readonly lastPos: Vec3 private eventListeners: Record = {} private readonly emitter: WorldDataEmitter - keepChunksDistance = 0 - addWaitTime = 1 - isPlayground = false + debugChunksInfo: Record + // blockUpdates: number + }> = {} - public reactive = proxy({ - cursorBlock: null as Vec3 | null, - cursorBlockBreakingStage: null as number | null, - }) + waitingSpiralChunksLoad = {} as Record void> + + addWaitTime = 1 + /* config */ keepChunksDistance = 0 + /* config */ isPlayground = false + /* config */ allowPositionUpdate = true constructor (public world: typeof __type_bot['world'], public viewDistance: number, position: Vec3 = new Vec3(0, 0, 0)) { // eslint-disable-next-line constructor-super @@ -60,12 +78,12 @@ export class WorldDataEmitter extends (EventEmitter as new () => TypedEmitter | void if (val) throw new Error('setBlockStateId returned promise (not supported)') - const chunkX = Math.floor(position.x / 16) - const chunkZ = Math.floor(position.z / 16) - if (!this.loadedChunks[`${chunkX},${chunkZ}`]) { - void this.loadChunk({ x: chunkX, z: chunkZ }) - return - } + // const chunkX = Math.floor(position.x / 16) + // const chunkZ = Math.floor(position.z / 16) + // if (!this.loadedChunks[`${chunkX},${chunkZ}`] && !this.waitingSpiralChunksLoad[`${chunkX},${chunkZ}`]) { + // void this.loadChunk({ x: chunkX, z: chunkZ }) + // return + // } this.emit('blockUpdate', { pos: position, stateId }) } @@ -76,13 +94,28 @@ export class WorldDataEmitter extends (EventEmitter as new () => TypedEmitter() + bot._client.prependListener('spawn_entity', (data) => { + if (data.objectData && data.entityId !== undefined) { + entitiesObjectData.set(data.entityId, data.objectData) + } + }) + const emitEntity = (e, name = 'entity') => { - if (!e || e === bot.entity) return + if (!e) return + if (e === bot.entity) { + if (name === 'entity') { + this.emitter.emit('playerEntity', e) + } + return + } if (!e.name) return // mineflayer received update for not spawned entity + e.objectData = entitiesObjectData.get(e.id) this.emitter.emit(name as any, { ...e, pos: e.position, username: e.username, + team: bot.teamMap[e.username] || bot.teamMap[e.uuid], // set debugTree (obj) { // e.debugTree = obj // } @@ -101,6 +134,9 @@ export class WorldDataEmitter extends (EventEmitter as new () => TypedEmitter TypedEmitter { - void this.loadChunk(pos) + const now = performance.now() + if (this.lastChunkReceiveTime) { + this.chunkReceiveTimes.push(now - this.lastChunkReceiveTime) + } + this.lastChunkReceiveTime = now + + if (this.waitingSpiralChunksLoad[`${pos.x},${pos.z}`]) { + this.waitingSpiralChunksLoad[`${pos.x},${pos.z}`](true) + delete this.waitingSpiralChunksLoad[`${pos.x},${pos.z}`] + } else if (this.loadedChunks[`${pos.x},${pos.z}`]) { + void this.loadChunk(pos, false, 'Received another chunkColumnLoad event while already loaded') + } + this.chunkProgress() }, chunkColumnUnload: (pos: Vec3) => { this.unloadChunk(pos) @@ -119,41 +167,55 @@ export class WorldDataEmitter extends (EventEmitter as new () => TypedEmitter { this.emitter.emit('time', bot.time.timeOfDay) - } + }, + end: () => { + this.emitter.emit('end') + }, + // when dimension might change + login: () => { + void this.updatePosition(bot.entity.position, true) + this.emitter.emit('playerEntity', bot.entity) + }, + respawn: () => { + void this.updatePosition(bot.entity.position, true) + this.emitter.emit('playerEntity', bot.entity) + this.emitter.emit('onWorldSwitch') + }, } satisfies Partial bot._client.on('update_light', ({ chunkX, chunkZ }) => { const chunkPos = new Vec3(chunkX * 16, 0, chunkZ * 16) - void this.loadChunk(chunkPos, true) + if (!this.waitingSpiralChunksLoad[`${chunkX},${chunkZ}`] && this.loadedChunks[`${chunkX},${chunkZ}`]) { + void this.loadChunk(chunkPos, true, 'update_light') + } }) - this.emitter.on('listening', () => { - this.emitter.emit('blockEntities', new Proxy({}, { - get (_target, posKey, receiver) { - if (typeof posKey !== 'string') return - const [x, y, z] = posKey.split(',').map(Number) - return bot.world.getBlock(new Vec3(x, y, z))?.entity - }, - })) - this.emitter.emit('renderDistance', this.viewDistance) - this.emitter.emit('time', bot.time.timeOfDay) - }) - // node.js stream data event pattern - if (this.emitter.listenerCount('blockEntities')) { - this.emitter.emit('listening') - } - for (const [evt, listener] of Object.entries(this.eventListeners)) { bot.on(evt as any, listener) } for (const id in bot.entities) { const e = bot.entities[id] - emitEntity(e) + try { + emitEntity(e) + } catch (err) { + // reportError?.(err) + console.error('error processing entity', err) + } } } + emitterGotConnected () { + this.emitter.emit('blockEntities', new Proxy({}, { + get (_target, posKey, receiver) { + if (typeof posKey !== 'string') return + const [x, y, z] = posKey.split(',').map(Number) + return bot.world.getBlock(new Vec3(x, y, z))?.entity + }, + })) + } + removeListenersFromBot (bot: import('mineflayer').Bot) { for (const [evt, listener] of Object.entries(this.eventListeners)) { bot.removeListener(evt as any, listener) @@ -163,36 +225,95 @@ export class WorldDataEmitter extends (EventEmitter as new () => TypedEmitter new Vec3((botX + x) * 16, 0, (botZ + z) * 16)) this.lastPos.update(pos) - await this._loadChunks(positions) + await this._loadChunks(positions, pos) } - async _loadChunks (positions: Vec3[], sliceSize = 5) { - const promises = [] as Array> - await delayedIterator(positions, this.addWaitTime, (pos) => { - promises.push(this.loadChunk(pos)) + chunkProgress () { + if (this.panicTimeout) clearTimeout(this.panicTimeout) + if (this.chunkReceiveTimes.length >= 5) { + const avgReceiveTime = this.chunkReceiveTimes.reduce((a, b) => a + b, 0) / this.chunkReceiveTimes.length + this.lastChunkReceiveTimeAvg = avgReceiveTime + const timeoutDelay = avgReceiveTime * 2 + 1000 // 2x average + 1 second + + // Clear any existing timeout + if (this.panicTimeout) clearTimeout(this.panicTimeout) + + // Set new timeout for panic reload + this.panicTimeout = setTimeout(() => { + if (!this.gotPanicLastTime && this.inLoading) { + console.warn('Chunk loading seems stuck, triggering panic reload') + this.gotPanicLastTime = true + this.panicChunksReload() + } + }, timeoutDelay) + } + } + + async _loadChunks (positions: Vec3[], centerPos: Vec3) { + this.spiralNumber++ + const { spiralNumber } = this + // stop loading previous chunks + for (const pos of Object.keys(this.waitingSpiralChunksLoad)) { + this.waitingSpiralChunksLoad[pos](false) + delete this.waitingSpiralChunksLoad[pos] + } + + let continueLoading = true + this.inLoading = true + await delayedIterator(positions, this.addWaitTime, async (pos) => { + if (!continueLoading || this.loadedChunks[`${pos.x},${pos.z}`]) return + + // Wait for chunk to be available from server + if (!this.world.getColumnAt(pos)) { + continueLoading = await new Promise(resolve => { + this.waitingSpiralChunksLoad[`${pos.x},${pos.z}`] = resolve + }) + } + if (!continueLoading) return + await this.loadChunk(pos, undefined, `spiral ${spiralNumber} from ${centerPos.x},${centerPos.z}`) + this.chunkProgress() }) - await Promise.all(promises) + if (this.panicTimeout) clearTimeout(this.panicTimeout) + this.inLoading = false + this.gotPanicLastTime = false + this.chunkReceiveTimes = [] + this.lastChunkReceiveTime = 0 } readdDebug () { const clonedLoadedChunks = { ...this.loadedChunks } this.unloadAllChunks() + console.time('readdDebug') for (const loadedChunk in clonedLoadedChunks) { const [x, z] = loadedChunk.split(',').map(Number) void this.loadChunk(new Vec3(x, 0, z)) } + const interval = setInterval(() => { + if (appViewer.rendererState.world.allChunksLoaded) { + clearInterval(interval) + console.timeEnd('readdDebug') + } + }, 100) } // debugGotChunkLatency = [] as number[] // lastTime = 0 - async loadChunk (pos: ChunkPos, isLightUpdate = false) { + async loadChunk (pos: ChunkPos, isLightUpdate = false, reason = 'spiral') { const [botX, botZ] = chunkPos(this.lastPos) + const dx = Math.abs(botX - Math.floor(pos.x / 16)) const dz = Math.abs(botZ - Math.floor(pos.z / 16)) if (dx <= this.viewDistance && dz <= this.viewDistance) { @@ -212,6 +333,15 @@ export class WorldDataEmitter extends (EventEmitter as new () => TypedEmitter TypedEmitter TypedEmitter { const pos = new Vec3((botX + x) * 16, 0, (botZ + z) * 16) if (!this.loadedChunks[`${pos.x},${pos.z}`]) return pos return undefined! }).filter(a => !!a) this.lastPos.update(pos) - void this._loadChunks(positions) + void this._loadChunks(positions, pos) } else { this.emitter.emit('chunkPosUpdate', { pos }) // todo-low this.lastPos.update(pos) diff --git a/renderer/viewer/lib/worldrendererCommon.ts b/renderer/viewer/lib/worldrendererCommon.ts index d803069d..4140e3fa 100644 --- a/renderer/viewer/lib/worldrendererCommon.ts +++ b/renderer/viewer/lib/worldrendererCommon.ts @@ -1,57 +1,96 @@ /* eslint-disable guard-for-in */ import { EventEmitter } from 'events' import { Vec3 } from 'vec3' -import * as THREE from 'three' import mcDataRaw from 'minecraft-data/data.js' // note: using alias import TypedEmitter from 'typed-emitter' -import { ItemsRenderer } from 'mc-assets/dist/itemsRenderer' import { WorldBlockProvider } from 'mc-assets/dist/worldBlockProvider' import { generateSpiralMatrix } from 'flying-squid/dist/utils' +import { subscribeKey } from 'valtio/utils' +import { proxy } from 'valtio' import { dynamicMcDataFiles } from '../../buildMesherConfig.mjs' -import { toMajorVersion } from '../../../src/utils' -import { ResourcesManager } from '../../../src/resourcesManager' -import { DisplayWorldOptions, RendererReactiveState } from '../../../src/appViewer' +import type { ResourcesManagerTransferred } from '../../../src/resourcesManager' +import { DisplayWorldOptions, GraphicsInitOptions, RendererReactiveState } from '../../../src/appViewer' import { SoundSystem } from '../three/threeJsSound' import { buildCleanupDecorator } from './cleanupDecorator' -import { HighestBlockInfo, MesherGeometryOutput, CustomBlockModels, BlockStateModelInfo, getBlockAssetsCacheKey, MesherConfig } from './mesher/shared' +import { HighestBlockInfo, CustomBlockModels, BlockStateModelInfo, getBlockAssetsCacheKey, MesherConfig, MesherMainEvent } from './mesher/shared' import { chunkPos } from './simpleUtils' -import { removeStat, updateStatText } from './ui/newStats' -import { WorldDataEmitter } from './worldDataEmitter' -import { IPlayerState } from './basePlayerState' +import { addNewStat, removeAllStats, updatePanesVisibility, updateStatText } from './ui/newStats' +import { WorldDataEmitterWorker } from './worldDataEmitter' +import { getPlayerStateUtils, PlayerStateReactive, PlayerStateRenderer, PlayerStateUtils } from './basePlayerState' +import { MesherLogReader } from './mesherlogReader' +import { setSkinsConfig } from './utils/skins' function mod (x, n) { return ((x % n) + n) % n } +const toMajorVersion = version => { + const [a, b] = (String(version)).split('.') + return `${a}.${b}` +} + export const worldCleanup = buildCleanupDecorator('resetWorld') export const defaultWorldRendererConfig = { + // Debug settings showChunkBorders: false, + enableDebugOverlay: false, + + // Performance settings mesherWorkers: 4, - isPlayground: false, - renderEars: true, - // game renderer setting actually - showHand: false, - viewBobbing: false, - extraBlockRenderers: true, - clipWorldBelowY: undefined as number | undefined, + addChunksBatchWaitTime: 200, + _experimentalSmoothChunkLoading: true, + _renderByChunks: false, + + // Rendering engine settings + dayCycle: true, smoothLighting: true, enableLighting: true, starfield: true, - addChunksBatchWaitTime: 200, - vrSupport: true, + defaultSkybox: true, renderEntities: true, + extraBlockRenderers: true, + foreground: true, fov: 75, - fetchPlayerSkins: true, + volume: 1, + + // Camera visual related settings + showHand: false, + viewBobbing: false, + renderEars: true, highlightBlockColor: 'blue', - foreground: true + + // Player models + fetchPlayerSkins: true, + skinTexturesProxy: undefined as string | undefined, + + // VR settings + vrSupport: true, + vrPageGameRendering: true, + + // World settings + clipWorldBelowY: undefined as number | undefined, + isPlayground: false } export type WorldRendererConfig = typeof defaultWorldRendererConfig export abstract class WorldRendererCommon { - displayStats = true + worldReadyResolvers = Promise.withResolvers() + worldReadyPromise = this.worldReadyResolvers.promise + timeOfTheDay = 0 worldSizeParams = { minY: 0, worldHeight: 256 } + reactiveDebugParams = proxy({ + stopRendering: false, + chunksRenderAboveOverride: undefined as number | undefined, + chunksRenderAboveEnabled: false, + chunksRenderBelowOverride: undefined as number | undefined, + chunksRenderBelowEnabled: false, + chunksRenderDistanceOverride: undefined as number | undefined, + chunksRenderDistanceEnabled: false, + disableEntities: false, + // disableParticles: false + }) active = false @@ -78,10 +117,11 @@ export abstract class WorldRendererCommon dirty (pos: Vec3, value: boolean): void update (/* pos: Vec3, value: boolean */): void chunkFinished (key: string): void + heightmap (key: string, heightmap: Uint8Array): void }> customTexturesDataUrl = undefined as string | undefined workers: any[] = [] - viewerPosition?: Vec3 + viewerChunkPosition?: Vec3 lastCamUpdate = 0 droppedFpsPercentage = 0 initialChunkLoadWasStartedIn: number | undefined @@ -91,18 +131,23 @@ export abstract class WorldRendererCommon viewDistance = -1 chunksLength = 0 allChunksFinished = false + messageQueue: any[] = [] + isProcessingQueue = false + ONMESSAGE_TIME_LIMIT = 30 // ms handleResize = () => { } - camera: THREE.PerspectiveCamera - highestBlocks = new Map() + highestBlocksByChunks = new Map() blockEntities = {} workersProcessAverageTime = 0 workersProcessAverageTimeCount = 0 maxWorkersProcessTime = 0 - geometryReceiveCount = {} + geometryReceiveCount = {} as Record allLoadedIn: undefined | number - + onWorldSwitched = [] as Array<() => void> + renderTimeMax = 0 + renderTimeAvg = 0 + renderTimeAvgCount = 0 edgeChunks = {} as Record lastAddChunk = null as null | { timeout: any @@ -113,9 +158,6 @@ export abstract class WorldRendererCommon lastChunkDistance = 0 debugStopGeometryUpdate = false - @worldCleanup() - itemsRenderer: ItemsRenderer | undefined - protocolCustomBlocks = new Map() @worldCleanup() @@ -128,37 +170,106 @@ export abstract class WorldRendererCommon abstract changeBackgroundColor (color: [number, number, number]): void worldRendererConfig: WorldRendererConfig - playerState: IPlayerState + playerStateReactive: PlayerStateReactive + playerStateUtils: PlayerStateUtils reactiveState: RendererReactiveState + mesherLogReader: MesherLogReader | undefined + forceCallFromMesherReplayer = false + stopMesherMessagesProcessing = false abortController = new AbortController() + lastRendered = 0 + renderingActive = true + geometryReceiveCountPerSec = 0 + mesherLogger = { + contents: [] as string[], + active: new URL(location.href).searchParams.get('mesherlog') === 'true' + } + currentRenderedFrames = 0 + fpsAverage = 0 + lastFps = 0 + fpsWorst = undefined as number | undefined + fpsSamples = 0 + mainThreadRendering = true + backendInfoReport = '-' + chunksFullInfo = '-' + workerCustomHandleTime = 0 - constructor (public readonly resourcesManager: ResourcesManager, public displayOptions: DisplayWorldOptions, public version: string) { - // this.initWorkers(1) // preload script on page load + get version () { + return this.displayOptions.version + } + + get displayAdvancedStats () { + return (this.initOptions.config.statsVisible ?? 0) > 1 + } + + constructor (public readonly resourcesManager: ResourcesManagerTransferred, public displayOptions: DisplayWorldOptions, public initOptions: GraphicsInitOptions) { this.snapshotInitialValues() this.worldRendererConfig = displayOptions.inWorldRenderingConfig - this.playerState = displayOptions.playerState + this.playerStateReactive = displayOptions.playerStateReactive + this.playerStateUtils = getPlayerStateUtils(this.playerStateReactive) this.reactiveState = displayOptions.rendererState - + // this.mesherLogReader = new MesherLogReader(this) this.renderUpdateEmitter.on('update', () => { const loadedChunks = Object.keys(this.finishedChunks).length updateStatText('loaded-chunks', `${loadedChunks}/${this.chunksLength} chunks (${this.lastChunkDistance}/${this.viewDistance})`) }) + addNewStat('downloaded-chunks', 100, 140, 20) + this.connect(this.displayOptions.worldView) + + const interval = setInterval(() => { + this.geometryReceiveCountPerSec = Object.values(this.geometryReceiveCount).reduce((acc, curr) => acc + curr, 0) + this.geometryReceiveCount = {} + updatePanesVisibility(this.displayAdvancedStats) + this.updateChunksStats() + if (this.mainThreadRendering) { + this.fpsUpdate() + } + }, 500) + this.abortController.signal.addEventListener('abort', () => { + clearInterval(interval) + }) } - init () { + fpsUpdate () { + this.fpsSamples++ + this.fpsAverage = (this.fpsAverage * (this.fpsSamples - 1) + this.currentRenderedFrames) / this.fpsSamples + if (this.fpsWorst === undefined) { + this.fpsWorst = this.currentRenderedFrames + } else { + this.fpsWorst = Math.min(this.fpsWorst, this.currentRenderedFrames) + } + this.lastFps = this.currentRenderedFrames + this.currentRenderedFrames = 0 + } + + logWorkerWork (message: string | (() => string)) { + if (!this.mesherLogger.active) return + this.mesherLogger.contents.push(typeof message === 'function' ? message() : message) + } + + async init () { if (this.active) throw new Error('WorldRendererCommon is already initialized') - void this.setVersion(this.version).then(() => { - this.resourcesManager.on('assetsTexturesUpdated', () => { - if (!this.active) return - void this.updateAssetsData() - }) - if (this.resourcesManager.currentResources) { - void this.updateAssetsData() - } + + await Promise.all([ + this.resetWorkers(), + (async () => { + if (this.resourcesManager.currentResources?.allReady) { + await this.updateAssetsData() + } + })() + ]) + + this.resourcesManager.on('assetsTexturesUpdated', async () => { + if (!this.active) return + await this.updateAssetsData() }) + + this.watchReactivePlayerState() + this.watchReactiveConfig() + this.worldReadyResolvers.resolve() } snapshotInitialValues () { } @@ -167,8 +278,8 @@ export abstract class WorldRendererCommon return this.loadedChunks[chunkKey] } - async getHighestBlocks () { - return this.highestBlocks + async getHighestBlocks (chunkKey: string) { + return this.highestBlocksByChunks.get(chunkKey) } updateCustomBlock (chunkKey: string, blockPos: string, model: string) { @@ -176,6 +287,7 @@ export abstract class WorldRendererCommon ...this.protocolCustomBlocks.get(chunkKey), [blockPos]: model }) + this.logWorkerWork(() => `-> updateCustomBlock ${chunkKey} ${blockPos} ${model} ${this.wasChunkSentToWorker(chunkKey)}`) if (this.wasChunkSentToWorker(chunkKey)) { const [x, y, z] = blockPos.split(',').map(Number) this.setBlockStateId(new Vec3(x, y, z), undefined) @@ -196,91 +308,177 @@ export abstract class WorldRendererCommon initWorkers (numWorkers = this.worldRendererConfig.mesherWorkers) { // init workers for (let i = 0; i < numWorkers + 1; i++) { - // Node environment needs an absolute path, but browser needs the url of the file - const workerName = 'mesher.js' - // eslint-disable-next-line node/no-path-concat - const src = typeof window === 'undefined' ? `${__dirname}/${workerName}` : workerName - - let worker: any - if (process.env.SINGLE_FILE_BUILD) { - const workerCode = document.getElementById('mesher-worker-code')!.textContent! - const blob = new Blob([workerCode], { type: 'text/javascript' }) - worker = new Worker(window.URL.createObjectURL(blob)) - } else { - worker = new Worker(src) - } - const handleMessage = (data) => { - if (!this.active) return - if (data.type !== 'geometry' || !this.debugStopGeometryUpdate) { - this.handleWorkerMessage(data) - } - if (data.type === 'geometry') { - this.geometryReceiveCount[data.workerIndex] ??= 0 - this.geometryReceiveCount[data.workerIndex]++ - const geometry = data.geometry as MesherGeometryOutput - for (const [key, highest] of geometry.highestBlocks.entries()) { - const currHighest = this.highestBlocks.get(key) - if (!currHighest || currHighest.y < highest.y) { - this.highestBlocks.set(key, highest) - } - } - // for (const key in geometry.highestBlocks) { - // const highest = geometry.highestBlocks[key] - // if (!this.highestBlocks[key] || this.highestBlocks[key].y < highest.y) { - // this.highestBlocks[key] = highest - // } - // } - const chunkCoords = data.key.split(',').map(Number) - this.lastChunkDistance = Math.max(...this.getDistance(new Vec3(chunkCoords[0], 0, chunkCoords[2]))) - } - if (data.type === 'sectionFinished') { // on after load & unload section - if (!this.sectionsWaiting.get(data.key)) throw new Error(`sectionFinished event for non-outstanding section ${data.key}`) - this.sectionsWaiting.set(data.key, this.sectionsWaiting.get(data.key)! - 1) - if (this.sectionsWaiting.get(data.key) === 0) { - this.sectionsWaiting.delete(data.key) - this.finishedSections[data.key] = true - } - - const chunkCoords = data.key.split(',').map(Number) - if (this.loadedChunks[`${chunkCoords[0]},${chunkCoords[2]}`]) { // ensure chunk data was added, not a neighbor chunk update - const loadingKeys = [...this.sectionsWaiting.keys()] - if (!loadingKeys.some(key => { - const [x, y, z] = key.split(',').map(Number) - return x === chunkCoords[0] && z === chunkCoords[2] - })) { - this.finishedChunks[`${chunkCoords[0]},${chunkCoords[2]}`] = true - this.renderUpdateEmitter.emit(`chunkFinished`, `${chunkCoords[0] / 16},${chunkCoords[2] / 16}`) - } - } - this.checkAllFinished() - - this.renderUpdateEmitter.emit('update') - if (data.processTime) { - this.workersProcessAverageTimeCount++ - this.workersProcessAverageTime = ((this.workersProcessAverageTime * (this.workersProcessAverageTimeCount - 1)) + data.processTime) / this.workersProcessAverageTimeCount - this.maxWorkersProcessTime = Math.max(this.maxWorkersProcessTime, data.processTime) - } - } - - if (data.type === 'blockStateModelInfo') { - for (const [cacheKey, info] of Object.entries(data.info)) { - this.blockStateModelInfo.set(cacheKey, info) - } - } - } - worker.onmessage = ({ data }) => { + const worker = initMesherWorker((data) => { if (Array.isArray(data)) { - // eslint-disable-next-line unicorn/no-array-for-each - data.forEach(handleMessage) - return + this.messageQueue.push(...data) + } else { + this.messageQueue.push(data) } - handleMessage(data) - } - if (worker.on) worker.on('message', (data) => { worker.onmessage({ data }) }) + void this.processMessageQueue('worker') + }) this.workers.push(worker) } } + onReactivePlayerStateUpdated(key: T, callback: (value: PlayerStateReactive[T]) => void, initial = true) { + if (initial) { + callback(this.playerStateReactive[key]) + } + subscribeKey(this.playerStateReactive, key, callback) + } + + onReactiveConfigUpdated(key: T, callback: (value: typeof this.worldRendererConfig[T]) => void) { + callback(this.worldRendererConfig[key]) + subscribeKey(this.worldRendererConfig, key, callback) + } + + onReactiveDebugUpdated(key: T, callback: (value: typeof this.reactiveDebugParams[T]) => void) { + callback(this.reactiveDebugParams[key]) + subscribeKey(this.reactiveDebugParams, key, callback) + } + + watchReactivePlayerState () { + this.onReactivePlayerStateUpdated('backgroundColor', (value) => { + this.changeBackgroundColor(value) + }) + } + + watchReactiveConfig () { + this.onReactiveConfigUpdated('fetchPlayerSkins', (value) => { + setSkinsConfig({ apiEnabled: value }) + }) + } + + async processMessageQueue (source: string) { + if (this.isProcessingQueue || this.messageQueue.length === 0) return + this.logWorkerWork(`# ${source} processing queue`) + if (this.lastRendered && performance.now() - this.lastRendered > this.ONMESSAGE_TIME_LIMIT && this.worldRendererConfig._experimentalSmoothChunkLoading && this.renderingActive) { + const start = performance.now() + await new Promise(resolve => { + requestAnimationFrame(resolve) + }) + this.logWorkerWork(`# processing got delayed by ${performance.now() - start}ms`) + } + this.isProcessingQueue = true + + const startTime = performance.now() + let processedCount = 0 + + while (this.messageQueue.length > 0) { + const processingStopped = this.stopMesherMessagesProcessing + if (!processingStopped) { + const data = this.messageQueue.shift()! + this.handleMessage(data) + processedCount++ + } + + // Check if we've exceeded the time limit + if (processingStopped || (performance.now() - startTime > this.ONMESSAGE_TIME_LIMIT && this.renderingActive && this.worldRendererConfig._experimentalSmoothChunkLoading)) { + // If we have more messages and exceeded time limit, schedule next batch + if (this.messageQueue.length > 0) { + requestAnimationFrame(async () => { + this.isProcessingQueue = false + void this.processMessageQueue('queue-delay') + }) + return + } + break + } + } + + this.isProcessingQueue = false + } + + handleMessage (rawData: any) { + const data = rawData as MesherMainEvent + if (!this.active) return + this.mesherLogReader?.workerMessageReceived(data.type, data) + if (data.type !== 'geometry' || !this.debugStopGeometryUpdate) { + const start = performance.now() + this.handleWorkerMessage(data as WorkerReceive) + this.workerCustomHandleTime += performance.now() - start + } + if (data.type === 'geometry') { + this.logWorkerWork(() => `-> ${data.workerIndex} geometry ${data.key} ${JSON.stringify({ dataSize: JSON.stringify(data).length })}`) + this.geometryReceiveCount[data.workerIndex] ??= 0 + this.geometryReceiveCount[data.workerIndex]++ + const chunkCoords = data.key.split(',').map(Number) + this.lastChunkDistance = Math.max(...this.getDistance(new Vec3(chunkCoords[0], 0, chunkCoords[2]))) + } + if (data.type === 'sectionFinished') { // on after load & unload section + this.logWorkerWork(`<- ${data.workerIndex} sectionFinished ${data.key} ${JSON.stringify({ processTime: data.processTime })}`) + if (!this.sectionsWaiting.has(data.key)) throw new Error(`sectionFinished event for non-outstanding section ${data.key}`) + this.sectionsWaiting.set(data.key, this.sectionsWaiting.get(data.key)! - 1) + if (this.sectionsWaiting.get(data.key) === 0) { + this.sectionsWaiting.delete(data.key) + this.finishedSections[data.key] = true + } + + const chunkCoords = data.key.split(',').map(Number) + const chunkKey = `${chunkCoords[0]},${chunkCoords[2]}` + if (this.loadedChunks[chunkKey]) { // ensure chunk data was added, not a neighbor chunk update + let loaded = true + for (let y = this.worldMinYRender; y < this.worldSizeParams.worldHeight; y += 16) { + if (!this.finishedSections[`${chunkCoords[0]},${y},${chunkCoords[2]}`]) { + loaded = false + break + } + } + if (loaded) { + // CHUNK FINISHED + this.finishedChunks[chunkKey] = true + this.reactiveState.world.chunksLoaded.add(`${Math.floor(chunkCoords[0] / 16)},${Math.floor(chunkCoords[2] / 16)}`) + this.renderUpdateEmitter.emit(`chunkFinished`, `${chunkCoords[0]},${chunkCoords[2]}`) + this.checkAllFinished() + // merge highest blocks by sections into highest blocks by chunks + // for (let y = this.worldMinYRender; y < this.worldSizeParams.worldHeight; y += 16) { + // const sectionKey = `${chunkCoords[0]},${y},${chunkCoords[2]}` + // for (let x = 0; x < 16; x++) { + // for (let z = 0; z < 16; z++) { + // const posInsideKey = `${chunkCoords[0] + x},${chunkCoords[2] + z}` + // let block = null as HighestBlockInfo | null + // const highestBlock = this.highestBlocksBySections[sectionKey]?.[posInsideKey] + // if (!highestBlock) continue + // if (!block || highestBlock.y > block.y) { + // block = highestBlock + // } + // if (block) { + // this.highestBlocksByChunks[chunkKey] ??= {} + // this.highestBlocksByChunks[chunkKey][posInsideKey] = block + // } + // } + // } + // delete this.highestBlocksBySections[sectionKey] + // } + } + } + + this.renderUpdateEmitter.emit('update') + if (data.processTime) { + this.workersProcessAverageTimeCount++ + this.workersProcessAverageTime = ((this.workersProcessAverageTime * (this.workersProcessAverageTimeCount - 1)) + data.processTime) / this.workersProcessAverageTimeCount + this.maxWorkersProcessTime = Math.max(this.maxWorkersProcessTime, data.processTime) + } + } + + if (data.type === 'blockStateModelInfo') { + for (const [cacheKey, info] of Object.entries(data.info)) { + this.blockStateModelInfo.set(cacheKey, info) + } + } + + if (data.type === 'heightmap') { + this.reactiveState.world.heightmaps.set(data.key, new Uint8Array(data.heightmap)) + } + } + + downloadMesherLog () { + const a = document.createElement('a') + a.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(this.mesherLogger.contents.join('\n')) + a.download = 'mesher.log' + a.click() + } + checkAllFinished () { if (this.sectionsWaiting.size === 0) { this.reactiveState.world.mesherWork = false @@ -312,8 +510,12 @@ export abstract class WorldRendererCommon timeUpdated? (newTime: number): void + biomeUpdated? (biome: any): void + + biomeReset? (): void + updateViewerPosition (pos: Vec3) { - this.viewerPosition = pos + this.viewerChunkPosition = pos for (const [key, value] of Object.entries(this.loadedChunks)) { if (!value) continue this.updatePosDataChunk?.(key) @@ -327,7 +529,7 @@ export abstract class WorldRendererCommon } getDistance (posAbsolute: Vec3) { - const [botX, botZ] = chunkPos(this.viewerPosition!) + const [botX, botZ] = chunkPos(this.viewerChunkPosition!) const dx = Math.abs(botX - Math.floor(posAbsolute.x / 16)) const dz = Math.abs(botZ - Math.floor(posAbsolute.z / 16)) return [dx, dz] as [number, number] @@ -343,13 +545,11 @@ export abstract class WorldRendererCommon this.workers = [] } - // new game load happens here - async setVersion (version: string) { - this.version = version + async resetWorkers () { this.resetWorld() // for workers in single file build - if (document?.readyState === 'loading') { + if (typeof document !== 'undefined' && document?.readyState === 'loading') { await new Promise(resolve => { document.addEventListener('DOMContentLoaded', resolve) }) @@ -358,24 +558,35 @@ export abstract class WorldRendererCommon this.initWorkers() this.active = true - await this.resourcesManager.loadMcData(version) this.sendMesherMcData() - if (!this.resourcesManager.currentResources) { - await this.resourcesManager.updateAssetsData({ }) - } } getMesherConfig (): MesherConfig { + let skyLight = 15 + const timeOfDay = this.timeOfTheDay + if (timeOfDay < 0 || timeOfDay > 24_000) { + // + } else if (timeOfDay <= 6000 || timeOfDay >= 18_000) { + skyLight = 15 + } else if (timeOfDay > 6000 && timeOfDay < 12_000) { + skyLight = 15 - ((timeOfDay - 6000) / 6000) * 15 + } else if (timeOfDay >= 12_000 && timeOfDay < 18_000) { + skyLight = ((timeOfDay - 12_000) / 6000) * 15 + } + + skyLight = Math.floor(skyLight) return { version: this.version, enableLighting: this.worldRendererConfig.enableLighting, - skyLight: 15, + skyLight, smoothLighting: this.worldRendererConfig.smoothLighting, outputFormat: this.outputFormat, - textureSize: this.resourcesManager.currentResources!.blocksAtlasParser.atlas.latest.width, + // textureSize: this.resourcesManager.currentResources!.blocksAtlasParser.atlas.latest.width, debugModelVariant: undefined, clipWorldBelowY: this.worldRendererConfig.clipWorldBelowY, - disableSignsMapsSupport: !this.worldRendererConfig.extraBlockRenderers + disableSignsMapsSupport: !this.worldRendererConfig.extraBlockRenderers, + worldMinY: this.worldMinYRender, + worldMaxY: this.worldMinYRender + this.worldSizeParams.worldHeight, } } @@ -391,10 +602,11 @@ export abstract class WorldRendererCommon for (const worker of this.workers) { worker.postMessage({ type: 'mcData', mcData, config: this.getMesherConfig() }) } + this.logWorkerWork('# mcData sent') } async updateAssetsData () { - const resources = this.resourcesManager.currentResources! + const resources = this.resourcesManager.currentResources if (this.workers.length === 0) throw new Error('workers not initialized yet') for (const [i, worker] of this.workers.entries()) { @@ -404,13 +616,14 @@ export abstract class WorldRendererCommon type: 'mesherData', workerIndex: i, blocksAtlas: { - latest: resources.blocksAtlasParser.atlas.latest + latest: resources.blocksAtlasJson }, blockstatesModels, config: this.getMesherConfig(), }) } + this.logWorkerWork('# mesherData sent') console.log('textures loaded') } @@ -420,10 +633,13 @@ export abstract class WorldRendererCommon updateChunksStats () { const loadedChunks = Object.keys(this.finishedChunks) - this.reactiveState.world.chunksLoaded = loadedChunks - this.reactiveState.world.chunksTotalNumber = this.chunksLength + this.displayOptions.nonReactiveState.world.chunksLoaded = new Set(loadedChunks) + this.displayOptions.nonReactiveState.world.chunksTotalNumber = this.chunksLength this.reactiveState.world.allChunksLoaded = this.allChunksFinished - updateStatText('downloaded-chunks', `${Object.keys(this.loadedChunks).length}/${this.chunksLength} chunks D (${this.workers.length}:${this.workersProcessAverageTime.toFixed(0)}ms/${this.allLoadedIn?.toFixed(1) ?? '-'}s)`) + + const text = `Q: ${this.messageQueue.length} ${Object.keys(this.loadedChunks).length}/${Object.keys(this.finishedChunks).length}/${this.chunksLength} chunks (${this.workers.length}:${this.workersProcessAverageTime.toFixed(0)}ms/${this.geometryReceiveCountPerSec}ss/${this.allLoadedIn?.toFixed(1) ?? '-'}s)` + this.chunksFullInfo = text + updateStatText('downloaded-chunks', text) } addColumn (x: number, z: number, chunk: any, isLightUpdate: boolean) { @@ -446,6 +662,13 @@ export abstract class WorldRendererCommon customBlockModels: customBlockModels || undefined }) } + this.workers[0].postMessage({ + type: 'getHeightmap', + x, + z, + }) + this.logWorkerWork(() => `-> chunk ${JSON.stringify({ x, z, chunkLength: chunk.length, customBlockModelsLength: customBlockModels ? Object.keys(customBlockModels).length : 0 })}`) + this.mesherLogReader?.chunkReceived(x, z, chunk.length) for (let y = this.worldMinYRender; y < this.worldSizeParams.worldHeight; y += 16) { const loc = new Vec3(x, y, z) this.setSectionDirty(loc) @@ -461,18 +684,19 @@ export abstract class WorldRendererCommon markAsLoaded (x, z) { this.loadedChunks[`${x},${z}`] = true this.finishedChunks[`${x},${z}`] = true + this.logWorkerWork(`-> markAsLoaded ${JSON.stringify({ x, z })}`) this.checkAllFinished() } removeColumn (x, z) { - this.updateChunksStats() delete this.loadedChunks[`${x},${z}`] for (const worker of this.workers) { worker.postMessage({ type: 'unloadChunk', x, z }) } + this.logWorkerWork(`-> unloadChunk ${JSON.stringify({ x, z })}`) delete this.finishedChunks[`${x},${z}`] this.allChunksFinished = Object.keys(this.finishedChunks).length === this.chunksLength - if (!this.allChunksFinished) { + if (Object.keys(this.finishedChunks).length === 0) { this.allLoadedIn = undefined this.initialChunkLoadWasStartedIn = undefined } @@ -480,20 +704,18 @@ export abstract class WorldRendererCommon this.setSectionDirty(new Vec3(x, y, z), false) delete this.finishedSections[`${x},${y},${z}`] } + this.highestBlocksByChunks.delete(`${x},${z}`) - // remove from highestBlocks - const startX = Math.floor(x / 16) * 16 - const startZ = Math.floor(z / 16) * 16 - const endX = Math.ceil((x + 1) / 16) * 16 - const endZ = Math.ceil((z + 1) / 16) * 16 - for (let x = startX; x < endX; x += 16) { - for (let z = startZ; z < endZ; z += 16) { - delete this.highestBlocks[`${x},${z}`] - } + this.updateChunksStats() + + if (Object.keys(this.loadedChunks).length === 0) { + this.mesherLogger.contents = [] + this.logWorkerWork('# all chunks unloaded. New log started') + void this.mesherLogReader?.maybeStartReplay() } } - setBlockStateId (pos: Vec3, stateId: number | undefined) { + setBlockStateId (pos: Vec3, stateId: number | undefined, needAoRecalculation = true) { const set = async () => { const sectionX = Math.floor(pos.x / 16) * 16 const sectionZ = Math.floor(pos.z / 16) * 16 @@ -507,16 +729,18 @@ export abstract class WorldRendererCommon if (!this.loadedChunks[`${sectionX},${sectionZ}`]) { // console.debug('[should be unreachable] setBlockStateId called for unloaded chunk', pos) } - this.setBlockStateIdInner(pos, stateId) + this.setBlockStateIdInner(pos, stateId, needAoRecalculation) } void set() } updateEntity (e: any, isUpdate = false) { } + abstract updatePlayerEntity? (e: any): void + lightUpdate (chunkX: number, chunkZ: number) { } - connect (worldView: WorldDataEmitter) { + connect (worldView: WorldDataEmitterWorker) { const worldEmitter = worldView worldEmitter.on('entity', (e) => { @@ -525,6 +749,9 @@ export abstract class WorldRendererCommon worldEmitter.on('entityMoved', (e) => { this.updateEntity(e, true) }) + worldEmitter.on('playerEntity', (e) => { + this.updatePlayerEntity?.(e) + }) let currentLoadChunkBatch = null as { timeout @@ -570,6 +797,10 @@ export abstract class WorldRendererCommon this.updateViewerPosition(pos) }) + worldEmitter.on('end', () => { + this.worldStop?.() + }) + worldEmitter.on('renderDistance', (d) => { this.viewDistance = d @@ -590,21 +821,24 @@ export abstract class WorldRendererCommon this.lightUpdate(pos.x, pos.z) }) + worldEmitter.on('onWorldSwitch', () => { + for (const fn of this.onWorldSwitched) { + try { + fn() + } catch (e) { + setTimeout(() => { + console.log('[Renderer Backend] Error in onWorldSwitched:') + throw e + }, 0) + } + } + }) + worldEmitter.on('time', (timeOfDay) => { + if (!this.worldRendererConfig.dayCycle) return this.timeUpdated?.(timeOfDay) - let skyLight = 15 - if (timeOfDay < 0 || timeOfDay > 24_000) { - throw new Error('Invalid time of day. It should be between 0 and 24000.') - } else if (timeOfDay <= 6000 || timeOfDay >= 18_000) { - skyLight = 15 - } else if (timeOfDay > 6000 && timeOfDay < 12_000) { - skyLight = 15 - ((timeOfDay - 6000) / 6000) * 15 - } else if (timeOfDay >= 12_000 && timeOfDay < 18_000) { - skyLight = ((timeOfDay - 12_000) / 6000) * 15 - } - - skyLight = Math.floor(skyLight) // todo: remove this after optimization + this.timeOfTheDay = timeOfDay // if (this.worldRendererConfig.skyLight === skyLight) return // this.worldRendererConfig.skyLight = skyLight @@ -613,11 +847,16 @@ export abstract class WorldRendererCommon // } }) - worldEmitter.emit('listening') + worldEmitter.on('biomeUpdate', ({ biome }) => { + this.biomeUpdated?.(biome) + }) + + worldEmitter.on('biomeReset', () => { + this.biomeReset?.() + }) } - setBlockStateIdInner (pos: Vec3, stateId: number | undefined) { - const needAoRecalculation = true + setBlockStateIdInner (pos: Vec3, stateId: number | undefined, needAoRecalculation = true) { const chunkKey = `${Math.floor(pos.x / 16) * 16},${Math.floor(pos.z / 16) * 16}` const blockPosKey = `${pos.x},${pos.y},${pos.z}` const customBlockModels = this.protocolCustomBlocks.get(chunkKey) || {} @@ -630,6 +869,7 @@ export abstract class WorldRendererCommon customBlockModels }) } + this.logWorkerWork(`-> blockUpdate ${JSON.stringify({ pos, stateId, customBlockModels })}`) this.setSectionDirty(pos, true, true) if (this.neighborChunkUpdates) { if ((pos.x & 15) === 0) this.setSectionDirty(pos.offset(-16, 0, 0), true, true) @@ -664,8 +904,10 @@ export abstract class WorldRendererCommon } } + abstract worldStop? () + queueAwaited = false - messagesQueue = {} as { [workerIndex: string]: any[] } + toWorkerMessagesQueue = {} as { [workerIndex: string]: any[] } getWorkerNumber (pos: Vec3, updateAction = false) { if (updateAction) { @@ -678,10 +920,31 @@ export abstract class WorldRendererCommon return hash + 1 } + async debugGetWorkerCustomBlockModel (pos: Vec3) { + const data = [] as Array> + for (const worker of this.workers) { + data.push(new Promise((resolve) => { + worker.addEventListener('message', (e) => { + if (e.data.type === 'customBlockModel') { + resolve(e.data.customBlockModel) + } + }) + })) + worker.postMessage({ + type: 'getCustomBlockModel', + pos + }) + } + return Promise.all(data) + } + setSectionDirty (pos: Vec3, value = true, useChangeWorker = false) { // value false is used for unloading chunks + if (!this.forceCallFromMesherReplayer && this.mesherLogReader) return + if (this.viewDistance === -1) throw new Error('viewDistance not set') this.reactiveState.world.mesherWork = true const distance = this.getDistance(pos) + // todo shouldnt we check loadedChunks instead? if (!this.workers.length || distance[0] > this.viewDistance || distance[1] > this.viewDistance) return const key = `${Math.floor(pos.x / 16) * 16},${Math.floor(pos.y / 16) * 16},${Math.floor(pos.z / 16) * 16}` // if (this.sectionsOutstanding.has(key)) return @@ -689,19 +952,30 @@ export abstract class WorldRendererCommon // Dispatch sections to workers based on position // This guarantees uniformity accross workers and that a given section // is always dispatched to the same worker - const hash = this.getWorkerNumber(pos, useChangeWorker) + const hash = this.getWorkerNumber(pos, useChangeWorker && this.mesherLogger.active) this.sectionsWaiting.set(key, (this.sectionsWaiting.get(key) ?? 0) + 1) - this.messagesQueue[hash] ??= [] - this.messagesQueue[hash].push({ - // this.workers[hash].postMessage({ - type: 'dirty', - x: pos.x, - y: pos.y, - z: pos.z, - value, - config: this.getMesherConfig(), - }) - this.dispatchMessages() + if (this.forceCallFromMesherReplayer) { + this.workers[hash].postMessage({ + type: 'dirty', + x: pos.x, + y: pos.y, + z: pos.z, + value, + config: this.getMesherConfig(), + }) + } else { + this.toWorkerMessagesQueue[hash] ??= [] + this.toWorkerMessagesQueue[hash].push({ + // this.workers[hash].postMessage({ + type: 'dirty', + x: pos.x, + y: pos.y, + z: pos.z, + value, + config: this.getMesherConfig(), + }) + this.dispatchMessages() + } } dispatchMessages () { @@ -709,11 +983,14 @@ export abstract class WorldRendererCommon this.queueAwaited = true setTimeout(() => { // group messages and send as one - for (const workerIndex in this.messagesQueue) { + for (const workerIndex in this.toWorkerMessagesQueue) { const worker = this.workers[Number(workerIndex)] - worker.postMessage(this.messagesQueue[workerIndex]) + worker.postMessage(this.toWorkerMessagesQueue[workerIndex]) + for (const message of this.toWorkerMessagesQueue[workerIndex]) { + this.logWorkerWork(`-> ${workerIndex} dispatchMessages ${message.type} ${JSON.stringify({ x: message.x, y: message.y, z: message.z, value: message.value })}`) + } } - this.messagesQueue = {} + this.toWorkerMessagesQueue = {} this.queueAwaited = false }) } @@ -770,9 +1047,41 @@ export abstract class WorldRendererCommon this.active = false this.renderUpdateEmitter.removeAllListeners() - this.displayOptions.worldView.removeAllListeners() // todo this.abortController.abort() - removeStat('chunks-loaded') - removeStat('chunks-read') + removeAllStats() + } +} + +export const initMesherWorker = (onGotMessage: (data: any) => void) => { + // Node environment needs an absolute path, but browser needs the url of the file + const workerName = 'mesher.js' + + let worker: any + if (process.env.SINGLE_FILE_BUILD) { + const workerCode = document.getElementById('mesher-worker-code')!.textContent! + const blob = new Blob([workerCode], { type: 'text/javascript' }) + worker = new Worker(window.URL.createObjectURL(blob)) + } else { + worker = new Worker(workerName) + } + + worker.onmessage = ({ data }) => { + onGotMessage(data) + } + if (worker.on) worker.on('message', (data) => { worker.onmessage({ data }) }) + return worker +} + +export const meshersSendMcData = (workers: Worker[], version: string, addData = {} as Record) => { + const allMcData = mcDataRaw.pc[version] ?? mcDataRaw.pc[toMajorVersion(version)] + const mcData = { + version: JSON.parse(JSON.stringify(allMcData.version)) + } + for (const key of dynamicMcDataFiles) { + mcData[key] = allMcData[key] + } + + for (const worker of workers) { + worker.postMessage({ type: 'mcData', mcData, ...addData }) } } diff --git a/renderer/viewer/sign-renderer/index.ts b/renderer/viewer/sign-renderer/index.ts index a1e4331f..f14b9b4c 100644 --- a/renderer/viewer/sign-renderer/index.ts +++ b/renderer/viewer/sign-renderer/index.ts @@ -1,5 +1,5 @@ -import { fromFormattedString, render, RenderNode, TextComponent } from '@xmcl/text-component' import type { ChatMessage } from 'prismarine-chat' +import { createCanvas } from '../lib/utils' type SignBlockEntity = { Color?: string @@ -32,29 +32,40 @@ const parseSafe = (text: string, task: string) => { } } -export const renderSign = (blockEntity: SignBlockEntity, PrismarineChat: typeof ChatMessage, ctxHook = (ctx) => { }) => { +const LEGACY_COLORS = { + black: '#000000', + dark_blue: '#0000AA', + dark_green: '#00AA00', + dark_aqua: '#00AAAA', + dark_red: '#AA0000', + dark_purple: '#AA00AA', + gold: '#FFAA00', + gray: '#AAAAAA', + dark_gray: '#555555', + blue: '#5555FF', + green: '#55FF55', + aqua: '#55FFFF', + red: '#FF5555', + light_purple: '#FF55FF', + yellow: '#FFFF55', + white: '#FFFFFF', +} + +export const renderSign = ( + blockEntity: SignBlockEntity, + isHanging: boolean, + PrismarineChat: typeof ChatMessage, + ctxHook = (ctx) => { }, + canvasCreator = (width, height): OffscreenCanvas => { return createCanvas(width, height) } +) => { // todo don't use texture rendering, investigate the font rendering when possible // or increase factor when needed const factor = 40 + const fontSize = 1.6 * factor const signboardY = [16, 9] const heightOffset = signboardY[0] - signboardY[1] const heightScalar = heightOffset / 16 - - let canvas: HTMLCanvasElement | undefined - let _ctx: CanvasRenderingContext2D | null = null - const getCtx = () => { - if (_ctx) return _ctx - canvas = document.createElement('canvas') - - canvas.width = 16 * factor - canvas.height = heightOffset * factor - - _ctx = canvas.getContext('2d')! - _ctx.imageSmoothingEnabled = false - - ctxHook(_ctx) - return _ctx - } + // todo the text should be clipped based on it's render width (needs investigate) const texts = 'front_text' in blockEntity ? /* > 1.20 */ blockEntity.front_text.messages : [ blockEntity.Text1, @@ -62,78 +73,144 @@ export const renderSign = (blockEntity: SignBlockEntity, PrismarineChat: typeof blockEntity.Text3, blockEntity.Text4 ] + + if (!texts.some((text) => text !== 'null')) { + return undefined + } + + const canvas = canvasCreator(16 * factor, heightOffset * factor) + + const _ctx = canvas.getContext('2d')! + + ctxHook(_ctx) const defaultColor = ('front_text' in blockEntity ? blockEntity.front_text.color : blockEntity.Color) || 'black' for (const [lineNum, text] of texts.slice(0, 4).entries()) { - // todo: in pre flatenning it seems the format was not json if (text === 'null') continue - const parsed = text?.startsWith('{') || text?.startsWith('"') ? parseSafe(text ?? '""', 'sign text') : text - if (!parsed || (typeof parsed !== 'object' && typeof parsed !== 'string')) continue - // todo fix type - const message = typeof parsed === 'string' ? fromFormattedString(parsed) : new PrismarineChat(parsed) as never - const patchExtra = ({ extra }: TextComponent) => { - if (!extra) return - for (const child of extra) { - if (child.color) { - child.color = child.color === 'dark_green' ? child.color.toUpperCase() : child.color.toLowerCase() - } - patchExtra(child) - } - } - patchExtra(message) - const rendered = render(message) - - const toRenderCanvas: Array<{ - fontStyle: string - fillStyle: string - underlineStyle: boolean - strikeStyle: boolean - text: string - }> = [] - let plainText = '' - // todo the text should be clipped based on it's render width (needs investigate) - const MAX_LENGTH = 50 // avoid abusing the signboard - const renderText = (node: RenderNode) => { - const { component } = node - let { text } = component - if (plainText.length + text.length > MAX_LENGTH) { - text = text.slice(0, MAX_LENGTH - plainText.length) - if (!text) return false - } - plainText += text - toRenderCanvas.push({ - fontStyle: `${component.bold ? 'bold' : ''} ${component.italic ? 'italic' : ''}`, - fillStyle: node.style['color'] || defaultColor, - underlineStyle: component.underlined ?? false, - strikeStyle: component.strikethrough ?? false, - text - }) - for (const child of node.children) { - const stop = renderText(child) === false - if (stop) return false - } - } - - renderText(rendered) - - // skip rendering empty lines (and possible signs) - if (!plainText.trim()) continue - - const ctx = getCtx() - const fontSize = 1.6 * factor - ctx.font = `${fontSize}px mojangles` - const textWidth = ctx.measureText(plainText).width - - let renderedWidth = 0 - for (const { fillStyle, fontStyle, strikeStyle, text, underlineStyle } of toRenderCanvas) { - // todo strikeStyle, underlineStyle - ctx.fillStyle = fillStyle - ctx.font = `${fontStyle} ${fontSize}px mojangles` - ctx.fillText(text, (canvas!.width - textWidth) / 2 + renderedWidth, fontSize * (lineNum + 1)) - renderedWidth += ctx.measureText(text).width // todo isn't the font is monospace? - } + renderComponent(text, PrismarineChat, canvas, fontSize, defaultColor, fontSize * (lineNum + 1) + (isHanging ? 0 : -8)) } - // ctx.fillStyle = 'red' - // ctx.fillRect(0, 0, canvas.width, canvas.height) - return canvas } + +export const renderComponent = ( + text: JsonEncodedType | string | undefined, + PrismarineChat: typeof ChatMessage, + canvas: OffscreenCanvas, + fontSize: number, + defaultColor: string, + offset = 0 +) => { + // todo: in pre flatenning it seems the format was not json + const parsed = typeof text === 'string' && (text?.startsWith('{') || text?.startsWith('"')) ? parseSafe(text ?? '""', 'sign text') : text + if (!parsed || (typeof parsed !== 'object' && typeof parsed !== 'string')) return + // todo fix type + + const ctx = canvas.getContext('2d')! + if (!ctx) throw new Error('Could not get 2d context') + ctx.imageSmoothingEnabled = false + ctx.font = `${fontSize}px mojangles` + + type Formatting = { + color: string | undefined + underlined: boolean | undefined + strikethrough: boolean | undefined + bold: boolean | undefined + italic: boolean | undefined + } + + type Message = ChatMessage & Formatting & { text: string } + + const message = new PrismarineChat(parsed) as Message + + const toRenderCanvas: Array<{ + fontStyle: string + fillStyle: string + underlineStyle: boolean + strikeStyle: boolean + offset: number + text: string + }> = [] + let visibleFormatting = false + let plainText = '' + let textOffset = offset + const textWidths: number[] = [] + + const renderText = (component: Message, parentFormatting?: Formatting | undefined) => { + const { text } = component + const formatting = { + color: component.color ?? parentFormatting?.color, + underlined: component.underlined ?? parentFormatting?.underlined, + strikethrough: component.strikethrough ?? parentFormatting?.strikethrough, + bold: component.bold ?? parentFormatting?.bold, + italic: component.italic ?? parentFormatting?.italic + } + visibleFormatting = visibleFormatting || formatting.underlined || formatting.strikethrough || false + if (text?.includes('\n')) { + for (const line of text.split('\n')) { + addTextPart(line, formatting) + textOffset += fontSize + plainText = '' + } + } else if (text) { + addTextPart(text, formatting) + } + if (component.extra) { + for (const child of component.extra) { + renderText(child as Message, formatting) + } + } + } + + const addTextPart = (text: string, formatting: Formatting) => { + plainText += text + textWidths[textOffset] = ctx.measureText(plainText).width + let color = formatting.color ?? defaultColor + if (!color.startsWith('#')) { + color = LEGACY_COLORS[color.toLowerCase()] || color + } + toRenderCanvas.push({ + fontStyle: `${formatting.bold ? 'bold' : ''} ${formatting.italic ? 'italic' : ''}`, + fillStyle: color, + underlineStyle: formatting.underlined ?? false, + strikeStyle: formatting.strikethrough ?? false, + offset: textOffset, + text + }) + } + + renderText(message) + + // skip rendering empty lines + if (!visibleFormatting && !message.toString().trim()) return + + let renderedWidth = 0 + let previousOffsetY = 0 + for (const { fillStyle, fontStyle, underlineStyle, strikeStyle, offset: offsetY, text } of toRenderCanvas) { + if (previousOffsetY !== offsetY) { + renderedWidth = 0 + } + previousOffsetY = offsetY + ctx.fillStyle = fillStyle + ctx.textRendering = 'optimizeLegibility' + ctx.font = `${fontStyle} ${fontSize}px mojangles` + const textWidth = textWidths[offsetY] ?? ctx.measureText(text).width + const offsetX = (canvas.width - textWidth) / 2 + renderedWidth + ctx.fillText(text, offsetX, offsetY) + if (strikeStyle) { + ctx.lineWidth = fontSize / 8 + ctx.strokeStyle = fillStyle + ctx.beginPath() + ctx.moveTo(offsetX, offsetY - ctx.lineWidth * 2.5) + ctx.lineTo(offsetX + ctx.measureText(text).width, offsetY - ctx.lineWidth * 2.5) + ctx.stroke() + } + if (underlineStyle) { + ctx.lineWidth = fontSize / 8 + ctx.strokeStyle = fillStyle + ctx.beginPath() + ctx.moveTo(offsetX, offsetY + ctx.lineWidth) + ctx.lineTo(offsetX + ctx.measureText(text).width, offsetY + ctx.lineWidth) + ctx.stroke() + } + renderedWidth += ctx.measureText(text).width + } +} diff --git a/renderer/viewer/sign-renderer/playground.ts b/renderer/viewer/sign-renderer/playground.ts index 92ff5d03..a7438092 100644 --- a/renderer/viewer/sign-renderer/playground.ts +++ b/renderer/viewer/sign-renderer/playground.ts @@ -21,9 +21,14 @@ const blockEntity = { await document.fonts.load('1em mojangles') -const canvas = renderSign(blockEntity, PrismarineChat, (ctx) => { +const canvas = renderSign(blockEntity, false, PrismarineChat, (ctx) => { ctx.drawImage(img, 0, 0, ctx.canvas.width, ctx.canvas.height) -}) +}, (width, height) => { + const canvas = document.createElement('canvas') + canvas.width = width + canvas.height = height + return canvas as unknown as OffscreenCanvas +}) as unknown as HTMLCanvasElement if (canvas) { canvas.style.imageRendering = 'pixelated' diff --git a/renderer/viewer/sign-renderer/tests.test.ts b/renderer/viewer/sign-renderer/tests.test.ts index b8fc94fc..ab268849 100644 --- a/renderer/viewer/sign-renderer/tests.test.ts +++ b/renderer/viewer/sign-renderer/tests.test.ts @@ -22,7 +22,7 @@ global.document = { const render = (entity) => { ctxTexts = [] - renderSign(entity, PrismarineChat) + renderSign(entity, true, PrismarineChat) return ctxTexts.map(({ text, y }) => [y / 64, text]) } @@ -37,10 +37,6 @@ test('sign renderer', () => { } as any expect(render(blockEntity)).toMatchInlineSnapshot(` [ - [ - 1, - "", - ], [ 1, "Minecraft ", diff --git a/renderer/viewer/three/appShared.ts b/renderer/viewer/three/appShared.ts index b41d32db..5be9e10b 100644 --- a/renderer/viewer/three/appShared.ts +++ b/renderer/viewer/three/appShared.ts @@ -1,16 +1,16 @@ import { BlockModel } from 'mc-assets/dist/types' -import { ItemSpecificContextProperties } from 'renderer/viewer/lib/basePlayerState' -import { renderSlot } from '../../../src/inventoryWindows' +import { ItemSpecificContextProperties, PlayerStateRenderer } from 'renderer/viewer/lib/basePlayerState' import { GeneralInputItem, getItemModelName } from '../../../src/mineflayer/items' -import { ResourcesManager } from '../../../src/resourcesManager' +import { ResourcesManager, ResourcesManagerTransferred } from '../../../src/resourcesManager' +import { renderSlot } from './renderSlot' -export const getItemUv = (item: Record, specificProps: ItemSpecificContextProperties, resourcesManager: ResourcesManager): { +export const getItemUv = (item: Record, specificProps: ItemSpecificContextProperties, resourcesManager: ResourcesManagerTransferred, playerState: PlayerStateRenderer): { u: number v: number su: number sv: number renderInfo?: ReturnType - texture: HTMLImageElement + // texture: ImageBitmap modelName: string } | { resolvedModel: BlockModel @@ -19,18 +19,22 @@ export const getItemUv = (item: Record, specificProps: ItemSpecific const resources = resourcesManager.currentResources if (!resources) throw new Error('Resources not loaded') const idOrName = item.itemId ?? item.blockId ?? item.name + const { blockState } = item try { - const name = typeof idOrName === 'number' ? loadedData.items[idOrName]?.name : idOrName + const name = + blockState + ? loadedData.blocksByStateId[blockState]?.name + : typeof idOrName === 'number' ? loadedData.items[idOrName]?.name : idOrName if (!name) throw new Error(`Item not found: ${idOrName}`) const model = getItemModelName({ ...item, name, - } as GeneralInputItem, specificProps) + } as GeneralInputItem, specificProps, resourcesManager, playerState) const renderInfo = renderSlot({ modelName: model, - }, false, true) + }, resourcesManager, false, true) if (!renderInfo) throw new Error(`Failed to get render info for item ${name}`) @@ -49,7 +53,7 @@ export const getItemUv = (item: Record, specificProps: ItemSpecific return { u, v, su, sv, renderInfo, - texture: img, + // texture: img, modelName: renderInfo.modelName! } } @@ -63,7 +67,7 @@ export const getItemUv = (item: Record, specificProps: ItemSpecific v: 0, su: 16 / resources.blocksAtlasImage.width, sv: 16 / resources.blocksAtlasImage.width, - texture: resources.blocksAtlasImage, + // texture: resources.blocksAtlasImage, modelName: 'missing' } } diff --git a/renderer/viewer/three/cameraShake.ts b/renderer/viewer/three/cameraShake.ts index f6a61e2e..7b159509 100644 --- a/renderer/viewer/three/cameraShake.ts +++ b/renderer/viewer/three/cameraShake.ts @@ -1,4 +1,5 @@ import * as THREE from 'three' +import { WorldRendererThree } from './worldrendererThree' export class CameraShake { private rollAngle = 0 @@ -8,7 +9,7 @@ export class CameraShake { private basePitch = 0 private baseYaw = 0 - constructor (public camera: THREE.Camera, public onRenderCallbacks: Array<() => void>) { + constructor (public worldRenderer: WorldRendererThree, public onRenderCallbacks: Array<() => void>) { onRenderCallbacks.push(() => { this.update() }) @@ -20,6 +21,10 @@ export class CameraShake { this.update() } + getBaseRotation () { + return { pitch: this.basePitch, yaw: this.baseYaw } + } + shakeFromDamage (yaw?: number) { // Add roll animation const startRoll = this.rollAngle @@ -34,6 +39,11 @@ export class CameraShake { } update () { + if (this.worldRenderer.playerStateUtils.isSpectatingEntity()) { + // Remove any shaking when spectating + this.rollAngle = 0 + this.rollAnimation = undefined + } // Update roll animation if (this.rollAnimation) { const now = performance.now() @@ -62,14 +72,25 @@ export class CameraShake { } } - // Create rotation quaternions - const pitchQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), this.basePitch) - const yawQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), this.baseYaw) - const rollQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 0, 1), THREE.MathUtils.degToRad(this.rollAngle)) + const camera = this.worldRenderer.cameraObject - // Combine rotations in the correct order: pitch -> yaw -> roll - const finalQuat = yawQuat.multiply(pitchQuat).multiply(rollQuat) - this.camera.setRotationFromQuaternion(finalQuat) + if (this.worldRenderer.cameraGroupVr) { + // For VR camera, only apply yaw rotation + const yawQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), this.baseYaw) + camera.setRotationFromQuaternion(yawQuat) + } else { + // For regular camera, apply all rotations + // Add tiny offsets to prevent z-fighting at ideal angles (90, 180, 270 degrees) + const pitchOffset = this.addAntiZfightingOffset(this.basePitch) + const yawOffset = this.addAntiZfightingOffset(this.baseYaw) + + const pitchQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), pitchOffset) + const yawQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), yawOffset) + const rollQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 0, 1), THREE.MathUtils.degToRad(this.rollAngle)) + // Combine rotations in the correct order: pitch -> yaw -> roll + const finalQuat = yawQuat.multiply(pitchQuat).multiply(rollQuat) + camera.setRotationFromQuaternion(finalQuat) + } } private easeOut (t: number): number { @@ -79,4 +100,21 @@ export class CameraShake { private easeInOut (t: number): number { return t < 0.5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2 } + + private addAntiZfightingOffset (angle: number): number { + const offset = 0.001 // Very small offset in radians (about 0.057 degrees) + + // Check if the angle is close to ideal angles (0, π/2, π, 3π/2) + const normalizedAngle = ((angle % (Math.PI * 2)) + Math.PI * 2) % (Math.PI * 2) + const tolerance = 0.01 // Tolerance for considering an angle "ideal" + + if (Math.abs(normalizedAngle) < tolerance || + Math.abs(normalizedAngle - Math.PI / 2) < tolerance || + Math.abs(normalizedAngle - Math.PI) < tolerance || + Math.abs(normalizedAngle - 3 * Math.PI / 2) < tolerance) { + return angle + offset + } + + return angle + } } diff --git a/renderer/viewer/three/documentRenderer.ts b/renderer/viewer/three/documentRenderer.ts index 29e43ee9..a5dc060d 100644 --- a/renderer/viewer/three/documentRenderer.ts +++ b/renderer/viewer/three/documentRenderer.ts @@ -3,17 +3,23 @@ import Stats from 'stats.js' import StatsGl from 'stats-gl' import * as tween from '@tweenjs/tween.js' import { GraphicsBackendConfig, GraphicsInitOptions } from '../../../src/appViewer' +import { WorldRendererConfig } from '../lib/worldrendererCommon' export class DocumentRenderer { - readonly canvas = document.createElement('canvas') + canvas: HTMLCanvasElement | OffscreenCanvas readonly renderer: THREE.WebGLRenderer private animationFrameId?: number + private timeoutId?: number private lastRenderTime = 0 - private previousWindowWidth = window.innerWidth - private previousWindowHeight = window.innerHeight + + private previousCanvasWidth = 0 + private previousCanvasHeight = 0 + private currentWidth = 0 + private currentHeight = 0 + private renderedFps = 0 private fpsInterval: any - private readonly stats: TopRightStats + private readonly stats: TopRightStats | undefined private paused = false disconnected = false preRender = () => { } @@ -22,10 +28,19 @@ export class DocumentRenderer { sizeChanged = () => { } droppedFpsPercentage: number config: GraphicsBackendConfig + onRender = [] as Array<(sizeChanged: boolean) => void> + inWorldRenderingConfig: WorldRendererConfig | undefined - constructor (initOptions: GraphicsInitOptions) { + constructor (initOptions: GraphicsInitOptions, public externalCanvas?: OffscreenCanvas) { this.config = initOptions.config + // Handle canvas creation/transfer based on context + if (externalCanvas) { + this.canvas = externalCanvas + } else { + this.addToPage() + } + try { this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas, @@ -34,17 +49,25 @@ export class DocumentRenderer { powerPreference: this.config.powerPreference }) } catch (err) { - initOptions.displayCriticalError(new Error(`Failed to create WebGL context, not possible to render (restart browser): ${err.message}`)) + initOptions.callbacks.displayCriticalError(new Error(`Failed to create WebGL context, not possible to render (restart browser): ${err.message}`)) throw err } this.renderer.outputColorSpace = THREE.LinearSRGBColorSpace - this.updatePixelRatio() - this.updateSize() - this.addToPage() + if (!externalCanvas) { + this.updatePixelRatio() + } + this.sizeUpdated() + // Initialize previous dimensions + this.previousCanvasWidth = this.canvas.width + this.previousCanvasHeight = this.canvas.height - this.stats = new TopRightStats(this.canvas, this.config.statsVisible) + const supportsWebGL2 = 'WebGL2RenderingContext' in window + // Only initialize stats and DOM-related features in main thread + if (!externalCanvas && supportsWebGL2) { + this.stats = new TopRightStats(this.canvas as HTMLCanvasElement, this.config.statsVisible) + this.setupFpsTracking() + } - this.setupFpsTracking() this.startRenderLoop() } @@ -56,15 +79,33 @@ export class DocumentRenderer { this.renderer.setPixelRatio(pixelRatio) } - updateSize () { - this.renderer.setSize(window.innerWidth, window.innerHeight) + sizeUpdated () { + this.renderer.setSize(this.currentWidth, this.currentHeight, false) } private addToPage () { - this.canvas.id = 'viewer-canvas' - this.canvas.style.width = '100%' - this.canvas.style.height = '100%' - document.body.appendChild(this.canvas) + this.canvas = addCanvasToPage() + this.updateCanvasSize() + } + + updateSizeExternal (newWidth: number, newHeight: number, pixelRatio: number) { + this.currentWidth = newWidth + this.currentHeight = newHeight + this.renderer.setPixelRatio(pixelRatio) + this.sizeUpdated() + } + + private updateCanvasSize () { + if (!this.externalCanvas) { + const innnerWidth = window.innerWidth + const innnerHeight = window.innerHeight + if (this.currentWidth !== innnerWidth) { + this.currentWidth = innnerWidth + } + if (this.currentHeight !== innnerHeight) { + this.currentHeight = innnerHeight + } + } } private setupFpsTracking () { @@ -78,22 +119,17 @@ export class DocumentRenderer { }, 1000) } - // private handleResize () { - // const width = window.innerWidth - // const height = window.innerHeight - - // viewer.camera.aspect = width / height - // viewer.camera.updateProjectionMatrix() - // this.renderer.setSize(width, height) - // viewer.world.handleResize() - // } - private startRenderLoop () { const animate = () => { if (this.disconnected) return - this.animationFrameId = requestAnimationFrame(animate) - if (this.paused) return + if (this.config.timeoutRendering) { + this.timeoutId = setTimeout(animate, this.config.fpsLimit ? 1000 / this.config.fpsLimit : 0) as unknown as number + } else { + this.animationFrameId = requestAnimationFrame(animate) + } + + if (this.paused || (this.renderer.xr.isPresenting && !this.inWorldRenderingConfig?.vrPageGameRendering)) return // Handle FPS limiting if (this.config.fpsLimit) { @@ -109,30 +145,40 @@ export class DocumentRenderer { } let sizeChanged = false - if (this.previousWindowWidth !== window.innerWidth || this.previousWindowHeight !== window.innerHeight) { - this.previousWindowWidth = window.innerWidth - this.previousWindowHeight = window.innerHeight - this.updateSize() + this.updateCanvasSize() + if (this.previousCanvasWidth !== this.currentWidth || this.previousCanvasHeight !== this.currentHeight) { + this.previousCanvasWidth = this.currentWidth + this.previousCanvasHeight = this.currentHeight + this.sizeUpdated() sizeChanged = true } - this.preRender() - this.stats.markStart() - tween.update() - this.render(sizeChanged) - this.renderedFps++ - this.stats.markEnd() - this.postRender() + this.frameRender(sizeChanged) - // Update stats visibility each frame + // Update stats visibility each frame (main thread only) if (this.config.statsVisible !== undefined) { - this.stats.setVisibility(this.config.statsVisible) + this.stats?.setVisibility(this.config.statsVisible) } } animate() } + frameRender (sizeChanged: boolean) { + this.preRender() + this.stats?.markStart() + tween.update() + if (!globalThis.freezeRender) { + this.render(sizeChanged) + } + for (const fn of this.onRender) { + fn(sizeChanged) + } + this.renderedFps++ + this.stats?.markEnd() + this.postRender() + } + setPaused (paused: boolean) { this.paused = paused } @@ -142,10 +188,15 @@ export class DocumentRenderer { if (this.animationFrameId) { cancelAnimationFrame(this.animationFrameId) } - this.canvas.remove() - this.renderer.dispose() + if (this.timeoutId) { + clearTimeout(this.timeoutId) + } + if (this.canvas instanceof HTMLCanvasElement) { + this.canvas.remove() + } clearInterval(this.fpsInterval) - this.stats.dispose() + this.stats?.dispose() + this.renderer.dispose() } } @@ -185,6 +236,10 @@ class TopRightStats { const hasRamPanel = this.stats2.dom.children.length === 3 this.addStat(this.stats.dom) + if (process.env.NODE_ENV === 'development' && document.exitPointerLock) { + this.stats.dom.style.top = '' + this.stats.dom.style.bottom = '0' + } if (hasRamPanel) { this.addStat(this.stats2.dom) } @@ -234,3 +289,40 @@ class TopRightStats { this.statsGl.container.remove() } } + +const addCanvasToPage = () => { + const canvas = document.createElement('canvas') + canvas.id = 'viewer-canvas' + document.body.appendChild(canvas) + return canvas +} + +export const addCanvasForWorker = () => { + const canvas = addCanvasToPage() + const transferred = canvas.transferControlToOffscreen() + let removed = false + let onSizeChanged = (w, h) => { } + let oldSize = { width: 0, height: 0 } + const checkSize = () => { + if (removed) return + if (oldSize.width !== window.innerWidth || oldSize.height !== window.innerHeight) { + onSizeChanged(window.innerWidth, window.innerHeight) + oldSize = { width: window.innerWidth, height: window.innerHeight } + } + requestAnimationFrame(checkSize) + } + requestAnimationFrame(checkSize) + return { + canvas: transferred, + destroy () { + removed = true + canvas.remove() + }, + onSizeChanged (cb: (width: number, height: number) => void) { + onSizeChanged = cb + }, + get size () { + return { width: window.innerWidth, height: window.innerHeight } + } + } +} diff --git a/renderer/viewer/three/entities.ts b/renderer/viewer/three/entities.ts index 45202608..fad30182 100644 --- a/renderer/viewer/three/entities.ts +++ b/renderer/viewer/three/entities.ts @@ -1,11 +1,10 @@ //@ts-check -import EventEmitter from 'events' import { UnionToIntersection } from 'type-fest' import nbt from 'prismarine-nbt' import * as TWEEN from '@tweenjs/tween.js' import * as THREE from 'three' -import { PlayerObject, PlayerAnimation } from 'skinview3d' -import { loadSkinToCanvas, loadEarsToCanvasFromSkin, inferModelType, loadCapeToCanvas, loadImage } from 'skinview-utils' +import { PlayerAnimation, PlayerObject } from 'skinview3d' +import { inferModelType, loadCapeToCanvas, loadEarsToCanvasFromSkin } from 'skinview-utils' // todo replace with url import { degreesToRadians } from '@nxg-org/mineflayer-tracker/lib/mathUtils' import { NameTagObject } from 'skinview3d/libs/nametag' @@ -13,24 +12,27 @@ import { flat, fromFormattedString } from '@xmcl/text-component' import mojangson from 'mojangson' import { snakeCase } from 'change-case' import { Item } from 'prismarine-item' -import { BlockModel } from 'mc-assets' import { isEntityAttackable } from 'mineflayer-mouse/dist/attackableEntity' -import { Vec3 } from 'vec3' +import { Team } from 'mineflayer' +import PrismarineChatLoader from 'prismarine-chat' import { EntityMetadataVersions } from '../../../src/mcDataTypes' import { ItemSpecificContextProperties } from '../lib/basePlayerState' -import { loadSkinImage, getLookupUrl, stevePngUrl, steveTexture } from '../lib/utils/skins' -import { loadTexture } from '../lib/utils' +import { loadSkinFromUsername, loadSkinImage, stevePngUrl } from '../lib/utils/skins' +import { renderComponent } from '../sign-renderer' +import { createCanvas } from '../lib/utils' +import { PlayerObjectType } from '../lib/createPlayerObject' import { getBlockMeshFromModel } from './holdingBlock' +import { createItemMesh } from './itemMesh' import * as Entity from './entity/EntityMesh' import { getMesh } from './entity/EntityMesh' import { WalkingGeneralSwing } from './entity/animations' -import { disposeObject } from './threeJsUtils' -import { armorModel, armorTextures } from './entity/armorModels' +import { disposeObject, loadTexture, loadThreeJsTextureFromUrl } from './threeJsUtils' +import { armorModel, armorTextures, elytraTexture } from './entity/armorModels' import { WorldRendererThree } from './worldrendererThree' -export const TWEEN_DURATION = 120 +export const steveTexture = loadThreeJsTextureFromUrl(stevePngUrl) -type PlayerObjectType = PlayerObject & { animation?: PlayerAnimation } +export const TWEEN_DURATION = 120 function convert2sComplementToHex (complement: number) { if (complement < 0) { @@ -91,8 +93,11 @@ function getUsernameTexture ({ username, nameTagBackgroundColor = 'rgba(0, 0, 0, 0.3)', nameTagTextOpacity = 255 -}: any, { fontFamily = 'sans-serif' }: any) { - const canvas = document.createElement('canvas') +}: any, { fontFamily = 'mojangles' }: any, version: string) { + const canvas = createCanvas(64, 64) + + const PrismarineChat = PrismarineChatLoader(version) + const ctx = canvas.getContext('2d') if (!ctx) throw new Error('Could not get 2d context') @@ -100,38 +105,39 @@ function getUsernameTexture ({ const padding = 5 ctx.font = `${fontSize}px ${fontFamily}` - const lines = String(username).split('\n') - + const plainLines = String(typeof username === 'string' ? username : new PrismarineChat(username).toString()).split('\n') let textWidth = 0 - for (const line of lines) { + for (const line of plainLines) { const width = ctx.measureText(line).width + padding * 2 if (width > textWidth) textWidth = width } canvas.width = textWidth - canvas.height = (fontSize + padding) * lines.length + canvas.height = (fontSize + padding) * plainLines.length ctx.fillStyle = nameTagBackgroundColor ctx.fillRect(0, 0, canvas.width, canvas.height) - ctx.font = `${fontSize}px ${fontFamily}` - ctx.fillStyle = `rgba(255, 255, 255, ${nameTagTextOpacity / 255})` - let i = 0 - for (const line of lines) { - i++ - ctx.fillText(line, (textWidth - ctx.measureText(line).width) / 2, -padding + fontSize * i) - } + ctx.globalAlpha = nameTagTextOpacity / 255 + + renderComponent(username, PrismarineChat, canvas, fontSize, 'white', -padding + fontSize) + + ctx.globalAlpha = 1 return canvas } -const addNametag = (entity, options, mesh) => { +const addNametag = (entity, options: { fontFamily: string }, mesh, version: string) => { + for (const c of mesh.children) { + if (c.name === 'nametag') { + c.removeFromParent() + } + } if (entity.username !== undefined) { - if (mesh.children.some(c => c.name === 'nametag')) return // todo update - const canvas = getUsernameTexture(entity, options) + const canvas = getUsernameTexture(entity, options, version) const tex = new THREE.Texture(canvas) tex.needsUpdate = true - let nameTag + let nameTag: THREE.Object3D if (entity.nameTagFixed) { const geometry = new THREE.PlaneGeometry() const material = new THREE.MeshBasicMaterial({ map: tex }) @@ -161,6 +167,7 @@ const addNametag = (entity, options, mesh) => { nameTag.name = 'nametag' mesh.add(nameTag) + return nameTag } } @@ -169,7 +176,7 @@ const nametags = {} const isFirstUpperCase = (str) => str.charAt(0) === str.charAt(0).toUpperCase() -function getEntityMesh (entity: import('prismarine-entity').Entity & { delete?: any; pos: any; name: any }, world: WorldRendererThree | undefined, options: { fontFamily: string }, overrides) { +function getEntityMesh (entity: import('prismarine-entity').Entity & { delete?: any; pos?: any; name?: any }, world: WorldRendererThree, options: { fontFamily: string }, overrides) { if (entity.name) { try { // https://github.com/PrismarineJS/prismarine-viewer/pull/410 @@ -177,7 +184,7 @@ function getEntityMesh (entity: import('prismarine-entity').Entity & { delete?: const e = new Entity.EntityMesh('1.16.4', entityName, world, overrides) if (e.mesh) { - addNametag(entity, options, e.mesh) + addNametag(entity, options, e.mesh, world.version) return e.mesh } } catch (err) { @@ -195,22 +202,22 @@ function getEntityMesh (entity: import('prismarine-entity').Entity & { delete?: addNametag({ username: entity.name, height: entity.height, - }, options, cube) + }, options, cube, world.version) } return cube } export type SceneEntity = THREE.Object3D & { - playerObject?: PlayerObject & { - animation?: PlayerAnimation - } + playerObject?: PlayerObjectType username?: string uuid?: string additionalCleanup?: () => void + originalEntity: import('prismarine-entity').Entity & { delete?; pos?, name, team?: Team } } export class Entities { entities = {} as Record + playerEntity: SceneEntity | null = null // Special entity for the player in third person entitiesOptions = { fontFamily: 'mojangles' } @@ -235,9 +242,50 @@ export class Entities { return Object.values(this.entities).filter(entity => entity.visible).length } + getDebugString (): string { + const totalEntities = Object.keys(this.entities).length + const visibleEntities = this.entitiesRenderingCount + + const playerEntities = Object.values(this.entities).filter(entity => entity.playerObject) + const visiblePlayerEntities = playerEntities.filter(entity => entity.visible) + + return `${visibleEntities}/${totalEntities} ${visiblePlayerEntities.length}/${playerEntities.length}` + } + constructor (public worldRenderer: WorldRendererThree) { this.debugMode = 'none' this.onSkinUpdate = () => { } + this.watchResourcesUpdates() + } + + handlePlayerEntity (playerData: SceneEntity['originalEntity']) { + // Create player entity if it doesn't exist + if (!this.playerEntity) { + // Create the player entity similar to how normal entities are created + const group = new THREE.Group() as unknown as SceneEntity + group.originalEntity = { ...playerData, name: 'player' } as SceneEntity['originalEntity'] + + const wrapper = new THREE.Group() + const playerObject = this.setupPlayerObject(playerData, wrapper, {}) + group.playerObject = playerObject + group.add(wrapper) + + group.name = 'player_entity' + this.playerEntity = group + this.worldRenderer.scene.add(group) + + void this.updatePlayerSkin(playerData.id, playerData.username, playerData.uuid ?? undefined, stevePngUrl) + } + + // Update position and rotation + if (playerData.position) { + this.playerEntity.position.set(playerData.position.x, playerData.position.y, playerData.position.z) + } + if (playerData.yaw !== undefined) { + this.playerEntity.rotation.y = playerData.yaw + } + + this.updateEntityEquipment(this.playerEntity, playerData) } clear () { @@ -246,6 +294,27 @@ export class Entities { disposeObject(mesh) } this.entities = {} + + // Clean up player entity + if (this.playerEntity) { + this.worldRenderer.scene.remove(this.playerEntity) + disposeObject(this.playerEntity) + this.playerEntity = null + } + } + + reloadEntities () { + for (const entity of Object.values(this.entities)) { + // update all entities textures like held items, armour, etc + // todo update entity textures itself + this.update({ ...entity.originalEntity, delete: true, } as SceneEntity['originalEntity'], {}) + this.update(entity.originalEntity, {}) + } + } + + watchResourcesUpdates () { + this.worldRenderer.resourcesManager.on('assetsTexturesUpdated', () => this.reloadEntities()) + this.worldRenderer.resourcesManager.on('assetsInventoryReady', () => this.reloadEntities()) } setDebugMode (mode: string, entity: THREE.Object3D | null = null) { @@ -278,12 +347,13 @@ export class Entities { } const dt = this.clock.getDelta() - const botPos = this.worldRenderer.viewerPosition - const VISIBLE_DISTANCE = 8 * 8 + const botPos = this.worldRenderer.viewerChunkPosition + const VISIBLE_DISTANCE = 10 * 10 - for (const entityId of Object.keys(this.entities)) { - const entity = this.entities[entityId] - const playerObject = entity.playerObject as PlayerObjectType | undefined + // Update regular entities + for (const [entityId, entity] of [...Object.entries(this.entities), ['player_entity', this.playerEntity] as [string, SceneEntity | null]]) { + if (!entity) continue + const { playerObject } = entity // Update animations if (playerObject?.animation) { @@ -297,19 +367,116 @@ export class Entities { const dz = entity.position.z - botPos.z const distanceSquared = dx * dx + dy * dy + dz * dz - // Get chunk coordinates - const chunkX = Math.floor(entity.position.x / 16) * 16 - const chunkZ = Math.floor(entity.position.z / 16) * 16 - const chunkKey = `${chunkX},${chunkZ}` + // Entity is visible if within 20 blocks OR in a finished chunk + entity.visible = !!(distanceSquared < VISIBLE_DISTANCE || this.worldRenderer.shouldObjectVisible(entity)) - // Entity is visible if within 16 blocks OR in a finished chunk - entity.visible = !!(distanceSquared < VISIBLE_DISTANCE || this.worldRenderer.finishedChunks[chunkKey]) + this.maybeRenderPlayerSkin(entityId) + } + + if (entity.visible) { + // Update armor positions + this.syncArmorPositions(entity) + } + + if (entityId === 'player_entity') { + entity.visible = this.worldRenderer.playerStateUtils.isThirdPerson() + + if (entity.visible) { + // sync + const yOffset = this.worldRenderer.playerStateReactive.eyeHeight + const pos = this.worldRenderer.cameraObject.position.clone().add(new THREE.Vector3(0, -yOffset, 0)) + entity.position.set(pos.x, pos.y, pos.z) + + const rotation = this.worldRenderer.cameraShake.getBaseRotation() + entity.rotation.set(0, rotation.yaw, 0) + + // Sync head rotation + entity.traverse((c) => { + if (c.name === 'head') { + c.rotation.set(-rotation.pitch, 0, 0) + } + }) + } } } } + private syncArmorPositions (entity: SceneEntity) { + if (!entity.playerObject) return + + // todo-low use property access for less loop iterations (small performance gain) + entity.traverse((armor) => { + if (!armor.name.startsWith('geometry_armor_')) return + + const { skin } = entity.playerObject! + + switch (armor.name) { + case 'geometry_armor_head': + // Head armor sync + if (armor.children[0]?.children[0]) { + armor.children[0].children[0].rotation.set( + -skin.head.rotation.x, + skin.head.rotation.y, + skin.head.rotation.z, + skin.head.rotation.order + ) + } + break + + case 'geometry_armor_legs': + // Legs armor sync + if (armor.children[0]) { + // Left leg + if (armor.children[0].children[2]) { + armor.children[0].children[2].rotation.set( + -skin.leftLeg.rotation.x, + skin.leftLeg.rotation.y, + skin.leftLeg.rotation.z, + skin.leftLeg.rotation.order + ) + } + // Right leg + if (armor.children[0].children[1]) { + armor.children[0].children[1].rotation.set( + -skin.rightLeg.rotation.x, + skin.rightLeg.rotation.y, + skin.rightLeg.rotation.z, + skin.rightLeg.rotation.order + ) + } + } + break + + case 'geometry_armor_feet': + // Boots armor sync + if (armor.children[0]) { + // Right boot + if (armor.children[0].children[0]) { + armor.children[0].children[0].rotation.set( + -skin.rightLeg.rotation.x, + skin.rightLeg.rotation.y, + skin.rightLeg.rotation.z, + skin.rightLeg.rotation.order + ) + } + // Left boot (reversed Z rotation) + if (armor.children[0].children[1]) { + armor.children[0].children[1].rotation.set( + -skin.leftLeg.rotation.x, + skin.leftLeg.rotation.y, + -skin.leftLeg.rotation.z, + skin.leftLeg.rotation.order + ) + } + } + break + } + }) + } + getPlayerObject (entityId: string | number) { - const playerObject = this.entities[entityId]?.playerObject as PlayerObjectType | undefined + if (this.playerEntity?.originalEntity.id === entityId) return this.playerEntity?.playerObject + const playerObject = this.entities[entityId]?.playerObject return playerObject } @@ -321,16 +488,21 @@ export class Entities { .some(channel => channel !== 0) } + // todo true/undefined doesnt reset the skin to the default one // eslint-disable-next-line max-params - updatePlayerSkin (entityId: string | number, username: string | undefined, uuid: string | undefined, skinUrl: string | true, capeUrl: string | true | undefined = undefined) { - if (uuid) { - if (typeof skinUrl === 'string' || typeof capeUrl === 'string') this.uuidPerSkinUrlsCache[uuid] = {} - if (typeof skinUrl === 'string') this.uuidPerSkinUrlsCache[uuid].skinUrl = skinUrl - if (typeof capeUrl === 'string') this.uuidPerSkinUrlsCache[uuid].capeUrl = capeUrl + async updatePlayerSkin (entityId: string | number, username: string | undefined, uuidCache: string | undefined, skinUrl: string | true, capeUrl: string | true | undefined = undefined) { + const isCustomSkin = skinUrl !== stevePngUrl + if (isCustomSkin) { + this.loadedSkinEntityIds.add(String(entityId)) + } + if (uuidCache) { + if (typeof skinUrl === 'string' || typeof capeUrl === 'string') this.uuidPerSkinUrlsCache[uuidCache] = {} + if (typeof skinUrl === 'string') this.uuidPerSkinUrlsCache[uuidCache].skinUrl = skinUrl + if (typeof capeUrl === 'string') this.uuidPerSkinUrlsCache[uuidCache].capeUrl = capeUrl if (skinUrl === true) { - skinUrl = this.uuidPerSkinUrlsCache[uuid]?.skinUrl ?? skinUrl + skinUrl = this.uuidPerSkinUrlsCache[uuidCache]?.skinUrl ?? skinUrl } - capeUrl ??= this.uuidPerSkinUrlsCache[uuid]?.capeUrl + capeUrl ??= this.uuidPerSkinUrlsCache[uuidCache]?.capeUrl } const playerObject = this.getPlayerObject(entityId) @@ -338,15 +510,21 @@ export class Entities { if (skinUrl === true) { if (!username) return - skinUrl = getLookupUrl(username, 'skin') + const newSkinUrl = await loadSkinFromUsername(username, 'skin') + if (!this.getPlayerObject(entityId)) return + if (!newSkinUrl) return + skinUrl = newSkinUrl } if (typeof skinUrl !== 'string') throw new Error('Invalid skin url') const renderEars = this.worldRenderer.worldRendererConfig.renderEars || username === 'deadmau5' - void this.loadAndApplySkin(entityId, skinUrl, renderEars).then(() => { + void this.loadAndApplySkin(entityId, skinUrl, renderEars).then(async () => { if (capeUrl) { if (capeUrl === true && username) { - capeUrl = getLookupUrl(username, 'cape') + const newCapeUrl = await loadSkinFromUsername(username, 'cape') + if (!this.getPlayerObject(entityId)) return + if (!newCapeUrl) return + capeUrl = newCapeUrl } if (typeof capeUrl === 'string') { void this.loadAndApplyCape(entityId, capeUrl) @@ -371,16 +549,16 @@ export class Entities { if (!playerObject) return try { - let playerCustomSkinImage: HTMLImageElement | undefined + let playerCustomSkinImage: ImageBitmap | undefined playerObject = this.getPlayerObject(entityId) if (!playerObject) return let skinTexture: THREE.Texture - let skinCanvas: HTMLCanvasElement + let skinCanvas: OffscreenCanvas if (skinUrl === stevePngUrl) { skinTexture = await steveTexture - const canvas = document.createElement('canvas') + const canvas = createCanvas(64, 64) const ctx = canvas.getContext('2d') if (!ctx) throw new Error('Failed to get context') ctx.drawImage(skinTexture.image, 0, 0) @@ -454,24 +632,72 @@ export class Entities { } } - playAnimation (entityPlayerId, animation: 'walking' | 'running' | 'oneSwing' | 'idle') { - const playerObject = this.getPlayerObject(entityPlayerId) + debugSwingArm () { + const playerObject = Object.values(this.entities).find(entity => entity.playerObject?.animation instanceof WalkingGeneralSwing) if (!playerObject) return + (playerObject.playerObject!.animation as WalkingGeneralSwing).swingArm() + } - if (animation === 'oneSwing') { - if (!(playerObject.animation instanceof WalkingGeneralSwing)) throw new Error('Expected WalkingGeneralSwing') - playerObject.animation.swingArm() + playAnimation (entityPlayerId, animation: 'walking' | 'running' | 'oneSwing' | 'idle' | 'crouch' | 'crouchWalking') { + // TODO CLEANUP! + // Handle special player entity ID for bot entity in third person + if (entityPlayerId === 'player_entity' && this.playerEntity?.playerObject) { + const { playerObject } = this.playerEntity + if (animation === 'oneSwing') { + if (!(playerObject.animation instanceof WalkingGeneralSwing)) throw new Error('Expected WalkingGeneralSwing') + playerObject.animation.swingArm() + return + } + + if (playerObject.animation instanceof WalkingGeneralSwing) { + playerObject.animation.switchAnimationCallback = () => { + if (!(playerObject.animation instanceof WalkingGeneralSwing)) throw new Error('Expected WalkingGeneralSwing') + playerObject.animation.isMoving = animation === 'walking' || animation === 'running' || animation === 'crouchWalking' + playerObject.animation.isRunning = animation === 'running' + playerObject.animation.isCrouched = animation === 'crouch' || animation === 'crouchWalking' + } + } return } - if (playerObject.animation instanceof WalkingGeneralSwing) { - playerObject.animation.switchAnimationCallback = () => { + // Handle regular entities + const playerObject = this.getPlayerObject(entityPlayerId) + if (playerObject) { + if (animation === 'oneSwing') { if (!(playerObject.animation instanceof WalkingGeneralSwing)) throw new Error('Expected WalkingGeneralSwing') - playerObject.animation.isMoving = animation !== 'idle' - playerObject.animation.isRunning = animation === 'running' + playerObject.animation.swingArm() + return } + + if (playerObject.animation instanceof WalkingGeneralSwing) { + playerObject.animation.switchAnimationCallback = () => { + if (!(playerObject.animation instanceof WalkingGeneralSwing)) throw new Error('Expected WalkingGeneralSwing') + playerObject.animation.isMoving = animation === 'walking' || animation === 'running' || animation === 'crouchWalking' + playerObject.animation.isRunning = animation === 'running' + playerObject.animation.isCrouched = animation === 'crouch' || animation === 'crouchWalking' + } + } + return } + // Handle player entity (for third person view) - fallback for backwards compatibility + if (this.playerEntity?.playerObject) { + const { playerObject: playerEntityObject } = this.playerEntity + if (animation === 'oneSwing') { + if (!(playerEntityObject.animation instanceof WalkingGeneralSwing)) throw new Error('Expected WalkingGeneralSwing') + playerEntityObject.animation.swingArm() + return + } + + if (playerEntityObject.animation instanceof WalkingGeneralSwing) { + playerEntityObject.animation.switchAnimationCallback = () => { + if (!(playerEntityObject.animation instanceof WalkingGeneralSwing)) throw new Error('Expected WalkingGeneralSwing') + playerEntityObject.animation.isMoving = animation === 'walking' || animation === 'running' || animation === 'crouchWalking' + playerEntityObject.animation.isRunning = animation === 'running' + playerEntityObject.animation.isCrouched = animation === 'crouch' || animation === 'crouchWalking' + } + } + } } parseEntityLabel (jsonLike) { @@ -492,12 +718,13 @@ export class Entities { return typeof component === 'string' ? component : component.text ?? '' } - getItemMesh (item, specificProps: ItemSpecificContextProperties, previousModel?: string) { + getItemMesh (item, specificProps: ItemSpecificContextProperties, faceCamera = false, previousModel?: string) { + if (!item.nbt && item.nbtData) item.nbt = item.nbtData const textureUv = this.worldRenderer.getItemRenderData(item, specificProps) if (previousModel && previousModel === textureUv?.modelName) return undefined if (textureUv && 'resolvedModel' in textureUv) { - const mesh = getBlockMeshFromModel(this.worldRenderer.material, textureUv.resolvedModel, textureUv.modelName, this.worldRenderer.resourcesManager.currentResources!.worldBlockProvider) + const mesh = getBlockMeshFromModel(this.worldRenderer.material, textureUv.resolvedModel, textureUv.modelName, this.worldRenderer.resourcesManager.currentResources.worldBlockProvider!) let SCALE = 1 if (specificProps['minecraft:display_context'] === 'ground') { SCALE = 0.5 @@ -510,60 +737,41 @@ export class Entities { return { mesh: outerGroup, isBlock: true, - itemsTexture: null, - itemsTextureFlipped: null, modelName: textureUv.modelName, } } - // TODO: Render proper model (especially for blocks) instead of flat texture + // Render proper 3D model for items if (textureUv) { const textureThree = textureUv.renderInfo?.texture === 'blocks' ? this.worldRenderer.material.map! : this.worldRenderer.itemsTexture - // todo use geometry buffer uv instead! const { u, v, su, sv } = textureUv - const size = undefined - const itemsTexture = textureThree.clone() - itemsTexture.flipY = true - const sizeY = (sv ?? size)! - const sizeX = (su ?? size)! - itemsTexture.offset.set(u, 1 - v - sizeY) - itemsTexture.repeat.set(sizeX, sizeY) - itemsTexture.needsUpdate = true - itemsTexture.magFilter = THREE.NearestFilter - itemsTexture.minFilter = THREE.NearestFilter - const itemsTextureFlipped = itemsTexture.clone() - itemsTextureFlipped.repeat.x *= -1 - itemsTextureFlipped.needsUpdate = true - itemsTextureFlipped.offset.set(u + (sizeX), 1 - v - sizeY) - const material = new THREE.MeshStandardMaterial({ - map: itemsTexture, - transparent: true, - alphaTest: 0.1, + const sizeX = su ?? 1 // su is actually width + const sizeY = sv ?? 1 // sv is actually height + + // Use the new unified item mesh function + const result = createItemMesh(textureThree, { + u, + v, + sizeX, + sizeY + }, { + faceCamera, + use3D: !faceCamera, // Only use 3D for non-camera-facing items }) - const materialFlipped = new THREE.MeshStandardMaterial({ - map: itemsTextureFlipped, - transparent: true, - alphaTest: 0.1, - }) - const mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 0), [ - // top left and right bottom are black box materials others are transparent - new THREE.MeshBasicMaterial({ color: 0x00_00_00 }), new THREE.MeshBasicMaterial({ color: 0x00_00_00 }), - new THREE.MeshBasicMaterial({ color: 0x00_00_00 }), new THREE.MeshBasicMaterial({ color: 0x00_00_00 }), - material, materialFlipped, - ]) + let SCALE = 1 if (specificProps['minecraft:display_context'] === 'ground') { SCALE = 0.5 } else if (specificProps['minecraft:display_context'] === 'thirdperson') { SCALE = 6 } - mesh.scale.set(SCALE, SCALE, SCALE) + result.mesh.scale.set(SCALE, SCALE, SCALE) + return { - mesh, + mesh: result.mesh, isBlock: false, - itemsTexture, - itemsTextureFlipped, modelName: textureUv.modelName, + cleanup: result.cleanup } } } @@ -578,9 +786,7 @@ export class Entities { } } - update (entity: import('prismarine-entity').Entity & { delete?; pos, name }, overrides) { - const justAdded = !this.entities[entity.id] - + update (entity: SceneEntity['originalEntity'], overrides) { const isPlayerModel = entity.name === 'player' if (entity.name === 'zombie_villager' || entity.name === 'husk') { overrides.texture = `textures/1.16.4/entity/${entity.name === 'zombie_villager' ? 'zombie_villager/zombie_villager.png' : `zombie/${entity.name}.png`}` @@ -591,6 +797,7 @@ export class Entities { } // this can be undefined in case where packet entity_destroy was sent twice (so it was already deleted) let e = this.entities[entity.id] + const justAdded = !e if (entity.delete) { if (!e) return @@ -606,78 +813,91 @@ export class Entities { return } - let mesh + let mesh: THREE.Object3D | undefined if (e === undefined) { - const group = new THREE.Group() - if (entity.name === 'item') { - const item = entity.metadata?.find((m: any) => typeof m === 'object' && m?.itemCount) + const group = new THREE.Group() as unknown as SceneEntity + group.originalEntity = entity + if (entity.name === 'item' || entity.name === 'tnt' || entity.name === 'falling_block' || entity.name === 'snowball' + || entity.name === 'egg' || entity.name === 'ender_pearl' || entity.name === 'experience_bottle' + || entity.name === 'splash_potion' || entity.name === 'lingering_potion') { + const item = entity.name === 'tnt' || entity.type === 'projectile' + ? { name: entity.name } + : entity.name === 'falling_block' + ? { blockState: entity['objectData'] } + : entity.metadata?.find((m: any) => typeof m === 'object' && m?.itemCount) if (item) { const object = this.getItemMesh(item, { 'minecraft:display_context': 'ground', - }) + }, entity.type === 'projectile') if (object) { mesh = object.mesh - mesh.scale.set(0.5, 0.5, 0.5) - mesh.position.set(0, 0.2, 0) + if (entity.name === 'item' || entity.type === 'projectile') { + mesh.scale.set(0.5, 0.5, 0.5) + mesh.position.set(0, entity.name === 'item' ? 0.2 : 0.1, 0) + } else { + mesh.scale.set(2, 2, 2) + mesh.position.set(0, 0.5, 0) + } // set faces // mesh.position.set(targetPos.x + 0.5 + 2, targetPos.y + 0.5, targetPos.z + 0.5) // viewer.scene.add(mesh) - const clock = new THREE.Clock() - mesh.onBeforeRender = () => { - const delta = clock.getDelta() - mesh.rotation.y += delta + if (entity.name === 'item') { + const clock = new THREE.Clock() + mesh.onBeforeRender = () => { + const delta = clock.getDelta() + mesh!.rotation.y += delta + } } - //@ts-expect-error + + // TNT blinking + // if (entity.name === 'tnt') { + // let lastBlink = 0 + // const blinkInterval = 500 // ms between blinks + // mesh.onBeforeRender = () => { + // const now = Date.now() + // if (now - lastBlink > blinkInterval) { + // lastBlink = now + // mesh.traverse((child) => { + // if (child instanceof THREE.Mesh) { + // const material = child.material as THREE.MeshLambertMaterial + // material.color.set(material.color?.equals(new THREE.Color(0xff_ff_ff)) + // ? new THREE.Color(0xff_00_00) + // : new THREE.Color(0xff_ff_ff)) + // } + // }) + // } + // } + // } + group.additionalCleanup = () => { // important: avoid texture memory leak and gpu slowdown - object.itemsTexture?.dispose() - object.itemsTextureFlipped?.dispose() + if (object.cleanup) { + object.cleanup() + } } } } } else if (isPlayerModel) { - // CREATE NEW PLAYER ENTITY const wrapper = new THREE.Group() - const playerObject = new PlayerObject() as PlayerObjectType - playerObject.position.set(0, 16, 0) - - // fix issues with starfield - playerObject.traverse((obj) => { - if (obj instanceof THREE.Mesh && obj.material instanceof THREE.MeshStandardMaterial) { - obj.material.transparent = true - } - }) - //@ts-expect-error - wrapper.add(playerObject) - const scale = 1 / 16 - wrapper.scale.set(scale, scale, scale) + const playerObject = this.setupPlayerObject(entity, wrapper, overrides) + group.playerObject = playerObject + mesh = wrapper if (entity.username) { - // todo proper colors - const nameTag = new NameTagObject(fromFormattedString(entity.username).text, { - font: `48px ${this.entitiesOptions.fontFamily}`, - }) - nameTag.position.y = playerObject.position.y + playerObject.scale.y * 16 + 3 - nameTag.renderOrder = 1000 - - //@ts-expect-error - wrapper.add(nameTag) + const nametag = addNametag(entity, { fontFamily: 'mojangles' }, wrapper, this.worldRenderer.version) + if (nametag) { + nametag.position.y = playerObject.position.y + playerObject.scale.y * 16 + 3 + nametag.scale.multiplyScalar(12) + } } - - //@ts-expect-error - group.playerObject = playerObject - wrapper.rotation.set(0, Math.PI, 0) - mesh = wrapper - playerObject.animation = new WalkingGeneralSwing() - //@ts-expect-error - playerObject.animation.isMoving = false } else { - mesh = getEntityMesh(entity, this.worldRenderer, this.entitiesOptions, overrides) + mesh = getEntityMesh(entity, this.worldRenderer, this.entitiesOptions, { ...overrides, customModel: entity['customModel'] }) } if (!mesh) return mesh.name = 'mesh' // set initial position so there are no weird jumps update after - group.position.set(entity.pos.x, entity.pos.y, entity.pos.z) + const pos = entity.pos ?? entity.position + group.position.set(pos.x, pos.y, pos.z) // todo use width and height instead const boxHelper = new THREE.BoxHelper( @@ -701,7 +921,7 @@ export class Entities { this.onAddEntity(entity) if (isPlayerModel) { - this.updatePlayerSkin(entity.id, entity.username, entity.uuid, overrides?.texture || stevePngUrl) + void this.updatePlayerSkin(entity.id, entity.username, overrides?.texture ? entity.uuid : undefined, overrides?.texture || stevePngUrl) } this.setDebugMode(this.debugMode, group) this.setRendering(this.currentlyRendering, group) @@ -709,22 +929,13 @@ export class Entities { mesh = e.children.find(c => c.name === 'mesh') } - // check if entity has armor - if (entity.equipment) { - this.addItemModel(e, 'left', entity.equipment[0]) - this.addItemModel(e, 'right', entity.equipment[1]) - addArmorModel(this.worldRenderer, e, 'feet', entity.equipment[2]) - addArmorModel(this.worldRenderer, e, 'legs', entity.equipment[3], 2) - addArmorModel(this.worldRenderer, e, 'chest', entity.equipment[4]) - addArmorModel(this.worldRenderer, e, 'head', entity.equipment[5]) - } + // Update equipment + this.updateEntityEquipment(e, entity) const meta = getGeneralEntitiesMetadata(entity) - //@ts-expect-error - // set visibility - const isInvisible = entity.metadata?.[0] & 0x20 - for (const child of mesh.children ?? []) { + const isInvisible = ((entity.metadata?.[0] ?? 0) as unknown as number) & 0x20 || (this.worldRenderer.playerStateReactive.cameraSpectatingEntity === entity.id && this.worldRenderer.playerStateUtils.isSpectator()) + for (const child of mesh!.children ?? []) { if (child.name !== 'nametag') { child.visible = !isInvisible } @@ -739,21 +950,22 @@ export class Entities { // entity specific meta const textDisplayMeta = getSpecificEntityMetadata('text_display', entity) const displayTextRaw = textDisplayMeta?.text || meta.custom_name_visible && meta.custom_name - const displayText = this.parseEntityLabel(displayTextRaw) - if (entity.name !== 'player' && displayText) { + if (entity.name !== 'player' && displayTextRaw) { const nameTagFixed = textDisplayMeta && (textDisplayMeta.billboard_render_constraints === 'fixed' || !textDisplayMeta.billboard_render_constraints) - const nameTagBackgroundColor = textDisplayMeta && toRgba(textDisplayMeta.background_color) + const nameTagBackgroundColor = (textDisplayMeta && (parseInt(textDisplayMeta.style_flags, 10) & 0x04) === 0) ? toRgba(textDisplayMeta.background_color) : undefined let nameTagTextOpacity: any if (textDisplayMeta?.text_opacity) { const rawOpacity = parseInt(textDisplayMeta?.text_opacity, 10) nameTagTextOpacity = rawOpacity > 0 ? rawOpacity : 256 - rawOpacity } addNametag( - { ...entity, username: displayText, nameTagBackgroundColor, nameTagTextOpacity, nameTagFixed, + { ...entity, username: typeof displayTextRaw === 'string' ? mojangson.simplify(mojangson.parse(displayTextRaw)) : nbt.simplify(displayTextRaw), + nameTagBackgroundColor, nameTagTextOpacity, nameTagFixed, nameTagScale: textDisplayMeta?.scale, nameTagTranslation: textDisplayMeta && (textDisplayMeta.translation || new THREE.Vector3(0, 0, 0)), nameTagRotationLeft: toQuaternion(textDisplayMeta?.left_rotation), nameTagRotationRight: toQuaternion(textDisplayMeta?.right_rotation) }, this.entitiesOptions, - mesh + mesh, + this.worldRenderer.version ) } @@ -763,8 +975,8 @@ export class Entities { const hasArms = (parseInt(armorStandMeta.client_flags, 10) & 0x04) !== 0 const hasBasePlate = (parseInt(armorStandMeta.client_flags, 10) & 0x08) === 0 const isMarker = (parseInt(armorStandMeta.client_flags, 10) & 0x10) !== 0 - mesh.castShadow = !isMarker - mesh.receiveShadow = !isMarker + mesh!.castShadow = !isMarker + mesh!.receiveShadow = !isMarker if (isSmall) { e.scale.set(0.5, 0.5, 0.5) } else { @@ -833,7 +1045,9 @@ export class Entities { // TODO: fix type // todo! fix errors in mc-data (no entities data prior 1.18.2) const item = (itemFrameMeta?.item ?? entity.metadata?.[8]) as any as { itemId, blockId, components, nbtData: { value: { map: { value: number } } } } - mesh.scale.set(1, 1, 1) + mesh!.scale.set(1, 1, 1) + mesh!.position.set(0, 0, -0.5) + e.rotation.x = -entity.pitch e.children.find(c => { if (c.name.startsWith('map_')) { @@ -850,25 +1064,33 @@ export class Entities { } return false })?.removeFromParent() + if (item && (item.itemId ?? item.blockId ?? 0) !== 0) { + // Get rotation from metadata, default to 0 if not present + // Rotation is stored in 45° increments (0-7) for items, 90° increments (0-3) for maps const rotation = (itemFrameMeta.rotation as any as number) ?? 0 const mapNumber = item.nbtData?.value?.map?.value ?? item.components?.find(x => x.type === 'map_id')?.data if (mapNumber) { // TODO: Use proper larger item frame model when a map exists - mesh.scale.set(16 / 12, 16 / 12, 1) + mesh!.scale.set(16 / 12, 16 / 12, 1) + // Handle map rotation (4 possibilities, 90° increments) this.addMapModel(e, mapNumber, rotation) } else { + // Handle regular item rotation (8 possibilities, 45° increments) const itemMesh = this.getItemMesh(item, { 'minecraft:display_context': 'fixed', }) if (itemMesh) { - itemMesh.mesh.position.set(0, 0, 0.43) + itemMesh.mesh.position.set(0, 0, -0.05) + // itemMesh.mesh.position.set(0, 0, 0.43) if (itemMesh.isBlock) { itemMesh.mesh.scale.set(0.25, 0.25, 0.25) } else { itemMesh.mesh.scale.set(0.5, 0.5, 0.5) } + // Rotate 180° around Y axis first itemMesh.mesh.rotateY(Math.PI) + // Then apply the 45° increment rotation itemMesh.mesh.rotateZ(-rotation * Math.PI / 4) itemMesh.mesh.name = 'item' e.add(itemMesh.mesh) @@ -877,17 +1099,11 @@ export class Entities { } } - if (entity.username) { + if (entity.username !== undefined) { e.username = entity.username } - if (entity.type === 'player' && entity.equipment && e.playerObject) { - const { playerObject } = e - playerObject.backEquipment = entity.equipment.some((item) => item?.name === 'elytra') ? 'elytra' : 'cape' - if (playerObject.cape.map === null) { - playerObject.cape.visible = false - } - } + this.updateNameTagVisibility(e) this.updateEntityPosition(entity, justAdded, overrides) } @@ -906,38 +1122,39 @@ export class Entities { } if (e?.playerObject && overrides?.rotation?.head) { - const playerObject = e.playerObject as PlayerObjectType + const { playerObject } = e const headRotationDiff = overrides.rotation.head.y ? overrides.rotation.head.y - entity.yaw : 0 playerObject.skin.head.rotation.y = -headRotationDiff playerObject.skin.head.rotation.x = overrides.rotation.head.x ? - overrides.rotation.head.x : 0 } - - this.maybeRenderPlayerSkin(entity) } onAddEntity (entity: import('prismarine-entity').Entity) { } - loadedSkinEntityIds = new Set() - maybeRenderPlayerSkin (entity: import('prismarine-entity').Entity) { - const mesh = this.entities[entity.id] + loadedSkinEntityIds = new Set() + maybeRenderPlayerSkin (entityId: string) { + let mesh = this.entities[entityId] + if (entityId === 'player_entity') { + mesh = this.playerEntity! + entityId = this.playerEntity?.originalEntity.id as any + } if (!mesh) return - if (!mesh.playerObject || !this.worldRenderer.worldRendererConfig.fetchPlayerSkins) return + if (!mesh.playerObject) return + if (!mesh.visible) return + const MAX_DISTANCE_SKIN_LOAD = 128 - const cameraPos = this.worldRenderer.camera.position - const distance = entity.position.distanceTo(new Vec3(cameraPos.x, cameraPos.y, cameraPos.z)) + const cameraPos = this.worldRenderer.cameraObject.position + const distance = mesh.position.distanceTo(cameraPos) if (distance < MAX_DISTANCE_SKIN_LOAD && distance < (this.worldRenderer.viewDistance * 16)) { - if (this.entities[entity.id]) { - if (this.loadedSkinEntityIds.has(entity.id)) return - this.loadedSkinEntityIds.add(entity.id) - this.updatePlayerSkin(entity.id, entity.username, entity.uuid, true, true) - } + if (this.loadedSkinEntityIds.has(String(entityId))) return + void this.updatePlayerSkin(entityId, mesh.playerObject.realUsername, mesh.playerObject.realPlayerUuid, true, true) } } playerPerAnimation = {} as Record onRemoveEntity (entity: import('prismarine-entity').Entity) { - this.loadedSkinEntityIds.delete(entity.id) + this.loadedSkinEntityIds.delete(entity.id.toString()) } updateMap (mapNumber: string | number, data: string) { @@ -955,6 +1172,20 @@ export class Entities { } } + updateNameTagVisibility (entity: SceneEntity) { + const playerTeam = this.worldRenderer.playerStateReactive.team + const entityTeam = entity.originalEntity.team + const nameTagVisibility = entityTeam?.nameTagVisibility || 'always' + const showNameTag = nameTagVisibility === 'always' || + (nameTagVisibility === 'hideForOwnTeam' && entityTeam?.team !== playerTeam?.team) || + (nameTagVisibility === 'hideForOtherTeams' && (entityTeam?.team === playerTeam?.team || playerTeam === undefined)) + entity.traverse(c => { + if (c.name === 'nametag') { + c.visible = showNameTag + } + }) + } + addMapModel (entityMesh: THREE.Object3D, mapNumber: number, rotation: number) { const imageData = this.cachedMapsImages?.[mapNumber] let texture: THREE.Texture | null = null @@ -985,6 +1216,7 @@ export class Entities { } else { mapMesh.position.set(0, 0, 0.437) } + // Apply 90° increment rotation for maps (0-3) mapMesh.rotateZ(Math.PI * 2 - rotation * Math.PI / 2) mapMesh.name = `map_${mapNumber}` @@ -1008,11 +1240,13 @@ export class Entities { return texture } - addItemModel (entityMesh: SceneEntity, hand: 'left' | 'right', item: Item) { - const parentName = `bone_${hand}item` + addItemModel (entityMesh: SceneEntity, hand: 'left' | 'right', item: Item, isPlayer = false) { + const bedrockParentName = `bone_${hand}item` + const itemName = `custom_item_${hand}` + // remove existing item entityMesh.traverse(c => { - if (c.parent?.name.toLowerCase() === parentName) { + if (c.name === itemName) { c.removeFromParent() if (c['additionalCleanup']) c['additionalCleanup']() } @@ -1024,12 +1258,13 @@ export class Entities { }) if (itemObject?.mesh) { entityMesh.traverse(c => { - if (c.name.toLowerCase() === parentName) { + if (c.name.toLowerCase() === bedrockParentName || c.name === `${hand}Arm`) { const group = new THREE.Object3D() group['additionalCleanup'] = () => { // important: avoid texture memory leak and gpu slowdown - itemObject.itemsTexture?.dispose() - itemObject.itemsTextureFlipped?.dispose() + if (itemObject.cleanup) { + itemObject.cleanup() + } } const itemMesh = itemObject.mesh group.rotation.z = -Math.PI / 16 @@ -1040,7 +1275,18 @@ export class Entities { group.rotation.y = Math.PI / 2 group.scale.multiplyScalar(2) } + + // if player, move item below and forward a bit + if (isPlayer) { + group.position.y = -8 + group.position.z = 5 + group.position.x = hand === 'left' ? 1 : -1 + group.rotation.x = Math.PI + } + group.add(itemMesh) + + group.name = itemName c.add(group) } }) @@ -1051,7 +1297,7 @@ export class Entities { const entityMesh = this.entities[entityId]?.children.find(c => c.name === 'mesh') if (entityMesh) { entityMesh.traverse((child) => { - if (child instanceof THREE.Mesh) { + if (child instanceof THREE.Mesh && child.material.clone) { const clonedMaterial = child.material.clone() clonedMaterial.dispose() child.material = child.material.clone() @@ -1064,6 +1310,64 @@ export class Entities { }) } } + + raycastSceneDebug () { + // return any object from scene. raycast from camera + const raycaster = new THREE.Raycaster() + raycaster.setFromCamera(new THREE.Vector2(0, 0), this.worldRenderer.camera) + const intersects = raycaster.intersectObjects(this.worldRenderer.scene.children) + return intersects[0]?.object + } + + private setupPlayerObject (entity: SceneEntity['originalEntity'], wrapper: THREE.Group, overrides: { texture?: string }): PlayerObjectType { + const playerObject = new PlayerObject() as PlayerObjectType + playerObject.realPlayerUuid = entity.uuid ?? '' + playerObject.realUsername = entity.username ?? '' + playerObject.position.set(0, 16, 0) + + // fix issues with starfield + playerObject.traverse((obj) => { + if (obj instanceof THREE.Mesh && obj.material instanceof THREE.MeshStandardMaterial) { + obj.material.transparent = true + } + }) + + wrapper.add(playerObject as any) + const scale = 1 / 16 + wrapper.scale.set(scale, scale, scale) + wrapper.rotation.set(0, Math.PI, 0) + + // Set up animation + playerObject.animation = new WalkingGeneralSwing() + //@ts-expect-error + playerObject.animation.isMoving = false + + return playerObject + } + + private updateEntityEquipment (entityMesh: SceneEntity, entity: SceneEntity['originalEntity']) { + if (!entityMesh || !entity.equipment) return + + const isPlayer = entity.type === 'player' + this.addItemModel(entityMesh, isPlayer ? 'right' : 'left', entity.equipment[0], isPlayer) + this.addItemModel(entityMesh, isPlayer ? 'left' : 'right', entity.equipment[1], isPlayer) + addArmorModel(this.worldRenderer, entityMesh, 'feet', entity.equipment[2]) + addArmorModel(this.worldRenderer, entityMesh, 'legs', entity.equipment[3], 2) + addArmorModel(this.worldRenderer, entityMesh, 'chest', entity.equipment[4]) + addArmorModel(this.worldRenderer, entityMesh, 'head', entity.equipment[5]) + + // Update player-specific equipment + if (isPlayer && entityMesh.playerObject) { + const { playerObject } = entityMesh + playerObject.backEquipment = entity.equipment.some((item) => item?.name === 'elytra') ? 'elytra' : 'cape' + if (playerObject.backEquipment === 'elytra') { + void this.loadAndApplyCape(entity.id, elytraTexture) + } + if (playerObject.cape.map === null) { + playerObject.cape.visible = false + } + } + } } function getGeneralEntitiesMetadata (entity: { name; metadata }): Partial> { @@ -1104,6 +1408,11 @@ function addArmorModel (worldRenderer: WorldRendererThree, entityMesh: THREE.Obj if (textureData) { const decodedData = JSON.parse(Buffer.from(textureData, 'base64').toString()) texturePath = decodedData.textures?.SKIN?.url + const { skinTexturesProxy } = this.worldRenderer.worldRendererConfig + if (skinTexturesProxy) { + texturePath = texturePath?.replace('http://textures.minecraft.net/', skinTexturesProxy) + .replace('https://textures.minecraft.net/', skinTexturesProxy) + } } } catch (err) { console.error('Error decoding player head texture:', err) @@ -1116,7 +1425,7 @@ function addArmorModel (worldRenderer: WorldRendererThree, entityMesh: THREE.Obj if (!texturePath) { // TODO: Support mirroring on certain parts of the model const armorTextureName = `${armorMaterial}_layer_${layer}${overlay ? '_overlay' : ''}` - texturePath = worldRenderer.resourcesManager.currentResources!.customTextures.armor?.textures[armorTextureName]?.src ?? armorTextures[armorTextureName] + texturePath = worldRenderer.resourcesManager.currentResources.customTextures.armor?.textures[armorTextureName]?.src ?? armorTextures[armorTextureName] } if (!texturePath || !armorModel[slotType]) { removeArmorModel(entityMesh, slotType) @@ -1128,7 +1437,7 @@ function addArmorModel (worldRenderer: WorldRendererThree, entityMesh: THREE.Obj let material if (mesh) { material = mesh.material - loadTexture(texturePath, texture => { + void loadTexture(texturePath, texture => { texture.magFilter = THREE.NearestFilter texture.minFilter = THREE.NearestFilter texture.flipY = false @@ -1138,6 +1447,16 @@ function addArmorModel (worldRenderer: WorldRendererThree, entityMesh: THREE.Obj }) } else { mesh = getMesh(worldRenderer, texturePath, armorModel[slotType]) + // // enable debug mode to see the mesh + // mesh.traverse(c => { + // if (c instanceof THREE.Mesh) { + // c.material.wireframe = true + // } + // }) + if (slotType === 'head') { + // avoid z-fighting with the head + mesh.children[0].position.y += 0.01 + } mesh.name = meshName material = mesh.material if (!isPlayerHead) { @@ -1162,12 +1481,6 @@ function addArmorModel (worldRenderer: WorldRendererThree, entityMesh: THREE.Obj group.name = `armor_${slotType}${overlay ? '_overlay' : ''}` group.add(mesh) - const skeletonHelper = new THREE.SkeletonHelper(mesh) - //@ts-expect-error - skeletonHelper.material.linewidth = 2 - skeletonHelper.visible = false - group.add(skeletonHelper) - entityMesh.add(mesh) } diff --git a/renderer/viewer/three/entity/EntityMesh.ts b/renderer/viewer/three/entity/EntityMesh.ts index 67222ed8..229da6d5 100644 --- a/renderer/viewer/three/entity/EntityMesh.ts +++ b/renderer/viewer/three/entity/EntityMesh.ts @@ -2,10 +2,11 @@ import * as THREE from 'three' import { OBJLoader } from 'three-stdlib' import huskPng from 'mc-assets/dist/other-textures/latest/entity/zombie/husk.png' import { Vec3 } from 'vec3' +import ocelotPng from '../../../../node_modules/mc-assets/dist/other-textures/latest/entity/cat/ocelot.png' import arrowTexture from '../../../../node_modules/mc-assets/dist/other-textures/1.21.2/entity/projectiles/arrow.png' import spectralArrowTexture from '../../../../node_modules/mc-assets/dist/other-textures/1.21.2/entity/projectiles/spectral_arrow.png' import tippedArrowTexture from '../../../../node_modules/mc-assets/dist/other-textures/1.21.2/entity/projectiles/tipped_arrow.png' -import { loadTexture } from '../../lib/utils' +import { loadTexture } from '../threeJsUtils' import { WorldRendererThree } from '../worldrendererThree' import entities from './entities.json' import { externalModels } from './objModels' @@ -237,10 +238,11 @@ export function getMesh ( if (useBlockTexture) { if (!worldRenderer) throw new Error('worldRenderer is required for block textures') const blockName = texture.slice(6) - const textureInfo = worldRenderer.resourcesManager.currentResources!.blocksAtlasParser.getTextureInfo(blockName) + const textureInfo = worldRenderer.resourcesManager.currentResources.blocksAtlasJson.textures[blockName] if (textureInfo) { - textureWidth = blocksTexture!.image.width - textureHeight = blocksTexture!.image.height + textureWidth = blocksTexture?.image.width ?? textureWidth + textureHeight = blocksTexture?.image.height ?? textureHeight + // todo support su/sv textureOffset = [textureInfo.u, textureInfo.v] } else { console.error(`Unknown block ${blockName}`) @@ -456,7 +458,7 @@ export class EntityMesh { 'skeleton_horse': `textures/${version}/entity/horse/horse_skeleton.png`, 'donkey': `textures/${version}/entity/horse/donkey.png`, 'mule': `textures/${version}/entity/horse/mule.png`, - 'ocelot': `textures/${version}/entity/cat/ocelot.png`, + 'ocelot': ocelotPng, 'arrow': arrowTexture, 'spectral_arrow': spectralArrowTexture, 'tipped_arrow': tippedArrowTexture @@ -527,12 +529,6 @@ export class EntityMesh { debugFlags) mesh.name = `geometry_${name}` this.mesh.add(mesh) - - const skeletonHelper = new THREE.SkeletonHelper(mesh) - //@ts-expect-error - skeletonHelper.material.linewidth = 2 - skeletonHelper.visible = false - this.mesh.add(skeletonHelper) } debugFlags.type = 'bedrock' } @@ -551,3 +547,4 @@ export class EntityMesh { } } } +globalThis.EntityMesh = EntityMesh diff --git a/renderer/viewer/three/entity/animations.js b/renderer/viewer/three/entity/animations.js index a6cabdbb..3295556f 100644 --- a/renderer/viewer/three/entity/animations.js +++ b/renderer/viewer/three/entity/animations.js @@ -1,3 +1,4 @@ +//@ts-check import { PlayerAnimation } from 'skinview3d' export class WalkingGeneralSwing extends PlayerAnimation { @@ -6,6 +7,7 @@ export class WalkingGeneralSwing extends PlayerAnimation { isRunning = false isMoving = true + isCrouched = false _startArmSwing @@ -15,7 +17,7 @@ export class WalkingGeneralSwing extends PlayerAnimation { animate(player) { // Multiply by animation's natural speed - let t + let t = 0 const updateT = () => { if (!this.isMoving) { t = 0 @@ -30,6 +32,8 @@ export class WalkingGeneralSwing extends PlayerAnimation { updateT() let reset = false + croughAnimation(player, this.isCrouched) + if ((this.isRunning ? Math.cos(t) : Math.sin(t)) < 0.01) { if (this.switchAnimationCallback) { reset = true @@ -50,11 +54,12 @@ export class WalkingGeneralSwing extends PlayerAnimation { if (this._startArmSwing) { const tHand = (this.progress - this._startArmSwing) * 18 + Math.PI * 0.5 - player.skin.rightArm.rotation.x = Math.cos(tHand) * 1.5 - const basicArmRotationZ = Math.PI * 0.1 - player.skin.rightArm.rotation.z = Math.cos(t + Math.PI) * 0.3 - basicArmRotationZ + // player.skin.rightArm.rotation.x = Math.cos(tHand) * 1.5 + // const basicArmRotationZ = Math.PI * 0.1 + // player.skin.rightArm.rotation.z = Math.cos(t + Math.PI) * 0.3 - basicArmRotationZ + HitAnimation.animate((this.progress - this._startArmSwing), player, this.isMoving) - if (tHand > Math.PI + Math.PI * 0.5) { + if (tHand > Math.PI + Math.PI) { this._startArmSwing = null player.skin.rightArm.rotation.z = 0 } @@ -101,3 +106,66 @@ export class WalkingGeneralSwing extends PlayerAnimation { } } } + +const HitAnimation = { + animate(progress, player, isMovingOrRunning) { + const t = progress * 18 + player.skin.rightArm.rotation.x = -0.453_786_055_2 * 2 + 2 * Math.sin(t + Math.PI) * 0.3 + + if (!isMovingOrRunning) { + const basicArmRotationZ = 0.01 * Math.PI + 0.06 + player.skin.rightArm.rotation.z = -Math.cos(t) * 0.403 + basicArmRotationZ + player.skin.body.rotation.y = -Math.cos(t) * 0.06 + player.skin.leftArm.rotation.x = Math.sin(t + Math.PI) * 0.077 + player.skin.leftArm.rotation.z = -Math.cos(t) * 0.015 + 0.13 - 0.05 + player.skin.leftArm.position.z = Math.cos(t) * 0.3 + player.skin.leftArm.position.x = 5 - Math.cos(t) * 0.05 + } + }, +} + +const croughAnimation = (player, isCrouched) => { + const erp = 0 + + // let pr = this.progress * 8; + let pr = isCrouched ? 1 : 0 + const showProgress = false + if (showProgress) { + pr = Math.floor(pr) + } + player.skin.body.rotation.x = 0.453_786_055_2 * Math.abs(Math.sin((pr * Math.PI) / 2)) + player.skin.body.position.z = + 1.325_618_1 * Math.abs(Math.sin((pr * Math.PI) / 2)) - 3.450_031_037_7 * Math.abs(Math.sin((pr * Math.PI) / 2)) + player.skin.body.position.y = -6 - 2.103_677_462 * Math.abs(Math.sin((pr * Math.PI) / 2)) + player.cape.position.y = 8 - 1.851_236_166_577_372 * Math.abs(Math.sin((pr * Math.PI) / 2)) + player.cape.rotation.x = (10.8 * Math.PI) / 180 + 0.294_220_265_771 * Math.abs(Math.sin((pr * Math.PI) / 2)) + player.cape.position.z = + -2 + 3.786_619_432 * Math.abs(Math.sin((pr * Math.PI) / 2)) - 3.450_031_037_7 * Math.abs(Math.sin((pr * Math.PI) / 2)) + player.elytra.position.x = player.cape.position.x + player.elytra.position.y = player.cape.position.y + player.elytra.position.z = player.cape.position.z + player.elytra.rotation.x = player.cape.rotation.x - (10.8 * Math.PI) / 180 + // const pr1 = this.progress / this.speed; + const pr1 = 1 + if (Math.abs(Math.sin((pr * Math.PI) / 2)) === 1) { + player.elytra.leftWing.rotation.z = + 0.261_799_44 + 0.458_200_6 * Math.abs(Math.sin((Math.min(pr1 - erp, 1) * Math.PI) / 2)) + player.elytra.updateRightWing() + } else if (isCrouched !== undefined) { + player.elytra.leftWing.rotation.z = + 0.72 - 0.458_200_6 * Math.abs(Math.sin((Math.min(pr1 - erp, 1) * Math.PI) / 2)) + player.elytra.updateRightWing() + } + player.skin.head.position.y = -3.618_325_234_674 * Math.abs(Math.sin((pr * Math.PI) / 2)) + player.skin.leftArm.position.z = + 3.618_325_234_674 * Math.abs(Math.sin((pr * Math.PI) / 2)) - 3.450_031_037_7 * Math.abs(Math.sin((pr * Math.PI) / 2)) + player.skin.rightArm.position.z = player.skin.leftArm.position.z + player.skin.leftArm.rotation.x = 0.410_367_746_202 * Math.abs(Math.sin((pr * Math.PI) / 2)) + player.skin.rightArm.rotation.x = player.skin.leftArm.rotation.x + player.skin.leftArm.rotation.z = 0.1 + player.skin.rightArm.rotation.z = -player.skin.leftArm.rotation.z + player.skin.leftArm.position.y = -2 - 2.539_433_18 * Math.abs(Math.sin((pr * Math.PI) / 2)) + player.skin.rightArm.position.y = player.skin.leftArm.position.y + player.skin.rightLeg.position.z = -3.450_031_037_7 * Math.abs(Math.sin((pr * Math.PI) / 2)) + player.skin.leftLeg.position.z = player.skin.rightLeg.position.z +} diff --git a/renderer/viewer/three/entity/armorModels.ts b/renderer/viewer/three/entity/armorModels.ts index 3a87f8db..3681344c 100644 --- a/renderer/viewer/three/entity/armorModels.ts +++ b/renderer/viewer/three/entity/armorModels.ts @@ -14,6 +14,7 @@ import { default as netheriteLayer1 } from 'mc-assets/dist/other-textures/latest import { default as netheriteLayer2 } from 'mc-assets/dist/other-textures/latest/models/armor/netherite_layer_2.png' import { default as turtleLayer1 } from 'mc-assets/dist/other-textures/latest/models/armor/turtle_layer_1.png' +export { default as elytraTexture } from 'mc-assets/dist/other-textures/latest/entity/elytra.png' export { default as armorModel } from './armorModels.json' export const armorTextures = { diff --git a/renderer/viewer/three/graphicsBackend.ts b/renderer/viewer/three/graphicsBackend.ts index 0f34052a..04cb00ca 100644 --- a/renderer/viewer/three/graphicsBackend.ts +++ b/renderer/viewer/three/graphicsBackend.ts @@ -1,15 +1,19 @@ import * as THREE from 'three' import { Vec3 } from 'vec3' -import { proxy } from 'valtio' -import { GraphicsBackendLoader, GraphicsBackend, GraphicsInitOptions, DisplayWorldOptions, RendererReactiveState } from '../../../src/appViewer' +import { GraphicsBackendLoader, GraphicsBackend, GraphicsInitOptions, DisplayWorldOptions } from '../../../src/appViewer' import { ProgressReporter } from '../../../src/core/progressReporter' +import { showNotification } from '../../../src/react/NotificationProvider' +import { displayEntitiesDebugList } from '../../playground/allEntitiesDebug' +import supportedVersions from '../../../src/supportedVersions.mjs' +import { ResourcesManager } from '../../../src/resourcesManager' import { WorldRendererThree } from './worldrendererThree' import { DocumentRenderer } from './documentRenderer' import { PanoramaRenderer } from './panorama' +import { initVR } from './world/vr' // https://discourse.threejs.org/t/updates-to-color-management-in-three-js-r152/50791 THREE.ColorManagement.enabled = false -window.THREE = THREE +globalThis.THREE = THREE const getBackendMethods = (worldRenderer: WorldRendererThree) => { return { @@ -19,18 +23,33 @@ const getBackendMethods = (worldRenderer: WorldRendererThree) => { playEntityAnimation: worldRenderer.entities.playAnimation.bind(worldRenderer.entities), damageEntity: worldRenderer.entities.handleDamageEvent.bind(worldRenderer.entities), updatePlayerSkin: worldRenderer.entities.updatePlayerSkin.bind(worldRenderer.entities), - setHighlightCursorBlock: worldRenderer.cursorBlock.setHighlightCursorBlock.bind(worldRenderer.cursorBlock), - updateBreakAnimation: worldRenderer.cursorBlock.updateBreakAnimation.bind(worldRenderer.cursorBlock), changeHandSwingingState: worldRenderer.changeHandSwingingState.bind(worldRenderer), getHighestBlocks: worldRenderer.getHighestBlocks.bind(worldRenderer), - rerenderAllChunks: worldRenderer.rerenderAllChunks.bind(worldRenderer), - addMedia: worldRenderer.addMedia.bind(worldRenderer), - destroyMedia: worldRenderer.destroyMedia.bind(worldRenderer), - setVideoPlaying: worldRenderer.setVideoPlaying.bind(worldRenderer), - setVideoSeeking: worldRenderer.setVideoSeeking.bind(worldRenderer), - setVideoVolume: worldRenderer.setVideoVolume.bind(worldRenderer), - setVideoSpeed: worldRenderer.setVideoSpeed.bind(worldRenderer), + reloadWorld: worldRenderer.reloadWorld.bind(worldRenderer), + + addMedia: worldRenderer.media.addMedia.bind(worldRenderer.media), + destroyMedia: worldRenderer.media.destroyMedia.bind(worldRenderer.media), + setVideoPlaying: worldRenderer.media.setVideoPlaying.bind(worldRenderer.media), + setVideoSeeking: worldRenderer.media.setVideoSeeking.bind(worldRenderer.media), + setVideoVolume: worldRenderer.media.setVideoVolume.bind(worldRenderer.media), + setVideoSpeed: worldRenderer.media.setVideoSpeed.bind(worldRenderer.media), + + addSectionAnimation (id: string, animation: typeof worldRenderer.sectionsOffsetsAnimations[string]) { + worldRenderer.sectionsOffsetsAnimations[id] = animation + }, + removeSectionAnimation (id: string) { + delete worldRenderer.sectionsOffsetsAnimations[id] + }, + shakeFromDamage: worldRenderer.cameraShake.shakeFromDamage.bind(worldRenderer.cameraShake), + onPageInteraction: worldRenderer.media.onPageInteraction.bind(worldRenderer.media), + downloadMesherLog: worldRenderer.downloadMesherLog.bind(worldRenderer), + + addWaypoint: worldRenderer.waypoints.addWaypoint.bind(worldRenderer.waypoints), + removeWaypoint: worldRenderer.waypoints.removeWaypoint.bind(worldRenderer.waypoints), + + // New method for updating skybox + setSkyboxImage: worldRenderer.skyboxRenderer.setSkyboxImage.bind(worldRenderer.skyboxRenderer) } } @@ -44,31 +63,42 @@ const createGraphicsBackend: GraphicsBackendLoader = (initOptions: GraphicsInitO let panoramaRenderer: PanoramaRenderer | null = null let worldRenderer: WorldRendererThree | null = null - const startPanorama = () => { + const startPanorama = async () => { + if (!documentRenderer) throw new Error('Document renderer not initialized') if (worldRenderer) return + const qs = new URLSearchParams(location.search) + if (qs.get('debugEntities')) { + const fullResourceManager = initOptions.resourcesManager as ResourcesManager + fullResourceManager.currentConfig = { version: qs.get('version') || supportedVersions.at(-1)!, noInventoryGui: true } + await fullResourceManager.updateAssetsData({ }) + + displayEntitiesDebugList(fullResourceManager.currentConfig.version) + return + } + if (!panoramaRenderer) { panoramaRenderer = new PanoramaRenderer(documentRenderer, initOptions, !!process.env.SINGLE_FILE_BUILD_MODE) - void panoramaRenderer.start() - window.panoramaRenderer = panoramaRenderer + globalThis.panoramaRenderer = panoramaRenderer + callModsMethod('panoramaCreated', panoramaRenderer) + await panoramaRenderer.start() + callModsMethod('panoramaReady', panoramaRenderer) } } - let version = '' - const prepareResources = async (ver: string, progressReporter: ProgressReporter): Promise => { - version = ver - await initOptions.resourcesManager.updateAssetsData({ }) - } - - const startWorld = (displayOptions: DisplayWorldOptions) => { + const startWorld = async (displayOptions: DisplayWorldOptions) => { if (panoramaRenderer) { panoramaRenderer.dispose() panoramaRenderer = null } worldRenderer = new WorldRendererThree(documentRenderer.renderer, initOptions, displayOptions) + void initVR(worldRenderer, documentRenderer) + await worldRenderer.worldReadyPromise documentRenderer.render = (sizeChanged: boolean) => { worldRenderer?.render(sizeChanged) } + documentRenderer.inWorldRenderingConfig = displayOptions.inWorldRenderingConfig window.world = worldRenderer + callModsMethod('worldReady', worldRenderer) } const disconnect = () => { @@ -94,8 +124,12 @@ const createGraphicsBackend: GraphicsBackendLoader = (initOptions: GraphicsInitO disconnect, setRendering (rendering) { documentRenderer.setPaused(!rendering) + if (worldRenderer) worldRenderer.renderingActive = rendering }, getDebugOverlay: () => ({ + get entitiesString () { + return worldRenderer?.entities.getDebugString() + }, }), updateCamera (pos: Vec3 | null, yaw: number, pitch: number) { worldRenderer?.setFirstPersonCamera(pos, yaw, pitch) @@ -109,7 +143,24 @@ const createGraphicsBackend: GraphicsBackendLoader = (initOptions: GraphicsInitO } } + globalThis.threeJsBackend = backend + globalThis.resourcesManager = initOptions.resourcesManager + callModsMethod('default', backend) + return backend } +const callModsMethod = (method: string, ...args: any[]) => { + for (const mod of Object.values((window.loadedMods ?? {}) as Record)) { + try { + mod.threeJsBackendModule?.[method]?.(...args) + } catch (err) { + const errorMessage = `[mod three.js] Error calling ${method} on ${mod.name}: ${err}` + showNotification(errorMessage, 'error') + throw new Error(errorMessage) + } + } +} + +createGraphicsBackend.id = 'threejs' export default createGraphicsBackend diff --git a/renderer/viewer/lib/hand.ts b/renderer/viewer/three/hand.ts similarity index 93% rename from renderer/viewer/lib/hand.ts rename to renderer/viewer/three/hand.ts index 3743aca9..2bd3832b 100644 --- a/renderer/viewer/lib/hand.ts +++ b/renderer/viewer/three/hand.ts @@ -1,6 +1,7 @@ import * as THREE from 'three' -import { loadSkinToCanvas } from 'skinview-utils' -import { getLookupUrl, loadSkinImage, steveTexture } from './utils/skins' +import { loadSkinFromUsername, loadSkinImage } from '../lib/utils/skins' +import { steveTexture } from './entities' + export const getMyHand = async (image?: string, userName?: string) => { let newMap: THREE.Texture @@ -8,7 +9,10 @@ export const getMyHand = async (image?: string, userName?: string) => { newMap = await steveTexture } else { if (!image) { - image = getLookupUrl(userName!, 'skin') + image = await loadSkinFromUsername(userName!, 'skin') + } + if (!image) { + return } const { canvas } = await loadSkinImage(image) newMap = new THREE.CanvasTexture(canvas) diff --git a/renderer/viewer/three/holdingBlock.ts b/renderer/viewer/three/holdingBlock.ts index 9ba76224..f9d00f0e 100644 --- a/renderer/viewer/three/holdingBlock.ts +++ b/renderer/viewer/three/holdingBlock.ts @@ -1,14 +1,15 @@ import * as THREE from 'three' import * as tweenJs from '@tweenjs/tween.js' +import PrismarineItem from 'prismarine-item' import worldBlockProvider, { WorldBlockProvider } from 'mc-assets/dist/worldBlockProvider' import { BlockModel } from 'mc-assets' import { getThreeBlockModelGroup, renderBlockThree, setBlockPosition } from '../lib/mesher/standaloneRenderer' -import { getMyHand } from '../lib/hand' -import { IPlayerState, MovementState } from '../lib/basePlayerState' +import { MovementState, PlayerStateRenderer } from '../lib/basePlayerState' import { DebugGui } from '../lib/DebugGui' import { SmoothSwitcher } from '../lib/smoothSwitcher' import { watchProperty } from '../lib/utils/proxy' import { WorldRendererConfig } from '../lib/worldrendererCommon' +import { getMyHand } from './hand' import { WorldRendererThree } from './worldrendererThree' import { disposeObject } from './threeJsUtils' @@ -115,41 +116,56 @@ export default class HoldingBlock { offHandModeLegacy = false swingAnimator: HandSwingAnimator | undefined - playerState: IPlayerState config: WorldRendererConfig constructor (public worldRenderer: WorldRendererThree, public offHand = false) { this.initCameraGroup() - this.playerState = worldRenderer.displayOptions.playerState - this.playerState.events.on('heldItemChanged', (_, isOffHand) => { - if (this.offHand !== isOffHand) return - this.updateItem() - }) + this.worldRenderer.onReactivePlayerStateUpdated('heldItemMain', () => { + if (!this.offHand) { + this.updateItem() + } + }, false) + this.worldRenderer.onReactivePlayerStateUpdated('heldItemOff', () => { + if (this.offHand) { + this.updateItem() + } + }, false) this.config = worldRenderer.displayOptions.inWorldRenderingConfig this.offHandDisplay = this.offHand // this.offHandDisplay = true if (!this.offHand) { - // watch over my hand - watchProperty( - async () => { - return getMyHand(this.playerState.reactive.playerSkin, this.playerState.onlineMode ? this.playerState.username : undefined) - }, - this.playerState.reactive, - 'playerSkin', - (newHand) => { - this.playerHand = newHand - }, - (oldHand) => { - disposeObject(oldHand, true) - } - ) + // load default hand + void getMyHand().then((hand) => { + this.playerHand = hand + // trigger update + this.updateItem() + }).then(() => { + // now watch over the player skin + watchProperty( + async () => { + return getMyHand(this.worldRenderer.playerStateReactive.playerSkin, this.worldRenderer.playerStateReactive.onlineMode ? this.worldRenderer.playerStateReactive.username : undefined) + }, + this.worldRenderer.playerStateReactive, + 'playerSkin', + (newHand) => { + if (newHand) { + this.playerHand = newHand + // trigger update + this.updateItem() + } + }, + (oldHand) => { + disposeObject(oldHand!, true) + } + ) + }) } } updateItem () { - if (!this.ready || !this.playerState.getHeldItem) return - const item = this.playerState.getHeldItem(this.offHand) + if (!this.ready) return + const item = this.offHand ? this.worldRenderer.playerStateReactive.heldItemOff : this.worldRenderer.playerStateReactive.heldItemMain if (item) { void this.setNewItem(item) } else if (this.offHand) { @@ -286,6 +302,7 @@ export default class HoldingBlock { } isDifferentItem (block: HandItemBlock | undefined) { + const Item = PrismarineItem(this.worldRenderer.version) if (!this.lastHeldItem) { return true } @@ -293,7 +310,7 @@ export default class HoldingBlock { return true } // eslint-disable-next-line sonarjs/prefer-single-boolean-return - if (JSON.stringify(this.lastHeldItem.fullItem) !== JSON.stringify(block?.fullItem ?? '{}')) { + if (!Item.equal(this.lastHeldItem.fullItem, block?.fullItem ?? {}) || JSON.stringify(this.lastHeldItem.fullItem.components) !== JSON.stringify(block?.fullItem?.components)) { return true } @@ -338,9 +355,9 @@ export default class HoldingBlock { itemId: handItem.id, }, { 'minecraft:display_context': 'firstperson', - 'minecraft:use_duration': this.playerState.getItemUsageTicks?.(), - 'minecraft:using_item': !!this.playerState.getItemUsageTicks?.(), - }, this.lastItemModelName) + 'minecraft:use_duration': this.worldRenderer.playerStateReactive.itemUsageTicks, + 'minecraft:using_item': !!this.worldRenderer.playerStateReactive.itemUsageTicks, + }, false, this.lastItemModelName) if (result) { const { mesh: itemMesh, isBlock, modelName } = result if (isBlock) { @@ -456,7 +473,7 @@ export default class HoldingBlock { this.swingAnimator = new HandSwingAnimator(this.holdingBlockInnerGroup) this.swingAnimator.type = result.type if (this.config.viewBobbing) { - this.idleAnimator = new HandIdleAnimator(this.holdingBlockInnerGroup, this.playerState) + this.idleAnimator = new HandIdleAnimator(this.holdingBlockInnerGroup, this.worldRenderer.playerStateReactive) } } @@ -537,7 +554,7 @@ class HandIdleAnimator { private readonly debugGui: DebugGui - constructor (public handMesh: THREE.Object3D, public playerState: IPlayerState) { + constructor (public handMesh: THREE.Object3D, public playerState: PlayerStateRenderer) { this.handMesh = handMesh this.globalTime = 0 this.currentState = 'NOT_MOVING' @@ -691,7 +708,7 @@ class HandIdleAnimator { // Check for state changes from player state if (this.playerState) { - const newState = this.playerState.getMovementState() + const newState = this.playerState.movementState if (newState !== this.targetState) { this.setState(newState) } @@ -911,6 +928,6 @@ export const getBlockMeshFromModel = (material: THREE.Material, model: BlockMode const worldRenderModel = blockProvider.transformModel(model, { name, properties: {} - }) + }) as any return getThreeBlockModelGroup(material, [[worldRenderModel]], undefined, 'plains', loadedData) } diff --git a/renderer/viewer/three/itemMesh.ts b/renderer/viewer/three/itemMesh.ts new file mode 100644 index 00000000..3fa069b9 --- /dev/null +++ b/renderer/viewer/three/itemMesh.ts @@ -0,0 +1,427 @@ +import * as THREE from 'three' + +export interface Create3DItemMeshOptions { + depth: number + pixelSize?: number +} + +export interface Create3DItemMeshResult { + geometry: THREE.BufferGeometry + totalVertices: number + totalTriangles: number +} + +/** + * Creates a 3D item geometry with front/back faces and connecting edges + * from a canvas containing the item texture + */ +export function create3DItemMesh ( + canvas: HTMLCanvasElement, + options: Create3DItemMeshOptions +): Create3DItemMeshResult { + const { depth, pixelSize } = options + + // Validate canvas dimensions + if (canvas.width <= 0 || canvas.height <= 0) { + throw new Error(`Invalid canvas dimensions: ${canvas.width}x${canvas.height}`) + } + + const ctx = canvas.getContext('2d')! + const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height) + const { data } = imageData + + const w = canvas.width + const h = canvas.height + const halfDepth = depth / 2 + const actualPixelSize = pixelSize ?? (1 / Math.max(w, h)) + + // Find opaque pixels + const isOpaque = (x: number, y: number) => { + if (x < 0 || y < 0 || x >= w || y >= h) return false + const i = (y * w + x) * 4 + return data[i + 3] > 128 // alpha > 128 + } + + const vertices: number[] = [] + const indices: number[] = [] + const uvs: number[] = [] + const normals: number[] = [] + + let vertexIndex = 0 + + // Helper to add a vertex + const addVertex = (x: number, y: number, z: number, u: number, v: number, nx: number, ny: number, nz: number) => { + vertices.push(x, y, z) + uvs.push(u, v) + normals.push(nx, ny, nz) + return vertexIndex++ + } + + // Helper to add a quad (two triangles) + const addQuad = (v0: number, v1: number, v2: number, v3: number) => { + indices.push(v0, v1, v2, v0, v2, v3) + } + + // Convert pixel coordinates to world coordinates + const pixelToWorld = (px: number, py: number) => { + const x = (px / w - 0.5) * actualPixelSize * w + const y = -(py / h - 0.5) * actualPixelSize * h + return { x, y } + } + + // Create a grid of vertices for front and back faces + const frontVertices: Array> = Array.from({ length: h + 1 }, () => Array.from({ length: w + 1 }, () => null)) + const backVertices: Array> = Array.from({ length: h + 1 }, () => Array.from({ length: w + 1 }, () => null)) + + // Create vertices at pixel corners + for (let py = 0; py <= h; py++) { + for (let px = 0; px <= w; px++) { + const { x, y } = pixelToWorld(px - 0.5, py - 0.5) + + // UV coordinates should map to the texture space of the extracted tile + const u = px / w + const v = py / h + + // Check if this vertex is needed for any face or edge + let needVertex = false + + // Check all 4 adjacent pixels to see if any are opaque + const adjacentPixels = [ + [px - 1, py - 1], // top-left pixel + [px, py - 1], // top-right pixel + [px - 1, py], // bottom-left pixel + [px, py] // bottom-right pixel + ] + + for (const [adjX, adjY] of adjacentPixels) { + if (isOpaque(adjX, adjY)) { + needVertex = true + break + } + } + + if (needVertex) { + frontVertices[py][px] = addVertex(x, y, halfDepth, u, v, 0, 0, 1) + backVertices[py][px] = addVertex(x, y, -halfDepth, u, v, 0, 0, -1) + } + } + } + + // Create front and back faces + for (let py = 0; py < h; py++) { + for (let px = 0; px < w; px++) { + if (!isOpaque(px, py)) continue + + const v00 = frontVertices[py][px] + const v10 = frontVertices[py][px + 1] + const v11 = frontVertices[py + 1][px + 1] + const v01 = frontVertices[py + 1][px] + + const b00 = backVertices[py][px] + const b10 = backVertices[py][px + 1] + const b11 = backVertices[py + 1][px + 1] + const b01 = backVertices[py + 1][px] + + if (v00 !== null && v10 !== null && v11 !== null && v01 !== null) { + // Front face + addQuad(v00, v10, v11, v01) + } + + if (b00 !== null && b10 !== null && b11 !== null && b01 !== null) { + // Back face (reversed winding) + addQuad(b10, b00, b01, b11) + } + } + } + + // Create edge faces for each side of the pixel with proper UVs + for (let py = 0; py < h; py++) { + for (let px = 0; px < w; px++) { + if (!isOpaque(px, py)) continue + + const pixelU = (px + 0.5) / w // Center of current pixel + const pixelV = (py + 0.5) / h + + // Left edge (x = px) + if (!isOpaque(px - 1, py)) { + const f0 = frontVertices[py][px] + const f1 = frontVertices[py + 1][px] + const b0 = backVertices[py][px] + const b1 = backVertices[py + 1][px] + + if (f0 !== null && f1 !== null && b0 !== null && b1 !== null) { + // Create new vertices for edge with current pixel's UV + const ef0 = addVertex(vertices[f0 * 3], vertices[f0 * 3 + 1], vertices[f0 * 3 + 2], pixelU, pixelV, -1, 0, 0) + const ef1 = addVertex(vertices[f1 * 3], vertices[f1 * 3 + 1], vertices[f1 * 3 + 2], pixelU, pixelV, -1, 0, 0) + const eb1 = addVertex(vertices[b1 * 3], vertices[b1 * 3 + 1], vertices[b1 * 3 + 2], pixelU, pixelV, -1, 0, 0) + const eb0 = addVertex(vertices[b0 * 3], vertices[b0 * 3 + 1], vertices[b0 * 3 + 2], pixelU, pixelV, -1, 0, 0) + addQuad(ef0, ef1, eb1, eb0) + } + } + + // Right edge (x = px + 1) + if (!isOpaque(px + 1, py)) { + const f0 = frontVertices[py + 1][px + 1] + const f1 = frontVertices[py][px + 1] + const b0 = backVertices[py + 1][px + 1] + const b1 = backVertices[py][px + 1] + + if (f0 !== null && f1 !== null && b0 !== null && b1 !== null) { + const ef0 = addVertex(vertices[f0 * 3], vertices[f0 * 3 + 1], vertices[f0 * 3 + 2], pixelU, pixelV, 1, 0, 0) + const ef1 = addVertex(vertices[f1 * 3], vertices[f1 * 3 + 1], vertices[f1 * 3 + 2], pixelU, pixelV, 1, 0, 0) + const eb1 = addVertex(vertices[b1 * 3], vertices[b1 * 3 + 1], vertices[b1 * 3 + 2], pixelU, pixelV, 1, 0, 0) + const eb0 = addVertex(vertices[b0 * 3], vertices[b0 * 3 + 1], vertices[b0 * 3 + 2], pixelU, pixelV, 1, 0, 0) + addQuad(ef0, ef1, eb1, eb0) + } + } + + // Top edge (y = py) + if (!isOpaque(px, py - 1)) { + const f0 = frontVertices[py][px] + const f1 = frontVertices[py][px + 1] + const b0 = backVertices[py][px] + const b1 = backVertices[py][px + 1] + + if (f0 !== null && f1 !== null && b0 !== null && b1 !== null) { + const ef0 = addVertex(vertices[f0 * 3], vertices[f0 * 3 + 1], vertices[f0 * 3 + 2], pixelU, pixelV, 0, -1, 0) + const ef1 = addVertex(vertices[f1 * 3], vertices[f1 * 3 + 1], vertices[f1 * 3 + 2], pixelU, pixelV, 0, -1, 0) + const eb1 = addVertex(vertices[b1 * 3], vertices[b1 * 3 + 1], vertices[b1 * 3 + 2], pixelU, pixelV, 0, -1, 0) + const eb0 = addVertex(vertices[b0 * 3], vertices[b0 * 3 + 1], vertices[b0 * 3 + 2], pixelU, pixelV, 0, -1, 0) + addQuad(ef0, ef1, eb1, eb0) + } + } + + // Bottom edge (y = py + 1) + if (!isOpaque(px, py + 1)) { + const f0 = frontVertices[py + 1][px + 1] + const f1 = frontVertices[py + 1][px] + const b0 = backVertices[py + 1][px + 1] + const b1 = backVertices[py + 1][px] + + if (f0 !== null && f1 !== null && b0 !== null && b1 !== null) { + const ef0 = addVertex(vertices[f0 * 3], vertices[f0 * 3 + 1], vertices[f0 * 3 + 2], pixelU, pixelV, 0, 1, 0) + const ef1 = addVertex(vertices[f1 * 3], vertices[f1 * 3 + 1], vertices[f1 * 3 + 2], pixelU, pixelV, 0, 1, 0) + const eb1 = addVertex(vertices[b1 * 3], vertices[b1 * 3 + 1], vertices[b1 * 3 + 2], pixelU, pixelV, 0, 1, 0) + const eb0 = addVertex(vertices[b0 * 3], vertices[b0 * 3 + 1], vertices[b0 * 3 + 2], pixelU, pixelV, 0, 1, 0) + addQuad(ef0, ef1, eb1, eb0) + } + } + } + } + + const geometry = new THREE.BufferGeometry() + geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3)) + geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2)) + geometry.setAttribute('normal', new THREE.Float32BufferAttribute(normals, 3)) + geometry.setIndex(indices) + + // Compute normals properly + geometry.computeVertexNormals() + + return { + geometry, + totalVertices: vertexIndex, + totalTriangles: indices.length / 3 + } +} + +export interface ItemTextureInfo { + u: number + v: number + sizeX: number + sizeY: number +} + +export interface ItemMeshResult { + mesh: THREE.Object3D + itemsTexture?: THREE.Texture + itemsTextureFlipped?: THREE.Texture + cleanup?: () => void +} + +/** + * Extracts item texture region to a canvas + */ +export function extractItemTextureToCanvas ( + sourceTexture: THREE.Texture, + textureInfo: ItemTextureInfo +): HTMLCanvasElement { + const { u, v, sizeX, sizeY } = textureInfo + + // Calculate canvas size - fix the calculation + const canvasWidth = Math.max(1, Math.floor(sizeX * sourceTexture.image.width)) + const canvasHeight = Math.max(1, Math.floor(sizeY * sourceTexture.image.height)) + + const canvas = document.createElement('canvas') + canvas.width = canvasWidth + canvas.height = canvasHeight + + const ctx = canvas.getContext('2d')! + ctx.imageSmoothingEnabled = false + + // Draw the item texture region to canvas + ctx.drawImage( + sourceTexture.image, + u * sourceTexture.image.width, + v * sourceTexture.image.height, + sizeX * sourceTexture.image.width, + sizeY * sourceTexture.image.height, + 0, + 0, + canvas.width, + canvas.height + ) + + return canvas +} + +/** + * Creates either a 2D or 3D item mesh based on parameters + */ +export function createItemMesh ( + sourceTexture: THREE.Texture, + textureInfo: ItemTextureInfo, + options: { + faceCamera?: boolean + use3D?: boolean + depth?: number + } = {} +): ItemMeshResult { + const { faceCamera = false, use3D = true, depth = 0.04 } = options + const { u, v, sizeX, sizeY } = textureInfo + + if (faceCamera) { + // Create sprite for camera-facing items + const itemsTexture = sourceTexture.clone() + itemsTexture.flipY = true + itemsTexture.offset.set(u, 1 - v - sizeY) + itemsTexture.repeat.set(sizeX, sizeY) + itemsTexture.needsUpdate = true + itemsTexture.magFilter = THREE.NearestFilter + itemsTexture.minFilter = THREE.NearestFilter + + const spriteMat = new THREE.SpriteMaterial({ + map: itemsTexture, + transparent: true, + alphaTest: 0.1, + }) + const mesh = new THREE.Sprite(spriteMat) + + return { + mesh, + itemsTexture, + cleanup () { + itemsTexture.dispose() + } + } + } + + if (use3D) { + // Try to create 3D mesh + try { + const canvas = extractItemTextureToCanvas(sourceTexture, textureInfo) + const { geometry } = create3DItemMesh(canvas, { depth }) + + // Create texture from canvas for the 3D mesh + const itemsTexture = new THREE.CanvasTexture(canvas) + itemsTexture.magFilter = THREE.NearestFilter + itemsTexture.minFilter = THREE.NearestFilter + itemsTexture.wrapS = itemsTexture.wrapT = THREE.ClampToEdgeWrapping + itemsTexture.flipY = false + itemsTexture.needsUpdate = true + + const material = new THREE.MeshStandardMaterial({ + map: itemsTexture, + side: THREE.DoubleSide, + transparent: true, + alphaTest: 0.1, + }) + + const mesh = new THREE.Mesh(geometry, material) + + return { + mesh, + itemsTexture, + cleanup () { + itemsTexture.dispose() + geometry.dispose() + if (material.map) material.map.dispose() + material.dispose() + } + } + } catch (error) { + console.warn('Failed to create 3D item mesh, falling back to 2D:', error) + // Fall through to 2D rendering + } + } + + // Fallback to 2D flat rendering + const itemsTexture = sourceTexture.clone() + itemsTexture.flipY = true + itemsTexture.offset.set(u, 1 - v - sizeY) + itemsTexture.repeat.set(sizeX, sizeY) + itemsTexture.needsUpdate = true + itemsTexture.magFilter = THREE.NearestFilter + itemsTexture.minFilter = THREE.NearestFilter + + const itemsTextureFlipped = itemsTexture.clone() + itemsTextureFlipped.repeat.x *= -1 + itemsTextureFlipped.needsUpdate = true + itemsTextureFlipped.offset.set(u + sizeX, 1 - v - sizeY) + + const material = new THREE.MeshStandardMaterial({ + map: itemsTexture, + transparent: true, + alphaTest: 0.1, + }) + const materialFlipped = new THREE.MeshStandardMaterial({ + map: itemsTextureFlipped, + transparent: true, + alphaTest: 0.1, + }) + const mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 0), [ + new THREE.MeshBasicMaterial({ color: 0x00_00_00 }), new THREE.MeshBasicMaterial({ color: 0x00_00_00 }), + new THREE.MeshBasicMaterial({ color: 0x00_00_00 }), new THREE.MeshBasicMaterial({ color: 0x00_00_00 }), + material, materialFlipped, + ]) + + return { + mesh, + itemsTexture, + itemsTextureFlipped, + cleanup () { + itemsTexture.dispose() + itemsTextureFlipped.dispose() + material.dispose() + materialFlipped.dispose() + } + } +} + +/** + * Creates a complete 3D item mesh from a canvas texture + */ +export function createItemMeshFromCanvas ( + canvas: HTMLCanvasElement, + options: Create3DItemMeshOptions +): THREE.Mesh { + const { geometry } = create3DItemMesh(canvas, options) + + // Base color texture for the item + const colorTexture = new THREE.CanvasTexture(canvas) + colorTexture.magFilter = THREE.NearestFilter + colorTexture.minFilter = THREE.NearestFilter + colorTexture.wrapS = colorTexture.wrapT = THREE.ClampToEdgeWrapping + colorTexture.flipY = false // Important for canvas textures + colorTexture.needsUpdate = true + + // Material - no transparency, no alpha test needed for edges + const material = new THREE.MeshBasicMaterial({ + map: colorTexture, + side: THREE.DoubleSide, + transparent: true, + alphaTest: 0.1 + }) + + return new THREE.Mesh(geometry, material) +} diff --git a/renderer/viewer/three/panorama.ts b/renderer/viewer/three/panorama.ts index ddc79cbd..254b980c 100644 --- a/renderer/viewer/three/panorama.ts +++ b/renderer/viewer/three/panorama.ts @@ -5,12 +5,15 @@ import { Vec3 } from 'vec3' import * as tweenJs from '@tweenjs/tween.js' import type { GraphicsInitOptions } from '../../../src/appViewer' import { WorldDataEmitter } from '../lib/worldDataEmitter' -import { defaultWorldRendererConfig } from '../lib/worldrendererCommon' -import { BasePlayerState } from '../lib/basePlayerState' +import { defaultWorldRendererConfig, WorldRendererCommon } from '../lib/worldrendererCommon' import { getDefaultRendererState } from '../baseGraphicsBackend' +import { ResourcesManager } from '../../../src/resourcesManager' +import { getInitialPlayerStateRenderer } from '../lib/basePlayerState' +import { loadThreeJsTextureFromUrl, loadThreeJsTextureFromUrlSync } from './threeJsUtils' import { WorldRendererThree } from './worldrendererThree' import { EntityMesh } from './entity/EntityMesh' import { DocumentRenderer } from './documentRenderer' +import { PANORAMA_VERSION } from './panoramaShared' const panoramaFiles = [ 'panorama_3.png', // right (+x) @@ -29,11 +32,14 @@ export class PanoramaRenderer { private panoramaGroup: THREE.Object3D | null = null private time = 0 private readonly abortController = new AbortController() - private worldRenderer: WorldRendererThree | undefined + private worldRenderer: WorldRendererCommon | WorldRendererThree | undefined + public WorldRendererClass = WorldRendererThree + public startTimes = new Map() constructor (private readonly documentRenderer: DocumentRenderer, private readonly options: GraphicsInitOptions, private readonly doWorldBlocksPanorama = false) { this.scene = new THREE.Scene() - this.scene.background = new THREE.Color(this.options.config.sceneBackground) + // #324568 + this.scene.background = new THREE.Color(0x32_45_68) // Add ambient light this.ambientLight = new THREE.AmbientLight(0xcc_cc_cc) @@ -45,7 +51,7 @@ export class PanoramaRenderer { this.directionalLight.castShadow = true this.scene.add(this.directionalLight) - this.camera = new THREE.PerspectiveCamera(85, window.innerWidth / window.innerHeight, 0.05, 1000) + this.camera = new THREE.PerspectiveCamera(85, this.documentRenderer.canvas.width / this.documentRenderer.canvas.height, 0.05, 1000) this.camera.position.set(0, 0, 0) this.camera.rotation.set(0, 0, 0) } @@ -60,38 +66,57 @@ export class PanoramaRenderer { this.documentRenderer.render = (sizeChanged = false) => { if (sizeChanged) { - this.camera.aspect = window.innerWidth / window.innerHeight + this.camera.aspect = this.documentRenderer.canvas.width / this.documentRenderer.canvas.height this.camera.updateProjectionMatrix() } this.documentRenderer.renderer.render(this.scene, this.camera) } } + async debugImageInFrontOfCamera () { + const image = await loadThreeJsTextureFromUrl(join('background', 'panorama_0.png')) + const mesh = new THREE.Mesh(new THREE.PlaneGeometry(1000, 1000), new THREE.MeshBasicMaterial({ map: image })) + mesh.position.set(0, 0, -500) + mesh.rotation.set(0, 0, 0) + this.scene.add(mesh) + } + addClassicPanorama () { const panorGeo = new THREE.BoxGeometry(1000, 1000, 1000) - const loader = new THREE.TextureLoader() const panorMaterials = [] as THREE.MeshBasicMaterial[] + const fadeInDuration = 200 + + // void this.debugImageInFrontOfCamera() for (const file of panoramaFiles) { - const texture = loader.load(join('background', file)) + const load = async () => { + const { texture } = loadThreeJsTextureFromUrlSync(join('background', file)) - // Instead of using repeat/offset to flip, we'll use the texture matrix - texture.matrixAutoUpdate = false - texture.matrix.set( - -1, 0, 1, 0, 1, 0, 0, 0, 1 - ) + // Instead of using repeat/offset to flip, we'll use the texture matrix + texture.matrixAutoUpdate = false + texture.matrix.set( + -1, 0, 1, 0, 1, 0, 0, 0, 1 + ) - texture.wrapS = THREE.ClampToEdgeWrapping // Changed from RepeatWrapping - texture.wrapT = THREE.ClampToEdgeWrapping // Changed from RepeatWrapping - texture.minFilter = THREE.LinearFilter - texture.magFilter = THREE.LinearFilter + texture.wrapS = THREE.ClampToEdgeWrapping + texture.wrapT = THREE.ClampToEdgeWrapping + texture.minFilter = THREE.LinearFilter + texture.magFilter = THREE.LinearFilter - panorMaterials.push(new THREE.MeshBasicMaterial({ - map: texture, - transparent: true, - side: THREE.DoubleSide, - depthWrite: false, - })) + const material = new THREE.MeshBasicMaterial({ + map: texture, + transparent: true, + side: THREE.DoubleSide, + depthWrite: false, + opacity: 0 // Start with 0 opacity + }) + + // Start fade-in when texture is loaded + this.startTimes.set(material, Date.now()) + panorMaterials.push(material) + } + + void load() } const panoramaBox = new THREE.Mesh(panorGeo, panorMaterials) @@ -99,6 +124,16 @@ export class PanoramaRenderer { this.time += 0.01 panoramaBox.rotation.y = Math.PI + this.time * 0.01 panoramaBox.rotation.z = Math.sin(-this.time * 0.001) * 0.001 + + // Time-based fade in animation for each material + for (const material of panorMaterials) { + const startTime = this.startTimes.get(material) + if (startTime) { + const elapsed = Date.now() - startTime + const progress = Math.min(1, elapsed / fadeInDuration) + material.opacity = progress + } + } } const group = new THREE.Object3D() @@ -122,9 +157,10 @@ export class PanoramaRenderer { } async worldBlocksPanorama () { - const version = '1.21.4' - this.options.resourcesManager.currentConfig = { version } - await this.options.resourcesManager.updateAssetsData({ }) + const version = PANORAMA_VERSION + const fullResourceManager = this.options.resourcesManager as ResourcesManager + fullResourceManager.currentConfig = { version, noInventoryGui: true, } + await fullResourceManager.updateAssetsData({ }) if (this.abortController.signal.aborted) return console.time('load panorama scene') const world = getSyncWorld(version) @@ -155,18 +191,21 @@ export class PanoramaRenderer { // worldView.addWaitTime = 0 if (this.abortController.signal.aborted) return - this.worldRenderer = new WorldRendererThree( + this.worldRenderer = new this.WorldRendererClass( this.documentRenderer.renderer, this.options, { version, worldView, inWorldRenderingConfig: defaultWorldRendererConfig, - playerState: new BasePlayerState(), - rendererState: getDefaultRendererState() + playerStateReactive: getInitialPlayerStateRenderer().reactive, + rendererState: getDefaultRendererState().reactive, + nonReactiveState: getDefaultRendererState().nonReactive } ) - this.scene = this.worldRenderer.scene + if (this.worldRenderer instanceof WorldRendererThree) { + this.scene = this.worldRenderer.scene + } void worldView.init(initPos) await this.worldRenderer.waitForChunksToRender() @@ -205,3 +244,59 @@ export class PanoramaRenderer { this.abortController.abort() } } + +// export class ClassicPanoramaRenderer { +// panoramaGroup: THREE.Object3D + +// constructor (private readonly backgroundFiles: string[], onRender: Array<(sizeChanged: boolean) => void>, addSquids = true) { +// const panorGeo = new THREE.BoxGeometry(1000, 1000, 1000) +// const loader = new THREE.TextureLoader() +// const panorMaterials = [] as THREE.MeshBasicMaterial[] + +// for (const file of this.backgroundFiles) { +// const texture = loader.load(file) + +// // Instead of using repeat/offset to flip, we'll use the texture matrix +// texture.matrixAutoUpdate = false +// texture.matrix.set( +// -1, 0, 1, 0, 1, 0, 0, 0, 1 +// ) + +// texture.wrapS = THREE.ClampToEdgeWrapping // Changed from RepeatWrapping +// texture.wrapT = THREE.ClampToEdgeWrapping // Changed from RepeatWrapping +// texture.minFilter = THREE.LinearFilter +// texture.magFilter = THREE.LinearFilter + +// panorMaterials.push(new THREE.MeshBasicMaterial({ +// map: texture, +// transparent: true, +// side: THREE.DoubleSide, +// depthWrite: false, +// })) +// } + +// const panoramaBox = new THREE.Mesh(panorGeo, panorMaterials) +// panoramaBox.onBeforeRender = () => { +// } + +// const group = new THREE.Object3D() +// group.add(panoramaBox) + +// if (addSquids) { +// // Add squids +// for (let i = 0; i < 20; i++) { +// const m = new EntityMesh('1.16.4', 'squid').mesh +// m.position.set(Math.random() * 30 - 15, Math.random() * 20 - 10, Math.random() * 10 - 17) +// m.rotation.set(0, Math.PI + Math.random(), -Math.PI / 4, 'ZYX') +// const v = Math.random() * 0.01 +// onRender.push(() => { +// m.rotation.y += v +// m.rotation.z = Math.cos(panoramaBox.rotation.y * 3) * Math.PI / 4 - Math.PI / 2 +// }) +// group.add(m) +// } +// } + +// this.panoramaGroup = group +// } +// } diff --git a/renderer/viewer/three/panoramaShared.ts b/renderer/viewer/three/panoramaShared.ts new file mode 100644 index 00000000..ad80367f --- /dev/null +++ b/renderer/viewer/three/panoramaShared.ts @@ -0,0 +1 @@ +export const PANORAMA_VERSION = '1.21.4' diff --git a/renderer/viewer/three/renderSlot.ts b/renderer/viewer/three/renderSlot.ts new file mode 100644 index 00000000..321633eb --- /dev/null +++ b/renderer/viewer/three/renderSlot.ts @@ -0,0 +1,82 @@ +import { getRenamedData } from 'flying-squid/dist/blockRenames' +import { BlockModel } from 'mc-assets' +import { versionToNumber } from 'mc-assets/dist/utils' +import type { ResourcesManagerCommon } from '../../../src/resourcesManager' + +export type ResolvedItemModelRender = { + modelName: string, + originalItemName?: string +} + +export const renderSlot = (model: ResolvedItemModelRender, resourcesManager: ResourcesManagerCommon, debugIsQuickbar = false, fullBlockModelSupport = false): { + texture: string, + blockData: Record & { resolvedModel: BlockModel } | null, + scale: number | null, + slice: number[] | null, + modelName: string | null, +} => { + let itemModelName = model.modelName + const isItem = loadedData.itemsByName[itemModelName] + + // #region normalize item name + if (versionToNumber(bot.version) < versionToNumber('1.13')) itemModelName = getRenamedData(isItem ? 'items' : 'blocks', itemModelName, bot.version, '1.13.1') as string + // #endregion + + + let itemTexture + + if (!fullBlockModelSupport) { + const atlas = resourcesManager.currentResources?.guiAtlas?.json + // todo atlas holds all rendered blocks, not all possibly rendered item/block models, need to request this on demand instead (this is how vanilla works) + const tryGetAtlasTexture = (name?: string) => name && atlas?.textures[name.replace('minecraft:', '').replace('block/', '').replace('blocks/', '').replace('item/', '').replace('items/', '').replace('_inventory', '')] + const item = tryGetAtlasTexture(itemModelName) ?? tryGetAtlasTexture(model.originalItemName) + if (item) { + const x = item.u * atlas.width + const y = item.v * atlas.height + return { + texture: 'gui', + slice: [x, y, atlas.tileSize, atlas.tileSize], + scale: 0.25, + blockData: null, + modelName: null + } + } + } + + const blockToTopTexture = (r) => r.top ?? r + + try { + if (!appViewer.resourcesManager.currentResources?.itemsRenderer) throw new Error('Items renderer is not available') + itemTexture = + appViewer.resourcesManager.currentResources.itemsRenderer.getItemTexture(itemModelName, {}, false, fullBlockModelSupport) + ?? (model.originalItemName ? appViewer.resourcesManager.currentResources.itemsRenderer.getItemTexture(model.originalItemName, {}, false, fullBlockModelSupport) : undefined) + ?? appViewer.resourcesManager.currentResources.itemsRenderer.getItemTexture('item/missing_texture')! + } catch (err) { + // get resourcepack from resource manager + reportError?.(`Failed to render item ${itemModelName} (original: ${model.originalItemName}) on ${bot.version} (resourcepack: TODO!): ${err.stack}`) + itemTexture = blockToTopTexture(appViewer.resourcesManager.currentResources!.itemsRenderer.getItemTexture('errored')!) + } + + itemTexture ??= blockToTopTexture(appViewer.resourcesManager.currentResources!.itemsRenderer.getItemTexture('unknown')!) + + + if ('type' in itemTexture) { + // is item + return { + texture: itemTexture.type, + slice: itemTexture.slice, + modelName: itemModelName, + blockData: null, + scale: null + } + } else { + // is block + return { + texture: 'blocks', + blockData: itemTexture, + modelName: itemModelName, + slice: null, + scale: null + } + } +} diff --git a/renderer/viewer/three/skyboxRenderer.ts b/renderer/viewer/three/skyboxRenderer.ts new file mode 100644 index 00000000..fb9edae6 --- /dev/null +++ b/renderer/viewer/three/skyboxRenderer.ts @@ -0,0 +1,406 @@ +import * as THREE from 'three' +import { DebugGui } from '../lib/DebugGui' + +export const DEFAULT_TEMPERATURE = 0.75 + +export class SkyboxRenderer { + private texture: THREE.Texture | null = null + private mesh: THREE.Mesh | null = null + private skyMesh: THREE.Mesh | null = null + private voidMesh: THREE.Mesh | null = null + + // World state + private worldTime = 0 + private partialTicks = 0 + private viewDistance = 4 + private temperature = DEFAULT_TEMPERATURE + private inWater = false + private waterBreathing = false + private fogBrightness = 0 + private prevFogBrightness = 0 + private readonly fogOrangeness = 0 // Debug property to control sky color orangeness + private readonly distanceFactor = 2.7 + + private readonly brightnessAtPosition = 1 + debugGui: DebugGui + + constructor (private readonly scene: THREE.Scene, public defaultSkybox: boolean, public initialImage: string | null) { + this.debugGui = new DebugGui('skybox_renderer', this, [ + 'temperature', + 'worldTime', + 'inWater', + 'waterBreathing', + 'fogOrangeness', + 'brightnessAtPosition', + 'distanceFactor' + ], { + brightnessAtPosition: { min: 0, max: 1, step: 0.01 }, + temperature: { min: 0, max: 1, step: 0.01 }, + worldTime: { min: 0, max: 24_000, step: 1 }, + fogOrangeness: { min: -1, max: 1, step: 0.01 }, + distanceFactor: { min: 0, max: 5, step: 0.01 }, + }) + + if (!initialImage) { + this.createGradientSky() + } + // this.debugGui.activate() + } + + async init () { + if (this.initialImage) { + await this.setSkyboxImage(this.initialImage) + } + } + + async setSkyboxImage (imageUrl: string) { + // Dispose old textures if they exist + if (this.texture) { + this.texture.dispose() + } + + // Load the equirectangular texture + const textureLoader = new THREE.TextureLoader() + this.texture = await new Promise((resolve) => { + textureLoader.load( + imageUrl, + (texture) => { + texture.mapping = THREE.EquirectangularReflectionMapping + texture.encoding = THREE.sRGBEncoding + // Keep pixelated look + texture.minFilter = THREE.NearestFilter + texture.magFilter = THREE.NearestFilter + texture.needsUpdate = true + resolve(texture) + } + ) + }) + + // Create or update the skybox + if (this.mesh) { + // Just update the texture on the existing material + this.mesh.material.map = this.texture + this.mesh.material.needsUpdate = true + } else { + // Create a large sphere geometry for the skybox + const geometry = new THREE.SphereGeometry(500, 60, 40) + // Flip the geometry inside out + geometry.scale(-1, 1, 1) + + // Create material using the loaded texture + const material = new THREE.MeshBasicMaterial({ + map: this.texture, + side: THREE.FrontSide // Changed to FrontSide since we're flipping the geometry + }) + + // Create and add the skybox mesh + this.mesh = new THREE.Mesh(geometry, material) + this.scene.add(this.mesh) + } + } + + update (cameraPosition: THREE.Vector3, newViewDistance: number) { + if (newViewDistance !== this.viewDistance) { + this.viewDistance = newViewDistance + this.updateSkyColors() + } + + if (this.mesh) { + // Update skybox position + this.mesh.position.copy(cameraPosition) + } else if (this.skyMesh) { + // Update gradient sky position + this.skyMesh.position.copy(cameraPosition) + this.voidMesh?.position.copy(cameraPosition) + this.updateSkyColors() // Update colors based on time of day + } + } + + // Update world time + updateTime (timeOfDay: number, partialTicks = 0) { + if (this.debugGui.visible) return + this.worldTime = timeOfDay + this.partialTicks = partialTicks + this.updateSkyColors() + } + + // Update view distance + updateViewDistance (viewDistance: number) { + this.viewDistance = viewDistance + this.updateSkyColors() + } + + // Update temperature (for biome support) + updateTemperature (temperature: number) { + if (this.debugGui.visible) return + this.temperature = temperature + this.updateSkyColors() + } + + // Update water state + updateWaterState (inWater: boolean, waterBreathing: boolean) { + if (this.debugGui.visible) return + this.inWater = inWater + this.waterBreathing = waterBreathing + this.updateSkyColors() + } + + // Update default skybox setting + updateDefaultSkybox (defaultSkybox: boolean) { + if (this.debugGui.visible) return + this.defaultSkybox = defaultSkybox + this.updateSkyColors() + } + + private createGradientSky () { + const size = 64 + const scale = 256 / size + 2 + + { + const geometry = new THREE.PlaneGeometry(size * scale * 2, size * scale * 2) + geometry.rotateX(-Math.PI / 2) + geometry.translate(0, 16, 0) + + const material = new THREE.MeshBasicMaterial({ + color: 0xff_ff_ff, + side: THREE.DoubleSide, + depthTest: false + }) + + this.skyMesh = new THREE.Mesh(geometry, material) + this.scene.add(this.skyMesh) + } + + { + const geometry = new THREE.PlaneGeometry(size * scale * 2, size * scale * 2) + geometry.rotateX(-Math.PI / 2) + geometry.translate(0, -16, 0) + + const material = new THREE.MeshBasicMaterial({ + color: 0xff_ff_ff, + side: THREE.DoubleSide, + depthTest: false + }) + + this.voidMesh = new THREE.Mesh(geometry, material) + this.scene.add(this.voidMesh) + } + + this.updateSkyColors() + } + + private getFogColor (partialTicks = 0): THREE.Vector3 { + const angle = this.getCelestialAngle(partialTicks) + let rotation = Math.cos(angle * Math.PI * 2) * 2 + 0.5 + rotation = Math.max(0, Math.min(1, rotation)) + + let x = 0.752_941_2 + let y = 0.847_058_83 + let z = 1 + + x *= (rotation * 0.94 + 0.06) + y *= (rotation * 0.94 + 0.06) + z *= (rotation * 0.91 + 0.09) + + return new THREE.Vector3(x, y, z) + } + + private getSkyColor (x = 0, z = 0, partialTicks = 0): THREE.Vector3 { + const angle = this.getCelestialAngle(partialTicks) + let brightness = Math.cos(angle * 3.141_593 * 2) * 2 + 0.5 + + if (brightness < 0) brightness = 0 + if (brightness > 1) brightness = 1 + + const temperature = this.getTemperature(x, z) + const rgb = this.getSkyColorByTemp(temperature) + + const red = ((rgb >> 16) & 0xff) / 255 + const green = ((rgb >> 8) & 0xff) / 255 + const blue = (rgb & 0xff) / 255 + + return new THREE.Vector3( + red * brightness, + green * brightness, + blue * brightness + ) + } + + private calculateCelestialAngle (time: number, partialTicks: number): number { + const modTime = (time % 24_000) + let angle = (modTime + partialTicks) / 24_000 - 0.25 + + if (angle < 0) { + angle++ + } + if (angle > 1) { + angle-- + } + + angle = 1 - ((Math.cos(angle * Math.PI) + 1) / 2) + angle += (angle - angle) / 3 + + return angle + } + + private getCelestialAngle (partialTicks: number): number { + return this.calculateCelestialAngle(this.worldTime, partialTicks) + } + + private getTemperature (x: number, z: number): number { + return this.temperature + } + + private getSkyColorByTemp (temperature: number): number { + temperature /= 3 + if (temperature < -1) temperature = -1 + if (temperature > 1) temperature = 1 + + // Apply debug fog orangeness to hue - positive values make it more orange, negative make it less orange + const baseHue = 0.622_222_2 - temperature * 0.05 + // Orange is around hue 0.08-0.15, so we need to shift from blue-purple (0.62) toward orange + // Use a more dramatic shift and also increase saturation for more noticeable effect + const orangeHue = 0.12 // Orange hue value + const hue = this.fogOrangeness > 0 + ? baseHue + (orangeHue - baseHue) * this.fogOrangeness * 0.8 // Blend toward orange + : baseHue + this.fogOrangeness * 0.1 // Subtle shift for negative values + const saturation = 0.5 + temperature * 0.1 + Math.abs(this.fogOrangeness) * 0.3 // Increase saturation with orangeness + const brightness = 1 + + return this.hsbToRgb(hue, saturation, brightness) + } + + private hsbToRgb (hue: number, saturation: number, brightness: number): number { + let r = 0; let g = 0; let b = 0 + if (saturation === 0) { + r = g = b = Math.floor(brightness * 255 + 0.5) + } else { + const h = (hue - Math.floor(hue)) * 6 + const f = h - Math.floor(h) + const p = brightness * (1 - saturation) + const q = brightness * (1 - saturation * f) + const t = brightness * (1 - (saturation * (1 - f))) + switch (Math.floor(h)) { + case 0: + r = Math.floor(brightness * 255 + 0.5) + g = Math.floor(t * 255 + 0.5) + b = Math.floor(p * 255 + 0.5) + break + case 1: + r = Math.floor(q * 255 + 0.5) + g = Math.floor(brightness * 255 + 0.5) + b = Math.floor(p * 255 + 0.5) + break + case 2: + r = Math.floor(p * 255 + 0.5) + g = Math.floor(brightness * 255 + 0.5) + b = Math.floor(t * 255 + 0.5) + break + case 3: + r = Math.floor(p * 255 + 0.5) + g = Math.floor(q * 255 + 0.5) + b = Math.floor(brightness * 255 + 0.5) + break + case 4: + r = Math.floor(t * 255 + 0.5) + g = Math.floor(p * 255 + 0.5) + b = Math.floor(brightness * 255 + 0.5) + break + case 5: + r = Math.floor(brightness * 255 + 0.5) + g = Math.floor(p * 255 + 0.5) + b = Math.floor(q * 255 + 0.5) + break + } + } + return 0xff_00_00_00 | (r << 16) | (g << 8) | (Math.trunc(b)) + } + + private updateSkyColors () { + if (!this.skyMesh || !this.voidMesh) return + + // If default skybox is disabled, hide the skybox meshes + if (!this.defaultSkybox) { + this.skyMesh.visible = false + this.voidMesh.visible = false + if (this.mesh) { + this.mesh.visible = false + } + return + } + + // Show skybox meshes when default skybox is enabled + this.skyMesh.visible = true + this.voidMesh.visible = true + if (this.mesh) { + this.mesh.visible = true + } + + // Update fog brightness with smooth transition + this.prevFogBrightness = this.fogBrightness + const renderDistance = this.viewDistance / 32 + const targetBrightness = this.brightnessAtPosition * (1 - renderDistance) + renderDistance + this.fogBrightness += (targetBrightness - this.fogBrightness) * 0.1 + + // Handle water fog + if (this.inWater) { + const waterViewDistance = this.waterBreathing ? 100 : 5 + this.scene.fog = new THREE.Fog(new THREE.Color(0, 0, 1), 0.0025, waterViewDistance) + this.scene.background = new THREE.Color(0, 0, 1) + + // Update sky and void colors for underwater effect + ;(this.skyMesh.material as THREE.MeshBasicMaterial).color.set(new THREE.Color(0, 0, 1)) + ;(this.voidMesh.material as THREE.MeshBasicMaterial).color.set(new THREE.Color(0, 0, 0.6)) + return + } + + // Normal sky colors + const viewDistance = this.viewDistance * 16 + const viewFactor = 1 - (0.25 + 0.75 * this.viewDistance / 32) ** 0.25 + + const angle = this.getCelestialAngle(this.partialTicks) + const skyColor = this.getSkyColor(0, 0, this.partialTicks) + const fogColor = this.getFogColor(this.partialTicks) + + const brightness = Math.cos(angle * Math.PI * 2) * 2 + 0.5 + const clampedBrightness = Math.max(0, Math.min(1, brightness)) + + // Interpolate fog brightness + const interpolatedBrightness = this.prevFogBrightness + (this.fogBrightness - this.prevFogBrightness) * this.partialTicks + + const red = (fogColor.x + (skyColor.x - fogColor.x) * viewFactor) * clampedBrightness * interpolatedBrightness + const green = (fogColor.y + (skyColor.y - fogColor.y) * viewFactor) * clampedBrightness * interpolatedBrightness + const blue = (fogColor.z + (skyColor.z - fogColor.z) * viewFactor) * clampedBrightness * interpolatedBrightness + + this.scene.background = new THREE.Color(red, green, blue) + this.scene.fog = new THREE.Fog(new THREE.Color(red, green, blue), 0.0025, viewDistance * this.distanceFactor) + + ;(this.skyMesh.material as THREE.MeshBasicMaterial).color.set(new THREE.Color(skyColor.x, skyColor.y, skyColor.z)) + ;(this.voidMesh.material as THREE.MeshBasicMaterial).color.set(new THREE.Color( + skyColor.x * 0.2 + 0.04, + skyColor.y * 0.2 + 0.04, + skyColor.z * 0.6 + 0.1 + )) + } + + dispose () { + if (this.texture) { + this.texture.dispose() + } + if (this.mesh) { + this.mesh.geometry.dispose() + ;(this.mesh.material as THREE.Material).dispose() + this.scene.remove(this.mesh) + } + if (this.skyMesh) { + this.skyMesh.geometry.dispose() + ;(this.skyMesh.material as THREE.Material).dispose() + this.scene.remove(this.skyMesh) + } + if (this.voidMesh) { + this.voidMesh.geometry.dispose() + ;(this.voidMesh.material as THREE.Material).dispose() + this.scene.remove(this.voidMesh) + } + } +} diff --git a/renderer/viewer/three/threeJsMedia.ts b/renderer/viewer/three/threeJsMedia.ts new file mode 100644 index 00000000..582273d1 --- /dev/null +++ b/renderer/viewer/three/threeJsMedia.ts @@ -0,0 +1,599 @@ +import * as THREE from 'three' +import { sendVideoPlay, sendVideoStop } from '../../../src/customChannels' +import { WorldRendererThree } from './worldrendererThree' +import { ThreeJsSound } from './threeJsSound' + +interface MediaProperties { + position: { x: number, y: number, z: number } + size: { width: number, height: number } + src: string + rotation?: 0 | 1 | 2 | 3 // 0-3 for 0°, 90°, 180°, 270° + doubleSide?: boolean + background?: number // Hexadecimal color (e.g., 0x000000 for black) + opacity?: number // 0-1 value for transparency + uvMapping?: { startU: number, endU: number, startV: number, endV: number } + allowOrigins?: string[] | boolean + loop?: boolean + volume?: number + autoPlay?: boolean + + allowLighting?: boolean +} + +export class ThreeJsMedia { + customMedia = new Map void + positionalAudio?: THREE.PositionalAudio + hadAutoPlayError?: boolean + }>() + + constructor (private readonly worldRenderer: WorldRendererThree) { + this.worldRenderer.onWorldSwitched.push(() => { + this.onWorldGone() + }) + + this.worldRenderer.onRender.push(() => { + this.render() + }) + } + + onWorldGone () { + for (const [id, videoData] of this.customMedia.entries()) { + this.destroyMedia(id) + } + } + + onWorldStop () { + for (const [id, videoData] of this.customMedia.entries()) { + this.setVideoPlaying(id, false) + } + } + + private createErrorTexture (width: number, height: number, background = 0x00_00_00, error = 'Failed to load'): THREE.CanvasTexture { + const canvas = document.createElement('canvas') + const MAX_DIMENSION = 100 + + canvas.width = MAX_DIMENSION + canvas.height = MAX_DIMENSION + + const ctx = canvas.getContext('2d') + if (!ctx) return new THREE.CanvasTexture(canvas) + + // Clear with transparent background + ctx.clearRect(0, 0, canvas.width, canvas.height) + + // Add background color + ctx.fillStyle = `rgba(${background >> 16 & 255}, ${background >> 8 & 255}, ${background & 255}, 0.5)` + ctx.fillRect(0, 0, canvas.width, canvas.height) + + // Add red text with size relative to canvas dimensions + ctx.fillStyle = '#ff0000' + ctx.font = 'bold 10px sans-serif' + ctx.textAlign = 'center' + ctx.textBaseline = 'middle' + ctx.fillText(error, canvas.width / 2, canvas.height / 2, canvas.width) + + const texture = new THREE.CanvasTexture(canvas) + texture.minFilter = THREE.LinearFilter + texture.magFilter = THREE.LinearFilter + return texture + } + + private createBackgroundTexture (width: number, height: number, color = 0x00_00_00, opacity = 1): THREE.CanvasTexture { + const canvas = document.createElement('canvas') + canvas.width = 1 + canvas.height = 1 + + const ctx = canvas.getContext('2d') + if (!ctx) return new THREE.CanvasTexture(canvas) + + // Convert hex color to rgba + const r = (color >> 16) & 255 + const g = (color >> 8) & 255 + const b = color & 255 + + ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${opacity})` + ctx.fillRect(0, 0, 1, 1) + + const texture = new THREE.CanvasTexture(canvas) + texture.minFilter = THREE.NearestFilter + texture.magFilter = THREE.NearestFilter + return texture + } + + validateOrigin (src: string, allowOrigins: string[] | boolean) { + if (allowOrigins === true) return true + if (allowOrigins === false) return false + const url = new URL(src) + return allowOrigins.some(origin => url.origin.endsWith(origin)) + } + + onPageInteraction () { + for (const [id, videoData] of this.customMedia.entries()) { + if (videoData.hadAutoPlayError) { + videoData.hadAutoPlayError = false + void videoData.video?.play() + .catch(err => { + if (err.name === 'AbortError') return + console.error('Failed to play video:', err) + videoData.hadAutoPlayError = true + return true + }) + .then((fromCatch) => { + if (fromCatch) return + if (videoData.positionalAudio) { + // workaround: audio has to be recreated + this.addMedia(id, videoData.props) + } + }) + } + } + } + + addMedia (id: string, props: MediaProperties) { + const originalProps = structuredClone(props) + this.destroyMedia(id) + + const { scene } = this.worldRenderer + + const originSecurityError = props.allowOrigins !== undefined && !this.validateOrigin(props.src, props.allowOrigins) + if (originSecurityError) { + console.warn('Remote resource blocked due to security policy', props.src, 'allowed origins:', props.allowOrigins, 'you can control it with `remoteContentNotSameOrigin` option') + props.src = '' + } + + const isImage = props.src.endsWith('.png') || props.src.endsWith('.jpg') || props.src.endsWith('.jpeg') + + let video: HTMLVideoElement | undefined + let positionalAudio: THREE.PositionalAudio | undefined + if (!isImage) { + video = document.createElement('video') + video.src = props.src.endsWith('.gif') ? props.src.replace('.gif', '.mp4') : props.src + video.loop = props.loop ?? true + video.volume = props.volume ?? 1 + video.playsInline = true + video.crossOrigin = 'anonymous' + + // Create positional audio + const soundSystem = this.worldRenderer.soundSystem as ThreeJsSound + soundSystem.initAudioListener() + if (!soundSystem.audioListener) throw new Error('Audio listener not initialized') + positionalAudio = new THREE.PositionalAudio(soundSystem.audioListener) + positionalAudio.setRefDistance(6) + positionalAudio.setVolume(props.volume ?? 1) + scene.add(positionalAudio) + positionalAudio.position.set(props.position.x, props.position.y, props.position.z) + + // Connect video to positional audio + positionalAudio.setMediaElementSource(video) + positionalAudio.connect() + + video.addEventListener('pause', () => { + positionalAudio?.pause() + sendVideoStop(id, 'paused', video!.currentTime) + }) + video.addEventListener('play', () => { + positionalAudio?.play() + sendVideoPlay(id) + }) + video.addEventListener('seeked', () => { + if (positionalAudio && video) { + positionalAudio.offset = video.currentTime + } + }) + video.addEventListener('stalled', () => { + sendVideoStop(id, 'stalled', video!.currentTime) + }) + video.addEventListener('waiting', () => { + sendVideoStop(id, 'waiting', video!.currentTime) + }) + video.addEventListener('error', ({ error }) => { + sendVideoStop(id, `error: ${error}`, video!.currentTime) + }) + video.addEventListener('ended', () => { + sendVideoStop(id, 'ended', video!.currentTime) + }) + } + + + // Create background texture first + const backgroundTexture = this.createBackgroundTexture( + props.size.width, + props.size.height, + props.background, + // props.opacity ?? 1 + ) + + const handleError = (text?: string) => { + const errorTexture = this.createErrorTexture(props.size.width, props.size.height, props.background, text) + material.map = errorTexture + material.needsUpdate = true + } + + // Create a plane geometry with configurable UV mapping + const geometry = new THREE.PlaneGeometry(1, 1) + + // Create material with initial properties using background texture + const MaterialClass = props.allowLighting ? THREE.MeshLambertMaterial : THREE.MeshBasicMaterial + const material = new MaterialClass({ + map: backgroundTexture, + transparent: true, + side: props.doubleSide ? THREE.DoubleSide : THREE.FrontSide, + alphaTest: 0.1 + }) + + const texture = video + ? new THREE.VideoTexture(video) + : new THREE.TextureLoader().load(props.src, () => { + if (this.customMedia.get(id)?.texture === texture) { + material.map = texture + material.needsUpdate = true + } + }, undefined, () => handleError()) // todo cache + texture.minFilter = THREE.NearestFilter + texture.magFilter = THREE.NearestFilter + // texture.format = THREE.RGBAFormat + // texture.colorSpace = THREE.SRGBColorSpace + texture.generateMipmaps = false + + // Create inner mesh for offsets + const mesh = new THREE.Mesh(geometry, material) + + const { mesh: panel } = this.positionMeshExact(mesh, THREE.MathUtils.degToRad((props.rotation ?? 0) * 90), props.position, props.size.width, props.size.height) + + scene.add(panel) + + if (video) { + // Start playing the video + video.play().catch(err => { + if (err.name === 'AbortError') return + console.error('Failed to play video:', err) + videoData.hadAutoPlayError = true + handleError(err.name === 'NotAllowedError' ? 'Waiting for user interaction' : 'Failed to auto play') + }) + + // Update texture in animation loop + mesh.onBeforeRender = () => { + if (video.readyState === video.HAVE_ENOUGH_DATA && (!video.paused || !videoData?.hadAutoPlayError)) { + if (material.map !== texture) { + material.map = texture + material.needsUpdate = true + } + texture.needsUpdate = true + + // Sync audio position with video position + if (positionalAudio) { + positionalAudio.position.copy(panel.position) + positionalAudio.rotation.copy(panel.rotation) + } + } + } + } + + // UV mapping configuration + const updateUVMapping = (config: { startU: number, endU: number, startV: number, endV: number }) => { + const uvs = geometry.attributes.uv.array as Float32Array + uvs[0] = config.startU + uvs[1] = config.startV + uvs[2] = config.endU + uvs[3] = config.startV + uvs[4] = config.endU + uvs[5] = config.endV + uvs[6] = config.startU + uvs[7] = config.endV + geometry.attributes.uv.needsUpdate = true + } + + // Apply initial UV mapping if provided + if (props.uvMapping) { + updateUVMapping(props.uvMapping) + } + + const videoData = { + mesh: panel, + video, + texture, + updateUVMapping, + positionalAudio, + props: originalProps, + hadAutoPlayError: false + } + // Store video data + this.customMedia.set(id, videoData) + + return id + } + + render () { + for (const [id, videoData] of this.customMedia.entries()) { + const chunkX = Math.floor(videoData.props.position.x / 16) * 16 + const chunkZ = Math.floor(videoData.props.position.z / 16) * 16 + const sectionY = Math.floor(videoData.props.position.y / 16) * 16 + + const chunkKey = `${chunkX},${chunkZ}` + const sectionKey = `${chunkX},${sectionY},${chunkZ}` + videoData.mesh.visible = !!this.worldRenderer.sectionObjects[sectionKey] || !!this.worldRenderer.finishedChunks[chunkKey] + } + } + + setVideoPlaying (id: string, playing: boolean) { + const videoData = this.customMedia.get(id) + if (videoData?.video) { + if (playing) { + videoData.video.play().catch(console.error) + } else { + videoData.video.pause() + } + } + } + + setVideoSeeking (id: string, seconds: number) { + const videoData = this.customMedia.get(id) + if (videoData?.video) { + videoData.video.currentTime = seconds + } + } + + setVideoVolume (id: string, volume: number) { + const videoData = this.customMedia.get(id) + if (videoData?.video) { + videoData.video.volume = volume + } + } + + setVideoSpeed (id: string, speed: number) { + const videoData = this.customMedia.get(id) + if (videoData?.video) { + videoData.video.playbackRate = speed + } + } + + destroyMedia (id: string) { + const { scene } = this.worldRenderer + const mediaData = this.customMedia.get(id) + if (mediaData) { + if (mediaData.video) { + mediaData.video.pause() + mediaData.video.src = '' + mediaData.video.remove() + } + if (mediaData.positionalAudio) { + // mediaData.positionalAudio.stop() + // mediaData.positionalAudio.disconnect() + scene.remove(mediaData.positionalAudio) + } + scene.remove(mediaData.mesh) + mediaData.texture.dispose() + + // Get the inner mesh from the group + const mesh = mediaData.mesh.children[0] as THREE.Mesh + if (mesh) { + mesh.geometry.dispose() + if (mesh.material instanceof THREE.Material) { + mesh.material.dispose() + } + } + + this.customMedia.delete(id) + } + } + + /** + * Positions a mesh exactly at startPosition and extends it along the rotation direction + * with the specified width and height + * + * @param mesh The mesh to position + * @param rotation Rotation in radians (applied to Y axis) + * @param startPosition The exact starting position (corner) of the mesh + * @param width Width of the mesh + * @param height Height of the mesh + * @param depth Depth of the mesh (default: 1) + * @returns The positioned mesh for chaining + */ + positionMeshExact ( + mesh: THREE.Mesh, + rotation: number, + startPosition: { x: number, y: number, z: number }, + width: number, + height: number, + depth = 1 + ) { + // avoid z-fighting with the ground plane + if (rotation === 0) { + startPosition.z += 0.001 + } + if (rotation === Math.PI / 2) { + startPosition.x -= 0.001 + } + if (rotation === Math.PI) { + startPosition.z -= 0.001 + } + if (rotation === 3 * Math.PI / 2) { + startPosition.x += 0.001 + } + + // rotation normalize coordinates + if (rotation === 0) { + startPosition.z += 1 + } + if (rotation === Math.PI) { + startPosition.x += 1 + } + if (rotation === 3 * Math.PI / 2) { + startPosition.z += 1 + startPosition.x += 1 + } + + + // First, clean up any previous transformations + mesh.matrix.identity() + mesh.position.set(0, 0, 0) + mesh.rotation.set(0, 0, 0) + mesh.scale.set(1, 1, 1) + + // By default, PlaneGeometry creates a plane in the XY plane (facing +Z) + // We need to set up the proper orientation for our use case + // Rotate the plane to face the correct direction based on the rotation parameter + mesh.rotateY(rotation) + if (rotation === Math.PI / 2 || rotation === 3 * Math.PI / 2) { + mesh.rotateZ(-Math.PI) + mesh.rotateX(-Math.PI) + } + + // Scale it to the desired size + mesh.scale.set(width, height, depth) + + // For a PlaneGeometry, if we want the corner at the origin, we need to offset + // by half the dimensions after scaling + mesh.geometry.translate(0.5, 0.5, 0) + mesh.geometry.attributes.position.needsUpdate = true + + // Now place the mesh at the start position + mesh.position.set(startPosition.x, startPosition.y, startPosition.z) + + // Create a group to hold our mesh and markers + const debugGroup = new THREE.Group() + debugGroup.add(mesh) + + // Add a marker at the starting position (should be exactly at pos) + const startMarker = new THREE.Mesh( + new THREE.BoxGeometry(0.1, 0.1, 0.1), + new THREE.MeshBasicMaterial({ color: 0xff_00_00 }) + ) + startMarker.position.copy(new THREE.Vector3(startPosition.x, startPosition.y, startPosition.z)) + debugGroup.add(startMarker) + + // Add a marker at the end position (width units away in the rotated direction) + const endX = startPosition.x + Math.cos(rotation) * width + const endZ = startPosition.z + Math.sin(rotation) * width + const endYMarker = new THREE.Mesh( + new THREE.BoxGeometry(0.1, 0.1, 0.1), + new THREE.MeshBasicMaterial({ color: 0x00_00_ff }) + ) + endYMarker.position.set(startPosition.x, startPosition.y + height, startPosition.z) + debugGroup.add(endYMarker) + + // Add a marker at the width endpoint + const endWidthMarker = new THREE.Mesh( + new THREE.BoxGeometry(0.1, 0.1, 0.1), + new THREE.MeshBasicMaterial({ color: 0xff_ff_00 }) + ) + endWidthMarker.position.set(endX, startPosition.y, endZ) + debugGroup.add(endWidthMarker) + + // Add a marker at the corner diagonal endpoint (both width and height) + const endCornerMarker = new THREE.Mesh( + new THREE.BoxGeometry(0.1, 0.1, 0.1), + new THREE.MeshBasicMaterial({ color: 0xff_00_ff }) + ) + endCornerMarker.position.set(endX, startPosition.y + height, endZ) + debugGroup.add(endCornerMarker) + + // Also add a visual helper to show the rotation direction + const directionHelper = new THREE.ArrowHelper( + new THREE.Vector3(Math.cos(rotation), 0, Math.sin(rotation)), + new THREE.Vector3(startPosition.x, startPosition.y, startPosition.z), + 1, + 0xff_00_00 + ) + debugGroup.add(directionHelper) + + return { + mesh, + debugGroup + } + } + + createTestCanvasTexture () { + const canvas = document.createElement('canvas') + canvas.width = 100 + canvas.height = 100 + const ctx = canvas.getContext('2d') + if (!ctx) return null + ctx.font = '10px Arial' + ctx.fillStyle = 'red' + ctx.fillText('Hello World', 0, 10) // at + return new THREE.CanvasTexture(canvas) + } + + /** + * Creates a test mesh that demonstrates the exact positioning + */ + addTestMeshExact (rotationNum: number) { + const pos = window.cursorBlockRel().position + console.log('Creating exact positioned test mesh at:', pos) + + // Create a plane mesh with a wireframe to visualize boundaries + const plane = new THREE.Mesh( + new THREE.PlaneGeometry(1, 1), + new THREE.MeshBasicMaterial({ + // side: THREE.DoubleSide, + map: this.createTestCanvasTexture() + }) + ) + + const width = 2 + const height = 1 + const rotation = THREE.MathUtils.degToRad(rotationNum * 90) // 90 degrees in radians + + // Position the mesh exactly where we want it + const { debugGroup } = this.positionMeshExact(plane, rotation, pos, width, height) + + this.worldRenderer.scene.add(debugGroup) + console.log('Exact test mesh added with dimensions:', width, height, 'and rotation:', rotation) + } + + lastCheck = 0 + THROTTLE_TIME = 100 + tryIntersectMedia () { + // hack: need to optimize this by pulling only in distance of interaction instead and throttle + if (this.customMedia.size === 0) return + if (Date.now() - this.lastCheck < this.THROTTLE_TIME) return + this.lastCheck = Date.now() + + const { camera, scene } = this.worldRenderer + const raycaster = new THREE.Raycaster() + + // Get mouse position at center of screen + const mouse = new THREE.Vector2(0, 0) + + // Update the raycaster + raycaster.setFromCamera(mouse, camera) + + // Check intersection with all objects in scene + const intersects = raycaster.intersectObjects(scene.children, true) + if (intersects.length > 0) { + const intersection = intersects[0] + const intersectedObject = intersection.object + + // Find if this object belongs to any media + for (const [id, videoData] of this.customMedia.entries()) { + // Check if the intersected object is part of our media mesh + if (intersectedObject === videoData.mesh || + videoData.mesh.children.includes(intersectedObject)) { + const { uv } = intersection + if (uv) { + const result = { + id, + x: uv.x, + y: uv.y + } + this.worldRenderer.reactiveState.world.intersectMedia = result + this.worldRenderer['debugVideo'] = videoData + this.worldRenderer.cursorBlock.cursorLinesHidden = true + return + } + } + } + } + + // No media intersection found + this.worldRenderer.reactiveState.world.intersectMedia = null + this.worldRenderer['debugVideo'] = null + this.worldRenderer.cursorBlock.cursorLinesHidden = false + } +} diff --git a/renderer/viewer/three/threeJsParticles.ts b/renderer/viewer/three/threeJsParticles.ts new file mode 100644 index 00000000..993f2b62 --- /dev/null +++ b/renderer/viewer/three/threeJsParticles.ts @@ -0,0 +1,160 @@ +import * as THREE from 'three' + +interface ParticleMesh extends THREE.Mesh { + velocity: THREE.Vector3; +} + +interface ParticleConfig { + fountainHeight: number; + resetHeight: number; + xVelocityRange: number; + zVelocityRange: number; + particleCount: number; + particleRadiusRange: { min: number; max: number }; + yVelocityRange: { min: number; max: number }; +} + +export interface FountainOptions { + position?: { x: number, y: number, z: number } + particleConfig?: Partial; +} + +export class Fountain { + private readonly particles: ParticleMesh[] = [] + private readonly config: { particleConfig: ParticleConfig } + private readonly position: THREE.Vector3 + container: THREE.Object3D | undefined + + constructor (public sectionId: string, options: FountainOptions = {}) { + this.position = options.position ? new THREE.Vector3(options.position.x, options.position.y, options.position.z) : new THREE.Vector3(0, 0, 0) + this.config = this.createConfig(options.particleConfig) + } + + private createConfig ( + particleConfigOverride?: Partial + ): { particleConfig: ParticleConfig } { + const particleConfig: ParticleConfig = { + fountainHeight: 10, + resetHeight: 0, + xVelocityRange: 0.4, + zVelocityRange: 0.4, + particleCount: 400, + particleRadiusRange: { min: 0.1, max: 0.6 }, + yVelocityRange: { min: 0.1, max: 2 }, + ...particleConfigOverride + } + + return { particleConfig } + } + + + createParticles (container: THREE.Object3D): void { + this.container = container + const colorStart = new THREE.Color(0xff_ff_00) + const colorEnd = new THREE.Color(0xff_a5_00) + + for (let i = 0; i < this.config.particleConfig.particleCount; i++) { + const radius = Math.random() * + (this.config.particleConfig.particleRadiusRange.max - this.config.particleConfig.particleRadiusRange.min) + + this.config.particleConfig.particleRadiusRange.min + const geometry = new THREE.SphereGeometry(radius) + const material = new THREE.MeshBasicMaterial({ + color: colorStart.clone().lerp(colorEnd, Math.random()) + }) + const mesh = new THREE.Mesh(geometry, material) + const particle = mesh as unknown as ParticleMesh + + particle.position.set( + this.position.x + (Math.random() - 0.5) * this.config.particleConfig.xVelocityRange * 2, + this.position.y + this.config.particleConfig.fountainHeight, + this.position.z + (Math.random() - 0.5) * this.config.particleConfig.zVelocityRange * 2 + ) + + particle.velocity = new THREE.Vector3( + (Math.random() - 0.5) * this.config.particleConfig.xVelocityRange, + -Math.random() * this.config.particleConfig.yVelocityRange.max, + (Math.random() - 0.5) * this.config.particleConfig.zVelocityRange + ) + + this.particles.push(particle) + this.container.add(particle) + + // this.container.onBeforeRender = () => { + // this.render() + // } + } + } + + render (): void { + for (const particle of this.particles) { + particle.velocity.y -= 0.01 + Math.random() * 0.1 + particle.position.add(particle.velocity) + + if (particle.position.y < this.position.y + this.config.particleConfig.resetHeight) { + particle.position.set( + this.position.x + (Math.random() - 0.5) * this.config.particleConfig.xVelocityRange * 2, + this.position.y + this.config.particleConfig.fountainHeight, + this.position.z + (Math.random() - 0.5) * this.config.particleConfig.zVelocityRange * 2 + ) + particle.velocity.set( + (Math.random() - 0.5) * this.config.particleConfig.xVelocityRange, + -Math.random() * this.config.particleConfig.yVelocityRange.max, + (Math.random() - 0.5) * this.config.particleConfig.zVelocityRange + ) + } + } + } + + private updateParticleCount (newCount: number): void { + if (newCount !== this.config.particleConfig.particleCount) { + this.config.particleConfig.particleCount = newCount + const currentCount = this.particles.length + + if (newCount > currentCount) { + this.addParticles(newCount - currentCount) + } else if (newCount < currentCount) { + this.removeParticles(currentCount - newCount) + } + } + } + + private addParticles (count: number): void { + const geometry = new THREE.SphereGeometry(0.1) + const material = new THREE.MeshBasicMaterial({ color: 0x00_ff_00 }) + + for (let i = 0; i < count; i++) { + const mesh = new THREE.Mesh(geometry, material) + const particle = mesh as unknown as ParticleMesh + particle.position.copy(this.position) + particle.velocity = new THREE.Vector3( + Math.random() * this.config.particleConfig.xVelocityRange - + this.config.particleConfig.xVelocityRange / 2, + Math.random() * 2, + Math.random() * this.config.particleConfig.zVelocityRange - + this.config.particleConfig.zVelocityRange / 2 + ) + this.particles.push(particle) + this.container!.add(particle) + } + } + + private removeParticles (count: number): void { + for (let i = 0; i < count; i++) { + const particle = this.particles.pop() + if (particle) { + this.container!.remove(particle) + } + } + } + + public dispose (): void { + for (const particle of this.particles) { + particle.geometry.dispose() + if (Array.isArray(particle.material)) { + for (const material of particle.material) material.dispose() + } else { + particle.material.dispose() + } + } + } +} diff --git a/renderer/viewer/three/threeJsSound.ts b/renderer/viewer/three/threeJsSound.ts index 64105423..699bb2cc 100644 --- a/renderer/viewer/three/threeJsSound.ts +++ b/renderer/viewer/three/threeJsSound.ts @@ -1,61 +1,99 @@ -import { Vec3 } from 'vec3' import * as THREE from 'three' import { WorldRendererThree } from './worldrendererThree' export interface SoundSystem { - playSound: (position: Vec3, path: string, volume?: number, pitch?: number) => void + playSound: (position: { x: number, y: number, z: number }, path: string, volume?: number, pitch?: number, timeout?: number) => void destroy: () => void } export class ThreeJsSound implements SoundSystem { audioListener: THREE.AudioListener | undefined private readonly activeSounds = new Set() + private readonly audioContext: AudioContext | undefined + private readonly soundVolumes = new Map() + baseVolume = 1 constructor (public worldRenderer: WorldRendererThree) { + worldRenderer.onWorldSwitched.push(() => { + this.stopAll() + }) + + worldRenderer.onReactiveConfigUpdated('volume', (volume) => { + this.changeVolume(volume) + }) } - playSound (position: Vec3, path: string, volume = 1, pitch = 1) { - if (!this.audioListener) { - this.audioListener = new THREE.AudioListener() - this.worldRenderer.camera.add(this.audioListener) - } + initAudioListener () { + if (this.audioListener) return + this.audioListener = new THREE.AudioListener() + this.worldRenderer.camera.add(this.audioListener) + } - const sound = new THREE.PositionalAudio(this.audioListener) + playSound (position: { x: number, y: number, z: number }, path: string, volume = 1, pitch = 1, timeout = 500) { + this.initAudioListener() + + const sound = new THREE.PositionalAudio(this.audioListener!) this.activeSounds.add(sound) + this.soundVolumes.set(sound, volume) const audioLoader = new THREE.AudioLoader() const start = Date.now() void audioLoader.loadAsync(path).then((buffer) => { - if (Date.now() - start > 500) return + if (Date.now() - start > timeout) { + console.warn('Ignored playing sound', path, 'due to timeout:', timeout, 'ms <', Date.now() - start, 'ms') + return + } // play sound.setBuffer(buffer) sound.setRefDistance(20) - sound.setVolume(volume) + sound.setVolume(volume * this.baseVolume) sound.setPlaybackRate(pitch) // set the pitch this.worldRenderer.scene.add(sound) // set sound position sound.position.set(position.x, position.y, position.z) sound.onEnded = () => { this.worldRenderer.scene.remove(sound) - sound.disconnect() + if (sound.source) { + sound.disconnect() + } this.activeSounds.delete(sound) + this.soundVolumes.delete(sound) audioLoader.manager.itemEnd(path) } sound.play() }) } - destroy () { - // Stop and clean up all active sounds + stopAll () { for (const sound of this.activeSounds) { + if (!sound) continue sound.stop() - sound.disconnect() + if (sound.source) { + sound.disconnect() + } + this.worldRenderer.scene.remove(sound) } + this.activeSounds.clear() + this.soundVolumes.clear() + } + changeVolume (volume: number) { + this.baseVolume = volume + for (const [sound, individualVolume] of this.soundVolumes) { + sound.setVolume(individualVolume * this.baseVolume) + } + } + + destroy () { + this.stopAll() // Remove and cleanup audio listener if (this.audioListener) { this.audioListener.removeFromParent() this.audioListener = undefined } } + + playTestSound () { + this.playSound(this.worldRenderer.camera.position, '/sound.mp3') + } } diff --git a/renderer/viewer/three/threeJsUtils.ts b/renderer/viewer/three/threeJsUtils.ts index 5ae3b24f..cbef9065 100644 --- a/renderer/viewer/three/threeJsUtils.ts +++ b/renderer/viewer/three/threeJsUtils.ts @@ -1,4 +1,6 @@ import * as THREE from 'three' +import { getLoadedImage } from 'mc-assets/dist/utils' +import { createCanvas } from '../lib/utils' export const disposeObject = (obj: THREE.Object3D, cleanTextures = false) => { // not cleaning texture there as it might be used by other objects, but would be good to also do that @@ -16,3 +18,56 @@ export const disposeObject = (obj: THREE.Object3D, cleanTextures = false) => { } } } + +let textureCache: Record = {} +let imagesPromises: Record> = {} + +export const loadThreeJsTextureFromUrlSync = (imageUrl: string) => { + const texture = new THREE.Texture() + const promise = getLoadedImage(imageUrl).then(image => { + texture.image = image + texture.needsUpdate = true + return texture + }) + return { + texture, + promise + } +} + +export const loadThreeJsTextureFromUrl = async (imageUrl: string) => { + const loaded = new THREE.TextureLoader().loadAsync(imageUrl) + return loaded +} + +export const loadThreeJsTextureFromBitmap = (image: ImageBitmap) => { + const canvas = createCanvas(image.width, image.height) + const ctx = canvas.getContext('2d')! + ctx.drawImage(image, 0, 0) + const texture = new THREE.Texture(canvas) + texture.magFilter = THREE.NearestFilter + texture.minFilter = THREE.NearestFilter + return texture +} + +export async function loadTexture (texture: string, cb: (texture: THREE.Texture) => void, onLoad?: () => void): Promise { + const cached = textureCache[texture] + if (!cached) { + const { promise, resolve } = Promise.withResolvers() + const t = loadThreeJsTextureFromUrlSync(texture) + textureCache[texture] = t.texture + void t.promise.then(resolve) + imagesPromises[texture] = promise + } + + cb(textureCache[texture]) + void imagesPromises[texture].then(() => { + onLoad?.() + }) +} + +export const clearTextureCache = () => { + textureCache = {} + imagesPromises = {} +} + diff --git a/renderer/viewer/three/waypointSprite.ts b/renderer/viewer/three/waypointSprite.ts new file mode 100644 index 00000000..6a30e6db --- /dev/null +++ b/renderer/viewer/three/waypointSprite.ts @@ -0,0 +1,418 @@ +import * as THREE from 'three' + +// Centralized visual configuration (in screen pixels) +export const WAYPOINT_CONFIG = { + // Target size in screen pixels (this controls the final sprite size) + TARGET_SCREEN_PX: 150, + // Canvas size for internal rendering (keep power of 2 for textures) + CANVAS_SIZE: 256, + // Relative positions in canvas (0-1) + LAYOUT: { + DOT_Y: 0.3, + NAME_Y: 0.45, + DISTANCE_Y: 0.55, + }, + // Multiplier for canvas internal resolution to keep text crisp + CANVAS_SCALE: 2, + ARROW: { + enabledDefault: false, + pixelSize: 50, + paddingPx: 50, + }, +} + +export type WaypointSprite = { + group: THREE.Group + sprite: THREE.Sprite + // Offscreen arrow controls + enableOffscreenArrow: (enabled: boolean) => void + setArrowParent: (parent: THREE.Object3D | null) => void + // Convenience combined updater + updateForCamera: ( + cameraPosition: THREE.Vector3, + camera: THREE.PerspectiveCamera, + viewportWidthPx: number, + viewportHeightPx: number + ) => boolean + // Utilities + setColor: (color: number) => void + setLabel: (label?: string) => void + updateDistanceText: (label: string, distanceText: string) => void + setVisible: (visible: boolean) => void + setPosition: (x: number, y: number, z: number) => void + dispose: () => void +} + +export function createWaypointSprite (options: { + position: THREE.Vector3 | { x: number, y: number, z: number }, + color?: number, + label?: string, + depthTest?: boolean, + // Y offset in world units used by updateScaleWorld only (screen-pixel API ignores this) + labelYOffset?: number, + metadata?: any, +}): WaypointSprite { + const color = options.color ?? 0xFF_00_00 + const depthTest = options.depthTest ?? false + const labelYOffset = options.labelYOffset ?? 1.5 + + // Build combined sprite + const sprite = createCombinedSprite(color, options.label ?? '', '0m', depthTest) + sprite.renderOrder = 10 + let currentLabel = options.label ?? '' + + // Offscreen arrow (detached by default) + let arrowSprite: THREE.Sprite | undefined + let arrowParent: THREE.Object3D | null = null + let arrowEnabled = WAYPOINT_CONFIG.ARROW.enabledDefault + + // Group for easy add/remove + const group = new THREE.Group() + group.add(sprite) + + // Initial position + const { x, y, z } = options.position + group.position.set(x, y, z) + + function setColor (newColor: number) { + const canvas = drawCombinedCanvas(newColor, currentLabel, '0m') + const texture = new THREE.CanvasTexture(canvas) + const mat = sprite.material + mat.map?.dispose() + mat.map = texture + mat.needsUpdate = true + } + + function setLabel (newLabel?: string) { + currentLabel = newLabel ?? '' + const canvas = drawCombinedCanvas(color, currentLabel, '0m') + const texture = new THREE.CanvasTexture(canvas) + const mat = sprite.material + mat.map?.dispose() + mat.map = texture + mat.needsUpdate = true + } + + function updateDistanceText (label: string, distanceText: string) { + const canvas = drawCombinedCanvas(color, label, distanceText) + const texture = new THREE.CanvasTexture(canvas) + const mat = sprite.material + mat.map?.dispose() + mat.map = texture + mat.needsUpdate = true + } + + function setVisible (visible: boolean) { + sprite.visible = visible + } + + function setPosition (nx: number, ny: number, nz: number) { + group.position.set(nx, ny, nz) + } + + // Keep constant pixel size on screen using global config + function updateScaleScreenPixels ( + cameraPosition: THREE.Vector3, + cameraFov: number, + distance: number, + viewportHeightPx: number + ) { + const vFovRad = cameraFov * Math.PI / 180 + const worldUnitsPerScreenHeightAtDist = Math.tan(vFovRad / 2) * 2 * distance + // Use configured target screen size + const scale = worldUnitsPerScreenHeightAtDist * (WAYPOINT_CONFIG.TARGET_SCREEN_PX / viewportHeightPx) + sprite.scale.set(scale, scale, 1) + } + + function ensureArrow () { + if (arrowSprite) return + const size = 128 + const canvas = document.createElement('canvas') + canvas.width = size + canvas.height = size + const ctx = canvas.getContext('2d')! + ctx.clearRect(0, 0, size, size) + + // Draw arrow shape + ctx.beginPath() + ctx.moveTo(size * 0.15, size * 0.5) + ctx.lineTo(size * 0.85, size * 0.5) + ctx.lineTo(size * 0.5, size * 0.15) + ctx.closePath() + + // Use waypoint color for arrow + const colorHex = `#${color.toString(16).padStart(6, '0')}` + ctx.lineWidth = 6 + ctx.strokeStyle = 'black' + ctx.stroke() + ctx.fillStyle = colorHex + ctx.fill() + + const texture = new THREE.CanvasTexture(canvas) + const material = new THREE.SpriteMaterial({ map: texture, transparent: true, depthTest: false, depthWrite: false }) + arrowSprite = new THREE.Sprite(material) + arrowSprite.renderOrder = 12 + arrowSprite.visible = false + if (arrowParent) arrowParent.add(arrowSprite) + } + + function enableOffscreenArrow (enabled: boolean) { + arrowEnabled = enabled + if (!enabled && arrowSprite) arrowSprite.visible = false + } + + function setArrowParent (parent: THREE.Object3D | null) { + if (arrowSprite?.parent) arrowSprite.parent.remove(arrowSprite) + arrowParent = parent + if (arrowSprite && parent) parent.add(arrowSprite) + } + + function updateOffscreenArrow ( + camera: THREE.PerspectiveCamera, + viewportWidthPx: number, + viewportHeightPx: number + ): boolean { + if (!arrowEnabled) return true + ensureArrow() + if (!arrowSprite) return true + + // Check if onlyLeftRight is enabled in metadata + const onlyLeftRight = options.metadata?.onlyLeftRight === true + + // Build camera basis using camera.up to respect custom orientations + const forward = new THREE.Vector3() + camera.getWorldDirection(forward) // camera look direction + const upWorld = camera.up.clone().normalize() + const right = new THREE.Vector3().copy(forward).cross(upWorld).normalize() + const upCam = new THREE.Vector3().copy(right).cross(forward).normalize() + + // Vector from camera to waypoint + const camPos = new THREE.Vector3().setFromMatrixPosition(camera.matrixWorld) + const toWp = new THREE.Vector3(group.position.x, group.position.y, group.position.z).sub(camPos) + + // Components in camera basis + const z = toWp.dot(forward) + const x = toWp.dot(right) + const y = toWp.dot(upCam) + + const aspect = viewportWidthPx / viewportHeightPx + const vFovRad = camera.fov * Math.PI / 180 + const hFovRad = 2 * Math.atan(Math.tan(vFovRad / 2) * aspect) + + // Determine if waypoint is inside view frustum using angular checks + const thetaX = Math.atan2(x, z) + const thetaY = Math.atan2(y, z) + const visible = z > 0 && Math.abs(thetaX) <= hFovRad / 2 && Math.abs(thetaY) <= vFovRad / 2 + if (visible) { + arrowSprite.visible = false + return true + } + + // Direction on screen in normalized frustum units + let rx = thetaX / (hFovRad / 2) + let ry = thetaY / (vFovRad / 2) + + // If behind the camera, snap to dominant axis to avoid confusing directions + if (z <= 0) { + if (Math.abs(rx) > Math.abs(ry)) { + rx = Math.sign(rx) + ry = 0 + } else { + rx = 0 + ry = Math.sign(ry) + } + } + + // Apply onlyLeftRight logic - restrict arrows to left/right edges only + if (onlyLeftRight) { + // Force the arrow to appear only on left or right edges + if (Math.abs(rx) > Math.abs(ry)) { + // Horizontal direction is dominant, keep it + ry = 0 + } else { + // Vertical direction is dominant, but we want only left/right + // So choose left or right based on the sign of rx + rx = rx >= 0 ? 1 : -1 + ry = 0 + } + } + + // Place on the rectangle border [-1,1]x[-1,1] + const s = Math.max(Math.abs(rx), Math.abs(ry)) || 1 + let ndcX = rx / s + let ndcY = ry / s + + // Apply padding in pixel space by clamping + const padding = WAYPOINT_CONFIG.ARROW.paddingPx + const pxX = ((ndcX + 1) * 0.5) * viewportWidthPx + const pxY = ((1 - ndcY) * 0.5) * viewportHeightPx + const clampedPxX = Math.min(Math.max(pxX, padding), viewportWidthPx - padding) + const clampedPxY = Math.min(Math.max(pxY, padding), viewportHeightPx - padding) + ndcX = (clampedPxX / viewportWidthPx) * 2 - 1 + ndcY = -(clampedPxY / viewportHeightPx) * 2 + 1 + + // Compute world position at a fixed distance in front of the camera using camera basis + const placeDist = Math.max(2, camera.near * 4) + const halfPlaneHeight = Math.tan(vFovRad / 2) * placeDist + const halfPlaneWidth = halfPlaneHeight * aspect + const pos = camPos.clone() + .add(forward.clone().multiplyScalar(placeDist)) + .add(right.clone().multiplyScalar(ndcX * halfPlaneWidth)) + .add(upCam.clone().multiplyScalar(ndcY * halfPlaneHeight)) + + // Update arrow sprite + arrowSprite.visible = true + arrowSprite.position.copy(pos) + + // Angle for rotation relative to screen right/up (derived from camera up vector) + const angle = Math.atan2(ry, rx) + arrowSprite.material.rotation = angle - Math.PI / 2 + + // Constant pixel size for arrow (use fixed placement distance) + const worldUnitsPerScreenHeightAtDist = Math.tan(vFovRad / 2) * 2 * placeDist + const sPx = worldUnitsPerScreenHeightAtDist * (WAYPOINT_CONFIG.ARROW.pixelSize / viewportHeightPx) + arrowSprite.scale.set(sPx, sPx, 1) + return false + } + + function computeDistance (cameraPosition: THREE.Vector3): number { + return cameraPosition.distanceTo(group.position) + } + + function updateForCamera ( + cameraPosition: THREE.Vector3, + camera: THREE.PerspectiveCamera, + viewportWidthPx: number, + viewportHeightPx: number + ): boolean { + const distance = computeDistance(cameraPosition) + // Keep constant pixel size + updateScaleScreenPixels(cameraPosition, camera.fov, distance, viewportHeightPx) + // Update text + updateDistanceText(currentLabel, `${Math.round(distance)}m`) + // Update arrow and visibility + const onScreen = updateOffscreenArrow(camera, viewportWidthPx, viewportHeightPx) + setVisible(onScreen) + return onScreen + } + + function dispose () { + const mat = sprite.material + mat.map?.dispose() + mat.dispose() + if (arrowSprite) { + const am = arrowSprite.material + am.map?.dispose() + am.dispose() + } + } + + return { + group, + sprite, + enableOffscreenArrow, + setArrowParent, + updateForCamera, + setColor, + setLabel, + updateDistanceText, + setVisible, + setPosition, + dispose, + } +} + +// Internal helpers +function drawCombinedCanvas (color: number, id: string, distance: string): HTMLCanvasElement { + const scale = WAYPOINT_CONFIG.CANVAS_SCALE * (globalThis.devicePixelRatio || 1) + const size = WAYPOINT_CONFIG.CANVAS_SIZE * scale + const canvas = document.createElement('canvas') + canvas.width = size + canvas.height = size + const ctx = canvas.getContext('2d')! + + // Clear canvas + ctx.clearRect(0, 0, size, size) + + // Draw dot + const centerX = size / 2 + const dotY = Math.round(size * WAYPOINT_CONFIG.LAYOUT.DOT_Y) + const radius = Math.round(size * 0.05) // Dot takes up ~12% of canvas height + const borderWidth = Math.max(2, Math.round(4 * scale)) + + // Outer border (black) + ctx.beginPath() + ctx.arc(centerX, dotY, radius + borderWidth, 0, Math.PI * 2) + ctx.fillStyle = 'black' + ctx.fill() + + // Inner circle (colored) + ctx.beginPath() + ctx.arc(centerX, dotY, radius, 0, Math.PI * 2) + ctx.fillStyle = `#${color.toString(16).padStart(6, '0')}` + ctx.fill() + + // Text properties + ctx.textAlign = 'center' + ctx.textBaseline = 'middle' + + // Title + const nameFontPx = Math.round(size * 0.08) // ~8% of canvas height + const distanceFontPx = Math.round(size * 0.06) // ~6% of canvas height + ctx.font = `bold ${nameFontPx}px mojangles` + ctx.lineWidth = Math.max(2, Math.round(3 * scale)) + const nameY = Math.round(size * WAYPOINT_CONFIG.LAYOUT.NAME_Y) + + ctx.strokeStyle = 'black' + ctx.strokeText(id, centerX, nameY) + ctx.fillStyle = 'white' + ctx.fillText(id, centerX, nameY) + + // Distance + ctx.font = `bold ${distanceFontPx}px mojangles` + ctx.lineWidth = Math.max(2, Math.round(2 * scale)) + const distanceY = Math.round(size * WAYPOINT_CONFIG.LAYOUT.DISTANCE_Y) + + ctx.strokeStyle = 'black' + ctx.strokeText(distance, centerX, distanceY) + ctx.fillStyle = '#CCCCCC' + ctx.fillText(distance, centerX, distanceY) + + return canvas +} + +function createCombinedSprite (color: number, id: string, distance: string, depthTest: boolean): THREE.Sprite { + const canvas = drawCombinedCanvas(color, id, distance) + const texture = new THREE.CanvasTexture(canvas) + texture.anisotropy = 1 + texture.magFilter = THREE.LinearFilter + texture.minFilter = THREE.LinearFilter + const material = new THREE.SpriteMaterial({ + map: texture, + transparent: true, + opacity: 1, + depthTest, + depthWrite: false, + }) + const sprite = new THREE.Sprite(material) + sprite.position.set(0, 0, 0) + return sprite +} + +export const WaypointHelpers = { + // World-scale constant size helper + computeWorldScale (distance: number, fixedReference = 10) { + return Math.max(0.0001, distance / fixedReference) + }, + // Screen-pixel constant size helper + computeScreenPixelScale ( + camera: THREE.PerspectiveCamera, + distance: number, + pixelSize: number, + viewportHeightPx: number + ) { + const vFovRad = camera.fov * Math.PI / 180 + const worldUnitsPerScreenHeightAtDist = Math.tan(vFovRad / 2) * 2 * distance + return worldUnitsPerScreenHeightAtDist * (pixelSize / viewportHeightPx) + } +} diff --git a/renderer/viewer/three/waypoints.ts b/renderer/viewer/three/waypoints.ts new file mode 100644 index 00000000..256ca6df --- /dev/null +++ b/renderer/viewer/three/waypoints.ts @@ -0,0 +1,140 @@ +import * as THREE from 'three' +import { WorldRendererThree } from './worldrendererThree' +import { createWaypointSprite, type WaypointSprite } from './waypointSprite' + +interface Waypoint { + id: string + x: number + y: number + z: number + minDistance: number + color: number + label?: string + sprite: WaypointSprite +} + +interface WaypointOptions { + color?: number + label?: string + minDistance?: number + metadata?: any +} + +export class WaypointsRenderer { + private readonly waypoints = new Map() + private readonly waypointScene = new THREE.Scene() + + constructor ( + private readonly worldRenderer: WorldRendererThree + ) { + } + + private updateWaypoints () { + const playerPos = this.worldRenderer.cameraObject.position + const sizeVec = this.worldRenderer.renderer.getSize(new THREE.Vector2()) + + for (const waypoint of this.waypoints.values()) { + const waypointPos = new THREE.Vector3(waypoint.x, waypoint.y, waypoint.z) + const distance = playerPos.distanceTo(waypointPos) + const visible = !waypoint.minDistance || distance >= waypoint.minDistance + + waypoint.sprite.setVisible(visible) + + if (visible) { + // Update position + waypoint.sprite.setPosition(waypoint.x, waypoint.y, waypoint.z) + // Ensure camera-based update each frame + waypoint.sprite.updateForCamera(this.worldRenderer.getCameraPosition(), this.worldRenderer.camera, sizeVec.width, sizeVec.height) + } + } + } + + render () { + if (this.waypoints.size === 0) return + + // Update waypoint scaling + this.updateWaypoints() + + // Render waypoints scene with the world camera + this.worldRenderer.renderer.render(this.waypointScene, this.worldRenderer.camera) + } + + // Removed sprite/label texture creation. Use utils/waypointSprite.ts + + addWaypoint ( + id: string, + x: number, + y: number, + z: number, + options: WaypointOptions = {} + ) { + // Remove existing waypoint if it exists + this.removeWaypoint(id) + + const color = options.color ?? 0xFF_00_00 + const { label, metadata } = options + const minDistance = options.minDistance ?? 0 + + const sprite = createWaypointSprite({ + position: new THREE.Vector3(x, y, z), + color, + label: (label || id), + metadata, + }) + sprite.enableOffscreenArrow(true) + sprite.setArrowParent(this.waypointScene) + + this.waypointScene.add(sprite.group) + + this.waypoints.set(id, { + id, x: x + 0.5, y: y + 0.5, z: z + 0.5, minDistance, + color, label, + sprite, + }) + } + + removeWaypoint (id: string) { + const waypoint = this.waypoints.get(id) + if (waypoint) { + this.waypointScene.remove(waypoint.sprite.group) + waypoint.sprite.dispose() + this.waypoints.delete(id) + } + } + + clear () { + for (const id of this.waypoints.keys()) { + this.removeWaypoint(id) + } + } + + testWaypoint () { + this.addWaypoint('Test Point', 0, 70, 0, { color: 0x00_FF_00, label: 'Test Point' }) + this.addWaypoint('Spawn', 0, 64, 0, { color: 0xFF_FF_00, label: 'Spawn' }) + this.addWaypoint('Far Point', 100, 70, 100, { color: 0x00_00_FF, label: 'Far Point' }) + } + + getWaypoint (id: string): Waypoint | undefined { + return this.waypoints.get(id) + } + + getAllWaypoints (): Waypoint[] { + return [...this.waypoints.values()] + } + + setWaypointColor (id: string, color: number) { + const waypoint = this.waypoints.get(id) + if (waypoint) { + waypoint.sprite.setColor(color) + waypoint.color = color + } + } + + setWaypointLabel (id: string, label?: string) { + const waypoint = this.waypoints.get(id) + if (waypoint) { + waypoint.label = label + waypoint.sprite.setLabel(label) + } + } +} diff --git a/renderer/viewer/three/world/cursorBlock.ts b/renderer/viewer/three/world/cursorBlock.ts index 048539d9..a03a6999 100644 --- a/renderer/viewer/three/world/cursorBlock.ts +++ b/renderer/viewer/three/world/cursorBlock.ts @@ -1,9 +1,9 @@ import * as THREE from 'three' import { LineMaterial, LineSegmentsGeometry, Wireframe } from 'three-stdlib' import { Vec3 } from 'vec3' -import { subscribeKey } from 'valtio/utils' -import { Block } from 'prismarine-block' +import { BlockShape, BlocksShapes } from 'renderer/viewer/lib/basePlayerState' import { WorldRendererThree } from '../worldrendererThree' +import { loadThreeJsTextureFromUrl } from '../threeJsUtils' import destroyStage0 from '../../../../assets/destroy_stage_0.png' import destroyStage1 from '../../../../assets/destroy_stage_1.png' import destroyStage2 from '../../../../assets/destroy_stage_2.png' @@ -16,25 +16,36 @@ import destroyStage8 from '../../../../assets/destroy_stage_8.png' import destroyStage9 from '../../../../assets/destroy_stage_9.png' export class CursorBlock { + _cursorLinesHidden = false + get cursorLinesHidden () { + return this._cursorLinesHidden + } + set cursorLinesHidden (value: boolean) { + if (this.interactionLines) { + this.interactionLines.mesh.visible = !value + } + this._cursorLinesHidden = value + } + cursorLineMaterial: LineMaterial - interactionLines: null | { blockPos; mesh } = null - prevColor + interactionLines: null | { blockPos: Vec3, mesh: THREE.Group, shapePositions: BlocksShapes | undefined } = null + prevColor: string | undefined blockBreakMesh: THREE.Mesh breakTextures: THREE.Texture[] = [] constructor (public readonly worldRenderer: WorldRendererThree) { // Initialize break mesh and textures - const loader = new THREE.TextureLoader() const destroyStagesImages = [ destroyStage0, destroyStage1, destroyStage2, destroyStage3, destroyStage4, destroyStage5, destroyStage6, destroyStage7, destroyStage8, destroyStage9 ] for (let i = 0; i < 10; i++) { - const texture = loader.load(destroyStagesImages[i]) - texture.magFilter = THREE.NearestFilter - texture.minFilter = THREE.NearestFilter - this.breakTextures.push(texture) + void loadThreeJsTextureFromUrl(destroyStagesImages[i]).then((texture) => { + texture.magFilter = THREE.NearestFilter + texture.minFilter = THREE.NearestFilter + this.breakTextures.push(texture) + }) } const breakMaterial = new THREE.MeshBasicMaterial({ @@ -48,18 +59,26 @@ export class CursorBlock { this.blockBreakMesh.name = 'blockBreakMesh' this.worldRenderer.scene.add(this.blockBreakMesh) - subscribeKey(this.worldRenderer.playerState.reactive, 'gameMode', () => { + this.worldRenderer.onReactivePlayerStateUpdated('gameMode', () => { this.updateLineMaterial() }) - - this.updateLineMaterial() + // todo figure out why otherwise fog from skybox breaks it + setTimeout(() => { + this.updateLineMaterial() + if (this.interactionLines) { + this.setHighlightCursorBlock(this.interactionLines.blockPos, this.interactionLines.shapePositions, true) + } + }) } // Update functions updateLineMaterial () { - const inCreative = this.worldRenderer.displayOptions.playerState.reactive.gameMode === 'creative' + const inCreative = this.worldRenderer.playerStateReactive.gameMode === 'creative' const pixelRatio = this.worldRenderer.renderer.getPixelRatio() + if (this.cursorLineMaterial) { + this.cursorLineMaterial.dispose() + } this.cursorLineMaterial = new LineMaterial({ color: (() => { switch (this.worldRenderer.worldRendererConfig.highlightBlockColor) { @@ -78,15 +97,13 @@ export class CursorBlock { this.prevColor = this.worldRenderer.worldRendererConfig.highlightBlockColor } - updateBreakAnimation (block: Block | undefined, stage: number | null) { + updateBreakAnimation (blockPosition: { x: number, y: number, z: number } | undefined, stage: number | null, mergedShape?: BlockShape) { this.hideBreakAnimation() - if (stage === null || !block) return + if (stage === null || !blockPosition || !mergedShape) return - const mergedShape = bot.mouse.getMergedCursorShape(block) - if (!mergedShape) return - const { position, width, height, depth } = bot.mouse.getDataFromShape(mergedShape) + const { position, width, height, depth } = mergedShape this.blockBreakMesh.scale.set(width * 1.001, height * 1.001, depth * 1.001) - position.add(block.position) + position.add(blockPosition) this.blockBreakMesh.position.set(position.x, position.y, position.z) this.blockBreakMesh.visible = true; @@ -108,8 +125,8 @@ export class CursorBlock { } } - setHighlightCursorBlock (blockPos: Vec3 | null, shapePositions?: Array<{ position: any; width: any; height: any; depth: any; }>): void { - if (blockPos && this.interactionLines && blockPos.equals(this.interactionLines.blockPos)) { + setHighlightCursorBlock (blockPos: Vec3 | null, shapePositions?: BlocksShapes, force = false): void { + if (blockPos && this.interactionLines && blockPos.equals(this.interactionLines.blockPos) && !force) { return } if (this.interactionLines !== null) { @@ -132,7 +149,8 @@ export class CursorBlock { group.add(wireframe) } this.worldRenderer.scene.add(group) - this.interactionLines = { blockPos, mesh: group } + group.visible = !this.cursorLinesHidden + this.interactionLines = { blockPos, mesh: group, shapePositions } } render () { diff --git a/renderer/viewer/three/world/vr.ts b/renderer/viewer/three/world/vr.ts index 925ba0bb..ecf1b299 100644 --- a/renderer/viewer/three/world/vr.ts +++ b/renderer/viewer/three/world/vr.ts @@ -4,8 +4,9 @@ import { XRControllerModelFactory } from 'three/examples/jsm/webxr/XRControllerM import { buttonMap as standardButtonsMap } from 'contro-max/build/gamepad' import * as THREE from 'three' import { WorldRendererThree } from '../worldrendererThree' +import { DocumentRenderer } from '../documentRenderer' -export async function initVR (worldRenderer: WorldRendererThree) { +export async function initVR (worldRenderer: WorldRendererThree, documentRenderer: DocumentRenderer) { if (!('xr' in navigator) || !worldRenderer.worldRendererConfig.vrSupport) return const { renderer } = worldRenderer @@ -26,12 +27,13 @@ export async function initVR (worldRenderer: WorldRendererThree) { function enableVr () { renderer.xr.enabled = true + // renderer.xr.setReferenceSpaceType('local-floor') worldRenderer.reactiveState.preventEscapeMenu = true } function disableVr () { renderer.xr.enabled = false - worldRenderer.cameraObjectOverride = undefined + worldRenderer.cameraGroupVr = undefined worldRenderer.reactiveState.preventEscapeMenu = false worldRenderer.scene.remove(user) vrButtonContainer.hidden = true @@ -100,7 +102,7 @@ export async function initVR (worldRenderer: WorldRendererThree) { // hack for vr camera const user = new THREE.Group() - user.add(worldRenderer.camera) + user.name = 'vr-camera-container' worldRenderer.scene.add(user) const controllerModelFactory = new XRControllerModelFactory(new GLTFLoader()) const controller1 = renderer.xr.getControllerGrip(0) @@ -189,7 +191,7 @@ export async function initVR (worldRenderer: WorldRendererThree) { } // appViewer.backend?.updateCamera(null, yawOffset, 0) - worldRenderer.updateCamera(null, bot.entity.yaw, bot.entity.pitch) + // worldRenderer.updateCamera(null, bot.entity.yaw, bot.entity.pitch) // todo restore this logic (need to preserve ability to move camera) // const xrCamera = renderer.xr.getCamera() @@ -197,16 +199,15 @@ export async function initVR (worldRenderer: WorldRendererThree) { // bot.entity.yaw = Math.atan2(-d.x, -d.z) // bot.entity.pitch = Math.asin(d.y) - // todo ? - // bot.physics.stepHeight = 1 - - worldRenderer.render() + documentRenderer.frameRender(false) }) renderer.xr.addEventListener('sessionstart', () => { - worldRenderer.cameraObjectOverride = user + user.add(worldRenderer.camera) + worldRenderer.cameraGroupVr = user }) renderer.xr.addEventListener('sessionend', () => { - worldRenderer.cameraObjectOverride = undefined + worldRenderer.cameraGroupVr = undefined + user.remove(worldRenderer.camera) }) worldRenderer.abortController.signal.addEventListener('abort', disableVr) diff --git a/renderer/viewer/three/worldrendererThree.ts b/renderer/viewer/three/worldrendererThree.ts index c74bba51..1b4e6152 100644 --- a/renderer/viewer/three/worldrendererThree.ts +++ b/renderer/viewer/three/worldrendererThree.ts @@ -3,44 +3,35 @@ import { Vec3 } from 'vec3' import nbt from 'prismarine-nbt' import PrismarineChatLoader from 'prismarine-chat' import * as tweenJs from '@tweenjs/tween.js' -import { subscribeKey } from 'valtio/utils' +import { Biome } from 'minecraft-data' import { renderSign } from '../sign-renderer' -import { DisplayWorldOptions, GraphicsInitOptions, RendererReactiveState } from '../../../src/appViewer' +import { DisplayWorldOptions, GraphicsInitOptions } from '../../../src/appViewer' import { chunkPos, sectionPos } from '../lib/simpleUtils' import { WorldRendererCommon } from '../lib/worldrendererCommon' -import { addNewStat, removeAllStats } from '../lib/ui/newStats' +import { addNewStat } from '../lib/ui/newStats' import { MesherGeometryOutput } from '../lib/mesher/shared' import { ItemSpecificContextProperties } from '../lib/basePlayerState' -import { getMyHand } from '../lib/hand' import { setBlockPosition } from '../lib/mesher/standaloneRenderer' +import { getMyHand } from './hand' import HoldingBlock from './holdingBlock' import { getMesh } from './entity/EntityMesh' import { armorModel } from './entity/armorModels' -import { disposeObject } from './threeJsUtils' +import { disposeObject, loadThreeJsTextureFromBitmap } from './threeJsUtils' import { CursorBlock } from './world/cursorBlock' import { getItemUv } from './appShared' -import { initVR } from './world/vr' import { Entities } from './entities' import { ThreeJsSound } from './threeJsSound' import { CameraShake } from './cameraShake' +import { ThreeJsMedia } from './threeJsMedia' +import { Fountain } from './threeJsParticles' +import { WaypointsRenderer } from './waypoints' +import { DEFAULT_TEMPERATURE, SkyboxRenderer } from './skyboxRenderer' -interface MediaProperties { - position: { x: number, y: number, z: number } - size: { width: number, height: number } - src: string - rotation?: 0 | 1 | 2 | 3 // 0-3 for 0°, 90°, 180°, 270° - doubleSide?: boolean - background?: number // Hexadecimal color (e.g., 0x000000 for black) - opacity?: number // 0-1 value for transparency - uvMapping?: { startU: number, endU: number, startV: number, endV: number } - allowOrigins?: string[] | boolean - loop?: boolean - volume?: number -} +type SectionKey = string export class WorldRendererThree extends WorldRendererCommon { outputFormat = 'threeJs' as const - sectionObjects: Record = {} + sectionObjects: Record = {} chunkTextures = new Map() signsCache = new Map() starField: StarField @@ -51,18 +42,41 @@ export class WorldRendererThree extends WorldRendererCommon { ambientLight = new THREE.AmbientLight(0xcc_cc_cc) directionalLight = new THREE.DirectionalLight(0xff_ff_ff, 0.5) entities = new Entities(this) - cameraObjectOverride?: THREE.Object3D // for xr + cameraGroupVr?: THREE.Object3D material = new THREE.MeshLambertMaterial({ vertexColors: true, transparent: true, alphaTest: 0.1 }) itemsTexture: THREE.Texture - cursorBlock = new CursorBlock(this) + cursorBlock: CursorBlock onRender: Array<() => void> = [] - customMedia = new Map void - }>() cameraShake: CameraShake + cameraContainer: THREE.Object3D + media: ThreeJsMedia + waitingChunksToDisplay = {} as { [chunkKey: string]: SectionKey[] } + waypoints: WaypointsRenderer + camera: THREE.PerspectiveCamera + renderTimeAvg = 0 + sectionsOffsetsAnimations = {} as { + [chunkKey: string]: { + time: number, + // also specifies direction + speedX: number, + speedY: number, + speedZ: number, + + currentOffsetX: number, + currentOffsetY: number, + currentOffsetZ: number, + + limitX?: number, + limitY?: number, + limitZ?: number, + } + } + fountains: Fountain[] = [] + DEBUG_RAYCAST = false + skyboxRenderer: SkyboxRenderer + + private currentPosTween?: tweenJs.Tween + private currentRotTween?: tweenJs.Tween<{ pitch: number, yaw: number }> get tilesRendered () { return Object.values(this.sectionObjects).reduce((acc, obj) => acc + (obj as any).tilesCount, 0) @@ -74,21 +88,51 @@ export class WorldRendererThree extends WorldRendererCommon { constructor (public renderer: THREE.WebGLRenderer, public initOptions: GraphicsInitOptions, public displayOptions: DisplayWorldOptions) { if (!initOptions.resourcesManager) throw new Error('resourcesManager is required') - super(initOptions.resourcesManager, displayOptions, displayOptions.version) + super(initOptions.resourcesManager, displayOptions, initOptions) + this.renderer = renderer displayOptions.rendererState.renderer = WorldRendererThree.getRendererInfo(renderer) ?? '...' - this.starField = new StarField(this.scene) + this.starField = new StarField(this) + this.cursorBlock = new CursorBlock(this) this.holdingBlock = new HoldingBlock(this) this.holdingBlockLeft = new HoldingBlock(this, true) + // Initialize skybox renderer + this.skyboxRenderer = new SkyboxRenderer(this.scene, this.worldRendererConfig.defaultSkybox, null) + void this.skyboxRenderer.init() + this.addDebugOverlay() this.resetScene() - this.watchReactivePlayerState() - this.init() - void initVR(this) + void this.init() this.soundSystem = new ThreeJsSound(this) - this.cameraShake = new CameraShake(this.camera, this.onRender) + this.cameraShake = new CameraShake(this, this.onRender) + this.media = new ThreeJsMedia(this) + this.waypoints = new WaypointsRenderer(this) + + // this.fountain = new Fountain(this.scene, this.scene, { + // position: new THREE.Vector3(0, 10, 0), + // }) + + this.renderUpdateEmitter.on('chunkFinished', (chunkKey: string) => { + this.finishChunk(chunkKey) + }) + this.worldSwitchActions() + } + + get cameraObject () { + return this.cameraGroupVr ?? this.cameraContainer + } + + worldSwitchActions () { + this.onWorldSwitched.push(() => { + // clear custom blocks + this.protocolCustomBlocks.clear() + // Reset section animations + this.sectionsOffsetsAnimations = {} + // Clear waypoints + this.waypoints.clear() + }) } updateEntity (e, isPosUpdate = false) { @@ -108,6 +152,10 @@ export class WorldRendererThree extends WorldRendererCommon { } } + updatePlayerEntity (e: any) { + this.entities.handlePlayerEntity(e) + } + resetScene () { this.scene.matrixAutoUpdate = false // for perf this.scene.background = new THREE.Color(this.initOptions.config.sceneBackground) @@ -118,27 +166,49 @@ export class WorldRendererThree extends WorldRendererCommon { const size = this.renderer.getSize(new THREE.Vector2()) this.camera = new THREE.PerspectiveCamera(75, size.x / size.y, 0.1, 1000) + this.cameraContainer = new THREE.Object3D() + this.cameraContainer.add(this.camera) + this.scene.add(this.cameraContainer) } - watchReactivePlayerState () { - const updateValue = (key: T, callback: (value: typeof this.displayOptions.playerState.reactive[T]) => void) => { - callback(this.displayOptions.playerState.reactive[key]) - subscribeKey(this.displayOptions.playerState.reactive, key, callback) - } - updateValue('backgroundColor', (value) => { - this.changeBackgroundColor(value) + override watchReactivePlayerState () { + super.watchReactivePlayerState() + this.onReactivePlayerStateUpdated('inWater', (value) => { + this.skyboxRenderer.updateWaterState(value, this.playerStateReactive.waterBreathing) }) - updateValue('inWater', (value) => { - this.scene.fog = value ? new THREE.Fog(0x00_00_ff, 0.1, 100) : null + this.onReactivePlayerStateUpdated('waterBreathing', (value) => { + this.skyboxRenderer.updateWaterState(this.playerStateReactive.inWater, value) }) - updateValue('ambientLight', (value) => { + this.onReactivePlayerStateUpdated('ambientLight', (value) => { if (!value) return this.ambientLight.intensity = value }) - updateValue('directionalLight', (value) => { + this.onReactivePlayerStateUpdated('directionalLight', (value) => { if (!value) return this.directionalLight.intensity = value }) + this.onReactivePlayerStateUpdated('lookingAtBlock', (value) => { + this.cursorBlock.setHighlightCursorBlock(value ? new Vec3(value.x, value.y, value.z) : null, value?.shapes) + }) + this.onReactivePlayerStateUpdated('diggingBlock', (value) => { + this.cursorBlock.updateBreakAnimation(value ? { x: value.x, y: value.y, z: value.z } : undefined, value?.stage ?? null, value?.mergedShape) + }) + this.onReactivePlayerStateUpdated('perspective', (value) => { + // Update camera perspective when it changes + const vecPos = new Vec3(this.cameraObject.position.x, this.cameraObject.position.y, this.cameraObject.position.z) + this.updateCamera(vecPos, this.cameraShake.getBaseRotation().yaw, this.cameraShake.getBaseRotation().pitch) + // todo also update camera when block within camera was changed + }) + } + + override watchReactiveConfig () { + super.watchReactiveConfig() + this.onReactiveConfigUpdated('showChunkBorders', (value) => { + this.updateShowChunksBorder(value) + }) + this.onReactiveConfigUpdated('defaultSkybox', (value) => { + this.skyboxRenderer.updateDefaultSkybox(value) + }) } changeHandSwingingState (isAnimationPlaying: boolean, isLeft = false) { @@ -151,20 +221,18 @@ export class WorldRendererThree extends WorldRendererCommon { } async updateAssetsData (): Promise { - const resources = this.resourcesManager.currentResources! + const resources = this.resourcesManager.currentResources const oldTexture = this.material.map const oldItemsTexture = this.itemsTexture - const texture = await new THREE.TextureLoader().loadAsync(resources.blocksAtlasParser.latestImage) - texture.magFilter = THREE.NearestFilter - texture.minFilter = THREE.NearestFilter + const texture = loadThreeJsTextureFromBitmap(resources.blocksAtlasImage) + texture.needsUpdate = true texture.flipY = false this.material.map = texture - const itemsTexture = await new THREE.TextureLoader().loadAsync(resources.itemsAtlasParser.latestImage) - itemsTexture.magFilter = THREE.NearestFilter - itemsTexture.minFilter = THREE.NearestFilter + const itemsTexture = loadThreeJsTextureFromBitmap(resources.itemsAtlasImage) + itemsTexture.needsUpdate = true itemsTexture.flipY = false this.itemsTexture = itemsTexture @@ -203,17 +271,30 @@ export class WorldRendererThree extends WorldRendererCommon { } else { this.starField.remove() } + + this.skyboxRenderer.updateTime(newTime) + } + + biomeUpdated (biome: Biome): void { + if (biome?.temperature !== undefined) { + this.skyboxRenderer.updateTemperature(biome.temperature) + } + } + + biomeReset (): void { + // Reset to default temperature when biome is unknown + this.skyboxRenderer.updateTemperature(DEFAULT_TEMPERATURE) } getItemRenderData (item: Record, specificProps: ItemSpecificContextProperties) { - return getItemUv(item, specificProps, this.resourcesManager) + return getItemUv(item, specificProps, this.resourcesManager, this.playerStateReactive) } async demoModel () { //@ts-expect-error const pos = cursorBlockRel(0, 1, 0).position - const mesh = await getMyHand() + const mesh = (await getMyHand())! // mesh.rotation.y = THREE.MathUtils.degToRad(90) setBlockPosition(mesh, pos) const helper = new THREE.BoxHelper(mesh, 0xff_ff_00) @@ -240,9 +321,19 @@ export class WorldRendererThree extends WorldRendererCommon { this.debugOverlayAdded = true const pane = addNewStat('debug-overlay') setInterval(() => { - pane.setVisibility(this.displayStats) - if (this.displayStats) { - pane.updateText(`C: ${this.renderer.info.render.calls} TR: ${this.renderer.info.render.triangles} TE: ${this.renderer.info.memory.textures} F: ${this.tilesRendered} B: ${this.blocksRendered}`) + pane.setVisibility(this.displayAdvancedStats) + if (this.displayAdvancedStats) { + const formatBigNumber = (num: number) => { + return new Intl.NumberFormat('en-US', {}).format(num) + } + let text = '' + text += `C: ${formatBigNumber(this.renderer.info.render.calls)} ` + text += `TR: ${formatBigNumber(this.renderer.info.render.triangles)} ` + text += `TE: ${formatBigNumber(this.renderer.info.memory.textures)} ` + text += `F: ${formatBigNumber(this.tilesRendered)} ` + text += `B: ${formatBigNumber(this.blocksRendered)}` + pane.updateText(text) + this.backendInfoReport = text } }, 200) } @@ -258,10 +349,11 @@ export class WorldRendererThree extends WorldRendererCommon { section.renderOrder = 500 - chunkDistance } - updateViewerPosition (pos: Vec3): void { - this.viewerPosition = pos - const cameraPos = this.camera.position.toArray().map(x => Math.floor(x / 16)) as [number, number, number] - this.cameraSectionPos = new Vec3(...cameraPos) + override updateViewerPosition (pos: Vec3): void { + this.viewerChunkPosition = pos + } + + cameraSectionPositionUpdate () { // eslint-disable-next-line guard-for-in for (const key in this.sectionObjects) { const value = this.sectionObjects[key] @@ -270,6 +362,18 @@ export class WorldRendererThree extends WorldRendererCommon { } } + getDir (current: number, origin: number) { + if (current === origin) return 0 + return current < origin ? 1 : -1 + } + + finishChunk (chunkKey: string) { + for (const sectionKey of this.waitingChunksToDisplay[chunkKey] ?? []) { + this.sectionObjects[sectionKey].visible = true + } + delete this.waitingChunksToDisplay[chunkKey] + } + // debugRecomputedDeletedObjects = 0 handleWorkerMessage (data: { geometry: MesherGeometryOutput, key, type }): void { if (data.type !== 'geometry') return @@ -287,26 +391,12 @@ export class WorldRendererThree extends WorldRendererCommon { // this.debugRecomputedDeletedObjects++ // } - // if (!this.initialChunksLoad && this.enableChunksLoadDelay) { - // const newPromise = new Promise(resolve => { - // if (this.droppedFpsPercentage > 0.5) { - // setTimeout(resolve, 1000 / 50 * this.droppedFpsPercentage) - // } else { - // setTimeout(resolve) - // } - // }) - // this.promisesQueue.push(newPromise) - // for (const promise of this.promisesQueue) { - // await promise - // } - // } - const geometry = new THREE.BufferGeometry() geometry.setAttribute('position', new THREE.BufferAttribute(data.geometry.positions, 3)) geometry.setAttribute('normal', new THREE.BufferAttribute(data.geometry.normals, 3)) geometry.setAttribute('color', new THREE.BufferAttribute(data.geometry.colors, 3)) geometry.setAttribute('uv', new THREE.BufferAttribute(data.geometry.uvs, 2)) - geometry.setIndex(data.geometry.indices) + geometry.index = new THREE.BufferAttribute(data.geometry.indices as Uint32Array | Uint16Array, 1) const mesh = new THREE.Mesh(geometry, this.material) mesh.position.set(data.geometry.sx, data.geometry.sy, data.geometry.sz) @@ -347,6 +437,17 @@ export class WorldRendererThree extends WorldRendererCommon { } } this.sectionObjects[data.key] = object + if (this.displayOptions.inWorldRenderingConfig._renderByChunks) { + object.visible = false + const chunkKey = `${chunkCoords[0]},${chunkCoords[2]}` + this.waitingChunksToDisplay[chunkKey] ??= [] + this.waitingChunksToDisplay[chunkKey].push(data.key) + if (this.finishedChunks[chunkKey]) { + // todo it might happen even when it was not an update + this.finishChunk(chunkKey) + } + } + this.updatePosDataChunk(data.key) object.matrixAutoUpdate = false mesh.onAfterRender = (renderer, scene, camera, geometry, material, group) => { @@ -356,7 +457,7 @@ export class WorldRendererThree extends WorldRendererCommon { this.scene.add(object) } - getSignTexture (position: Vec3, blockEntity, backSide = false) { + getSignTexture (position: Vec3, blockEntity, isHanging, backSide = false) { const chunk = chunkPos(position) let textures = this.chunkTextures.get(`${chunk[0]},${chunk[1]}`) if (!textures) { @@ -368,7 +469,7 @@ export class WorldRendererThree extends WorldRendererCommon { if (textures[texturekey]) return textures[texturekey] const PrismarineChat = PrismarineChatLoader(this.version) - const canvas = renderSign(blockEntity, PrismarineChat) + const canvas = renderSign(blockEntity, isHanging, PrismarineChat) if (!canvas) return const tex = new THREE.Texture(canvas) tex.magFilter = THREE.NearestFilter @@ -378,49 +479,149 @@ export class WorldRendererThree extends WorldRendererCommon { return tex } - tryIntersectMedia () { - const { camera } = this - const raycaster = new THREE.Raycaster() + getCameraPosition () { + const worldPos = new THREE.Vector3() + this.camera.getWorldPosition(worldPos) + return worldPos + } - // Get mouse position at center of screen - const mouse = new THREE.Vector2(0, 0) + getSectionCameraPosition () { + const pos = this.getCameraPosition() + return new Vec3( + Math.floor(pos.x / 16), + Math.floor(pos.y / 16), + Math.floor(pos.z / 16) + ) + } - // Update the raycaster - raycaster.setFromCamera(mouse, camera) - - let result = null as { id: string, x: number, y: number } | null - // Check intersection with all video meshes - for (const [id, videoData] of this.customMedia.entries()) { - // Get the actual mesh (first child of the group) - const mesh = videoData.mesh.children[0] as THREE.Mesh - if (!mesh) continue - - const intersects = raycaster.intersectObject(mesh, false) - if (intersects.length > 0) { - const intersection = intersects[0] - const { uv } = intersection - if (uv) { - result = { - id, - x: uv.x, - y: uv.y - } - break - } - } + updateCameraSectionPos () { + const newSectionPos = this.getSectionCameraPosition() + if (!this.cameraSectionPos.equals(newSectionPos)) { + this.cameraSectionPos = newSectionPos + this.cameraSectionPositionUpdate() } - this.reactiveState.world.intersectMedia = result } setFirstPersonCamera (pos: Vec3 | null, yaw: number, pitch: number) { - const cam = this.cameraObjectOverride || this.camera - const yOffset = this.displayOptions.playerState.getEyeHeight() + const yOffset = this.playerStateReactive.eyeHeight - this.camera = cam as THREE.PerspectiveCamera this.updateCamera(pos?.offset(0, yOffset, 0) ?? null, yaw, pitch) - this.tryIntersectMedia() + this.media.tryIntersectMedia() + this.updateCameraSectionPos() } + getThirdPersonCamera (pos: THREE.Vector3 | null, yaw: number, pitch: number) { + pos ??= this.cameraObject.position + + // Calculate camera offset based on perspective + const isBack = this.playerStateReactive.perspective === 'third_person_back' + const distance = 4 // Default third person distance + + // Calculate direction vector using proper world orientation + // We need to get the camera's current look direction and use that for positioning + + // Create a direction vector that represents where the camera is looking + // This matches the Three.js camera coordinate system + const direction = new THREE.Vector3(0, 0, -1) // Forward direction in camera space + + // Apply the same rotation that's applied to the camera container + const pitchQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), pitch) + const yawQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), yaw) + const finalQuat = new THREE.Quaternion().multiplyQuaternions(yawQuat, pitchQuat) + + // Transform the direction vector by the camera's rotation + direction.applyQuaternion(finalQuat) + + // For back view, we want the camera behind the player (opposite to view direction) + // For front view, we want the camera in front of the player (same as view direction) + if (isBack) { + direction.multiplyScalar(-1) + } + + // Create debug visualization if advanced stats are enabled + if (this.DEBUG_RAYCAST) { + this.debugRaycast(pos, direction, distance) + } + + // Perform raycast to avoid camera going through blocks + const raycaster = new THREE.Raycaster() + raycaster.set(pos, direction) + raycaster.far = distance // Limit raycast distance + + // Filter to only nearby chunks for performance + const nearbyChunks = Object.values(this.sectionObjects) + .filter(obj => obj.name === 'chunk' && obj.visible) + .filter(obj => { + // Get the mesh child which has the actual geometry + const mesh = obj.children.find(child => child.name === 'mesh') + if (!mesh) return false + + // Check distance from player position to chunk + const chunkWorldPos = new THREE.Vector3() + mesh.getWorldPosition(chunkWorldPos) + const distance = pos.distanceTo(chunkWorldPos) + return distance < 80 // Only check chunks within 80 blocks + }) + + // Get all mesh children for raycasting + const meshes: THREE.Object3D[] = [] + for (const chunk of nearbyChunks) { + const mesh = chunk.children.find(child => child.name === 'mesh') + if (mesh) meshes.push(mesh) + } + + const intersects = raycaster.intersectObjects(meshes, false) + + let finalDistance = distance + if (intersects.length > 0) { + // Use intersection distance minus a small offset to prevent clipping + finalDistance = Math.max(0.5, intersects[0].distance - 0.2) + } + + const finalPos = new Vec3( + pos.x + direction.x * finalDistance, + pos.y + direction.y * finalDistance, + pos.z + direction.z * finalDistance + ) + + return finalPos + } + + private debugRaycastHelper?: THREE.ArrowHelper + private debugHitPoint?: THREE.Mesh + + private debugRaycast (pos: THREE.Vector3, direction: THREE.Vector3, distance: number) { + // Remove existing debug objects + if (this.debugRaycastHelper) { + this.scene.remove(this.debugRaycastHelper) + this.debugRaycastHelper = undefined + } + if (this.debugHitPoint) { + this.scene.remove(this.debugHitPoint) + this.debugHitPoint = undefined + } + + // Create raycast arrow + this.debugRaycastHelper = new THREE.ArrowHelper( + direction.clone().normalize(), + pos, + distance, + 0xff_00_00, // Red color + distance * 0.1, + distance * 0.05 + ) + this.scene.add(this.debugRaycastHelper) + + // Create hit point indicator + const hitGeometry = new THREE.SphereGeometry(0.2, 8, 8) + const hitMaterial = new THREE.MeshBasicMaterial({ color: 0x00_ff_00 }) + this.debugHitPoint = new THREE.Mesh(hitGeometry, hitMaterial) + this.debugHitPoint.position.copy(pos).add(direction.clone().multiplyScalar(distance)) + this.scene.add(this.debugHitPoint) + } + + prevFramePerspective = null as string | null + updateCamera (pos: Vec3 | null, yaw: number, pitch: number): void { // if (this.freeFlyMode) { // pos = this.freeFlyState.position @@ -429,45 +630,179 @@ export class WorldRendererThree extends WorldRendererCommon { // } if (pos) { - new tweenJs.Tween(this.camera.position).to({ x: pos.x, y: pos.y, z: pos.z }, 50).start() + if (this.renderer.xr.isPresenting) { + pos.y -= this.camera.position.y // Fix Y position of camera in world + } + + this.currentPosTween?.stop() + this.currentPosTween = new tweenJs.Tween(this.cameraObject.position).to({ x: pos.x, y: pos.y, z: pos.z }, this.playerStateUtils.isSpectatingEntity() ? 150 : 50).start() // this.freeFlyState.position = pos } - this.cameraShake.setBaseRotation(pitch, yaw) + + if (this.playerStateUtils.isSpectatingEntity()) { + const rotation = this.cameraShake.getBaseRotation() + // wrap in the correct direction + let yawOffset = 0 + const halfPi = Math.PI / 2 + if (rotation.yaw < halfPi && yaw > Math.PI + halfPi) { + yawOffset = -Math.PI * 2 + } else if (yaw < halfPi && rotation.yaw > Math.PI + halfPi) { + yawOffset = Math.PI * 2 + } + this.currentRotTween?.stop() + this.currentRotTween = new tweenJs.Tween(rotation).to({ pitch, yaw: yaw + yawOffset }, 100) + .onUpdate(params => this.cameraShake.setBaseRotation(params.pitch, params.yaw - yawOffset)).start() + } else { + this.currentRotTween?.stop() + this.cameraShake.setBaseRotation(pitch, yaw) + + const { perspective } = this.playerStateReactive + if (perspective === 'third_person_back' || perspective === 'third_person_front') { + // Use getThirdPersonCamera for proper raycasting with max distance of 4 + const currentCameraPos = this.cameraObject.position + const thirdPersonPos = this.getThirdPersonCamera( + new THREE.Vector3(currentCameraPos.x, currentCameraPos.y, currentCameraPos.z), + yaw, + pitch + ) + + const distance = currentCameraPos.distanceTo(new THREE.Vector3(thirdPersonPos.x, thirdPersonPos.y, thirdPersonPos.z)) + // Apply Z offset based on perspective and calculated distance + const zOffset = perspective === 'third_person_back' ? distance : -distance + this.camera.position.set(0, 0, zOffset) + + if (perspective === 'third_person_front') { + // Flip camera view 180 degrees around Y axis for front view + this.camera.rotation.set(0, Math.PI, 0) + } else { + this.camera.rotation.set(0, 0, 0) + } + } else { + this.camera.position.set(0, 0, 0) + this.camera.rotation.set(0, 0, 0) + + // remove any debug raycasting + if (this.debugRaycastHelper) { + this.scene.remove(this.debugRaycastHelper) + this.debugRaycastHelper = undefined + } + if (this.debugHitPoint) { + this.scene.remove(this.debugHitPoint) + this.debugHitPoint = undefined + } + } + } + + this.updateCameraSectionPos() + } + + debugChunksVisibilityOverride () { + const { chunksRenderAboveOverride, chunksRenderBelowOverride, chunksRenderDistanceOverride, chunksRenderAboveEnabled, chunksRenderBelowEnabled, chunksRenderDistanceEnabled } = this.reactiveDebugParams + + const baseY = this.cameraSectionPos.y * 16 + + if ( + this.displayOptions.inWorldRenderingConfig.enableDebugOverlay && + chunksRenderAboveOverride !== undefined || + chunksRenderBelowOverride !== undefined || + chunksRenderDistanceOverride !== undefined + ) { + for (const [key, object] of Object.entries(this.sectionObjects)) { + const [x, y, z] = key.split(',').map(Number) + const isVisible = + // eslint-disable-next-line no-constant-binary-expression, sonarjs/no-redundant-boolean + (chunksRenderAboveEnabled && chunksRenderAboveOverride !== undefined) ? y <= (baseY + chunksRenderAboveOverride) : true && + // eslint-disable-next-line @stylistic/indent-binary-ops, no-constant-binary-expression, sonarjs/no-redundant-boolean + (chunksRenderBelowEnabled && chunksRenderBelowOverride !== undefined) ? y >= (baseY - chunksRenderBelowOverride) : true && + // eslint-disable-next-line @stylistic/indent-binary-ops + (chunksRenderDistanceEnabled && chunksRenderDistanceOverride !== undefined) ? Math.abs(y - baseY) <= chunksRenderDistanceOverride : true + + object.visible = isVisible + } + } else { + for (const object of Object.values(this.sectionObjects)) { + object.visible = true + } + } } render (sizeChanged = false) { + if (this.reactiveDebugParams.stopRendering) return + this.debugChunksVisibilityOverride() + const start = performance.now() + this.lastRendered = performance.now() this.cursorBlock.render() + this.updateSectionOffsets() + + // Update skybox position to follow camera + const cameraPos = this.getCameraPosition() + this.skyboxRenderer.update(cameraPos, this.viewDistance) const sizeOrFovChanged = sizeChanged || this.displayOptions.inWorldRenderingConfig.fov !== this.camera.fov if (sizeOrFovChanged) { - this.camera.aspect = window.innerWidth / window.innerHeight + const size = this.renderer.getSize(new THREE.Vector2()) + this.camera.aspect = size.width / size.height this.camera.fov = this.displayOptions.inWorldRenderingConfig.fov this.camera.updateProjectionMatrix() } - this.entities.render() + if (!this.reactiveDebugParams.disableEntities) { + this.entities.render() + } // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style - const cam = this.camera instanceof THREE.Group ? this.camera.children.find(child => child instanceof THREE.PerspectiveCamera) as THREE.PerspectiveCamera : this.camera + const cam = this.cameraGroupVr instanceof THREE.Group ? this.cameraGroupVr.children.find(child => child instanceof THREE.PerspectiveCamera) as THREE.PerspectiveCamera : this.camera this.renderer.render(this.scene, cam) - if (this.displayOptions.inWorldRenderingConfig.showHand/* && !this.freeFlyMode */) { + if ( + this.displayOptions.inWorldRenderingConfig.showHand && + this.playerStateReactive.gameMode !== 'spectator' && + this.playerStateReactive.perspective === 'first_person' && + // !this.freeFlyMode && + !this.renderer.xr.isPresenting + ) { this.holdingBlock.render(this.camera, this.renderer, this.ambientLight, this.directionalLight) this.holdingBlockLeft.render(this.camera, this.renderer, this.ambientLight, this.directionalLight) } + for (const fountain of this.fountains) { + if (this.sectionObjects[fountain.sectionId] && !this.sectionObjects[fountain.sectionId].foutain) { + fountain.createParticles(this.sectionObjects[fountain.sectionId]) + this.sectionObjects[fountain.sectionId].foutain = true + } + fountain.render() + } + + this.waypoints.render() + for (const onRender of this.onRender) { onRender() } + const end = performance.now() + const totalTime = end - start + this.renderTimeAvgCount++ + this.renderTimeAvg = ((this.renderTimeAvg * (this.renderTimeAvgCount - 1)) + totalTime) / this.renderTimeAvgCount + this.renderTimeMax = Math.max(this.renderTimeMax, totalTime) + this.currentRenderedFrames++ } renderHead (position: Vec3, rotation: number, isWall: boolean, blockEntity) { - const textures = blockEntity.SkullOwner?.Properties?.textures[0] - if (!textures) return + let textureData: string + if (blockEntity.SkullOwner) { + textureData = blockEntity.SkullOwner.Properties?.textures?.[0]?.Value + } else { + textureData = blockEntity.profile?.properties?.find(p => p.name === 'textures')?.value + } + if (!textureData) return try { - const textureData = JSON.parse(Buffer.from(textures.Value, 'base64').toString()) - const skinUrl = textureData.textures?.SKIN?.url + const decodedData = JSON.parse(Buffer.from(textureData, 'base64').toString()) + let skinUrl = decodedData.textures?.SKIN?.url + const { skinTexturesProxy } = this.worldRendererConfig + if (skinTexturesProxy) { + skinUrl = skinUrl?.replace('http://textures.minecraft.net/', skinTexturesProxy) + .replace('https://textures.minecraft.net/', skinTexturesProxy) + } const mesh = getMesh(this, skinUrl, armorModel.head) const group = new THREE.Group() @@ -491,7 +826,7 @@ export class WorldRendererThree extends WorldRendererCommon { } renderSign (position: Vec3, rotation: number, isWall: boolean, isHanging: boolean, blockEntity) { - const tex = this.getSignTexture(position, blockEntity) + const tex = this.getSignTexture(position, blockEntity, isHanging) if (!tex) return @@ -547,7 +882,6 @@ export class WorldRendererThree extends WorldRendererCommon { } updateShowChunksBorder (value: boolean) { - this.displayOptions.inWorldRenderingConfig.showChunkBorders = value for (const object of Object.values(this.sectionObjects)) { for (const child of object.children) { if (child.name === 'helper') { @@ -563,6 +897,16 @@ export class WorldRendererThree extends WorldRendererCommon { for (const mesh of Object.values(this.sectionObjects)) { this.scene.remove(mesh) } + + // Clean up debug objects + if (this.debugRaycastHelper) { + this.scene.remove(this.debugRaycastHelper) + this.debugRaycastHelper = undefined + } + if (this.debugHitPoint) { + this.scene.remove(this.debugHitPoint) + this.debugHitPoint = undefined + } } getLoadedChunksRelative (pos: Vec3, includeY = false) { @@ -632,405 +976,76 @@ export class WorldRendererThree extends WorldRendererCommon { } } - private createErrorTexture (width: number, height: number, background = 0x00_00_00): THREE.CanvasTexture { - const canvas = document.createElement('canvas') - // Scale up the canvas size for better text quality - canvas.width = width * 100 - canvas.height = height * 100 - - const ctx = canvas.getContext('2d') - if (!ctx) return new THREE.CanvasTexture(canvas) - - // Clear with transparent background - ctx.clearRect(0, 0, canvas.width, canvas.height) - - // Add background color - ctx.fillStyle = `rgba(${background >> 16 & 255}, ${background >> 8 & 255}, ${background & 255}, 0.5)` - ctx.fillRect(0, 0, canvas.width, canvas.height) - - // Add red text - ctx.fillStyle = '#ff0000' - ctx.font = 'bold 10px sans-serif' - ctx.textAlign = 'center' - ctx.textBaseline = 'middle' - ctx.fillText('Failed to load', canvas.width / 2, canvas.height / 2, canvas.width) - - const texture = new THREE.CanvasTexture(canvas) - texture.minFilter = THREE.LinearFilter - texture.magFilter = THREE.LinearFilter - return texture - } - - private createBackgroundTexture (width: number, height: number, color = 0x00_00_00, opacity = 1): THREE.CanvasTexture { - const canvas = document.createElement('canvas') - canvas.width = 1 - canvas.height = 1 - - const ctx = canvas.getContext('2d') - if (!ctx) return new THREE.CanvasTexture(canvas) - - // Convert hex color to rgba - const r = (color >> 16) & 255 - const g = (color >> 8) & 255 - const b = color & 255 - - ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${opacity})` - ctx.fillRect(0, 0, 1, 1) - - const texture = new THREE.CanvasTexture(canvas) - texture.minFilter = THREE.NearestFilter - texture.magFilter = THREE.NearestFilter - return texture - } - - validateOrigin (src: string, allowOrigins: string[] | boolean) { - if (allowOrigins === true) return true - if (allowOrigins === false) return false - const url = new URL(src) - return allowOrigins.some(origin => url.origin.endsWith(origin)) - } - - addMedia (id: string, props: MediaProperties) { - this.destroyMedia(id) - - const originSecurityError = props.allowOrigins !== undefined && !this.validateOrigin(props.src, props.allowOrigins) - if (originSecurityError) { - console.warn('Remote resource blocked due to security policy', props.src, 'allowed origins:', props.allowOrigins, 'you can control it with `remoteContentNotSameOrigin` option') - props.src = '' - } - - const isImage = props.src.endsWith('.png') || props.src.endsWith('.jpg') || props.src.endsWith('.jpeg') - - let video: HTMLVideoElement | undefined - if (!isImage) { - video = document.createElement('video') - video.src = props.src - video.loop = props.loop ?? true - video.volume = props.volume ?? 1 - video.muted = !props.volume - video.playsInline = true - video.crossOrigin = 'anonymous' - } - - // Create background texture first - const backgroundTexture = this.createBackgroundTexture( - props.size.width, - props.size.height, - props.background, - // props.opacity ?? 1 - ) - - const handleError = () => { - const errorTexture = this.createErrorTexture(props.size.width, props.size.height, props.background) - material.map = errorTexture - material.needsUpdate = true - } - - // Create a plane geometry with configurable UV mapping - const geometry = new THREE.PlaneGeometry(1, 1) - - // Create material with initial properties using background texture - const material = new THREE.MeshLambertMaterial({ - map: backgroundTexture, - transparent: true, - side: props.doubleSide ? THREE.DoubleSide : THREE.FrontSide, - alphaTest: 0.1 - }) - - const texture = video - ? new THREE.VideoTexture(video) - : new THREE.TextureLoader().load(props.src, () => { - if (this.customMedia.get(id)?.texture === texture) { - material.map = texture - material.needsUpdate = true - } - }, undefined, handleError) // todo cache - texture.minFilter = THREE.NearestFilter - texture.magFilter = THREE.NearestFilter - texture.format = THREE.RGBAFormat - texture.colorSpace = THREE.SRGBColorSpace - texture.generateMipmaps = false - - // Create inner mesh for offsets - const mesh = new THREE.Mesh(geometry, material) - - const { mesh: panel } = this.positionMeshExact(mesh, THREE.MathUtils.degToRad((props.rotation ?? 0) * 90), props.position, props.size.width, props.size.height) - - this.scene.add(panel) - - if (video) { - // Start playing the video - video.play().catch(err => { - console.error('Failed to play video:', err) - handleError() - }) - - // Update texture in animation loop - mesh.onBeforeRender = () => { - if (video.readyState === video.HAVE_ENOUGH_DATA) { - if (material.map !== texture) { - material.map = texture - material.needsUpdate = true - } - texture.needsUpdate = true - } - } - } - - // UV mapping configuration - const updateUVMapping = (config: { startU: number, endU: number, startV: number, endV: number }) => { - const uvs = geometry.attributes.uv.array as Float32Array - uvs[0] = config.startU - uvs[1] = config.startV - uvs[2] = config.endU - uvs[3] = config.startV - uvs[4] = config.endU - uvs[5] = config.endV - uvs[6] = config.startU - uvs[7] = config.endV - geometry.attributes.uv.needsUpdate = true - } - - // Apply initial UV mapping if provided - if (props.uvMapping) { - updateUVMapping(props.uvMapping) - } - - // Store video data - this.customMedia.set(id, { - mesh: panel, - video, - texture, - updateUVMapping - }) - - return id - } - - setVideoPlaying (id: string, playing: boolean) { - const videoData = this.customMedia.get(id) - if (videoData?.video) { - if (playing) { - videoData.video.play().catch(console.error) - } else { - videoData.video.pause() - } - } - } - - setVideoSeeking (id: string, seconds: number) { - const videoData = this.customMedia.get(id) - if (videoData?.video) { - videoData.video.currentTime = seconds - } - } - - setVideoVolume (id: string, volume: number) { - const videoData = this.customMedia.get(id) - if (videoData?.video) { - videoData.video.volume = volume - } - } - - setVideoSpeed (id: string, speed: number) { - const videoData = this.customMedia.get(id) - if (videoData?.video) { - videoData.video.playbackRate = speed - } - } - - destroyMedia (id: string) { - const media = this.customMedia.get(id) - if (media) { - if (media.video) { - media.video.pause() - media.video.src = '' - } - this.scene.remove(media.mesh) - media.texture.dispose() - - // Get the inner mesh from the group - const mesh = media.mesh.children[0] as THREE.Mesh - if (mesh) { - mesh.geometry.dispose() - if (mesh.material instanceof THREE.Material) { - mesh.material.dispose() - } - } - - this.customMedia.delete(id) - } - } - - /** - * Positions a mesh exactly at startPosition and extends it along the rotation direction - * with the specified width and height - * - * @param mesh The mesh to position - * @param rotation Rotation in radians (applied to Y axis) - * @param startPosition The exact starting position (corner) of the mesh - * @param width Width of the mesh - * @param height Height of the mesh - * @param depth Depth of the mesh (default: 1) - * @returns The positioned mesh for chaining - */ - positionMeshExact ( - mesh: THREE.Mesh, - rotation: number, - startPosition: { x: number, y: number, z: number }, - width: number, - height: number, - depth = 1 - ) { - // avoid z-fighting with the ground plane - if (rotation === 0) { - startPosition.z += 0.001 - } - if (rotation === Math.PI / 2) { - startPosition.x -= 0.001 - } - if (rotation === Math.PI) { - startPosition.z -= 0.001 - } - if (rotation === 3 * Math.PI / 2) { - startPosition.x += 0.001 - } - - // rotation normalize coordinates - if (rotation === 0) { - startPosition.z += 1 - } - if (rotation === Math.PI) { - startPosition.x += 1 - } - if (rotation === 3 * Math.PI / 2) { - startPosition.z += 1 - startPosition.x += 1 - } - - - // First, clean up any previous transformations - mesh.matrix.identity() - mesh.position.set(0, 0, 0) - mesh.rotation.set(0, 0, 0) - mesh.scale.set(1, 1, 1) - - // By default, PlaneGeometry creates a plane in the XY plane (facing +Z) - // We need to set up the proper orientation for our use case - // Rotate the plane to face the correct direction based on the rotation parameter - mesh.rotateY(rotation) - if (rotation === Math.PI / 2 || rotation === 3 * Math.PI / 2) { - mesh.rotateZ(-Math.PI) - mesh.rotateX(-Math.PI) - } - - // Scale it to the desired size - mesh.scale.set(width, height, depth) - - // For a PlaneGeometry, if we want the corner at the origin, we need to offset - // by half the dimensions after scaling - mesh.geometry.translate(0.5, 0.5, 0) - mesh.geometry.attributes.position.needsUpdate = true - - // Now place the mesh at the start position - mesh.position.set(startPosition.x, startPosition.y, startPosition.z) - - // Create a group to hold our mesh and markers - const debugGroup = new THREE.Group() - debugGroup.add(mesh) - - // Add a marker at the starting position (should be exactly at pos) - const startMarker = new THREE.Mesh( - new THREE.BoxGeometry(0.1, 0.1, 0.1), - new THREE.MeshBasicMaterial({ color: 0xff_00_00 }) - ) - startMarker.position.copy(new THREE.Vector3(startPosition.x, startPosition.y, startPosition.z)) - debugGroup.add(startMarker) - - // Add a marker at the end position (width units away in the rotated direction) - const endX = startPosition.x + Math.cos(rotation) * width - const endZ = startPosition.z + Math.sin(rotation) * width - const endYMarker = new THREE.Mesh( - new THREE.BoxGeometry(0.1, 0.1, 0.1), - new THREE.MeshBasicMaterial({ color: 0x00_00_ff }) - ) - endYMarker.position.set(startPosition.x, startPosition.y + height, startPosition.z) - debugGroup.add(endYMarker) - - // Add a marker at the width endpoint - const endWidthMarker = new THREE.Mesh( - new THREE.BoxGeometry(0.1, 0.1, 0.1), - new THREE.MeshBasicMaterial({ color: 0xff_ff_00 }) - ) - endWidthMarker.position.set(endX, startPosition.y, endZ) - debugGroup.add(endWidthMarker) - - // Add a marker at the corner diagonal endpoint (both width and height) - const endCornerMarker = new THREE.Mesh( - new THREE.BoxGeometry(0.1, 0.1, 0.1), - new THREE.MeshBasicMaterial({ color: 0xff_00_ff }) - ) - endCornerMarker.position.set(endX, startPosition.y + height, endZ) - debugGroup.add(endCornerMarker) - - // Also add a visual helper to show the rotation direction - const directionHelper = new THREE.ArrowHelper( - new THREE.Vector3(Math.cos(rotation), 0, Math.sin(rotation)), - new THREE.Vector3(startPosition.x, startPosition.y, startPosition.z), - 1, - 0xff_00_00 - ) - debugGroup.add(directionHelper) - - return { - mesh, - debugGroup - } - } - - createTestCanvasTexture () { - const canvas = document.createElement('canvas') - canvas.width = 100 - canvas.height = 100 - const ctx = canvas.getContext('2d') - if (!ctx) return null - ctx.font = '10px Arial' - ctx.fillStyle = 'red' - ctx.fillText('Hello World', 0, 10) // at - return new THREE.CanvasTexture(canvas) - } - - /** - * Creates a test mesh that demonstrates the exact positioning - */ - addTestMeshExact (rotationNum: number) { - const pos = window.cursorBlockRel().position - console.log('Creating exact positioned test mesh at:', pos) - - // Create a plane mesh with a wireframe to visualize boundaries - const plane = new THREE.Mesh( - new THREE.PlaneGeometry(1, 1), - new THREE.MeshBasicMaterial({ - // side: THREE.DoubleSide, - map: this.createTestCanvasTexture() - }) - ) - - const width = 2 - const height = 1 - const rotation = THREE.MathUtils.degToRad(rotationNum * 90) // 90 degrees in radians - - // Position the mesh exactly where we want it - const { debugGroup } = this.positionMeshExact(plane, rotation, pos, width, height) - - this.scene.add(debugGroup) - console.log('Exact test mesh added with dimensions:', width, height, 'and rotation:', rotation) - + worldStop () { + this.media.onWorldStop() } destroy (): void { - removeAllStats() super.destroy() + this.skyboxRenderer.dispose() + } + + shouldObjectVisible (object: THREE.Object3D) { + // Get chunk coordinates + const chunkX = Math.floor(object.position.x / 16) * 16 + const chunkZ = Math.floor(object.position.z / 16) * 16 + const sectionY = Math.floor(object.position.y / 16) * 16 + + const chunkKey = `${chunkX},${chunkZ}` + const sectionKey = `${chunkX},${sectionY},${chunkZ}` + + return !!this.finishedChunks[chunkKey] || !!this.sectionObjects[sectionKey] + } + + updateSectionOffsets () { + const currentTime = performance.now() + for (const [key, anim] of Object.entries(this.sectionsOffsetsAnimations)) { + const timeDelta = (currentTime - anim.time) / 1000 // Convert to seconds + anim.time = currentTime + + // Update offsets based on speed and time delta + anim.currentOffsetX += anim.speedX * timeDelta + anim.currentOffsetY += anim.speedY * timeDelta + anim.currentOffsetZ += anim.speedZ * timeDelta + + // Apply limits if they exist + if (anim.limitX !== undefined) { + if (anim.speedX > 0) { + anim.currentOffsetX = Math.min(anim.currentOffsetX, anim.limitX) + } else { + anim.currentOffsetX = Math.max(anim.currentOffsetX, anim.limitX) + } + } + if (anim.limitY !== undefined) { + if (anim.speedY > 0) { + anim.currentOffsetY = Math.min(anim.currentOffsetY, anim.limitY) + } else { + anim.currentOffsetY = Math.max(anim.currentOffsetY, anim.limitY) + } + } + if (anim.limitZ !== undefined) { + if (anim.speedZ > 0) { + anim.currentOffsetZ = Math.min(anim.currentOffsetZ, anim.limitZ) + } else { + anim.currentOffsetZ = Math.max(anim.currentOffsetZ, anim.limitZ) + } + } + + // Apply the offset to the section object + const section = this.sectionObjects[key] + if (section) { + section.position.set( + anim.currentOffsetX, + anim.currentOffsetY, + anim.currentOffsetZ + ) + section.updateMatrix() + } + } + } + + reloadWorld () { + this.entities.reloadEntities() } } @@ -1048,7 +1063,16 @@ class StarField { } } - constructor (private readonly scene: THREE.Scene) { + constructor ( + private readonly worldRenderer: WorldRendererThree + ) { + const clock = new THREE.Clock() + const speed = 0.2 + this.worldRenderer.onRender.push(() => { + if (!this.points) return + this.points.position.copy(this.worldRenderer.getCameraPosition()); + (this.points.material as StarfieldMaterial).uniforms.time.value = clock.getElapsedTime() * speed + }) } addToScene () { @@ -1059,7 +1083,6 @@ class StarField { const count = 7000 const factor = 7 const saturation = 10 - const speed = 0.2 const geometry = new THREE.BufferGeometry() @@ -1090,13 +1113,8 @@ class StarField { // Create points and add them to the scene this.points = new THREE.Points(geometry, material) - this.scene.add(this.points) + this.worldRenderer.scene.add(this.points) - const clock = new THREE.Clock() - this.points.onBeforeRender = (renderer, scene, camera) => { - this.points?.position.copy?.(camera.position) - material.uniforms.time.value = clock.getElapsedTime() * speed - } this.points.renderOrder = -1 } @@ -1104,7 +1122,7 @@ class StarField { if (this.points) { this.points.geometry.dispose(); (this.points.material as THREE.Material).dispose() - this.scene.remove(this.points) + this.worldRenderer.scene.remove(this.points) this.points = undefined } diff --git a/rsbuild.config.ts b/rsbuild.config.ts index 1701fc5c..6cd6b2ed 100644 --- a/rsbuild.config.ts +++ b/rsbuild.config.ts @@ -1,3 +1,4 @@ +/// import { defineConfig, mergeRsbuildConfig, RsbuildPluginAPI } from '@rsbuild/core' import { pluginReact } from '@rsbuild/plugin-react' import { pluginTypedCSSModules } from '@rsbuild/plugin-typed-css-modules' @@ -14,6 +15,7 @@ import { appAndRendererSharedConfig } from './renderer/rsbuildSharedConfig' import { genLargeDataAliases } from './scripts/genLargeDataAliases' import sharp from 'sharp' import supportedVersions from './src/supportedVersions.mjs' +import { startWsServer } from './scripts/wsServer' const SINGLE_FILE_BUILD = process.env.SINGLE_FILE_BUILD === 'true' @@ -48,7 +50,7 @@ if (fs.existsSync('./assets/release.json')) { const configJson = JSON.parse(fs.readFileSync('./config.json', 'utf8')) try { - Object.assign(configJson, JSON.parse(fs.readFileSync('./config.local.json', 'utf8'))) + Object.assign(configJson, JSON.parse(fs.readFileSync(process.env.LOCAL_CONFIG_FILE || './config.local.json', 'utf8'))) } catch (err) {} if (dev) { configJson.defaultProxy = ':8080' @@ -58,6 +60,8 @@ const configSource = (SINGLE_FILE_BUILD ? 'BUNDLED' : (process.env.CONFIG_JSON_S const faviconPath = 'favicon.png' +const enableMetrics = process.env.ENABLE_METRICS === 'true' + // base options are in ./renderer/rsbuildSharedConfig.ts const appConfig = defineConfig({ html: { @@ -69,7 +73,7 @@ const appConfig = defineConfig({ tag: 'link', attrs: { rel: 'manifest', - crossorigin: 'use-credentials', + crossorigin: 'anonymous', href: 'manifest.json' }, } @@ -111,6 +115,22 @@ const appConfig = defineConfig({ js: 'source-map', css: true, }, + minify: { + // js: false, + jsOptions: { + minimizerOptions: { + mangle: { + safari10: true, + keep_classnames: true, + keep_fnames: true, + keep_private_props: true, + }, + compress: { + unused: true, + }, + }, + }, + }, distPath: SINGLE_FILE_BUILD ? { html: './single', } : undefined, @@ -119,6 +139,13 @@ const appConfig = defineConfig({ // 50kb limit for data uri dataUriLimit: SINGLE_FILE_BUILD ? 1 * 1024 * 1024 * 1024 : 50 * 1024 }, + performance: { + // prefetch: { + // include(filename) { + // return filename.includes('mc-data') || filename.includes('mc-assets') + // }, + // }, + }, source: { entry: { index: './src/index.ts', @@ -134,12 +161,15 @@ const appConfig = defineConfig({ 'process.platform': '"browser"', 'process.env.GITHUB_URL': JSON.stringify(`https://github.com/${process.env.GITHUB_REPOSITORY || `${process.env.VERCEL_GIT_REPO_OWNER}/${process.env.VERCEL_GIT_REPO_SLUG}` || githubRepositoryFallback}`), - 'process.env.DEPS_VERSIONS': JSON.stringify({}), + 'process.env.ALWAYS_MINIMAL_SERVER_UI': JSON.stringify(process.env.ALWAYS_MINIMAL_SERVER_UI), 'process.env.RELEASE_TAG': JSON.stringify(releaseTag), 'process.env.RELEASE_LINK': JSON.stringify(releaseLink), 'process.env.RELEASE_CHANGELOG': JSON.stringify(releaseChangelog), 'process.env.DISABLE_SERVICE_WORKER': JSON.stringify(disableServiceWorker), 'process.env.INLINED_APP_CONFIG': JSON.stringify(configSource === 'BUNDLED' ? configJson : null), + 'process.env.ENABLE_COOKIE_STORAGE': JSON.stringify(process.env.ENABLE_COOKIE_STORAGE || true), + 'process.env.COOKIE_STORAGE_PREFIX': JSON.stringify(process.env.COOKIE_STORAGE_PREFIX || ''), + 'process.env.WS_PORT': JSON.stringify(enableMetrics ? 8081 : false), }, }, server: { @@ -167,19 +197,21 @@ const appConfig = defineConfig({ childProcess.execSync('tsx ./scripts/optimizeBlockCollisions.ts', { stdio: 'inherit' }) } // childProcess.execSync(['tsx', './scripts/genLargeDataAliases.ts', ...(SINGLE_FILE_BUILD ? ['--compressed'] : [])].join(' '), { stdio: 'inherit' }) - genLargeDataAliases(SINGLE_FILE_BUILD) + genLargeDataAliases(SINGLE_FILE_BUILD || process.env.ALWAYS_COMPRESS_LARGE_DATA === 'true') fsExtra.copySync('./node_modules/mc-assets/dist/other-textures/latest/entity', './dist/textures/entity') fsExtra.copySync('./assets/background', './dist/background') fs.copyFileSync('./assets/favicon.png', './dist/favicon.png') fs.copyFileSync('./assets/playground.html', './dist/playground.html') fs.copyFileSync('./assets/manifest.json', './dist/manifest.json') + fs.copyFileSync('./assets/config.html', './dist/config.html') + fs.copyFileSync('./assets/debug-inputs.html', './dist/debug-inputs.html') fs.copyFileSync('./assets/loading-bg.jpg', './dist/loading-bg.jpg') if (fs.existsSync('./assets/release.json')) { fs.copyFileSync('./assets/release.json', './dist/release.json') } if (configSource === 'REMOTE') { - fs.writeFileSync('./dist/config.json', JSON.stringify(configJson), 'utf8') + fs.writeFileSync('./dist/config.json', JSON.stringify(configJson, undefined, 2), 'utf8') } if (fs.existsSync('./generated/sounds.js')) { fs.copyFileSync('./generated/sounds.js', './dist/sounds.js') @@ -195,6 +227,12 @@ const appConfig = defineConfig({ await execAsync('pnpm run build-mesher') } fs.writeFileSync('./dist/version.txt', buildingVersion, 'utf-8') + + // Start WebSocket server in development + if (dev && enableMetrics) { + await startWsServer(8081, false) + } + console.timeEnd('total-prep') } if (!dev) { @@ -202,7 +240,17 @@ const appConfig = defineConfig({ prep() }) build.onAfterBuild(async () => { + if (fs.readdirSync('./assets/customTextures').length > 0) { + childProcess.execSync('tsx ./scripts/patchAssets.ts', { stdio: 'inherit' }) + } + if (SINGLE_FILE_BUILD) { + // check that only index.html is in the dist/single folder + const singleBuildFiles = fs.readdirSync('./dist/single') + if (singleBuildFiles.length !== 1 || singleBuildFiles[0] !== 'index.html') { + throw new Error('Single file build must only have index.html in the dist/single folder. Ensure workers are imported & built correctly.') + } + // process index.html const singleBuildHtml = './dist/single/index.html' let html = fs.readFileSync(singleBuildHtml, 'utf8') diff --git a/scripts/build.js b/scripts/build.js index 028a9fdc..2d5e0a2e 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -55,6 +55,7 @@ exports.getSwAdditionalEntries = () => { 'manifest.json', 'worldSaveWorker.js', `textures/entity/squid/squid.png`, + 'sounds.js', // everything but not .map 'static/**/!(*.map)', ] diff --git a/scripts/genLargeDataAliases.ts b/scripts/genLargeDataAliases.ts index 0cf206df..2372dbfd 100644 --- a/scripts/genLargeDataAliases.ts +++ b/scripts/genLargeDataAliases.ts @@ -16,7 +16,8 @@ export const genLargeDataAliases = async (isCompressed: boolean) => { let str = `${decoderCode}\nexport const importLargeData = async (mod: ${Object.keys(modules).map(x => `'${x}'`).join(' | ')}) => {\n` for (const [module, { compressed, raw }] of Object.entries(modules)) { - let importCode = `(await import('${isCompressed ? compressed : raw}')).default`; + const chunkName = module === 'mcData' ? 'mc-data' : 'mc-assets'; + let importCode = `(await import(/* webpackChunkName: "${chunkName}" */ '${isCompressed ? compressed : raw}')).default`; if (isCompressed) { importCode = `JSON.parse(decompressFromBase64(${importCode}))` } @@ -30,6 +31,8 @@ export const genLargeDataAliases = async (isCompressed: boolean) => { const decoderCode = /* ts */ ` import pako from 'pako'; +globalThis.pako = { inflate: pako.inflate.bind(pako) } + function decompressFromBase64(input) { console.time('decompressFromBase64') // Decode the Base64 string diff --git a/scripts/githubActions.mjs b/scripts/githubActions.mjs index ab786ea9..3e8eb0f6 100644 --- a/scripts/githubActions.mjs +++ b/scripts/githubActions.mjs @@ -15,6 +15,17 @@ const fns = { // set github output setOutput('alias', alias[1]) } + }, + getReleasingAlias() { + const final = (ver) => `${ver}.mcraft.fun,${ver}.pcm.gg` + const releaseJson = JSON.parse(fs.readFileSync('./assets/release.json', 'utf8')) + const tag = releaseJson.latestTag + const [major, minor, patch] = tag.replace('v', '').split('.') + if (major === '0' && minor === '1') { + setOutput('alias', final(`v${patch}`)) + } else { + setOutput('alias', final(tag)) + } } } diff --git a/scripts/makeOptimizedMcData.mjs b/scripts/makeOptimizedMcData.mjs index 05948cf2..a572d067 100644 --- a/scripts/makeOptimizedMcData.mjs +++ b/scripts/makeOptimizedMcData.mjs @@ -6,8 +6,8 @@ import { dirname } from 'node:path' import supportedVersions from '../src/supportedVersions.mjs' import { gzipSizeFromFileSync } from 'gzip-size' import fs from 'fs' -import {default as _JsonOptimizer} from '../src/optimizeJson' -import { gzipSync } from 'zlib'; +import { default as _JsonOptimizer } from '../src/optimizeJson' +import { gzipSync } from 'zlib' import MinecraftData from 'minecraft-data' import MCProtocol from 'minecraft-protocol' @@ -21,12 +21,12 @@ const require = Module.createRequire(import.meta.url) const dataPaths = require('minecraft-data/minecraft-data/data/dataPaths.json') -function toMajor (version) { +function toMajor(version) { const [a, b] = (version + '').split('.') return `${a}.${b}` } -const versions = {} +let versions = {} const dataTypes = new Set() for (const [version, dataSet] of Object.entries(dataPaths.pc)) { @@ -42,6 +42,31 @@ const versionToNumber = (ver) => { return +`${x.padStart(2, '0')}${y.padStart(2, '0')}${z.padStart(2, '0')}` } +// Version clipping support +const minVersion = process.env.MIN_MC_VERSION +const maxVersion = process.env.MAX_MC_VERSION + +// Filter versions based on MIN_VERSION and MAX_VERSION if provided +if (minVersion || maxVersion) { + const filteredVersions = {} + const minVersionNum = minVersion ? versionToNumber(minVersion) : 0 + const maxVersionNum = maxVersion ? versionToNumber(maxVersion) : Infinity + + for (const [version, dataSet] of Object.entries(versions)) { + const versionNum = versionToNumber(version) + if (versionNum >= minVersionNum && versionNum <= maxVersionNum) { + filteredVersions[version] = dataSet + } + } + + versions = filteredVersions + + console.log(`Version clipping applied: ${minVersion || 'none'} to ${maxVersion || 'none'}`) + console.log(`Processing ${Object.keys(versions).length} versions:`, Object.keys(versions).sort((a, b) => versionToNumber(a) - versionToNumber(b))) +} + +console.log('Bundling version range:', Object.keys(versions)[0], 'to', Object.keys(versions).at(-1)) + // if not included here (even as {}) will not be bundled & accessible! // const compressedOutput = !!process.env.SINGLE_FILE_BUILD const compressedOutput = true @@ -57,22 +82,27 @@ const dataTypeBundling2 = { } } const dataTypeBundling = { - language: { + language: process.env.SKIP_MC_DATA_LANGUAGE === 'true' ? { + raw: {} + } : { ignoreRemoved: true, ignoreChanges: true }, blocks: { arrKey: 'name', - processData (current, prev) { + processData(current, prev, _, version) { for (const block of current) { + const prevBlock = prev?.find(x => x.name === block.name) if (block.transparent) { const forceOpaque = block.name.includes('shulker_box') || block.name.match(/^double_.+_slab\d?$/) || ['melon_block', 'lit_pumpkin', 'lit_redstone_ore', 'lit_furnace'].includes(block.name) - const prevBlock = prev?.find(x => x.name === block.name); if (forceOpaque || (prevBlock && !prevBlock.transparent)) { block.transparent = false } } + if (block.hardness === 0 && prevBlock && prevBlock.hardness > 0) { + block.hardness = prevBlock.hardness + } } } // ignoreRemoved: true, @@ -136,7 +166,9 @@ const dataTypeBundling = { blockLoot: { arrKey: 'block' }, - recipes: { + recipes: process.env.SKIP_MC_DATA_RECIPES === 'true' ? { + raw: {} + } : { raw: true // processData: processRecipes }, @@ -150,7 +182,7 @@ const dataTypeBundling = { // } } -function processRecipes (current, prev, getData, version) { +function processRecipes(current, prev, getData, version) { // can require the same multiple times per different versions if (current._proccessed) return const items = getData('items') @@ -242,30 +274,39 @@ for (const [i, [version, dataSet]] of versionsArr.reverse().entries()) { for (const [dataType, dataPath] of Object.entries(dataSet)) { const config = dataTypeBundling[dataType] if (!config) continue - if (dataType === 'blockCollisionShapes' && versionToNumber(version) >= versionToNumber('1.13')) { - // contents += ` get ${dataType} () { return window.globalGetCollisionShapes?.("${version}") },\n` - continue - } + const ignoreCollisionShapes = dataType === 'blockCollisionShapes' && versionToNumber(version) >= versionToNumber('1.13') + let injectCode = '' - const getData = (type) => { + const getRealData = (type) => { const loc = `minecraft-data/data/${dataSet[type]}/` const dataPathAbsolute = require.resolve(`minecraft-data/${loc}${type}`) // const data = fs.readFileSync(dataPathAbsolute, 'utf8') const dataRaw = require(dataPathAbsolute) return dataRaw } - const dataRaw = getData(dataType) + const dataRaw = getRealData(dataType) let rawData = dataRaw if (config.raw) { rawDataVersions[dataType] ??= {} rawDataVersions[dataType][version] = rawData - rawData = dataRaw + if (config.raw === true) { + rawData = dataRaw + } else { + rawData = config.raw + } + + if (ignoreCollisionShapes && dataType === 'blockCollisionShapes') { + rawData = { + blocks: {}, + shapes: {} + } + } } else { if (!diffSources[dataType]) { diffSources[dataType] = new JsonOptimizer(config.arrKey, config.ignoreChanges, config.ignoreRemoved) } try { - config.processData?.(dataRaw, previousData[dataType], getData, version) + config.processData?.(dataRaw, previousData[dataType], getRealData, version) diffSources[dataType].recordDiff(version, dataRaw) injectCode = `restoreDiff(sources, ${JSON.stringify(dataType)}, ${JSON.stringify(version)})` } catch (err) { @@ -297,16 +338,16 @@ console.log('total size (mb)', totalSize / 1024 / 1024) console.log( 'size per data type (mb, %)', Object.fromEntries(Object.entries(sizePerDataType).map(([dataType, size]) => { - return [dataType, [size / 1024 / 1024, Math.round(size / totalSize * 100)]]; + return [dataType, [size / 1024 / 1024, Math.round(size / totalSize * 100)]] }).sort((a, b) => { //@ts-ignore - return b[1][1] - a[1][1]; + return b[1][1] - a[1][1] })) ) function compressToBase64(input) { - const buffer = gzipSync(input); - return buffer.toString('base64'); + const buffer = gzipSync(input) + return buffer.toString('base64') } const filePath = './generated/minecraft-data-optimized.json' @@ -330,6 +371,7 @@ console.log('size', fs.lstatSync(filePath).size / 1000 / 1000, gzipSizeFromFileS const { defaultVersion } = MCProtocol const data = MinecraftData(defaultVersion) +console.log('defaultVersion', defaultVersion, !!data) const initialMcData = { [defaultVersion]: { version: data.version, diff --git a/scripts/patchAssets.ts b/scripts/patchAssets.ts new file mode 100644 index 00000000..99994f5f --- /dev/null +++ b/scripts/patchAssets.ts @@ -0,0 +1,137 @@ +import blocksAtlas from 'mc-assets/dist/blocksAtlases.json' +import itemsAtlas from 'mc-assets/dist/itemsAtlases.json' +import * as fs from 'fs' +import * as path from 'path' +import sharp from 'sharp' + +interface AtlasFile { + latest: { + suSv: number + tileSize: number + width: number + height: number + textures: { + [key: string]: { + u: number + v: number + su: number + sv: number + tileIndex: number + } + } + } +} + +async function patchTextureAtlas( + atlasType: 'blocks' | 'items', + atlasData: AtlasFile, + customTexturesDir: string, + distDir: string +) { + // Check if custom textures directory exists and has files + if (!fs.existsSync(customTexturesDir) || fs.readdirSync(customTexturesDir).length === 0) { + return + } + + // Find the latest atlas file + const atlasFiles = fs.readdirSync(distDir) + .filter(file => file.startsWith(`${atlasType}AtlasLatest`) && file.endsWith('.png')) + .sort() + + if (atlasFiles.length === 0) { + console.log(`No ${atlasType}AtlasLatest.png found in ${distDir}`) + return + } + + const latestAtlasFile = atlasFiles[atlasFiles.length - 1] + const atlasPath = path.join(distDir, latestAtlasFile) + console.log(`Patching ${atlasPath}`) + + // Get atlas dimensions + const atlasMetadata = await sharp(atlasPath).metadata() + if (!atlasMetadata.width || !atlasMetadata.height) { + throw new Error(`Failed to get atlas dimensions for ${atlasPath}`) + } + + // Process each custom texture + const customTextureFiles = fs.readdirSync(customTexturesDir) + .filter(file => file.endsWith('.png')) + + if (customTextureFiles.length === 0) return + + // Prepare composite operations + const composites: sharp.OverlayOptions[] = [] + + for (const textureFile of customTextureFiles) { + const textureName = path.basename(textureFile, '.png') + + if (atlasData.latest.textures[textureName]) { + const textureData = atlasData.latest.textures[textureName] + const customTexturePath = path.join(customTexturesDir, textureFile) + + try { + // Convert UV coordinates to pixel coordinates + const x = Math.round(textureData.u * atlasMetadata.width) + const y = Math.round(textureData.v * atlasMetadata.height) + const width = Math.round((textureData.su ?? atlasData.latest.suSv) * atlasMetadata.width) + const height = Math.round((textureData.sv ?? atlasData.latest.suSv) * atlasMetadata.height) + + // Resize custom texture to match atlas dimensions and add to composite operations + const resizedTextureBuffer = await sharp(customTexturePath) + .resize(width, height, { + fit: 'fill', + kernel: 'nearest' // Preserve pixel art quality + }) + .png() + .toBuffer() + + composites.push({ + input: resizedTextureBuffer, + left: x, + top: y, + blend: 'over' + }) + + console.log(`Prepared ${textureName} at (${x}, ${y}) with size (${width}, ${height})`) + } catch (error) { + console.error(`Failed to prepare ${textureName}:`, error) + } + } else { + console.warn(`Texture ${textureName} not found in ${atlasType} atlas`) + } + } + + if (composites.length > 0) { + // Apply all patches at once using Sharp's composite + await sharp(atlasPath) + .composite(composites) + .png() + .toFile(atlasPath + '.tmp') + + // Replace original with patched version + fs.renameSync(atlasPath + '.tmp', atlasPath) + console.log(`Saved patched ${atlasType} atlas to ${atlasPath}`) + } +} + +async function main() { + const customBlocksDir = './assets/customTextures/blocks' + const customItemsDir = './assets/customTextures/items' + const distDir = './dist/static/image' + + try { + // Patch blocks atlas + await patchTextureAtlas('blocks', blocksAtlas as unknown as AtlasFile, customBlocksDir, distDir) + + // Patch items atlas + await patchTextureAtlas('items', itemsAtlas as unknown as AtlasFile, customItemsDir, distDir) + + console.log('Texture atlas patching completed!') + } catch (error) { + console.error('Failed to patch texture atlases:', error) + process.exit(1) + } +} + +// Run the script +main() diff --git a/scripts/prepareSounds.mjs b/scripts/prepareSounds.mjs index 7ff614a2..02026a04 100644 --- a/scripts/prepareSounds.mjs +++ b/scripts/prepareSounds.mjs @@ -11,7 +11,12 @@ import supportedVersions from '../src/supportedVersions.mjs' const __dirname = path.dirname(fileURLToPath(new URL(import.meta.url))) -const targetedVersions = supportedVersions.reverse() +export const versionToNumber = (ver) => { + const [x, y = '0', z = '0'] = ver.split('.') + return +`${x.padStart(2, '0')}${y.padStart(2, '0')}${z.padStart(2, '0')}` +} + +const targetedVersions = [...supportedVersions].sort((a, b) => versionToNumber(b) - versionToNumber(a)) /** @type {{name, size, hash}[]} */ let prevSounds = null @@ -173,13 +178,36 @@ const writeSoundsMap = async () => { // todo REMAP ONLY IDS. Do diffs, as mostly only ids are changed between versions // const localTargetedVersions = targetedVersions.slice(0, 2) + let lastMappingsJson const localTargetedVersions = targetedVersions - for (const targetedVersion of localTargetedVersions) { + for (const targetedVersion of [...localTargetedVersions].reverse()) { + console.log('Processing version', targetedVersion) + const burgerData = await fetch(burgerDataUrl(targetedVersion)).then((r) => r.json()).catch((err) => { - console.error('error fetching burger data', targetedVersion, err) + // console.error('error fetching burger data', targetedVersion, err) return null }) - if (!burgerData) continue + /** @type {{sounds: string[]}} */ + const mappingJson = await fetch(`https://raw.githubusercontent.com/ViaVersion/Mappings/7a45c1f9dbc1f1fdadacfecdb205ba84e55766fc/mappings/mapping-${targetedVersion}.json`).then(async (r) => { + return r.json() + // lastMappingsJson = r.status === 404 ? lastMappingsJson : (await r.json()) + // if (r.status === 404) { + // console.warn('using prev mappings json for ' + targetedVersion) + // } + // return lastMappingsJson + }).catch((err) => { + // console.error('error fetching mapping json', targetedVersion, err) + return null + }) + // if (!mappingJson) throw new Error('no initial mapping json for ' + targetedVersion) + if (burgerData && !mappingJson) { + console.warn('has burger but no mapping json for ' + targetedVersion) + continue + } + if (!mappingJson || !burgerData) { + console.warn('no mapping json or burger data for ' + targetedVersion) + continue + } const allSoundsMap = getSoundsMap(burgerData) // console.log(Object.keys(sounds).length, 'ids') const outputIdMap = {} @@ -190,7 +218,7 @@ const writeSoundsMap = async () => { new: 0, same: 0 } - for (const { id, subtitle, sounds, name } of Object.values(allSoundsMap)) { + for (const { _id, subtitle, sounds, name } of Object.values(allSoundsMap)) { if (!sounds?.length /* && !subtitle */) continue const firstName = sounds[0].name // const includeSound = isSoundWhitelisted(firstName) @@ -210,6 +238,11 @@ const writeSoundsMap = async () => { if (sound.weight && isNaN(sound.weight)) debugger outputUseSoundLine.push(`${sound.volume ?? 1};${sound.name};${sound.weight ?? minWeight}`) } + const id = mappingJson.sounds.findIndex(x => x === name) + if (id === -1) { + console.warn('no id for sound', name, targetedVersion) + continue + } const key = `${id};${name}` outputIdMap[key] = outputUseSoundLine.join(',') if (prevMap && prevMap[key]) { @@ -283,6 +316,6 @@ if (action) { } else { // downloadAllSoundsAndCreateMap() // convertSounds() - // writeSoundsMap() - makeSoundsBundle() + writeSoundsMap() + // makeSoundsBundle() } diff --git a/scripts/requestData.ts b/scripts/requestData.ts new file mode 100644 index 00000000..dc866a1b --- /dev/null +++ b/scripts/requestData.ts @@ -0,0 +1,42 @@ +import WebSocket from 'ws' + +function formatBytes(bytes: number) { + return `${(bytes).toFixed(2)} MB` +} + +function formatTime(ms: number) { + return `${(ms / 1000).toFixed(2)}s` +} + +const ws = new WebSocket('ws://localhost:8081') + +ws.on('open', () => { + console.log('Connected to metrics server, waiting for metrics...') +}) + +ws.on('message', (data) => { + try { + const metrics = JSON.parse(data.toString()) + console.log('\nPerformance Metrics:') + console.log('------------------') + console.log(`Load Time: ${formatTime(metrics.loadTime)}`) + console.log(`Memory Usage: ${formatBytes(metrics.memoryUsage)}`) + console.log(`Timestamp: ${new Date(metrics.timestamp).toLocaleString()}`) + if (!process.argv.includes('-f')) { // follow mode + process.exit(0) + } + } catch (error) { + console.error('Error parsing metrics:', error) + } +}) + +ws.on('error', (error) => { + console.error('WebSocket error:', error) + process.exit(1) +}) + +// Exit if no metrics received after 5 seconds +setTimeout(() => { + console.error('Timeout waiting for metrics') + process.exit(1) +}, 5000) diff --git a/scripts/updateGitDeps.ts b/scripts/updateGitDeps.ts new file mode 100644 index 00000000..797aea8f --- /dev/null +++ b/scripts/updateGitDeps.ts @@ -0,0 +1,160 @@ +import fs from 'fs' +import path from 'path' +import yaml from 'yaml' +import { execSync } from 'child_process' +import { createInterface } from 'readline' + +interface LockfilePackage { + specifier: string + version: string +} + +interface Lockfile { + importers: { + '.': { + dependencies?: Record + devDependencies?: Record + } + } +} + +interface PackageJson { + pnpm?: { + updateConfig?: { + ignoreDependencies?: string[] + } + } +} + +async function prompt(question: string): Promise { + const rl = createInterface({ + input: process.stdin, + output: process.stdout + }) + + return new Promise(resolve => { + rl.question(question, answer => { + rl.close() + resolve(answer.toLowerCase().trim()) + }) + }) +} + +async function getLatestCommit(owner: string, repo: string): Promise { + const response = await fetch(`https://api.github.com/repos/${owner}/${repo}/commits/HEAD`) + if (!response.ok) { + throw new Error(`Failed to fetch latest commit: ${response.statusText}`) + } + const data = await response.json() + return data.sha +} + +function extractGitInfo(specifier: string): { owner: string; repo: string; branch: string } | null { + const match = specifier.match(/github:([^/]+)\/([^#]+)(?:#(.+))?/) + if (!match) return null + return { + owner: match[1], + repo: match[2], + branch: match[3] || 'master' + } +} + +function extractCommitHash(version: string): string | null { + const match = version.match(/https:\/\/codeload\.github\.com\/[^/]+\/[^/]+\/tar\.gz\/([a-f0-9]+)/) + return match ? match[1] : null +} + +function getIgnoredDependencies(): string[] { + try { + const packageJsonPath = path.join(process.cwd(), 'package.json') + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as PackageJson + return packageJson.pnpm?.updateConfig?.ignoreDependencies || [] + } catch (error) { + console.warn('Failed to read package.json for ignored dependencies:', error) + return [] + } +} + +async function main() { + const lockfilePath = path.join(process.cwd(), 'pnpm-lock.yaml') + const lockfileContent = fs.readFileSync(lockfilePath, 'utf8') + const lockfile = yaml.parse(lockfileContent) as Lockfile + + const ignoredDependencies = new Set(getIgnoredDependencies()) + console.log('Ignoring dependencies:', Array.from(ignoredDependencies).join(', ') || 'none') + + const dependencies = { + ...lockfile.importers['.'].dependencies, + ...lockfile.importers['.'].devDependencies + } + + const updates: Array<{ + name: string + currentHash: string + latestHash: string + gitInfo: ReturnType + }> = [] + + console.log('\nChecking git dependencies...') + for (const [name, pkg] of Object.entries(dependencies)) { + if (ignoredDependencies.has(name)) { + console.log(`Skipping ignored dependency: ${name}`) + continue + } + + if (!pkg.specifier.startsWith('github:')) continue + + const gitInfo = extractGitInfo(pkg.specifier) + if (!gitInfo) continue + + const currentHash = extractCommitHash(pkg.version) + if (!currentHash) continue + + try { + process.stdout.write(`Checking ${name}... `) + const latestHash = await getLatestCommit(gitInfo.owner, gitInfo.repo) + if (currentHash !== latestHash) { + console.log('update available') + updates.push({ name, currentHash, latestHash, gitInfo }) + } else { + console.log('up to date') + } + } catch (error) { + console.log('failed') + console.error(`Error checking ${name}:`, error) + } + } + + if (updates.length === 0) { + console.log('\nAll git dependencies are up to date!') + return + } + + console.log('\nThe following git dependencies can be updated:') + for (const update of updates) { + console.log(`\n${update.name}:`) + console.log(` Current: ${update.currentHash}`) + console.log(` Latest: ${update.latestHash}`) + console.log(` Repo: ${update.gitInfo!.owner}/${update.gitInfo!.repo}`) + } + + const answer = await prompt('\nWould you like to update these dependencies? (y/N): ') + if (answer === 'y' || answer === 'yes') { + let newLockfileContent = lockfileContent + for (const update of updates) { + newLockfileContent = newLockfileContent.replace( + new RegExp(update.currentHash, 'g'), + update.latestHash + ) + } + fs.writeFileSync(lockfilePath, newLockfileContent) + console.log('\nUpdated pnpm-lock.yaml with new commit hashes') + // console.log('Running pnpm install to apply changes...') + // execSync('pnpm install', { stdio: 'inherit' }) + console.log('Done!') + } else { + console.log('\nNo changes were made.') + } +} + +main().catch(console.error) diff --git a/scripts/wsServer.ts b/scripts/wsServer.ts new file mode 100644 index 00000000..43035f52 --- /dev/null +++ b/scripts/wsServer.ts @@ -0,0 +1,45 @@ +import {WebSocketServer} from 'ws' + +export function startWsServer(port: number = 8081, tryOtherPort: boolean = true): Promise { + return new Promise((resolve, reject) => { + const tryPort = (currentPort: number) => { + const wss = new WebSocketServer({ port: currentPort }) + .on('listening', () => { + console.log(`WebSocket server started on port ${currentPort}`) + resolve(currentPort) + }) + .on('error', (err: any) => { + if (err.code === 'EADDRINUSE' && tryOtherPort) { + console.log(`Port ${currentPort} in use, trying ${currentPort + 1}`) + wss.close() + tryPort(currentPort + 1) + } else { + reject(err) + } + }) + + wss.on('connection', (ws) => { + console.log('Client connected') + + ws.on('message', (message) => { + try { + // Simply relay the message to all connected clients except sender + wss.clients.forEach(client => { + if (client !== ws && client.readyState === WebSocket.OPEN) { + client.send(message.toString()) + } + }) + } catch (error) { + console.error('Error processing message:', error) + } + }) + + ws.on('close', () => { + console.log('Client disconnected') + }) + }) + } + + tryPort(port) + }) +} diff --git a/server.js b/server.js index 20e66051..49699cdb 100644 --- a/server.js +++ b/server.js @@ -16,9 +16,23 @@ try { const app = express() const isProd = process.argv.includes('--prod') || process.env.NODE_ENV === 'production' +const timeoutIndex = process.argv.indexOf('--timeout') +let timeout = timeoutIndex > -1 && timeoutIndex + 1 < process.argv.length + ? parseInt(process.argv[timeoutIndex + 1]) + : process.env.TIMEOUT + ? parseInt(process.env.TIMEOUT) + : 10000 +if (isNaN(timeout) || timeout < 0) { + console.warn('Invalid timeout value provided, using default of 10000ms') + timeout = 10000 +} app.use(compression()) app.use(cors()) -app.use(netApi({ allowOrigin: '*' })) +app.use(netApi({ + allowOrigin: '*', + log: process.argv.includes('--log') || process.env.LOG === 'true', + timeout +})) if (!isProd) { app.use('/sounds', express.static(path.join(__dirname, './generated/sounds/'))) } diff --git a/src/appConfig.ts b/src/appConfig.ts index b8f83ad1..c29d74e8 100644 --- a/src/appConfig.ts +++ b/src/appConfig.ts @@ -1,7 +1,31 @@ +import { defaultsDeep } from 'lodash' import { disabledSettings, options, qsOptions } from './optionsStorage' import { miscUiState } from './globalState' import { setLoadingScreenStatus } from './appStatus' import { setStorageDataOnAppConfigLoad } from './react/appStorageProvider' +import { customKeymaps, updateBinds } from './controls' + +export type CustomAction = { + readonly type: string + readonly input: readonly any[] +} + +export type ActionType = string | CustomAction + +export type ActionHoldConfig = { + readonly command: ActionType + readonly longPressAction?: ActionType + readonly duration?: number + readonly threshold?: number +} + +export type MobileButtonConfig = { + readonly label?: string + readonly icon?: string + readonly action?: ActionType + readonly actionHold?: ActionType | ActionHoldConfig + readonly iconStyle?: React.CSSProperties +} export type AppConfig = { // defaultHost?: string @@ -11,19 +35,34 @@ export type AppConfig = { // defaultVersion?: string peerJsServer?: string peerJsServerFallback?: string - promoteServers?: Array<{ ip, description, version? }> + promoteServers?: Array<{ ip, description, name?, version?, }> mapsProvider?: string appParams?: Record // query string params + rightSideText?: string defaultSettings?: Record forceSettings?: Record // hideSettings?: Record allowAutoConnect?: boolean + splashText?: string + splashTextFallback?: string pauseLinks?: Array>> + mobileButtons?: MobileButtonConfig[] + keybindings?: Record + defaultLanguage?: string + displayLanguageSelector?: boolean + supportedLanguages?: string[] + showModsButton?: boolean + defaultUsername?: string + skinTexturesProxy?: string + alwaysReconnectButton?: boolean + reportBugButtonWithReconnect?: boolean + disabledCommands?: string[] // Array of command IDs to disable (e.g. ['general.jump', 'general.chat']) } export const loadAppConfig = (appConfig: AppConfig) => { + if (miscUiState.appConfig) { Object.assign(miscUiState.appConfig, appConfig) } else { @@ -35,7 +74,7 @@ export const loadAppConfig = (appConfig: AppConfig) => { if (value) { disabledSettings.value.add(key) // since the setting is forced, we need to set it to that value - if (appConfig.defaultSettings?.[key] && !qsOptions[key]) { + if (appConfig.defaultSettings && key in appConfig.defaultSettings && !qsOptions[key]) { options[key] = appConfig.defaultSettings[key] } } else { @@ -43,8 +82,16 @@ export const loadAppConfig = (appConfig: AppConfig) => { } } } + // todo apply defaultSettings to defaults even if not forced in case of remote config - setStorageDataOnAppConfigLoad() + if (appConfig.keybindings) { + Object.assign(customKeymaps, defaultsDeep(appConfig.keybindings, customKeymaps)) + updateBinds(customKeymaps) + } + + appViewer?.appConfigUdpate() + + setStorageDataOnAppConfigLoad(appConfig) } export const isBundledConfigUsed = !!process.env.INLINED_APP_CONFIG diff --git a/src/appParams.ts b/src/appParams.ts index b550ea02..4c8ca186 100644 --- a/src/appParams.ts +++ b/src/appParams.ts @@ -12,6 +12,7 @@ export type AppQsParams = { username?: string lockConnect?: string autoConnect?: string + alwaysReconnect?: string // googledrive.ts params state?: string // ServersListProvider.tsx params @@ -42,6 +43,11 @@ export type AppQsParams = { suggest_save?: string noPacketsValidation?: string testCrashApp?: string + onlyConnect?: string + connectText?: string + freezeSettings?: string + testIosCrash?: string + addPing?: string // Replay params replayFilter?: string @@ -51,6 +57,13 @@ export type AppQsParams = { replayStopOnError?: string replaySkipMissingOnTimeout?: string replayPacketsSenderDelay?: string + + // Benchmark params + openBenchmark?: string + renderDistance?: string + downloadBenchmark?: string + benchmarkMapZipUrl?: string + benchmarkPosition?: string } export type AppQsParamsArray = { diff --git a/src/appStatus.ts b/src/appStatus.ts index d3bfc461..101714f5 100644 --- a/src/appStatus.ts +++ b/src/appStatus.ts @@ -1,8 +1,10 @@ +import { resetStateAfterDisconnect } from './browserfs' import { hideModal, activeModalStack, showModal, miscUiState } from './globalState' import { appStatusState, resetAppStatusState } from './react/AppStatusProvider' let ourLastStatus: string | undefined = '' export const setLoadingScreenStatus = function (status: string | undefined | null, isError = false, hideDots = false, fromFlyingSquid = false, minecraftJsonMessage?: Record) { + if (typeof status === 'string') status = window.translateText?.(status) ?? status // null can come from flying squid, should restore our last status if (status === null) { status = ourLastStatus @@ -24,7 +26,6 @@ export const setLoadingScreenStatus = function (status: string | undefined | nul } showModal({ reactType: 'app-status' }) if (appStatusState.isError) { - miscUiState.gameLoaded = false return } appStatusState.hideDots = hideDots @@ -32,5 +33,9 @@ export const setLoadingScreenStatus = function (status: string | undefined | nul appStatusState.lastStatus = isError ? appStatusState.status : '' appStatusState.status = status appStatusState.minecraftJsonMessage = minecraftJsonMessage ?? null + + if (isError && miscUiState.gameLoaded) { + resetStateAfterDisconnect() + } } globalThis.setLoadingScreenStatus = setLoadingScreenStatus diff --git a/src/appViewer.ts b/src/appViewer.ts index 561204c0..628d11b4 100644 --- a/src/appViewer.ts +++ b/src/appViewer.ts @@ -1,23 +1,30 @@ -import { WorldDataEmitter } from 'renderer/viewer/lib/worldDataEmitter' -import { IPlayerState } from 'renderer/viewer/lib/basePlayerState' +import { WorldDataEmitter, WorldDataEmitterWorker } from 'renderer/viewer/lib/worldDataEmitter' +import { getInitialPlayerState, PlayerStateRenderer, PlayerStateReactive } from 'renderer/viewer/lib/basePlayerState' import { subscribeKey } from 'valtio/utils' import { defaultWorldRendererConfig, WorldRendererConfig } from 'renderer/viewer/lib/worldrendererCommon' import { Vec3 } from 'vec3' import { SoundSystem } from 'renderer/viewer/three/threeJsSound' -import { proxy } from 'valtio' +import { proxy, subscribe } from 'valtio' import { getDefaultRendererState } from 'renderer/viewer/baseGraphicsBackend' +import { getSyncWorld } from 'renderer/playground/shared' +import { MaybePromise } from 'contro-max/build/types/store' +import { PANORAMA_VERSION } from 'renderer/viewer/three/panoramaShared' import { playerState } from './mineflayer/playerState' import { createNotificationProgressReporter, ProgressReporter } from './core/progressReporter' import { setLoadingScreenStatus } from './appStatus' import { activeModalStack, miscUiState } from './globalState' import { options } from './optionsStorage' -import { ResourcesManager } from './resourcesManager' +import { ResourcesManager, ResourcesManagerTransferred } from './resourcesManager' import { watchOptionsAfterWorldViewInit } from './watchOptions' +import { loadMinecraftData } from './connect' +import { reloadChunks } from './utils' +import { displayClientChat } from './botUtils' export interface RendererReactiveState { world: { - chunksLoaded: string[] - chunksTotalNumber: number + chunksLoaded: Set + // chunksTotalNumber: number + heightmaps: Map allChunksLoaded: boolean mesherWork: boolean intersectMedia: { id: string, x: number, y: number } | null @@ -25,36 +32,53 @@ export interface RendererReactiveState { renderer: string preventEscapeMenu: boolean } +export interface NonReactiveState { + world: { + chunksLoaded: Set + chunksTotalNumber: number + } +} export interface GraphicsBackendConfig { fpsLimit?: number powerPreference?: 'high-performance' | 'low-power' statsVisible?: number sceneBackground: string + timeoutRendering?: boolean } const defaultGraphicsBackendConfig: GraphicsBackendConfig = { fpsLimit: undefined, powerPreference: undefined, - sceneBackground: 'lightblue' + sceneBackground: 'lightblue', + timeoutRendering: false } -export interface GraphicsInitOptions { - resourcesManager: ResourcesManager +export interface GraphicsInitOptions { + resourcesManager: ResourcesManagerTransferred config: GraphicsBackendConfig + rendererSpecificSettings: S - displayCriticalError: (error: Error) => void + callbacks: { + displayCriticalError: (error: Error) => void + setRendererSpecificSettings: (key: string, value: any) => void + + fireCustomEvent: (eventName: string, ...args: any[]) => void + } } export interface DisplayWorldOptions { version: string - worldView: WorldDataEmitter + worldView: WorldDataEmitterWorker inWorldRenderingConfig: WorldRendererConfig - playerState: IPlayerState + playerStateReactive: PlayerStateReactive rendererState: RendererReactiveState + nonReactiveState: NonReactiveState } -export type GraphicsBackendLoader = (options: GraphicsInitOptions) => GraphicsBackend +export type GraphicsBackendLoader = ((options: GraphicsInitOptions) => MaybePromise) & { + id: string +} // no sync methods export interface GraphicsBackend { @@ -62,7 +86,7 @@ export interface GraphicsBackend { displayName?: string startPanorama: () => void // prepareResources: (version: string, progressReporter: ProgressReporter) => Promise - startWorld: (options: DisplayWorldOptions) => void + startWorld: (options: DisplayWorldOptions) => Promise | void disconnect: () => void setRendering: (rendering: boolean) => void getDebugOverlay?: () => Record @@ -74,6 +98,8 @@ export interface GraphicsBackend { } export class AppViewer { + waitBackendLoadPromises = [] as Array> + resourcesManager = new ResourcesManager() worldView: WorldDataEmitter | undefined readonly config: GraphicsBackendConfig = { @@ -90,7 +116,8 @@ export class AppViewer { inWorldRenderingConfig: WorldRendererConfig = proxy(defaultWorldRendererConfig) lastCamUpdate = 0 playerState = playerState - rendererState = proxy(getDefaultRendererState()) + rendererState = getDefaultRendererState().reactive + nonReactiveState: NonReactiveState = getDefaultRendererState().nonReactive worldReady: Promise private resolveWorldReady: () => void @@ -98,21 +125,40 @@ export class AppViewer { this.disconnectBackend() } - loadBackend (loader: GraphicsBackendLoader) { + async loadBackend (loader: GraphicsBackendLoader) { if (this.backend) { this.disconnectBackend() } + await Promise.all(this.waitBackendLoadPromises) + this.waitBackendLoadPromises = [] + this.backendLoader = loader - const loaderOptions: GraphicsInitOptions = { - resourcesManager: this.resourcesManager, - config: this.config, - displayCriticalError (error) { - console.error(error) - setLoadingScreenStatus(error.message, true) - }, + const rendererSpecificSettings = {} as Record + const rendererSettingsKey = `renderer.${this.backendLoader?.id}` + for (const key in options) { + if (key.startsWith(rendererSettingsKey)) { + rendererSpecificSettings[key.slice(rendererSettingsKey.length + 1)] = options[key] + } } - this.backend = loader(loaderOptions) + const loaderOptions: GraphicsInitOptions = { // todo! + resourcesManager: this.resourcesManager as ResourcesManagerTransferred, + config: this.config, + callbacks: { + displayCriticalError (error) { + console.error(error) + setLoadingScreenStatus(error.message, true) + }, + setRendererSpecificSettings (key: string, value: any) { + options[`${rendererSettingsKey}.${key}`] = value + }, + fireCustomEvent (eventName, ...args) { + // this.callbacks.fireCustomEvent(eventName, ...args) + } + }, + rendererSpecificSettings, + } + this.backend = await loader(loaderOptions) // if (this.resourcesManager.currentResources) { // void this.prepareResources(this.resourcesManager.currentResources.version, createNotificationProgressReporter()) @@ -120,56 +166,90 @@ export class AppViewer { // Execute queued action if exists if (this.currentState) { - const { method, args } = this.currentState - this.backend[method](...args) - if (method === 'startWorld') { - void this.worldView!.init(args[0].playerState.getPosition()) + if (this.currentState.method === 'startPanorama') { + this.startPanorama() + } else { + const { method, args } = this.currentState + this.backend[method](...args) + if (method === 'startWorld') { + void this.worldView!.init(bot.entity.position) + // void this.worldView!.init(args[0].playerState.getPosition()) + } } } + + // todo + modalStackUpdateChecks() + } + + async startWithBot () { + const renderDistance = miscUiState.singleplayer ? options.renderDistance : options.multiplayerRenderDistance + await this.startWorld(bot.world, renderDistance) + this.worldView!.listenToBot(bot) + } + + appConfigUdpate () { + if (miscUiState.appConfig) { + this.inWorldRenderingConfig.skinTexturesProxy = miscUiState.appConfig.skinTexturesProxy + } } - startWorld (world, renderDistance: number, playerStateSend: IPlayerState = playerState) { + async startWorld (world, renderDistance: number, playerStateSend: PlayerStateRenderer = this.playerState.reactive) { if (this.currentDisplay === 'world') throw new Error('World already started') this.currentDisplay = 'world' - const startPosition = playerStateSend.getPosition() + const startPosition = bot.entity?.position ?? new Vec3(0, 64, 0) this.worldView = new WorldDataEmitter(world, renderDistance, startPosition) + this.worldView.panicChunksReload = () => { + if (!options.experimentalClientSelfReload) return + if (process.env.NODE_ENV === 'development') { + displayClientChat(`[client] client panicked due to too long loading time. Soft reloading chunks...`) + } + void reloadChunks() + } window.worldView = this.worldView watchOptionsAfterWorldViewInit(this.worldView) + this.appConfigUdpate() const displayWorldOptions: DisplayWorldOptions = { version: this.resourcesManager.currentConfig!.version, worldView: this.worldView, inWorldRenderingConfig: this.inWorldRenderingConfig, - playerState: playerStateSend, - rendererState: this.rendererState + playerStateReactive: playerStateSend, + rendererState: this.rendererState, + nonReactiveState: this.nonReactiveState } + let promise: undefined | Promise if (this.backend) { - this.backend.startWorld(displayWorldOptions) - void this.worldView.init(startPosition) + promise = this.backend.startWorld(displayWorldOptions) ?? undefined + // void this.worldView.init(startPosition) } this.currentState = { method: 'startWorld', args: [displayWorldOptions] } + await promise // Resolve the promise after world is started this.resolveWorldReady() + return !!promise } resetBackend (cleanState = false) { - if (cleanState) { - this.currentState = undefined - this.currentDisplay = null - this.worldView = undefined - } + this.disconnectBackend(cleanState) if (this.backendLoader) { - this.loadBackend(this.backendLoader) + void this.loadBackend(this.backendLoader) } } startPanorama () { if (this.currentDisplay === 'menu') return - this.currentDisplay = 'menu' if (options.disableAssets) return - if (this.backend) { - this.backend.startPanorama() + if (this.backend && !hasAppStatus()) { + this.currentDisplay = 'menu' + if (process.env.SINGLE_FILE_BUILD_MODE) { + void loadMinecraftData(PANORAMA_VERSION).then(() => { + this.backend?.startPanorama() + }) + } else { + this.backend.startPanorama() + } } this.currentState = { method: 'startPanorama', args: [] } } @@ -185,7 +265,12 @@ export class AppViewer { this.resourcesManager.destroy() } - disconnectBackend () { + disconnectBackend (cleanState = false) { + if (cleanState) { + this.currentState = undefined + this.currentDisplay = null + this.worldView = undefined + } if (this.backend) { this.backend.disconnect() this.backend = undefined @@ -194,7 +279,8 @@ export class AppViewer { const { promise, resolve } = Promise.withResolvers() this.worldReady = promise this.resolveWorldReady = resolve - Object.assign(this.rendererState, getDefaultRendererState()) + this.rendererState = proxy(getDefaultRendererState().reactive) + this.nonReactiveState = getDefaultRendererState().nonReactive // this.queuedDisplay = undefined } @@ -215,6 +301,7 @@ export class AppViewer { } } +// do not import this. Use global appViewer instead (without window prefix). export const appViewer = new AppViewer() window.appViewer = appViewer @@ -222,30 +309,46 @@ const initialMenuStart = async () => { if (appViewer.currentDisplay === 'world') { appViewer.resetBackend(true) } - appViewer.startPanorama() + const demo = new URLSearchParams(window.location.search).get('demo') + if (!demo) { + appViewer.startPanorama() + return + } - // await appViewer.resourcesManager.loadMcData('1.21.4') - // const world = getSyncWorld('1.21.4') - // await appViewer.prepareResources('1.21.4', createNullProgressReporter()) - // world.setBlockStateId(new Vec3(0, 64, 0), 1) - // appViewer.startWorld(world, 3, new Vec3(0, 64, 0), new BasePlayerState()) - // appViewer.backend?.updateCamera(new Vec3(0, 64, 2), 0, 0) - // void appViewer.worldView.init(new Vec3(0, 64, 0)) + // const version = '1.18.2' + const version = '1.21.4' + const { loadMinecraftData } = await import('./connect') + const { getSyncWorld } = await import('../renderer/playground/shared') + await loadMinecraftData(version) + const world = getSyncWorld(version) + world.setBlockStateId(new Vec3(0, 64, 0), loadedData.blocksByName.water.defaultState) + world.setBlockStateId(new Vec3(1, 64, 0), loadedData.blocksByName.water.defaultState) + world.setBlockStateId(new Vec3(1, 64, 1), loadedData.blocksByName.water.defaultState) + world.setBlockStateId(new Vec3(0, 64, 1), loadedData.blocksByName.water.defaultState) + world.setBlockStateId(new Vec3(-1, 64, -1), loadedData.blocksByName.water.defaultState) + world.setBlockStateId(new Vec3(-1, 64, 0), loadedData.blocksByName.water.defaultState) + world.setBlockStateId(new Vec3(0, 64, -1), loadedData.blocksByName.water.defaultState) + appViewer.resourcesManager.currentConfig = { version } + appViewer.playerState.reactive = getInitialPlayerState() + await appViewer.resourcesManager.updateAssetsData({}) + await appViewer.startWorld(world, 3) + appViewer.backend!.updateCamera(new Vec3(0, 65.7, 0), 0, -Math.PI / 2) // Y+1 and pitch = PI/2 to look down + void appViewer.worldView!.init(new Vec3(0, 64, 0)) } window.initialMenuStart = initialMenuStart +const hasAppStatus = () => activeModalStack.some(m => m.reactType === 'app-status') + const modalStackUpdateChecks = () => { // maybe start panorama - if (activeModalStack.length === 0 && !miscUiState.gameLoaded) { + if (!miscUiState.gameLoaded && !hasAppStatus()) { void initialMenuStart() } if (appViewer.backend) { - const hasAppStatus = activeModalStack.some(m => m.reactType === 'app-status') - appViewer.backend.setRendering(!hasAppStatus) + appViewer.backend.setRendering(!hasAppStatus()) } appViewer.inWorldRenderingConfig.foreground = activeModalStack.length === 0 } -subscribeKey(activeModalStack, 'length', modalStackUpdateChecks) -modalStackUpdateChecks() +subscribe(activeModalStack, modalStackUpdateChecks) diff --git a/src/appViewerLoad.ts b/src/appViewerLoad.ts new file mode 100644 index 00000000..53260662 --- /dev/null +++ b/src/appViewerLoad.ts @@ -0,0 +1,51 @@ +import { subscribeKey } from 'valtio/utils' +import createGraphicsBackend from 'renderer/viewer/three/graphicsBackend' +import { options } from './optionsStorage' +import { appViewer } from './appViewer' +import { miscUiState } from './globalState' +import { watchOptionsAfterViewerInit } from './watchOptions' +import { showNotification } from './react/NotificationProvider' + +const backends = [ + createGraphicsBackend, +] +const loadBackend = async () => { + let backend = backends.find(backend => backend.id === options.activeRenderer) + if (!backend) { + showNotification(`No backend found for renderer ${options.activeRenderer}`, `Falling back to ${backends[0].id}`, true) + backend = backends[0] + } + await appViewer.loadBackend(backend) +} +window.loadBackend = loadBackend +if (process.env.SINGLE_FILE_BUILD_MODE) { + const unsub = subscribeKey(miscUiState, 'fsReady', () => { + if (miscUiState.fsReady) { + // don't do it earlier to load fs and display menu faster + void loadBackend() + unsub() + } + }) +} else { + setTimeout(() => { + void loadBackend() + }) +} + +const animLoop = () => { + for (const fn of beforeRenderFrame) fn() + requestAnimationFrame(animLoop) +} +requestAnimationFrame(animLoop) + +watchOptionsAfterViewerInit() + +// reset backend when renderer changes + +subscribeKey(options, 'activeRenderer', async () => { + if (appViewer.currentDisplay === 'world' && bot) { + appViewer.resetBackend(true) + await loadBackend() + void appViewer.startWithBot() + } +}) diff --git a/src/basicSounds.ts b/src/basicSounds.ts index 40428c6b..54af0d35 100644 --- a/src/basicSounds.ts +++ b/src/basicSounds.ts @@ -7,7 +7,12 @@ let audioContext: AudioContext const sounds: Record = {} // Track currently playing sounds and their gain nodes -const activeSounds: Array<{ source: AudioBufferSourceNode; gainNode: GainNode; volumeMultiplier: number }> = [] +const activeSounds: Array<{ + source: AudioBufferSourceNode; + gainNode: GainNode; + volumeMultiplier: number; + isMusic: boolean; +}> = [] window.activeSounds = activeSounds // load as many resources on page load as possible instead on demand as user can disable internet connection after he thinks the page is loaded @@ -43,7 +48,7 @@ export async function loadSound (path: string, contents = path) { } } -export const loadOrPlaySound = async (url, soundVolume = 1, loadTimeout = 500) => { +export const loadOrPlaySound = async (url, soundVolume = 1, loadTimeout = options.remoteSoundsLoadTimeout, loop = false, isMusic = false) => { const soundBuffer = sounds[url] if (!soundBuffer) { const start = Date.now() @@ -51,11 +56,11 @@ export const loadOrPlaySound = async (url, soundVolume = 1, loadTimeout = 500) = if (cancelled || Date.now() - start > loadTimeout) return } - return playSound(url, soundVolume) + return playSound(url, soundVolume, loop, isMusic) } -export async function playSound (url, soundVolume = 1) { - const volume = soundVolume * (options.volume / 100) +export async function playSound (url, soundVolume = 1, loop = false, isMusic = false) { + const volume = soundVolume * (options.volume / 100) * (isMusic ? options.musicVolume / 100 : 1) if (!volume) return @@ -75,13 +80,14 @@ export async function playSound (url, soundVolume = 1) { const gainNode = audioContext.createGain() const source = audioContext.createBufferSource() source.buffer = soundBuffer + source.loop = loop source.connect(gainNode) gainNode.connect(audioContext.destination) gainNode.gain.value = volume source.start(0) // Add to active sounds - activeSounds.push({ source, gainNode, volumeMultiplier: soundVolume }) + activeSounds.push({ source, gainNode, volumeMultiplier: soundVolume, isMusic }) const callbacks = [] as Array<() => void> source.onended = () => { @@ -99,6 +105,17 @@ export async function playSound (url, soundVolume = 1) { onEnded (callback: () => void) { callbacks.push(callback) }, + stop () { + try { + source.stop() + // Remove from active sounds + const index = activeSounds.findIndex(s => s.source === source) + if (index !== -1) activeSounds.splice(index, 1) + } catch (err) { + console.warn('Failed to stop sound:', err) + } + }, + gainNode, } } @@ -113,11 +130,24 @@ export function stopAllSounds () { activeSounds.length = 0 } -export function changeVolumeOfCurrentlyPlayingSounds (newVolume: number) { - const normalizedVolume = newVolume / 100 - for (const { gainNode, volumeMultiplier } of activeSounds) { +export function stopSound (url: string) { + const soundIndex = activeSounds.findIndex(s => s.source.buffer === sounds[url]) + if (soundIndex !== -1) { + const { source } = activeSounds[soundIndex] try { - gainNode.gain.value = normalizedVolume * volumeMultiplier + source.stop() + } catch (err) { + console.warn('Failed to stop sound:', err) + } + activeSounds.splice(soundIndex, 1) + } +} + +export function changeVolumeOfCurrentlyPlayingSounds (newVolume: number, newMusicVolume: number) { + const normalizedVolume = newVolume / 100 + for (const { gainNode, volumeMultiplier, isMusic } of activeSounds) { + try { + gainNode.gain.value = normalizedVolume * volumeMultiplier * (isMusic ? newMusicVolume / 100 : 1) } catch (err) { console.warn('Failed to change sound volume:', err) } @@ -125,5 +155,9 @@ export function changeVolumeOfCurrentlyPlayingSounds (newVolume: number) { } subscribeKey(options, 'volume', () => { - changeVolumeOfCurrentlyPlayingSounds(options.volume) + changeVolumeOfCurrentlyPlayingSounds(options.volume, options.musicVolume) +}) + +subscribeKey(options, 'musicVolume', () => { + changeVolumeOfCurrentlyPlayingSounds(options.volume, options.musicVolume) }) diff --git a/src/benchmark.ts b/src/benchmark.ts new file mode 100644 index 00000000..42603a10 --- /dev/null +++ b/src/benchmark.ts @@ -0,0 +1,311 @@ +import { Vec3 } from 'vec3' +import { WorldRendererCommon } from 'renderer/viewer/lib/worldrendererCommon' +import prettyBytes from 'pretty-bytes' +import { subscribe } from 'valtio' +import { downloadAndOpenMapFromUrl } from './downloadAndOpenFile' +import { activeModalStack, miscUiState } from './globalState' +import { disabledSettings, options } from './optionsStorage' +import { BenchmarkAdapterInfo, getAllInfoLines } from './benchmarkAdapter' +import { appQueryParams } from './appParams' +import { getScreenRefreshRate } from './utils' +import { setLoadingScreenStatus } from './appStatus' + +const DEFAULT_RENDER_DISTANCE = 5 + +interface BenchmarkFixture { + urlZip?: string + urlDir?: string[] + replayFileUrl?: string + spawn?: [number, number, number] +} + +const fixtures: Record = { + default: { + urlZip: 'https://bucket.mcraft.fun/Future CITY 4.4-slim.zip', + spawn: [-133, 87, 309] as [number, number, number], + }, + dir: { + urlDir: ['https://bucket.mcraft.fun/Greenfield%20v0.5.1/map-index.json', 'https://mcraft-proxy.vercel.app/0/bucket.mcraft.fun/Greenfield%20v0.5.1/map-index.json'], + }, + replay: { + replayFileUrl: 'https://raw.githubusercontent.com/zardoy/mcraft-fun-replays/refs/heads/main/hypepixel-tnt-lobby.worldstate.txt', + }, +} + +Error.stackTraceLimit = Error.stackTraceLimit < 30 ? 30 : Error.stackTraceLimit + +const SESSION_STORAGE_BACKUP_KEY = 'benchmark-backup' +export const openBenchmark = async (renderDistance = DEFAULT_RENDER_DISTANCE) => { + let fixtureNameOpen = appQueryParams.openBenchmark + if (!fixtureNameOpen || fixtureNameOpen === '1' || fixtureNameOpen === 'true' || fixtureNameOpen === 'zip') { + fixtureNameOpen = 'default' + } + + + if (sessionStorage.getItem(SESSION_STORAGE_BACKUP_KEY)) { + const backup = JSON.stringify(JSON.parse(sessionStorage.getItem(SESSION_STORAGE_BACKUP_KEY)!), null, 2) + setLoadingScreenStatus('Either other tab with benchmark is open or page crashed. Last data backup is downloaded. Reload page to retry.') + // download file + const a = document.createElement('a') + a.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(backup) + a.download = `benchmark-${appViewer.backend?.id}.txt` + a.click() + sessionStorage.removeItem(SESSION_STORAGE_BACKUP_KEY) + return + } + + const fixture: BenchmarkFixture = appQueryParams.benchmarkMapZipUrl ? { + urlZip: appQueryParams.benchmarkMapZipUrl, + spawn: appQueryParams.benchmarkPosition ? appQueryParams.benchmarkPosition.split(',').map(Number) as [number, number, number] : fixtures.default.spawn, + } : fixtures[fixtureNameOpen] + + if (!fixture) { + setLoadingScreenStatus(`Benchmark fixture ${fixtureNameOpen} not found`) + return + } + + let memoryUsageAverage = 0 + let memoryUsageSamples = 0 + let memoryUsageWorst = 0 + setInterval(() => { + const memoryUsage = (window.performance as any)?.memory?.usedJSHeapSize + if (memoryUsage) { + memoryUsageAverage = (memoryUsageAverage * memoryUsageSamples + memoryUsage) / (memoryUsageSamples + 1) + memoryUsageSamples++ + if (memoryUsage > memoryUsageWorst) { + memoryUsageWorst = memoryUsage + } + } + }, 200) + + let mainThreadFpsAverage = 0 + let mainThreadFpsWorst = undefined as number | undefined + let mainThreadFpsSamples = 0 + let currentPassedFrames = 0 + const mainLoop = () => { + currentPassedFrames++ + requestAnimationFrame(mainLoop) + } + requestAnimationFrame(mainLoop) + setInterval(() => { + mainThreadFpsAverage = (mainThreadFpsAverage * mainThreadFpsSamples + currentPassedFrames) / (mainThreadFpsSamples + 1) + mainThreadFpsSamples++ + if (mainThreadFpsWorst === undefined) { + mainThreadFpsWorst = currentPassedFrames + } else { + mainThreadFpsWorst = Math.min(mainThreadFpsWorst, currentPassedFrames) + } + currentPassedFrames = 0 + }, 1000) + + // todo urlDir fix + let fixtureName = `${fixture.urlZip ?? fixture.urlDir?.join('|') ?? fixture.replayFileUrl ?? 'unknown'}` + if (fixture.spawn) { + fixtureName += ` - ${fixture.spawn.join(' ')}` + } + + fixtureName += ` - ${renderDistance}` + if (process.env.NODE_ENV !== 'development') { // do not delay + setLoadingScreenStatus('Benchmark requested... Getting screen refresh rate') + await new Promise(resolve => { + setTimeout(resolve, 1000) + }) + } + let start = 0 + // interval to backup data in sessionStorage in case of page crash + const saveBackupInterval = setInterval(() => { + if (!window.world) return + const backup = JSON.parse(JSON.stringify(window.benchmarkAdapter)) + backup.timePassed = ((Date.now() - start) / 1000).toFixed(2) + sessionStorage.setItem(SESSION_STORAGE_BACKUP_KEY, JSON.stringify(backup)) + }, 500) + + const screenRefreshRate = await getScreenRefreshRate() + const benchmarkAdapter: BenchmarkAdapterInfo = { + get fixture () { + return fixtureName + }, + get worldLoadTimeSeconds () { + return window.worldLoadTime + }, + get mesherWorkersCount () { + return (window.world as WorldRendererCommon).worldRendererConfig.mesherWorkers + }, + get mesherProcessAvgMs () { + return (window.world as WorldRendererCommon).workersProcessAverageTime + }, + get mesherProcessTotalMs () { + return (window.world as WorldRendererCommon).workersProcessAverageTime * (window.world as WorldRendererCommon).workersProcessAverageTimeCount + }, + get mesherProcessWorstMs () { + return (window.world as WorldRendererCommon).maxWorkersProcessTime + }, + get chunksFullInfo () { + return (window.world as WorldRendererCommon).chunksFullInfo + }, + get averageRenderTimeMs () { + return (window.world as WorldRendererCommon).renderTimeAvg + }, + get worstRenderTimeMs () { + return (window.world as WorldRendererCommon).renderTimeMax + }, + get fpsAveragePrediction () { + const avgRenderTime = (window.world as WorldRendererCommon).renderTimeAvg + return 1000 / avgRenderTime + }, + get fpsWorstPrediction () { + const maxRenderTime = (window.world as WorldRendererCommon).renderTimeMax + return 1000 / maxRenderTime + }, + get fpsAverageReal () { + return `${(window.world as WorldRendererCommon).fpsAverage.toFixed(0)} / ${screenRefreshRate}` + }, + get fpsWorstReal () { + return (window.world as WorldRendererCommon).fpsWorst ?? -1 + }, + get backendInfoReport () { + return (window.world as WorldRendererCommon).backendInfoReport + }, + get fpsAverageMainThread () { + return mainThreadFpsAverage + }, + get fpsWorstMainThread () { + return mainThreadFpsWorst ?? -1 + }, + get memoryUsageAverage () { + return prettyBytes(memoryUsageAverage) + }, + get memoryUsageWorst () { + return prettyBytes(memoryUsageWorst) + }, + get gpuInfo () { + return appViewer.rendererState.renderer + }, + get hardwareConcurrency () { + return navigator.hardwareConcurrency + }, + get userAgent () { + return navigator.userAgent + }, + clientVersion: `${process.env.RELEASE_TAG} ${process.env.BUILD_VERSION} ${process.env.RELEASE_LINK ?? ''}`, + } + window.benchmarkAdapter = benchmarkAdapter + + disabledSettings.value.add('renderDistance') + options.renderDistance = renderDistance + disabledSettings.value.add('renderDebug') + options.renderDebug = 'advanced' + disabledSettings.value.add('waitForChunksRender') + options.waitForChunksRender = false + + void downloadAndOpenMapFromUrl(fixture.urlZip, undefined, fixture.urlDir, fixture.replayFileUrl, { + connectEvents: { + serverCreated () { + if (fixture.spawn) { + localServer!.spawnPoint = new Vec3(...fixture.spawn) + localServer!.on('newPlayer', (player) => { + player.on('dataLoaded', () => { + player.position = new Vec3(...fixture.spawn!) + start = Date.now() + }) + }) + } + }, + } + }) + + document.addEventListener('cypress-world-ready', () => { + clearInterval(saveBackupInterval) + sessionStorage.removeItem(SESSION_STORAGE_BACKUP_KEY) + let stats = getAllInfoLines(window.benchmarkAdapter) + const downloadFile = () => { + // const changedSettings = + + const a = document.createElement('a') + a.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(stats.join('\n')) + a.download = `benchmark-${appViewer.backend?.id}.txt` + a.click() + } + if (appQueryParams.downloadBenchmark) { + downloadFile() + } + + const panel = document.createElement('div') + panel.style.position = 'fixed' + panel.style.top = '20px' + panel.style.right = '10px' + panel.style.backgroundColor = 'rgba(0,0,0,0.8)' + panel.style.color = 'white' + panel.style.padding = '10px' + panel.style.zIndex = '1000' + panel.style.fontFamily = 'monospace' + panel.style.maxWidth = '80%' + panel.style.maxHeight = '90vh' + panel.style.overflow = 'auto' + panel.id = 'benchmark-panel' + + // Add download button + const downloadButton = document.createElement('button') + downloadButton.textContent = 'Download Results' + downloadButton.style.marginBottom = '10px' + downloadButton.style.padding = '5px 10px' + downloadButton.style.backgroundColor = '#4CAF50' + downloadButton.style.color = 'white' + downloadButton.style.border = 'none' + downloadButton.style.borderRadius = '4px' + downloadButton.style.cursor = 'pointer' + downloadButton.onclick = downloadFile + panel.appendChild(downloadButton) + + const pre = document.createElement('pre') + pre.style.whiteSpace = 'pre-wrap' + pre.style.wordBreak = 'break-word' + panel.appendChild(pre) + + pre.textContent = stats.join('\n') + const updateStats = () => { + stats = getAllInfoLines(window.benchmarkAdapter) + pre.textContent = stats.join('\n') + } + + document.body.appendChild(panel) + // setInterval(updateStats, 100) + }) +} + +// add before unload +window.addEventListener('beforeunload', () => { + // remove sessionStorage backup + sessionStorage.removeItem(SESSION_STORAGE_BACKUP_KEY) +}) + +document.addEventListener('pointerlockchange', (e) => { + const panel = document.querySelector('#benchmark-panel') + if (panel) { + panel.hidden = !!document.pointerLockElement + } +}) + +subscribe(activeModalStack, () => { + const panel = document.querySelector('#benchmark-panel') + if (panel && activeModalStack.length > 1) { + panel.hidden = true + } +}) + +export const registerOpenBenchmarkListener = () => { + if (appQueryParams.openBenchmark) { + void openBenchmark(appQueryParams.renderDistance ? +appQueryParams.renderDistance : undefined) + } + + window.addEventListener('keydown', (e) => { + if (e.code === 'KeyB' && e.shiftKey && !miscUiState.gameLoaded && activeModalStack.length === 0) { + e.preventDefault() + // add ?openBenchmark=true to url without reload + const url = new URL(window.location.href) + url.searchParams.set('openBenchmark', 'true') + window.history.replaceState({}, '', url.toString()) + void openBenchmark() + } + }) +} diff --git a/src/benchmarkAdapter.ts b/src/benchmarkAdapter.ts new file mode 100644 index 00000000..e3da6669 --- /dev/null +++ b/src/benchmarkAdapter.ts @@ -0,0 +1,66 @@ +import { noCase } from 'change-case' + +export interface BenchmarkAdapterInfo { + fixture: string + // general load info + worldLoadTimeSeconds: number + + // mesher + mesherWorkersCount: number + mesherProcessAvgMs: number + mesherProcessWorstMs: number + mesherProcessTotalMs: number + chunksFullInfo: string + + // rendering backend + averageRenderTimeMs: number + worstRenderTimeMs: number + fpsAveragePrediction: number + fpsWorstPrediction: number + fpsAverageReal: string + fpsWorstReal: number + backendInfoReport: string + + // main thread + fpsAverageMainThread: number + fpsWorstMainThread: number + + // memory total + memoryUsageAverage: string + memoryUsageWorst: string + + // context info + gpuInfo: string + hardwareConcurrency: number + userAgent: string + clientVersion: string +} + +export const getAllInfo = (adapter: BenchmarkAdapterInfo) => { + return Object.fromEntries( + Object.entries(adapter).map(([key, value]) => { + if (typeof value === 'function') { + value = (value as () => any)() + } + if (typeof value === 'number') { + value = value.toFixed(2) + } + return [noCase(key), value] + }) + ) +} + +export const getAllInfoLines = (adapter: BenchmarkAdapterInfo, delayed = false) => { + const info = getAllInfo(adapter) + if (delayed) { + for (const key in info) { + if (key !== 'fpsAveragePrediction' && key !== 'fpsAverageReal') { + delete info[key] + } + } + } + + return Object.entries(info).map(([key, value]) => { + return `${key}${delayed ? ' (delayed)' : ''}: ${value}` + }) +} diff --git a/src/botUtils.ts b/src/botUtils.ts index 5a6f92f7..10609322 100644 --- a/src/botUtils.ts +++ b/src/botUtils.ts @@ -21,15 +21,15 @@ export const displayClientChat = (text: string) => { } export const parseFormattedMessagePacket = (arg) => { - // if (typeof arg === 'string') { - // try { - // arg = JSON.parse(arg) - // return { - // formatted: arg, - // plain: '' - // } - // } catch {} - // } + if (typeof arg === 'string') { + try { + arg = JSON.parse(arg) + return { + formatted: arg, + plain: '' + } + } catch {} + } if (typeof arg === 'object') { try { return { diff --git a/src/browserfs.ts b/src/browserfs.ts index 9fb0771f..006b6db8 100644 --- a/src/browserfs.ts +++ b/src/browserfs.ts @@ -16,6 +16,7 @@ import { packetsReplayState } from './react/state/packetsReplayState' import { createFullScreenProgressReporter } from './core/progressReporter' import { showNotification } from './react/NotificationProvider' import { resetAppStorage } from './react/appStorageProvider' +import { ConnectOptions } from './connect' const { GoogleDriveFileSystem } = require('google-drive-browserfs/src/backends/GoogleDrive') browserfs.install(window) @@ -262,7 +263,7 @@ export const mountGoogleDriveFolder = async (readonly: boolean, rootId: string) return true } -export async function removeFileRecursiveAsync (path) { +export async function removeFileRecursiveAsync (path, removeDirectoryItself = true) { const errors = [] as Array<[string, Error]> try { const files = await fs.promises.readdir(path) @@ -281,7 +282,9 @@ export async function removeFileRecursiveAsync (path) { })) // After removing all files/directories, remove the current directory - await fs.promises.rmdir(path) + if (removeDirectoryItself) { + await fs.promises.rmdir(path) + } } catch (error) { errors.push([path, error]) } @@ -558,7 +561,7 @@ export const openWorldFromHttpDir = async (fileDescriptorUrls: string[]/* | und } // todo rename method -const openWorldZipInner = async (file: File | ArrayBuffer, name = file['name']) => { +const openWorldZipInner = async (file: File | ArrayBuffer, name = file['name'], connectOptions?: Partial) => { await new Promise(async resolve => { browserfs.configure({ // todo @@ -603,7 +606,7 @@ const openWorldZipInner = async (file: File | ArrayBuffer, name = file['name']) } if (availableWorlds.length === 1) { - await loadSave(`/world/${availableWorlds[0]}`) + await loadSave(`/world/${availableWorlds[0]}`, connectOptions) return } diff --git a/src/builtinCommands.ts b/src/builtinCommands.ts index 278ff57f..a292c5cd 100644 --- a/src/builtinCommands.ts +++ b/src/builtinCommands.ts @@ -1,12 +1,14 @@ import fs from 'fs' import { join } from 'path' import JSZip from 'jszip' -import { readLevelDat } from './loadSave' +import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' +import { fsState, readLevelDat } from './loadSave' import { closeWan, openToWanAndCopyJoinLink } from './localServerMultiplayer' import { copyFilesAsync, uniqueFileNameFromWorldName } from './browserfs' import { saveServer } from './flyingSquidUtils' import { setLoadingScreenStatus } from './appStatus' import { displayClientChat } from './botUtils' +import { miscUiState } from './globalState' const notImplemented = () => { return 'Not implemented yet' @@ -68,7 +70,7 @@ export const exportWorld = async (path: string, type: 'zip' | 'folder', zipName // todo include in help const exportLoadedWorld = async () => { await saveServer() - let { worldFolder } = localServer!.options + let worldFolder = fsState.inMemorySavePath if (!worldFolder.startsWith('/')) worldFolder = `/${worldFolder}` await exportWorld(worldFolder, 'zip') } @@ -129,16 +131,23 @@ export const commands: Array<{ await navigator.clipboard.writeText(formatted) writeText(`Copied position to clipboard: ${formatted}`) } + }, + { + command: ['/mesherlog'], + alwaysAvailable: true, + invoke () { + getThreeJsRendererMethods()?.downloadMesherLog() + } } ] //@ts-format-ignore-endregion -export const getBuiltinCommandsList = () => commands.filter(command => command.alwaysAvailable || localServer).flatMap(command => command.command) +export const getBuiltinCommandsList = () => commands.filter(command => command.alwaysAvailable || miscUiState.singleplayer).flatMap(command => command.command) export const tryHandleBuiltinCommand = (message: string) => { const [userCommand, ...args] = message.split(' ') - for (const command of commands.filter(command => command.alwaysAvailable || localServer)) { + for (const command of commands.filter(command => command.alwaysAvailable || miscUiState.singleplayer)) { if (command.command.includes(userCommand)) { void command.invoke(args) // ignoring for now return true diff --git a/src/cameraRotationControls.ts b/src/cameraRotationControls.ts index 8b21e53d..679a3a44 100644 --- a/src/cameraRotationControls.ts +++ b/src/cameraRotationControls.ts @@ -18,6 +18,7 @@ export function onCameraMove (e: MouseEvent | CameraMoveEvent) { if (!isGameActive(true)) return if (e.type === 'mousemove' && !document.pointerLockElement) return e.stopPropagation?.() + if (appViewer.playerState.utils.isSpectatingEntity()) return const now = performance.now() // todo: limit camera movement for now to avoid unexpected jumps if (now - lastMouseMove < 4 && !options.preciseMouseInput) return @@ -32,7 +33,6 @@ export function onCameraMove (e: MouseEvent | CameraMoveEvent) { updateMotion() } - export const moveCameraRawHandler = ({ x, y }: { x: number; y: number }) => { const maxPitch = 0.5 * Math.PI const minPitch = -0.5 * Math.PI @@ -74,9 +74,6 @@ export const onControInit = () => { } function pointerLockChangeCallback () { - if (notificationProxy.id === 'pointerlockchange') { - hideNotification() - } if (appViewer.rendererState.preventEscapeMenu) return if (!pointerLock.hasPointerLock && activeModalStack.length === 0 && miscUiState.gameLoaded) { showModal({ reactType: 'pause-screen' }) diff --git a/src/chatUtils.test.ts b/src/chatUtils.test.ts index e717da28..6d683919 100644 --- a/src/chatUtils.test.ts +++ b/src/chatUtils.test.ts @@ -1,6 +1,6 @@ import { test, expect } from 'vitest' import mcData from 'minecraft-data' -import { formatMessage } from './chatUtils' +import { formatMessage, isAllowedChatCharacter, isStringAllowed } from './chatUtils' //@ts-expect-error globalThis.loadedData ??= mcData('1.20.1') @@ -64,3 +64,21 @@ test('formatMessage', () => { ] `) }) + +test('isAllowedChatCharacter', () => { + expect(isAllowedChatCharacter('a')).toBe(true) + expect(isAllowedChatCharacter('a')).toBe(true) + expect(isAllowedChatCharacter('§')).toBe(false) + expect(isAllowedChatCharacter(' ')).toBe(true) + expect(isStringAllowed('a§b')).toMatchObject({ + valid: false, + clean: 'ab', + invalid: ['§'] + }) + expect(isStringAllowed('aツ')).toMatchObject({ + valid: true, + }) + expect(isStringAllowed('a🟢')).toMatchObject({ + valid: true, + }) +}) diff --git a/src/chatUtils.ts b/src/chatUtils.ts index 5143c10f..849d5847 100644 --- a/src/chatUtils.ts +++ b/src/chatUtils.ts @@ -4,6 +4,10 @@ import { fromFormattedString, TextComponent } from '@xmcl/text-component' import type { IndexedData } from 'minecraft-data' import { versionToNumber } from 'renderer/viewer/common/utils' +export interface MessageFormatOptions { + doShadow?: boolean +} + export type MessageFormatPart = Pick & { text: string color?: string @@ -89,7 +93,10 @@ export const formatMessage = (message: MessageInput, mcData: IndexedData = globa } if (msg.extra) { - for (const ex of msg.extra) { + for (let ex of msg.extra) { + if (typeof ex === 'string') { + ex = { text: ex } + } readMsg({ ...styles, ...ex }) } } @@ -111,6 +118,14 @@ export const formatMessage = (message: MessageInput, mcData: IndexedData = globa return msglist } +export const messageToString = (message: MessageInput | string) => { + if (typeof message === 'string') { + return message + } + const msglist = formatMessage(message) + return msglist.map(msg => msg.text).join('') +} + const blockToItemRemaps = { water: 'water_bucket', lava: 'lava_bucket', @@ -122,3 +137,37 @@ export const getItemFromBlock = (block: import('prismarine-block').Block) => { const item = global.loadedData.itemsByName[blockToItemRemaps[block.name] ?? block.name] return item } + +export function isAllowedChatCharacter (char: string): boolean { + // if (char.length !== 1) { + // throw new Error('Input must be a single character') + // } + + const charCode = char.codePointAt(0)! + return charCode !== 167 && charCode >= 32 && charCode !== 127 +} + +export const isStringAllowed = (str: string) => { + const invalidChars = new Set() + for (const [i, char] of [...str].entries()) { + const isSurrogatePair = str.codePointAt(i) !== str['charCodeAt'](i) + if (isSurrogatePair) continue + + if (!isAllowedChatCharacter(char)) { + invalidChars.add(char) + } + } + + const valid = invalidChars.size === 0 + if (valid) { + return { + valid: true + } + } + + return { + valid, + clean: [...str].filter(c => !invalidChars.has(c)).join(''), + invalid: [...invalidChars] + } +} diff --git a/src/clientMods.ts b/src/clientMods.ts new file mode 100644 index 00000000..204a5861 --- /dev/null +++ b/src/clientMods.ts @@ -0,0 +1,637 @@ +/* eslint-disable no-await-in-loop */ +import { openDB } from 'idb' +import * as React from 'react' +import * as valtio from 'valtio' +import * as valtioUtils from 'valtio/utils' +import { gt } from 'semver' +import { proxy } from 'valtio' +import { options } from './optionsStorage' +import { appStorage } from './react/appStorageProvider' +import { showInputsModal, showOptionsModal } from './react/SelectOption' +import { ProgressReporter } from './core/progressReporter' +import { showNotification } from './react/NotificationProvider' + +let sillyProtection = false +const protectRuntime = () => { + if (sillyProtection) return + sillyProtection = true + const sensetiveKeys = new Set(['authenticatedAccounts', 'serversList', 'username']) + const proxy = new Proxy(window.localStorage, { + get (target, prop) { + if (typeof prop === 'string') { + if (sensetiveKeys.has(prop)) { + console.warn(`Access to sensitive key "${prop}" was blocked`) + return null + } + if (prop === 'getItem') { + return (key: string) => { + if (sensetiveKeys.has(key)) { + console.warn(`Access to sensitive key "${key}" via getItem was blocked`) + return null + } + return target.getItem(key) + } + } + if (prop === 'setItem') { + return (key: string, value: string) => { + if (sensetiveKeys.has(key)) { + console.warn(`Attempt to set sensitive key "${key}" via setItem was blocked`) + return + } + target.setItem(key, value) + } + } + if (prop === 'removeItem') { + return (key: string) => { + if (sensetiveKeys.has(key)) { + console.warn(`Attempt to delete sensitive key "${key}" via removeItem was blocked`) + return + } + target.removeItem(key) + } + } + if (prop === 'clear') { + console.warn('Attempt to clear localStorage was blocked') + return () => {} + } + } + return Reflect.get(target, prop) + }, + set (target, prop, value) { + if (typeof prop === 'string' && sensetiveKeys.has(prop)) { + console.warn(`Attempt to set sensitive key "${prop}" was blocked`) + return false + } + return Reflect.set(target, prop, value) + }, + deleteProperty (target, prop) { + if (typeof prop === 'string' && sensetiveKeys.has(prop)) { + console.warn(`Attempt to delete sensitive key "${prop}" was blocked`) + return false + } + return Reflect.deleteProperty(target, prop) + } + }) + Object.defineProperty(window, 'localStorage', { + value: proxy, + writable: false, + configurable: false, + }) +} + +// #region Database +const dbPromise = openDB('mods-db', 1, { + upgrade (db) { + db.createObjectStore('mods', { + keyPath: 'name', + }) + db.createObjectStore('repositories', { + keyPath: 'url', + }) + }, +}) + +export interface ModSetting { + label?: string + type: 'toggle' | 'choice' | 'input' | 'slider' + hidden?: boolean + values?: string[] + inputType?: string + hint?: string + default?: any +} + +export interface ModSettingsDict { + [settingId: string]: ModSetting +} + +export interface ModAction { + method?: string + label?: string + /** @default false */ + gameGlobal?: boolean + /** @default false */ + onlyForeground?: boolean +} + +// mcraft-repo.json +export interface McraftRepoFile { + packages: ClientModDefinition[] + /** @default true */ + prefix?: string | boolean + name?: string // display name + description?: string + mirrorUrls?: string[] + autoUpdateOverride?: boolean + lastUpdated?: number +} +export interface Repository extends McraftRepoFile { + url: string +} + +export interface ClientMod { + name: string; // unique identifier like owner.name + version: string + enabled?: boolean + + scriptMainUnstable?: string; + serverPlugin?: string + // serverPlugins?: string[] + // mesherThread?: string + stylesGlobal?: string + threeJsBackend?: string // three.js + // stylesLocal?: string + + requiresNetwork?: boolean + fullyOffline?: boolean + description?: string + author?: string + section?: string + autoUpdateOverride?: boolean + lastUpdated?: number + wasModifiedLocally?: boolean + // todo depends, hashsum + + settings?: ModSettingsDict + actionsMain?: Record +} + +const cleanupFetchedModData = (mod: ClientModDefinition | Record) => { + delete mod['enabled'] + delete mod['repo'] + delete mod['autoUpdateOverride'] + delete mod['lastUpdated'] + delete mod['wasModifiedLocally'] + return mod +} + +export type ClientModDefinition = Omit & { + scriptMainUnstable?: boolean + stylesGlobal?: boolean + serverPlugin?: boolean + threeJsBackend?: boolean +} + +export async function saveClientModData (data: ClientMod) { + const db = await dbPromise + data.lastUpdated = Date.now() + await db.put('mods', data) + modsReactiveUpdater.counter++ +} + +async function getPlugin (name: string) { + const db = await dbPromise + return db.get('mods', name) as Promise +} + +export async function getAllMods () { + const db = await dbPromise + return db.getAll('mods') as Promise +} + +async function deletePlugin (name) { + const db = await dbPromise + await db.delete('mods', name) + modsReactiveUpdater.counter++ +} + +async function removeAllMods () { + const db = await dbPromise + await db.clear('mods') + modsReactiveUpdater.counter++ +} + +// --- + +async function saveRepository (data: Repository) { + const db = await dbPromise + data.lastUpdated = Date.now() + await db.put('repositories', data) +} + +async function getRepository (url: string) { + const db = await dbPromise + return db.get('repositories', url) as Promise +} + +async function getAllRepositories () { + const db = await dbPromise + return db.getAll('repositories') as Promise +} +window.getAllRepositories = getAllRepositories + +async function deleteRepository (url) { + const db = await dbPromise + await db.delete('repositories', url) +} + +// --- + +// #endregion + +window.mcraft = { + version: process.env.RELEASE_TAG, + build: process.env.BUILD_VERSION, + ui: {}, + React, + valtio: { + ...valtio, + ...valtioUtils, + }, + // openDB +} + +const activateMod = async (mod: ClientMod, reason: string) => { + if (mod.enabled === false) return false + protectRuntime() + console.debug(`Activating mod ${mod.name} (${reason})...`) + window.loadedMods ??= {} + if (window.loadedMods[mod.name]) { + console.warn(`Mod is ${mod.name} already loaded, skipping activation...`) + return false + } + if (mod.stylesGlobal) { + const style = document.createElement('style') + style.textContent = mod.stylesGlobal + style.id = `mod-${mod.name}` + document.head.appendChild(style) + } + if (mod.scriptMainUnstable) { + const blob = new Blob([mod.scriptMainUnstable], { type: 'text/javascript' }) + const url = URL.createObjectURL(blob) + // eslint-disable-next-line no-useless-catch + try { + const module = await import(/* webpackIgnore: true */ url) + module.default?.(structuredClone(mod), { settings: getModSettingsProxy(mod) }) + window.loadedMods[mod.name] ??= {} + window.loadedMods[mod.name].mainUnstableModule = module + } catch (e) { + throw e + } + URL.revokeObjectURL(url) + } + if (mod.threeJsBackend) { + const blob = new Blob([mod.threeJsBackend], { type: 'text/javascript' }) + const url = URL.createObjectURL(blob) + // eslint-disable-next-line no-useless-catch + try { + const module = await import(/* webpackIgnore: true */ url) + // todo + window.loadedMods[mod.name] ??= {} + // for accessing global world var + window.loadedMods[mod.name].threeJsBackendModule = module + } catch (e) { + throw e + } + URL.revokeObjectURL(url) + } + mod.enabled = true + return true +} + +export const appStartup = async () => { + void checkModsUpdates() + + const mods = await getAllMods() + for (const mod of mods) { + await activateMod(mod, 'autostart').catch(e => { + modsErrors[mod.name] ??= [] + modsErrors[mod.name].push(`startup: ${String(e)}`) + console.error(`Error activating mod on startup ${mod.name}:`, e) + }) + } +} + +export const modsUpdateStatus = proxy({} as Record) +export const modsWaitingReloadStatus = proxy({} as Record) +export const modsErrors = proxy({} as Record) + +const normalizeRepoUrl = (url: string) => { + if (url.startsWith('https://')) return url + if (url.startsWith('http://')) return url + if (url.startsWith('//')) return `https:${url}` + return `https://raw.githubusercontent.com/${url}/master` +} + +const installOrUpdateMod = async (repo: Repository, mod: ClientModDefinition, activate = true, progress?: ProgressReporter) => { + // eslint-disable-next-line no-useless-catch + try { + const fetchData = async (urls: string[]) => { + const errored = [] as string[] + // eslint-disable-next-line no-unreachable-loop + for (const urlTemplate of urls) { + const modNameOnly = mod.name.split('.').pop() + const modFolder = repo.prefix === false ? modNameOnly : typeof repo.prefix === 'string' ? `${repo.prefix}/${modNameOnly}` : mod.name + const url = new URL(`${modFolder}/${urlTemplate}`, normalizeRepoUrl(repo.url).replace(/\/$/, '') + '/').href + // eslint-disable-next-line no-useless-catch + try { + const response = await fetch(url) + if (!response.ok) throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`) + return await response.text() + } catch (e) { + // errored.push(String(e)) + throw e + } + } + console.warn(`[${mod.name}] Error installing component of ${urls[0]}: ${errored.join(', ')}`) + return undefined + } + if (mod.stylesGlobal) { + await progress?.executeWithMessage( + `Downloading ${mod.name} styles`, + async () => { + mod.stylesGlobal = await fetchData(['global.css']) as any + } + ) + } + if (mod.scriptMainUnstable) { + await progress?.executeWithMessage( + `Downloading ${mod.name} script`, + async () => { + mod.scriptMainUnstable = await fetchData(['mainUnstable.js']) as any + } + ) + } + if (mod.threeJsBackend) { + await progress?.executeWithMessage( + `Downloading ${mod.name} three.js backend`, + async () => { + mod.threeJsBackend = await fetchData(['three.js']) as any + } + ) + } + if (mod.serverPlugin) { + if (mod.name.endsWith('.disabled')) throw new Error(`Mod name ${mod.name} can't end with .disabled`) + await progress?.executeWithMessage( + `Downloading ${mod.name} server plugin`, + async () => { + mod.serverPlugin = await fetchData(['serverPlugin.js']) as any + } + ) + } + if (activate) { + // todo try to de-activate mod if it's already loaded + if (window.loadedMods?.[mod.name]) { + modsWaitingReloadStatus[mod.name] = true + } else { + await activateMod(mod as ClientMod, 'install') + } + } + await saveClientModData(mod as ClientMod) + delete modsUpdateStatus[mod.name] + } catch (e) { + // console.error(`Error installing mod ${mod.name}:`, e) + throw e + } +} + +const checkRepositoryUpdates = async (repo: Repository) => { + for (const mod of repo.packages) { + + const modExisting = await getPlugin(mod.name) + if (modExisting?.version && gt(mod.version, modExisting.version)) { + modsUpdateStatus[mod.name] = [modExisting.version, mod.version] + if (options.modsAutoUpdate === 'always' && (!repo.autoUpdateOverride && !modExisting.autoUpdateOverride)) { + void installOrUpdateMod(repo, mod).catch(e => { + console.error(`Error updating mod ${mod.name}:`, e) + }) + } + } + } + +} + +export const fetchRepository = async (urlOriginal: string, url: string, hasMirrors = false) => { + const fetchUrl = normalizeRepoUrl(url).replace(/\/$/, '') + '/mcraft-repo.json' + try { + const response = await fetch(fetchUrl).then(async res => res.json()) + if (!response.packages) throw new Error(`No packages field in the response json of the repository: ${fetchUrl}`) + response.autoUpdateOverride = (await getRepository(urlOriginal))?.autoUpdateOverride + response.url = urlOriginal + void saveRepository(response) + modsReactiveUpdater.counter++ + return true + } catch (e) { + console.warn(`Error fetching repository (trying other mirrors) ${url}:`, e) + return false + } +} + +export const fetchAllRepositories = async () => { + const repositories = await getAllRepositories() + await Promise.all(repositories.map(async (repo) => { + const allUrls = [repo.url, ...(repo.mirrorUrls || [])] + for (const [i, url] of allUrls.entries()) { + const isLast = i === allUrls.length - 1 + + if (await fetchRepository(repo.url, url, !isLast)) break + } + })) + appStorage.modsAutoUpdateLastCheck = Date.now() +} + +const checkModsUpdates = async () => { + await autoRefreshModRepositories() + for (const repo of await getAllRepositories()) { + + await checkRepositoryUpdates(repo) + } +} + +const autoRefreshModRepositories = async () => { + if (options.modsAutoUpdate === 'never') return + const lastCheck = appStorage.modsAutoUpdateLastCheck + if (lastCheck && Date.now() - lastCheck < 1000 * 60 * 60 * options.modsUpdatePeriodCheck) return + await fetchAllRepositories() + // todo think of not updating check timestamp on offline access +} + +export const installModByName = async (repoUrl: string, name: string, progress?: ProgressReporter) => { + progress?.beginStage('main', `Installing ${name}`) + const repo = await getRepository(repoUrl) + if (!repo) throw new Error(`Repository ${repoUrl} not found`) + const mod = repo.packages.find(m => m.name === name) + if (!mod) throw new Error(`Mod ${name} not found in repository ${repoUrl}`) + await installOrUpdateMod(repo, mod, undefined, progress) + progress?.endStage('main') +} + +export const uninstallModAction = async (name: string) => { + const choice = await showOptionsModal(`Uninstall mod ${name}?`, ['Yes']) + if (!choice) return + await deletePlugin(name) + window.loadedMods ??= {} + if (window.loadedMods[name]) { + // window.loadedMods[name].default?.(null) + delete window.loadedMods[name] + modsWaitingReloadStatus[name] = true + } + // Clear any errors associated with the mod + delete modsErrors[name] +} + +export const setEnabledModAction = async (name: string, newEnabled: boolean) => { + const mod = await getPlugin(name) + if (!mod) throw new Error(`Mod ${name} not found`) + if (newEnabled) { + mod.enabled = true + if (!window.loadedMods?.[mod.name]) { + await activateMod(mod, 'manual') + } + } else { + // todo deactivate mod + mod.enabled = false + if (window.loadedMods?.[mod.name]) { + if (window.loadedMods[mod.name]?.threeJsBackendModule) { + window.loadedMods[mod.name].threeJsBackendModule.deactivate() + delete window.loadedMods[mod.name].threeJsBackendModule + } + if (window.loadedMods[mod.name]?.mainUnstableModule) { + window.loadedMods[mod.name].mainUnstableModule.deactivate() + delete window.loadedMods[mod.name].mainUnstableModule + } + + if (Object.keys(window.loadedMods[mod.name]).length === 0) { + delete window.loadedMods[mod.name] + } + } + } + await saveClientModData(mod) +} + +export const modsReactiveUpdater = proxy({ + counter: 0 +}) + +export const getAllModsDisplayList = async () => { + const repos = await getAllRepositories() + const installedMods = await getAllMods() + const modsWithoutRepos = installedMods.filter(mod => !repos.some(repo => repo.packages.some(m => m.name === mod.name))) + const mapMods = (mapMods: ClientMod[]) => mapMods.map(mod => ({ + ...mod, + installed: installedMods.find(m => m.name === mod.name), + activated: !!window.loadedMods?.[mod.name], + installedVersion: installedMods.find(m => m.name === mod.name)?.version, + canBeActivated: mod.scriptMainUnstable || mod.stylesGlobal, + })) + return { + repos: repos.map(repo => ({ + ...repo, + packages: mapMods(repo.packages as ClientMod[]), + })), + modsWithoutRepos: mapMods(modsWithoutRepos), + } +} + +export const removeRepositoryAction = async (url: string) => { + // todo remove mods + const choice = await showOptionsModal('Remove repository? Installed mods wont be automatically removed.', ['Yes']) + if (!choice) return + await deleteRepository(url) + modsReactiveUpdater.counter++ +} + +export const selectAndRemoveRepository = async () => { + const repos = await getAllRepositories() + const choice = await showOptionsModal('Select repository to remove', repos.map(repo => repo.url)) + if (!choice) return + await removeRepositoryAction(choice) +} + +export const addRepositoryAction = async () => { + const { url } = await showInputsModal('Add repository', { + url: { + type: 'text', + label: 'Repository URL or slug', + placeholder: 'github-owner/repo-name', + }, + }) + if (!url) return + await fetchRepository(url, url) +} + +export const getServerPlugin = async (plugin: string) => { + const mod = await getPlugin(plugin) + if (!mod) return null + if (mod.serverPlugin) { + return { + content: mod.serverPlugin, + version: mod.version + } + } + return null +} + +export const getAvailableServerPlugins = async () => { + const mods = await getAllMods() + return mods.filter(mod => mod.serverPlugin) +} + +window.inspectInstalledMods = getAllMods + +type ModifiableField = { + field: string + label: string + language: string + getContent?: () => string +} + +// --- + +export const getAllModsModifiableFields = () => { + const fields: ModifiableField[] = [ + { + field: 'scriptMainUnstable', + label: 'Main Thread Script (unstable)', + language: 'js' + }, + { + field: 'stylesGlobal', + label: 'Global CSS Styles', + language: 'css' + }, + { + field: 'threeJsBackend', + label: 'Three.js Renderer Backend Thread', + language: 'js' + }, + { + field: 'serverPlugin', + label: 'Built-in server plugin', + language: 'js' + } + ] + return fields +} + +export const getModModifiableFields = (mod: ClientMod): ModifiableField[] => { + return getAllModsModifiableFields().filter(field => mod[field.field]) +} + +export const getModSettingsProxy = (mod: ClientMod) => { + if (!mod.settings) return valtio.proxy({}) + + const proxy = valtio.proxy({}) + for (const [key, setting] of Object.entries(mod.settings)) { + proxy[key] = options[`mod-${mod.name}-${key}`] ?? setting.default + } + + valtio.subscribe(proxy, (ops) => { + for (const op of ops) { + const [type, path, value] = op + const key = path[0] as string + options[`mod-${mod.name}-${key}`] = value + } + }) + + return proxy +} + +export const callMethodAction = async (modName: string, type: 'main', method: string) => { + try { + const mod = window.loadedMods?.[modName] + await mod[method]() + } catch (err) { + showNotification(`Failed to execute ${method}`, `Problem in ${type} js script of ${modName}`, true) + } +} diff --git a/src/connect.ts b/src/connect.ts index 5afdb0f6..cb6b8f65 100644 --- a/src/connect.ts +++ b/src/connect.ts @@ -3,7 +3,6 @@ import MinecraftData from 'minecraft-data' import PrismarineBlock from 'prismarine-block' import PrismarineItem from 'prismarine-item' -import pathfinder from 'mineflayer-pathfinder' import { miscUiState } from './globalState' import supportedVersions from './supportedVersions.mjs' import { options } from './optionsStorage' @@ -15,15 +14,13 @@ export type ConnectOptions = { singleplayer?: any username: string proxy?: string - botVersion?: any + botVersion?: string serverOverrides? serverOverridesFlat? peerId?: string ignoreQs?: boolean onSuccessfulPlay?: () => void - autoLoginPassword?: string serverIndex?: string - /** If true, will show a UI to authenticate with a new account */ authenticatedAccount?: AuthenticatedAccount | true peerOptions?: any viewerWsConnect?: string @@ -31,6 +28,15 @@ export type ConnectOptions = { /** Will enable local replay server */ worldStateFileContents?: string + + connectEvents?: { + serverCreated?: () => void + // connect: () => void; + // disconnect: () => void; + // error: (err: any) => void; + // ready: () => void; + // end: () => void; + } } export const getVersionAutoSelect = (autoVersionSelect = options.serversAutoVersionSelect) => { @@ -58,12 +64,15 @@ export const loadMinecraftData = async (version: string) => { window.PrismarineItem = PrismarineItem(mcData.version.minecraftVersion!) window.loadedData = mcData window.mcData = mcData - window.pathfinder = pathfinder miscUiState.loadedDataVersion = version } -export const downloadAllMinecraftData = async () => { +export type AssetDownloadReporter = (asset: string, isDone: boolean) => void + +export const downloadAllMinecraftData = async (reporter?: AssetDownloadReporter) => { + reporter?.('mc-data', false) await window._LOAD_MC_DATA() + reporter?.('mc-data', true) } const loadFonts = async () => { @@ -76,6 +85,12 @@ const loadFonts = async () => { } } -export const downloadOtherGameData = async () => { - await Promise.all([loadFonts(), downloadSoundsIfNeeded()]) +export const downloadOtherGameData = async (reporter?: AssetDownloadReporter) => { + reporter?.('fonts', false) + reporter?.('sounds', false) + + await Promise.all([ + loadFonts().then(() => reporter?.('fonts', true)), + downloadSoundsIfNeeded().then(() => reporter?.('sounds', true)) + ]) } diff --git a/src/controls.ts b/src/controls.ts index b91ae7ab..db6a6fc6 100644 --- a/src/controls.ts +++ b/src/controls.ts @@ -7,6 +7,7 @@ import { ControMax } from 'contro-max/build/controMax' import { CommandEventArgument, SchemaCommandInput } from 'contro-max/build/types' import { stringStartsWith } from 'contro-max/build/stringUtils' import { GameMode } from 'mineflayer' +import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal, miscUiState, hideModal, hideAllModals } from './globalState' import { goFullscreen, isInRealGameSession, pointerLock, reloadChunks } from './utils' import { options } from './optionsStorage' @@ -26,7 +27,9 @@ import { onCameraMove, onControInit } from './cameraRotationControls' import { createNotificationProgressReporter } from './core/progressReporter' import { appStorage } from './react/appStorageProvider' import { switchGameMode } from './packetsReplay/replayPackets' - +import { tabListState } from './react/PlayerListOverlayProvider' +import { type ActionType, type ActionHoldConfig, type CustomAction } from './appConfig' +import { playerState } from './mineflayer/playerState' export const customKeymaps = proxy(appStorage.keybindings) subscribe(customKeymaps, () => { @@ -40,36 +43,48 @@ const controlOptions = { export const contro = new ControMax({ commands: { general: { + // movement jump: ['Space', 'A'], inventory: ['KeyE', 'X'], drop: ['KeyQ', 'B'], + dropStack: [null], sneak: ['ShiftLeft'], toggleSneakOrDown: [null, 'Right Stick'], sprint: ['ControlLeft', 'Left Stick'], + // game interactions nextHotbarSlot: [null, 'Right Bumper'], prevHotbarSlot: [null, 'Left Bumper'], attackDestroy: [null, 'Right Trigger'], interactPlace: [null, 'Left Trigger'], - chat: [['KeyT', 'Enter']], - command: ['Slash'], swapHands: ['KeyF'], - zoom: ['KeyC'], - selectItem: ['KeyH'], // default will be removed + selectItem: ['KeyH'], rotateCameraLeft: [null], rotateCameraRight: [null], rotateCameraUp: [null], rotateCameraDown: [null], - viewerConsole: ['Backquote'] + // ui? + chat: [['KeyT', 'Enter']], + command: ['Slash'], + playersList: ['Tab'], + debugOverlay: ['F3'], + debugOverlayHelpMenu: [null], + // client side + zoom: ['KeyC'], + viewerConsole: ['Backquote'], + togglePerspective: ['F5'], }, ui: { toggleFullscreen: ['F11'], back: [null/* 'Escape' */, 'B'], - toggleMap: ['KeyM'], + toggleMap: ['KeyJ'], leftClick: [null, 'A'], rightClick: [null, 'Y'], speedupCursor: [null, 'Left Stick'], pauseMenu: [null, 'Start'] }, + communication: { + toggleMicrophone: ['KeyM'], + }, advanced: { lockUrl: ['KeyY'], }, @@ -101,6 +116,10 @@ export const contro = new ControMax({ window.controMax = contro export type Command = CommandEventArgument['command'] +export const isCommandDisabled = (command: Command) => { + return miscUiState.appConfig?.disabledCommands?.includes(command) +} + onControInit() updateBinds(customKeymaps) @@ -118,7 +137,14 @@ const setSprinting = (state: boolean) => { gameAdditionalState.isSprinting = state } +const isSpectatingEntity = () => { + return appViewer.playerState.utils.isSpectatingEntity() +} + contro.on('movementUpdate', ({ vector, soleVector, gamepadIndex }) => { + // Don't allow movement while spectating an entity + if (isSpectatingEntity()) return + if (gamepadIndex !== undefined && gamepadUiCursorState.display) { const deadzone = 0.1 // TODO make deadzone configurable if (Math.abs(soleVector.x) < deadzone && Math.abs(soleVector.z) < deadzone) { @@ -176,6 +202,7 @@ contro.on('movementUpdate', ({ vector, soleVector, gamepadIndex }) => { if (action) { void contro.emit('trigger', { command: 'general.forward' } as any) } else { + void contro.emit('release', { command: 'general.forward' } as any) setSprinting(false) } } @@ -226,6 +253,10 @@ const inModalCommand = (command: Command, pressed: boolean) => { if (command === 'ui.back') { hideCurrentModal() } + if (command === 'ui.pauseMenu') { + // hide all modals + hideAllModals() + } if (command === 'ui.leftClick' || command === 'ui.rightClick') { // in percent const { x, y } = gamepadUiCursorState @@ -322,6 +353,9 @@ const cameraRotationControls = { cameraRotationControls.updateMovement() }, handleCommand (command: string, pressed: boolean) { + // Don't allow movement while spectating an entity + if (isSpectatingEntity()) return + const directionMap = { 'general.rotateCameraLeft': 'left', 'general.rotateCameraRight': 'right', @@ -343,6 +377,7 @@ window.cameraRotationControls = cameraRotationControls const setSneaking = (state: boolean) => { gameAdditionalState.isSneaking = state bot.setControlState('sneak', state) + } const onTriggerOrReleased = (command: Command, pressed: boolean) => { @@ -353,6 +388,7 @@ const onTriggerOrReleased = (command: Command, pressed: boolean) => { // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check switch (command) { case 'general.jump': + if (isSpectatingEntity()) break // if (viewer.world.freeFlyMode) { // const moveSpeed = 0.5 // viewer.world.freeFlyState.position.add(new Vec3(0, pressed ? moveSpeed : 0, 0)) @@ -390,12 +426,67 @@ const onTriggerOrReleased = (command: Command, pressed: boolean) => { case 'general.zoom': gameAdditionalState.isZooming = pressed break + case 'general.debugOverlay': + if (pressed) { + miscUiState.showDebugHud = !miscUiState.showDebugHud + } + break + case 'general.debugOverlayHelpMenu': + if (pressed) { + void onF3LongPress() + } + break case 'general.rotateCameraLeft': case 'general.rotateCameraRight': case 'general.rotateCameraUp': case 'general.rotateCameraDown': cameraRotationControls.handleCommand(command, pressed) break + case 'general.playersList': + tabListState.isOpen = pressed + break + case 'general.viewerConsole': + if (lastConnectOptions.value?.viewerWsConnect) { + showModal({ reactType: 'console' }) + } + break + case 'general.togglePerspective': + if (pressed) { + const currentPerspective = playerState.reactive.perspective + // eslint-disable-next-line sonarjs/no-nested-switch + switch (currentPerspective) { + case 'first_person': + playerState.reactive.perspective = 'third_person_back' + break + case 'third_person_back': + playerState.reactive.perspective = 'third_person_front' + break + case 'third_person_front': + playerState.reactive.perspective = 'first_person' + break + } + } + break + } + } else if (stringStartsWith(command, 'ui')) { + switch (command) { + case 'ui.pauseMenu': + if (pressed) { + if (activeModalStack.length) { + hideCurrentModal() + } else { + showModal({ reactType: 'pause-screen' }) + } + } + break + case 'ui.back': + case 'ui.toggleFullscreen': + case 'ui.toggleMap': + case 'ui.leftClick': + case 'ui.rightClick': + case 'ui.speedupCursor': + // These are handled elsewhere + break } } } @@ -412,12 +503,16 @@ const alwaysPressedHandledCommand = (command: Command) => { if (command === 'advanced.lockUrl') { lockUrl() } + if (command === 'communication.toggleMicrophone') { + toggleMicrophoneMuted?.() + } } export function lockUrl () { let newQs = '' - if (fsState.saveLoaded) { - const save = localServer!.options.worldFolder.split('/').at(-1) + if (fsState.saveLoaded && fsState.inMemorySave) { + const worldFolder = fsState.inMemorySavePath + const save = worldFolder.split('/').at(-1) newQs = `loadSave=${save}` } else if (process.env.NODE_ENV === 'development') { newQs = `reconnect=1` @@ -453,6 +548,8 @@ const customCommandsHandler = ({ command }) => { contro.on('trigger', customCommandsHandler) contro.on('trigger', ({ command }) => { + if (isCommandDisabled(command)) return + const willContinue = !isGameActive(true) alwaysPressedHandledCommand(command) if (willContinue) return @@ -484,13 +581,22 @@ contro.on('trigger', ({ command }) => { case 'general.rotateCameraRight': case 'general.rotateCameraUp': case 'general.rotateCameraDown': + case 'general.debugOverlay': + case 'general.debugOverlayHelpMenu': + case 'general.playersList': + case 'general.togglePerspective': // no-op break case 'general.swapHands': { - bot._client.write('entity_action', { - entityId: bot.entity.id, - actionId: 6, - jumpBoost: 0 + if (isSpectatingEntity()) break + bot._client.write('block_dig', { + 'status': 6, + 'location': { + 'x': 0, + 'z': 0, + 'y': 0 + }, + 'face': 0, }) break } @@ -498,11 +604,13 @@ contro.on('trigger', ({ command }) => { // handled in onTriggerOrReleased break case 'general.inventory': + if (isSpectatingEntity()) break document.exitPointerLock?.() openPlayerInventory() break case 'general.drop': { - // if (bot.heldItem/* && ctrl */) bot.tossStack(bot.heldItem) + if (isSpectatingEntity()) break + // protocol 1.9+ bot._client.write('block_dig', { 'status': 4, 'location': { @@ -521,6 +629,12 @@ contro.on('trigger', ({ command }) => { } break } + case 'general.dropStack': { + if (bot.heldItem) { + void bot.tossStack(bot.heldItem) + } + break + } case 'general.chat': showModal({ reactType: 'chat' }) break @@ -529,12 +643,15 @@ contro.on('trigger', ({ command }) => { showModal({ reactType: 'chat' }) break case 'general.selectItem': + if (isSpectatingEntity()) break void selectItem() break case 'general.nextHotbarSlot': + if (isSpectatingEntity()) break cycleHotbarSlot(1) break case 'general.prevHotbarSlot': + if (isSpectatingEntity()) break cycleHotbarSlot(-1) break case 'general.zoom': @@ -547,10 +664,6 @@ contro.on('trigger', ({ command }) => { } } - if (command === 'ui.pauseMenu') { - showModal({ reactType: 'pause-screen' }) - } - if (command === 'ui.toggleFullscreen') { void goFullscreen(true) } @@ -570,6 +683,8 @@ contro.on('trigger', ({ command }) => { }) contro.on('release', ({ command }) => { + if (isCommandDisabled(command)) return + inModalCommand(command, false) onTriggerOrReleased(command, false) }) @@ -578,7 +693,7 @@ contro.on('release', ({ command }) => { export const f3Keybinds: Array<{ key?: string, - action: () => void, + action: () => void | Promise, mobileTitle: string enabled?: () => boolean }> = [ @@ -601,6 +716,9 @@ export const f3Keybinds: Array<{ localServer.players[0].world.columns = {} } void reloadChunks() + if (appViewer.backend?.backendMethods && typeof appViewer.backend.backendMethods.reloadWorld === 'function') { + appViewer.backend.backendMethods.reloadWorld() + } }, mobileTitle: 'Reload chunks', }, @@ -611,6 +729,19 @@ export const f3Keybinds: Array<{ }, mobileTitle: 'Toggle chunk borders', }, + { + key: 'KeyH', + action () { + showModal({ reactType: 'chunks-debug' }) + }, + mobileTitle: 'Show Chunks Debug', + }, + { + action () { + showModal({ reactType: 'renderer-debug' }) + }, + mobileTitle: 'Renderer Debug Menu', + }, { key: 'KeyY', async action () { @@ -687,167 +818,50 @@ export const f3Keybinds: Array<{ } ] -const hardcodedPressedKeys = new Set() +export const reloadChunksAction = () => { + const action = f3Keybinds.find(f3Keybind => f3Keybind.key === 'KeyA') + void action!.action() +} + document.addEventListener('keydown', (e) => { if (!isGameActive(false)) return - if (hardcodedPressedKeys.has('F3')) { + if (contro.pressedKeys.has('F3')) { const keybind = f3Keybinds.find((v) => v.key === e.code) if (keybind && (keybind.enabled?.() ?? true)) { - keybind.action() + void keybind.action() e.stopPropagation() } - return } - - hardcodedPressedKeys.add(e.code) }, { capture: true, }) -document.addEventListener('keyup', (e) => { - hardcodedPressedKeys.delete(e.code) -}) -document.addEventListener('visibilitychange', (e) => { - if (document.visibilityState === 'hidden') { - hardcodedPressedKeys.clear() - } -}) -// #region creative fly -// these controls are more like for gamemode 3 - -const makeInterval = (fn, interval) => { - const intervalId = setInterval(fn, interval) - - const cleanup = () => { - clearInterval(intervalId) - cleanup.active = false - } - cleanup.active = true - return cleanup -} - -const isFlying = () => bot.physics.gravity === 0 -let endFlyLoop: ReturnType | undefined - -const currentFlyVector = new Vec3(0, 0, 0) -window.currentFlyVector = currentFlyVector - -// todo cleanup -const flyingPressedKeys = { - down: false, - up: false -} - -const startFlyLoop = () => { - if (!isFlying()) return - endFlyLoop?.() - - endFlyLoop = makeInterval(() => { - if (!bot) { - endFlyLoop?.() - return - } - - bot.entity.position.add(currentFlyVector.clone().multiply(new Vec3(0, 0.5, 0))) - }, 50) -} - -// todo we will get rid of patching it when refactor controls -let originalSetControlState -const patchedSetControlState = (action, state) => { - if (!isFlying()) { - return originalSetControlState(action, state) - } - - const actionPerFlyVector = { - jump: new Vec3(0, 1, 0), - sneak: new Vec3(0, -1, 0), - } - - const changeVec = actionPerFlyVector[action] - if (!changeVec) { - return originalSetControlState(action, state) - } - if (flyingPressedKeys[state === 'jump' ? 'up' : 'down'] === state) return - const toAddVec = changeVec.scaled(state ? 1 : -1) - for (const coord of ['x', 'y', 'z']) { - if (toAddVec[coord] === 0) continue - if (currentFlyVector[coord] === toAddVec[coord]) return - } - currentFlyVector.add(toAddVec) - flyingPressedKeys[state === 'jump' ? 'up' : 'down'] = state -} +const isFlying = () => (bot.entity as any).flying const startFlying = (sendAbilities = true) => { - bot.entity['creativeFly'] = true if (sendAbilities) { bot._client.write('abilities', { flags: 2, }) } - // window.flyingSpeed will be removed - bot.physics['airborneAcceleration'] = window.flyingSpeed ?? 0.1 // todo use abilities - bot.entity.velocity = new Vec3(0, 0, 0) - bot.creative.startFlying() - startFlyLoop() + (bot.entity as any).flying = true } const endFlying = (sendAbilities = true) => { - bot.entity['creativeFly'] = false - if (bot.physics.gravity !== 0) return + if (!isFlying()) return if (sendAbilities) { bot._client.write('abilities', { flags: 0, }) } - Object.assign(flyingPressedKeys, { - up: false, - down: false - }) - currentFlyVector.set(0, 0, 0) - bot.physics['airborneAcceleration'] = standardAirborneAcceleration - bot.creative.stopFlying() - endFlyLoop?.() + (bot.entity as any).flying = false } -let allowFlying = false - export const onBotCreate = () => { - let wasSpectatorFlying = false - bot._client.on('abilities', ({ flags }) => { - allowFlying = !!(flags & 4) - if (flags & 2) { // flying - toggleFly(true, false) - } else { - toggleFly(false, false) - } - }) - const gamemodeCheck = () => { - if (bot.game.gameMode === 'spectator') { - allowFlying = true - toggleFly(true, false) - wasSpectatorFlying = true - } else if (wasSpectatorFlying) { - toggleFly(false, false) - wasSpectatorFlying = false - } - } - bot.on('game', () => { - gamemodeCheck() - }) - bot.on('login', () => { - gamemodeCheck() - }) } -const standardAirborneAcceleration = 0.02 const toggleFly = (newState = !isFlying(), sendAbilities?: boolean) => { - // if (bot.game.gameMode !== 'creative' && bot.game.gameMode !== 'spectator') return - if (!allowFlying) return - if (bot.setControlState !== patchedSetControlState) { - originalSetControlState = bot.setControlState - bot.setControlState = patchedSetControlState - } + if (!bot.entity.canFly) return if (newState) { startFlying(sendAbilities) @@ -856,7 +870,6 @@ const toggleFly = (newState = !isFlying(), sendAbilities?: boolean) => { } gameAdditionalState.isFlying = isFlying() } -// #endregion const selectItem = async () => { const block = bot.blockAtCursor(5) @@ -870,10 +883,16 @@ const selectItem = async () => { } addEventListener('mousedown', async (e) => { + // always prevent default for side buttons (back / forward navigation) + if (e.button === 3 || e.button === 4) { + e.preventDefault() + } + if ((e.target as HTMLElement).matches?.('#VRButton')) return if (!isInRealGameSession() && !(e.target as HTMLElement).id.includes('ui-root')) return void pointerLock.requestPointerLock() if (!bot) return + getThreeJsRendererMethods()?.onPageInteraction() // wheel click // todo support ctrl+wheel (+nbt) if (e.button === 1) { @@ -883,6 +902,10 @@ addEventListener('mousedown', async (e) => { window.addEventListener('keydown', (e) => { if (e.code !== 'Escape') return + if (!activeModalStack.length) { + getThreeJsRendererMethods()?.onPageInteraction() + } + if (activeModalStack.length) { const hideAll = e.ctrlKey || e.metaKey if (hideAll) { @@ -891,6 +914,7 @@ window.addEventListener('keydown', (e) => { hideCurrentModal() } if (activeModalStack.length === 0) { + getThreeJsRendererMethods()?.onPageInteraction() pointerLock.justHitEscape = true } } else if (pointerLock.hasPointerLock) { @@ -926,13 +950,17 @@ window.addEventListener('keydown', (e) => { if (e.code === 'KeyL' && e.altKey && !e.shiftKey && !e.ctrlKey && !e.metaKey) { console.clear() } - if (e.code === 'KeyK' && e.altKey && !e.shiftKey && !e.ctrlKey && !e.metaKey) { + if (e.code === 'KeyK' && e.altKey && e.shiftKey && !e.ctrlKey && !e.metaKey) { if (sessionStorage.delayLoadUntilFocus) { sessionStorage.removeItem('delayLoadUntilFocus') } else { sessionStorage.setItem('delayLoadUntilFocus', 'true') } } + if (e.code === 'KeyK' && e.altKey && !e.shiftKey && !e.ctrlKey && !e.metaKey) { + // eslint-disable-next-line no-debugger + debugger + } }) // #endregion @@ -962,3 +990,62 @@ export function updateBinds (commands: any) { })) } } + +export const onF3LongPress = async () => { + const actions = f3Keybinds.filter(f3Keybind => { + return f3Keybind.mobileTitle && (f3Keybind.enabled?.() ?? true) + }) + const actionNames = actions.map(f3Keybind => { + return `${f3Keybind.mobileTitle}${f3Keybind.key ? ` (F3+${f3Keybind.key})` : ''}` + }) + const select = await showOptionsModal('', actionNames) + if (!select) return + const actionIndex = actionNames.indexOf(select) + const f3Keybind = actions[actionIndex]! + void f3Keybind.action() +} + +export const handleMobileButtonCustomAction = (action: CustomAction) => { + const handler = customCommandsConfig[action.type]?.handler + if (handler) { + handler([...action.input]) + } +} + +export const triggerCommand = (command: Command, isDown: boolean) => { + handleMobileButtonActionCommand(command, isDown) +} + +export const handleMobileButtonActionCommand = (command: ActionType | ActionHoldConfig, isDown: boolean) => { + const commandValue = typeof command === 'string' ? command : 'command' in command ? command.command : command + + // Check if command is disabled before proceeding + if (typeof commandValue === 'string' && isCommandDisabled(commandValue as Command)) return + + if (typeof commandValue === 'string' && !stringStartsWith(commandValue, 'custom')) { + const event: CommandEventArgument = { + command: commandValue as Command, + schema: { + keys: [], + gamepad: [] + } + } + if (isDown) { + contro.emit('trigger', event) + } else { + contro.emit('release', event) + } + } else if (typeof commandValue === 'object') { + if (isDown) { + handleMobileButtonCustomAction(commandValue) + } + } +} + +export const handleMobileButtonLongPress = (actionHold: ActionHoldConfig) => { + if (typeof actionHold.longPressAction === 'string' && actionHold.longPressAction === 'general.debugOverlayHelpMenu') { + void onF3LongPress() + } else if (actionHold.longPressAction) { + handleMobileButtonActionCommand(actionHold.longPressAction, true) + } +} diff --git a/src/core/ideChannels.ts b/src/core/ideChannels.ts new file mode 100644 index 00000000..a9c517f7 --- /dev/null +++ b/src/core/ideChannels.ts @@ -0,0 +1,106 @@ +import { proxy } from 'valtio' + +export const ideState = proxy({ + id: '', + contents: '', + line: 0, + column: 0, + language: 'typescript', + title: '', +}) +globalThis.ideState = ideState + +export const registerIdeChannels = () => { + registerIdeOpenChannel() + registerIdeSaveChannel() +} + +const registerIdeOpenChannel = () => { + const CHANNEL_NAME = 'minecraft-web-client:ide-open' + + const packetStructure = [ + 'container', + [ + { + name: 'id', + type: ['pstring', { countType: 'i16' }] + }, + { + name: 'language', + type: ['pstring', { countType: 'i16' }] + }, + { + name: 'contents', + type: ['pstring', { countType: 'i16' }] + }, + { + name: 'line', + type: 'i32' + }, + { + name: 'column', + type: 'i32' + }, + { + name: 'title', + type: ['pstring', { countType: 'i16' }] + } + ] + ] + + bot._client.registerChannel(CHANNEL_NAME, packetStructure, true) + + bot._client.on(CHANNEL_NAME as any, (data) => { + const { id, language, contents, line, column, title } = data + + ideState.contents = contents + ideState.line = line + ideState.column = column + ideState.id = id + ideState.language = language || 'typescript' + ideState.title = title + }) + + console.debug(`registered custom channel ${CHANNEL_NAME} channel`) +} +const IDE_SAVE_CHANNEL_NAME = 'minecraft-web-client:ide-save' +const registerIdeSaveChannel = () => { + + const packetStructure = [ + 'container', + [ + { + name: 'id', + type: ['pstring', { countType: 'i16' }] + }, + { + name: 'contents', + type: ['pstring', { countType: 'i16' }] + }, + { + name: 'language', + type: ['pstring', { countType: 'i16' }] + }, + { + name: 'line', + type: 'i32' + }, + { + name: 'column', + type: 'i32' + }, + ] + ] + bot._client.registerChannel(IDE_SAVE_CHANNEL_NAME, packetStructure, true) +} + +export const saveIde = () => { + bot._client.writeChannel(IDE_SAVE_CHANNEL_NAME, { + id: ideState.id, + contents: ideState.contents, + language: ideState.language, + // todo: reflect updated + line: ideState.line, + column: ideState.column, + }) +} diff --git a/src/core/importExport.ts b/src/core/importExport.ts new file mode 100644 index 00000000..b3e26347 --- /dev/null +++ b/src/core/importExport.ts @@ -0,0 +1,219 @@ +import { appStorage } from '../react/appStorageProvider' +import { getChangedSettings, options } from '../optionsStorage' +import { customKeymaps } from '../controls' +import { showInputsModal } from '../react/SelectOption' + +interface ExportedFile { + _about: string + options?: Record + keybindings?: Record + servers?: any[] + username?: string + proxy?: string + proxies?: string[] + accountTokens?: any[] +} + +export const importData = async () => { + try { + const input = document.createElement('input') + input.type = 'file' + input.accept = '.json' + input.click() + + const file = await new Promise((resolve) => { + input.onchange = () => { + if (!input.files?.[0]) return + resolve(input.files[0]) + } + }) + + const text = await file.text() + const data = JSON.parse(text) + + if (!data._about?.includes('Minecraft Web Client')) { + const doContinue = confirm('This file does not appear to be a Minecraft Web Client profile. Continue anyway?') + if (!doContinue) return + } + + // Build available data types for selection + const availableData: Record, { present: boolean, description: string }> = { + options: { present: !!data.options, description: 'Game settings and preferences' }, + keybindings: { present: !!data.keybindings, description: 'Custom key mappings' }, + servers: { present: !!data.servers, description: 'Saved server list' }, + username: { present: !!data.username, description: 'Username' }, + proxy: { present: !!data.proxy, description: 'Selected proxy server' }, + proxies: { present: !!data.proxies, description: 'Global proxies list' }, + accountTokens: { present: !!data.accountTokens, description: 'Account authentication tokens' }, + } + + // Filter to only present data types + const presentTypes = Object.fromEntries(Object.entries(availableData) + .filter(([_, info]) => info.present) + .map(([key, info]) => [key, info])) + + if (Object.keys(presentTypes).length === 0) { + alert('No compatible data found in the imported file.') + return + } + + const importChoices = await showInputsModal('Select Data to Import', { + mergeData: { + type: 'checkbox', + label: 'Merge with existing data (uncheck to remove old data)', + defaultValue: true, + }, + ...Object.fromEntries(Object.entries(presentTypes).map(([key, info]) => [key, { + type: 'checkbox', + label: info.description, + defaultValue: true, + }])) + }) as { mergeData: boolean } & Record + + if (!importChoices) return + + const importedTypes: string[] = [] + const shouldMerge = importChoices.mergeData + + if (importChoices.options && data.options) { + if (shouldMerge) { + Object.assign(options, data.options) + } else { + for (const key of Object.keys(options)) { + if (key in data.options) { + options[key as any] = data.options[key] + } + } + } + importedTypes.push('settings') + } + + if (importChoices.keybindings && data.keybindings) { + if (shouldMerge) { + Object.assign(customKeymaps, data.keybindings) + } else { + for (const key of Object.keys(customKeymaps)) delete customKeymaps[key] + Object.assign(customKeymaps, data.keybindings) + } + importedTypes.push('keybindings') + } + + if (importChoices.servers && data.servers) { + if (shouldMerge && appStorage.serversList) { + // Merge by IP, update existing entries and add new ones + const existingIps = new Set(appStorage.serversList.map(s => s.ip)) + const newServers = data.servers.filter(s => !existingIps.has(s.ip)) + appStorage.serversList = [...appStorage.serversList, ...newServers] + } else { + appStorage.serversList = data.servers + } + importedTypes.push('servers') + } + + if (importChoices.username && data.username) { + appStorage.username = data.username + importedTypes.push('username') + } + + if ((importChoices.proxy && data.proxy) || (importChoices.proxies && data.proxies)) { + if (!appStorage.proxiesData) { + appStorage.proxiesData = { proxies: [], selected: '' } + } + + if (importChoices.proxies && data.proxies) { + if (shouldMerge) { + // Merge unique proxies + const uniqueProxies = new Set([...appStorage.proxiesData.proxies, ...data.proxies]) + appStorage.proxiesData.proxies = [...uniqueProxies] + } else { + appStorage.proxiesData.proxies = data.proxies + } + importedTypes.push('proxies list') + } + + if (importChoices.proxy && data.proxy) { + appStorage.proxiesData.selected = data.proxy + importedTypes.push('selected proxy') + } + } + + if (importChoices.accountTokens && data.accountTokens) { + if (shouldMerge && appStorage.authenticatedAccounts) { + // Merge by unique identifier (assuming accounts have some unique ID or username) + const existingAccounts = new Set(appStorage.authenticatedAccounts.map(a => a.username)) + const newAccounts = data.accountTokens.filter(a => !existingAccounts.has(a.username)) + appStorage.authenticatedAccounts = [...appStorage.authenticatedAccounts, ...newAccounts] + } else { + appStorage.authenticatedAccounts = data.accountTokens + } + importedTypes.push('account tokens') + } + + alert(`Profile imported successfully! Imported data: ${importedTypes.join(', ')}.\nYou may need to reload the page for some changes to take effect.`) + } catch (err) { + console.error('Failed to import profile:', err) + alert('Failed to import profile: ' + (err.message || err)) + } +} + +export const exportData = async () => { + const data = await showInputsModal('Export Profile', { + profileName: { + type: 'text', + }, + exportSettings: { + type: 'checkbox', + defaultValue: true, + }, + exportKeybindings: { + type: 'checkbox', + defaultValue: true, + }, + exportServers: { + type: 'checkbox', + defaultValue: true, + }, + saveUsernameAndProxy: { + type: 'checkbox', + defaultValue: true, + }, + exportGlobalProxiesList: { + type: 'checkbox', + defaultValue: false, + }, + exportAccountTokens: { + type: 'checkbox', + defaultValue: false, + }, + }) + const fileName = `${data.profileName ? `${data.profileName}-` : ''}web-client-profile.json` + const json: ExportedFile = { + _about: 'Minecraft Web Client (mcraft.fun) Profile', + ...data.exportSettings ? { + options: getChangedSettings(), + } : {}, + ...data.exportKeybindings ? { + keybindings: customKeymaps, + } : {}, + ...data.exportServers ? { + servers: appStorage.serversList, + } : {}, + ...data.saveUsernameAndProxy ? { + username: appStorage.username, + proxy: appStorage.proxiesData?.selected, + } : {}, + ...data.exportGlobalProxiesList ? { + proxies: appStorage.proxiesData?.proxies, + } : {}, + ...data.exportAccountTokens ? { + accountTokens: appStorage.authenticatedAccounts, + } : {}, + } + const blob = new Blob([JSON.stringify(json, null, 2)], { type: 'application/json' }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = fileName + a.click() + URL.revokeObjectURL(url) +} diff --git a/src/core/progressReporter.ts b/src/core/progressReporter.ts index f4e4e701..75878fd2 100644 --- a/src/core/progressReporter.ts +++ b/src/core/progressReporter.ts @@ -1,6 +1,7 @@ import { setLoadingScreenStatus } from '../appStatus' import { appStatusState } from '../react/AppStatusProvider' import { hideNotification, showNotification } from '../react/NotificationProvider' +import { pixelartIcons } from '../react/PixelartIcon' export interface ProgressReporter { currentMessage: string | undefined @@ -121,6 +122,7 @@ const createProgressReporter = (implementation: ReporterDisplayImplementation): }, setMessage (message: string): void { + if (ended) return implementation.setMessage(message) }, @@ -129,6 +131,7 @@ const createProgressReporter = (implementation: ReporterDisplayImplementation): }, error (message: string): void { + if (ended) return implementation.error(message) } } @@ -163,15 +166,16 @@ export const createFullScreenProgressReporter = (): ProgressReporter => { } export const createNotificationProgressReporter = (endMessage?: string): ProgressReporter => { + const id = `progress-reporter-${Math.random().toString(36).slice(2)}` return createProgressReporter({ setMessage (message: string) { - showNotification(`${message}...`, '', false, '', undefined, true) + showNotification(`${message}...`, '', false, '', undefined, true, id) }, end () { if (endMessage) { - showNotification(endMessage, '', false, '', undefined, true) + showNotification(endMessage, '', false, pixelartIcons.check, undefined, true) } else { - hideNotification() + hideNotification(id) } }, diff --git a/src/core/timers.ts b/src/core/timers.ts index fd9c72f5..570f46c0 100644 --- a/src/core/timers.ts +++ b/src/core/timers.ts @@ -124,12 +124,12 @@ export const preventThrottlingWithSound = () => { // Start playing oscillator.start() - return () => { + return async () => { try { oscillator.stop() - audioContext.close() + await audioContext.close() } catch (err) { - console.error('Error stopping silent audio:', err) + console.warn('Error stopping silent audio:', err) } } } catch (err) { diff --git a/src/customChannels.ts b/src/customChannels.ts index fabe71ec..506ea776 100644 --- a/src/customChannels.ts +++ b/src/customChannels.ts @@ -2,18 +2,20 @@ import PItem from 'prismarine-item' import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' import { options } from './optionsStorage' import { jeiCustomCategories } from './inventoryWindows' +import { registerIdeChannels } from './core/ideChannels' export default () => { customEvents.on('mineflayerBotCreated', async () => { if (!options.customChannels) return - await new Promise(resolve => { - bot.once('login', () => { - resolve(true) - }) + bot.once('login', () => { + registerBlockModelsChannel() + registerMediaChannels() + registerSectionAnimationChannels() + registeredJeiChannel() + registerBlockInteractionsCustomizationChannel() + registerWaypointChannels() + registerIdeChannels() }) - registerBlockModelsChannel() - registerMediaChannels() - registeredJeiChannel() }) } @@ -31,6 +33,95 @@ const registerChannel = (channelName: string, packetStructure: any[], handler: ( console.debug(`registered custom channel ${channelName} channel`) } +const registerBlockInteractionsCustomizationChannel = () => { + const CHANNEL_NAME = 'minecraft-web-client:block-interactions-customization' + const packetStructure = [ + 'container', + [ + { + name: 'newConfiguration', + type: ['pstring', { countType: 'i16' }] + }, + ] + ] + + registerChannel(CHANNEL_NAME, packetStructure, (data) => { + const config = JSON.parse(data.newConfiguration) + bot.mouse.setConfigFromPacket(config) + }, true) +} + +const registerWaypointChannels = () => { + const packetStructure = [ + 'container', + [ + { + name: 'id', + type: ['pstring', { countType: 'i16' }] + }, + { + name: 'x', + type: 'f32' + }, + { + name: 'y', + type: 'f32' + }, + { + name: 'z', + type: 'f32' + }, + { + name: 'minDistance', + type: 'i32' + }, + { + name: 'label', + type: ['pstring', { countType: 'i16' }] + }, + { + name: 'color', + type: 'i32' + }, + { + name: 'metadataJson', + type: ['pstring', { countType: 'i16' }] + } + ] + ] + + registerChannel('minecraft-web-client:waypoint-add', packetStructure, (data) => { + // Parse metadata if provided + let metadata: any = {} + if (data.metadataJson && data.metadataJson.trim() !== '') { + try { + metadata = JSON.parse(data.metadataJson) + } catch (error) { + console.warn('Failed to parse waypoint metadataJson:', error) + } + } + + getThreeJsRendererMethods()?.addWaypoint(data.id, data.x, data.y, data.z, { + minDistance: data.minDistance, + label: data.label || undefined, + color: data.color || undefined, + metadata + }) + }) + + registerChannel('minecraft-web-client:waypoint-delete', [ + 'container', + [ + { + name: 'id', + type: ['pstring', { countType: 'i16' }] + } + ] + ], (data) => { + getThreeJsRendererMethods()?.removeWaypoint(data.id) + }) +} + const registerBlockModelsChannel = () => { const CHANNEL_NAME = 'minecraft-web-client:blockmodels' @@ -72,6 +163,86 @@ const registerBlockModelsChannel = () => { }, true) } +const registerSectionAnimationChannels = () => { + const ADD_CHANNEL = 'minecraft-web-client:section-animation-add' + const REMOVE_CHANNEL = 'minecraft-web-client:section-animation-remove' + + /** + * Add a section animation + * @param id - Section position for animation like `16,32,16` + * @param offset - Initial offset in blocks + * @param speedX - Movement speed in blocks per second on X axis + * @param speedY - Movement speed in blocks per second on Y axis + * @param speedZ - Movement speed in blocks per second on Z axis + * @param limitX - Maximum offset in blocks on X axis (0 means no limit) + * @param limitY - Maximum offset in blocks on Y axis (0 means no limit) + * @param limitZ - Maximum offset in blocks on Z axis (0 means no limit) + */ + const addPacketStructure = [ + 'container', + [ + { name: 'id', type: ['pstring', { countType: 'i16' }] }, + { name: 'offset', type: 'f32' }, + { name: 'speedX', type: 'f32' }, + { name: 'speedY', type: 'f32' }, + { name: 'speedZ', type: 'f32' }, + { name: 'limitX', type: 'f32' }, + { name: 'limitY', type: 'f32' }, + { name: 'limitZ', type: 'f32' } + ] + ] + + /** + * Remove a section animation + * @param id - Identifier of the animation to remove + */ + const removePacketStructure = [ + 'container', + [ + { name: 'id', type: ['pstring', { countType: 'i16' }] } + ] + ] + + registerChannel(ADD_CHANNEL, addPacketStructure, (data) => { + const { id, offset, speedX, speedY, speedZ, limitX, limitY, limitZ } = data + getThreeJsRendererMethods()?.addSectionAnimation(id, { + time: performance.now(), + speedX, + speedY, + speedZ, + currentOffsetX: offset, + currentOffsetY: offset, + currentOffsetZ: offset, + limitX: limitX === 0 ? undefined : limitX, + limitY: limitY === 0 ? undefined : limitY, + limitZ: limitZ === 0 ? undefined : limitZ + }) + }, true) + + registerChannel(REMOVE_CHANNEL, removePacketStructure, (data) => { + const { id } = data + getThreeJsRendererMethods()?.removeSectionAnimation(id) + }, true) + + console.debug('Registered section animation channels') +} + +window.testSectionAnimation = (speedY = 1) => { + const pos = bot.entity.position + const id = `${Math.floor(pos.x / 16) * 16},${Math.floor(pos.y / 16) * 16},${Math.floor(pos.z / 16) * 16}` + getThreeJsRendererMethods()?.addSectionAnimation(id, { + time: performance.now(), + speedX: 0, + speedY, + speedZ: 0, + currentOffsetX: 0, + currentOffsetY: 0, + currentOffsetZ: 0, + // limitX: 10, + // limitY: 10, + }) +} + const registeredJeiChannel = () => { const CHANNEL_NAME = 'minecraft-web-client:jei' // id - string, categoryTitle - string, items - string (json array) @@ -137,10 +308,6 @@ const registerMediaChannels = () => { { name: 'z', type: 'f32' }, { name: 'width', type: 'f32' }, { name: 'height', type: 'f32' }, - // N, 0 - // W, 3 - // S, 2 - // E, 1 { name: 'rotation', type: 'i16' }, // 0: 0° - towards positive z, 1: 90° - positive x, 2: 180° - negative z, 3: 270° - negative x (3-6 is same but double side) { name: 'source', type: ['pstring', { countType: 'i16' }] }, { name: 'loop', type: 'bool' }, @@ -179,13 +346,30 @@ const registerMediaChannels = () => { ] // Register channels - bot._client.registerChannel(ADD_CHANNEL, addPacketStructure, true) - bot._client.registerChannel(PLAY_CHANNEL, noDataPacketStructure, true) - bot._client.registerChannel(PAUSE_CHANNEL, noDataPacketStructure, true) - bot._client.registerChannel(SEEK_CHANNEL, setNumberPacketStructure, true) - bot._client.registerChannel(VOLUME_CHANNEL, setNumberPacketStructure, true) - bot._client.registerChannel(SPEED_CHANNEL, setNumberPacketStructure, true) - bot._client.registerChannel(DESTROY_CHANNEL, noDataPacketStructure, true) + registerChannel(PLAY_CHANNEL, noDataPacketStructure, (data) => { + const { id } = data + getThreeJsRendererMethods()?.setVideoPlaying(id, true) + }, true) + registerChannel(PAUSE_CHANNEL, noDataPacketStructure, (data) => { + const { id } = data + getThreeJsRendererMethods()?.setVideoPlaying(id, false) + }, true) + registerChannel(SEEK_CHANNEL, setNumberPacketStructure, (data) => { + const { id, seconds } = data + getThreeJsRendererMethods()?.setVideoSeeking(id, seconds) + }, true) + registerChannel(VOLUME_CHANNEL, setNumberPacketStructure, (data) => { + const { id, volume } = data + getThreeJsRendererMethods()?.setVideoVolume(id, volume) + }, true) + registerChannel(SPEED_CHANNEL, setNumberPacketStructure, (data) => { + const { id, speed } = data + getThreeJsRendererMethods()?.setVideoSpeed(id, speed) + }, true) + registerChannel(DESTROY_CHANNEL, noDataPacketStructure, (data) => { + const { id } = data + getThreeJsRendererMethods()?.destroyMedia(id) + }, true) // Handle media add registerChannel(ADD_CHANNEL, addPacketStructure, (data) => { @@ -207,42 +391,6 @@ const registerMediaChannels = () => { }) }) - // Handle media play - registerChannel(PLAY_CHANNEL, noDataPacketStructure, (data) => { - const { id } = data - getThreeJsRendererMethods()?.setVideoPlaying(id, true) - }, true) - - // Handle media pause - registerChannel(PAUSE_CHANNEL, noDataPacketStructure, (data) => { - const { id } = data - getThreeJsRendererMethods()?.setVideoPlaying(id, false) - }, true) - - // Handle media seek - registerChannel(SEEK_CHANNEL, setNumberPacketStructure, (data) => { - const { id, seconds } = data - getThreeJsRendererMethods()?.setVideoSeeking(id, seconds) - }, true) - - // Handle media destroy - registerChannel(DESTROY_CHANNEL, noDataPacketStructure, (data) => { - const { id } = data - getThreeJsRendererMethods()?.destroyMedia(id) - }, true) - - // Handle media volume - registerChannel(VOLUME_CHANNEL, setNumberPacketStructure, (data) => { - const { id, volume } = data - getThreeJsRendererMethods()?.setVideoVolume(id, volume) - }, true) - - // Handle media speed - registerChannel(SPEED_CHANNEL, setNumberPacketStructure, (data) => { - const { id, speed } = data - getThreeJsRendererMethods()?.setVideoSpeed(id, speed) - }, true) - // --- // Video interaction channel @@ -258,15 +406,42 @@ const registerMediaChannels = () => { bot._client.registerChannel(MEDIA_INTERACTION_CHANNEL, interactionPacketStructure, true) + // Media play channel + bot._client.registerChannel(MEDIA_PLAY_CHANNEL_CLIENTBOUND, noDataPacketStructure, true) + const mediaStopPacketStructure = [ + 'container', + [ + { name: 'id', type: ['pstring', { countType: 'i16' }] }, + // ended - emitted even when loop is true (will continue playing) + // error: ... + // stalled - connection drops, server stops sending data + // waiting - connection is slow, server is sending data, but not fast enough (buffering) + // control + { name: 'reason', type: ['pstring', { countType: 'i16' }] }, + { name: 'time', type: 'f32' } + ] + ] + bot._client.registerChannel(MEDIA_STOP_CHANNEL_CLIENTBOUND, mediaStopPacketStructure, true) + console.debug('Registered media channels') } const MEDIA_INTERACTION_CHANNEL = 'minecraft-web-client:media-interaction' +const MEDIA_PLAY_CHANNEL_CLIENTBOUND = 'minecraft-web-client:media-play' +const MEDIA_STOP_CHANNEL_CLIENTBOUND = 'minecraft-web-client:media-stop' export const sendVideoInteraction = (id: string, x: number, y: number, isRightClick: boolean) => { bot._client.writeChannel(MEDIA_INTERACTION_CHANNEL, { id, x, y, isRightClick }) } +export const sendVideoPlay = (id: string) => { + bot._client.writeChannel(MEDIA_PLAY_CHANNEL_CLIENTBOUND, { id }) +} + +export const sendVideoStop = (id: string, reason: string, time: number) => { + bot._client.writeChannel(MEDIA_STOP_CHANNEL_CLIENTBOUND, { id, reason, time }) +} + export const videoCursorInteraction = () => { const { intersectMedia } = appViewer.rendererState.world if (!intersectMedia) return null diff --git a/src/customClient.js b/src/customClient.js index b6c85fcc..b1a99904 100644 --- a/src/customClient.js +++ b/src/customClient.js @@ -1,6 +1,7 @@ +//@ts-check +import * as nbt from 'prismarine-nbt' import { options } from './optionsStorage' -//@ts-check const { EventEmitter } = require('events') const debug = require('debug')('minecraft-protocol') const states = require('minecraft-protocol/src/states') @@ -51,8 +52,20 @@ class CustomChannelClient extends EventEmitter { this.emit('state', newProperty, oldProperty) } - end(reason) { - this._endReason = reason + end(endReason, fullReason) { + // eslint-disable-next-line unicorn/no-this-assignment + const client = this + if (client.state === states.PLAY) { + fullReason ||= loadedData.supportFeature('chatPacketsUseNbtComponents') + ? nbt.comp({ text: nbt.string(endReason) }) + : JSON.stringify({ text: endReason }) + client.write('kick_disconnect', { reason: fullReason }) + } else if (client.state === states.LOGIN) { + fullReason ||= JSON.stringify({ text: endReason }) + client.write('disconnect', { reason: fullReason }) + } + + this._endReason = endReason this.emit('end', this._endReason) // still emits on server side only, doesn't send anything to our client } diff --git a/src/dayCycle.ts b/src/dayCycle.ts deleted file mode 100644 index 50e63a21..00000000 --- a/src/dayCycle.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { options } from './optionsStorage' -import { assertDefined } from './utils' -import { updateBackground } from './water' - -export default () => { - const timeUpdated = () => { - // 0 morning - const dayTotal = 24_000 - const evening = 11_500 - const night = 13_500 - const morningStart = 23_000 - const morningEnd = 23_961 - const timeProgress = options.dayCycleAndLighting ? bot.time.timeOfDay : 0 - - // todo check actual colors - const dayColorRainy = { r: 111 / 255, g: 156 / 255, b: 236 / 255 } - // todo yes, we should make animations (and rain) - // eslint-disable-next-line unicorn/numeric-separators-style - const dayColor = bot.isRaining ? dayColorRainy : { r: 0.6784313725490196, g: 0.8470588235294118, b: 0.9019607843137255 } // lightblue - // let newColor = dayColor - let int = 1 - if (timeProgress < evening) { - // stay dayily - } else if (timeProgress < night) { - const progressNorm = timeProgress - evening - const progressMax = night - evening - int = 1 - progressNorm / progressMax - } else if (timeProgress < morningStart) { - int = 0 - } else if (timeProgress < morningEnd) { - const progressNorm = timeProgress - morningStart - const progressMax = night - morningEnd - int = progressNorm / progressMax - } - // todo need to think wisely how to set these values & also move directional light around! - const colorInt = Math.max(int, 0.1) - updateBackground({ r: dayColor.r * colorInt, g: dayColor.g * colorInt, b: dayColor.b * colorInt }) - if (!options.newVersionsLighting && bot.supportFeature('blockStateId')) { - appViewer.playerState.reactive.ambientLight = Math.max(int, 0.25) - appViewer.playerState.reactive.directionalLight = Math.min(int, 0.5) - } - } - - bot.on('time', timeUpdated) - timeUpdated() -} diff --git a/src/defaultLocalServerOptions.js b/src/defaultLocalServerOptions.js index cd949567..3b93910d 100644 --- a/src/defaultLocalServerOptions.js +++ b/src/defaultLocalServerOptions.js @@ -8,6 +8,7 @@ module.exports = { 'gameMode': 0, 'difficulty': 0, 'worldFolder': 'world', + 'pluginsFolder': true, // todo set sid, disable entities auto-spawn 'generation': { // grass_field @@ -33,6 +34,6 @@ module.exports = { keepAlive: false, 'everybody-op': true, 'max-entities': 100, - 'version': '1.18.2', + 'version': '1.18', versionMajor: '1.18' } diff --git a/src/defaultOptions.ts b/src/defaultOptions.ts new file mode 100644 index 00000000..48c1cfad --- /dev/null +++ b/src/defaultOptions.ts @@ -0,0 +1,159 @@ +export const defaultOptions = { + renderDistance: 3, + keepChunksDistance: 1, + multiplayerRenderDistance: 3, + closeConfirmation: true, + autoFullScreen: false, + mouseRawInput: true, + autoExitFullscreen: false, + localUsername: 'wanderer', + mouseSensX: 50, + mouseSensY: -1, + chatWidth: 320, + chatHeight: 180, + chatScale: 100, + chatOpacity: 100, + chatOpacityOpened: 100, + messagesLimit: 200, + volume: 50, + enableMusic: true, + musicVolume: 50, + // fov: 70, + fov: 75, + defaultPerspective: 'first_person' as 'first_person' | 'third_person_back' | 'third_person_front', + guiScale: 3, + autoRequestCompletions: true, + touchButtonsSize: 40, + touchButtonsOpacity: 80, + touchButtonsPosition: 12, + touchControlsPositions: getDefaultTouchControlsPositions(), + touchControlsSize: getTouchControlsSize(), + touchMovementType: 'modern' as 'modern' | 'classic', + touchInteractionType: 'classic' as 'classic' | 'buttons', + gpuPreference: 'default' as 'default' | 'high-performance' | 'low-power', + backgroundRendering: '20fps' as 'full' | '20fps' | '5fps', + /** @unstable */ + disableAssets: false, + /** @unstable */ + debugLogNotFrequentPackets: false, + unimplementedContainers: false, + dayCycleAndLighting: true, + loadPlayerSkins: true, + renderEars: true, + lowMemoryMode: false, + starfieldRendering: true, + defaultSkybox: true, + enabledResourcepack: null as string | null, + useVersionsTextures: 'latest', + serverResourcePacks: 'prompt' as 'prompt' | 'always' | 'never', + showHand: true, + viewBobbing: true, + displayRecordButton: true, + packetsLoggerPreset: 'all' as 'all' | 'no-buffers', + serversAutoVersionSelect: 'auto' as 'auto' | 'latest' | '1.20.4' | string, + customChannels: false, + remoteContentNotSameOrigin: false as boolean | string[], + packetsRecordingAutoStart: false, + language: 'auto', + preciseMouseInput: false, + // todo ui setting, maybe enable by default? + waitForChunksRender: false as 'sp-only' | boolean, + jeiEnabled: true as boolean | Array<'creative' | 'survival' | 'adventure' | 'spectator'>, + modsSupport: false, + modsAutoUpdate: 'check' as 'check' | 'never' | 'always', + modsUpdatePeriodCheck: 24, // hours + preventBackgroundTimeoutKick: false, + preventSleep: false, + debugContro: false, + debugChatScroll: false, + chatVanillaRestrictions: true, + debugResponseTimeIndicator: false, + chatPingExtension: true, + // antiAliasing: false, + topRightTimeDisplay: 'only-fullscreen' as 'only-fullscreen' | 'always' | 'never', + + clipWorldBelowY: undefined as undefined | number, // will be removed + disableSignsMapsSupport: false, + singleplayerAutoSave: false, + showChunkBorders: false, // todo rename option + frameLimit: false as number | false, + alwaysBackupWorldBeforeLoading: undefined as boolean | undefined | null, + alwaysShowMobileControls: false, + excludeCommunicationDebugEvents: [] as string[], + preventDevReloadWhilePlaying: false, + numWorkers: 4, + localServerOptions: { + gameMode: 1 + } as any, + saveLoginPassword: 'prompt' as 'prompt' | 'never' | 'always', + preferLoadReadonly: false, + experimentalClientSelfReload: false, + remoteSoundsSupport: false, + remoteSoundsLoadTimeout: 500, + disableLoadPrompts: false, + guestUsername: 'guest', + askGuestName: true, + errorReporting: true, + /** Actually might be useful */ + showCursorBlockInSpectator: false, + renderEntities: true, + smoothLighting: true, + newVersionsLighting: false, + chatSelect: true, + autoJump: 'auto' as 'auto' | 'always' | 'never', + autoParkour: false, + vrSupport: true, // doesn't directly affect the VR mode, should only disable the button which is annoying to android users + vrPageGameRendering: false, + renderDebug: 'basic' as 'none' | 'advanced' | 'basic', + rendererPerfDebugOverlay: false, + + // advanced bot options + autoRespawn: false, + mutedSounds: [] as string[], + plugins: [] as Array<{ enabled: boolean, name: string, description: string, script: string }>, + /** Wether to popup sign editor on server action */ + autoSignEditor: true, + wysiwygSignEditor: 'auto' as 'auto' | 'always' | 'never', + showMinimap: 'never' as 'always' | 'singleplayer' | 'never', + minimapOptimizations: true, + displayBossBars: true, + disabledUiParts: [] as string[], + neighborChunkUpdates: true, + highlightBlockColor: 'auto' as 'auto' | 'blue' | 'classic', + activeRenderer: 'threejs', + rendererSharedOptions: { + _experimentalSmoothChunkLoading: true, + _renderByChunks: false + } +} + +function getDefaultTouchControlsPositions () { + return { + action: [ + 70, + 76 + ], + sneak: [ + 84, + 76 + ], + break: [ + 70, + 57 + ], + jump: [ + 84, + 57 + ], + } as Record +} + +function getTouchControlsSize () { + return { + joystick: 55, + action: 36, + break: 36, + jump: 36, + sneak: 36, + } +} diff --git a/src/devtools.ts b/src/devtools.ts index 5b15711f..1f8ef8e8 100644 --- a/src/devtools.ts +++ b/src/devtools.ts @@ -5,6 +5,17 @@ import { WorldRendererThree } from 'renderer/viewer/three/worldrendererThree' import { enable, disable, enabled } from 'debug' import { Vec3 } from 'vec3' +customEvents.on('mineflayerBotCreated', () => { + window.debugServerPacketNames = Object.fromEntries(Object.keys(loadedData.protocol.play.toClient.types).map(name => { + name = name.replace('packet_', '') + return [name, name] + })) + window.debugClientPacketNames = Object.fromEntries(Object.keys(loadedData.protocol.play.toServer.types).map(name => { + name = name.replace('packet_', '') + return [name, name] + })) +}) + window.Vec3 = Vec3 window.cursorBlockRel = (x = 0, y = 0, z = 0) => { const newPos = bot.blockAtCursor(5)?.position.offset(x, y, z) @@ -21,7 +32,8 @@ window.inspectPlayer = () => require('fs').promises.readFile('/world/playerdata/ Object.defineProperty(window, 'debugSceneChunks', { get () { - return (window.world as WorldRendererThree)?.getLoadedChunksRelative?.(bot.entity.position, true) + if (!(window.world instanceof WorldRendererThree)) return undefined + return (window.world)?.getLoadedChunksRelative?.(bot.entity.position, true) }, }) @@ -149,7 +161,7 @@ Object.defineProperty(window, 'debugToggle', { }) customEvents.on('gameLoaded', () => { - window.holdingBlock = (window.world as WorldRendererThree).holdingBlock + window.holdingBlock = (window.world as WorldRendererThree | undefined)?.holdingBlock }) window.clearStorage = (...keysToKeep: string[]) => { @@ -208,3 +220,105 @@ setInterval(() => { }, 1000) // --- + +// Add type declaration for performance.memory +declare global { + interface Performance { + memory?: { + usedJSHeapSize: number + totalJSHeapSize: number + jsHeapSizeLimit: number + } + } +} + +// Performance metrics WebSocket client +let ws: WebSocket | null = null +let wsReconnectTimeout: NodeJS.Timeout | null = null +let metricsInterval: NodeJS.Timeout | null = null + +// Start collecting metrics immediately +const startTime = performance.now() + +function collectAndSendMetrics () { + if (!ws || ws.readyState !== WebSocket.OPEN) return + + const metrics = { + loadTime: performance.now() - startTime, + memoryUsage: (performance.memory?.usedJSHeapSize ?? 0) / 1024 / 1024, + timestamp: Date.now() + } + + ws.send(JSON.stringify(metrics)) +} + +function getWebSocketUrl () { + const wsPort = process.env.WS_PORT + if (!wsPort) return null + + const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:' + const { hostname } = window.location + return `${protocol}//${hostname}:${wsPort}` +} + +function connectWebSocket () { + if (ws) return + + const wsUrl = getWebSocketUrl() + if (!wsUrl) { + return + } + + ws = new WebSocket(wsUrl) + + ws.onopen = () => { + console.log('Connected to metrics server') + if (wsReconnectTimeout) { + clearTimeout(wsReconnectTimeout) + wsReconnectTimeout = null + } + + // Start sending metrics immediately after connection + collectAndSendMetrics() + + // Clear existing interval if any + if (metricsInterval) { + clearInterval(metricsInterval) + } + + // Set new interval + metricsInterval = setInterval(collectAndSendMetrics, 500) + } + + ws.onclose = () => { + console.log('Disconnected from metrics server') + ws = null + + // Clear metrics interval + if (metricsInterval) { + clearInterval(metricsInterval) + metricsInterval = null + } + + // Try to reconnect after 3 seconds + wsReconnectTimeout = setTimeout(connectWebSocket, 3000) + } + + ws.onerror = (error) => { + console.error('WebSocket error:', error) + } +} + +// Connect immediately +connectWebSocket() + +// Add command to request current metrics +window.requestMetrics = () => { + const metrics = { + loadTime: performance.now() - startTime, + memoryUsage: (performance.memory?.usedJSHeapSize ?? 0) / 1024 / 1024, + timestamp: Date.now() + } + console.log('Current metrics:', metrics) + return metrics +} diff --git a/src/downloadAndOpenFile.ts b/src/downloadAndOpenFile.ts index 78cd6984..1ff318ff 100644 --- a/src/downloadAndOpenFile.ts +++ b/src/downloadAndOpenFile.ts @@ -5,13 +5,25 @@ import { setLoadingScreenStatus } from './appStatus' import { appQueryParams, appQueryParamsArray } from './appParams' import { VALID_REPLAY_EXTENSIONS, openFile } from './packetsReplay/replayPackets' import { createFullScreenProgressReporter } from './core/progressReporter' +import { ConnectOptions } from './connect' export const getFixedFilesize = (bytes: number) => { return prettyBytes(bytes, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) } +export const isInterestedInDownload = () => { + const { map, texturepack, replayFileUrl } = appQueryParams + const { mapDir } = appQueryParamsArray + return !!map || !!texturepack || !!replayFileUrl || !!mapDir +} + const inner = async () => { - const { replayFileUrl } = appQueryParams + const { map, texturepack, replayFileUrl } = appQueryParams + const { mapDir } = appQueryParamsArray + return downloadAndOpenMapFromUrl(map, texturepack, mapDir, replayFileUrl) +} + +export const downloadAndOpenMapFromUrl = async (mapUrl: string | undefined, texturepackUrl: string | undefined, mapUrlDir: string[] | undefined, replayFileUrl: string | undefined, connectOptions?: Partial) => { if (replayFileUrl) { setLoadingScreenStatus('Downloading replay file') const response = await fetch(replayFileUrl) @@ -58,31 +70,30 @@ const inner = async () => { return true } - const mapUrlDir = appQueryParamsArray.mapDir ?? [] const mapUrlDirGuess = appQueryParams.mapDirGuess const mapUrlDirBaseUrl = appQueryParams.mapDirBaseUrl - if (mapUrlDir.length) { + if (mapUrlDir?.length) { await openWorldFromHttpDir(mapUrlDir, mapUrlDirBaseUrl ?? undefined) return true } + if (mapUrlDirGuess) { // await openWorldFromHttpDir(undefined, mapUrlDirGuess) return true } - let mapUrl = appQueryParams.map - const { texturepack } = appQueryParams + // fixme - if (texturepack) mapUrl = texturepack + if (texturepackUrl) mapUrl = texturepackUrl if (!mapUrl) return false - if (texturepack) { + if (texturepackUrl) { await updateTexturePackInstalledState() if (resourcePackState.resourcePackInstalled) { if (!confirm(`You are going to install a new resource pack, which will REPLACE the current one: ${await getResourcePackNames()[0]} Continue?`)) return } } const name = mapUrl.slice(mapUrl.lastIndexOf('/') + 1).slice(-25) - const downloadThing = texturepack ? 'texturepack' : 'world' + const downloadThing = texturepackUrl ? 'texturepack' : 'world' setLoadingScreenStatus(`Downloading ${downloadThing} ${name}...`) const response = await fetch(mapUrl) @@ -115,25 +126,25 @@ const inner = async () => { const progress = contentLength ? (downloadedBytes / contentLength) * 100 : undefined setLoadingScreenStatus(`Download ${downloadThing} progress: ${progress === undefined ? '?' : Math.floor(progress)}% (${getFixedFilesize(downloadedBytes)} / ${contentLength && getFixedFilesize(contentLength)})`, false, true) - // Pass the received data to the controller controller.enqueue(value) } }, })).arrayBuffer() - if (texturepack) { + if (texturepackUrl) { const name = mapUrl.slice(mapUrl.lastIndexOf('/') + 1).slice(-30) await installResourcepackPack(buffer, createFullScreenProgressReporter(), name) } else { - await openWorldZip(buffer) + await openWorldZip(buffer, undefined, connectOptions) } + return true } export default async () => { try { return await inner() } catch (err) { - setLoadingScreenStatus(`Failed to download. Either refresh page or remove map param from URL. Reason: ${err.message}`) + setLoadingScreenStatus(`Failed to download/open. Either refresh page or remove map param from URL. Reason: ${err.message}`) return true } } diff --git a/src/dragndrop.ts b/src/dragndrop.ts index 6be90551..5a16bc05 100644 --- a/src/dragndrop.ts +++ b/src/dragndrop.ts @@ -3,6 +3,7 @@ import fs from 'fs' import * as nbt from 'prismarine-nbt' import RegionFile from 'prismarine-provider-anvil/src/region' import { versions } from 'minecraft-data' +import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' import { openWorldDirectory, openWorldZip } from './browserfs' import { isGameActive } from './globalState' import { showNotification } from './react/NotificationProvider' @@ -12,6 +13,9 @@ const parseNbt = promisify(nbt.parse) const simplifyNbt = nbt.simplify window.nbt = nbt +// Supported image types for skybox +const VALID_IMAGE_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.webp'] + // todo display drop zone for (const event of ['drag', 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'drop']) { window.addEventListener(event, (e: any) => { @@ -45,6 +49,34 @@ window.addEventListener('drop', async e => { }) async function handleDroppedFile (file: File) { + // Check for image files first when game is active + if (isGameActive(false) && VALID_IMAGE_EXTENSIONS.some(ext => file.name.toLowerCase().endsWith(ext))) { + try { + // Convert image to base64 + const reader = new FileReader() + const base64Promise = new Promise((resolve, reject) => { + reader.onload = () => resolve(reader.result as string) + reader.onerror = reject + }) + reader.readAsDataURL(file) + const base64Image = await base64Promise + + // Get ThreeJS backend methods and update skybox + const setSkyboxImage = getThreeJsRendererMethods()?.setSkyboxImage + if (setSkyboxImage) { + await setSkyboxImage(base64Image) + showNotification('Skybox updated successfully') + } else { + showNotification('Cannot update skybox - renderer does not support it') + } + return + } catch (err) { + console.error('Failed to update skybox:', err) + showNotification('Failed to update skybox', 'error') + return + } + } + if (file.name.endsWith('.zip')) { void openWorldZip(file) return diff --git a/src/entities.ts b/src/entities.ts index 9ba31f2e..674f91ef 100644 --- a/src/entities.ts +++ b/src/entities.ts @@ -4,15 +4,17 @@ import tracker from '@nxg-org/mineflayer-tracker' import { loader as autoJumpPlugin } from '@nxg-org/mineflayer-auto-jump' import { subscribeKey } from 'valtio/utils' import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' +import { Team } from 'mineflayer' import { options, watchValue } from './optionsStorage' -import { miscUiState } from './globalState' +import { gameAdditionalState, miscUiState } from './globalState' +import { EntityStatus } from './mineflayer/entityStatus' const updateAutoJump = () => { if (!bot?.autoJumper) return const autoJump = options.autoParkour || (options.autoJump === 'auto' ? miscUiState.currentTouch && !miscUiState.usingGamepadInput : options.autoJump === 'always') bot.autoJumper.setOpts({ - jumpIntoWater: options.autoParkour, + // jumpIntoWater: options.autoParkour, jumpOnAllEdges: options.autoParkour, // strictBlockCollision: true, }) @@ -42,7 +44,7 @@ customEvents.on('gameLoaded', () => { updateAutoJump() const playerPerAnimation = {} as Record - const entityData = (e: Entity) => { + const checkEntityData = (e: Entity) => { if (!e.username) return window.debugEntityMetadata ??= {} window.debugEntityMetadata[e.username] = e @@ -51,6 +53,13 @@ customEvents.on('gameLoaded', () => { } } + const trackBotEntity = () => { + // Always track the bot entity for animations + if (bot.entity) { + bot.tracker.trackEntity(bot.entity) + } + } + let lastCall = 0 bot.on('physicsTick', () => { // throttle, tps: 6 @@ -60,14 +69,24 @@ customEvents.on('gameLoaded', () => { if (!tracking) continue const e = bot.entities[id] if (!e) continue - const speed = info.avgSpeed + const speed = info.avgVel const WALKING_SPEED = 0.03 const SPRINTING_SPEED = 0.18 + const isCrouched = e === bot.entity ? gameAdditionalState.isSneaking : e['crouching'] const isWalking = Math.abs(speed.x) > WALKING_SPEED || Math.abs(speed.z) > WALKING_SPEED const isSprinting = Math.abs(speed.x) > SPRINTING_SPEED || Math.abs(speed.z) > SPRINTING_SPEED - const newAnimation = isWalking ? (isSprinting ? 'running' : 'walking') : 'idle' + + const newAnimation = + isCrouched ? (isWalking ? 'crouchWalking' : 'crouch') + : isWalking ? (isSprinting ? 'running' : 'walking') + : 'idle' if (newAnimation !== playerPerAnimation[id]) { - getThreeJsRendererMethods()?.playEntityAnimation(e.id, newAnimation) + // Handle bot entity animation specially (for player entity in third person) + if (e === bot.entity) { + getThreeJsRendererMethods()?.playEntityAnimation('player_entity', newAnimation) + } else { + getThreeJsRendererMethods()?.playEntityAnimation(e.id, newAnimation) + } playerPerAnimation[id] = newAnimation } } @@ -77,6 +96,25 @@ customEvents.on('gameLoaded', () => { getThreeJsRendererMethods()?.playEntityAnimation(e.id, 'oneSwing') }) + bot.on('botArmSwingStart', (hand) => { + if (hand === 'right') { + getThreeJsRendererMethods()?.playEntityAnimation('player_entity', 'oneSwing') + } + }) + + bot.inventory.on('updateSlot', (slot) => { + if (slot === 5 || slot === 6 || slot === 7 || slot === 8) { + const item = bot.inventory.slots[slot]! + bot.entity.equipment[slot - 3] = item + appViewer.worldView?.emit('playerEntity', bot.entity) + } + }) + bot.on('heldItemChanged', () => { + const item = bot.inventory.slots[bot.quickBarSlot + 36]! + bot.entity.equipment[0] = item + appViewer.worldView?.emit('playerEntity', bot.entity) + }) + bot._client.on('damage_event', (data) => { const { entityId, sourceTypeId: damage } = data getThreeJsRendererMethods()?.damageEntity(entityId, damage) @@ -85,63 +123,246 @@ customEvents.on('gameLoaded', () => { bot._client.on('entity_status', (data) => { if (versionToNumber(bot.version) >= versionToNumber('1.19.4')) return const { entityId, entityStatus } = data - if (entityStatus === 2) { + if (entityStatus === EntityStatus.HURT) { getThreeJsRendererMethods()?.damageEntity(entityId, entityStatus) } + + if (entityStatus === EntityStatus.BURNED) { + updateEntityStates(entityId, true, true) + } }) + // on fire events + bot._client.on('entity_metadata', (data) => { + if (data.entityId !== bot.entity.id) return + handleEntityMetadata(data) + }) + + bot.on('end', () => { + if (onFireTimeout) { + clearTimeout(onFireTimeout) + } + }) + + bot.on('respawn', () => { + if (onFireTimeout) { + clearTimeout(onFireTimeout) + } + }) + + const updateCamera = (entity: Entity) => { + if (bot.game.gameMode !== 'spectator') return + bot.entity.position = entity.position.clone() + void bot.look(entity.yaw, entity.pitch, true) + bot.entity.yaw = entity.yaw + bot.entity.pitch = entity.pitch + } + bot.on('entityGone', (entity) => { bot.tracker.stopTrackingEntity(entity, true) }) bot.on('entityMoved', (e) => { - entityData(e) + checkEntityData(e) + if (appViewer.playerState.reactive.cameraSpectatingEntity === e.id) { + updateCamera(e) + } }) bot._client.on('entity_velocity', (packet) => { const e = bot.entities[packet.entityId] if (!e) return - entityData(e) + checkEntityData(e) }) for (const entity of Object.values(bot.entities)) { if (entity !== bot.entity) { - entityData(entity) + checkEntityData(entity) } } - bot.on('entitySpawn', entityData) - bot.on('entityUpdate', entityData) - bot.on('entityEquip', entityData) + // Track bot entity initially + trackBotEntity() + + bot.on('entitySpawn', (e) => { + checkEntityData(e) + if (appViewer.playerState.reactive.cameraSpectatingEntity === e.id) { + updateCamera(e) + } + }) + bot.on('entityUpdate', checkEntityData) + bot.on('entityEquip', checkEntityData) + + // Re-track bot entity after login + bot.on('login', () => { + setTimeout(() => { + trackBotEntity() + }) // Small delay to ensure bot.entity is properly set + }) + + bot._client.on('camera', (packet) => { + if (bot.player.entity.id === packet.cameraId) { + if (appViewer.playerState.utils.isSpectatingEntity() && appViewer.playerState.reactive.cameraSpectatingEntity) { + const entity = bot.entities[appViewer.playerState.reactive.cameraSpectatingEntity] + appViewer.playerState.reactive.cameraSpectatingEntity = undefined + if (entity) { + // do a force entity update + bot.emit('entityUpdate', entity) + } + } + } else if (appViewer.playerState.reactive.gameMode === 'spectator') { + const entity = bot.entities[packet.cameraId] + appViewer.playerState.reactive.cameraSpectatingEntity = packet.cameraId + if (entity) { + updateCamera(entity) + // do a force entity update + bot.emit('entityUpdate', entity) + } + } + }) + + const applySkinTexturesProxy = (url: string | undefined) => { + const { appConfig } = miscUiState + if (appConfig?.skinTexturesProxy) { + return url?.replace('http://textures.minecraft.net/', appConfig.skinTexturesProxy) + .replace('https://textures.minecraft.net/', appConfig.skinTexturesProxy) + } + return url + } // Texture override from packet properties - bot._client.on('player_info', (packet) => { - for (const playerEntry of packet.data) { - if (!playerEntry.player && !playerEntry.properties) continue - let textureProperty = playerEntry.properties?.find(prop => prop?.name === 'textures') - if (!textureProperty) { - textureProperty = playerEntry.player?.properties?.find(prop => prop?.key === 'textures') - } - if (textureProperty) { - try { - const textureData = JSON.parse(Buffer.from(textureProperty.value, 'base64').toString()) - const skinUrl = textureData.textures?.SKIN?.url - const capeUrl = textureData.textures?.CAPE?.url + const updateSkin = (player: import('mineflayer').Player) => { + if (!player.uuid || !player.username || !player.skinData) return - // Find entity with matching UUID and update skin - let entityId = '' - for (const [entId, entity] of Object.entries(bot.entities)) { - if (entity.uuid === playerEntry.uuid) { - entityId = entId - break - } - } - // even if not found, still record to cache - getThreeJsRendererMethods()?.updatePlayerSkin(entityId, playerEntry.player?.name, playerEntry.uuid, skinUrl, capeUrl) - } catch (err) { - console.error('Error decoding player texture:', err) + try { + const skinUrl = applySkinTexturesProxy(player.skinData.url) + const capeUrl = applySkinTexturesProxy((player.skinData as any).capeUrl) + + // Find entity with matching UUID and update skin + let entityId = '' + for (const [entId, entity] of Object.entries(bot.entities)) { + if (entity.uuid === player.uuid) { + entityId = entId + break + } + } + // even if not found, still record to cache + void getThreeJsRendererMethods()!.updatePlayerSkin(entityId, player.username, player.uuid, skinUrl ?? true, capeUrl) + } catch (err) { + reportError(new Error('Error applying skin texture:', { cause: err })) + } + } + + bot.on('playerJoined', updateSkin) + bot.on('playerUpdated', updateSkin) + for (const entity of Object.values(bot.players)) { + updateSkin(entity) + } + + const teamUpdated = (team: Team) => { + for (const entity of Object.values(bot.entities)) { + if (entity.type === 'player' && entity.username && team.members.includes(entity.username) || entity.uuid && team.members.includes(entity.uuid)) { + bot.emit('entityUpdate', entity) + } + } + } + bot.on('teamUpdated', teamUpdated) + for (const team of Object.values(bot.teams)) { + teamUpdated(team) + } + + const updateEntityNameTags = (team: Team) => { + for (const entity of Object.values(bot.entities)) { + const entityTeam = entity.type === 'player' && entity.username ? bot.teamMap[entity.username] : entity.uuid ? bot.teamMap[entity.uuid] : undefined + if ((entityTeam?.nameTagVisibility === 'hideForOwnTeam' && entityTeam.name === team.name) + || (entityTeam?.nameTagVisibility === 'hideForOtherTeams' && entityTeam.name !== team.name)) { + bot.emit('entityUpdate', entity) + } + } + } + + const doEntitiesNeedUpdating = (team: Team) => { + return team.nameTagVisibility === 'never' + || (team.nameTagVisibility === 'hideForOtherTeams' && appViewer.playerState.reactive.team?.team !== team.team) + || (team.nameTagVisibility === 'hideForOwnTeam' && appViewer.playerState.reactive.team?.team === team.team) + } + + bot.on('teamMemberAdded', (team: Team, members: string[]) => { + if (members.includes(bot.username) && appViewer.playerState.reactive.team?.team !== team.team) { + appViewer.playerState.reactive.team = team + // Player was added to a team, need to check if any entities need updating + updateEntityNameTags(team) + } else if (doEntitiesNeedUpdating(team)) { + // Need to update all entities that were added + for (const entity of Object.values(bot.entities)) { + if (entity.type === 'player' && entity.username && members.includes(entity.username) || entity.uuid && members.includes(entity.uuid)) { + bot.emit('entityUpdate', entity) } } } - }) + + bot.on('teamMemberRemoved', (team: Team, members: string[]) => { + if (members.includes(bot.username) && appViewer.playerState.reactive.team?.team === team.team) { + appViewer.playerState.reactive.team = undefined + // Player was removed from a team, need to check if any entities need updating + updateEntityNameTags(team) + } else if (doEntitiesNeedUpdating(team)) { + // Need to update all entities that were removed + for (const entity of Object.values(bot.entities)) { + if (entity.type === 'player' && entity.username && members.includes(entity.username) || entity.uuid && members.includes(entity.uuid)) { + bot.emit('entityUpdate', entity) + } + } + } + }) + + bot.on('teamRemoved', (team: Team) => { + if (appViewer.playerState.reactive.team?.team === team?.team) { + appViewer.playerState.reactive.team = undefined + // Player's team was removed, need to update all entities that are in a team + updateEntityNameTags(team) + } + }) + }) + +// Constants +const SHARED_FLAGS_KEY = 0 +const ENTITY_FLAGS = { + ON_FIRE: 0x01, // Bit 0 + SNEAKING: 0x02, // Bit 1 + SPRINTING: 0x08, // Bit 3 + SWIMMING: 0x10, // Bit 4 + INVISIBLE: 0x20, // Bit 5 + GLOWING: 0x40, // Bit 6 + FALL_FLYING: 0x80 // Bit 7 (elytra flying) +} + +let onFireTimeout: NodeJS.Timeout | undefined +const updateEntityStates = (entityId: number, onFire: boolean, timeout?: boolean) => { + if (entityId !== bot.entity.id) return + appViewer.playerState.reactive.onFire = onFire + if (onFireTimeout) { + clearTimeout(onFireTimeout) + } + if (timeout) { + onFireTimeout = setTimeout(() => { + updateEntityStates(entityId, false, false) + }, 5000) + } +} + +// Process entity metadata packet +function handleEntityMetadata (packet: { entityId: number, metadata: Array<{ key: number, type: string, value: number }> }) { + const { entityId, metadata } = packet + + // Find shared flags in metadata + const flagsData = metadata.find(meta => meta.key === SHARED_FLAGS_KEY && + meta.type === 'byte') + + // Update fire state if flags were found + if (flagsData) { + const wasOnFire = appViewer.playerState.reactive.onFire + appViewer.playerState.reactive.onFire = (flagsData.value & ENTITY_FLAGS.ON_FIRE) !== 0 + } +} diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 00000000..e565fcec --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1,37 @@ +declare namespace NodeJS { + interface ProcessEnv { + // Build configuration + NODE_ENV: 'development' | 'production' + MIN_MC_VERSION?: string + MAX_MC_VERSION?: string + ALWAYS_COMPRESS_LARGE_DATA?: 'true' | 'false' + SINGLE_FILE_BUILD?: 'true' | 'false' + WS_PORT?: string + DISABLE_SERVICE_WORKER?: 'true' | 'false' + CONFIG_JSON_SOURCE?: 'BUNDLED' | 'REMOTE' + LOCAL_CONFIG_FILE?: string + BUILD_VERSION?: string + + // Build internals + GITHUB_REPOSITORY?: string + VERCEL_GIT_REPO_OWNER?: string + VERCEL_GIT_REPO_SLUG?: string + + // UI + MAIN_MENU_LINKS?: string + ALWAYS_MINIMAL_SERVER_UI?: 'true' | 'false' + + // App features + ENABLE_COOKIE_STORAGE?: string + COOKIE_STORAGE_PREFIX?: string + + // Build info. Release information + RELEASE_TAG?: string + RELEASE_LINK?: string + RELEASE_CHANGELOG?: string + + // Build info + INLINED_APP_CONFIG?: string + GITHUB_URL?: string + } +} diff --git a/src/flyingSquidUtils.ts b/src/flyingSquidUtils.ts index 012830d9..2ae0be7c 100644 --- a/src/flyingSquidUtils.ts +++ b/src/flyingSquidUtils.ts @@ -18,9 +18,10 @@ export function nameToMcOfflineUUID (name) { } export async function savePlayers (autoSave: boolean) { + if (!localServer?.players[0]) return if (autoSave && new URL(location.href).searchParams.get('noSave') === 'true') return //@ts-expect-error TODO - await localServer!.savePlayersSingleplayer() + await localServer.savePlayersSingleplayer() } // todo flying squid should expose save function instead diff --git a/src/globalDomListeners.ts b/src/globalDomListeners.ts index 5055c600..bfce0d42 100644 --- a/src/globalDomListeners.ts +++ b/src/globalDomListeners.ts @@ -35,3 +35,12 @@ window.addEventListener('beforeunload', (event) => { event.returnValue = '' // Required for some browsers return 'The game is running. Are you sure you want to close this page?' }) + +window.addEventListener('contextmenu', (e) => { + const ALLOW_TAGS = ['INPUT', 'TEXTAREA', 'A'] + // allow if target is in ALLOW_TAGS or has selection text + if (ALLOW_TAGS.includes((e.target as HTMLElement)?.tagName) || window.getSelection()?.toString()) { + return + } + e.preventDefault() +}) diff --git a/src/globalState.ts b/src/globalState.ts index 2d77b720..b8982de7 100644 --- a/src/globalState.ts +++ b/src/globalState.ts @@ -8,7 +8,11 @@ import { AppConfig } from './appConfig' // todo: refactor structure with support of hideNext=false -export const notHideableModalsWithoutForce = new Set(['app-status']) +export const notHideableModalsWithoutForce = new Set([ + 'app-status', + 'divkit:nonclosable', + 'only-connect-server', +]) type Modal = ({ elem?: HTMLElement & Record } & { reactType: string }) @@ -35,13 +39,15 @@ const showModalInner = (modal: Modal) => { return true } -export const showModal = (elem: /* (HTMLElement & Record) | */{ reactType: string }) => { - const resolved = elem +export const showModal = (elem: /* (HTMLElement & Record) | */{ reactType: string } | string) => { + const resolved = typeof elem === 'string' ? { reactType: elem } : elem const curModal = activeModalStack.at(-1) - if (/* elem === curModal?.elem || */(elem.reactType && elem.reactType === curModal?.reactType) || !showModalInner(resolved)) return + if ((resolved.reactType && resolved.reactType === curModal?.reactType) || !showModalInner(resolved)) return activeModalStack.push(resolved) } +window.showModal = showModal + /** * * @returns true if previous modal was restored @@ -49,7 +55,7 @@ export const showModal = (elem: /* (HTMLElement & Record) | */{ re export const hideModal = (modal = activeModalStack.at(-1), data: any = undefined, options: { force?: boolean; restorePrevious?: boolean } = {}) => { const { force = false, restorePrevious = true } = options if (!modal) return - let cancel = notHideableModalsWithoutForce.has(modal.reactType) ? !force : undefined + let cancel = [...notHideableModalsWithoutForce].some(m => modal.reactType.startsWith(m)) ? !force : undefined if (force) { cancel = undefined } @@ -117,6 +123,7 @@ export const miscUiState = proxy({ /** wether game hud is shown (in playing state) */ gameLoaded: false, showUI: true, + showDebugHud: false, loadedServerIndex: '', /** currently trying to load or loaded mc version, after all data is loaded */ loadedDataVersion: null as string | null, diff --git a/src/globals.d.ts b/src/globals.d.ts index 2a854f16..7a2c6f1f 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -27,11 +27,30 @@ declare const customEvents: import('typed-emitter').default<{ search (q: string): void activateItem (item: Item, slot: number, offhand: boolean): void hurtAnimation (yaw?: number): void + customChannelRegister (channel: string, parser: any): void }> declare const beforeRenderFrame: Array<() => void> +declare const translate: (key: T) => T + +// API LAYER +declare const toggleMicrophoneMuted: undefined | (() => void) +declare const translateText: undefined | ((text: string) => string) declare interface Document { exitPointerLock?(): void } +declare module '*.frag' { + const png: string + export default png +} +declare module '*.vert' { + const png: string + export default png +} +declare module '*.wgsl' { + const png: string + export default png +} + declare interface Window extends Record { } diff --git a/src/globals.js b/src/globals.js index 005d422f..11351555 100644 --- a/src/globals.js +++ b/src/globals.js @@ -5,6 +5,12 @@ window.bot = undefined window.THREE = undefined window.localServer = undefined window.worldView = undefined -window.viewer = undefined +window.viewer = undefined // legacy +window.appViewer = undefined window.loadedData = undefined window.customEvents = new EventEmitter() +window.customEvents.setMaxListeners(10_000) +window.translate = (key) => { + if (typeof key !== 'string') return key + return window.translateText?.(key) ?? key +} diff --git a/src/googledrive.ts b/src/googledrive.ts index 76fa1ce2..5e5e9ae9 100644 --- a/src/googledrive.ts +++ b/src/googledrive.ts @@ -4,7 +4,6 @@ import React from 'react' import { loadScript } from 'renderer/viewer/lib/utils' import { loadGoogleDriveApi, loadInMemorySave } from './react/SingleplayerProvider' import { setLoadingScreenStatus } from './appStatus' -import { mountGoogleDriveFolder } from './browserfs' import { showOptionsModal } from './react/SelectOption' import { appQueryParams } from './appParams' @@ -67,7 +66,7 @@ export const possiblyHandleStateVariable = async () => { } setLoadingScreenStatus('Opening world in read only mode...') googleProviderState.accessToken = response.access_token - await mountGoogleDriveFolder(true, parsed.ids[0]) + // await mountGoogleDriveFolder(true, parsed.ids[0]) await loadInMemorySave('/google') } }) diff --git a/src/index.ts b/src/index.ts index 5e346ae1..7764188f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,7 @@ import './testCrasher' import './globals' import './devtools' import './entities' -import './customChannels' +import customChannels from './customChannels' import './globalDomListeners' import './mineflayer/maps' import './mineflayer/cameraShake' @@ -14,6 +14,7 @@ import './mineflayer/java-tester/index' import './external' import './appConfig' import './mineflayer/timers' +import './mineflayer/plugins' import { getServerInfo } from './mineflayer/mc-protocol' import { onGameLoad } from './inventoryWindows' import initCollisionShapes from './getCollisionInteractionShapes' @@ -27,12 +28,11 @@ import { options } from './optionsStorage' import './reactUi' import { lockUrl, onBotCreate } from './controls' import './dragndrop' -import { possiblyCleanHandle, resetStateAfterDisconnect } from './browserfs' -import { watchOptionsAfterViewerInit, watchOptionsAfterWorldViewInit } from './watchOptions' -import downloadAndOpenFile from './downloadAndOpenFile' +import { possiblyCleanHandle } from './browserfs' +import downloadAndOpenFile, { isInterestedInDownload } from './downloadAndOpenFile' import fs from 'fs' -import net from 'net' +import net, { Socket } from 'net' import mineflayer from 'mineflayer' import debug from 'debug' @@ -56,13 +56,12 @@ import { isCypress } from './standaloneUtils' import { startLocalServer, unsupportedLocalServerFeatures } from './createLocalServer' import defaultServerOptions from './defaultLocalServerOptions' -import dayCycle from './dayCycle' import { onAppLoad, resourcepackReload, resourcePackState } from './resourcePack' import { ConnectPeerOptions, connectToPeer } from './localServerMultiplayer' import CustomChannelClient from './customClient' import { registerServiceWorker } from './serviceWorker' -import { appStatusState, lastConnectOptions } from './react/AppStatusProvider' +import { appStatusState, lastConnectOptions, quickDevReconnect } from './react/AppStatusProvider' import { fsState } from './loadSave' import { watchFov } from './rendererUtils' @@ -74,29 +73,30 @@ import { showNotification } from './react/NotificationProvider' import { saveToBrowserMemory } from './react/PauseScreen' import './devReload' import './water' -import { ConnectOptions, loadMinecraftData, getVersionAutoSelect, downloadOtherGameData, downloadAllMinecraftData } from './connect' +import { ConnectOptions, getVersionAutoSelect, downloadOtherGameData, downloadAllMinecraftData, loadMinecraftData } from './connect' import { ref, subscribe } from 'valtio' import { signInMessageState } from './react/SignInMessageProvider' -import { updateAuthenticatedAccountData, updateLoadedServerData, updateServerConnectionHistory } from './react/serversStorage' -import packetsPatcher from './mineflayer/plugins/packetsPatcher' +import { findServerPassword, updateAuthenticatedAccountData, updateLoadedServerData, updateServerConnectionHistory } from './react/serversStorage' import { mainMenuState } from './react/MainMenuRenderApp' import './mobileShim' import { parseFormattedMessagePacket } from './botUtils' -import { getViewerVersionData, getWsProtocolStream, handleCustomChannel } from './viewerConnector' +import { appStartup } from './clientMods' +import { getViewerVersionData, getWsProtocolStream, onBotCreatedViewerHandler } from './viewerConnector' import { getWebsocketStream } from './mineflayer/websocket-core' import { appQueryParams, appQueryParamsArray } from './appParams' import { playerState } from './mineflayer/playerState' import { states } from 'minecraft-protocol' import { initMotionTracking } from './react/uiMotion' import { UserError } from './mineflayer/userError' -import ping from './mineflayer/plugins/ping' -import mouse from './mineflayer/plugins/mouse' import { startLocalReplayServer } from './packetsReplay/replayPackets' -import { localRelayServerPlugin } from './mineflayer/plugins/packetsRecording' -import { createConsoleLogProgressReporter, createFullScreenProgressReporter, ProgressReporter } from './core/progressReporter' +import { createFullScreenProgressReporter, createWrappedProgressReporter, ProgressReporter } from './core/progressReporter' import { appViewer } from './appViewer' -import createGraphicsBackend from 'renderer/viewer/three/graphicsBackend' -import { subscribeKey } from 'valtio/utils' +import './appViewerLoad' +import { registerOpenBenchmarkListener } from './benchmark' +import { tryHandleBuiltinCommand } from './builtinCommands' +import { loadingTimerState } from './react/LoadingTimer' +import { loadPluginsIntoWorld } from './react/CreateWorldProvider' +import { getCurrentProxy, getCurrentUsername } from './react/ServersList' window.debug = debug window.beforeRenderFrame = [] @@ -109,47 +109,32 @@ void registerServiceWorker().then(() => { watchFov() initCollisionShapes() initializePacketsReplay() -packetsPatcher() onAppLoad() +customChannels() if (appQueryParams.testCrashApp === '2') throw new Error('test') -const loadBackend = () => { - appViewer.loadBackend(createGraphicsBackend) -} -window.loadBackend = loadBackend -if (process.env.SINGLE_FILE_BUILD_MODE) { - const unsub = subscribeKey(miscUiState, 'fsReady', () => { - if (miscUiState.fsReady) { - // don't do it earlier to load fs and display menu faster - loadBackend() - unsub() - } - }) -} else { - loadBackend() -} - -const animLoop = () => { - for (const fn of beforeRenderFrame) fn() - requestAnimationFrame(animLoop) -} -requestAnimationFrame(animLoop) - -watchOptionsAfterViewerInit() - function hideCurrentScreens () { activeModalStacks['main-menu'] = [...activeModalStack] insertActiveModalStack('', []) } -const loadSingleplayer = (serverOverrides = {}, flattenedServerOverrides = {}) => { +const loadSingleplayer = (serverOverrides = {}, flattenedServerOverrides = {}, connectOptions?: Partial) => { const serverSettingsQsRaw = appQueryParamsArray.serverSetting ?? [] const serverSettingsQs = serverSettingsQsRaw.map(x => x.split(':')).reduce>((acc, [key, value]) => { acc[key] = JSON.parse(value) return acc }, {}) - void connect({ singleplayer: true, username: options.localUsername, serverOverrides, serverOverridesFlat: { ...flattenedServerOverrides, ...serverSettingsQs } }) + void connect({ + singleplayer: true, + username: options.localUsername, + serverOverrides, + serverOverridesFlat: { + ...flattenedServerOverrides, + ...serverSettingsQs + }, + ...connectOptions + }) } function listenGlobalEvents () { window.addEventListener('connect', e => { @@ -157,7 +142,9 @@ function listenGlobalEvents () { void connect(options) }) window.addEventListener('singleplayer', (e) => { - loadSingleplayer((e as CustomEvent).detail) + const { detail } = (e as CustomEvent) + const { connectOptions, ...rest } = detail + loadSingleplayer(rest, {}, connectOptions) }) } @@ -173,7 +160,15 @@ export async function connect (connectOptions: ConnectOptions) { } }) } + if (sessionStorage.delayLoadUntilClick) { + await new Promise(resolve => { + window.addEventListener('click', resolve) + }) + } + appStatusState.showReconnect = false + loadingTimerState.loading = true + loadingTimerState.start = Date.now() miscUiState.hasErrors = false lastConnectOptions.value = connectOptions @@ -215,8 +210,19 @@ export async function connect (connectOptions: ConnectOptions) { let ended = false let bot!: typeof __type_bot - const destroyAll = () => { + let hadConnected = false + const destroyAll = (wasKicked = false) => { if (ended) return + loadingTimerState.loading = false + const { alwaysReconnect } = appQueryParams + if ((!wasKicked && miscUiState.appConfig?.allowAutoConnect && appQueryParams.autoConnect && hadConnected) || (alwaysReconnect)) { + if (alwaysReconnect === 'quick' || alwaysReconnect === 'fast') { + quickDevReconnect() + } else { + location.reload() + } + } + errorAbortController.abort() ended = true progress.end() // dont reset viewer so we can still do debugging @@ -229,12 +235,15 @@ export async function connect (connectOptions: ConnectOptions) { bot.emit('end', '') bot.removeAllListeners() bot._client.removeAllListeners() - //@ts-expect-error TODO? - bot._client = undefined + bot._client = { + //@ts-expect-error + write (packetName) { + console.warn('Tried to write packet', packetName, 'after bot was destroyed') + } + } //@ts-expect-error window.bot = bot = undefined } - resetStateAfterDisconnect() cleanFs() } const cleanFs = () => { @@ -255,10 +264,13 @@ export async function connect (connectOptions: ConnectOptions) { if (err === 'ResizeObserver loop completed with undelivered notifications.') { return } - errorAbortController.abort() if (isCypress()) throw err miscUiState.hasErrors = true if (miscUiState.gameLoaded) return + // close all modals + for (const modal of activeModalStack) { + hideModal(modal) + } setLoadingScreenStatus(`Error encountered. ${err}`, true) appStatusState.showReconnect = true @@ -266,6 +278,7 @@ export async function connect (connectOptions: ConnectOptions) { destroyAll() } + // todo(hard): remove it! const errorAbortController = new AbortController() window.addEventListener('unhandledrejection', (e) => { if (e.reason.name === 'ServerPluginLoadFailure') { @@ -273,6 +286,10 @@ export async function connect (connectOptions: ConnectOptions) { return } } + if (e.reason?.stack?.includes('chrome-extension://')) { + // ignore issues caused by chrome extension + return + } handleError(e.reason) }, { signal: errorAbortController.signal @@ -287,22 +304,36 @@ export async function connect (connectOptions: ConnectOptions) { if (connectOptions.server && !connectOptions.viewerWsConnect && !parsedServer.isWebSocket) { console.log(`using proxy ${proxy.host}:${proxy.port || location.port}`) - net['setProxy']({ hostname: proxy.host, port: proxy.port }) + net['setProxy']({ hostname: proxy.host, port: proxy.port, headers: { Authorization: `Bearer ${new URLSearchParams(location.search).get('token') ?? ''}` }, artificialDelay: appQueryParams.addPing ? Number(appQueryParams.addPing) : undefined }) } const renderDistance = singleplayer ? renderDistanceSingleplayer : multiplayerRenderDistance let updateDataAfterJoin = () => { } let localServer let localReplaySession: ReturnType | undefined + let lastKnownKickReason = undefined as string | undefined try { const serverOptions = defaultsDeep({}, connectOptions.serverOverrides ?? {}, options.localServerOptions, defaultServerOptions) Object.assign(serverOptions, connectOptions.serverOverridesFlat ?? {}) - await progress.executeWithMessage('Downloading minecraft data', 'download-mcdata', async () => { + await progress.executeWithMessage('Downloading Minecraft data', 'download-mcdata', async () => { + loadingTimerState.networkOnlyStart = Date.now() + + let downloadingAssets = [] as string[] + const reportAssetDownload = (asset: string, isDone: boolean) => { + if (isDone) { + downloadingAssets = downloadingAssets.filter(a => a !== asset) + } else { + downloadingAssets.push(asset) + } + progress.setSubStage('download-mcdata', `(${downloadingAssets.join(', ')})`) + } + await Promise.all([ - downloadAllMinecraftData(), - downloadOtherGameData() + downloadAllMinecraftData(reportAssetDownload), + downloadOtherGameData(reportAssetDownload) ]) + loadingTimerState.networkOnlyStart = 0 }) let dataDownloaded = false @@ -312,8 +343,9 @@ export async function connect (connectOptions: ConnectOptions) { appViewer.resourcesManager.currentConfig = { version, texturesVersion: options.useVersionsTextures || undefined } await progress.executeWithMessage( - 'Loading minecraft data', + 'Processing downloaded Minecraft data', async () => { + await loadMinecraftData(version) await appViewer.resourcesManager.loadSourceData(version) } ) @@ -365,7 +397,18 @@ export async function connect (connectOptions: ConnectOptions) { // Client (class) of flying-squid (in server/login.js of mc-protocol): onLogin handler: skip most logic & go to loginClient() which assigns uuid and sends 'success' back to client (onLogin handler) and emits 'login' on the server (login.js in flying-squid handler) // flying-squid: 'login' -> player.login -> now sends 'login' event to the client (handled in many plugins in mineflayer) -> then 'update_health' is sent which emits 'spawn' in mineflayer + const serverPlugins = new URLSearchParams(location.search).getAll('serverPlugin') + if (serverPlugins.length > 0 && !serverOptions.worldFolder) { + console.log('Placing server plugins', serverPlugins) + + serverOptions.worldFolder ??= '/temp' + await loadPluginsIntoWorld('/temp', serverPlugins) + + console.log('Server plugins placed') + } + localServer = window.localServer = window.server = startLocalServer(serverOptions) + connectOptions?.connectEvents?.serverCreated?.() // todo need just to call quit if started // loadingScreen.maybeRecoverable = false // init world, todo: do it for any async plugins @@ -397,8 +440,10 @@ export async function connect (connectOptions: ConnectOptions) { } else if (connectOptions.server) { if (!finalVersion) { const versionAutoSelect = getVersionAutoSelect() - setLoadingScreenStatus(`Fetching server version. Preffered: ${versionAutoSelect}`) + const wrapped = createWrappedProgressReporter(progress, `Fetching server version. Preffered: ${versionAutoSelect}`) + loadingTimerState.networkOnlyStart = Date.now() const autoVersionSelect = await getServerInfo(server.host, server.port ? Number(server.port) : undefined, versionAutoSelect) + wrapped.end() finalVersion = autoVersionSelect.version } initialLoadingText = `Connecting to server ${server.host}:${server.port ?? 25_565} with version ${finalVersion}` @@ -409,25 +454,29 @@ export async function connect (connectOptions: ConnectOptions) { } else { initialLoadingText = 'We have no idea what to do' } - setLoadingScreenStatus(initialLoadingText) + progress.setMessage(initialLoadingText) if (parsedServer.isWebSocket) { + loadingTimerState.networkOnlyStart = Date.now() clientDataStream = (await getWebsocketStream(server.host)).mineflayerStream } let newTokensCacheResult = null as any const cachedTokens = typeof connectOptions.authenticatedAccount === 'object' ? connectOptions.authenticatedAccount.cachedTokens : {} - const authData = connectOptions.authenticatedAccount ? await microsoftAuthflow({ - tokenCaches: cachedTokens, - proxyBaseUrl: connectOptions.proxy, - setProgressText (text) { - setLoadingScreenStatus(text) - }, - setCacheResult (result) { - newTokensCacheResult = result - }, - connectingServer: server.host - }) : undefined + let authData: Awaited> | undefined + if (connectOptions.authenticatedAccount) { + authData = await microsoftAuthflow({ + tokenCaches: cachedTokens, + proxyBaseUrl: connectOptions.proxy, + setProgressText (text) { + progress.setMessage(text) + }, + setCacheResult (result) { + newTokensCacheResult = result + }, + connectingServer: server.host + }) + } if (p2pMultiplayer) { clientDataStream = await connectToPeer(connectOptions.peerId!, connectOptions.peerOptions) @@ -455,12 +504,15 @@ export async function connect (connectOptions: ConnectOptions) { if (finalVersion) { // ensure data is downloaded + loadingTimerState.networkOnlyStart ??= Date.now() await downloadMcData(finalVersion) } + const brand = clientDataStream ? 'minecraft-web-client' : undefined bot = mineflayer.createBot({ host: server.host, port: server.port ? +server.port : undefined, + brand, version: finalVersion || false, ...clientDataStream ? { stream: clientDataStream as any, @@ -535,8 +587,9 @@ export async function connect (connectOptions: ConnectOptions) { // "mapDownloader-saveInternal": false, // do not save into memory, todo must be implemeneted as we do really care of ram }) as unknown as typeof __type_bot window.bot = bot + if (connectOptions.viewerWsConnect) { - void handleCustomChannel() + void onBotCreatedViewerHandler() } customEvents.emit('mineflayerBotCreated') if (singleplayer || p2pMultiplayer || localReplaySession) { @@ -558,6 +611,16 @@ export async function connect (connectOptions: ConnectOptions) { bot._client.emit('connect') } else { const setupConnectHandlers = () => { + Socket.prototype['handleStringMessage'] = function (message: string) { + if (message.startsWith('proxy-message') || message.startsWith('proxy-command:')) { // for future + return false + } + if (message.startsWith('proxy-shutdown:')) { + lastKnownKickReason = message.slice('proxy-shutdown:'.length) + return false + } + return true + } bot._client.socket.on('connect', () => { console.log('Proxy WebSocket connection established') //@ts-expect-error @@ -596,14 +659,6 @@ export async function connect (connectOptions: ConnectOptions) { } if (!bot) return - if (connectOptions.server) { - bot.loadPlugin(ping) - } - bot.loadPlugin(mouse) - if (!localReplaySession) { - bot.loadPlugin(localRelayServerPlugin) - } - const p2pConnectTimeout = p2pMultiplayer ? setTimeout(() => { throw new UserError('Spawn timeout. There might be error on the other side, check console.') }, 20_000) : undefined // bot.on('inject_allowed', () => { @@ -615,13 +670,15 @@ export async function connect (connectOptions: ConnectOptions) { bot.on('kicked', (kickReason) => { console.log('You were kicked!', kickReason) const { formatted: kickReasonFormatted, plain: kickReasonString } = parseFormattedMessagePacket(kickReason) + // close all modals + for (const modal of activeModalStack) { + hideModal(modal) + } setLoadingScreenStatus(`The Minecraft server kicked you. Kick reason: ${kickReasonString}`, true, undefined, undefined, kickReasonFormatted) appStatusState.showReconnect = true - destroyAll() + destroyAll(true) }) - // bot.emit('kicked', '{"translate":"disconnect.genericReason","with":["Internal Exception: io.netty.handler.codec.EncoderException: com.viaversion.viaversion.exception.InformativeException: Please report this on the Via support Discord or open an issue on the relevant GitHub repository\\nPacket Type: SYSTEM_CHAT, Index: 1, Type: TagType, Data: [], Packet ID: 103, Source 0: com.viaversion.viabackwards.protocol.v1_20_3to1_20_2.Protocol1_20_3To1_20_2$$Lambda/0x00007f9930f63080"]}', false) - const packetBeforePlay = (_, __, ___, fullBuffer) => { lastPacket = fullBuffer.toString() } @@ -637,9 +694,13 @@ export async function connect (connectOptions: ConnectOptions) { if (ended) return console.log('disconnected for', endReason) if (endReason === 'socketClosed') { - endReason = 'Connection with server lost' + endReason = lastKnownKickReason ?? 'Connection with proxy server lost' } - setLoadingScreenStatus(`You have been disconnected from the server. End reason: ${endReason}`, true) + // close all modals + for (const modal of activeModalStack) { + hideModal(modal) + } + setLoadingScreenStatus(`You have been disconnected from the server. End reason:\n${endReason}`, true) appStatusState.showReconnect = true onPossibleErrorDisconnect() destroyAll() @@ -649,35 +710,33 @@ export async function connect (connectOptions: ConnectOptions) { onBotCreate() bot.once('login', () => { - setLoadingScreenStatus('Loading world') + errorAbortController.abort() + loadingTimerState.networkOnlyStart = 0 + progress.setMessage('Loading world') }) - const loadStart = Date.now() let worldWasReady = false const waitForChunksToLoad = async (progress?: ProgressReporter) => { await new Promise(resolve => { + if (worldWasReady) { + resolve() + return + } const unsub = subscribe(appViewer.rendererState, () => { - if (worldWasReady) return - if (appViewer.rendererState.world.allChunksLoaded) { + if (appViewer.rendererState.world.allChunksLoaded && appViewer.nonReactiveState.world.chunksTotalNumber) { worldWasReady = true resolve() unsub() } else { - const perc = Math.round(appViewer.rendererState.world.chunksLoaded.length / appViewer.rendererState.world.chunksTotalNumber * 100) + const perc = Math.round(appViewer.rendererState.world.chunksLoaded.size / appViewer.nonReactiveState.world.chunksTotalNumber * 100) progress?.reportProgress('chunks', perc / 100) } }) }) } - void waitForChunksToLoad().then(() => { - console.log('All chunks done and ready! Time from renderer connect to ready', (Date.now() - loadStart) / 1000, 's') - document.dispatchEvent(new Event('cypress-world-ready')) - }) - const spawnEarlier = !singleplayer && !p2pMultiplayer - // don't use spawn event, player can be dead - bot.once(spawnEarlier ? 'forcedMove' : 'health', async () => { + const displayWorld = async () => { if (resourcePackState.isServerInstalling) { await new Promise(resolve => { subscribe(resourcePackState, () => { @@ -686,89 +745,134 @@ export async function connect (connectOptions: ConnectOptions) { } }) }) + await appViewer.resourcesManager.promiseAssetsReady } - window.focus?.() - errorAbortController.abort() - - if (p2pConnectTimeout) clearTimeout(p2pConnectTimeout) - playerState.onlineMode = !!connectOptions.authenticatedAccount - - progress.setMessage('Placing blocks (starting viewer)') - if (!connectOptions.worldStateFileContents || connectOptions.worldStateFileContents.length < 3 * 1024 * 1024) { - localStorage.lastConnectOptions = JSON.stringify(connectOptions) - if (process.env.NODE_ENV === 'development' && !localStorage.lockUrl && !Object.keys(window.debugQueryParams).length) { - lockUrl() - } - } else { - localStorage.removeItem('lastConnectOptions') - } - connectOptions.onSuccessfulPlay?.() - updateDataAfterJoin() - if (connectOptions.autoLoginPassword) { - bot.chat(`/login ${connectOptions.autoLoginPassword}`) - } - - - console.log('bot spawned - starting viewer') - appViewer.startWorld(bot.world, renderDistance) - appViewer.worldView!.listenToBot(bot) - - initMotionTracking() - dayCycle() - - // Bot position callback - function botPosition () { - appViewer.lastCamUpdate = Date.now() - // this might cause lag, but not sure - appViewer.backend?.updateCamera(bot.entity.position, bot.entity.yaw, bot.entity.pitch) - void appViewer.worldView?.updatePosition(bot.entity.position) - } - bot.on('move', botPosition) - botPosition() - - progress.setMessage('Setting callbacks') - - onGameLoad(() => {}) - if (appStatusState.isError) return - const waitForChunks = async () => { - if (appQueryParams.sp === '1') return //todo - const waitForChunks = options.waitForChunksRender === 'sp-only' ? !!singleplayer : options.waitForChunksRender - if (!appViewer.backend || appViewer.rendererState.world.allChunksLoaded || !waitForChunks) { - return - } - - await progress.executeWithMessage( - 'Loading chunks', - 'chunks', - async () => { - await waitForChunksToLoad(progress) - } - ) + if (!appViewer.resourcesManager.currentResources?.itemsRenderer) { + await appViewer.resourcesManager.updateAssetsData({}) } - await waitForChunks() + const loadWorldStart = Date.now() + console.log('try to focus window') + window.focus?.() + void waitForChunksToLoad().then(() => { + window.worldLoadTime = (Date.now() - loadWorldStart) / 1000 + console.log('All chunks done and ready! Time from renderer connect to ready', (Date.now() - loadWorldStart) / 1000, 's') + document.dispatchEvent(new Event('cypress-world-ready')) + }) - setTimeout(() => { - if (appQueryParams.suggest_save) { - showNotification('Suggestion', 'Save the world to keep your progress!', false, undefined, async () => { - const savePath = await saveToBrowserMemory() - if (!savePath) return - const saveName = savePath.split('/').pop() - bot.end() - // todo hot reload - location.search = `loadSave=${saveName}` - }) + try { + if (p2pConnectTimeout) clearTimeout(p2pConnectTimeout) + playerState.reactive.onlineMode = !!connectOptions.authenticatedAccount + + progress.setMessage('Placing blocks (starting viewer)') + if (!connectOptions.worldStateFileContents || connectOptions.worldStateFileContents.length < 3 * 1024 * 1024) { + localStorage.lastConnectOptions = JSON.stringify(connectOptions) + if (process.env.NODE_ENV === 'development' && !localStorage.lockUrl && !location.search.slice(1).length) { + lockUrl() + } + } else { + localStorage.removeItem('lastConnectOptions') + } + connectOptions.onSuccessfulPlay?.() + updateDataAfterJoin() + const password = findServerPassword() + if (password) { + setTimeout(() => { + bot.chat(`/login ${password}`) + }, 500) } - }, 600) - miscUiState.gameLoaded = true - miscUiState.loadedServerIndex = connectOptions.serverIndex ?? '' - customEvents.emit('gameLoaded') - progress.end() - setLoadingScreenStatus(undefined) - }) + + console.log('bot spawned - starting viewer') + await appViewer.startWorld(bot.world, renderDistance) + appViewer.worldView!.listenToBot(bot) + if (appViewer.backend) { + void appViewer.worldView!.init(bot.entity.position) + } + + initMotionTracking() + + // Bot position callback + const botPosition = () => { + appViewer.lastCamUpdate = Date.now() + // this might cause lag, but not sure + appViewer.backend?.updateCamera(bot.entity.position, bot.entity.yaw, bot.entity.pitch) + void appViewer.worldView?.updatePosition(bot.entity.position) + } + bot.on('move', botPosition) + botPosition() + + progress.setMessage('Setting callbacks') + + onGameLoad() + + if (appStatusState.isError) return + + const waitForChunks = async () => { + if (appQueryParams.sp === '1') return //todo + const waitForChunks = options.waitForChunksRender === 'sp-only' ? !!singleplayer : options.waitForChunksRender + if (!appViewer.backend || appViewer.rendererState.world.allChunksLoaded || !waitForChunks) { + return + } + + await progress.executeWithMessage( + 'Loading chunks', + 'chunks', + async () => { + await waitForChunksToLoad(progress) + } + ) + } + + await waitForChunks() + + setTimeout(() => { + if (appQueryParams.suggest_save) { + showNotification('Suggestion', 'Save the world to keep your progress!', false, undefined, async () => { + const savePath = await saveToBrowserMemory() + if (!savePath) return + const saveName = savePath.split('/').pop() + bot.end() + // todo hot reload + location.search = `loadSave=${saveName}` + }) + } + }, 600) + + miscUiState.gameLoaded = true + miscUiState.loadedServerIndex = connectOptions.serverIndex ?? '' + customEvents.emit('gameLoaded') + + // Test iOS Safari crash by creating memory pressure + if (appQueryParams.testIosCrash) { + setTimeout(() => { + console.log('Starting iOS crash test with memory pressure...') + // eslint-disable-next-line sonarjs/no-unused-collection + const arrays: number[][] = [] + try { + // Create large arrays until we run out of memory + // eslint-disable-next-line no-constant-condition + while (true) { + const arr = Array.from({ length: 1024 * 1024 }).fill(0).map((_, i) => i) + arrays.push(arr) + } + } catch (e) { + console.error('Memory allocation failed:', e) + } + }, 1000) + } + + progress.end() + setLoadingScreenStatus(undefined) + } catch (err) { + handleError(err) + } + hadConnected = true + } + // don't use spawn event, player can be dead + bot.once(spawnEarlier ? 'forcedMove' : 'health', displayWorld) if (singleplayer && connectOptions.serverOverrides.worldFolder) { fsState.saveLoaded = true @@ -780,43 +884,16 @@ export async function connect (connectOptions: ConnectOptions) { const commands = appQueryParamsArray.command ?? [] for (let command of commands) { if (!command.startsWith('/')) command = `/${command}` - bot.chat(command) + const builtinHandled = tryHandleBuiltinCommand(command) + if (!builtinHandled) { + bot.chat(command) + } } }) } } -const reconnectOptions = sessionStorage.getItem('reconnectOptions') ? JSON.parse(sessionStorage.getItem('reconnectOptions')!) : undefined - listenGlobalEvents() -const unsubscribe = subscribe(miscUiState, async () => { - if (miscUiState.fsReady && miscUiState.appConfig) { - unsubscribe() - if (reconnectOptions) { - sessionStorage.removeItem('reconnectOptions') - if (Date.now() - reconnectOptions.timestamp < 1000 * 60 * 2) { - void connect(reconnectOptions.value) - } - } else { - if (appQueryParams.singleplayer === '1' || appQueryParams.sp === '1') { - loadSingleplayer({}, { - worldFolder: undefined, - ...appQueryParams.version ? { version: appQueryParams.version } : {} - }) - } - if (appQueryParams.loadSave) { - const savePath = `/data/worlds/${appQueryParams.loadSave}` - try { - await fs.promises.stat(savePath) - } catch (err) { - alert(`Save ${savePath} not found`) - return - } - await loadInMemorySave(savePath) - } - } - } -}) // #region fire click event on touch as we disable default behaviors let activeTouch: { touch: Touch, elem: HTMLElement, start: number } | undefined @@ -831,8 +908,8 @@ document.body.addEventListener('touchend', (e) => { activeTouch = undefined }) document.body.addEventListener('touchstart', (e) => { - const ignoreElem = (e.target as HTMLElement).matches('vercel-live-feedback') || (e.target as HTMLElement).closest('.hotbar') - if (!isGameActive(true) || ignoreElem) return + const targetElement = (e.target as HTMLElement).closest('#ui-root') + if (!isGameActive(true) || !targetElement) return // we always prevent default behavior to disable magnifier on ios, but by doing so we also disable click events e.preventDefault() let firstClickable // todo remove composedPath and this workaround when lit-element is fully dropped @@ -852,86 +929,148 @@ document.body.addEventListener('touchstart', (e) => { }, { passive: false }) // #endregion -// qs open actions -if (!reconnectOptions) { - downloadAndOpenFile().then((downloadAction) => { - if (downloadAction) return - if (appQueryParams.reconnect && process.env.NODE_ENV === 'development') { - const lastConnect = JSON.parse(localStorage.lastConnectOptions ?? {}) +// immediate game enter actions: reconnect or URL QS +const maybeEnterGame = () => { + const waitForConfigFsLoad = (fn: () => void) => { + let unsubscribe: () => void | undefined + const checkDone = () => { + if (miscUiState.fsReady && miscUiState.appConfig) { + fn() + unsubscribe?.() + return true + } + return false + } + + if (!checkDone()) { + const text = miscUiState.appConfig ? 'Loading' : 'Loading config' + setLoadingScreenStatus(text) + unsubscribe = subscribe(miscUiState, checkDone) + } + } + + const reconnectOptions = sessionStorage.getItem('reconnectOptions') ? JSON.parse(sessionStorage.getItem('reconnectOptions')!) : undefined + + if (reconnectOptions) { + sessionStorage.removeItem('reconnectOptions') + if (Date.now() - reconnectOptions.timestamp < 1000 * 60 * 2) { + return waitForConfigFsLoad(async () => { + void connect(reconnectOptions.value) + }) + } + } + + if (appQueryParams.reconnect && localStorage.lastConnectOptions && process.env.NODE_ENV === 'development') { + const lastConnect = JSON.parse(localStorage.lastConnectOptions ?? {}) + return waitForConfigFsLoad(async () => { void connect({ botVersion: appQueryParams.version ?? undefined, ...lastConnect, ip: appQueryParams.ip || undefined }) - return + }) + } + + if (appQueryParams.singleplayer === '1' || appQueryParams.sp === '1') { + return waitForConfigFsLoad(async () => { + loadSingleplayer({}, { + worldFolder: undefined, + ...appQueryParams.version ? { version: appQueryParams.version } : {} + }) + }) + } + if (appQueryParams.loadSave) { + const enterSave = async () => { + const savePath = `/data/worlds/${appQueryParams.loadSave}` + try { + await fs.promises.stat(savePath) + await loadInMemorySave(savePath) + } catch (err) { + alert(`Save ${savePath} not found`) + } } - if (appQueryParams.ip || appQueryParams.proxy) { - const waitAppConfigLoad = !appQueryParams.proxy - const openServerEditor = () => { - hideModal() + return waitForConfigFsLoad(enterSave) + } + + if (appQueryParams.ip || appQueryParams.proxy) { + const openServerAction = () => { + if (appQueryParams.autoConnect && miscUiState.appConfig?.allowAutoConnect) { + void connect({ + server: appQueryParams.ip, + proxy: getCurrentProxy(), + botVersion: appQueryParams.version ?? undefined, + username: getCurrentUsername()!, + }) + return + } + + setLoadingScreenStatus(undefined) + if (appQueryParams.onlyConnect || process.env.ALWAYS_MINIMAL_SERVER_UI === 'true') { + showModal({ reactType: 'only-connect-server' }) + } else { showModal({ reactType: 'editServer' }) } - showModal({ reactType: 'empty' }) - if (waitAppConfigLoad) { - const unsubscribe = subscribe(miscUiState, checkCanDisplay) - checkCanDisplay() - // eslint-disable-next-line no-inner-declarations - function checkCanDisplay () { - if (miscUiState.appConfig) { - unsubscribe() - openServerEditor() - return true - } - } - } else { - openServerEditor() - } } - void Promise.resolve().then(() => { - // try to connect to peer - const peerId = appQueryParams.connectPeer - const peerOptions = {} as ConnectPeerOptions - if (appQueryParams.server) { - peerOptions.server = appQueryParams.server - } - const version = appQueryParams.peerVersion - if (peerId) { - let username: string | null = options.guestUsername - if (options.askGuestName) username = prompt('Enter your username', username) - if (!username) return - options.guestUsername = username - void connect({ - username, - botVersion: version || undefined, - peerId, - peerOptions - }) - } + // showModal({ reactType: 'empty' }) + return waitForConfigFsLoad(openServerAction) + } + + if (appQueryParams.connectPeer) { + // try to connect to peer + const peerId = appQueryParams.connectPeer + const peerOptions = {} as ConnectPeerOptions + if (appQueryParams.server) { + peerOptions.server = appQueryParams.server + } + const version = appQueryParams.peerVersion + let username: string | null = options.guestUsername + if (options.askGuestName) username = prompt('Enter your username to connect to peer', username) + if (!username) return + options.guestUsername = username + void connect({ + username, + botVersion: version || undefined, + peerId, + peerOptions }) + return - if (appQueryParams.serversList) { - showModal({ reactType: 'serversList' }) - } + } - const viewerWsConnect = appQueryParams.viewerConnect - if (viewerWsConnect) { - void connect({ - username: `viewer-${Math.random().toString(36).slice(2, 10)}`, - viewerWsConnect, - }) - } + if (appQueryParams.viewerConnect) { + void connect({ + username: `viewer-${Math.random().toString(36).slice(2, 10)}`, + viewerWsConnect: appQueryParams.viewerConnect, + }) + return + } - if (appQueryParams.modal) { - const modals = appQueryParams.modal.split(',') - for (const modal of modals) { - showModal({ reactType: modal }) - } + if (appQueryParams.modal) { + const modals = appQueryParams.modal.split(',') + for (const modal of modals) { + showModal({ reactType: modal }) } - }, (err) => { - console.error(err) - alert(`Failed to download file: ${err}`) - }) + return + } + + if (appQueryParams.serversList && !miscUiState.appConfig?.appParams?.serversList) { + // open UI only if it's in URL + showModal({ reactType: 'serversList' }) + } + + if (isInterestedInDownload()) { + void downloadAndOpenFile() + } + + void possiblyHandleStateVariable() +} + +try { + maybeEnterGame() +} catch (err) { + console.error(err) + alert(`Something went wrong: ${err}`) } // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion @@ -942,4 +1081,5 @@ if (initialLoader) { } window.pageLoaded = true -void possiblyHandleStateVariable() +appViewer.waitBackendLoadPromises.push(appStartup()) +registerOpenBenchmarkListener() diff --git a/src/interactionShapesGenerated.json b/src/interactionShapesGenerated.json index 8c8c283e..804952e0 100644 --- a/src/interactionShapesGenerated.json +++ b/src/interactionShapesGenerated.json @@ -457,7 +457,14 @@ 13, 14 ], - "powder_snow": "PowderSnowBlock", + "powder_snow": [ + 0, + 0, + 0, + 16, + 16, + 16 + ], "spore_blossom": [ 2, 13, @@ -1311,55 +1318,47 @@ 13 ], "lever": { - "face=ceiling,facing=east": [ - 4, - 0, - 5, - 12, - 6, - 11 - ], - "face=ceiling,facing=north": [ - 5, - 0, - 4, - 11, - 6, - 12 - ], - "face=ceiling,facing=south": [ - 5, - 0, - 4, - 11, - 6, - 12 - ], - "face=ceiling,facing=west": [ - 4, - 0, - 5, - 12, - 6, - 11 - ], "face=floor,facing=east": [ 4, - 10, + 0, 5, 12, - 16, + 6, 11 ], "face=floor,facing=north": [ 5, - 10, + 0, 4, 11, - 16, + 6, 12 ], "face=floor,facing=south": [ + 5, + 0, + 4, + 11, + 6, + 12 + ], + "face=floor,facing=west": [ + 4, + 0, + 5, + 12, + 6, + 11 + ], + "face=ceiling,facing=east": [ + 4, + 10, + 5, + 12, + 16, + 11 + ], + "face=ceiling,facing=north": [ 5, 10, 4, @@ -1367,7 +1366,15 @@ 16, 12 ], - "face=floor,facing=west": [ + "face=ceiling,facing=south": [ + 5, + 10, + 4, + 11, + 16, + 12 + ], + "face=ceiling,facing=west": [ 4, 10, 5, @@ -6547,7 +6554,6 @@ 16, 15 ], - "pink_petals": "PinkPetalsBlock", "big_dripleaf_stem": { "facing=north": [ 5, diff --git a/src/inventoryWindows.ts b/src/inventoryWindows.ts index a6cd4a3e..d40260df 100644 --- a/src/inventoryWindows.ts +++ b/src/inventoryWindows.ts @@ -9,8 +9,10 @@ import PItem, { Item } from 'prismarine-item' import { versionToNumber } from 'renderer/viewer/common/utils' import { getRenamedData } from 'flying-squid/dist/blockRenames' import PrismarineChatLoader from 'prismarine-chat' +import * as nbt from 'prismarine-nbt' import { BlockModel } from 'mc-assets' -import { activeGuiAtlas } from 'renderer/viewer/lib/guiRenderer' +import { renderSlot } from 'renderer/viewer/three/renderSlot' +import { loadSkinFromUsername } from 'renderer/viewer/lib/utils/skins' import Generic95 from '../assets/generic_95.png' import { appReplacableResources } from './generated/resources' import { activeModalStack, hideCurrentModal, hideModal, miscUiState, showModal } from './globalState' @@ -21,42 +23,55 @@ import { currentScaling } from './scaleInterface' import { getItemDescription } from './itemsDescriptions' import { MessageFormatPart } from './chatUtils' import { GeneralInputItem, getItemMetadata, getItemModelName, getItemNameRaw, RenderItem } from './mineflayer/items' +import { playerState } from './mineflayer/playerState' +import { modelViewerState } from './react/OverlayModelViewer' -const loadedImagesCache = new Map() +const loadedImagesCache = new Map() const cleanLoadedImagesCache = () => { loadedImagesCache.delete('blocks') + loadedImagesCache.delete('items') } let lastWindow: ReturnType +let lastWindowType: string | null | undefined // null is inventory /** bot version */ let version: string let PrismarineItem: typeof Item -export const allImagesLoadedState = proxy({ - value: false -}) - export const jeiCustomCategories = proxy({ value: [] as Array<{ id: string, categoryTitle: string, items: any[] }> }) -export const onGameLoad = (onLoad) => { - allImagesLoadedState.value = false - version = bot.version +let remotePlayerSkin: string | undefined | Promise - const checkIfLoaded = () => { - if (!appViewer.resourcesManager.currentResources?.itemsAtlasParser) return - if (!allImagesLoadedState.value) { - onLoad?.() - } - allImagesLoadedState.value = false - setTimeout(() => { - allImagesLoadedState.value = true - }, 0) +export const showInventoryPlayer = () => { + modelViewerState.model = { + positioning: { + windowWidth: 176, + windowHeight: 166, + x: 25, + y: 8, + width: 50, + height: 70, + scaled: true, + onlyInitialScale: true, + followCursor: true, + }, + // models: ['https://bucket.mcraft.fun/sitarbuckss.glb'], + // debug: true, + steveModelSkin: appViewer.playerState.reactive.playerSkin ?? (typeof remotePlayerSkin === 'string' ? remotePlayerSkin : ''), } - appViewer.resourcesManager.on('assetsTexturesUpdated', checkIfLoaded) - appViewer.resourcesManager.on('assetsInventoryReady', checkIfLoaded) - checkIfLoaded() + if (remotePlayerSkin === undefined && !appViewer.playerState.reactive.playerSkin) { + remotePlayerSkin = loadSkinFromUsername(bot.username, 'skin').then(a => { + setTimeout(() => { showInventoryPlayer() }, 0) // todo patch instead and make reactive + remotePlayerSkin = a ?? '' + return remotePlayerSkin + }) + } +} + +export const onGameLoad = () => { + version = bot.version PrismarineItem = PItem(version) @@ -72,12 +87,23 @@ export const onGameLoad = (onLoad) => { return type } + const maybeParseNbtJson = (data: any) => { + if (typeof data === 'string') { + try { + data = JSON.parse(data) + } catch (err) { + // ignore + } + } + return nbt.simplify(data) ?? data + } + bot.on('windowOpen', (win) => { const implementedWindow = implementedContainersGuiMap[mapWindowType(win.type as string, win.inventoryStart)] if (implementedWindow) { - openWindow(implementedWindow) + openWindow(implementedWindow, maybeParseNbtJson(win.title)) } else if (options.unimplementedContainers) { - openWindow('ChestWin') + openWindow('ChestWin', maybeParseNbtJson(win.title)) } else { // todo format displayClientChat(`[client error] cannot open unimplemented window ${win.id} (${win.type}). Slots: ${win.slots.map(item => getItemName(item)).filter(Boolean).join(', ')}`) @@ -134,13 +160,26 @@ export const onGameLoad = (onLoad) => { if (!lastWindow) return upJei(q) }) + + if (!appViewer.resourcesManager['_inventoryChangeTracked']) { + appViewer.resourcesManager['_inventoryChangeTracked'] = true + const texturesChanged = () => { + cleanLoadedImagesCache() + if (!lastWindow) return + upWindowItemsLocal() + upJei(lastJeiSearch) + } + appViewer.resourcesManager.on('assetsInventoryReady', () => texturesChanged()) + appViewer.resourcesManager.on('assetsTexturesUpdated', () => texturesChanged()) + } } -const getImageSrc = (path): string | HTMLImageElement => { +const getImageSrc = (path): string | HTMLImageElement | ImageBitmap => { switch (path) { case 'gui/container/inventory': return appReplacableResources.latest_gui_container_inventory.content - case 'blocks': return appViewer.resourcesManager.currentResources!.blocksAtlasParser.latestImage - case 'items': return appViewer.resourcesManager.currentResources!.itemsAtlasParser.latestImage + case 'blocks': return appViewer.resourcesManager.blocksAtlasParser.latestImage + case 'items': return appViewer.resourcesManager.itemsAtlasParser.latestImage + case 'gui': return appViewer.resourcesManager.currentResources!.guiAtlas!.image case 'gui/container/dispenser': return appReplacableResources.latest_gui_container_dispenser.content case 'gui/container/furnace': return appReplacableResources.latest_gui_container_furnace.content case 'gui/container/crafting_table': return appReplacableResources.latest_gui_container_crafting_table.content @@ -163,12 +202,20 @@ const getImage = ({ path = undefined as string | undefined, texture = undefined if (image) { return image } - if (!path && !texture) throw new Error('Either pass path or texture') + if (!path && !texture) { + throw new Error('Either pass path or texture') + } const loadPath = (blockData ? 'blocks' : path ?? texture)! if (loadedImagesCache.has(loadPath)) { onLoad() } else { const imageSrc = getImageSrc(loadPath) + if (imageSrc instanceof ImageBitmap) { + onLoad() + loadedImagesCache.set(loadPath, imageSrc) + return imageSrc + } + let image: HTMLImageElement if (imageSrc instanceof Image) { image = imageSrc @@ -182,103 +229,53 @@ const getImage = ({ path = undefined as string | undefined, texture = undefined return loadedImagesCache.get(loadPath) } -export type ResolvedItemModelRender = { - modelName: string, -} - -export const renderSlot = (model: ResolvedItemModelRender, debugIsQuickbar = false, fullBlockModelSupport = false): { - texture: string, - blockData?: Record & { resolvedModel: BlockModel }, - scale?: number, - slice?: number[], - modelName?: string, - image?: HTMLImageElement -} | undefined => { - let itemModelName = model.modelName - const originalItemName = itemModelName - const isItem = loadedData.itemsByName[itemModelName] - - // #region normalize item name - if (versionToNumber(bot.version) < versionToNumber('1.13')) itemModelName = getRenamedData(isItem ? 'items' : 'blocks', itemModelName, bot.version, '1.13.1') as string - // #endregion - - - let itemTexture - - if (!fullBlockModelSupport) { - const atlas = activeGuiAtlas.atlas?.json - // todo atlas holds all rendered blocks, not all possibly rendered item/block models, need to request this on demand instead (this is how vanilla works) - const item = atlas?.textures[itemModelName.replace('minecraft:', '').replace('block/', '').replace('blocks/', '').replace('item/', '').replace('items/', '').replace('_inventory', '').replace('_bottom', '')] - if (item) { - const x = item.u * atlas.width - const y = item.v * atlas.height - return { - texture: 'gui', - image: activeGuiAtlas.atlas!.image, - slice: [x, y, atlas.tileSize, atlas.tileSize], - scale: 0.25, - } - } - } - - try { - assertDefined(appViewer.resourcesManager.currentResources?.itemsRenderer) - itemTexture = - appViewer.resourcesManager.currentResources.itemsRenderer.getItemTexture(itemModelName, {}, false, fullBlockModelSupport) - ?? appViewer.resourcesManager.currentResources.itemsRenderer.getItemTexture('item/missing_texture')! - } catch (err) { - inGameError(`Failed to render item ${itemModelName} (original: ${originalItemName}) on ${bot.version} (resourcepack: ${options.enabledResourcepack}): ${err.stack}`) - itemTexture = appViewer.resourcesManager.currentResources!.itemsRenderer.getItemTexture('block/errored')! - } - - - if ('type' in itemTexture) { - // is item - return { - texture: itemTexture.type, - slice: itemTexture.slice, - modelName: itemModelName - } - } else { - // is block - return { - texture: 'blocks', - blockData: itemTexture, - modelName: itemModelName - } - } -} - const getItemName = (slot: Item | RenderItem | null) => { - const parsed = getItemNameRaw(slot) + const parsed = getItemNameRaw(slot, appViewer.resourcesManager) if (!parsed) return // todo display full text renderer from sign renderer - const text = flat(parsed as MessageFormatPart).map(x => x.text) + const text = flat(parsed as MessageFormatPart).map(x => (typeof x === 'string' ? x : x.text)) return text.join('') } -let lastMappedSots = [] as any[] +let lastMappedSlots = [] as any[] const itemToVisualKey = (slot: RenderItem | Item | null) => { - if (!slot) return null - return slot.name + (slot['metadata'] ?? '-') + (slot.nbt ? JSON.stringify(slot.nbt) : '') + (slot['components'] ? JSON.stringify(slot['components']) : '') + if (!slot) return '' + const keys = [ + slot.name, + slot.durabilityUsed, + slot.maxDurability, + slot['count'], + slot['metadata'], + slot.nbt ? JSON.stringify(slot.nbt) : '', + slot['components'] ? JSON.stringify(slot['components']) : '', + appViewer.resourcesManager.currentResources!.guiAtlasVersion, + ].join('|') + return keys +} +const validateSlot = (slot: any, index: number) => { + if (!slot.texture) { + throw new Error(`Slot has no texture: ${index} ${slot.name}`) + } } const mapSlots = (slots: Array, isJei = false) => { const newSlots = slots.map((slot, i) => { - // todo stateid - if (!slot) return + if (!slot) return null if (!isJei) { - const oldKey = itemToVisualKey(lastMappedSots[i]) - if (oldKey && oldKey === itemToVisualKey(slot)) { - return lastMappedSots[i] + const oldKey = lastMappedSlots[i]?.cacheKey + const newKey = itemToVisualKey(slot) + slot['cacheKey'] = i + '|' + newKey + if (oldKey && oldKey === newKey) { + validateSlot(lastMappedSlots[i], i) + return lastMappedSlots[i] } } try { if (slot.durabilityUsed && slot.maxDurability) slot.durabilityUsed = Math.min(slot.durabilityUsed, slot.maxDurability) const debugIsQuickbar = !isJei && i === bot.inventory.hotbarStart + bot.quickBarSlot - const modelName = getItemModelName(slot, { 'minecraft:display_context': 'gui', }) - const slotCustomProps = renderSlot({ modelName }, debugIsQuickbar) + const modelName = getItemModelName(slot, { 'minecraft:display_context': 'gui', }, appViewer.resourcesManager, appViewer.playerState.reactive) + const slotCustomProps = renderSlot({ modelName, originalItemName: slot.name }, appViewer.resourcesManager, debugIsQuickbar) const itemCustomName = getItemName(slot) Object.assign(slot, { ...slotCustomProps, displayName: itemCustomName ?? slot.displayName }) //@ts-expect-error @@ -288,12 +285,13 @@ const mapSlots = (slots: Array, isJei = false) => { const { icon, ...rest } = slot return rest } + validateSlot(slot, i) } catch (err) { inGameError(err) } return slot }) - lastMappedSots = newSlots + lastMappedSlots = JSON.parse(JSON.stringify(newSlots)) return newSlots } @@ -302,6 +300,7 @@ export const upInventoryItems = (isInventory: boolean, invWindow = lastWindow) = // inv.pwindow.inv.slots[2].blockData = getBlockData('dirt') const customSlots = mapSlots((isInventory ? bot.inventory : bot.currentWindow)!.slots) invWindow.pwindow.setSlots(customSlots) + return customSlots } export const onModalClose = (callback: () => any) => { @@ -328,6 +327,8 @@ const implementedContainersGuiMap = { 'minecraft:generic_3x3': 'DropDispenseWin', 'minecraft:furnace': 'FurnaceWin', 'minecraft:smoker': 'FurnaceWin', + 'minecraft:shulker_box': 'ChestWin', + 'minecraft:blast_furnace': 'FurnaceWin', 'minecraft:crafting': 'CraftingWin', 'minecraft:crafting3x3': 'CraftingWin', // todo different result slot 'minecraft:anvil': 'AnvilWin', @@ -339,7 +340,9 @@ const implementedContainersGuiMap = { 'minecraft:villager': 'VillagerWin', } +let lastJeiSearch = '' const upJei = (search: string) => { + lastJeiSearch = search search = search.toLowerCase() // todo fix pre flat const itemsArray = [ @@ -384,8 +387,17 @@ export const openItemsCanvas = (type, _bot = bot as typeof bot | null) => { return inv } +const upWindowItemsLocal = () => { + if (!lastWindow && bot.currentWindow) { + // edge case: might happen due to high ping, inventory should be closed soon! + // openWindow(implementedContainersGuiMap[bot.currentWindow.type]) + return + } + void Promise.resolve().then(() => upInventoryItems(lastWindowType === null)) +} + let skipClosePacketSending = false -const openWindow = (type: string | undefined) => { +const openWindow = (type: string | undefined, title: string | any = undefined) => { // if (activeModalStack.some(x => x.reactType?.includes?.('player_win:'))) { if (activeModalStack.length) { // game is not in foreground, don't close current modal if (type) { @@ -396,6 +408,7 @@ const openWindow = (type: string | undefined) => { return } } + lastWindowType = type ?? null showModal({ reactType: `player_win:${type}`, }) @@ -404,15 +417,21 @@ const openWindow = (type: string | undefined) => { if (type !== undefined && bot.currentWindow && !skipClosePacketSending) bot.currentWindow['close']() lastWindow.destroy() lastWindow = null as any - window.lastWindow = lastWindow + lastWindowType = null + window.inventory = null miscUiState.displaySearchInput = false destroyFn() skipClosePacketSending = false + + modelViewerState.model = undefined }) + if (type === undefined) { + showInventoryPlayer() + } cleanLoadedImagesCache() const inv = openItemsCanvas(type) inv.canvasManager.children[0].mobileHelpers = miscUiState.currentTouch - const title = bot.currentWindow?.title + window.inventory = inv const PrismarineChat = PrismarineChatLoader(bot.version) try { inv.canvasManager.children[0].customTitleText = title ? @@ -441,15 +460,8 @@ const openWindow = (type: string | undefined) => { } lastWindow = inv - const upWindowItems = () => { - if (!lastWindow && bot.currentWindow) { - // edge case: might happen due to high ping, inventory should be closed soon! - // openWindow(implementedContainersGuiMap[bot.currentWindow.type]) - return - } - void Promise.resolve().then(() => upInventoryItems(type === undefined)) - } - upWindowItems() + + upWindowItemsLocal() lastWindow.pwindow.touch = miscUiState.currentTouch ?? false const oldOnInventoryEvent = lastWindow.pwindow.onInventoryEvent.bind(lastWindow.pwindow) @@ -458,6 +470,7 @@ const openWindow = (type: string | undefined) => { const isRightClick = type === 'rightclick' const isLeftClick = type === 'leftclick' if (isLeftClick || isRightClick) { + modelViewerState.model = undefined inv.canvasManager.children[0].showRecipesOrUsages(isLeftClick, item) } } else { @@ -465,6 +478,10 @@ const openWindow = (type: string | undefined) => { } } lastWindow.pwindow.onJeiClick = (slotItem, _index, isRightclick) => { + if (versionToNumber(bot.version) < versionToNumber('1.13')) { + alert('Item give is broken on 1.12.2 and below, we are working on it!') + return + } // slotItem is the slot from mapSlots const itemId = loadedData.itemsByName[slotItem.name]?.id if (!itemId) { @@ -485,6 +502,7 @@ const openWindow = (type: string | undefined) => { if (freeSlot === null) return void bot.creative.setInventorySlot(freeSlot, item) } else { + modelViewerState.model = undefined inv.canvasManager.children[0].showRecipesOrUsages(!isRightclick, mapSlots([item], true)[0]) } } @@ -511,14 +529,14 @@ const openWindow = (type: string | undefined) => { if (type === undefined) { // player inventory - bot.inventory.on('updateSlot', upWindowItems) + bot.inventory.on('updateSlot', upWindowItemsLocal) destroyFn = () => { - bot.inventory.off('updateSlot', upWindowItems) + bot.inventory.off('updateSlot', upWindowItemsLocal) } } else { //@ts-expect-error bot.currentWindow.on('updateSlot', () => { - upWindowItems() + upWindowItemsLocal() }) } } @@ -553,7 +571,7 @@ const getResultingRecipe = (slots: Array, gridRows: number) => { type Result = RecipeItem | undefined let shapelessResult: Result let shapeResult: Result - outer: for (const [id, recipeVariants] of Object.entries(loadedData.recipes)) { + outer: for (const [id, recipeVariants] of Object.entries(loadedData.recipes ?? {})) { for (const recipeVariant of recipeVariants) { if ('inShape' in recipeVariant && equals(currentShape, recipeVariant.inShape as number[][])) { shapeResult = recipeVariant.result! @@ -581,7 +599,7 @@ const getAllItemRecipes = (itemName: string) => { const item = loadedData.itemsByName[itemName] if (!item) return const itemId = item.id - const recipes = loadedData.recipes[itemId] + const recipes = loadedData.recipes?.[itemId] if (!recipes) return const results = [] as Array<{ result: Item, @@ -626,7 +644,7 @@ const getAllItemUsages = (itemName: string) => { if (!item) return const foundRecipeIds = [] as string[] - for (const [id, recipes] of Object.entries(loadedData.recipes)) { + for (const [id, recipes] of Object.entries(loadedData.recipes ?? {})) { for (const recipe of recipes) { if ('inShape' in recipe) { if (recipe.inShape.some(row => row.includes(item.id))) { diff --git a/src/loadSave.ts b/src/loadSave.ts index 4746a95c..f1676cff 100644 --- a/src/loadSave.ts +++ b/src/loadSave.ts @@ -11,6 +11,7 @@ import { isMajorVersionGreater } from './utils' import { activeModalStacks, insertActiveModalStack, miscUiState } from './globalState' import supportedVersions from './supportedVersions.mjs' +import { ConnectOptions } from './connect' import { appQueryParams } from './appParams' // todo include name of opened handle (zip)! @@ -22,7 +23,8 @@ export const fsState = proxy({ saveLoaded: false, openReadOperations: 0, openWriteOperations: 0, - remoteBackend: false + remoteBackend: false, + inMemorySavePath: '' }) const PROPOSE_BACKUP = true @@ -48,7 +50,7 @@ export const readLevelDat = async (path) => { return { levelDat, dataRaw: parsed.value.Data!.value as Record } } -export const loadSave = async (root = '/world') => { +export const loadSave = async (root = '/world', connectOptions?: Partial) => { // todo test if (miscUiState.gameLoaded) { await disconnect() @@ -83,7 +85,6 @@ export const loadSave = async (root = '/world') => { } let version: string | undefined | null - let isFlat = false if (levelDat) { version = appQueryParams.mapVersion ?? levelDat.Version?.Name if (!version) { @@ -101,21 +102,6 @@ export const loadSave = async (root = '/world') => { version = prompt(`Version ${version} is not supported, supported versions are ${supportedVersions.join(', ')}, what try to use instead?`, lowerBound ? firstSupportedVersion : lastSupportedVersion) if (!version) return } - if (levelDat.WorldGenSettings) { - for (const [key, value] of Object.entries(levelDat.WorldGenSettings.dimensions)) { - if (key.slice(10) === 'overworld') { - if (value.generator.type === 'flat') isFlat = true - break - } - } - } - - if (levelDat.generatorName) { - isFlat = levelDat.generatorName === 'flat' - } - if (!isFlat && levelDat.generatorName !== 'default' && levelDat.generatorName !== 'customized') { - // warnings.push(`Generator ${levelDat.generatorName} may not be supported yet, be careful of new chunks writes`) - } const playerUuid = nameToMcOfflineUUID(options.localUsername) const playerDatPath = `${root}/playerdata/${playerUuid}.dat` @@ -181,18 +167,15 @@ export const loadSave = async (root = '/world') => { // todo should not be set here fsState.saveLoaded = true + fsState.inMemorySavePath = root window.dispatchEvent(new CustomEvent('singleplayer', { // todo check gamemode level.dat data etc detail: { version, - ...isFlat ? { - generation: { - name: 'superflat' - } - } : {}, ...root === '/world' ? {} : { 'worldFolder': root - } + }, + connectOptions }, })) } diff --git a/src/localServerMultiplayer.ts b/src/localServerMultiplayer.ts index de49ffd6..7eaa2427 100644 --- a/src/localServerMultiplayer.ts +++ b/src/localServerMultiplayer.ts @@ -1,5 +1,5 @@ import { Duplex } from 'stream' -import Peer, { DataConnection } from 'peerjs' +import { Peer, DataConnection } from 'peerjs' import Client from 'minecraft-protocol/src/client' import { resolveTimeout } from './utils' import { setLoadingScreenStatus } from './appStatus' @@ -59,6 +59,7 @@ export const openToWanAndCopyJoinLink = async (writeText: (text) => void, doCopy const params = host ? parseUrl(host) : undefined const peer = new Peer({ debug: 3, + secure: true, ...params }) peerInstance = peer @@ -119,11 +120,18 @@ export const openToWanAndCopyJoinLink = async (writeText: (text) => void, doCopy await copyJoinLink() resolve('Copied join link to clipboard') }) - timeout = setTimeout(() => { + timeout = setTimeout(async () => { if (!hadErrorReported && timeout !== undefined) { - writeText('timeout') + if (hasFallback && overridePeerJsServer === null) { + destroy() + overridePeerJsServer = fallbackServer + console.log('Trying fallback server due to timeout', fallbackServer) + resolve((await openToWanAndCopyJoinLink(writeText, doCopy))!) + } else { + writeText('timeout') + resolve('Failed to open to wan (timeout)') + } } - resolve('Failed to open to wan (timeout)') }, 6000) // fallback @@ -139,7 +147,7 @@ export const openToWanAndCopyJoinLink = async (writeText: (text) => void, doCopy } }) }) - if (!peerInstance.open) { + if (peerInstance && !peerInstance.open) { destroy() } miscUiState.wanOpening = false @@ -200,7 +208,7 @@ export const connectToPeer = async (peerId: string, options: ConnectPeerOptions const clientDuplex = new CustomDuplex({}, (data) => { // todo debug until play state // console.debug('sending', data.toString()) - connection.send(data) + void connection.send(data) }) connection.on('data', (data: any) => { console.debug('received', Buffer.from(data).toString()) diff --git a/src/microsoftAuthflow.ts b/src/microsoftAuthflow.ts index 00f4e675..d759a7dc 100644 --- a/src/microsoftAuthflow.ts +++ b/src/microsoftAuthflow.ts @@ -71,7 +71,7 @@ export default async ({ tokenCaches, proxyBaseUrl, setProgressText = (text) => { onMsaCodeCallback(json) // this.codeCallback(json) } - if (json.error) throw new Error(json.error) + if (json.error) throw new Error(`Auth server error: ${json.error}`) if (json.token) result = json if (json.newCache) setCacheResult(json.newCache) } diff --git a/src/mineflayer/entityStatus.ts b/src/mineflayer/entityStatus.ts new file mode 100644 index 00000000..e13784bc --- /dev/null +++ b/src/mineflayer/entityStatus.ts @@ -0,0 +1,70 @@ +export const EntityStatus = { + JUMP: 1, + HURT: 2, // legacy + DEATH: 3, + START_ATTACKING: 4, + STOP_ATTACKING: 5, + TAMING_FAILED: 6, + TAMING_SUCCEEDED: 7, + SHAKE_WETNESS: 8, + USE_ITEM_COMPLETE: 9, + EAT_GRASS: 10, + OFFER_FLOWER: 11, + LOVE_HEARTS: 12, + VILLAGER_ANGRY: 13, + VILLAGER_HAPPY: 14, + WITCH_HAT_MAGIC: 15, + ZOMBIE_CONVERTING: 16, + FIREWORKS_EXPLODE: 17, + IN_LOVE_HEARTS: 18, + SQUID_ANIM_SYNCH: 19, + SILVERFISH_MERGE_ANIM: 20, + GUARDIAN_ATTACK_SOUND: 21, + REDUCED_DEBUG_INFO: 22, + FULL_DEBUG_INFO: 23, + PERMISSION_LEVEL_ALL: 24, + PERMISSION_LEVEL_MODERATORS: 25, + PERMISSION_LEVEL_GAMEMASTERS: 26, + PERMISSION_LEVEL_ADMINS: 27, + PERMISSION_LEVEL_OWNERS: 28, + ATTACK_BLOCKED: 29, + SHIELD_DISABLED: 30, + FISHING_ROD_REEL_IN: 31, + ARMORSTAND_WOBBLE: 32, + THORNED: 33, // legacy + STOP_OFFER_FLOWER: 34, + TALISMAN_ACTIVATE: 35, // legacy + DROWNED: 36, // legacy + BURNED: 37, // legacy + DOLPHIN_LOOKING_FOR_TREASURE: 38, + RAVAGER_STUNNED: 39, + TRUSTING_FAILED: 40, + TRUSTING_SUCCEEDED: 41, + VILLAGER_SWEAT: 42, + BAD_OMEN_TRIGGERED: 43, // legacy + POKED: 44, // legacy + FOX_EAT: 45, + TELEPORT: 46, + MAINHAND_BREAK: 47, + OFFHAND_BREAK: 48, + HEAD_BREAK: 49, + CHEST_BREAK: 50, + LEGS_BREAK: 51, + FEET_BREAK: 52, + HONEY_SLIDE: 53, + HONEY_JUMP: 54, + SWAP_HANDS: 55, + CANCEL_SHAKE_WETNESS: 56, + FROZEN: 57, // legacy + START_RAM: 58, + END_RAM: 59, + POOF: 60, + TENDRILS_SHIVER: 61, + SONIC_CHARGE: 62, + SNIFFER_DIGGING_SOUND: 63, + ARMADILLO_PEEK: 64, + BODY_BREAK: 65, + SHAKE: 66 +} as const + +export type EntityStatusName = keyof typeof EntityStatus diff --git a/src/mineflayer/items.ts b/src/mineflayer/items.ts index 8ddb476c..48d0dfe0 100644 --- a/src/mineflayer/items.ts +++ b/src/mineflayer/items.ts @@ -1,10 +1,10 @@ import mojangson from 'mojangson' import nbt from 'prismarine-nbt' import { fromFormattedString } from '@xmcl/text-component' -import { ItemSpecificContextProperties } from 'renderer/viewer/lib/basePlayerState' +import { getItemSelector, ItemSpecificContextProperties, PlayerStateRenderer } from 'renderer/viewer/lib/basePlayerState' import { getItemDefinition } from 'mc-assets/dist/itemDefinitions' import { MessageFormatPart } from '../chatUtils' -import { playerState } from './playerState' +import { ResourcesManager, ResourcesManagerCommon, ResourcesManagerTransferred } from '../resourcesManager' type RenderSlotComponent = { type: string, @@ -27,13 +27,21 @@ export type GeneralInputItem = Pick { +export const getItemMetadata = (item: GeneralInputItem, resourcesManager: ResourcesManagerCommon) => { let customText = undefined as string | any | undefined let customModel = undefined as string | undefined + + let itemId = item.name + if (!itemId.includes(':')) { + itemId = `minecraft:${itemId}` + } + const customModelDataDefinitions = resourcesManager.currentResources?.customItemModelNames[itemId] + if (item.components) { const componentMap = new Map() for (const component of item.components) { @@ -48,6 +56,23 @@ export const getItemMetadata = (item: GeneralInputItem) => { if (customModelComponent) { customModel = customModelComponent.data } + if (customModelDataDefinitions) { + const customModelDataComponent: any = componentMap.get('custom_model_data') + if (customModelDataComponent?.data) { + let customModelData: number | undefined + if (typeof customModelDataComponent.data === 'number') { + customModelData = customModelDataComponent.data + } else if (typeof customModelDataComponent.data === 'object' + && 'floats' in customModelDataComponent.data + && Array.isArray(customModelDataComponent.data.floats) + && customModelDataComponent.data.floats.length > 0) { + customModelData = customModelDataComponent.data.floats[0] + } + if (customModelData && customModelDataDefinitions[customModelData]) { + customModel = customModelDataDefinitions[customModelData] + } + } + } const loreComponent = componentMap.get('lore') if (loreComponent) { customText ??= item.displayName ?? item.name @@ -61,6 +86,9 @@ export const getItemMetadata = (item: GeneralInputItem) => { if (customName) { customText = customName } + if (customModelDataDefinitions && itemNbt.CustomModelData && customModelDataDefinitions[itemNbt.CustomModelData]) { + customModel = customModelDataDefinitions[itemNbt.CustomModelData] + } } return { @@ -70,8 +98,9 @@ export const getItemMetadata = (item: GeneralInputItem) => { } -export const getItemNameRaw = (item: Pick | null) => { - const { customText } = getItemMetadata(item as any) +export const getItemNameRaw = (item: Pick | null, resourcesManager: ResourcesManagerCommon) => { + if (!item) return '' + const { customText } = getItemMetadata(item as GeneralInputItem, resourcesManager) if (!customText) return try { if (typeof customText === 'object') { @@ -90,14 +119,14 @@ export const getItemNameRaw = (item: Pick } } -export const getItemModelName = (item: GeneralInputItem, specificProps: ItemSpecificContextProperties) => { +export const getItemModelName = (item: GeneralInputItem, specificProps: ItemSpecificContextProperties, resourcesManager: ResourcesManagerCommon, playerState: PlayerStateRenderer) => { let itemModelName = item.name - const { customModel } = getItemMetadata(item) + const { customModel } = getItemMetadata(item, resourcesManager) if (customModel) { itemModelName = customModel } - const itemSelector = playerState.getItemSelector({ + const itemSelector = getItemSelector(playerState, { ...specificProps }) const modelFromDef = getItemDefinition(appViewer.resourcesManager.itemsDefinitionsStore, { diff --git a/src/mineflayer/mc-protocol.ts b/src/mineflayer/mc-protocol.ts index 63a90fa4..cd21d01f 100644 --- a/src/mineflayer/mc-protocol.ts +++ b/src/mineflayer/mc-protocol.ts @@ -1,12 +1,46 @@ +import net from 'net' import { Client } from 'minecraft-protocol' import { appQueryParams } from '../appParams' import { downloadAllMinecraftData, getVersionAutoSelect } from '../connect' import { gameAdditionalState } from '../globalState' +import { ProgressReporter } from '../core/progressReporter' +import { parseServerAddress } from '../parseServerAddress' +import { getCurrentProxy } from '../react/ServersList' import { pingServerVersion, validatePacket } from './minecraft-protocol-extra' import { getWebsocketStream } from './websocket-core' let lastPacketTime = 0 customEvents.on('mineflayerBotCreated', () => { + // const oldParsePacketBuffer = bot._client.deserializer.parsePacketBuffer + // try { + // const parsed = oldParsePacketBuffer(buffer) + // } catch (err) { + // debugger + // reportError(new Error(`Error parsing packet ${buffer.subarray(0, 30).toString('hex')}`, { cause: err })) + // throw err + // } + // } + class MinecraftProtocolError extends Error { + constructor (message: string, cause?: Error, public data?: any) { + if (data?.customPayload) { + message += ` (Custom payload: ${data.customPayload.channel})` + } + super(message, { cause }) + this.name = 'MinecraftProtocolError' + } + } + + const onClientError = (err, data) => { + const error = new MinecraftProtocolError(`Minecraft protocol client error: ${err.message}`, err, data) + reportError(error) + } + if (typeof bot._client['_events'].error === 'function') { + // dont report to bot for more explicit error + bot._client['_events'].error = onClientError + } else { + bot._client.on('error' as any, onClientError) + } + // todo move more code here if (!appQueryParams.noPacketsValidation) { (bot._client as unknown as Client).on('packet', (data, packetMeta, buffer, fullBuffer) => { @@ -34,16 +68,72 @@ setInterval(() => { }, 1000) -export const getServerInfo = async (ip: string, port?: number, preferredVersion = getVersionAutoSelect(), ping = false) => { +export const getServerInfo = async (ip: string, port?: number, preferredVersion = getVersionAutoSelect(), ping = false, progressReporter?: ProgressReporter, setProxyParams?: ProxyParams) => { await downloadAllMinecraftData() const isWebSocket = ip.startsWith('ws://') || ip.startsWith('wss://') let stream if (isWebSocket) { + progressReporter?.setMessage('Connecting to WebSocket server') stream = (await getWebsocketStream(ip)).mineflayerStream + progressReporter?.setMessage('WebSocket connected. Ping packet sent, waiting for response') + } else if (setProxyParams) { + setProxy(setProxyParams) + } + window.setLoadingMessage = (message?: string) => { + if (message === undefined) { + progressReporter?.endStage('dns') + } else { + progressReporter?.beginStage('dns', message) + } } return pingServerVersion(ip, port, { ...(stream ? { stream } : {}), ...(ping ? { noPongTimeout: 3000 } : {}), ...(preferredVersion ? { version: preferredVersion } : {}), + }).finally(() => { + window.setLoadingMessage = undefined }) } + +globalThis.debugTestPing = async (ip: string) => { + const parsed = parseServerAddress(ip, false) + const result = await getServerInfo(parsed.host, parsed.port ? Number(parsed.port) : undefined, undefined, true, undefined, { address: getCurrentProxy(), }) + console.log('result', result) + return result +} + +export const getDefaultProxyParams = () => { + return { + headers: { + Authorization: `Bearer ${new URLSearchParams(location.search).get('token') ?? ''}` + } + } +} + +export type ProxyParams = { + address?: string + headers?: Record +} + +export const setProxy = (proxyParams: ProxyParams) => { + if (proxyParams.address?.startsWith(':')) { + proxyParams.address = `${location.protocol}//${location.hostname}${proxyParams.address}` + } + if (proxyParams.address && location.port !== '80' && location.port !== '443' && !/:\d+$/.test(proxyParams.address)) { + const https = proxyParams.address.startsWith('https://') || location.protocol === 'https:' + proxyParams.address = `${proxyParams.address}:${https ? 443 : 80}` + } + + const parsedProxy = parseServerAddress(proxyParams.address, false) + const proxy = { host: parsedProxy.host, port: parsedProxy.port } + proxyParams.headers ??= getDefaultProxyParams().headers + net['setProxy']({ + hostname: proxy.host, + port: proxy.port, + headers: proxyParams.headers, + artificialDelay: appQueryParams.addPing ? Number(appQueryParams.addPing) : undefined + }) + return { + proxy + } +} diff --git a/src/mineflayer/minecraft-protocol-extra.ts b/src/mineflayer/minecraft-protocol-extra.ts index e8216a00..65260979 100644 --- a/src/mineflayer/minecraft-protocol-extra.ts +++ b/src/mineflayer/minecraft-protocol-extra.ts @@ -3,13 +3,11 @@ import clientAutoVersion from 'minecraft-protocol/src/client/autoVersion' export const pingServerVersion = async (ip: string, port?: number, mergeOptions: Record = {}) => { const fakeClient = new EventEmitter() as any - fakeClient.on('error', (err) => { - throw new Error(err.message ?? err) - }) const options = { host: ip, port, - noPongTimeout: Infinity, // disable timeout + noPongTimeout: 10_000, + closeTimeout: 20_000, ...mergeOptions, } let latency = 0 @@ -19,12 +17,28 @@ export const pingServerVersion = async (ip: string, port?: number, mergeOptions: fullInfo = res }] - // TODO! use client.socket.destroy() instead of client.end() for faster cleanup - await clientAutoVersion(fakeClient, options) + // TODO use client.socket.destroy() instead of client.end() for faster cleanup + clientAutoVersion(fakeClient, options) + await Promise.race([ + new Promise((resolve, reject) => { + fakeClient.once('connect_allowed', () => { + resolve() + }) + }), + new Promise((resolve, reject) => { + fakeClient.on('error', (err) => { + reject(new Error(err.message ?? err)) + }) + if (mergeOptions.stream) { + mergeOptions.stream.on('end', (err) => { + setTimeout(() => { + reject(new Error('Connection closed. Please report if you see this but the server is actually fine.')) + }) + }) + } + }) + ]) - await new Promise((resolve, reject) => { - fakeClient.once('connect_allowed', resolve) - }) return { version: fakeClient.version, latency, diff --git a/src/mineflayer/playerState.ts b/src/mineflayer/playerState.ts index 964e3d1b..33f7af77 100644 --- a/src/mineflayer/playerState.ts +++ b/src/mineflayer/playerState.ts @@ -1,45 +1,28 @@ -import { EventEmitter } from 'events' -import { Vec3 } from 'vec3' -import { BasePlayerState, IPlayerState, ItemSpecificContextProperties, MovementState, PlayerStateEvents } from 'renderer/viewer/lib/basePlayerState' import { HandItemBlock } from 'renderer/viewer/three/holdingBlock' -import TypedEmitter from 'typed-emitter' -import { ItemSelector } from 'mc-assets/dist/itemDefinitions' -import { proxy } from 'valtio' +import { getInitialPlayerState, getPlayerStateUtils, PlayerStateReactive, PlayerStateRenderer, PlayerStateUtils } from 'renderer/viewer/lib/basePlayerState' +import { subscribe } from 'valtio' +import { subscribeKey } from 'valtio/utils' import { gameAdditionalState } from '../globalState' +import { options } from '../optionsStorage' -export class PlayerStateManager implements IPlayerState { +/** + * can be used only in main thread. Mainly for more convenient reactive state updates. + * In renderer/ directory, use PlayerStateControllerRenderer type or worldRenderer.playerState. + */ +export class PlayerStateControllerMain { disableStateUpdates = false - private static instance: PlayerStateManager - readonly events = new EventEmitter() as TypedEmitter - // Movement and physics state - private lastVelocity = new Vec3(0, 0, 0) - private movementState: MovementState = 'NOT_MOVING' private timeOffGround = 0 private lastUpdateTime = performance.now() // Held item state - private heldItem?: HandItemBlock - private offHandItem?: HandItemBlock - private itemUsageTicks = 0 private isUsingItem = false - private ready = false - onlineMode = false - get username () { - return bot.player?.username ?? '' - } + ready = false - reactive: IPlayerState['reactive'] = new BasePlayerState().reactive - - static getInstance (): PlayerStateManager { - if (!this.instance) { - this.instance = new PlayerStateManager() - } - return this.instance - } + reactive: PlayerStateReactive + utils: PlayerStateUtils constructor () { - this.updateState = this.updateState.bind(this) customEvents.on('mineflayerBotCreated', () => { this.ready = false bot.on('inject_allowed', () => { @@ -47,12 +30,42 @@ export class PlayerStateManager implements IPlayerState { this.ready = true this.botCreated() }) + bot.on('end', () => { + this.ready = false + }) }) } + private onBotCreatedOrGameJoined () { + this.reactive.username = bot.username ?? '' + } + private botCreated () { + console.log('bot created & plugins injected') + this.reactive = getInitialPlayerState() + this.reactive.perspective = options.defaultPerspective + this.utils = getPlayerStateUtils(this.reactive) + this.onBotCreatedOrGameJoined() + + const handleDimensionData = (data) => { + let hasSkyLight = 1 + try { + hasSkyLight = data.dimension.value.has_skylight.value + } catch {} + this.reactive.lightingDisabled = bot.game.dimension === 'the_nether' || bot.game.dimension === 'the_end' || !hasSkyLight + } + + bot._client.on('login', (packet) => { + handleDimensionData(packet) + }) + bot._client.on('respawn', (packet) => { + handleDimensionData(packet) + }) + // Movement tracking - bot.on('move', this.updateState) + bot.on('move', () => { + this.updateMovementState() + }) // Item tracking bot.on('heldItemChanged', () => { @@ -61,8 +74,22 @@ export class PlayerStateManager implements IPlayerState { bot.inventory.on('updateSlot', (index) => { if (index === 45) this.updateHeldItem(true) }) + const updateSneakingOrFlying = () => { + this.updateMovementState() + this.reactive.sneaking = bot.controlState.sneak + this.reactive.flying = gameAdditionalState.isFlying + this.reactive.eyeHeight = bot.controlState.sneak && !gameAdditionalState.isFlying ? 1.27 : 1.62 + } bot.on('physicsTick', () => { - if (this.isUsingItem) this.itemUsageTicks++ + if (this.isUsingItem) this.reactive.itemUsageTicks++ + updateSneakingOrFlying() + }) + // todo move from gameAdditionalState to reactive directly + subscribeKey(gameAdditionalState, 'isSneaking', () => { + updateSneakingOrFlying() + }) + subscribeKey(gameAdditionalState, 'isFlying', () => { + updateSneakingOrFlying() }) // Initial held items setup @@ -73,13 +100,19 @@ export class PlayerStateManager implements IPlayerState { this.reactive.gameMode = bot.game.gameMode }) this.reactive.gameMode = bot.game?.gameMode + + customEvents.on('gameLoaded', () => { + this.reactive.team = bot.teamMap[bot.username] + }) + + this.watchReactive() } // #region Movement and Physics State - private updateState () { - if (!bot.player?.entity || this.disableStateUpdates) return + private updateMovementState () { + if (!bot?.entity || this.disableStateUpdates) return - const { velocity } = bot.player.entity + const { velocity } = bot.entity const isOnGround = bot.entity.onGround const VELOCITY_THRESHOLD = 0.01 const SPRINTING_VELOCITY = 0.15 @@ -89,7 +122,7 @@ export class PlayerStateManager implements IPlayerState { const deltaTime = now - this.lastUpdateTime this.lastUpdateTime = now - this.lastVelocity = velocity + // this.lastVelocity = velocity // Update time off ground if (isOnGround) { @@ -98,60 +131,26 @@ export class PlayerStateManager implements IPlayerState { this.timeOffGround += deltaTime } - if (this.isSneaking() || this.isFlying() || (this.timeOffGround > OFF_GROUND_THRESHOLD)) { - this.movementState = 'SNEAKING' + if (gameAdditionalState.isSneaking || gameAdditionalState.isFlying || (this.timeOffGround > OFF_GROUND_THRESHOLD)) { + this.reactive.movementState = 'SNEAKING' } else if (Math.abs(velocity.x) > VELOCITY_THRESHOLD || Math.abs(velocity.z) > VELOCITY_THRESHOLD) { - this.movementState = Math.abs(velocity.x) > SPRINTING_VELOCITY || Math.abs(velocity.z) > SPRINTING_VELOCITY + this.reactive.movementState = Math.abs(velocity.x) > SPRINTING_VELOCITY || Math.abs(velocity.z) > SPRINTING_VELOCITY ? 'SPRINTING' : 'WALKING' } else { - this.movementState = 'NOT_MOVING' + this.reactive.movementState = 'NOT_MOVING' } } - getMovementState (): MovementState { - return this.movementState - } - - getVelocity (): Vec3 { - return this.lastVelocity - } - - getEyeHeight (): number { - return bot.controlState.sneak ? 1.27 : 1.62 - } - - isOnGround (): boolean { - return bot?.entity?.onGround ?? true - } - - isSneaking (): boolean { - return gameAdditionalState.isSneaking - } - - isFlying (): boolean { - return gameAdditionalState.isFlying - } - - isSprinting (): boolean { - return gameAdditionalState.isSprinting - } - - getPosition (): Vec3 { - return bot.player?.entity.position ?? new Vec3(0, 0, 0) - } - // #endregion - // #region Held Item State private updateHeldItem (isLeftHand: boolean) { const newItem = isLeftHand ? bot.inventory.slots[45] : bot.heldItem if (!newItem) { if (isLeftHand) { - this.offHandItem = undefined + this.reactive.heldItemOff = undefined } else { - this.heldItem = undefined + this.reactive.heldItemMain = undefined } - this.events.emit('heldItemChanged', undefined, isLeftHand) return } @@ -166,42 +165,36 @@ export class PlayerStateManager implements IPlayerState { } if (isLeftHand) { - this.offHandItem = item + this.reactive.heldItemOff = item } else { - this.heldItem = item + this.reactive.heldItemMain = item } - this.events.emit('heldItemChanged', item, isLeftHand) + // this.events.emit('heldItemChanged', item, isLeftHand) } startUsingItem () { if (this.isUsingItem) return this.isUsingItem = true - this.itemUsageTicks = 0 + this.reactive.itemUsageTicks = 0 } stopUsingItem () { this.isUsingItem = false - this.itemUsageTicks = 0 + this.reactive.itemUsageTicks = 0 } getItemUsageTicks (): number { - return this.itemUsageTicks + return this.reactive.itemUsageTicks } - getHeldItem (isLeftHand = false): HandItemBlock | undefined { - return isLeftHand ? this.offHandItem : this.heldItem + watchReactive () { + subscribeKey(this.reactive, 'eyeHeight', () => { + appViewer.backend?.updateCamera(bot.entity.position, bot.entity.yaw, bot.entity.pitch) + }) } - getItemSelector (specificProperties: ItemSpecificContextProperties, item?: import('prismarine-item').Item): ItemSelector['properties'] { - return { - ...specificProperties, - 'minecraft:date': new Date(), - // "minecraft:context_dimension": bot.entityp, - 'minecraft:time': bot.time.timeOfDay / 24_000, - } - } // #endregion } -export const playerState = PlayerStateManager.getInstance() +export const playerState = new PlayerStateControllerMain() window.playerState = playerState diff --git a/src/mineflayer/plugins/index.ts b/src/mineflayer/plugins/index.ts new file mode 100644 index 00000000..6ac11376 --- /dev/null +++ b/src/mineflayer/plugins/index.ts @@ -0,0 +1,21 @@ +import { lastConnectOptions } from '../../react/AppStatusProvider' +import mouse from './mouse' +import packetsPatcher from './packetsPatcher' +import { localRelayServerPlugin } from './packetsRecording' +import ping from './ping' +import webFeatures from './webFeatures' + +// register +webFeatures() +packetsPatcher() + + +customEvents.on('mineflayerBotCreated', () => { + if (lastConnectOptions.value!.server) { + bot.loadPlugin(ping) + } + bot.loadPlugin(mouse) + if (!lastConnectOptions.value!.worldStateFileContents) { + bot.loadPlugin(localRelayServerPlugin) + } +}) diff --git a/src/mineflayer/plugins/mouse.ts b/src/mineflayer/plugins/mouse.ts index a0ae60ec..14e19345 100644 --- a/src/mineflayer/plugins/mouse.ts +++ b/src/mineflayer/plugins/mouse.ts @@ -10,21 +10,37 @@ import { sendVideoInteraction, videoCursorInteraction } from '../../customChanne function cursorBlockDisplay (bot: Bot) { const updateCursorBlock = (data?: { block: Block }) => { - if (!data?.block) { - getThreeJsRendererMethods()?.setHighlightCursorBlock(null) + if (!data?.block || bot.game.gameMode === 'spectator') { + playerState.reactive.lookingAtBlock = undefined return } const { block } = data - getThreeJsRendererMethods()?.setHighlightCursorBlock(block.position, bot.mouse.getBlockCursorShapes(block).map(shape => { - return bot.mouse.getDataFromShape(shape) - })) + playerState.reactive.lookingAtBlock = { + x: block.position.x, + y: block.position.y, + z: block.position.z, + shapes: bot.mouse.getBlockCursorShapes(block).map(shape => { + return bot.mouse.getDataFromShape(shape) + }) + } } bot.on('highlightCursorBlock', updateCursorBlock) + bot.on('game', () => { + const block = bot.mouse.getCursorState().cursorBlock + updateCursorBlock(block ? { block } : undefined) + }) bot.on('blockBreakProgressStage', (block, stage) => { - getThreeJsRendererMethods()?.updateBreakAnimation(block, stage) + const mergedShape = bot.mouse.getMergedCursorShape(block) + playerState.reactive.diggingBlock = stage === null ? undefined : { + x: block.position.x, + y: block.position.y, + z: block.position.z, + stage, + mergedShape: mergedShape ? bot.mouse.getDataFromShape(mergedShape) : undefined + } }) } @@ -65,10 +81,13 @@ const otherListeners = () => { } const domListeners = (bot: Bot) => { + const abortController = new AbortController() document.addEventListener('mousedown', (e) => { if (e.isTrusted && !document.pointerLockElement && !isCypress()) return if (!isGameActive(true)) return + getThreeJsRendererMethods()?.onPageInteraction() + const videoInteraction = videoCursorInteraction() if (videoInteraction) { sendVideoInteraction(videoInteraction.id, videoInteraction.x, videoInteraction.y, e.button === 0) @@ -80,7 +99,7 @@ const domListeners = (bot: Bot) => { } else if (e.button === 2) { bot.rightClickStart() } - }) + }, { signal: abortController.signal }) document.addEventListener('mouseup', (e) => { if (e.button === 0) { @@ -88,12 +107,16 @@ const domListeners = (bot: Bot) => { } else if (e.button === 2) { bot.rightClickEnd() } - }) + }, { signal: abortController.signal }) bot.mouse.beforeUpdateChecks = () => { - if (!document.hasFocus()) { + if (!document.hasFocus() || !isGameActive(true)) { // deactive all buttons bot.mouse.buttons.fill(false) } } + + bot.on('end', () => { + abortController.abort() + }) } diff --git a/src/mineflayer/plugins/packetsRecording.ts b/src/mineflayer/plugins/packetsRecording.ts index 53a63bd8..b9ba028c 100644 --- a/src/mineflayer/plugins/packetsRecording.ts +++ b/src/mineflayer/plugins/packetsRecording.ts @@ -72,6 +72,7 @@ export const localRelayServerPlugin = (bot: Bot) => { position: position++, timestamp: Date.now(), }) + packetsReplayState.progress.current++ } }) bot._client.on('packet', (data, { name }) => { @@ -86,8 +87,22 @@ export const localRelayServerPlugin = (bot: Bot) => { position: position++, timestamp: Date.now(), }) + packetsReplayState.progress.total++ } }) + const oldWriteChannel = bot._client.writeChannel.bind(bot._client) + bot._client.writeChannel = (channel, params) => { + packetsReplayState.packetsPlayback.push({ + name: channel, + data: params, + isFromClient: true, + isUpcoming: false, + position: position++, + timestamp: Date.now(), + isCustomChannel: true, + }) + oldWriteChannel(channel, params) + } upPacketsReplayPanel() } @@ -95,6 +110,8 @@ export const localRelayServerPlugin = (bot: Bot) => { const upPacketsReplayPanel = () => { if (packetsRecordingState.active && bot) { packetsReplayState.isOpen = true + packetsReplayState.isMinimized = true + packetsReplayState.isRecording = true packetsReplayState.replayName = 'Recording all packets for ' + bot.username } } diff --git a/src/mineflayer/plugins/ping.ts b/src/mineflayer/plugins/ping.ts index 9753e4ed..d6a23554 100644 --- a/src/mineflayer/plugins/ping.ts +++ b/src/mineflayer/plugins/ping.ts @@ -19,7 +19,7 @@ export default () => { let pingId = 0 bot.pingServer = async () => { - if (versionToNumber(bot.version) < versionToNumber('1.20.2')) return bot.player.ping + if (versionToNumber(bot.version) < versionToNumber('1.20.2')) return bot.player?.ping ?? -1 return new Promise((resolve) => { const curId = pingId++ bot._client.write('ping_request', { id: BigInt(curId) }) diff --git a/src/mineflayer/plugins/webFeatures.ts b/src/mineflayer/plugins/webFeatures.ts new file mode 100644 index 00000000..c56d7d66 --- /dev/null +++ b/src/mineflayer/plugins/webFeatures.ts @@ -0,0 +1,12 @@ +import { Bot } from 'mineflayer' +import { getAppLanguage } from '../../optionsStorage' + +export default () => { + customEvents.on('mineflayerBotCreated', () => { + bot.loadPlugin(plugin) + }) +} + +const plugin = (bot: Bot) => { + bot.settings['locale'] = getAppLanguage() +} diff --git a/src/mineflayer/timers.ts b/src/mineflayer/timers.ts index 698b624e..99110718 100644 --- a/src/mineflayer/timers.ts +++ b/src/mineflayer/timers.ts @@ -1,9 +1,71 @@ +import { subscribeKey } from 'valtio/utils' import { preventThrottlingWithSound } from '../core/timers' import { options } from '../optionsStorage' customEvents.on('mineflayerBotCreated', () => { - if (options.preventBackgroundTimeoutKick) { - const unsub = preventThrottlingWithSound() - bot.on('end', unsub) + const abortController = new AbortController() + + const maybeGoBackgroundKickPrevention = () => { + if (options.preventBackgroundTimeoutKick && !bot.backgroundKickPrevention) { + const unsub = preventThrottlingWithSound() + bot.on('end', unsub) + bot.backgroundKickPrevention = true + } } + maybeGoBackgroundKickPrevention() + subscribeKey(options, 'preventBackgroundTimeoutKick', (value) => { + maybeGoBackgroundKickPrevention() + }) + + // wake lock + const requestWakeLock = async () => { + if (!('wakeLock' in navigator)) { + console.warn('Wake Lock API is not supported in this browser') + return + } + + if (options.preventSleep && !bot.wakeLock && !bot.lockRequested) { + bot.lockRequested = true + bot.wakeLock = await navigator.wakeLock.request('screen').finally(() => { + bot.lockRequested = false + }) + + bot.wakeLock.addEventListener('release', () => { + bot.wakeLock = undefined + }, { + once: true, + }) + } + + if (!options.preventSleep && bot.wakeLock) { + void bot.wakeLock.release() + } + } + document.addEventListener('visibilitychange', () => { + if (document.visibilityState === 'visible') { + // we are back to the tab, request wake lock again + void requestWakeLock() + } + }, { + signal: abortController.signal, + }) + void requestWakeLock() + subscribeKey(options, 'preventSleep', (value) => { + void requestWakeLock() + }) + + bot.on('end', () => { + if (bot.wakeLock) { + void bot.wakeLock.release() + } + abortController.abort() + }) }) + +declare module 'mineflayer' { + interface Bot { + backgroundKickPrevention?: boolean + wakeLock?: WakeLockSentinel + lockRequested?: boolean + } +} diff --git a/src/mineflayer/websocket-core.ts b/src/mineflayer/websocket-core.ts index 482f0def..f8163102 100644 --- a/src/mineflayer/websocket-core.ts +++ b/src/mineflayer/websocket-core.ts @@ -15,13 +15,18 @@ class CustomDuplex extends Duplex { } export const getWebsocketStream = async (host: string) => { - const baseProtocol = location.protocol === 'https:' ? 'wss' : host.startsWith('ws://') ? 'ws' : 'wss' + const baseProtocol = host.startsWith('ws://') ? 'ws' : 'wss' const hostClean = host.replace('ws://', '').replace('wss://', '') - const ws = new WebSocket(`${baseProtocol}://${hostClean}`) + const hostURL = new URL(`${baseProtocol}://${hostClean}`) + const hostParams = hostURL.searchParams + hostParams.append('client_mcraft', '') + const ws = new WebSocket(`${baseProtocol}://${hostURL.host}${hostURL.pathname}?${hostParams.toString()}`) const clientDuplex = new CustomDuplex(undefined, data => { ws.send(data) }) + clientDuplex.on('error', () => {}) + ws.addEventListener('message', async message => { let { data } = message if (data instanceof Blob) { @@ -33,10 +38,14 @@ export const getWebsocketStream = async (host: string) => { ws.addEventListener('close', () => { console.log('ws closed') clientDuplex.end() + setTimeout(() => { + clientDuplex.emit('end', 'Connection lost') + }, 500) }) ws.addEventListener('error', err => { console.log('ws error', err) + clientDuplex.emit('error', err) }) await new Promise((resolve, reject) => { diff --git a/src/optionsGuiScheme.tsx b/src/optionsGuiScheme.tsx index 4078d5e2..0cb0fe1e 100644 --- a/src/optionsGuiScheme.tsx +++ b/src/optionsGuiScheme.tsx @@ -1,4 +1,4 @@ -import { useRef, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import { useSnapshot } from 'valtio' import { openURL } from 'renderer/viewer/lib/simpleUtils' import { noCase } from 'change-case' @@ -14,11 +14,13 @@ import { openFilePicker, resetLocalStorage } from './browserfs' import { completeResourcepackPackInstall, getResourcePackNames, resourcepackReload, resourcePackState, uninstallResourcePack } from './resourcePack' import { downloadPacketsReplay, packetsRecordingState } from './packetsReplay/packetsReplayLegacy' import { showInputsModal, showOptionsModal } from './react/SelectOption' +import { ClientMod, getAllMods, modsUpdateStatus } from './clientMods' import supportedVersions from './supportedVersions.mjs' import { getVersionAutoSelect } from './connect' import { createNotificationProgressReporter } from './core/progressReporter' import { customKeymaps } from './controls' import { appStorage } from './react/appStorageProvider' +import { exportData, importData } from './core/importExport' export const guiOptionsScheme: { [t in OptionsGroupType]: Array<{ [K in keyof AppOptions]?: Partial> } & { custom? }> @@ -61,8 +63,6 @@ export const guiOptionsScheme: { custom () { return } }, @@ -569,53 +686,7 @@ export const guiOptionsScheme: { custom () { return } }, @@ -645,7 +716,7 @@ const Category = ({ children }) =>
{children}
-const UiToggleButton = ({ name, addUiText = false, label = noCase(name) }) => { +const UiToggleButton = ({ name, addUiText = false, label = noCase(name) }: { name: string, addUiText?: boolean, label?: string }) => { const { disabledUiParts } = useSnapshot(options) const currentlyDisabled = disabledUiParts.includes(name) diff --git a/src/optionsStorage.ts b/src/optionsStorage.ts index eb1aa262..22d5ef26 100644 --- a/src/optionsStorage.ts +++ b/src/optionsStorage.ts @@ -1,136 +1,14 @@ import { proxy, subscribe } from 'valtio/vanilla' import { subscribeKey } from 'valtio/utils' import { omitObj } from '@zardoy/utils' -import { appQueryParamsArray } from './appParams' +import { appQueryParams, appQueryParamsArray } from './appParams' import type { AppConfig } from './appConfig' import { appStorage } from './react/appStorageProvider' +import { miscUiState } from './globalState' +import { defaultOptions } from './defaultOptions' const isDev = process.env.NODE_ENV === 'development' const initialAppConfig = process.env?.INLINED_APP_CONFIG as AppConfig ?? {} -const defaultOptions = { - renderDistance: 3, - keepChunksDistance: 1, - multiplayerRenderDistance: 3, - closeConfirmation: true, - autoFullScreen: false, - mouseRawInput: true, - autoExitFullscreen: false, - localUsername: 'wanderer', - mouseSensX: 50, - mouseSensY: -1, - chatWidth: 320, - chatHeight: 180, - chatScale: 100, - chatOpacity: 100, - chatOpacityOpened: 100, - messagesLimit: 200, - volume: 50, - enableMusic: false, - // fov: 70, - fov: 75, - guiScale: 3, - autoRequestCompletions: true, - touchButtonsSize: 40, - touchButtonsOpacity: 80, - touchButtonsPosition: 12, - touchControlsPositions: getDefaultTouchControlsPositions(), - touchMovementType: 'modern' as 'modern' | 'classic', - touchInteractionType: 'classic' as 'classic' | 'buttons', - gpuPreference: 'default' as 'default' | 'high-performance' | 'low-power', - backgroundRendering: '20fps' as 'full' | '20fps' | '5fps', - /** @unstable */ - disableAssets: false, - /** @unstable */ - debugLogNotFrequentPackets: false, - unimplementedContainers: false, - dayCycleAndLighting: true, - loadPlayerSkins: true, - renderEars: true, - lowMemoryMode: false, - starfieldRendering: true, - enabledResourcepack: null as string | null, - useVersionsTextures: 'latest', - serverResourcePacks: 'prompt' as 'prompt' | 'always' | 'never', - showHand: true, - viewBobbing: true, - displayRecordButton: true, - packetsLoggerPreset: 'all' as 'all' | 'no-buffers', - serversAutoVersionSelect: 'auto' as 'auto' | 'latest' | '1.20.4' | string, - customChannels: false, - remoteContentNotSameOrigin: false as boolean | string[], - packetsReplayAutoStart: false, - preciseMouseInput: false, - // todo ui setting, maybe enable by default? - waitForChunksRender: 'sp-only' as 'sp-only' | boolean, - jeiEnabled: true as boolean | Array<'creative' | 'survival' | 'adventure' | 'spectator'>, - preventBackgroundTimeoutKick: false, - - // antiAliasing: false, - - clipWorldBelowY: undefined as undefined | number, // will be removed - disableSignsMapsSupport: false, - singleplayerAutoSave: false, - showChunkBorders: false, // todo rename option - frameLimit: false as number | false, - alwaysBackupWorldBeforeLoading: undefined as boolean | undefined | null, - alwaysShowMobileControls: false, - excludeCommunicationDebugEvents: [], - preventDevReloadWhilePlaying: false, - numWorkers: 4, - localServerOptions: { - gameMode: 1 - } as any, - preferLoadReadonly: false, - disableLoadPrompts: false, - guestUsername: 'guest', - askGuestName: true, - errorReporting: true, - /** Actually might be useful */ - showCursorBlockInSpectator: false, - renderEntities: true, - smoothLighting: true, - newVersionsLighting: false, - chatSelect: true, - autoJump: 'auto' as 'auto' | 'always' | 'never', - autoParkour: false, - vrSupport: true, // doesn't directly affect the VR mode, should only disable the button which is annoying to android users - renderDebug: (isDev ? 'advanced' : 'basic') as 'none' | 'advanced' | 'basic', - - // advanced bot options - autoRespawn: false, - mutedSounds: [] as string[], - plugins: [] as Array<{ enabled: boolean, name: string, description: string, script: string }>, - /** Wether to popup sign editor on server action */ - autoSignEditor: true, - wysiwygSignEditor: 'auto' as 'auto' | 'always' | 'never', - showMinimap: 'never' as 'always' | 'singleplayer' | 'never', - minimapOptimizations: true, - displayBossBars: true, - disabledUiParts: [] as string[], - neighborChunkUpdates: true, - highlightBlockColor: 'auto' as 'auto' | 'blue' | 'classic', -} - -function getDefaultTouchControlsPositions () { - return { - action: [ - 70, - 76 - ], - sneak: [ - 84, - 76 - ], - break: [ - 70, - 60 - ], - jump: [ - 84, - 60 - ], - } as Record -} // const qsOptionsRaw = new URLSearchParams(location.search).getAll('setting') const qsOptionsRaw = appQueryParamsArray.setting ?? [] @@ -161,6 +39,18 @@ const migrateOptions = (options: Partial>) => { return options } +const migrateOptionsLocalStorage = () => { + if (Object.keys(appStorage['options'] ?? {}).length) { + for (const key of Object.keys(appStorage['options'])) { + if (!(key in defaultOptions)) continue // drop unknown options + const defaultValue = defaultOptions[key] + if (JSON.stringify(defaultValue) !== JSON.stringify(appStorage['options'][key])) { + appStorage.changedSettings[key] = appStorage['options'][key] + } + } + delete appStorage['options'] + } +} export type AppOptions = typeof defaultOptions @@ -181,14 +71,15 @@ const isDeepEqual = (a: any, b: any): boolean => { export const getChangedSettings = () => { return Object.fromEntries( - Object.entries(options).filter(([key, value]) => !isDeepEqual(defaultOptions[key], value)) + Object.entries(appStorage.changedSettings).filter(([key, value]) => !isDeepEqual(defaultOptions[key], value)) ) } +migrateOptionsLocalStorage() export const options: AppOptions = proxy({ ...defaultOptions, ...initialAppConfig.defaultSettings, - ...migrateOptions(appStorage.options), + ...migrateOptions(appStorage.changedSettings), ...qsOptions }) @@ -204,10 +95,18 @@ Object.defineProperty(window, 'debugChangedOptions', { }, }) -subscribe(options, () => { - // Don't save disabled settings to localStorage - const saveOptions = omitObj(options, [...disabledSettings.value] as any) - appStorage.options = saveOptions +subscribe(options, (ops) => { + if (appQueryParams.freezeSettings === 'true') return + for (const op of ops) { + const [type, path, value] = op + // let patch + // let accessor = options + // for (const part of path) { + // } + const key = path[0] as string + if (disabledSettings.value.has(key)) continue + appStorage.changedSettings[key] = options[key] + } }) type WatchValue = >(proxy: T, callback: (p: T, isChanged: boolean) => void) => () => void @@ -254,3 +153,12 @@ export const useOptionValue = (setting, valueCallback) => { valueCallback(setting) subscribe(setting, valueCallback) } + +export const getAppLanguage = () => { + if (options.language === 'auto') { + return miscUiState.appConfig?.defaultLanguage ?? navigator.language + } + return options.language +} + +export { defaultOptions } from './defaultOptions' diff --git a/src/packetsReplay/packetsReplayLegacy.ts b/src/packetsReplay/packetsReplayLegacy.ts index dc9b7a2d..a9cc71ec 100644 --- a/src/packetsReplay/packetsReplayLegacy.ts +++ b/src/packetsReplay/packetsReplayLegacy.ts @@ -3,7 +3,7 @@ import { PacketsLogger } from 'mcraft-fun-mineflayer/build/packetsLogger' import { options } from '../optionsStorage' export const packetsRecordingState = proxy({ - active: options.packetsReplayAutoStart, + active: options.packetsRecordingAutoStart, hasRecordedPackets: false }) diff --git a/src/packetsReplay/replayPackets.ts b/src/packetsReplay/replayPackets.ts index f1c85a94..54b3d652 100644 --- a/src/packetsReplay/replayPackets.ts +++ b/src/packetsReplay/replayPackets.ts @@ -4,11 +4,11 @@ import { ParsedReplayPacket, parseReplayContents } from 'mcraft-fun-mineflayer/b import { PACKETS_REPLAY_FILE_EXTENSION, WORLD_STATE_FILE_EXTENSION } from 'mcraft-fun-mineflayer/build/worldState' import MinecraftData from 'minecraft-data' import { GameMode } from 'mineflayer' -import { LocalServer } from '../customServer' import { UserError } from '../mineflayer/userError' import { packetsReplayState } from '../react/state/packetsReplayState' import { getFixedFilesize } from '../react/simpleUtils' import { appQueryParams } from '../appParams' +import { LocalServer } from '../customServer' const SUPPORTED_FORMAT_VERSION = 1 @@ -59,6 +59,7 @@ export const startLocalReplayServer = (contents: string) => { const server = createServer({ Server: LocalServer as any, version: header.minecraftVersion, + keepAlive: false, 'online-mode': false }) @@ -194,9 +195,11 @@ const mainPacketsReplayer = async (client: ServerClient, packets: ParsedReplayPa continue } playServerPacket(packet.name, packet.params) - await new Promise(resolve => { - setTimeout(resolve, packet.diff * packetsReplayState.speed + ADDITIONAL_DELAY * (packetsReplayState.customButtons.packetsSenderDelay.state ? 1 : 0)) - }) + if (packet.diff) { + await new Promise(resolve => { + setTimeout(resolve, packet.diff * packetsReplayState.speed + ADDITIONAL_DELAY * (packetsReplayState.customButtons.packetsSenderDelay.state ? 1 : 0)) + }) + } } else if (ignoreClientPacketsWait !== true && !ignoreClientPacketsWait.includes(packet.name)) { clientPackets.push({ name: packet.name, params: packet.params }) if (playPackets[i + 1]?.isFromServer) { diff --git a/src/react/AddServerOrConnect.tsx b/src/react/AddServerOrConnect.tsx index 08ef7f29..36fd5264 100644 --- a/src/react/AddServerOrConnect.tsx +++ b/src/react/AddServerOrConnect.tsx @@ -29,10 +29,9 @@ interface Props { accounts?: string[] authenticatedAccounts?: number versions?: string[] - allowAutoConnect?: boolean } -export default ({ onBack, onConfirm, title = 'Add a Server', initialData, parseQs, onQsConnect, placeholders, accounts, versions, allowAutoConnect }: Props) => { +export default ({ onBack, onConfirm, title = 'Add a Server', initialData, parseQs, onQsConnect, placeholders, accounts, versions }: Props) => { const isSmallHeight = !usePassesScaledDimensions(null, 350) const qsParamName = parseQs ? appQueryParams.name : undefined const qsParamIp = parseQs ? appQueryParams.ip : undefined @@ -40,14 +39,12 @@ export default ({ onBack, onConfirm, title = 'Add a Server', initialData, parseQ const qsParamProxy = parseQs ? appQueryParams.proxy : undefined const qsParamUsername = parseQs ? appQueryParams.username : undefined const qsParamLockConnect = parseQs ? appQueryParams.lockConnect : undefined - const qsParamAutoConnect = parseQs ? appQueryParams.autoConnect : undefined const parsedQsIp = parseServerAddress(qsParamIp) const parsedInitialIp = parseServerAddress(initialData?.ip) const [serverName, setServerName] = React.useState(initialData?.name ?? qsParamName ?? '') - const [serverIp, setServerIp] = React.useState(parsedQsIp.host || parsedInitialIp.host || '') - const [serverPort, setServerPort] = React.useState(parsedQsIp.port || parsedInitialIp.port || '') + const [serverIp, setServerIp] = React.useState(parsedQsIp.serverIpFull || parsedInitialIp.serverIpFull || '') const [versionOverride, setVersionOverride] = React.useState(initialData?.versionOverride ?? /* legacy */ initialData?.['version'] ?? qsParamVersion ?? '') const [proxyOverride, setProxyOverride] = React.useState(initialData?.proxyOverride ?? qsParamProxy ?? '') const [usernameOverride, setUsernameOverride] = React.useState(initialData?.usernameOverride ?? qsParamUsername ?? '') @@ -61,7 +58,7 @@ export default ({ onBack, onConfirm, title = 'Add a Server', initialData, parseQ const noAccountSelected = accountIndex === -1 const authenticatedAccountOverride = noAccountSelected ? undefined : freshAccount ? true : accounts?.[accountIndex] - let ipFinal = serverIp.includes(':') ? serverIp : `${serverIp}${serverPort ? `:${serverPort}` : ''}` + let ipFinal = serverIp ipFinal = ipFinal.replace(/:$/, '') const commonUseOptions: BaseServerInfo = { name: serverName, @@ -119,13 +116,10 @@ export default ({ onBack, onConfirm, title = 'Add a Server', initialData, parseQ } } - useEffect(() => { - if (qsParamAutoConnect && qsParamIp && qsParamVersion && allowAutoConnect) { - onQsConnect?.(commonUseOptions) - } - }, []) - const displayConnectButton = qsParamIp + const serverExamples = ['example.com:25565', 'play.hypixel.net', 'ws://play.pcm.gg', 'wss://play.webmc.fun'] + // pick random example + const example = serverExamples[Math.floor(Math.random() * serverExamples.length)] return
- {!lockConnect && <> -
- setServerName(value)} placeholder='Defaults to IP' /> -
- } - setServerPort(value)} placeholder={serverIp.startsWith('ws://') || serverIp.startsWith('wss://') ? '' : '25565'} /> + {!lockConnect && <> +
+ setServerName(value)} placeholder='Defaults to IP' /> +
+ } {isSmallHeight ?
:
Overrides:
}
- {displayConnectButton ? 'Save' : Save} + {displayConnectButton ? translate('Save') : {translate('Save')}} } {displayConnectButton && ( @@ -244,7 +238,7 @@ export default ({ onBack, onConfirm, title = 'Add a Server', initialData, parseQ onQsConnect?.(commonUseOptions) }} > - Connect + {translate('Connect')}
)} diff --git a/src/react/AppStatus.tsx b/src/react/AppStatus.tsx index 8dd181d7..b8c7dbde 100644 --- a/src/react/AppStatus.tsx +++ b/src/react/AppStatus.tsx @@ -4,6 +4,7 @@ import styles from './appStatus.module.css' import Button from './Button' import Screen from './Screen' import LoadingChunks from './LoadingChunks' +import LoadingTimer from './LoadingTimer' export default ({ status, @@ -37,56 +38,61 @@ export default ({ void statusRunner() }, []) + const lockConnect = appQueryParams.lockConnect === 'true' return ( - - - {status} - - -

{description}

-

{lastStatus ? `Last status: ${lastStatus}` : lastStatus}

- - } - backdrop='dirt' - > - {isError && ( - <> - {showReconnect && onReconnect && } - {actionsSlot} - - {backAction && } + {actionsSlot} + {!lockConnect && } + {backAction &&
) } diff --git a/src/react/AppStatusProvider.tsx b/src/react/AppStatusProvider.tsx index 5f3e7e06..9c7b34ac 100644 --- a/src/react/AppStatusProvider.tsx +++ b/src/react/AppStatusProvider.tsx @@ -54,6 +54,17 @@ export const reconnectReload = () => { } } +export const quickDevReconnect = () => { + if (!lastConnectOptions.value) { + return + } + + resetAppStatusState() + window.dispatchEvent(new window.CustomEvent('connect', { + detail: lastConnectOptions.value + })) +} + export default () => { const lastState = useRef(JSON.parse(JSON.stringify(appStatusState))) const currentState = useSnapshot(appStatusState) @@ -71,23 +82,40 @@ export default () => { useDidUpdateEffect(() => { // todo play effect only when world successfully loaded if (!isOpen) { - const divingElem: HTMLElement = document.querySelector('#viewer-canvas')! - divingElem.style.animationName = 'dive-animation' - divingElem.parentElement!.style.perspective = '1200px' - divingElem.onanimationend = () => { - divingElem.parentElement!.style.perspective = '' - divingElem.onanimationend = null + const startDiveAnimation = (divingElem: HTMLElement) => { + divingElem.style.animationName = 'dive-animation' + divingElem.parentElement!.style.perspective = '1200px' + divingElem.onanimationend = () => { + divingElem.parentElement!.style.perspective = '' + divingElem.onanimationend = null + } + } + + const divingElem = document.querySelector('#viewer-canvas') + let observer: MutationObserver | null = null + if (divingElem) { + startDiveAnimation(divingElem as HTMLElement) + } else { + observer = new MutationObserver((mutations) => { + const divingElem = document.querySelector('#viewer-canvas') + if (divingElem) { + startDiveAnimation(divingElem as HTMLElement) + observer!.disconnect() + } + }) + observer.observe(document.body, { + childList: true, + subtree: true + }) + } + return () => { + if (observer) { + observer.disconnect() + } } } }, [isOpen]) - const reconnect = () => { - resetAppStatusState() - window.dispatchEvent(new window.CustomEvent('connect', { - detail: lastConnectOptions.value - })) - } - useEffect(() => { const controller = new AbortController() window.addEventListener('keyup', (e) => { @@ -95,7 +123,7 @@ export default () => { if (activeModalStack.at(-1)?.reactType !== 'app-status') return // todo do only if reconnect is possible if (e.code !== 'KeyR' || !lastConnectOptions.value) return - reconnect() + quickDevReconnect() }, { signal: controller.signal }) @@ -103,7 +131,9 @@ export default () => { }, []) const displayAuthButton = status.includes('This server appears to be an online server and you are providing no authentication.') - const displayVpnButton = status.includes('VPN') || status.includes('Proxy') + || JSON.stringify(minecraftJsonMessage ?? {}).toLowerCase().includes('authenticate') + const hasVpnText = (text: string) => text.includes('VPN') || text.includes('Proxy') + const displayVpnButton = hasVpnText(status) || (minecraftJsonMessage && hasVpnText(JSON.stringify(minecraftJsonMessage))) const authReconnectAction = async () => { let accounts = [] as AuthenticatedAccount[] updateAuthenticatedAccountData(oldAccounts => { @@ -114,7 +144,7 @@ export default () => { const account = await showOptionsModal('Choose account to connect with', [...accounts.map(account => account.username), 'Use other account']) if (!account) return lastConnectOptions.value!.authenticatedAccount = accounts.find(acc => acc.username === account) || true - reconnect() + quickDevReconnect() } const lastAutoCapturedPackets = getLastAutoCapturedPackets() @@ -141,10 +171,10 @@ export default () => { } } } - return + return { actionsSlot={ <> {displayAuthButton && - diff --git a/src/react/Chat.tsx b/src/react/Chat.tsx index 78c69bec..d927a558 100644 --- a/src/react/Chat.tsx +++ b/src/react/Chat.tsx @@ -1,6 +1,6 @@ import { proxy, subscribe } from 'valtio' import { useEffect, useMemo, useRef, useState } from 'react' -import { MessageFormatPart } from '../chatUtils' +import { isStringAllowed, MessageFormatPart } from '../chatUtils' import { MessagePart } from './MessageFormatted' import './Chat.css' import { isIos, reactKeyForMessage } from './utils' @@ -11,20 +11,59 @@ import { useScrollBehavior } from './hooks/useScrollBehavior' export type Message = { parts: MessageFormatPart[], id: number - fading?: boolean - faded?: boolean + timestamp?: number } -const MessageLine = ({ message }: { message: Message }) => { +const MessageLine = ({ message, currentPlayerName, chatOpened }: { message: Message, currentPlayerName?: string, chatOpened?: boolean }) => { + const [fadeState, setFadeState] = useState<'visible' | 'fading' | 'faded'>('visible') + + useEffect(() => { + if (window.debugStopChatFade) return + // Start fading after 5 seconds + const fadeTimeout = setTimeout(() => { + setFadeState('fading') + }, 5000) + + // Remove after fade animation (3s) completes + const removeTimeout = setTimeout(() => { + setFadeState('faded') + }, 8000) + + // Cleanup timeouts if component unmounts + return () => { + clearTimeout(fadeTimeout) + clearTimeout(removeTimeout) + } + }, []) // Empty deps array since we only want this to run once when message is added + const classes = { - 'chat-message-fadeout': message.fading, - 'chat-message-fade': message.fading, - 'chat-message-faded': message.faded, - 'chat-message': true + 'chat-message': true, + 'chat-message-fading': !chatOpened && fadeState === 'fading', + 'chat-message-faded': !chatOpened && fadeState === 'faded' } - return
  • val).map(([name]) => name).join(' ')}> - {message.parts.map((msg, i) => )} + return
  • val).map(([name]) => name).join(' ')} data-time={message.timestamp ? new Date(message.timestamp).toLocaleString('en-US', { hour12: false }) : undefined}> + {message.parts.map((msg, i) => { + // Check if this is a text part that might contain a mention + if (typeof msg.text === 'string' && currentPlayerName) { + const parts = msg.text.split(new RegExp(`(@${currentPlayerName})`, 'i')) + if (parts.length > 1) { + return parts.map((txtPart, j) => { + const part = { + ...msg, + text: txtPart + } + if (txtPart.toLowerCase() === `@${currentPlayerName}`.toLowerCase()) { + part.color = '#ffa500' + part.bold = true + return + } + return + }) + } + } + return + })}
  • } @@ -34,29 +73,22 @@ type Props = { opacity?: number opened?: boolean onClose?: () => void - sendMessage?: (message: string) => boolean | void + sendMessage?: (message: string) => Promise | void fetchCompletionItems?: (triggerKind: 'implicit' | 'explicit', completeValue: string, fullValue: string, abortController?: AbortController) => Promise // width?: number allowSelection?: boolean inputDisabled?: string placeholder?: string + chatVanillaRestrictions?: boolean + debugChatScroll?: boolean + getPingComplete?: (value: string) => Promise + currentPlayerName?: string } export const chatInputValueGlobal = proxy({ value: '' }) -export const fadeMessage = (message: Message, initialTimeout: boolean, requestUpdate: () => void) => { - setTimeout(() => { - message.fading = true - requestUpdate() - setTimeout(() => { - message.faded = true - requestUpdate() - }, 3000) - }, initialTimeout ? 5000 : 0) -} - export default ({ messages, opacity = 1, @@ -67,12 +99,23 @@ export default ({ usingTouch, allowSelection, inputDisabled, - placeholder + placeholder, + chatVanillaRestrictions, + debugChatScroll, + getPingComplete, + currentPlayerName }: Props) => { + const playerNameValidated = useMemo(() => { + if (!/^[\w\d_]+$/i.test(currentPlayerName ?? '')) return '' + return currentPlayerName + }, [currentPlayerName]) + const sendHistoryRef = useRef(JSON.parse(window.sessionStorage.chatHistory || '[]')) const [isInputFocused, setIsInputFocused] = useState(false) - // const [spellCheckEnabled, setSpellCheckEnabled] = useState(false) - const spellCheckEnabled = false + const [spellCheckEnabled, setSpellCheckEnabled] = useState(false) + const [preservedInputValue, setPreservedInputValue] = useState('') + const [inputKey, setInputKey] = useState(0) + const pingHistoryRef = useRef(JSON.parse(window.localStorage.pingHistory || '[]')) const [completePadText, setCompletePadText] = useState('') const completeRequestValue = useRef('') @@ -82,22 +125,40 @@ export default ({ const chatInput = useRef(null!) const chatMessages = useRef(null) const chatHistoryPos = useRef(sendHistoryRef.current.length) + const commandHistoryPos = useRef(0) const inputCurrentlyEnteredValue = useRef('') + const commandHistoryRef = useRef(sendHistoryRef.current.filter((msg: string) => msg.startsWith('/'))) - const { scrollToBottom } = useScrollBehavior(chatMessages, { messages, opened }) + const { scrollToBottom, isAtBottom, wasAtBottom, currentlyAtBottom } = useScrollBehavior(chatMessages, { messages, opened }) + const [rightNowAtBottom, setRightNowAtBottom] = useState(false) + + useEffect(() => { + if (!debugChatScroll) return + const interval = setInterval(() => { + setRightNowAtBottom(isAtBottom()) + }, 50) + return () => clearInterval(interval) + }, [debugChatScroll]) const setSendHistory = (newHistory: string[]) => { sendHistoryRef.current = newHistory window.sessionStorage.chatHistory = JSON.stringify(newHistory) chatHistoryPos.current = newHistory.length + // Update command history (only messages starting with /) + commandHistoryRef.current = newHistory.filter((msg: string) => msg.startsWith('/')) + commandHistoryPos.current = commandHistoryRef.current.length } const acceptComplete = (item: string) => { const base = completeRequestValue.current === '/' ? '' : getCompleteValue() updateInputValue(base + item) - // todo would be cool but disabled because some comands don't need args (like ping) - // // trigger next tab complete - // this.chatInput.dispatchEvent(new KeyboardEvent('keydown', { code: 'Space' })) + // Record ping completion in history + if (item.startsWith('@')) { + const newHistory = [item, ...pingHistoryRef.current.filter((x: string) => x !== item)].slice(0, 10) + pingHistoryRef.current = newHistory + // todo use appStorage + window.localStorage.pingHistory = JSON.stringify(newHistory) + } chatInput.current.focus() } @@ -124,6 +185,21 @@ export default ({ updateInputValue(sendHistoryRef.current[chatHistoryPos.current] || inputCurrentlyEnteredValue.current || '') } + const handleCommandArrowUp = () => { + if (commandHistoryPos.current === 0 || commandHistoryRef.current.length === 0) return + if (commandHistoryPos.current === commandHistoryRef.current.length) { // started navigating command history + inputCurrentlyEnteredValue.current = chatInput.current.value + } + commandHistoryPos.current-- + updateInputValue(commandHistoryRef.current[commandHistoryPos.current] || '') + } + + const handleCommandArrowDown = () => { + if (commandHistoryPos.current === commandHistoryRef.current.length) return + commandHistoryPos.current++ + updateInputValue(commandHistoryRef.current[commandHistoryPos.current] || inputCurrentlyEnteredValue.current || '') + } + const auxInputFocus = (direction: 'up' | 'down') => { chatInput.current.focus() if (direction === 'up') { @@ -147,6 +223,7 @@ export default ({ updateInputValue(chatInputValueGlobal.value) chatInputValueGlobal.value = '' chatHistoryPos.current = sendHistoryRef.current.length + commandHistoryPos.current = commandHistoryRef.current.length if (!usingTouch) { chatInput.current.focus() } @@ -183,10 +260,21 @@ export default ({ if (opened) { completeRequestValue.current = '' resetCompletionItems() + } else { + setPreservedInputValue('') } }, [opened]) const onMainInputChange = () => { + const lastWord = chatInput.current.value.slice(0, chatInput.current.selectionEnd ?? chatInput.current.value.length).split(' ').at(-1)! + const isCommand = chatInput.current.value.startsWith('/') + + if (lastWord.startsWith('@') && getPingComplete && !isCommand) { + setCompletePadText(lastWord) + void fetchPingCompletions(true, lastWord.slice(1)) + return + } + const completeValue = getCompleteValue() setCompletePadText(completeValue === '/' ? '' : completeValue) // not sure if enabling would be useful at all (maybe make as a setting in the future?) @@ -202,9 +290,6 @@ export default ({ resetCompletionItems() } completeRequestValue.current = completeValue - // if (completeValue === '/') { - // void fetchCompletions(true) - // } } const fetchCompletions = async (implicit: boolean, inputValue = chatInput.current.value) => { @@ -217,6 +302,24 @@ export default ({ updateFilteredCompleteItems(newItems) } + const fetchPingCompletions = async (implicit: boolean, inputValue: string) => { + completeRequestValue.current = inputValue + resetCompletionItems() + const newItems = await getPingComplete?.(inputValue) ?? [] + if (inputValue !== completeRequestValue.current) return + // Sort items by ping history + const sortedItems = [...newItems].sort((a, b) => { + const aIndex = pingHistoryRef.current.indexOf(a) + const bIndex = pingHistoryRef.current.indexOf(b) + if (aIndex === -1 && bIndex === -1) return 0 + if (aIndex === -1) return 1 + if (bIndex === -1) return -1 + return aIndex - bIndex + }) + setCompletionItemsSource(sortedItems) + updateFilteredCompleteItems(sortedItems) + } + const updateFilteredCompleteItems = (sourceItems: string[] | Array<{ match: string, toolip: string }>) => { const newCompleteItems = sourceItems .map((item): string => (typeof item === 'string' ? item : item.match)) @@ -224,8 +327,11 @@ export default ({ // this regex is imporatnt is it controls the word matching // const compareableParts = item.split(/[[\]{},_:]/) const lastWord = chatInput.current.value.slice(0, chatInput.current.selectionEnd ?? chatInput.current.value.length).split(' ').at(-1)! - // return [item, ...compareableParts].some(compareablePart => compareablePart.startsWith(lastWord)) + if (lastWord.startsWith('@')) { + return item.toLowerCase().includes(lastWord.slice(1).toLowerCase()) + } return item.includes(lastWord) + // return [item, ...compareableParts].some(compareablePart => compareablePart.startsWith(lastWord)) }) setCompletionItems(newCompleteItems) } @@ -234,6 +340,7 @@ export default ({ const raw = chatInput.current.value return raw.slice(0, chatInput.current.selectionEnd ?? raw.length) } + const getCompleteValue = (value = getDefaultCompleteValue()) => { const valueParts = value.split(' ') const lastLength = valueParts.at(-1)!.length @@ -242,23 +349,140 @@ export default ({ return completeValue } + const handleSlashCommand = () => { + remountInput('/') + } + + const handleAcceptFirstCompletion = () => { + if (completionItems.length > 0) { + acceptComplete(completionItems[0]) + } + } + + const remountInput = (newValue?: string) => { + if (newValue !== undefined) { + setPreservedInputValue(newValue) + } + setInputKey(k => k + 1) + } + + useEffect(() => { + if (preservedInputValue && chatInput.current) { + chatInput.current.focus() + } + }, [inputKey]) // Changed from spellCheckEnabled to inputKey + return ( <>
    {opacity &&
    + {debugChatScroll && ( +
    +
    +
    +
    +
    +
    + )} {messages.map((m) => ( - + ))}
    || undefined}
    +
    + ) +} diff --git a/src/react/ControDebug.tsx b/src/react/ControDebug.tsx new file mode 100644 index 00000000..ca096707 --- /dev/null +++ b/src/react/ControDebug.tsx @@ -0,0 +1,75 @@ +import { useEffect, useState } from 'react' +import { options } from '../optionsStorage' +import { contro } from '../controls' + +export default () => { + const [pressedKeys, setPressedKeys] = useState>(new Set()) + const [actions, setActions] = useState([]) + + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + setPressedKeys(prev => new Set([...prev, e.code])) + } + + const handleKeyUp = (e: KeyboardEvent) => { + setPressedKeys(prev => { + const newSet = new Set(prev) + newSet.delete(e.code) + return newSet + }) + } + + const handleBlur = () => { + setPressedKeys(new Set()) + } + + const handleControTrigger = ({ command }) => { + setActions(prev => [...prev, command]) + } + + const handleControReleased = ({ command }) => { + setActions(prev => prev.filter(action => action !== command)) + } + + window.addEventListener('keydown', handleKeyDown) + window.addEventListener('keyup', handleKeyUp) + window.addEventListener('blur', handleBlur) + + contro.on('trigger', handleControTrigger) + contro.on('release', handleControReleased) + + return () => { + window.removeEventListener('keydown', handleKeyDown) + window.removeEventListener('keyup', handleKeyUp) + window.removeEventListener('blur', handleBlur) + contro.off('trigger', handleControTrigger) + contro.off('released', handleControReleased) + } + }, []) + + if (!options.debugContro) return null + + return ( +
    +
    Keys: {[...pressedKeys].join(', ')}
    +
    Actions: {actions.join(', ')}
    +
    + ) +} diff --git a/src/react/CreateWorld.tsx b/src/react/CreateWorld.tsx index a936594b..4cdf186d 100644 --- a/src/react/CreateWorld.tsx +++ b/src/react/CreateWorld.tsx @@ -1,27 +1,31 @@ import { useEffect, useState } from 'react' import { proxy, useSnapshot } from 'valtio' import { filesize } from 'filesize' +import { getAvailableServerPlugins } from '../clientMods' +import { showModal } from '../globalState' import Input from './Input' import Screen from './Screen' import Button from './Button' import SelectGameVersion from './SelectGameVersion' import styles from './createWorld.module.css' +import { InputOption, showInputsModal, showOptionsModal } from './SelectOption' // const worldTypes = ['default', 'flat', 'largeBiomes', 'amplified', 'customized', 'buffet', 'debug_all_block_states'] -const worldTypes = ['default', 'flat'/* , 'void' */] +const worldTypes = ['default', 'flat', 'empty', 'nether', 'all_the_blocks'] const gameModes = ['survival', 'creative'/* , 'adventure', 'spectator' */] export const creatingWorldState = proxy({ title: '', type: worldTypes[0], gameMode: gameModes[0], - version: '' + version: '', + plugins: [] as string[] }) export default ({ cancelClick, createClick, customizeClick, versions, defaultVersion }) => { const [quota, setQuota] = useState('') - const { title, type, version, gameMode } = useSnapshot(creatingWorldState) + const { title, type, version, gameMode, plugins } = useSnapshot(creatingWorldState) useEffect(() => { creatingWorldState.version = defaultVersion void navigator.storage?.estimate?.().then(({ quota, usage }) => { @@ -69,7 +73,38 @@ export default ({ cancelClick, createClick, customizeClick, versions, defaultVer creatingWorldState.gameMode = gameModes[index === gameModes.length - 1 ? 0 : index + 1] }} > - Gamemode: {gameMode} + Game Mode: {gameMode} + +
    +
    + +
    Default and other world types are WIP
    @@ -80,7 +115,11 @@ export default ({ cancelClick, createClick, customizeClick, versions, defaultVer }} >Cancel - +
    Note: save important worlds in folders on your hard drive!
    {quota}
    diff --git a/src/react/CreateWorldProvider.tsx b/src/react/CreateWorldProvider.tsx index b01f129c..619a31f5 100644 --- a/src/react/CreateWorldProvider.tsx +++ b/src/react/CreateWorldProvider.tsx @@ -1,7 +1,10 @@ +import fs from 'fs' +import path from 'path' import { hideCurrentModal, showModal } from '../globalState' import defaultLocalServerOptions from '../defaultLocalServerOptions' import { mkdirRecursive, uniqueFileNameFromWorldName } from '../browserfs' import supportedVersions from '../supportedVersions.mjs' +import { getServerPlugin } from '../clientMods' import CreateWorld, { WorldCustomize, creatingWorldState } from './CreateWorld' import { getWorldsPath } from './SingleplayerProvider' import { useIsModalActive } from './utilsApp' @@ -14,7 +17,7 @@ export default () => { const versions = Object.values(versionsPerMinor).map(x => { return { version: x, - label: x === defaultLocalServerOptions.version ? `${x} (available offline)` : x + label: x === defaultLocalServerOptions.version ? `${x} (default)` : x } }) return { }} createClick={async () => { // create new world - const { title, type, version, gameMode } = creatingWorldState + const { title, type, version, gameMode, plugins } = creatingWorldState // todo display path in ui + disable if exist const savePath = await uniqueFileNameFromWorldName(title, getWorldsPath()) await mkdirRecursive(savePath) - let generation - if (type === 'flat') { - generation = { - name: 'superflat', - } - } - if (type === 'void') { - generation = { - name: 'superflat', - layers: [], - noDefaults: true - } - } - if (type === 'nether') { - generation = { - name: 'nether' - } - } + await loadPluginsIntoWorld(savePath, plugins) hideCurrentModal() window.dispatchEvent(new CustomEvent('singleplayer', { detail: { levelName: title, version, - generation, + generation: { + name: type + }, 'worldFolder': savePath, gameMode: gameMode === 'survival' ? 0 : 1, }, @@ -68,3 +56,16 @@ export default () => { } return null } + +export const loadPluginsIntoWorld = async (worldPath: string, plugins: string[]) => { + for (const plugin of plugins) { + // eslint-disable-next-line no-await-in-loop + const { content, version } = await getServerPlugin(plugin) ?? {} + if (content) { + // eslint-disable-next-line no-await-in-loop + await mkdirRecursive(path.join(worldPath, 'plugins')) + // eslint-disable-next-line no-await-in-loop + await fs.promises.writeFile(path.join(worldPath, 'plugins', `${plugin}-${version}.js`), content) + } + } +} diff --git a/src/react/CreditsAboutModal.module.css b/src/react/CreditsAboutModal.module.css new file mode 100644 index 00000000..753d0448 --- /dev/null +++ b/src/react/CreditsAboutModal.module.css @@ -0,0 +1,84 @@ +.modalScreen { + margin-top: -15px; +} + +.container { + position: relative; + background-color: #eee0c3; + border: 5px solid #7A5C3E; + padding: 15px; + width: 80%; + margin: 0 auto; + color: #3F2A14; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); + max-height: 70vh; + overflow-y: auto; +} + +.title { + text-align: center; + margin-top: 0; + margin-bottom: 0; + font-size: 10px; +} + +.contentWrapper { + margin-bottom: 5px; +} + +.subtitle { + font-size: 6px; + margin-bottom: 4px; + font-style: italic; +} + +.paragraph { + font-size: 6px; + margin-bottom: 4px; +} + +.list { + list-style-type: none; + padding: 0; + font-size: 6px; +} + +.listItem { + margin-bottom: 2px; +} + +.link { + color: #0000AA; + text-decoration: none; +} + +.sectionTitle { + margin-top: 7px; + margin-bottom: 5px; + font-size: 8px; +} + +.closeButton { + position: absolute; + top: 1px; + right: 1px; + display: flex; + justify-content: center; + cursor: pointer; + padding: 5px; + background: none; + border: none; + outline: none; +} + +.closeButton:hover { + opacity: 0.8; +} + +.closeButton:focus-visible { + outline: 1px dashed #7A5C3E; +} + +.closeIcon { + color: #3F2A14; +} \ No newline at end of file diff --git a/src/react/CreditsAboutModal.module.css.d.ts b/src/react/CreditsAboutModal.module.css.d.ts new file mode 100644 index 00000000..30ac3261 --- /dev/null +++ b/src/react/CreditsAboutModal.module.css.d.ts @@ -0,0 +1,18 @@ +// This file is automatically generated. +// Please do not change this file! +interface CssExports { + closeButton: string; + closeIcon: string; + container: string; + contentWrapper: string; + link: string; + list: string; + listItem: string; + modalScreen: string; + paragraph: string; + sectionTitle: string; + subtitle: string; + title: string; +} +declare const cssExports: CssExports; +export default cssExports; diff --git a/src/react/CreditsAboutModal.tsx b/src/react/CreditsAboutModal.tsx new file mode 100644 index 00000000..24826cd3 --- /dev/null +++ b/src/react/CreditsAboutModal.tsx @@ -0,0 +1,57 @@ +import { hideCurrentModal } from '../globalState' +import { useIsModalActive } from './utilsApp' +import Screen from './Screen' +import PixelartIcon, { pixelartIcons } from './PixelartIcon' +import styles from './CreditsAboutModal.module.css' + +export default () => { + const isModalActive = useIsModalActive('credits-about') + + if (!isModalActive) return null + + return ( + +
    +

    Minecraft Open Source JS Edition

    + +
    + What if Minecraft was an online game? +

    + Hey! You are on the safest modern Minecraft clone rewritten in JavaScript. A huge amount of work has gone into this project to make it fast and complete, and many features would not be possible without these awesome people and projects: +

    +
      +
    • - Everyone who provided awesome mods for the game
    • +
    • - [Gen] for rewriting the physics engine to be Grim-compliant
    • +
    • - [ViaVersion] for providing reliable sound id mappings
    • +
    • - [Bluemap] for providing block entity models like chest
    • +
    • - [Deepslate] for rendering 3d blocks in GUI (inventory)
    • +
    • - [skinview3d] for rendering skins & player geometry
    • +
    • - [Polymer] (c++ project) for providing fast & accurate server light implementation
    • +
    + +

    Current contributors:

    +
      +
    • - Maxim Grigorev - React UI & Core Developer Maintainer
    • +
    • - And many more community contributors!
    • +
    + + +
    +
    +
    + ) +} diff --git a/src/react/CreditsBookButton.module.css b/src/react/CreditsBookButton.module.css new file mode 100644 index 00000000..83af5d80 --- /dev/null +++ b/src/react/CreditsBookButton.module.css @@ -0,0 +1,27 @@ +.creditsButton { + position: absolute; + top: 1px; + right: -30px; + display: flex; + align-items: center; + justify-content: center; + background: none; + border: none; + cursor: pointer; + color: white; + opacity: 1; + transition: opacity 0.2s ease; +} + +.creditsButton:hover { + opacity: 0.9; +} + +.creditsButton:focus:not(:hover) { + outline: 1px solid #fff; +} + +.creditsButton svg { + width: 15px; + height: 15px; +} diff --git a/src/react/CreditsBookButton.module.css.d.ts b/src/react/CreditsBookButton.module.css.d.ts new file mode 100644 index 00000000..72f94435 --- /dev/null +++ b/src/react/CreditsBookButton.module.css.d.ts @@ -0,0 +1,7 @@ +// This file is automatically generated. +// Please do not change this file! +interface CssExports { + creditsButton: string; +} +declare const cssExports: CssExports; +export default cssExports; diff --git a/src/react/CreditsBookButton.tsx b/src/react/CreditsBookButton.tsx new file mode 100644 index 00000000..a3be740f --- /dev/null +++ b/src/react/CreditsBookButton.tsx @@ -0,0 +1,22 @@ +import { showModal } from '../globalState' +import styles from './CreditsBookButton.module.css' + +export default () => { + const handleClick = () => { + showModal({ reactType: 'credits-about' }) + } + + return ( + + ) +} diff --git a/src/react/DeathScreen.tsx b/src/react/DeathScreen.tsx index 8f4c3f00..3501368f 100644 --- a/src/react/DeathScreen.tsx +++ b/src/react/DeathScreen.tsx @@ -24,7 +24,7 @@ export default ({ dieReasonMessage, respawnCallback, disconnectCallback }: Props }} /> {userConfig?.[group]?.[action]?.[inputType === 'keyboard' ? 'keys' : 'gamepad']?.some(key => Object.keys(bindsMap[inputType]).includes(key) - && bindsMap[inputType][key].length > 1 - && bindsMap[inputType][key].some(prop => prop.index === index - && prop.group === group - && prop.action === action)) ? ( + && bindsMap[inputType][key].length > 1 + && bindsMap[inputType][key].some(prop => prop.index === index + && prop.group === group + && prop.action === action)) ? ( //@ts-format-ignore-region
    { + loadingTimerState.loading = false +}) + +export default () => { + // const time = useSnapshot(timerState).start + const { networkTimeTotal, total } = useSnapshot(loadingTimerState) + + useEffect(() => { + const interval = setInterval(() => { + if (!loadingTimerState.loading) return + if (loadingTimerState.networkOnlyStart) { + loadingTimerState.networkTimeTotal = ((Date.now() - loadingTimerState.networkOnlyStart) / 1000).toFixed(2) + } else { + loadingTimerState.total = ((Date.now() - loadingTimerState.start) / 1000).toFixed(2) + } + }, 100) + return () => clearInterval(interval) + }, []) + + return +
    + {total}/{networkTimeTotal} +
    +
    +} + +const Portal = ({ children, to = document.body }) => { + return createPortal(children, to) +} diff --git a/src/react/MainMenu.tsx b/src/react/MainMenu.tsx index 85c5367e..c1332530 100644 --- a/src/react/MainMenu.tsx +++ b/src/react/MainMenu.tsx @@ -1,13 +1,24 @@ -import React from 'react' +import React, { useEffect, useMemo } from 'react' import { openURL } from 'renderer/viewer/lib/simpleUtils' +import { useSnapshot } from 'valtio' import { haveDirectoryPicker } from '../utils' import { ConnectOptions } from '../connect' +import { miscUiState } from '../globalState' +import { + isRemoteSplashText, + loadRemoteSplashText, + getCachedSplashText, + cacheSplashText, + cacheSourceUrl, + clearSplashCache +} from '../utils/splashText' import styles from './mainMenu.module.css' import Button from './Button' import ButtonWithTooltip from './ButtonWithTooltip' import { pixelartIcons } from './PixelartIcon' import useLongPress from './useLongPress' import PauseLinkButtons from './PauseLinkButtons' +import CreditsBookButton from './CreditsBookButton' type Action = (e: React.MouseEvent) => void @@ -42,8 +53,48 @@ export default ({ versionTitle, onVersionStatusClick, bottomRightLinks, - singleplayerAvailable = true + singleplayerAvailable = true, }: Props) => { + const { appConfig } = useSnapshot(miscUiState) + + const splashText = useMemo(() => { + const cachedText = getCachedSplashText() + + const configSplashFromApp = appConfig?.splashText + const isRemote = configSplashFromApp && isRemoteSplashText(configSplashFromApp) + const sourceKey = isRemote ? configSplashFromApp : (configSplashFromApp || '') + const storedSourceKey = localStorage.getItem('minecraft_splash_url') + + if (storedSourceKey !== sourceKey) { + clearSplashCache() + cacheSourceUrl(sourceKey) + } else if (cachedText) { + return cachedText + } + + if (!isRemote && configSplashFromApp && configSplashFromApp.trim() !== '') { + cacheSplashText(configSplashFromApp) + return configSplashFromApp + } + + return appConfig?.splashTextFallback || '' + }, []) + + useEffect(() => { + const configSplashFromApp = appConfig?.splashText + if (configSplashFromApp && isRemoteSplashText(configSplashFromApp)) { + loadRemoteSplashText(configSplashFromApp) + .then(fetchedText => { + if (fetchedText && fetchedText.trim() !== '' && !fetchedText.includes('Failed to load')) { + cacheSplashText(fetchedText) + } + }) + .catch(error => { + console.error('Failed to preload splash text for next session:', error) + }) + } + }, [appConfig?.splashText]) + if (!bottomRightLinks?.trim()) bottomRightLinks = undefined // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion const linksParsed = bottomRightLinks?.split(/;|\n/g).map(l => { @@ -71,7 +122,7 @@ export default ({ const connectToServerLongPress = useLongPress( () => { if (process.env.NODE_ENV === 'development') { - // Connect to :25565 + // Connect to :25565 const origin = window.location.hostname const connectOptions: ConnectOptions = { server: `${origin}:25565`, @@ -89,7 +140,7 @@ export default ({
    - Prismarine is a beautiful block + {splashText}
    @@ -145,6 +196,7 @@ export default ({
    +
    @@ -177,7 +229,7 @@ export default ({
    })}
    - A Minecraft client clone in the browser! + {appConfig?.rightSideText}
    diff --git a/src/react/MainMenuRenderApp.tsx b/src/react/MainMenuRenderApp.tsx index f678e7f7..c6c36ca3 100644 --- a/src/react/MainMenuRenderApp.tsx +++ b/src/react/MainMenuRenderApp.tsx @@ -1,5 +1,5 @@ import fs from 'fs' -import { Transition } from 'react-transition-group' +import { motion, AnimatePresence } from 'framer-motion' import { proxy, subscribe, useSnapshot } from 'valtio' import { useEffect, useState } from 'react' import { activeModalStack, miscUiState, openOptionsMenu, showModal } from '../globalState' @@ -112,40 +112,53 @@ export default () => { } }, []) - let mapsProviderUrl = appConfig?.mapsProvider - if (mapsProviderUrl && location.origin !== 'https://mcraft.fun') mapsProviderUrl = mapsProviderUrl + '?to=' + encodeURIComponent(location.href) + const mapsProviderUrl = appConfig?.mapsProvider && new URL(appConfig?.mapsProvider) + if (mapsProviderUrl && location.origin !== 'https://mcraft.fun') { + mapsProviderUrl.searchParams.set('to', location.href) + } - // todo clean, use custom csstransition - return - {(state) =>
    - showModal({ reactType: 'serversList' })} - singleplayerAction={async () => { - showModal({ reactType: 'singleplayer' }) - }} - githubAction={() => openGithub()} - optionsAction={() => openOptionsMenu('main')} - bottomRightLinks={process.env.MAIN_MENU_LINKS} - openFileAction={e => { - if (!!window.showDirectoryPicker && !e.shiftKey) { - void openWorldDirectory() - } else { - openFilePicker() - } - }} - mapsProvider={mapsProviderUrl} - versionStatus={versionStatus} - versionTitle={versionTitle} - onVersionStatusClick={async () => { - setVersionStatus('(reloading)') - await refreshApp() - }} - onVersionTextClick={async () => { - openGithub(process.env.RELEASE_LINK) - }} - versionText={process.env.RELEASE_TAG} - /> -
    } -
    + return ( + + {!noDisplay && ( + + showModal({ reactType: 'serversList' })} + singleplayerAction={async () => { + showModal({ reactType: 'singleplayer' }) + }} + githubAction={() => openGithub()} + optionsAction={() => openOptionsMenu('main')} + bottomRightLinks={process.env.MAIN_MENU_LINKS} + openFileAction={e => { + if (!!window.showDirectoryPicker && !e.shiftKey) { + void openWorldDirectory() + } else { + openFilePicker() + } + }} + mapsProvider={mapsProviderUrl?.toString()} + versionStatus={versionStatus} + versionTitle={versionTitle} + onVersionStatusClick={async () => { + setVersionStatus('(reloading)') + await refreshApp() + }} + onVersionTextClick={async () => { + openGithub(process.env.RELEASE_LINK) + }} + versionText={process.env.RELEASE_TAG} + /> + + )} + + ) } diff --git a/src/react/MessageFormatted.css b/src/react/MessageFormatted.css index 7e5be00a..f16a0644 100644 --- a/src/react/MessageFormatted.css +++ b/src/react/MessageFormatted.css @@ -1,5 +1,5 @@ /* base global styles */ .formatted-message { - text-shadow: 1px 1px 0px #3f3f3f;; + /* text-shadow: 1px 1px 0px #3f3f3f; */ } diff --git a/src/react/MessageFormatted.tsx b/src/react/MessageFormatted.tsx index 554d5a9b..a70ca3b1 100644 --- a/src/react/MessageFormatted.tsx +++ b/src/react/MessageFormatted.tsx @@ -3,7 +3,7 @@ import { render } from '@xmcl/text-component' import { noCase } from 'change-case' import mojangson from 'mojangson' import { openURL } from 'renderer/viewer/lib/simpleUtils' -import { MessageFormatPart } from '../chatUtils' +import { MessageFormatOptions, MessageFormatPart } from '../chatUtils' import { chatInputValueGlobal } from './Chat' import './MessageFormatted.css' import { showOptionsModal } from './SelectOption' @@ -67,9 +67,10 @@ const clickEventToProps = (clickEvent: MessageFormatPart['clickEvent']) => { } } -export const MessagePart = ({ part, ...props }: { part: MessageFormatPart } & ComponentProps<'span'>) => { +export const MessagePart = ({ part, formatOptions, ...props }: { part: MessageFormatPart, formatOptions?: MessageFormatOptions } & ComponentProps<'span'>) => { - const { color, italic, bold, underlined, strikethrough, text, clickEvent, hoverEvent, obfuscated } = part + const { color: _color, italic, bold, underlined, strikethrough, text, clickEvent, hoverEvent, obfuscated } = part + const color = _color ?? 'white' const clickProps = clickEventToProps(clickEvent) const hoverMessageRaw = hoverItemToText(hoverEvent) @@ -77,7 +78,7 @@ export const MessagePart = ({ part, ...props }: { part: MessageFormatPart } & Co const applyStyles = [ clickProps && messageFormatStylesMap.clickEvent, - color ? colorF(color.toLowerCase()) + `; text-shadow: 1px 1px 0px ${getColorShadow(colorF(color.toLowerCase()).replace('color:', ''))}` : messageFormatStylesMap.white, + colorF(color.toLowerCase()) + ((formatOptions?.doShadow ?? true) ? `; text-shadow: 1px 1px 0px ${getColorShadow(colorF(color.toLowerCase()).replace('color:', ''))}` : ''), italic && messageFormatStylesMap.italic, bold && messageFormatStylesMap.bold, italic && messageFormatStylesMap.italic, @@ -89,10 +90,10 @@ export const MessagePart = ({ part, ...props }: { part: MessageFormatPart } & Co return {text} } -export default ({ parts, className }: { parts: readonly MessageFormatPart[], className?: string }) => { +export default ({ parts, className, formatOptions }: { parts: readonly MessageFormatPart[], className?: string, formatOptions?: MessageFormatOptions }) => { return ( - {parts.map((part, i) => )} + {parts.map((part, i) => )} ) } @@ -123,22 +124,22 @@ export function parseInlineStyle (style: string): Record { } export const messageFormatStylesMap = { - black: 'color:#000000', - dark_blue: 'color:#0000AA', - dark_green: 'color:#00AA00', - dark_aqua: 'color:#00AAAA', - dark_red: 'color:#AA0000', - dark_purple: 'color:#AA00AA', - gold: 'color:#FFAA00', - gray: 'color:#AAAAAA', - dark_gray: 'color:#555555', - blue: 'color:#5555FF', - green: 'color:#55FF55', - aqua: 'color:#55FFFF', - red: 'color:#FF5555', - light_purple: 'color:#FF55FF', - yellow: 'color:#FFFF55', - white: 'color:#FFFFFF', + black: 'color:color(display-p3 0 0 0)', + dark_blue: 'color:color(display-p3 0 0 0.6667)', + dark_green: 'color:color(display-p3 0 0.6667 0)', + dark_aqua: 'color:color(display-p3 0 0.6667 0.6667)', + dark_red: 'color:color(display-p3 0.6667 0 0)', + dark_purple: 'color:color(display-p3 0.6667 0 0.6667)', + gold: 'color:color(display-p3 1 0.6667 0)', + gray: 'color:color(display-p3 0.6667 0.6667 0.6667)', + dark_gray: 'color:color(display-p3 0.3333 0.3333 0.3333)', + blue: 'color:color(display-p3 0.3333 0.3333 1)', + green: 'color:color(display-p3 0.3333 1 0.3333)', + aqua: 'color:color(display-p3 0.3333 1 1)', + red: 'color:color(display-p3 1 0.3333 0.3333)', + light_purple: 'color:color(display-p3 1 0.3333 1)', + yellow: 'color:color(display-p3 1 1 0.3333)', + white: 'color:color(display-p3 1 1 1)', bold: 'font-weight:900', strikethrough: 'text-decoration:line-through', underlined: 'text-decoration:underline', diff --git a/src/react/MessageFormattedString.tsx b/src/react/MessageFormattedString.tsx index f667cdd8..1fe8166a 100644 --- a/src/react/MessageFormattedString.tsx +++ b/src/react/MessageFormattedString.tsx @@ -1,14 +1,15 @@ import { useMemo } from 'react' import { fromFormattedString } from '@xmcl/text-component' import { ErrorBoundary } from '@zardoy/react-util' -import { formatMessage } from '../chatUtils' +import { formatMessage, MessageFormatOptions } from '../chatUtils' import MessageFormatted from './MessageFormatted' /** like MessageFormatted, but receives raw string or json instead, uses window.loadedData */ -export default ({ message, fallbackColor, className }: { +export default ({ message, fallbackColor, className, formatOptions }: { message: string | Record | null, fallbackColor?: string, className?: string + formatOptions?: MessageFormatOptions }) => { const messageJson = useMemo(() => { if (!message) return null @@ -30,6 +31,6 @@ export default ({ message, fallbackColor, className }: { console.error(error) return
    [text component crashed]
    }}> - + : null } diff --git a/src/react/MineflayerPluginConsole.tsx b/src/react/MineflayerPluginConsole.tsx index e681f882..2e1b6c1a 100644 --- a/src/react/MineflayerPluginConsole.tsx +++ b/src/react/MineflayerPluginConsole.tsx @@ -17,6 +17,7 @@ export const mineflayerConsoleState = proxy({ messages: [] as ConsoleMessage[], replEnabled: false, consoleEnabled: false, + takeoverMode: false }) const MessageLine = ({ message }: { message: ConsoleMessage }) => { diff --git a/src/react/Minimap.tsx b/src/react/Minimap.tsx index 10c2b666..9eb8a253 100644 --- a/src/react/Minimap.tsx +++ b/src/react/Minimap.tsx @@ -22,8 +22,14 @@ export default ( const canvasTick = useRef(0) const canvasRef = useRef(null) const [position, setPosition] = useState({ x: 0, y: 0, z: 0 }) + const lastUpdate = useRef(0) + const THROTTLE_MS = 50 // 20fps const updateMap = () => { + const now = Date.now() + if (now - lastUpdate.current < THROTTLE_MS) return + lastUpdate.current = now + setPosition({ x: adapter.playerPosition.x, y: adapter.playerPosition.y, z: adapter.playerPosition.z }) if (adapter.mapDrawer) { if (!full.current) { @@ -85,6 +91,7 @@ export default ( top: '0px', padding: '5px 5px 0px 0px', textAlign: 'center', + zIndex: 7, }} onClick={() => { toggleFullMap?.() @@ -106,7 +113,7 @@ export default ( textShadow: '0.1em 0 black, 0 0.1em black, -0.1em 0 black, 0 -0.1em black, -0.1em -0.1em black, -0.1em 0.1em black, 0.1em -0.1em black, 0.1em 0.1em black' }} > - {position.x.toFixed(2)} {position.y.toFixed(2)} {position.z.toFixed(2)} + {Math.round(position.x)} {Math.round(position.y)} {Math.round(position.z)} : null } diff --git a/src/react/MinimapProvider.tsx b/src/react/MinimapProvider.tsx index b1d39e80..26a15134 100644 --- a/src/react/MinimapProvider.tsx +++ b/src/react/MinimapProvider.tsx @@ -10,7 +10,7 @@ import { Chunk } from 'prismarine-world/types/world' import { Block } from 'prismarine-block' import { INVISIBLE_BLOCKS } from 'renderer/viewer/lib/mesher/worldConstants' import { getRenamedData } from 'flying-squid/dist/blockRenames' -import { useSnapshot } from 'valtio' +import { useSnapshot, subscribe } from 'valtio' import { subscribeKey } from 'valtio/utils' import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods' import BlockData from '../../renderer/viewer/lib/moreBlockDataGenerated.json' @@ -42,10 +42,10 @@ export class DrawerAdapterImpl extends TypedEventEmitter implements yaw: number world: string warps: WorldWarp[] = gameAdditionalState.warps - chunksStore = new Map() + chunksStore = new Map() loadingChunksQueue = new Set() loadChunk: (key: string) => Promise = this.loadChunkMinimap - mapDrawer = new MinimapDrawer(this.loadChunk, this.warps, this.loadingChunksQueue, this.chunksStore) + mapDrawer = new MinimapDrawer(this.loadChunk.bind(this), this.warps, this.loadingChunksQueue, this.chunksStore) currChunk: PCChunk | undefined currChunkPos: { x: number, z: number } = { x: 0, z: 0 } isOldVersion: boolean @@ -80,8 +80,13 @@ export class DrawerAdapterImpl extends TypedEventEmitter implements const readZ = chunkZ % 32 < 0 ? 32 + chunkZ % 32 : chunkZ % 32 console.log('heightmap check begun', readX, readZ) void this.regions.get(regionKey)?.read(readX, readZ)?.then((rawChunk) => { - const chunk = simplify(rawChunk as any) - const heightmap = findHeightMap(chunk) + let heightmap: number[] | undefined + try { + const chunk = simplify(rawChunk as any) + heightmap = findHeightMap(chunk) + } catch (err) { + console.warn('error getting heightmap', err) + } if (heightmap) { this.isBuiltinHeightmapAvailable = true this.loadChunkFullmap = this.loadChunkFromRegion @@ -114,9 +119,9 @@ export class DrawerAdapterImpl extends TypedEventEmitter implements this.blockData.set(renamedKey, BlockData.colors[blockKey]) } - subscribeKey(appViewer.rendererState, 'world', () => { + subscribe(appViewer.rendererState.world, () => { for (const key of this.loadingChunksQueue) { - if (appViewer.rendererState.world.chunksLoaded.includes(key)) { + if (appViewer.rendererState.world.chunksLoaded.has(key)) { this.loadingChunksQueue.delete(key) void this.loadChunk(key) } @@ -164,9 +169,9 @@ export class DrawerAdapterImpl extends TypedEventEmitter implements // type suppressed until server is updated. It works fine void (localServer as any).setWarp(warp, remove) } else if (remove) { - localStorage.removeItem(`warps: ${bot.player.username} ${lastConnectOptions.value!.server}`) + localStorage.removeItem(`warps: ${bot.username} ${lastConnectOptions.value!.server}`) } else { - localStorage.setItem(`warps: ${bot.player.username} ${lastConnectOptions.value!.server}`, JSON.stringify(this.warps)) + localStorage.setItem(`warps: ${bot.username} ${lastConnectOptions.value!.server}`, JSON.stringify(this.warps)) } this.emit('updateWarps') } @@ -200,33 +205,31 @@ export class DrawerAdapterImpl extends TypedEventEmitter implements const [chunkX, chunkZ] = key.split(',').map(Number) const chunkWorldX = chunkX * 16 const chunkWorldZ = chunkZ * 16 - if (appViewer.rendererState.world.chunksLoaded.includes(`${chunkWorldX},${chunkWorldZ}`)) { - const highestBlocks = await getThreeJsRendererMethods()?.getHighestBlocks() - if (!highestBlocks) return undefined - const heightmap = new Uint8Array(256) + if (appViewer.rendererState.world.chunksLoaded.has(key)) { + // console.log('[MinimapProvider] loading chunk for minimap', key) + const heightmap = appViewer.rendererState.world.heightmaps.get(key) + if (heightmap) { + // console.log('[MinimapProvider] did get highest blocks') + } else { + console.warn('[MinimapProvider] no highestBlocks from renderMethods') + return undefined + } const colors = Array.from({ length: 256 }).fill('') as string[] // avoid creating new object every time const blockPos = new Vec3(0, 0, 0) - // filling up colors and heightmap + // filling up colors for (let z = 0; z < 16; z += 1) { for (let x = 0; x < 16; x += 1) { const blockX = chunkWorldX + x const blockZ = chunkWorldZ + z - const hBlock = highestBlocks.get(`${blockX},${blockZ}`) - blockPos.x = blockX; blockPos.z = blockZ; blockPos.y = hBlock?.y ?? 0 - let block = bot.world.getBlock(blockPos) - while (block?.name.includes('air')) { - blockPos.y -= 1 - block = bot.world.getBlock(blockPos) - } const index = z * 16 + x + blockPos.x = blockX; blockPos.z = blockZ; blockPos.y = heightmap[index] + const block = bot.world.getBlock(blockPos) // blocks which are not set are shown as half transparent - if (!block || !hBlock) { - heightmap[index] = 0 + if (!block) { colors[index] = 'rgba(0, 0, 0, 0.5)' continue } - heightmap[index] = block.position.y colors[index] = this.setColor(block) } } @@ -237,6 +240,7 @@ export class DrawerAdapterImpl extends TypedEventEmitter implements } else { this.loadingChunksQueue.add(`${chunkX},${chunkZ}`) this.chunksStore.set(key, 'requested') + // console.log('[MinimapProvider] requested new chunk', key) } } @@ -333,8 +337,8 @@ export class DrawerAdapterImpl extends TypedEventEmitter implements const [chunkX, chunkZ] = key.split(',').map(Number) const chunkWorldX = chunkX * 16 const chunkWorldZ = chunkZ * 16 - const highestBlocks = await getThreeJsRendererMethods()?.getHighestBlocks() - if (appViewer.rendererState.world.chunksLoaded.includes(`${chunkWorldX},${chunkWorldZ}`)) { + const highestBlocks = await getThreeJsRendererMethods()?.getHighestBlocks(`${chunkWorldX},${chunkWorldZ}`) + if (appViewer.rendererState.world.chunksLoaded.has(`${chunkWorldX},${chunkWorldZ}`)) { const heightmap = new Uint8Array(256) const colors = Array.from({ length: 256 }).fill('') as string[] if (!highestBlocks) return null @@ -342,7 +346,7 @@ export class DrawerAdapterImpl extends TypedEventEmitter implements for (let x = 0; x < 16; x += 1) { const blockX = chunkWorldX + x const blockZ = chunkWorldZ + z - const hBlock = highestBlocks.get(`${blockX},${blockZ}`) + const hBlock = highestBlocks[`${blockX},${blockZ}`] const block = bot.world.getBlock(new Vec3(blockX, hBlock?.y ?? 0, blockZ)) // const block = Block.fromStateId(hBlock?.stateId ?? -1, hBlock?.biomeId ?? -1) const index = z * 16 + x @@ -462,7 +466,7 @@ export class DrawerAdapterImpl extends TypedEventEmitter implements let color: string if (this.isOldVersion) { color = BlockData.colors[preflatMap.blocks[`${block.type}:${block.metadata}`]?.replaceAll(/\[.*?]/g, '')] - ?? 'rgb(0, 0, 255)' + ?? 'rgb(0, 0, 255)' } else { color = this.blockData.get(block.name) ?? 'rgb(0, 255, 0)' } diff --git a/src/react/MobileTopButtons.module.css b/src/react/MobileTopButtons.module.css index d1692f8b..55246492 100644 --- a/src/react/MobileTopButtons.module.css +++ b/src/react/MobileTopButtons.module.css @@ -35,3 +35,17 @@ padding: 4px 6px; outline: 0.5px solid white; } + +.tab-btn { + color: #fff; + background: #9c8c86; + outline: .5px solid #fff; + padding: 4px 6px; + font-family: pixelarticons, mojangles, monospace; + font-size: 8px; +} + +.tab-btn:has(> div) { + padding: 3px 5px; + font-size: 12px; +} diff --git a/src/react/MobileTopButtons.module.css.d.ts b/src/react/MobileTopButtons.module.css.d.ts index 859cc929..6b38dde0 100644 --- a/src/react/MobileTopButtons.module.css.d.ts +++ b/src/react/MobileTopButtons.module.css.d.ts @@ -9,6 +9,8 @@ interface CssExports { mobileTopBtns: string; 'pause-btn': string; pauseBtn: string; + 'tab-btn': string; + tabBtn: string; } declare const cssExports: CssExports; export default cssExports; diff --git a/src/react/MobileTopButtons.tsx b/src/react/MobileTopButtons.tsx index 4d18f817..f048af56 100644 --- a/src/react/MobileTopButtons.tsx +++ b/src/react/MobileTopButtons.tsx @@ -1,87 +1,162 @@ import { useEffect, useRef } from 'react' -import { f3Keybinds } from '../controls' +import { useSnapshot } from 'valtio' +import { handleMobileButtonActionCommand, handleMobileButtonLongPress } from '../controls' import { watchValue } from '../optionsStorage' -import { showModal, miscUiState, activeModalStack, hideCurrentModal } from '../globalState' -import { showOptionsModal } from './SelectOption' -import useLongPress from './useLongPress' +import { type MobileButtonConfig, type ActionHoldConfig, type ActionType, type CustomAction } from '../appConfig' +import { miscUiState } from '../globalState' +import PixelartIcon from './PixelartIcon' import styles from './MobileTopButtons.module.css' - export default () => { const elRef = useRef(null) + const { appConfig } = useSnapshot(miscUiState) + const mobileButtonsConfig = appConfig?.mobileButtons - const showMobileControls = (bl) => { - if (elRef.current) elRef.current.style.display = bl ? 'flex' : 'none' + const longPressTimerIdRef = useRef(null) + const actionToShortPressRef = useRef(null) + + const showMobileControls = (visible: boolean) => { + if (elRef.current) { + elRef.current.style.display = visible ? 'flex' : 'none' + } } useEffect(() => { watchValue(miscUiState, o => { - showMobileControls(o.currentTouch) + showMobileControls(Boolean(o.currentTouch)) }) }, []) - const onLongPress = async () => { - const select = await showOptionsModal('', f3Keybinds.filter(f3Keybind => f3Keybind.mobileTitle && (f3Keybind.enabled?.() ?? true)).map(f3Keybind => f3Keybind.mobileTitle)) - if (!select) return - const f3Keybind = f3Keybinds.find(f3Keybind => f3Keybind.mobileTitle === select) - if (f3Keybind) f3Keybind.action() - } + const getButtonClassName = (button: MobileButtonConfig): string => { + const actionForStyle = button.action || (button.actionHold && typeof button.actionHold === 'object' && 'command' in button.actionHold ? button.actionHold.command : undefined) - const defaultOptions = { - shouldPreventDefault: true, - delay: 500, - } - const longPressEvent = useLongPress(onLongPress, () => {}, defaultOptions) - - - const onChatLongPress = () => { - document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Tab' })) - } - - const onChatClick = () => { - if (activeModalStack.at(-1)?.reactType === 'chat') { - hideCurrentModal() - } else { - showModal({ reactType: 'chat' }) + if (typeof actionForStyle === 'string') { + switch (actionForStyle) { + case 'general.chat': + return styles['chat-btn'] + case 'ui.pauseMenu': + return styles['pause-btn'] + case 'general.playersList': + return styles['tab-btn'] + default: + return styles['debug-btn'] + } } + return styles['debug-btn'] } - const chatLongPressEvent = useLongPress( - onChatLongPress, - onChatClick, - { - shouldPreventDefault: true, - delay: 300, - } - ) + const renderConfigButtons = () => { + return mobileButtonsConfig?.map((button, index) => { + const className = getButtonClassName(button) + let label: string | JSX.Element = button.icon || button.label || '' + + if (typeof label === 'string' && label.startsWith('pixelarticons:')) { + const iconName = label.replace('pixelarticons:', '') + label = + } + + const onPointerDown = (e: React.PointerEvent) => { + const elem = e.currentTarget as HTMLElement + elem.setPointerCapture(e.pointerId) + + if (longPressTimerIdRef.current) { + clearTimeout(longPressTimerIdRef.current) + longPressTimerIdRef.current = null + } + actionToShortPressRef.current = null + + const { actionHold, action } = button + + if (actionHold) { + if (typeof actionHold === 'object' && 'command' in actionHold) { + const config = actionHold + if (config.longPressAction) { + actionToShortPressRef.current = config.command + longPressTimerIdRef.current = window.setTimeout(() => { + handleMobileButtonLongPress(config) + actionToShortPressRef.current = null + longPressTimerIdRef.current = null + }, config.duration || 500) + } else { + handleMobileButtonActionCommand(config.command, true) + } + } else if (action) { + actionToShortPressRef.current = action + longPressTimerIdRef.current = window.setTimeout(() => { + handleMobileButtonActionCommand(actionHold, true) + actionToShortPressRef.current = null + longPressTimerIdRef.current = null + }, 500) + } else { + handleMobileButtonActionCommand(actionHold, true) + } + } else if (action) { + handleMobileButtonActionCommand(action, true) + } + } + + const onPointerUp = (e: React.PointerEvent) => { + const elem = e.currentTarget as HTMLElement + elem.releasePointerCapture(e.pointerId) + + const { actionHold, action } = button + let wasShortPressHandled = false + + if (longPressTimerIdRef.current) { + clearTimeout(longPressTimerIdRef.current) + longPressTimerIdRef.current = null + if (actionToShortPressRef.current) { + handleMobileButtonActionCommand(actionToShortPressRef.current, true) + handleMobileButtonActionCommand(actionToShortPressRef.current, false) + wasShortPressHandled = true + } + } + + if (!wasShortPressHandled) { + if (actionHold) { + if (typeof actionHold === 'object' && 'command' in actionHold) { + const config = actionHold + if (config.longPressAction) { + if (actionToShortPressRef.current === null) { + if (typeof config.longPressAction === 'string') { + handleMobileButtonActionCommand(config.longPressAction, false) + } + } + } else { + handleMobileButtonActionCommand(config.command, false) + } + } else if (action) { + if (actionToShortPressRef.current === null) { + handleMobileButtonActionCommand(actionHold, false) + } + } else { + handleMobileButtonActionCommand(actionHold, false) + } + } else if (action) { + handleMobileButtonActionCommand(action, false) + } + } + actionToShortPressRef.current = null + } + + return ( +
    + {label} +
    + ) + }) + } // ios note: just don't use