diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e86db1be2..032faaa5a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: image: [ubuntu-20.04] - php: [8.0.22, 8.1.9] + php: [8.0.23, 8.1.10] steps: - name: Build and prepare PHP cache @@ -31,7 +31,7 @@ jobs: fail-fast: false matrix: image: [ubuntu-20.04] - php: [8.0.22, 8.1.9] + php: [8.0.23, 8.1.10] steps: - uses: actions/checkout@v3 @@ -69,7 +69,7 @@ jobs: fail-fast: false matrix: image: [ubuntu-20.04] - php: [8.0.22, 8.1.9] + php: [8.0.23, 8.1.10] steps: - uses: actions/checkout@v3 @@ -107,7 +107,7 @@ jobs: fail-fast: false matrix: image: [ubuntu-20.04] - php: [8.0.22, 8.1.9] + php: [8.0.23, 8.1.10] steps: - uses: actions/checkout@v3 @@ -147,7 +147,7 @@ jobs: fail-fast: false matrix: image: [ubuntu-20.04] - php: [8.0.22, 8.1.9] + php: [8.0.23, 8.1.10] steps: - uses: actions/checkout@v3 @@ -201,7 +201,7 @@ jobs: uses: shivammathur/setup-php@2.21.2 with: php-version: 8.0 - tools: php-cs-fixer:3.8 + tools: php-cs-fixer:3.11 - name: Run PHP-CS-Fixer run: php-cs-fixer fix --dry-run --diff --ansi diff --git a/composer.json b/composer.json index 206fce6d5..05c5e7f2f 100644 --- a/composer.json +++ b/composer.json @@ -43,7 +43,7 @@ "pocketmine/classloader": "^0.2.0", "pocketmine/color": "^0.2.0", "pocketmine/errorhandler": "^0.6.0", - "pocketmine/locale-data": "~2.8.0", + "pocketmine/locale-data": "~2.8.0 <2.8.9", "pocketmine/log": "^0.4.0", "pocketmine/log-pthreads": "^0.4.0", "pocketmine/math": "^0.4.0", @@ -55,7 +55,7 @@ "webmozart/path-util": "^2.3" }, "require-dev": { - "phpstan/phpstan": "1.8.2", + "phpstan/phpstan": "1.8.5", "phpstan/phpstan-phpunit": "^1.1.0", "phpstan/phpstan-strict-rules": "^1.2.0", "phpunit/phpunit": "^9.2" diff --git a/composer.lock b/composer.lock index 9bfb5608c..3bfc79abe 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5e91ab5b70093a7566adf2d1be7a7dbc", + "content-hash": "ab34faed0ca4120106748663b00e9604", "packages": [ { "name": "adhocore/json-comment", @@ -586,16 +586,16 @@ }, { "name": "pocketmine/locale-data", - "version": "2.8.6", + "version": "2.8.7", "source": { "type": "git", "url": "https://github.com/pmmp/Language.git", - "reference": "87f1afaa4824998ece14d71ce37e94bc1f1d3116" + "reference": "e115d3d64a508065f1cedad1be55528906308456" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/Language/zipball/87f1afaa4824998ece14d71ce37e94bc1f1d3116", - "reference": "87f1afaa4824998ece14d71ce37e94bc1f1d3116", + "url": "https://api.github.com/repos/pmmp/Language/zipball/e115d3d64a508065f1cedad1be55528906308456", + "reference": "e115d3d64a508065f1cedad1be55528906308456", "shasum": "" }, "type": "library", @@ -603,9 +603,9 @@ "description": "Language resources used by PocketMine-MP", "support": { "issues": "https://github.com/pmmp/Language/issues", - "source": "https://github.com/pmmp/Language/tree/2.8.6" + "source": "https://github.com/pmmp/Language/tree/2.8.7" }, - "time": "2022-08-18T15:25:44+00:00" + "time": "2022-08-21T20:37:16+00:00" }, { "name": "pocketmine/log", @@ -694,16 +694,16 @@ }, { "name": "pocketmine/math", - "version": "0.4.2", + "version": "0.4.3", "source": { "type": "git", "url": "https://github.com/pmmp/Math.git", - "reference": "aacc3759a508a69dfa5bc4dfa770ab733c5c94bf" + "reference": "47a243d320b01c8099d65309967934c188111549" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/Math/zipball/aacc3759a508a69dfa5bc4dfa770ab733c5c94bf", - "reference": "aacc3759a508a69dfa5bc4dfa770ab733c5c94bf", + "url": "https://api.github.com/repos/pmmp/Math/zipball/47a243d320b01c8099d65309967934c188111549", + "reference": "47a243d320b01c8099d65309967934c188111549", "shasum": "" }, "require": { @@ -712,7 +712,7 @@ }, "require-dev": { "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "1.2.0", + "phpstan/phpstan": "1.8.2", "phpstan/phpstan-strict-rules": "^1.0", "phpunit/phpunit": "^8.5 || ^9.5" }, @@ -729,9 +729,9 @@ "description": "PHP library containing math related code used in PocketMine-MP", "support": { "issues": "https://github.com/pmmp/Math/issues", - "source": "https://github.com/pmmp/Math/tree/0.4.2" + "source": "https://github.com/pmmp/Math/tree/0.4.3" }, - "time": "2021-12-05T01:15:17+00:00" + "time": "2022-08-25T18:43:37+00:00" }, { "name": "pocketmine/nbt", @@ -777,16 +777,16 @@ }, { "name": "pocketmine/raklib", - "version": "0.14.4", + "version": "0.14.5", "source": { "type": "git", "url": "https://github.com/pmmp/RakLib.git", - "reference": "1ea8e3b95a1b6bf785dc27d76578657be4185f42" + "reference": "85b4e5cb7117d37e010eeadb3ff53b21276c6f48" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/RakLib/zipball/1ea8e3b95a1b6bf785dc27d76578657be4185f42", - "reference": "1ea8e3b95a1b6bf785dc27d76578657be4185f42", + "url": "https://api.github.com/repos/pmmp/RakLib/zipball/85b4e5cb7117d37e010eeadb3ff53b21276c6f48", + "reference": "85b4e5cb7117d37e010eeadb3ff53b21276c6f48", "shasum": "" }, "require": { @@ -798,7 +798,7 @@ "pocketmine/log": "^0.3.0 || ^0.4.0" }, "require-dev": { - "phpstan/phpstan": "1.5.4", + "phpstan/phpstan": "1.7.7", "phpstan/phpstan-strict-rules": "^1.0" }, "type": "library", @@ -814,9 +814,9 @@ "description": "A RakNet server implementation written in PHP", "support": { "issues": "https://github.com/pmmp/RakLib/issues", - "source": "https://github.com/pmmp/RakLib/tree/0.14.4" + "source": "https://github.com/pmmp/RakLib/tree/0.14.5" }, - "time": "2022-04-17T18:42:17+00:00" + "time": "2022-08-25T16:16:44+00:00" }, { "name": "pocketmine/raklib-ipc", @@ -980,20 +980,20 @@ }, { "name": "ramsey/uuid", - "version": "4.4.0", + "version": "4.5.0", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "373f7bacfcf3de038778ff27dcce5672ddbf4c8a" + "reference": "ef842484ba57f163c6d465ab744bfecb872a11d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/373f7bacfcf3de038778ff27dcce5672ddbf4c8a", - "reference": "373f7bacfcf3de038778ff27dcce5672ddbf4c8a", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/ef842484ba57f163c6d465ab744bfecb872a11d4", + "reference": "ef842484ba57f163c6d465ab744bfecb872a11d4", "shasum": "" }, "require": { - "brick/math": "^0.8 || ^0.9 || ^0.10", + "brick/math": "^0.8.8 || ^0.9 || ^0.10", "ext-ctype": "*", "ext-json": "*", "php": "^8.0", @@ -1014,12 +1014,13 @@ "php-mock/php-mock-mockery": "^1.3", "php-parallel-lint/php-parallel-lint": "^1.1", "phpbench/phpbench": "^1.0", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-mockery": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.1", "phpunit/phpunit": "^8.5 || ^9", - "slevomat/coding-standard": "^7.0", + "ramsey/composer-repl": "^1.4", + "slevomat/coding-standard": "^8.4", "squizlabs/php_codesniffer": "^3.5", "vimeo/psalm": "^4.9" }, @@ -1057,7 +1058,7 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.4.0" + "source": "https://github.com/ramsey/uuid/tree/4.5.0" }, "funding": [ { @@ -1069,7 +1070,7 @@ "type": "tidelift" } ], - "time": "2022-08-05T17:58:37+00:00" + "time": "2022-09-15T01:44:53+00:00" }, { "name": "symfony/polyfill-php81", @@ -1392,16 +1393,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.14.0", + "version": "v4.15.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1" + "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/34bea19b6e03d8153165d8f30bba4c3be86184c1", - "reference": "34bea19b6e03d8153165d8f30bba4c3be86184c1", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", + "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900", "shasum": "" }, "require": { @@ -1442,9 +1443,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.14.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1" }, - "time": "2022-05-31T20:59:12+00:00" + "time": "2022-09-04T07:30:47+00:00" }, { "name": "phar-io/manifest", @@ -1557,245 +1558,18 @@ }, "time": "2022-02-21T01:04:05+00:00" }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" - }, - "time": "2021-10-19T17:43:47+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.6.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "77a32518733312af16a44300404e945338981de3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3", - "reference": "77a32518733312af16a44300404e945338981de3", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" - }, - "time": "2022-03-15T21:29:03+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "v1.15.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.2", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0 || ^7.0", - "phpunit/phpunit": "^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/v1.15.0" - }, - "time": "2021-12-08T12:19:24+00:00" - }, { "name": "phpstan/phpstan", - "version": "1.8.2", + "version": "1.8.5", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c" + "reference": "f6598a5ff12ca4499a836815e08b4d77a2ddeb20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c53312ecc575caf07b0e90dee43883fdf90ca67c", - "reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/f6598a5ff12ca4499a836815e08b4d77a2ddeb20", + "reference": "f6598a5ff12ca4499a836815e08b4d77a2ddeb20", "shasum": "" }, "require": { @@ -1819,9 +1593,13 @@ "MIT" ], "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.8.2" + "source": "https://github.com/phpstan/phpstan/tree/1.8.5" }, "funding": [ { @@ -1832,16 +1610,12 @@ "url": "https://github.com/phpstan", "type": "github" }, - { - "url": "https://www.patreon.com/phpstan", - "type": "patreon" - }, { "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", "type": "tidelift" } ], - "time": "2022-07-20T09:57:31+00:00" + "time": "2022-09-07T16:05:32+00:00" }, { "name": "phpstan/phpstan-phpunit", @@ -1897,21 +1671,21 @@ }, { "name": "phpstan/phpstan-strict-rules", - "version": "1.3.0", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "543675a9be82d4befb9ca0bd8cdc9d211665037f" + "reference": "431b3d6e8040075de196680cd5bc95735987b4ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/543675a9be82d4befb9ca0bd8cdc9d211665037f", - "reference": "543675a9be82d4befb9ca0bd8cdc9d211665037f", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/431b3d6e8040075de196680cd5bc95735987b4ae", + "reference": "431b3d6e8040075de196680cd5bc95735987b4ae", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.7.15" + "phpstan/phpstan": "^1.8.3" }, "require-dev": { "nikic/php-parser": "^4.13.0", @@ -1939,29 +1713,29 @@ "description": "Extra strict and opinionated rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.3.0" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.3" }, - "time": "2022-06-24T06:47:20+00:00" + "time": "2022-08-26T15:05:46+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.15", + "version": "9.2.17", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f" + "reference": "aa94dc41e8661fe90c7316849907cba3007b10d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2e9da11878c4202f97915c1cb4bb1ca318a63f5f", - "reference": "2e9da11878c4202f97915c1cb4bb1ca318a63f5f", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8", + "reference": "aa94dc41e8661fe90c7316849907cba3007b10d8", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.13.0", + "nikic/php-parser": "^4.14", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -2010,7 +1784,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.15" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17" }, "funding": [ { @@ -2018,7 +1792,7 @@ "type": "github" } ], - "time": "2022-03-07T09:28:20+00:00" + "time": "2022-08-30T12:24:04+00:00" }, { "name": "phpunit/php-file-iterator", @@ -2263,16 +2037,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.21", + "version": "9.5.24", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1" + "reference": "d0aa6097bef9fd42458a9b3c49da32c6ce6129c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0e32b76be457de00e83213528f6bb37e2a38fcb1", - "reference": "0e32b76be457de00e83213528f6bb37e2a38fcb1", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d0aa6097bef9fd42458a9b3c49da32c6ce6129c5", + "reference": "d0aa6097bef9fd42458a9b3c49da32c6ce6129c5", "shasum": "" }, "require": { @@ -2287,7 +2061,6 @@ "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", "phpunit/php-code-coverage": "^9.2.13", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", @@ -2302,12 +2075,9 @@ "sebastian/global-state": "^5.0.1", "sebastian/object-enumerator": "^4.0.3", "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.0", + "sebastian/type": "^3.1", "sebastian/version": "^3.0.2" }, - "require-dev": { - "phpspec/prophecy-phpunit": "^2.0.1" - }, "suggest": { "ext-soap": "*", "ext-xdebug": "*" @@ -2349,7 +2119,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.21" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.24" }, "funding": [ { @@ -2361,7 +2131,7 @@ "type": "github" } ], - "time": "2022-06-19T12:14:25+00:00" + "time": "2022-08-30T07:42:16+00:00" }, { "name": "sebastian/cli-parser", @@ -2532,16 +2302,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { @@ -2594,7 +2364,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" }, "funding": [ { @@ -2602,7 +2372,7 @@ "type": "github" } ], - "time": "2020-10-26T15:49:45+00:00" + "time": "2022-09-14T12:41:17+00:00" }, { "name": "sebastian/complexity", @@ -2792,16 +2562,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", "shasum": "" }, "require": { @@ -2857,7 +2627,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" }, "funding": [ { @@ -2865,7 +2635,7 @@ "type": "github" } ], - "time": "2021-11-11T14:18:36+00:00" + "time": "2022-09-14T06:03:37+00:00" }, { "name": "sebastian/global-state", @@ -3220,16 +2990,16 @@ }, { "name": "sebastian/type", - "version": "3.0.0", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad" + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", - "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", "shasum": "" }, "require": { @@ -3241,7 +3011,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -3264,7 +3034,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.0.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" }, "funding": [ { @@ -3272,7 +3042,7 @@ "type": "github" } ], - "time": "2022-03-15T09:54:48+00:00" + "time": "2022-09-12T14:47:03+00:00" }, { "name": "sebastian/version", diff --git a/resources/pocketmine.yml b/resources/pocketmine.yml index f922cb225..4ad8ea9c0 100644 --- a/resources/pocketmine.yml +++ b/resources/pocketmine.yml @@ -168,6 +168,9 @@ timings: host: timings.pmmp.io console: + #Whether to accept commands via the console. If disabled, anything typed on the console will be ignored. + #Useful to save resources on headless servers where the console is never used (e.g. hosted server, Docker, etc.) + enable-input: true #Choose whether to enable server stats reporting on the console title. #NOTE: The title ticker will be disabled regardless if console colours are not enabled. title-tick: true diff --git a/src/Server.php b/src/Server.php index 66bcc1c66..02f2a3f5e 100644 --- a/src/Server.php +++ b/src/Server.php @@ -31,7 +31,7 @@ use pocketmine\command\Command; use pocketmine\command\CommandSender; use pocketmine\command\SimpleCommandMap; use pocketmine\console\ConsoleCommandSender; -use pocketmine\console\ConsoleReaderThread; +use pocketmine\console\ConsoleReaderChildProcessDaemon; use pocketmine\crafting\CraftingManager; use pocketmine\crafting\CraftingManagerFromDataHelper; use pocketmine\crash\CrashDump; @@ -88,7 +88,6 @@ use pocketmine\promise\PromiseResolver; use pocketmine\resourcepacks\ResourcePackManager; use pocketmine\scheduler\AsyncPool; use pocketmine\snooze\SleeperHandler; -use pocketmine\snooze\SleeperNotifier; use pocketmine\stats\SendUsageTask; use pocketmine\timings\Timings; use pocketmine\timings\TimingsHandler; @@ -132,6 +131,7 @@ use function get_class; use function ini_set; use function is_array; use function is_dir; +use function is_int; use function is_object; use function is_resource; use function is_string; @@ -165,7 +165,6 @@ use function zlib_encode; use const DIRECTORY_SEPARATOR; use const PHP_EOL; use const PHP_INT_MAX; -use const PTHREADS_INHERIT_NONE; use const ZLIB_ENCODING_GZIP; /** @@ -225,7 +224,8 @@ class Server{ private MemoryManager $memoryManager; - private ConsoleReaderThread $console; + private ?ConsoleReaderChildProcessDaemon $console = null; + private ?ConsoleCommandSender $consoleSender = null; private SimpleCommandMap $commandMap; @@ -570,6 +570,7 @@ class Server{ $playerPos = null; $spawn = $world->getSpawnLocation(); } + /** @phpstan-var PromiseResolver $playerPromiseResolver */ $playerPromiseResolver = new PromiseResolver(); $world->requestChunkPopulation($spawn->getFloorX() >> Chunk::COORD_BIT_SIZE, $spawn->getFloorZ() >> Chunk::COORD_BIT_SIZE, null)->onCompletion( function() use ($playerPromiseResolver, $class, $session, $playerInfo, $authenticated, $world, $playerPos, $spawn, $offlinePlayerData) : void{ @@ -1048,17 +1049,9 @@ class Server{ $this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_ADMINISTRATIVE, $consoleSender); $this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_USERS, $consoleSender); - $consoleNotifier = new SleeperNotifier(); - $commandBuffer = new \Threaded(); - $this->console = new ConsoleReaderThread($commandBuffer, $consoleNotifier); - $this->tickSleeper->addNotifier($consoleNotifier, function() use ($commandBuffer, $consoleSender) : void{ - Timings::$serverCommand->startTiming(); - while(($line = $commandBuffer->shift()) !== null){ - $this->dispatchCommand($consoleSender, (string) $line); - } - Timings::$serverCommand->stopTiming(); - }); - $this->console->start(PTHREADS_INHERIT_NONE); + if($this->configGroup->getPropertyBool("console.enable-input", true)){ + $this->console = new ConsoleReaderChildProcessDaemon($this->logger); + } $this->tickProcessor(); $this->forceShutdown(); @@ -1511,7 +1504,7 @@ class Server{ $this->configGroup->save(); } - if(isset($this->console)){ + if($this->console !== null){ $this->getLogger()->debug("Closing console"); $this->console->quit(); } @@ -1650,12 +1643,14 @@ class Server{ ], 10, [], $postUrlError); if($reply !== null && is_object($data = json_decode($reply->getBody()))){ - if(isset($data->crashId) && isset($data->crashUrl)){ + if(isset($data->crashId) && is_int($data->crashId) && isset($data->crashUrl) && is_string($data->crashUrl)){ $reportId = $data->crashId; $reportUrl = $data->crashUrl; $this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_archive($reportUrl, (string) $reportId))); - }elseif(isset($data->error)){ + }elseif(isset($data->error) && is_string($data->error)){ $this->logger->emergency("Automatic crash report submission failed: $data->error"); + }else{ + $this->logger->emergency("Invalid JSON response received from crash archive: " . $reply->getBody()); } }else{ $this->logger->emergency("Failed to communicate with crash archive: $postUrlError"); @@ -1853,6 +1848,13 @@ class Server{ $this->getMemoryManager()->check(); + if($this->console !== null){ + while(($line = $this->console->readLine()) !== null){ + $this->consoleSender ??= new ConsoleCommandSender($this, $this->language); + $this->dispatchCommand($this->consoleSender, $line); + } + } + Timings::$serverTick->stopTiming(); $now = microtime(true); diff --git a/src/block/Cactus.php b/src/block/Cactus.php index 67066ab68..2f384b923 100644 --- a/src/block/Cactus.php +++ b/src/block/Cactus.php @@ -67,7 +67,7 @@ class Cactus extends Transparent{ * @return AxisAlignedBB[] */ protected function recalculateCollisionBoxes() : array{ - static $shrinkSize = 1 / 16; + $shrinkSize = 1 / 16; return [AxisAlignedBB::one()->contract($shrinkSize, 0, $shrinkSize)->trim(Facing::UP, $shrinkSize)]; } diff --git a/src/block/DeadBush.php b/src/block/DeadBush.php index 09754b07d..4565332a3 100644 --- a/src/block/DeadBush.php +++ b/src/block/DeadBush.php @@ -34,7 +34,7 @@ use function mt_rand; class DeadBush extends Flowable{ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{ - if(!$this->getSide(Facing::DOWN)->isTransparent()){ + if($this->canBeSupportedBy($this->getSide(Facing::DOWN))){ return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player); } @@ -42,7 +42,7 @@ class DeadBush extends Flowable{ } public function onNearbyBlockChange() : void{ - if($this->getSide(Facing::DOWN)->isTransparent()){ + if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){ $this->position->getWorld()->useBreakOn($this->position); } } @@ -64,4 +64,15 @@ class DeadBush extends Flowable{ public function getFlammability() : int{ return 100; } + + private function canBeSupportedBy(Block $block) : bool{ + $blockId = $block->getTypeId(); + return $blockId === BlockTypeIds::SAND + || $blockId === BlockTypeIds::RED_SAND + || $blockId === BlockTypeIds::PODZOL + || $blockId === BlockTypeIds::MYCELIUM + || $blockId === BlockTypeIds::DIRT + || $blockId === BlockTypeIds::HARDENED_CLAY + || $blockId === BlockTypeIds::STAINED_CLAY; + } } diff --git a/src/block/VanillaBlocks.php b/src/block/VanillaBlocks.php index 53458fbd9..4b1c127e1 100644 --- a/src/block/VanillaBlocks.php +++ b/src/block/VanillaBlocks.php @@ -731,6 +731,7 @@ final class VanillaBlocks{ /** * @return Block[] + * @phpstan-return array */ public static function getAll() : array{ //phpstan doesn't support generic traits yet :( diff --git a/src/console/ConsoleReaderChildProcess.php b/src/console/ConsoleReaderChildProcess.php index 5bf2ff71f..2d4e3fc56 100644 --- a/src/console/ConsoleReaderChildProcess.php +++ b/src/console/ConsoleReaderChildProcess.php @@ -23,12 +23,14 @@ declare(strict_types=1); namespace pocketmine\console; +use pocketmine\utils\Process; use function cli_set_process_title; use function count; use function dirname; use function feof; use function fwrite; use function stream_socket_client; +use const PTHREADS_INHERIT_NONE; require dirname(__DIR__, 2) . '/vendor/autoload.php'; @@ -43,9 +45,40 @@ $socket = stream_socket_client($argv[1], $errCode, $errMessage, 15.0); if($socket === false){ throw new \RuntimeException("Failed to connect to server process ($errCode): $errMessage"); } -$consoleReader = new ConsoleReader(); + +$channel = new \Threaded(); +$thread = new class($channel) extends \Thread{ + public function __construct( + private \Threaded $channel, + ){} + + public function run(){ + require dirname(__DIR__, 2) . '/vendor/autoload.php'; + + $channel = $this->channel; + $reader = new ConsoleReader(); + while(true){ // @phpstan-ignore-line + $line = $reader->readLine(); + if($line !== null){ + $channel->synchronized(function() use ($channel, $line) : void{ + $channel[] = $line; + $channel->notify(); + }); + } + } + } +}; + +$thread->start(PTHREADS_INHERIT_NONE); while(!feof($socket)){ - $line = $consoleReader->readLine(); + $line = $channel->synchronized(function() use ($channel) : ?string{ + if(count($channel) === 0){ + $channel->wait(1_000_000); + } + /** @var string|null $line */ + $line = $channel->shift(); + return $line; + }); if(@fwrite($socket, ($line ?? "") . "\n") === false){ //Always send even if there's no line, to check if the parent is alive //If the parent process was terminated forcibly, it won't close the connection properly, so feof() will return @@ -53,3 +86,8 @@ while(!feof($socket)){ break; } } + +//For simplicity's sake, we don't bother with a graceful shutdown here. +//The parent process would normally forcibly terminate the child process anyway, so we only reach this point if the +//parent process was terminated forcibly and didn't clean up after itself. +Process::kill(Process::pid(), false); diff --git a/src/console/ConsoleReaderThread.php b/src/console/ConsoleReaderChildProcessDaemon.php similarity index 50% rename from src/console/ConsoleReaderThread.php rename to src/console/ConsoleReaderChildProcessDaemon.php index eac19ef84..a0c689d37 100644 --- a/src/console/ConsoleReaderThread.php +++ b/src/console/ConsoleReaderChildProcessDaemon.php @@ -23,8 +23,6 @@ declare(strict_types=1); namespace pocketmine\console; -use pocketmine\snooze\SleeperNotifier; -use pocketmine\thread\Thread; use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\Utils; use Webmozart\PathUtil\Path; @@ -45,36 +43,35 @@ use function trim; use const PHP_BINARY; use const STREAM_SHUT_RDWR; -final class ConsoleReaderThread extends Thread{ +/** + * This pile of shit exists because PHP on Windows is broken, and can't handle stream_select() on stdin or pipes + * properly - stdin native triggers stream_select() when a key is pressed, causing it to get stuck in fgets() + * waiting for a line that might never come (and Windows doesn't support character-based reading either), and + * pipes just constantly trigger stream_select() instead of only when data is returned, rendering it useless. + * + * This results in whichever process reads stdin getting stuck on shutdown, which previously forced us to kill + * the entire server process to make it go away. + * + * To get around this problem, we delegate the responsibility of reading stdin to a subprocess, which we can + * then brutally murder when the server shuts down, without killing the entire server process. + * Thankfully, stream_select() actually works properly on sockets, so we can use them for inter-process + * communication. + */ +final class ConsoleReaderChildProcessDaemon{ + private \PrefixedLogger $logger; + /** @var resource */ + private $subprocess; + /** @var resource */ + private $socket; + public function __construct( - private \Threaded $buffer, - private ?SleeperNotifier $notifier = null - ){} - - protected function onRun() : void{ - $buffer = $this->buffer; - $notifier = $this->notifier; - - while(!$this->isKilled){ - $this->runSubprocess($buffer, $notifier); - } + \Logger $logger + ){ + $this->logger = new \PrefixedLogger($logger, "Console Reader Daemon"); + $this->prepareSubprocess(); } - /** - * This pile of shit exists because PHP on Windows is broken, and can't handle stream_select() on stdin or pipes - * properly - stdin native triggers stream_select() when a key is pressed, causing it to get stuck in fgets() - * waiting for a line that might never come (and Windows doesn't support character-based reading either), and - * pipes just constantly trigger stream_select() instead of only when data is returned, rendering it useless. - * - * This results in whichever process reads stdin getting stuck on shutdown, which previously forced us to kill - * the entire server process to make it go away. - * - * To get around this problem, we delegate the responsibility of reading stdin to a subprocess, which we can - * then brutally murder when the server shuts down, without killing the entire server process. - * Thankfully, stream_select() actually works properly on sockets, so we can use them for inter-process - * communication. - */ - private function runSubprocess(\Threaded $buffer, ?SleeperNotifier $notifier) : void{ + private function prepareSubprocess() : void{ $server = stream_socket_server("tcp://127.0.0.1:0"); if($server === false){ throw new \RuntimeException("Failed to open console reader socket server"); @@ -96,41 +93,43 @@ final class ConsoleReaderThread extends Thread{ throw new AssumptionFailedError("stream_socket_accept() returned false"); } stream_socket_shutdown($server, STREAM_SHUT_RDWR); - while(!$this->isKilled){ - $r = [$client]; - $w = null; - $e = null; - if(stream_select($r, $w, $e, 0, 200000) === 1){ - $command = fgets($client); - if($command === false){ - //subprocess died for some reason; this could be someone killed it manually from outside (e.g. - //mistyped PID) or it might be a ctrl+c signal to this process that the child is handling - //differently (different signal handlers). - //since we have no way to know the difference, we just kill the sub and start a new one. - break; - } - $command = preg_replace("#\\x1b\\x5b([^\\x1b]*\\x7e|[\\x40-\\x50])#", "", trim($command)) ?? throw new AssumptionFailedError("This regex is assumed to be valid"); - $command = preg_replace('/[[:cntrl:]]/', '', $command) ?? throw new AssumptionFailedError("This regex is assumed to be valid"); - if($command === ""){ - continue; - } - $buffer[] = $command; - if($notifier !== null){ - $notifier->wakeupSleeper(); - } - } - } + $this->subprocess = $sub; + $this->socket = $client; + } + private function shutdownSubprocess() : void{ //we have no way to signal to the subprocess to shut down gracefully; besides, Windows sucks, and the subprocess //gets stuck in a blocking fgets() read because stream_select() is a hunk of junk (hence the separate process in //the first place). - proc_terminate($sub); - proc_close($sub); - stream_socket_shutdown($client, STREAM_SHUT_RDWR); + proc_terminate($this->subprocess); + proc_close($this->subprocess); + stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR); } - public function getThreadName() : string{ - return "Console"; + public function readLine() : ?string{ + $r = [$this->socket]; + $w = null; + $e = null; + if(stream_select($r, $w, $e, 0, 0) === 1){ + $command = fgets($this->socket); + if($command === false){ + $this->logger->debug("Lost connection to subprocess, restarting (maybe the child process was killed from outside?)"); + $this->shutdownSubprocess(); + $this->prepareSubprocess(); + return null; + } + + $command = preg_replace("#\\x1b\\x5b([^\\x1b]*\\x7e|[\\x40-\\x50])#", "", trim($command)) ?? throw new AssumptionFailedError("This regex is assumed to be valid"); + $command = preg_replace('/[[:cntrl:]]/', '', $command) ?? throw new AssumptionFailedError("This regex is assumed to be valid"); + + return $command !== "" ? $command : null; + } + + return null; + } + + public function quit() : void{ + $this->shutdownSubprocess(); } } diff --git a/src/entity/ExperienceManager.php b/src/entity/ExperienceManager.php index b74b87192..9cff48f33 100644 --- a/src/entity/ExperienceManager.php +++ b/src/entity/ExperienceManager.php @@ -237,11 +237,10 @@ class ExperienceManager{ } public function onPickupXp(int $xpValue) : void{ - static $mainHandIndex = -1; - static $offHandIndex = -2; + $mainHandIndex = -1; + $offHandIndex = -2; //TODO: replace this with a more generic equipment getting/setting interface - /** @var Durable[] $equipment */ $equipment = []; if(($item = $this->entity->getInventory()->getItemInHand()) instanceof Durable && $item->hasEnchantment(VanillaEnchantments::MENDING())){ diff --git a/src/entity/effect/Effect.php b/src/entity/effect/Effect.php index 442028d4c..cce009733 100644 --- a/src/entity/effect/Effect.php +++ b/src/entity/effect/Effect.php @@ -38,7 +38,6 @@ class Effect{ * @param Translatable|string $name Translation key used for effect name * @param Color $color Color of bubbles given by this effect * @param bool $bad Whether the effect is harmful - * @param int $defaultDuration * @param bool $hasBubbles Whether the effect has potion bubbles. Some do not (e.g. Instant Damage has its own particles instead of bubbles) */ public function __construct( diff --git a/src/entity/effect/VanillaEffects.php b/src/entity/effect/VanillaEffects.php index 249ce367c..04f7985da 100644 --- a/src/entity/effect/VanillaEffects.php +++ b/src/entity/effect/VanillaEffects.php @@ -101,6 +101,7 @@ final class VanillaEffects{ /** * @return Effect[] + * @phpstan-return array */ public static function getAll() : array{ //phpstan doesn't support generic traits yet :( diff --git a/src/inventory/BaseInventory.php b/src/inventory/BaseInventory.php index a37064e83..4e3f4e2a5 100644 --- a/src/inventory/BaseInventory.php +++ b/src/inventory/BaseInventory.php @@ -75,11 +75,13 @@ abstract class BaseInventory implements Inventory{ /** * @param Item[] $items + * @phpstan-param array $items */ abstract protected function internalSetContents(array $items) : void; /** * @param Item[] $items + * @phpstan-param array $items */ public function setContents(array $items) : void{ if(count($items) > $this->getSize()){ diff --git a/src/inventory/Inventory.php b/src/inventory/Inventory.php index fa45d4a78..230f6aa49 100644 --- a/src/inventory/Inventory.php +++ b/src/inventory/Inventory.php @@ -47,12 +47,20 @@ interface Inventory{ public function setItem(int $index, Item $item) : void; /** + * Returns an array of all the itemstacks in the inventory, indexed by their slot number. + * Empty slots are not included unless includeEmpty is true. + * * @return Item[] + * @phpstan-return array */ public function getContents(bool $includeEmpty = false) : array; /** + * Sets the contents of the inventory. Non-numeric offsets or offsets larger than the size of the inventory are + * ignored. + * * @param Item[] $items + * @phpstan-param array $items */ public function setContents(array $items) : void; @@ -85,8 +93,10 @@ interface Inventory{ /** * Will return all the Items that has the same id and metadata (if not null). * Won't check amount + * The returned array is indexed by slot number. * * @return Item[] + * @phpstan-return array */ public function all(Item $item) : array; diff --git a/src/inventory/SimpleInventory.php b/src/inventory/SimpleInventory.php index 95ed29c24..aae11c84c 100644 --- a/src/inventory/SimpleInventory.php +++ b/src/inventory/SimpleInventory.php @@ -58,6 +58,7 @@ class SimpleInventory extends BaseInventory{ /** * @return Item[] + * @phpstan-return array */ public function getContents(bool $includeEmpty = false) : array{ $contents = []; diff --git a/src/item/VanillaItems.php b/src/item/VanillaItems.php index d7091041e..93634d2bc 100644 --- a/src/item/VanillaItems.php +++ b/src/item/VanillaItems.php @@ -316,6 +316,7 @@ final class VanillaItems{ /** * @return Item[] + * @phpstan-return array */ public static function getAll() : array{ //phpstan doesn't support generic traits yet :( diff --git a/src/lang/Language.php b/src/lang/Language.php index 3b3133ff5..035726a16 100644 --- a/src/lang/Language.php +++ b/src/lang/Language.php @@ -27,6 +27,7 @@ use pocketmine\utils\Utils; use Webmozart\PathUtil\Path; use function array_filter; use function array_map; +use function count; use function explode; use function file_exists; use function is_dir; @@ -67,10 +68,14 @@ class Language{ $result = []; foreach($files as $file){ - $code = explode(".", $file)[0]; - $strings = self::loadLang($path, $code); - if(isset($strings["language.name"])){ - $result[$code] = $strings["language.name"]; + try{ + $code = explode(".", $file)[0]; + $strings = self::loadLang($path, $code); + if(isset($strings["language.name"])){ + $result[$code] = $strings["language.name"]; + } + }catch(LanguageNotFoundException $e){ + // no-op } } @@ -122,7 +127,10 @@ class Language{ protected static function loadLang(string $path, string $languageCode) : array{ $file = Path::join($path, $languageCode . ".ini"); if(file_exists($file)){ - return array_map('\stripcslashes', Utils::assumeNotFalse(parse_ini_file($file, false, INI_SCANNER_RAW), "Missing or inaccessible required resource files")); + $strings = array_map('stripcslashes', Utils::assumeNotFalse(parse_ini_file($file, false, INI_SCANNER_RAW), "Missing or inaccessible required resource files")); + if(count($strings) > 0){ + return $strings; + } } throw new LanguageNotFoundException("Language \"$languageCode\" not found"); diff --git a/src/network/mcpe/cache/ChunkCache.php b/src/network/mcpe/cache/ChunkCache.php index dae5e27d6..15b696945 100644 --- a/src/network/mcpe/cache/ChunkCache.php +++ b/src/network/mcpe/cache/ChunkCache.php @@ -43,8 +43,6 @@ class ChunkCache implements ChunkListener{ /** * Fetches the ChunkCache instance for the given world. This lazily creates cache systems as needed. - * - * @return ChunkCache */ public static function getInstance(World $world, Compressor $compressor) : self{ $worldId = spl_object_id($world); diff --git a/src/plugin/PluginManager.php b/src/plugin/PluginManager.php index 78e450943..1e7797201 100644 --- a/src/plugin/PluginManager.php +++ b/src/plugin/PluginManager.php @@ -75,6 +75,9 @@ class PluginManager{ /** @var Plugin[] */ protected array $enabledPlugins = []; + /** @var array> */ + private array $pluginDependents = []; + private bool $loadPluginsGuard = false; /** @@ -453,6 +456,15 @@ class PluginManager{ if($plugin->isEnabled()){ //the plugin may have disabled itself during onEnable() $this->enabledPlugins[$plugin->getDescription()->getName()] = $plugin; + foreach($plugin->getDescription()->getDepend() as $dependency){ + $this->pluginDependents[$dependency][$plugin->getDescription()->getName()] = true; + } + foreach($plugin->getDescription()->getSoftDepend() as $dependency){ + if(isset($this->plugins[$dependency])){ + $this->pluginDependents[$dependency][$plugin->getDescription()->getName()] = true; + } + } + (new PluginEnableEvent($plugin))->call(); return true; @@ -472,8 +484,19 @@ class PluginManager{ } public function disablePlugins() : void{ - foreach($this->getPlugins() as $plugin){ - $this->disablePlugin($plugin); + while(count($this->enabledPlugins) > 0){ + foreach($this->enabledPlugins as $plugin){ + if(!$plugin->isEnabled()){ + continue; //in case a plugin disabled another plugin + } + $name = $plugin->getDescription()->getName(); + if(isset($this->pluginDependents[$name]) && count($this->pluginDependents[$name]) > 0){ + $this->server->getLogger()->debug("Deferring disable of plugin $name due to dependent plugins still enabled: " . implode(", ", array_keys($this->pluginDependents[$name]))); + continue; + } + + $this->disablePlugin($plugin); + } } } @@ -483,6 +506,12 @@ class PluginManager{ (new PluginDisableEvent($plugin))->call(); unset($this->enabledPlugins[$plugin->getDescription()->getName()]); + foreach(Utils::stringifyKeys($this->pluginDependents) as $dependency => $dependentList){ + unset($this->pluginDependents[$dependency][$plugin->getDescription()->getName()]); + if(count($this->pluginDependents[$dependency]) === 0){ + unset($this->pluginDependents[$dependency]); + } + } $plugin->onEnableStateChange(false); $plugin->getScheduler()->shutdown(); diff --git a/src/utils/EnumTrait.php b/src/utils/EnumTrait.php index 315561444..c9d24e0fc 100644 --- a/src/utils/EnumTrait.php +++ b/src/utils/EnumTrait.php @@ -48,6 +48,7 @@ trait EnumTrait{ * This is overridden to change the return typehint. * * @return self[] + * @phpstan-return array */ public static function getAll() : array{ //phpstan doesn't support generic traits yet :( diff --git a/src/utils/RegistryTrait.php b/src/utils/RegistryTrait.php index 989800ef0..776980599 100644 --- a/src/utils/RegistryTrait.php +++ b/src/utils/RegistryTrait.php @@ -29,7 +29,10 @@ use function mb_strtoupper; use function preg_match; trait RegistryTrait{ - /** @var object[] */ + /** + * @var object[] + * @phpstan-var array + */ private static $members = null; private static function verifyName(string $name) : void{ @@ -107,6 +110,7 @@ trait RegistryTrait{ /** * @return object[] + * @phpstan-return array */ private static function _registryGetAll() : array{ self::checkInit(); diff --git a/src/utils/Utils.php b/src/utils/Utils.php index 8d27c9861..35d6595ca 100644 --- a/src/utils/Utils.php +++ b/src/utils/Utils.php @@ -109,6 +109,7 @@ final class Utils{ private static ?string $os = null; private static ?UuidInterface $serverUniqueId = null; + private static ?int $cpuCores = null; /** * Returns a readable identifier for the given Closure, including file and line. @@ -296,14 +297,11 @@ final class Utils{ } public static function getCoreCount(bool $recalculate = false) : int{ - static $processors = 0; - - if($processors > 0 && !$recalculate){ - return $processors; - }else{ - $processors = 0; + if(self::$cpuCores !== null && !$recalculate){ + return self::$cpuCores; } + $processors = 0; switch(Utils::getOS()){ case Utils::OS_LINUX: case Utils::OS_ANDROID: @@ -327,7 +325,7 @@ final class Utils{ $processors = (int) getenv("NUMBER_OF_PROCESSORS"); break; } - return $processors; + return self::$cpuCores = $processors; } /** @@ -366,12 +364,6 @@ final class Utils{ $ord -= 0x100; } $hash = 31 * $hash + $ord; - while($hash > 0x7FFFFFFF){ - $hash -= 0x100000000; - } - while($hash < -0x80000000){ - $hash += 0x100000000; - } $hash &= 0xFFFFFFFF; } return $hash; diff --git a/src/world/World.php b/src/world/World.php index 68ea37fa0..11b8263f5 100644 --- a/src/world/World.php +++ b/src/world/World.php @@ -173,6 +173,8 @@ class World implements ChunkManager{ /** @var Entity[] */ public array $updateEntities = []; + + private bool $inDynamicStateRecalculation = false; /** @var Block[][] */ private array $blockCache = []; @@ -1559,21 +1561,19 @@ class World implements ChunkManager{ $block->position($this, $x, $y, $z); - static $dynamicStateRead = false; - - if($dynamicStateRead){ + if($this->inDynamicStateRecalculation){ //this call was generated by a parent getBlock() call calculating dynamic stateinfo //don't calculate dynamic state and don't add to block cache (since it won't have dynamic state calculated). //this ensures that it's impossible for dynamic state properties to recursively depend on each other. $addToCache = false; }else{ - $dynamicStateRead = true; + $this->inDynamicStateRecalculation = true; $replacement = $block->readStateFromWorld(); if($replacement !== $block){ $replacement->position($this, $x, $y, $z); $block = $replacement; } - $dynamicStateRead = false; + $this->inDynamicStateRecalculation = false; } if($addToCache && $relativeBlockHash !== null){ diff --git a/tests/phpstan/configs/actual-problems.neon b/tests/phpstan/configs/actual-problems.neon index c3b0b6b47..cff6d9623 100644 --- a/tests/phpstan/configs/actual-problems.neon +++ b/tests/phpstan/configs/actual-problems.neon @@ -785,18 +785,8 @@ parameters: count: 1 path: ../../../src/plugin/PluginBase.php - - - message: "#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\\.$#" - count: 1 - path: ../../../src/plugin/PluginDescription.php - - message: "#^Cannot cast mixed to string\\.$#" - count: 5 - path: ../../../src/plugin/PluginDescription.php - - - - message: "#^Parameter \\#1 \\$data of static method pocketmine\\\\permission\\\\PermissionParser\\:\\:loadPermissions\\(\\) expects array\\\\>, mixed given\\.$#" count: 1 path: ../../../src/plugin/PluginDescription.php @@ -805,11 +795,6 @@ parameters: count: 1 path: ../../../src/plugin/PluginDescription.php - - - message: "#^Parameter \\#1 \\$name of static method pocketmine\\\\plugin\\\\PluginEnableOrder\\:\\:fromString\\(\\) expects string, mixed given\\.$#" - count: 1 - path: ../../../src/plugin/PluginDescription.php - - message: "#^Parameter \\#2 \\$subject of function preg_match expects string, mixed given\\.$#" count: 1 @@ -820,26 +805,6 @@ parameters: count: 1 path: ../../../src/plugin/PluginDescription.php - - - message: "#^Property pocketmine\\\\plugin\\\\PluginDescription\\:\\:\\$authors \\(array\\\\) does not accept array\\.$#" - count: 1 - path: ../../../src/plugin/PluginDescription.php - - - - message: "#^Property pocketmine\\\\plugin\\\\PluginDescription\\:\\:\\$authors \\(array\\\\) does not accept array\\\\.$#" - count: 1 - path: ../../../src/plugin/PluginDescription.php - - - - message: "#^Property pocketmine\\\\plugin\\\\PluginDescription\\:\\:\\$depend \\(array\\\\) does not accept array\\.$#" - count: 1 - path: ../../../src/plugin/PluginDescription.php - - - - message: "#^Property pocketmine\\\\plugin\\\\PluginDescription\\:\\:\\$loadBefore \\(array\\\\) does not accept array\\.$#" - count: 1 - path: ../../../src/plugin/PluginDescription.php - - message: "#^Property pocketmine\\\\plugin\\\\PluginDescription\\:\\:\\$main \\(string\\) does not accept mixed\\.$#" count: 1 @@ -850,16 +815,6 @@ parameters: count: 1 path: ../../../src/plugin/PluginDescription.php - - - message: "#^Property pocketmine\\\\plugin\\\\PluginDescription\\:\\:\\$softDepend \\(array\\\\) does not accept array\\.$#" - count: 1 - path: ../../../src/plugin/PluginDescription.php - - - - message: "#^Property pocketmine\\\\plugin\\\\PluginDescription\\:\\:\\$srcNamespacePrefix \\(string\\) does not accept mixed\\.$#" - count: 1 - path: ../../../src/plugin/PluginDescription.php - - message: "#^Cannot call method addChild\\(\\) on pocketmine\\\\permission\\\\Permission\\|null\\.$#" count: 4 diff --git a/tests/phpstan/configs/impossible-generics.neon b/tests/phpstan/configs/impossible-generics.neon index 0281bcd7f..b0e67d294 100644 --- a/tests/phpstan/configs/impossible-generics.neon +++ b/tests/phpstan/configs/impossible-generics.neon @@ -10,8 +10,3 @@ parameters: count: 1 path: ../../../src/event/RegisteredListener.php - - - message: "#^Property pocketmine\\\\event\\\\RegisteredListener\\:\\:\\$handler type has no signature specified for Closure\\.$#" - count: 1 - path: ../../../src/event/RegisteredListener.php - diff --git a/tests/phpstan/configs/php-bugs.neon b/tests/phpstan/configs/php-bugs.neon index f4754087b..c70ef1ecb 100644 --- a/tests/phpstan/configs/php-bugs.neon +++ b/tests/phpstan/configs/php-bugs.neon @@ -1,7 +1,6 @@ parameters: ignoreErrors: - - message: "#^Property pocketmine\\\\network\\\\mcpe\\\\handler\\\\StupidJsonDecodeTest\\:\\:\\$stupidJsonDecodeFunc \\(Closure\\(string, bool\\)\\: mixed\\) does not accept Closure\\|null\\.$#" + message: "#^Property pocketmine\\\\network\\\\mcpe\\\\handler\\\\StupidJsonDecodeTest\\:\\:\\$stupidJsonDecodeFunc \\(Closure\\(string, bool=\\)\\: mixed\\) does not accept Closure\\|null\\.$#" count: 1 path: ../../phpunit/network/mcpe/handler/StupidJsonDecodeTest.php - diff --git a/tests/phpstan/configs/phpstan-bugs.neon b/tests/phpstan/configs/phpstan-bugs.neon index dcfda66bc..b9e3e76b8 100644 --- a/tests/phpstan/configs/phpstan-bugs.neon +++ b/tests/phpstan/configs/phpstan-bugs.neon @@ -55,6 +55,11 @@ parameters: count: 1 path: ../../../src/plugin/PluginManager.php + - + message: "#^Offset \\(int\\|string\\) on non\\-empty\\-array\\ in isset\\(\\) always exists and is not nullable\\.$#" + count: 1 + path: ../../../src/plugin/PluginManager.php + - message: "#^Static property pocketmine\\\\scheduler\\\\AsyncTask\\:\\:\\$threadLocalStorage \\(ArrayObject\\\\>\\|null\\) does not accept non\\-empty\\-array\\\\>\\|ArrayObject\\\\>\\.$#" count: 1 @@ -70,6 +75,11 @@ parameters: count: 1 path: ../../../src/thread/Worker.php + - + message: "#^Offset \\(int\\|string\\) on non\\-empty\\-array\\ in isset\\(\\) always exists and is not nullable\\.$#" + count: 1 + path: ../../../src/world/WorldManager.php + - message: "#^Call to function is_resource\\(\\) with resource will always evaluate to true\\.$#" count: 2 diff --git a/tests/phpunit/block/BrewingStandTest.php b/tests/phpunit/block/BrewingStandTest.php index 58be37470..c61a1db6d 100644 --- a/tests/phpunit/block/BrewingStandTest.php +++ b/tests/phpunit/block/BrewingStandTest.php @@ -25,6 +25,7 @@ namespace pocketmine\block; use PHPUnit\Framework\TestCase; use pocketmine\block\utils\BrewingStandSlot; +use function array_values; use function count; class BrewingStandTest extends TestCase{ @@ -33,7 +34,7 @@ class BrewingStandTest extends TestCase{ * @phpstan-return \Generator}, void, void> */ public function slotsProvider() : \Generator{ - yield [BrewingStandSlot::getAll()]; + yield [array_values(BrewingStandSlot::getAll())]; yield [[BrewingStandSlot::EAST()]]; yield [[BrewingStandSlot::EAST(), BrewingStandSlot::NORTHWEST()]]; }