add massive eslint config and big number of fixes for it! thx to ext

This commit is contained in:
Vitaly 2023-09-26 08:01:17 +03:00
commit 5b9c268750
23 changed files with 893 additions and 214 deletions

52
.eslintrc.json Normal file
View file

@ -0,0 +1,52 @@
{
"extends": "zardoy",
"rules": {
// perf
"import/no-deprecated": "off",
// ---
"@typescript-eslint/prefer-nullish-coalescing": "off",
"@typescript-eslint/naming-convention": "off",
"prefer-template": "off",
// intentional: improve readability in some cases
"no-else-return": "off",
"@typescript-eslint/padding-line-between-statements": "off",
"arrow-body-style": "off",
"unicorn/prefer-ternary": "off",
"unicorn/switch-case-braces": "off",
"@typescript-eslint/consistent-type-definitions": "off",
"unicorn/explicit-length-check": "off",
"unicorn/prefer-dom-node-append": "off",
"typescript-eslint/no-confusing-void-expression": "off",
"unicorn/no-lonely-if": "off",
"no-multi-assign": "off",
"sonarjs/no-duplicate-string": "off",
"new-cap": "off",
"unicorn/consistent-destructuring": "off",
"unicorn/no-await-expression-member": "off",
"unicorn/prefer-add-event-listener": "off",
"unicorn/prefer-top-level-await": "off",
"default-case": "off",
// I guess it would better to fix
"node/prefer-global/buffer": "off",
"unicorn/prefer-optional-catch-binding": "off", // still useful for debugging
"no-alert": "off", // todo once replaced with ui, enable
"@typescript-eslint/restrict-plus-operands": "off",
// ---
"@typescript-eslint/no-throw-literal": "off", // disabling because of "rule expansion"
"no-empty-function": "off",
"@typescript-eslint/no-explicit-any": "off",
"import/no-extraneous-dependencies": "off",
"@typescript-eslint/ban-types": "off",
"unicorn/prefer-query-selector": "off",
"@typescript-eslint/dot-notation": "off", // trick prop type-checking
"@typescript-eslint/consistent-type-imports": "off",
"no-negated-condition": "off",
"@typescript-eslint/no-require-imports": "off",
"unicorn/prefer-number-properties": "off",
"@typescript-eslint/no-confusing-void-expression": "off",
// needs to be fixed actually
"@typescript-eslint/no-floating-promises": "warn",
"no-async-promise-executor": "off",
"no-bitwise": "off"
}
}

View file

@ -11,6 +11,7 @@ jobs:
- name: Install pnpm
run: npm i -g pnpm
- run: pnpm install
- run: pnpm lint
- run: pnpm check-build
- run: nohup pnpm prod-start &
- run: nohup node cypress/minecraft-server.mjs &

View file

