diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78de9b773..c132fa563 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: - name: Install pnpm run: npm i -g pnpm - run: pnpm install - - run: pnpm build + - run: pnpm check-build - run: nohup pnpm prod-start & - run: nohup node cypress/minecraft-server.mjs & - uses: cypress-io/github-action@v5 diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 9ba981108..bc5d5ecd1 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -14,11 +14,14 @@ jobs: ( contains(github.event.comment.body, '/deploy') ) + permissions: + pull-requests: write steps: - name: Checkout uses: actions/checkout@v2 with: fetch-depth: 0 + ref: refs/pull/${{ github.event.issue.number }}/head - name: Install Global Dependencies run: npm install --global vercel pnpm - name: Pull Vercel Environment Information @@ -26,4 +29,11 @@ jobs: - name: Build Project Artifacts run: vercel build --token=${{ secrets.VERCEL_TOKEN }} - name: Deploy Project Artifacts to Vercel - run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} + uses: mathiasvr/command-output@v2.0.0 + with: + run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} + id: deploy + - uses: mshick/add-pr-comment@v2 + with: + message: | + Deployed to Vercel Preview: ${{ steps.deploy.outputs.stdout }} diff --git a/cypress/integration/__image_snapshots__/superflat-world #0.png b/cypress/integration/__image_snapshots__/superflat-world #0.png index 58f2bd21d..dcddd3ad7 100644 Binary files a/cypress/integration/__image_snapshots__/superflat-world #0.png and b/cypress/integration/__image_snapshots__/superflat-world #0.png differ diff --git a/cypress/integration/index.spec.ts b/cypress/integration/index.spec.ts index 31a113ab6..c4f239178 100644 --- a/cypress/integration/index.spec.ts +++ b/cypress/integration/index.spec.ts @@ -1,65 +1,78 @@ /// +import type { AppOptions } from '../../src/optionsStorage' -const setLocalStorageSettings = () => { +const cleanVisit = () => { + window.localStorage.clear() + visit() +} + +const visit = (url = '/') => { window.localStorage.cypress = 'true' - window.localStorage.server = 'localhost' + cy.visit(url) } // todo use ssl +const compareRenderedFlatWorld = () => { + // wait for render + // cy.wait(6000) + // cy.get('body').toMatchImageSnapshot({ + // name: 'superflat-world', + // }) +} + +const testWorldLoad = () => { + cy.document().then({ timeout: 20_000, }, doc => { + return new Cypress.Promise(resolve => { + doc.addEventListener('cypress-world-ready', resolve) + }) + }).then(() => { + compareRenderedFlatWorld() + }) +} + +const setOptions = (options: Partial) => { + cy.window().then(win => { + Object.assign(win['options'], options) + }) +} + it('Loads & renders singleplayer', () => { - cy.visit('/') - window.localStorage.clear() - window.localStorage.setItem('renderDistance', '2') - window.localStorage.setItem('options', JSON.stringify({ + cleanVisit() + setOptions({ localServerOptions: { generation: { name: 'superflat', options: { seed: 250869072 } - } - } - })) - setLocalStorageSettings() - cy.get('#title-screen').find('[data-test-id="singleplayer-button"]', { includeShadowDom: true, }).click() - // todo implement load event - cy.wait(12000) - cy.get('body').toMatchImageSnapshot({ - name: 'superflat-world', + }, + }, + renderDistance: 2 }) + cy.get('#title-screen').find('[data-test-id="singleplayer-button"]', { includeShadowDom: true, }).click() + testWorldLoad() }) it('Joins to server', () => { - cy.visit('/') - setLocalStorageSettings() + // visit('/?version=1.16.1') + window.localStorage.version = '1.16.1' + visit() // todo replace with data-test cy.get('#title-screen').find('[data-test-id="connect-screen-button"]', { includeShadowDom: true, }).click() cy.get('input#serverip', { includeShadowDom: true, }).clear().focus().type('localhost') cy.get('[data-test-id="connect-to-server"]', { includeShadowDom: true, }).click() - // todo implement load event - cy.wait(12000) - cy.get('body').toMatchImageSnapshot({ - name: 'superflat-world', - }) + testWorldLoad() }) it('Loads & renders zip world', () => { - cy.visit('/') - setLocalStorageSettings() + cleanVisit() cy.get('#title-screen').find('[data-test-id="select-file-folder"]', { includeShadowDom: true, }).click({ shiftKey: true }) cy.get('input[type="file"]').selectFile('cypress/superflat.zip', { force: true }) - // todo implement load event - cy.wait(12000) - cy.get('body').toMatchImageSnapshot({ - name: 'superflat-world', - }) + testWorldLoad() }) it.skip('Performance test', () => { - cy.visit('/') - window.localStorage.cypress = 'true' - window.localStorage.setItem('renderDistance', '6') - cy.get('#title-screen').find('.menu > div:nth-child(2) > pmui-button:nth-child(1)', { includeShadowDom: true, }).selectFile('worlds') - // -2 85 24 + // select that world + // from -2 85 24 // await bot.loadPlugin(pathfinder.pathfinder) // bot.pathfinder.goto(new pathfinder.goals.GoalXZ(28, -28)) }) diff --git a/package.json b/package.json index bebbd01ef..05adc7c26 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "scripts": { "start": "node scripts/build.js copyFilesDev && node scripts/prepareData.mjs && node esbuild.mjs --watch", "start-watch-script": "nodemon -w esbuild.mjs esbuild.mjs", - "build": "node scripts/build.js copyFiles && node scripts/prepareData.mjs && node esbuild.mjs --minify --prod", + "build": "node scripts/build.js copyFiles && node scripts/prepareData.mjs -f && node esbuild.mjs --minify --prod", + "check-build": "tsc && pnpm build", "watch": "node scripts/build.js copyFilesDev && webpack serve --config webpack.dev.js --progress", "test:cypress": "cypress run", "test:e2e": "start-test http-get://localhost:8080 test:cypress", @@ -31,9 +32,10 @@ "browserfs": "github:zardoy/browserfs#build", "compression": "^1.7.4", "cypress-plugin-snapshots": "^1.4.4", + "debug": "^4.3.4", "diamond-square": "^1.2.0", "eruda": "^3.0.1", - "esbuild": "^0.19.2", + "esbuild": "^0.19.3", "esbuild-loader": "^4.0.0", "esbuild-plugin-polyfill-node": "^0.3.0", "express": "^4.18.2", @@ -92,6 +94,7 @@ "style-loader": "^3.3.3", "three": "0.128.0", "timers-browserify": "^2.0.12", + "typescript": "^5.2.2", "url-loader": "^4.1.1", "use-typed-event-listener": "^4.0.2", "vite": "^4.4.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3fc6960ba..5007cd892 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,6 +48,9 @@ importers: cypress-plugin-snapshots: specifier: ^1.4.4 version: 1.4.4(cypress@9.5.4) + debug: + specifier: ^4.3.4 + version: 4.3.4(supports-color@8.1.1) diamond-square: specifier: ^1.2.0 version: 1.2.0 @@ -55,14 +58,14 @@ importers: specifier: ^3.0.1 version: 3.0.1 esbuild: - specifier: ^0.19.2 - version: 0.19.2 + specifier: ^0.19.3 + version: 0.19.3 esbuild-loader: specifier: ^4.0.0 version: 4.0.0(webpack@5.88.2) esbuild-plugin-polyfill-node: specifier: ^0.3.0 - version: 0.3.0(esbuild@0.19.2) + version: 0.3.0(esbuild@0.19.3) express: specifier: ^4.18.2 version: 4.18.2 @@ -147,7 +150,7 @@ importers: version: 1.0.0 contro-max: specifier: ^0.1.1 - version: 0.1.1 + version: 0.1.1(typescript@5.2.2) copy-webpack-plugin: specifier: ^11.0.0 version: 11.0.0(webpack@5.88.2) @@ -177,7 +180,7 @@ importers: version: 1.7.0 http-server: specifier: ^14.1.1 - version: 14.1.1 + version: 14.1.1(debug@4.3.4) https-browserify: specifier: ^1.0.0 version: 1.0.0 @@ -226,18 +229,21 @@ importers: timers-browserify: specifier: ^2.0.12 version: 2.0.12 + typescript: + specifier: ^5.2.2 + version: 5.2.2 url-loader: specifier: ^4.1.1 version: 4.1.1(webpack@5.88.2) use-typed-event-listener: specifier: ^4.0.2 - version: 4.0.2(react@18.2.0) + version: 4.0.2(react@18.2.0)(typescript@5.2.2) vite: specifier: ^4.4.9 version: 4.4.9 webpack: specifier: ^5.88.2 - version: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + version: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) webpack-cli: specifier: ^5.1.4 version: 5.1.4(webpack-dev-server@4.15.1)(webpack@5.88.2) @@ -246,7 +252,7 @@ importers: version: 6.1.1(webpack@5.88.2) webpack-dev-server: specifier: ^4.15.1 - version: 4.15.1(webpack-cli@5.1.4)(webpack@5.88.2) + version: 4.15.1(debug@4.3.4)(webpack-cli@5.1.4)(webpack@5.88.2) webpack-merge: specifier: ^5.9.0 version: 5.9.0 @@ -273,7 +279,7 @@ importers: version: 3.45.0 prismarine-block: specifier: github:zardoy/prismarine-block#next-era - version: github.com/zardoy/prismarine-block/100f3e3be7927b8144e19a71c8d06f6218021a02 + version: github.com/zardoy/prismarine-block/753cf1fe507f7647063c69d5c124d40f85b29cc2 prismarine-chunk: specifier: ^1.22.0 version: 1.35.0(minecraft-data@3.45.0) @@ -316,7 +322,7 @@ importers: version: 27.0.4(canvas@2.11.2) jest-puppeteer: specifier: ^6.0.0 - version: 6.0.0(puppeteer@16.0.0) + version: 6.0.0(debug@4.3.4)(puppeteer@16.0.0) minecraft-assets: specifier: ^1.9.0 version: 1.9.0 @@ -349,7 +355,7 @@ importers: version: 17.0.0 webpack: specifier: ^5.10.2 - version: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + version: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) webpack-cli: specifier: ^5.1.1 version: 5.1.4(webpack-dev-server@4.15.1)(webpack@5.88.2) @@ -1669,8 +1675,8 @@ packages: dev: true optional: true - /@esbuild/android-arm64@0.19.2: - resolution: {integrity: sha512-lsB65vAbe90I/Qe10OjkmrdxSX4UJDjosDgb8sZUKcg3oefEuW2OT2Vozz8ef7wrJbMcmhvCC+hciF8jY/uAkw==} + /@esbuild/android-arm64@0.19.3: + resolution: {integrity: sha512-w+Akc0vv5leog550kjJV9Ru+MXMR2VuMrui3C61mnysim0gkFCPOUTAfzTP0qX+HpN9Syu3YA3p1hf3EPqObRw==} engines: {node: '>=12'} cpu: [arm64] os: [android] @@ -1686,8 +1692,8 @@ packages: dev: true optional: true - /@esbuild/android-arm@0.19.2: - resolution: {integrity: sha512-tM8yLeYVe7pRyAu9VMi/Q7aunpLwD139EY1S99xbQkT4/q2qa6eA4ige/WJQYdJ8GBL1K33pPFhPfPdJ/WzT8Q==} + /@esbuild/android-arm@0.19.3: + resolution: {integrity: sha512-Lemgw4io4VZl9GHJmjiBGzQ7ONXRfRPHcUEerndjwiSkbxzrpq0Uggku5MxxrXdwJ+pTj1qyw4jwTu7hkPsgIA==} engines: {node: '>=12'} cpu: [arm] os: [android] @@ -1703,8 +1709,8 @@ packages: dev: true optional: true - /@esbuild/android-x64@0.19.2: - resolution: {integrity: sha512-qK/TpmHt2M/Hg82WXHRc/W/2SGo/l1thtDHZWqFq7oi24AjZ4O/CpPSu6ZuYKFkEgmZlFoa7CooAyYmuvnaG8w==} + /@esbuild/android-x64@0.19.3: + resolution: {integrity: sha512-FKQJKkK5MXcBHoNZMDNUAg1+WcZlV/cuXrWCoGF/TvdRiYS4znA0m5Il5idUwfxrE20bG/vU1Cr5e1AD6IEIjQ==} engines: {node: '>=12'} cpu: [x64] os: [android] @@ -1720,8 +1726,8 @@ packages: dev: true optional: true - /@esbuild/darwin-arm64@0.19.2: - resolution: {integrity: sha512-Ora8JokrvrzEPEpZO18ZYXkH4asCdc1DLdcVy8TGf5eWtPO1Ie4WroEJzwI52ZGtpODy3+m0a2yEX9l+KUn0tA==} + /@esbuild/darwin-arm64@0.19.3: + resolution: {integrity: sha512-kw7e3FXU+VsJSSSl2nMKvACYlwtvZB8RUIeVShIEY6PVnuZ3c9+L9lWB2nWeeKWNNYDdtL19foCQ0ZyUL7nqGw==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] @@ -1737,8 +1743,8 @@ packages: dev: true optional: true - /@esbuild/darwin-x64@0.19.2: - resolution: {integrity: sha512-tP+B5UuIbbFMj2hQaUr6EALlHOIOmlLM2FK7jeFBobPy2ERdohI4Ka6ZFjZ1ZYsrHE/hZimGuU90jusRE0pwDw==} + /@esbuild/darwin-x64@0.19.3: + resolution: {integrity: sha512-tPfZiwF9rO0jW6Jh9ipi58N5ZLoSjdxXeSrAYypy4psA2Yl1dAMhM71KxVfmjZhJmxRjSnb29YlRXXhh3GqzYw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] @@ -1754,8 +1760,8 @@ packages: dev: true optional: true - /@esbuild/freebsd-arm64@0.19.2: - resolution: {integrity: sha512-YbPY2kc0acfzL1VPVK6EnAlig4f+l8xmq36OZkU0jzBVHcOTyQDhnKQaLzZudNJQyymd9OqQezeaBgkTGdTGeQ==} + /@esbuild/freebsd-arm64@0.19.3: + resolution: {integrity: sha512-ERDyjOgYeKe0Vrlr1iLrqTByB026YLPzTytDTz1DRCYM+JI92Dw2dbpRHYmdqn6VBnQ9Bor6J8ZlNwdZdxjlSg==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] @@ -1771,8 +1777,8 @@ packages: dev: true optional: true - /@esbuild/freebsd-x64@0.19.2: - resolution: {integrity: sha512-nSO5uZT2clM6hosjWHAsS15hLrwCvIWx+b2e3lZ3MwbYSaXwvfO528OF+dLjas1g3bZonciivI8qKR/Hm7IWGw==} + /@esbuild/freebsd-x64@0.19.3: + resolution: {integrity: sha512-nXesBZ2Ad1qL+Rm3crN7NmEVJ5uvfLFPLJev3x1j3feCQXfAhoYrojC681RhpdOph8NsvKBBwpYZHR7W0ifTTA==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] @@ -1788,8 +1794,8 @@ packages: dev: true optional: true - /@esbuild/linux-arm64@0.19.2: - resolution: {integrity: sha512-ig2P7GeG//zWlU0AggA3pV1h5gdix0MA3wgB+NsnBXViwiGgY77fuN9Wr5uoCrs2YzaYfogXgsWZbm+HGr09xg==} + /@esbuild/linux-arm64@0.19.3: + resolution: {integrity: sha512-qXvYKmXj8GcJgWq3aGvxL/JG1ZM3UR272SdPU4QSTzD0eymrM7leiZH77pvY3UetCy0k1xuXZ+VPvoJNdtrsWQ==} engines: {node: '>=12'} cpu: [arm64] os: [linux] @@ -1805,8 +1811,8 @@ packages: dev: true optional: true - /@esbuild/linux-arm@0.19.2: - resolution: {integrity: sha512-Odalh8hICg7SOD7XCj0YLpYCEc+6mkoq63UnExDCiRA2wXEmGlK5JVrW50vZR9Qz4qkvqnHcpH+OFEggO3PgTg==} + /@esbuild/linux-arm@0.19.3: + resolution: {integrity: sha512-zr48Cg/8zkzZCzDHNxXO/89bf9e+r4HtzNUPoz4GmgAkF1gFAFmfgOdCbR8zMbzFDGb1FqBBhdXUpcTQRYS1cQ==} engines: {node: '>=12'} cpu: [arm] os: [linux] @@ -1822,8 +1828,8 @@ packages: dev: true optional: true - /@esbuild/linux-ia32@0.19.2: - resolution: {integrity: sha512-mLfp0ziRPOLSTek0Gd9T5B8AtzKAkoZE70fneiiyPlSnUKKI4lp+mGEnQXcQEHLJAcIYDPSyBvsUbKUG2ri/XQ==} + /@esbuild/linux-ia32@0.19.3: + resolution: {integrity: sha512-7XlCKCA0nWcbvYpusARWkFjRQNWNGlt45S+Q18UeS///K6Aw8bB2FKYe9mhVWy/XLShvCweOLZPrnMswIaDXQA==} engines: {node: '>=12'} cpu: [ia32] os: [linux] @@ -1839,8 +1845,8 @@ packages: dev: true optional: true - /@esbuild/linux-loong64@0.19.2: - resolution: {integrity: sha512-hn28+JNDTxxCpnYjdDYVMNTR3SKavyLlCHHkufHV91fkewpIyQchS1d8wSbmXhs1fiYDpNww8KTFlJ1dHsxeSw==} + /@esbuild/linux-loong64@0.19.3: + resolution: {integrity: sha512-qGTgjweER5xqweiWtUIDl9OKz338EQqCwbS9c2Bh5jgEH19xQ1yhgGPNesugmDFq+UUSDtWgZ264st26b3de8A==} engines: {node: '>=12'} cpu: [loong64] os: [linux] @@ -1856,8 +1862,8 @@ packages: dev: true optional: true - /@esbuild/linux-mips64el@0.19.2: - resolution: {integrity: sha512-KbXaC0Sejt7vD2fEgPoIKb6nxkfYW9OmFUK9XQE4//PvGIxNIfPk1NmlHmMg6f25x57rpmEFrn1OotASYIAaTg==} + /@esbuild/linux-mips64el@0.19.3: + resolution: {integrity: sha512-gy1bFskwEyxVMFRNYSvBauDIWNggD6pyxUksc0MV9UOBD138dKTzr8XnM2R4mBsHwVzeuIH8X5JhmNs2Pzrx+A==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] @@ -1873,8 +1879,8 @@ packages: dev: true optional: true - /@esbuild/linux-ppc64@0.19.2: - resolution: {integrity: sha512-dJ0kE8KTqbiHtA3Fc/zn7lCd7pqVr4JcT0JqOnbj4LLzYnp+7h8Qi4yjfq42ZlHfhOCM42rBh0EwHYLL6LEzcw==} + /@esbuild/linux-ppc64@0.19.3: + resolution: {integrity: sha512-UrYLFu62x1MmmIe85rpR3qou92wB9lEXluwMB/STDzPF9k8mi/9UvNsG07Tt9AqwPQXluMQ6bZbTzYt01+Ue5g==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] @@ -1890,8 +1896,8 @@ packages: dev: true optional: true - /@esbuild/linux-riscv64@0.19.2: - resolution: {integrity: sha512-7Z/jKNFufZ/bbu4INqqCN6DDlrmOTmdw6D0gH+6Y7auok2r02Ur661qPuXidPOJ+FSgbEeQnnAGgsVynfLuOEw==} + /@esbuild/linux-riscv64@0.19.3: + resolution: {integrity: sha512-9E73TfyMCbE+1AwFOg3glnzZ5fBAFK4aawssvuMgCRqCYzE0ylVxxzjEfut8xjmKkR320BEoMui4o/t9KA96gA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] @@ -1907,8 +1913,8 @@ packages: dev: true optional: true - /@esbuild/linux-s390x@0.19.2: - resolution: {integrity: sha512-U+RinR6aXXABFCcAY4gSlv4CL1oOVvSSCdseQmGO66H+XyuQGZIUdhG56SZaDJQcLmrSfRmx5XZOWyCJPRqS7g==} + /@esbuild/linux-s390x@0.19.3: + resolution: {integrity: sha512-LlmsbuBdm1/D66TJ3HW6URY8wO6IlYHf+ChOUz8SUAjVTuaisfuwCOAgcxo3Zsu3BZGxmI7yt//yGOxV+lHcEA==} engines: {node: '>=12'} cpu: [s390x] os: [linux] @@ -1924,8 +1930,8 @@ packages: dev: true optional: true - /@esbuild/linux-x64@0.19.2: - resolution: {integrity: sha512-oxzHTEv6VPm3XXNaHPyUTTte+3wGv7qVQtqaZCrgstI16gCuhNOtBXLEBkBREP57YTd68P0VgDgG73jSD8bwXQ==} + /@esbuild/linux-x64@0.19.3: + resolution: {integrity: sha512-ogV0+GwEmvwg/8ZbsyfkYGaLACBQWDvO0Kkh8LKBGKj9Ru8VM39zssrnu9Sxn1wbapA2qNS6BiLdwJZGouyCwQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] @@ -1941,8 +1947,8 @@ packages: dev: true optional: true - /@esbuild/netbsd-x64@0.19.2: - resolution: {integrity: sha512-WNa5zZk1XpTTwMDompZmvQLHszDDDN7lYjEHCUmAGB83Bgs20EMs7ICD+oKeT6xt4phV4NDdSi/8OfjPbSbZfQ==} + /@esbuild/netbsd-x64@0.19.3: + resolution: {integrity: sha512-o1jLNe4uzQv2DKXMlmEzf66Wd8MoIhLNO2nlQBHLtWyh2MitDG7sMpfCO3NTcoTMuqHjfufgUQDFRI5C+xsXQw==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] @@ -1958,8 +1964,8 @@ packages: dev: true optional: true - /@esbuild/openbsd-x64@0.19.2: - resolution: {integrity: sha512-S6kI1aT3S++Dedb7vxIuUOb3oAxqxk2Rh5rOXOTYnzN8JzW1VzBd+IqPiSpgitu45042SYD3HCoEyhLKQcDFDw==} + /@esbuild/openbsd-x64@0.19.3: + resolution: {integrity: sha512-AZJCnr5CZgZOdhouLcfRdnk9Zv6HbaBxjcyhq0StNcvAdVZJSKIdOiPB9az2zc06ywl0ePYJz60CjdKsQacp5Q==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] @@ -1975,8 +1981,8 @@ packages: dev: true optional: true - /@esbuild/sunos-x64@0.19.2: - resolution: {integrity: sha512-VXSSMsmb+Z8LbsQGcBMiM+fYObDNRm8p7tkUDMPG/g4fhFX5DEFmjxIEa3N8Zr96SjsJ1woAhF0DUnS3MF3ARw==} + /@esbuild/sunos-x64@0.19.3: + resolution: {integrity: sha512-Acsujgeqg9InR4glTRvLKGZ+1HMtDm94ehTIHKhJjFpgVzZG9/pIcWW/HA/DoMfEyXmANLDuDZ2sNrWcjq1lxw==} engines: {node: '>=12'} cpu: [x64] os: [sunos] @@ -1992,8 +1998,8 @@ packages: dev: true optional: true - /@esbuild/win32-arm64@0.19.2: - resolution: {integrity: sha512-5NayUlSAyb5PQYFAU9x3bHdsqB88RC3aM9lKDAz4X1mo/EchMIT1Q+pSeBXNgkfNmRecLXA0O8xP+x8V+g/LKg==} + /@esbuild/win32-arm64@0.19.3: + resolution: {integrity: sha512-FSrAfjVVy7TifFgYgliiJOyYynhQmqgPj15pzLyJk8BUsnlWNwP/IAy6GAiB1LqtoivowRgidZsfpoYLZH586A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] @@ -2009,8 +2015,8 @@ packages: dev: true optional: true - /@esbuild/win32-ia32@0.19.2: - resolution: {integrity: sha512-47gL/ek1v36iN0wL9L4Q2MFdujR0poLZMJwhO2/N3gA89jgHp4MR8DKCmwYtGNksbfJb9JoTtbkoe6sDhg2QTA==} + /@esbuild/win32-ia32@0.19.3: + resolution: {integrity: sha512-xTScXYi12xLOWZ/sc5RBmMN99BcXp/eEf7scUC0oeiRoiT5Vvo9AycuqCp+xdpDyAU+LkrCqEpUS9fCSZF8J3Q==} engines: {node: '>=12'} cpu: [ia32] os: [win32] @@ -2026,8 +2032,8 @@ packages: dev: true optional: true - /@esbuild/win32-x64@0.19.2: - resolution: {integrity: sha512-tcuhV7ncXBqbt/Ybf0IyrMcwVOAPDckMK9rXNHtF17UTK18OKLpg08glminN06pt2WCoALhXdLfSPbVvK/6fxw==} + /@esbuild/win32-x64@0.19.3: + resolution: {integrity: sha512-FbUN+0ZRXsypPyWE2IwIkVjDkDnJoMJARWOcFZn4KPPli+QnKqF0z1anvfaYe3ev5HFCpRDLLBDHyOALLppWHw==} engines: {node: '>=12'} cpu: [x64] os: [win32] @@ -2868,8 +2874,8 @@ packages: react-refresh: 0.14.0 schema-utils: 3.3.0 source-map: 0.7.4 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) - webpack-dev-server: 4.15.1(webpack-cli@5.1.4)(webpack@5.88.2) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) + webpack-dev-server: 4.15.1(debug@4.3.4)(webpack-cli@5.1.4)(webpack@5.88.2) dev: false /@popperjs/core@2.11.8: @@ -3020,7 +3026,7 @@ packages: /@types/connect@3.4.35: resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} dependencies: - '@types/node': 20.5.7 + '@types/node': 20.6.4 /@types/cookie@0.4.1: resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} @@ -3028,7 +3034,7 @@ packages: /@types/cors@2.8.13: resolution: {integrity: sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==} dependencies: - '@types/node': 20.6.2 + '@types/node': 20.6.4 /@types/eslint-scope@3.7.4: resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==} @@ -3134,6 +3140,10 @@ packages: /@types/node@20.6.2: resolution: {integrity: sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw==} + dev: true + + /@types/node@20.6.4: + resolution: {integrity: sha512-nU6d9MPY0NBUMiE/nXd2IIoC4OLvsLpwAjheoAeuzgvDZA1Cb10QYg+91AF6zQiKWRN5i1m07x6sMe0niBznoQ==} /@types/parse-json@4.0.0: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} @@ -3168,13 +3178,13 @@ packages: /@types/readable-stream@4.0.2: resolution: {integrity: sha512-hhzOsMEISZ+mX1l+01F0duYt9wHEbCGmjARed0PcQoVS5zAdu7u5YbWYuNGhw09M1MgGr3kfsto+ut/MnAdKqA==} dependencies: - '@types/node': 20.6.2 + '@types/node': 20.6.4 safe-buffer: 5.1.2 /@types/resolve@1.17.1: resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} dependencies: - '@types/node': 20.6.2 + '@types/node': 20.6.4 /@types/retry@0.12.0: resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} @@ -3186,7 +3196,7 @@ packages: resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==} dependencies: '@types/mime': 1.3.2 - '@types/node': 20.5.7 + '@types/node': 20.6.4 /@types/serve-index@1.9.1: resolution: {integrity: sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==} @@ -3245,7 +3255,7 @@ packages: resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} requiresBuild: true dependencies: - '@types/node': 20.5.7 + '@types/node': 20.6.4 optional: true /@webassemblyjs/ast@1.11.6: @@ -3346,7 +3356,7 @@ packages: webpack: 5.x.x webpack-cli: 5.x.x dependencies: - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@4.15.1)(webpack@5.88.2) /@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.88.2): @@ -3356,7 +3366,7 @@ packages: webpack: 5.x.x webpack-cli: 5.x.x dependencies: - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@4.15.1)(webpack@5.88.2) /@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack-dev-server@4.15.1)(webpack@5.88.2): @@ -3370,9 +3380,9 @@ packages: webpack-dev-server: optional: true dependencies: - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@4.15.1)(webpack@5.88.2) - webpack-dev-server: 4.15.1(webpack-cli@5.1.4)(webpack@5.88.2) + webpack-dev-server: 4.15.1(debug@4.3.4)(webpack-cli@5.1.4)(webpack@5.88.2) /@xboxreplay/errors@0.1.0: resolution: {integrity: sha512-Tgz1d/OIPDWPeyOvuL5+aai5VCcqObhPnlI3skQuf80GVF3k1I0lPCnGC+8Cm5PV9aLBT5m8qPcJoIUQ2U4y9g==} @@ -3805,11 +3815,11 @@ packages: /axios@0.21.4(debug@4.3.4): resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} dependencies: - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.3(debug@4.3.4) transitivePeerDependencies: - debug - /axios@0.25.0: + /axios@0.25.0(debug@4.3.4): resolution: {integrity: sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==} dependencies: follow-redirects: 1.15.2(debug@4.3.4) @@ -4386,7 +4396,7 @@ packages: webpack: '>=4.0.0 <6.0.0' dependencies: del: 4.1.1 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) dev: true /cli-cursor@3.1.0: @@ -4589,14 +4599,14 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} - /contro-max@0.1.1: + /contro-max@0.1.1(typescript@5.2.2): resolution: {integrity: sha512-H+bzJWxiuxu98Tz8iGs1occMkRlr9fOzfOKeflVU8bD5teAEiJu8zjVnNSbweLQIR+Vhdynygv18N69t97rVAw==} dependencies: emittery: 0.10.2 lodash-es: 4.17.21 optionalDependencies: react: 17.0.2 - use-typed-event-listener: 4.0.2(react@17.0.2) + use-typed-event-listener: 4.0.2(react@17.0.2)(typescript@5.2.2) transitivePeerDependencies: - typescript dev: true @@ -4633,7 +4643,7 @@ packages: normalize-path: 3.0.0 schema-utils: 4.2.0 serialize-javascript: 6.0.1 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) dev: true /core-js-compat@3.32.1: @@ -4775,7 +4785,7 @@ packages: postcss-modules-values: 4.0.0(postcss@8.4.28) postcss-value-parser: 4.2.0 semver: 7.5.4 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) dev: true /css-select@4.3.0: @@ -5366,7 +5376,7 @@ packages: dependencies: '@types/cookie': 0.4.1 '@types/cors': 2.8.13 - '@types/node': 20.6.2 + '@types/node': 20.6.4 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.4.2 @@ -5524,20 +5534,20 @@ packages: peerDependencies: webpack: ^4.40.0 || ^5.0.0 dependencies: - esbuild: 0.19.2 + esbuild: 0.19.3 get-tsconfig: 4.7.0 loader-utils: 2.0.4 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) webpack-sources: 1.4.3 dev: false - /esbuild-plugin-polyfill-node@0.3.0(esbuild@0.19.2): + /esbuild-plugin-polyfill-node@0.3.0(esbuild@0.19.3): resolution: {integrity: sha512-SHG6CKUfWfYyYXGpW143NEZtcVVn8S/WHcEOxk62LuDXnY4Zpmc+WmxJKN6GMTgTClXJXhEM5KQlxKY6YjbucQ==} peerDependencies: esbuild: '*' dependencies: '@jspm/core': 2.0.1 - esbuild: 0.19.2 + esbuild: 0.19.3 import-meta-resolve: 3.0.0 dev: false @@ -5571,34 +5581,34 @@ packages: '@esbuild/win32-x64': 0.18.20 dev: true - /esbuild@0.19.2: - resolution: {integrity: sha512-G6hPax8UbFakEj3hWO0Vs52LQ8k3lnBhxZWomUJDxfz3rZTLqF5k/FCzuNdLx2RbpBiQQF9H9onlDDH1lZsnjg==} + /esbuild@0.19.3: + resolution: {integrity: sha512-UlJ1qUUA2jL2nNib1JTSkifQTcYTroFqRjwCFW4QYEKEsixXD5Tik9xML7zh2gTxkYTBKGHNH9y7txMwVyPbjw==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/android-arm': 0.19.2 - '@esbuild/android-arm64': 0.19.2 - '@esbuild/android-x64': 0.19.2 - '@esbuild/darwin-arm64': 0.19.2 - '@esbuild/darwin-x64': 0.19.2 - '@esbuild/freebsd-arm64': 0.19.2 - '@esbuild/freebsd-x64': 0.19.2 - '@esbuild/linux-arm': 0.19.2 - '@esbuild/linux-arm64': 0.19.2 - '@esbuild/linux-ia32': 0.19.2 - '@esbuild/linux-loong64': 0.19.2 - '@esbuild/linux-mips64el': 0.19.2 - '@esbuild/linux-ppc64': 0.19.2 - '@esbuild/linux-riscv64': 0.19.2 - '@esbuild/linux-s390x': 0.19.2 - '@esbuild/linux-x64': 0.19.2 - '@esbuild/netbsd-x64': 0.19.2 - '@esbuild/openbsd-x64': 0.19.2 - '@esbuild/sunos-x64': 0.19.2 - '@esbuild/win32-arm64': 0.19.2 - '@esbuild/win32-ia32': 0.19.2 - '@esbuild/win32-x64': 0.19.2 + '@esbuild/android-arm': 0.19.3 + '@esbuild/android-arm64': 0.19.3 + '@esbuild/android-x64': 0.19.3 + '@esbuild/darwin-arm64': 0.19.3 + '@esbuild/darwin-x64': 0.19.3 + '@esbuild/freebsd-arm64': 0.19.3 + '@esbuild/freebsd-x64': 0.19.3 + '@esbuild/linux-arm': 0.19.3 + '@esbuild/linux-arm64': 0.19.3 + '@esbuild/linux-ia32': 0.19.3 + '@esbuild/linux-loong64': 0.19.3 + '@esbuild/linux-mips64el': 0.19.3 + '@esbuild/linux-ppc64': 0.19.3 + '@esbuild/linux-riscv64': 0.19.3 + '@esbuild/linux-s390x': 0.19.3 + '@esbuild/linux-x64': 0.19.3 + '@esbuild/netbsd-x64': 0.19.3 + '@esbuild/openbsd-x64': 0.19.3 + '@esbuild/sunos-x64': 0.19.3 + '@esbuild/win32-arm64': 0.19.3 + '@esbuild/win32-ia32': 0.19.3 + '@esbuild/win32-x64': 0.19.3 /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} @@ -6283,6 +6293,17 @@ packages: dependencies: debug: 4.3.4(supports-color@8.1.1) + /follow-redirects@1.15.3(debug@4.3.4): + resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dependencies: + debug: 4.3.4(supports-color@8.1.1) + /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: @@ -6784,7 +6805,7 @@ packages: lodash: 4.17.21 pretty-error: 4.0.0 tapable: 2.2.1 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) dev: true /htmlparser2@6.1.0: @@ -6839,7 +6860,7 @@ packages: - supports-color dev: true - /http-proxy-middleware@2.0.6(@types/express@4.17.17): + /http-proxy-middleware@2.0.6(@types/express@4.17.17)(debug@4.3.4): resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} engines: {node: '>=12.0.0'} peerDependencies: @@ -6850,14 +6871,14 @@ packages: dependencies: '@types/express': 4.17.17 '@types/http-proxy': 1.17.11 - http-proxy: 1.18.1 + http-proxy: 1.18.1(debug@4.3.4) is-glob: 4.0.3 is-plain-obj: 3.0.0 micromatch: 4.0.5 transitivePeerDependencies: - debug - /http-proxy@1.18.1: + /http-proxy@1.18.1(debug@4.3.4): resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} engines: {node: '>=8.0.0'} dependencies: @@ -6867,7 +6888,7 @@ packages: transitivePeerDependencies: - debug - /http-server@14.1.1: + /http-server@14.1.1(debug@4.3.4): resolution: {integrity: sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==} engines: {node: '>=12'} hasBin: true @@ -6877,7 +6898,7 @@ packages: corser: 2.0.1 he: 1.2.0 html-encoding-sniffer: 3.0.0 - http-proxy: 1.18.1 + http-proxy: 1.18.1(debug@4.3.4) mime: 1.6.0 minimist: 1.2.8 opener: 1.5.2 @@ -7529,7 +7550,7 @@ packages: - utf-8-validate dev: true - /jest-dev-server@6.2.0: + /jest-dev-server@6.2.0(debug@4.3.4): resolution: {integrity: sha512-ZWh8CuvxwjhYfvw4tGeftziqIvw/26R6AG3OTgNTQeXul8aZz48RQjDpnlDwnWX53jxJJl9fcigqIdSU5lYZuw==} dependencies: chalk: 4.1.2 @@ -7538,7 +7559,7 @@ packages: prompts: 2.4.2 spawnd: 6.2.0 tree-kill: 1.2.2 - wait-on: 6.0.1 + wait-on: 6.0.1(debug@4.3.4) transitivePeerDependencies: - debug - supports-color @@ -7602,12 +7623,12 @@ packages: jest-util: 27.5.1 dev: true - /jest-environment-puppeteer@6.2.0: + /jest-environment-puppeteer@6.2.0(debug@4.3.4): resolution: {integrity: sha512-a/oSu6dO9D+XoDDe3ZY/0Sk79Jl2FcJl7Q0D+3x22l1eWNOYe4ikXnPGhtmNZ3mJIpuAVIX6LytA8EraOk/aqQ==} dependencies: chalk: 4.1.2 cwd: 0.10.0 - jest-dev-server: 6.2.0 + jest-dev-server: 6.2.0(debug@4.3.4) jest-environment-node: 27.5.1 merge-deep: 3.0.3 transitivePeerDependencies: @@ -7718,13 +7739,13 @@ packages: jest-resolve: 27.5.1 dev: true - /jest-puppeteer@6.0.0(puppeteer@16.0.0): + /jest-puppeteer@6.0.0(debug@4.3.4)(puppeteer@16.0.0): resolution: {integrity: sha512-dgZJdBxRafMRqHFRxnsqLDbuJcOcdgaJlg2PLoMxgPy9nQZTrtG9ezwQsRf1poSaLbZGMAL2JVS907MBCYPEJw==} peerDependencies: puppeteer: '>= 1.5.0' dependencies: expect-puppeteer: 6.1.1 - jest-environment-puppeteer: 6.2.0 + jest-environment-puppeteer: 6.2.0(debug@4.3.4) puppeteer: 16.0.0 transitivePeerDependencies: - debug @@ -7904,7 +7925,7 @@ packages: resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 20.6.2 + '@types/node': 20.6.4 merge-stream: 2.0.0 supports-color: 7.2.0 @@ -8355,7 +8376,7 @@ packages: webpack: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.1.0 dependencies: lodash: 4.17.21 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) dev: true /lodash.compact@3.0.1: @@ -8632,7 +8653,7 @@ packages: resolution: {integrity: sha512-HAXakZrJRb1UC+5dv8EaDrqjW3ZnBnBk3nkb6x/YWyhHCUKn/E7VU0FO+UN9whuqPlkSaVumEdXJdydE6lSYxQ==} dependencies: minecraft-data: 3.45.0 - prismarine-block: github.com/zardoy/prismarine-block/100f3e3be7927b8144e19a71c8d06f6218021a02 + prismarine-block: github.com/zardoy/prismarine-block/753cf1fe507f7647063c69d5c124d40f85b29cc2 prismarine-entity: 2.3.1 prismarine-item: 1.14.0 prismarine-nbt: 2.2.1 @@ -8645,15 +8666,15 @@ packages: engines: {node: '>=14'} dependencies: minecraft-data: 3.45.0 - minecraft-protocol: github.com/zardoy/minecraft-protocol/ef7c0b8d7a56ef997c21d4eba076f9e34560e91a + minecraft-protocol: github.com/zardoy/minecraft-protocol/320088fcc115b4c500f8de66d0e3ae87efadcc15 prismarine-biome: 1.3.0(minecraft-data@3.45.0)(prismarine-registry@1.7.0) - prismarine-block: github.com/zardoy/prismarine-block/100f3e3be7927b8144e19a71c8d06f6218021a02 + prismarine-block: github.com/zardoy/prismarine-block/753cf1fe507f7647063c69d5c124d40f85b29cc2 prismarine-chat: 1.9.1 prismarine-chunk: 1.35.0(minecraft-data@3.45.0) prismarine-entity: 2.3.1 prismarine-item: 1.14.0 prismarine-nbt: 2.2.1 - prismarine-physics: 1.7.0 + prismarine-physics: 1.8.0 prismarine-recipe: 1.3.1(prismarine-registry@1.7.0) prismarine-windows: 2.8.0 prismarine-world: github.com/zardoy/prismarine-world/c358222204d21fe7d45379fbfcefb047f926c786 @@ -8671,9 +8692,9 @@ packages: engines: {node: '>=14'} dependencies: minecraft-data: 3.45.0 - minecraft-protocol: github.com/zardoy/minecraft-protocol/ef7c0b8d7a56ef997c21d4eba076f9e34560e91a + minecraft-protocol: github.com/zardoy/minecraft-protocol/320088fcc115b4c500f8de66d0e3ae87efadcc15 prismarine-biome: 1.3.0(minecraft-data@3.45.0)(prismarine-registry@1.7.0) - prismarine-block: github.com/zardoy/prismarine-block/100f3e3be7927b8144e19a71c8d06f6218021a02 + prismarine-block: github.com/zardoy/prismarine-block/753cf1fe507f7647063c69d5c124d40f85b29cc2 prismarine-chat: 1.9.1 prismarine-chunk: 1.35.0(minecraft-data@3.45.0) prismarine-entity: 2.3.1 @@ -9594,7 +9615,7 @@ packages: engines: {node: '>=14'} dependencies: prismarine-biome: 1.3.0(minecraft-data@3.45.0)(prismarine-registry@1.7.0) - prismarine-block: github.com/zardoy/prismarine-block/100f3e3be7927b8144e19a71c8d06f6218021a02 + prismarine-block: github.com/zardoy/prismarine-block/753cf1fe507f7647063c69d5c124d40f85b29cc2 prismarine-nbt: 2.2.1 prismarine-registry: 1.7.0 smart-buffer: 4.2.0 @@ -9672,7 +9693,7 @@ packages: resolution: {integrity: sha512-iMam8wsUIYoqty3PSfAbbSLIWto/EnXs+zv7lHiZxwaiSR8GgFyN71H4Lp3g5ly4yuiLK8ROF4AINjrKx+vmUA==} dependencies: minecraft-data: 3.45.0 - prismarine-block: github.com/zardoy/prismarine-block/100f3e3be7927b8144e19a71c8d06f6218021a02 + prismarine-block: github.com/zardoy/prismarine-block/753cf1fe507f7647063c69d5c124d40f85b29cc2 prismarine-nbt: 1.6.0 prismarine-world: github.com/zardoy/prismarine-world/c358222204d21fe7d45379fbfcefb047f926c786 vec3: 0.1.8 @@ -10882,7 +10903,7 @@ packages: webpack: ^1 || ^2 || ^3 || ^4 || ^5 dependencies: chalk: 4.1.2 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) dev: false /spiralloop@1.0.2: @@ -11122,7 +11143,7 @@ packages: peerDependencies: webpack: ^5.0.0 dependencies: - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) dev: true /stylis@4.2.0: @@ -11220,7 +11241,7 @@ packages: supports-hyperlinks: 2.3.0 dev: true - /terser-webpack-plugin@5.3.9(esbuild@0.19.2)(webpack@5.88.2): + /terser-webpack-plugin@5.3.9(esbuild@0.19.3)(webpack@5.88.2): resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -11237,12 +11258,12 @@ packages: optional: true dependencies: '@jridgewell/trace-mapping': 0.3.19 - esbuild: 0.19.2 + esbuild: 0.19.3 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.1 terser: 5.19.2 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) /terser@5.19.2: resolution: {integrity: sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==} @@ -11509,6 +11530,12 @@ packages: is-typedarray: 1.0.0 dev: true + /typescript@5.2.2: + resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + /uint4@0.1.2: resolution: {integrity: sha512-lhEx78gdTwFWG+mt6cWAZD/R6qrIj0TTBeH5xwyuDJyswLNlGe+KVlUPQ6+mx5Ld332pS0AMUTo9hIly7YsWxQ==} @@ -11634,7 +11661,7 @@ packages: loader-utils: 2.0.4 mime-types: 2.1.35 schema-utils: 3.3.0 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) dev: true /url-parse@1.5.10: @@ -11676,7 +11703,7 @@ packages: dependencies: react: 18.2.0 - /use-typed-event-listener@4.0.2(react@17.0.2): + /use-typed-event-listener@4.0.2(react@17.0.2)(typescript@5.2.2): resolution: {integrity: sha512-AhjRw+qg5t7OWg7en2Q4XDCdi2iyhALFl71tITL3FeZqt/jD1Qa6KnbH/UolARtID1Gd0IElizbCgolv3ZbUFA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} peerDependencies: @@ -11688,11 +11715,12 @@ packages: dependencies: '@babel/runtime': 7.22.11 react: 17.0.2 + typescript: 5.2.2 use-deep-compare: 1.1.0(react@17.0.2) dev: true optional: true - /use-typed-event-listener@4.0.2(react@18.2.0): + /use-typed-event-listener@4.0.2(react@18.2.0)(typescript@5.2.2): resolution: {integrity: sha512-AhjRw+qg5t7OWg7en2Q4XDCdi2iyhALFl71tITL3FeZqt/jD1Qa6KnbH/UolARtID1Gd0IElizbCgolv3ZbUFA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} peerDependencies: @@ -11704,6 +11732,7 @@ packages: dependencies: '@babel/runtime': 7.22.11 react: 18.2.0 + typescript: 5.2.2 use-deep-compare: 1.1.0(react@18.2.0) dev: true @@ -11864,12 +11893,12 @@ packages: xml-name-validator: 3.0.0 dev: true - /wait-on@6.0.1: + /wait-on@6.0.1(debug@4.3.4): resolution: {integrity: sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==} engines: {node: '>=10.0.0'} hasBin: true dependencies: - axios: 0.25.0 + axios: 0.25.0(debug@4.3.4) joi: 17.10.0 lodash: 4.17.21 minimist: 1.2.8 @@ -11947,8 +11976,8 @@ packages: import-local: 3.1.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) - webpack-dev-server: 4.15.1(webpack-cli@5.1.4)(webpack@5.88.2) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) + webpack-dev-server: 4.15.1(debug@4.3.4)(webpack-cli@5.1.4)(webpack@5.88.2) webpack-merge: 5.9.0 /webpack-dev-middleware@5.3.3(webpack@5.88.2): @@ -11962,7 +11991,7 @@ packages: mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.2.0 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) /webpack-dev-middleware@6.1.1(webpack@5.88.2): resolution: {integrity: sha512-y51HrHaFeeWir0YO4f0g+9GwZawuigzcAdRNon6jErXy/SqV/+O6eaVAzDqE6t3e3NpGeR5CS+cCDaTC+V3yEQ==} @@ -11978,10 +12007,10 @@ packages: mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.2.0 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) dev: true - /webpack-dev-server@4.15.1(webpack-cli@5.1.4)(webpack@5.88.2): + /webpack-dev-server@4.15.1(debug@4.3.4)(webpack-cli@5.1.4)(webpack@5.88.2): resolution: {integrity: sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==} engines: {node: '>= 12.13.0'} hasBin: true @@ -12011,7 +12040,7 @@ packages: express: 4.18.2 graceful-fs: 4.2.11 html-entities: 2.4.0 - http-proxy-middleware: 2.0.6(@types/express@4.17.17) + http-proxy-middleware: 2.0.6(@types/express@4.17.17)(debug@4.3.4) ipaddr.js: 2.1.0 launch-editor: 2.6.0 open: 8.4.2 @@ -12022,7 +12051,7 @@ packages: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@4.15.1)(webpack@5.88.2) webpack-dev-middleware: 5.3.3(webpack@5.88.2) ws: 8.13.0 @@ -12049,7 +12078,7 @@ packages: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} - /webpack@5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4): + /webpack@5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4): resolution: {integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==} engines: {node: '>=10.13.0'} hasBin: true @@ -12080,7 +12109,7 @@ packages: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.9(esbuild@0.19.2)(webpack@5.88.2) + terser-webpack-plugin: 5.3.9(esbuild@0.19.3)(webpack@5.88.2) watchpack: 2.4.0 webpack-cli: 5.1.4(webpack-dev-server@4.15.1)(webpack@5.88.2) webpack-sources: 3.2.3 @@ -12508,7 +12537,7 @@ packages: fast-json-stable-stringify: 2.1.0 pretty-bytes: 5.6.0 upath: 1.2.0 - webpack: 5.88.2(esbuild@0.19.2)(webpack-cli@5.1.4) + webpack: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4) webpack-sources: 1.4.3 workbox-build: 6.6.0 transitivePeerDependencies: @@ -12799,7 +12828,7 @@ packages: compression: 1.7.4 express: 4.18.2 minecraft-data: 3.45.0 - prismarine-block: github.com/zardoy/prismarine-block/100f3e3be7927b8144e19a71c8d06f6218021a02 + prismarine-block: github.com/zardoy/prismarine-block/753cf1fe507f7647063c69d5c124d40f85b29cc2 prismarine-chunk: 1.35.0(minecraft-data@3.45.0) prismarine-world: github.com/zardoy/prismarine-world/c358222204d21fe7d45379fbfcefb047f926c786 socket.io: 4.7.2 @@ -12854,8 +12883,8 @@ packages: - react dev: true - github.com/zardoy/minecraft-protocol/ef7c0b8d7a56ef997c21d4eba076f9e34560e91a: - resolution: {tarball: https://codeload.github.com/zardoy/minecraft-protocol/tar.gz/ef7c0b8d7a56ef997c21d4eba076f9e34560e91a} + github.com/zardoy/minecraft-protocol/320088fcc115b4c500f8de66d0e3ae87efadcc15: + resolution: {tarball: https://codeload.github.com/zardoy/minecraft-protocol/tar.gz/320088fcc115b4c500f8de66d0e3ae87efadcc15} name: minecraft-protocol version: 1.44.0 engines: {node: '>=14'} @@ -12889,9 +12918,9 @@ packages: engines: {node: '>=14'} dependencies: minecraft-data: 3.45.0 - minecraft-protocol: github.com/zardoy/minecraft-protocol/ef7c0b8d7a56ef997c21d4eba076f9e34560e91a + minecraft-protocol: github.com/zardoy/minecraft-protocol/320088fcc115b4c500f8de66d0e3ae87efadcc15 prismarine-biome: 1.3.0(minecraft-data@3.45.0)(prismarine-registry@1.7.0) - prismarine-block: github.com/zardoy/prismarine-block/100f3e3be7927b8144e19a71c8d06f6218021a02 + prismarine-block: github.com/zardoy/prismarine-block/753cf1fe507f7647063c69d5c124d40f85b29cc2 prismarine-chat: 1.9.1 prismarine-chunk: 1.35.0(minecraft-data@3.45.0) prismarine-entity: 2.3.1 @@ -12910,8 +12939,8 @@ packages: - supports-color dev: true - github.com/zardoy/prismarine-block/100f3e3be7927b8144e19a71c8d06f6218021a02: - resolution: {tarball: https://codeload.github.com/zardoy/prismarine-block/tar.gz/100f3e3be7927b8144e19a71c8d06f6218021a02} + github.com/zardoy/prismarine-block/753cf1fe507f7647063c69d5c124d40f85b29cc2: + resolution: {tarball: https://codeload.github.com/zardoy/prismarine-block/tar.gz/753cf1fe507f7647063c69d5c124d40f85b29cc2} name: prismarine-block version: 1.17.1 dependencies: @@ -12947,7 +12976,7 @@ packages: compression: 1.7.4 express: 4.18.2 minecraft-data: 3.45.0 - prismarine-block: github.com/zardoy/prismarine-block/100f3e3be7927b8144e19a71c8d06f6218021a02 + prismarine-block: github.com/zardoy/prismarine-block/753cf1fe507f7647063c69d5c124d40f85b29cc2 prismarine-chunk: 1.35.0(minecraft-data@3.45.0) prismarine-world: github.com/zardoy/prismarine-world/c358222204d21fe7d45379fbfcefb047f926c786 socket.io: 4.7.2 @@ -12985,7 +13014,7 @@ packages: flatmap: 0.0.3 long: 5.2.3 minecraft-data: 3.45.0 - minecraft-protocol: github.com/zardoy/minecraft-protocol/ef7c0b8d7a56ef997c21d4eba076f9e34560e91a + minecraft-protocol: github.com/zardoy/minecraft-protocol/320088fcc115b4c500f8de66d0e3ae87efadcc15 moment: 2.29.4 needle: 2.9.1 node-gzip: 1.1.2 diff --git a/scripts/build.js b/scripts/build.js index 86899312f..94ece21a6 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -6,30 +6,32 @@ const fs = require('fs') const crypto = require('crypto') const path = require('path') -const prismarineViewerBase = "./node_modules/prismarine-viewer"; +const prismarineViewerBase = "./node_modules/prismarine-viewer" // these files could be copied at build time eg with copy plugin, but copy plugin slows down the config so we copy them there, alternative we could inline it in esbuild config const webpackFilesToCopy = [ { from: `${prismarineViewerBase}/public/blocksStates/`, to: 'dist/blocksStates/' }, { from: `${prismarineViewerBase}/public/worker.js`, to: 'dist/worker.js' }, { from: './assets/', to: './dist/' }, - { from: './config.json', to: 'dist/config.json' } + { from: './config.json', to: 'dist/config.json' }, + { from: `${prismarineViewerBase}/public/textures/1.16.4/entity`, to: 'dist/textures/1.16.4/entity' }, ] exports.webpackFilesToCopy = webpackFilesToCopy exports.copyFiles = (isDev = false) => { - console.time('copy files'); - webpackFilesToCopy.forEach(file => { - fsExtra.copySync(file.from, file.to) - }) - // todo copy directly only needed + console.time('copy files') + // copy glob const cwd = `${prismarineViewerBase}/public/textures/` - const files = glob.sync('{*/entity/**,*.png}', { cwd: cwd, nodir: true, }) + const files = glob.sync('*.png', { cwd: cwd, nodir: true, }) for (const file of files) { const copyDest = path.join('dist/textures/', file) fs.mkdirSync(path.dirname(copyDest), { recursive: true, }) fs.copyFileSync(path.join(cwd, file), copyDest) } + webpackFilesToCopy.forEach(file => { + fsExtra.copySync(file.from, file.to) + }) + console.timeEnd('copy files') } diff --git a/scripts/prepareData.mjs b/scripts/prepareData.mjs index 6d13156cf..1c5d62401 100644 --- a/scripts/prepareData.mjs +++ b/scripts/prepareData.mjs @@ -4,7 +4,7 @@ import { existsSync } from 'node:fs' import Module from "node:module" import { dirname } from 'node:path' -if (existsSync('dist/mc-data')) { +if (existsSync('dist/mc-data') && !process.argv.includes('-f')) { console.log('using cached prepared data') process.exit(0) } diff --git a/server.js b/server.js index 0da756cad..d89018c9d 100644 --- a/server.js +++ b/server.js @@ -29,9 +29,14 @@ if (process.argv[3] === 'dev') { app.use(express.static(path.join(__dirname, './dist'))) } +const portArg = process.argv.indexOf('--port') +const port = (require.main === module ? process.argv[2] : portArg !== -1 ? process.argv[portArg + 1] : undefined) || 8080 + // Start the server -const server = process.argv.includes('--prod') ? undefined : app.listen(require.main !== module || process.argv[2] === undefined ? 8080 : process.argv[2], function () { - console.log('Server listening on port ' + server.address().port) -}) +const server = process.argv.includes('--prod') ? + undefined : + app.listen(port, function () { + console.log('Server listening on port ' + server.address().port) + }) module.exports = { app } diff --git a/src/blockInteraction.js b/src/blockInteraction.js new file mode 100644 index 000000000..5b94ca571 --- /dev/null +++ b/src/blockInteraction.js @@ -0,0 +1,226 @@ +//@ts-check + +// wouldn't better to create atlas instead? +import destroyStage0 from 'minecraft-assets/minecraft-assets/data/1.10/blocks/destroy_stage_0.png' +import destroyStage1 from 'minecraft-assets/minecraft-assets/data/1.10/blocks/destroy_stage_1.png' +import destroyStage2 from 'minecraft-assets/minecraft-assets/data/1.10/blocks/destroy_stage_2.png' +import destroyStage3 from 'minecraft-assets/minecraft-assets/data/1.10/blocks/destroy_stage_3.png' +import destroyStage4 from 'minecraft-assets/minecraft-assets/data/1.10/blocks/destroy_stage_4.png' +import destroyStage5 from 'minecraft-assets/minecraft-assets/data/1.10/blocks/destroy_stage_5.png' +import destroyStage6 from 'minecraft-assets/minecraft-assets/data/1.10/blocks/destroy_stage_6.png' +import destroyStage7 from 'minecraft-assets/minecraft-assets/data/1.10/blocks/destroy_stage_7.png' +import destroyStage8 from 'minecraft-assets/minecraft-assets/data/1.10/blocks/destroy_stage_8.png' +import destroyStage9 from 'minecraft-assets/minecraft-assets/data/1.10/blocks/destroy_stage_9.png' + +import { Vec3 } from 'vec3' +import { isGameActive } from './globalState' + +function getViewDirection (pitch, yaw) { + const csPitch = Math.cos(pitch) + const snPitch = Math.sin(pitch) + const csYaw = Math.cos(yaw) + const snYaw = Math.sin(yaw) + return new Vec3(-snYaw * csPitch, snPitch, -csYaw * csPitch) +} + +class BlockInteraction { + static instance = null + + init () { + bot.on('physicsTick', () => { if (this.lastBlockPlaced < 4) this.lastBlockPlaced++ }) + + // Init state + this.buttons = [false, false, false] + this.lastButtons = [false, false, false] + this.breakStartTime = 0 + this.cursorBlock = null + + const loader = new THREE.TextureLoader() + this.breakTextures = [] + 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) + } + const breakMaterial = new THREE.MeshBasicMaterial({ + transparent: true, + blending: THREE.MultiplyBlending + }) + this.blockBreakMesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), breakMaterial) + this.blockBreakMesh.visible = false + this.blockBreakMesh.renderOrder = 999 + viewer.scene.add(this.blockBreakMesh) + + // Setup events + document.addEventListener('mouseup', (e) => { + this.buttons[e.button] = false + }) + + this.lastBlockPlaced = 4 // ticks since last placed + document.addEventListener('mousedown', (e) => { + if (e.isTrusted && !document.pointerLockElement) return + if (!isGameActive(true)) return + this.buttons[e.button] = true + + const entity = bot.nearestEntity((e) => { + if (e.position.distanceTo(bot.entity.position) <= (bot.game.gameMode === 'creative' ? 5 : 3)) { + const dir = getViewDirection(bot.entity.pitch, bot.entity.yaw) + const { width, height } = e + const { x: eX, y: eY, z: eZ } = e.position + const { x: bX, y: bY, z: bZ } = bot.entity.position + const box = new THREE.Box3( + new THREE.Vector3(eX - width / 2, eY, eZ - width / 2), + new THREE.Vector3(eX + width / 2, eY + height, eZ + width / 2) + ) + + const r = new THREE.Raycaster( + new THREE.Vector3(bX, bY + 1.52, bZ), + new THREE.Vector3(dir.x, dir.y, dir.z) + ) + const int = r.ray.intersectBox(box, new THREE.Vector3(eX, eY, eZ)) + return int !== null + } + + return false + }) + + if (entity) { + bot.attack(entity) + } + }) + } + + /** @type {null | {blockPos,mesh}} */ + interactionLines = null + updateBlockInteractionLines (/** @type {Vec3 | null} */blockPos, /** @type {{position, width, height, depth}[]} */shapePositions = undefined) { + if (this.interactionLines !== null) { + viewer.scene.remove(this.interactionLines.mesh) + this.interactionLines = null + } + if (blockPos === null || (this.interactionLines && blockPos.equals(this.interactionLines.blockPos))) { + return + } + + const group = new THREE.Group() + for (const { position, width, height, depth } of shapePositions) { + const geometry = new THREE.BoxGeometry(1.001 * width, 1.001 * height, 1.001 * depth) + const mesh = new THREE.LineSegments(new THREE.EdgesGeometry(geometry), new THREE.LineBasicMaterial({ color: 0 })) + const pos = blockPos.plus(position) + mesh.position.set(pos.x, pos.y, pos.z) + group.add(mesh) + } + viewer.scene.add(group) + this.interactionLines = { blockPos, mesh: group } + } + + // todo this shouldnt be done in the render loop, migrate the code to dom events to avoid delays on lags + update () { + const cursorBlock = bot.blockAtCursor(5) + let cursorBlockDiggable = cursorBlock + if (!bot.canDigBlock(cursorBlock) && bot.game.gameMode !== 'creative') cursorBlockDiggable = null + + let cursorChanged = !cursorBlock !== !this.cursorBlock + if (cursorBlock && this.cursorBlock) { + cursorChanged = !cursorBlock.position.equals(this.cursorBlock.position) + } + + // Place + if (cursorBlock && this.buttons[2] && (!this.lastButtons[2] || cursorChanged) && this.lastBlockPlaced >= 4) { + const vecArray = [new Vec3(0, -1, 0), new Vec3(0, 1, 0), new Vec3(0, 0, -1), new Vec3(0, 0, 1), new Vec3(-1, 0, 0), new Vec3(1, 0, 0)] + //@ts-ignore + const delta = cursorBlock.intersect.minus(cursorBlock.position) + // check instead? + //@ts-ignore + bot._placeBlockWithOptions(cursorBlock, vecArray[cursorBlock.face], { delta, forceLook: 'ignore' }).catch(console.warn) + this.lastBlockPlaced = 0 + } + + // Start break + // todo last check doesnt work as cursorChanged happens once (after that check is false) + if (cursorBlockDiggable && this.buttons[0] && (!this.lastButtons[0] || (cursorChanged && Date.now() - (this.lastDigged ?? 0) > 100))) { + this.breakStartTime = performance.now() + bot.dig(cursorBlock, 'ignore').catch((err) => { + if (err.message === 'Digging aborted') return + throw err + }) + this.lastDigged = Date.now() + } + + // Stop break + if (!this.buttons[0] && this.lastButtons[0]) { + try { + bot.stopDigging() // this shouldnt throw anything... + } catch (e) { } // to be reworked in mineflayer, then remove the try here + } + + // Show cursor + if (!cursorBlock) { + this.updateBlockInteractionLines(null) + } else { + const allShapes = [...cursorBlock.shapes, ...cursorBlock['interactionShapes'] ?? []] + this.updateBlockInteractionLines(cursorBlock.position, allShapes.map(shape => { + return getDataFromShape(shape) + })) + { + // union of all values + const breakShape = allShapes.reduce((acc, cur) => { + return [ + Math.min(acc[0], cur[0]), + Math.min(acc[1], cur[1]), + Math.min(acc[2], cur[2]), + Math.max(acc[3], cur[3]), + Math.max(acc[4], cur[4]), + Math.max(acc[5], cur[5]) + ] + }) + const { position, width, height, depth } = getDataFromShape(breakShape) + this.blockBreakMesh.scale.set(width * 1.001, height * 1.001, depth * 1.001) + position.add(cursorBlock.position) + this.blockBreakMesh.position.set(position.x, position.y, position.z) + } + } + + // Show break animation + if (cursorBlockDiggable && this.buttons[0]) { + const elapsed = performance.now() - this.breakStartTime + const time = bot.digTime(cursorBlock) + const state = Math.floor((elapsed / time) * 10) + this.blockBreakMesh.material.map = this.breakTextures[state] + this.blockBreakMesh.visible = true + } else { + this.blockBreakMesh.visible = false + } + + // Update state + this.cursorBlock = cursorBlock + this.lastButtons[0] = this.buttons[0] + this.lastButtons[1] = this.buttons[1] + this.lastButtons[2] = this.buttons[2] + } +} + +const getDataFromShape = (shape) => { + const width = shape[3] - shape[0] + const height = shape[4] - shape[1] + const depth = shape[5] - shape[2] + const centerX = (shape[3] + shape[0]) / 2 + const centerY = (shape[4] + shape[1]) / 2 + const centerZ = (shape[5] + shape[2]) / 2 + const position = new Vec3(centerX, centerY, centerZ) + return { position, width, height, depth } +} + +export default new BlockInteraction() diff --git a/src/chat.js b/src/chat.js index 43fa396ef..318e8889f 100644 --- a/src/chat.js +++ b/src/chat.js @@ -466,13 +466,13 @@ class ChatBox extends LitElement { chatInput.addEventListener('keydown', (e) => { if (e.code === 'Tab') { if (this.completionItems.length) { - this.tabComplete(this.completionItems[0]) + this.acceptComplete(this.completionItems[0]) } else { void this.fetchCompletion(chatInput.value) } e.preventDefault() } - if (e.code === 'Space' && options.autoRequestCompletions) { + if (e.code === 'Space' && options.autoRequestCompletions && chatInput.value.startsWith('/')) { // alternative we could just simply use keyup, but only with keydown we can display suggestions popup as soon as possible void this.fetchCompletion(this.getCompleteValue(chatInput.value + ' ')) } @@ -553,8 +553,8 @@ class ChatBox extends LitElement { this.chatInput.focus() } - tabComplete (item) { - const base = this.completeRequestValue === '/' ? '' : this.completeRequestValue + acceptComplete (item) { + const base = this.completeRequestValue === '/' ? '' : this.getCompleteValue() this.updateInputValue(base + item) // would be cool but disabled because some comands don't need args (like ping) // // trigger next tab complete @@ -576,7 +576,7 @@ class ChatBox extends LitElement { ${this.completionItems.length ? html`
${this.completePadText}
- ${repeat(this.completionItems, (i) => i, (i) => html`
this.tabComplete(i)}>${i}
`)} + ${repeat(this.completionItems, (i) => i, (i) => html`
this.acceptComplete(i)}>${i}
`)}
` : ''} { diff --git a/src/index.ts b/src/index.ts index fe08f45b0..768ab13cd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -41,7 +41,7 @@ import { WorldView, Viewer } from 'prismarine-viewer/viewer' import pathfinder from 'mineflayer-pathfinder' import { Vec3 } from 'vec3' -import Cursor from './cursor' +import blockInteraction from './blockInteraction' import * as THREE from 'three' @@ -82,11 +82,11 @@ import { contro } from './controls' import { genTexturePackTextures, watchTexturepackInViewer } from './texturePack' import { connectToPeer } from './localServerMultiplayer' import CustomChannelClient from './customClient' +import debug from 'debug' +window.debug = debug //@ts-ignore window.THREE = THREE -// workaround to be used in prismarine-block -globalThis.emptyShapeReplacer = [[0.0, 0.0, 0.0, 1.0, 1.0, 1.0]] if ('serviceWorker' in navigator && !isCypress() && process.env.NODE_ENV !== 'development') { window.addEventListener('load', () => { @@ -100,6 +100,7 @@ if ('serviceWorker' in navigator && !isCypress() && process.env.NODE_ENV !== 'de // ACTUAL CODE +// todo stats-gl let stats let stats2 stats = new Stats() @@ -198,12 +199,11 @@ const pauseMenu = document.getElementById('pause-screen') let mouseMovePostHandle = (e) => { } let lastMouseMove: number -let cursor: Cursor let debugMenu const updateCursor = () => { - cursor.update(bot) + blockInteraction.update() debugMenu ??= hud.shadowRoot.querySelector('#debug-overlay') - debugMenu.cursorBlock = cursor.cursorBlock + debugMenu.cursorBlock = blockInteraction.cursorBlock } function onCameraMove(e) { if (e.type !== 'touchmove' && !pointerLock.hasPointerLock) return @@ -336,7 +336,9 @@ async function connect(connectOptions: { bot.removeAllListeners() bot._client.removeAllListeners() bot._client = undefined - bot = undefined + // for debugging + window._botDisconnected = undefined + window.bot = bot = undefined } removeAllListeners() for (const timeout of timeouts) { @@ -363,6 +365,7 @@ async function connect(connectOptions: { setLoadingScreenStatus(`Error encountered. Error message: ${err}`, true) destroyAll() + if (isCypress()) throw err } const errorAbortController = new AbortController() @@ -468,8 +471,10 @@ async function connect(connectOptions: { closeTimeout: 240 * 1000, async versionSelectedHook(client) { await downloadMcData(client.version) + setLoadingScreenStatus('Connecting to server') } }) + window.bot = bot if (singeplayer || p2pMultiplayer) { // p2pMultiplayer still uses the same flying-squid server const _supportFeature = bot.supportFeature @@ -482,13 +487,24 @@ async function connect(connectOptions: { bot.emit('inject_allowed') bot._client.emit('connect') + } else { + bot._client.socket.on('connect', () => { + console.log('TCP connection established') + //@ts-ignore + bot._client.socket._ws.addEventListener('close', () => { + console.log('TCP connection closed') + setTimeout(() => { + if (bot) { + bot.emit('end', 'TCP connection closed with unknown reason') + } + }) + }) + }) } } catch (err) { handleError(err) } if (!bot) return - cursor = new Cursor(viewer, renderer, bot) - // bot.on('move', () => updateCursor()) let p2pConnectTimeout = p2pMultiplayer ? setTimeout(() => { throw new Error('Spawn timeout. There might be error on other side, check console.') }, 20_000) : undefined hud.preload(bot) @@ -509,6 +525,7 @@ async function connect(connectOptions: { console.log('disconnected for', endReason) destroyAll() setLoadingScreenStatus(`You have been disconnected from the server. End reason: ${endReason}`, true) + if (isCypress()) throw new Error(`disconnected: ${endReason}`) }) bot.once('login', () => { @@ -564,7 +581,6 @@ async function connect(connectOptions: { const debugMenu = hud.shadowRoot.querySelector('#debug-overlay') window.loadedData = mcData - window.bot = bot window.Vec3 = Vec3 window.pathfinder = pathfinder window.debugMenu = debugMenu @@ -617,19 +633,30 @@ async function connect(connectOptions: { registerListener(document, 'pointerlockchange', changeCallback, false) + let holdingTouch: { touch: Touch, elem: HTMLElement } | undefined + document.body.addEventListener('touchend', (e) => { + if (!isGameActive(true)) return + if (holdingTouch?.touch.identifier !== e.changedTouches[0].identifier) return + holdingTouch.elem.click() + holdingTouch = undefined + }) + document.body.addEventListener('touchstart', (e) => { + if (!isGameActive(true)) return + e.preventDefault() + holdingTouch = { + touch: e.touches[0], + elem: e.composedPath()[0] as HTMLElement + } + }, { passive: false }) + const cameraControlEl = hud - // after what time of holding the finger start breaking the block + /** after what time of holding the finger start breaking the block */ const touchStartBreakingBlockMs = 500 let virtualClickActive = false let virtualClickTimeout let screenTouches = 0 let capturedPointer: { id; x; y; sourceX; sourceY; activateCameraMove; time } | null - document.body.addEventListener('touchstart', (e) => { - if (isGameActive(true)) { - e.preventDefault() - } - }, { passive: false }) registerListener(document, 'pointerdown', (e) => { const clickedEl = e.composedPath()[0] if (!isGameActive(true) || !miscUiState.currentTouch || clickedEl !== cameraControlEl || e.pointerId === undefined) { @@ -650,7 +677,7 @@ async function connect(connectOptions: { sourceX: e.clientX, sourceY: e.clientY, activateCameraMove: false, - time: new Date() + time: Date.now() } virtualClickTimeout ??= setTimeout(() => { virtualClickActive = true @@ -695,9 +722,8 @@ async function connect(connectOptions: { virtualClickActive = false } else if (!capturedPointer.activateCameraMove && (Date.now() - capturedPointer.time < touchStartBreakingBlockMs)) { document.dispatchEvent(new MouseEvent('mousedown', { button: 2 })) - nextFrameFn.push(() => { - document.dispatchEvent(new MouseEvent('mouseup', { button: 2 })) - }) + blockInteraction.update() + document.dispatchEvent(new MouseEvent('mouseup', { button: 2 })) } capturedPointer = undefined }, { passive: false }) @@ -722,6 +748,7 @@ async function connect(connectOptions: { hud.init(renderer, bot, host) hud.style.display = 'block' + blockInteraction.init() setTimeout(function () { errorAbortController.abort() @@ -729,6 +756,10 @@ async function connect(connectOptions: { // remove loading screen, wait a second to make sure a frame has properly rendered setLoadingScreenStatus(undefined) hideCurrentScreens() + viewer.waitForChunksToRender().then(() => { + console.log('All done and ready!') + document.dispatchEvent(new Event('cypress-world-ready')) + }) }, singeplayer ? 0 : 2500) }) } diff --git a/src/menus/advanced_options_screen.js b/src/menus/advanced_options_screen.js index 18d180a5a..7efa690a1 100644 --- a/src/menus/advanced_options_screen.js +++ b/src/menus/advanced_options_screen.js @@ -2,7 +2,7 @@ const { html, css, LitElement } = require('lit') const { commonCss, openURL } = require('./components/common') const { hideCurrentModal } = require('../globalState') -const { toNumber, getScreenRefreshRate } = require('../utils') +const { getScreenRefreshRate } = require('../utils') const { subscribe } = require('valtio') const { options } = require('../optionsStorage') @@ -74,6 +74,11 @@ class AdvancedOptionsScreen extends LitElement { this.requestUpdate() }}> +
+ { + options.touchButtonsSize = +e.target.value + }}> +
hideCurrentModal()}> diff --git a/src/menus/components/button.js b/src/menus/components/button.js index d1a402470..6ccc6bad5 100644 --- a/src/menus/components/button.js +++ b/src/menus/components/button.js @@ -1,15 +1,46 @@ //@ts-check const { LitElement, html, css, unsafeCSS } = require('lit') const widgetsGui = require('minecraft-assets/minecraft-assets/data/1.17.1/gui/widgets.png') -const { options, watchValue } = require('../../optionsStorage') +const { options } = require('../../optionsStorage') + +let audioContext +/** @type {Record} */ +const sounds = {} -const buttonClickAudio = new Audio() -buttonClickAudio.src = 'button_click.mp3' // 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 -buttonClickAudio.load() -watchValue(options, o => { - buttonClickAudio.volume = o.volume / 100 -}) +let loadingSounds = [] +async function loadSound (path) { + loadingSounds.push(path) + const res = await window.fetch(path) + const data = await res.arrayBuffer() + + // sounds[path] = await audioContext.decodeAudioData(data) + sounds[path] = data + loadingSounds.splice(loadingSounds.indexOf(path), 1) +} + +export async function playSound (path) { + if (!audioContext) { + audioContext = new window.AudioContext() + for (const [soundName, sound] of Object.entries(sounds)) { + sounds[soundName] = await audioContext.decodeAudioData(sound) + } + } + + const volume = options.volume / 100 + + if (loadingSounds.includes(path)) return + const soundBuffer = sounds[path] + if (!soundBuffer) throw new Error(`Sound ${path} not loaded`) + + const gainNode = audioContext.createGain() + const source = audioContext.createBufferSource() + source.buffer = soundBuffer + source.connect(gainNode) + gainNode.connect(audioContext.destination) + gainNode.gain.value = volume + source.start(0) +} class Button extends LitElement { static get styles () { @@ -134,9 +165,10 @@ class Button extends LitElement { } onBtnClick (e) { - buttonClickAudio.play() + playSound('button_click.mp3') this.dispatchEvent(new window.CustomEvent('pmui-click', { detail: e, })) } } +loadSound('button_click.mp3') window.customElements.define('pmui-button', Button) diff --git a/src/menus/components/hotbar.js b/src/menus/components/hotbar.js index a4ff4a0c5..95744da69 100644 --- a/src/menus/components/hotbar.js +++ b/src/menus/components/hotbar.js @@ -187,48 +187,20 @@ class Hotbar extends LitElement {

${this.activeItemName}

-
{ +
{ if (!e.target.id.startsWith('hotbar')) return const slot = +e.target.id.split('-')[1] this.reloadHotbarSelected(slot) }}> -
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
- ${miscUiState.currentTouch ? html`
{ + ${Array.from({ length: 9 }).map((_, i) => html` +
{ + this.reloadHotbarSelected(i) + }}> +
+ +
+ `)} + ${miscUiState.currentTouch ? html`
{ showModal({ reactType: 'inventory', }) }}>` : undefined}
diff --git a/src/menus/hud.js b/src/menus/hud.js index 4906ed25f..590085a43 100644 --- a/src/menus/hud.js +++ b/src/menus/hud.js @@ -303,17 +303,6 @@ class Hud extends LitElement { /** @param {boolean} bl */ showMobileControls (bl) { this.shadowRoot.querySelector('#mobile-top').style.display = bl ? 'flex' : 'none' - // this.shadowRoot.querySelector('#mobile-left').style.display = bl ? 'block' : 'none' - // this.shadowRoot.querySelector('#mobile-right').style.display = bl ? 'flex' : 'none' - } - - /** - * @param {any} id - * @param {boolean} action - */ - mobileControl (e, id, action) { - e.stopPropagation() - this.bot.setControlState(id, action) } render () { @@ -334,47 +323,6 @@ class Hud extends LitElement { showModal(document.getElementById('pause-screen')) }}>
- diff --git a/src/optionsStorage.ts b/src/optionsStorage.ts index 81f9b8232..51aeb35d5 100644 --- a/src/optionsStorage.ts +++ b/src/optionsStorage.ts @@ -24,6 +24,7 @@ const defaultOptions = { fov: 75, guiScale: 3, autoRequestCompletions: true, + touchButtonsSize: 40, frameLimit: false as number | false, alwaysBackupWorldBeforeLoading: undefined as boolean | undefined | null, @@ -39,6 +40,8 @@ const defaultOptions = { askGuestName: true } +export type AppOptions = typeof defaultOptions + export const options = proxy( mergeAny(defaultOptions, JSON.parse(localStorage.options || '{}')) ) diff --git a/src/reactUi.jsx b/src/reactUi.jsx index f686ac95a..efe49792e 100644 --- a/src/reactUi.jsx +++ b/src/reactUi.jsx @@ -4,12 +4,12 @@ import { renderToDom } from '@zardoy/react-util' import { LeftTouchArea, RightTouchArea, useUsingTouch, useInterfaceState } from '@dimaka/interface' import { css } from '@emotion/css' import { activeModalStack, isGameActive, miscUiState } from './globalState' -import { isProbablyIphone } from './menus/components/common' // import DeathScreen from './react/DeathScreen' import { useSnapshot } from 'valtio' import { contro } from './controls' import { QRCodeSVG } from 'qrcode.react' import { createPortal } from 'react-dom' +import { options, watchValue } from './optionsStorage' // todo useInterfaceState.setState({ @@ -40,6 +40,14 @@ useInterfaceState.setState({ } }) +watchValue(options, (o) => { + useInterfaceState.setState({ + uiCustomization: { + touchButtonSize: o.touchButtonsSize, + }, + }) +}) + const TouchControls = () => { // todo setting const usingTouch = useUsingTouch() diff --git a/src/texturePack.ts b/src/texturePack.ts index d0ecc18bd..0f54e2961 100644 --- a/src/texturePack.ts +++ b/src/texturePack.ts @@ -123,7 +123,7 @@ const applyTexturePackData = async (version: string, { blockSize }: TextureResol const blockStates: BlockStates = await result.json() const factor = blockSize / 16 - // this will be refactored with prerender refactor + // this will be refactored with generateTextures refactor const processObj = (x) => { if (typeof x !== 'object' || !x) return if (Array.isArray(x)) { diff --git a/tsconfig.json b/tsconfig.json index d6ed70d8f..754ae40e4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,18 +1,24 @@ { "compilerOptions": { - "target": "ES2022", + "target": "ESNext", "moduleResolution": "Node", - "module": "CommonJS", + "module": "ESNext", "allowJs": true, "jsx": "react-jsx", "allowSyntheticDefaultImports": true, "noEmit": true, - "strictFunctionTypes": true, "resolveJsonModule": true, - "noFallthroughCasesInSwitch": true + "strictFunctionTypes": true, + "noImplicitAny": false, + "noFallthroughCasesInSwitch": true, + "allowUnreachableCode": true, + "forceConsistentCasingInFileNames": true, + "useUnknownInCatchVariables": false, + "skipLibCheck": true // "strictNullChecks": true }, "include": [ - "src" + "src", + "cypress" ] }