diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml index d8a972585d9..311e0c82799 100644 --- a/.github/workflows/draft-release.yml +++ b/.github/workflows/draft-release.yml @@ -92,7 +92,7 @@ jobs: - name: Create draft release uses: ncipollo/release-action@v1.14.0 with: - artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json + artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json,${{ github.workspace }}/core-permissions.rst commit: ${{ github.sha }} draft: true prerelease: ${{ steps.get-pm-version.outputs.PRERELEASE }} diff --git a/changelogs/5.16.md b/changelogs/5.16.md new file mode 100644 index 00000000000..8b4251d76d2 --- /dev/null +++ b/changelogs/5.16.md @@ -0,0 +1,26 @@ +# 5.16.0 +Released 13th June 2024. + +**For Minecraft: Bedrock Edition 1.21.0** + +This is a support release for Minecraft: Bedrock Edition 1.21.0. + +**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace. +Do not update plugin minimum API versions unless you need new features added in this release. + +**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.** +Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly. + +## General +- Added support for Minecraft: Bedrock Edition 1.21.0. +- Removed support for earlier versions. +- Generated permission docs are now included with every release. +- Crash throttle message (which appears when the server crashed after being up for less than 120 seconds) now shows the server uptime as well as the wait time. This should make it clearer how the wait time is decided. + +## Tools +- Added `install-local-protocol.sh` script. This allows installing local copies of protocol dependencies without needing to create releases. Useful for integration testing when doing protocol updates. + +## Fixes +- Attacking an entity with a higher damage weapon while it's on attack cooldown from a lower damage weapon (switching) no longer causes additional knockback to the victim. +- Wooden stairs can now be used as fuel in furnaces. +- Fixed incorrect description of the permission `pocketmine.command.save.perform`. diff --git a/composer.json b/composer.json index 72e75e7be56..9a7e61b73b5 100644 --- a/composer.json +++ b/composer.json @@ -33,10 +33,10 @@ "composer-runtime-api": "^2.0", "adhocore/json-comment": "~1.2.0", "pocketmine/netresearch-jsonmapper": "~v4.4.999", - "pocketmine/bedrock-block-upgrade-schema": "~4.1.0+bedrock-1.20.80", - "pocketmine/bedrock-data": "~2.10.0+bedrock-1.20.80", - "pocketmine/bedrock-item-upgrade-schema": "~1.9.0+bedrock-1.20.80", - "pocketmine/bedrock-protocol": "~30.0.0+bedrock-1.20.80", + "pocketmine/bedrock-block-upgrade-schema": "~4.2.0+bedrock-1.21.0", + "pocketmine/bedrock-data": "~2.11.0+bedrock-1.21.0", + "pocketmine/bedrock-item-upgrade-schema": "~1.10.0+bedrock-1.21.0", + "pocketmine/bedrock-protocol": "~31.0.0+bedrock-1.21.0", "pocketmine/binaryutils": "^0.2.1", "pocketmine/callback-validator": "^1.0.2", "pocketmine/color": "^0.3.0", @@ -52,10 +52,10 @@ "symfony/filesystem": "~6.4.0" }, "require-dev": { - "phpstan/phpstan": "1.10.67", + "phpstan/phpstan": "1.11.2", "phpstan/phpstan-phpunit": "^1.1.0", "phpstan/phpstan-strict-rules": "^1.2.0", - "phpunit/phpunit": "~10.3.0 || ~10.2.0 || ~10.1.0" + "phpunit/phpunit": "^10.5.24" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 22fdd9305f6..ce8d52e266c 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": "99069514f4fb8ee6b03b0da07a77a486", + "content-hash": "6254ce9a454f8c9acd4936512c4d315a", "packages": [ { "name": "adhocore/json-comment", @@ -127,16 +127,16 @@ }, { "name": "pocketmine/bedrock-block-upgrade-schema", - "version": "4.1.0", + "version": "4.2.0", "source": { "type": "git", "url": "https://github.com/pmmp/BedrockBlockUpgradeSchema.git", - "reference": "d6b10cb0a5e69fb1dfe3b7f493bf4f519723a9cb" + "reference": "8a327197b3b462fa282f40f76b070ffe585a25d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/d6b10cb0a5e69fb1dfe3b7f493bf4f519723a9cb", - "reference": "d6b10cb0a5e69fb1dfe3b7f493bf4f519723a9cb", + "url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/8a327197b3b462fa282f40f76b070ffe585a25d2", + "reference": "8a327197b3b462fa282f40f76b070ffe585a25d2", "shasum": "" }, "type": "library", @@ -147,22 +147,22 @@ "description": "Schemas describing how to upgrade saved block data in older Minecraft: Bedrock Edition world saves", "support": { "issues": "https://github.com/pmmp/BedrockBlockUpgradeSchema/issues", - "source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/4.1.0" + "source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/4.2.0" }, - "time": "2024-04-05T17:28:14+00:00" + "time": "2024-06-13T17:28:26+00:00" }, { "name": "pocketmine/bedrock-data", - "version": "2.10.0+bedrock-1.20.80", + "version": "2.11.0+bedrock-1.21.0", "source": { "type": "git", "url": "https://github.com/pmmp/BedrockData.git", - "reference": "d7d709fec3848f56ca77f5ff0e5d4741b59f9d69" + "reference": "cae40bde98081b388c4d3ab59d45b8d1cf5d8761" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BedrockData/zipball/d7d709fec3848f56ca77f5ff0e5d4741b59f9d69", - "reference": "d7d709fec3848f56ca77f5ff0e5d4741b59f9d69", + "url": "https://api.github.com/repos/pmmp/BedrockData/zipball/cae40bde98081b388c4d3ab59d45b8d1cf5d8761", + "reference": "cae40bde98081b388c4d3ab59d45b8d1cf5d8761", "shasum": "" }, "type": "library", @@ -173,22 +173,22 @@ "description": "Blobs of data generated from Minecraft: Bedrock Edition, used by PocketMine-MP", "support": { "issues": "https://github.com/pmmp/BedrockData/issues", - "source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.20.80" + "source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.21.0" }, - "time": "2024-04-25T10:08:23+00:00" + "time": "2024-06-13T17:17:55+00:00" }, { "name": "pocketmine/bedrock-item-upgrade-schema", - "version": "1.9.0", + "version": "1.10.0", "source": { "type": "git", "url": "https://github.com/pmmp/BedrockItemUpgradeSchema.git", - "reference": "24a89457c17c271b5378b195931e720873865a79" + "reference": "b4687afa19f91eacebd46c40d487f4cc515be504" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/24a89457c17c271b5378b195931e720873865a79", - "reference": "24a89457c17c271b5378b195931e720873865a79", + "url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/b4687afa19f91eacebd46c40d487f4cc515be504", + "reference": "b4687afa19f91eacebd46c40d487f4cc515be504", "shasum": "" }, "type": "library", @@ -199,22 +199,22 @@ "description": "JSON schemas for upgrading items found in older Minecraft: Bedrock world saves", "support": { "issues": "https://github.com/pmmp/BedrockItemUpgradeSchema/issues", - "source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.9.0" + "source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.10.0" }, - "time": "2024-04-05T18:46:07+00:00" + "time": "2024-05-15T15:15:55+00:00" }, { "name": "pocketmine/bedrock-protocol", - "version": "30.0.0+bedrock-1.20.80", + "version": "31.0.0+bedrock-1.21.0", "source": { "type": "git", "url": "https://github.com/pmmp/BedrockProtocol.git", - "reference": "dc7606a9f778eeeeccfae393bd58e0b62ec6f85a" + "reference": "972373b6b8068963649f0a95163424eb5b645e29" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/dc7606a9f778eeeeccfae393bd58e0b62ec6f85a", - "reference": "dc7606a9f778eeeeccfae393bd58e0b62ec6f85a", + "url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/972373b6b8068963649f0a95163424eb5b645e29", + "reference": "972373b6b8068963649f0a95163424eb5b645e29", "shasum": "" }, "require": { @@ -227,7 +227,7 @@ "ramsey/uuid": "^4.1" }, "require-dev": { - "phpstan/phpstan": "1.10.59", + "phpstan/phpstan": "1.11.2", "phpstan/phpstan-phpunit": "^1.0.0", "phpstan/phpstan-strict-rules": "^1.0.0", "phpunit/phpunit": "^9.5 || ^10.0" @@ -245,9 +245,9 @@ "description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP", "support": { "issues": "https://github.com/pmmp/BedrockProtocol/issues", - "source": "https://github.com/pmmp/BedrockProtocol/tree/30.0.0+bedrock-1.20.80" + "source": "https://github.com/pmmp/BedrockProtocol/tree/31.0.0+bedrock-1.21.0" }, - "time": "2024-04-05T17:53:35+00:00" + "time": "2024-06-13T17:34:14+00:00" }, { "name": "pocketmine/binaryutils", @@ -926,23 +926,25 @@ }, { "name": "symfony/filesystem", - "version": "v6.4.7", + "version": "v6.4.9", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "78dde75f8f6dbbca4ec436a4b0087f7af02076d4" + "reference": "b51ef8059159330b74a4d52f68e671033c0fe463" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/78dde75f8f6dbbca4ec436a4b0087f7af02076d4", - "reference": "78dde75f8f6dbbca4ec436a4b0087f7af02076d4", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b51ef8059159330b74a4d52f68e671033c0fe463", + "reference": "b51ef8059159330b74a4d52f68e671033c0fe463", "shasum": "" }, "require": { "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/process": "^5.4|^6.4" + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^5.4|^6.4|^7.0" }, "type": "library", "autoload": { @@ -970,7 +972,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.7" + "source": "https://github.com/symfony/filesystem/tree/v6.4.9" }, "funding": [ { @@ -986,20 +988,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-06-28T09:49:33+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + "reference": "0424dff1c58f028c451efff2045f5d92410bd540" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", + "reference": "0424dff1c58f028c451efff2045f5d92410bd540", "shasum": "" }, "require": { @@ -1049,7 +1051,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" }, "funding": [ { @@ -1065,20 +1067,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", "shasum": "" }, "require": { @@ -1129,68 +1131,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-01-29T20:11:03+00:00" - }, - { - "name": "symfony/process", - "version": "v6.4.7", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "cdb1c81c145fd5aa9b0038bab694035020943381" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/cdb1c81c145fd5aa9b0038bab694035020943381", - "reference": "cdb1c81c145fd5aa9b0038bab694035020943381", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v6.4.7" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" }, "funding": [ { @@ -1206,22 +1147,22 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-06-19T12:30:46+00:00" } ], "packages-dev": [ { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { @@ -1229,11 +1170,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -1259,7 +1201,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" }, "funding": [ { @@ -1267,7 +1209,7 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-06-12T14:39:25+00:00" }, { "name": "nikic/php-parser", @@ -1447,16 +1389,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.67", + "version": "1.11.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493" + "reference": "0d5d4294a70deb7547db655c47685d680e39cfec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/16ddbe776f10da6a95ebd25de7c1dbed397dc493", - "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0d5d4294a70deb7547db655c47685d680e39cfec", + "reference": "0d5d4294a70deb7547db655c47685d680e39cfec", "shasum": "" }, "require": { @@ -1501,7 +1443,7 @@ "type": "github" } ], - "time": "2024-04-16T07:22:02+00:00" + "time": "2024-05-24T13:23:04+00:00" }, { "name": "phpstan/phpstan-phpunit", @@ -1606,16 +1548,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "10.1.14", + "version": "10.1.15", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "e3f51450ebffe8e0efdf7346ae966a656f7d5e5b" + "reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e3f51450ebffe8e0efdf7346ae966a656f7d5e5b", - "reference": "e3f51450ebffe8e0efdf7346ae966a656f7d5e5b", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae", + "reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae", "shasum": "" }, "require": { @@ -1672,7 +1614,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.14" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.15" }, "funding": [ { @@ -1680,7 +1622,7 @@ "type": "github" } ], - "time": "2024-03-12T15:33:41+00:00" + "time": "2024-06-29T08:25:15+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1927,16 +1869,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.3.5", + "version": "10.5.24", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "747c3b2038f1139e3dcd9886a3f5a948648b7503" + "reference": "5f124e3e3e561006047b532fd0431bf5bb6b9015" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/747c3b2038f1139e3dcd9886a3f5a948648b7503", - "reference": "747c3b2038f1139e3dcd9886a3f5a948648b7503", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5f124e3e3e561006047b532fd0431bf5bb6b9015", + "reference": "5f124e3e3e561006047b532fd0431bf5bb6b9015", "shasum": "" }, "require": { @@ -1976,7 +1918,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.3-dev" + "dev-main": "10.5-dev" } }, "autoload": { @@ -2008,7 +1950,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.5" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.24" }, "funding": [ { @@ -2024,7 +1966,7 @@ "type": "tidelift" } ], - "time": "2023-09-19T05:42:37+00:00" + "time": "2024-06-20T13:09:54+00:00" }, { "name": "sebastian/cli-parser", diff --git a/src/block/Bell.php b/src/block/Bell.php index ec033cef87a..53a6fc7fbb4 100644 --- a/src/block/Bell.php +++ b/src/block/Bell.php @@ -150,6 +150,10 @@ public function ring(int $faceHit) : void{ } } + public function getDropsForIncompatibleTool(Item $item) : array{ + return [$this->asItem()]; + } + private function isValidFaceToRing(int $faceHit) : bool{ return match($this->attachmentType){ BellAttachmentType::CEILING => true, diff --git a/src/crafting/CraftingManagerFromDataHelper.php b/src/crafting/CraftingManagerFromDataHelper.php index 8315f2b3b33..6e5bbcd1fa4 100644 --- a/src/crafting/CraftingManagerFromDataHelper.php +++ b/src/crafting/CraftingManagerFromDataHelper.php @@ -236,6 +236,7 @@ public static function make(string $directoryPath) : CraftingManager{ } $outputs[] = $output; } + //TODO: check unlocking requirements - our current system doesn't support this $result->registerShapelessRecipe(new ShapelessRecipe( $inputs, $outputs, @@ -262,6 +263,7 @@ public static function make(string $directoryPath) : CraftingManager{ } $outputs[] = $output; } + //TODO: check unlocking requirements - our current system doesn't support this $result->registerShapedRecipe(new ShapedRecipe( $recipe->shape, $inputs, diff --git a/src/crafting/json/ShapedRecipeData.php b/src/crafting/json/ShapedRecipeData.php index dd040f516ed..965a437ea62 100644 --- a/src/crafting/json/ShapedRecipeData.php +++ b/src/crafting/json/ShapedRecipeData.php @@ -23,7 +23,9 @@ namespace pocketmine\crafting\json; -final class ShapedRecipeData{ +use function count; + +final class ShapedRecipeData implements \JsonSerializable{ /** * @required * @var string[] @@ -51,22 +53,39 @@ final class ShapedRecipeData{ /** @required */ public int $priority; + /** @var RecipeIngredientData[] */ + public array $unlockingIngredients = []; + /** * TODO: convert this to use promoted properties - avoiding them for now since it would break JsonMapper * * @param string[] $shape * @param RecipeIngredientData[] $input * @param ItemStackData[] $output + * @param RecipeIngredientData[] $unlockingIngredients * * @phpstan-param list $shape * @phpstan-param array $input * @phpstan-param list $output + * @phpstan-param list $unlockingIngredients */ - public function __construct(array $shape, array $input, array $output, string $block, int $priority){ + public function __construct(array $shape, array $input, array $output, string $block, int $priority, array $unlockingIngredients = []){ $this->block = $block; $this->priority = $priority; $this->shape = $shape; $this->input = $input; $this->output = $output; + $this->unlockingIngredients = $unlockingIngredients; + } + + /** + * @return mixed[] + */ + public function jsonSerialize() : array{ + $result = (array) $this; + if(count($this->unlockingIngredients) === 0){ + unset($result["unlockingIngredients"]); + } + return $result; } } diff --git a/src/crafting/json/ShapelessRecipeData.php b/src/crafting/json/ShapelessRecipeData.php index d59bafbbf3f..23cfebde0b0 100644 --- a/src/crafting/json/ShapelessRecipeData.php +++ b/src/crafting/json/ShapelessRecipeData.php @@ -23,7 +23,9 @@ namespace pocketmine\crafting\json; -final class ShapelessRecipeData{ +use function count; + +final class ShapelessRecipeData implements \JsonSerializable{ /** * @required @@ -45,17 +47,34 @@ final class ShapelessRecipeData{ /** @required */ public int $priority; + /** @var RecipeIngredientData[] */ + public array $unlockingIngredients = []; + /** * @param RecipeIngredientData[] $input * @param ItemStackData[] $output + * @param RecipeIngredientData[] $unlockingIngredients * * @phpstan-param list $input * @phpstan-param list $output + * @phpstan-param list $unlockingIngredients */ - public function __construct(array $input, array $output, string $block, int $priority){ + public function __construct(array $input, array $output, string $block, int $priority, array $unlockingIngredients = []){ $this->block = $block; $this->priority = $priority; $this->input = $input; $this->output = $output; + $this->unlockingIngredients = $unlockingIngredients; + } + + /** + * @return mixed[] + */ + public function jsonSerialize() : array{ + $result = (array) $this; + if(count($this->unlockingIngredients) === 0){ + unset($result["unlockingIngredients"]); + } + return $result; } } diff --git a/src/data/bedrock/block/BlockStateData.php b/src/data/bedrock/block/BlockStateData.php index 21f2bc53cd6..51899b72bf8 100644 --- a/src/data/bedrock/block/BlockStateData.php +++ b/src/data/bedrock/block/BlockStateData.php @@ -41,8 +41,8 @@ final class BlockStateData{ */ public const CURRENT_VERSION = (1 << 24) | //major - (20 << 16) | //minor - (80 << 8) | //patch + (21 << 16) | //minor + (0 << 8) | //patch (3); //revision public const TAG_NAME = "name"; diff --git a/src/data/bedrock/block/BlockStateNames.php b/src/data/bedrock/block/BlockStateNames.php index b996acf04ed..4564f696eab 100644 --- a/src/data/bedrock/block/BlockStateNames.php +++ b/src/data/bedrock/block/BlockStateNames.php @@ -59,7 +59,6 @@ private function __construct(){ public const COLOR_BIT = "color_bit"; public const COMPOSTER_FILL_LEVEL = "composter_fill_level"; public const CONDITIONAL_BIT = "conditional_bit"; - public const CORAL_COLOR = "coral_color"; public const CORAL_DIRECTION = "coral_direction"; public const CORAL_FAN_DIRECTION = "coral_fan_direction"; public const CORAL_HANG_TYPE_BIT = "coral_hang_type_bit"; @@ -73,7 +72,6 @@ private function __construct(){ public const DIRT_TYPE = "dirt_type"; public const DISARMED_BIT = "disarmed_bit"; public const DOOR_HINGE_BIT = "door_hinge_bit"; - public const DOUBLE_PLANT_TYPE = "double_plant_type"; public const DRAG_DOWN = "drag_down"; public const DRIPSTONE_THICKNESS = "dripstone_thickness"; public const END_PORTAL_EYE_BIT = "end_portal_eye_bit"; @@ -105,6 +103,7 @@ private function __construct(){ public const MONSTER_EGG_STONE_TYPE = "monster_egg_stone_type"; public const MULTI_FACE_DIRECTION_BITS = "multi_face_direction_bits"; public const OCCUPIED_BIT = "occupied_bit"; + public const OMINOUS = "ominous"; public const OPEN_BIT = "open_bit"; public const ORIENTATION = "orientation"; public const OUTPUT_LIT_BIT = "output_lit_bit"; @@ -137,7 +136,6 @@ private function __construct(){ public const STRUCTURE_BLOCK_TYPE = "structure_block_type"; public const STRUCTURE_VOID_TYPE = "structure_void_type"; public const SUSPENDED_BIT = "suspended_bit"; - public const TALL_GRASS_TYPE = "tall_grass_type"; public const TOGGLE_BIT = "toggle_bit"; public const TORCH_FACING_DIRECTION = "torch_facing_direction"; public const TRIAL_SPAWNER_STATE = "trial_spawner_state"; diff --git a/src/data/bedrock/block/BlockStateStringValues.php b/src/data/bedrock/block/BlockStateStringValues.php index 2b45c473873..8538c3deb8b 100644 --- a/src/data/bedrock/block/BlockStateStringValues.php +++ b/src/data/bedrock/block/BlockStateStringValues.php @@ -62,12 +62,6 @@ private function __construct(){ public const CHISEL_TYPE_LINES = "lines"; public const CHISEL_TYPE_SMOOTH = "smooth"; - public const CORAL_COLOR_BLUE = "blue"; - public const CORAL_COLOR_PINK = "pink"; - public const CORAL_COLOR_PURPLE = "purple"; - public const CORAL_COLOR_RED = "red"; - public const CORAL_COLOR_YELLOW = "yellow"; - public const CRACKED_STATE_CRACKED = "cracked"; public const CRACKED_STATE_MAX_CRACKED = "max_cracked"; public const CRACKED_STATE_NO_CRACKS = "no_cracks"; @@ -80,13 +74,6 @@ private function __construct(){ public const DIRT_TYPE_COARSE = "coarse"; public const DIRT_TYPE_NORMAL = "normal"; - public const DOUBLE_PLANT_TYPE_FERN = "fern"; - public const DOUBLE_PLANT_TYPE_GRASS = "grass"; - public const DOUBLE_PLANT_TYPE_PAEONIA = "paeonia"; - public const DOUBLE_PLANT_TYPE_ROSE = "rose"; - public const DOUBLE_PLANT_TYPE_SUNFLOWER = "sunflower"; - public const DOUBLE_PLANT_TYPE_SYRINGA = "syringa"; - public const DRIPSTONE_THICKNESS_BASE = "base"; public const DRIPSTONE_THICKNESS_FRUSTUM = "frustum"; public const DRIPSTONE_THICKNESS_MERGE = "merge"; @@ -220,11 +207,6 @@ private function __construct(){ public const STRUCTURE_VOID_TYPE_AIR = "air"; public const STRUCTURE_VOID_TYPE_VOID = "void"; - public const TALL_GRASS_TYPE_DEFAULT = "default"; - public const TALL_GRASS_TYPE_FERN = "fern"; - public const TALL_GRASS_TYPE_SNOW = "snow"; - public const TALL_GRASS_TYPE_TALL = "tall"; - public const TORCH_FACING_DIRECTION_EAST = "east"; public const TORCH_FACING_DIRECTION_NORTH = "north"; public const TORCH_FACING_DIRECTION_SOUTH = "south"; diff --git a/src/data/bedrock/block/BlockTypeNames.php b/src/data/bedrock/block/BlockTypeNames.php index 9dc0961d2df..25433e6ebc0 100644 --- a/src/data/bedrock/block/BlockTypeNames.php +++ b/src/data/bedrock/block/BlockTypeNames.php @@ -144,9 +144,11 @@ private function __construct(){ public const BOOKSHELF = "minecraft:bookshelf"; public const BORDER_BLOCK = "minecraft:border_block"; public const BRAIN_CORAL = "minecraft:brain_coral"; + public const BRAIN_CORAL_BLOCK = "minecraft:brain_coral_block"; public const BRAIN_CORAL_FAN = "minecraft:brain_coral_fan"; public const BREWING_STAND = "minecraft:brewing_stand"; public const BRICK_BLOCK = "minecraft:brick_block"; + public const BRICK_SLAB = "minecraft:brick_slab"; public const BRICK_STAIRS = "minecraft:brick_stairs"; public const BROWN_CANDLE = "minecraft:brown_candle"; public const BROWN_CANDLE_CAKE = "minecraft:brown_candle_cake"; @@ -163,6 +165,7 @@ private function __construct(){ public const BROWN_WOOL = "minecraft:brown_wool"; public const BUBBLE_COLUMN = "minecraft:bubble_column"; public const BUBBLE_CORAL = "minecraft:bubble_coral"; + public const BUBBLE_CORAL_BLOCK = "minecraft:bubble_coral_block"; public const BUBBLE_CORAL_FAN = "minecraft:bubble_coral_fan"; public const BUDDING_AMETHYST = "minecraft:budding_amethyst"; public const CACTUS = "minecraft:cactus"; @@ -221,6 +224,7 @@ private function __construct(){ public const COBBLED_DEEPSLATE_STAIRS = "minecraft:cobbled_deepslate_stairs"; public const COBBLED_DEEPSLATE_WALL = "minecraft:cobbled_deepslate_wall"; public const COBBLESTONE = "minecraft:cobblestone"; + public const COBBLESTONE_SLAB = "minecraft:cobblestone_slab"; public const COBBLESTONE_WALL = "minecraft:cobblestone_wall"; public const COCOA = "minecraft:cocoa"; public const COLORED_TORCH_BP = "minecraft:colored_torch_bp"; @@ -234,7 +238,6 @@ private function __construct(){ public const COPPER_GRATE = "minecraft:copper_grate"; public const COPPER_ORE = "minecraft:copper_ore"; public const COPPER_TRAPDOOR = "minecraft:copper_trapdoor"; - public const CORAL_BLOCK = "minecraft:coral_block"; public const CORAL_FAN_HANG = "minecraft:coral_fan_hang"; public const CORAL_FAN_HANG2 = "minecraft:coral_fan_hang2"; public const CORAL_FAN_HANG3 = "minecraft:coral_fan_hang3"; @@ -299,14 +302,19 @@ private function __construct(){ public const DAYLIGHT_DETECTOR = "minecraft:daylight_detector"; public const DAYLIGHT_DETECTOR_INVERTED = "minecraft:daylight_detector_inverted"; public const DEAD_BRAIN_CORAL = "minecraft:dead_brain_coral"; + public const DEAD_BRAIN_CORAL_BLOCK = "minecraft:dead_brain_coral_block"; public const DEAD_BRAIN_CORAL_FAN = "minecraft:dead_brain_coral_fan"; public const DEAD_BUBBLE_CORAL = "minecraft:dead_bubble_coral"; + public const DEAD_BUBBLE_CORAL_BLOCK = "minecraft:dead_bubble_coral_block"; public const DEAD_BUBBLE_CORAL_FAN = "minecraft:dead_bubble_coral_fan"; public const DEAD_FIRE_CORAL = "minecraft:dead_fire_coral"; + public const DEAD_FIRE_CORAL_BLOCK = "minecraft:dead_fire_coral_block"; public const DEAD_FIRE_CORAL_FAN = "minecraft:dead_fire_coral_fan"; public const DEAD_HORN_CORAL = "minecraft:dead_horn_coral"; + public const DEAD_HORN_CORAL_BLOCK = "minecraft:dead_horn_coral_block"; public const DEAD_HORN_CORAL_FAN = "minecraft:dead_horn_coral_fan"; public const DEAD_TUBE_CORAL = "minecraft:dead_tube_coral"; + public const DEAD_TUBE_CORAL_BLOCK = "minecraft:dead_tube_coral_block"; public const DEAD_TUBE_CORAL_FAN = "minecraft:dead_tube_coral_fan"; public const DEADBUSH = "minecraft:deadbush"; public const DECORATED_POT = "minecraft:decorated_pot"; @@ -339,7 +347,6 @@ private function __construct(){ public const DIRT_WITH_ROOTS = "minecraft:dirt_with_roots"; public const DISPENSER = "minecraft:dispenser"; public const DOUBLE_CUT_COPPER_SLAB = "minecraft:double_cut_copper_slab"; - public const DOUBLE_PLANT = "minecraft:double_plant"; public const DOUBLE_STONE_BLOCK_SLAB = "minecraft:double_stone_block_slab"; public const DOUBLE_STONE_BLOCK_SLAB2 = "minecraft:double_stone_block_slab2"; public const DOUBLE_STONE_BLOCK_SLAB3 = "minecraft:double_stone_block_slab3"; @@ -490,8 +497,10 @@ private function __construct(){ public const EXPOSED_DOUBLE_CUT_COPPER_SLAB = "minecraft:exposed_double_cut_copper_slab"; public const FARMLAND = "minecraft:farmland"; public const FENCE_GATE = "minecraft:fence_gate"; + public const FERN = "minecraft:fern"; public const FIRE = "minecraft:fire"; public const FIRE_CORAL = "minecraft:fire_coral"; + public const FIRE_CORAL_BLOCK = "minecraft:fire_coral_block"; public const FIRE_CORAL_FAN = "minecraft:fire_coral_fan"; public const FLETCHING_TABLE = "minecraft:fletching_table"; public const FLOWER_POT = "minecraft:flower_pot"; @@ -583,6 +592,7 @@ private function __construct(){ public const HONEYCOMB_BLOCK = "minecraft:honeycomb_block"; public const HOPPER = "minecraft:hopper"; public const HORN_CORAL = "minecraft:horn_coral"; + public const HORN_CORAL_BLOCK = "minecraft:horn_coral_block"; public const HORN_CORAL_FAN = "minecraft:horn_coral_fan"; public const ICE = "minecraft:ice"; public const INFESTED_DEEPSLATE = "minecraft:infested_deepslate"; @@ -619,6 +629,7 @@ private function __construct(){ public const LAPIS_BLOCK = "minecraft:lapis_block"; public const LAPIS_ORE = "minecraft:lapis_ore"; public const LARGE_AMETHYST_BUD = "minecraft:large_amethyst_bud"; + public const LARGE_FERN = "minecraft:large_fern"; public const LAVA = "minecraft:lava"; public const LECTERN = "minecraft:lectern"; public const LEVER = "minecraft:lever"; @@ -646,6 +657,7 @@ private function __construct(){ public const LIGHT_GRAY_WOOL = "minecraft:light_gray_wool"; public const LIGHT_WEIGHTED_PRESSURE_PLATE = "minecraft:light_weighted_pressure_plate"; public const LIGHTNING_ROD = "minecraft:lightning_rod"; + public const LILAC = "minecraft:lilac"; public const LILY_OF_THE_VALLEY = "minecraft:lily_of_the_valley"; public const LIME_CANDLE = "minecraft:lime_candle"; public const LIME_CANDLE_CAKE = "minecraft:lime_candle_cake"; @@ -718,6 +730,7 @@ private function __construct(){ public const MYCELIUM = "minecraft:mycelium"; public const NETHER_BRICK = "minecraft:nether_brick"; public const NETHER_BRICK_FENCE = "minecraft:nether_brick_fence"; + public const NETHER_BRICK_SLAB = "minecraft:nether_brick_slab"; public const NETHER_BRICK_STAIRS = "minecraft:nether_brick_stairs"; public const NETHER_GOLD_ORE = "minecraft:nether_gold_ore"; public const NETHER_SPROUTS = "minecraft:nether_sprouts"; @@ -767,6 +780,8 @@ private function __construct(){ public const PACKED_ICE = "minecraft:packed_ice"; public const PACKED_MUD = "minecraft:packed_mud"; public const PEARLESCENT_FROGLIGHT = "minecraft:pearlescent_froglight"; + public const PEONY = "minecraft:peony"; + public const PETRIFIED_OAK_SLAB = "minecraft:petrified_oak_slab"; public const PINK_CANDLE = "minecraft:pink_candle"; public const PINK_CANDLE_CAKE = "minecraft:pink_candle_cake"; public const PINK_CARPET = "minecraft:pink_carpet"; @@ -842,6 +857,7 @@ private function __construct(){ public const QUARTZ_BLOCK = "minecraft:quartz_block"; public const QUARTZ_BRICKS = "minecraft:quartz_bricks"; public const QUARTZ_ORE = "minecraft:quartz_ore"; + public const QUARTZ_SLAB = "minecraft:quartz_slab"; public const QUARTZ_STAIRS = "minecraft:quartz_stairs"; public const RAIL = "minecraft:rail"; public const RAW_COPPER_BLOCK = "minecraft:raw_copper_block"; @@ -875,8 +891,10 @@ private function __construct(){ public const REPEATING_COMMAND_BLOCK = "minecraft:repeating_command_block"; public const RESERVED6 = "minecraft:reserved6"; public const RESPAWN_ANCHOR = "minecraft:respawn_anchor"; + public const ROSE_BUSH = "minecraft:rose_bush"; public const SAND = "minecraft:sand"; public const SANDSTONE = "minecraft:sandstone"; + public const SANDSTONE_SLAB = "minecraft:sandstone_slab"; public const SANDSTONE_STAIRS = "minecraft:sandstone_stairs"; public const SCAFFOLDING = "minecraft:scaffolding"; public const SCULK = "minecraft:sculk"; @@ -887,6 +905,7 @@ private function __construct(){ public const SEA_LANTERN = "minecraft:sea_lantern"; public const SEA_PICKLE = "minecraft:sea_pickle"; public const SEAGRASS = "minecraft:seagrass"; + public const SHORT_GRASS = "minecraft:short_grass"; public const SHROOMLIGHT = "minecraft:shroomlight"; public const SILVER_GLAZED_TERRACOTTA = "minecraft:silver_glazed_terracotta"; public const SKULL = "minecraft:skull"; @@ -900,6 +919,7 @@ private function __construct(){ public const SMOOTH_RED_SANDSTONE_STAIRS = "minecraft:smooth_red_sandstone_stairs"; public const SMOOTH_SANDSTONE_STAIRS = "minecraft:smooth_sandstone_stairs"; public const SMOOTH_STONE = "minecraft:smooth_stone"; + public const SMOOTH_STONE_SLAB = "minecraft:smooth_stone_slab"; public const SNIFFER_EGG = "minecraft:sniffer_egg"; public const SNOW = "minecraft:snow"; public const SNOW_LAYER = "minecraft:snow_layer"; @@ -933,10 +953,10 @@ private function __construct(){ public const STICKY_PISTON = "minecraft:sticky_piston"; public const STICKY_PISTON_ARM_COLLISION = "minecraft:sticky_piston_arm_collision"; public const STONE = "minecraft:stone"; - public const STONE_BLOCK_SLAB = "minecraft:stone_block_slab"; public const STONE_BLOCK_SLAB2 = "minecraft:stone_block_slab2"; public const STONE_BLOCK_SLAB3 = "minecraft:stone_block_slab3"; public const STONE_BLOCK_SLAB4 = "minecraft:stone_block_slab4"; + public const STONE_BRICK_SLAB = "minecraft:stone_brick_slab"; public const STONE_BRICK_STAIRS = "minecraft:stone_brick_stairs"; public const STONE_BUTTON = "minecraft:stone_button"; public const STONE_PRESSURE_PLATE = "minecraft:stone_pressure_plate"; @@ -967,10 +987,11 @@ private function __construct(){ public const STRIPPED_WARPED_STEM = "minecraft:stripped_warped_stem"; public const STRUCTURE_BLOCK = "minecraft:structure_block"; public const STRUCTURE_VOID = "minecraft:structure_void"; + public const SUNFLOWER = "minecraft:sunflower"; public const SUSPICIOUS_GRAVEL = "minecraft:suspicious_gravel"; public const SUSPICIOUS_SAND = "minecraft:suspicious_sand"; public const SWEET_BERRY_BUSH = "minecraft:sweet_berry_bush"; - public const TALLGRASS = "minecraft:tallgrass"; + public const TALL_GRASS = "minecraft:tall_grass"; public const TARGET = "minecraft:target"; public const TINTED_GLASS = "minecraft:tinted_glass"; public const TNT = "minecraft:tnt"; @@ -983,6 +1004,7 @@ private function __construct(){ public const TRIP_WIRE = "minecraft:trip_wire"; public const TRIPWIRE_HOOK = "minecraft:tripwire_hook"; public const TUBE_CORAL = "minecraft:tube_coral"; + public const TUBE_CORAL_BLOCK = "minecraft:tube_coral_block"; public const TUBE_CORAL_FAN = "minecraft:tube_coral_fan"; public const TUFF = "minecraft:tuff"; public const TUFF_BRICK_DOUBLE_SLAB = "minecraft:tuff_brick_double_slab"; diff --git a/src/data/bedrock/block/convert/BlockObjectToStateSerializer.php b/src/data/bedrock/block/convert/BlockObjectToStateSerializer.php index e0c570ee4ba..ab98e75f36b 100644 --- a/src/data/bedrock/block/convert/BlockObjectToStateSerializer.php +++ b/src/data/bedrock/block/convert/BlockObjectToStateSerializer.php @@ -552,6 +552,16 @@ private function registerFlatCoralSerializers() : void{ Axis::Z => 1, default => throw new BlockStateSerializeException("Invalid axis {$axis}"), })); + + $this->map(Blocks::CORAL_BLOCK(), fn(CoralBlock $block) => Writer::create( + match($block->getCoralType()){ + CoralType::BRAIN => $block->isDead() ? Ids::DEAD_BRAIN_CORAL_BLOCK : Ids::BRAIN_CORAL_BLOCK, + CoralType::BUBBLE => $block->isDead() ? Ids::DEAD_BUBBLE_CORAL_BLOCK : Ids::BUBBLE_CORAL_BLOCK, + CoralType::FIRE => $block->isDead() ? Ids::DEAD_FIRE_CORAL_BLOCK : Ids::FIRE_CORAL_BLOCK, + CoralType::HORN => $block->isDead() ? Ids::DEAD_HORN_CORAL_BLOCK : Ids::HORN_CORAL_BLOCK, + CoralType::TUBE => $block->isDead() ? Ids::DEAD_TUBE_CORAL_BLOCK : Ids::TUBE_CORAL_BLOCK, + } + )); } private function registerCauldronSerializers() : void{ @@ -928,6 +938,7 @@ private function registerSimpleSerializers() : void{ $this->mapSimple(Blocks::ENCHANTING_TABLE(), Ids::ENCHANTING_TABLE); $this->mapSimple(Blocks::END_STONE(), Ids::END_STONE); $this->mapSimple(Blocks::END_STONE_BRICKS(), Ids::END_BRICKS); + $this->mapSimple(Blocks::FERN(), Ids::FERN); $this->mapSimple(Blocks::FLETCHING_TABLE(), Ids::FLETCHING_TABLE); $this->mapSimple(Blocks::GILDED_BLACKSTONE(), Ids::GILDED_BLACKSTONE); $this->mapSimple(Blocks::GLASS(), Ids::GLASS); @@ -1006,6 +1017,7 @@ private function registerSimpleSerializers() : void{ $this->mapSimple(Blocks::SOUL_SOIL(), Ids::SOUL_SOIL); $this->mapSimple(Blocks::SPORE_BLOSSOM(), Ids::SPORE_BLOSSOM); $this->mapSimple(Blocks::STONE(), Ids::STONE); + $this->mapSimple(Blocks::TALL_GRASS(), Ids::SHORT_GRASS); //no, this is not a typo - tall_grass is now the double block, just to be confusing :( $this->mapSimple(Blocks::TINTED_GLASS(), Ids::TINTED_GLASS); $this->mapSimple(Blocks::TORCHFLOWER(), Ids::TORCHFLOWER); $this->mapSimple(Blocks::TUFF(), Ids::TUFF); @@ -1136,7 +1148,7 @@ private function registerSerializers() : void{ ->writeBool(StateNames::BREWING_STAND_SLOT_B_BIT, $block->hasSlot(BrewingStandSlot::SOUTHWEST)) ->writeBool(StateNames::BREWING_STAND_SLOT_C_BIT, $block->hasSlot(BrewingStandSlot::NORTHWEST)); }); - $this->map(Blocks::BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, StringValues::STONE_SLAB_TYPE_BRICK)); + $this->map(Blocks::BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::BRICK_SLAB, StringValues::STONE_SLAB_TYPE_BRICK)); $this->mapStairs(Blocks::BRICK_STAIRS(), Ids::BRICK_STAIRS); $this->map(Blocks::BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_BRICK)); $this->map(Blocks::BROWN_MUSHROOM_BLOCK(), fn(BrownMushroomBlock $block) => Helper::encodeMushroomBlock($block, new Writer(Ids::BROWN_MUSHROOM_BLOCK))); @@ -1192,7 +1204,7 @@ private function registerSerializers() : void{ $this->mapSlab(Blocks::COBBLED_DEEPSLATE_SLAB(), Ids::COBBLED_DEEPSLATE_SLAB, Ids::COBBLED_DEEPSLATE_DOUBLE_SLAB); $this->mapStairs(Blocks::COBBLED_DEEPSLATE_STAIRS(), Ids::COBBLED_DEEPSLATE_STAIRS); $this->map(Blocks::COBBLED_DEEPSLATE_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::COBBLED_DEEPSLATE_WALL))); - $this->map(Blocks::COBBLESTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, StringValues::STONE_SLAB_TYPE_COBBLESTONE)); + $this->map(Blocks::COBBLESTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::COBBLESTONE_SLAB, StringValues::STONE_SLAB_TYPE_COBBLESTONE)); $this->mapStairs(Blocks::COBBLESTONE_STAIRS(), Ids::STONE_STAIRS); $this->map(Blocks::COBBLESTONE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_COBBLESTONE)); $this->map(Blocks::COPPER(), function(Copper $block) : Writer{ @@ -1275,11 +1287,6 @@ private function registerSerializers() : void{ ->writeLegacyHorizontalFacing(Facing::opposite($block->getFacing())); }); $this->map(Blocks::COMPOUND_CREATOR(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, StringValues::CHEMISTRY_TABLE_TYPE_COMPOUND_CREATOR, new Writer(Ids::CHEMISTRY_TABLE))); - $this->map(Blocks::CORAL_BLOCK(), function(CoralBlock $block) : Writer{ - return Writer::create(Ids::CORAL_BLOCK) - ->writeBool(StateNames::DEAD_BIT, $block->isDead()) - ->writeCoralType($block->getCoralType()); - }); $this->map(Blocks::CRACKED_STONE_BRICKS(), fn() => Helper::encodeStoneBricks(StringValues::STONE_BRICK_TYPE_CRACKED)); $this->map(Blocks::CUT_RED_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::RED_SANDSTONE, StringValues::SAND_STONE_TYPE_CUT)); $this->map(Blocks::CUT_RED_SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab4($block, StringValues::STONE_SLAB_TYPE_4_CUT_RED_SANDSTONE)); @@ -1324,7 +1331,7 @@ private function registerSerializers() : void{ //ROOTED was already checked above }); }); - $this->map(Blocks::DOUBLE_TALLGRASS(), fn(DoubleTallGrass $block) => Helper::encodeDoublePlant($block, StringValues::DOUBLE_PLANT_TYPE_GRASS, Writer::create(Ids::DOUBLE_PLANT))); + $this->map(Blocks::DOUBLE_TALLGRASS(), fn(DoubleTallGrass $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::TALL_GRASS))); $this->map(Blocks::ELEMENT_CONSTRUCTOR(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, StringValues::CHEMISTRY_TABLE_TYPE_ELEMENT_CONSTRUCTOR, new Writer(Ids::CHEMISTRY_TABLE))); $this->map(Blocks::ENDER_CHEST(), function(EnderChest $block) : Writer{ return Writer::create(Ids::ENDER_CHEST) @@ -1342,13 +1349,11 @@ private function registerSerializers() : void{ $this->map(Blocks::END_STONE_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_END_STONE_BRICK)); $this->mapStairs(Blocks::END_STONE_BRICK_STAIRS(), Ids::END_BRICK_STAIRS); $this->map(Blocks::END_STONE_BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_END_BRICK)); - $this->map(Blocks::FAKE_WOODEN_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, StringValues::STONE_SLAB_TYPE_WOOD)); + $this->map(Blocks::FAKE_WOODEN_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::PETRIFIED_OAK_SLAB, StringValues::STONE_SLAB_TYPE_WOOD)); $this->map(Blocks::FARMLAND(), function(Farmland $block) : Writer{ return Writer::create(Ids::FARMLAND) ->writeInt(StateNames::MOISTURIZED_AMOUNT, $block->getWetness()); }); - $this->map(Blocks::FERN(), fn() => Writer::create(Ids::TALLGRASS) - ->writeString(StateNames::TALL_GRASS_TYPE, StringValues::TALL_GRASS_TYPE_FERN)); $this->map(Blocks::FIRE(), function(Fire $block) : Writer{ return Writer::create(Ids::FIRE) ->writeInt(StateNames::AGE, $block->getAge()); @@ -1413,7 +1418,7 @@ private function registerSerializers() : void{ return Writer::create(Ids::LANTERN) ->writeBool(StateNames::HANGING, $block->isHanging()); }); - $this->map(Blocks::LARGE_FERN(), fn(DoubleTallGrass $block) => Helper::encodeDoublePlant($block, StringValues::DOUBLE_PLANT_TYPE_FERN, Writer::create(Ids::DOUBLE_PLANT))); + $this->map(Blocks::LARGE_FERN(), fn(DoubleTallGrass $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::LARGE_FERN))); $this->map(Blocks::LAVA(), fn(Lava $block) => Helper::encodeLiquid($block, Ids::LAVA, Ids::FLOWING_LAVA)); $this->map(Blocks::LECTERN(), function(Lectern $block) : Writer{ return Writer::create(Ids::LECTERN) @@ -1442,7 +1447,7 @@ private function registerSerializers() : void{ return Writer::create(Ids::LIGHTNING_ROD) ->writeFacingDirection($block->getFacing()); }); - $this->map(Blocks::LILAC(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, StringValues::DOUBLE_PLANT_TYPE_SYRINGA, Writer::create(Ids::DOUBLE_PLANT))); + $this->map(Blocks::LILAC(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::LILAC))); $this->map(Blocks::LIT_PUMPKIN(), function(LitPumpkin $block) : Writer{ return Writer::create(Ids::LIT_PUMPKIN) ->writeCardinalHorizontalFacing($block->getFacing()); @@ -1471,7 +1476,7 @@ private function registerSerializers() : void{ ->writePillarAxis($block->getAxis())); $this->map(Blocks::MUSHROOM_STEM(), fn() => Writer::create(Ids::BROWN_MUSHROOM_BLOCK) ->writeInt(StateNames::HUGE_MUSHROOM_BITS, BlockLegacyMetadata::MUSHROOM_BLOCK_STEM)); - $this->map(Blocks::NETHER_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, StringValues::STONE_SLAB_TYPE_NETHER_BRICK)); + $this->map(Blocks::NETHER_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::NETHER_BRICK_SLAB, StringValues::STONE_SLAB_TYPE_NETHER_BRICK)); $this->mapStairs(Blocks::NETHER_BRICK_STAIRS(), Ids::NETHER_BRICK_STAIRS); $this->map(Blocks::NETHER_BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_NETHER_BRICK)); $this->map(Blocks::NETHER_PORTAL(), function(NetherPortal $block) : Writer{ @@ -1486,7 +1491,7 @@ private function registerSerializers() : void{ return Writer::create(Ids::NETHER_WART) ->writeInt(StateNames::AGE, $block->getAge()); }); - $this->map(Blocks::PEONY(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, StringValues::DOUBLE_PLANT_TYPE_PAEONIA, Writer::create(Ids::DOUBLE_PLANT))); + $this->map(Blocks::PEONY(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::PEONY))); $this->map(Blocks::PINK_PETALS(), function(PinkPetals $block) : Writer{ return Writer::create(Ids::PINK_PETALS) ->writeCardinalHorizontalFacing($block->getFacing()) @@ -1562,7 +1567,7 @@ private function registerSerializers() : void{ $this->mapStairs(Blocks::PURPUR_STAIRS(), Ids::PURPUR_STAIRS); $this->map(Blocks::QUARTZ(), fn() => Helper::encodeQuartz(StringValues::CHISEL_TYPE_DEFAULT, Axis::Y)); $this->map(Blocks::QUARTZ_PILLAR(), fn(SimplePillar $block) => Helper::encodeQuartz(StringValues::CHISEL_TYPE_LINES, $block->getAxis())); - $this->map(Blocks::QUARTZ_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, StringValues::STONE_SLAB_TYPE_QUARTZ)); + $this->map(Blocks::QUARTZ_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::QUARTZ_SLAB, StringValues::STONE_SLAB_TYPE_QUARTZ)); $this->mapStairs(Blocks::QUARTZ_STAIRS(), Ids::QUARTZ_STAIRS); $this->map(Blocks::RAIL(), function(Rail $block) : Writer{ return Writer::create(Ids::RAIL) @@ -1600,11 +1605,11 @@ private function registerSerializers() : void{ $this->mapStairs(Blocks::RED_SANDSTONE_STAIRS(), Ids::RED_SANDSTONE_STAIRS); $this->map(Blocks::RED_SANDSTONE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_RED_SANDSTONE)); $this->map(Blocks::RED_TORCH(), fn(Torch $block) => Helper::encodeColoredTorch($block, false, Writer::create(Ids::COLORED_TORCH_RG))); - $this->map(Blocks::ROSE_BUSH(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, StringValues::DOUBLE_PLANT_TYPE_ROSE, Writer::create(Ids::DOUBLE_PLANT))); + $this->map(Blocks::ROSE_BUSH(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::ROSE_BUSH))); $this->map(Blocks::SAND(), fn() => Writer::create(Ids::SAND) ->writeString(StateNames::SAND_TYPE, StringValues::SAND_TYPE_NORMAL)); $this->map(Blocks::SANDSTONE(), fn() => Helper::encodeSandstone(Ids::SANDSTONE, StringValues::SAND_STONE_TYPE_DEFAULT)); - $this->map(Blocks::SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, StringValues::STONE_SLAB_TYPE_SANDSTONE)); + $this->map(Blocks::SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::SANDSTONE_SLAB, StringValues::STONE_SLAB_TYPE_SANDSTONE)); $this->mapStairs(Blocks::SANDSTONE_STAIRS(), Ids::SANDSTONE_STAIRS); $this->map(Blocks::SANDSTONE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_SANDSTONE)); $this->map(Blocks::SEA_PICKLE(), function(SeaPickle $block) : Writer{ @@ -1627,7 +1632,7 @@ private function registerSerializers() : void{ $this->map(Blocks::SMOOTH_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::SANDSTONE, StringValues::SAND_STONE_TYPE_SMOOTH)); $this->map(Blocks::SMOOTH_SANDSTONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab2($block, StringValues::STONE_SLAB_TYPE_2_SMOOTH_SANDSTONE)); $this->mapStairs(Blocks::SMOOTH_SANDSTONE_STAIRS(), Ids::SMOOTH_SANDSTONE_STAIRS); - $this->map(Blocks::SMOOTH_STONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, StringValues::STONE_SLAB_TYPE_SMOOTH_STONE)); + $this->map(Blocks::SMOOTH_STONE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::SMOOTH_STONE_SLAB, StringValues::STONE_SLAB_TYPE_SMOOTH_STONE)); $this->map(Blocks::SNOW_LAYER(), function(SnowLayer $block) : Writer{ return Writer::create(Ids::SNOW_LAYER) ->writeBool(StateNames::COVERED_BIT, false) @@ -1652,7 +1657,7 @@ private function registerSerializers() : void{ $this->map(Blocks::STONECUTTER(), fn(Stonecutter $block) => Writer::create(Ids::STONECUTTER_BLOCK) ->writeCardinalHorizontalFacing($block->getFacing())); $this->map(Blocks::STONE_BRICKS(), fn() => Helper::encodeStoneBricks(StringValues::STONE_BRICK_TYPE_DEFAULT)); - $this->map(Blocks::STONE_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, StringValues::STONE_SLAB_TYPE_STONE_BRICK)); + $this->map(Blocks::STONE_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, Ids::STONE_BRICK_SLAB, StringValues::STONE_SLAB_TYPE_STONE_BRICK)); $this->mapStairs(Blocks::STONE_BRICK_STAIRS(), Ids::STONE_BRICK_STAIRS); $this->map(Blocks::STONE_BRICK_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_STONE_BRICK)); $this->map(Blocks::STONE_BUTTON(), fn(StoneButton $block) => Helper::encodeButton($block, new Writer(Ids::STONE_BUTTON))); @@ -1663,13 +1668,11 @@ private function registerSerializers() : void{ return Writer::create(Ids::REEDS) ->writeInt(StateNames::AGE, $block->getAge()); }); - $this->map(Blocks::SUNFLOWER(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, StringValues::DOUBLE_PLANT_TYPE_SUNFLOWER, Writer::create(Ids::DOUBLE_PLANT))); + $this->map(Blocks::SUNFLOWER(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, Writer::create(Ids::SUNFLOWER))); $this->map(Blocks::SWEET_BERRY_BUSH(), function(SweetBerryBush $block) : Writer{ return Writer::create(Ids::SWEET_BERRY_BUSH) ->writeInt(StateNames::GROWTH, $block->getAge()); }); - $this->map(Blocks::TALL_GRASS(), fn() => Writer::create(Ids::TALLGRASS) - ->writeString(StateNames::TALL_GRASS_TYPE, StringValues::TALL_GRASS_TYPE_TALL)); $this->map(Blocks::TNT(), function(TNT $block) : Writer{ return Writer::create(Ids::TNT) ->writeBool(StateNames::ALLOW_UNDERWATER_BIT, $block->worksUnderwater()) diff --git a/src/data/bedrock/block/convert/BlockStateDeserializerHelper.php b/src/data/bedrock/block/convert/BlockStateDeserializerHelper.php index de0964a20c9..6dda9fb81a1 100644 --- a/src/data/bedrock/block/convert/BlockStateDeserializerHelper.php +++ b/src/data/bedrock/block/convert/BlockStateDeserializerHelper.php @@ -32,6 +32,7 @@ use pocketmine\block\Crops; use pocketmine\block\DaylightSensor; use pocketmine\block\Door; +use pocketmine\block\DoublePlant; use pocketmine\block\FenceGate; use pocketmine\block\FloorCoralFan; use pocketmine\block\FloorSign; @@ -48,6 +49,7 @@ use pocketmine\block\Stem; use pocketmine\block\Trapdoor; use pocketmine\block\utils\CopperOxidation; +use pocketmine\block\utils\SlabType; use pocketmine\block\VanillaBlocks; use pocketmine\block\Wall; use pocketmine\block\WallCoralFan; @@ -139,6 +141,12 @@ public static function decodeDoor(Door $block, BlockStateReader $in) : Door{ ->setOpen($in->readBool(BlockStateNames::OPEN_BIT)); } + /** @throws BlockStateDeserializeException */ + public static function decodeDoublePlant(DoublePlant $block, BlockStateReader $in) : DoublePlant{ + return $block + ->setTop($in->readBool(BlockStateNames::UPPER_BLOCK_BIT)); + } + /** @throws BlockStateDeserializeException */ public static function decodeFenceGate(FenceGate $block, BlockStateReader $in) : FenceGate{ return $block @@ -233,6 +241,17 @@ public static function decodeSimplePressurePlate(SimplePressurePlate $block, Blo return $block->setPressed($in->readBoundedInt(BlockStateNames::REDSTONE_SIGNAL, 0, 15) !== 0); } + /** @throws BlockStateDeserializeException */ + public static function decodeSingleSlab(Slab $block, BlockStateReader $in) : Slab{ + return $block->setSlabType($in->readSlabPosition()); + } + + /** @throws BlockStateDeserializeException */ + public static function decodeDoubleSlab(Slab $block, BlockStateReader $in) : Slab{ + $in->ignored(StateNames::MC_VERTICAL_HALF); + return $block->setSlabType(SlabType::DOUBLE); + } + /** @throws BlockStateDeserializeException */ public static function decodeStairs(Stair $block, BlockStateReader $in) : Stair{ return $block diff --git a/src/data/bedrock/block/convert/BlockStateReader.php b/src/data/bedrock/block/convert/BlockStateReader.php index 07effd4f994..e3a02885f08 100644 --- a/src/data/bedrock/block/convert/BlockStateReader.php +++ b/src/data/bedrock/block/convert/BlockStateReader.php @@ -24,7 +24,6 @@ namespace pocketmine\data\bedrock\block\convert; use pocketmine\block\utils\BellAttachmentType; -use pocketmine\block\utils\CoralType; use pocketmine\block\utils\SlabType; use pocketmine\block\utils\WallConnectionType; use pocketmine\data\bedrock\block\BlockLegacyMetadata; @@ -309,18 +308,6 @@ public function readTorchFacing() : int{ }; } - /** @throws BlockStateDeserializeException */ - public function readCoralType() : CoralType{ - return match($type = $this->readString(BlockStateNames::CORAL_COLOR)){ - StringValues::CORAL_COLOR_BLUE => CoralType::TUBE, - StringValues::CORAL_COLOR_PINK => CoralType::BRAIN, - StringValues::CORAL_COLOR_PURPLE => CoralType::BUBBLE, - StringValues::CORAL_COLOR_RED => CoralType::FIRE, - StringValues::CORAL_COLOR_YELLOW => CoralType::HORN, - default => throw $this->badValueException(BlockStateNames::CORAL_COLOR, $type), - }; - } - /** @throws BlockStateDeserializeException */ public function readBellAttachmentType() : BellAttachmentType{ return match($type = $this->readString(BlockStateNames::ATTACHMENT)){ diff --git a/src/data/bedrock/block/convert/BlockStateSerializerHelper.php b/src/data/bedrock/block/convert/BlockStateSerializerHelper.php index a7d5ea774e3..a1f417d8945 100644 --- a/src/data/bedrock/block/convert/BlockStateSerializerHelper.php +++ b/src/data/bedrock/block/convert/BlockStateSerializerHelper.php @@ -107,10 +107,9 @@ public static function encodeDoor(Door $block, Writer $out) : Writer{ ->writeBool(BlockStateNames::OPEN_BIT, $block->isOpen()); } - public static function encodeDoublePlant(DoublePlant $block, string $doublePlantType, Writer $out) : Writer{ + public static function encodeDoublePlant(DoublePlant $block, Writer $out) : Writer{ return $out - ->writeBool(BlockStateNames::UPPER_BLOCK_BIT, $block->isTop()) - ->writeString(BlockStateNames::DOUBLE_PLANT_TYPE, $doublePlantType); + ->writeBool(BlockStateNames::UPPER_BLOCK_BIT, $block->isTop()); } public static function encodeFenceGate(FenceGate $block, Writer $out) : Writer{ @@ -183,11 +182,21 @@ public static function encodeSimplePressurePlate(SimplePressurePlate $block, Wri ->writeInt(BlockStateNames::REDSTONE_SIGNAL, $block->isPressed() ? 15 : 0); } - public static function encodeSlab(Slab $block, string $singleId, string $doubleId) : Writer{ - $slabType = $block->getSlabType(); - return Writer::create($slabType === SlabType::DOUBLE ? $doubleId : $singleId) + private static function encodeSingleSlab(Slab $block, string $id) : Writer{ + return Writer::create($id) + ->writeSlabPosition($block->getSlabType()); + } + + private static function encodeDoubleSlab(Slab $block, string $id) : Writer{ + return Writer::create($id) //this is (intentionally) also written for double slabs (as zero) to maintain bug parity with MCPE - ->writeSlabPosition($slabType === SlabType::DOUBLE ? SlabType::BOTTOM : $slabType); + ->writeSlabPosition(SlabType::BOTTOM); + } + + public static function encodeSlab(Slab $block, string $singleId, string $doubleId) : Writer{ + return $block->getSlabType() === SlabType::DOUBLE ? + self::encodeDoubleSlab($block, $doubleId) : + self::encodeSingleSlab($block, $singleId); } public static function encodeStairs(Stair $block, Writer $out) : Writer{ @@ -215,8 +224,12 @@ private static function encodeStoneSlab(Slab $block, string $singleId, string $d ->writeString($typeKey, $typeValue); } - public static function encodeStoneSlab1(Slab $block, string $typeValue) : Writer{ - return self::encodeStoneSlab($block, Ids::STONE_BLOCK_SLAB, Ids::DOUBLE_STONE_BLOCK_SLAB, BlockStateNames::STONE_SLAB_TYPE, $typeValue); + public static function encodeStoneSlab1(Slab $block, string $singleId, string $doubleTypeValue) : Writer{ + //1.21 made this a mess by flattening single slab IDs but not double ones + return $block->getSlabType() === SlabType::DOUBLE ? + self::encodeDoubleSlab($block, Ids::DOUBLE_STONE_BLOCK_SLAB) + ->writeString(BlockStateNames::STONE_SLAB_TYPE, $doubleTypeValue) : + self::encodeSingleSlab($block, $singleId); } public static function encodeStoneSlab2(Slab $block, string $typeValue) : Writer{ diff --git a/src/data/bedrock/block/convert/BlockStateToObjectDeserializer.php b/src/data/bedrock/block/convert/BlockStateToObjectDeserializer.php index 7220c0f8b9f..4c9ec4b798e 100644 --- a/src/data/bedrock/block/convert/BlockStateToObjectDeserializer.php +++ b/src/data/bedrock/block/convert/BlockStateToObjectDeserializer.php @@ -44,7 +44,6 @@ use pocketmine\block\utils\DyeColor; use pocketmine\block\utils\FroglightType; use pocketmine\block\utils\LeverFacing; -use pocketmine\block\utils\SlabType; use pocketmine\block\VanillaBlocks as Blocks; use pocketmine\block\Wood; use pocketmine\data\bedrock\block\BlockLegacyMetadata; @@ -115,11 +114,8 @@ public function mapSimple(string $id, \Closure $getBlock) : void{ * @phpstan-param \Closure(Reader) : Slab $getBlock */ public function mapSlab(string $singleId, string $doubleId, \Closure $getBlock) : void{ - $this->map($singleId, fn(Reader $in) : Slab => $getBlock($in)->setSlabType($in->readSlabPosition())); - $this->map($doubleId, function(Reader $in) use ($getBlock) : Slab{ - $in->ignored(StateNames::MC_VERTICAL_HALF); - return $getBlock($in)->setSlabType(SlabType::DOUBLE); - }); + $this->map($singleId, fn(Reader $in) => Helper::decodeSingleSlab($getBlock($in), $in)); + $this->map($doubleId, fn(Reader $in) => Helper::decodeDoubleSlab($getBlock($in), $in)); } /** @@ -450,6 +446,17 @@ private function registerFlatCoralDeserializers() : void{ $this->map($aliveId, fn(Reader $in) => Helper::decodeFloorCoralFan(Blocks::CORAL_FAN()->setCoralType($coralType)->setDead(false), $in)); $this->map($deadId, fn(Reader $in) => Helper::decodeFloorCoralFan(Blocks::CORAL_FAN()->setCoralType($coralType)->setDead(true), $in)); } + + foreach([ + [CoralType::BRAIN, Ids::BRAIN_CORAL_BLOCK, Ids::DEAD_BRAIN_CORAL_BLOCK], + [CoralType::BUBBLE, Ids::BUBBLE_CORAL_BLOCK, Ids::DEAD_BUBBLE_CORAL_BLOCK], + [CoralType::FIRE, Ids::FIRE_CORAL_BLOCK, Ids::DEAD_FIRE_CORAL_BLOCK], + [CoralType::HORN, Ids::HORN_CORAL_BLOCK, Ids::DEAD_HORN_CORAL_BLOCK], + [CoralType::TUBE, Ids::TUBE_CORAL_BLOCK, Ids::DEAD_TUBE_CORAL_BLOCK], + ] as [$coralType, $aliveId, $deadId]){ + $this->map($aliveId, fn(Reader $in) => Blocks::CORAL_BLOCK()->setCoralType($coralType)->setDead(false)); + $this->map($deadId, fn(Reader $in) => Blocks::CORAL_BLOCK()->setCoralType($coralType)->setDead(true)); + } } private function registerCauldronDeserializers() : void{ @@ -819,6 +826,7 @@ private function registerSimpleDeserializers() : void{ $this->mapSimple(Ids::ENCHANTING_TABLE, fn() => Blocks::ENCHANTING_TABLE()); $this->mapSimple(Ids::END_BRICKS, fn() => Blocks::END_STONE_BRICKS()); $this->mapSimple(Ids::END_STONE, fn() => Blocks::END_STONE()); + $this->mapSimple(Ids::FERN, fn() => Blocks::FERN()); $this->mapSimple(Ids::FLETCHING_TABLE, fn() => Blocks::FLETCHING_TABLE()); $this->mapSimple(Ids::GILDED_BLACKSTONE, fn() => Blocks::GILDED_BLACKSTONE()); $this->mapSimple(Ids::GLASS, fn() => Blocks::GLASS()); @@ -884,6 +892,7 @@ private function registerSimpleDeserializers() : void{ $this->mapSimple(Ids::RESERVED6, fn() => Blocks::RESERVED6()); $this->mapSimple(Ids::SCULK, fn() => Blocks::SCULK()); $this->mapSimple(Ids::SEA_LANTERN, fn() => Blocks::SEA_LANTERN()); + $this->mapSimple(Ids::SHORT_GRASS, fn() => Blocks::TALL_GRASS()); //no, this is not a typo - tall_grass is now the double block, just to be confusing :( $this->mapSimple(Ids::SHROOMLIGHT, fn() => Blocks::SHROOMLIGHT()); $this->mapSimple(Ids::SLIME, fn() => Blocks::SLIME()); $this->mapSimple(Ids::SMITHING_TABLE, fn() => Blocks::SMITHING_TABLE()); @@ -1109,11 +1118,6 @@ private function registerDeserializers() : void{ $this->map(Ids::CUT_COPPER, fn() => Helper::decodeCopper(Blocks::CUT_COPPER(), CopperOxidation::NONE)); $this->mapSlab(Ids::CUT_COPPER_SLAB, Ids::DOUBLE_CUT_COPPER_SLAB, fn() => Helper::decodeCopper(Blocks::CUT_COPPER_SLAB(), CopperOxidation::NONE)); $this->mapStairs(Ids::CUT_COPPER_STAIRS, fn() => Helper::decodeCopper(Blocks::CUT_COPPER_STAIRS(), CopperOxidation::NONE)); - $this->map(Ids::CORAL_BLOCK, function(Reader $in) : Block{ - return Blocks::CORAL_BLOCK() - ->setCoralType($in->readCoralType()) - ->setDead($in->readBool(StateNames::DEAD_BIT)); - }); $this->map(Ids::CORAL_FAN_HANG, fn(Reader $in) => Helper::decodeWallCoralFan(Blocks::WALL_CORAL_FAN(), $in) ->setCoralType($in->readBool(StateNames::CORAL_HANG_TYPE_BIT) ? CoralType::BRAIN : CoralType::TUBE)); $this->map(Ids::CORAL_FAN_HANG2, fn(Reader $in) => Helper::decodeWallCoralFan(Blocks::WALL_CORAL_FAN(), $in) @@ -1154,17 +1158,12 @@ private function registerDeserializers() : void{ }); }); $this->map(Ids::DIRT_WITH_ROOTS, fn() => Blocks::DIRT()->setDirtType(DirtType::ROOTED)); - $this->map(Ids::DOUBLE_PLANT, function(Reader $in) : Block{ - return (match($type = $in->readString(StateNames::DOUBLE_PLANT_TYPE)){ - StringValues::DOUBLE_PLANT_TYPE_FERN => Blocks::LARGE_FERN(), - StringValues::DOUBLE_PLANT_TYPE_GRASS => Blocks::DOUBLE_TALLGRASS(), - StringValues::DOUBLE_PLANT_TYPE_PAEONIA => Blocks::PEONY(), - StringValues::DOUBLE_PLANT_TYPE_ROSE => Blocks::ROSE_BUSH(), - StringValues::DOUBLE_PLANT_TYPE_SUNFLOWER => Blocks::SUNFLOWER(), - StringValues::DOUBLE_PLANT_TYPE_SYRINGA => Blocks::LILAC(), - default => throw $in->badValueException(StateNames::DOUBLE_PLANT_TYPE, $type), - })->setTop($in->readBool(StateNames::UPPER_BLOCK_BIT)); - }); + $this->map(Ids::LARGE_FERN, fn(Reader $in) => Helper::decodeDoublePlant(Blocks::LARGE_FERN(), $in)); + $this->map(Ids::TALL_GRASS, fn(Reader $in) => Helper::decodeDoublePlant(Blocks::DOUBLE_TALLGRASS(), $in)); + $this->map(Ids::PEONY, fn(Reader $in) => Helper::decodeDoublePlant(Blocks::PEONY(), $in)); + $this->map(Ids::ROSE_BUSH, fn(Reader $in) => Helper::decodeDoublePlant(Blocks::ROSE_BUSH(), $in)); + $this->map(Ids::SUNFLOWER, fn(Reader $in) => Helper::decodeDoublePlant(Blocks::SUNFLOWER(), $in)); + $this->map(Ids::LILAC, fn(Reader $in) => Helper::decodeDoublePlant(Blocks::LILAC(), $in)); $this->mapStairs(Ids::END_BRICK_STAIRS, fn() => Blocks::END_STONE_BRICK_STAIRS()); $this->map(Ids::END_PORTAL_FRAME, function(Reader $in) : Block{ return Blocks::END_PORTAL_FRAME() @@ -1437,7 +1436,7 @@ private function registerDeserializers() : void{ $in->ignored(StateNames::PILLAR_AXIS); return Blocks::SMOOTH_QUARTZ(); default: - return throw $in->badValueException(StateNames::CHISEL_TYPE, $type); + throw $in->badValueException(StateNames::CHISEL_TYPE, $type); } }); $this->mapStairs(Ids::QUARTZ_STAIRS, fn() => Blocks::QUARTZ_STAIRS()); @@ -1552,7 +1551,18 @@ private function registerDeserializers() : void{ $this->mapStairs(Ids::STONE_BRICK_STAIRS, fn() => Blocks::STONE_BRICK_STAIRS()); $this->map(Ids::STONE_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::STONE_BUTTON(), $in)); $this->map(Ids::STONE_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::STONE_PRESSURE_PLATE(), $in)); - $this->mapSlab(Ids::STONE_BLOCK_SLAB, Ids::DOUBLE_STONE_BLOCK_SLAB, fn(Reader $in) => Helper::mapStoneSlab1Type($in)); + + //mess for partially flattened slabs - the single IDs were flattened but not the double ones + $this->map(Ids::DOUBLE_STONE_BLOCK_SLAB, fn(Reader $in) => Helper::decodeDoubleSlab(Helper::mapStoneSlab1Type($in), $in)); + $this->map(Ids::BRICK_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::BRICK_SLAB(), $in)); + $this->map(Ids::COBBLESTONE_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::COBBLESTONE_SLAB(), $in)); + $this->map(Ids::NETHER_BRICK_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::NETHER_BRICK_SLAB(), $in)); + $this->map(Ids::PETRIFIED_OAK_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::FAKE_WOODEN_SLAB(), $in)); + $this->map(Ids::QUARTZ_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::QUARTZ_SLAB(), $in)); + $this->map(Ids::SANDSTONE_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::SANDSTONE_SLAB(), $in)); + $this->map(Ids::SMOOTH_STONE_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::SMOOTH_STONE_SLAB(), $in)); + $this->map(Ids::STONE_BRICK_SLAB, fn(Reader $in) => Helper::decodeSingleSlab(Blocks::STONE_BRICK_SLAB(), $in)); + $this->mapSlab(Ids::STONE_BLOCK_SLAB2, Ids::DOUBLE_STONE_BLOCK_SLAB2, fn(Reader $in) => Helper::mapStoneSlab2Type($in)); $this->mapSlab(Ids::STONE_BLOCK_SLAB3, Ids::DOUBLE_STONE_BLOCK_SLAB3, fn(Reader $in) => Helper::mapStoneSlab3Type($in)); $this->mapSlab(Ids::STONE_BLOCK_SLAB4, Ids::DOUBLE_STONE_BLOCK_SLAB4, fn(Reader $in) => Helper::mapStoneSlab4Type($in)); @@ -1577,13 +1587,6 @@ private function registerDeserializers() : void{ return Blocks::SWEET_BERRY_BUSH() ->setAge(min($growth, SweetBerryBush::STAGE_MATURE)); }); - $this->map(Ids::TALLGRASS, function(Reader $in) : Block{ - return match($type = $in->readString(StateNames::TALL_GRASS_TYPE)){ - StringValues::TALL_GRASS_TYPE_DEFAULT, StringValues::TALL_GRASS_TYPE_SNOW, StringValues::TALL_GRASS_TYPE_TALL => Blocks::TALL_GRASS(), - StringValues::TALL_GRASS_TYPE_FERN => Blocks::FERN(), - default => throw $in->badValueException(StateNames::TALL_GRASS_TYPE, $type), - }; - }); $this->map(Ids::TNT, function(Reader $in) : Block{ return Blocks::TNT() ->setUnstable($in->readBool(StateNames::EXPLODE_BIT)) diff --git a/src/data/bedrock/block/convert/BlockStateWriter.php b/src/data/bedrock/block/convert/BlockStateWriter.php index 33e82a5c02d..63af92d1009 100644 --- a/src/data/bedrock/block/convert/BlockStateWriter.php +++ b/src/data/bedrock/block/convert/BlockStateWriter.php @@ -24,7 +24,6 @@ namespace pocketmine\data\bedrock\block\convert; use pocketmine\block\utils\BellAttachmentType; -use pocketmine\block\utils\CoralType; use pocketmine\block\utils\SlabType; use pocketmine\block\utils\WallConnectionType; use pocketmine\data\bedrock\block\BlockLegacyMetadata; @@ -256,18 +255,6 @@ public function writeTorchFacing(int $facing) : self{ return $this; } - /** @return $this */ - public function writeCoralType(CoralType $coralType) : self{ - $this->writeString(BlockStateNames::CORAL_COLOR, match($coralType){ - CoralType::TUBE => StringValues::CORAL_COLOR_BLUE, - CoralType::BRAIN => StringValues::CORAL_COLOR_PINK, - CoralType::BUBBLE => StringValues::CORAL_COLOR_PURPLE, - CoralType::FIRE => StringValues::CORAL_COLOR_RED, - CoralType::HORN => StringValues::CORAL_COLOR_YELLOW, - }); - return $this; - } - /** @return $this */ public function writeBellAttachmentType(BellAttachmentType $attachmentType) : self{ $this->writeString(BlockStateNames::ATTACHMENT, match($attachmentType){ diff --git a/src/data/bedrock/item/ItemTypeNames.php b/src/data/bedrock/item/ItemTypeNames.php index cadbb7aa6b0..c2bc71caf12 100644 --- a/src/data/bedrock/item/ItemTypeNames.php +++ b/src/data/bedrock/item/ItemTypeNames.php @@ -143,6 +143,7 @@ final class ItemTypeNames{ public const COPPER_DOOR = "minecraft:copper_door"; public const COPPER_INGOT = "minecraft:copper_ingot"; public const CORAL = "minecraft:coral"; + public const CORAL_BLOCK = "minecraft:coral_block"; public const CORAL_FAN = "minecraft:coral_fan"; public const CORAL_FAN_DEAD = "minecraft:coral_fan_dead"; public const COW_SPAWN_EGG = "minecraft:cow_spawn_egg"; @@ -173,6 +174,7 @@ final class ItemTypeNames{ public const DISC_FRAGMENT_5 = "minecraft:disc_fragment_5"; public const DOLPHIN_SPAWN_EGG = "minecraft:dolphin_spawn_egg"; public const DONKEY_SPAWN_EGG = "minecraft:donkey_spawn_egg"; + public const DOUBLE_PLANT = "minecraft:double_plant"; public const DRAGON_BREATH = "minecraft:dragon_breath"; public const DRIED_KELP = "minecraft:dried_kelp"; public const DROWNED_SPAWN_EGG = "minecraft:drowned_spawn_egg"; @@ -331,11 +333,14 @@ final class ItemTypeNames{ public const MUSIC_DISC_BLOCKS = "minecraft:music_disc_blocks"; public const MUSIC_DISC_CAT = "minecraft:music_disc_cat"; public const MUSIC_DISC_CHIRP = "minecraft:music_disc_chirp"; + public const MUSIC_DISC_CREATOR = "minecraft:music_disc_creator"; + public const MUSIC_DISC_CREATOR_MUSIC_BOX = "minecraft:music_disc_creator_music_box"; public const MUSIC_DISC_FAR = "minecraft:music_disc_far"; public const MUSIC_DISC_MALL = "minecraft:music_disc_mall"; public const MUSIC_DISC_MELLOHI = "minecraft:music_disc_mellohi"; public const MUSIC_DISC_OTHERSIDE = "minecraft:music_disc_otherside"; public const MUSIC_DISC_PIGSTEP = "minecraft:music_disc_pigstep"; + public const MUSIC_DISC_PRECIPICE = "minecraft:music_disc_precipice"; public const MUSIC_DISC_RELIC = "minecraft:music_disc_relic"; public const MUSIC_DISC_STAL = "minecraft:music_disc_stal"; public const MUSIC_DISC_STRAD = "minecraft:music_disc_strad"; @@ -366,6 +371,8 @@ final class ItemTypeNames{ public const OAK_HANGING_SIGN = "minecraft:oak_hanging_sign"; public const OAK_SIGN = "minecraft:oak_sign"; public const OCELOT_SPAWN_EGG = "minecraft:ocelot_spawn_egg"; + public const OMINOUS_BOTTLE = "minecraft:ominous_bottle"; + public const OMINOUS_TRIAL_KEY = "minecraft:ominous_trial_key"; public const ORANGE_DYE = "minecraft:orange_dye"; public const OXIDIZED_COPPER_DOOR = "minecraft:oxidized_copper_door"; public const PAINTING = "minecraft:painting"; @@ -467,6 +474,7 @@ final class ItemTypeNames{ public const STAINED_HARDENED_CLAY = "minecraft:stained_hardened_clay"; public const STICK = "minecraft:stick"; public const STONE_AXE = "minecraft:stone_axe"; + public const STONE_BLOCK_SLAB = "minecraft:stone_block_slab"; public const STONE_HOE = "minecraft:stone_hoe"; public const STONE_PICKAXE = "minecraft:stone_pickaxe"; public const STONE_SHOVEL = "minecraft:stone_shovel"; @@ -480,6 +488,7 @@ final class ItemTypeNames{ public const SWEET_BERRIES = "minecraft:sweet_berries"; public const TADPOLE_BUCKET = "minecraft:tadpole_bucket"; public const TADPOLE_SPAWN_EGG = "minecraft:tadpole_spawn_egg"; + public const TALLGRASS = "minecraft:tallgrass"; public const TIDE_ARMOR_TRIM_SMITHING_TEMPLATE = "minecraft:tide_armor_trim_smithing_template"; public const TNT_MINECART = "minecraft:tnt_minecart"; public const TORCHFLOWER_SEEDS = "minecraft:torchflower_seeds"; diff --git a/src/item/Bowl.php b/src/item/Bowl.php index d83044307d7..217346df54c 100644 --- a/src/item/Bowl.php +++ b/src/item/Bowl.php @@ -25,5 +25,7 @@ class Bowl extends Item{ - //TODO: check fuel + public function getFuelTime() : int{ + return 200; + } } diff --git a/src/network/mcpe/InventoryManager.php b/src/network/mcpe/InventoryManager.php index e2b71ab3106..8c0d5b6e610 100644 --- a/src/network/mcpe/InventoryManager.php +++ b/src/network/mcpe/InventoryManager.php @@ -96,6 +96,7 @@ class InventoryManager{ private array $complexSlotToInventoryMap = []; private int $lastInventoryNetworkId = ContainerIds::FIRST; + private int $currentWindowType = WindowTypes::CONTAINER; private int $clientSelectedHotbarSlot = -1; @@ -327,9 +328,15 @@ public function onCurrentWindowChange(Inventory $inventory) : void{ foreach($this->containerOpenCallbacks as $callback){ $pks = $callback($windowId, $inventory); if($pks !== null){ + $windowType = null; foreach($pks as $pk){ + if($pk instanceof ContainerOpenPacket){ + //workaround useless bullshit in 1.21 - ContainerClose requires a type now for some reason + $windowType = $pk->windowType; + } $this->session->sendDataPacket($pk); } + $this->currentWindowType = $windowType ?? WindowTypes::CONTAINER; $this->syncContents($inventory); return; } @@ -378,10 +385,11 @@ public function onClientOpenMainInventory() : void{ $this->openWindowDeferred(function() : void{ $windowId = $this->getNewWindowId(); $this->associateIdWithInventory($windowId, $this->player->getInventory()); + $this->currentWindowType = WindowTypes::INVENTORY; $this->session->sendDataPacket(ContainerOpenPacket::entityInv( $windowId, - WindowTypes::INVENTORY, + $this->currentWindowType, $this->player->getId() )); }); @@ -390,7 +398,7 @@ public function onClientOpenMainInventory() : void{ public function onCurrentWindowRemove() : void{ if(isset($this->networkIdToInventoryMap[$this->lastInventoryNetworkId])){ $this->remove($this->lastInventoryNetworkId); - $this->session->sendDataPacket(ContainerClosePacket::create($this->lastInventoryNetworkId, true)); + $this->session->sendDataPacket(ContainerClosePacket::create($this->lastInventoryNetworkId, $this->currentWindowType, true)); if($this->pendingCloseWindowId !== null){ throw new AssumptionFailedError("We should not have opened a new window while a window was waiting to be closed"); } @@ -411,7 +419,7 @@ public function onClientRemoveWindow(int $id) : void{ //Always send this, even if no window matches. If we told the client to close a window, it will behave as if it //initiated the close and expect an ack. - $this->session->sendDataPacket(ContainerClosePacket::create($id, false)); + $this->session->sendDataPacket(ContainerClosePacket::create($id, $this->currentWindowType, false)); if($this->pendingCloseWindowId === $id){ $this->pendingCloseWindowId = null; diff --git a/src/network/mcpe/cache/CraftingDataCache.php b/src/network/mcpe/cache/CraftingDataCache.php index c4a5578633e..29f37590e3b 100644 --- a/src/network/mcpe/cache/CraftingDataCache.php +++ b/src/network/mcpe/cache/CraftingDataCache.php @@ -36,6 +36,7 @@ use pocketmine\network\mcpe\protocol\types\recipe\IntIdMetaItemDescriptor; use pocketmine\network\mcpe\protocol\types\recipe\PotionContainerChangeRecipe as ProtocolPotionContainerChangeRecipe; use pocketmine\network\mcpe\protocol\types\recipe\PotionTypeRecipe as ProtocolPotionTypeRecipe; +use pocketmine\network\mcpe\protocol\types\recipe\RecipeUnlockingRequirement; use pocketmine\network\mcpe\protocol\types\recipe\ShapedRecipe as ProtocolShapedRecipe; use pocketmine\network\mcpe\protocol\types\recipe\ShapelessRecipe as ProtocolShapelessRecipe; use pocketmine\timings\Timings; @@ -79,6 +80,7 @@ private function buildCraftingDataCache(CraftingManager $manager) : CraftingData $converter = TypeConverter::getInstance(); $recipesWithTypeIds = []; + $noUnlockingRequirement = new RecipeUnlockingRequirement(null); foreach($manager->getCraftingRecipeIndex() as $index => $recipe){ if($recipe instanceof ShapelessRecipe){ $typeTag = match($recipe->getType()){ @@ -95,6 +97,7 @@ private function buildCraftingDataCache(CraftingManager $manager) : CraftingData $nullUUID, $typeTag, 50, + $noUnlockingRequirement, $index ); }elseif($recipe instanceof ShapedRecipe){ @@ -114,6 +117,7 @@ private function buildCraftingDataCache(CraftingManager $manager) : CraftingData CraftingRecipeBlockName::CRAFTING_TABLE, 50, true, + $noUnlockingRequirement, $index, ); }else{ diff --git a/src/world/format/io/data/BedrockWorldData.php b/src/world/format/io/data/BedrockWorldData.php index 924021d7e26..9dc89ad9969 100644 --- a/src/world/format/io/data/BedrockWorldData.php +++ b/src/world/format/io/data/BedrockWorldData.php @@ -51,12 +51,12 @@ class BedrockWorldData extends BaseNbtWorldData{ public const CURRENT_STORAGE_VERSION = 10; - public const CURRENT_STORAGE_NETWORK_VERSION = 671; + public const CURRENT_STORAGE_NETWORK_VERSION = 685; public const CURRENT_CLIENT_VERSION_TARGET = [ 1, //major - 20, //minor - 80, //patch - 5, //revision + 21, //minor + 0, //patch + 3, //revision 0 //is beta ]; diff --git a/tests/phpunit/data/bedrock/block/BlockStateDataTest.php b/tests/phpunit/data/bedrock/block/BlockStateDataTest.php index 836edfc38f3..7add2eddae6 100644 --- a/tests/phpunit/data/bedrock/block/BlockStateDataTest.php +++ b/tests/phpunit/data/bedrock/block/BlockStateDataTest.php @@ -27,6 +27,7 @@ use pocketmine\data\bedrock\block\BlockStateData; use pocketmine\data\bedrock\block\upgrade\BlockStateUpgradeSchemaUtils; use Symfony\Component\Filesystem\Path; +use function sprintf; use const PHP_INT_MAX; use const pocketmine\BEDROCK_BLOCK_UPGRADE_SCHEMA_PATH; @@ -39,7 +40,19 @@ public function testCurrentVersion() : void{ ) as $schema){ $expected = BlockStateData::CURRENT_VERSION; $actual = $schema->getVersionId(); - self::assertLessThanOrEqual($expected, $actual, "Schema version $actual is newer than the current version $expected"); + self::assertLessThanOrEqual($expected, $actual, sprintf( + "Schema version %d (%d.%d.%d.%d) is newer than the current version %d (%d.%d.%d.%d)", + $actual, + ($actual >> 24) & 0xff, + ($actual >> 16) & 0xff, + ($actual >> 8) & 0xff, + $actual & 0xff, + $expected, + ($expected >> 24) & 0xff, + ($expected >> 16) & 0xff, + ($expected >> 8) & 0xff, + $expected & 0xff + )); } } } diff --git a/tools/generate-bedrock-data-from-packets.php b/tools/generate-bedrock-data-from-packets.php index 795e7ad1fdd..16c3062b845 100644 --- a/tools/generate-bedrock-data-from-packets.php +++ b/tools/generate-bedrock-data-from-packets.php @@ -195,7 +195,7 @@ private function itemStackToJson(ItemStack $itemStack) : ItemStackData{ * @return mixed[] */ private static function objectToOrderedArray(object $object) : array{ - $result = (array) $object; + $result = (array) ($object instanceof \JsonSerializable ? $object->jsonSerialize() : $object); ksort($result, SORT_STRING); foreach($result as $property => $value){ @@ -335,21 +335,25 @@ private function shapedRecipeToJson(ShapedRecipe $entry) : ShapedRecipeData{ } } } + $unlockingIngredients = $entry->getUnlockingRequirement()->getUnlockingIngredients(); return new ShapedRecipeData( array_map(fn(array $array) => implode('', $array), $shape), $outputsByKey, array_map(fn(ItemStack $output) => $this->itemStackToJson($output), $entry->getOutput()), $entry->getBlockName(), - $entry->getPriority() + $entry->getPriority(), + $unlockingIngredients !== null ? array_map(fn(RecipeIngredient $input) => $this->recipeIngredientToJson($input), $unlockingIngredients) : [] ); } private function shapelessRecipeToJson(ShapelessRecipe $recipe) : ShapelessRecipeData{ + $unlockingIngredients = $recipe->getUnlockingRequirement()->getUnlockingIngredients(); return new ShapelessRecipeData( array_map(fn(RecipeIngredient $input) => $this->recipeIngredientToJson($input), $recipe->getInputs()), array_map(fn(ItemStack $output) => $this->itemStackToJson($output), $recipe->getOutputs()), $recipe->getBlockName(), - $recipe->getPriority() + $recipe->getPriority(), + $unlockingIngredients !== null ? array_map(fn(RecipeIngredient $input) => $this->recipeIngredientToJson($input), $unlockingIngredients) : [] ); }