@ -43,6 +43,7 @@ it('Loads & renders singleplayer', () => {
localServerOptions: {
generation: {
name: 'superflat',
// eslint-disable-next-line unicorn/numeric-separators-style
options: { seed: 250869072 }
},
},

View file

@ -10,7 +10,8 @@
"test:cypress": "cypress run",
"test:e2e": "start-test http-get://localhost:8080 test:cypress",
"prod-start": "node server.js",
"postinstall": "node scripts/gen-texturepack-files.mjs"
"postinstall": "node scripts/gen-texturepack-files.mjs",
"lint": "eslint \"{src,cypress}/**/*.{ts,js,jsx,tsx}\""
},
"keywords": [
"prismarine",
@ -61,6 +62,8 @@
"crypto-browserify": "^3.12.0",
"cypress": "^9.5.4",
"cypress-esbuild-preprocessor": "^1.0.2",
"eslint": "^8.50.0",
"eslint-config-zardoy": "^0.2.17",
"events": "^3.3.0",
"filesize": "^10.0.12",
"http-browserify": "^1.7.0",

674
pnpm-lock.yaml generated
View file

@ -133,6 +133,12 @@ importers:
cypress-esbuild-preprocessor:
specifier: ^1.0.2
version: 1.0.2
eslint:
specifier: ^8.50.0
version: 8.50.0
eslint-config-zardoy:
specifier: ^0.2.17
version: 0.2.17(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.33.2)(eslint@8.50.0)(typescript@5.2.2)
events:
specifier: ^3.3.0
version: 3.3.0
@ -283,7 +289,7 @@ importers:
version: 16.0.0
standard:
specifier: ^17.0.0
version: 17.0.0
version: 17.0.0(@typescript-eslint/parser@6.7.3)
webpack:
specifier: ^5.10.2
version: 5.88.2(esbuild@0.19.3)(webpack-cli@5.1.4)
@ -1847,6 +1853,16 @@ packages:
eslint-visitor-keys: 3.4.3
dev: true
/@eslint-community/eslint-utils@4.4.0(eslint@8.50.0):
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
dependencies:
eslint: 8.50.0
eslint-visitor-keys: 3.4.3
dev: true
/@eslint-community/regexpp@4.8.0:
resolution: {integrity: sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
@ -1874,6 +1890,11 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/@eslint/js@8.50.0:
resolution: {integrity: sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/@hapi/hoek@9.3.0:
resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
dev: true
@ -1895,6 +1916,17 @@ packages:
- supports-color
dev: true
/@humanwhocodes/config-array@0.11.11:
resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==}
engines: {node: '>=10.10.0'}
dependencies:
'@humanwhocodes/object-schema': 1.2.1
debug: 4.3.4(supports-color@8.1.1)
minimatch: 3.1.2
transitivePeerDependencies:
- supports-color
dev: true
/@humanwhocodes/module-importer@1.0.1:
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
engines: {node: '>=12.22'}
@ -2690,6 +2722,10 @@ packages:
rollup: 2.79.1
dev: false
/@rushstack/eslint-patch@1.4.0:
resolution: {integrity: sha512-cEjvTPU32OM9lUFegJagO0mRnIn+rbqrG89vV8/xLnLFX0DoR0r1oy5IlTga71Q7uT3Qus7qm7wgeiMT/+Irlg==}
dev: true
/@sideway/address@4.1.4:
resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==}
dependencies:
@ -2842,6 +2878,10 @@ packages:
/@types/node@20.6.4:
resolution: {integrity: sha512-nU6d9MPY0NBUMiE/nXd2IIoC4OLvsLpwAjheoAeuzgvDZA1Cb10QYg+91AF6zQiKWRN5i1m07x6sMe0niBznoQ==}
/@types/normalize-package-data@2.4.2:
resolution: {integrity: sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==}
dev: true
/@types/parse-json@4.0.0:
resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==}
dev: false
@ -2881,6 +2921,10 @@ packages:
/@types/scheduler@0.16.3:
resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==}
/@types/semver@7.5.3:
resolution: {integrity: sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==}
dev: true
/@types/sinonjs__fake-timers@8.1.1:
resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==}
@ -2920,6 +2964,180 @@ packages:
'@types/node': 20.5.7
optional: true
/@typescript-eslint/eslint-plugin@6.1.0(@typescript-eslint/parser@6.7.3)(eslint@8.50.0)(typescript@5.2.2):
resolution: {integrity: sha512-qg7Bm5TyP/I7iilGyp6DRqqkt8na00lI6HbjWZObgk3FFSzH5ypRwAHXJhJkwiRtTcfn+xYQIMOR5kJgpo6upw==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
'@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
eslint: ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@eslint-community/regexpp': 4.8.0
'@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2)
'@typescript-eslint/scope-manager': 6.1.0
'@typescript-eslint/type-utils': 6.1.0(eslint@8.50.0)(typescript@5.2.2)
'@typescript-eslint/utils': 6.1.0(eslint@8.50.0)(typescript@5.2.2)
'@typescript-eslint/visitor-keys': 6.1.0
debug: 4.3.4(supports-color@8.1.1)
eslint: 8.50.0
graphemer: 1.4.0
ignore: 5.2.4
natural-compare: 1.4.0
natural-compare-lite: 1.4.0
semver: 7.5.4
ts-api-utils: 1.0.3(typescript@5.2.2)
typescript: 5.2.2
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/parser@6.7.3(eslint@8.50.0)(typescript@5.2.2):
resolution: {integrity: sha512-TlutE+iep2o7R8Lf+yoer3zU6/0EAUc8QIBB3GYBc1KGz4c4TRm83xwXUZVPlZ6YCLss4r77jbu6j3sendJoiQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/scope-manager': 6.7.3
'@typescript-eslint/types': 6.7.3
'@typescript-eslint/typescript-estree': 6.7.3(typescript@5.2.2)
'@typescript-eslint/visitor-keys': 6.7.3
debug: 4.3.4(supports-color@8.1.1)
eslint: 8.50.0
typescript: 5.2.2
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/scope-manager@6.1.0:
resolution: {integrity: sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
'@typescript-eslint/types': 6.1.0
'@typescript-eslint/visitor-keys': 6.1.0
dev: true
/@typescript-eslint/scope-manager@6.7.3:
resolution: {integrity: sha512-wOlo0QnEou9cHO2TdkJmzF7DFGvAKEnB82PuPNHpT8ZKKaZu6Bm63ugOTn9fXNJtvuDPanBc78lGUGGytJoVzQ==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
'@typescript-eslint/types': 6.7.3
'@typescript-eslint/visitor-keys': 6.7.3
dev: true
/@typescript-eslint/type-utils@6.1.0(eslint@8.50.0)(typescript@5.2.2):
resolution: {integrity: sha512-kFXBx6QWS1ZZ5Ni89TyT1X9Ag6RXVIVhqDs0vZE/jUeWlBv/ixq2diua6G7ece6+fXw3TvNRxP77/5mOMusx2w==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 6.1.0(typescript@5.2.2)
'@typescript-eslint/utils': 6.1.0(eslint@8.50.0)(typescript@5.2.2)
debug: 4.3.4(supports-color@8.1.1)
eslint: 8.50.0
ts-api-utils: 1.0.3(typescript@5.2.2)
typescript: 5.2.2
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/types@6.1.0:
resolution: {integrity: sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==}
engines: {node: ^16.0.0 || >=18.0.0}
dev: true
/@typescript-eslint/types@6.7.3:
resolution: {integrity: sha512-4g+de6roB2NFcfkZb439tigpAMnvEIg3rIjWQ+EM7IBaYt/CdJt6em9BJ4h4UpdgaBWdmx2iWsafHTrqmgIPNw==}
engines: {node: ^16.0.0 || >=18.0.0}
dev: true
/@typescript-eslint/typescript-estree@6.1.0(typescript@5.2.2):
resolution: {integrity: sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/types': 6.1.0
'@typescript-eslint/visitor-keys': 6.1.0
debug: 4.3.4(supports-color@8.1.1)
globby: 11.1.0
is-glob: 4.0.3
semver: 7.5.4
ts-api-utils: 1.0.3(typescript@5.2.2)
typescript: 5.2.2
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/typescript-estree@6.7.3(typescript@5.2.2):
resolution: {integrity: sha512-YLQ3tJoS4VxLFYHTw21oe1/vIZPRqAO91z6Uv0Ss2BKm/Ag7/RVQBcXTGcXhgJMdA4U+HrKuY5gWlJlvoaKZ5g==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/types': 6.7.3
'@typescript-eslint/visitor-keys': 6.7.3
debug: 4.3.4(supports-color@8.1.1)
globby: 11.1.0
is-glob: 4.0.3
semver: 7.5.4
ts-api-utils: 1.0.3(typescript@5.2.2)
typescript: 5.2.2
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/utils@6.1.0(eslint@8.50.0)(typescript@5.2.2):
resolution: {integrity: sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.50.0)
'@types/json-schema': 7.0.12
'@types/semver': 7.5.3
'@typescript-eslint/scope-manager': 6.1.0
'@typescript-eslint/types': 6.1.0
'@typescript-eslint/typescript-estree': 6.1.0(typescript@5.2.2)
eslint: 8.50.0
semver: 7.5.4
transitivePeerDependencies:
- supports-color
- typescript
dev: true
/@typescript-eslint/visitor-keys@6.1.0:
resolution: {integrity: sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
'@typescript-eslint/types': 6.1.0
eslint-visitor-keys: 3.4.3
dev: true
/@typescript-eslint/visitor-keys@6.7.3:
resolution: {integrity: sha512-HEVXkU9IB+nk9o63CeICMHxFWbHWr3E1mpilIQBe9+7L/lH97rleFLVtYsfnWB+JVMaiFnEaxvknvmIzX+CqVg==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
'@typescript-eslint/types': 6.7.3
eslint-visitor-keys: 3.4.3
dev: true
/@webassemblyjs/ast@1.11.6:
resolution: {integrity: sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==}
dependencies:
@ -3330,6 +3548,11 @@ packages:
is-string: 1.0.7
dev: true
/array-union@2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
dev: true
/array.prototype.findlastindex@1.2.2:
resolution: {integrity: sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==}
engines: {node: '>= 0.4'}
@ -3826,7 +4049,6 @@ packages:
/builtin-modules@3.3.0:
resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
engines: {node: '>=6'}
dev: false
/builtins@5.0.1:
resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==}
@ -3996,6 +4218,13 @@ packages:
resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==}
dev: false
/clean-regexp@1.0.0:
resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==}
engines: {node: '>=4'}
dependencies:
escape-string-regexp: 1.0.5
dev: true
/clean-stack@2.2.0:
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
engines: {node: '>=6'}
@ -4163,6 +4392,10 @@ packages:
/concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
/confusing-browser-globals@1.0.11:
resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==}
dev: true
/console-control-strings@1.1.0:
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
dev: true
@ -4651,6 +4884,13 @@ packages:
randombytes: 2.1.0
dev: true
/dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
dependencies:
path-type: 4.0.0
dev: true
/discontinuous-range@1.0.0:
resolution: {integrity: sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==}
@ -5053,6 +5293,15 @@ packages:
source-map: 0.6.1
dev: true
/eslint-config-prettier@8.10.0(eslint@8.50.0):
resolution: {integrity: sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==}
hasBin: true
peerDependencies:
eslint: '>=7.0.0'
dependencies:
eslint: 8.50.0
dev: true
/eslint-config-standard-jsx@11.0.0(eslint-plugin-react@7.33.2)(eslint@8.48.0):
resolution: {integrity: sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==}
peerDependencies:
@ -5072,11 +5321,85 @@ packages:
eslint-plugin-promise: ^6.0.0
dependencies:
eslint: 8.48.0
eslint-plugin-import: 2.28.1(eslint@8.48.0)
eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.3)(eslint@8.48.0)
eslint-plugin-n: 15.7.0(eslint@8.48.0)
eslint-plugin-promise: 6.1.1(eslint@8.48.0)
dev: true
/eslint-config-xo-react@0.27.0(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.33.2)(eslint@8.50.0):
resolution: {integrity: sha512-wiV215xQIn71XZyyVfaOXHaFpR1B14IJttwOjMi/eqUK1s+ojJdHr7eHqTLaGUfh6FKgWha1QNwePlIXx7mBUg==}
engines: {node: '>=12'}
peerDependencies:
eslint: '>=8.6.0'
eslint-plugin-react: '>=7.29.0'
eslint-plugin-react-hooks: '>=4.3.0'
dependencies:
eslint: 8.50.0
eslint-plugin-react: 7.33.2(eslint@8.50.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.50.0)
dev: true
/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.2.2):
resolution: {integrity: sha512-vPQssnRSUgBFOEfB/KY12CXwltwFSn4RSCfa+w7gjBC2PFQ7Yfgmyei+1XUZ3K+8LRGef2NMJUcxts7PldhDjg==}
engines: {node: '>=16'}
peerDependencies:
'@typescript-eslint/eslint-plugin': '>=6.0.0'
'@typescript-eslint/parser': '>=6.0.0'
eslint: '>=8.0.0'
typescript: '>=4.7'
dependencies:
'@typescript-eslint/eslint-plugin': 6.1.0(@typescript-eslint/parser@6.7.3)(eslint@8.50.0)(typescript@5.2.2)
'@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2)
eslint: 8.50.0
typescript: 5.2.2
dev: true
/eslint-config-xo@0.43.1(eslint@8.50.0):
resolution: {integrity: sha512-azv1L2PysRA0NkZOgbndUpN+581L7wPqkgJOgxxw3hxwXAbJgD6Hqb/SjHRiACifXt/AvxCzE/jIKFAlI7XjvQ==}
engines: {node: '>=12'}
peerDependencies:
eslint: '>=8.27.0'
dependencies:
confusing-browser-globals: 1.0.11
eslint: 8.50.0
dev: true
/eslint-config-zardoy@0.2.17(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.33.2)(eslint@8.50.0)(typescript@5.2.2):
resolution: {integrity: sha512-d31WsjyVSQqHbzTpBSmH96+nw5gwY2yhDbZatU89gr+U8ou1FRUkJSApYJUgmcINt8AQocj1RDDAVYmVSILZgQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
peerDependencies:
eslint: ^8.5.0
eslint-plugin-vue: ^8.4.1
typescript: ^4.5.2
vue-eslint-parser: ^8.2.0
peerDependenciesMeta:
eslint-plugin-vue:
optional: true
vue-eslint-parser:
optional: true
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.2.2)
'@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2)
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-plugin-react@7.33.2)(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.2.2)
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)
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)
typescript: 5.2.2
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- eslint-plugin-react
- eslint-plugin-react-hooks
- supports-color
dev: true
/eslint-import-resolver-node@0.3.9:
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
dependencies:
@ -5087,7 +5410,7 @@ packages:
- supports-color
dev: true
/eslint-module-utils@2.8.0(eslint-import-resolver-node@0.3.9)(eslint@8.48.0):
/eslint-module-utils@2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint@8.48.0):
resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
engines: {node: '>=4'}
peerDependencies:
@ -5108,6 +5431,7 @@ packages:
eslint-import-resolver-webpack:
optional: true
dependencies:
'@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2)
debug: 3.2.7(supports-color@8.1.1)
eslint: 8.48.0
eslint-import-resolver-node: 0.3.9
@ -5115,6 +5439,46 @@ packages:
- supports-color
dev: true
/eslint-module-utils@2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint@8.50.0):
resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
engines: {node: '>=4'}
peerDependencies:
'@typescript-eslint/parser': '*'
eslint: '*'
eslint-import-resolver-node: '*'
eslint-import-resolver-typescript: '*'
eslint-import-resolver-webpack: '*'
peerDependenciesMeta:
'@typescript-eslint/parser':
optional: true
eslint:
optional: true
eslint-import-resolver-node:
optional: true
eslint-import-resolver-typescript:
optional: true
eslint-import-resolver-webpack:
optional: true
dependencies:
'@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2)
debug: 3.2.7(supports-color@8.1.1)
eslint: 8.50.0
eslint-import-resolver-node: 0.3.9
transitivePeerDependencies:
- supports-color
dev: true
/eslint-plugin-es@3.0.1(eslint@8.50.0):
resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==}
engines: {node: '>=8.10.0'}
peerDependencies:
eslint: '>=4.19.1'
dependencies:
eslint: 8.50.0
eslint-utils: 2.1.0
regexpp: 3.2.0
dev: true
/eslint-plugin-es@4.1.0(eslint@8.48.0):
resolution: {integrity: sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==}
engines: {node: '>=8.10.0'}
@ -5126,7 +5490,51 @@ packages:
regexpp: 3.2.0
dev: true
/eslint-plugin-import@2.28.1(eslint@8.48.0):
/eslint-plugin-eslint-comments@3.2.0(eslint@8.50.0):
resolution: {integrity: sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==}
engines: {node: '>=6.5.0'}
peerDependencies:
eslint: '>=4.19.1'
dependencies:
escape-string-regexp: 1.0.5
eslint: 8.50.0
ignore: 5.2.4
dev: true
/eslint-plugin-import@2.27.5(@typescript-eslint/parser@6.7.3)(eslint@8.50.0):
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
engines: {node: '>=4'}
peerDependencies:
'@typescript-eslint/parser': '*'
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
peerDependenciesMeta:
'@typescript-eslint/parser':
optional: true
dependencies:
'@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2)
array-includes: 3.1.6
array.prototype.flat: 1.3.1
array.prototype.flatmap: 1.3.1
debug: 3.2.7(supports-color@8.1.1)
doctrine: 2.1.0
eslint: 8.50.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint@8.50.0)
has: 1.0.3
is-core-module: 2.13.0
is-glob: 4.0.3
minimatch: 3.1.2
object.values: 1.1.7
resolve: 1.22.4
semver: 6.3.1
tsconfig-paths: 3.14.2
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
dev: true
/eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.7.3)(eslint@8.48.0):
resolution: {integrity: sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==}
engines: {node: '>=4'}
peerDependencies:
@ -5136,6 +5544,7 @@ packages:
'@typescript-eslint/parser':
optional: true
dependencies:
'@typescript-eslint/parser': 6.7.3(eslint@8.50.0)(typescript@5.2.2)
array-includes: 3.1.6
array.prototype.findlastindex: 1.2.2
array.prototype.flat: 1.3.1
@ -5144,7 +5553,7 @@ packages:
doctrine: 2.1.0
eslint: 8.48.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.0(eslint-import-resolver-node@0.3.9)(eslint@8.48.0)
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.3)(eslint-import-resolver-node@0.3.9)(eslint@8.48.0)
has: 1.0.3
is-core-module: 2.13.0
is-glob: 4.0.3
@ -5177,6 +5586,21 @@ packages:
semver: 7.5.4
dev: true
/eslint-plugin-node@11.1.0(eslint@8.50.0):
resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==}
engines: {node: '>=8.10.0'}
peerDependencies:
eslint: '>=5.16.0'
dependencies:
eslint: 8.50.0
eslint-plugin-es: 3.0.1(eslint@8.50.0)
eslint-utils: 2.1.0
ignore: 5.2.4
minimatch: 3.1.2
resolve: 1.22.4
semver: 6.3.1
dev: true
/eslint-plugin-promise@6.1.1(eslint@8.48.0):
resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@ -5186,6 +5610,15 @@ packages:
eslint: 8.48.0
dev: true
/eslint-plugin-react-hooks@4.6.0(eslint@8.50.0):
resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==}
engines: {node: '>=10'}
peerDependencies:
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
dependencies:
eslint: 8.50.0
dev: true
/eslint-plugin-react@7.33.2(eslint@8.48.0):
resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==}
engines: {node: '>=4'}
@ -5211,6 +5644,64 @@ packages:
string.prototype.matchall: 4.0.8
dev: true
/eslint-plugin-react@7.33.2(eslint@8.50.0):
resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==}
engines: {node: '>=4'}
peerDependencies:
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
dependencies:
array-includes: 3.1.6
array.prototype.flatmap: 1.3.1
array.prototype.tosorted: 1.1.1
doctrine: 2.1.0
es-iterator-helpers: 1.0.14
eslint: 8.50.0
estraverse: 5.3.0
jsx-ast-utils: 3.3.5
minimatch: 3.1.2
object.entries: 1.1.7
object.fromentries: 2.0.6
object.hasown: 1.1.3
object.values: 1.1.7
prop-types: 15.8.1
resolve: 2.0.0-next.4
semver: 6.3.1
string.prototype.matchall: 4.0.8
dev: true
/eslint-plugin-sonarjs@0.19.0(eslint@8.50.0):
resolution: {integrity: sha512-6+s5oNk5TFtVlbRxqZN7FIGmjdPCYQKaTzFPmqieCmsU1kBYDzndTeQav0xtQNwZJWu5awWfTGe8Srq9xFOGnw==}
engines: {node: '>=14'}
peerDependencies:
eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
eslint: 8.50.0
dev: true
/eslint-plugin-unicorn@48.0.0(eslint@8.50.0):
resolution: {integrity: sha512-8fk/v3p1ro34JSVDBEmtOq6EEQRpMR0iTir79q69KnXFZ6DJyPkT3RAi+ZoTqhQMdDSpGh8BGR68ne1sP5cnAA==}
engines: {node: '>=16'}
peerDependencies:
eslint: '>=8.44.0'
dependencies:
'@babel/helper-validator-identifier': 7.22.5
'@eslint-community/eslint-utils': 4.4.0(eslint@8.50.0)
ci-info: 3.8.0
clean-regexp: 1.0.0
eslint: 8.50.0
esquery: 1.5.0
indent-string: 4.0.0
is-builtin-module: 3.2.1
jsesc: 3.0.2
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.5.4
strip-indent: 3.0.0
dev: true
/eslint-scope@5.1.1:
resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
engines: {node: '>=8.0.0'}
@ -5305,6 +5796,52 @@ packages:
- supports-color
dev: true
/eslint@8.50.0:
resolution: {integrity: sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
hasBin: true
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
'@humanwhocodes/module-importer': 1.0.1
'@nodelib/fs.walk': 1.2.8
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.3
debug: 4.3.4(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
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
graphemer: 1.4.0
ignore: 5.2.4
imurmurhash: 0.1.4
is-glob: 4.0.3
is-path-inside: 3.0.3
js-yaml: 4.1.0
json-stable-stringify-without-jsonify: 1.0.1
levn: 0.4.1
lodash.merge: 4.6.2
minimatch: 3.1.2
natural-compare: 1.4.0
optionator: 0.9.3
strip-ansi: 6.0.1
text-table: 0.2.0
transitivePeerDependencies:
- supports-color
dev: true
/espree@9.6.1:
resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@ -5527,6 +6064,17 @@ 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==}
engines: {node: '>=8.6.0'}
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
dev: true
/fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
@ -5908,6 +6456,13 @@ packages:
dependencies:
assert-plus: 1.0.0
/glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
dependencies:
is-glob: 4.0.3
dev: true
/glob-parent@6.0.2:
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
engines: {node: '>=10.13.0'}
@ -5989,6 +6544,18 @@ packages:
dependencies:
define-properties: 1.2.0
/globby@11.1.0:
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
engines: {node: '>=10'}
dependencies:
array-union: 2.1.0
dir-glob: 3.0.1
fast-glob: 3.3.1
ignore: 5.2.4
merge2: 1.4.1
slash: 3.0.0
dev: true
/gopd@1.0.1:
resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
dependencies:
@ -6400,6 +6967,13 @@ packages:
resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==}
dev: true
/is-builtin-module@3.2.1:
resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==}
engines: {node: '>=6'}
dependencies:
builtin-modules: 3.3.0
dev: true
/is-callable@1.2.7:
resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
engines: {node: '>= 0.4'}
@ -7310,13 +7884,18 @@ packages:
/jsesc@0.5.0:
resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==}
hasBin: true
dev: false
/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
dev: true
/json-buffer@3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
dev: true
@ -7776,6 +8355,11 @@ packages:
/merge-stream@2.0.0:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
/merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
dev: true
/merge@1.2.1:
resolution: {integrity: sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==}
dev: false
@ -7830,6 +8414,11 @@ packages:
dom-walk: 0.1.2
dev: false
/min-indent@1.0.1:
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
engines: {node: '>=4'}
dev: true
/minecraft-assets@1.9.0:
resolution: {integrity: sha512-KtvIRd9gcKlxbvrswGv1Ap9k7tVs//QW2ukp+8vJ28miYwkhUmYfjTZyElIG8KUXV/46wL2kDzLH8SJbXQ56Mg==}
dev: true
@ -8071,6 +8660,10 @@ packages:
stylis: 4.2.0
dev: false
/natural-compare-lite@1.4.0:
resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
dev: true
/natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
dev: true
@ -8548,7 +9141,6 @@ packages:
/path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
dev: false
/pbkdf2@3.1.2:
resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==}
@ -8641,6 +9233,11 @@ packages:
find-up: 4.1.0
dev: true
/pluralize@8.0.0:
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
engines: {node: '>=4'}
dev: true
/pngjs@3.4.0:
resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==}
engines: {node: '>=4.0.0'}
@ -9140,6 +9737,15 @@ packages:
dependencies:
loose-envify: 1.4.0
/read-pkg-up@7.0.1:
resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==}
engines: {node: '>=8'}
dependencies:
find-up: 4.1.0
read-pkg: 5.2.0
type-fest: 0.8.1
dev: true
/read-pkg@3.0.0:
resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==}
engines: {node: '>=4'}
@ -9149,6 +9755,16 @@ packages:
path-type: 3.0.0
dev: true
/read-pkg@5.2.0:
resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==}
engines: {node: '>=8'}
dependencies:
'@types/normalize-package-data': 2.4.2
normalize-package-data: 2.5.0
parse-json: 5.2.0
type-fest: 0.6.0
dev: true
/readable-stream@2.3.8:
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
dependencies:
@ -9226,6 +9842,11 @@ packages:
'@babel/runtime': 7.22.11
dev: false
/regexp-tree@0.1.27:
resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==}
hasBin: true
dev: true
/regexp.prototype.flags@1.5.0:
resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==}
engines: {node: '>= 0.4'}
@ -9251,6 +9872,13 @@ packages:
unicode-match-property-value-ecmascript: 2.1.0
dev: false
/regjsparser@0.10.0:
resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==}
hasBin: true
dependencies:
jsesc: 0.5.0
dev: true
/regjsparser@0.9.1:
resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==}
hasBin: true
@ -9966,7 +10594,7 @@ packages:
xdg-basedir: 4.0.0
dev: true
/standard@17.0.0:
/standard@17.0.0(@typescript-eslint/parser@6.7.3):
resolution: {integrity: sha512-GlCM9nzbLUkr+TYR5I2WQoIah4wHA2lMauqbyPLV/oI5gJxqhHzhjl9EG2N0lr/nRqI3KCbCvm/W3smxvLaChA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
hasBin: true
@ -9974,7 +10602,7 @@ packages:
eslint: 8.48.0
eslint-config-standard: 17.0.0(eslint-plugin-import@2.28.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.48.0)
eslint-config-standard-jsx: 11.0.0(eslint-plugin-react@7.33.2)(eslint@8.48.0)
eslint-plugin-import: 2.28.1(eslint@8.48.0)
eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.3)(eslint@8.48.0)
eslint-plugin-n: 15.7.0(eslint@8.48.0)
eslint-plugin-promise: 6.1.1(eslint@8.48.0)
eslint-plugin-react: 7.33.2(eslint@8.48.0)
@ -10126,6 +10754,13 @@ packages:
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
engines: {node: '>=6'}
/strip-indent@3.0.0:
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
engines: {node: '>=8'}
dependencies:
min-indent: 1.0.1
dev: true
/strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
@ -10403,6 +11038,15 @@ packages:
utf8-byte-length: 1.0.4
dev: false
/ts-api-utils@1.0.3(typescript@5.2.2):
resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==}
engines: {node: '>=16.13.0'}
peerDependencies:
typescript: '>=4.2.0'
dependencies:
typescript: 5.2.2
dev: true
/ts-easing@0.2.0:
resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==}
dev: false
@ -10458,6 +11102,16 @@ packages:
engines: {node: '>=6'}
dev: true
/type-fest@0.6.0:
resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==}
engines: {node: '>=8'}
dev: true
/type-fest@0.8.1:
resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==}
engines: {node: '>=8'}
dev: true
/type-fest@2.19.0:
resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
engines: {node: '>=12.20'}

View file

@ -1,13 +1,13 @@
//@ts-check
import { fsState, loadSave } from './loadSave'
import { join } from 'path'
import { promisify } from 'util'
import fs from 'fs'
import { oneOf } from '@zardoy/utils'
import JSZip from 'jszip'
import { join } from 'path'
import * as browserfs from 'browserfs'
import { options } from './optionsStorage'
import { promisify } from 'util'
import * as browserfs from 'browserfs'
import fs from 'fs'
import { fsState, loadSave } from './loadSave'
import { installTexturePack, updateTexturePackInstalledState } from './texturePack'
browserfs.install(window)
@ -15,7 +15,7 @@ browserfs.install(window)
const deafultMountablePoints = {
"/world": { fs: "LocalStorage" },
'/userData': { fs: 'IndexedDB' },
};
}
browserfs.configure({
fs: 'MountableFileSystem',
options: deafultMountablePoints,
@ -26,10 +26,9 @@ browserfs.configure({
export const forceCachedDataPaths = {}
//@ts-ignore
//@ts-expect-error
fs.promises = new Proxy(Object.fromEntries(['readFile', 'writeFile', 'stat', 'mkdir', 'rmdir', 'unlink', 'rename', /* 'copyFile', */'readdir'].map(key => [key, promisify(fs[key])])), {
get(target, p, receiver) {
//@ts-ignore
get(target, p: string, receiver) {
if (!target[p]) throw new Error(`Not implemented fs.promises.${p}`)
return (...args) => {
// browser fs bug: if path doesn't start with / dirname will return . which would cause infinite loop, so we need to normalize paths
@ -50,20 +49,20 @@ fs.promises = new Proxy(Object.fromEntries(['readFile', 'writeFile', 'stat', 'mk
if (p === 'open' && fsState.isReadonly) {
args[1] = 'r' // read-only, zipfs throw otherwise
}
//@ts-ignore
return target[p](...args)
}
}
})
//@ts-ignore
//@ts-expect-error
fs.promises.open = async (...args) => {
const fd = await promisify(fs.open)(...args)
return {
...Object.fromEntries(['read', 'write', 'close'].map(x => [x, async (...args) => {
return await new Promise(resolve => {
return new Promise(resolve => {
// todo it results in world corruption on interactions eg block placements
if (x === 'write' && fsState.isReadonly) {
return resolve({ buffer: Buffer.from([]), bytesRead: 0 })
resolve({ buffer: Buffer.from([]), bytesRead: 0 })
return
}
fs[x](fd, ...args, (err, bytesRead, buffer) => {
@ -80,7 +79,7 @@ fs.promises.open = async (...args) => {
// for debugging
fd,
filename: args[0],
close: () => {
async close() {
return new Promise<void>(resolve => {
fs.close(fd, (err) => {
if (err) {
@ -96,7 +95,7 @@ fs.promises.open = async (...args) => {
// for testing purposes, todo move it to core patch
const removeFileRecursiveSync = (path) => {
fs.readdirSync(path).forEach((file) => {
for (const file of fs.readdirSync(path)) {
const curPath = join(path, file)
if (fs.lstatSync(curPath).isDirectory()) {
// recurse
@ -106,30 +105,26 @@ const removeFileRecursiveSync = (path) => {
// delete file
fs.unlinkSync(curPath)
}
})
}
}
window.removeFileRecursiveSync = removeFileRecursiveSync
// todo it still doesnt clean the storage, need to debug
export async function removeFileRecursiveAsync(path) {
try {
const files = await fs.promises.readdir(path);
for (const file of files) {
const curPath = join(path, file);
const stats = await fs.promises.stat(curPath);
if (stats.isDirectory()) {
// Recurse
await removeFileRecursiveAsync(curPath);
} else {
// Delete file
await fs.promises.unlink(curPath);
}
const files = await fs.promises.readdir(path)
for (const file of files) {
const curPath = join(path, file)
const stats = await fs.promises.stat(curPath)
if (stats.isDirectory()) {
// Recurse
await removeFileRecursiveAsync(curPath)
} else {
// Delete file
await fs.promises.unlink(curPath)
}
await fs.promises.rmdir(path);
} catch (error) {
throw error;
}
await fs.promises.rmdir(path)
}
@ -181,9 +176,9 @@ export const openWorldDirectory = async (dragndropHandle?: FileSystemDirectoryHa
const tryToDetectResourcePack = async (file: File | ArrayBuffer) => {
const askInstall = async () => {
return alert('ATM You can install texturepacks only via options menu. WIll be fixed')
if (confirm('Resource pack detected, do you want to install it?')) {
await installTexturePack(file)
}
// if (confirm('Resource pack detected, do you want to install it?')) {
// await installTexturePack(file)
// }
}
if (fs.existsSync('/world/pack.mcmeta')) {
@ -243,7 +238,7 @@ const openWorldZipInner = async (file: File | ArrayBuffer, name = file['name'])
await loadSave()
} else {
const dirs = fs.readdirSync('/world')
let availableWorlds: string[] = []
const availableWorlds: string[] = []
for (const dir of dirs) {
if (fs.existsSync(`/world/${dir}/level.dat`)) {
availableWorlds.push(dir)

View file

@ -1,6 +1,6 @@
import JSZip from 'jszip'
import fs from 'fs'
import { join } from 'path'
import JSZip from 'jszip'
import { fsState } from './loadSave'
import { closeWan, openToWanAndCopyJoinLink } from './localServerMultiplayer'
@ -32,7 +32,7 @@ async function addFolderToZip(folderPath, zip, relativePath) {
const exportWorld = async () => {
// todo issue into chat warning if fs is writable!
const zip = new JSZip()
let worldFolder: string = localServer.options.worldFolder
let {worldFolder} = localServer.options
if (!worldFolder.startsWith('/')) worldFolder = `/${worldFolder}`
await addFolderToZip(worldFolder, zip, '')
@ -64,21 +64,21 @@ const commands = [
},
{
command: ['/publish', '/share'],
invoke: async () => {
async invoke() {
const text = await openToWanAndCopyJoinLink(writeText)
if (text) writeText(text)
}
},
{
command: ['/close'],
invoke: () => {
invoke() {
const text = closeWan()
if (text) writeText(text)
}
},
{
command: '/reset-world -y',
invoke: async () => {
async invoke() {
if (fsState.inMemorySave) return
// todo for testing purposes
sessionStorage.oldData = localStorage
@ -90,7 +90,7 @@ const commands = [
},
{
command: ['/save'],
invoke: () => {
invoke() {
saveWorld()
}
}

View file

@ -1,12 +1,12 @@
//@ts-check
import { Vec3 } from 'vec3'
import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal } from './globalState'
import { proxy, subscribe } from 'valtio'
import { ControMax } from 'contro-max/build/controMax'
import { CommandEventArgument, SchemaCommandInput } from 'contro-max/build/types'
import { stringStartsWith } from 'contro-max/build/stringUtils'
import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal } from './globalState'
import { reloadChunks } from './utils'
// doesnt seem to work for now
@ -137,6 +137,7 @@ const onTriggerOrReleased = (command: Command, pressed: boolean) => {
}
if (stringStartsWith(command, 'general')) {
// handle general commands
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
switch (command) {
case 'general.jump':
bot.setControlState('jump', pressed)
@ -189,6 +190,7 @@ contro.on('trigger', ({ command }) => {
onTriggerOrReleased(command, true)
if (stringStartsWith(command, 'general')) {
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
switch (command) {
case 'general.inventory':
document.exitPointerLock?.()
@ -225,7 +227,7 @@ document.addEventListener('keydown', (e) => {
if (hardcodedPressedKeys.has('F3')) {
// reload chunks
if (e.code === 'KeyA') {
//@ts-ignore
//@ts-expect-error
const loadedChunks = Object.entries(worldView.loadedChunks).filter(([, v]) => v).map(([key]) => key.split(',').map(Number))
for (const [x, z] of loadedChunks) {
worldView.unloadChunk({ x, z })

View file

@ -1,7 +1,7 @@
import prettyBytes from 'pretty-bytes'
import { openWorldZip } from './browserfs'
import { getResourcePackName, installTexturePack, resourcePackState, updateTexturePackInstalledState } from './texturePack'
import { setLoadingScreenStatus } from './utils'
import prettyBytes from 'pretty-bytes'
const getConstantFilesize = (bytes: number) => {
return prettyBytes(bytes, { minimumFractionDigits: 2, maximumFractionDigits: 2 })
@ -15,14 +15,14 @@ export default async () => {
if (texturepack) mapUrl = texturepack
if (!mapUrl) return false
if (!texturepack) {
const menu = document.getElementById('play-screen')
menu.style = 'display: none;'
} else {
if (texturepack) {
await updateTexturePackInstalledState()
if (resourcePackState.resourcePackInstalled) {
if (!confirm(`You are going to install a new texturepack which would override a current one: ${getResourcePackName()} Continue?`)) return
if (!confirm(`You are going to install a new texturepack which would override a current one: ${await getResourcePackName()} Continue?`)) return
}
} else {
const menu = document.getElementById('play-screen')
menu.style = 'display: none;'
}
const name = mapUrl.slice(mapUrl.lastIndexOf('/') + 1).slice(-25)
const downloadThing = texturepack ? 'texturepack' : 'world'
@ -42,6 +42,7 @@ export default async () => {
async start(controller) {
const reader = response.body.getReader()
// eslint-disable-next-line no-constant-condition
while (true) {
const { done, value } = await reader.read()

View file

@ -1,5 +1,5 @@
import * as nbt from 'prismarine-nbt'
import { promisify } from 'util'
import * as nbt from 'prismarine-nbt'
import { showNotification } from './menus/notification'
import { openWorldDirectory, openWorldZip } from './browserfs'
import { isGameActive } from './globalState'
@ -8,7 +8,7 @@ const parseNbt = promisify(nbt.parse)
window.nbt = nbt;
// todo display drop zone
["drag", "dragstart", "dragend", "dragover", "dragenter", "dragleave", "drop"].forEach(event => {
for (const event of ["drag", "dragstart", "dragend", "dragover", "dragenter", "dragleave", "drop"]) {
window.addEventListener(event, (e: any) => {
if (e.dataTransfer && !e.dataTransfer.types.includes("Files")) {
// e.dataTransfer.effectAllowed = "none"
@ -16,7 +16,7 @@ window.nbt = nbt;
}
e.preventDefault()
})
})
}
window.addEventListener("drop", async e => {
if (!e.dataTransfer?.files.length) return
const { items } = e.dataTransfer
@ -32,7 +32,7 @@ window.addEventListener("drop", async e => {
alert('Exit current world first, before loading a new one.')
return
}
await openWorldDirectory(filehandle as FileSystemDirectoryHandle)
await openWorldDirectory(filehandle )
}
} else {
await handleDroppedFile(item.getAsFile())

View file

@ -45,7 +45,7 @@ const showModalInner = (modal: Modal) => {
export const showModal = (elem: (HTMLElement & Record<string, any>) | { reactType: string }) => {
const resolved = elem instanceof HTMLElement ? { elem: ref(elem) } : elem
const curModal = activeModalStack.slice(-1)[0]
const curModal = activeModalStack.at(-1)
if (elem === curModal?.elem || !showModalInner(resolved)) return
if (curModal) defaultModalActions.hide(curModal)
activeModalStack.push(resolved)
@ -55,7 +55,7 @@ export const showModal = (elem: (HTMLElement & Record<string, any>) | { reactTyp
*
* @returns true if previous modal was restored
*/
export const hideModal = (modal = activeModalStack.slice(-1)[0], data: any = undefined, options: { force?: boolean; restorePrevious?: boolean } = {}) => {
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 = modal.elem?.hide?.(data)
@ -66,7 +66,7 @@ export const hideModal = (modal = activeModalStack.slice(-1)[0], data: any = und
if (!cancel || cancel === customDisplayManageKeyword) {
if (cancel !== customDisplayManageKeyword) defaultModalActions.hide(modal)
activeModalStack.pop()
const newModal = activeModalStack.slice(-1)[0]
const newModal = activeModalStack.at(-1)
if (newModal && restorePrevious) {
// would be great to ignore cancel I guess?
showModalInner(newModal)
@ -79,10 +79,10 @@ export const hideCurrentModal = (_data = undefined, restoredActions = undefined)
if (hideModal(undefined, undefined)) {
restoredActions?.()
if (activeModalStack.length === 0) {
if (!isGameActive(false)) {
showModal(document.getElementById('title-screen'))
} else {
if (isGameActive(false)) {
pointerLock.requestPointerLock()
} else {
showModal(document.getElementById('title-screen'))
}
}
}
@ -149,8 +149,8 @@ window.inspectPlayer = () => require('fs').promises.readFile('/world/playerdata/
window.addEventListener('beforeunload', (event) => {
// todo-low maybe exclude chat?
if (!isGameActive(true) && activeModalStack.at(-1)?.elem.id !== 'chat') return
if (sessionStorage.lastReload && options.preventDevReloadWhilePlaying === false) return
if (options.closeConfirmation === false) return
if (sessionStorage.lastReload && !options.preventDevReloadWhilePlaying) return
if (!options.closeConfirmation) return
// For major browsers doning only this is enough
event.preventDefault()

6
src/globals.d.ts vendored
View file

@ -30,10 +30,10 @@ type StringKeys<T extends object> = Extract<keyof T, string>
interface ObjectConstructor {
keys<T extends object>(obj: T): StringKeys<T>[]
entries<T extends object>(obj: T): [StringKeys<T>, T[keyof T]][]
keys<T extends object>(obj: T): Array<StringKeys<T>>
entries<T extends object>(obj: T): Array<[StringKeys<T>, T[keyof T]]>
// todo review https://stackoverflow.com/questions/57390305/trying-to-get-fromentries-type-right
fromEntries<T extends [string, any][]>(obj: T): Record<T[number][0], T[number][1]>
fromEntries<T extends Array<[string, any]>>(obj: T): Record<T[number][0], T[number][1]>
assign<T extends Record<string, any>, K extends Record<string, any>>(target: T, source: K): asserts target is T & K
}

View file

@ -1,3 +1,4 @@
/* eslint-disable import/order */
import './importsWorkaround'
import './styles.css'
import './globals'
@ -25,9 +26,9 @@ import './menus/advanced_options_screen'
import { notification } from './menus/notification'
import './menus/title_screen'
import './optionsStorage'
import { options, watchValue } from './optionsStorage'
import './reactUi.jsx'
import './controls'
import { contro } from './controls'
import './dragndrop'
import './browserfs'
import './eruda'
@ -75,25 +76,24 @@ import {
import { startLocalServer, unsupportedLocalServerFeatures } from './createLocalServer'
import serverOptions from './defaultLocalServerOptions'
import updateTime from './updateTime'
import { options, watchValue } from './optionsStorage'
import { subscribeKey } from 'valtio/utils'
import _ from 'lodash'
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
if ('serviceWorker' in navigator && !isCypress() && process.env.NODE_ENV !== 'development') {
window.addEventListener('load', () => {
navigator.serviceWorker.register('./service-worker.js').then(registration => {
console.log('SW registered: ', registration)
console.log('SW registered:', registration)
}).catch(registrationError => {
console.log('SW registration failed: ', registrationError)
console.log('SW registration failed:', registrationError)
})
})
}
@ -101,10 +101,8 @@ if ('serviceWorker' in navigator && !isCypress() && process.env.NODE_ENV !== 'de
// ACTUAL CODE
// todo stats-gl
let stats
let stats2
stats = new Stats()
stats2 = new Stats()
const stats = new Stats()
const stats2 = new Stats()
stats2.showPanel(2)
document.body.appendChild(stats.dom)
@ -121,19 +119,6 @@ if (localStorage.hideStats || isCypress()) {
stats2.dom.style.display = 'none'
}
// const debugPitch = document.createElement('span')
// debugPitch.style.cssText = `
// position: absolute;
// top: 0;
// right: 0;
// z-index: 100;
// color:white;
// `
// document.body.appendChild(debugPitch)
const maxPitch = 0.5 * Math.PI
const minPitch = -0.5 * Math.PI
// Create three.js context, add to page
const renderer = new THREE.WebGLRenderer()
renderer.setPixelRatio(window.devicePixelRatio || 1) // todo this value is too high on ios, need to check, probably we should use avg, also need to make it configurable
@ -163,7 +148,7 @@ const renderFrame = (time: DOMHighResTimeStamp) => {
delta += time - lastTime
lastTime = time
if (delta > renderInterval) {
delta = delta % renderInterval
delta %= renderInterval
// continue rendering
} else {
return
@ -207,7 +192,6 @@ function onCameraMove(e) {
lastMouseMove = now
let { mouseSensX, mouseSensY } = options
if (mouseSensY === true) mouseSensY = mouseSensX
// debugPitch.innerText = +debugPitch.innerText + e.movementX
mouseMovePostHandle({
x: e.movementX * mouseSensX * 0.0001,
y: e.movementY * mouseSensY * 0.0001
@ -234,7 +218,7 @@ async function main() {
connect({ server: '', port: '', proxy: '', singleplayer: true, username: options.localUsername, password: '', serverOverrides })
}
document.querySelector('#title-screen').addEventListener('singleplayer', (e) => {
//@ts-ignore
//@ts-expect-error
connectSingleplayer(e.detail)
})
const qs = new URLSearchParams(window.location.search)
@ -247,9 +231,7 @@ async function main() {
}
let listeners = []
let disposables = []
let timeouts = []
let intervals = []
// only for dom listeners (no removeAllListeners)
// todo refactor them out of connect fn instead
const registerListener: import('./utilsTs').RegisterListener = (target, event, callback) => {
@ -257,16 +239,14 @@ const registerListener: import('./utilsTs').RegisterListener = (target, event, c
listeners.push({ target, event, callback })
}
const removeAllListeners = () => {
listeners.forEach(({ target, event, callback }) => {
for (const { target, event, callback } of listeners) {
target.removeEventListener(event, callback)
})
listeners = []
for (const disposable of disposables) {
disposable()
}
disposables = []
listeners = []
}
// todo
// eslint-disable-next-line complexity
async function connect(connectOptions: {
server: any; port?: string; singleplayer?: any; username: any; password: any; proxy: any; botVersion?: any; serverOverrides?; peerId?: string
}) {
@ -278,15 +258,8 @@ async function connect(connectOptions: {
const p2pMultiplayer = !!connectOptions.peerId
miscUiState.singleplayer = singeplayer
miscUiState.flyingSquid = singeplayer || p2pMultiplayer
const oldSetInterval = window.setInterval
// @ts-ignore
window.setInterval = (callback, ms) => {
const id = oldSetInterval.call(window, callback, ms)
timeouts.push(id)
return id
}
const oldSetTimeout = window.setTimeout
//@ts-ignore
//@ts-expect-error
window.setTimeout = (callback, ms) => {
const id = oldSetTimeout.call(window, callback, ms)
timeouts.push(id)
@ -295,24 +268,24 @@ async function connect(connectOptions: {
const { renderDistance, maxMultiplayerRenderDistance } = options
const hostprompt = connectOptions.server
const proxyprompt = connectOptions.proxy
const username = connectOptions.username
const password = connectOptions.password
const { username } = connectOptions
const { password } = connectOptions
let host, port, proxy, proxyport
if (!hostprompt.includes(':')) {
host = hostprompt
port = 25565
} else {
let host; let port; let proxy; let proxyport
if (hostprompt.includes(':')) {
[host, port] = hostprompt.split(':')
port = parseInt(port, 10)
} else {
host = hostprompt
port = 25_565
}
if (!proxyprompt.includes(':')) {
proxy = proxyprompt
proxyport = undefined
} else {
if (proxyprompt.includes(':')) {
[proxy, proxyport] = proxyprompt.split(':')
proxyport = parseInt(proxyport, 10)
} else {
proxy = proxyprompt
proxyport = undefined
}
console.log(`connecting to ${host} ${port} with ${username}`)
@ -338,10 +311,6 @@ async function connect(connectOptions: {
clearTimeout(timeout)
}
timeouts = []
for (const interval of intervals) {
clearInterval(interval)
}
intervals = []
}
const handleError = (err) => {
console.log('Encountered error!', err)
@ -389,7 +358,7 @@ async function connect(connectOptions: {
// console.error(err)
// throw new Error(`Proxy server ${proxy}:${proxyport} is not available`)
// }
//@ts-ignore
//@ts-expect-error
net.setProxy({ hostname: proxy, port: proxyport })
}
@ -444,7 +413,7 @@ async function connect(connectOptions: {
bot = mineflayer.createBot({
host,
port,
version: !connectOptions.botVersion ? false : connectOptions.botVersion,
version: connectOptions.botVersion || false,
...p2pMultiplayer ? {
stream: await connectToPeer(connectOptions.peerId),
} : {},
@ -483,7 +452,7 @@ async function connect(connectOptions: {
} else {
bot._client.socket.on('connect', () => {
console.log('TCP connection established')
//@ts-ignore
//@ts-expect-error
bot._client.socket._ws.addEventListener('close', () => {
console.log('TCP connection closed')
setTimeout(() => {
@ -499,7 +468,7 @@ async function connect(connectOptions: {
}
if (!bot) return
let p2pConnectTimeout = p2pMultiplayer ? setTimeout(() => { throw new Error('Spawn timeout. There might be error on other side, check console.') }, 20_000) : undefined
const p2pConnectTimeout = p2pMultiplayer ? setTimeout(() => { throw new Error('Spawn timeout. There might be error on other side, check console.') }, 20_000) : undefined
hud.preload(bot)
// bot.on('inject_allowed', () => {
@ -539,7 +508,7 @@ async function connect(connectOptions: {
console.log('bot spawned - starting viewer')
const version = bot.version
const { version } = bot
const center = bot.entity.position
@ -611,6 +580,8 @@ async function connect(connectOptions: {
setLoadingScreenStatus('Setting callbacks')
const maxPitch = 0.5 * Math.PI
const minPitch = -0.5 * Math.PI
mouseMovePostHandle = ({ x, y }) => {
bot.entity.pitch -= y
bot.entity.pitch = Math.max(minPitch, Math.min(maxPitch, bot.entity.pitch))
@ -743,7 +714,7 @@ async function connect(connectOptions: {
hud.style.display = 'block'
blockInteraction.init()
setTimeout(function () {
setTimeout(() => {
errorAbortController.abort()
if (loadingScreen.hasError) return
// remove loading screen, wait a second to make sure a frame has properly rendered
@ -769,15 +740,13 @@ window.addEventListener('keydown', (e) => {
pointerLock.justHitEscape = true
}
})
} else {
if (pointerLock.hasPointerLock) {
document.exitPointerLock()
if (options.autoExitFullscreen) {
document.exitFullscreen()
}
} else {
document.dispatchEvent(new Event('pointerlockchange'))
} else if (pointerLock.hasPointerLock) {
document.exitPointerLock()
if (options.autoExitFullscreen) {
document.exitFullscreen()
}
} else {
document.dispatchEvent(new Event('pointerlockchange'))
}
})
@ -793,9 +762,9 @@ window.addEventListener('keydown', (e) => {
addPanoramaCubeMap()
showModal(document.getElementById('title-screen'))
main()
void main()
downloadAndOpenFile().then((downloadAction) => {
if (downloadAction !== false) return
if (downloadAction) return
window.addEventListener('hud-ready', (e) => {
// try to connect to peer

View file

@ -1,16 +1,16 @@
import { subscribe } from 'valtio'
import { activeModalStack, hideCurrentModal, miscUiState } from './globalState'
import { showInventory } from 'minecraft-inventory-gui/web/ext.mjs'
import InventoryGui from 'minecraft-assets/minecraft-assets/data/1.17.1/gui/container/inventory.png'
import Dirt from 'minecraft-assets/minecraft-assets/data/1.17.1/blocks/dirt.png'
import { subscribeKey } from 'valtio/utils'
import MinecraftData from 'minecraft-data'
import invspriteJson from './invsprite.json'
import { getVersion } from 'prismarine-viewer/viewer/lib/version'
import invspriteJson from './invsprite.json'
import { activeModalStack, hideCurrentModal, miscUiState } from './globalState'
const loadedImages = new Map<string, HTMLImageElement>()
export type BlockStates = Record<string, null | {
variants: Record<string, {
variants: Record<string, Array<{
model: {
textures: {
up: {
@ -21,7 +21,7 @@ export type BlockStates = Record<string, null | {
}
}
}
}[]>
}>>
}>
let blockStates: BlockStates
@ -37,7 +37,7 @@ subscribeKey(miscUiState, 'gameLoaded', async () => {
// on game load
version = getVersion(bot.version)
blockStates = await fetch(`blocksStates/${version}.json`).then(res => res.json())
blockStates = await fetch(`blocksStates/${version}.json`).then(async res => res.json())
getImage({ path: 'blocks', } as any)
getImage({ path: 'invsprite', } as any)
mcData = MinecraftData(version)
@ -53,7 +53,7 @@ const findBlockStateTexturesAtlas = (name) => {
const getBlockData = (name) => {
const blocksImg = loadedImages.get('blocks')
if (!blocksImg || !blocksImg.width) return
if (!blocksImg?.width) return
const data = findBlockStateTexturesAtlas(name)
if (!data) return
@ -79,7 +79,7 @@ const getBlockData = (name) => {
const getItemSlice = (name) => {
const invspriteImg = loadedImages.get('invsprite')
if (!invspriteImg || !invspriteImg.width) return
if (!invspriteImg?.width) return
const { x, y } = invspriteJson[name] ?? /* unknown item */ { x: 0, y: 0 }
const sprite = [x, y, 32, 32]
@ -131,7 +131,7 @@ const upInventory = () => {
}
subscribe(activeModalStack, () => {
const inventoryOpened = activeModalStack.slice(-1)[0]?.reactType === 'inventory'
const inventoryOpened = activeModalStack.at(-1)?.reactType === 'inventory'
if (inventoryOpened) {
const inv = showInventory(undefined, getImage, {}, bot)
inv.canvas.style.zIndex = 10

View file

@ -1,12 +1,12 @@
import fs from 'fs'
import { promisify } from 'util'
import { supportedVersions } from 'flying-squid/src/lib/version'
import * as nbt from 'prismarine-nbt'
import { promisify } from 'util'
import { options } from './optionsStorage'
import { proxy } from 'valtio'
import { gzip } from 'node-gzip'
import { options } from './optionsStorage'
import { nameToMcOfflineUUID } from './utils'
import { forceCachedDataPaths } from './browserfs'
import { gzip } from 'node-gzip'
const parseNbt = promisify(nbt.parse)
@ -20,11 +20,14 @@ export const fsState = proxy({
const PROPOSE_BACKUP = true
// eslint-disable-next-line complexity
export const loadSave = async (root = '/world') => {
const disablePrompts = options.disableLoadPrompts
// todo do it in singleplayer as well
// eslint-disable-next-line guard-for-in
for (const key in forceCachedDataPaths) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete forceCachedDataPaths[key]
}
@ -35,10 +38,10 @@ export const loadSave = async (root = '/world') => {
levelDatContent = await fs.promises.readFile(`${root}/level.dat`)
} catch (err) {
if (err.code === 'ENOENT') {
if (!fsState.isReadonly) {
warnings.push('level.dat not found, world in current folder will be created')
} else {
if (fsState.isReadonly) {
throw new Error('level.dat not found, ensure you are loading world folder')
} else {
warnings.push('level.dat not found, world in current folder will be created')
}
} else {
throw err
@ -54,7 +57,7 @@ export const loadSave = async (root = '/world') => {
const qs = new URLSearchParams(window.location.search)
version = levelDat.Version?.Name ?? qs.get('mapVersion')
if (!version) {
const newVersion = disablePrompts ? '1.8.8' : prompt(`In 1.8 and before world save doesn\'t contain version info, please enter version you want to use to load the world.\nSupported versions ${supportedVersions.join(', ')}`, '1.8.8')
const newVersion = disablePrompts ? '1.8.8' : prompt(`In 1.8 and before world save doesn't contain version info, please enter version you want to use to load the world.\nSupported versions ${supportedVersions.join(', ')}`, '1.8.8')
if (!newVersion) return
version = newVersion
}
@ -131,9 +134,9 @@ export const loadSave = async (root = '/world') => {
name: 'superflat'
}
} : {},
...root !== '/world' ? {
...root === '/world' ? {} : {
'worldFolder': root
} : {}
}
},
}))
}

View file

@ -84,7 +84,7 @@ export const openToWanAndCopyJoinLink = async (writeText: (text) => void, doCopy
console.error(error)
writeText(error.message)
})
return await new Promise<string>(resolve => {
return new Promise<string>(resolve => {
peer.on('open', async () => {
await copyJoinLink()
resolve('Copied join link to clipboard')
@ -120,7 +120,7 @@ export const connectToPeer = async (peerId: string) => {
connection.once('error', (error) => {
console.log(error.type, error.name)
console.log(error)
return reject(error.message)
reject(error.message);
})
connection.once('open', resolve)
}))

View file

@ -62,11 +62,11 @@ export const watchValue: WatchValue = (proxy, callback) => {
return Reflect.get(target, p, receiver)
},
}))
watchedProps.forEach(prop => {
for (const prop of watchedProps) {
subscribeKey(proxy, prop, () => {
callback(proxy)
})
})
}
}
watchValue(options, o => {

View file

@ -37,7 +37,7 @@ const possiblyLoadPanoramaFromResourcePack = async (file) => {
else return join('extra-textures/background', file)
}
const updateResourecePackSupportPanorama = async () => {
const updateResourcePackSupportPanorama = async () => {
try {
await fs.promises.readFile(fromTexturePackPath(join(panoramaResourcePackPath, panoramaFiles[0])), 'base64')
panoramaUsesResourePack = true
@ -48,7 +48,7 @@ const updateResourecePackSupportPanorama = async () => {
subscribeKey(resourcePackState, 'resourcePackInstalled', async () => {
const oldState = panoramaUsesResourePack
const newState = resourcePackState.resourcePackInstalled && (await updateResourecePackSupportPanorama(), panoramaUsesResourePack)
const newState = resourcePackState.resourcePackInstalled && (await updateResourcePackSupportPanorama(), panoramaUsesResourePack)
if (newState === oldState) return
removePanorama()
addPanoramaCubeMap()
@ -56,6 +56,7 @@ subscribeKey(resourcePackState, 'resourcePackInstalled', async () => {
// Menu panorama background
export async function addPanoramaCubeMap () {
if (panoramaCubeMap) return
// remove all existing object in the viewer.scene
// viewer.scene.children = []
@ -68,7 +69,7 @@ export async function addPanoramaCubeMap () {
const loader = new THREE.TextureLoader()
let panorMaterials = []
await updateResourecePackSupportPanorama()
await updateResourcePackSupportPanorama()
for (const file of panoramaFiles) {
panorMaterials.push(new THREE.MeshBasicMaterial({
map: loader.load(await possiblyLoadPanoramaFromResourcePack(file)),

View file

@ -3,12 +3,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 DeathScreen from './react/DeathScreen'
import { useSnapshot } from 'valtio'
import { contro } from './controls'
import { QRCodeSVG } from 'qrcode.react'
import { createPortal } from 'react-dom'
import { contro } from './controls'
import { activeModalStack, isGameActive, miscUiState } from './globalState'
import { options, watchValue } from './optionsStorage'
// todo
@ -17,7 +17,7 @@ useInterfaceState.setState({
uiCustomization: {
touchButtonSize: 40,
},
updateCoord: ([coord, state]) => {
updateCoord([coord, state]) {
const coordToAction = [
['z', -1, 'KeyW'],
['z', 1, 'KeyS'],
@ -27,14 +27,14 @@ useInterfaceState.setState({
['y', -1, 'ShiftLeft'], // todo jump
]
// todo refactor
const actionAndState = state !== 0 ? coordToAction.find(([axis, value]) => axis === coord && value === state) : coordToAction.filter(([axis]) => axis === coord)
const actionAndState = state === 0 ? coordToAction.filter(([axis]) => axis === coord) : coordToAction.find(([axis, value]) => axis === coord && value === state)
if (!bot) return
if (state === 0) {
for (const action of actionAndState) {
contro.pressedKeyOrButtonChanged({code: action[2],}, false)
}
} else {
//@ts-ignore
//@ts-expect-error
contro.pressedKeyOrButtonChanged({code: actionAndState[2],}, true)
}
}

View file

@ -1,14 +1,14 @@
import { setLoadingScreenStatus } from './utils'
import blocksFileNames from '../generated/blocks.json'
import JSZip from 'jszip'
import { join, dirname } from 'path'
import fs from 'fs'
import type { BlockStates } from './inventory'
import JSZip from 'jszip'
import type { Viewer } from 'prismarine-viewer/viewer/lib/viewer'
import { removeFileRecursiveAsync } from './browserfs'
import { subscribeKey } from 'valtio/utils'
import { showNotification } from './menus/notification'
import { proxy, ref } from 'valtio'
import blocksFileNames from '../generated/blocks.json'
import { showNotification } from './menus/notification'
import type { BlockStates } from './inventory'
import { removeFileRecursiveAsync } from './browserfs'
import { setLoadingScreenStatus } from './utils'
export const resourcePackState = proxy({
resourcePackInstalled: false,
@ -130,7 +130,7 @@ const applyTexturePackData = async (version: string, { blockSize }: TextureResol
for (const v of x) {
processObj(v)
}
return
} else {
const actual = Object.keys(x)
const needed = ['u', 'v', 'su', 'sv']
@ -161,7 +161,7 @@ const getSizeFromImage = async (filePath: string) => {
const file = await fs.promises.readFile(filePath, 'base64')
probeImg.src = `data:image/png;base64,${file}`
await new Promise((resolve, reject) => {
probeImg.onload = resolve
probeImg.addEventListener('load', resolve)
})
if (probeImg.width !== probeImg.height) throw new Error(`Probe texture ${filePath} is not square`)
return probeImg.width
@ -174,14 +174,14 @@ export const genTexturePackTextures = async (version: string) => {
const blocksBasePathAlt = '/userData/resourcePacks/default/assets/minecraft/textures/blocks'
const blocksGenereatedPath = `/userData/resourcePacks/default/${version}.png`
const genereatedPathData = `/userData/resourcePacks/default/${version}.json`
if (await existsAsync(blocksBasePath) === false) {
if (await existsAsync(blocksBasePathAlt) === false) {
return
} else {
if (!(await existsAsync(blocksBasePath))) {
if (await existsAsync(blocksBasePathAlt)) {
blocksBasePath = blocksBasePathAlt
} else {
return
}
}
if (await existsAsync(blocksGenereatedPath) === true) {
if (await existsAsync(blocksGenereatedPath)) {
applyTexturePackData(version, JSON.parse(await fs.promises.readFile(genereatedPathData, 'utf8')), await fs.promises.readFile(blocksGenereatedPath, 'utf8'))
return
}
@ -214,7 +214,7 @@ export const genTexturePackTextures = async (version: string) => {
img.src = src
await new Promise((resolve, reject) => {
img.onerror = reject
img.onload = resolve
img.addEventListener('load', resolve)
})
for (const [i, fileName] of textureFiles.entries()) {
const x = (i % texSize) * tileSize
@ -226,10 +226,10 @@ export const genTexturePackTextures = async (version: string) => {
const fileBase64 = await fs.promises.readFile(join(blocksBasePath, fileName), 'base64')
const _imgCustom = new Image()
await new Promise<void>(resolve => {
_imgCustom.onload = () => {
_imgCustom.addEventListener('load', () => {
imgCustom = _imgCustom
resolve()
}
})
_imgCustom.onerror = () => {
console.log('Skipping issued texture', fileName)
resolve()

View file

@ -2,15 +2,16 @@ export default (bot: import('mineflayer').Bot) => {
bot.on('time', () => {
// 0 morning
const dayTotal = 24_000
const evening = 12542 / dayTotal
const night = 17843 / dayTotal
const morningStart = 22300 / dayTotal
const morningEnd = 23961 / dayTotal
const evening = 12_542 / dayTotal
const night = 17_843 / dayTotal
const morningStart = 22_300 / dayTotal
const morningEnd = 23_961 / dayTotal
const timeProgress = bot.time.time / dayTotal
// 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

View file

@ -1,7 +1,7 @@
import { activeModalStack, hideModal, miscUiState, showModal } from './globalState'
import { notification } from './menus/notification'
import * as crypto from 'crypto'
import UUID from 'uuid-1345'
import { activeModalStack, hideModal, miscUiState, showModal } from './globalState'
import { notification } from './menus/notification'
import { options } from './optionsStorage'
import { saveWorld } from './builtinCommands'
import { openWorldZip } from './browserfs'
@ -12,7 +12,7 @@ export const goFullscreen = async (doToggle = false) => {
// todo display a message or repeat?
await document.documentElement.requestFullscreen().catch(() => { })
// request full keyboard access
//@ts-ignore
//@ts-expect-error
navigator.keyboard?.lock?.(['Escape', 'KeyW'])
} else if (doToggle) {
await document.exitFullscreen().catch(() => { })
@ -43,7 +43,7 @@ export const pointerLock = {
if (!(document.fullscreenElement && navigator['keyboard']) && this.justHitEscape) {
displayBrowserProblem()
} else {
//@ts-ignore
//@ts-expect-error
const promise: any = document.documentElement.requestPointerLock({
unadjustedMovement: options.mouseRawInput
})
@ -68,7 +68,7 @@ window.getScreenRefreshRate = getScreenRefreshRate
/**
* Allows to obtain the estimated Hz of the primary monitor in the system.
*/
export function getScreenRefreshRate(): Promise<number> {
export async function getScreenRefreshRate(): Promise<number> {
let requestId = null
let callbackTriggered = false
let resolve
@ -79,8 +79,8 @@ export function getScreenRefreshRate(): Promise<number> {
DOMHighResTimeStampCollection.unshift(DOMHighResTimeStamp)
if (DOMHighResTimeStampCollection.length > 10) {
let t0 = DOMHighResTimeStampCollection.pop()
let fps = Math.floor(1000 * 10 / (DOMHighResTimeStamp - t0))
const t0 = DOMHighResTimeStampCollection.pop()
const fps = Math.floor(1000 * 10 / (DOMHighResTimeStamp - t0))
if (!callbackTriggered) {
resolve(fps/* , DOMHighResTimeStampCollection */)
@ -177,9 +177,9 @@ export const loadScript = async function (scriptSrc: string) {
scriptElement.src = scriptSrc
scriptElement.async = true
scriptElement.onload = () => {
scriptElement.addEventListener('load', () => {
resolve(scriptElement)
}
})
scriptElement.onerror = (error) => {
reject(error)
@ -191,7 +191,7 @@ export const loadScript = async function (scriptSrc: string) {
// doesn't support snapshots
export const toMajorVersion = (version) => {
const [a, b] = (version + '').split('.')
const [a, b] = (String(version)).split('.')
return `${a}.${b}`
}
@ -239,7 +239,7 @@ export const openFilePicker = (specificCase?: 'resourcepack') => {
picker.click()
}
export const resolveTimeout = (promise, timeout = 10000) => {
export const resolveTimeout = async (promise, timeout = 10_000) => {
return new Promise((resolve, reject) => {
promise.then(resolve, reject)
setTimeout(() => {

View file

@ -3,29 +3,25 @@ type Options = boolean | Readonly<AddEventListenerOptions> | undefined
function registerListener<KD extends keyof DocumentEventMap>(
element: Readonly<Document> | null | undefined,
eventType: KD,
// eslint-disable-next-line functional/prefer-immutable-types
listener: (this: Document, evt: DocumentEventMap[KD]) => void,
options?: Options,
): void
function registerListener<KH extends keyof HTMLElementEventMap>(
element: Readonly<HTMLElement> | null | undefined,
eventType: KH,
// eslint-disable-next-line functional/prefer-immutable-types
listener: (this: HTMLElement, evt: HTMLElementEventMap[KH]) => void,
options?: Options,
): void
function registerListener<KW extends keyof WindowEventMap>(
element: Readonly<Window> | null | undefined,
eventType: KW,
// eslint-disable-next-line functional/prefer-immutable-types
listener: (this: Window, evt: WindowEventMap[KW]) => void,
options?: Options,
): void
//@ts-ignore
//@ts-expect-error
function registerListener(
element: Readonly<Document | HTMLElement | Window> | null | undefined,
eventType: string,
// eslint-disable-next-line functional/prefer-immutable-types
listener: (evt: Event) => void,
options?: Options,
): void